Merge pull request #41 from realm/al-rpc

Partial chrome support (enough for the example)
This commit is contained in:
Ari Lazier 2015-10-08 16:46:52 -06:00
commit a670961b13
32 changed files with 1171 additions and 60 deletions

4
.gitignore vendored
View File

@ -93,3 +93,7 @@ build/
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
.rvmrc
# node.js
node_modules/
npm-debug.log

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "vendor/GCDWebServer"]
path = vendor/GCDWebServer
url = https://github.com/swisspol/GCDWebServer.git

View File

@ -17,8 +17,8 @@
////////////////////////////////////////////////////////////////////////////
#import <UIKit/UIKit.h>
#import "Base/RCTBridgeModule.h"
@import RealmJS;
@protocol RCTBridgeModule;

View File

@ -21,6 +21,7 @@
#import "Base/RCTLog.h"
#import "Base/RCTBridge.h"
@import GCDWebServers;
@import RealmJS;
@import JavaScriptCore;
@ -49,6 +50,29 @@ 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];
// Add a handler to respond to POST requests on any URL
[webServer addDefaultHandlerForMethod:@"POST"
requestClass:[GCDWebServerDataRequest class]
processBlock:^GCDWebServerResponse *(GCDWebServerRequest* request) {
NSError *error;
NSData *data = [(GCDWebServerDataRequest *)request data];
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
if (error) {
NSLog(@"%@", error);
return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_UnprocessableEntity underlyingError:error message:@"Invalid RPC request"];
}
GCDWebServerDataResponse *response = [GCDWebServerDataResponse responseWithJSONObject:[rpcServer performRequest:request.path args:json]];
[response setValue:@"http://localhost:8081" forAdditionalHeader:@"Access-Control-Allow-Origin"];
return response;
}];
[webServer startWithPort:8082 bonjourName:nil];
return;
}

View File

@ -7,6 +7,8 @@
objects = {
/* 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 = (); }; };
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 */; };
@ -19,16 +21,16 @@
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 */; };
0270BC501B7CFC0D00010E03 /* RJSObject.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 0270BC421B7CFC0D00010E03 /* RJSObject.hpp */; };
0270BC4F1B7CFC0D00010E03 /* RJSArray.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 0270BC411B7CFC0D00010E03 /* RJSArray.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 */; };
0270BC521B7CFC0D00010E03 /* RJSRealm.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 0270BC441B7CFC0D00010E03 /* RJSRealm.hpp */; settings = {ATTRIBUTES = (Private, ); }; };
0270BC531B7CFC0D00010E03 /* RJSRealm.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0270BC451B7CFC0D00010E03 /* RJSRealm.mm */; };
0270BC541B7CFC0D00010E03 /* RJSResults.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 0270BC461B7CFC0D00010E03 /* RJSResults.hpp */; };
0270BC541B7CFC0D00010E03 /* RJSResults.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 0270BC461B7CFC0D00010E03 /* RJSResults.hpp */; settings = {ATTRIBUTES = (Private, ); }; };
0270BC551B7CFC0D00010E03 /* RJSResults.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0270BC471B7CFC0D00010E03 /* RJSResults.mm */; };
0270BC561B7CFC0D00010E03 /* RJSSchema.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 0270BC481B7CFC0D00010E03 /* RJSSchema.hpp */; };
0270BC561B7CFC0D00010E03 /* RJSSchema.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 0270BC481B7CFC0D00010E03 /* RJSSchema.hpp */; settings = {ATTRIBUTES = (Private, ); }; };
0270BC571B7CFC0D00010E03 /* RJSSchema.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0270BC491B7CFC0D00010E03 /* RJSSchema.mm */; };
0270BC581B7CFC0D00010E03 /* RJSUtil.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 0270BC4A1B7CFC0D00010E03 /* RJSUtil.hpp */; };
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 */; };
@ -49,6 +51,7 @@
0270BC861B7D020100010E03 /* TestObjects.js in Resources */ = {isa = PBXBuildFile; fileRef = 0270BC7F1B7D020100010E03 /* TestObjects.js */; };
0270BC871B7D023200010E03 /* RealmJS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 02B58CB11AE99CEC009B348C /* RealmJS.framework */; };
0270BCD11B7D067300010E03 /* RealmReactModule.m in Sources */ = {isa = PBXBuildFile; fileRef = 0270BCD01B7D067300010E03 /* RealmReactModule.m */; };
02A3C7971BC4318600B1A7BE /* GCDWebServers.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 02A3C7941BC4317A00B1A7BE /* GCDWebServers.framework */; };
02B29A311B7CF86D008A7E6B /* RealmJS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 02B58CB11AE99CEC009B348C /* RealmJS.framework */; };
02B58CCE1AE99D4D009B348C /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 02B58CCD1AE99D4D009B348C /* JavaScriptCore.framework */; };
02D456DA1B7E59A500EE1299 /* ArrayTests.js in Resources */ = {isa = PBXBuildFile; fileRef = 02D456D91B7E59A500EE1299 /* ArrayTests.js */; };
@ -56,6 +59,41 @@
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
02A3C78D1BC4317A00B1A7BE /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 02A3C7841BC4317A00B1A7BE /* GCDWebServer.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 8DD76FB20486AB0100D96B5E;
remoteInfo = "GCDWebServer (Mac)";
};
02A3C78F1BC4317A00B1A7BE /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 02A3C7841BC4317A00B1A7BE /* GCDWebServer.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = E221125A1690B4DE0048D2B2;
remoteInfo = "GCDWebServer (iOS)";
};
02A3C7911BC4317A00B1A7BE /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 02A3C7841BC4317A00B1A7BE /* GCDWebServer.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = CEE28CD11AE004D800F4023C;
remoteInfo = "GCDWebServers (Mac)";
};
02A3C7931BC4317A00B1A7BE /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 02A3C7841BC4317A00B1A7BE /* GCDWebServer.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = CEE28CEF1AE0051F00F4023C;
remoteInfo = "GCDWebServers (iOS)";
};
02A3C7951BC4317A00B1A7BE /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 02A3C7841BC4317A00B1A7BE /* GCDWebServer.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = E24039251BA09207000B7089;
remoteInfo = "Tests (Mac)";
};
02B29A2F1B7CF7ED008A7E6B /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 02B58CA81AE99CEB009B348C /* Project object */;
@ -85,6 +123,8 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
02258FB11BC6E2D00075F13A /* RealmRPC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RealmRPC.h; path = src/RealmRPC.h; sourceTree = "<group>"; };
02258FB21BC6E2D00075F13A /* RealmRPC.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = RealmRPC.mm; path = src/RealmRPC.mm; sourceTree = "<group>"; };
02601F011BA0F0C4007C91FF /* external_commit_helper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = external_commit_helper.cpp; path = "src/object-store/apple/external_commit_helper.cpp"; sourceTree = "<group>"; };
02601F021BA0F0C4007C91FF /* external_commit_helper.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = external_commit_helper.hpp; path = "src/object-store/apple/external_commit_helper.hpp"; sourceTree = "<group>"; };
02601F051BA0F0CD007C91FF /* index_set.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = index_set.cpp; path = "src/object-store/index_set.cpp"; sourceTree = "<group>"; };
@ -130,6 +170,8 @@
0270BC7F1B7D020100010E03 /* TestObjects.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = TestObjects.js; path = tests/TestObjects.js; sourceTree = SOURCE_ROOT; };
0270BCCF1B7D067300010E03 /* RealmReactModule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RealmReactModule.h; path = ReactNative/RealmReactModule.h; sourceTree = "<group>"; };
0270BCD01B7D067300010E03 /* RealmReactModule.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RealmReactModule.m; path = ReactNative/RealmReactModule.m; sourceTree = "<group>"; };
02A3C7841BC4317A00B1A7BE /* GCDWebServer.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = GCDWebServer.xcodeproj; path = vendor/GCDWebServer/GCDWebServer.xcodeproj; sourceTree = "<group>"; };
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; };
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; };
@ -142,6 +184,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
02A3C7971BC4318600B1A7BE /* GCDWebServers.framework in Frameworks */,
02B29A311B7CF86D008A7E6B /* RealmJS.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
@ -191,6 +234,8 @@
02601F071BA0F0CD007C91FF /* realm_delegate.hpp */,
0270BC3E1B7CFC0D00010E03 /* RealmJS.h */,
0270BC3F1B7CFC0D00010E03 /* RealmJS.mm */,
02258FB11BC6E2D00075F13A /* RealmRPC.h */,
02258FB21BC6E2D00075F13A /* RealmRPC.mm */,
0270BC401B7CFC0D00010E03 /* RJSArray.cpp */,
0270BC411B7CFC0D00010E03 /* RJSArray.hpp */,
0270BC421B7CFC0D00010E03 /* RJSObject.hpp */,
@ -217,9 +262,22 @@
name = ReactNativeModule;
sourceTree = "<group>";
};
02A3C7851BC4317A00B1A7BE /* Products */ = {
isa = PBXGroup;
children = (
02A3C78E1BC4317A00B1A7BE /* GCDWebServer */,
02A3C7901BC4317A00B1A7BE /* GCDWebServer.app */,
02A3C7921BC4317A00B1A7BE /* GCDWebServers.framework */,
02A3C7941BC4317A00B1A7BE /* GCDWebServers.framework */,
02A3C7961BC4317A00B1A7BE /* Tests.xctest */,
);
name = Products;
sourceTree = "<group>";
};
02B58CA71AE99CEB009B348C = {
isa = PBXGroup;
children = (
02A3C7841BC4317A00B1A7BE /* GCDWebServer.xcodeproj */,
02B58CCF1AE99D8C009B348C /* Frameworks */,
0270BC3D1B7CFBFD00010E03 /* RealmJS */,
02B58CC01AE99CEC009B348C /* RealmJSTests */,
@ -257,6 +315,7 @@
02B58CCF1AE99D8C009B348C /* Frameworks */ = {
isa = PBXGroup;
children = (
02A3C7A41BC4341500B1A7BE /* libc++.tbd */,
02B58CCD1AE99D4D009B348C /* JavaScriptCore.framework */,
);
name = Frameworks;
@ -270,23 +329,24 @@
buildActionMask = 2147483647;
files = (
0270BC4C1B7CFC0D00010E03 /* RealmJS.h in Headers */,
02258FB31BC6E2D00075F13A /* RealmRPC.h in Headers */,
0270BC4F1B7CFC0D00010E03 /* RJSArray.hpp in Headers */,
0270BC541B7CFC0D00010E03 /* RJSResults.hpp in Headers */,
0270BC581B7CFC0D00010E03 /* RJSUtil.hpp in Headers */,
0270BC561B7CFC0D00010E03 /* RJSSchema.hpp in Headers */,
0270BC521B7CFC0D00010E03 /* RJSRealm.hpp in Headers */,
0270BC501B7CFC0D00010E03 /* RJSObject.hpp in Headers */,
02601F0E1BA0F3A7007C91FF /* schema.hpp in Headers */,
0270BC6C1B7CFC1C00010E03 /* object_store.hpp in Headers */,
02601F0A1BA0F0CD007C91FF /* realm_delegate.hpp in Headers */,
0270BC541B7CFC0D00010E03 /* RJSResults.hpp in Headers */,
02601F121BA10228007C91FF /* transact_log_handler.hpp in Headers */,
0270BC681B7CFC1C00010E03 /* object_accessor.hpp in Headers */,
0270BC711B7CFC1C00010E03 /* shared_realm.hpp in Headers */,
0270BC581B7CFC0D00010E03 /* RJSUtil.hpp in Headers */,
0270BC6A1B7CFC1C00010E03 /* object_schema.hpp in Headers */,
02601F041BA0F0C4007C91FF /* external_commit_helper.hpp in Headers */,
02601F091BA0F0CD007C91FF /* index_set.hpp in Headers */,
0270BC6D1B7CFC1C00010E03 /* property.hpp in Headers */,
0270BC6F1B7CFC1C00010E03 /* results.hpp in Headers */,
0270BC561B7CFC0D00010E03 /* RJSSchema.hpp in Headers */,
0270BC521B7CFC0D00010E03 /* RJSRealm.hpp in Headers */,
0270BC501B7CFC0D00010E03 /* RJSObject.hpp in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -378,6 +438,12 @@
mainGroup = 02B58CA71AE99CEB009B348C;
productRefGroup = 02B58CB21AE99CEC009B348C /* Products */;
projectDirPath = "";
projectReferences = (
{
ProductGroup = 02A3C7851BC4317A00B1A7BE /* Products */;
ProjectRef = 02A3C7841BC4317A00B1A7BE /* GCDWebServer.xcodeproj */;
},
);
projectRoot = "";
targets = (
02B58CB01AE99CEC009B348C /* RealmJS */,
@ -387,6 +453,44 @@
};
/* End PBXProject section */
/* Begin PBXReferenceProxy section */
02A3C78E1BC4317A00B1A7BE /* GCDWebServer */ = {
isa = PBXReferenceProxy;
fileType = "compiled.mach-o.executable";
path = GCDWebServer;
remoteRef = 02A3C78D1BC4317A00B1A7BE /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
02A3C7901BC4317A00B1A7BE /* GCDWebServer.app */ = {
isa = PBXReferenceProxy;
fileType = wrapper.application;
path = GCDWebServer.app;
remoteRef = 02A3C78F1BC4317A00B1A7BE /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
02A3C7921BC4317A00B1A7BE /* GCDWebServers.framework */ = {
isa = PBXReferenceProxy;
fileType = wrapper.framework;
path = GCDWebServers.framework;
remoteRef = 02A3C7911BC4317A00B1A7BE /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
02A3C7941BC4317A00B1A7BE /* GCDWebServers.framework */ = {
isa = PBXReferenceProxy;
fileType = wrapper.framework;
path = GCDWebServers.framework;
remoteRef = 02A3C7931BC4317A00B1A7BE /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
02A3C7961BC4317A00B1A7BE /* Tests.xctest */ = {
isa = PBXReferenceProxy;
fileType = wrapper.cfbundle;
path = Tests.xctest;
remoteRef = 02A3C7951BC4317A00B1A7BE /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
/* End PBXReferenceProxy section */
/* Begin PBXResourcesBuildPhase section */
02B58CAF1AE99CEC009B348C /* Resources */ = {
isa = PBXResourcesBuildPhase;
@ -447,6 +551,7 @@
0270BC511B7CFC0D00010E03 /* RJSObject.mm in Sources */,
0270BC4D1B7CFC0D00010E03 /* RealmJS.mm in Sources */,
02601F081BA0F0CD007C91FF /* index_set.cpp in Sources */,
02258FB41BC6E2D00075F13A /* RealmRPC.mm in Sources */,
02601F111BA10228007C91FF /* transact_log_handler.cpp in Sources */,
0270BC591B7CFC0D00010E03 /* RJSUtil.mm in Sources */,
0270BC551B7CFC0D00010E03 /* RJSResults.mm in Sources */,
@ -486,6 +591,11 @@
02B29A281B7CF7C9008A7E6B /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_CXX_LANGUAGE_STANDARD = "c++14";
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)",
);
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
@ -495,7 +605,12 @@
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
"$(SRCROOT)/examples/ReactExample/node_modules/react-native/React/",
);
IPHONEOS_DEPLOYMENT_TARGET = 8.4;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
OTHER_CPLUSPLUSFLAGS = (
"$(OTHER_CFLAGS)",
"-isystem",
core/include,
);
OTHER_LDFLAGS = "-ObjC";
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
@ -505,12 +620,22 @@
02B29A291B7CF7C9008A7E6B /* GCov_Build */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_CXX_LANGUAGE_STANDARD = "c++14";
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)",
);
HEADER_SEARCH_PATHS = (
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
"$(SRCROOT)/examples/ReactExample/node_modules/react-native/React/",
);
IPHONEOS_DEPLOYMENT_TARGET = 8.4;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
OTHER_CPLUSPLUSFLAGS = (
"$(OTHER_CFLAGS)",
"-isystem",
core/include,
);
OTHER_LDFLAGS = "-ObjC";
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
@ -520,12 +645,22 @@
02B29A2A1B7CF7C9008A7E6B /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_CXX_LANGUAGE_STANDARD = "c++14";
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)",
);
HEADER_SEARCH_PATHS = (
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
"$(SRCROOT)/examples/ReactExample/node_modules/react-native/React/",
);
IPHONEOS_DEPLOYMENT_TARGET = 8.4;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
OTHER_CPLUSPLUSFLAGS = (
"$(OTHER_CFLAGS)",
"-isystem",
core/include,
);
OTHER_LDFLAGS = "-ObjC";
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
@ -636,7 +771,7 @@
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
FRAMEWORK_SEARCH_PATHS = "";
FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)";
GCC_NO_COMMON_BLOCKS = NO;
GCC_PREPROCESSOR_DEFINITIONS = (
REALM_HAVE_CONFIG,
@ -650,7 +785,7 @@
);
INFOPLIST_FILE = src/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 7.0;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
LIBRARY_SEARCH_PATHS = core;
OTHER_CPLUSPLUSFLAGS = (
@ -674,7 +809,7 @@
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
FRAMEWORK_SEARCH_PATHS = "";
FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)";
GCC_NO_COMMON_BLOCKS = NO;
HEADER_SEARCH_PATHS = (
"$(inherited)",
@ -682,7 +817,7 @@
);
INFOPLIST_FILE = src/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 7.0;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
LIBRARY_SEARCH_PATHS = core;
OTHER_CPLUSPLUSFLAGS = (
@ -710,6 +845,7 @@
"$(inherited)",
);
INFOPLIST_FILE = tests/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_NAME = "$(TARGET_NAME)";
};
@ -724,6 +860,7 @@
build/iOS,
);
INFOPLIST_FILE = tests/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_NAME = "$(TARGET_NAME)";
};
@ -788,7 +925,7 @@
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
FRAMEWORK_SEARCH_PATHS = "";
FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)";
GCC_NO_COMMON_BLOCKS = NO;
GCC_PREPROCESSOR_DEFINITIONS = (
REALM_HAVE_CONFIG,
@ -802,7 +939,7 @@
);
INFOPLIST_FILE = src/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 7.0;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
LIBRARY_SEARCH_PATHS = core;
OTHER_CPLUSPLUSFLAGS = (
@ -830,6 +967,7 @@
"$(inherited)",
);
INFOPLIST_FILE = tests/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_NAME = "$(TARGET_NAME)";
};

View File

@ -15,6 +15,7 @@
00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */; };
0270BCD21B7D095C00010E03 /* libRealmReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0270BCB31B7D04D700010E03 /* libRealmReact.a */; };
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 */; };
@ -161,6 +162,7 @@
027798461BBB2F1000C96559 /* ReactExampleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ReactExampleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
027798481BBB2F1000C96559 /* ReactExampleTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ReactExampleTests.m; sourceTree = "<group>"; };
0277984A1BBB2F1000C96559 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
02A3C7A61BC4347100B1A7BE /* libc++.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = "libc++.tbd"; path = "usr/lib/libc++.tbd"; sourceTree = SDKROOT; };
139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTSettings.xcodeproj; path = "node_modules/react-native/Libraries/Settings/RCTSettings.xcodeproj"; sourceTree = "<group>"; };
139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTWebSocket.xcodeproj; path = "node_modules/react-native/Libraries/WebSocket/RCTWebSocket.xcodeproj"; sourceTree = "<group>"; };
13B07F961A680F5B00A75B9A /* ReactExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ReactExample.app; sourceTree = BUILT_PRODUCTS_DIR; };
@ -187,6 +189,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
02A3C7A71BC4347100B1A7BE /* libc++.tbd in Frameworks */,
0270BCD21B7D095C00010E03 /* libRealmReact.a in Frameworks */,
146834051AC3E58100842450 /* libReact.a in Frameworks */,
00C302E51ABCBA2D00DB3ED1 /* libRCTActionSheet.a in Frameworks */,
@ -339,6 +342,7 @@
83CBB9F61A601CBA00E9B192 = {
isa = PBXGroup;
children = (
02A3C7A61BC4347100B1A7BE /* libc++.tbd */,
13B07FAE1A68108700A75B9A /* ReactExample */,
832341AE1AAA6A7D00B99B32 /* Libraries */,
027798471BBB2F1000C96559 /* ReactExampleTests */,
@ -382,6 +386,7 @@
isa = PBXNativeTarget;
buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "ReactExample" */;
buildPhases = (
02A3C7C11BC4597900B1A7BE /* ShellScript */,
13B07F871A680F5B00A75B9A /* Sources */,
13B07F8C1A680F5B00A75B9A /* Frameworks */,
13B07F8E1A680F5B00A75B9A /* Resources */,
@ -591,6 +596,22 @@
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
02A3C7C11BC4597900B1A7BE /* ShellScript */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "rm -rf ./node_modules/realm\nnpm install realm";
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
027798421BBB2F1000C96559 /* Sources */ = {
isa = PBXSourcesBuildPhase;
@ -645,7 +666,7 @@
ENABLE_TESTABILITY = YES;
GCC_NO_COMMON_BLOCKS = YES;
INFOPLIST_FILE = ReactExampleTests/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = io.realm.ReactExampleTests;
PRODUCT_NAME = "$(TARGET_NAME)";
@ -661,7 +682,7 @@
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
GCC_NO_COMMON_BLOCKS = YES;
INFOPLIST_FILE = ReactExampleTests/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = io.realm.ReactExampleTests;
PRODUCT_NAME = "$(TARGET_NAME)";
@ -705,7 +726,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LANGUAGE_STANDARD = "c++14";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
@ -740,7 +761,7 @@
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
"$(SRCROOT)/node_modules/react-native/React/**",
);
IPHONEOS_DEPLOYMENT_TARGET = 7.0;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
@ -751,7 +772,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LANGUAGE_STANDARD = "c++14";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
@ -780,7 +801,7 @@
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
"$(SRCROOT)/node_modules/react-native/React/**",
);
IPHONEOS_DEPLOYMENT_TARGET = 7.0;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
VALIDATE_PRODUCT = YES;

View File

@ -4,6 +4,7 @@
*/
'use strict';
var Realm = require('realm');
var React = require('react-native');
var {

View File

@ -6,6 +6,7 @@
"start": "node_modules/react-native/packager/packager.sh"
},
"dependencies": {
"react-native": "0.11.4"
"react-native": "0.11.4",
"realm": "file:../../lib"
}
}

14
lib/.eslintrc Normal file
View File

@ -0,0 +1,14 @@
{
"root": true,
"extends": "eslint:recommended",
"env": {
"commonjs": true,
"browser": true,
"es6": true,
},
"rules": {
"comma-dangle": 0,
"no-unused-vars": 1,
"strict": [2, "global"]
}
}

7
lib/index.js Normal file
View File

@ -0,0 +1,7 @@
'use strict';
if (typeof Realm != 'undefined') {
module.exports = Realm; // eslint-disable-line no-undef
} else {
module.exports = require('./realm');
}

63
lib/lists.js Normal file
View File

@ -0,0 +1,63 @@
'use strict';
let rpc = require('./rpc');
let util = require('./util');
let idKey = util.idKey;
let realmKey = util.realmKey;
let resizeListKey = util.resizeListKey;
let prototype = {};
exports.create = create;
[
'pop',
'shift',
'push',
'unshift',
'splice',
].forEach(function(name) {
Object.defineProperty(prototype, name, {
value: function() {
let listId = this[idKey];
let realmId = this[realmKey];
if (!listId || !realmId) {
throw new TypeError(name + ' method was not called on a List!');
}
let result = rpc.callListMethod(realmId, listId, name, Array.from(arguments));
this[resizeListKey]();
return result;
}
});
});
function create(realmId, info) {
let list = util.createList(prototype, getterForLength, getterForIndex, setterForIndex);
let size = info.size;
list[realmKey] = realmId;
list[idKey] = info.id;
list[resizeListKey](size);
return list;
}
function getterForLength() {
return rpc.getListSize(this[realmKey], this[idKey]);
}
function getterForIndex(index) {
return function() {
return rpc.getListItem(this[realmKey], this[idKey], index);
};
}
function setterForIndex(index) {
return function(value) {
rpc.setListItem(this[realmKey], this[idKey], index, value);
};
}

50
lib/objects.js Normal file
View File

@ -0,0 +1,50 @@
'use strict';
let rpc = require('./rpc');
let util = require('./util');
let idKey = util.idKey;
let realmKey = util.realmKey;
let registeredConstructors = {};
exports.create = create;
exports.registerConstructors = registerConstructors;
function create(realmId, info) {
let schema = info.schema;
let constructor = (registeredConstructors[realmId] || {})[schema.name];
let object = constructor ? Object.create(constructor.prototype) : {};
let props = {};
object[realmKey] = realmId;
object[idKey] = info.id;
for (let prop of schema.properties) {
let name = prop.name;
props[name] = {
get: getterForProperty(name),
set: setterForProperty(name),
};
}
Object.defineProperties(object, props);
return object;
}
function registerConstructors(realmId, constructors) {
registeredConstructors[realmId] = constructors;
}
function getterForProperty(name) {
return function() {
return rpc.getObjectProperty(this[realmKey], this[idKey], name);
};
}
function setterForProperty(name) {
return function(value) {
rpc.setObjectProperty(this[realmKey], this[idKey], name, value);
};
}

5
lib/package.json Normal file
View File

@ -0,0 +1,5 @@
{
"name": "realm",
"version": "0.0.1",
"private": true
}

86
lib/realm.js Normal file
View File

@ -0,0 +1,86 @@
'use strict';
let lists = require('./lists');
let objects = require('./objects');
let results = require('./results');
let rpc = require('./rpc');
let types = require('./types');
let util = require('./util');
let realmKey = util.realmKey;
// TODO: DATA
rpc.registerTypeConverter(types.DATE, (_, info) => new Date(info.value));
rpc.registerTypeConverter(types.LIST, lists.create);
rpc.registerTypeConverter(types.OBJECT, objects.create);
rpc.registerTypeConverter('ObjectTypesRESULTS', results.create);
class Realm {
constructor(config) {
let schema = typeof config == 'object' && config.schema;
let constructors = {};
for (let i = 0, len = schema ? schema.length : 0; i < len; i++) {
let item = schema[i];
let proto = item.prototype;
if (proto && proto.schema) {
schema.splice(i, 1, proto.schema);
constructors[proto.schema.name] = item;
}
}
let realmId = this[realmKey] = rpc.createRealm(config);
objects.registerConstructors(realmId, constructors);
}
addNotification(callback) {
// TODO
}
write(callback) {
let realmId = this[realmKey];
if (!realmId) {
throw new TypeError('write method was not called on a Realm object!');
}
if (typeof callback != 'function') {
throw new TypeError('Realm.write() must be passed a function!');
}
rpc.beginTransaction(realmId);
try {
callback();
} catch (e) {
rpc.cancelTransaction(realmId);
throw e;
}
rpc.commitTransaction(realmId);
}
}
[
'create',
'delete',
'deleteAll',
'objects',
].forEach(function(name) {
Object.defineProperty(Realm.prototype, name, {
value: function() {
let realmId = this[realmKey];
if (!realmId) {
throw new TypeError(name + ' method was not called on a Realm object!');
}
return rpc.callRealmMethod(realmId, name, Array.from(arguments));
}
});
});
Object.defineProperty(Realm, 'Types', {value: types});
module.exports = Realm;

32
lib/results.js Normal file
View File

@ -0,0 +1,32 @@
'use strict';
let rpc = require('./rpc');
let util = require('./util');
let idKey = util.idKey;
let realmKey = util.realmKey;
let resizeListKey = util.resizeListKey;
exports.create = create;
function create(realmId, info) {
let results = util.createList(null, getterForLength, getterForIndex);
let size = info.size;
results[realmKey] = realmId;
results[idKey] = info.id;
results[resizeListKey](size);
return results;
}
function getterForLength() {
return rpc.getResultsSize(this[realmKey], this[idKey]);
}
function getterForIndex(index) {
return function() {
return rpc.getResultsItem(this[realmKey], this[idKey], index);
};
}

170
lib/rpc.js Normal file
View File

@ -0,0 +1,170 @@
'use strict';
let util = require('./util');
let DEVICE_HOST = 'localhost:8082';
let idKey = util.idKey;
let realmKey = util.realmKey;
let typeConverters = {};
let XMLHttpRequest = window.XMLHttpRequest;
// Check if XMLHttpRequest has been overridden, and get the native one if that's the case.
if (XMLHttpRequest.__proto__ != window.XMLHttpRequestEventTarget) {
let override = XMLHttpRequest;
delete window.XMLHttpRequest;
XMLHttpRequest = window.XMLHttpRequest;
window.XMLHttpRequest = override;
}
exports.registerTypeConverter = registerTypeConverter;
exports.createRealm = createRealm;
exports.callRealmMethod = callRealmMethod;
exports.getObjectProperty = getObjectProperty;
exports.setObjectProperty = setObjectProperty;
exports.getListItem = getListItem;
exports.setListItem = setListItem;
exports.getListSize = getListSize;
exports.callListMethod = callListMethod;
exports.getResultsItem = getResultsItem;
exports.getResultsSize = getResultsSize;
exports.beginTransaction = beginTransaction;
exports.cancelTransaction = cancelTransaction;
exports.commitTransaction = commitTransaction;
function registerTypeConverter(type, handler) {
typeConverters[type] = handler;
}
function createRealm(config) {
return sendRequest('create_realm', config);
}
function callRealmMethod(realmId, name, args) {
if (args) {
args = args.map((arg) => serialize(realmId, arg));
}
let result = sendRequest('call_realm_method', {realmId, name, arguments: args});
return deserialize(realmId, result);
}
function getObjectProperty(realmId, objectId, name) {
let result = sendRequest('get_property', {realmId, objectId, name});
return deserialize(realmId, result);
}
function setObjectProperty(realmId, objectId, name, value) {
value = serialize(realmId, value);
sendRequest('set_property', {realmId, objectId, name, value});
}
function getListItem(realmId, listId, index) {
let result = sendRequest('get_list_item', {realmId, listId, index});
return deserialize(realmId, result);
}
function setListItem(realmId, listId, index, value) {
sendRequest('set_list_item', {realmId, listId, index, value});
}
function getListSize(realmId, listId) {
return sendRequest('get_list_size', {realmId, listId});
}
function callListMethod(realmId, listId, name, args) {
if (args) {
args = args.map((arg) => serialize(realmId, arg));
}
let result = sendRequest('call_list_method', {realmId, listId, name, arguments: args});
return deserialize(realmId, result);
}
function getResultsItem(realmId, resultsId, index) {
let result = sendRequest('get_results_item', {realmId, resultsId, index});
return deserialize(realmId, result);
}
function getResultsSize(realmId, resultsId) {
return sendRequest('get_results_size', {realmId, resultsId});
}
function beginTransaction(realmId) {
sendRequest('begin_transaction', {realmId});
}
function cancelTransaction(realmId) {
sendRequest('cancel_transaction', {realmId});
}
function commitTransaction(realmId) {
sendRequest('commit_transaction', {realmId});
}
function serialize(realmId, value) {
if (!value || typeof value != 'object') {
return {value: value};
}
let id = value[idKey];
if (id) {
if (value[realmKey] != realmId) {
throw new Error('Unable to serialize value from another Realm');
}
return {id: id};
}
if (Array.isArray(value)) {
let array = value.map((item) => serialize(realmId, item));
return {value: array};
}
let object = {};
for (let key in value) {
object[key] = serialize(realmId, value[key]);
}
return {value: object};
}
function deserialize(realmId, info) {
let type = info.type;
let handler = type && typeConverters[type];
if (handler) {
return handler(realmId, info);
}
let value = info.value;
if (value && Array.isArray(value)) {
return value.map((item) => deserialize(realmId, item));
}
return value;
}
function sendRequest(command, data) {
let body = JSON.stringify(data);
let request = new XMLHttpRequest();
let url = 'http://' + DEVICE_HOST + '/' + command;
request.open('POST', url, false);
request.send(body);
if (request.status != 200) {
throw new Error(request.responseText);
}
let response = JSON.parse(request.responseText);
if (!response || response.error) {
throw new Error((response && response.error) || 'Invalid response for "' + command + '"');
}
return response.result;
}

19
lib/types.js Normal file
View File

@ -0,0 +1,19 @@
'use strict';
let types = {};
[
'BOOL',
'INT',
'FLOAT',
'DOUBLE',
'STRING',
'DATE',
'DATA',
'OBJECT',
'LIST',
].forEach(function(type) {
types[type] = 'PropTypes' + type;
});
module.exports = Object.freeze(types);

47
lib/util.js Normal file
View File

@ -0,0 +1,47 @@
'use strict';
let idKey = exports.idKey = Symbol();
let realmKey = exports.realmKey = Symbol();
let resizeListKey = exports.resizeListKey = Symbol();
exports.createList = createList;
function createList(prototype, getterForLength, getterForIndex, setterForIndex) {
var list = prototype ? Object.create(prototype) : {};
var size = 0;
Object.defineProperty(list, 'length', {get: getterForLength});
list[resizeListKey] = function(length) {
if (length == null) {
length = this.length;
}
if (length == size) {
return;
}
if (length > size) {
let props = {};
for (let i = size; i < length; i++) {
props[i] = {
get: getterForIndex(i),
set: setterForIndex && setterForIndex(i),
enumerable: true,
configurable: true,
};
}
Object.defineProperties(this, props);
}
else if (length < size) {
for (let i = size - 1; i >= length; i--) {
delete this[i];
}
}
size = length;
};
return list;
}

View File

@ -21,6 +21,7 @@
#include "RJSUtil.hpp"
#include "object_accessor.hpp"
using RJSAccessor = realm::NativeAccessor<JSValueRef, JSContextRef>;
using namespace realm;
size_t ObjectArray::size() {
@ -197,15 +198,16 @@ JSObjectRef RJSArrayCreate(JSContextRef ctx, realm::ObjectArray *array) {
return RJSWrapObject<ObjectArray *>(ctx, RJSArrayClass(), array);
}
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},
{NULL, NULL},
};
JSClassRef RJSArrayClass() {
const JSStaticFunction arrayFuncs[] = {
{"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},
{NULL, NULL},
};
static JSClassRef s_arrayClass = RJSCreateWrapperClass<Object>("RealmArray", ArrayGetProperty, NULL, arrayFuncs, NULL, ArrayPropertyNames);
static JSClassRef s_arrayClass = RJSCreateWrapperClass<Object>("RealmArray", ArrayGetProperty, NULL, RJSArrayFuncs, NULL, ArrayPropertyNames);
return s_arrayClass;
}

View File

@ -34,5 +34,8 @@ namespace realm {
};
}
extern const JSStaticFunction RJSArrayFuncs[];
JSClassRef RJSArrayClass();
JSObjectRef RJSArrayCreate(JSContextRef ctx, realm::ObjectArray *array);
JSValueRef ArrayGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* jsException);

View File

@ -17,14 +17,14 @@
////////////////////////////////////////////////////////////////////////////
#import "RJSUtil.hpp"
#import "shared_realm.hpp"
#import "object_accessor.hpp"
namespace realm {
class Object;
}
using RJSAccessor = realm::NativeAccessor<JSValueRef, JSContextRef>;
JSClassRef RJSObjectClass();
JSObjectRef RJSObjectCreate(JSContextRef ctx, realm::Object object);
JSValueRef ObjectGetProperty(JSContextRef ctx, JSObjectRef jsObject, JSStringRef jsPropertyName, JSValueRef* exception);
bool ObjectSetProperty(JSContextRef ctx, JSObjectRef jsObject, JSStringRef jsPropertyName, JSValueRef value, JSValueRef* exception);

View File

@ -25,6 +25,7 @@
#import "object_store.hpp"
#import "object_accessor.hpp"
using RJSAccessor = realm::NativeAccessor<JSValueRef, JSContextRef>;
using namespace realm;
JSValueRef ObjectGetProperty(JSContextRef ctx, JSObjectRef jsObject, JSStringRef jsPropertyName, JSValueRef* exception) {
@ -69,7 +70,6 @@ JSValueRef ObjectGetProperty(JSContextRef ctx, JSObjectRef jsObject, JSStringRef
auto arrayObjectSchema = obj->realm->config().schema->find(prop->object_type);
return RJSArrayCreate(ctx, new ObjectArray(obj->realm, *arrayObjectSchema, static_cast<LinkViewRef>(obj->row.get_linklist(prop->table_column))));
}
}
return NULL;
}

View File

@ -18,6 +18,8 @@
#import "RJSUtil.hpp"
extern const JSStaticFunction RJSRealmFuncs[];
JSClassRef RJSRealmClass();
JSClassRef RJSRealmConstructorClass();
JSClassRef RJSNotificationClass();
@ -25,3 +27,4 @@ JSClassRef RJSNotificationClass();
std::string RJSDefaultPath();
void RJSSetDefaultPath(std::string path);
JSObjectRef RealmConstructor(JSContextRef ctx, JSObjectRef constructor, size_t argumentCount, const JSValueRef arguments[], JSValueRef* jsException);

View File

@ -409,18 +409,18 @@ void RJSNotificationFinalize(JSObjectRef object) {
RJSFinalize<Notification *>(object);
}
const JSStaticFunction RJSRealmFuncs[] = {
{"objects", RealmObjects, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
{"create", RealmCreateObject, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
{"delete", RealmDelete, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
{"deleteAll", RealmDeleteAll, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
{"write", RealmWrite, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
{"addNotification", RealmAddNotification, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
{NULL, NULL},
};
JSClassRef RJSRealmClass() {
const JSStaticFunction realmFuncs[] = {
{"objects", RealmObjects, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
{"create", RealmCreateObject, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
{"delete", RealmDelete, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
{"deleteAll", RealmDeleteAll, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
{"write", RealmWrite, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
{"addNotification", RealmAddNotification, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
{NULL, NULL},
};
static JSClassRef s_realmClass = RJSCreateWrapperClass<SharedRealm *>("Realm", RealmGetProperty, NULL, realmFuncs);
static JSClassRef s_realmClass = RJSCreateWrapperClass<SharedRealm *>("Realm", RealmGetProperty, NULL, RJSRealmFuncs);
return s_realmClass;
}

View File

@ -26,3 +26,6 @@ namespace realm {
JSClassRef RJSResultsClass();
JSObjectRef RJSResultsCreate(JSContextRef ctx, realm::SharedRealm realm, std::string className);
JSObjectRef RJSResultsCreate(JSContextRef ctx, realm::SharedRealm realm, std::string className, std::string query);
JSValueRef ResultsGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* jsException);

View File

@ -19,6 +19,7 @@
#include <JavaScriptCore/JavaScriptCore.h>
#include <string>
#include <stdexcept>
#include "property.hpp"
#include "schema.hpp"
template<typename T>
@ -55,7 +56,11 @@ JSClassRef RJSCreateWrapperClass(const char * name, JSObjectGetPropertyCallback
JSObjectRef RJSRegisterGlobalClass(JSContextRef ctx, JSObjectRef globalObject, JSClassRef classRef, const char * name, JSValueRef *exception);
std::string RJSTypeGet(realm::PropertyType propertyType);
std::string RJSTypeGet(std::string typeString);
std::string RJSStringForJSString(JSStringRef jsString);
std::string RJSStringForValue(JSContextRef ctx, JSValueRef value);
std::string RJSValidatedStringForValue(JSContextRef ctx, JSValueRef value, const char * name = nullptr);
JSStringRef RJSStringForString(const std::string &str);

View File

@ -18,6 +18,8 @@
#import "RJSUtil.hpp"
using namespace realm;
JSObjectRef RJSRegisterGlobalClass(JSContextRef ctx, JSObjectRef globalObject, JSClassRef classRef, const char * name, JSValueRef *exception) {
JSObjectRef classObject = JSObjectMake(ctx, classRef, NULL);
JSStringRef nameString = JSStringCreateWithUTF8CString(name);
@ -43,6 +45,25 @@ JSValueRef RJSMakeError(JSContextRef ctx, const std::string &message) {
return JSObjectMakeError(ctx, 1, &value, NULL);
}
std::string RJSTypeGet(PropertyType propertyType) {
switch (propertyType) {
case PropertyTypeBool: return RJSTypeGet("BOOL");
case PropertyTypeInt: return RJSTypeGet("INT");
case PropertyTypeFloat: return RJSTypeGet("FLOAT");
case PropertyTypeDouble:return RJSTypeGet("DOUBLE");
case PropertyTypeString:return RJSTypeGet("STRING");
case PropertyTypeDate: return RJSTypeGet("DATE");
case PropertyTypeData: return RJSTypeGet("DATA");
case PropertyTypeObject:return RJSTypeGet("OBJECT");
case PropertyTypeArray: return RJSTypeGet("LIST");
default: return nullptr;
}
}
std::string RJSTypeGet(std::string propertyTypeString) {
return "PropTypes" + propertyTypeString;
}
std::string RJSStringForJSString(JSStringRef jsString) {
std::string str;
size_t maxSize = JSStringGetMaximumUTF8CStringSize(jsString);
@ -51,6 +72,19 @@ std::string RJSStringForJSString(JSStringRef jsString) {
return str;
}
std::string RJSStringForValue(JSContextRef ctx, JSValueRef value) {
JSValueRef *exception;
JSStringRef jsString = JSValueToStringCopy(ctx, value, exception);
if (!jsString) {
throw RJSException(ctx, *exception);
}
std::string string = RJSStringForJSString(jsString);
JSStringRelease(jsString);
return string;
}
std::string RJSValidatedStringForValue(JSContextRef ctx, JSValueRef value, const char * name) {
if (!JSValueIsString(ctx, value)) {
if (name) {
@ -61,13 +95,7 @@ std::string RJSValidatedStringForValue(JSContextRef ctx, JSValueRef value, const
}
}
JSValueRef *exception;
JSStringRef jsString = JSValueToStringCopy(ctx, value, exception);
if (!jsString) {
throw RJSException(ctx, *exception);
}
return RJSStringForJSString(jsString);
return RJSStringForValue(ctx, value);
}
JSStringRef RJSStringForString(const std::string &str) {

View File

@ -18,6 +18,7 @@
#import <Foundation/Foundation.h>
#import <JavaScriptCore/JavaScriptCore.h>
#import <RealmJS/RealmRPC.h>
@interface RealmJS : NSObject

View File

@ -19,9 +19,10 @@
#import "RealmJS.h"
#import "RJSRealm.hpp"
#import "RJSObject.hpp"
#import "RJSUtil.hpp"
JSValueRef RJSTypeGet(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception) {
return RJSValueForString(ctx, "PropTypes" + RJSStringForJSString(propertyName));
return RJSValueForString(ctx, RJSTypeGet(RJSStringForJSString(propertyName)));
}
JSClassRef RJSRealmTypeClass() {

27
src/RealmRPC.h Normal file
View File

@ -0,0 +1,27 @@
////////////////////////////////////////////////////////////////////////////
//
// 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.
//
////////////////////////////////////////////////////////////////////////////
#pragma once
#import <Foundation/Foundation.h>
@interface RJSRPCServer : NSObject
- (NSDictionary *)performRequest:(NSString *)name args:(NSDictionary *)args;
@end

352
src/RealmRPC.mm Normal file
View File

@ -0,0 +1,352 @@
////////////////////////////////////////////////////////////////////////////
//
// 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.
//
////////////////////////////////////////////////////////////////////////////
#import "RealmRPC.h"
#import <JavaScriptCore/JavaScriptCore.h>
#include <map>
#include <string>
#include "RealmJS.h"
#include "RJSObject.hpp"
#include "RJSResults.hpp"
#include "RJSArray.hpp"
#include "RJSRealm.hpp"
#include "RJSUtil.hpp"
#include "object_accessor.hpp"
#include "shared_realm.hpp"
#include "results.hpp"
using RPCObjectID = u_int64_t;
using RPCRequest = std::function<NSDictionary *(NSDictionary *dictionary)>;
@implementation RJSRPCServer {
JSGlobalContextRef _context;
std::map<std::string, RPCRequest> _requests;
std::map<RPCObjectID, JSObjectRef> _objects;
}
- (instancetype)init {
self = [super init];
if (self) {
_context = JSGlobalContextCreate(NULL);
_requests["/create_realm"] = [=](NSDictionary *dict) {
// We should have a method for serializing schema rather than relying on JSValue
JSValueRef value = [[JSValue valueWithObject:dict
inContext:[JSContext contextWithJSGlobalContextRef:_context]] JSValueRef];
JSValueRef ex = NULL;
RPCObjectID realmId = [self storeObject:RealmConstructor(_context, NULL, 1, &value, &ex)];
if (ex) {
return @{@"error": @(RJSStringForValue(_context, ex).c_str())};
}
return @{@"result": @(realmId)};
};
_requests["/begin_transaction"] = [=](NSDictionary *dict) {
RPCObjectID realmId = [dict[@"realmId"] unsignedLongValue];
RJSGetInternal<realm::SharedRealm *>(_objects[realmId])->get()->begin_transaction();
return @{};
};
_requests["/cancel_transaction"] = [=](NSDictionary *dict) {
RPCObjectID realmId = [dict[@"realmId"] unsignedLongValue];
RJSGetInternal<realm::SharedRealm *>(_objects[realmId])->get()->cancel_transaction();
return @{};
};
_requests["/commit_transaction"] = [=](NSDictionary *dict) {
RPCObjectID realmId = [dict[@"realmId"] unsignedLongValue];
RJSGetInternal<realm::SharedRealm *>(_objects[realmId])->get()->commit_transaction();
return @{};
};
_requests["/call_realm_method"] = [=](NSDictionary *dict) {
NSString *name = dict[@"name"];
return [self performObjectMethod:name.UTF8String
classMethods:RJSRealmFuncs
args:dict[@"arguments"]
objectId:[dict[@"realmId"] unsignedLongValue]];
};
_requests["/get_property"] = [=](NSDictionary *dict) {
JSValueRef exception = NULL;
NSString *name = dict[@"name"];
JSStringRef propString = RJSStringForString(name.UTF8String);
RPCObjectID objectId = [dict[@"objectId"] unsignedLongValue];
JSValueRef propertyValue = ObjectGetProperty(_context, _objects[objectId], propString, &exception);
JSStringRelease(propString);
if (exception) {
return @{@"error": @(RJSStringForValue(_context, exception).c_str())};
}
return @{@"result": [self resultForJSValue:propertyValue]};
};
_requests["/set_property"] = [=](NSDictionary *dict) {
JSStringRef propString = RJSStringForString([dict[@"name"] UTF8String]);
RPCObjectID realmId = [dict[@"objectId"] unsignedLongValue];
JSValueRef value = [self valueFromDictionary:dict[@"value"]];
JSValueRef exception = NULL;
ObjectSetProperty(_context, _objects[realmId], propString, value, &exception);
JSStringRelease(propString);
return exception ? @{@"error": @(RJSStringForValue(_context, exception).c_str())} : @{};
};
_requests["/dispose_object"] = [=](NSDictionary *dict) {
RPCObjectID oid = [dict[@"id"] unsignedLongValue];
JSValueUnprotect(_context, _objects[oid]);
_objects.erase(oid);
return @{};
};
_requests["/get_results_size"] = [=](NSDictionary *dict) {
RPCObjectID resultsId = [dict[@"resultsId"] unsignedLongValue];
JSValueRef exception = NULL;
static JSStringRef lengthPropertyName = JSStringCreateWithUTF8CString("length");
JSValueRef lengthValue = ResultsGetProperty(_context, _objects[resultsId], lengthPropertyName, &exception);
size_t length = JSValueToNumber(_context, lengthValue, &exception);
if (exception) {
return @{@"error": @(RJSStringForValue(_context, exception).c_str())};
}
return @{@"result": @(length)};
};
_requests["/get_results_item"] = [=](NSDictionary *dict) {
RPCObjectID resultsId = [dict[@"resultsId"] unsignedLongValue];
long index = [dict[@"index"] longValue];
JSValueRef exception = NULL;
JSStringRef indexPropertyName = JSStringCreateWithUTF8CString(std::to_string(index).c_str());
JSValueRef objectValue = ResultsGetProperty(_context, _objects[resultsId], indexPropertyName, &exception);
JSStringRelease(indexPropertyName);
if (exception) {
return @{@"error": @(RJSStringForValue(_context, exception).c_str())};
}
return @{@"result": [self resultForJSValue:objectValue]};
};
_requests["/get_list_size"] = [=](NSDictionary *dict) {
RPCObjectID listId = [dict[@"listId"] unsignedLongValue];
JSValueRef exception = NULL;
static JSStringRef lengthPropertyName = JSStringCreateWithUTF8CString("length");
JSValueRef lengthValue = ArrayGetProperty(_context, _objects[listId], lengthPropertyName, &exception);
size_t length = JSValueToNumber(_context, lengthValue, &exception);
if (exception) {
return @{@"error": @(RJSStringForValue(_context, exception).c_str())};
}
return @{@"result": @(length)};
};
_requests["/get_list_item"] = [=](NSDictionary *dict) {
RPCObjectID listId = [dict[@"listId"] unsignedLongValue];
long index = [dict[@"index"] longValue];
JSValueRef exception = NULL;
JSStringRef indexPropertyName = JSStringCreateWithUTF8CString(std::to_string(index).c_str());
JSValueRef objectValue = ArrayGetProperty(_context, _objects[listId], indexPropertyName, &exception);
JSStringRelease(indexPropertyName);
if (exception) {
return @{@"error": @(RJSStringForValue(_context, exception).c_str())};
}
return @{@"result": [self resultForJSValue:objectValue]};
};
_requests["/call_list_method"] = [=](NSDictionary *dict) {
NSString *name = dict[@"name"];
return [self performObjectMethod:name.UTF8String
classMethods:RJSArrayFuncs
args:dict[@"arguments"]
objectId:[dict[@"listId"] unsignedLongValue]];
};
}
return self;
}
- (NSDictionary *)performRequest:(NSString *)name args:(NSDictionary *)args {
// perform all realm ops on the main thread
RPCRequest action = _requests[name.UTF8String];
__block id response;
dispatch_sync(dispatch_get_main_queue(), ^{
try {
response = action(args);
} catch (std::exception &exception) {
response = @{@"error": [@"exception thrown: " stringByAppendingString:@(exception.what())]};
}
});
return response;
}
- (NSDictionary *)performObjectMethod:(const char *)name
classMethods:(const JSStaticFunction [])methods
args:(NSArray *)args
objectId:(RPCObjectID)oid {
NSUInteger count = args.count;
JSValueRef argValues[count];
for (NSUInteger i = 0; i < count; i++) {
argValues[i] = [self valueFromDictionary:args[i]];
}
size_t index = 0;
while (methods[index].name) {
if (!strcmp(methods[index].name, name)) {
JSValueRef ex = NULL;
JSValueRef ret = methods[index].callAsFunction(_context, NULL, _objects[oid], count, argValues, &ex);
if (ex) {
return @{@"error": @(RJSStringForValue(_context, ex).c_str())};
}
return @{@"result": [self resultForJSValue:ret]};
}
index++;
}
return @{@"error": @"invalid method"};
}
- (RPCObjectID)storeObject:(JSObjectRef)object {
static RPCObjectID s_next_id = 1;
RPCObjectID next_id = s_next_id++;
JSValueProtect(_context, object);
_objects[next_id] = object;
return next_id;
}
- (NSDictionary *)resultForJSValue:(JSValueRef)value {
switch (JSValueGetType(_context, value)) {
case kJSTypeUndefined:
return @{};
case kJSTypeNull:
return @{@"value": [NSNull null]};
case kJSTypeBoolean:
return @{@"value": @(JSValueToBoolean(_context, value))};
case kJSTypeNumber:
return @{@"value": @(JSValueToNumber(_context, value, NULL))};
case kJSTypeString:
return @{@"value": @(RJSStringForValue(_context, value).c_str())};
case kJSTypeObject:
break;
}
JSObjectRef jsObject = JSValueToObject(_context, value, NULL);
if (JSValueIsObjectOfClass(_context, value, RJSObjectClass())) {
realm::Object *object = RJSGetInternal<realm::Object *>(jsObject);
RPCObjectID oid = [self storeObject:jsObject];
return @{
@"type": @(RJSTypeGet(realm::PropertyTypeObject).c_str()),
@"id": @(oid),
@"schema": [self objectSchemaToJSONObject:object->object_schema]
};
}
else if (JSValueIsObjectOfClass(_context, value, RJSArrayClass())) {
realm::ObjectArray *array = RJSGetInternal<realm::ObjectArray *>(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]
};
}
else if (JSValueIsObjectOfClass(_context, value, RJSResultsClass())) {
realm::Results *results = RJSGetInternal<realm::Results *>(jsObject);
RPCObjectID oid = [self storeObject:jsObject];
return @{
@"type": @"ObjectTypesRESULTS",
@"id": @(oid),
@"size": @(results->size()),
@"schema": [self objectSchemaToJSONObject:results->object_schema]
};
}
else if (RJSIsValueArray(_context, value)) {
size_t length = RJSValidatedArrayLength(_context, jsObject);
NSMutableArray *array = [NSMutableArray new];
for (unsigned int i = 0; i < length; i++) {
[array addObject:[self resultForJSValue:JSObjectGetPropertyAtIndex(_context, jsObject, i, NULL)]];
}
return @{@"value": array};
}
else {
assert(0);
}
}
- (NSDictionary *)objectSchemaToJSONObject:(realm::ObjectSchema &)objectSchema {
NSMutableArray *properties = [[NSMutableArray alloc] init];
for (realm::Property prop : objectSchema.properties) {
NSDictionary *dict = @{
@"name": @(prop.name.c_str()),
@"type": @(RJSTypeGet(prop.type).c_str()),
};
[properties addObject:dict];
}
return @{
@"name": @(objectSchema.name.c_str()),
@"properties": properties,
};
}
- (JSValueRef)valueFromDictionary:(NSDictionary *)dict {
RPCObjectID oid = [dict[@"id"] longValue];
if (oid) {
return _objects[oid];
}
id value = dict[@"value"];
if (!value) {
return JSValueMakeUndefined(_context);
}
else if ([value isKindOfClass:[NSNull class]]) {
return JSValueMakeNull(_context);
}
else if ([value isKindOfClass:[@YES class]]) {
return JSValueMakeBoolean(_context, [value boolValue]);
}
else if ([value isKindOfClass:[NSNumber class]]) {
return JSValueMakeNumber(_context, [value doubleValue]);
}
else if ([value isKindOfClass:[NSString class]]) {
return RJSValueForString(_context, std::string([value UTF8String]));
}
else if ([value isKindOfClass:[NSArray class]]) {
NSUInteger count = [value count];
JSValueRef jsValues[count];
for (NSUInteger i = 0; i < count; i++) {
jsValues[i] = [self valueFromDictionary:value[i]];
}
return JSObjectMakeArray(_context, count, jsValues, NULL);
}
else if ([value isKindOfClass:[NSDictionary class]]) {
JSObjectRef jsObject = JSObjectMake(_context, NULL, NULL);
for (NSString *key in value) {
JSValueRef jsValue = [self valueFromDictionary:value[key]];
JSStringRef jsKey = JSStringCreateWithCFString((__bridge CFStringRef)key);
JSObjectSetProperty(_context, jsObject, jsKey, jsValue, 0, NULL);
JSStringRelease(jsKey);
}
return jsObject;
}
return JSValueMakeUndefined(_context);
}
@end

1
vendor/GCDWebServer vendored Submodule

@ -0,0 +1 @@
Subproject commit 3c33e9f056e41adc97422c42d75d9388693e255e