diff --git a/React/Base/RCTBridge.m b/React/Base/RCTBridge.m index b9cee66c3159e3..6e76a173700f3a 100644 --- a/React/Base/RCTBridge.m +++ b/React/Base/RCTBridge.m @@ -224,12 +224,19 @@ @implementation RCTModuleMethod return methodName; } -- (instancetype)initWithMethodName:(NSString *)methodName - JSMethodName:(NSString *)JSMethodName +- (instancetype)initLegacyWithMethodName:(NSString *)methodName + JSMethodName:(NSString *)JSMethodName +{ + return [self initWithReactMethodName:methodName objCMethodName:methodName JSMethodName:JSMethodName]; +} + +- (instancetype)initWithReactMethodName:(NSString *)reactMethodName + objCMethodName:(NSString *)objCMethodName + JSMethodName:(NSString *)JSMethodName { if ((self = [super init])) { - _methodName = methodName; - NSArray *parts = [[methodName substringWithRange:(NSRange){2, methodName.length - 3}] componentsSeparatedByString:@" "]; + _methodName = reactMethodName; + NSArray *parts = [[reactMethodName substringWithRange:(NSRange){2, reactMethodName.length - 3}] componentsSeparatedByString:@" "]; // Parse class and method _moduleClassName = parts[0]; @@ -243,7 +250,7 @@ - (instancetype)initWithMethodName:(NSString *)methodName // New format NSString *selectorString = [parts[1] substringFromIndex:14]; _selector = NSSelectorFromString(selectorString); - _JSMethodName = RCTStringUpToFirstArgument(selectorString); + _JSMethodName = JSMethodName ?: RCTStringUpToFirstArgument(selectorString); static NSRegularExpression *regExp; if (!regExp) { @@ -255,8 +262,8 @@ - (instancetype)initWithMethodName:(NSString *)methodName } argumentNames = [NSMutableArray array]; - [regExp enumerateMatchesInString:JSMethodName options:0 range:NSMakeRange(0, JSMethodName.length) usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) { - NSString *argumentName = [JSMethodName substringWithRange:[result rangeAtIndex:1]]; + [regExp enumerateMatchesInString:objCMethodName options:0 range:NSMakeRange(0, objCMethodName.length) usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) { + NSString *argumentName = [objCMethodName substringWithRange:[result rangeAtIndex:1]]; [(NSMutableArray *)argumentNames addObject:argumentName]; }]; } else { @@ -267,14 +274,14 @@ - (instancetype)initWithMethodName:(NSString *)methodName } // Extract class and method details - _isClassMethod = [methodName characterAtIndex:0] == '+'; + _isClassMethod = [reactMethodName characterAtIndex:0] == '+'; _moduleClass = NSClassFromString(_moduleClassName); #if DEBUG // Sanity check RCTAssert([_moduleClass conformsToProtocol:@protocol(RCTBridgeModule)], @"You are attempting to export the method %@, but %@ does not \ - conform to the RCTBridgeModule Protocol", methodName, _moduleClassName); + conform to the RCTBridgeModule Protocol", objCMethodName, _moduleClassName); #endif // Get method signature @@ -493,15 +500,21 @@ - (NSString *)description for (RCTHeaderValue addr = section->offset; addr < section->offset + section->size; - addr += sizeof(const char **) * 2) { + addr += sizeof(const char **) * 3) { // Get data entry const char **entries = (const char **)(mach_header + addr); // Create method - RCTModuleMethod *moduleMethod = - [[RCTModuleMethod alloc] initWithMethodName:@(entries[0]) - JSMethodName:strlen(entries[1]) ? @(entries[1]) : nil]; + RCTModuleMethod *moduleMethod; + if (entries[2] == NULL) { + moduleMethod = [[RCTModuleMethod alloc] initLegacyWithMethodName:@(entries[0]) + JSMethodName:strlen(entries[1]) ? @(entries[1]) : nil]; + } else { + moduleMethod = [[RCTModuleMethod alloc] initWithReactMethodName:@(entries[0]) + objCMethodName:strlen(entries[1]) ? @(entries[1]) : nil + JSMethodName:strlen(entries[2]) ? @(entries[2]) : nil]; + } // Cache method NSArray *methods = methodsByModuleClassName[moduleMethod.moduleClassName]; diff --git a/React/Base/RCTBridgeModule.h b/React/Base/RCTBridgeModule.h index 7fc526e35e6682..e9755594f73c69 100644 --- a/React/Base/RCTBridgeModule.h +++ b/React/Base/RCTBridgeModule.h @@ -51,13 +51,14 @@ typedef void (^RCTResponseSenderBlock)(NSArray *response); #define RCT_EXPORT(js_name) \ _Pragma("message(\"RCT_EXPORT is deprecated. Use RCT_EXPORT_METHOD instead.\")") \ __attribute__((used, section("__DATA,RCTExport"))) \ - static const char *__rct_export_entry__[] = { __func__, #js_name } + __attribute__((__aligned__(1))) \ + static const char *__rct_export_entry__[] = { __func__, #js_name, NULL } /** * Wrap the parameter line of your method implementation with this macro to - * expose it to JS. Unlike the deprecated RCT_EXPORT, this macro does not take - * a js_name argument and the exposed method will match the first part of the - * Objective-C method selector name (up to the first colon). + * expose it to JS. By default the exposed method will match the first part of + * the Objective-C method selector name (up to the first colon). Use + * RCT_REMAP_METHOD to specify the JS name of the method. * * For example, in MyClass.m: * @@ -74,9 +75,21 @@ typedef void (^RCTResponseSenderBlock)(NSArray *response); * and is exposed to JavaScript as `NativeModules.ModuleName.doSomething`. */ #define RCT_EXPORT_METHOD(method) \ + RCT_REMAP_METHOD(, method) + +/** + * Similar to RCT_EXPORT_METHOD but lets you set the JS name of the exported + * method. Example usage: + * + * RCT_REMAP_METHOD(executeQueryWithParameters, + * executeQuery:(NSString *)query parameters:(NSDictionary *)parameters) + * {} + */ +#define RCT_REMAP_METHOD(js_name, method) \ - (void)__rct_export__##method { \ __attribute__((used, section("__DATA,RCTExport"))) \ - static const char *__rct_export_entry__[] = { __func__, #method }; \ + __attribute__((__aligned__(1))) \ + static const char *__rct_export_entry__[] = { __func__, #method, #js_name }; \ } \ - (void)method