diff --git a/CHANGELOG.md b/CHANGELOG.md index ffb20964..1107f19c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,69 @@ + +X.Y.Z Release notes +============================================================= +### Breaking changes +* None. + +### Enhancements +* Added property `Realm.isClosed` which indicates if a Realm instance is closed or not. + +### Bug fixes +* None. + +### Internal +* None. + +2.0.13 Release notes (2017-12-8) +============================================================= +### Breaking changes +* None. + +### Enhancements +* None. + +### Bug fixes +* [Object Server] When authentication fails due to a misbehaving server, a proper error is thrown. + +### Internal +* [Object Server] Strings can now be assigned to Date columns. When that happens the JavaScript Date constructor will be invoked to parse the string. +* [Object Server] Base64 strings can now be assigned to Data columns. + +2.0.12 Release notes (2017-12-1) +============================================================= +### Breaking changes +* None. + +### Enhancements +* None. + +### Bug fixes +* Fixed a bug in 3rd party JSON parser: `localeconv()` does not exist on Android API < 21 and should not be called. + +### Internal +* Fixed issues in unit tests (`addListener` hangs on Android). +* Upgraded to Realm Sync 2.1.8 (no external effects). + +2.0.11 Release notes (2017-11-23) +============================================================= +### Breaking changes +* None. + +### Enhancements +* None + +### Bug fixes +* [Object Server] Fixed a bug where deleted-then-recreated objects with identical primary keys to become empty. +* [Object Server] Fixed a bug in outward partial sync is changed to ensure convergence of partial sync in the case where the client creates a primary key object, that is already present on the server, and subscribes to it in the same transaction. + +### Internal +* Updated to Realm Sync 2.1.7 (see under "Bug fixes"). + 2.0.10 Release notes (2017-11-21) ============================================================= ### Breaking changes * None. -### Enchancements +### Enhancements * None ### Bug fixes @@ -17,7 +77,7 @@ ### Breaking changes * None. -### Enchancements +### Enhancements * None ### Bug fixes @@ -31,7 +91,7 @@ ### Breaking changes * None. -### Enchancements +### Enhancements * [Object Server] Improving performance of processing large changesets. ### Bug fixes @@ -46,7 +106,7 @@ ### Breaking changes * None -### Enchancements +### Enhancements * None ### Bug fixes @@ -61,7 +121,7 @@ ### Breaking changes * None. -### Enchancements +### Enhancements * Improved notification performance for objects with no object or list properties. ### Bug fixes @@ -77,7 +137,7 @@ ### Breaking changes * None. -### Enchancements +### Enhancements * None. ### Bug fixes diff --git a/binding.gyp b/binding.gyp index bac961b6..19b604bb 100644 --- a/binding.gyp +++ b/binding.gyp @@ -10,9 +10,37 @@ "object-store" ], "sources": [ - "src/node/platform.cpp", "src/js_realm.cpp", - "src/node/node_init.cpp" + "src/node/node_init.cpp", + "src/node/platform.cpp", + + "src/concurrent_deque.hpp", + "src/event_loop_dispatcher.hpp", + "src/js_class.hpp", + "src/js_collection.hpp", + "src/js_list.hpp", + "src/js_object_accessor.hpp", + "src/js_observable.hpp", + "src/js_realm.hpp", + "src/js_realm_object.hpp", + "src/js_results.hpp", + "src/js_schema.hpp", + "src/js_sync.hpp", + "src/js_types.hpp", + "src/js_util.hpp", + "src/node/node_class.hpp", + "src/node/node_context.hpp", + "src/node/node_exception.hpp", + "src/node/node_function.hpp", + "src/node/node_init.hpp", + "src/node/node_object.hpp", + "src/node/node_protected.hpp", + "src/node/node_return_value.hpp", + "src/node/node_string.hpp", + "src/node/node_types.hpp", + "src/node/node_value.hpp", + "src/platform.hpp", + "src/rpc.hpp", ], "include_dirs": [ "src" @@ -28,6 +56,100 @@ "destination": "<(module_path)" } ] + }, + { + "target_name": "scripts", + "type": "none", + "sources": [ + "CHANGELOG.md", + "README.md", + "binding.gyp", + "dependencies.list", + "package.json", + "realm.gypi", + "target_defaults.gypi", + + "lib/collection-methods.js", + "lib/errors.js", + "lib/extensions.js", + "lib/index.d.ts", + "lib/index.js", + "lib/management-schema.js", + "lib/permission-api.js", + "lib/submit-analytics.js", + "lib/user-methods.js", + + "lib/browser/base64.js", + "lib/browser/collections.js", + "lib/browser/constants.js", + "lib/browser/index.js", + "lib/browser/lists.js", + "lib/browser/objects.js", + "lib/browser/results.js", + "lib/browser/rpc.js", + "lib/browser/session.js", + "lib/browser/user.js", + "lib/browser/util.js" + + "scripts/build-node-pre-gyp.ps1", + "scripts/build-node-pre-gyp.sh", + "scripts/ccache-clang++.sh", + "scripts/ccache-clang.sh", + "scripts/changelog-header.sh", + "scripts/check-environment.js", + "scripts/docker-android-wrapper.sh", + "scripts/docker-wrapper.sh", + "scripts/docker_build_wrapper.sh", + "scripts/download-object-server.sh", + "scripts/download-realm.js", + "scripts/download_and_start_server.sh", + "scripts/find-ios-device.rb", + "scripts/git-win-symlink-aliases", + "scripts/handle-license-check.js", + "scripts/prepublish.js", + "scripts/publish.sh", + "scripts/react-tests-android.js", + "scripts/set-version.sh", + "scripts/test.sh", + + "tests/.eslintrc.json", + "tests/index.js", + "tests/js/admin-user-helper.js", + "tests/js/asserts.js", + "tests/js/async-tests.js", + "tests/js/download-api-helper.js", + "tests/js/encryption-tests.js", + "tests/js/garbage-collection.js", + "tests/js/index.js", + "tests/js/linkingobjects-tests.js", + "tests/js/list-tests.js", + "tests/js/migration-tests.js", + "tests/js/object-id-tests.js", + "tests/js/object-tests.js", + "tests/js/package.json", + "tests/js/permission-tests.js", + "tests/js/query-tests.js", + "tests/js/query-tests.json", + "tests/js/realm-tests.js", + "tests/js/results-tests.js", + "tests/js/schemas.js", + "tests/js/session-tests.js", + "tests/js/user-tests.js", + "tests/js/worker-tests-script.js", + "tests/js/worker.js", + "tests/package.json", + "tests/spec/helpers/mock_realm.js", + "tests/spec/helpers/reporters.js", + "tests/spec/helpers/setup-module-path.js", + "tests/spec/support/jasmine.json", + "tests/spec/unit_tests.js", + "tests/test-runners/ava/package.json", + "tests/test-runners/ava/test.js", + "tests/test-runners/jest/package.json", + "tests/test-runners/jest/test.js", + "tests/test-runners/mocha/package.json", + "tests/test-runners/mocha/test.js", + ] } ] } diff --git a/dependencies.list b/dependencies.list index d02ad1c6..3e987eb2 100644 --- a/dependencies.list +++ b/dependencies.list @@ -1,5 +1,5 @@ PACKAGE_NAME=realm-js -VERSION=2.0.10 +VERSION=2.0.13 REALM_CORE_VERSION=4.0.2 -REALM_SYNC_VERSION=2.1.6 +REALM_SYNC_VERSION=2.1.8 REALM_OBJECT_SERVER_VERSION=2.0.21 diff --git a/docs/realm.js b/docs/realm.js index 5ae17650..a6cf1a22 100644 --- a/docs/realm.js +++ b/docs/realm.js @@ -72,6 +72,14 @@ class Realm { */ get isInTransaction() {} + /** + * Indicates if this Realm has been closed. + * @type {boolean} + * @readonly + * @since 2.1.0 + */ + get isClosed() {} + /** * Gets the sync session if this is a synced Realm * @type {Session} diff --git a/docs/sync.js b/docs/sync.js index 711d0046..d14a747d 100644 --- a/docs/sync.js +++ b/docs/sync.js @@ -408,7 +408,7 @@ class Adapter { * @param {string} local_path - the local path where realm files are stored * @param {string} server_url - the sync server to listen to * @param {SyncUser} admin_user - an admin user obtained by calling `new Realm.Sync.User.adminUser` - * @param {string} regex - a regular expression used to determine which cahnged Realms should be monitored - + * @param {string} regex - a regular expression used to determine which changed Realms should be monitored - * use `.*` to match all all Realms * @param {function(realm_path)} change_callback - called when a new transaction is available * to process for the given realm_path diff --git a/lib/browser/index.js b/lib/browser/index.js index 607af4af..17c16a45 100644 --- a/lib/browser/index.js +++ b/lib/browser/index.js @@ -60,6 +60,7 @@ function setupRealm(realm, realmId) { 'schemaVersion', 'syncSession', 'isInTransaction', + 'isClosed', 'subscribeToObjects', ].forEach((name) => { Object.defineProperty(realm, name, {get: util.getterForProperty(name)}); diff --git a/lib/index.d.ts b/lib/index.d.ts index ca94aae4..d7243ce9 100644 --- a/lib/index.d.ts +++ b/lib/index.d.ts @@ -458,6 +458,7 @@ declare class Realm { readonly schema: Realm.ObjectSchema[]; readonly schemaVersion: number; readonly isInTransaction: boolean; + readonly isClosed: boolean; readonly syncSession: Realm.Sync.Session | null; diff --git a/lib/user-methods.js b/lib/user-methods.js index 3ec76eba..b0f4210c 100644 --- a/lib/user-methods.js +++ b/lib/user-methods.js @@ -154,7 +154,15 @@ function _authenticate(userConstructor, server, json, callback) { const promise = performFetch(url, options) .then((response) => { - if (response.status !== 200) { + const contentType = response.headers.get('Content-Type'); + if (contentType.indexOf('application/json') === -1) { + return response.text().then((body) => { + throw new AuthError({ + title: `Could not authenticate: Realm Object Server didn't respond with valid JSON`, + body, + }); + }); + } else if (!response.ok) { return response.json().then((body) => Promise.reject(new AuthError(body))); } else { return response.json().then(function (body) { diff --git a/package-lock.json b/package-lock.json index e209caf5..2368e85c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "realm", - "version": "2.0.0-rc11", + "version": "2.0.12", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -270,9 +270,9 @@ } }, "bluebird": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.0.tgz", - "integrity": "sha1-eRQg1/VR7qKJdFOop3ZT+WYG1nw=", + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", + "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==", "dev": true }, "boom": { @@ -1537,18 +1537,18 @@ "optional": true }, "jsdoc": { - "version": "3.5.4", - "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.5.4.tgz", - "integrity": "sha1-zu73xLrEM1yxD/QeOg9Yk5pTRCg=", + "version": "3.5.5", + "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.5.5.tgz", + "integrity": "sha512-6PxB65TAU4WO0Wzyr/4/YhlGovXl0EVYfpKbpSroSj0qBxT4/xod/l40Opkm38dRHRdQgdeY836M0uVnJQG7kg==", "dev": true, "requires": { "babylon": "7.0.0-beta.19", - "bluebird": "3.5.0", + "bluebird": "3.5.1", "catharsis": "0.8.9", "escape-string-regexp": "1.0.5", "js2xmlparser": "3.0.0", "klaw": "2.0.0", - "marked": "0.3.6", + "marked": "0.3.7", "mkdirp": "0.5.1", "requizzle": "0.2.1", "strip-json-comments": "2.0.1", @@ -2497,9 +2497,9 @@ } }, "marked": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/marked/-/marked-0.3.6.tgz", - "integrity": "sha1-ssbGGPzOzk74bE/Gy4p8v1rtqNc=", + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/marked/-/marked-0.3.7.tgz", + "integrity": "sha512-zBEP4qO1YQp5aXHt8S5wTiOv9i2X74V/LQL0zhUNvVaklt6Ywa6lChxIvS+ibYlCGgADwKwZFhjC3+XfpsvQvQ==", "dev": true }, "mime-db": { diff --git a/package.json b/package.json index c2ed7ef1..19f0a8c0 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "realm", "description": "Realm is a mobile database: an alternative to SQLite and key-value stores", - "version": "2.0.10", + "version": "2.0.13", "license": "Apache-2.0", "homepage": "https://realm.io", "keywords": [ @@ -99,7 +99,7 @@ "eslint": "^3.2.2", "eslint-plugin-jasmine": "^2.1.0", "eslint-plugin-react": "^6.7.0", - "jsdoc": "^3.4.0", + "jsdoc": "^3.5.5", "license-checker": "^8.0.3", "mockery": "^2.0.0", "rimraf": "^2.6.1", diff --git a/realm.gypi b/realm.gypi index cc67c761..eeb33271 100644 --- a/realm.gypi +++ b/realm.gypi @@ -63,6 +63,68 @@ "src/object-store/src/parser/query_builder.cpp", "src/object-store/src/util/format.cpp", "src/object-store/src/util/uuid.cpp", + + "src/object-store/src/binding_callback_thread_observer.hpp", + "src/object-store/src/binding_context.hpp", + "src/object-store/src/collection_notifications.hpp", + "src/object-store/src/descriptor_ordering.hpp", + "src/object-store/src/execution_context_id.hpp", + "src/object-store/src/feature_checks.hpp", + "src/object-store/src/impl/apple/external_commit_helper.hpp", + "src/object-store/src/impl/apple/keychain_helper.hpp", + "src/object-store/src/impl/collection_change_builder.hpp", + "src/object-store/src/impl/collection_notifier.hpp", + "src/object-store/src/impl/epoll/external_commit_helper.hpp", + "src/object-store/src/impl/external_commit_helper.hpp", + "src/object-store/src/impl/generic/external_commit_helper.hpp", + "src/object-store/src/impl/list_notifier.hpp", + "src/object-store/src/impl/notification_wrapper.hpp", + "src/object-store/src/impl/object_accessor_impl.hpp", + "src/object-store/src/impl/object_notifier.hpp", + "src/object-store/src/impl/primitive_list_notifier.hpp", + "src/object-store/src/impl/realm_coordinator.hpp", + "src/object-store/src/impl/results_notifier.hpp", + "src/object-store/src/impl/transact_log_handler.hpp", + "src/object-store/src/impl/weak_realm_notifier.hpp", + "src/object-store/src/impl/windows/external_commit_helper.hpp", + "src/object-store/src/index_set.hpp", + "src/object-store/src/list.hpp", + "src/object-store/src/object.hpp", + "src/object-store/src/object_accessor.hpp", + "src/object-store/src/object_schema.hpp", + "src/object-store/src/object_store.hpp", + "src/object-store/src/parser/parser.hpp", + "src/object-store/src/parser/query_builder.hpp", + "src/object-store/src/property.hpp", + "src/object-store/src/results.hpp", + "src/object-store/src/schema.hpp", + "src/object-store/src/shared_realm.hpp", + "src/object-store/src/sync/impl/apple/network_reachability_observer.hpp", + "src/object-store/src/sync/impl/apple/system_configuration.hpp", + "src/object-store/src/sync/impl/network_reachability.hpp", + "src/object-store/src/sync/impl/sync_client.hpp", + "src/object-store/src/sync/impl/sync_file.hpp", + "src/object-store/src/sync/impl/sync_metadata.hpp", + "src/object-store/src/sync/partial_sync.hpp", + "src/object-store/src/sync/sync_config.hpp", + "src/object-store/src/sync/sync_manager.hpp", + "src/object-store/src/sync/sync_permission.hpp", + "src/object-store/src/sync/sync_session.hpp", + "src/object-store/src/sync/sync_user.hpp", + "src/object-store/src/thread_safe_reference.hpp", + "src/object-store/src/util/aligned_union.hpp", + "src/object-store/src/util/android/event_loop_signal.hpp", + "src/object-store/src/util/any.hpp", + "src/object-store/src/util/apple/event_loop_signal.hpp", + "src/object-store/src/util/atomic_shared_ptr.hpp", + "src/object-store/src/util/compiler.hpp", + "src/object-store/src/util/event_loop_signal.hpp", + "src/object-store/src/util/format.hpp", + "src/object-store/src/util/generic/event_loop_signal.hpp", + "src/object-store/src/util/tagged_bool.hpp", + "src/object-store/src/util/time.hpp", + "src/object-store/src/util/uuid.hpp", + "src/object-store/src/util/uv/event_loop_signal.hpp", ], "conditions": [ ["OS=='win'", { @@ -115,13 +177,15 @@ "target_name": "realm-core", "type": "none", "direct_dependent_settings": { - "libraries": [ "-lrealm<(debug_library_suffix)" ], "conditions": [ ["use_realm_debug", { "defines": [ "REALM_DEBUG=1" ] }] ] }, + "link_settings": { + "libraries": [ "-lrealm<(debug_library_suffix)" ], + }, "variables": { "prefix": " +#endif + namespace realm { class List; class Object; @@ -239,7 +243,23 @@ struct Unbox { if (ctx->is_null(value)) { return BinaryData(); } - ctx->m_owned_binary_data = js::Value::validated_to_binary(ctx->m_ctx, value, "Property"); +#if REALM_ENABLE_SYNC + // realm-sync holds the base64-decoding routine + if (js::Value::is_string(ctx->m_ctx, value)) { + // the incoming value might be a base64 string, so let's try to parse it + std::string str = js::Value::to_string(ctx->m_ctx, value); + size_t max_size = util::base64_decoded_size(str.size()); + std::unique_ptr data(new char[max_size]); + if (auto size = util::base64_decode(str, data.get(), max_size)) { + ctx->m_owned_binary_data = OwnedBinaryData(std::move(data), *size); + return ctx->m_owned_binary_data.get(); + } else { + throw std::runtime_error("Attempting to populate BinaryData from string that is not valid base64"); + } + } +#endif + + ctx->m_owned_binary_data = js::Value::validated_to_binary(ctx->m_ctx, value); return ctx->m_owned_binary_data.get(); } }; @@ -257,7 +277,14 @@ struct Unbox { if (ctx->is_null(value)) { return Timestamp(); } - auto date = js::Value::validated_to_date(ctx->m_ctx, value, "Property"); + typename JSEngine::Value date; + if (js::Value::is_string(ctx->m_ctx, value)) { + // the incoming value might be a date string, so let the Date constructor have at it + date = js::Value::to_date(ctx->m_ctx, value); + } else { + date = js::Value::validated_to_date(ctx->m_ctx, value); + } + double milliseconds = js::Value::to_number(ctx->m_ctx, date); int64_t seconds = milliseconds / 1000; int32_t nanoseconds = ((int64_t)milliseconds % 1000) * 1000000; diff --git a/src/js_realm.hpp b/src/js_realm.hpp index aa00e8bc..2672721b 100644 --- a/src/js_realm.hpp +++ b/src/js_realm.hpp @@ -198,6 +198,7 @@ public: static void get_in_memory(ContextType, ObjectType, ReturnValue &); static void get_read_only(ContextType, ObjectType, ReturnValue &); static void get_is_in_transaction(ContextType, ObjectType, ReturnValue &); + static void get_is_closed(ContextType, ObjectType, ReturnValue &); #if REALM_ENABLE_SYNC static void get_sync_session(ContextType, ObjectType, ReturnValue &); #endif @@ -259,6 +260,7 @@ public: {"inMemory", {wrap, nullptr}}, {"readOnly", {wrap, nullptr}}, {"isInTransaction", {wrap, nullptr}}, + {"isClosed", {wrap, nullptr}}, #if REALM_ENABLE_SYNC {"syncSession", {wrap, nullptr}}, #endif @@ -694,6 +696,11 @@ void RealmClass::get_is_in_transaction(ContextType ctx, ObjectType object, Re return_value.set(get_internal>(object)->get()->is_in_transaction()); } +template +void RealmClass::get_is_closed(ContextType ctx, ObjectType object, ReturnValue &return_value) { + return_value.set(get_internal>(object)->get()->is_closed()); +} + #if REALM_ENABLE_SYNC template void RealmClass::get_sync_session(ContextType ctx, ObjectType object, ReturnValue &return_value) { @@ -738,7 +745,7 @@ void RealmClass::wait_for_download_completion(ContextType ctx, ObjectType thi ValueType callback_arguments[1]; callback_arguments[0] = object; - + Function::callback(protected_ctx, protected_callback, typename T::Object(), 1, callback_arguments); } diff --git a/src/js_types.hpp b/src/js_types.hpp index 64f78096..0c7e5309 100644 --- a/src/js_types.hpp +++ b/src/js_types.hpp @@ -389,9 +389,9 @@ inline bool Value::is_valid_for_property_type(ContextType context, const Valu case PropertyType::String: return is_string(context, value); case PropertyType::Data: - return is_binary(context, value); + return is_binary(context, value) || is_string(context, value); case PropertyType::Date: - return is_date(context, value); + return is_date(context, value) || is_string(context, value); case PropertyType::Object: return true; case PropertyType::Any: diff --git a/src/jsc/jsc_value.hpp b/src/jsc/jsc_value.hpp index 4d4cab89..5c113e56 100644 --- a/src/jsc/jsc_value.hpp +++ b/src/jsc/jsc_value.hpp @@ -203,6 +203,15 @@ inline JSObjectRef jsc::Value::to_constructor(JSContextRef ctx, const JSValueRef template<> inline JSObjectRef jsc::Value::to_date(JSContextRef ctx, const JSValueRef &value) { + if (JSValueIsString(ctx, value)) { + JSValueRef error; + std::array args { value }; + if (JSObjectRef result = JSObjectMakeDate(ctx, args.size(), args.data(), &error)) { + return result; + } else { + throw jsc::Exception(ctx, error); + } + } return to_object(ctx, value); } diff --git a/src/node/node_init.hpp b/src/node/node_init.hpp index f2a9cbca..dfc795b6 100644 --- a/src/node/node_init.hpp +++ b/src/node/node_init.hpp @@ -21,9 +21,9 @@ #include "node_string.hpp" #include "node_protected.hpp" #include "node_context.hpp" -#include "node_value.hpp" #include "node_object.hpp" #include "node_function.hpp" +#include "node_value.hpp" #include "node_exception.hpp" #include "node_return_value.hpp" #include "node_class.hpp" diff --git a/src/node/node_value.hpp b/src/node/node_value.hpp index 20dc7d8e..1339028f 100644 --- a/src/node/node_value.hpp +++ b/src/node/node_value.hpp @@ -204,11 +204,6 @@ inline v8::Local node::Value::to_array(v8::Isolate* isolate, const v return to_object(isolate, value); } -template<> -inline v8::Local node::Value::to_date(v8::Isolate* isolate, const v8::Local &value) { - return to_object(isolate, value); -} - template<> inline v8::Local node::Value::to_function(v8::Isolate* isolate, const v8::Local &value) { return value->IsFunction() ? v8::Local::Cast(value) : v8::Local(); @@ -218,6 +213,16 @@ template<> inline v8::Local node::Value::to_constructor(v8::Isolate* isolate, const v8::Local &value) { return to_function(isolate, value); } - + +template<> +inline v8::Local node::Value::to_date(v8::Isolate* isolate, const v8::Local &value) { + if (value->IsString()) { + v8::Local date_constructor = to_constructor(isolate, node::Object::get_property(isolate, isolate->GetCurrentContext()->Global(), "Date")); + std::array, 1> args { {value} }; + return node::Function::construct(isolate, date_constructor, args.size(), args.data()); + } + return to_object(isolate, value); +} + } // js } // realm diff --git a/tests/js/list-tests.js b/tests/js/list-tests.js index 17d978d6..417cd5b6 100644 --- a/tests/js/list-tests.js +++ b/tests/js/list-tests.js @@ -39,7 +39,6 @@ module.exports = { }); TestCase.assertThrowsContaining(() => new Realm.List(), 'constructor'); - TestCase.assertType(Realm.List, 'function'); TestCase.assertInstanceOf(Realm.List, Function); }, diff --git a/tests/js/object-tests.js b/tests/js/object-tests.js index 0b19e20e..88792067 100644 --- a/tests/js/object-tests.js +++ b/tests/js/object-tests.js @@ -297,6 +297,15 @@ module.exports = { }); TestCase.assertArraysEqual(new Uint8Array(object.dataCol), RANDOM_DATA); + if (Realm.Sync) { + // The base64 decoder comes from realm-sync + // Should be able to also set a data property to base64-encoded string. + realm.write(function() { + object.dataCol = require('buffer/').Buffer.from(RANDOM_DATA).toString('base64'); + }); + TestCase.assertArraysEqual(new Uint8Array(object.dataCol), RANDOM_DATA); + } + // Should be to set a data property to a DataView. realm.write(function() { object.dataCol = new DataView(RANDOM_DATA.buffer); @@ -348,7 +357,7 @@ module.exports = { object.dataCol = 1; }); TestCase.assertThrows(function() { - object.dataCol = 'data'; + object.dataCol = 'some binary data'; }); TestCase.assertThrows(function() { object.dataCol = [1]; @@ -431,15 +440,18 @@ module.exports = { // test different dates var realm = new Realm({schema: [schemas.DateObject]}); + const stringifiedDate = new Date(); realm.write(function() { realm.create('Date', { currentDate: new Date(10000) }); realm.create('Date', { currentDate: new Date(-10000) }); realm.create('Date', { currentDate: new Date(1000000000000) }); realm.create('Date', { currentDate: new Date(-1000000000000) }); + realm.create('Date', { currentDate: stringifiedDate.toString() }); }); TestCase.assertEqual(realm.objects('Date')[0].currentDate.getTime(), 10000); TestCase.assertEqual(realm.objects('Date')[1].currentDate.getTime(), -10000); TestCase.assertEqual(realm.objects('Date')[2].currentDate.getTime(), 1000000000000); TestCase.assertEqual(realm.objects('Date')[3].currentDate.getTime(), -1000000000000); + TestCase.assertEqual(realm.objects('Date')[4].currentDate.toString(), stringifiedDate.toString()); } }; diff --git a/tests/js/package.json b/tests/js/package.json index c7afa5d5..4a67b4e0 100644 --- a/tests/js/package.json +++ b/tests/js/package.json @@ -3,6 +3,7 @@ "version": "0.0.1", "private": true, "dependencies": { + "buffer": "^5.0.8", "es6-promise": "^3.2.1" } } diff --git a/tests/js/realm-tests.js b/tests/js/realm-tests.js index 665cbc9b..74538114 100644 --- a/tests/js/realm-tests.js +++ b/tests/js/realm-tests.js @@ -57,6 +57,13 @@ module.exports = { TestCase.assertEqual(realm2.path, defaultDir + testPath2); }, + testRealmIsClosed: function() { + const realm = new Realm({schema: []}); + TestCase.assertFalse(realm.isClosed); + realm.close(); + TestCase.assertTrue(realm.isClosed); + }, + testRealmConstructorSchemaVersion: function() { const defaultRealm = new Realm({schema: []}); TestCase.assertEqual(defaultRealm.schemaVersion, 0); diff --git a/tests/js/results-tests.js b/tests/js/results-tests.js index b6a74033..a6fd668b 100644 --- a/tests/js/results-tests.js +++ b/tests/js/results-tests.js @@ -451,11 +451,11 @@ module.exports = { }); return new Promise((r, _reject) => { - resolve = r; - realm.write(() => { - realm.create('TestObject', { doubleCol: 1 }); - }); + resolve = r; + realm.write(() => { + realm.create('TestObject', { doubleCol: 1 }); }); + }); }, testResultsAggregateFunctions: function() { diff --git a/tests/js/user-tests.js b/tests/js/user-tests.js index b1c02b3a..404ba1fa 100644 --- a/tests/js/user-tests.js +++ b/tests/js/user-tests.js @@ -160,6 +160,20 @@ module.exports = { .catch((e) => assertIsError(e)); }, + testLoginTowardsMisbehavingServer() { + const username = uuid(); + + // Try authenticating towards a server thats clearly not ROS + return Realm.Sync.User.register('https://github.com/realm/realm-js', username, 'user') + .catch((e) => { + assertIsError(e); + TestCase.assertEqual( + e.message, + "Could not authenticate: Realm Object Server didn't respond with valid JSON" + ); + }); + }, + testAll() { const all = Realm.Sync.User.all; TestCase.assertArrayLength(Object.keys(all), 0); @@ -324,4 +338,3 @@ module.exports = { }, */ }; - diff --git a/vendor/json.hpp b/vendor/json.hpp index b20cc48d..a3e2d380 100644 --- a/vendor/json.hpp +++ b/vendor/json.hpp @@ -8333,15 +8333,15 @@ class basic_json // check if buffer was large enough assert(static_cast(written_bytes) < m_buf.size()); + #if defined(ANDROID) + // Android NDK doesn't have access to locale info yet; API < 21 doesn't have localeconv() + const char thousands_sep = ','; + const char decimal_point = '.'; + #else // read information from locale const auto loc = localeconv(); assert(loc != nullptr); - #if defined(ANDROID) - // Android NDK doesn't have access to locale info yet - const char thousands_sep = ','; - const char decimal_point = '.'; - #else const char thousands_sep = !loc->thousands_sep ? '\0' : loc->thousands_sep[0]; @@ -11176,11 +11176,11 @@ basic_json_parser_74: // since dealing with strtod family of functions, we're // getting the decimal point char from the C locale facilities // instead of C++'s numpunct facet of the current std::locale - const auto loc = localeconv(); - assert(loc != nullptr); #if defined(ANDROID) const char decimal_point_char = '.'; #else + const auto loc = localeconv(); + assert(loc != nullptr); const char decimal_point_char = (loc->decimal_point == nullptr) ? '.' : loc->decimal_point[0]; #endif