diff --git a/src/js_realm_object.hpp b/src/js_realm_object.hpp index c113c515..6bbef168 100644 --- a/src/js_realm_object.hpp +++ b/src/js_realm_object.hpp @@ -107,6 +107,9 @@ bool RealmObjectClass::set_property(ContextType ctx, ObjectType object, const try { realm_object->set_property_value(ctx, property, value, true); } + catch (TypeErrorException &ex) { + throw TypeErrorException(realm_object->get_object_schema().name + "." + std::string(property), ex.type()); + } catch (InvalidPropertyException &ex) { return false; } diff --git a/src/js_types.hpp b/src/js_types.hpp index 76f7d47b..5d57a143 100644 --- a/src/js_types.hpp +++ b/src/js_types.hpp @@ -71,6 +71,22 @@ struct Context { static AbstractExecutionContextID get_execution_context_id(ContextType); }; +class TypeErrorException : public std::invalid_argument { +public: + std::string const& prefix() const { return m_prefix; } + std::string const& type() const { return m_type; } + + TypeErrorException(std::string prefix, std::string type) : + std::invalid_argument(prefix + " must be of type: " + type), + m_prefix(std::move(prefix)), + m_type(std::move(type)) + {} + +private: + std::string m_prefix; + std::string m_type; +}; + template struct Value { using ContextType = typename T::Context; @@ -111,7 +127,7 @@ struct Value { static return_t validated_to_##type(ContextType ctx, const ValueType &value, const char *name = nullptr) { \ if (!is_##type(ctx, value)) { \ std::string prefix = name ? std::string("'") + name + "'" : "JS value"; \ - throw std::invalid_argument(prefix + " must be of type: " #type); \ + throw TypeErrorException(prefix, #type); \ } \ return to_##type(ctx, value); \ } diff --git a/tests/js/asserts.js b/tests/js/asserts.js index f8633842..ea92694b 100644 --- a/tests/js/asserts.js +++ b/tests/js/asserts.js @@ -107,6 +107,9 @@ module.exports = { } catch (e) { caught = true; + if (e.name !== expectedException.name) { + throw new TestFailureError('Expected a ' + expectedException.name + ' exception but caught a ' + e.name + ' instead. Message was: ' + e.message); + } if (e.message != expectedException.message) { throw new TestFailureError('Expected exception "' + expectedException + '" not thrown - instead caught: "' + e + '"'); } diff --git a/tests/js/realm-tests.js b/tests/js/realm-tests.js index f918b2d3..9ec02292 100644 --- a/tests/js/realm-tests.js +++ b/tests/js/realm-tests.js @@ -866,4 +866,15 @@ module.exports = { realm = new Realm({path: 'dates-v5.realm', schema: [schemas.DateObject]}); TestCase.assertEqual(realm.objects('Date')[0].currentDate.getTime(), 1); }, + + testErrorMessageFromInvalidWrite: function() { + var realm = new Realm({schema: [schemas.PersonObject]}); + + TestCase.assertThrowsException(function() { + realm.write(function () { + var p1 = realm.create('PersonObject', { name: 'Ari', age: 10 }); + p1.age = "Ten"; + }); + }, new Error("PersonObject.age must be of type: number")); + } };