diff --git a/packages/react-native/Libraries/TurboModule/TurboModuleRegistry.js b/packages/react-native/Libraries/TurboModule/TurboModuleRegistry.js index 9f2a3735861642..135be5bca89d7a 100644 --- a/packages/react-native/Libraries/TurboModule/TurboModuleRegistry.js +++ b/packages/react-native/Libraries/TurboModule/TurboModuleRegistry.js @@ -16,9 +16,6 @@ const NativeModules = require('../BatchedBridge/NativeModules'); const turboModuleProxy = global.__turboModuleProxy; -const useLegacyNativeModuleInterop = - global.RN$Bridgeless !== true || global.RN$TurboInterop === true; - function requireModule(name: string): ?T { if (turboModuleProxy != null) { const module: ?T = turboModuleProxy(name); @@ -27,8 +24,11 @@ function requireModule(name: string): ?T { } } - if (useLegacyNativeModuleInterop) { - // Backward compatibility layer during migration. + if ( + global.RN$Bridgeless !== true || + global.RN$TurboInterop === true || + global.RN$UnifiedNativeModuleProxy === true + ) { const legacyModule: ?T = NativeModules[name]; if (legacyModule != null) { return legacyModule; 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 1bc4d716e9a9d0..32d1f997b2f820 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboModuleBinding.cpp +++ b/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboModuleBinding.cpp @@ -17,11 +17,25 @@ using namespace facebook; namespace facebook::react { class BridgelessNativeModuleProxy : public jsi::HostObject { - std::unique_ptr binding_; + TurboModuleBinding turboBinding_; + std::unique_ptr legacyBinding_; public: - BridgelessNativeModuleProxy(std::unique_ptr binding) - : binding_(std::move(binding)) {} + BridgelessNativeModuleProxy( + jsi::Runtime& runtime, + TurboModuleProviderFunctionType&& moduleProvider, + TurboModuleProviderFunctionType&& legacyModuleProvider, + std::shared_ptr longLivedObjectCollection) + : turboBinding_( + runtime, + std::move(moduleProvider), + longLivedObjectCollection), + legacyBinding_( + legacyModuleProvider ? std::make_unique( + runtime, + std::move(legacyModuleProvider), + longLivedObjectCollection) + : nullptr) {} jsi::Value get(jsi::Runtime& runtime, const jsi::PropNameID& name) override { /** @@ -42,14 +56,19 @@ class BridgelessNativeModuleProxy : public jsi::HostObject { return jsi::Value(false); } - if (binding_) { - return binding_->getModule(runtime, moduleName); + auto turboModule = turboBinding_.getModule(runtime, moduleName); + if (turboModule.isObject()) { + return turboModule; } - throw jsi::JSError( - runtime, - "Tried to access NativeModule \"" + name.utf8(runtime) + - "\" from the bridge. This isn't allowed in Bridgeless mode."); + if (legacyBinding_) { + auto legacyModule = legacyBinding_->getModule(runtime, moduleName); + if (legacyModule.isObject()) { + return legacyModule; + } + } + + return jsi::Value::null(); } void set( @@ -79,44 +98,46 @@ void TurboModuleBinding::install( TurboModuleProviderFunctionType&& moduleProvider, TurboModuleProviderFunctionType&& legacyModuleProvider, std::shared_ptr longLivedObjectCollection) { - runtime.global().setProperty( + // TODO(T208105802): We can get this information from the native side! + auto isBridgeless = runtime.global().hasProperty(runtime, "RN$Bridgeless"); + + if (!isBridgeless) { + runtime.global().setProperty( + runtime, + "__turboModuleProxy", + jsi::Function::createFromHostFunction( + runtime, + jsi::PropNameID::forAscii(runtime, "__turboModuleProxy"), + 1, + [binding = TurboModuleBinding( + runtime, + std::move(moduleProvider), + longLivedObjectCollection)]( + jsi::Runtime& rt, + const jsi::Value& /*thisVal*/, + const jsi::Value* args, + size_t count) { + if (count < 1) { + throw std::invalid_argument( + "__turboModuleProxy must be called with at least 1 argument"); + } + std::string moduleName = args[0].getString(rt).utf8(rt); + return binding.getModule(rt, moduleName); + })); + return; + } + + defineReadOnlyGlobal(runtime, "RN$UnifiedNativeModuleProxy", true); + defineReadOnlyGlobal( runtime, - "__turboModuleProxy", - jsi::Function::createFromHostFunction( + "nativeModuleProxy", + jsi::Object::createFromHostObject( runtime, - jsi::PropNameID::forAscii(runtime, "__turboModuleProxy"), - 1, - [binding = TurboModuleBinding( - runtime, std::move(moduleProvider), longLivedObjectCollection)]( - jsi::Runtime& rt, - const jsi::Value& thisVal, - const jsi::Value* args, - size_t count) { - if (count < 1) { - throw std::invalid_argument( - "__turboModuleProxy must be called with at least 1 argument"); - } - std::string moduleName = args[0].getString(rt).utf8(rt); - return binding.getModule(rt, moduleName); - })); - - if (runtime.global().hasProperty(runtime, "RN$Bridgeless")) { - bool rnTurboInterop = legacyModuleProvider != nullptr; - auto turboModuleBinding = legacyModuleProvider - ? std::make_unique( + std::make_shared( runtime, + std::move(moduleProvider), std::move(legacyModuleProvider), - longLivedObjectCollection) - : nullptr; - auto nativeModuleProxy = std::make_shared( - std::move(turboModuleBinding)); - defineReadOnlyGlobal( - runtime, "RN$TurboInterop", jsi::Value(rnTurboInterop)); - defineReadOnlyGlobal( - runtime, - "nativeModuleProxy", - jsi::Object::createFromHostObject(runtime, nativeModuleProxy)); - } + longLivedObjectCollection))); } TurboModuleBinding::~TurboModuleBinding() {