diff --git a/Examples/UIExplorer/UIExplorerUnitTests/RCTBridgeTests.m b/Examples/UIExplorer/UIExplorerUnitTests/RCTBridgeTests.m index 7802f4ad1..a3c4c4354 100644 --- a/Examples/UIExplorer/UIExplorerUnitTests/RCTBridgeTests.m +++ b/Examples/UIExplorer/UIExplorerUnitTests/RCTBridgeTests.m @@ -136,25 +136,19 @@ _Pragma("clang diagnostic pop") NSString *injectedStuff; RUN_RUNLOOP_WHILE(!(injectedStuff = executor.injectedStuff[@"__fbBatchedBridgeConfig"])); - __block NSNumber *testModuleID = nil; - __block NSDictionary *testConstants = nil; - __block NSNumber *testMethodID = nil; - - NSArray *remoteModuleConfig = RCTJSONParse(injectedStuff, NULL)[@"remoteModuleConfig"]; - [remoteModuleConfig enumerateObjectsUsingBlock:^(id moduleConfig, NSUInteger i, BOOL *stop) { - if ([moduleConfig isKindOfClass:[NSArray class]] && [moduleConfig[0] isEqualToString:@"TestModule"]) { - testModuleID = @(i); - testConstants = moduleConfig[1]; - testMethodID = @([moduleConfig[2] indexOfObject:@"testMethod"]); - *stop = YES; - } - }]; + NSDictionary *moduleConfig = RCTJSONParse(injectedStuff, NULL); + NSDictionary *remoteModuleConfig = moduleConfig[@"remoteModuleConfig"]; + NSDictionary *testModuleConfig = remoteModuleConfig[@"TestModule"]; + NSDictionary *constants = testModuleConfig[@"constants"]; + NSDictionary *methods = testModuleConfig[@"methods"]; + XCTAssertNotNil(moduleConfig); XCTAssertNotNil(remoteModuleConfig); - XCTAssertNotNil(testModuleID); - XCTAssertNotNil(testConstants); - XCTAssertEqualObjects(testConstants[@"eleventyMillion"], @42); - XCTAssertNotNil(testMethodID); + XCTAssertNotNil(testModuleConfig); + XCTAssertNotNil(constants); + XCTAssertEqualObjects(constants[@"eleventyMillion"], @42); + XCTAssertNotNil(methods); + XCTAssertNotNil(methods[@"testMethod"]); } - (void)testCallNativeMethod @@ -164,19 +158,13 @@ _Pragma("clang diagnostic pop") NSString *injectedStuff; RUN_RUNLOOP_WHILE(!(injectedStuff = executor.injectedStuff[@"__fbBatchedBridgeConfig"])); - __block NSNumber *testModuleID = nil; - __block NSDictionary *testConstants = nil; - __block NSNumber *testMethodID = nil; - - NSArray *remoteModuleConfig = RCTJSONParse(injectedStuff, NULL)[@"remoteModuleConfig"]; - [remoteModuleConfig enumerateObjectsUsingBlock:^(id moduleConfig, NSUInteger i, __unused BOOL *stop) { - if ([moduleConfig isKindOfClass:[NSArray class]] && [moduleConfig[0] isEqualToString:@"TestModule"]) { - testModuleID = @(i); - testConstants = moduleConfig[1]; - testMethodID = @([moduleConfig[2] indexOfObject:@"testMethod"]); - *stop = YES; - } - }]; + NSDictionary *moduleConfig = RCTJSONParse(injectedStuff, NULL); + NSDictionary *remoteModuleConfig = moduleConfig[@"remoteModuleConfig"]; + NSDictionary *testModuleConfig = remoteModuleConfig[@"TestModule"]; + NSNumber *testModuleID = testModuleConfig[@"moduleID"]; + NSDictionary *methods = testModuleConfig[@"methods"]; + NSDictionary *testMethod = methods[@"testMethod"]; + NSNumber *testMethodID = testMethod[@"methodID"]; NSArray *args = @[@1234, @5678, @"stringy", @{@"a": @1}, @42]; NSArray *buffer = @[@[testModuleID], @[testMethodID], @[args], @[], @1234567]; diff --git a/Libraries/Utilities/MessageQueue.js b/Libraries/Utilities/MessageQueue.js index b93885d0e..d37881d91 100644 --- a/Libraries/Utilities/MessageQueue.js +++ b/Libraries/Utilities/MessageQueue.js @@ -30,6 +30,7 @@ let MIN_TIME_BETWEEN_FLUSHES_MS = 5; let SPY_MODE = false; let MethodTypes = keyMirror({ + local: null, remote: null, remoteAsync: null, }); @@ -61,18 +62,15 @@ class MessageQueue { 'flushedQueue', ].forEach((fn) => this[fn] = this[fn].bind(this)); - let modulesConfig = this._genModulesConfig(remoteModules); - this._genModules(modulesConfig); + this._genModules(remoteModules); localModules && this._genLookupTables( - this._genModulesConfig(localModules),this._moduleTable, this._methodTable - ); + localModules, this._moduleTable, this._methodTable); this._debugInfo = {}; this._remoteModuleTable = {}; this._remoteMethodTable = {}; this._genLookupTables( - modulesConfig, this._remoteModuleTable, this._remoteMethodTable - ); + remoteModules, this._remoteModuleTable, this._remoteMethodTable); } /** @@ -184,118 +182,43 @@ class MessageQueue { /** * Private helper methods */ - - /** - * Converts the old, object-based module structure to the new - * array-based structure. TODO (t8823865) Removed this - * functin once Android has been updated. - */ - _genModulesConfig(modules /* array or object */) { - if (Array.isArray(modules)) { - return modules; - } else { - let moduleArray = []; - let moduleNames = Object.keys(modules); - for (var i = 0, l = moduleNames.length; i < l; i++) { - let moduleName = moduleNames[i]; - let moduleConfig = modules[moduleName]; - let module = [moduleName]; - if (moduleConfig.constants) { - module.push(moduleConfig.constants); - } - let methodsConfig = moduleConfig.methods; - if (methodsConfig) { - let methods = []; - let asyncMethods = []; - let methodNames = Object.keys(methodsConfig); - for (var j = 0, ll = methodNames.length; j < ll; j++) { - let methodName = methodNames[j]; - let methodConfig = methodsConfig[methodName]; - methods[methodConfig.methodID] = methodName; - if (methodConfig.type === MethodTypes.remoteAsync) { - asyncMethods.push(methodConfig.methodID); - } - } - if (methods.length) { - module.push(methods); - if (asyncMethods.length) { - module.push(asyncMethods); - } - } - } - moduleArray[moduleConfig.moduleID] = module; - } - return moduleArray; - } - } - - _genLookupTables(modulesConfig, moduleTable, methodTable) { - for (var moduleID = 0, l = modulesConfig.length; moduleID < l; moduleID++) { - let module = modulesConfig[moduleID]; - if (!module) { - continue; - } - let moduleName = module[0]; + _genLookupTables(localModules, moduleTable, methodTable) { + let moduleNames = Object.keys(localModules); + for (var i = 0, l = moduleNames.length; i < l; i++) { + let moduleName = moduleNames[i]; + let methods = localModules[moduleName].methods || {}; + let moduleID = localModules[moduleName].moduleID; moduleTable[moduleID] = moduleName; methodTable[moduleID] = {}; - if (module.length > 1) { - let methodsIndex = 1; - if (!Array.isArray(module[1])) { - methodsIndex = 2; - } - if (module.length > methodsIndex) { - let methods = module[methodsIndex]; - for (var methodID = 0, ll = methods.length; methodID < ll; methodID++) { - methodTable[moduleID][methodID] = methods[methodID]; - } - } + + let methodNames = Object.keys(methods); + for (var j = 0, k = methodNames.length; j < k; j++) { + let methodName = methodNames[j]; + let methodConfig = methods[methodName]; + methodTable[moduleID][methodConfig.methodID] = methodName; } } } _genModules(remoteModules) { - for (var i = 0, l = remoteModules.length; i < l; i++) { - let module = remoteModules[i]; - if (!module) { - continue; - } - let moduleName = module[0]; - let constants = null; - let methods = null; - let asyncMethods = null; - if (module.length > 0) { - let methodsIndex = 1; - if (!Array.isArray(module[1])) { - constants = module[1]; - methodsIndex = 2; - } - if (module.length > methodsIndex) { - methods = module[methodsIndex]; - if (module.length > methodsIndex) { - asyncMethods = module[methodsIndex]; - } - } - } - let moduleConfig = { - moduleID: i, - constants, - methods, - asyncMethods, - }; + let moduleNames = Object.keys(remoteModules); + for (var i = 0, l = moduleNames.length; i < l; i++) { + let moduleName = moduleNames[i]; + let moduleConfig = remoteModules[moduleName]; this.RemoteModules[moduleName] = this._genModule({}, moduleConfig); } } _genModule(module, moduleConfig) { - let methods = moduleConfig.methods || []; - let asyncMethods = moduleConfig.asyncMethods || []; - for (var methodID = 0, l = methods.length; methodID < l; methodID++) { - let methodName = methods[methodID]; - let isAsync = (asyncMethods.indexOf(methodID) !== -1); + let methods = moduleConfig.methods || {}; + let methodNames = Object.keys(methods); + for (var i = 0, l = methodNames.length; i < l; i++) { + let methodName = methodNames[i]; + let methodConfig = methods[methodName]; module[methodName] = this._genMethod( moduleConfig.moduleID, - methodID, - isAsync ? MethodTypes.remoteAsync : MethodTypes.remote + methodConfig.methodID, + methodConfig.type || MethodTypes.remote ); } Object.assign(module, moduleConfig.constants); @@ -303,6 +226,10 @@ class MessageQueue { } _genMethod(module, method, type) { + if (type === MethodTypes.local) { + return null; + } + let fn = null; let self = this; if (type === MethodTypes.remoteAsync) { diff --git a/React/Base/RCTBatchedBridge.m b/React/Base/RCTBatchedBridge.m index 1a9e9d299..d6cc0c249 100644 --- a/React/Base/RCTBatchedBridge.m +++ b/React/Base/RCTBatchedBridge.m @@ -308,9 +308,12 @@ RCT_EXTERN NSArray *RCTGetModuleClasses(void); - (NSString *)moduleConfig { - NSMutableArray *config = [NSMutableArray new]; + NSMutableDictionary *config = [NSMutableDictionary new]; for (RCTModuleData *moduleData in _moduleDataByID) { - [config addObject:moduleData.config]; + NSDictionary *moduleConfig = moduleData.config; + if (moduleConfig) { + config[moduleData.name] = moduleConfig; + } if ([moduleData.instance conformsToProtocol:@protocol(RCTFrameUpdateObserver)]) { [_frameUpdateObservers addObject:moduleData]; diff --git a/React/Base/RCTModuleData.h b/React/Base/RCTModuleData.h index d01ccbdd7..310dd2fc7 100644 --- a/React/Base/RCTModuleData.h +++ b/React/Base/RCTModuleData.h @@ -20,7 +20,7 @@ @property (nonatomic, strong, readonly) Class moduleClass; @property (nonatomic, copy, readonly) NSString *name; @property (nonatomic, copy, readonly) NSArray *methods; -@property (nonatomic, copy, readonly) NSArray *config; +@property (nonatomic, copy, readonly) NSDictionary *config; @property (nonatomic, strong) dispatch_queue_t queue; diff --git a/React/Base/RCTModuleData.m b/React/Base/RCTModuleData.m index 9dc96c7e6..a95d79dd6 100644 --- a/React/Base/RCTModuleData.m +++ b/React/Base/RCTModuleData.m @@ -12,7 +12,6 @@ #import "RCTBridge.h" #import "RCTModuleMethod.h" #import "RCTLog.h" -#import "RCTUtils.h" @implementation RCTModuleData { @@ -80,36 +79,37 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init); return _methods; } -- (NSArray *)config +- (NSDictionary *)config { if (_constants.count == 0 && self.methods.count == 0) { - return (id)kCFNull; // Nothing to export + return nil; // Nothing to export } - NSMutableArray *methods = self.methods.count ? [NSMutableArray new] : nil; - NSMutableArray *asyncMethods = nil; - for (id method in self.methods) { - [methods addObject:method.JSMethodName]; + NSMutableDictionary *config = [NSMutableDictionary new]; + config[@"moduleID"] = _moduleID; + + if (_constants) { + config[@"constants"] = _constants; + } + + NSMutableDictionary *methodconfig = [NSMutableDictionary new]; + [self.methods enumerateObjectsUsingBlock:^(id method, NSUInteger idx, __unused BOOL *stop) { if (method.functionType == RCTFunctionTypePromise) { - if (!asyncMethods) { - asyncMethods = [NSMutableArray new]; - } - [asyncMethods addObject:@(methods.count)]; + methodconfig[method.JSMethodName] = @{ + @"methodID": @(idx), + @"type": @"remoteAsync", + }; + } else { + methodconfig[method.JSMethodName] = @{ + @"methodID": @(idx), + }; } + }]; + if (methodconfig.count) { + config[@"methods"] = [methodconfig copy]; } - NSMutableArray *config = [NSMutableArray new]; - [config addObject:_name]; - if (_constants.count) { - [config addObject:_constants]; - } - if (methods) { - [config addObject:methods]; - if (asyncMethods) { - [config addObject:asyncMethods]; - } - } - return config; + return [config copy]; } - (dispatch_queue_t)queue diff --git a/React/Base/RCTModuleMethod.h b/React/Base/RCTModuleMethod.h index f450c412c..ff5c1cda6 100644 --- a/React/Base/RCTModuleMethod.h +++ b/React/Base/RCTModuleMethod.h @@ -31,6 +31,7 @@ typedef NS_ENUM(NSUInteger, RCTNullability) { @property (nonatomic, readonly) Class moduleClass; @property (nonatomic, readonly) SEL selector; +@property (nonatomic, readonly) RCTFunctionType functionType; - (instancetype)initWithObjCMethodName:(NSString *)objCMethodName JSMethodName:(NSString *)JSMethodName diff --git a/React/Base/RCTModuleMethod.m b/React/Base/RCTModuleMethod.m index efc0076ef..e684f79a8 100644 --- a/React/Base/RCTModuleMethod.m +++ b/React/Base/RCTModuleMethod.m @@ -54,7 +54,6 @@ typedef BOOL (^RCTArgumentBlock)(RCTBridge *, NSUInteger, id); } @synthesize JSMethodName = _JSMethodName; -@synthesize functionType = _functionType; static void RCTLogArgumentError(RCTModuleMethod *method, NSUInteger index, id valueOrType, const char *issue)