Skip to content

Commit

Permalink
fix realm.delete for RealmObjects not inheriting from RealmObjectCons… (
Browse files Browse the repository at this point in the history
#3100)

* fix realm.delete for RealmObjects not inheriting from RealmObjectConstructor

* update changelog

* fix testRealmObjectCreationByConstructor

* fix delete for node for schema with class syntax and user defined ctor

* update tests
  • Loading branch information
blagoev authored Jul 30, 2020
1 parent e1b2e7b commit e4636fe
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 7 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ NOTE: This version bumps the Realm file format to version 11. It is not possible
### Fixed
* Fixed a crash when calling `user.apiKeys.fetchAll()`. ([#3067](https://github.com/realm/realm-js/pull/3067))
* Fixed calling `app.emailPasswordAuth.resetPassword` and `app.emailPasswordAuth.callResetPasswordFunction`, which would throw an error of mismatch in count of arguments. ([#3079](https://github.com/realm/realm-js/pull/3079))
* realm.delete throws an exception `Argument to 'delete' must be a Realm object or a collection of Realm objects.` for schema objects defined with JS class syntax and not inheriting from RealmObject [2848](https://github.com/realm/realm-js/issues/2848).

### Compatibility
* MongoDB Realm Cloud.
Expand Down
9 changes: 9 additions & 0 deletions src/jsc/jsc_class.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -600,6 +600,7 @@ bool ObjectWrap<ClassType>::has_instance(JSContextRef ctx, JSValueRef value) {
return false;
}

//search for RealmObjectClassConstructor on the prototype chain of the object
JSObjectRef proto = try_get_prototype(ctx, object);
while (proto != nullptr && !JSValueIsNull(ctx, proto)) {
if (JSValueIsStrictEqual(ctx, proto, RealmObjectClassConstructorPrototype)) {
Expand All @@ -609,6 +610,14 @@ bool ObjectWrap<ClassType>::has_instance(JSContextRef ctx, JSValueRef value) {
proto = try_get_prototype(ctx, proto);
}

//handle RealmObjects using user defined ctors without extending RealmObject.
//In this case we just check for existing internal value to identify RealmObject instances
auto internal = ObjectWrap<ClassType>::get_internal(ctx, object);
if (internal != nullptr) {
return true;
}

//if there is no RealmObjectClass on the prototype chain and the object does not have existing internal value then this is not an RealmObject instance
return false;
}

Expand Down
12 changes: 12 additions & 0 deletions src/node/node_class.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -490,6 +490,18 @@ inline bool WrappedObject<ClassType>::is_instance(Napi::Env env, const Napi::Obj
isInstanceOf = instance.InstanceOf(ctor);
}

//handle RealmObjects with user defined ctors without extending RealmObject
//In this case we just check for existing internal value to identify RealmObject instances
if (!isInstanceOf) {
bool isRealmObjectClass = std::is_same<ClassType, realm::js::RealmObjectClass<realm::node::Types>>::value;
if (isRealmObjectClass) {
Napi::External<typename ClassType::Internal> external = object.Get(ExternalSymbol).As<Napi::External<typename ClassType::Internal>>();
if (!external.IsUndefined()) {
return true;
}
}
}

return isInstanceOf;
}

Expand Down
13 changes: 6 additions & 7 deletions tests/js/realm-tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ module.exports = {
Object.setPrototypeOf(Car2, Realm.Object);

//test class syntax support without extending Realm.Object
let car3ConstructorCalled = true;
let car3ConstructorCalled = false;
class Car3 {
constructor() {
car3ConstructorCalled = true;
Expand All @@ -155,44 +155,43 @@ module.exports = {
TestCase.assertEqual(car.make, "Audi");
TestCase.assertEqual(car.model, "A4");
TestCase.assertEqual(car.kilometers, 24);
TestCase.assertTrue(car instanceof Realm.Object);
TestCase.assertInstanceOf(car, Realm.Object, "car not an instance of Realm.Object");

let cars = realm.objects("Car");
TestCase.assertUndefined(cars[""]);
let carZero = cars[0];
TestCase.assertEqual(carZero.make, "Audi");
TestCase.assertEqual(carZero.model, "A4");
TestCase.assertEqual(carZero.kilometers, 24);
TestCase.assertTrue(carZero instanceof Realm.Object);
TestCase.assertInstanceOf(carZero, Realm.Object, "carZero not an instance of Realm.Object");

constructorCalled = false;
let car1 = realm.create('Car', { make: 'VW', model: 'Touareg', kilometers: 13 });
TestCase.assertTrue(constructorCalled);
TestCase.assertEqual(car1.make, "VW");
TestCase.assertEqual(car1.model, "Touareg");
TestCase.assertEqual(car1.kilometers, 13);
TestCase.assertTrue(car1 instanceof Realm.Object);
TestCase.assertInstanceOf(car1, Realm.Object, "car1 not an instance of Realm.Object");

let car2 = realm.create('Car2', { make: 'Audi', model: 'A4', kilometers: 24 });
TestCase.assertTrue(calledAsConstructor);
TestCase.assertEqual(car2.make, "Audi");
TestCase.assertEqual(car2.model, "A4");
TestCase.assertEqual(car2.kilometers, 24);
TestCase.assertTrue(car2 instanceof Realm.Object);
TestCase.assertInstanceOf(car2, Realm.Object, "car2 not an instance of Realm.Object");

let car2_1 = realm.create('Car2', { make: 'VW', model: 'Touareg', kilometers: 13 });
TestCase.assertTrue(calledAsConstructor);
TestCase.assertEqual(car2_1.make, "VW");
TestCase.assertEqual(car2_1.model, "Touareg");
TestCase.assertEqual(car2_1.kilometers, 13);
TestCase.assertTrue(car2_1 instanceof Realm.Object);
TestCase.assertInstanceOf(car2_1, Realm.Object, "car2_1 not an instance of Realm.Object");

let car3 = realm.create('Car3', { make: 'Audi', model: 'A4', kilometers: 24 });
TestCase.assertTrue(car3ConstructorCalled);
TestCase.assertEqual(car3.make, "Audi");
TestCase.assertEqual(car3.model, "A4");
TestCase.assertEqual(car3.kilometers, 24);
TestCase.assertFalse(car3 instanceof Realm.Object);
//methods from Realm.Objects should be present
TestCase.assertDefined(car3.addListener);

Expand Down

0 comments on commit e4636fe

Please sign in to comment.