Skip to content

Commit

Permalink
Verify exported modules only once to support dynamic context in DEBUG…
Browse files Browse the repository at this point in the history
…-mode

Summary:
**Motivation:** We have a project that dynamically changes classes in runtime. This component is initialised within the React Native context. Therefor `RCTBatchedBridge` copies the classes before changes are made to them. While React Native is running, changes are made to the classes dynamically. When the project reloads the `RCTBatchedBridge`, it now has an invalid list of classes containing trash pointers. This causes the project to crash on https://github.com/facebook/react-native/blob/master/React/Base/RCTBatchedBridge.m#L288 with EXC_BAD_ACCESS in the DEBUG-mode.

**Solution:** Copy the class list on each reload to get the current state. Since this is only a DEBUG-feature the overhead of this should not be a major issue.
Closes #9541

Differential Revision: D3775012

Pulled By: javache

fbshipit-source-id: d55fa0742ca100d8018c73080230cf718aa5a7e9
  • Loading branch information
kasper authored and Facebook Github Bot 1 committed Aug 29, 2016
1 parent 3fb7669 commit 101190f
Showing 1 changed file with 23 additions and 23 deletions.
46 changes: 23 additions & 23 deletions React/Base/RCTBatchedBridge.m
Original file line number Diff line number Diff line change
Expand Up @@ -266,38 +266,38 @@ - (void)initModulesWithDispatchGroup:(dispatch_group_t)dispatchGroup
extraModules = self.moduleProvider();
}

if (RCT_DEBUG && !RCTRunningInTestEnvironment()) {
// Check for unexported modules
static Class *classes;
static unsigned int classCount;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
if (RCT_DEBUG && !RCTRunningInTestEnvironment()) {
// Check for unexported modules
Class *classes;
unsigned int classCount;
classes = objc_copyClassList(&classCount);
});

NSMutableSet *moduleClasses = [NSMutableSet new];
[moduleClasses addObjectsFromArray:RCTGetModuleClasses()];
[moduleClasses addObjectsFromArray:[extraModules valueForKeyPath:@"class"]];
NSMutableSet *moduleClasses = [NSMutableSet new];
[moduleClasses addObjectsFromArray:RCTGetModuleClasses()];
[moduleClasses addObjectsFromArray:[extraModules valueForKeyPath:@"class"]];

for (unsigned int i = 0; i < classCount; i++)
{
Class cls = classes[i];
Class superclass = cls;
while (superclass)
for (unsigned int i = 0; i < classCount; i++)
{
if (class_conformsToProtocol(superclass, @protocol(RCTBridgeModule)))
Class cls = classes[i];
Class superclass = cls;
while (superclass)
{
if (![moduleClasses containsObject:cls] &&
![cls respondsToSelector:@selector(moduleName)]) {
RCTLogWarn(@"Class %@ was not exported. Did you forget to use "
"RCT_EXPORT_MODULE()?", cls);
if (class_conformsToProtocol(superclass, @protocol(RCTBridgeModule)))
{
if (![moduleClasses containsObject:cls] &&
![cls respondsToSelector:@selector(moduleName)]) {
RCTLogWarn(@"Class %@ was not exported. Did you forget to use "
"RCT_EXPORT_MODULE()?", cls);
}
break;
}
break;
superclass = class_getSuperclass(superclass);
}
superclass = class_getSuperclass(superclass);
}
}
}
});

NSMutableArray<Class> *moduleClassesByID = [NSMutableArray new];
NSMutableArray<RCTModuleData *> *moduleDataByID = [NSMutableArray new];
Expand Down

0 comments on commit 101190f

Please sign in to comment.