diff --git a/React/Base/RCTBatchedBridge.m b/React/Base/RCTBatchedBridge.m index 9b77ad466..569c7f779 100644 --- a/React/Base/RCTBatchedBridge.m +++ b/React/Base/RCTBatchedBridge.m @@ -106,6 +106,13 @@ id RCTGetLatestExecutor(void) */ [self registerModules]; + /** + * If currently profiling, hook into the current instance + */ + if (RCTProfileIsProfiling()) { + RCTProfileHookModules(self); + } + /** * Start the application script */ @@ -364,8 +371,13 @@ RCT_NOT_IMPLEMENTED(-initWithBundleURL:(__unused NSURL *)bundleURL } moduleData.queue = nil; } + dispatch_group_notify(group, dispatch_get_main_queue(), ^{ [_javaScriptExecutor executeBlockOnJavaScriptQueue:^{ + if (RCTProfileIsProfiling()) { + RCTProfileUnhookModules(self); + } + [_jsDisplayLink invalidate]; _jsDisplayLink = nil; diff --git a/React/Base/RCTProfile.h b/React/Base/RCTProfile.h index 469a81552..66cf40bf4 100644 --- a/React/Base/RCTProfile.h +++ b/React/Base/RCTProfile.h @@ -103,6 +103,16 @@ RCT_EXTERN void RCTProfileImmediateEvent(NSString *, NSTimeInterval , NSString * RCTProfileEndEvent([NSString stringWithFormat:@"[%@ %@]", NSStringFromClass([self class]), NSStringFromSelector(_cmd)], category, arguments); \ } +/** + * Hook into a bridge instance to log all bridge module's method calls + */ +RCT_EXTERN void RCTProfileHookModules(RCTBridge *); + +/** + * Unhook from a given bridge instance's modules + */ +RCT_EXTERN void RCTProfileUnhookModules(RCTBridge *); + #else #define RCTProfileBeginFlowEvent() @@ -125,4 +135,7 @@ RCT_EXTERN void RCTProfileImmediateEvent(NSString *, NSTimeInterval , NSString * #define RCTProfileBlock(block, ...) block +#define RCTProfileHookModules(...) +#define RCTProfileUnhookModules(...) + #endif diff --git a/React/Base/RCTProfile.m b/React/Base/RCTProfile.m index 62a17fe7b..4eeaf3e9d 100644 --- a/React/Base/RCTProfile.m +++ b/React/Base/RCTProfile.m @@ -144,14 +144,17 @@ static IMP RCTProfileMsgForward(NSObject *self, SEL selector) return imp; } -static void RCTProfileHookModules(RCTBridge *); -static void RCTProfileHookModules(RCTBridge *bridge) +void RCTProfileHookModules(RCTBridge *bridge) { for (RCTModuleData *moduleData in [bridge valueForKey:@"_modules"]) { [moduleData dispatchBlock:^{ Class moduleClass = moduleData.cls; Class proxyClass = objc_allocateClassPair(moduleClass, RCTProfileProxyClassName(moduleClass), 0); + if (!proxyClass) { + return; + } + unsigned int methodCount; Method *methods = class_copyMethodList(moduleClass, &methodCount); for (NSUInteger i = 0; i < methodCount; i++) { @@ -185,7 +188,6 @@ static void RCTProfileHookModules(RCTBridge *bridge) } } -void RCTProfileUnhookModules(RCTBridge *); void RCTProfileUnhookModules(RCTBridge *bridge) { for (RCTModuleData *moduleData in [bridge valueForKey:@"_modules"]) { diff --git a/React/Views/RCTNavigator.m b/React/Views/RCTNavigator.m index 63e3d8023..ff91b0b54 100644 --- a/React/Views/RCTNavigator.m +++ b/React/Views/RCTNavigator.m @@ -436,7 +436,7 @@ RCT_NOT_IMPLEMENTED(-initWithCoder:(NSCoder *)aDecoder) */ - (UIView *)reactSuperview { - RCTAssert(self.superview != nil, @"put reactNavSuperviewLink back"); + RCTAssert(!_bridge.isValid || self.superview != nil, @"put reactNavSuperviewLink back"); return self.superview ? self.superview : self.reactNavSuperviewLink; }