From 82c4ed3e005bfadf3f1d71651b4137355aefdbd8 Mon Sep 17 00:00:00 2001 From: Christoph Purrer Date: Fri, 29 May 2026 21:47:23 -0700 Subject: [PATCH] Enable TurboModule interop layer opt out via RCT_REMOVE_LEGACY_INTEROP (#56984) Summary: Changelog: [Internal][General] Enable TurboModule interop layer opt out via RCT_REMOVE_LEGACY_INTEROP Differential Revision: D106109160 --- .../Libraries/AppDelegate/RCTRootViewFactory.mm | 3 +++ packages/react-native/React/Base/RCTBridge.h | 2 ++ packages/react-native/React/Base/RCTBridge.mm | 2 ++ .../turbomodule/ReactCommon/TurboModuleManager.cpp | 8 ++++++++ .../turbomodule/ReactCommon/TurboModuleManager.h | 4 ++++ .../android/ReactCommon/JavaInteropTurboModule.cpp | 4 ++++ .../android/ReactCommon/JavaInteropTurboModule.h | 4 ++++ .../ios/ReactCommon/RCTInteropTurboModule.h | 4 ++++ .../ios/ReactCommon/RCTInteropTurboModule.mm | 4 ++++ .../ios/ReactCommon/RCTTurboModuleManager.mm | 14 ++++++++++++++ 10 files changed, 49 insertions(+) diff --git a/packages/react-native/Libraries/AppDelegate/RCTRootViewFactory.mm b/packages/react-native/Libraries/AppDelegate/RCTRootViewFactory.mm index 2ba1a49ae118..e64b2620562a 100644 --- a/packages/react-native/Libraries/AppDelegate/RCTRootViewFactory.mm +++ b/packages/react-native/Libraries/AppDelegate/RCTRootViewFactory.mm @@ -152,7 +152,10 @@ - (void)initializeReactHostWithLaunchOptions:(NSDictionary *)launchOptions devMenuConfiguration:(RCTDevMenuConfiguration *)devMenuConfiguration { // Enable TurboModule interop by default in Bridgeless mode +#ifndef RCT_REMOVE_LEGACY_MODULE_INTEROP RCTEnableTurboModuleInterop(YES); +#endif // RCT_REMOVE_LEGACY_MODULE_INTEROP + RCTEnableTurboModuleInteropBridgeProxy(YES); [self createReactHostIfNeeded:launchOptions bundleConfiguration:bundleConfiguration diff --git a/packages/react-native/React/Base/RCTBridge.h b/packages/react-native/React/Base/RCTBridge.h index 37ab428aeb42..aa8b7f1cb9a9 100644 --- a/packages/react-native/React/Base/RCTBridge.h +++ b/packages/react-native/React/Base/RCTBridge.h @@ -50,9 +50,11 @@ NSMutableArray *getModulesLoadedWithOldArch(void); BOOL RCTTurboModuleEnabled(void); void RCTEnableTurboModule(BOOL enabled); +#ifndef RCT_REMOVE_LEGACY_MODULE_INTEROP // Turn on TurboModule interop BOOL RCTTurboModuleInteropEnabled(void); void RCTEnableTurboModuleInterop(BOOL enabled); +#endif // RCT_REMOVE_LEGACY_MODULE_INTEROP // Turn on the fabric interop layer BOOL RCTFabricInteropLayerEnabled(void); diff --git a/packages/react-native/React/Base/RCTBridge.mm b/packages/react-native/React/Base/RCTBridge.mm index d80bd7d678c3..e6dfbf754a1e 100644 --- a/packages/react-native/React/Base/RCTBridge.mm +++ b/packages/react-native/React/Base/RCTBridge.mm @@ -199,6 +199,7 @@ void RCTEnableTurboModule(BOOL enabled) // The new Architecture is enabled by default and we are ignoring changes to the TurboModule system. } +#ifndef RCT_REMOVE_LEGACY_MODULE_INTEROP static BOOL turboModuleInteropEnabled = NO; BOOL RCTTurboModuleInteropEnabled(void) { @@ -208,6 +209,7 @@ void RCTEnableTurboModuleInterop(BOOL enabled) { turboModuleInteropEnabled = enabled; } +#endif // RCT_REMOVE_LEGACY_MODULE_INTEROP static BOOL fabricInteropLayerEnabled = YES; BOOL RCTFabricInteropLayerEnabled() 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 5d4600e6c8a1..b1461a35eeff 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 @@ -24,6 +24,7 @@ namespace facebook::react { +#ifndef RCT_REMOVE_LEGACY_MODULE_INTEROP namespace { class JMethodDescriptor : public jni::JavaClass { @@ -93,6 +94,7 @@ class JMethodDescriptor : public jni::JavaClass { } }; } // namespace +#endif // RCT_REMOVE_LEGACY_MODULE_INTEROP TurboModuleManager::TurboModuleManager( std::shared_ptr jsCallInvoker, @@ -222,6 +224,7 @@ std::shared_ptr TurboModuleManager::getTurboModule( return nullptr; } +#ifndef RCT_REMOVE_LEGACY_MODULE_INTEROP TurboModuleProviderFunctionTypeWithRuntime TurboModuleManager::createLegacyModuleProvider( jni::alias_ref javaPart) { @@ -318,14 +321,19 @@ std::shared_ptr TurboModuleManager::getLegacyModule( return nullptr; } +#endif // RCT_REMOVE_LEGACY_MODULE_INTEROP void TurboModuleManager::installJSBindings( jsi::Runtime& runtime, jni::alias_ref javaPart) { +#ifndef RCT_REMOVE_LEGACY_MODULE_INTEROP TurboModuleBinding::install( runtime, createTurboModuleProvider(javaPart), createLegacyModuleProvider(javaPart)); +#else + TurboModuleBinding::install(runtime, createTurboModuleProvider(javaPart)); +#endif // RCT_REMOVE_LEGACY_MODULE_INTEROP } void TurboModuleManager::dispatchJSBindingInstall( diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/turbomodule/ReactCommon/TurboModuleManager.h b/packages/react-native/ReactAndroid/src/main/jni/react/turbomodule/ReactCommon/TurboModuleManager.h index c520373f6893..0cc6a096436e 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/turbomodule/ReactCommon/TurboModuleManager.h +++ b/packages/react-native/ReactAndroid/src/main/jni/react/turbomodule/ReactCommon/TurboModuleManager.h @@ -48,7 +48,9 @@ class TurboModuleManager : public jni::HybridClass { * they want to be long-lived or short-lived. */ ModuleCache turboModuleCache_; +#ifndef RCT_REMOVE_LEGACY_MODULE_INTEROP ModuleCache legacyModuleCache_; +#endif // RCT_REMOVE_LEGACY_MODULE_INTEROP explicit TurboModuleManager( std::shared_ptr jsCallInvoker, @@ -64,8 +66,10 @@ class TurboModuleManager : public jni::HybridClass { std::shared_ptr getTurboModule(jni::alias_ref javaPart, const std::string &name, jsi::Runtime &runtime); +#ifndef RCT_REMOVE_LEGACY_MODULE_INTEROP static TurboModuleProviderFunctionTypeWithRuntime createLegacyModuleProvider(jni::alias_ref javaPart); std::shared_ptr getLegacyModule(jni::alias_ref javaPart, const std::string &name); +#endif // RCT_REMOVE_LEGACY_MODULE_INTEROP }; } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/nativemodule/core/platform/android/ReactCommon/JavaInteropTurboModule.cpp b/packages/react-native/ReactCommon/react/nativemodule/core/platform/android/ReactCommon/JavaInteropTurboModule.cpp index 7c716886d5c9..35816244d6cd 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/core/platform/android/ReactCommon/JavaInteropTurboModule.cpp +++ b/packages/react-native/ReactCommon/react/nativemodule/core/platform/android/ReactCommon/JavaInteropTurboModule.cpp @@ -7,6 +7,8 @@ #include "JavaInteropTurboModule.h" +#ifndef RCT_REMOVE_LEGACY_MODULE_INTEROP + namespace facebook::react { namespace { @@ -189,3 +191,5 @@ std::vector JavaInteropTurboModule::getPropertyNames( } } // namespace facebook::react + +#endif // RCT_REMOVE_LEGACY_MODULE_INTEROP diff --git a/packages/react-native/ReactCommon/react/nativemodule/core/platform/android/ReactCommon/JavaInteropTurboModule.h b/packages/react-native/ReactCommon/react/nativemodule/core/platform/android/ReactCommon/JavaInteropTurboModule.h index c70923bc936f..8dba9d0bb75e 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/core/platform/android/ReactCommon/JavaInteropTurboModule.h +++ b/packages/react-native/ReactCommon/react/nativemodule/core/platform/android/ReactCommon/JavaInteropTurboModule.h @@ -7,6 +7,8 @@ #pragma once +#ifndef RCT_REMOVE_LEGACY_MODULE_INTEROP + #include #include @@ -46,3 +48,5 @@ class JSI_EXPORT JavaInteropTurboModule : public JavaTurboModule { }; } // namespace facebook::react + +#endif // RCT_REMOVE_LEGACY_MODULE_INTEROP diff --git a/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTInteropTurboModule.h b/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTInteropTurboModule.h index b3e98589eb14..f170c5e0e6ac 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTInteropTurboModule.h +++ b/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTInteropTurboModule.h @@ -7,6 +7,8 @@ #pragma once +#ifndef RCT_REMOVE_LEGACY_MODULE_INTEROP + #import #import @@ -88,3 +90,5 @@ class JSI_EXPORT ObjCInteropTurboModule : public ObjCTurboModule { }; } // namespace facebook::react + +#endif // RCT_REMOVE_LEGACY_MODULE_INTEROP diff --git a/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTInteropTurboModule.mm b/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTInteropTurboModule.mm index 1e3738bcbc6e..b4c11eafaa59 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTInteropTurboModule.mm +++ b/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTInteropTurboModule.mm @@ -7,6 +7,8 @@ #include "RCTInteropTurboModule.h" +#ifndef RCT_REMOVE_LEGACY_MODULE_INTEROP + #import #import @@ -694,3 +696,5 @@ T RCTConvertTo(SEL selector, id json) } } // namespace facebook::react + +#endif // RCT_REMOVE_LEGACY_MODULE_INTEROP 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 94be5df0c5c5..4b3ee5b616e5 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 @@ -161,10 +161,12 @@ bool isTurboModuleClass(Class cls) return [cls conformsToProtocol:@protocol(RCTTurboModule)]; } +#ifndef RCT_REMOVE_LEGACY_MODULE_INTEROP bool isTurboModuleInstance(id module) { return isTurboModuleClass([module class]); } +#endif // RCT_REMOVE_LEGACY_MODULE_INTEROP struct ModuleQueuePair { id module; @@ -236,6 +238,7 @@ - (instancetype)initWithBridge:(RCTBridge *)bridge _sharedModuleQueue = dispatch_queue_create("com.meta.react.turbomodulemanager.queue", DISPATCH_QUEUE_SERIAL); _devMenuConfigurationDecorator = devMenuConfigurationDecorator; +#ifndef RCT_REMOVE_LEGACY_MODULE_INTEROP if (RCTTurboModuleInteropEnabled()) { // TODO(T174674274): Implement lazy loading of legacy modules in the new architecture. NSMutableDictionary> *legacyInitializedModules = [NSMutableDictionary new]; @@ -257,6 +260,7 @@ - (instancetype)initWithBridge:(RCTBridge *)bridge } _legacyEagerlyRegisteredModuleClasses = legacyEagerlyRegisteredModuleClasses; } +#endif // RCT_REMOVE_LEGACY_MODULE_INTEROP [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(bridgeWillInvalidateModules:) @@ -418,6 +422,7 @@ - (instancetype)initWithBridgeProxy:(RCTBridgeProxy *)bridgeProxy return nullptr; } +#ifndef RCT_REMOVE_LEGACY_MODULE_INTEROP - (std::shared_ptr)provideLegacyModule:(const char *)moduleName { auto legacyModuleLookup = _legacyModuleCache.find(moduleName); @@ -465,6 +470,7 @@ - (instancetype)initWithBridgeProxy:(RCTBridgeProxy *)bridgeProxy _legacyModuleCache.insert({moduleName, turboModule}); return turboModule; } +#endif // RCT_REMOVE_LEGACY_MODULE_INTEROP #pragma mark - Private Methods @@ -492,9 +498,11 @@ - (BOOL)_isLegacyModuleClass:(Class)moduleClass moduleProvider = [_delegate getModuleProvider:moduleName]; } +#ifndef RCT_REMOVE_LEGACY_MODULE_INTEROP if (RCTTurboModuleInteropEnabled() && ![self _isTurboModule:moduleName] && !moduleProvider) { return nil; } +#endif // RCT_REMOVE_LEGACY_MODULE_INTEROP if (moduleProvider) { if ([moduleProvider conformsToProtocol:@protocol(RCTTurboModule)]) { @@ -631,9 +639,11 @@ - (ModuleHolder *)_getOrCreateModuleHolder:(const char *)moduleName - (BOOL)_shouldCreateObjCModule:(Class)moduleClass { +#ifndef RCT_REMOVE_LEGACY_MODULE_INTEROP if (RCTTurboModuleInteropEnabled()) { return [moduleClass conformsToProtocol:@protocol(RCTBridgeModule)]; } +#endif // RCT_REMOVE_LEGACY_MODULE_INTEROP return [moduleClass conformsToProtocol:@protocol(RCTTurboModule)]; } @@ -946,6 +956,7 @@ - (void)installJSBindings:(facebook::jsi::Runtime &)runtime return turboModule; }; +#ifndef RCT_REMOVE_LEGACY_MODULE_INTEROP if (RCTTurboModuleInteropEnabled()) { auto legacyModuleProvider = [self](jsi::Runtime & /*runtime*/, const std::string &name) -> std::shared_ptr { @@ -972,6 +983,9 @@ - (void)installJSBindings:(facebook::jsi::Runtime &)runtime } else { TurboModuleBinding::install(runtime, std::move(turboModuleProvider)); } +#else + TurboModuleBinding::install(runtime, std::move(turboModuleProvider)); +#endif // RCT_REMOVE_LEGACY_MODULE_INTEROP } #pragma mark RCTTurboModuleRegistry