diff --git a/CHANGELOG.md b/CHANGELOG.md index c9e4ebed..1ca1ce6e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,7 @@ X.Y.Z Release notes * None. ### Enhancements -* None. +* Add the `oldModifications` and `newModifications` properties to the listener change objects, which report the indices that changed in the collection both before and after the changes being notified for. The `modifications` property is kept as an alias for `oldModifications` but might be removed in a future version. ### Bug fixes * [Sync] Fixed a bug which crash query-based Realms. A bug in gcc's optimizer will generate code which in some case will lead to a memory violation and eventually a segmentation fault. diff --git a/docs/collection.js b/docs/collection.js index 53e5e7ed..07c92472 100644 --- a/docs/collection.js +++ b/docs/collection.js @@ -427,22 +427,19 @@ class Collection { * @param {function(collection, changes)} callback - A function to be called when changes occur. * The callback function is called with two arguments: * - `collection`: the collection instance that changed, - * - `changes`: a dictionary with keys `insertions`, `modifications` and `deletions`, - * each containing a list of indices that were inserted, updated or deleted respectively. If - * partial sync is enabled, an additional key `partial_sync` is added. - * - `changes.partial_sync`: `error` indicates if an error has occurred, `old_state` is the previous - * state, and `new_state` is the current state. + * - `changes`: a dictionary with keys `insertions`, `newModifications`, `oldModifications` + * and `deletions`, each containing a list of indices in the collection that were + * inserted, updated or deleted respectively. `deletions` and `oldModifications` are + * indices into the collection before the change happened, while `insertions` and + * `newModifications` are indices into the new version of the collection. * @throws {Error} If `callback` is not a function. * @example * wines.addListener((collection, changes) => { * // collection === wines - * if (changes.partial_sync.new_state == Realm.Sync.SubscriptionState.Initialized) { - * console.log('Our subset is ready'); - * console.log(`${changes.insertions.length} insertions`); - * console.log(`${changes.modifications.length} modifications`); - * console.log(`${changes.deletions.length} deletions`); - * console.log(`new size of collection: ${collection.length}`); - * } + * console.log(`${changes.insertions.length} insertions`); + * console.log(`${changes.modifications.length} modifications`); + * console.log(`${changes.deletions.length} deletions`); + * console.log(`new size of collection: ${collection.length}`); * }); */ addListener(callback) {} diff --git a/lib/index.d.ts b/lib/index.d.ts index a810d858..11ba8602 100644 --- a/lib/index.d.ts +++ b/lib/index.d.ts @@ -140,6 +140,8 @@ declare namespace Realm { insertions: number[]; deletions: number[]; modifications: number[]; + newModifications: number[]; + oldModifications: number[]; } type CollectionChangeCallback = (collection: Collection, change: CollectionChangeSet) => void; diff --git a/src/js_collection.hpp b/src/js_collection.hpp index a83db75f..f75e2823 100644 --- a/src/js_collection.hpp +++ b/src/js_collection.hpp @@ -50,27 +50,28 @@ template typename T::Value CollectionClass::create_collection_change_set(ContextType ctx, const CollectionChangeSet &change_set) { ObjectType object = Object::create_empty(ctx); - std::vector deletions, insertions, modifications; + std::vector scratch; + auto make_array = [&](realm::IndexSet const& index_set) { + scratch.clear(); + scratch.reserve(index_set.count()); + for (auto index : index_set.as_indexes()) { + scratch.push_back(Value::from_number(ctx, index)); + } + return Object::create_array(ctx, scratch); + }; if (change_set.deletions.count() == std::numeric_limits::max()) { - deletions.push_back(Value::from_null(ctx)); + Object::set_property(ctx, object, "deletions", Object::create_array(ctx, {Value::from_null(ctx)})); } else { - for (auto index : change_set.deletions.as_indexes()) { - deletions.push_back(Value::from_number(ctx, index)); - } + Object::set_property(ctx, object, "deletions", make_array(change_set.deletions)); } - Object::set_property(ctx, object, "deletions", Object::create_array(ctx, deletions)); + Object::set_property(ctx, object, "insertions", make_array(change_set.insertions)); + Object::set_property(ctx, object, "newModifications", make_array(change_set.modifications_new)); - for (auto index : change_set.insertions.as_indexes()) { - insertions.push_back(Value::from_number(ctx, index)); - } - Object::set_property(ctx, object, "insertions", Object::create_array(ctx, insertions)); - - for (auto index : change_set.modifications.as_indexes()) { - modifications.push_back(Value::from_number(ctx, index)); - } - Object::set_property(ctx, object, "modifications", Object::create_array(ctx, modifications)); + auto old_modifications = make_array(change_set.modifications); + Object::set_property(ctx, object, "modifications", old_modifications); + Object::set_property(ctx, object, "oldModifications", old_modifications); return object; } diff --git a/tests/js/results-tests.js b/tests/js/results-tests.js index adb345bf..09b234c7 100644 --- a/tests/js/results-tests.js +++ b/tests/js/results-tests.js @@ -452,10 +452,16 @@ module.exports = { if (first) { TestCase.assertEqual(testObjects.length, 3); TestCase.assertEqual(changes.insertions.length, 0); + TestCase.assertEqual(changes.modifications.length, 0); + TestCase.assertEqual(changes.newModifications.length, 0); + TestCase.assertEqual(changes.oldModifications.length, 0); } else { TestCase.assertEqual(testObjects.length, 4); TestCase.assertEqual(changes.insertions.length, 1); + TestCase.assertEqual(changes.modifications.length, 1); + TestCase.assertEqual(changes.newModifications.length, 1); + TestCase.assertEqual(changes.oldModifications.length, 1); } first = false; resolve(); @@ -464,6 +470,7 @@ module.exports = { return new Promise((r, _reject) => { resolve = r; realm.write(() => { + realm.objects('TestObject')[0].doubleCol = 5; realm.create('TestObject', { doubleCol: 1 }); }); });