From b9b3812c8693f397fda6a2cec70b1daeb64f56b7 Mon Sep 17 00:00:00 2001 From: Ari Lazier Date: Thu, 28 Apr 2016 13:56:49 -0700 Subject: [PATCH 1/5] support for read-only realms --- src/js_realm.hpp | 18 +++++++++++------- tests/js/realm-tests.js | 21 +++++++++++++++++++++ 2 files changed, 32 insertions(+), 7 deletions(-) diff --git a/src/js_realm.hpp b/src/js_realm.hpp index 417364a5..e3c33e04 100644 --- a/src/js_realm.hpp +++ b/src/js_realm.hpp @@ -246,12 +246,6 @@ inline typename T::Function Realm::create_constructor(ContextType ctx) { template void Realm::constructor(ContextType ctx, ObjectType this_object, size_t argc, const ValueType arguments[]) { - static const String path_string = "path"; - static const String schema_string = "schema"; - static const String schema_version_string = "schemaVersion"; - static const String encryption_key_string = "encryptionKey"; - static const String migration_string = "migration"; - realm::Realm::Config config; typename Schema::ObjectDefaultsMap defaults; typename Schema::ConstructorMap constructors; @@ -267,6 +261,7 @@ void Realm::constructor(ContextType ctx, ObjectType this_object, size_t argc, else if (Value::is_object(ctx, value)) { ObjectType object = Value::validated_to_object(ctx, value); + static const String path_string = "path"; ValueType path_value = Object::get_property(ctx, object, path_string); if (!Value::is_undefined(ctx, path_value)) { config.path = Value::validated_to_string(ctx, path_value, "path"); @@ -274,13 +269,19 @@ void Realm::constructor(ContextType ctx, ObjectType this_object, size_t argc, else { config.path = js::default_path(); } + + static const String read_only_string = "readOnly"; + ValueType read_only_value = Object::get_property(ctx, object, read_only_string); + config.read_only = Value::is_undefined(ctx, read_only_value) ? false : Value::validated_to_boolean(ctx, read_only_value, "readOnly"); + static const String schema_string = "schema"; ValueType schema_value = Object::get_property(ctx, object, schema_string); if (!Value::is_undefined(ctx, schema_value)) { ObjectType schema_object = Value::validated_to_object(ctx, schema_value, "schema"); config.schema.reset(new realm::Schema(Schema::parse_schema(ctx, schema_object, defaults, constructors))); } + static const String schema_version_string = "schemaVersion"; ValueType version_value = Object::get_property(ctx, object, schema_version_string); if (!Value::is_undefined(ctx, version_value)) { config.schema_version = Value::validated_to_number(ctx, version_value, "schemaVersion"); @@ -288,7 +289,8 @@ void Realm::constructor(ContextType ctx, ObjectType this_object, size_t argc, else { config.schema_version = 0; } - + + static const String migration_string = "migration"; ValueType migration_value = Object::get_property(ctx, object, migration_string); if (!Value::is_undefined(ctx, migration_value)) { FunctionType migration_function = Value::validated_to_function(ctx, migration_value, "migration"); @@ -301,6 +303,8 @@ void Realm::constructor(ContextType ctx, ObjectType this_object, size_t argc, }; } + + static const String encryption_key_string = "encryptionKey"; ValueType encryption_key_value = Object::get_property(ctx, object, encryption_key_string); if (!Value::is_undefined(ctx, encryption_key_value)) { std::string encryption_key = NativeAccessor::to_binary(ctx, encryption_key_value); diff --git a/tests/js/realm-tests.js b/tests/js/realm-tests.js index b83462e3..c8df1596 100644 --- a/tests/js/realm-tests.js +++ b/tests/js/realm-tests.js @@ -119,6 +119,27 @@ module.exports = BaseTest.extend({ }, 'The schema should be an array of ObjectSchema objects'); }, + testRealmConstructorReadOnly: function() { + var realm = new Realm({schema: [schemas.TestObject]}); + realm.write(function() { + realm.create('TestObject', [1]) + }); + realm.close(); + + realm = new Realm({readOnly: true, schema: [schemas.TestObject]}); + var objects = realm.objects('TestObject'); + TestCase.assertEqual(objects.length, 1); + TestCase.assertEqual(objects[0].doubleCol, 1.0); + + TestCase.assertThrows(function() { + realm.write(function() {}); + }); + realm.close(); + + realm = new Realm({readOnly: true}); + TestCase.assertEqual(realm.schema.length, 1); + }, + testDefaultPath: function() { var defaultRealm = new Realm({schema: []}); TestCase.assertEqual(defaultRealm.path, Realm.defaultPath); From 2b3536011751b7e2641e40530cc0a5815005931f Mon Sep 17 00:00:00 2001 From: Ari Lazier Date: Thu, 28 Apr 2016 15:50:43 -0700 Subject: [PATCH 2/5] add readOnly property --- lib/browser/index.js | 2 ++ src/js_realm.hpp | 7 +++++++ tests/js/realm-tests.js | 3 +++ 3 files changed, 12 insertions(+) diff --git a/lib/browser/index.js b/lib/browser/index.js index 64ca70b7..583d897c 100644 --- a/lib/browser/index.js +++ b/lib/browser/index.js @@ -71,6 +71,8 @@ export default class Realm { [ 'path', + 'readOnly', + 'schema', 'schemaVersion', ].forEach((name) => { Object.defineProperty(this, name, {get: util.getterForProperty(name)}); diff --git a/src/js_realm.hpp b/src/js_realm.hpp index e3c33e04..ce046a11 100644 --- a/src/js_realm.hpp +++ b/src/js_realm.hpp @@ -148,6 +148,7 @@ class Realm { static void get_path(ContextType, ObjectType, ReturnValue &); static void get_schema_version(ContextType, ObjectType, ReturnValue &); static void get_schema(ContextType, ObjectType, ReturnValue &); + static void get_read_only(ContextType, ObjectType, ReturnValue &); // static methods static void constructor(ContextType, ObjectType, size_t, const ValueType[]); @@ -224,6 +225,7 @@ struct RealmClass : ClassDefinition { {"path", {wrap, nullptr}}, {"schemaVersion", {wrap, nullptr}}, {"schema", {wrap, nullptr}}, + {"readOnly", {wrap, nullptr}}, }; }; @@ -387,6 +389,11 @@ void Realm::get_schema(ContextType ctx, ObjectType object, ReturnValue &retur return_value.set(Schema::object_for_schema(ctx, *schema)); } +template +void Realm::get_read_only(ContextType ctx, ObjectType object, ReturnValue &return_value) { + return_value.set(get_internal>(object)->get()->config().read_only); +} + template void Realm::objects(ContextType ctx, ObjectType this_object, size_t argc, const ValueType arguments[], ReturnValue &return_value) { validate_argument_count(argc, 1); diff --git a/tests/js/realm-tests.js b/tests/js/realm-tests.js index c8df1596..35294bd4 100644 --- a/tests/js/realm-tests.js +++ b/tests/js/realm-tests.js @@ -124,12 +124,14 @@ module.exports = BaseTest.extend({ realm.write(function() { realm.create('TestObject', [1]) }); + TestCase.assertEqual(realm.readOnly, false); realm.close(); realm = new Realm({readOnly: true, schema: [schemas.TestObject]}); var objects = realm.objects('TestObject'); TestCase.assertEqual(objects.length, 1); TestCase.assertEqual(objects[0].doubleCol, 1.0); + TestCase.assertEqual(realm.readOnly, true); TestCase.assertThrows(function() { realm.write(function() {}); @@ -138,6 +140,7 @@ module.exports = BaseTest.extend({ realm = new Realm({readOnly: true}); TestCase.assertEqual(realm.schema.length, 1); + TestCase.assertEqual(realm.readOnly, true); }, testDefaultPath: function() { From 85919dc66f67ea69a86fe0f37b6f539692463267 Mon Sep 17 00:00:00 2001 From: Scott Kyle Date: Thu, 28 Apr 2016 16:22:16 -0700 Subject: [PATCH 3/5] Fix realm.schema property in Chrome debug mode --- lib/browser/rpc.js | 2 +- src/rpc.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/browser/rpc.js b/lib/browser/rpc.js index 8d8e0ca5..8e729076 100644 --- a/lib/browser/rpc.js +++ b/lib/browser/rpc.js @@ -152,7 +152,7 @@ function deserializeDict(realmId, info) { let object = {}; for (let i = 0, len = keys.length; i < len; i++) { - object[keys[i]] = values[i]; + object[keys[i]] = deserialize(realmId, values[i]); } return object; diff --git a/src/rpc.cpp b/src/rpc.cpp index e30a8efd..2599df1d 100644 --- a/src/rpc.cpp +++ b/src/rpc.cpp @@ -275,7 +275,7 @@ json RPCServer::serialize_json_value(JSValueRef js_value) { JSValueRef js_value = jsc::Object::get_property(m_context, js_object, js_key); keys.push_back(js_key); - values.push_back(js_value); + values.push_back(serialize_json_value(js_value)); } return { From 950b75fd2f0cb07460ab8ea50044cf9813a1af96 Mon Sep 17 00:00:00 2001 From: Scott Kyle Date: Thu, 28 Apr 2016 16:36:07 -0700 Subject: [PATCH 4/5] Fix broken testResultsInvalidation test on Chrome We needed more actions to actually get sent over the RPC. --- lib/browser/collections.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/lib/browser/collections.js b/lib/browser/collections.js index a35dd465..b6091fa2 100644 --- a/lib/browser/collections.js +++ b/lib/browser/collections.js @@ -54,7 +54,7 @@ export function fireMutationListeners(realmId) { export function createCollection(prototype, realmId, info, mutable) { let collection = Object.create(prototype); - let size = 0; + let size; Object.defineProperties(collection, { 'length': { @@ -70,7 +70,10 @@ export function createCollection(prototype, realmId, info, mutable) { length = collection.length; } if (length == size) { - return; + return; // Nothing has changed. + } + if (size == null) { + size = 0; // This is first pass. } let props = {}; @@ -79,7 +82,7 @@ export function createCollection(prototype, realmId, info, mutable) { for (let i = size; i < length; i++) { props[i] = { get: getterForProperty(i), - set: mutable ? setterForProperty(i) : undefined, + set: setterForProperty(i), enumerable: true, configurable: true, }; @@ -93,7 +96,8 @@ export function createCollection(prototype, realmId, info, mutable) { // Helpfully throw an exception on attempts to set to one past the last index. props[length] = { - value: undefined, + get: getterForProperty(length), + set: setterForProperty(length), configurable: true, }; From 5a9e24cb06ec17684f6ca81399a5ee5b74c052ed Mon Sep 17 00:00:00 2001 From: Ari Lazier Date: Fri, 29 Apr 2016 13:11:19 -0700 Subject: [PATCH 5/5] tab to space --- src/js_realm.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/js_realm.hpp b/src/js_realm.hpp index ce046a11..45b6b8c3 100644 --- a/src/js_realm.hpp +++ b/src/js_realm.hpp @@ -292,7 +292,7 @@ void Realm::constructor(ContextType ctx, ObjectType this_object, size_t argc, config.schema_version = 0; } - static const String migration_string = "migration"; + static const String migration_string = "migration"; ValueType migration_value = Object::get_property(ctx, object, migration_string); if (!Value::is_undefined(ctx, migration_value)) { FunctionType migration_function = Value::validated_to_function(ctx, migration_value, "migration");