From 3740c943e7aa4a6c64e75aab3130d633e68450e0 Mon Sep 17 00:00:00 2001 From: Ramanpreet Nara Date: Sat, 27 Dec 2025 16:43:19 -0800 Subject: [PATCH 1/2] Make TurboModuleBinding constructor private Summary: The TurboModuleBinding constructor actually doesn't need to be public! It's only called from BridgelessTurboModuleProxy or TurboModuleBinding::install. Changelog: [General][Breaking] Make the TurboModuleBinding constructor private. Reviewed By: christophpurrer Differential Revision: D89751218 --- .../core/ReactCommon/TurboModuleBinding.cpp | 13 +++++++------ .../core/ReactCommon/TurboModuleBinding.h | 10 +++++----- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboModuleBinding.cpp b/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboModuleBinding.cpp index 195811f9876..f826fe16253 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboModuleBinding.cpp +++ b/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboModuleBinding.cpp @@ -19,7 +19,7 @@ namespace facebook::react { class BridgelessNativeModuleProxy : public jsi::HostObject { TurboModuleBinding turboBinding_; - std::unique_ptr legacyBinding_; + std::optional legacyBinding_; public: BridgelessNativeModuleProxy( @@ -32,11 +32,12 @@ class BridgelessNativeModuleProxy : public jsi::HostObject { std::move(moduleProvider), longLivedObjectCollection), legacyBinding_( - legacyModuleProvider ? std::make_unique( - runtime, - std::move(legacyModuleProvider), - longLivedObjectCollection) - : nullptr) {} + legacyModuleProvider + ? std::make_optional(TurboModuleBinding( + runtime, + std::move(legacyModuleProvider), + longLivedObjectCollection)) + : std::nullopt) {} jsi::Value get(jsi::Runtime& runtime, const jsi::PropNameID& name) override { /** diff --git a/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboModuleBinding.h b/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboModuleBinding.h index ef94423c04e..a6aece1e39e 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboModuleBinding.h +++ b/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboModuleBinding.h @@ -33,16 +33,16 @@ class TurboModuleBinding final { TurboModuleProviderFunctionType &&legacyModuleProvider = nullptr, std::shared_ptr longLivedObjectCollection = nullptr); - TurboModuleBinding( - jsi::Runtime &runtime, - TurboModuleProviderFunctionType &&moduleProvider, - std::shared_ptr longLivedObjectCollection); - ~TurboModuleBinding(); private: friend BridgelessNativeModuleProxy; + TurboModuleBinding( + jsi::Runtime &runtime, + TurboModuleProviderFunctionType &&moduleProvider, + std::shared_ptr longLivedObjectCollection); + /** * A lookup function exposed to JS to get an instance of a TurboModule * for the given name. From 41ad94b3b52d9eeacbd32ff1d246d8879ab267a2 Mon Sep 17 00:00:00 2001 From: Ramanpreet Nara Date: Sat, 27 Dec 2025 16:43:19 -0800 Subject: [PATCH 2/2] Make TurboModuleBinding accept a provider with a runtime Summary: This way we can stop capturing the runtime pointer inside the providers created by turbomodule manager delegate. ## iOS https://www.internalfb.com/code/fbsource/[bf6c0a76ea2c967a93b6bc2b8977cac23211ec0d]/xplat/js/react-native-github/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModuleManager.mm?lines=919-920%2C946%2C969 ## Android https://www.internalfb.com/code/fbsource/[d226c31f345fd69c8453d4c8270b0df083c64ad5]/xplat/js/react-native-github/packages/react-native/ReactAndroid/src/main/jni/react/turbomodule/ReactCommon/TurboModuleManager.cpp?lines=128-132%2C144-145 Changelog: [Internal] Reviewed By: christophpurrer Differential Revision: D89751221 --- .../core/ReactCommon/TurboModule.h | 2 ++ .../core/ReactCommon/TurboModuleBinding.cpp | 27 ++++++++++++++++--- .../core/ReactCommon/TurboModuleBinding.h | 10 +++++-- 3 files changed, 33 insertions(+), 6 deletions(-) diff --git a/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboModule.h b/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboModule.h index fc622dfb526..adf0f2dc56d 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboModule.h +++ b/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboModule.h @@ -145,5 +145,7 @@ class JSI_EXPORT TurboModule : public jsi::HostObject { * given a name. */ using TurboModuleProviderFunctionType = std::function(const std::string &name)>; +using TurboModuleProviderFunctionTypeWithRuntime = + std::function(jsi::Runtime &runtime, const std::string &name)>; } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboModuleBinding.cpp b/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboModuleBinding.cpp index f826fe16253..4d02c5a60f5 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboModuleBinding.cpp +++ b/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboModuleBinding.cpp @@ -24,8 +24,8 @@ class BridgelessNativeModuleProxy : public jsi::HostObject { public: BridgelessNativeModuleProxy( jsi::Runtime& runtime, - TurboModuleProviderFunctionType&& moduleProvider, - TurboModuleProviderFunctionType&& legacyModuleProvider, + TurboModuleProviderFunctionTypeWithRuntime&& moduleProvider, + TurboModuleProviderFunctionTypeWithRuntime&& legacyModuleProvider, std::shared_ptr longLivedObjectCollection) : turboBinding_( runtime, @@ -89,7 +89,7 @@ class BridgelessNativeModuleProxy : public jsi::HostObject { TurboModuleBinding::TurboModuleBinding( jsi::Runtime& runtime, - TurboModuleProviderFunctionType&& moduleProvider, + TurboModuleProviderFunctionTypeWithRuntime&& moduleProvider, std::shared_ptr longLivedObjectCollection) : runtime_(runtime), moduleProvider_(std::move(moduleProvider)), @@ -100,6 +100,25 @@ void TurboModuleBinding::install( TurboModuleProviderFunctionType&& moduleProvider, TurboModuleProviderFunctionType&& legacyModuleProvider, std::shared_ptr longLivedObjectCollection) { + install( + runtime, + [moduleProvider = std::move(moduleProvider)]( + jsi::Runtime& runtime, const std::string& name) { + return moduleProvider(name); + }, + legacyModuleProvider == nullptr + ? (TurboModuleProviderFunctionTypeWithRuntime) nullptr + : [legacyModuleProvider = std::move(legacyModuleProvider)]( + jsi::Runtime& runtime, + const std::string& name) { return legacyModuleProvider(name); }, + longLivedObjectCollection); +} + +void TurboModuleBinding::install( + jsi::Runtime& runtime, + TurboModuleProviderFunctionTypeWithRuntime&& moduleProvider, + TurboModuleProviderFunctionTypeWithRuntime&& legacyModuleProvider, + std::shared_ptr longLivedObjectCollection) { // TODO(T208105802): We can get this information from the native side! auto isBridgeless = runtime.global().hasProperty(runtime, "RN$Bridgeless"); @@ -154,7 +173,7 @@ jsi::Value TurboModuleBinding::getModule( std::shared_ptr module; { TraceSection s("TurboModuleBinding::moduleProvider", "module", moduleName); - module = moduleProvider_(moduleName); + module = moduleProvider_(runtime, moduleName); } if (module) { TurboModuleWithJSIBindings::installJSIBindings(module, runtime); diff --git a/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboModuleBinding.h b/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboModuleBinding.h index a6aece1e39e..91fc2e7a116 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboModuleBinding.h +++ b/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboModuleBinding.h @@ -33,6 +33,12 @@ class TurboModuleBinding final { TurboModuleProviderFunctionType &&legacyModuleProvider = nullptr, std::shared_ptr longLivedObjectCollection = nullptr); + static void install( + jsi::Runtime &runtime, + TurboModuleProviderFunctionTypeWithRuntime &&moduleProvider, + TurboModuleProviderFunctionTypeWithRuntime &&legacyModuleProvider = nullptr, + std::shared_ptr longLivedObjectCollection = nullptr); + ~TurboModuleBinding(); private: @@ -40,7 +46,7 @@ class TurboModuleBinding final { TurboModuleBinding( jsi::Runtime &runtime, - TurboModuleProviderFunctionType &&moduleProvider, + TurboModuleProviderFunctionTypeWithRuntime &&moduleProvider, std::shared_ptr longLivedObjectCollection); /** @@ -50,7 +56,7 @@ class TurboModuleBinding final { jsi::Value getModule(jsi::Runtime &runtime, const std::string &moduleName) const; jsi::Runtime &runtime_; - TurboModuleProviderFunctionType moduleProvider_; + TurboModuleProviderFunctionTypeWithRuntime moduleProvider_; std::shared_ptr longLivedObjectCollection_; };