diff --git a/packages/react-native/React/Base/RCTBridgeProxy.h b/packages/react-native/React/Base/RCTBridgeProxy.h index ef392aad70a..274e48c6514 100644 --- a/packages/react-native/React/Base/RCTBridgeProxy.h +++ b/packages/react-native/React/Base/RCTBridgeProxy.h @@ -14,6 +14,7 @@ NS_ASSUME_NONNULL_BEGIN @class RCTBundleManager; @class RCTCallableJSModules; @class RCTModuleRegistry; +@class RCTPerformanceLogger; @class RCTViewRegistry; @interface RCTBridgeProxy : NSProxy @@ -21,6 +22,13 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype)init NS_UNAVAILABLE; + (instancetype)new NS_UNAVAILABLE; +/** + * The performance logger for this React instance. In bridgeless mode it is + * injected by RCTInstance so that consumers reading `[bridge performanceLogger]` + * on `RCTJavaScriptDidLoadNotification` keep working; previously it returned nil. + */ +@property (nonatomic, strong, nullable) RCTPerformanceLogger *performanceLogger; + - (instancetype)initWithViewRegistry:(RCTViewRegistry *)viewRegistry moduleRegistry:(RCTModuleRegistry *)moduleRegistry bundleManager:(RCTBundleManager *)bundleManager diff --git a/packages/react-native/React/Base/RCTBridgeProxy.mm b/packages/react-native/React/Base/RCTBridgeProxy.mm index d2268f9768c..d09514d6e6a 100644 --- a/packages/react-native/React/Base/RCTBridgeProxy.mm +++ b/packages/react-native/React/Base/RCTBridgeProxy.mm @@ -41,6 +41,8 @@ @implementation RCTBridgeProxy { void *_runtime; } +@synthesize performanceLogger = _performanceLogger; + #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wobjc-designated-initializers" - (instancetype)initWithViewRegistry:(RCTViewRegistry *)viewRegistry @@ -213,12 +215,6 @@ - (BOOL)valid return NO; } -- (RCTPerformanceLogger *)performanceLogger -{ - [self logWarning:@"This method is not supported. Returning nil." cmd:_cmd]; - return nil; -} - - (void)reload { [self logError:@"Please use RCTReloadCommand instead. Nooping." cmd:_cmd]; diff --git a/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTInstance.mm b/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTInstance.mm index e744e34c727..86bd9e4ee04 100644 --- a/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTInstance.mm +++ b/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTInstance.mm @@ -115,6 +115,7 @@ @implementation RCTInstance { RCTPerformanceLogger *_performanceLogger; RCTDisplayLink *_displayLink; RCTTurboModuleManager *_turboModuleManager; + RCTBridgeProxy *_bridgeProxy; std::mutex _invalidationMutex; std::atomic _valid; RCTJSThreadManager *_jsThreadManager; @@ -351,6 +352,8 @@ - (void)_start runtime:_reactInstance->getJavaScriptContext() launchOptions:_launchOptions]; bridgeProxy.jsCallInvoker = jsCallInvoker; + bridgeProxy.performanceLogger = _performanceLogger; + _bridgeProxy = bridgeProxy; [RCTBridge setCurrentBridge:(RCTBridge *)bridgeProxy]; // Set up TurboModules @@ -606,8 +609,20 @@ - (void)_loadScriptFromSource:(RCTSource *)source waitUntilModuleSetupComplete(); } }; - auto afterLoad = [](jsi::Runtime &_) { + __weak __typeof(self) weakSelf = self; + auto afterLoad = [weakSelf](jsi::Runtime &) { [[NSNotificationCenter defaultCenter] postNotificationName:@"RCTInstanceDidLoadBundle" object:nil]; + __strong __typeof(weakSelf) strongSelf = weakSelf; + if (strongSelf) { + RCTBridgeProxy *bridgeProxy = strongSelf->_bridgeProxy; + // afterLoad runs on the JS thread; post on main like the legacy bridge so + // RCTJavaScriptDidLoadNotification observers aren't invoked off-main. + RCTExecuteOnMainQueue(^{ + [[NSNotificationCenter defaultCenter] postNotificationName:RCTJavaScriptDidLoadNotification + object:strongSelf + userInfo:bridgeProxy ? @{@"bridge" : bridgeProxy} : @{}]; + }); + } }; _reactInstance->loadScript(std::move(script), url, beforeLoad, afterLoad); } diff --git a/scripts/cxx-api/api-snapshots/ReactAppleDebugCxx.api b/scripts/cxx-api/api-snapshots/ReactAppleDebugCxx.api index ef3f2079032..50d3e417ca4 100644 --- a/scripts/cxx-api/api-snapshots/ReactAppleDebugCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactAppleDebugCxx.api @@ -725,6 +725,7 @@ interface RCTBridgeModuleDecorator : public NSObject { } interface RCTBridgeProxy : public NSProxy { + public @property (strong) RCTPerformanceLogger* performanceLogger; public virtual NSMethodSignature* methodSignatureForSelector:(SEL sel); public virtual id moduleForClass:(Class moduleClass); public virtual id moduleForName:lazilyLoadIfNecessary:(NSString* moduleName, BOOL lazilyLoad); diff --git a/scripts/cxx-api/api-snapshots/ReactAppleNewarchCxx.api b/scripts/cxx-api/api-snapshots/ReactAppleNewarchCxx.api index 951775f5a1b..14ab009b2bd 100644 --- a/scripts/cxx-api/api-snapshots/ReactAppleNewarchCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactAppleNewarchCxx.api @@ -723,6 +723,7 @@ interface RCTBridgeModuleDecorator : public NSObject { } interface RCTBridgeProxy : public NSProxy { + public @property (strong) RCTPerformanceLogger* performanceLogger; public virtual NSMethodSignature* methodSignatureForSelector:(SEL sel); public virtual id moduleForClass:(Class moduleClass); public virtual id moduleForName:lazilyLoadIfNecessary:(NSString* moduleName, BOOL lazilyLoad); diff --git a/scripts/cxx-api/api-snapshots/ReactAppleReleaseCxx.api b/scripts/cxx-api/api-snapshots/ReactAppleReleaseCxx.api index 5226973262d..018321623dc 100644 --- a/scripts/cxx-api/api-snapshots/ReactAppleReleaseCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactAppleReleaseCxx.api @@ -725,6 +725,7 @@ interface RCTBridgeModuleDecorator : public NSObject { } interface RCTBridgeProxy : public NSProxy { + public @property (strong) RCTPerformanceLogger* performanceLogger; public virtual NSMethodSignature* methodSignatureForSelector:(SEL sel); public virtual id moduleForClass:(Class moduleClass); public virtual id moduleForName:lazilyLoadIfNecessary:(NSString* moduleName, BOOL lazilyLoad);