From 8dddde49b2f3170afceedf988ce05d1dae895d81 Mon Sep 17 00:00:00 2001 From: Nicola Corti Date: Mon, 22 Sep 2025 14:24:33 +0100 Subject: [PATCH] [0.82] Ensure legacy architecture can't be initialized (#53843) * Ensure legacy architecture can't be initialized in Android (#53806) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/53806 The Legacy architecture of React Native is not supported anymore, let's ensure nobody can initialize it anymore changelog: [internal] internal Reviewed By: cortinico Differential Revision: D82465004 fbshipit-source-id: 099764fb59d906b11cf6ad0cc6208f56df029d19 * Runtime check that NewArchitecture is enabled in DefaultNewArchitectureEntryPoint (#53780) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/53780 This is a commit we're going to pick in 0.82 as we want to make sure users cannot invoke `load()` from `DefaultNewArchitectureEntryPoint` with flags that are not true,true,true. Changelog: [Android] [Changed] - Runtime check that NewArchitecture is enabled in DefaultNewArchitectureEntryPoint Reviewed By: mdvacca Differential Revision: D82456975 fbshipit-source-id: 749996a3491913cfe400173608218077c3ffbc10 * Fix DefaultNewArchitectureEntryPoint config validation (#53807) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/53807 We need to read the values off feature flags before checking them. ## Changelog [Internal] Reviewed By: javache Differential Revision: D82572898 fbshipit-source-id: 09fbc09570c78b41d9c25fb03c5557e390da7cae * Fix incorrect validation of feature flags in DefaultNewArchitectureEntryPoint.loadWithFeatureFlags() method (#53863) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/53863 In this diff I'm fixing an incorrect validation of feature flags in DefaultNewArchitectureEntryPoint.loadWithFeatureFlags() method. changelog: [internal] internal Reviewed By: cortinico Differential Revision: D82841006 fbshipit-source-id: 6f50f2475255d7b841d9224bc8808119dcc68aec --------- Co-authored-by: David Vacca Co-authored-by: Eric Rozell --- .../facebook/react/ReactInstanceManager.java | 10 ++++++ .../DefaultNewArchitectureEntryPoint.kt | 26 +++++++++----- .../DefaultNewArchitectureEntryPointTest.kt | 36 ++++++++++++------- 3 files changed, 52 insertions(+), 20 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java index 04affe8015d..090e806461c 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java @@ -328,6 +328,15 @@ public class ReactInstanceManager { } registerCxxErrorHandlerFunc(); + + // Using `if (true)` just to prevent tests / lint errors. + if (true) { + // Legacy architecture of React Native is deprecated and can't be initialized anymore. + // More details on: + // https://github.com/react-native-community/discussions-and-proposals/blob/nc/legacy-arch-removal/proposals/0929-legacy-architecture-removal.md + throw new UnsupportedOperationException( + "ReactInstanceManager.createReactContext is unsupported."); + } } private ReactInstanceDevHelper createDevHelperInterface() { @@ -1446,6 +1455,7 @@ public class ReactInstanceManager { */ private ReactApplicationContext createReactContext( JavaScriptExecutor jsExecutor, JSBundleLoader jsBundleLoader) { + FLog.d(ReactConstants.TAG, "ReactInstanceManager.createReactContext()"); ReactMarker.logMarker(CREATE_REACT_CONTEXT_START, jsExecutor.getName()); diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultNewArchitectureEntryPoint.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultNewArchitectureEntryPoint.kt index ca81f28d83b..cb9cdb1749a 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultNewArchitectureEntryPoint.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultNewArchitectureEntryPoint.kt @@ -125,6 +125,16 @@ public object DefaultNewArchitectureEntryPoint { privateConcurrentReactEnabled = featureFlags.enableFabricRenderer() privateBridgelessEnabled = featureFlags.enableBridgelessArchitecture() + val (isValid, errorMessage) = + isConfigurationValid( + privateTurboModulesEnabled, + privateFabricEnabled, + privateBridgelessEnabled, + ) + if (!isValid) { + error(errorMessage) + } + DefaultSoLoader.maybeLoadSoLibrary() } @@ -158,13 +168,13 @@ public object DefaultNewArchitectureEntryPoint { fabricEnabled: Boolean, bridgelessEnabled: Boolean, ): Pair = - when { - fabricEnabled && !turboModulesEnabled -> - false to - "fabricEnabled=true requires turboModulesEnabled=true (is now false) - Please update your DefaultNewArchitectureEntryPoint.load() parameters." - bridgelessEnabled && (!turboModulesEnabled || !fabricEnabled) -> - false to - "bridgelessEnabled=true requires (turboModulesEnabled=true AND fabricEnabled=true) - Please update your DefaultNewArchitectureEntryPoint.load() parameters." - else -> true to "" + if (!turboModulesEnabled || !fabricEnabled || !bridgelessEnabled) { + false to + "You cannot load React Native with the New Architecture disabled. " + + "Please use DefaultNewArchitectureEntryPoint.load() instead of " + + "DefaultNewArchitectureEntryPoint.load(turboModulesEnabled=$turboModulesEnabled, " + + "fabricEnabled=$fabricEnabled, bridgelessEnabled=$bridgelessEnabled)" + } else { + true to "" } } diff --git a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/defaults/DefaultNewArchitectureEntryPointTest.kt b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/defaults/DefaultNewArchitectureEntryPointTest.kt index 68a1d720572..5727d2fc310 100644 --- a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/defaults/DefaultNewArchitectureEntryPointTest.kt +++ b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/defaults/DefaultNewArchitectureEntryPointTest.kt @@ -13,36 +13,48 @@ import org.junit.Test class DefaultNewArchitectureEntryPointTest { @Test - fun isConfigurationValid_withEverythingOff_returnsTrue() { - val (isValid, _) = + fun isConfigurationValid_withEverythingOff_returnsFalse() { + val (isValid, errorMessage) = DefaultNewArchitectureEntryPoint.isConfigurationValid( turboModulesEnabled = false, fabricEnabled = false, bridgelessEnabled = false, ) - assertThat(isValid).isTrue() + assertThat(isValid).isFalse() + assertThat(errorMessage) + .isEqualTo( + "You cannot load React Native with the New Architecture disabled. Please use DefaultNewArchitectureEntryPoint.load() instead of DefaultNewArchitectureEntryPoint.load(turboModulesEnabled=false, fabricEnabled=false, bridgelessEnabled=false)" + ) } @Test - fun isConfigurationValid_withNewArchOn_returnsTrue() { - val (isValid, _) = + fun isConfigurationValid_withNewArchOnlyOn_returnsFalse() { + val (isValid, errorMessage) = DefaultNewArchitectureEntryPoint.isConfigurationValid( turboModulesEnabled = true, fabricEnabled = true, bridgelessEnabled = false, ) - assertThat(isValid).isTrue() + assertThat(isValid).isFalse() + assertThat(errorMessage) + .isEqualTo( + "You cannot load React Native with the New Architecture disabled. Please use DefaultNewArchitectureEntryPoint.load() instead of DefaultNewArchitectureEntryPoint.load(turboModulesEnabled=true, fabricEnabled=true, bridgelessEnabled=false)" + ) } @Test - fun isConfigurationValid_withTurboModulesOnlyOn_returnsTrue() { - val (isValid, _) = + fun isConfigurationValid_withTurboModulesOnlyOn_returnsFalse() { + val (isValid, errorMessage) = DefaultNewArchitectureEntryPoint.isConfigurationValid( turboModulesEnabled = true, fabricEnabled = false, bridgelessEnabled = false, ) - assertThat(isValid).isTrue() + assertThat(isValid).isFalse() + assertThat(errorMessage) + .isEqualTo( + "You cannot load React Native with the New Architecture disabled. Please use DefaultNewArchitectureEntryPoint.load() instead of DefaultNewArchitectureEntryPoint.load(turboModulesEnabled=true, fabricEnabled=false, bridgelessEnabled=false)" + ) } @Test @@ -67,7 +79,7 @@ class DefaultNewArchitectureEntryPointTest { assertThat(isValid).isFalse() assertThat(errorMessage) .isEqualTo( - "fabricEnabled=true requires turboModulesEnabled=true (is now false) - Please update your DefaultNewArchitectureEntryPoint.load() parameters." + "You cannot load React Native with the New Architecture disabled. Please use DefaultNewArchitectureEntryPoint.load() instead of DefaultNewArchitectureEntryPoint.load(turboModulesEnabled=false, fabricEnabled=true, bridgelessEnabled=false)" ) } @@ -82,7 +94,7 @@ class DefaultNewArchitectureEntryPointTest { assertThat(isValid).isFalse() assertThat(errorMessage) .isEqualTo( - "fabricEnabled=true requires turboModulesEnabled=true (is now false) - Please update your DefaultNewArchitectureEntryPoint.load() parameters." + "You cannot load React Native with the New Architecture disabled. Please use DefaultNewArchitectureEntryPoint.load() instead of DefaultNewArchitectureEntryPoint.load(turboModulesEnabled=false, fabricEnabled=true, bridgelessEnabled=true)" ) } @@ -97,7 +109,7 @@ class DefaultNewArchitectureEntryPointTest { assertThat(isValid).isFalse() assertThat(errorMessage) .isEqualTo( - "bridgelessEnabled=true requires (turboModulesEnabled=true AND fabricEnabled=true) - Please update your DefaultNewArchitectureEntryPoint.load() parameters." + "You cannot load React Native with the New Architecture disabled. Please use DefaultNewArchitectureEntryPoint.load() instead of DefaultNewArchitectureEntryPoint.load(turboModulesEnabled=true, fabricEnabled=false, bridgelessEnabled=true)" ) } }