From 57778ce878bba79f3c613376f2691c9e601eb8f4 Mon Sep 17 00:00:00 2001 From: Scott Kyle Date: Mon, 19 Oct 2015 15:52:32 -0700 Subject: [PATCH] Improve calling object methods through RPC --- lib/realm.js | 2 +- lib/rpc.js | 4 ++-- lib/util.js | 2 +- src/RJSList.cpp | 2 +- src/RJSList.hpp | 1 - src/RJSRealm.hpp | 2 -- src/RJSRealm.mm | 2 +- src/RJSResults.hpp | 1 - src/RJSResults.mm | 2 +- src/RealmRPC.mm | 41 ++++++++++++----------------------------- 10 files changed, 19 insertions(+), 40 deletions(-) diff --git a/lib/realm.js b/lib/realm.js index 7e2f48d4..55ddbf46 100644 --- a/lib/realm.js +++ b/lib/realm.js @@ -62,7 +62,7 @@ class Realm { throw new Error('Realm.addNotification must be passed a function!'); } - let notification = rpc.callMethod(realmId, realmId, internal.REALM, 'addNotification', [callback]); + let notification = rpc.callMethod(realmId, realmId, 'addNotification', [callback]); notification[notificationCallbackKey] = callback; this[notificationsKey].push(notification); diff --git a/lib/rpc.js b/lib/rpc.js index f04d9c04..2e7508f4 100644 --- a/lib/rpc.js +++ b/lib/rpc.js @@ -42,12 +42,12 @@ function createRealm(args) { return sendRequest('create_realm', {arguments: args}); } -function callMethod(realmId, id, type, name, args) { +function callMethod(realmId, id, name, args) { if (args) { args = args.map((arg) => serialize(realmId, arg)); } - let result = sendRequest('call_method', {realmId, id, type, name, arguments: args}); + let result = sendRequest('call_method', {realmId, id, name, arguments: args}); return deserialize(realmId, result); } diff --git a/lib/util.js b/lib/util.js index 72c617f7..c6ab34b9 100644 --- a/lib/util.js +++ b/lib/util.js @@ -71,7 +71,7 @@ function createMethods(prototype, type, methodNames, resize) { throw new TypeError(name + ' method was called on an object of the wrong type!'); } - let result = rpc.callMethod(realmId, id, type, name, Array.from(arguments)); + let result = rpc.callMethod(realmId, id, name, Array.from(arguments)); if (resize) { this[keys.resize](); diff --git a/src/RJSList.cpp b/src/RJSList.cpp index 66978780..83179568 100644 --- a/src/RJSList.cpp +++ b/src/RJSList.cpp @@ -214,7 +214,7 @@ JSObjectRef RJSListCreate(JSContextRef ctx, realm::List &list) { return RJSWrapObject(ctx, RJSListClass(), new List(list)); } -const JSStaticFunction RJSListFuncs[] = { +static const JSStaticFunction RJSListFuncs[] = { {"push", ListPush, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, {"pop", ListPop, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, {"shift", ListShift, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, diff --git a/src/RJSList.hpp b/src/RJSList.hpp index 03666854..c820d21d 100644 --- a/src/RJSList.hpp +++ b/src/RJSList.hpp @@ -20,6 +20,5 @@ #import "shared_realm.hpp" #import "list.hpp" -extern const JSStaticFunction RJSListFuncs[]; JSClassRef RJSListClass(); JSObjectRef RJSListCreate(JSContextRef ctx, realm::List &list); diff --git a/src/RJSRealm.hpp b/src/RJSRealm.hpp index d2002ea1..edec1217 100644 --- a/src/RJSRealm.hpp +++ b/src/RJSRealm.hpp @@ -18,8 +18,6 @@ #import "RJSUtil.hpp" -extern const JSStaticFunction RJSRealmFuncs[]; - JSClassRef RJSRealmClass(); JSClassRef RJSRealmConstructorClass(); JSClassRef RJSNotificationClass(); diff --git a/src/RJSRealm.mm b/src/RJSRealm.mm index 78d45c5c..6fcc7c25 100644 --- a/src/RJSRealm.mm +++ b/src/RJSRealm.mm @@ -433,7 +433,7 @@ JSValueRef RealmClose(JSContextRef ctx, JSObjectRef function, JSObjectRef thisOb return NULL; } -const JSStaticFunction RJSRealmFuncs[] = { +static const JSStaticFunction RJSRealmFuncs[] = { {"objects", RealmObjects, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, {"create", RealmCreateObject, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, {"delete", RealmDelete, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, diff --git a/src/RJSResults.hpp b/src/RJSResults.hpp index 09442d75..b1ba3b26 100644 --- a/src/RJSResults.hpp +++ b/src/RJSResults.hpp @@ -23,7 +23,6 @@ namespace realm { typedef std::shared_ptr SharedRealm; } -extern const JSStaticFunction RJSResultsFuncs[]; 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); diff --git a/src/RJSResults.mm b/src/RJSResults.mm index 1ed15eab..661847b0 100644 --- a/src/RJSResults.mm +++ b/src/RJSResults.mm @@ -118,7 +118,7 @@ JSObjectRef RJSResultsCreate(JSContextRef ctx, SharedRealm realm, std::string cl return RJSWrapObject(ctx, RJSResultsClass(), new Results(realm, *object_schema, std::move(query))); } -const JSStaticFunction RJSResultsFuncs[] = { +static const JSStaticFunction RJSResultsFuncs[] = { {"sortByProperty", SortByProperty, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, {NULL, NULL}, }; diff --git a/src/RealmRPC.mm b/src/RealmRPC.mm index ce0e1276..1e914fd1 100644 --- a/src/RealmRPC.mm +++ b/src/RealmRPC.mm @@ -38,23 +38,14 @@ using RPCRequest = std::function; static const char * const RealmObjectTypesFunction = "ObjectTypesFUNCTION"; static const char * const RealmObjectTypesNotification = "ObjectTypesNOTIFICATION"; -static const char * const RealmObjectTypesRealm = "ObjectTypesREALM"; static const char * const RealmObjectTypesResults = "ObjectTypesRESULTS"; -static std::map s_objectTypeMethods; - @implementation RJSRPCServer { JSGlobalContextRef _context; std::map _requests; std::map _objects; } -+ (void)initialize { - s_objectTypeMethods[RealmObjectTypesRealm] = RJSRealmFuncs; - s_objectTypeMethods[RealmObjectTypesResults] = RJSResultsFuncs; - s_objectTypeMethods[RJSTypeGet(realm::PropertyTypeArray)] = RJSListFuncs; -} - - (void)dealloc { for (auto item : _objects) { JSValueUnprotect(_context, item.second); @@ -115,7 +106,6 @@ static std::map s_objectTypeMethods; }; _requests["/call_method"] = [=](NSDictionary *dict) { return [self performObjectMethod:dict[@"name"] - withType:dict[@"type"] args:dict[@"arguments"] objectId:[dict[@"id"] unsignedLongValue]]; }; @@ -194,32 +184,25 @@ static std::map s_objectTypeMethods; return response ?: @{}; } -- (NSDictionary *)performObjectMethod:(NSString *)method - withType:(NSString *)type - args:(NSArray *)args - objectId:(RPCObjectID)oid { - const JSStaticFunction *methods = s_objectTypeMethods.at(type.UTF8String); +- (NSDictionary *)performObjectMethod:(NSString *)method args:(NSArray *)args objectId:(RPCObjectID)oid { + JSObjectRef object = _objects[oid]; + JSStringRef methodString = RJSStringForString(method.UTF8String); + JSObjectRef function = RJSValidatedObjectProperty(_context, object, methodString); + JSStringRelease(methodString); + NSUInteger argCount = args.count; JSValueRef argValues[argCount]; for (NSUInteger i = 0; i < argCount; i++) { argValues[i] = [self deserializeDictionaryValue:args[i]]; } - const char *name = method.UTF8String; - size_t index = 0; - while (methods[index].name) { - if (!strcmp(methods[index].name, name)) { - JSValueRef exception = NULL; - JSValueRef ret = methods[index].callAsFunction(_context, NULL, _objects[oid], argCount, argValues, &exception); - if (exception) { - return @{@"error": @(RJSStringForValue(_context, exception).c_str())}; - } - return @{@"result": [self resultForJSValue:ret]}; - } - index++; - } + JSValueRef exception = NULL; + JSValueRef result = JSObjectCallAsFunction(_context, function, object, argCount, argValues, &exception); - return @{@"error": [NSString stringWithFormat:@"Attempted to call invalid method (%@) on type: %@", method, type]}; + if (exception) { + return @{@"error": @(RJSStringForValue(_context, exception).c_str())}; + } + return @{@"result": [self resultForJSValue:result]}; } - (RPCObjectID)storeObject:(JSObjectRef)object {