diff --git a/src/js_list.hpp b/src/js_list.hpp index 18f07777..d936159c 100644 --- a/src/js_list.hpp +++ b/src/js_list.hpp @@ -57,7 +57,8 @@ struct ListClass : ClassDefinition> { static void snapshot(ContextType, ObjectType, size_t, const ValueType[], ReturnValue &); static void filtered(ContextType, ObjectType, size_t, const ValueType[], ReturnValue &); static void sorted(ContextType, ObjectType, size_t, const ValueType[], ReturnValue &); - + static void is_valid(ContextType, ObjectType, size_t, const ValueType [], ReturnValue &); + std::string const name = "List"; MethodMap const methods = { @@ -69,6 +70,7 @@ struct ListClass : ClassDefinition> { {"snapshot", wrap}, {"filtered", wrap}, {"sorted", wrap}, + {"isValid", wrap}, }; PropertyMap const properties = { @@ -224,5 +226,10 @@ void ListClass::sorted(ContextType ctx, ObjectType this_object, size_t argc, return_value.set(ResultsClass::create_sorted(ctx, *list, argc, arguments)); } +template +void ListClass::is_valid(ContextType ctx, ObjectType this_object, size_t argc, const ValueType arguments[], ReturnValue &return_value) { + return_value.set(get_internal>(this_object)->is_valid()); +} + } // js } // realm diff --git a/src/js_realm.hpp b/src/js_realm.hpp index d7b427ee..8a96e862 100644 --- a/src/js_realm.hpp +++ b/src/js_realm.hpp @@ -247,14 +247,14 @@ inline typename T::Function RealmClass::create_constructor(ContextType ctx) { return realm_constructor; } -static void convert_outdated_datetime_columns(const SharedRealm &realm) { +static inline void convert_outdated_datetime_columns(const SharedRealm &realm) { if (realm->config().upgrade_initial_version != realm->config().upgrade_final_version && realm->config().upgrade_initial_version < 5) { // any versions earlier than file format 5 are stored as milliseconds and need to be converted to the new format for (auto& object_schema : *realm->config().schema) { auto table = ObjectStore::table_for_object_type(realm->read_group(), object_schema.name); for (auto& property : object_schema.properties) { - if (property.type == PropertyTypeDate) { + if (property.type == realm::PropertyType::Date) { if (!realm->is_in_transaction()) { realm->begin_transaction(); } diff --git a/src/js_results.hpp b/src/js_results.hpp index 9d025c86..9f021fb7 100644 --- a/src/js_results.hpp +++ b/src/js_results.hpp @@ -55,6 +55,7 @@ struct ResultsClass : ClassDefinition> { static void snapshot(ContextType, ObjectType, size_t, const ValueType[], ReturnValue &); static void filtered(ContextType, ObjectType, size_t, const ValueType[], ReturnValue &); static void sorted(ContextType, ObjectType, size_t, const ValueType[], ReturnValue &); + static void is_valid(ContextType, ObjectType, size_t, const ValueType [], ReturnValue &); std::string const name = "Results"; @@ -62,6 +63,7 @@ struct ResultsClass : ClassDefinition> { {"snapshot", wrap}, {"filtered", wrap}, {"sorted", wrap}, + {"isValid", wrap}, }; PropertyMap const properties = { @@ -233,5 +235,10 @@ void ResultsClass::sorted(ContextType ctx, ObjectType this_object, size_t arg return_value.set(create_sorted(ctx, *results, argc, arguments)); } +template +void ResultsClass::is_valid(ContextType ctx, ObjectType this_object, size_t argc, const ValueType arguments[], ReturnValue &return_value) { + return_value.set(get_internal>(this_object)->is_valid()); +} + } // js } // realm diff --git a/src/object-store/src/results.cpp b/src/object-store/src/results.cpp index f2961337..1daa32fc 100644 --- a/src/object-store/src/results.cpp +++ b/src/object-store/src/results.cpp @@ -90,15 +90,23 @@ Results::~Results() } } +bool Results::is_valid() const +{ + if (m_table && !m_table->is_attached()) + return false; + if (m_mode == Mode::TableView && (!m_table_view.is_attached() || m_table_view.depends_on_deleted_object())) + return false; + if (m_mode == Mode::LinkView && !m_link_view->is_attached()) + return false; + + return true; +} + void Results::validate_read() const { if (m_realm) m_realm->verify_thread(); - if (m_table && !m_table->is_attached()) - throw InvalidatedException(); - if (m_mode == Mode::TableView && (!m_table_view.is_attached() || m_table_view.depends_on_deleted_object())) - throw InvalidatedException(); - if (m_mode == Mode::LinkView && !m_link_view->is_attached()) + if (!is_valid()) throw InvalidatedException(); } diff --git a/src/object-store/src/results.hpp b/src/object-store/src/results.hpp index 6b25982a..c8a02f44 100644 --- a/src/object-store/src/results.hpp +++ b/src/object-store/src/results.hpp @@ -193,6 +193,9 @@ public: static void set_table_view(Results& results, TableView&& tv); }; + // Returns if this Results class is still valid + bool is_valid() const; + private: SharedRealm m_realm; const ObjectSchema *m_object_schema; diff --git a/tests/js/list-tests.js b/tests/js/list-tests.js index ab8f8472..8fadfb5c 100644 --- a/tests/js/list-tests.js +++ b/tests/js/list-tests.js @@ -627,4 +627,25 @@ module.exports = BaseTest.extend({ }); }); }, + + testIsValid: function() { + var realm = new Realm({schema: [schemas.PersonObject, schemas.PersonList]}); + var object; + var list; + realm.write(function() { + object = realm.create('PersonList', {list: [ + {name: 'Ari', age: 10}, + {name: 'Tim', age: 11}, + {name: 'Bjarne', age: 12}, + ]}); + list = object.list; + TestCase.assertEqual(list.isValid(), true); + realm.delete(object); + }); + + TestCase.assertEqual(list.isValid(), false); + TestCase.assertThrows(function() { + list.length; + }); + }, }); diff --git a/tests/js/results-tests.js b/tests/js/results-tests.js index 8a3f3f4e..b8ab3fad 100644 --- a/tests/js/results-tests.js +++ b/tests/js/results-tests.js @@ -285,28 +285,37 @@ module.exports = BaseTest.extend({ testResultsInvalidation: function() { var realm = new Realm({schema: [schemas.TestObject]}); - var testObjects = realm.objects('TestObject'); - var filteredObjects = testObjects.filtered('doubleCol > 1'); - var sortedObjects = testObjects.sorted('doubleCol'); - var snapshotObjects = testObjects.snapshot(); + realm.write(function() { + for (var i = 10; i > 0; i--) { + realm.create('TestObject', [i]); + } + }); + var resultsVariants = [ + realm.objects('TestObject'), + realm.objects('TestObject').filtered('doubleCol > 1'), + realm.objects('TestObject').filtered('doubleCol > 1').sorted('doubleCol'), + realm.objects('TestObject').filtered('doubleCol > 1').snapshot() + ]; + + // test isValid + resultsVariants.forEach(function(objects) { + TestCase.assertEqual(objects.isValid(), true); + }); + + // close and test invalidated accessors realm.close(); - realm = new Realm({ schemaVersion: 1, schema: [schemas.TestObject, schemas.BasicTypes] }); - [ - testObjects, - filteredObjects, - sortedObjects, - snapshotObjects, - ].forEach(function(objects) { + resultsVariants.forEach(function(objects) { + TestCase.assertEqual(objects.isValid(), false); TestCase.assertThrows(function() { objects[0]; }); TestCase.assertThrows(function() { objects.filtered('doubleCol < 42'); }); TestCase.assertThrows(function() { objects.sorted('doubleCol', true); }); TestCase.assertThrows(function() { objects.snapshot(); }); }); - } + }, });