diff --git a/src/js_realm.hpp b/src/js_realm.hpp index b3cb1351..1c01207e 100644 --- a/src/js_realm.hpp +++ b/src/js_realm.hpp @@ -138,6 +138,7 @@ class Realm { static void create(ContextType, ObjectType, size_t, const ValueType[], ReturnValue &); static void delete_one(ContextType, ObjectType, size_t, const ValueType[], ReturnValue &); static void delete_all(ContextType, ObjectType, size_t, const ValueType[], ReturnValue &); + static void is_object_valid(ContextType, ObjectType, size_t, const ValueType[], ReturnValue &); static void write(ContextType, ObjectType, size_t, const ValueType[], ReturnValue &); static void add_listener(ContextType, ObjectType, size_t, const ValueType[], ReturnValue &); static void remove_listener(ContextType, ObjectType, size_t, const ValueType[], ReturnValue &); @@ -212,6 +213,7 @@ struct RealmClass : ClassDefinition { {"create", wrap}, {"delete", wrap}, {"deleteAll", wrap}, + {"isValid", wrap}, {"write", wrap}, {"addListener", wrap}, {"removeListener", wrap}, @@ -454,6 +456,18 @@ void Realm::delete_all(ContextType ctx, ObjectType this_object, size_t argc, ObjectStore::table_for_object_type(realm->read_group(), objectSchema.name)->clear(); } } + +template +void Realm::is_object_valid(ContextType ctx, ObjectType this_object, size_t argc, const ValueType arguments[], ReturnValue &return_value) { + validate_argument_count(argc, 0); + + ObjectType arg = Value::validated_to_object(ctx, arguments[0]); + if (!Object::template is_instance>(ctx, arg)) { + throw std::runtime_error("Argument to Realm.isValid must be a 'RealmObject'"); + } + auto object = get_internal>(arg); + return_value.set(object->is_valid()); +} template void Realm::write(ContextType ctx, ObjectType this_object, size_t argc, const ValueType arguments[], ReturnValue &return_value) { diff --git a/src/object-store/src/object_accessor.hpp b/src/object-store/src/object_accessor.hpp index 61ef0a1d..c27d7a52 100644 --- a/src/object-store/src/object_accessor.hpp +++ b/src/object-store/src/object_accessor.hpp @@ -47,6 +47,8 @@ namespace realm { SharedRealm realm() { return m_realm; } const ObjectSchema &get_object_schema() { return *m_object_schema; } Row row() { return m_row; } + + bool is_valid() { return m_row.is_attached(); } private: SharedRealm m_realm; @@ -57,6 +59,8 @@ namespace realm { inline void set_property_value_impl(ContextType ctx, const Property &property, ValueType value, bool try_update); template inline ValueType get_property_value_impl(ContextType ctx, const Property &property); + + inline void verify_attached(); }; // @@ -109,6 +113,13 @@ namespace realm { static Mixed to_mixed(ContextType ctx, ValueType &val) { throw std::runtime_error("'Any' type is unsupported"); } }; + class InvalidatedObjectException : public std::runtime_error + { + public: + InvalidatedObjectException(const std::string object_type, const std::string message) : std::runtime_error(message), object_type(object_type) {} + const std::string object_type; + }; + class InvalidPropertyException : public std::runtime_error { public: @@ -137,6 +148,8 @@ namespace realm { template inline void Object::set_property_value(ContextType ctx, std::string prop_name, ValueType value, bool try_update) { + verify_attached(); + const Property *prop = m_object_schema->property_for_name(prop_name); if (!prop) { throw InvalidPropertyException(m_object_schema->name, prop_name, @@ -148,6 +161,8 @@ namespace realm { template inline ValueType Object::get_property_value(ContextType ctx, std::string prop_name) { + verify_attached(); + const Property *prop = m_object_schema->property_for_name(prop_name); if (!prop) { throw InvalidPropertyException(m_object_schema->name, prop_name, @@ -324,6 +339,13 @@ namespace realm { } return object; } + + inline void Object::verify_attached() { + if (!m_row.is_attached()) { + throw InvalidatedObjectException("Accessing object of type " + m_object_schema->name + " which has been deleted", + m_object_schema->name); + } + } // // List implementation