/** | |
* This function parses the exported methods inside RCTBridgeModules and | |
* generates an array of arrays of RCTModuleMethod objects, keyed | |
* by module index. | |
*/ | |
static RCTSparseArray *RCTExportedMethodsByModuleID(void) | |
{ | |
static RCTSparseArray *methodsByModuleID; | |
static dispatch_once_t onceToken; | |
dispatch_once(&onceToken, ^{ | |
Dl_info info; | |
dladdr(&RCTExportedMethodsByModuleID, &info); | |
#ifdef __LP64__ | |
typedef uint64_t RCTExportValue; | |
typedef struct section_64 RCTExportSection; | |
#define RCTGetSectByNameFromHeader getsectbynamefromheader_64 | |
#else | |
typedef uint32_t RCTExportValue; | |
typedef struct section RCTExportSection; | |
#define RCTGetSectByNameFromHeader getsectbynamefromheader | |
#endif | |
const RCTExportValue mach_header = (RCTExportValue)info.dli_fbase; | |
const RCTExportSection *section = RCTGetSectByNameFromHeader((void *)mach_header, "__DATA", "RCTExport"); | |
if (section == NULL) { | |
return; | |
} | |
NSArray *classes = RCTBridgeModuleClassesByModuleID(); | |
NSMutableDictionary *methodsByModuleClassName = [NSMutableDictionary dictionaryWithCapacity:[classes count]]; | |
for (RCTExportValue addr = section->offset; | |
addr < section->offset + section->size; | |
addr += sizeof(const char **) * 2) { | |
// 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]; | |
// Cache method | |
NSArray *methods = methodsByModuleClassName[moduleMethod.moduleClassName]; | |
methodsByModuleClassName[moduleMethod.moduleClassName] = | |
methods ? [methods arrayByAddingObject:moduleMethod] : @[moduleMethod]; | |
} | |
methodsByModuleID = [[RCTSparseArray alloc] initWithCapacity:[classes count]]; | |
[classes enumerateObjectsUsingBlock:^(Class moduleClass, NSUInteger moduleID, BOOL *stop) { | |
methodsByModuleID[moduleID] = methodsByModuleClassName[NSStringFromClass(moduleClass)]; | |
}]; | |
}); | |
return methodsByModuleID; | |
} |