From 48c9336526d1fde9dfb394a7ac31aa77fc870d77 Mon Sep 17 00:00:00 2001 From: Scott Kyle Date: Mon, 12 Oct 2015 01:59:34 -0700 Subject: [PATCH 01/27] Tabs -> Spaces in ObjectTests.js --- tests/ObjectTests.js | 104 +++++++++++++++++++++---------------------- 1 file changed, 52 insertions(+), 52 deletions(-) diff --git a/tests/ObjectTests.js b/tests/ObjectTests.js index 4e847ab3..874731a5 100644 --- a/tests/ObjectTests.js +++ b/tests/ObjectTests.js @@ -20,67 +20,67 @@ var ObjectTests = { testBasicTypesPropertyGetters: function() { - var basicTypesValues = [true, 1, 1.1, 1.11, 'string', new Date(1), 'DATA']; - var realm = new Realm({schema: [BasicTypesObjectSchema]}); - var object = null; - realm.write(function() { - object = realm.create('BasicTypesObject', basicTypesValues); - }); + var basicTypesValues = [true, 1, 1.1, 1.11, 'string', new Date(1), 'DATA']; + var realm = new Realm({schema: [BasicTypesObjectSchema]}); + var object = null; + realm.write(function() { + object = realm.create('BasicTypesObject', basicTypesValues); + }); - for (var i = 0; i < BasicTypesObjectSchema.properties.length; i++) { - var prop = BasicTypesObjectSchema.properties[i]; - if (prop.type == Realm.Types.FLOAT) { - TestCase.assertEqualWithTolerance(object[prop.name], basicTypesValues[i], 0.000001); - } - else if (prop.type == Realm.Types.DATE) { - TestCase.assertEqual(object[prop.name].getTime(), basicTypesValues[i].getTime()); - } - else { - TestCase.assertEqual(object[prop.name], basicTypesValues[i]); - } - } + for (var i = 0; i < BasicTypesObjectSchema.properties.length; i++) { + var prop = BasicTypesObjectSchema.properties[i]; + if (prop.type == Realm.Types.FLOAT) { + TestCase.assertEqualWithTolerance(object[prop.name], basicTypesValues[i], 0.000001); + } + else if (prop.type == Realm.Types.DATE) { + TestCase.assertEqual(object[prop.name].getTime(), basicTypesValues[i].getTime()); + } + else { + TestCase.assertEqual(object[prop.name], basicTypesValues[i]); + } + } }, testBasicTypesPropertySetters: function() { - var basicTypesValues = [true, 1, 1.1, 1.11, 'string', new Date(1), 'DATA']; - var realm = new Realm({schema: [BasicTypesObjectSchema]}); - var obj = null; - realm.write(function() { - obj = realm.create('BasicTypesObject', basicTypesValues); - obj.boolCol = false; - obj.intCol = 2; - obj.floatCol = 2.2; - obj.doubleCol = 2.22; - obj.stringCol = 'STRING'; - obj.dateCol = new Date(2); - obj.dataCol = 'b'; - }); - TestCase.assertEqual(obj.boolCol, false, 'wrong bool value'); - TestCase.assertEqual(obj.intCol, 2, 'wrong int value'); - TestCase.assertEqualWithTolerance(obj.floatCol, 2.2, 0.000001, 'wrong float value'); - TestCase.assertEqual(obj.doubleCol, 2.22, 'wrong double value'); - TestCase.assertEqual(obj.stringCol, 'STRING', 'wrong string value'); - TestCase.assertEqual(obj.dateCol.getTime(), 2, 'wrong date value'); - TestCase.assertEqual(obj.dataCol, 'b', 'wrong data value'); + var basicTypesValues = [true, 1, 1.1, 1.11, 'string', new Date(1), 'DATA']; + var realm = new Realm({schema: [BasicTypesObjectSchema]}); + var obj = null; + realm.write(function() { + obj = realm.create('BasicTypesObject', basicTypesValues); + obj.boolCol = false; + obj.intCol = 2; + obj.floatCol = 2.2; + obj.doubleCol = 2.22; + obj.stringCol = 'STRING'; + obj.dateCol = new Date(2); + obj.dataCol = 'b'; + }); + TestCase.assertEqual(obj.boolCol, false, 'wrong bool value'); + TestCase.assertEqual(obj.intCol, 2, 'wrong int value'); + TestCase.assertEqualWithTolerance(obj.floatCol, 2.2, 0.000001, 'wrong float value'); + TestCase.assertEqual(obj.doubleCol, 2.22, 'wrong double value'); + TestCase.assertEqual(obj.stringCol, 'STRING', 'wrong string value'); + TestCase.assertEqual(obj.dateCol.getTime(), 2, 'wrong date value'); + TestCase.assertEqual(obj.dataCol, 'b', 'wrong data value'); }, testLinkTypesPropertyGetters: function() { - var realm = new Realm({schema: [LinkTypesObjectSchema, TestObjectSchema]}); - var obj = null; - realm.write(function() { - obj = realm.create('LinkTypesObject', [[1], null, [[3]]]); - }); + var realm = new Realm({schema: [LinkTypesObjectSchema, TestObjectSchema]}); + var obj = null; + realm.write(function() { + obj = realm.create('LinkTypesObject', [[1], null, [[3]]]); + }); - var objVal = obj.objectCol; - TestCase.assertEqual(typeof objVal, 'object'); - TestCase.assertNotEqual(objVal, null); - TestCase.assertEqual(objVal.doubleCol, 1); + var objVal = obj.objectCol; + TestCase.assertEqual(typeof objVal, 'object'); + TestCase.assertNotEqual(objVal, null); + TestCase.assertEqual(objVal.doubleCol, 1); TestCase.assertEqual(obj.objectCol1, null); - var arrayVal = obj.arrayCol; - TestCase.assertEqual(typeof arrayVal, 'object'); - TestCase.assertNotEqual(arrayVal, null); - TestCase.assertEqual(arrayVal.length, 1); - TestCase.assertEqual(arrayVal[0].doubleCol, 3); + var arrayVal = obj.arrayCol; + TestCase.assertEqual(typeof arrayVal, 'object'); + TestCase.assertNotEqual(arrayVal, null); + TestCase.assertEqual(arrayVal.length, 1); + TestCase.assertEqual(arrayVal[0].doubleCol, 3); }, testLinkTypesPropertySetters: function() { var realm = new Realm({schema: [LinkTypesObjectSchema, TestObjectSchema]}); From 37d5a12094f454997c7e04d5bfbd68b992424ad5 Mon Sep 17 00:00:00 2001 From: Scott Kyle Date: Mon, 12 Oct 2015 02:01:29 -0700 Subject: [PATCH 02/27] Add test for calling create() outside transaction --- tests/RealmTests.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tests/RealmTests.js b/tests/RealmTests.js index 760ea37b..3c7b6a21 100644 --- a/tests/RealmTests.js +++ b/tests/RealmTests.js @@ -73,6 +73,11 @@ var RealmTests = { testRealmCreate: function() { var realm = new Realm({schema: [IntPrimaryObjectSchema, AllTypesObjectSchema, TestObjectSchema]}); + + TestCase.assertThrows(function() { + realm.create('TestObject', [1]); + }, 'can only create inside a write transaction'); + realm.write(function() { realm.create('TestObject', [1]); realm.create('TestObject', {'doubleCol': 2}); @@ -171,7 +176,7 @@ var RealmTests = { var objects = realm.objects('TestObject'); TestCase.assertThrows(function() { realm.delete(objects[0]); - }, "can only delete in a write transaction"); + }, 'can only delete in a write transaction'); realm.write(function() { TestCase.assertThrows(function() { @@ -208,7 +213,7 @@ var RealmTests = { TestCase.assertThrows(function() { realm.deleteAll(); - }); + }, 'can only deleteAll in a write transaction'); realm.write(function() { realm.deleteAll(); From 33e0f5d8b1c65931e06c62506f7eda3a642edc98 Mon Sep 17 00:00:00 2001 From: Scott Kyle Date: Mon, 12 Oct 2015 02:02:23 -0700 Subject: [PATCH 03/27] Setting properties outside transaction should throw Resolves #40 --- src/RJSObject.mm | 2 +- src/object-store/object_accessor.hpp | 4 ++++ tests/ObjectTests.js | 10 ++++++++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/RJSObject.mm b/src/RJSObject.mm index 09dbfb66..a9324bda 100644 --- a/src/RJSObject.mm +++ b/src/RJSObject.mm @@ -79,7 +79,7 @@ bool ObjectSetProperty(JSContextRef ctx, JSObjectRef jsObject, JSStringRef jsPro Object *obj = RJSGetInternal(jsObject); obj->set_property_value(ctx, RJSStringForJSString(jsPropertyName), value, true); } catch (std::exception &ex) { - if (*exception) { + if (exception) { *exception = RJSMakeError(ctx, ex); } return false; diff --git a/src/object-store/object_accessor.hpp b/src/object-store/object_accessor.hpp index dfb24f69..fa6d6366 100644 --- a/src/object-store/object_accessor.hpp +++ b/src/object-store/object_accessor.hpp @@ -98,6 +98,10 @@ namespace realm { { using Accessor = NativeAccessor; + if (!realm->is_in_transaction()) { + throw std::runtime_error("Can only set property values within a transaction."); + } + size_t column = property.table_column; switch (property.type) { case PropertyTypeBool: diff --git a/tests/ObjectTests.js b/tests/ObjectTests.js index 874731a5..1331e9ad 100644 --- a/tests/ObjectTests.js +++ b/tests/ObjectTests.js @@ -44,6 +44,7 @@ var ObjectTests = { var basicTypesValues = [true, 1, 1.1, 1.11, 'string', new Date(1), 'DATA']; var realm = new Realm({schema: [BasicTypesObjectSchema]}); var obj = null; + realm.write(function() { obj = realm.create('BasicTypesObject', basicTypesValues); obj.boolCol = false; @@ -54,6 +55,11 @@ var ObjectTests = { obj.dateCol = new Date(2); obj.dataCol = 'b'; }); + + TestCase.assertThrows(function() { + obj.boolCol = true; + }, 'can only set property values in a write transaction'); + TestCase.assertEqual(obj.boolCol, false, 'wrong bool value'); TestCase.assertEqual(obj.intCol, 2, 'wrong int value'); TestCase.assertEqualWithTolerance(obj.floatCol, 2.2, 0.000001, 'wrong float value'); @@ -90,6 +96,10 @@ var ObjectTests = { }); TestCase.assertEqual(realm.objects('TestObject').length, 2); + TestCase.assertThrows(function() { + obj.objectCol1 = obj.objectCol; + }, 'can only set property values in a write transaction'); + // set/reuse object property realm.write(function() { obj.objectCol1 = obj.objectCol; From c600af9182dc8eee6588a846d0d36f0d8c0dd54a Mon Sep 17 00:00:00 2001 From: Scott Kyle Date: Mon, 12 Oct 2015 02:23:09 -0700 Subject: [PATCH 04/27] Mutating lists outside transaction should throw --- src/RJSArray.cpp | 18 +++++++++++++----- tests/ArrayTests.js | 36 +++++++++++++++++++++++------------- 2 files changed, 36 insertions(+), 18 deletions(-) diff --git a/src/RJSArray.cpp b/src/RJSArray.cpp index 2ad920b7..3f7cb3f7 100644 --- a/src/RJSArray.cpp +++ b/src/RJSArray.cpp @@ -49,6 +49,14 @@ static inline ObjectArray * RJSVerifiedArray(JSObjectRef object) { return array; } +static inline ObjectArray * RJSVerifiedMutableArray(JSObjectRef object) { + ObjectArray *array = RJSVerifiedArray(object); + if (!array->realm->is_in_transaction()) { + throw std::runtime_error("Can only mutate lists within a transaction."); + } + return array; +} + JSValueRef ArrayGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* jsException) { try { // index subscripting @@ -89,7 +97,7 @@ void ArrayPropertyNames(JSContextRef ctx, JSObjectRef object, JSPropertyNameAccu JSValueRef ArrayPush(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* jsException) { try { - ObjectArray *array = RJSVerifiedArray(thisObject); + ObjectArray *array = RJSVerifiedMutableArray(thisObject); RJSValidateArgumentCountIsAtLeast(argumentCount, 1); for (size_t i = 0; i < argumentCount; i++) { array->link_view->add(RJSAccessor::to_object_index(ctx, array->realm, const_cast(arguments[i]), array->object_schema.name, false)); @@ -106,7 +114,7 @@ JSValueRef ArrayPush(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObj JSValueRef ArrayPop(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* jsException) { try { - ObjectArray *array = RJSVerifiedArray(thisObject); + ObjectArray *array = RJSVerifiedMutableArray(thisObject); RJSValidateArgumentCount(argumentCount, 0); size_t size = array->size(); @@ -128,7 +136,7 @@ JSValueRef ArrayPop(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObje JSValueRef ArrayUnshift(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* jsException) { try { - ObjectArray *array = RJSVerifiedArray(thisObject); + ObjectArray *array = RJSVerifiedMutableArray(thisObject); RJSValidateArgumentCountIsAtLeast(argumentCount, 1); for (size_t i = 0; i < argumentCount; i++) { array->link_view->insert(i, RJSAccessor::to_object_index(ctx, array->realm, const_cast(arguments[i]), array->object_schema.name, false)); @@ -145,7 +153,7 @@ JSValueRef ArrayUnshift(JSContextRef ctx, JSObjectRef function, JSObjectRef this JSValueRef ArrayShift(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* jsException) { try { - ObjectArray *array = RJSVerifiedArray(thisObject); + ObjectArray *array = RJSVerifiedMutableArray(thisObject); RJSValidateArgumentCount(argumentCount, 0); if (array->size() == 0) { return JSValueMakeUndefined(ctx); @@ -164,7 +172,7 @@ JSValueRef ArrayShift(JSContextRef ctx, JSObjectRef function, JSObjectRef thisOb JSValueRef ArraySplice(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* jsException) { try { - ObjectArray *array = RJSVerifiedArray(thisObject); + ObjectArray *array = RJSVerifiedMutableArray(thisObject); size_t size = array->size(); RJSValidateArgumentCountIsAtLeast(argumentCount, 2); diff --git a/tests/ArrayTests.js b/tests/ArrayTests.js index c07a3d7d..667b594f 100644 --- a/tests/ArrayTests.js +++ b/tests/ArrayTests.js @@ -108,6 +108,7 @@ var ArrayTests = { testPush: function() { var realm = new Realm({schema: [LinkTypesObjectSchema, TestObjectSchema]}); var array; + realm.write(function() { var obj = realm.create('LinkTypesObject', [[1], [2], [[3]]]); TestCase.assertEqual(obj.arrayCol.length, 1); @@ -128,14 +129,15 @@ var ArrayTests = { }); TestCase.assertEqual(array.length, 4); - // TestCase.assertThrows(function() { - // array.push([1]); - // }); + TestCase.assertThrows(function() { + array.push([1]); + }, 'can only push in a write transaction'); }, testPop: function() { var realm = new Realm({schema: [LinkTypesObjectSchema, TestObjectSchema]}); var array; + realm.write(function() { var obj = realm.create('LinkTypesObject', [[1], [2], [[3], [4]]]); array = obj.arrayCol; @@ -151,14 +153,15 @@ var ArrayTests = { }); }); - // TestCase.assertThrows(function() { - // array.pop(); - // }); + TestCase.assertThrows(function() { + array.pop(); + }, 'can only pop in a write transaction'); }, testUnshift: function() { var realm = new Realm({schema: [LinkTypesObjectSchema, TestObjectSchema]}); var array; + realm.write(function() { var obj = realm.create('LinkTypesObject', [[1], [2], [[3]]]); TestCase.assertEqual(obj.arrayCol.length, 1); @@ -175,14 +178,15 @@ var ArrayTests = { }); TestCase.assertEqual(array.length, 4); - // TestCase.assertThrows(function() { - // array.unshift([1]); - // }); + TestCase.assertThrows(function() { + array.unshift([1]); + }, 'can only unshift in a write transaction'); }, testShift: function() { var realm = new Realm({schema: [LinkTypesObjectSchema, TestObjectSchema]}); var array; + realm.write(function() { var obj = realm.create('LinkTypesObject', [[1], [2], [[3], [4]]]); array = obj.arrayCol; @@ -198,19 +202,21 @@ var ArrayTests = { }); }); - // TestCase.assertThrows(function() { - // array.shift(); - // }); + TestCase.assertThrows(function() { + array.shift(); + }, 'can only shift in a write transaction'); }, testSplice: function() { var realm = new Realm({schema: [LinkTypesObjectSchema, TestObjectSchema]}); + var array; realm.write(function() { var obj = realm.create('LinkTypesObject', [[1], [2], [[3], [4]]]); - var array = obj.arrayCol; var removed; + array = obj.arrayCol; + removed = array.splice(0, 0, obj.objectCol, obj.objectCol1); TestCase.assertEqual(removed.length, 0); TestCase.assertEqual(array.length, 4); @@ -248,5 +254,9 @@ var ArrayTests = { array.splice(0, 0, 0); }); }); + + TestCase.assertThrows(function() { + obj.arrayCol.splice(0, 0, obj.objectCol); + }, 'can only splice in a write transaction'); }, }; From cc294e0353e62bb5b78482012adc597c57ac6cf0 Mon Sep 17 00:00:00 2001 From: Scott Kyle Date: Mon, 12 Oct 2015 12:59:40 -0700 Subject: [PATCH 05/27] Move object property setter assert downward --- tests/ObjectTests.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tests/ObjectTests.js b/tests/ObjectTests.js index 1331e9ad..3c84ecb3 100644 --- a/tests/ObjectTests.js +++ b/tests/ObjectTests.js @@ -56,10 +56,6 @@ var ObjectTests = { obj.dataCol = 'b'; }); - TestCase.assertThrows(function() { - obj.boolCol = true; - }, 'can only set property values in a write transaction'); - TestCase.assertEqual(obj.boolCol, false, 'wrong bool value'); TestCase.assertEqual(obj.intCol, 2, 'wrong int value'); TestCase.assertEqualWithTolerance(obj.floatCol, 2.2, 0.000001, 'wrong float value'); @@ -67,6 +63,12 @@ var ObjectTests = { TestCase.assertEqual(obj.stringCol, 'STRING', 'wrong string value'); TestCase.assertEqual(obj.dateCol.getTime(), 2, 'wrong date value'); TestCase.assertEqual(obj.dataCol, 'b', 'wrong data value'); + + TestCase.assertThrows(function() { + obj.boolCol = true; + }, 'can only set property values in a write transaction'); + + TestCase.assertEqual(obj.boolCol, false, 'bool value changed outside transaction'); }, testLinkTypesPropertyGetters: function() { var realm = new Realm({schema: [LinkTypesObjectSchema, TestObjectSchema]}); From ae52840ee7baf2028614015fe9039320a19c7a79 Mon Sep 17 00:00:00 2001 From: Ari Lazier Date: Mon, 12 Oct 2015 13:09:00 -0700 Subject: [PATCH 06/27] add GCDWebServer as dependency --- RealmJS.xcodeproj/project.pbxproj | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/RealmJS.xcodeproj/project.pbxproj b/RealmJS.xcodeproj/project.pbxproj index fdcaea6a..2abf22b5 100644 --- a/RealmJS.xcodeproj/project.pbxproj +++ b/RealmJS.xcodeproj/project.pbxproj @@ -9,6 +9,7 @@ /* Begin PBXBuildFile section */ 02258FB31BC6E2D00075F13A /* RealmRPC.h in Headers */ = {isa = PBXBuildFile; fileRef = 02258FB11BC6E2D00075F13A /* RealmRPC.h */; settings = {ATTRIBUTES = (Public, ); }; }; 02258FB41BC6E2D00075F13A /* RealmRPC.mm in Sources */ = {isa = PBXBuildFile; fileRef = 02258FB21BC6E2D00075F13A /* RealmRPC.mm */; settings = {ASSET_TAGS = (); }; }; + 02313C4E1BCC4A4B003F9107 /* GCDWebServers.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 02A3C7941BC4317A00B1A7BE /* GCDWebServers.framework */; }; 02601F031BA0F0C4007C91FF /* external_commit_helper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02601F011BA0F0C4007C91FF /* external_commit_helper.cpp */; }; 02601F041BA0F0C4007C91FF /* external_commit_helper.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 02601F021BA0F0C4007C91FF /* external_commit_helper.hpp */; }; 02601F081BA0F0CD007C91FF /* index_set.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02601F051BA0F0CD007C91FF /* index_set.cpp */; }; @@ -51,7 +52,6 @@ 0270BC861B7D020100010E03 /* TestObjects.js in Resources */ = {isa = PBXBuildFile; fileRef = 0270BC7F1B7D020100010E03 /* TestObjects.js */; }; 0270BC871B7D023200010E03 /* RealmJS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 02B58CB11AE99CEC009B348C /* RealmJS.framework */; }; 0270BCD11B7D067300010E03 /* RealmReactModule.m in Sources */ = {isa = PBXBuildFile; fileRef = 0270BCD01B7D067300010E03 /* RealmReactModule.m */; }; - 02A3C7971BC4318600B1A7BE /* GCDWebServers.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 02A3C7941BC4317A00B1A7BE /* GCDWebServers.framework */; }; 02B29A311B7CF86D008A7E6B /* RealmJS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 02B58CB11AE99CEC009B348C /* RealmJS.framework */; }; 02B58CCE1AE99D4D009B348C /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 02B58CCD1AE99D4D009B348C /* JavaScriptCore.framework */; }; 02D456DA1B7E59A500EE1299 /* ArrayTests.js in Resources */ = {isa = PBXBuildFile; fileRef = 02D456D91B7E59A500EE1299 /* ArrayTests.js */; }; @@ -59,6 +59,13 @@ /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ + 02313C461BCC4A43003F9107 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 02A3C7841BC4317A00B1A7BE /* GCDWebServer.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = CEE28CEE1AE0051F00F4023C; + remoteInfo = "GCDWebServers (iOS)"; + }; 02A3C78D1BC4317A00B1A7BE /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 02A3C7841BC4317A00B1A7BE /* GCDWebServer.xcodeproj */; @@ -184,7 +191,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 02A3C7971BC4318600B1A7BE /* GCDWebServers.framework in Frameworks */, + 02313C4E1BCC4A4B003F9107 /* GCDWebServers.framework in Frameworks */, 02B29A311B7CF86D008A7E6B /* RealmJS.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -364,6 +371,7 @@ buildRules = ( ); dependencies = ( + 02313C471BCC4A43003F9107 /* PBXTargetDependency */, 02B29A301B7CF7ED008A7E6B /* PBXTargetDependency */, ); name = RealmReact; @@ -575,6 +583,11 @@ /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ + 02313C471BCC4A43003F9107 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = "GCDWebServers (iOS)"; + targetProxy = 02313C461BCC4A43003F9107 /* PBXContainerItemProxy */; + }; 02B29A301B7CF7ED008A7E6B /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 02B58CB01AE99CEC009B348C /* RealmJS */; From 515ece8fdd0b315f69ac066c3f2d1fa3f40d65fa Mon Sep 17 00:00:00 2001 From: Scott Kyle Date: Mon, 12 Oct 2015 02:42:15 -0700 Subject: [PATCH 07/27] Remove duplicated test in ArrayTests.js This must have been accidentally copy-pasted from ObjectTests.js --- tests/ArrayTests.js | 31 ------------------------------- 1 file changed, 31 deletions(-) diff --git a/tests/ArrayTests.js b/tests/ArrayTests.js index 667b594f..4d3f0b5f 100644 --- a/tests/ArrayTests.js +++ b/tests/ArrayTests.js @@ -19,37 +19,6 @@ 'use strict'; var ArrayTests = { - testLinkTypesPropertySetters: function() { - var realm = new Realm({schema: [LinkTypesObjectSchema, TestObjectSchema]}); - var obj = null; - realm.write(function() { - obj = realm.create('LinkTypesObject', [[1], undefined, [[3]]]); - }); - TestCase.assertEqual(realm.objects('TestObject').length, 2); - - // set/reuse object property - realm.write(function() { - obj.objectCol1 = obj.objectCol; - }); - TestCase.assertEqual(obj.objectCol1.doubleCol, 1); - //TestCase.assertEqual(obj.objectCol, obj.objectCol1); - TestCase.assertEqual(realm.objects('TestObject').length, 2); - - realm.write(function() { - obj.objectCol = undefined; - obj.objectCol1 = null; - }); - TestCase.assertEqual(obj.objectCol, null); - TestCase.assertEqual(obj.objectCol1, null); - - // set object as JSON - realm.write(function() { - obj.objectCol = { doubleCol: 3 }; - }); - TestCase.assertEqual(obj.objectCol.doubleCol, 3); - TestCase.assertEqual(realm.objects('TestObject').length, 3); - }, - testArrayLength: function() { var realm = new Realm({schema: [LinkTypesObjectSchema, TestObjectSchema]}); realm.write(function() { From ae9ae4dc77dcd0729cfcf44f263a08378ea5267a Mon Sep 17 00:00:00 2001 From: Scott Kyle Date: Mon, 12 Oct 2015 02:55:37 -0700 Subject: [PATCH 08/27] Add list item setters in JS Added a test and made other array tests syntactically consistent. Resolves #45 --- src/RJSArray.cpp | 31 ++++++++++++++++++++- tests/ArrayTests.js | 66 +++++++++++++++++++++++++++++++++++---------- 2 files changed, 82 insertions(+), 15 deletions(-) diff --git a/src/RJSArray.cpp b/src/RJSArray.cpp index 3f7cb3f7..9a10c3c0 100644 --- a/src/RJSArray.cpp +++ b/src/RJSArray.cpp @@ -82,6 +82,35 @@ JSValueRef ArrayGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef pr } } +bool ArraySetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* jsException) { + try { + ObjectArray *array = RJSVerifiedMutableArray(object); + size_t size = array->size(); + std::string indexStr = RJSStringForJSString(propertyName); + if (indexStr == "length") { + throw std::runtime_error("The 'length' property is readonly."); + } + + size_t index = std::stol(indexStr); + if (index >= size) { + throw std::out_of_range("Cannot set list item beyond its bounds."); + } + + array->link_view->set(index, RJSAccessor::to_object_index(ctx, array->realm, const_cast(value), array->object_schema.name, false)); + return true; + } + catch (std::invalid_argument &exp) { + // for stol failure this could be another property that is handled externally, so ignore + return false; + } + catch (std::exception &exp) { + if (jsException) { + *jsException = RJSMakeError(ctx, exp); + } + return false; + } +} + void ArrayPropertyNames(JSContextRef ctx, JSObjectRef object, JSPropertyNameAccumulatorRef propertyNames) { ObjectArray *array = RJSVerifiedArray(object); size_t size = array->size(); @@ -216,6 +245,6 @@ const JSStaticFunction RJSArrayFuncs[] = { }; JSClassRef RJSArrayClass() { - static JSClassRef s_arrayClass = RJSCreateWrapperClass("RealmArray", ArrayGetProperty, NULL, RJSArrayFuncs, NULL, ArrayPropertyNames); + static JSClassRef s_arrayClass = RJSCreateWrapperClass("RealmArray", ArrayGetProperty, ArraySetProperty, RJSArrayFuncs, NULL, ArrayPropertyNames); return s_arrayClass; } diff --git a/tests/ArrayTests.js b/tests/ArrayTests.js index 4d3f0b5f..7a4c4f7f 100644 --- a/tests/ArrayTests.js +++ b/tests/ArrayTests.js @@ -30,35 +30,74 @@ var ArrayTests = { obj.arrayCol = [[1], [2]]; TestCase.assertEqual(obj.arrayCol.length, 2); - }); + }); }, - testArraySubscript: function() { + testArraySubscriptGetters: function() { var realm = new Realm({schema: [LinkTypesObjectSchema, TestObjectSchema]}); - realm.write(function() { realm.create('LinkTypesObject', [[1], [2], [[3], [4]]]); }); + var array; + + realm.write(function() { + var obj = realm.create('LinkTypesObject', [[1], [2], [[3], [4]]]); + array = obj.arrayCol; + }); - var array = realm.objects('LinkTypesObject')[0].arrayCol; TestCase.assertEqual(array[0].doubleCol, 3); TestCase.assertEqual(array[1].doubleCol, 4); TestCase.assertThrows(function() { array[2]; }, 'Invalid index'); TestCase.assertThrows(function() { array[-1]; }, 'Invalid index'); }, - testArrayInvalidProperty: function() { + testArraySubscriptSetters: function() { var realm = new Realm({schema: [LinkTypesObjectSchema, TestObjectSchema]}); - realm.write(function() { realm.create('LinkTypesObject', [[1], [2], [[3], [4]]]); }); + var array; + + realm.write(function() { + var obj = realm.create('LinkTypesObject', [[1], [2], [[3], [4]]]); + array = obj.arrayCol; + + array[0] = [5]; + array[1] = [6]; + + TestCase.assertEqual(array[0].doubleCol, 5); + TestCase.assertEqual(array[1].doubleCol, 6); + + TestCase.assertThrows(function() { + array.length = 0; + }, 'cannot set length property on lists'); + + TestCase.assertThrows(function() { + array[2] = [1]; + }, 'cannot set list item beyond its bounds'); + }); + + TestCase.assertThrows(function() { + array[0] = [3]; + }, 'cannot set list item outside write transaction'); + }, + + testArrayInvalidProperty: function() { + var realm = new Realm({schema: [LinkTypesObjectSchema, TestObjectSchema]}); + var array; + + realm.write(function() { + var obj = realm.create('LinkTypesObject', [[1], [2], [[3], [4]]]); + array = obj.arrayCol; + }); - var array = realm.objects('LinkTypesObject')[0].arrayCol; TestCase.assertEqual(undefined, array.ablasdf); }, testArrayEnumerate: function() { var realm = new Realm({schema: [LinkTypesObjectSchema, TestObjectSchema]}); - realm.write(function() { realm.create('LinkTypesObject', [[1], [2], []]); }); + var obj; - var obj = realm.objects('LinkTypesObject')[0]; - for (var object in obj.arrayCol) { - TestCase.assertTrue(false, "No objects should have been enumerated: " + object); + realm.write(function() { + obj = realm.create('LinkTypesObject', [[1], [2], []]); + }); + + for (var index in obj.arrayCol) { + TestCase.assertTrue(false, "No objects should have been enumerated: " + index); } realm.write(function() { @@ -67,10 +106,9 @@ var ArrayTests = { }); var count = 0; - for (var object in obj.arrayCol) { + for (var index in obj.arrayCol) { count++; - //TestCase.assertTrue(object instanceof Object); - } + } TestCase.assertEqual(2, count); }, From a5bd3264c1c9eee4aa14fd51dbac9d159a30c626 Mon Sep 17 00:00:00 2001 From: Scott Kyle Date: Mon, 12 Oct 2015 15:02:44 -0700 Subject: [PATCH 09/27] Consolidate code that verifies array index bounds --- src/RJSArray.cpp | 35 +++++++++++++++++++++++------------ src/RJSArray.hpp | 2 ++ 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/src/RJSArray.cpp b/src/RJSArray.cpp index 9a10c3c0..3196c26e 100644 --- a/src/RJSArray.cpp +++ b/src/RJSArray.cpp @@ -29,13 +29,22 @@ size_t ObjectArray::size() { } Row ObjectArray::get(std::size_t row_ndx) { - if (row_ndx >= link_view->size()) { - throw std::range_error(std::string("Index ") + std::to_string(row_ndx) + " is outside of range 0..." + - std::to_string(link_view->size()) + "."); - } + verify_valid_row(row_ndx); return link_view->get(row_ndx); } +void ObjectArray::set(std::size_t row_ndx, std::size_t target_row_ndx) { + verify_valid_row(row_ndx); + link_view->set(row_ndx, target_row_ndx); +} + +void ObjectArray::verify_valid_row(std::size_t row_ndx) { + size_t size = link_view->size(); + if (row_ndx >= size) { + throw std::out_of_range(std::string("Index ") + std::to_string(row_ndx) + " is outside of range 0..." + std::to_string(size) + "."); + } +} + void ObjectArray::verify_attached() { if (!link_view->is_attached()) { throw std::runtime_error("Tableview is not attached"); @@ -57,6 +66,14 @@ static inline ObjectArray * RJSVerifiedMutableArray(JSObjectRef object) { return array; } +static inline size_t RJSVerifiedPositiveIndex(std::string indexStr) { + long index = std::stol(indexStr); + if (index < 0) { + throw std::out_of_range(std::string("Index ") + indexStr + " cannot be less than zero."); + } + return index; +} + JSValueRef ArrayGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* jsException) { try { // index subscripting @@ -68,7 +85,7 @@ JSValueRef ArrayGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef pr return JSValueMakeNumber(ctx, size); } - return RJSObjectCreate(ctx, Object(array->realm, array->object_schema, array->get(std::stol(indexStr)))); + return RJSObjectCreate(ctx, Object(array->realm, array->object_schema, array->get(RJSVerifiedPositiveIndex(indexStr)))); } catch (std::invalid_argument &exp) { // for stol failure this could be another property that is handled externally, so ignore @@ -85,18 +102,12 @@ JSValueRef ArrayGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef pr bool ArraySetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* jsException) { try { ObjectArray *array = RJSVerifiedMutableArray(object); - size_t size = array->size(); std::string indexStr = RJSStringForJSString(propertyName); if (indexStr == "length") { throw std::runtime_error("The 'length' property is readonly."); } - size_t index = std::stol(indexStr); - if (index >= size) { - throw std::out_of_range("Cannot set list item beyond its bounds."); - } - - array->link_view->set(index, RJSAccessor::to_object_index(ctx, array->realm, const_cast(value), array->object_schema.name, false)); + array->set(RJSVerifiedPositiveIndex(indexStr), RJSAccessor::to_object_index(ctx, array->realm, const_cast(value), array->object_schema.name, false)); return true; } catch (std::invalid_argument &exp) { diff --git a/src/RJSArray.hpp b/src/RJSArray.hpp index a4a0807d..08934e9d 100644 --- a/src/RJSArray.hpp +++ b/src/RJSArray.hpp @@ -30,6 +30,8 @@ namespace realm { size_t size(); Row get(std::size_t row_ndx); + void set(std::size_t row_ndx, std::size_t target_row_ndx); + void verify_valid_row(std::size_t row_ndx); void verify_attached(); }; } From 6788cd6f3da47f4fa05ea80b26ecb2bf3ac20f67 Mon Sep 17 00:00:00 2001 From: Scott Kyle Date: Mon, 12 Oct 2015 15:25:23 -0700 Subject: [PATCH 10/27] Out of bounds list item getters return undefined Resolves #50 --- src/RJSArray.cpp | 4 ++++ tests/ArrayTests.js | 18 +++++++++++------- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/RJSArray.cpp b/src/RJSArray.cpp index 3196c26e..ca24a36a 100644 --- a/src/RJSArray.cpp +++ b/src/RJSArray.cpp @@ -87,6 +87,10 @@ JSValueRef ArrayGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef pr return RJSObjectCreate(ctx, Object(array->realm, array->object_schema, array->get(RJSVerifiedPositiveIndex(indexStr)))); } + catch (std::out_of_range &exp) { + // getters for nonexistent properties in JS should always return undefined + return JSValueMakeUndefined(ctx); + } catch (std::invalid_argument &exp) { // for stol failure this could be another property that is handled externally, so ignore return NULL; diff --git a/tests/ArrayTests.js b/tests/ArrayTests.js index 7a4c4f7f..85a93df5 100644 --- a/tests/ArrayTests.js +++ b/tests/ArrayTests.js @@ -30,6 +30,10 @@ var ArrayTests = { obj.arrayCol = [[1], [2]]; TestCase.assertEqual(obj.arrayCol.length, 2); + + TestCase.assertThrows(function() { + obj.arrayCol.length = 0; + }, 'cannot set length property on lists'); }); }, @@ -44,8 +48,8 @@ var ArrayTests = { TestCase.assertEqual(array[0].doubleCol, 3); TestCase.assertEqual(array[1].doubleCol, 4); - TestCase.assertThrows(function() { array[2]; }, 'Invalid index'); - TestCase.assertThrows(function() { array[-1]; }, 'Invalid index'); + TestCase.assertEqual(array[2], undefined); + TestCase.assertEqual(array[-1], undefined); }, testArraySubscriptSetters: function() { @@ -62,13 +66,13 @@ var ArrayTests = { TestCase.assertEqual(array[0].doubleCol, 5); TestCase.assertEqual(array[1].doubleCol, 6); - TestCase.assertThrows(function() { - array.length = 0; - }, 'cannot set length property on lists'); - TestCase.assertThrows(function() { array[2] = [1]; }, 'cannot set list item beyond its bounds'); + + TestCase.assertThrows(function() { + array[-1] = [1]; + }, 'cannot set list item with negative index'); }); TestCase.assertThrows(function() { @@ -133,7 +137,7 @@ var ArrayTests = { TestCase.assertThrows(function() { array.push(); }); - }); + }); TestCase.assertEqual(array.length, 4); TestCase.assertThrows(function() { From 35a8f9816cb2070da536ee92c6cff3d53bbb9b70 Mon Sep 17 00:00:00 2001 From: Scott Kyle Date: Mon, 12 Oct 2015 15:35:13 -0700 Subject: [PATCH 11/27] Out of bounds getters for Results return undefined --- src/RJSArray.cpp | 12 ++---------- src/RJSResults.mm | 6 +++++- src/RJSUtil.hpp | 8 ++++++++ src/object-store/results.cpp | 2 +- tests/ResultsTests.js | 4 ++-- 5 files changed, 18 insertions(+), 14 deletions(-) diff --git a/src/RJSArray.cpp b/src/RJSArray.cpp index ca24a36a..b11f1446 100644 --- a/src/RJSArray.cpp +++ b/src/RJSArray.cpp @@ -66,14 +66,6 @@ static inline ObjectArray * RJSVerifiedMutableArray(JSObjectRef object) { return array; } -static inline size_t RJSVerifiedPositiveIndex(std::string indexStr) { - long index = std::stol(indexStr); - if (index < 0) { - throw std::out_of_range(std::string("Index ") + indexStr + " cannot be less than zero."); - } - return index; -} - JSValueRef ArrayGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* jsException) { try { // index subscripting @@ -85,7 +77,7 @@ JSValueRef ArrayGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef pr return JSValueMakeNumber(ctx, size); } - return RJSObjectCreate(ctx, Object(array->realm, array->object_schema, array->get(RJSVerifiedPositiveIndex(indexStr)))); + return RJSObjectCreate(ctx, Object(array->realm, array->object_schema, array->get(RJSValidatedPositiveIndex(indexStr)))); } catch (std::out_of_range &exp) { // getters for nonexistent properties in JS should always return undefined @@ -111,7 +103,7 @@ bool ArraySetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef property throw std::runtime_error("The 'length' property is readonly."); } - array->set(RJSVerifiedPositiveIndex(indexStr), RJSAccessor::to_object_index(ctx, array->realm, const_cast(value), array->object_schema.name, false)); + array->set(RJSValidatedPositiveIndex(indexStr), RJSAccessor::to_object_index(ctx, array->realm, const_cast(value), array->object_schema.name, false)); return true; } catch (std::invalid_argument &exp) { diff --git a/src/RJSResults.mm b/src/RJSResults.mm index 5be3cf37..9443af85 100644 --- a/src/RJSResults.mm +++ b/src/RJSResults.mm @@ -34,7 +34,11 @@ JSValueRef ResultsGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef return JSValueMakeNumber(ctx, size); } - return RJSObjectCreate(ctx, Object(results->realm, results->object_schema, results->get(std::stol(indexStr)))); + return RJSObjectCreate(ctx, Object(results->realm, results->object_schema, results->get(RJSValidatedPositiveIndex(indexStr)))); + } + catch (std::out_of_range &exp) { + // getters for nonexistent properties in JS should always return undefined + return JSValueMakeUndefined(ctx); } catch (std::invalid_argument &exp) { // for stol failure this could be another property that is handled externally, so ignore diff --git a/src/RJSUtil.hpp b/src/RJSUtil.hpp index 1c74a105..f6369ac5 100644 --- a/src/RJSUtil.hpp +++ b/src/RJSUtil.hpp @@ -179,6 +179,14 @@ static inline size_t RJSValidatedArrayLength(JSContextRef ctx, JSObjectRef objec return RJSValidatedValueToNumber(ctx, lengthValue); } +static inline size_t RJSValidatedPositiveIndex(std::string indexStr) { + long index = std::stol(indexStr); + if (index < 0) { + throw std::out_of_range(std::string("Index ") + indexStr + " cannot be less than zero."); + } + return index; +} + static inline bool RJSIsValueObjectOfType(JSContextRef ctx, JSValueRef value, JSStringRef type) { JSObjectRef globalObject = JSContextGetGlobalObject(ctx); diff --git a/src/object-store/results.cpp b/src/object-store/results.cpp index f33fc465..e4ad126e 100644 --- a/src/object-store/results.cpp +++ b/src/object-store/results.cpp @@ -43,7 +43,7 @@ Row Results::get(std::size_t row_ndx) { verify_attached(); if (row_ndx >= table_view.size()) { - throw std::range_error(std::string("Index ") + std::to_string(row_ndx) + " is outside of range 0..." + + throw std::out_of_range(std::string("Index ") + std::to_string(row_ndx) + " is outside of range 0..." + std::to_string(table_view.size()) + "."); } return table_view.get(row_ndx); diff --git a/tests/ResultsTests.js b/tests/ResultsTests.js index 7c953bb5..b0db81ad 100644 --- a/tests/ResultsTests.js +++ b/tests/ResultsTests.js @@ -40,8 +40,8 @@ var ResultsTests = { var people = realm.objects('PersonObject'); TestCase.assertEqual(people[0].age, 1); TestCase.assertEqual(people[1].age, 2); - TestCase.assertThrows(function() { people[2]; }, 'Invalid index'); - TestCase.assertThrows(function() { people[-1]; }, 'Invalid index'); + TestCase.assertEqual(people[2], undefined); + TestCase.assertEqual(people[-1], undefined); TestCase.assertTrue(Object.getPrototypeOf(people[0]) === PersonObject.prototype); }, testResultsInvalidProperty: function() { From a4194586eab163f475c743b737f2f6009b11bd2f Mon Sep 17 00:00:00 2001 From: Scott Kyle Date: Mon, 12 Oct 2015 15:42:56 -0700 Subject: [PATCH 12/27] Native methods should convert to numbers/bools It will still throw if unable to make the conversion. Fixes #51 --- src/RJSRealm.mm | 2 +- src/RJSResults.mm | 2 +- src/RJSUtil.hpp | 15 --------------- 3 files changed, 2 insertions(+), 17 deletions(-) diff --git a/src/RJSRealm.mm b/src/RJSRealm.mm index 192b7a34..83fe4be1 100644 --- a/src/RJSRealm.mm +++ b/src/RJSRealm.mm @@ -261,7 +261,7 @@ JSValueRef RealmCreateObject(JSContextRef ctx, JSObjectRef function, JSObjectRef bool update = false; if (argumentCount == 3) { - update = RJSValidatedValueToBool(ctx, arguments[2]); + update = JSValueToBoolean(ctx, arguments[2]); } return RJSObjectCreate(ctx, Object::create(ctx, sharedRealm, *object_schema, object, update)); diff --git a/src/RJSResults.mm b/src/RJSResults.mm index 9443af85..7cdad982 100644 --- a/src/RJSResults.mm +++ b/src/RJSResults.mm @@ -75,7 +75,7 @@ JSValueRef SortByProperty(JSContextRef ctx, JSObjectRef function, JSObjectRef th bool ascending = true; if (argumentCount == 2) { - ascending = RJSValidatedValueToBool(ctx, arguments[1]); + ascending = JSValueToBoolean(ctx, arguments[1]); } SortOrder sort = {{prop->table_column}, {ascending}}; diff --git a/src/RJSUtil.hpp b/src/RJSUtil.hpp index f6369ac5..0a8412ed 100644 --- a/src/RJSUtil.hpp +++ b/src/RJSUtil.hpp @@ -108,9 +108,6 @@ static inline JSObjectRef RJSValidatedValueToObject(JSContextRef ctx, JSValueRef static inline double RJSValidatedValueToNumber(JSContextRef ctx, JSValueRef value) { JSValueRef exception = NULL; - if (!JSValueIsNumber(ctx, value)) { - throw std::runtime_error("Value is not a number"); - } double number = JSValueToNumber(ctx, value, &exception); if (exception) { throw RJSException(ctx, exception); @@ -118,18 +115,6 @@ static inline double RJSValidatedValueToNumber(JSContextRef ctx, JSValueRef valu return number; } -static inline bool RJSValidatedValueToBool(JSContextRef ctx, JSValueRef value) { - JSValueRef exception = NULL; - if (!JSValueIsBoolean(ctx, value)) { - throw std::runtime_error("Value is not a boolean"); - } - bool b = JSValueToNumber(ctx, value, &exception); - if (exception) { - throw RJSException(ctx, exception); - } - return b; -} - static inline JSValueRef RJSValidatedPropertyValue(JSContextRef ctx, JSObjectRef object, JSStringRef property) { JSValueRef exception = NULL; JSValueRef propertyValue = JSObjectGetProperty(ctx, object, property, &exception); From aa035717a5236812111ea10725eb26929afdfd84 Mon Sep 17 00:00:00 2001 From: Ari Lazier Date: Mon, 12 Oct 2015 16:43:05 -0700 Subject: [PATCH 13/27] allow running all tests at the same path by invalidating all cached realm paths between test runs --- RealmJS.xcodeproj/project.pbxproj | 15 +++++++++++++++ src/object-store/shared_realm.cpp | 17 ++++++++++++++++- src/object-store/shared_realm.hpp | 1 + tests/RealmJSTests.mm | 14 ++++++++------ 4 files changed, 40 insertions(+), 7 deletions(-) diff --git a/RealmJS.xcodeproj/project.pbxproj b/RealmJS.xcodeproj/project.pbxproj index 2abf22b5..3366743b 100644 --- a/RealmJS.xcodeproj/project.pbxproj +++ b/RealmJS.xcodeproj/project.pbxproj @@ -860,6 +860,11 @@ INFOPLIST_FILE = tests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + OTHER_CPLUSPLUSFLAGS = ( + "$(OTHER_CFLAGS)", + "-isystem", + core/include, + ); PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; @@ -875,6 +880,11 @@ INFOPLIST_FILE = tests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + OTHER_CPLUSPLUSFLAGS = ( + "$(OTHER_CFLAGS)", + "-isystem", + core/include, + ); PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; @@ -982,6 +992,11 @@ INFOPLIST_FILE = tests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + OTHER_CPLUSPLUSFLAGS = ( + "$(OTHER_CFLAGS)", + "-isystem", + core/include, + ); PRODUCT_NAME = "$(TARGET_NAME)"; }; name = GCov_Build; diff --git a/src/object-store/shared_realm.cpp b/src/object-store/shared_realm.cpp index 8b003d30..77d39c21 100644 --- a/src/object-store/shared_realm.cpp +++ b/src/object-store/shared_realm.cpp @@ -198,7 +198,9 @@ bool Realm::update_schema(std::unique_ptr schema, uint64_t version) auto migration_function = [&](Group*, Schema&) { SharedRealm old_realm(new Realm(old_config)); auto updated_realm = shared_from_this(); - m_config.migration_function(old_realm, updated_realm); + if (m_config.migration_function) { + m_config.migration_function(old_realm, updated_realm); + } }; try { @@ -438,6 +440,19 @@ void RealmCache::cache_realm(SharedRealm &realm, std::thread::id thread_id) } } +void RealmCache::invalidate_all() +{ + std::lock_guard lock(m_mutex); + + for (auto &path_realms:m_cache) { + for (auto &realm_iter:path_realms.second) { + if (auto realm = realm_iter.second.lock()) { + realm->invalidate(); + } + } + } +} + void RealmCache::clear() { std::lock_guard lock(m_mutex); diff --git a/src/object-store/shared_realm.hpp b/src/object-store/shared_realm.hpp index aa19071e..4721e37e 100644 --- a/src/object-store/shared_realm.hpp +++ b/src/object-store/shared_realm.hpp @@ -131,6 +131,7 @@ namespace realm { SharedRealm get_any_realm(const std::string &path); void remove(const std::string &path, std::thread::id thread_id); void cache_realm(SharedRealm &realm, std::thread::id thread_id = std::this_thread::get_id()); + void invalidate_all(); void clear(); private: diff --git a/tests/RealmJSTests.mm b/tests/RealmJSTests.mm index bd7445bc..08ca2ff3 100644 --- a/tests/RealmJSTests.mm +++ b/tests/RealmJSTests.mm @@ -20,6 +20,8 @@ #import "RJSUtil.hpp" #import "RJSRealm.hpp" +#import "shared_realm.hpp" + NSString *RealmPathForFile(NSString *fileName) { #if TARGET_OS_IPHONE NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0]; @@ -30,10 +32,9 @@ NSString *RealmPathForFile(NSString *fileName) { return [path stringByAppendingPathComponent:fileName]; } -static NSString *s_testPrefix; NSString *TestRealmPath() { - return RealmPathForFile([s_testPrefix stringByAppendingPathComponent:@"test.realm"]); + return RealmPathForFile(@"test.realm"); } static void DeleteOrThrow(NSString *path) { @@ -72,10 +73,8 @@ static JSClassRef s_globalClass; - (void)setUp { [super setUp]; - s_testPrefix = [[NSUUID UUID] UUIDString]; - NSString *defaultDir = RealmPathForFile(s_testPrefix); + NSString *defaultDir = [[NSString stringWithUTF8String:RJSDefaultPath().c_str()] stringByDeletingLastPathComponent]; [[NSFileManager defaultManager] createDirectoryAtPath:defaultDir withIntermediateDirectories:YES attributes:nil error:nil]; - RJSSetDefaultPath([defaultDir stringByAppendingPathComponent:@"default.realm"].UTF8String); JSGlobalContextRef ctx = JSGlobalContextCreateInGroup(NULL, s_globalClass); self.context = [JSContext contextWithJSGlobalContextRef:ctx]; @@ -90,9 +89,12 @@ static JSClassRef s_globalClass; - (void)tearDown { self.context = nil; + realm::Realm::s_global_cache.invalidate_all(); + realm::Realm::s_global_cache.clear(); + DeleteRealmFilesAtPath(TestRealmPath()); DeleteRealmFilesAtPath(@(RJSDefaultPath().c_str())); - + [super tearDown]; } From c2e51ab5410543fa008349fb90c8dc8db9baf30f Mon Sep 17 00:00:00 2001 From: Scott Kyle Date: Mon, 12 Oct 2015 16:50:45 -0700 Subject: [PATCH 14/27] Check for NaN inside RJSValidatedValueToNumber Turns out this API can return NaN without an exception. Also added tests to make sure these conversions either work or throw exceptions in the appropriate places. --- src/RJSUtil.hpp | 3 +++ tests/ArrayTests.js | 10 +++++++++- tests/ObjectTests.js | 10 ++++++++++ 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/RJSUtil.hpp b/src/RJSUtil.hpp index 0a8412ed..056b93bb 100644 --- a/src/RJSUtil.hpp +++ b/src/RJSUtil.hpp @@ -112,6 +112,9 @@ static inline double RJSValidatedValueToNumber(JSContextRef ctx, JSValueRef valu if (exception) { throw RJSException(ctx, exception); } + if (isnan(number)) { + throw std::invalid_argument("Value not convertible to a number."); + } return number; } diff --git a/tests/ArrayTests.js b/tests/ArrayTests.js index 85a93df5..29cd15af 100644 --- a/tests/ArrayTests.js +++ b/tests/ArrayTests.js @@ -260,7 +260,15 @@ var ArrayTests = { TestCase.assertEqual(removed.length, 1); TestCase.assertEqual(removed[0].doubleCol, 1); TestCase.assertEqual(array.length, 0); - + + removed = array.splice('0', '0', obj.objectCol); + TestCase.assertEqual(removed.length, 0); + TestCase.assertEqual(array.length, 1); + + TestCase.assertThrows(function() { + array.splice('cat', 1); + }); + TestCase.assertThrows(function() { array.splice(0, 0, 0); }); diff --git a/tests/ObjectTests.js b/tests/ObjectTests.js index 3c84ecb3..d2ebbf1b 100644 --- a/tests/ObjectTests.js +++ b/tests/ObjectTests.js @@ -64,6 +64,16 @@ var ObjectTests = { TestCase.assertEqual(obj.dateCol.getTime(), 2, 'wrong date value'); TestCase.assertEqual(obj.dataCol, 'b', 'wrong data value'); + realm.write(function() { + TestCase.assertThrows(function() { + obj.boolCol = 'cat'; + }); + + TestCase.assertThrows(function() { + obj.intCol = 'dog'; + }); + }); + TestCase.assertThrows(function() { obj.boolCol = true; }, 'can only set property values in a write transaction'); From 8ad1b0907d1f9a0998ef9a6d6ea27ff5fb2c3ceb Mon Sep 17 00:00:00 2001 From: Ari Lazier Date: Mon, 12 Oct 2015 17:01:51 -0700 Subject: [PATCH 15/27] minimal tests for migrations --- src/RJSRealm.mm | 16 ++++++++++++++++ tests/RealmJSTests.mm | 4 +++- tests/RealmTests.js | 12 ++++++++++++ 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/src/RJSRealm.mm b/src/RJSRealm.mm index 192b7a34..2eec3d4f 100644 --- a/src/RJSRealm.mm +++ b/src/RJSRealm.mm @@ -403,6 +403,21 @@ JSValueRef RealmAddNotification(JSContextRef ctx, JSObjectRef function, JSObject } } +JSValueRef RealmClose(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* jsException) { + try { + RJSValidateArgumentCount(argumentCount, 0); + SharedRealm realm = *RJSGetInternal(thisObject); + realm->invalidate(); + realm::Realm::s_global_cache.remove(realm->config().path, realm->thread_id()); + } + catch (std::exception &exp) { + if (jsException) { + *jsException = RJSMakeError(ctx, exp); + } + } + return NULL; +} + void RJSNotificationFinalize(JSObjectRef object) { Notification *notification = RJSGetInternal(object); JSGlobalContextRelease(notification->ctx); @@ -416,6 +431,7 @@ const JSStaticFunction RJSRealmFuncs[] = { {"deleteAll", RealmDeleteAll, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, {"write", RealmWrite, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, {"addNotification", RealmAddNotification, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, + {"close", RealmClose, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, {NULL, NULL}, }; diff --git a/tests/RealmJSTests.mm b/tests/RealmJSTests.mm index 08ca2ff3..cd5ea149 100644 --- a/tests/RealmJSTests.mm +++ b/tests/RealmJSTests.mm @@ -92,7 +92,9 @@ static JSClassRef s_globalClass; realm::Realm::s_global_cache.invalidate_all(); realm::Realm::s_global_cache.clear(); - DeleteRealmFilesAtPath(TestRealmPath()); + DeleteRealmFilesAtPath(RealmPathForFile(@"test.realm")); + DeleteRealmFilesAtPath(RealmPathForFile(@"test1.realm")); + DeleteRealmFilesAtPath(RealmPathForFile(@"test2.realm")); DeleteRealmFilesAtPath(@(RJSDefaultPath().c_str())); [super tearDown]; diff --git a/tests/RealmTests.js b/tests/RealmTests.js index 3c7b6a21..4b004036 100644 --- a/tests/RealmTests.js +++ b/tests/RealmTests.js @@ -54,6 +54,18 @@ var RealmTests = { var testPath = TestUtil.realmPathForFile('test1.realm'); var realm = new Realm({path: testPath, schema: [], schemaVersion: 1}); TestCase.assertEqual(realm.schemaVersion, 1); + //TestCase.assertEqual(realm.schema.length, 0); + + realm.close(); +// TestCase.assertThrows(function() { +// realm = new Realm({path: testPath, schema: [TestObjectSchema], schemaVersion: 1}); +// }, "schema changes require updating the schema version"); + + realm = new Realm({path: testPath, schema: [TestObjectSchema], schemaVersion: 2}); + realm.write(function() { + realm.create('TestObject', [1]); + }); + TestCase.assertEqual(realm.objects('TestObject')[0].doubleCol, 1) //realm = undefined; //realm = new Realm({path: testPath, schema: [], schemaVersion: 2}); From c81ea6e5be33f9d911f6d18142c143c37722dc4d Mon Sep 17 00:00:00 2001 From: Ari Lazier Date: Mon, 12 Oct 2015 17:18:49 -0700 Subject: [PATCH 16/27] pr fixes --- src/object-store/shared_realm.cpp | 4 ++-- tests/RealmJSTests.mm | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/object-store/shared_realm.cpp b/src/object-store/shared_realm.cpp index 77d39c21..42217a8f 100644 --- a/src/object-store/shared_realm.cpp +++ b/src/object-store/shared_realm.cpp @@ -444,8 +444,8 @@ void RealmCache::invalidate_all() { std::lock_guard lock(m_mutex); - for (auto &path_realms:m_cache) { - for (auto &realm_iter:path_realms.second) { + for (auto &path_realms : m_cache) { + for (auto &realm_iter : path_realms.second) { if (auto realm = realm_iter.second.lock()) { realm->invalidate(); } diff --git a/tests/RealmJSTests.mm b/tests/RealmJSTests.mm index cd5ea149..5f556422 100644 --- a/tests/RealmJSTests.mm +++ b/tests/RealmJSTests.mm @@ -92,6 +92,7 @@ static JSClassRef s_globalClass; realm::Realm::s_global_cache.invalidate_all(); realm::Realm::s_global_cache.clear(); + // FIXME - find all realm files in the docs dir and delete them rather than hardcoding these DeleteRealmFilesAtPath(RealmPathForFile(@"test.realm")); DeleteRealmFilesAtPath(RealmPathForFile(@"test1.realm")); DeleteRealmFilesAtPath(RealmPathForFile(@"test2.realm")); From 5021429927a41c351c42dc230325b94fa6c50516 Mon Sep 17 00:00:00 2001 From: Ari Lazier Date: Mon, 12 Oct 2015 17:23:47 -0700 Subject: [PATCH 17/27] Add comments --- tests/RealmTests.js | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/tests/RealmTests.js b/tests/RealmTests.js index 4b004036..bb60f2b3 100644 --- a/tests/RealmTests.js +++ b/tests/RealmTests.js @@ -54,21 +54,20 @@ var RealmTests = { var testPath = TestUtil.realmPathForFile('test1.realm'); var realm = new Realm({path: testPath, schema: [], schemaVersion: 1}); TestCase.assertEqual(realm.schemaVersion, 1); + // FIXME - enable once Realm exposes a schema object //TestCase.assertEqual(realm.schema.length, 0); realm.close(); -// TestCase.assertThrows(function() { -// realm = new Realm({path: testPath, schema: [TestObjectSchema], schemaVersion: 1}); -// }, "schema changes require updating the schema version"); + // FIXME - enable once realm initialization supports schema comparison + // TestCase.assertThrows(function() { + // realm = new Realm({path: testPath, schema: [TestObjectSchema], schemaVersion: 1}); + // }, "schema changes require updating the schema version"); realm = new Realm({path: testPath, schema: [TestObjectSchema], schemaVersion: 2}); realm.write(function() { realm.create('TestObject', [1]); }); TestCase.assertEqual(realm.objects('TestObject')[0].doubleCol, 1) - - //realm = undefined; - //realm = new Realm({path: testPath, schema: [], schemaVersion: 2}); }, testDefaultPath: function() { From d996147b094be0ae4c0262460148a5800ba027c6 Mon Sep 17 00:00:00 2001 From: Scott Kyle Date: Mon, 12 Oct 2015 17:17:43 -0700 Subject: [PATCH 18/27] Protect realm and callback from GC in addNotification Fixes #54 --- src/RJSRealm.mm | 20 +++++++++++++++----- src/RJSUtil.hpp | 8 ++++++++ 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/src/RJSRealm.mm b/src/RJSRealm.mm index aed02df9..0efcd38b 100644 --- a/src/RJSRealm.mm +++ b/src/RJSRealm.mm @@ -346,7 +346,7 @@ JSValueRef RealmWrite(JSContextRef ctx, JSObjectRef function, JSObjectRef thisOb try { RJSValidateArgumentCount(argumentCount, 1); - JSObjectRef object = RJSValidatedValueToObject(ctx, arguments[0]); + JSObjectRef object = RJSValidatedValueToFunction(ctx, arguments[0]); SharedRealm realm = *RJSGetInternal(thisObject); realm->begin_transaction(); JSObjectCallAsFunction(ctx, object, thisObject, 0, NULL, jsException); @@ -370,6 +370,8 @@ JSValueRef RealmWrite(JSContextRef ctx, JSObjectRef function, JSObjectRef thisOb namespace realm { struct Notification { JSGlobalContextRef ctx; + JSObjectRef realmObject; + JSObjectRef callbackObject; RJSRealmDelegate::NotificationFunction func; }; } @@ -378,22 +380,26 @@ JSValueRef RealmAddNotification(JSContextRef ctx, JSObjectRef function, JSObject try { RJSValidateArgumentCount(argumentCount, 1); - JSObjectRef user_function = RJSValidatedValueToObject(ctx, arguments[0]); + JSObjectRef callback = RJSValidatedValueToFunction(ctx, arguments[0]); SharedRealm realm = *RJSGetInternal(thisObject); JSGlobalContextRef gCtx = JSGlobalContextRetain(JSContextGetGlobalContext(ctx)); + + JSValueProtect(gCtx, thisObject); + JSValueProtect(gCtx, callback); + RJSRealmDelegate::NotificationFunction func = std::make_shared>([=](std::string notification_name) { JSValueRef arguments[2]; arguments[0] = thisObject; arguments[1] = RJSValueForString(gCtx, notification_name); JSValueRef ex = NULL; - JSObjectCallAsFunction(gCtx, user_function, thisObject, 2, arguments, &ex); + JSObjectCallAsFunction(gCtx, callback, thisObject, 2, arguments, &ex); if (ex) { throw RJSException(gCtx, ex); } }); static_cast(realm->m_delegate.get())->add_notification(func); - return RJSWrapObject(ctx, RJSNotificationClass(), new Notification { gCtx, func }); + return RJSWrapObject(ctx, RJSNotificationClass(), new Notification { gCtx, thisObject, callback, func }); } catch (std::exception &exp) { if (jsException) { @@ -420,7 +426,11 @@ JSValueRef RealmClose(JSContextRef ctx, JSObjectRef function, JSObjectRef thisOb void RJSNotificationFinalize(JSObjectRef object) { Notification *notification = RJSGetInternal(object); - JSGlobalContextRelease(notification->ctx); + JSGlobalContextRef ctx = notification->ctx; + + JSValueUnprotect(ctx, notification->callbackObject); + JSValueUnprotect(ctx, notification->realmObject); + JSGlobalContextRelease(ctx); RJSFinalize(object); } diff --git a/src/RJSUtil.hpp b/src/RJSUtil.hpp index 056b93bb..2d15ee9e 100644 --- a/src/RJSUtil.hpp +++ b/src/RJSUtil.hpp @@ -106,6 +106,14 @@ static inline JSObjectRef RJSValidatedValueToObject(JSContextRef ctx, JSValueRef return object; } +static inline JSObjectRef RJSValidatedValueToFunction(JSContextRef ctx, JSValueRef value, const char *message = NULL) { + JSObjectRef object = JSValueToObject(ctx, value, NULL); + if (!object || !JSObjectIsFunction(ctx, object)) { + throw std::runtime_error(message ?: "Value is not a function."); + } + return object; +} + static inline double RJSValidatedValueToNumber(JSContextRef ctx, JSValueRef value) { JSValueRef exception = NULL; double number = JSValueToNumber(ctx, value, &exception); From 290234cb8a89e4220277da2a28c52cf9faf8bbc3 Mon Sep 17 00:00:00 2001 From: Scott Kyle Date: Mon, 12 Oct 2015 23:17:02 -0700 Subject: [PATCH 19/27] RJSException no longer requires JS strings Since most often some kind of JS Error is passed into RJSException, it would mask the original error by throwing a new exception because that Error was not a string! --- src/RJSUtil.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/RJSUtil.hpp b/src/RJSUtil.hpp index 2d15ee9e..fc90edb7 100644 --- a/src/RJSUtil.hpp +++ b/src/RJSUtil.hpp @@ -86,7 +86,7 @@ inline void RJSValidateArgumentRange(size_t argumentCount, size_t min, size_t ma class RJSException : public std::runtime_error { public: - RJSException(JSContextRef ctx, JSValueRef &ex) : std::runtime_error(RJSValidatedStringForValue(ctx, ex, "exception")), + RJSException(JSContextRef ctx, JSValueRef &ex) : std::runtime_error(RJSStringForValue(ctx, ex)), m_jsException(ex) {} JSValueRef exception() { return m_jsException; } From 6a550f285f0adfef51d806c8bd99533f561bf904 Mon Sep 17 00:00:00 2001 From: Scott Kyle Date: Mon, 12 Oct 2015 23:19:54 -0700 Subject: [PATCH 20/27] Small improvement to notifications test --- tests/RealmTests.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/tests/RealmTests.js b/tests/RealmTests.js index bb60f2b3..8773f581 100644 --- a/tests/RealmTests.js +++ b/tests/RealmTests.js @@ -272,14 +272,19 @@ var RealmTests = { }, testNotifications: function() { - var notificationCount = 0; var realm = new Realm({schema: []}); - var notification = realm.addNotification(function() { - notificationCount++; + var notificationCount = 0; + var notificationName; + + var notification = realm.addNotification(function(realm, name) { + notificationCount++; + notificationName = name; }); + TestCase.assertEqual(notificationCount, 0); realm.write(function() {}); TestCase.assertEqual(notificationCount, 1); + TestCase.assertEqual(notificationName, 'DidChangeNotification'); }, }; From d5ae329d8a5e6fd1e3fa990fc3ed7c544954156c Mon Sep 17 00:00:00 2001 From: Scott Kyle Date: Mon, 12 Oct 2015 23:21:13 -0700 Subject: [PATCH 21/27] Add Notification constructor and destructor These handle the life cycle of the member variables. --- src/RJSRealm.mm | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/src/RJSRealm.mm b/src/RJSRealm.mm index 0efcd38b..dff5b647 100644 --- a/src/RJSRealm.mm +++ b/src/RJSRealm.mm @@ -373,6 +373,18 @@ namespace realm { JSObjectRef realmObject; JSObjectRef callbackObject; RJSRealmDelegate::NotificationFunction func; + + Notification(JSGlobalContextRef c, JSObjectRef r, JSObjectRef cb, RJSRealmDelegate::NotificationFunction f) : ctx(c), realmObject(r), callbackObject(cb), func(f) { + JSGlobalContextRetain(ctx); + JSValueProtect(ctx, realmObject); + JSValueProtect(ctx, callbackObject); + } + + ~Notification() { + JSValueUnprotect(ctx, callbackObject); + JSValueUnprotect(ctx, realmObject); + JSGlobalContextRelease(ctx); + } }; } @@ -382,10 +394,7 @@ JSValueRef RealmAddNotification(JSContextRef ctx, JSObjectRef function, JSObject JSObjectRef callback = RJSValidatedValueToFunction(ctx, arguments[0]); SharedRealm realm = *RJSGetInternal(thisObject); - JSGlobalContextRef gCtx = JSGlobalContextRetain(JSContextGetGlobalContext(ctx)); - - JSValueProtect(gCtx, thisObject); - JSValueProtect(gCtx, callback); + JSGlobalContextRef gCtx = JSContextGetGlobalContext(ctx); RJSRealmDelegate::NotificationFunction func = std::make_shared>([=](std::string notification_name) { JSValueRef arguments[2]; @@ -424,16 +433,6 @@ JSValueRef RealmClose(JSContextRef ctx, JSObjectRef function, JSObjectRef thisOb return NULL; } -void RJSNotificationFinalize(JSObjectRef object) { - Notification *notification = RJSGetInternal(object); - JSGlobalContextRef ctx = notification->ctx; - - JSValueUnprotect(ctx, notification->callbackObject); - JSValueUnprotect(ctx, notification->realmObject); - JSGlobalContextRelease(ctx); - RJSFinalize(object); -} - const JSStaticFunction RJSRealmFuncs[] = { {"objects", RealmObjects, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, {"create", RealmCreateObject, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, @@ -451,7 +450,7 @@ JSClassRef RJSRealmClass() { } JSClassRef RJSNotificationClass() { - static JSClassRef s_notificationClass = RJSCreateWrapperClass("Notification", NULL, NULL, NULL, RJSNotificationFinalize); + static JSClassRef s_notificationClass = RJSCreateWrapperClass("Notification", NULL, NULL, NULL); return s_notificationClass; } From 9cb9960af5e0027c3b89957f462d9f4055d09994 Mon Sep 17 00:00:00 2001 From: Ari Lazier Date: Tue, 13 Oct 2015 14:41:51 -0700 Subject: [PATCH 22/27] ObjectArray -> List --- src/RJSArray.cpp | 74 ++++++++++++++++++++++++------------------------ src/RJSArray.hpp | 6 ++-- src/RJSObject.mm | 2 +- src/RealmRPC.mm | 6 ++-- 4 files changed, 44 insertions(+), 44 deletions(-) diff --git a/src/RJSArray.cpp b/src/RJSArray.cpp index b11f1446..b96f70ba 100644 --- a/src/RJSArray.cpp +++ b/src/RJSArray.cpp @@ -24,60 +24,60 @@ using RJSAccessor = realm::NativeAccessor; using namespace realm; -size_t ObjectArray::size() { +size_t List::size() { return link_view->size(); } -Row ObjectArray::get(std::size_t row_ndx) { +Row List::get(std::size_t row_ndx) { verify_valid_row(row_ndx); return link_view->get(row_ndx); } -void ObjectArray::set(std::size_t row_ndx, std::size_t target_row_ndx) { +void List::set(std::size_t row_ndx, std::size_t target_row_ndx) { verify_valid_row(row_ndx); link_view->set(row_ndx, target_row_ndx); } -void ObjectArray::verify_valid_row(std::size_t row_ndx) { +void List::verify_valid_row(std::size_t row_ndx) { size_t size = link_view->size(); if (row_ndx >= size) { throw std::out_of_range(std::string("Index ") + std::to_string(row_ndx) + " is outside of range 0..." + std::to_string(size) + "."); } } -void ObjectArray::verify_attached() { +void List::verify_attached() { if (!link_view->is_attached()) { throw std::runtime_error("Tableview is not attached"); } link_view->sync_if_needed(); } -static inline ObjectArray * RJSVerifiedArray(JSObjectRef object) { - ObjectArray *array = RJSGetInternal(object); - array->verify_attached(); - return array; +static inline List * RJSVerifiedArray(JSObjectRef object) { + List *list = RJSGetInternal(object); + list->verify_attached(); + return list; } -static inline ObjectArray * RJSVerifiedMutableArray(JSObjectRef object) { - ObjectArray *array = RJSVerifiedArray(object); - if (!array->realm->is_in_transaction()) { +static inline List * RJSVerifiedMutableArray(JSObjectRef object) { + List *list = RJSVerifiedArray(object); + if (!list->realm->is_in_transaction()) { throw std::runtime_error("Can only mutate lists within a transaction."); } - return array; + return list; } JSValueRef ArrayGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* jsException) { try { // index subscripting - ObjectArray *array = RJSVerifiedArray(object); - size_t size = array->size(); + List *list = RJSVerifiedArray(object); + size_t size = list->size(); std::string indexStr = RJSStringForJSString(propertyName); if (indexStr == "length") { return JSValueMakeNumber(ctx, size); } - return RJSObjectCreate(ctx, Object(array->realm, array->object_schema, array->get(RJSValidatedPositiveIndex(indexStr)))); + return RJSObjectCreate(ctx, Object(list->realm, list->object_schema, list->get(RJSValidatedPositiveIndex(indexStr)))); } catch (std::out_of_range &exp) { // getters for nonexistent properties in JS should always return undefined @@ -97,13 +97,13 @@ JSValueRef ArrayGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef pr bool ArraySetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* jsException) { try { - ObjectArray *array = RJSVerifiedMutableArray(object); + List *list = RJSVerifiedMutableArray(object); std::string indexStr = RJSStringForJSString(propertyName); if (indexStr == "length") { throw std::runtime_error("The 'length' property is readonly."); } - array->set(RJSValidatedPositiveIndex(indexStr), RJSAccessor::to_object_index(ctx, array->realm, const_cast(value), array->object_schema.name, false)); + list->set(RJSValidatedPositiveIndex(indexStr), RJSAccessor::to_object_index(ctx, list->realm, const_cast(value), list->object_schema.name, false)); return true; } catch (std::invalid_argument &exp) { @@ -119,8 +119,8 @@ bool ArraySetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef property } void ArrayPropertyNames(JSContextRef ctx, JSObjectRef object, JSPropertyNameAccumulatorRef propertyNames) { - ObjectArray *array = RJSVerifiedArray(object); - size_t size = array->size(); + List *list = RJSVerifiedArray(object); + size_t size = list->size(); char str[32]; for (size_t i = 0; i < size; i++) { @@ -133,7 +133,7 @@ void ArrayPropertyNames(JSContextRef ctx, JSObjectRef object, JSPropertyNameAccu JSValueRef ArrayPush(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* jsException) { try { - ObjectArray *array = RJSVerifiedMutableArray(thisObject); + List *array = RJSVerifiedMutableArray(thisObject); RJSValidateArgumentCountIsAtLeast(argumentCount, 1); for (size_t i = 0; i < argumentCount; i++) { array->link_view->add(RJSAccessor::to_object_index(ctx, array->realm, const_cast(arguments[i]), array->object_schema.name, false)); @@ -150,16 +150,16 @@ JSValueRef ArrayPush(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObj JSValueRef ArrayPop(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* jsException) { try { - ObjectArray *array = RJSVerifiedMutableArray(thisObject); + List *list = RJSVerifiedMutableArray(thisObject); RJSValidateArgumentCount(argumentCount, 0); - size_t size = array->size(); + size_t size = list->size(); if (size == 0) { return JSValueMakeUndefined(ctx); } size_t index = size - 1; - JSValueRef obj = RJSObjectCreate(ctx, Object(array->realm, array->object_schema, array->get(index))); - array->link_view->remove(index); + JSValueRef obj = RJSObjectCreate(ctx, Object(list->realm, list->object_schema, list->get(index))); + list->link_view->remove(index); return obj; } catch (std::exception &exp) { @@ -172,7 +172,7 @@ JSValueRef ArrayPop(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObje JSValueRef ArrayUnshift(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* jsException) { try { - ObjectArray *array = RJSVerifiedMutableArray(thisObject); + List *array = RJSVerifiedMutableArray(thisObject); RJSValidateArgumentCountIsAtLeast(argumentCount, 1); for (size_t i = 0; i < argumentCount; i++) { array->link_view->insert(i, RJSAccessor::to_object_index(ctx, array->realm, const_cast(arguments[i]), array->object_schema.name, false)); @@ -189,13 +189,13 @@ JSValueRef ArrayUnshift(JSContextRef ctx, JSObjectRef function, JSObjectRef this JSValueRef ArrayShift(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* jsException) { try { - ObjectArray *array = RJSVerifiedMutableArray(thisObject); + List *list = RJSVerifiedMutableArray(thisObject); RJSValidateArgumentCount(argumentCount, 0); - if (array->size() == 0) { + if (list->size() == 0) { return JSValueMakeUndefined(ctx); } - JSValueRef obj = RJSObjectCreate(ctx, Object(array->realm, array->object_schema, array->get(0))); - array->link_view->remove(0); + JSValueRef obj = RJSObjectCreate(ctx, Object(list->realm, list->object_schema, list->get(0))); + list->link_view->remove(0); return obj; } catch (std::exception &exp) { @@ -208,8 +208,8 @@ JSValueRef ArrayShift(JSContextRef ctx, JSObjectRef function, JSObjectRef thisOb JSValueRef ArraySplice(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* jsException) { try { - ObjectArray *array = RJSVerifiedMutableArray(thisObject); - size_t size = array->size(); + List *list = RJSVerifiedMutableArray(thisObject); + size_t size = list->size(); RJSValidateArgumentCountIsAtLeast(argumentCount, 2); long index = std::min(RJSValidatedValueToNumber(ctx, arguments[0]), size); @@ -222,11 +222,11 @@ JSValueRef ArraySplice(JSContextRef ctx, JSObjectRef function, JSObjectRef thisO std::vector removedObjects(remove); for (size_t i = 0; i < remove; i++) { - removedObjects[i] = RJSObjectCreate(ctx, Object(array->realm, array->object_schema, array->get(index))); - array->link_view->remove(index); + removedObjects[i] = RJSObjectCreate(ctx, Object(list->realm, list->object_schema, list->get(index))); + list->link_view->remove(index); } for (size_t i = 2; i < argumentCount; i++) { - array->link_view->insert(index + i - 2, RJSAccessor::to_object_index(ctx, array->realm, const_cast(arguments[i]), array->object_schema.name, false)); + list->link_view->insert(index + i - 2, RJSAccessor::to_object_index(ctx, list->realm, const_cast(arguments[i]), list->object_schema.name, false)); } return JSObjectMakeArray(ctx, remove, removedObjects.data(), jsException); } @@ -238,8 +238,8 @@ JSValueRef ArraySplice(JSContextRef ctx, JSObjectRef function, JSObjectRef thisO return NULL; } -JSObjectRef RJSArrayCreate(JSContextRef ctx, realm::ObjectArray *array) { - return RJSWrapObject(ctx, RJSArrayClass(), array); +JSObjectRef RJSArrayCreate(JSContextRef ctx, realm::List *list) { + return RJSWrapObject(ctx, RJSArrayClass(), list); } const JSStaticFunction RJSArrayFuncs[] = { diff --git a/src/RJSArray.hpp b/src/RJSArray.hpp index 08934e9d..bafbb3b5 100644 --- a/src/RJSArray.hpp +++ b/src/RJSArray.hpp @@ -21,8 +21,8 @@ #import namespace realm { - struct ObjectArray { - ObjectArray(SharedRealm &r, ObjectSchema &s, LinkViewRef l) : realm(r), object_schema(s), link_view(l) {} + struct List { + List(SharedRealm &r, ObjectSchema &s, LinkViewRef l) : realm(r), object_schema(s), link_view(l) {} // FIXME - all should be const SharedRealm realm; ObjectSchema &object_schema; @@ -38,6 +38,6 @@ namespace realm { extern const JSStaticFunction RJSArrayFuncs[]; JSClassRef RJSArrayClass(); -JSObjectRef RJSArrayCreate(JSContextRef ctx, realm::ObjectArray *array); +JSObjectRef RJSArrayCreate(JSContextRef ctx, realm::List *list); JSValueRef ArrayGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* jsException); diff --git a/src/RJSObject.mm b/src/RJSObject.mm index a9324bda..3333f73a 100644 --- a/src/RJSObject.mm +++ b/src/RJSObject.mm @@ -68,7 +68,7 @@ JSValueRef ObjectGetProperty(JSContextRef ctx, JSObjectRef jsObject, JSStringRef } case PropertyTypeArray: { auto arrayObjectSchema = obj->realm->config().schema->find(prop->object_type); - return RJSArrayCreate(ctx, new ObjectArray(obj->realm, *arrayObjectSchema, static_cast(obj->row.get_linklist(prop->table_column)))); + return RJSArrayCreate(ctx, new List(obj->realm, *arrayObjectSchema, static_cast(obj->row.get_linklist(prop->table_column)))); } } return NULL; diff --git a/src/RealmRPC.mm b/src/RealmRPC.mm index d38d664e..566c140e 100644 --- a/src/RealmRPC.mm +++ b/src/RealmRPC.mm @@ -250,13 +250,13 @@ using RPCRequest = std::function; }; } else if (JSValueIsObjectOfClass(_context, value, RJSArrayClass())) { - realm::ObjectArray *array = RJSGetInternal(jsObject); + realm::List *list = RJSGetInternal(jsObject); RPCObjectID oid = [self storeObject:jsObject]; return @{ @"type": @(RJSTypeGet(realm::PropertyTypeArray).c_str()), @"id": @(oid), - @"size": @(array->link_view->size()), - @"schema": [self objectSchemaToJSONObject:array->object_schema] + @"size": @(list->link_view->size()), + @"schema": [self objectSchemaToJSONObject:list->object_schema] }; } else if (JSValueIsObjectOfClass(_context, value, RJSResultsClass())) { From 77359f14e39d89b2763ebf96b5e343789f09ce18 Mon Sep 17 00:00:00 2001 From: Ari Lazier Date: Tue, 13 Oct 2015 14:44:31 -0700 Subject: [PATCH 23/27] move List class to its own file --- RealmJS.xcodeproj/project.pbxproj | 8 +++++ src/RJSArray.cpp | 28 ----------------- src/RJSArray.hpp | 18 +---------- src/object-store/list.cpp | 50 +++++++++++++++++++++++++++++++ src/object-store/list.hpp | 42 ++++++++++++++++++++++++++ 5 files changed, 101 insertions(+), 45 deletions(-) create mode 100644 src/object-store/list.cpp create mode 100644 src/object-store/list.hpp diff --git a/RealmJS.xcodeproj/project.pbxproj b/RealmJS.xcodeproj/project.pbxproj index 3366743b..6b4c1b3d 100644 --- a/RealmJS.xcodeproj/project.pbxproj +++ b/RealmJS.xcodeproj/project.pbxproj @@ -54,6 +54,8 @@ 0270BCD11B7D067300010E03 /* RealmReactModule.m in Sources */ = {isa = PBXBuildFile; fileRef = 0270BCD01B7D067300010E03 /* RealmReactModule.m */; }; 02B29A311B7CF86D008A7E6B /* RealmJS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 02B58CB11AE99CEC009B348C /* RealmJS.framework */; }; 02B58CCE1AE99D4D009B348C /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 02B58CCD1AE99D4D009B348C /* JavaScriptCore.framework */; }; + 02C0864E1BCDB27000942F9C /* list.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02C0864C1BCDB27000942F9C /* list.cpp */; settings = {ASSET_TAGS = (); }; }; + 02C0864F1BCDB27000942F9C /* list.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 02C0864D1BCDB27000942F9C /* list.hpp */; settings = {ASSET_TAGS = (); }; }; 02D456DA1B7E59A500EE1299 /* ArrayTests.js in Resources */ = {isa = PBXBuildFile; fileRef = 02D456D91B7E59A500EE1299 /* ArrayTests.js */; }; 02D8D1F71B601984006DB49D /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 02B58CCD1AE99D4D009B348C /* JavaScriptCore.framework */; }; /* End PBXBuildFile section */ @@ -183,6 +185,8 @@ 02B58CB11AE99CEC009B348C /* RealmJS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = RealmJS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 02B58CBC1AE99CEC009B348C /* RealmJSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RealmJSTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 02B58CCD1AE99D4D009B348C /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; }; + 02C0864C1BCDB27000942F9C /* list.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = list.cpp; path = "src/object-store/list.cpp"; sourceTree = ""; }; + 02C0864D1BCDB27000942F9C /* list.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = list.hpp; path = "src/object-store/list.hpp"; sourceTree = ""; }; 02D456D91B7E59A500EE1299 /* ArrayTests.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = ArrayTests.js; path = tests/ArrayTests.js; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ @@ -234,6 +238,8 @@ 02601F021BA0F0C4007C91FF /* external_commit_helper.hpp */, 02601F051BA0F0CD007C91FF /* index_set.cpp */, 02601F061BA0F0CD007C91FF /* index_set.hpp */, + 02C0864C1BCDB27000942F9C /* list.cpp */, + 02C0864D1BCDB27000942F9C /* list.hpp */, 02601F0B1BA0F3A7007C91FF /* schema.cpp */, 02601F0C1BA0F3A7007C91FF /* schema.hpp */, 02601F0F1BA10228007C91FF /* transact_log_handler.cpp */, @@ -353,6 +359,7 @@ 02601F041BA0F0C4007C91FF /* external_commit_helper.hpp in Headers */, 02601F091BA0F0CD007C91FF /* index_set.hpp in Headers */, 0270BC6D1B7CFC1C00010E03 /* property.hpp in Headers */, + 02C0864F1BCDB27000942F9C /* list.hpp in Headers */, 0270BC6F1B7CFC1C00010E03 /* results.hpp in Headers */, ); runOnlyForDeploymentPostprocessing = 0; @@ -563,6 +570,7 @@ 02601F111BA10228007C91FF /* transact_log_handler.cpp in Sources */, 0270BC591B7CFC0D00010E03 /* RJSUtil.mm in Sources */, 0270BC551B7CFC0D00010E03 /* RJSResults.mm in Sources */, + 02C0864E1BCDB27000942F9C /* list.cpp in Sources */, 02601F031BA0F0C4007C91FF /* external_commit_helper.cpp in Sources */, 0270BC6B1B7CFC1C00010E03 /* object_store.cpp in Sources */, 0270BC701B7CFC1C00010E03 /* shared_realm.cpp in Sources */, diff --git a/src/RJSArray.cpp b/src/RJSArray.cpp index b96f70ba..94b5dec4 100644 --- a/src/RJSArray.cpp +++ b/src/RJSArray.cpp @@ -24,34 +24,6 @@ using RJSAccessor = realm::NativeAccessor; using namespace realm; -size_t List::size() { - return link_view->size(); -} - -Row List::get(std::size_t row_ndx) { - verify_valid_row(row_ndx); - return link_view->get(row_ndx); -} - -void List::set(std::size_t row_ndx, std::size_t target_row_ndx) { - verify_valid_row(row_ndx); - link_view->set(row_ndx, target_row_ndx); -} - -void List::verify_valid_row(std::size_t row_ndx) { - size_t size = link_view->size(); - if (row_ndx >= size) { - throw std::out_of_range(std::string("Index ") + std::to_string(row_ndx) + " is outside of range 0..." + std::to_string(size) + "."); - } -} - -void List::verify_attached() { - if (!link_view->is_attached()) { - throw std::runtime_error("Tableview is not attached"); - } - link_view->sync_if_needed(); -} - static inline List * RJSVerifiedArray(JSObjectRef object) { List *list = RJSGetInternal(object); list->verify_attached(); diff --git a/src/RJSArray.hpp b/src/RJSArray.hpp index bafbb3b5..0cb70e36 100644 --- a/src/RJSArray.hpp +++ b/src/RJSArray.hpp @@ -18,23 +18,7 @@ #import "RJSUtil.hpp" #import "shared_realm.hpp" -#import - -namespace realm { - struct List { - List(SharedRealm &r, ObjectSchema &s, LinkViewRef l) : realm(r), object_schema(s), link_view(l) {} - // FIXME - all should be const - SharedRealm realm; - ObjectSchema &object_schema; - LinkViewRef link_view; - - size_t size(); - Row get(std::size_t row_ndx); - void set(std::size_t row_ndx, std::size_t target_row_ndx); - void verify_valid_row(std::size_t row_ndx); - void verify_attached(); - }; -} +#import "list.hpp" extern const JSStaticFunction RJSArrayFuncs[]; JSClassRef RJSArrayClass(); diff --git a/src/object-store/list.cpp b/src/object-store/list.cpp new file mode 100644 index 00000000..d4b2bb57 --- /dev/null +++ b/src/object-store/list.cpp @@ -0,0 +1,50 @@ +//////////////////////////////////////////////////////////////////////////// +// +// Copyright 2015 Realm Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////// + +#include "list.hpp" +#import + +using namespace realm; + +size_t List::size() { + return link_view->size(); +} + +Row List::get(std::size_t row_ndx) { + verify_valid_row(row_ndx); + return link_view->get(row_ndx); +} + +void List::set(std::size_t row_ndx, std::size_t target_row_ndx) { + verify_valid_row(row_ndx); + link_view->set(row_ndx, target_row_ndx); +} + +void List::verify_valid_row(std::size_t row_ndx) { + size_t size = link_view->size(); + if (row_ndx >= size) { + throw std::out_of_range(std::string("Index ") + std::to_string(row_ndx) + " is outside of range 0..." + std::to_string(size) + "."); + } +} + +void List::verify_attached() { + if (!link_view->is_attached()) { + throw std::runtime_error("Tableview is not attached"); + } + link_view->sync_if_needed(); +} diff --git a/src/object-store/list.hpp b/src/object-store/list.hpp new file mode 100644 index 00000000..a1fa1dde --- /dev/null +++ b/src/object-store/list.hpp @@ -0,0 +1,42 @@ +//////////////////////////////////////////////////////////////////////////// +// +// Copyright 2015 Realm Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////// + +#ifndef REALM_LIST_HPP +#define REALM_LIST_HPP + +#import "shared_realm.hpp" +#import + +namespace realm { + struct List { + List(SharedRealm &r, ObjectSchema &s, LinkViewRef l) : realm(r), object_schema(s), link_view(l) {} + // FIXME - all should be const + SharedRealm realm; + ObjectSchema &object_schema; + LinkViewRef link_view; + + size_t size(); + Row get(std::size_t row_ndx); + void set(std::size_t row_ndx, std::size_t target_row_ndx); + void verify_valid_row(std::size_t row_ndx); + void verify_attached(); + }; +} + + +#endif /* REALM_LIST_HPP */ From 385f38733206ba5c1a7880b67113bcc16e27573e Mon Sep 17 00:00:00 2001 From: Ari Lazier Date: Tue, 13 Oct 2015 15:25:06 -0700 Subject: [PATCH 24/27] move property getters to object store code --- RealmJS.xcodeproj/project.pbxproj | 4 - src/RJSArray.cpp | 4 +- src/RJSArray.hpp | 2 +- src/RJSObject.mm | 83 ++++++++-------- src/RJSRealm.mm | 4 +- src/RJSSchema.mm | 4 +- src/RJSUtil.hpp | 2 +- src/RealmRPC.mm | 2 +- src/object-store/object_accessor.cpp | 19 ---- src/object-store/object_accessor.hpp | 140 +++++++++++++++++++-------- 10 files changed, 149 insertions(+), 115 deletions(-) delete mode 100644 src/object-store/object_accessor.cpp diff --git a/RealmJS.xcodeproj/project.pbxproj b/RealmJS.xcodeproj/project.pbxproj index 6b4c1b3d..8be4202f 100644 --- a/RealmJS.xcodeproj/project.pbxproj +++ b/RealmJS.xcodeproj/project.pbxproj @@ -33,7 +33,6 @@ 0270BC571B7CFC0D00010E03 /* RJSSchema.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0270BC491B7CFC0D00010E03 /* RJSSchema.mm */; }; 0270BC581B7CFC0D00010E03 /* RJSUtil.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 0270BC4A1B7CFC0D00010E03 /* RJSUtil.hpp */; settings = {ATTRIBUTES = (Private, ); }; }; 0270BC591B7CFC0D00010E03 /* RJSUtil.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0270BC4B1B7CFC0D00010E03 /* RJSUtil.mm */; }; - 0270BC671B7CFC1C00010E03 /* object_accessor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0270BC5C1B7CFC1C00010E03 /* object_accessor.cpp */; }; 0270BC681B7CFC1C00010E03 /* object_accessor.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 0270BC5D1B7CFC1C00010E03 /* object_accessor.hpp */; }; 0270BC691B7CFC1C00010E03 /* object_schema.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0270BC5E1B7CFC1C00010E03 /* object_schema.cpp */; }; 0270BC6A1B7CFC1C00010E03 /* object_schema.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 0270BC5F1B7CFC1C00010E03 /* object_schema.hpp */; }; @@ -158,7 +157,6 @@ 0270BC4A1B7CFC0D00010E03 /* RJSUtil.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = RJSUtil.hpp; path = src/RJSUtil.hpp; sourceTree = ""; }; 0270BC4B1B7CFC0D00010E03 /* RJSUtil.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = RJSUtil.mm; path = src/RJSUtil.mm; sourceTree = ""; }; 0270BC5A1B7CFC1300010E03 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = src/Info.plist; sourceTree = ""; }; - 0270BC5C1B7CFC1C00010E03 /* object_accessor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = object_accessor.cpp; path = "src/object-store/object_accessor.cpp"; sourceTree = ""; }; 0270BC5D1B7CFC1C00010E03 /* object_accessor.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = object_accessor.hpp; path = "src/object-store/object_accessor.hpp"; sourceTree = ""; }; 0270BC5E1B7CFC1C00010E03 /* object_schema.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = object_schema.cpp; path = "src/object-store/object_schema.cpp"; sourceTree = ""; }; 0270BC5F1B7CFC1C00010E03 /* object_schema.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = object_schema.hpp; path = "src/object-store/object_schema.hpp"; sourceTree = ""; }; @@ -223,7 +221,6 @@ 0270BC3D1B7CFBFD00010E03 /* RealmJS */ = { isa = PBXGroup; children = ( - 0270BC5C1B7CFC1C00010E03 /* object_accessor.cpp */, 0270BC5D1B7CFC1C00010E03 /* object_accessor.hpp */, 0270BC5E1B7CFC1C00010E03 /* object_schema.cpp */, 0270BC5F1B7CFC1C00010E03 /* object_schema.hpp */, @@ -574,7 +571,6 @@ 02601F031BA0F0C4007C91FF /* external_commit_helper.cpp in Sources */, 0270BC6B1B7CFC1C00010E03 /* object_store.cpp in Sources */, 0270BC701B7CFC1C00010E03 /* shared_realm.cpp in Sources */, - 0270BC671B7CFC1C00010E03 /* object_accessor.cpp in Sources */, 0270BC4E1B7CFC0D00010E03 /* RJSArray.cpp in Sources */, 0270BC531B7CFC0D00010E03 /* RJSRealm.mm in Sources */, ); diff --git a/src/RJSArray.cpp b/src/RJSArray.cpp index 94b5dec4..60e5a771 100644 --- a/src/RJSArray.cpp +++ b/src/RJSArray.cpp @@ -210,8 +210,8 @@ JSValueRef ArraySplice(JSContextRef ctx, JSObjectRef function, JSObjectRef thisO return NULL; } -JSObjectRef RJSArrayCreate(JSContextRef ctx, realm::List *list) { - return RJSWrapObject(ctx, RJSArrayClass(), list); +JSObjectRef RJSArrayCreate(JSContextRef ctx, realm::List &list) { + return RJSWrapObject(ctx, RJSArrayClass(), new List(list)); } const JSStaticFunction RJSArrayFuncs[] = { diff --git a/src/RJSArray.hpp b/src/RJSArray.hpp index 0cb70e36..3805646b 100644 --- a/src/RJSArray.hpp +++ b/src/RJSArray.hpp @@ -22,6 +22,6 @@ extern const JSStaticFunction RJSArrayFuncs[]; JSClassRef RJSArrayClass(); -JSObjectRef RJSArrayCreate(JSContextRef ctx, realm::List *list); +JSObjectRef RJSArrayCreate(JSContextRef ctx, realm::List &list); JSValueRef ArrayGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* jsException); diff --git a/src/RJSObject.mm b/src/RJSObject.mm index 3333f73a..941e8504 100644 --- a/src/RJSObject.mm +++ b/src/RJSObject.mm @@ -29,49 +29,15 @@ using RJSAccessor = realm::NativeAccessor; using namespace realm; JSValueRef ObjectGetProperty(JSContextRef ctx, JSObjectRef jsObject, JSStringRef jsPropertyName, JSValueRef* exception) { - Object *obj = RJSGetInternal(jsObject); - - std::string propName = RJSStringForJSString(jsPropertyName); - ObjectSchema &objectSchema = obj->object_schema; - Property *prop = objectSchema.property_for_name(propName); - if (!prop) { + try { + Object *obj = RJSGetInternal(jsObject); + return obj->get_property_value(ctx, RJSStringForJSString(jsPropertyName)); + } catch (std::exception &ex) { + if (exception) { + *exception = RJSMakeError(ctx, ex); + } return NULL; } - - switch (prop->type) { - case PropertyTypeBool: - return JSValueMakeBoolean(ctx, obj->row.get_bool(prop->table_column)); - case PropertyTypeInt: - return JSValueMakeNumber(ctx, obj->row.get_int(prop->table_column)); - case PropertyTypeFloat: - return JSValueMakeNumber(ctx, obj->row.get_float(prop->table_column)); - case PropertyTypeDouble: - return JSValueMakeNumber(ctx, obj->row.get_double(prop->table_column)); - case PropertyTypeString: - return RJSValueForString(ctx, obj->row.get_string(prop->table_column)); - case PropertyTypeData: - return RJSValueForString(ctx, (std::string)obj->row.get_binary(prop->table_column)); - case PropertyTypeAny: - *exception = RJSMakeError(ctx, "'Any' type not supported"); - return NULL; - case PropertyTypeDate: { - JSValueRef time = JSValueMakeNumber(ctx, obj->row.get_datetime(prop->table_column).get_datetime()); - return JSObjectMakeDate(ctx, 1, &time, exception); - } - case PropertyTypeObject: { - auto linkObjectSchema = obj->realm->config().schema->find(prop->object_type); - TableRef table = ObjectStore::table_for_object_type(obj->realm->read_group(), linkObjectSchema->name); - if (obj->row.is_null_link(prop->table_column)) { - return JSValueMakeNull(ctx); - } - return RJSObjectCreate(ctx, Object(obj->realm, *linkObjectSchema, table->get(obj->row.get_link(prop->table_column)))); - } - case PropertyTypeArray: { - auto arrayObjectSchema = obj->realm->config().schema->find(prop->object_type); - return RJSArrayCreate(ctx, new List(obj->realm, *arrayObjectSchema, static_cast(obj->row.get_linklist(prop->table_column)))); - } - } - return NULL; } bool ObjectSetProperty(JSContextRef ctx, JSObjectRef jsObject, JSStringRef jsPropertyName, JSValueRef value, JSValueRef* exception) { @@ -133,6 +99,9 @@ template<> JSValueRef RJSAccessor::default_value_for_property(JSContextRef ctx, template<> bool RJSAccessor::is_null(JSContextRef ctx, JSValueRef &val) { return JSValueIsUndefined(ctx, val) || JSValueIsNull(ctx, val); } +template<> JSValueRef RJSAccessor::null_value(JSContextRef ctx) { + return JSValueMakeNull(ctx); +} template<> bool RJSAccessor::to_bool(JSContextRef ctx, JSValueRef &val) { if (!JSValueIsBoolean(ctx, val)) { @@ -140,22 +109,37 @@ template<> bool RJSAccessor::to_bool(JSContextRef ctx, JSValueRef &val) { } return JSValueToBoolean(ctx, val); } +template<> JSValueRef RJSAccessor::from_bool(JSContextRef ctx, bool b) { + return JSValueMakeBoolean(ctx, b); +} template<> long long RJSAccessor::to_long(JSContextRef ctx, JSValueRef &val) { return RJSValidatedValueToNumber(ctx, val); } +template<> JSValueRef RJSAccessor::from_long(JSContextRef ctx, long long l) { + return JSValueMakeNumber(ctx, l); +} template<> float RJSAccessor::to_float(JSContextRef ctx, JSValueRef &val) { return RJSValidatedValueToNumber(ctx, val); } +template<> JSValueRef RJSAccessor::from_float(JSContextRef ctx, float f) { + return JSValueMakeNumber(ctx, f); +} template<> double RJSAccessor::to_double(JSContextRef ctx, JSValueRef &val) { return RJSValidatedValueToNumber(ctx, val); } +template<> JSValueRef RJSAccessor::from_double(JSContextRef ctx, double d) { + return JSValueMakeNumber(ctx, d); +} template<> std::string RJSAccessor::to_string(JSContextRef ctx, JSValueRef &val) { return RJSValidatedStringForValue(ctx, val); } +template<> JSValueRef RJSAccessor::from_string(JSContextRef ctx, StringData s) { + return RJSValueForString(ctx, s); +} template<> DateTime RJSAccessor::to_datetime(JSContextRef ctx, JSValueRef &val) { JSObjectRef object = RJSValidatedValueToObject(ctx, val, "Property must be a Date"); @@ -176,6 +160,10 @@ template<> DateTime RJSAccessor::to_datetime(JSContextRef ctx, JSValueRef &val) return DateTime(utc); } +template<> JSValueRef RJSAccessor::from_datetime(JSContextRef ctx, DateTime dt) { + JSValueRef time = JSValueMakeNumber(ctx, dt.get_datetime()); + return JSObjectMakeDate(ctx, 1, &time, NULL); +} extern JSObjectRef RJSDictForPropertyArray(JSContextRef ctx, ObjectSchema &object_schema, JSObjectRef array); @@ -193,11 +181,16 @@ template<> size_t RJSAccessor::to_object_index(JSContextRef ctx, SharedRealm &re Object child = Object::create(ctx, realm, *object_schema, (JSValueRef)object, try_update); return child.row.get_index(); } - -template<> size_t RJSAccessor::array_size(JSContextRef ctx, JSValueRef &val) { - return RJSValidatedArrayLength(ctx, RJSValidatedValueToObject(ctx, val)); +template<> JSValueRef RJSAccessor::from_object(JSContextRef ctx, Object object) { + return RJSObjectCreate(ctx, object); } -template<> JSValueRef RJSAccessor::array_value_at_index(JSContextRef ctx, JSValueRef &val, size_t index) { +template<> size_t RJSAccessor::list_size(JSContextRef ctx, JSValueRef &val) { + return RJSValidatedListLength(ctx, RJSValidatedValueToObject(ctx, val)); +} +template<> JSValueRef RJSAccessor::list_value_at_index(JSContextRef ctx, JSValueRef &val, size_t index) { return RJSValidatedObjectAtIndex(ctx, RJSValidatedValueToObject(ctx, val), (unsigned int)index); } +template<> JSValueRef RJSAccessor::from_list(JSContextRef ctx, List list) { + return RJSArrayCreate(ctx, list); +} diff --git a/src/RJSRealm.mm b/src/RJSRealm.mm index aed02df9..9323ce99 100644 --- a/src/RJSRealm.mm +++ b/src/RJSRealm.mm @@ -221,7 +221,7 @@ JSValueRef RealmObjects(JSContextRef ctx, JSObjectRef function, JSObjectRef this JSObjectRef RJSDictForPropertyArray(JSContextRef ctx, ObjectSchema &object_schema, JSObjectRef array) { // copy to dictionary - if (object_schema.properties.size() != RJSValidatedArrayLength(ctx, array)) { + if (object_schema.properties.size() != RJSValidatedListLength(ctx, array)) { throw std::runtime_error("Array must contain values for all object properties"); } @@ -283,7 +283,7 @@ JSValueRef RealmDelete(JSContextRef ctx, JSObjectRef function, JSObjectRef thisO JSValueIsObjectOfClass(ctx, arguments[0], RJSArrayClass())) { JSObjectRef array = RJSValidatedValueToObject(ctx, arguments[0]); - size_t length = RJSValidatedArrayLength(ctx, array); + size_t length = RJSValidatedListLength(ctx, array); for (long i = length-1; i >= 0; i--) { JSValueRef object = RJSValidatedObjectAtIndex(ctx, array, (unsigned int)i); RealmDelete(ctx, function, thisObject, 1, &object, jsException); diff --git a/src/RJSSchema.mm b/src/RJSSchema.mm index 534b44b5..ef9fdb12 100644 --- a/src/RJSSchema.mm +++ b/src/RJSSchema.mm @@ -127,7 +127,7 @@ static inline ObjectSchema RJSParseObjectSchema(JSContextRef ctx, JSObjectRef ob static JSStringRef nameString = JSStringCreateWithUTF8CString("name"); objectSchema.name = RJSValidatedStringProperty(ctx, objectSchemaObject, nameString); - size_t numProperties = RJSValidatedArrayLength(ctx, propertiesObject); + size_t numProperties = RJSValidatedListLength(ctx, propertiesObject); for (unsigned int p = 0; p < numProperties; p++) { JSObjectRef property = RJSValidatedObjectAtIndex(ctx, propertiesObject, p); objectSchema.properties.emplace_back(RJSParseProperty(ctx, property)); @@ -163,7 +163,7 @@ static inline ObjectSchema RJSParseObjectSchema(JSContextRef ctx, JSObjectRef ob realm::Schema RJSParseSchema(JSContextRef ctx, JSObjectRef jsonObject) { std::vector schema; - size_t length = RJSValidatedArrayLength(ctx, jsonObject); + size_t length = RJSValidatedListLength(ctx, jsonObject); for (unsigned int i = 0; i < length; i++) { JSObjectRef jsonObjectSchema = RJSValidatedObjectAtIndex(ctx, jsonObject, i); ObjectSchema objectSchema = RJSParseObjectSchema(ctx, jsonObjectSchema); diff --git a/src/RJSUtil.hpp b/src/RJSUtil.hpp index 056b93bb..bb692d16 100644 --- a/src/RJSUtil.hpp +++ b/src/RJSUtil.hpp @@ -153,7 +153,7 @@ static inline std::string RJSValidatedStringProperty(JSContextRef ctx, JSObjectR return RJSValidatedStringForValue(ctx, propertyValue); } -static inline size_t RJSValidatedArrayLength(JSContextRef ctx, JSObjectRef object) { +static inline size_t RJSValidatedListLength(JSContextRef ctx, JSObjectRef object) { JSValueRef exception = NULL; static JSStringRef lengthString = JSStringCreateWithUTF8CString("length"); JSValueRef lengthValue = JSObjectGetProperty(ctx, object, lengthString, &exception); diff --git a/src/RealmRPC.mm b/src/RealmRPC.mm index 566c140e..d498d0c3 100644 --- a/src/RealmRPC.mm +++ b/src/RealmRPC.mm @@ -270,7 +270,7 @@ using RPCRequest = std::function; }; } else if (RJSIsValueArray(_context, value)) { - size_t length = RJSValidatedArrayLength(_context, jsObject); + size_t length = RJSValidatedListLength(_context, jsObject); NSMutableArray *array = [NSMutableArray new]; for (unsigned int i = 0; i < length; i++) { [array addObject:[self resultForJSValue:JSObjectGetPropertyAtIndex(_context, jsObject, i, NULL)]]; diff --git a/src/object-store/object_accessor.cpp b/src/object-store/object_accessor.cpp deleted file mode 100644 index 2516cc5d..00000000 --- a/src/object-store/object_accessor.cpp +++ /dev/null @@ -1,19 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2015 Realm Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -//////////////////////////////////////////////////////////////////////////// - -#include "object_accessor.hpp" diff --git a/src/object-store/object_accessor.hpp b/src/object-store/object_accessor.hpp index fa6d6366..69bffa70 100644 --- a/src/object-store/object_accessor.hpp +++ b/src/object-store/object_accessor.hpp @@ -21,43 +21,9 @@ #include #include "shared_realm.hpp" +#include "list.hpp" namespace realm { - template - class NativeAccessor { - public: - // - // Value converters - template specializations must be implemented for each platform - // - static bool dict_has_value_for_key(ContextType ctx, ValueType dict, const std::string &prop_name); - static ValueType dict_value_for_key(ContextType ctx, ValueType dict, const std::string &prop_name); - - static bool has_default_value_for_property(ContextType ctx, const ObjectSchema &object_schema, const std::string &prop_name); - static ValueType default_value_for_property(ContextType ctx, const ObjectSchema &object_schema, const std::string &prop_name); - - static bool to_bool(ContextType ctx, ValueType &val); - static long long to_long(ContextType ctx, ValueType &val); - static float to_float(ContextType ctx, ValueType &val); - static double to_double(ContextType ctx, ValueType &val); - static std::string to_string(ContextType ctx, ValueType &val); - static DateTime to_datetime(ContextType ctx, ValueType &val); - - static bool is_null(ContextType ctx, ValueType &val); - - // convert value to persisted object - // for existing objects return the existing row index - // for new/updated objects return the row index - static size_t to_object_index(ContextType ctx, SharedRealm &realm, ValueType &val, std::string &type, bool try_update); - - // array value acessors - static size_t array_size(ContextType ctx, ValueType &val); - static ValueType array_value_at_index(ContextType ctx, ValueType &val, size_t index); - - // - // Deprecated - // - static Mixed to_mixed(ContextType ctx, ValueType &val) { throw std::runtime_error("'Any' type is unsupported"); } - }; class Object { public: @@ -67,10 +33,13 @@ namespace realm { ObjectSchema &object_schema; Row row; - // property setter + // property getter/setter template inline void set_property_value(ContextType ctx, std::string prop_name, ValueType value, bool try_update); + template + inline ValueType get_property_value(ContextType ctx, std::string prop_name); + // create an Object from a native representation template static inline Object create(ContextType ctx, SharedRealm realm, ObjectSchema &object_schema, ValueType value, bool try_update); @@ -78,6 +47,53 @@ namespace realm { private: template inline void set_property_value_impl(ContextType ctx, Property &property, ValueType value, bool try_update); + template + inline ValueType get_property_value_impl(ContextType ctx, Property &property); + }; + + // + // Value converters - template specializations must be implemented for each platform in order to call templated methods on Object + // + template + class NativeAccessor { + public: + static bool dict_has_value_for_key(ContextType ctx, ValueType dict, const std::string &prop_name); + static ValueType dict_value_for_key(ContextType ctx, ValueType dict, const std::string &prop_name); + + static bool has_default_value_for_property(ContextType ctx, const ObjectSchema &object_schema, const std::string &prop_name); + static ValueType default_value_for_property(ContextType ctx, const ObjectSchema &object_schema, const std::string &prop_name); + + static bool to_bool(ContextType, ValueType &); + static ValueType from_bool(ContextType, bool); + static long long to_long(ContextType, ValueType &); + static ValueType from_long(ContextType, long long); + static float to_float(ContextType, ValueType &); + static ValueType from_float(ContextType, float); + static double to_double(ContextType, ValueType &); + static ValueType from_double(ContextType, double); + static std::string to_string(ContextType, ValueType &); + static ValueType from_string(ContextType, StringData); + static DateTime to_datetime(ContextType, ValueType &); + static ValueType from_datetime(ContextType, DateTime); + + static bool is_null(ContextType, ValueType &); + static ValueType null_value(ContextType); + + // convert value to persisted object + // for existing objects return the existing row index + // for new/updated objects return the row index + static size_t to_object_index(ContextType ctx, SharedRealm &realm, ValueType &val, std::string &type, bool try_update); + static ValueType from_object(ContextType ctx, Object); + + // list value acessors + static size_t list_size(ContextType ctx, ValueType &val); + static ValueType list_value_at_index(ContextType ctx, ValueType &val, size_t index); + static ValueType from_list(ContextType ctx, List); + + // + // Deprecated + // + static Mixed to_mixed(ContextType ctx, ValueType &val) { throw std::runtime_error("'Any' type is unsupported"); } }; // @@ -93,6 +109,16 @@ namespace realm { set_property_value_impl(ctx, *prop, value, try_update); }; + template + inline ValueType Object::get_property_value(ContextType ctx, std::string prop_name) + { + Property *prop = object_schema.property_for_name(prop_name); + if (!prop) { + throw std::runtime_error("Setting invalid property '" + prop_name + "' on object '" + object_schema.name + "'."); + } + return get_property_value_impl(ctx, *prop); + }; + template inline void Object::set_property_value_impl(ContextType ctx, Property &property, ValueType value, bool try_update) { @@ -140,9 +166,9 @@ namespace realm { case PropertyTypeArray: { realm::LinkViewRef link_view = row.get_linklist(column); link_view->clear(); - size_t count = Accessor::array_size(ctx, value); + size_t count = Accessor::list_size(ctx, value); for (size_t i = 0; i < count; i++) { - ValueType element = Accessor::array_value_at_index(ctx, value, i); + ValueType element = Accessor::list_value_at_index(ctx, value, i); link_view->add(Accessor::to_object_index(ctx, realm, element, property.object_type, try_update)); } break; @@ -150,6 +176,44 @@ namespace realm { } } + template + inline ValueType Object::get_property_value_impl(ContextType ctx, Property &property) + { + using Accessor = NativeAccessor; + + size_t column = property.table_column; + switch (property.type) { + case PropertyTypeBool: + return Accessor::from_bool(ctx, row.get_bool(column)); + case PropertyTypeInt: + return Accessor::from_long(ctx, row.get_int(column)); + case PropertyTypeFloat: + return Accessor::from_float(ctx, row.get_float(column)); + case PropertyTypeDouble: + return Accessor::from_double(ctx, row.get_double(column)); + case PropertyTypeString: + return Accessor::from_string(ctx, row.get_string(column)); + case PropertyTypeData: + return Accessor::from_string(ctx, (std::string)row.get_binary(column)); + case PropertyTypeAny: + throw "Any not supported"; + case PropertyTypeDate: + return Accessor::from_datetime(ctx, row.get_datetime(column)); + case PropertyTypeObject: { + auto linkObjectSchema = realm->config().schema->find(property.object_type); + TableRef table = ObjectStore::table_for_object_type(realm->read_group(), linkObjectSchema->name); + if (row.is_null_link(property.table_column)) { + return Accessor::null_value(ctx); + } + return Accessor::from_object(ctx, std::move(Object(realm, *linkObjectSchema, table->get(row.get_link(column))))); + } + case PropertyTypeArray: { + auto arrayObjectSchema = realm->config().schema->find(property.object_type); + return Accessor::from_list(ctx, std::move(List(realm, *arrayObjectSchema, static_cast(row.get_linklist(column))))); + } + } + } + template inline Object Object::create(ContextType ctx, SharedRealm realm, ObjectSchema &object_schema, ValueType value, bool try_update) { From f6e0d34022089a54bdeaa80a5379aeaf66d0ecec Mon Sep 17 00:00:00 2001 From: Ari Lazier Date: Tue, 13 Oct 2015 15:27:24 -0700 Subject: [PATCH 25/27] RJSArray -> RJSList --- RealmJS.xcodeproj/project.pbxproj | 16 ++++++++-------- src/{RJSArray.cpp => RJSList.cpp} | 12 ++++++------ src/{RJSArray.hpp => RJSList.hpp} | 6 +++--- src/RJSObject.mm | 4 ++-- src/RJSRealm.mm | 4 ++-- src/RealmRPC.mm | 6 +++--- tests/RealmJSTests.mm | 4 ++-- 7 files changed, 26 insertions(+), 26 deletions(-) rename src/{RJSArray.cpp => RJSList.cpp} (96%) rename src/{RJSArray.hpp => RJSList.hpp} (86%) diff --git a/RealmJS.xcodeproj/project.pbxproj b/RealmJS.xcodeproj/project.pbxproj index 8be4202f..125febe4 100644 --- a/RealmJS.xcodeproj/project.pbxproj +++ b/RealmJS.xcodeproj/project.pbxproj @@ -21,8 +21,8 @@ 02601F121BA10228007C91FF /* transact_log_handler.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 02601F101BA10228007C91FF /* transact_log_handler.hpp */; }; 0270BC4C1B7CFC0D00010E03 /* RealmJS.h in Headers */ = {isa = PBXBuildFile; fileRef = 0270BC3E1B7CFC0D00010E03 /* RealmJS.h */; settings = {ATTRIBUTES = (Public, ); }; }; 0270BC4D1B7CFC0D00010E03 /* RealmJS.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0270BC3F1B7CFC0D00010E03 /* RealmJS.mm */; }; - 0270BC4E1B7CFC0D00010E03 /* RJSArray.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0270BC401B7CFC0D00010E03 /* RJSArray.cpp */; }; - 0270BC4F1B7CFC0D00010E03 /* RJSArray.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 0270BC411B7CFC0D00010E03 /* RJSArray.hpp */; settings = {ATTRIBUTES = (Private, ); }; }; + 0270BC4E1B7CFC0D00010E03 /* RJSList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0270BC401B7CFC0D00010E03 /* RJSList.cpp */; }; + 0270BC4F1B7CFC0D00010E03 /* RJSList.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 0270BC411B7CFC0D00010E03 /* RJSList.hpp */; settings = {ATTRIBUTES = (Private, ); }; }; 0270BC501B7CFC0D00010E03 /* RJSObject.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 0270BC421B7CFC0D00010E03 /* RJSObject.hpp */; settings = {ATTRIBUTES = (Private, ); }; }; 0270BC511B7CFC0D00010E03 /* RJSObject.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0270BC431B7CFC0D00010E03 /* RJSObject.mm */; }; 0270BC521B7CFC0D00010E03 /* RJSRealm.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 0270BC441B7CFC0D00010E03 /* RJSRealm.hpp */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -144,8 +144,8 @@ 02601F101BA10228007C91FF /* transact_log_handler.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = transact_log_handler.hpp; path = "src/object-store/transact_log_handler.hpp"; sourceTree = ""; }; 0270BC3E1B7CFC0D00010E03 /* RealmJS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RealmJS.h; path = src/RealmJS.h; sourceTree = ""; }; 0270BC3F1B7CFC0D00010E03 /* RealmJS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = RealmJS.mm; path = src/RealmJS.mm; sourceTree = ""; }; - 0270BC401B7CFC0D00010E03 /* RJSArray.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RJSArray.cpp; path = src/RJSArray.cpp; sourceTree = ""; }; - 0270BC411B7CFC0D00010E03 /* RJSArray.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = RJSArray.hpp; path = src/RJSArray.hpp; sourceTree = ""; }; + 0270BC401B7CFC0D00010E03 /* RJSList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RJSList.cpp; path = src/RJSList.cpp; sourceTree = ""; }; + 0270BC411B7CFC0D00010E03 /* RJSList.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = RJSList.hpp; path = src/RJSList.hpp; sourceTree = ""; }; 0270BC421B7CFC0D00010E03 /* RJSObject.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = RJSObject.hpp; path = src/RJSObject.hpp; sourceTree = ""; }; 0270BC431B7CFC0D00010E03 /* RJSObject.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = RJSObject.mm; path = src/RJSObject.mm; sourceTree = ""; }; 0270BC441B7CFC0D00010E03 /* RJSRealm.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = RJSRealm.hpp; path = src/RJSRealm.hpp; sourceTree = ""; }; @@ -246,8 +246,8 @@ 0270BC3F1B7CFC0D00010E03 /* RealmJS.mm */, 02258FB11BC6E2D00075F13A /* RealmRPC.h */, 02258FB21BC6E2D00075F13A /* RealmRPC.mm */, - 0270BC401B7CFC0D00010E03 /* RJSArray.cpp */, - 0270BC411B7CFC0D00010E03 /* RJSArray.hpp */, + 0270BC401B7CFC0D00010E03 /* RJSList.cpp */, + 0270BC411B7CFC0D00010E03 /* RJSList.hpp */, 0270BC421B7CFC0D00010E03 /* RJSObject.hpp */, 0270BC431B7CFC0D00010E03 /* RJSObject.mm */, 0270BC441B7CFC0D00010E03 /* RJSRealm.hpp */, @@ -340,7 +340,7 @@ files = ( 0270BC4C1B7CFC0D00010E03 /* RealmJS.h in Headers */, 02258FB31BC6E2D00075F13A /* RealmRPC.h in Headers */, - 0270BC4F1B7CFC0D00010E03 /* RJSArray.hpp in Headers */, + 0270BC4F1B7CFC0D00010E03 /* RJSList.hpp in Headers */, 0270BC541B7CFC0D00010E03 /* RJSResults.hpp in Headers */, 0270BC581B7CFC0D00010E03 /* RJSUtil.hpp in Headers */, 0270BC561B7CFC0D00010E03 /* RJSSchema.hpp in Headers */, @@ -571,7 +571,7 @@ 02601F031BA0F0C4007C91FF /* external_commit_helper.cpp in Sources */, 0270BC6B1B7CFC1C00010E03 /* object_store.cpp in Sources */, 0270BC701B7CFC1C00010E03 /* shared_realm.cpp in Sources */, - 0270BC4E1B7CFC0D00010E03 /* RJSArray.cpp in Sources */, + 0270BC4E1B7CFC0D00010E03 /* RJSList.cpp in Sources */, 0270BC531B7CFC0D00010E03 /* RJSRealm.mm in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/src/RJSArray.cpp b/src/RJSList.cpp similarity index 96% rename from src/RJSArray.cpp rename to src/RJSList.cpp index 60e5a771..11556f9b 100644 --- a/src/RJSArray.cpp +++ b/src/RJSList.cpp @@ -16,7 +16,7 @@ // //////////////////////////////////////////////////////////////////////////// -#include "RJSArray.hpp" +#include "RJSList.hpp" #include "RJSObject.hpp" #include "RJSUtil.hpp" #include "object_accessor.hpp" @@ -210,11 +210,11 @@ JSValueRef ArraySplice(JSContextRef ctx, JSObjectRef function, JSObjectRef thisO return NULL; } -JSObjectRef RJSArrayCreate(JSContextRef ctx, realm::List &list) { - return RJSWrapObject(ctx, RJSArrayClass(), new List(list)); +JSObjectRef RJSListCreate(JSContextRef ctx, realm::List &list) { + return RJSWrapObject(ctx, RJSListClass(), new List(list)); } -const JSStaticFunction RJSArrayFuncs[] = { +const JSStaticFunction RJSListFuncs[] = { {"push", ArrayPush, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, {"pop", ArrayPop, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, {"shift", ArrayShift, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, @@ -223,7 +223,7 @@ const JSStaticFunction RJSArrayFuncs[] = { {NULL, NULL}, }; -JSClassRef RJSArrayClass() { - static JSClassRef s_arrayClass = RJSCreateWrapperClass("RealmArray", ArrayGetProperty, ArraySetProperty, RJSArrayFuncs, NULL, ArrayPropertyNames); +JSClassRef RJSListClass() { + static JSClassRef s_arrayClass = RJSCreateWrapperClass("RealmList", ArrayGetProperty, ArraySetProperty, RJSListFuncs, NULL, ArrayPropertyNames); return s_arrayClass; } diff --git a/src/RJSArray.hpp b/src/RJSList.hpp similarity index 86% rename from src/RJSArray.hpp rename to src/RJSList.hpp index 3805646b..2b521203 100644 --- a/src/RJSArray.hpp +++ b/src/RJSList.hpp @@ -20,8 +20,8 @@ #import "shared_realm.hpp" #import "list.hpp" -extern const JSStaticFunction RJSArrayFuncs[]; -JSClassRef RJSArrayClass(); -JSObjectRef RJSArrayCreate(JSContextRef ctx, realm::List &list); +extern const JSStaticFunction RJSListFuncs[]; +JSClassRef RJSListClass(); +JSObjectRef RJSListCreate(JSContextRef ctx, realm::List &list); JSValueRef ArrayGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* jsException); diff --git a/src/RJSObject.mm b/src/RJSObject.mm index 941e8504..1d088469 100644 --- a/src/RJSObject.mm +++ b/src/RJSObject.mm @@ -20,7 +20,7 @@ #import "RJSObject.hpp" #import "RJSResults.hpp" #import "RJSSchema.hpp" -#import "RJSArray.hpp" +#import "RJSList.hpp" #import "object_store.hpp" #import "object_accessor.hpp" @@ -192,5 +192,5 @@ template<> JSValueRef RJSAccessor::list_value_at_index(JSContextRef ctx, JSValue return RJSValidatedObjectAtIndex(ctx, RJSValidatedValueToObject(ctx, val), (unsigned int)index); } template<> JSValueRef RJSAccessor::from_list(JSContextRef ctx, List list) { - return RJSArrayCreate(ctx, list); + return RJSListCreate(ctx, list); } diff --git a/src/RJSRealm.mm b/src/RJSRealm.mm index 9323ce99..e8366c22 100644 --- a/src/RJSRealm.mm +++ b/src/RJSRealm.mm @@ -19,7 +19,7 @@ #import "RJSRealm.hpp" #import "RJSObject.hpp" #import "RJSResults.hpp" -#import "RJSArray.hpp" +#import "RJSList.hpp" #import "RJSSchema.hpp" #import "shared_realm.hpp" @@ -280,7 +280,7 @@ JSValueRef RealmDelete(JSContextRef ctx, JSObjectRef function, JSObjectRef thisO if (RJSIsValueArray(ctx, arguments[0]) || JSValueIsObjectOfClass(ctx, arguments[0], RJSResultsClass()) || - JSValueIsObjectOfClass(ctx, arguments[0], RJSArrayClass())) + JSValueIsObjectOfClass(ctx, arguments[0], RJSListClass())) { JSObjectRef array = RJSValidatedValueToObject(ctx, arguments[0]); size_t length = RJSValidatedListLength(ctx, array); diff --git a/src/RealmRPC.mm b/src/RealmRPC.mm index d498d0c3..c3004356 100644 --- a/src/RealmRPC.mm +++ b/src/RealmRPC.mm @@ -24,7 +24,7 @@ #include "RealmJS.h" #include "RJSObject.hpp" #include "RJSResults.hpp" -#include "RJSArray.hpp" +#include "RJSList.hpp" #include "RJSRealm.hpp" #include "RJSUtil.hpp" @@ -166,7 +166,7 @@ using RPCRequest = std::function; _requests["/call_list_method"] = [=](NSDictionary *dict) { NSString *name = dict[@"name"]; return [self performObjectMethod:name.UTF8String - classMethods:RJSArrayFuncs + classMethods:RJSListFuncs args:dict[@"arguments"] objectId:[dict[@"listId"] unsignedLongValue]]; }; @@ -249,7 +249,7 @@ using RPCRequest = std::function; @"schema": [self objectSchemaToJSONObject:object->object_schema] }; } - else if (JSValueIsObjectOfClass(_context, value, RJSArrayClass())) { + else if (JSValueIsObjectOfClass(_context, value, RJSListClass())) { realm::List *list = RJSGetInternal(jsObject); RPCObjectID oid = [self storeObject:jsObject]; return @{ diff --git a/tests/RealmJSTests.mm b/tests/RealmJSTests.mm index 5f556422..0f89a761 100644 --- a/tests/RealmJSTests.mm +++ b/tests/RealmJSTests.mm @@ -243,9 +243,9 @@ static JSClassRef s_globalClass; } @end -@interface RJSArrayTests : RealmJSTests +@interface RJSListTests : RealmJSTests @end -@implementation RJSArrayTests +@implementation RJSListTests + (NSString *)jsSuiteName { return @"ArrayTests"; } From 7db001c3dab017d925d8f31dba2c5d0aad7ad169 Mon Sep 17 00:00:00 2001 From: Ari Lazier Date: Tue, 13 Oct 2015 15:56:43 -0700 Subject: [PATCH 26/27] finish Array to List rename --- src/RJSList.cpp | 52 ++++++++++++++++++++++++------------------------- src/RJSList.hpp | 2 +- src/RealmRPC.mm | 4 ++-- 3 files changed, 29 insertions(+), 29 deletions(-) diff --git a/src/RJSList.cpp b/src/RJSList.cpp index 11556f9b..dfb35bb5 100644 --- a/src/RJSList.cpp +++ b/src/RJSList.cpp @@ -24,24 +24,24 @@ using RJSAccessor = realm::NativeAccessor; using namespace realm; -static inline List * RJSVerifiedArray(JSObjectRef object) { +static inline List * RJSVerifiedList(JSObjectRef object) { List *list = RJSGetInternal(object); list->verify_attached(); return list; } -static inline List * RJSVerifiedMutableArray(JSObjectRef object) { - List *list = RJSVerifiedArray(object); +static inline List * RJSVerifiedMutableList(JSObjectRef object) { + List *list = RJSVerifiedList(object); if (!list->realm->is_in_transaction()) { throw std::runtime_error("Can only mutate lists within a transaction."); } return list; } -JSValueRef ArrayGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* jsException) { +JSValueRef ListGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* jsException) { try { // index subscripting - List *list = RJSVerifiedArray(object); + List *list = RJSVerifiedList(object); size_t size = list->size(); std::string indexStr = RJSStringForJSString(propertyName); @@ -67,9 +67,9 @@ JSValueRef ArrayGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef pr } } -bool ArraySetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* jsException) { +bool ListSetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* jsException) { try { - List *list = RJSVerifiedMutableArray(object); + List *list = RJSVerifiedMutableList(object); std::string indexStr = RJSStringForJSString(propertyName); if (indexStr == "length") { throw std::runtime_error("The 'length' property is readonly."); @@ -90,8 +90,8 @@ bool ArraySetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef property } } -void ArrayPropertyNames(JSContextRef ctx, JSObjectRef object, JSPropertyNameAccumulatorRef propertyNames) { - List *list = RJSVerifiedArray(object); +void ListPropertyNames(JSContextRef ctx, JSObjectRef object, JSPropertyNameAccumulatorRef propertyNames) { + List *list = RJSVerifiedList(object); size_t size = list->size(); char str[32]; @@ -103,9 +103,9 @@ void ArrayPropertyNames(JSContextRef ctx, JSObjectRef object, JSPropertyNameAccu } } -JSValueRef ArrayPush(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* jsException) { +JSValueRef ListPush(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* jsException) { try { - List *array = RJSVerifiedMutableArray(thisObject); + List *array = RJSVerifiedMutableList(thisObject); RJSValidateArgumentCountIsAtLeast(argumentCount, 1); for (size_t i = 0; i < argumentCount; i++) { array->link_view->add(RJSAccessor::to_object_index(ctx, array->realm, const_cast(arguments[i]), array->object_schema.name, false)); @@ -120,9 +120,9 @@ JSValueRef ArrayPush(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObj return NULL; } -JSValueRef ArrayPop(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* jsException) { +JSValueRef ListPop(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* jsException) { try { - List *list = RJSVerifiedMutableArray(thisObject); + List *list = RJSVerifiedMutableList(thisObject); RJSValidateArgumentCount(argumentCount, 0); size_t size = list->size(); @@ -142,9 +142,9 @@ JSValueRef ArrayPop(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObje return NULL; } -JSValueRef ArrayUnshift(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* jsException) { +JSValueRef ListUnshift(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* jsException) { try { - List *array = RJSVerifiedMutableArray(thisObject); + List *array = RJSVerifiedMutableList(thisObject); RJSValidateArgumentCountIsAtLeast(argumentCount, 1); for (size_t i = 0; i < argumentCount; i++) { array->link_view->insert(i, RJSAccessor::to_object_index(ctx, array->realm, const_cast(arguments[i]), array->object_schema.name, false)); @@ -159,9 +159,9 @@ JSValueRef ArrayUnshift(JSContextRef ctx, JSObjectRef function, JSObjectRef this return NULL; } -JSValueRef ArrayShift(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* jsException) { +JSValueRef ListShift(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* jsException) { try { - List *list = RJSVerifiedMutableArray(thisObject); + List *list = RJSVerifiedMutableList(thisObject); RJSValidateArgumentCount(argumentCount, 0); if (list->size() == 0) { return JSValueMakeUndefined(ctx); @@ -178,9 +178,9 @@ JSValueRef ArrayShift(JSContextRef ctx, JSObjectRef function, JSObjectRef thisOb return NULL; } -JSValueRef ArraySplice(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* jsException) { +JSValueRef ListSplice(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* jsException) { try { - List *list = RJSVerifiedMutableArray(thisObject); + List *list = RJSVerifiedMutableList(thisObject); size_t size = list->size(); RJSValidateArgumentCountIsAtLeast(argumentCount, 2); @@ -215,15 +215,15 @@ JSObjectRef RJSListCreate(JSContextRef ctx, realm::List &list) { } const JSStaticFunction RJSListFuncs[] = { - {"push", ArrayPush, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, - {"pop", ArrayPop, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, - {"shift", ArrayShift, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, - {"unshift", ArrayUnshift, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, - {"splice", ArraySplice, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, + {"push", ListPush, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, + {"pop", ListPop, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, + {"shift", ListShift, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, + {"unshift", ListUnshift, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, + {"splice", ListSplice, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, {NULL, NULL}, }; JSClassRef RJSListClass() { - static JSClassRef s_arrayClass = RJSCreateWrapperClass("RealmList", ArrayGetProperty, ArraySetProperty, RJSListFuncs, NULL, ArrayPropertyNames); - return s_arrayClass; + static JSClassRef s_listClass = RJSCreateWrapperClass("RealmList", ListGetProperty, ListSetProperty, RJSListFuncs, NULL, ListPropertyNames); + return s_listClass; } diff --git a/src/RJSList.hpp b/src/RJSList.hpp index 2b521203..6dbe9dd0 100644 --- a/src/RJSList.hpp +++ b/src/RJSList.hpp @@ -24,4 +24,4 @@ extern const JSStaticFunction RJSListFuncs[]; JSClassRef RJSListClass(); JSObjectRef RJSListCreate(JSContextRef ctx, realm::List &list); -JSValueRef ArrayGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* jsException); +JSValueRef ListGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* jsException); diff --git a/src/RealmRPC.mm b/src/RealmRPC.mm index c3004356..c8a2a5a6 100644 --- a/src/RealmRPC.mm +++ b/src/RealmRPC.mm @@ -140,7 +140,7 @@ using RPCRequest = std::function; JSValueRef exception = NULL; static JSStringRef lengthPropertyName = JSStringCreateWithUTF8CString("length"); - JSValueRef lengthValue = ArrayGetProperty(_context, _objects[listId], lengthPropertyName, &exception); + JSValueRef lengthValue = ListGetProperty(_context, _objects[listId], lengthPropertyName, &exception); size_t length = JSValueToNumber(_context, lengthValue, &exception); if (exception) { @@ -154,7 +154,7 @@ using RPCRequest = std::function; JSValueRef exception = NULL; JSStringRef indexPropertyName = JSStringCreateWithUTF8CString(std::to_string(index).c_str()); - JSValueRef objectValue = ArrayGetProperty(_context, _objects[listId], indexPropertyName, &exception); + JSValueRef objectValue = ListGetProperty(_context, _objects[listId], indexPropertyName, &exception); JSStringRelease(indexPropertyName); if (exception) { From 9916fe14a42005cd6af005b809aaa28685641742 Mon Sep 17 00:00:00 2001 From: Scott Kyle Date: Tue, 13 Oct 2015 18:36:15 -0700 Subject: [PATCH 27/27] Change RealmReact to be a dynamic framework It embeds RealmJS and GCDWebServers frameworks. This fixes #58, where there were issues with building for devices rather than just the simulator. Some changes were made so that RealmReact.m didn't need to be weakly linked to libReact.a since that would actually cause any executable that uses this framework from being able to compile with bitcode. --- .../{RealmReactModule.h => RealmReact.h} | 8 +- .../{RealmReactModule.m => RealmReact.m} | 58 +++++++----- RealmJS.xcodeproj/project.pbxproj | 91 ++++++++++++++----- .../xcschemes/RealmReact.xcscheme | 6 +- .../ReactExample.xcodeproj/project.pbxproj | 53 ++++++----- .../xcschemes/ReactExample.xcscheme | 2 +- examples/ReactExample/iOS/Info.plist | 17 ++-- src/Info.plist | 2 +- tests/Info.plist | 2 +- 9 files changed, 150 insertions(+), 89 deletions(-) rename ReactNative/{RealmReactModule.h => RealmReact.h} (83%) rename ReactNative/{RealmReactModule.m => RealmReact.m} (72%) diff --git a/ReactNative/RealmReactModule.h b/ReactNative/RealmReact.h similarity index 83% rename from ReactNative/RealmReactModule.h rename to ReactNative/RealmReact.h index 17982952..fa334b79 100644 --- a/ReactNative/RealmReactModule.h +++ b/ReactNative/RealmReact.h @@ -16,11 +16,7 @@ // //////////////////////////////////////////////////////////////////////////// -#import -#import "Base/RCTBridgeModule.h" -@import RealmJS; +@import Foundation; -@protocol RCTBridgeModule; - -@interface Realm : NSObject +@interface RealmReact : NSObject @end diff --git a/ReactNative/RealmReactModule.m b/ReactNative/RealmReact.m similarity index 72% rename from ReactNative/RealmReactModule.m rename to ReactNative/RealmReact.m index 6a6abfa5..57992ea8 100644 --- a/ReactNative/RealmReactModule.m +++ b/ReactNative/RealmReact.m @@ -16,32 +16,43 @@ // //////////////////////////////////////////////////////////////////////////// -#import -#import "RealmReactModule.h" -#import "Base/RCTLog.h" +#import "RealmReact.h" #import "Base/RCTBridge.h" @import GCDWebServers; @import RealmJS; @import JavaScriptCore; +@import ObjectiveC; +@import Darwin; -@interface RCTBridge (executor) -@property (weak) id javaScriptExecutor; -@end - -@interface RCTJavaScriptContext : NSObject -@property (nonatomic, assign, readonly) JSGlobalContextRef ctx; -- (void)executeBlockOnJavaScriptQueue:(dispatch_block_t)block; +@interface NSObject (RCTJavaScriptContext) - (instancetype)initWithJSContext:(JSGlobalContextRef)context; +- (JSGlobalContextRef)ctx; @end -@implementation Realm +@interface RealmReact () +@end -RCT_EXPORT_MODULE() +@implementation RealmReact @synthesize bridge = _bridge; --(void)setBridge:(RCTBridge *)bridge { ++ (void)load { + void (*RCTRegisterModule)(Class) = dlsym(RTLD_DEFAULT, "RCTRegisterModule"); + + if (RCTRegisterModule) { + RCTRegisterModule(self); + } + else { + NSLog(@"Failed to load RCTRegisterModule symbol - %s", dlerror()); + } +} + ++ (NSString *)moduleName { + return @"Realm"; +} + +- (void)setBridge:(RCTBridge *)bridge { _bridge = bridge; Ivar executorIvar = class_getInstanceVariable([bridge class], "_javaScriptExecutor"); @@ -50,7 +61,6 @@ RCT_EXPORT_MODULE() // The executor could be a RCTWebSocketExecutor, in which case it won't have a JS context. if (!contextIvar) { - [GCDWebServer setLogLevel:3]; GCDWebServer *webServer = [[GCDWebServer alloc] init]; RJSRPCServer *rpcServer = [[RJSRPCServer alloc] init]; @@ -77,22 +87,26 @@ RCT_EXPORT_MODULE() } [contextExecutor executeBlockOnJavaScriptQueue:^{ - RCTJavaScriptContext *rctJSContext = object_getIvar(contextExecutor, contextIvar); + id rctJSContext = object_getIvar(contextExecutor, contextIvar); JSGlobalContextRef ctx; + if (rctJSContext) { - ctx = rctJSContext.ctx; + ctx = [rctJSContext ctx]; } else { - ctx = JSGlobalContextCreate(NULL); - object_setIvar(contextExecutor, contextIvar, [[RCTJavaScriptContext alloc] initWithJSContext:ctx]); + Class RCTJavaScriptContext = NSClassFromString(@"RCTJavaScriptContext"); + + if (RCTJavaScriptContext) { + ctx = JSGlobalContextCreate(NULL); + object_setIvar(contextExecutor, contextIvar, [[RCTJavaScriptContext alloc] initWithJSContext:ctx]); + } + else { + NSLog(@"Failed to load RCTJavaScriptContext class"); + } } [RealmJS initializeContext:ctx]; - - RCTLogInfo(@"Realm initialized"); }]; } - @end - diff --git a/RealmJS.xcodeproj/project.pbxproj b/RealmJS.xcodeproj/project.pbxproj index 125febe4..5796f13b 100644 --- a/RealmJS.xcodeproj/project.pbxproj +++ b/RealmJS.xcodeproj/project.pbxproj @@ -8,8 +8,7 @@ /* Begin PBXBuildFile section */ 02258FB31BC6E2D00075F13A /* RealmRPC.h in Headers */ = {isa = PBXBuildFile; fileRef = 02258FB11BC6E2D00075F13A /* RealmRPC.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 02258FB41BC6E2D00075F13A /* RealmRPC.mm in Sources */ = {isa = PBXBuildFile; fileRef = 02258FB21BC6E2D00075F13A /* RealmRPC.mm */; settings = {ASSET_TAGS = (); }; }; - 02313C4E1BCC4A4B003F9107 /* GCDWebServers.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 02A3C7941BC4317A00B1A7BE /* GCDWebServers.framework */; }; + 02258FB41BC6E2D00075F13A /* RealmRPC.mm in Sources */ = {isa = PBXBuildFile; fileRef = 02258FB21BC6E2D00075F13A /* RealmRPC.mm */; }; 02601F031BA0F0C4007C91FF /* external_commit_helper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02601F011BA0F0C4007C91FF /* external_commit_helper.cpp */; }; 02601F041BA0F0C4007C91FF /* external_commit_helper.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 02601F021BA0F0C4007C91FF /* external_commit_helper.hpp */; }; 02601F081BA0F0CD007C91FF /* index_set.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02601F051BA0F0CD007C91FF /* index_set.cpp */; }; @@ -50,13 +49,17 @@ 0270BC851B7D020100010E03 /* TestCase.js in Resources */ = {isa = PBXBuildFile; fileRef = 0270BC7E1B7D020100010E03 /* TestCase.js */; }; 0270BC861B7D020100010E03 /* TestObjects.js in Resources */ = {isa = PBXBuildFile; fileRef = 0270BC7F1B7D020100010E03 /* TestObjects.js */; }; 0270BC871B7D023200010E03 /* RealmJS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 02B58CB11AE99CEC009B348C /* RealmJS.framework */; }; - 0270BCD11B7D067300010E03 /* RealmReactModule.m in Sources */ = {isa = PBXBuildFile; fileRef = 0270BCD01B7D067300010E03 /* RealmReactModule.m */; }; + 0270BCD11B7D067300010E03 /* RealmReact.m in Sources */ = {isa = PBXBuildFile; fileRef = 0270BCD01B7D067300010E03 /* RealmReact.m */; }; 02B29A311B7CF86D008A7E6B /* RealmJS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 02B58CB11AE99CEC009B348C /* RealmJS.framework */; }; 02B58CCE1AE99D4D009B348C /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 02B58CCD1AE99D4D009B348C /* JavaScriptCore.framework */; }; 02C0864E1BCDB27000942F9C /* list.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02C0864C1BCDB27000942F9C /* list.cpp */; settings = {ASSET_TAGS = (); }; }; 02C0864F1BCDB27000942F9C /* list.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 02C0864D1BCDB27000942F9C /* list.hpp */; settings = {ASSET_TAGS = (); }; }; 02D456DA1B7E59A500EE1299 /* ArrayTests.js in Resources */ = {isa = PBXBuildFile; fileRef = 02D456D91B7E59A500EE1299 /* ArrayTests.js */; }; 02D8D1F71B601984006DB49D /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 02B58CCD1AE99D4D009B348C /* JavaScriptCore.framework */; }; + F636F6C81BCDB3570023F35C /* RealmReact.h in Headers */ = {isa = PBXBuildFile; fileRef = 0270BCCF1B7D067300010E03 /* RealmReact.h */; settings = {ATTRIBUTES = (Public, ); }; }; + F64426C51BCDB1E200A81210 /* RealmJS.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 02B58CB11AE99CEC009B348C /* RealmJS.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + F67191381BCE231100AD0939 /* GCDWebServers.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 02A3C7941BC4317A00B1A7BE /* GCDWebServers.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + F6B3963D1BCE2430008BDC39 /* GCDWebServers.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 02A3C7941BC4317A00B1A7BE /* GCDWebServers.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -119,13 +122,16 @@ /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ - 02B29A141B7CF7C9008A7E6B /* CopyFiles */ = { + F64426BF1BCDA3FE00A81210 /* Embed Frameworks */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; - dstPath = "include/$(PRODUCT_NAME)"; - dstSubfolderSpec = 16; + dstPath = ""; + dstSubfolderSpec = 10; files = ( + F67191381BCE231100AD0939 /* GCDWebServers.framework in Embed Frameworks */, + F64426C51BCDB1E200A81210 /* RealmJS.framework in Embed Frameworks */, ); + name = "Embed Frameworks"; runOnlyForDeploymentPostprocessing = 0; }; /* End PBXCopyFilesBuildPhase section */ @@ -175,11 +181,11 @@ 0270BC7D1B7D020100010E03 /* ResultsTests.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = ResultsTests.js; path = tests/ResultsTests.js; sourceTree = SOURCE_ROOT; }; 0270BC7E1B7D020100010E03 /* TestCase.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = TestCase.js; path = tests/TestCase.js; sourceTree = SOURCE_ROOT; }; 0270BC7F1B7D020100010E03 /* TestObjects.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = TestObjects.js; path = tests/TestObjects.js; sourceTree = SOURCE_ROOT; }; - 0270BCCF1B7D067300010E03 /* RealmReactModule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RealmReactModule.h; path = ReactNative/RealmReactModule.h; sourceTree = ""; }; - 0270BCD01B7D067300010E03 /* RealmReactModule.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RealmReactModule.m; path = ReactNative/RealmReactModule.m; sourceTree = ""; }; + 0270BCCF1B7D067300010E03 /* RealmReact.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RealmReact.h; path = ReactNative/RealmReact.h; sourceTree = ""; }; + 0270BCD01B7D067300010E03 /* RealmReact.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RealmReact.m; path = ReactNative/RealmReact.m; sourceTree = ""; }; 02A3C7841BC4317A00B1A7BE /* GCDWebServer.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = GCDWebServer.xcodeproj; path = vendor/GCDWebServer/GCDWebServer.xcodeproj; sourceTree = ""; }; 02A3C7A41BC4341500B1A7BE /* libc++.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = "libc++.tbd"; path = "usr/lib/libc++.tbd"; sourceTree = SDKROOT; }; - 02B29A161B7CF7C9008A7E6B /* libRealmReact.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRealmReact.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 02B29A161B7CF7C9008A7E6B /* RealmReact.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = RealmReact.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 02B58CB11AE99CEC009B348C /* RealmJS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = RealmJS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 02B58CBC1AE99CEC009B348C /* RealmJSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RealmJSTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 02B58CCD1AE99D4D009B348C /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; }; @@ -193,7 +199,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 02313C4E1BCC4A4B003F9107 /* GCDWebServers.framework in Frameworks */, + F6B3963D1BCE2430008BDC39 /* GCDWebServers.framework in Frameworks */, 02B29A311B7CF86D008A7E6B /* RealmJS.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -263,13 +269,13 @@ name = RealmJS; sourceTree = ""; }; - 0270BCCE1B7D066100010E03 /* ReactNativeModule */ = { + 0270BCCE1B7D066100010E03 /* RealmReact */ = { isa = PBXGroup; children = ( - 0270BCCF1B7D067300010E03 /* RealmReactModule.h */, - 0270BCD01B7D067300010E03 /* RealmReactModule.m */, + 0270BCCF1B7D067300010E03 /* RealmReact.h */, + 0270BCD01B7D067300010E03 /* RealmReact.m */, ); - name = ReactNativeModule; + name = RealmReact; sourceTree = ""; }; 02A3C7851BC4317A00B1A7BE /* Products */ = { @@ -291,7 +297,7 @@ 02B58CCF1AE99D8C009B348C /* Frameworks */, 0270BC3D1B7CFBFD00010E03 /* RealmJS */, 02B58CC01AE99CEC009B348C /* RealmJSTests */, - 0270BCCE1B7D066100010E03 /* ReactNativeModule */, + 0270BCCE1B7D066100010E03 /* RealmReact */, 02B58CB21AE99CEC009B348C /* Products */, ); sourceTree = ""; @@ -301,7 +307,7 @@ children = ( 02B58CB11AE99CEC009B348C /* RealmJS.framework */, 02B58CBC1AE99CEC009B348C /* RealmJSTests.xctest */, - 02B29A161B7CF7C9008A7E6B /* libRealmReact.a */, + 02B29A161B7CF7C9008A7E6B /* RealmReact.framework */, ); name = Products; sourceTree = ""; @@ -361,6 +367,14 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + F64426BD1BCDA39000A81210 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + F636F6C81BCDB3570023F35C /* RealmReact.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ @@ -370,7 +384,8 @@ buildPhases = ( 02B29A121B7CF7C9008A7E6B /* Sources */, 02B29A131B7CF7C9008A7E6B /* Frameworks */, - 02B29A141B7CF7C9008A7E6B /* CopyFiles */, + F64426BD1BCDA39000A81210 /* Headers */, + F64426BF1BCDA3FE00A81210 /* Embed Frameworks */, ); buildRules = ( ); @@ -380,8 +395,8 @@ ); name = RealmReact; productName = RealmReact; - productReference = 02B29A161B7CF7C9008A7E6B /* libRealmReact.a */; - productType = "com.apple.product-type.library.static"; + productReference = 02B29A161B7CF7C9008A7E6B /* RealmReact.framework */; + productType = "com.apple.product-type.framework"; }; 02B58CB01AE99CEC009B348C /* RealmJS */ = { isa = PBXNativeTarget; @@ -426,7 +441,7 @@ 02B58CA81AE99CEB009B348C /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0630; + LastUpgradeCheck = 0700; ORGANIZATIONNAME = Realm; TargetAttributes = { 02B29A151B7CF7C9008A7E6B = { @@ -548,7 +563,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 0270BCD11B7D067300010E03 /* RealmReactModule.m in Sources */, + 0270BCD11B7D067300010E03 /* RealmReact.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -609,6 +624,10 @@ isa = XCBuildConfiguration; buildSettings = { CLANG_CXX_LANGUAGE_STANDARD = "c++14"; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)", @@ -622,13 +641,16 @@ /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, "$(SRCROOT)/examples/ReactExample/node_modules/react-native/React/", ); + INFOPLIST_FILE = src/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @loader_path/Frameworks"; OTHER_CPLUSPLUSFLAGS = ( "$(OTHER_CFLAGS)", "-isystem", core/include, ); - OTHER_LDFLAGS = "-ObjC"; + PRODUCT_BUNDLE_IDENTIFIER = "io.realm.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; }; @@ -638,6 +660,10 @@ isa = XCBuildConfiguration; buildSettings = { CLANG_CXX_LANGUAGE_STANDARD = "c++14"; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)", @@ -647,13 +673,16 @@ /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, "$(SRCROOT)/examples/ReactExample/node_modules/react-native/React/", ); + INFOPLIST_FILE = src/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @loader_path/Frameworks"; OTHER_CPLUSPLUSFLAGS = ( "$(OTHER_CFLAGS)", "-isystem", core/include, ); - OTHER_LDFLAGS = "-ObjC"; + PRODUCT_BUNDLE_IDENTIFIER = "io.realm.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; }; @@ -663,6 +692,10 @@ isa = XCBuildConfiguration; buildSettings = { CLANG_CXX_LANGUAGE_STANDARD = "c++14"; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)", @@ -672,13 +705,16 @@ /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, "$(SRCROOT)/examples/ReactExample/node_modules/react-native/React/", ); + INFOPLIST_FILE = src/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @loader_path/Frameworks"; OTHER_CPLUSPLUSFLAGS = ( "$(OTHER_CFLAGS)", "-isystem", core/include, ); - OTHER_LDFLAGS = "-ObjC"; + PRODUCT_BUNDLE_IDENTIFIER = "io.realm.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; }; @@ -706,6 +742,7 @@ CURRENT_PROJECT_VERSION = 1; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_GENERATE_TEST_COVERAGE_FILES = NO; @@ -812,6 +849,7 @@ ); OTHER_LDFLAGS = "-lrealm-ios-dbg"; OTHER_LIBTOOLFLAGS = "-lrealm-ios-dbg"; + PRODUCT_BUNDLE_IDENTIFIER = "io.realm.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; }; @@ -844,6 +882,7 @@ ); OTHER_LDFLAGS = "-lrealm-ios"; OTHER_LIBTOOLFLAGS = "-lrealm-ios"; + PRODUCT_BUNDLE_IDENTIFIER = "io.realm.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; }; @@ -869,6 +908,7 @@ "-isystem", core/include, ); + PRODUCT_BUNDLE_IDENTIFIER = "io.realm.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; @@ -889,6 +929,7 @@ "-isystem", core/include, ); + PRODUCT_BUNDLE_IDENTIFIER = "io.realm.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; @@ -976,6 +1017,7 @@ ); OTHER_LDFLAGS = "-lrealm-ios-dbg"; OTHER_LIBTOOLFLAGS = "-lrealm-ios-dbg"; + PRODUCT_BUNDLE_IDENTIFIER = "io.realm.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; }; @@ -1001,6 +1043,7 @@ "-isystem", core/include, ); + PRODUCT_BUNDLE_IDENTIFIER = "io.realm.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = GCov_Build; diff --git a/RealmJS.xcodeproj/xcshareddata/xcschemes/RealmReact.xcscheme b/RealmJS.xcodeproj/xcshareddata/xcschemes/RealmReact.xcscheme index de1f2d10..2699e2b9 100644 --- a/RealmJS.xcodeproj/xcshareddata/xcschemes/RealmReact.xcscheme +++ b/RealmJS.xcodeproj/xcshareddata/xcschemes/RealmReact.xcscheme @@ -15,7 +15,7 @@ @@ -46,7 +46,7 @@ @@ -64,7 +64,7 @@ diff --git a/examples/ReactExample/ReactExample.xcodeproj/project.pbxproj b/examples/ReactExample/ReactExample.xcodeproj/project.pbxproj index 4b62b0e4..27b3d906 100644 --- a/examples/ReactExample/ReactExample.xcodeproj/project.pbxproj +++ b/examples/ReactExample/ReactExample.xcodeproj/project.pbxproj @@ -13,11 +13,9 @@ 00C302E81ABCBA2D00DB3ED1 /* libRCTImage.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302C01ABCB91800DB3ED1 /* libRCTImage.a */; }; 00C302E91ABCBA2D00DB3ED1 /* libRCTNetwork.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */; }; 00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */; }; - 0270BCD21B7D095C00010E03 /* libRealmReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0270BCB31B7D04D700010E03 /* libRealmReact.a */; }; + 0270BCD21B7D095C00010E03 /* RealmReact.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0270BCB31B7D04D700010E03 /* RealmReact.framework */; }; 027798491BBB2F1000C96559 /* ReactExampleTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 027798481BBB2F1000C96559 /* ReactExampleTests.m */; }; 02A3C7A71BC4347100B1A7BE /* libc++.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 02A3C7A61BC4347100B1A7BE /* libc++.tbd */; }; - 02BB0BE51B9A06DC004D6DD2 /* RealmJS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0270BCAF1B7D04D700010E03 /* RealmJS.framework */; }; - 02BB0BE61B9A06DC004D6DD2 /* RealmJS.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 0270BCAF1B7D04D700010E03 /* RealmJS.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 133E29F31AD74F7200F7D852 /* libRCTLinking.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 78C398B91ACF4ADC00677621 /* libRCTLinking.a */; }; 139105C61AF99C1200B5F7CC /* libRCTSettings.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139105C11AF99BAD00B5F7CC /* libRCTSettings.a */; }; 139FDEF61B0652A700C62182 /* libRCTWebSocket.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139FDEF41B06529B00C62182 /* libRCTWebSocket.a */; }; @@ -27,6 +25,7 @@ 13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; }; 146834051AC3E58100842450 /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 146834041AC3E56700842450 /* libReact.a */; }; 832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 832341B51AAA6A8300B99B32 /* libRCTText.a */; }; + F636F6E11BCDB71A0023F35C /* RealmReact.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 0270BCB31B7D04D700010E03 /* RealmReact.framework */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -93,13 +92,6 @@ remoteGlobalIDString = 13B07F861A680F5B00A75B9A; remoteInfo = ReactExample; }; - 02BB0BE71B9A06DC004D6DD2 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 0270BC9E1B7D04D700010E03 /* RealmJS.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = 02B58CB01AE99CEC009B348C; - remoteInfo = RealmJS; - }; 139105C01AF99BAD00B5F7CC /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */; @@ -135,6 +127,13 @@ remoteGlobalIDString = 58B5119B1A9E6C1200147676; remoteInfo = RCTText; }; + F636F6E21BCDB72D0023F35C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 0270BC9E1B7D04D700010E03 /* RealmJS.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 02B29A151B7CF7C9008A7E6B; + remoteInfo = RealmReact; + }; /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -144,7 +143,7 @@ dstPath = ""; dstSubfolderSpec = 10; files = ( - 02BB0BE61B9A06DC004D6DD2 /* RealmJS.framework in Embed Frameworks */, + F636F6E11BCDB71A0023F35C /* RealmReact.framework in Embed Frameworks */, ); name = "Embed Frameworks"; runOnlyForDeploymentPostprocessing = 0; @@ -190,14 +189,13 @@ buildActionMask = 2147483647; files = ( 02A3C7A71BC4347100B1A7BE /* libc++.tbd in Frameworks */, - 0270BCD21B7D095C00010E03 /* libRealmReact.a in Frameworks */, + 0270BCD21B7D095C00010E03 /* RealmReact.framework in Frameworks */, 146834051AC3E58100842450 /* libReact.a in Frameworks */, 00C302E51ABCBA2D00DB3ED1 /* libRCTActionSheet.a in Frameworks */, 00C302E71ABCBA2D00DB3ED1 /* libRCTGeolocation.a in Frameworks */, 00C302E81ABCBA2D00DB3ED1 /* libRCTImage.a in Frameworks */, 133E29F31AD74F7200F7D852 /* libRCTLinking.a in Frameworks */, 00C302E91ABCBA2D00DB3ED1 /* libRCTNetwork.a in Frameworks */, - 02BB0BE51B9A06DC004D6DD2 /* RealmJS.framework in Frameworks */, 139105C61AF99C1200B5F7CC /* libRCTSettings.a in Frameworks */, 832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */, 00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */, @@ -253,7 +251,7 @@ children = ( 0270BCAF1B7D04D700010E03 /* RealmJS.framework */, 0270BCB11B7D04D700010E03 /* RealmJSTests.xctest */, - 0270BCB31B7D04D700010E03 /* libRealmReact.a */, + 0270BCB31B7D04D700010E03 /* RealmReact.framework */, ); name = Products; sourceTree = ""; @@ -395,7 +393,7 @@ buildRules = ( ); dependencies = ( - 02BB0BE81B9A06DC004D6DD2 /* PBXTargetDependency */, + F636F6E31BCDB72D0023F35C /* PBXTargetDependency */, ); name = ReactExample; productName = "Hello World"; @@ -408,7 +406,7 @@ 83CBB9F71A601CBA00E9B192 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0610; + LastUpgradeCheck = 0700; ORGANIZATIONNAME = Facebook; TargetAttributes = { 027798451BBB2F1000C96559 = { @@ -532,10 +530,10 @@ remoteRef = 0270BCB01B7D04D700010E03 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 0270BCB31B7D04D700010E03 /* libRealmReact.a */ = { + 0270BCB31B7D04D700010E03 /* RealmReact.framework */ = { isa = PBXReferenceProxy; - fileType = archive.ar; - path = libRealmReact.a; + fileType = wrapper.framework; + path = RealmReact.framework; remoteRef = 0270BCB21B7D04D700010E03 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -638,10 +636,10 @@ target = 13B07F861A680F5B00A75B9A /* ReactExample */; targetProxy = 0277984B1BBB2F1000C96559 /* PBXContainerItemProxy */; }; - 02BB0BE81B9A06DC004D6DD2 /* PBXTargetDependency */ = { + F636F6E31BCDB72D0023F35C /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = RealmJS; - targetProxy = 02BB0BE71B9A06DC004D6DD2 /* PBXContainerItemProxy */; + name = RealmReact; + targetProxy = F636F6E21BCDB72D0023F35C /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ @@ -668,6 +666,10 @@ INFOPLIST_FILE = ReactExampleTests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + OTHER_LDFLAGS = ( + "-undefined", + dynamic_lookup, + ); PRODUCT_BUNDLE_IDENTIFIER = io.realm.ReactExampleTests; PRODUCT_NAME = "$(TARGET_NAME)"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/ReactExample.app/ReactExample"; @@ -684,6 +686,10 @@ INFOPLIST_FILE = ReactExampleTests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + OTHER_LDFLAGS = ( + "-undefined", + dynamic_lookup, + ); PRODUCT_BUNDLE_IDENTIFIER = io.realm.ReactExampleTests; PRODUCT_NAME = "$(TARGET_NAME)"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/ReactExample.app/ReactExample"; @@ -702,6 +708,7 @@ INFOPLIST_FILE = iOS/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; OTHER_LDFLAGS = "-ObjC"; + PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = ReactExample; }; name = Debug; @@ -718,6 +725,7 @@ INFOPLIST_FILE = iOS/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; OTHER_LDFLAGS = "-ObjC"; + PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = ReactExample; }; name = Release; @@ -742,6 +750,7 @@ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_OPTIMIZATION_LEVEL = 0; diff --git a/examples/ReactExample/ReactExample.xcodeproj/xcshareddata/xcschemes/ReactExample.xcscheme b/examples/ReactExample/ReactExample.xcodeproj/xcshareddata/xcschemes/ReactExample.xcscheme index 0928dd7a..2f9563ca 100644 --- a/examples/ReactExample/ReactExample.xcodeproj/xcshareddata/xcschemes/ReactExample.xcscheme +++ b/examples/ReactExample/ReactExample.xcodeproj/xcshareddata/xcschemes/ReactExample.xcscheme @@ -1,6 +1,6 @@ CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier - org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier) + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName @@ -22,6 +22,13 @@ 1 LSRequiresIPhoneOS + NSAppTransportSecurity + + NSAllowsArbitraryLoads + + + NSLocationWhenInUseUsageDescription + UILaunchStoryboardName LaunchScreen UIRequiredDeviceCapabilities @@ -36,13 +43,5 @@ UIViewControllerBasedStatusBarAppearance - NSLocationWhenInUseUsageDescription - - NSAppTransportSecurity - - - NSAllowsArbitraryLoads - - diff --git a/src/Info.plist b/src/Info.plist index a52e52a4..d3de8eef 100644 --- a/src/Info.plist +++ b/src/Info.plist @@ -7,7 +7,7 @@ CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier - io.realm.$(PRODUCT_NAME:rfc1034identifier) + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName diff --git a/tests/Info.plist b/tests/Info.plist index 0d400b71..ba72822e 100644 --- a/tests/Info.plist +++ b/tests/Info.plist @@ -7,7 +7,7 @@ CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier - io.realm.$(PRODUCT_NAME:rfc1034identifier) + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName