diff --git a/src/object-store/object_accessor.cpp b/ReactNative/RealmReact.h similarity index 92% rename from src/object-store/object_accessor.cpp rename to ReactNative/RealmReact.h index 2516cc5d..fa334b79 100644 --- a/src/object-store/object_accessor.cpp +++ b/ReactNative/RealmReact.h @@ -16,4 +16,7 @@ // //////////////////////////////////////////////////////////////////////////// -#include "object_accessor.hpp" +@import Foundation; + +@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 ad712f1b..aa78e2fa 100644 --- a/RealmJS.xcodeproj/project.pbxproj +++ b/RealmJS.xcodeproj/project.pbxproj @@ -8,7 +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 = (); }; }; + 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 */; }; @@ -20,8 +20,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, ); }; }; @@ -32,7 +32,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 */; }; @@ -50,18 +49,30 @@ 0270BC851B7D020100010E03 /* asserts.js in Resources */ = {isa = PBXBuildFile; fileRef = 0270BC7E1B7D020100010E03 /* asserts.js */; }; 0270BC861B7D020100010E03 /* schemas.js in Resources */ = {isa = PBXBuildFile; fileRef = 0270BC7F1B7D020100010E03 /* schemas.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 */; }; + 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 */; }; F64E1EF11BC3510E00E0E150 /* util.js in Resources */ = {isa = PBXBuildFile; fileRef = F64E1EF01BC3510E00E0E150 /* util.js */; settings = {ASSET_TAGS = (); }; }; F68A278C1BC2722A0063D40A /* RJSModuleLoader.m in Sources */ = {isa = PBXBuildFile; fileRef = F68A278B1BC2722A0063D40A /* RJSModuleLoader.m */; settings = {ASSET_TAGS = (); }; }; F68A278E1BC30F0A0063D40A /* index.js in Resources */ = {isa = PBXBuildFile; fileRef = F68A278D1BC30F0A0063D40A /* index.js */; settings = {ASSET_TAGS = (); }; }; /* 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 */; @@ -114,13 +125,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 */ @@ -139,8 +153,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 = ""; }; @@ -152,7 +166,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 = ""; }; @@ -171,14 +184,16 @@ 0270BC7D1B7D020100010E03 /* ResultsTests.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = ResultsTests.js; path = tests/ResultsTests.js; sourceTree = SOURCE_ROOT; }; 0270BC7E1B7D020100010E03 /* asserts.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = asserts.js; path = tests/asserts.js; sourceTree = SOURCE_ROOT; }; 0270BC7F1B7D020100010E03 /* schemas.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = schemas.js; path = tests/schemas.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; }; + 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; }; F64E1EF01BC3510E00E0E150 /* util.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = util.js; path = tests/util.js; sourceTree = SOURCE_ROOT; }; F68A278A1BC2722A0063D40A /* RJSModuleLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RJSModuleLoader.h; path = tests/RJSModuleLoader.h; sourceTree = SOURCE_ROOT; }; @@ -191,7 +206,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 02A3C7971BC4318600B1A7BE /* GCDWebServers.framework in Frameworks */, + F6B3963D1BCE2430008BDC39 /* GCDWebServers.framework in Frameworks */, 02B29A311B7CF86D008A7E6B /* RealmJS.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -219,7 +234,6 @@ 0270BC3D1B7CFBFD00010E03 /* RealmJS */ = { isa = PBXGroup; children = ( - 0270BC5C1B7CFC1C00010E03 /* object_accessor.cpp */, 0270BC5D1B7CFC1C00010E03 /* object_accessor.hpp */, 0270BC5E1B7CFC1C00010E03 /* object_schema.cpp */, 0270BC5F1B7CFC1C00010E03 /* object_schema.hpp */, @@ -234,6 +248,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 */, @@ -243,8 +259,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 */, @@ -260,13 +276,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 */ = { @@ -288,7 +304,7 @@ 02B58CCF1AE99D8C009B348C /* Frameworks */, 0270BC3D1B7CFBFD00010E03 /* RealmJS */, 02B58CC01AE99CEC009B348C /* RealmJSTests */, - 0270BCCE1B7D066100010E03 /* ReactNativeModule */, + 0270BCCE1B7D066100010E03 /* RealmReact */, 02B58CB21AE99CEC009B348C /* Products */, ); sourceTree = ""; @@ -298,7 +314,7 @@ children = ( 02B58CB11AE99CEC009B348C /* RealmJS.framework */, 02B58CBC1AE99CEC009B348C /* RealmJSTests.xctest */, - 02B29A161B7CF7C9008A7E6B /* libRealmReact.a */, + 02B29A161B7CF7C9008A7E6B /* RealmReact.framework */, ); name = Products; sourceTree = ""; @@ -341,7 +357,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 */, @@ -357,10 +373,19 @@ 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; }; + F64426BD1BCDA39000A81210 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + F636F6C81BCDB3570023F35C /* RealmReact.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ @@ -370,17 +395,19 @@ buildPhases = ( 02B29A121B7CF7C9008A7E6B /* Sources */, 02B29A131B7CF7C9008A7E6B /* Frameworks */, - 02B29A141B7CF7C9008A7E6B /* CopyFiles */, + F64426BD1BCDA39000A81210 /* Headers */, + F64426BF1BCDA3FE00A81210 /* Embed Frameworks */, ); buildRules = ( ); dependencies = ( + 02313C471BCC4A43003F9107 /* PBXTargetDependency */, 02B29A301B7CF7ED008A7E6B /* PBXTargetDependency */, ); 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; @@ -425,7 +452,7 @@ 02B58CA81AE99CEB009B348C /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0630; + LastUpgradeCheck = 0700; ORGANIZATIONNAME = Realm; TargetAttributes = { 02B29A151B7CF7C9008A7E6B = { @@ -549,7 +576,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 0270BCD11B7D067300010E03 /* RealmReactModule.m in Sources */, + 0270BCD11B7D067300010E03 /* RealmReact.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -568,11 +595,11 @@ 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 */, - 0270BC671B7CFC1C00010E03 /* object_accessor.cpp in Sources */, - 0270BC4E1B7CFC0D00010E03 /* RJSArray.cpp in Sources */, + 0270BC4E1B7CFC0D00010E03 /* RJSList.cpp in Sources */, 0270BC531B7CFC0D00010E03 /* RJSRealm.mm in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -589,6 +616,11 @@ /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ + 02313C471BCC4A43003F9107 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = "GCDWebServers (iOS)"; + targetProxy = 02313C461BCC4A43003F9107 /* PBXContainerItemProxy */; + }; 02B29A301B7CF7ED008A7E6B /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 02B58CB01AE99CEC009B348C /* RealmJS */; @@ -606,6 +638,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)", @@ -619,13 +655,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; }; @@ -635,6 +674,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)", @@ -644,13 +687,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; }; @@ -660,6 +706,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)", @@ -669,13 +719,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; }; @@ -703,6 +756,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; @@ -809,6 +863,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; }; @@ -841,6 +896,7 @@ ); OTHER_LDFLAGS = "-lrealm-ios"; OTHER_LIBTOOLFLAGS = "-lrealm-ios"; + PRODUCT_BUNDLE_IDENTIFIER = "io.realm.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; }; @@ -861,6 +917,12 @@ 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_BUNDLE_IDENTIFIER = "io.realm.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; @@ -876,6 +938,12 @@ 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_BUNDLE_IDENTIFIER = "io.realm.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; @@ -963,6 +1031,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; }; @@ -983,6 +1052,12 @@ 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_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/src/RJSArray.cpp b/src/RJSList.cpp similarity index 51% rename from src/RJSArray.cpp rename to src/RJSList.cpp index 2ad920b7..dfb35bb5 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" @@ -24,43 +24,36 @@ using RJSAccessor = realm::NativeAccessor; using namespace realm; -size_t ObjectArray::size() { - return link_view->size(); +static inline List * RJSVerifiedList(JSObjectRef object) { + List *list = RJSGetInternal(object); + list->verify_attached(); + return list; } -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()) + "."); +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 link_view->get(row_ndx); + return list; } -void ObjectArray::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; -} - -JSValueRef ArrayGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* jsException) { +JSValueRef ListGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* jsException) { try { // index subscripting - ObjectArray *array = RJSVerifiedArray(object); - size_t size = array->size(); + List *list = RJSVerifiedList(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(std::stol(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 + return JSValueMakeUndefined(ctx); } catch (std::invalid_argument &exp) { // for stol failure this could be another property that is handled externally, so ignore @@ -74,9 +67,32 @@ JSValueRef ArrayGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef pr } } -void ArrayPropertyNames(JSContextRef ctx, JSObjectRef object, JSPropertyNameAccumulatorRef propertyNames) { - ObjectArray *array = RJSVerifiedArray(object); - size_t size = array->size(); +bool ListSetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* jsException) { + try { + List *list = RJSVerifiedMutableList(object); + std::string indexStr = RJSStringForJSString(propertyName); + if (indexStr == "length") { + throw std::runtime_error("The 'length' property is readonly."); + } + + 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) { + // 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 ListPropertyNames(JSContextRef ctx, JSObjectRef object, JSPropertyNameAccumulatorRef propertyNames) { + List *list = RJSVerifiedList(object); + size_t size = list->size(); char str[32]; for (size_t i = 0; i < size; i++) { @@ -87,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 { - ObjectArray *array = RJSVerifiedArray(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)); @@ -104,18 +120,18 @@ 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 { - ObjectArray *array = RJSVerifiedArray(thisObject); + List *list = RJSVerifiedMutableList(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) { @@ -126,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 { - ObjectArray *array = RJSVerifiedArray(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)); @@ -143,15 +159,15 @@ 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 { - ObjectArray *array = RJSVerifiedArray(thisObject); + List *list = RJSVerifiedMutableList(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) { @@ -162,10 +178,10 @@ 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 { - ObjectArray *array = RJSVerifiedArray(thisObject); - size_t size = array->size(); + List *list = RJSVerifiedMutableList(thisObject); + size_t size = list->size(); RJSValidateArgumentCountIsAtLeast(argumentCount, 2); long index = std::min(RJSValidatedValueToNumber(ctx, arguments[0]), size); @@ -178,11 +194,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); } @@ -194,20 +210,20 @@ JSValueRef ArraySplice(JSContextRef ctx, JSObjectRef function, JSObjectRef thisO return NULL; } -JSObjectRef RJSArrayCreate(JSContextRef ctx, realm::ObjectArray *array) { - return RJSWrapObject(ctx, RJSArrayClass(), array); +JSObjectRef RJSListCreate(JSContextRef ctx, realm::List &list) { + return RJSWrapObject(ctx, RJSListClass(), new List(list)); } -const JSStaticFunction RJSArrayFuncs[] = { - {"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}, +const JSStaticFunction RJSListFuncs[] = { + {"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 RJSArrayClass() { - static JSClassRef s_arrayClass = RJSCreateWrapperClass("RealmArray", ArrayGetProperty, NULL, RJSArrayFuncs, NULL, ArrayPropertyNames); - return s_arrayClass; +JSClassRef RJSListClass() { + static JSClassRef s_listClass = RJSCreateWrapperClass("RealmList", ListGetProperty, ListSetProperty, RJSListFuncs, NULL, ListPropertyNames); + return s_listClass; } diff --git a/ReactNative/RealmReactModule.h b/src/RJSList.hpp similarity index 69% rename from ReactNative/RealmReactModule.h rename to src/RJSList.hpp index 17982952..6dbe9dd0 100644 --- a/ReactNative/RealmReactModule.h +++ b/src/RJSList.hpp @@ -16,11 +16,12 @@ // //////////////////////////////////////////////////////////////////////////// -#import -#import "Base/RCTBridgeModule.h" -@import RealmJS; +#import "RJSUtil.hpp" +#import "shared_realm.hpp" +#import "list.hpp" -@protocol RCTBridgeModule; +extern const JSStaticFunction RJSListFuncs[]; +JSClassRef RJSListClass(); +JSObjectRef RJSListCreate(JSContextRef ctx, realm::List &list); -@interface Realm : NSObject -@end +JSValueRef ListGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* jsException); diff --git a/src/RJSObject.mm b/src/RJSObject.mm index 09dbfb66..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" @@ -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 ObjectArray(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) { @@ -79,7 +45,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; @@ -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 RJSListCreate(ctx, list); +} diff --git a/src/RJSRealm.mm b/src/RJSRealm.mm index 192b7a34..78d45c5c 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" @@ -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"); } @@ -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)); @@ -280,10 +280,10 @@ 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 = 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); @@ -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,7 +370,21 @@ JSValueRef RealmWrite(JSContextRef ctx, JSObjectRef function, JSObjectRef thisOb namespace realm { struct Notification { JSGlobalContextRef ctx; + 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); + } }; } @@ -378,22 +392,23 @@ 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)); + JSGlobalContextRef gCtx = JSContextGetGlobalContext(ctx); + 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) { @@ -403,10 +418,19 @@ JSValueRef RealmAddNotification(JSContextRef ctx, JSObjectRef function, JSObject } } -void RJSNotificationFinalize(JSObjectRef object) { - Notification *notification = RJSGetInternal(object); - JSGlobalContextRelease(notification->ctx); - RJSFinalize(object); +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; } const JSStaticFunction RJSRealmFuncs[] = { @@ -416,6 +440,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}, }; @@ -425,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; } diff --git a/src/RJSResults.mm b/src/RJSResults.mm index 5be3cf37..7cdad982 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 @@ -71,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/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 1c74a105..b53f2034 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; } @@ -106,30 +106,26 @@ 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; - 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); } + if (isnan(number)) { + throw std::invalid_argument("Value not convertible to a number."); + } 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); @@ -165,7 +161,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); @@ -179,6 +175,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/RealmRPC.mm b/src/RealmRPC.mm index d38d664e..c8a2a5a6 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" @@ -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) { @@ -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,14 +249,14 @@ using RPCRequest = std::function; @"schema": [self objectSchemaToJSONObject:object->object_schema] }; } - else if (JSValueIsObjectOfClass(_context, value, RJSArrayClass())) { - realm::ObjectArray *array = RJSGetInternal(jsObject); + else if (JSValueIsObjectOfClass(_context, value, RJSListClass())) { + 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())) { @@ -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/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/RJSArray.hpp b/src/object-store/list.hpp similarity index 71% rename from src/RJSArray.hpp rename to src/object-store/list.hpp index a4a0807d..a1fa1dde 100644 --- a/src/RJSArray.hpp +++ b/src/object-store/list.hpp @@ -16,13 +16,15 @@ // //////////////////////////////////////////////////////////////////////////// -#import "RJSUtil.hpp" +#ifndef REALM_LIST_HPP +#define REALM_LIST_HPP + #import "shared_realm.hpp" #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; @@ -30,12 +32,11 @@ 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(); }; } -extern const JSStaticFunction RJSArrayFuncs[]; -JSClassRef RJSArrayClass(); -JSObjectRef RJSArrayCreate(JSContextRef ctx, realm::ObjectArray *array); -JSValueRef ArrayGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* jsException); +#endif /* REALM_LIST_HPP */ diff --git a/src/object-store/object_accessor.hpp b/src/object-store/object_accessor.hpp index dfb24f69..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,11 +109,25 @@ 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) { 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: @@ -136,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; @@ -146,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) { 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/src/object-store/shared_realm.cpp b/src/object-store/shared_realm.cpp index 8b003d30..42217a8f 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/ArrayTests.js b/tests/ArrayTests.js index 15b02e8c..24590821 100644 --- a/tests/ArrayTests.js +++ b/tests/ArrayTests.js @@ -23,37 +23,6 @@ var TestCase = require('./asserts'); var schemas = require('./schemas'); module.exports = { - testLinkTypesPropertySetters: function() { - var realm = new Realm({schema: [schemas.LinkTypes, schemas.TestObject]}); - 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: [schemas.LinkTypes, schemas.TestObject]}); realm.write(function() { @@ -65,35 +34,78 @@ module.exports = { obj.arrayCol = [[1], [2]]; TestCase.assertEqual(obj.arrayCol.length, 2); - }); + + TestCase.assertThrows(function() { + obj.arrayCol.length = 0; + }, 'cannot set length property on lists'); + }); }, - testArraySubscript: function() { + testArraySubscriptGetters: function() { var realm = new Realm({schema: [schemas.LinkTypes, schemas.TestObject]}); - 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'); + TestCase.assertEqual(array[2], undefined); + TestCase.assertEqual(array[-1], undefined); }, - testArrayInvalidProperty: function() { + testArraySubscriptSetters: function() { var realm = new Realm({schema: [schemas.LinkTypes, schemas.TestObject]}); - 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[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() { + array[0] = [3]; + }, 'cannot set list item outside write transaction'); + }, + + testArrayInvalidProperty: function() { + var realm = new Realm({schema: [schemas.LinkTypes, schemas.TestObject]}); + 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: [schemas.LinkTypes, schemas.TestObject]}); - 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() { @@ -102,16 +114,16 @@ module.exports = { }); 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); }, testPush: function() { var realm = new Realm({schema: [schemas.LinkTypes, schemas.TestObject]}); var array; + realm.write(function() { var obj = realm.create('LinkTypesObject', [[1], [2], [[3]]]); TestCase.assertEqual(obj.arrayCol.length, 1); @@ -129,17 +141,18 @@ module.exports = { TestCase.assertThrows(function() { array.push(); }); - }); + }); 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: [schemas.LinkTypes, schemas.TestObject]}); var array; + realm.write(function() { var obj = realm.create('LinkTypesObject', [[1], [2], [[3], [4]]]); array = obj.arrayCol; @@ -155,14 +168,15 @@ module.exports = { }); }); - // TestCase.assertThrows(function() { - // array.pop(); - // }); + TestCase.assertThrows(function() { + array.pop(); + }, 'can only pop in a write transaction'); }, testUnshift: function() { var realm = new Realm({schema: [schemas.LinkTypes, schemas.TestObject]}); var array; + realm.write(function() { var obj = realm.create('LinkTypesObject', [[1], [2], [[3]]]); TestCase.assertEqual(obj.arrayCol.length, 1); @@ -179,14 +193,15 @@ module.exports = { }); 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: [schemas.LinkTypes, schemas.TestObject]}); var array; + realm.write(function() { var obj = realm.create('LinkTypesObject', [[1], [2], [[3], [4]]]); array = obj.arrayCol; @@ -202,19 +217,21 @@ module.exports = { }); }); - // TestCase.assertThrows(function() { - // array.shift(); - // }); + TestCase.assertThrows(function() { + array.shift(); + }, 'can only shift in a write transaction'); }, testSplice: function() { var realm = new Realm({schema: [schemas.LinkTypes, schemas.TestObject]}); + 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); @@ -247,10 +264,22 @@ module.exports = { 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); }); }); + + TestCase.assertThrows(function() { + obj.arrayCol.splice(0, 0, obj.objectCol); + }, 'can only splice in a write transaction'); }, }; 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 diff --git a/tests/ObjectTests.js b/tests/ObjectTests.js index 33160c15..b8aa97c9 100644 --- a/tests/ObjectTests.js +++ b/tests/ObjectTests.js @@ -24,67 +24,85 @@ var schemas = require('./schemas'); module.exports = { testBasicTypesPropertyGetters: function() { - var basicTypesValues = [true, 1, 1.1, 1.11, 'string', new Date(1), 'DATA']; - var realm = new Realm({schema: [schemas.BasicTypes]}); - 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: [schemas.BasicTypes]}); + var object = null; + realm.write(function() { + object = realm.create('BasicTypesObject', basicTypesValues); + }); - for (var i = 0; i < schemas.BasicTypes.properties.length; i++) { - var prop = schemas.BasicTypes.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 < schemas.BasicTypes.properties.length; i++) { + var prop = schemas.BasicTypes.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: [schemas.BasicTypes]}); - 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: [schemas.BasicTypes]}); + 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'); + + 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'); + + TestCase.assertEqual(obj.boolCol, false, 'bool value changed outside transaction'); }, testLinkTypesPropertyGetters: function() { - var realm = new Realm({schema: [schemas.LinkTypes, schemas.TestObject]}); - var obj = null; - realm.write(function() { - obj = realm.create('LinkTypesObject', [[1], null, [[3]]]); - }); + var realm = new Realm({schema: [schemas.LinkTypes, schemas.TestObject]}); + 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: [schemas.LinkTypes, schemas.TestObject]}); @@ -94,6 +112,10 @@ module.exports = { }); 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; diff --git a/tests/RealmJSTests.mm b/tests/RealmJSTests.mm index a12b72e7..9cec8089 100644 --- a/tests/RealmJSTests.mm +++ b/tests/RealmJSTests.mm @@ -23,6 +23,8 @@ #import "RJSRealm.hpp" #import "RJSModuleLoader.h" +#import "shared_realm.hpp" + NSString *RealmPathForFile(NSString *fileName) { #if TARGET_OS_IPHONE NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0]; @@ -33,10 +35,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) { @@ -82,18 +83,22 @@ static void DeleteRealmFilesAtPath(NSString *path) { - (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); self.context.exception = nil; } - (void)tearDown { - DeleteRealmFilesAtPath(TestRealmPath()); + 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")); DeleteRealmFilesAtPath(@(RJSDefaultPath().c_str())); - + [super tearDown]; } diff --git a/tests/RealmTests.js b/tests/RealmTests.js index 23fc8354..22c5662d 100644 --- a/tests/RealmTests.js +++ b/tests/RealmTests.js @@ -59,9 +59,20 @@ module.exports = { var testPath = util.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(); + // FIXME - enable once realm initialization supports schema comparison + // TestCase.assertThrows(function() { + // realm = new Realm({path: testPath, schema: [schemas.TestObject], schemaVersion: 1}); + // }, "schema changes require updating the schema version"); - //realm = undefined; - //realm = new Realm({path: testPath, schema: [], schemaVersion: 2}); + realm = new Realm({path: testPath, schema: [schemas.TestObject], schemaVersion: 2}); + realm.write(function() { + realm.create('TestObject', [1]); + }); + TestCase.assertEqual(realm.objects('TestObject')[0].doubleCol, 1) }, testDefaultPath: function() { @@ -78,6 +89,11 @@ module.exports = { testRealmCreate: function() { var realm = new Realm({schema: [schemas.IntPrimary, schemas.AllTypes, schemas.TestObject]}); + + 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}); @@ -176,7 +192,7 @@ module.exports = { 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() { @@ -213,7 +229,7 @@ module.exports = { TestCase.assertThrows(function() { realm.deleteAll(); - }); + }, 'can only deleteAll in a write transaction'); realm.write(function() { realm.deleteAll(); @@ -261,13 +277,18 @@ module.exports = { }, 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'); }, }; diff --git a/tests/ResultsTests.js b/tests/ResultsTests.js index 140c4fa6..82033fb3 100644 --- a/tests/ResultsTests.js +++ b/tests/ResultsTests.js @@ -44,8 +44,8 @@ module.exports = { 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]) === schemas.PersonObject.prototype); }, testResultsInvalidProperty: function() {