From 8c1210f9bc38e7d3e25b0a581b9df89dfa40e85f Mon Sep 17 00:00:00 2001 From: Christoph Purrer Date: Fri, 5 Jun 2026 10:05:12 -0700 Subject: [PATCH] Gate shared C++ + Java/Kotlin legacy view manager interop behind `RCT_REMOVE_LEGACY_COMPONENT_INTEROP` (#57073) Summary: Changelog: [General][Added] Gate shared C++ and Android Java/Kotlin legacy view manager interop behind `RCT_REMOVE_LEGACY_COMPONENT_INTEROP` Reviewed By: cortinico, javache Differential Revision: D107477086 --- packages/react-native/ReactAndroid/api/ReactAndroid.api | 1 + packages/react-native/ReactAndroid/build.gradle.kts | 1 + .../java/com/facebook/react/bridge/ReactContext.java | 7 +++++++ .../com/facebook/react/common/build/ReactBuildConfig.kt | 4 ++++ .../java/com/facebook/react/fabric/FabricUIManager.java | 9 ++++++--- .../com/facebook/react/runtime/BridgelessReactContext.kt | 5 ++++- .../react/uimanager/UIManagerModuleConstantsHelper.kt | 4 ++-- .../componentregistry/ComponentDescriptorRegistry.cpp | 6 ++++++ .../LegacyViewManagerInteropShadowNode.cpp | 4 ++++ .../LegacyViewManagerInteropShadowNode.h | 4 ++++ .../LegacyViewManagerInteropState.h | 4 ++++ .../LegacyViewManagerInteropViewProps.cpp | 5 +++++ .../LegacyViewManagerInteropViewProps.h | 4 ++++ ...ableLegacyViewManagerAutomaticComponentDescriptor.cpp | 5 +++++ ...stableLegacyViewManagerAutomaticComponentDescriptor.h | 4 ++++ .../UnstableLegacyViewManagerAutomaticShadowNode.cpp | 4 ++++ .../UnstableLegacyViewManagerAutomaticShadowNode.h | 4 ++++ ...UnstableLegacyViewManagerInteropComponentDescriptor.h | 4 ++++ 18 files changed, 73 insertions(+), 6 deletions(-) diff --git a/packages/react-native/ReactAndroid/api/ReactAndroid.api b/packages/react-native/ReactAndroid/api/ReactAndroid.api index 2f2a53ba14d8..fe791820641e 100644 --- a/packages/react-native/ReactAndroid/api/ReactAndroid.api +++ b/packages/react-native/ReactAndroid/api/ReactAndroid.api @@ -1655,6 +1655,7 @@ public final class com/facebook/react/common/build/ReactBuildConfig { public static final field IS_INTERNAL_BUILD Z public static final field UNSTABLE_ENABLE_FUSEBOX_RELEASE Z public static final field UNSTABLE_ENABLE_MINIFY_LEGACY_ARCHITECTURE Z + public static final field UNSTABLE_REMOVE_LEGACY_COMPONENT_INTEROP Z } public abstract interface class com/facebook/react/common/mapbuffer/MapBuffer : java/lang/Iterable, kotlin/jvm/internal/markers/KMappedMarker { diff --git a/packages/react-native/ReactAndroid/build.gradle.kts b/packages/react-native/ReactAndroid/build.gradle.kts index b0136db3c8f5..7da7a5bc2d00 100644 --- a/packages/react-native/ReactAndroid/build.gradle.kts +++ b/packages/react-native/ReactAndroid/build.gradle.kts @@ -561,6 +561,7 @@ android { buildConfigField("boolean", "UNSTABLE_ENABLE_FUSEBOX_RELEASE", "false") buildConfigField("boolean", "ENABLE_PERFETTO", "false") buildConfigField("boolean", "UNSTABLE_ENABLE_MINIFY_LEGACY_ARCHITECTURE", "false") + buildConfigField("boolean", "UNSTABLE_REMOVE_LEGACY_COMPONENT_INTEROP", "false") resValue("integer", "react_native_dev_server_port", reactNativeDevServerPort()) resValue("string", "react_native_dev_server_ip", "localhost") diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactContext.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactContext.java index 8bf13e1cf383..15b0d6691a85 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactContext.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactContext.java @@ -26,6 +26,7 @@ import com.facebook.react.bridge.queue.MessageQueueThread; import com.facebook.react.bridge.queue.ReactQueueConfiguration; import com.facebook.react.common.LifecycleState; +import com.facebook.react.common.build.ReactBuildConfig; import com.facebook.react.interfaces.ExtraWindowEventListener; import com.facebook.react.turbomodule.core.interfaces.CallInvokerHolder; import java.lang.ref.WeakReference; @@ -110,6 +111,9 @@ public synchronized void initializeMessageQueueThreads(ReactQueueConfiguration q } protected void initializeInteropModules() { + if (ReactBuildConfig.UNSTABLE_REMOVE_LEGACY_COMPONENT_INTEROP) { + return; + } mInteropModuleRegistry = new InteropModuleRegistry(); } @@ -579,6 +583,9 @@ public boolean startActivityForResult(Intent intent, int code, Bundle bundle) { */ public void internal_registerInteropModule( Class interopModuleInterface, Object interopModule) { + if (ReactBuildConfig.UNSTABLE_REMOVE_LEGACY_COMPONENT_INTEROP) { + return; + } if (mInteropModuleRegistry != null) { mInteropModuleRegistry.registerInteropModule(interopModuleInterface, interopModule); } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/common/build/ReactBuildConfig.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/common/build/ReactBuildConfig.kt index f5afec5157fa..010437128dd6 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/common/build/ReactBuildConfig.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/common/build/ReactBuildConfig.kt @@ -37,4 +37,8 @@ public object ReactBuildConfig { @JvmField public val UNSTABLE_ENABLE_MINIFY_LEGACY_ARCHITECTURE: Boolean = BuildConfig.UNSTABLE_ENABLE_MINIFY_LEGACY_ARCHITECTURE + + @JvmField + public val UNSTABLE_REMOVE_LEGACY_COMPONENT_INTEROP: Boolean = + BuildConfig.UNSTABLE_REMOVE_LEGACY_COMPONENT_INTEROP } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java index 2a0baaeace09..ee64131ab187 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java @@ -447,7 +447,8 @@ public void initialize() { ReactMarker.addFabricListener(mDevToolsReactPerfLogger); } - if (ReactNativeNewArchitectureFeatureFlags.useFabricInterop()) { + if (!ReactBuildConfig.UNSTABLE_REMOVE_LEGACY_COMPONENT_INTEROP + && ReactNativeNewArchitectureFeatureFlags.useFabricInterop()) { InteropEventEmitter interopEventEmitter = new InteropEventEmitter(mReactApplicationContext); mReactApplicationContext.internal_registerInteropModule( RCTEventEmitter.class, interopEventEmitter); @@ -514,7 +515,8 @@ public void sweepActiveTouchForTag(int surfaceId, int reactTag) { * [addUiBlock] and [prependUiBlock] on UIManagerModule. */ public void addUIBlock(UIBlock block) { - if (ReactNativeNewArchitectureFeatureFlags.useFabricInterop()) { + if (!ReactBuildConfig.UNSTABLE_REMOVE_LEGACY_COMPONENT_INTEROP + && ReactNativeNewArchitectureFeatureFlags.useFabricInterop()) { InteropUIBlockListener listener = getInteropUIBlockListener(); listener.addUIBlock(block); } @@ -525,7 +527,8 @@ public void addUIBlock(UIBlock block) { * [addUiBlock] and [prependUiBlock] on UIManagerModule. */ public void prependUIBlock(UIBlock block) { - if (ReactNativeNewArchitectureFeatureFlags.useFabricInterop()) { + if (!ReactBuildConfig.UNSTABLE_REMOVE_LEGACY_COMPONENT_INTEROP + && ReactNativeNewArchitectureFeatureFlags.useFabricInterop()) { InteropUIBlockListener listener = getInteropUIBlockListener(); listener.prependUIBlock(block); } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/BridgelessReactContext.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/BridgelessReactContext.kt index bfaf55b140d3..4b607f238bd9 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/BridgelessReactContext.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/BridgelessReactContext.kt @@ -56,7 +56,10 @@ internal class BridgelessReactContext(context: Context, private val reactHost: R get() = reactHost.defaultBackButtonHandler init { - if (ReactNativeNewArchitectureFeatureFlags.useFabricInterop()) { + if ( + !ReactBuildConfig.UNSTABLE_REMOVE_LEGACY_COMPONENT_INTEROP && + ReactNativeNewArchitectureFeatureFlags.useFabricInterop() + ) { initializeInteropModules() } } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModuleConstantsHelper.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModuleConstantsHelper.kt index 45e1ae70716b..3039c01cdace 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModuleConstantsHelper.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModuleConstantsHelper.kt @@ -143,7 +143,7 @@ internal object UIManagerModuleConstantsHelper { var viewManagerBubblingEvents: MutableMap? = viewManager.exportedCustomBubblingEventTypeConstants if (viewManagerBubblingEvents != null) { - if (useFabricInterop()) { + if (!ReactBuildConfig.UNSTABLE_REMOVE_LEGACY_COMPONENT_INTEROP && useFabricInterop()) { // For Fabric, events needs to be fired with a "top" prefix. // For the sake of Fabric Interop, here we normalize events adding "top" in their // name if the user hasn't provided it. @@ -160,7 +160,7 @@ internal object UIManagerModuleConstantsHelper { viewManager.exportedCustomDirectEventTypeConstants validateDirectEventNames(viewManager.getName(), viewManagerDirectEvents) if (viewManagerDirectEvents != null) { - if (useFabricInterop()) { + if (!ReactBuildConfig.UNSTABLE_REMOVE_LEGACY_COMPONENT_INTEROP && useFabricInterop()) { // For Fabric, events needs to be fired with a "top" prefix. // For the sake of Fabric Interop, here we normalize events adding "top" in their // name if the user hasn't provided it. diff --git a/packages/react-native/ReactCommon/react/renderer/componentregistry/ComponentDescriptorRegistry.cpp b/packages/react-native/ReactCommon/react/renderer/componentregistry/ComponentDescriptorRegistry.cpp index 4838b3b6013e..e1d479198111 100644 --- a/packages/react-native/ReactCommon/react/renderer/componentregistry/ComponentDescriptorRegistry.cpp +++ b/packages/react-native/ReactCommon/react/renderer/componentregistry/ComponentDescriptorRegistry.cpp @@ -12,8 +12,10 @@ #include #include #include +#ifndef RCT_REMOVE_LEGACY_COMPONENT_INTEROP #include #include +#endif // RCT_REMOVE_LEGACY_COMPONENT_INTEROP #include #include #include @@ -84,6 +86,7 @@ const ComponentDescriptor& ComponentDescriptorRegistry::at( } if (it == _registryByName.end()) { +#ifndef RCT_REMOVE_LEGACY_COMPONENT_INTEROP if (ReactNativeFeatureFlags::useFabricInterop()) { // When interop is enabled, if the component is not found we rely on // UnstableLegacyViewManagerAutomaticComponentDescriptor to support legacy @@ -94,6 +97,7 @@ const ComponentDescriptor& ComponentDescriptorRegistry::at( registerComponentDescriptor(componentDescriptor); return *_registryByName.find(unifiedComponentName)->second; } else { +#endif // RCT_REMOVE_LEGACY_COMPONENT_INTEROP // When interop is disabled, if the component is not found we rely on // fallbackComponentDescriptor (default: // UnimplementedNativeViewComponentDescriptor). @@ -107,7 +111,9 @@ const ComponentDescriptor& ComponentDescriptorRegistry::at( } else { return *_fallbackComponentDescriptor.get(); } +#ifndef RCT_REMOVE_LEGACY_COMPONENT_INTEROP } +#endif // RCT_REMOVE_LEGACY_COMPONENT_INTEROP } return *it->second; diff --git a/packages/react-native/ReactCommon/react/renderer/components/legacyviewmanagerinterop/LegacyViewManagerInteropShadowNode.cpp b/packages/react-native/ReactCommon/react/renderer/components/legacyviewmanagerinterop/LegacyViewManagerInteropShadowNode.cpp index 81ddc89db1f9..ba685febf323 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/legacyviewmanagerinterop/LegacyViewManagerInteropShadowNode.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/legacyviewmanagerinterop/LegacyViewManagerInteropShadowNode.cpp @@ -5,9 +5,13 @@ * LICENSE file in the root directory of this source tree. */ +#ifndef RCT_REMOVE_LEGACY_COMPONENT_INTEROP + namespace facebook::react { extern const char LegacyViewManagerInteropComponentName[] = "LegacyViewManagerInterop"; } // namespace facebook::react + +#endif // RCT_REMOVE_LEGACY_COMPONENT_INTEROP diff --git a/packages/react-native/ReactCommon/react/renderer/components/legacyviewmanagerinterop/LegacyViewManagerInteropShadowNode.h b/packages/react-native/ReactCommon/react/renderer/components/legacyviewmanagerinterop/LegacyViewManagerInteropShadowNode.h index 0372688ae96f..7fa63d88e88e 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/legacyviewmanagerinterop/LegacyViewManagerInteropShadowNode.h +++ b/packages/react-native/ReactCommon/react/renderer/components/legacyviewmanagerinterop/LegacyViewManagerInteropShadowNode.h @@ -7,6 +7,8 @@ #pragma once +#ifndef RCT_REMOVE_LEGACY_COMPONENT_INTEROP + #include #include #include @@ -22,3 +24,5 @@ using LegacyViewManagerInteropShadowNode = ConcreteViewShadowNode< LegacyViewManagerInteropState>; } // namespace facebook::react + +#endif // RCT_REMOVE_LEGACY_COMPONENT_INTEROP diff --git a/packages/react-native/ReactCommon/react/renderer/components/legacyviewmanagerinterop/LegacyViewManagerInteropState.h b/packages/react-native/ReactCommon/react/renderer/components/legacyviewmanagerinterop/LegacyViewManagerInteropState.h index d3ef25302a3e..8b8e4e112db8 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/legacyviewmanagerinterop/LegacyViewManagerInteropState.h +++ b/packages/react-native/ReactCommon/react/renderer/components/legacyviewmanagerinterop/LegacyViewManagerInteropState.h @@ -7,6 +7,8 @@ #pragma once +#ifndef RCT_REMOVE_LEGACY_COMPONENT_INTEROP + #import namespace facebook::react { @@ -20,3 +22,5 @@ class LegacyViewManagerInteropState final { }; } // namespace facebook::react + +#endif // RCT_REMOVE_LEGACY_COMPONENT_INTEROP diff --git a/packages/react-native/ReactCommon/react/renderer/components/legacyviewmanagerinterop/LegacyViewManagerInteropViewProps.cpp b/packages/react-native/ReactCommon/react/renderer/components/legacyviewmanagerinterop/LegacyViewManagerInteropViewProps.cpp index 0b73576a74db..a5acd66e93be 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/legacyviewmanagerinterop/LegacyViewManagerInteropViewProps.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/legacyviewmanagerinterop/LegacyViewManagerInteropViewProps.cpp @@ -6,6 +6,9 @@ */ #include "LegacyViewManagerInteropViewProps.h" + +#ifndef RCT_REMOVE_LEGACY_COMPONENT_INTEROP + #include namespace facebook::react { @@ -21,3 +24,5 @@ LegacyViewManagerInteropViewProps::LegacyViewManagerInteropViewProps( NullValueStrategy::Override)) {} } // namespace facebook::react + +#endif // RCT_REMOVE_LEGACY_COMPONENT_INTEROP diff --git a/packages/react-native/ReactCommon/react/renderer/components/legacyviewmanagerinterop/LegacyViewManagerInteropViewProps.h b/packages/react-native/ReactCommon/react/renderer/components/legacyviewmanagerinterop/LegacyViewManagerInteropViewProps.h index 6b564ecc36fa..a6a1c8c191fd 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/legacyviewmanagerinterop/LegacyViewManagerInteropViewProps.h +++ b/packages/react-native/ReactCommon/react/renderer/components/legacyviewmanagerinterop/LegacyViewManagerInteropViewProps.h @@ -5,6 +5,8 @@ * LICENSE file in the root directory of this source tree. */ +#ifndef RCT_REMOVE_LEGACY_COMPONENT_INTEROP + #include #include #include @@ -26,3 +28,5 @@ class LegacyViewManagerInteropViewProps final : public ViewProps { }; } // namespace facebook::react + +#endif // RCT_REMOVE_LEGACY_COMPONENT_INTEROP diff --git a/packages/react-native/ReactCommon/react/renderer/components/legacyviewmanagerinterop/UnstableLegacyViewManagerAutomaticComponentDescriptor.cpp b/packages/react-native/ReactCommon/react/renderer/components/legacyviewmanagerinterop/UnstableLegacyViewManagerAutomaticComponentDescriptor.cpp index b6ba28e651f8..2b2702455310 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/legacyviewmanagerinterop/UnstableLegacyViewManagerAutomaticComponentDescriptor.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/legacyviewmanagerinterop/UnstableLegacyViewManagerAutomaticComponentDescriptor.cpp @@ -6,6 +6,9 @@ */ #include "UnstableLegacyViewManagerAutomaticComponentDescriptor.h" + +#ifndef RCT_REMOVE_LEGACY_COMPONENT_INTEROP + #include #include #include @@ -24,3 +27,5 @@ UnstableLegacyViewManagerAutomaticComponentDescriptor::getComponentHandle() return reinterpret_cast(getComponentName()); } } // namespace facebook::react + +#endif // RCT_REMOVE_LEGACY_COMPONENT_INTEROP diff --git a/packages/react-native/ReactCommon/react/renderer/components/legacyviewmanagerinterop/UnstableLegacyViewManagerAutomaticComponentDescriptor.h b/packages/react-native/ReactCommon/react/renderer/components/legacyviewmanagerinterop/UnstableLegacyViewManagerAutomaticComponentDescriptor.h index 0f9dd1aabe3c..674fe898f770 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/legacyviewmanagerinterop/UnstableLegacyViewManagerAutomaticComponentDescriptor.h +++ b/packages/react-native/ReactCommon/react/renderer/components/legacyviewmanagerinterop/UnstableLegacyViewManagerAutomaticComponentDescriptor.h @@ -7,6 +7,8 @@ #pragma once +#ifndef RCT_REMOVE_LEGACY_COMPONENT_INTEROP + #include #include #include @@ -33,3 +35,5 @@ class UnstableLegacyViewManagerAutomaticComponentDescriptor final std::string legacyComponentName_; }; } // namespace facebook::react + +#endif // RCT_REMOVE_LEGACY_COMPONENT_INTEROP diff --git a/packages/react-native/ReactCommon/react/renderer/components/legacyviewmanagerinterop/UnstableLegacyViewManagerAutomaticShadowNode.cpp b/packages/react-native/ReactCommon/react/renderer/components/legacyviewmanagerinterop/UnstableLegacyViewManagerAutomaticShadowNode.cpp index f5c24f5310f6..356b617c7e0b 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/legacyviewmanagerinterop/UnstableLegacyViewManagerAutomaticShadowNode.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/legacyviewmanagerinterop/UnstableLegacyViewManagerAutomaticShadowNode.cpp @@ -5,9 +5,13 @@ * LICENSE file in the root directory of this source tree. */ +#ifndef RCT_REMOVE_LEGACY_COMPONENT_INTEROP + namespace facebook::react { extern const char LegacyViewManagerAndroidInteropComponentName[] = "LegacyViewManagerInterop"; } // namespace facebook::react + +#endif // RCT_REMOVE_LEGACY_COMPONENT_INTEROP diff --git a/packages/react-native/ReactCommon/react/renderer/components/legacyviewmanagerinterop/UnstableLegacyViewManagerAutomaticShadowNode.h b/packages/react-native/ReactCommon/react/renderer/components/legacyviewmanagerinterop/UnstableLegacyViewManagerAutomaticShadowNode.h index 6fb431f0d990..bc6a7767f139 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/legacyviewmanagerinterop/UnstableLegacyViewManagerAutomaticShadowNode.h +++ b/packages/react-native/ReactCommon/react/renderer/components/legacyviewmanagerinterop/UnstableLegacyViewManagerAutomaticShadowNode.h @@ -7,6 +7,8 @@ #pragma once +#ifndef RCT_REMOVE_LEGACY_COMPONENT_INTEROP + #include #include @@ -18,3 +20,5 @@ using LegacyViewManagerAndroidInteropShadowNode = ConcreteViewShadowNode; } // namespace facebook::react + +#endif // RCT_REMOVE_LEGACY_COMPONENT_INTEROP diff --git a/packages/react-native/ReactCommon/react/renderer/components/legacyviewmanagerinterop/UnstableLegacyViewManagerInteropComponentDescriptor.h b/packages/react-native/ReactCommon/react/renderer/components/legacyviewmanagerinterop/UnstableLegacyViewManagerInteropComponentDescriptor.h index 9d9d0ff739b1..e3ba08bbd944 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/legacyviewmanagerinterop/UnstableLegacyViewManagerInteropComponentDescriptor.h +++ b/packages/react-native/ReactCommon/react/renderer/components/legacyviewmanagerinterop/UnstableLegacyViewManagerInteropComponentDescriptor.h @@ -7,6 +7,8 @@ #pragma once +#ifndef RCT_REMOVE_LEGACY_COMPONENT_INTEROP + #include #include #include @@ -33,3 +35,5 @@ class UnstableLegacyViewManagerInteropComponentDescriptor }; } // namespace facebook::react + +#endif // RCT_REMOVE_LEGACY_COMPONENT_INTEROP