From cbf10a937f9c684fe9f10a8bcb4ce1c39ea279e4 Mon Sep 17 00:00:00 2001 From: Pieter De Baets Date: Thu, 27 Nov 2025 04:19:14 -0800 Subject: [PATCH] Extract TurboModuleManager from ReactHost (#54651) Summary: Break up ReactHost and TurboModuleManager, so in the future we can inject this more easily. Changelog: [Internal] Reviewed By: lenaic Differential Revision: D87774276 --- .../core/ReactCommon/TurboModuleBinding.h | 4 +- .../react/devsupport/DevSettingsModule.h | 2 +- .../react/runtime/ReactHost.cpp | 125 +++--------------- .../react/runtime/TurboModuleManager.cpp | 110 +++++++++++++++ .../react/runtime/TurboModuleManager.h | 53 ++++++++ 5 files changed, 184 insertions(+), 110 deletions(-) create mode 100644 packages/react-native/ReactCxxPlatform/react/runtime/TurboModuleManager.cpp create mode 100644 packages/react-native/ReactCxxPlatform/react/runtime/TurboModuleManager.h 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 a4a7ef222116..ef94423c04ee 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboModuleBinding.h +++ b/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboModuleBinding.h @@ -21,7 +21,7 @@ class BridgelessNativeModuleProxy; /** * Represents the JavaScript binding for the TurboModule system. */ -class TurboModuleBinding { +class TurboModuleBinding final { public: /* * Installs TurboModuleBinding into JavaScript runtime. @@ -38,7 +38,7 @@ class TurboModuleBinding { TurboModuleProviderFunctionType &&moduleProvider, std::shared_ptr longLivedObjectCollection); - virtual ~TurboModuleBinding(); + ~TurboModuleBinding(); private: friend BridgelessNativeModuleProxy; diff --git a/packages/react-native/ReactCxxPlatform/react/devsupport/DevSettingsModule.h b/packages/react-native/ReactCxxPlatform/react/devsupport/DevSettingsModule.h index 47a1cdc11eab..a9ec5cd41978 100644 --- a/packages/react-native/ReactCxxPlatform/react/devsupport/DevSettingsModule.h +++ b/packages/react-native/ReactCxxPlatform/react/devsupport/DevSettingsModule.h @@ -21,7 +21,7 @@ class DevSettingsModule : public NativeDevSettingsCxxSpec { DevSettingsModule( std::shared_ptr jsInvoker, std::weak_ptr devServerHelper, - LiveReloadCallback &&liveReloadCallback) + LiveReloadCallback liveReloadCallback) : NativeDevSettingsCxxSpec(jsInvoker), devServerHelper_(std::move(devServerHelper)), liveReloadCallback_(std::move(liveReloadCallback)) diff --git a/packages/react-native/ReactCxxPlatform/react/runtime/ReactHost.cpp b/packages/react-native/ReactCxxPlatform/react/runtime/ReactHost.cpp index 896ec4f76790..ca1f38300f38 100644 --- a/packages/react-native/ReactCxxPlatform/react/runtime/ReactHost.cpp +++ b/packages/react-native/ReactCxxPlatform/react/runtime/ReactHost.cpp @@ -13,31 +13,15 @@ #include #include #include -#include -#include -#include #include -#include #include -#include #include -#include #include -#include #include #include #include -#include -#include #include -#include #include -#include -#include -#include -#include -#include -#include #include #include #include @@ -50,6 +34,8 @@ #include #include +#include "TurboModuleManager.h" + namespace facebook::react { struct ReactInstanceData { @@ -257,6 +243,18 @@ void ReactHost::createReactInstance() { } auto liveReloadCallback = [this]() { reloadReactInstance(); }; + TurboModuleManager turboModuleManager( + reactInstanceData_->turboModuleProviders, + jsInvoker, + reactInstanceData_->onJsError, + reactInstanceData_->animatedNodesManagerProvider, + reactInstanceConfig_.enableDevMode ? devServerHelper_ : nullptr, + reactInstanceData_->devUIDelegate, + reactInstanceData_->logBoxSurfaceDelegate, + httpClientFactory, + webSocketClientFactory, + std::move(liveReloadCallback)); + reactInstance_->initializeRuntime( { #if defined(WITH_PERFETTO) || defined(RNCXX_WITH_PROFILING_PROVIDER) @@ -268,20 +266,9 @@ void ReactHost::createReactInstance() { [weakMountingManager = std::weak_ptr(reactInstanceData_->mountingManager), logger = reactInstanceData_->logger, - devUIDelegate = reactInstanceData_->devUIDelegate, - turboModuleProviders = reactInstanceData_->turboModuleProviders, - jsInvoker = std::move(jsInvoker), - logBoxSurfaceDelegate = reactInstanceData_->logBoxSurfaceDelegate, - devServerHelper = - reactInstanceConfig_.enableDevMode ? devServerHelper_ : nullptr, - animatedNodesManagerProvider = - reactInstanceData_->animatedNodesManagerProvider, - onJsError = reactInstanceData_->onJsError, bindingsInstallFunc = reactInstanceData_->bindingsInstallFunc, - httpClientFactory = std::move(httpClientFactory), - webSocketClientFactory = std::move(webSocketClientFactory), - liveReloadCallback = - std::move(liveReloadCallback)](jsi::Runtime& runtime) { + turboModuleManager = + std::move(turboModuleManager)](jsi::Runtime& runtime) mutable { if (logger) { bindNativeLogger(runtime, logger); } @@ -295,85 +282,9 @@ void ReactHost::createReactInstance() { return false; }); - auto turboModuleProvider = - [turboModuleProviders, - jsInvoker, - logBoxSurfaceDelegate, - devServerHelper, - devUIDelegate, - animatedNodesManagerProvider, - onJsError, - httpClientFactory = httpClientFactory, - webSocketClientFactory = webSocketClientFactory, - liveReloadCallback = liveReloadCallback]( - const std::string& name) -> std::shared_ptr { - react_native_assert( - !name.empty() && "TurboModule name must not be empty"); - - for (const auto& turboModuleProvider : turboModuleProviders) { - if (turboModuleProvider) { - if (auto turboModule = turboModuleProvider(name, jsInvoker)) { - return turboModule; - } - } - } - - if (auto turboModule = - DefaultTurboModules::getTurboModule(name, jsInvoker)) { - return turboModule; - } - - if (name == AnimatedModule::kModuleName) { - return std::make_shared( - jsInvoker, animatedNodesManagerProvider); - } else if (name == AppStateModule::kModuleName) { - return std::make_shared(jsInvoker); - } else if (name == DeviceInfoModule::kModuleName) { - return std::make_shared(jsInvoker); - } else if ( - devUIDelegate != nullptr && - name == DevLoadingViewModule::kModuleName) { - return std::make_shared( - jsInvoker, devUIDelegate); - } else if ( - devServerHelper && name == DevSettingsModule::kModuleName) { - return std::make_shared( - jsInvoker, devServerHelper, liveReloadCallback); - } else if (name == PlatformConstantsModule::kModuleName) { - return std::make_shared(jsInvoker); - } else if (name == ImageLoaderModule::kModuleName) { - return std::make_shared(jsInvoker); - } else if (name == SourceCodeModule::kModuleName) { - return std::make_shared( - jsInvoker, devServerHelper); - } else if (name == WebSocketModule::kModuleName) { - return std::make_shared( - jsInvoker, webSocketClientFactory); - } else if (name == NativeExceptionsManager::kModuleName) { - return std::make_shared( - onJsError, jsInvoker); - } else if (name == NativePerformance::kModuleName) { - return std::make_shared(jsInvoker); - } else if (name == NativeIntersectionObserver::kModuleName) { - return std::make_shared(jsInvoker); - } else if (name == NativeMutationObserver::kModuleName) { - return std::make_shared(jsInvoker); - } else if (name == NetworkingModule::kModuleName) { - return std::make_shared( - jsInvoker, httpClientFactory); - } else if (name == LogBoxModule::kModuleName) { - if (logBoxSurfaceDelegate) { - return std::make_shared( - jsInvoker, logBoxSurfaceDelegate); - } - } - - LOG_WARNING_ONCE << "Failed to load TurboModule: " << name; - return nullptr; - }; - // Set up TurboModules - TurboModuleBinding::install(runtime, turboModuleProvider); + TurboModuleBinding::install(runtime, std::move(turboModuleManager)); + if (bindingsInstallFunc) { bindingsInstallFunc(runtime); } diff --git a/packages/react-native/ReactCxxPlatform/react/runtime/TurboModuleManager.cpp b/packages/react-native/ReactCxxPlatform/react/runtime/TurboModuleManager.cpp new file mode 100644 index 000000000000..0b33212a6dd6 --- /dev/null +++ b/packages/react-native/ReactCxxPlatform/react/runtime/TurboModuleManager.cpp @@ -0,0 +1,110 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include "TurboModuleManager.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace facebook::react; + +TurboModuleManager::TurboModuleManager( + TurboModuleProviders turboModuleProviders, + std::shared_ptr jsInvoker, + JsErrorHandler::OnJsError onJsError, + std::shared_ptr + animatedNodesManagerProvider, + std::shared_ptr devServerHelper, + std::shared_ptr devUIDelegate, + std::shared_ptr logBoxSurfaceDelegate, + HttpClientFactory httpClientFactory, + WebSocketClientFactory webSocketClientFactory, + std::function liveReloadCallback) + : turboModuleProviders_(std::move(turboModuleProviders)), + jsInvoker_(std::move(jsInvoker)), + onJsError_(std::move(onJsError)), + animatedNodesManagerProvider_(std::move(animatedNodesManagerProvider)), + devServerHelper_(std::move(devServerHelper)), + devUIDelegate_(std::move(devUIDelegate)), + logBoxSurfaceDelegate_(std::move(logBoxSurfaceDelegate)), + httpClientFactory_(std::move(httpClientFactory)), + webSocketClientFactory_(std::move(webSocketClientFactory)), + liveReloadCallback_(std::move(liveReloadCallback)) {} + +std::shared_ptr TurboModuleManager::operator()( + const std::string& name) const { + react_native_assert(!name.empty() && "TurboModule name must not be empty"); + + for (const auto& turboModuleProvider : turboModuleProviders_) { + if (turboModuleProvider) { + if (auto turboModule = turboModuleProvider(name, jsInvoker_)) { + return turboModule; + } + } + } + + if (auto turboModule = + DefaultTurboModules::getTurboModule(name, jsInvoker_)) { + return turboModule; + } + + if (name == AnimatedModule::kModuleName) { + return std::make_shared( + jsInvoker_, animatedNodesManagerProvider_); + } else if (name == AppStateModule::kModuleName) { + return std::make_shared(jsInvoker_); + } else if (name == DeviceInfoModule::kModuleName) { + return std::make_shared(jsInvoker_); + } else if ( + devUIDelegate_ != nullptr && name == DevLoadingViewModule::kModuleName) { + return std::make_shared(jsInvoker_, devUIDelegate_); + } else if (devServerHelper_ && name == DevSettingsModule::kModuleName) { + return std::make_shared( + jsInvoker_, devServerHelper_, liveReloadCallback_); + } else if (name == PlatformConstantsModule::kModuleName) { + return std::make_shared(jsInvoker_); + } else if (name == ImageLoaderModule::kModuleName) { + return std::make_shared(jsInvoker_); + } else if (name == SourceCodeModule::kModuleName) { + return std::make_shared(jsInvoker_, devServerHelper_); + } else if (name == WebSocketModule::kModuleName) { + return std::make_shared( + jsInvoker_, webSocketClientFactory_); + } else if (name == NativeExceptionsManager::kModuleName) { + return std::make_shared(onJsError_, jsInvoker_); + } else if (name == NativePerformance::kModuleName) { + return std::make_shared(jsInvoker_); + } else if (name == NativeIntersectionObserver::kModuleName) { + return std::make_shared(jsInvoker_); + } else if (name == NativeMutationObserver::kModuleName) { + return std::make_shared(jsInvoker_); + } else if (name == NetworkingModule::kModuleName) { + return std::make_shared(jsInvoker_, httpClientFactory_); + } else if (name == LogBoxModule::kModuleName) { + if (logBoxSurfaceDelegate_) { + return std::make_shared(jsInvoker_, logBoxSurfaceDelegate_); + } + } + + LOG(WARNING) << "Failed to load TurboModule: " << name; + return nullptr; +} diff --git a/packages/react-native/ReactCxxPlatform/react/runtime/TurboModuleManager.h b/packages/react-native/ReactCxxPlatform/react/runtime/TurboModuleManager.h new file mode 100644 index 000000000000..a1e05ab2bc1a --- /dev/null +++ b/packages/react-native/ReactCxxPlatform/react/runtime/TurboModuleManager.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include +#include +#include +#include +#include + +namespace facebook::react { + +class CallInvoker; +class DevServerHelper; +class NativeAnimatedNodesManagerProvider; +class SurfaceDelegate; +struct IDevUIDelegate; + +class TurboModuleManager final { + public: + TurboModuleManager( + TurboModuleProviders turboModuleProviders, + std::shared_ptr jsInvoker, + JsErrorHandler::OnJsError onJsError, + std::shared_ptr animatedNodesManagerProvider = nullptr, + std::shared_ptr devServerHelper = nullptr, + std::shared_ptr devUIDelegate = nullptr, + std::shared_ptr logBoxSurfaceDelegate = nullptr, + HttpClientFactory httpClientFactory = nullptr, + WebSocketClientFactory webSocketClientFactory = nullptr, + std::function liveReloadCallback = nullptr); + + std::shared_ptr operator()(const std::string &name) const; + + private: + TurboModuleProviders turboModuleProviders_; + std::shared_ptr jsInvoker_; + JsErrorHandler::OnJsError onJsError_; + std::shared_ptr animatedNodesManagerProvider_; + std::shared_ptr devServerHelper_; + std::shared_ptr devUIDelegate_; + std::shared_ptr logBoxSurfaceDelegate_; + HttpClientFactory httpClientFactory_; + WebSocketClientFactory webSocketClientFactory_; + std::function liveReloadCallback_; +}; + +} // namespace facebook::react