diff --git a/CHANGELOG.md b/CHANGELOG.md index e0bdfb8f..173931a3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ X.Y.Z Release notes * Added additional parameter for `Realm.open` and `Realm.openAsync` for download progress notifications * Added `Realm.deleteFile` for deleting a Realm (#363). * Added `Realm.deleteModel` for deleting a Realm model in a migration (#573). +* Added support for in-memory Realms. * `Realm.Sync.User.login`, `Realm.Sync.User.register`, and `Realm.Sync.User.registerWithProvider` return Promises and deprecate the callback style for them. Callbacks will continue to work for backward compatibility. ### Bug fixes diff --git a/docs/realm.js b/docs/realm.js index be25e46b..b6055106 100644 --- a/docs/realm.js +++ b/docs/realm.js @@ -278,6 +278,11 @@ Realm.defaultPath; * will be skipped if another process is accessing it. * @property {string} [path={@link Realm.defaultPath}] - The path to the file where the * Realm database should be stored. + * @property {boolean} [inMemory=false] - Specifies if this Realm should be opened in-memory. This + * still requires a path (can be the default path) to identify the Realm so other processes can + * open the same Realm. The file will also be used as swap space if the Realm becomes bigger than + * what fits in memory, but it is not persistent and will be removed when the last instance + * is closed. * @property {boolean} [readOnly=false] - Specifies if this Realm should be opened as read-only. * @property {Array} [schema] - Specifies all the * object types in this Realm. **Required** when first creating a Realm at this `path`. diff --git a/lib/browser/index.js b/lib/browser/index.js index cb285f8e..10bc7512 100644 --- a/lib/browser/index.js +++ b/lib/browser/index.js @@ -55,6 +55,7 @@ function setupRealm(realm, realmId) { 'empty', 'path', 'readOnly', + 'inMemory', 'schema', 'schemaVersion', 'syncSession', diff --git a/lib/index.d.ts b/lib/index.d.ts index 804cdc82..19e9a085 100644 --- a/lib/index.d.ts +++ b/lib/index.d.ts @@ -80,6 +80,7 @@ declare namespace Realm { shouldCompactOnLaunch?: (totalBytes: number, usedBytes: number) => boolean; path?: string; readOnly?: boolean; + inMemory?: boolean; schema?: ObjectClass[] | ObjectSchema[]; schemaVersion?: number; sync?: Realm.Sync.SyncConfiguration; diff --git a/src/js_realm.hpp b/src/js_realm.hpp index 6bfdb496..931b4d3d 100644 --- a/src/js_realm.hpp +++ b/src/js_realm.hpp @@ -187,6 +187,7 @@ public: 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_in_memory(ContextType, ObjectType, ReturnValue &); static void get_read_only(ContextType, ObjectType, ReturnValue &); static void get_is_in_transaction(ContextType, ObjectType, ReturnValue &); #if REALM_ENABLE_SYNC @@ -243,6 +244,7 @@ public: {"path", {wrap, nullptr}}, {"schemaVersion", {wrap, nullptr}}, {"schema", {wrap, nullptr}}, + {"inMemory", {wrap, nullptr}}, {"readOnly", {wrap, nullptr}}, {"isInTransaction", {wrap, nullptr}}, #if REALM_ENABLE_SYNC @@ -380,6 +382,12 @@ void RealmClass::constructor(ContextType ctx, ObjectType this_object, size_t else if (config.path.empty()) { config.path = js::default_path(); } + + static const String in_memory_string = "inMemory"; + ValueType in_memory_value = Object::get_property(ctx, object, in_memory_string); + if (!Value::is_undefined(ctx, in_memory_value) && Value::validated_to_boolean(ctx, in_memory_value, "inMemory")) { + config.in_memory = true; + } static const String read_only_string = "readOnly"; ValueType read_only_value = Object::get_property(ctx, object, read_only_string); @@ -606,6 +614,11 @@ void RealmClass::get_schema(ContextType ctx, ObjectType object, ReturnValue & return_value.set(Schema::object_for_schema(ctx, schema)); } +template +void RealmClass::get_in_memory(ContextType ctx, ObjectType object, ReturnValue &return_value) { + return_value.set(get_internal>(object)->get()->config().in_memory); +} + template void RealmClass::get_read_only(ContextType ctx, ObjectType object, ReturnValue &return_value) { return_value.set(get_internal>(object)->get()->config().read_only()); diff --git a/tests/js/realm-tests.js b/tests/js/realm-tests.js index e98db623..fb52b048 100644 --- a/tests/js/realm-tests.js +++ b/tests/js/realm-tests.js @@ -161,6 +161,36 @@ module.exports = { }]}); }, "Property 'InvalidObject.link' declared as origin of linking objects property 'InvalidObject.linkingObjects' links to type 'IntObject'") }, + + testRealmConstructorInMemory: function() { + // open in-memory realm instance + const realm1 = new Realm({inMemory: true, schema: [schemas.TestObject]}); + realm1.write(function() { + realm1.create('TestObject', [1]) + }); + TestCase.assertEqual(realm1.inMemory, true); + + // open a second instance of the same realm and check that they share data + const realm2 = new Realm({inMemory: true}); + const objects = realm2.objects('TestObject'); + TestCase.assertEqual(objects.length, 1); + TestCase.assertEqual(objects[0].doubleCol, 1.0); + TestCase.assertEqual(realm2.inMemory, true); + + // Close both realms (this should delete the realm since there are no more + // references to it. + realm1.close(); + realm2.close(); + + // Open the same in-memory realm again and verify that it is now empty + const realm3 = new Realm({inMemory: true}); + TestCase.assertEqual(realm3.schema.length, 0); + + // try to open the same realm in persistent mode (should fail as you cannot mix modes) + TestCase.assertThrows(function() { + const realm4 = new Realm({}); + }); + }, testRealmConstructorReadOnly: function() { var realm = new Realm({schema: [schemas.TestObject]});