diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/turbomodule/ReactCommon/TurboModuleManager.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/turbomodule/ReactCommon/TurboModuleManager.cpp index 85a2fdab53b..cd9f033fe1d 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/turbomodule/ReactCommon/TurboModuleManager.cpp +++ b/packages/react-native/ReactAndroid/src/main/jni/react/turbomodule/ReactCommon/TurboModuleManager.cpp @@ -12,6 +12,7 @@ #include #include +#include #include #include #include @@ -168,6 +169,14 @@ TurboModuleProviderFunctionType TurboModuleManager::createTurboModuleProvider( return cxxModule; } + auto& cxxTurboModuleMapProvider = globalExportedCxxTurboModuleMap(); + auto it = cxxTurboModuleMapProvider.find(name); + if (it != cxxTurboModuleMapProvider.end()) { + auto turboModule = it->second(jsCallInvoker); + turboModuleCache->insert({name, turboModule}); + return turboModule; + } + static auto getTurboLegacyCxxModule = javaPart->getClass() ->getMethod( diff --git a/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/CxxTurboModuleUtils.cpp b/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/CxxTurboModuleUtils.cpp new file mode 100644 index 00000000000..4ddafa742ad --- /dev/null +++ b/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/CxxTurboModuleUtils.cpp @@ -0,0 +1,32 @@ +/* + * 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 "CxxTurboModuleUtils.h" + +namespace facebook::react { + +std::unordered_map< + std::string, + std::function< + std::shared_ptr(std::shared_ptr jsInvoker)>>& +globalExportedCxxTurboModuleMap() { + static std::unordered_map< + std::string, + std::function( + std::shared_ptr jsInvoker)>> + map; + return map; +} + +void registerCxxModuleToGlobalModuleMap( + std::string name, + std::function( + std::shared_ptr jsInvoker)> moduleProviderFunc) { + globalExportedCxxTurboModuleMap()[name] = moduleProviderFunc; +} + +} // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/CxxTurboModuleUtils.h b/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/CxxTurboModuleUtils.h new file mode 100644 index 00000000000..64c5cf3eb46 --- /dev/null +++ b/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/CxxTurboModuleUtils.h @@ -0,0 +1,67 @@ +/* + * 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 + +namespace facebook::react { + +std::unordered_map< + std::string, + std::function< + std::shared_ptr(std::shared_ptr jsInvoker)>>& +globalExportedCxxTurboModuleMap(); + +void registerCxxModuleToGlobalModuleMap( + std::string name, + std::function( + std::shared_ptr jsInvoker)> moduleProviderFunc); + +} // namespace facebook::react + +/* + * You can use this macro to register your C++ TurboModule in your .cpp + * implementation if you do not have access to getTurboModule:jsInvoker: + * callback. This will register the module before main() is called, + * so it will incur a startup cost. + * + * RCT_EXPORT_CXX_MODULE_EXPERIMENTAL(ModuleExample) becomes: + * + * #pragma clang diagnostic push + * #pragma clang diagnostic ignored "-Wglobal-constructors" + * struct ModuleExampleLoad { + * ModuleExampleLoad() { + * facebook::react::registerCxxModule(name, + * [&](std::shared_ptr jsInvoker) { + * return + * std::make_shared(jsInvoker); + * }); + * } + * }; + * static ModuleExampleLoad moduleExampleLoad; + * #pragma clang diagnostic pop + * + */ +#define RCT_EXPORT_CXX_MODULE_EXPERIMENTAL(name) \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Wglobal-constructors\"") struct \ + name##Load { \ + name##Load() { \ + facebook::react::registerCxxModuleToGlobalModuleMap( \ + #name, \ + [&](std::shared_ptr jsInvoker) { \ + return std::make_shared(jsInvoker); \ + }); \ + } \ + }; \ + static name##Load _##name##Load; \ + _Pragma("clang diagnostic pop") 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 09ea2122987..d93d606fce4 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 @@ -27,6 +27,7 @@ #import #import #import +#import #import #import #import @@ -325,6 +326,14 @@ static Class getFallbackClassFromName(const char *name) TurboModulePerfLogger::moduleCreateFail(moduleName, moduleId); } + auto &cxxTurboModuleMapProvider = globalExportedCxxTurboModuleMap(); + auto it = cxxTurboModuleMapProvider.find(moduleName); + if (it != cxxTurboModuleMapProvider.end()) { + auto turboModule = it->second(_jsInvoker); + _turboModuleCache.insert({moduleName, turboModule}); + return turboModule; + } + /** * Step 2: Look for platform-specific modules. */