diff --git a/React/Base/RCTBatchedBridge.m b/React/Base/RCTBatchedBridge.m index 7975b5e7c..a38476f4d 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 */ @@ -361,6 +368,7 @@ RCT_NOT_IMPLEMENTED(-initWithBundleURL:(__unused NSURL *)bundleURL } moduleData.queue = nil; } + dispatch_group_notify(group, dispatch_get_main_queue(), ^{ [_javaScriptExecutor executeBlockOnJavaScriptQueue:^{ [_jsDisplayLink invalidate]; @@ -368,11 +376,15 @@ RCT_NOT_IMPLEMENTED(-initWithBundleURL:(__unused NSURL *)bundleURL [_javaScriptExecutor invalidate]; _javaScriptExecutor = nil; - }]; - _modules = nil; - _modulesByName = nil; - _frameUpdateObservers = nil; + if (RCTProfileIsProfiling()) { + RCTProfileUnhookModules(self); + } + _modules = nil; + _modulesByName = nil; + _frameUpdateObservers = 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..5174af4f1 100644 --- a/React/Base/RCTProfile.m +++ b/React/Base/RCTProfile.m @@ -124,6 +124,8 @@ static void RCTProfileForwardInvocation(NSObject *self, __unused SEL cmd, NSInvo RCTProfileBeginEvent(); [invocation invoke]; RCTProfileEndEvent(name, @"objc_call,modules,auto", nil); + } else if ([self respondsToSelector:invocation.selector]) { + [invocation invoke]; } else { // Use original selector to don't change error message [self doesNotRecognizeSelector:invocation.selector]; @@ -144,14 +146,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,20 +190,17 @@ static void RCTProfileHookModules(RCTBridge *bridge) } } -void RCTProfileUnhookModules(RCTBridge *); void RCTProfileUnhookModules(RCTBridge *bridge) { - for (RCTModuleData *moduleData in [bridge valueForKey:@"_modules"]) { - [moduleData dispatchBlock:^{ - RCTProfileLock( - Class proxyClass = object_getClass(moduleData.instance); - if (moduleData.cls != proxyClass) { - object_setClass(moduleData.instance, moduleData.cls); - objc_disposeClassPair(proxyClass); - } - ); - }]; - }; + RCTProfileLock( + for (RCTModuleData *moduleData in [bridge valueForKey:@"_modules"]) { + Class proxyClass = object_getClass(moduleData.instance); + if (moduleData.cls != proxyClass) { + object_setClass(moduleData.instance, moduleData.cls); + objc_disposeClassPair(proxyClass); + } + }; + ); } 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; }