From 5f84d7338f42fe9b1d5bf2a9b1c8321b59551f15 Mon Sep 17 00:00:00 2001 From: Ramanpreet Nara Date: Wed, 5 Jul 2023 15:00:36 -0700 Subject: [PATCH] Bridgeless mode: Attach bridge/bridgeless apis to interop modules (#38202) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/38202 ## Context Native modules can synthesize these bridge/bridgeless-agnostic abstractions: - viewRegistry_DEPRECATED - bundleManager - callableJSModules - moduleRegistry ## The Problem The TurboModule interop layer wasn't attaching these abstractions to legacy modules. ## The Issue In Bridgeless mode, the React instance attaches these abstractions to **all** modules, by implementing TurboModuleManagerDelegate. But, the TurboModuleManager creates legacy modules without calling into the TurboModuleManagerDelegate. So, legacy modules never had these abstractions attached. ## The Fix Move the attachment logic to within TurboModuleManager. Changelog: [Internal] Reviewed By: dmytrorykun Differential Revision: D47074304 fbshipit-source-id: 87408106c00db8011740068ac0bd7dacd6b5ff81 --- packages/react-native/React/Base/RCTBridge.h | 3 +- packages/react-native/React/Base/RCTBridge.m | 4 +- .../React/CxxBridge/RCTCxxBridge.mm | 14 +++---- .../platform/ios/Core/RCTInstance.mm | 40 +++++++++---------- .../ios/ReactCommon/RCTTurboModuleManager.h | 9 +++-- .../ios/ReactCommon/RCTTurboModuleManager.mm | 31 ++++++++++++-- 6 files changed, 62 insertions(+), 39 deletions(-) diff --git a/packages/react-native/React/Base/RCTBridge.h b/packages/react-native/React/Base/RCTBridge.h index 92545c4317ebe5..7c178b160f4a4d 100644 --- a/packages/react-native/React/Base/RCTBridge.h +++ b/packages/react-native/React/Base/RCTBridge.h @@ -9,6 +9,7 @@ #import #import +#import #import #import #import @@ -149,7 +150,7 @@ RCT_EXTERN void RCTSetTurboModuleCleanupMode(RCTTurboModuleCleanupMode mode); * It allows the bridge to attach properties to ObjC modules that give those modules * access to Bridge APIs. */ -- (void)attachBridgeAPIsToObjCModule:(id)module; +- (RCTBridgeModuleDecorator *)bridgeModuleDecorator; /** * Convenience method for retrieving all modules conforming to a given protocol. diff --git a/packages/react-native/React/Base/RCTBridge.m b/packages/react-native/React/Base/RCTBridge.m index b8300f27f073b8..62533221222ad4 100644 --- a/packages/react-native/React/Base/RCTBridge.m +++ b/packages/react-native/React/Base/RCTBridge.m @@ -226,9 +226,9 @@ - (void)setRCTTurboModuleRegistry:(id)turboModuleRegistr [self.batchedBridge setRCTTurboModuleRegistry:turboModuleRegistry]; } -- (void)attachBridgeAPIsToObjCModule:(id)module +- (RCTBridgeModuleDecorator *)bridgeModuleDecorator { - [self.batchedBridge attachBridgeAPIsToObjCModule:module]; + return [self.batchedBridge bridgeModuleDecorator]; } - (void)didReceiveReloadCommand diff --git a/packages/react-native/React/CxxBridge/RCTCxxBridge.mm b/packages/react-native/React/CxxBridge/RCTCxxBridge.mm index a23413895768c1..23f8be7b384086 100644 --- a/packages/react-native/React/CxxBridge/RCTCxxBridge.mm +++ b/packages/react-native/React/CxxBridge/RCTCxxBridge.mm @@ -245,14 +245,12 @@ - (void)setRCTTurboModuleRegistry:(id)turboModuleRegistr [_objCModuleRegistry setTurboModuleRegistry:_turboModuleRegistry]; } -- (void)attachBridgeAPIsToObjCModule:(id)module -{ - RCTBridgeModuleDecorator *bridgeModuleDecorator = - [[RCTBridgeModuleDecorator alloc] initWithViewRegistry:_viewRegistry_DEPRECATED - moduleRegistry:_objCModuleRegistry - bundleManager:_bundleManager - callableJSModules:_callableJSModules]; - [bridgeModuleDecorator attachInteropAPIsToModule:module]; +- (RCTBridgeModuleDecorator *)bridgeModuleDecorator +{ + return [[RCTBridgeModuleDecorator alloc] initWithViewRegistry:_viewRegistry_DEPRECATED + moduleRegistry:_objCModuleRegistry + bundleManager:_bundleManager + callableJSModules:_callableJSModules]; } - (std::shared_ptr)jsMessageThread diff --git a/packages/react-native/ReactCommon/react/bridgeless/platform/ios/Core/RCTInstance.mm b/packages/react-native/ReactCommon/react/bridgeless/platform/ios/Core/RCTInstance.mm index 4dd5528934dd04..55ecef1552e5aa 100644 --- a/packages/react-native/ReactCommon/react/bridgeless/platform/ios/Core/RCTInstance.mm +++ b/packages/react-native/ReactCommon/react/bridgeless/platform/ios/Core/RCTInstance.mm @@ -224,26 +224,26 @@ - (void)_start RuntimeExecutor bufferedRuntimeExecutor = _reactInstance->getBufferedRuntimeExecutor(); timerManager->setRuntimeExecutor(bufferedRuntimeExecutor); + RCTBridgeProxy *bridgeProxy = RCTTurboModuleInteropEnabled() && RCTTurboModuleInteropBridgeProxyEnabled() + ? [[RCTBridgeProxy alloc] + initWithViewRegistry:_bridgeModuleDecorator.viewRegistry_DEPRECATED + moduleRegistry:_bridgeModuleDecorator.moduleRegistry + bundleManager:_bridgeModuleDecorator.bundleManager + callableJSModules:_bridgeModuleDecorator.callableJSModules + dispatchToJSThread:^(dispatch_block_t block) { + __strong __typeof(self) strongSelf = weakSelf; + if (strongSelf && strongSelf->_valid) { + strongSelf->_reactInstance->getBufferedRuntimeExecutor()([=](jsi::Runtime &runtime) { block(); }); + } + }] + : nil; + // Set up TurboModules - _turboModuleManager = - [[RCTTurboModuleManager alloc] initWithBridge:nil - delegate:self - jsInvoker:std::make_shared(bufferedRuntimeExecutor)]; - - if (RCTTurboModuleInteropEnabled() && RCTTurboModuleInteropBridgeProxyEnabled()) { - RCTBridgeProxy *bridgeProxy = [[RCTBridgeProxy alloc] - initWithViewRegistry:_bridgeModuleDecorator.viewRegistry_DEPRECATED - moduleRegistry:_bridgeModuleDecorator.moduleRegistry - bundleManager:_bridgeModuleDecorator.bundleManager - callableJSModules:_bridgeModuleDecorator.callableJSModules - dispatchToJSThread:^(dispatch_block_t block) { - __strong __typeof(self) strongSelf = weakSelf; - if (strongSelf && strongSelf->_valid) { - strongSelf->_reactInstance->getBufferedRuntimeExecutor()([=](jsi::Runtime &runtime) { block(); }); - } - }]; - [_turboModuleManager setBridgeProxy:bridgeProxy]; - } + _turboModuleManager = [[RCTTurboModuleManager alloc] + initWithBridgeProxy:bridgeProxy + bridgeModuleDecorator:_bridgeModuleDecorator + delegate:self + jsInvoker:std::make_shared(bufferedRuntimeExecutor)]; // Initialize RCTModuleRegistry so that TurboModules can require other TurboModules. [_bridgeModuleDecorator.moduleRegistry setTurboModuleRegistry:_turboModuleManager]; @@ -346,8 +346,6 @@ - (void)_attachBridgelessAPIsToModule:(id)module } #endif } - - [_bridgeModuleDecorator attachInteropAPIsToModule:(id)module]; } - (void)_loadJSBundle:(NSURL *)sourceURL diff --git a/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModuleManager.h b/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModuleManager.h index 4d0872fbab4a69..417da9d857e5dd 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModuleManager.h +++ b/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModuleManager.h @@ -9,6 +9,7 @@ #import +#import #import #import #import @@ -59,6 +60,11 @@ RCT_EXTERN void RCTTurboModuleSetBindingMode(facebook::react::TurboModuleBinding delegate:(id)delegate jsInvoker:(std::shared_ptr)jsInvoker; +- (instancetype)initWithBridgeProxy:(RCTBridgeProxy *)bridgeProxy + bridgeModuleDecorator:(RCTBridgeModuleDecorator *)bridgeModuleDecorator + delegate:(id)delegate + jsInvoker:(std::shared_ptr)jsInvoker; + - (void)installJSBindings:(facebook::jsi::Runtime &)runtime; /** @@ -66,9 +72,6 @@ RCT_EXTERN void RCTTurboModuleSetBindingMode(facebook::react::TurboModuleBinding */ - (void)installJSBindingWithRuntimeExecutor:(facebook::react::RuntimeExecutor &)runtimeExecutor; -// TODO: Should we move this into the initializer? -- (void)setBridgeProxy:(RCTBridgeProxy *)bridgeProxy; - - (void)invalidate; @end diff --git a/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModuleManager.mm b/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModuleManager.mm index 2e47e39300f60d..1f8846763bf557 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModuleManager.mm +++ b/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModuleManager.mm @@ -211,9 +211,12 @@ @implementation RCTTurboModuleManager { NSDictionary *_legacyEagerlyRegisteredModuleClasses; RCTBridgeProxy *_bridgeProxy; + RCTBridgeModuleDecorator *_bridgeModuleDecorator; } - (instancetype)initWithBridge:(RCTBridge *)bridge + bridgeProxy:(RCTBridgeProxy *)bridgeProxy + bridgeModuleDecorator:(RCTBridgeModuleDecorator *)bridgeModuleDecorator delegate:(id)delegate jsInvoker:(std::shared_ptr)jsInvoker { @@ -221,6 +224,8 @@ - (instancetype)initWithBridge:(RCTBridge *)bridge _jsInvoker = std::move(jsInvoker); _delegate = delegate; _bridge = bridge; + _bridgeProxy = bridgeProxy; + _bridgeModuleDecorator = bridgeModuleDecorator; _invalidating = false; if (RCTTurboModuleInteropEnabled()) { @@ -256,9 +261,27 @@ - (instancetype)initWithBridge:(RCTBridge *)bridge return self; } -- (void)setBridgeProxy:(RCTBridgeProxy *)bridgeProxy +- (instancetype)initWithBridge:(RCTBridge *)bridge + delegate:(id)delegate + jsInvoker:(std::shared_ptr)jsInvoker { - _bridgeProxy = bridgeProxy; + return [self initWithBridge:bridge + bridgeProxy:nil + bridgeModuleDecorator:[bridge bridgeModuleDecorator] + delegate:delegate + jsInvoker:jsInvoker]; +} + +- (instancetype)initWithBridgeProxy:(RCTBridgeProxy *)bridgeProxy + bridgeModuleDecorator:(RCTBridgeModuleDecorator *)bridgeModuleDecorator + delegate:(id)delegate + jsInvoker:(std::shared_ptr)jsInvoker +{ + return [self initWithBridge:nil + bridgeProxy:bridgeProxy + bridgeModuleDecorator:bridgeModuleDecorator + delegate:delegate + jsInvoker:jsInvoker]; } - (void)notifyAboutTurboModuleSetup:(const char *)name @@ -720,8 +743,8 @@ - (BOOL)_shouldCreateObjCModule:(Class)moduleClass /** * Decorate NativeModules with bridgeless-compatible APIs that call into the bridge. */ - if (_bridge) { - [_bridge attachBridgeAPIsToObjCModule:module]; + if (_bridgeModuleDecorator) { + [_bridgeModuleDecorator attachInteropAPIsToModule:module]; } /**