From b8984a22d9d3d69df6e165e4d51b72bbf06a1107 Mon Sep 17 00:00:00 2001 From: Pieter De Baets Date: Mon, 22 Jul 2024 01:36:02 -0700 Subject: [PATCH] Remove delay between instance start and surface creation (#45545) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/45545 ReactInstance creation in bridgeless returns a callback that requires dispatching on the UI thread to complete the init. If that thread is busy (eg with other startup tasks), we delay starting the initial surface unnecessarily. This diff adds an experiment to return early from that startup task to allow follow-up tasks to be scheduled on the JS thread without waiting for lifecycle changes to have been applied. Changelog: [Internal] Reviewed By: markv Differential Revision: D59961779 --- .../featureflags/ReactNativeFeatureFlags.kt | 8 +- .../ReactNativeFeatureFlagsCxxAccessor.kt | 12 +- .../ReactNativeFeatureFlagsCxxInterop.kt | 4 +- .../ReactNativeFeatureFlagsDefaults.kt | 4 +- .../ReactNativeFeatureFlagsLocalAccessor.kt | 13 +- .../ReactNativeFeatureFlagsProvider.kt | 4 +- .../facebook/react/runtime/ReactHostImpl.java | 243 ++++++++++-------- .../JReactNativeFeatureFlagsCxxInterop.cpp | 16 +- .../JReactNativeFeatureFlagsCxxInterop.h | 5 +- .../featureflags/ReactNativeFeatureFlags.cpp | 6 +- .../featureflags/ReactNativeFeatureFlags.h | 7 +- .../ReactNativeFeatureFlagsAccessor.cpp | 74 ++++-- .../ReactNativeFeatureFlagsAccessor.h | 6 +- .../ReactNativeFeatureFlagsDefaults.h | 6 +- .../ReactNativeFeatureFlagsProvider.h | 3 +- .../NativeReactNativeFeatureFlags.cpp | 7 +- .../NativeReactNativeFeatureFlags.h | 4 +- .../ReactNativeFeatureFlags.config.js | 5 + .../featureflags/ReactNativeFeatureFlags.js | 7 +- .../specs/NativeReactNativeFeatureFlags.js | 3 +- 20 files changed, 280 insertions(+), 157 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt index 4d3932fc3dc4..3fd9cab87e06 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<3fa1a97be20aa80ef7a1e1595bee0dac>> + * @generated SignedSource<<687c29d850df9a857749d06c54cbddb7>> */ /** @@ -58,6 +58,12 @@ public object ReactNativeFeatureFlags { @JvmStatic public fun changeOrderOfMountingInstructionsOnAndroid(): Boolean = accessor.changeOrderOfMountingInstructionsOnAndroid() + /** + * Do not wait for a main-thread dispatch to complete init to start executing work on the JS thread on Android + */ + @JvmStatic + public fun completeReactInstanceCreationOnBgThreadOnAndroid(): Boolean = accessor.completeReactInstanceCreationOnBgThreadOnAndroid() + /** * When enabled, ReactInstanceManager will clean up Fabric surfaces on destroy(). */ diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt index 6c5f44ced848..d015715e250c 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<89b4a679d8121ece9291dd55c46567ad>> + * @generated SignedSource<> */ /** @@ -25,6 +25,7 @@ public class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAccesso private var allowRecursiveCommitsWithSynchronousMountOnAndroidCache: Boolean? = null private var batchRenderingUpdatesInEventLoopCache: Boolean? = null private var changeOrderOfMountingInstructionsOnAndroidCache: Boolean? = null + private var completeReactInstanceCreationOnBgThreadOnAndroidCache: Boolean? = null private var destroyFabricSurfacesInReactInstanceManagerCache: Boolean? = null private var enableAlignItemsBaselineOnFabricIOSCache: Boolean? = null private var enableCleanTextInputYogaNodeCache: Boolean? = null @@ -98,6 +99,15 @@ public class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAccesso return cached } + override fun completeReactInstanceCreationOnBgThreadOnAndroid(): Boolean { + var cached = completeReactInstanceCreationOnBgThreadOnAndroidCache + if (cached == null) { + cached = ReactNativeFeatureFlagsCxxInterop.completeReactInstanceCreationOnBgThreadOnAndroid() + completeReactInstanceCreationOnBgThreadOnAndroidCache = cached + } + return cached + } + override fun destroyFabricSurfacesInReactInstanceManager(): Boolean { var cached = destroyFabricSurfacesInReactInstanceManagerCache if (cached == null) { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt index c371dd0a3c84..73489e6f07a8 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<98bd8f4b2b262ac3e75897da515706f5>> + * @generated SignedSource<> */ /** @@ -38,6 +38,8 @@ public object ReactNativeFeatureFlagsCxxInterop { @DoNotStrip @JvmStatic public external fun changeOrderOfMountingInstructionsOnAndroid(): Boolean + @DoNotStrip @JvmStatic public external fun completeReactInstanceCreationOnBgThreadOnAndroid(): Boolean + @DoNotStrip @JvmStatic public external fun destroyFabricSurfacesInReactInstanceManager(): Boolean @DoNotStrip @JvmStatic public external fun enableAlignItemsBaselineOnFabricIOS(): Boolean diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt index d5b910ea1d1a..072db8e72a0d 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<8903d3fb0088fcdd9ac3e789299b8b6c>> */ /** @@ -33,6 +33,8 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi override fun changeOrderOfMountingInstructionsOnAndroid(): Boolean = false + override fun completeReactInstanceCreationOnBgThreadOnAndroid(): Boolean = false + override fun destroyFabricSurfacesInReactInstanceManager(): Boolean = false override fun enableAlignItemsBaselineOnFabricIOS(): Boolean = true diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt index 2de5f3a7d44b..4e095d9baeed 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<96ed168a0e80e78d1d6f96374f045eca>> + * @generated SignedSource<> */ /** @@ -29,6 +29,7 @@ public class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcces private var allowRecursiveCommitsWithSynchronousMountOnAndroidCache: Boolean? = null private var batchRenderingUpdatesInEventLoopCache: Boolean? = null private var changeOrderOfMountingInstructionsOnAndroidCache: Boolean? = null + private var completeReactInstanceCreationOnBgThreadOnAndroidCache: Boolean? = null private var destroyFabricSurfacesInReactInstanceManagerCache: Boolean? = null private var enableAlignItemsBaselineOnFabricIOSCache: Boolean? = null private var enableCleanTextInputYogaNodeCache: Boolean? = null @@ -107,6 +108,16 @@ public class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcces return cached } + override fun completeReactInstanceCreationOnBgThreadOnAndroid(): Boolean { + var cached = completeReactInstanceCreationOnBgThreadOnAndroidCache + if (cached == null) { + cached = currentProvider.completeReactInstanceCreationOnBgThreadOnAndroid() + accessedFeatureFlags.add("completeReactInstanceCreationOnBgThreadOnAndroid") + completeReactInstanceCreationOnBgThreadOnAndroidCache = cached + } + return cached + } + override fun destroyFabricSurfacesInReactInstanceManager(): Boolean { var cached = destroyFabricSurfacesInReactInstanceManagerCache if (cached == null) { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt index 9e73803e3fda..ade464ad88c2 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<13469640e36f5985531f872b28ff0c30>> + * @generated SignedSource<<0284ff2541a06bfa36bb7049d47cb4d2>> */ /** @@ -33,6 +33,8 @@ public interface ReactNativeFeatureFlagsProvider { @DoNotStrip public fun changeOrderOfMountingInstructionsOnAndroid(): Boolean + @DoNotStrip public fun completeReactInstanceCreationOnBgThreadOnAndroid(): Boolean + @DoNotStrip public fun destroyFabricSurfacesInReactInstanceManager(): Boolean @DoNotStrip public fun enableAlignItemsBaselineOnFabricIOS(): Boolean diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.java index 06d0fadfc1c5..ceac67cccc77 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.java @@ -62,6 +62,7 @@ import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler; import com.facebook.react.modules.core.DeviceEventManagerModule; import com.facebook.react.modules.systeminfo.AndroidInfoHelpers; +import com.facebook.react.runtime.internal.bolts.Continuation; import com.facebook.react.runtime.internal.bolts.Task; import com.facebook.react.runtime.internal.bolts.TaskCompletionSource; import com.facebook.react.turbomodule.core.interfaces.CallInvokerHolder; @@ -949,7 +950,10 @@ private Task callWithExistingReactInstance( .get() .onSuccess( task -> { - final ReactInstance reactInstance = mReactInstance; + final ReactInstance reactInstance = + ReactNativeFeatureFlags.completeReactInstanceCreationOnBgThreadOnAndroid() + ? task.getResult() + : mReactInstance; if (reactInstance == null) { raiseSoftException(method, "Execute: reactInstance is null. Dropping work."); return FALSE; @@ -975,7 +979,10 @@ private Task callAfterGetOrCreateReactInstance( return getOrCreateReactInstance() .onSuccess( task -> { - final ReactInstance reactInstance = mReactInstance; + final ReactInstance reactInstance = + ReactNativeFeatureFlags.completeReactInstanceCreationOnBgThreadOnAndroid() + ? task.getResult() + : mReactInstance; if (reactInstance == null) { raiseSoftException(method, "Execute: reactInstance is null. Dropping work."); return null; @@ -1050,6 +1057,18 @@ private Task waitThenCallGetOrCreateReactInstanceTaskWithRetries( return getOrCreateReactInstanceTask(); } + private static class CreationResult { + final ReactInstance mInstance; + final ReactContext mContext; + final boolean mIsReloading; + + private CreationResult(ReactInstance instance, ReactContext context, boolean isReloading) { + mInstance = instance; + mContext = context; + mIsReloading = isReloading; + } + } + @ThreadConfined("ReactHost") private Task getOrCreateReactInstanceTask() { final String method = "getOrCreateReactInstanceTask()"; @@ -1064,116 +1083,118 @@ private Task getOrCreateReactInstanceTask() { ReactMarker.logMarker( ReactMarkerConstants.REACT_BRIDGELESS_LOADING_START, BRIDGELESS_MARKER_INSTANCE_KEY); - return getJsBundleLoader() - .onSuccess( - task -> { - final JSBundleLoader bundleLoader = task.getResult(); - final BridgelessReactContext reactContext = getOrCreateReactContext(); - final DevSupportManager devSupportManager = getDevSupportManager(); - reactContext.setJSExceptionHandler(devSupportManager); - - log(method, "Creating ReactInstance"); - final ReactInstance instance = - new ReactInstance( - reactContext, - mReactHostDelegate, - mComponentFactory, - devSupportManager, - this::handleHostException, - mUseDevSupport, - getOrCreateReactHostInspectorTarget()); - mReactInstance = instance; - - MemoryPressureListener memoryPressureListener = - createMemoryPressureListener(instance); - mMemoryPressureListener = memoryPressureListener; - mMemoryPressureRouter.addMemoryPressureListener(memoryPressureListener); - - // Eagerly initialize turbo modules in parallel with JS bundle execution - // as TurboModuleManager will handle any concurrent access - instance.initializeEagerTurboModules(); - - log(method, "Loading JS Bundle"); - instance.loadJSBundle(bundleLoader); - - log( - method, - "Calling DevSupportManagerBase.onNewReactContextCreated(reactContext)"); - devSupportManager.onNewReactContextCreated(reactContext); - - reactContext.runOnJSQueueThread( - () -> { - // Executing on the JS thread to ensurethat we're done - // loading the JS bundle. - // TODO T76081936 Move this if we switch to a sync RTE - ReactMarker.logMarker( - ReactMarkerConstants.REACT_BRIDGELESS_LOADING_END, - BRIDGELESS_MARKER_INSTANCE_KEY); - }); - - class Result { - final ReactInstance mInstance = instance; - final ReactContext mContext = reactContext; - final boolean mIsReloading = mReloadTask != null; - } - - return new Result(); - }, - mBGExecutor) - .onSuccess( - task -> { - final ReactInstance reactInstance = task.getResult().mInstance; - final ReactContext reactContext = task.getResult().mContext; - final boolean isReloading = task.getResult().mIsReloading; - final boolean isManagerResumed = - mReactLifecycleStateManager.getLifecycleState() == LifecycleState.RESUMED; - - /** - * ReactContext.onHostResume() should only be called when the user navigates to - * the first React Native screen. - * - *

During init: The application puts the React manager in a resumed state, - * when the user navigates to a React Native screen. Two types of init: (1) If - * React Native init happens when the user navigates to a React Native screen, - * the React manager will get resumed on init start, so - * ReactContext.onHostResume() will be executed here. (2) If React Native init - * happens before the user navigates to a React Native screen (i.e: React Native - * is preloaded), the React manager won't be in a resumed state here. So - * ReactContext.onHostResume() won't be executed here. But, when the user - * navigates to their first React Native screen, the application will call - * ReactHost.onHostResume(). That will call ReactContext.onHostResume(). - * - *

During reloads, if the manager isn't resumed, call - * ReactContext.onHostResume(). If React Native is reloading, it seems - * reasonable to assume that: (1) We must have navigated to a React Native - * screen in the past, or (2) We must be on a React Native screen. - */ - if (isReloading && !isManagerResumed) { - mReactLifecycleStateManager.moveToOnHostResume( - reactContext, getCurrentActivity()); - } else { - /** - * Call ReactContext.onHostResume() only when already in the resumed state - * which aligns with the bridge https://fburl.com/diffusion/2qhxmudv. - */ - mReactLifecycleStateManager.resumeReactContextIfHostResumed( - reactContext, getCurrentActivity()); - } + Task creationTask = + getJsBundleLoader() + .onSuccess( + task -> { + final JSBundleLoader bundleLoader = task.getResult(); + final BridgelessReactContext reactContext = getOrCreateReactContext(); + final DevSupportManager devSupportManager = getDevSupportManager(); + reactContext.setJSExceptionHandler(devSupportManager); + + log(method, "Creating ReactInstance"); + final ReactInstance instance = + new ReactInstance( + reactContext, + mReactHostDelegate, + mComponentFactory, + devSupportManager, + this::handleHostException, + mUseDevSupport, + getOrCreateReactHostInspectorTarget()); + mReactInstance = instance; + + MemoryPressureListener memoryPressureListener = + createMemoryPressureListener(instance); + mMemoryPressureListener = memoryPressureListener; + mMemoryPressureRouter.addMemoryPressureListener(memoryPressureListener); + + // Eagerly initialize turbo modules in parallel with JS bundle execution + // as TurboModuleManager will handle any concurrent access + instance.initializeEagerTurboModules(); + + log(method, "Loading JS Bundle"); + instance.loadJSBundle(bundleLoader); + + log( + method, + "Calling DevSupportManagerBase.onNewReactContextCreated(reactContext)"); + devSupportManager.onNewReactContextCreated(reactContext); + + reactContext.runOnJSQueueThread( + () -> { + // Executing on the JS thread to ensure that we're done + // loading the JS bundle. + // TODO T76081936 Move this if we switch to a sync RTE + ReactMarker.logMarker( + ReactMarkerConstants.REACT_BRIDGELESS_LOADING_END, + BRIDGELESS_MARKER_INSTANCE_KEY); + }); + + return new CreationResult(instance, reactContext, mReloadTask != null); + }, + mBGExecutor); + + Continuation lifecycleUpdateTask = + task -> { + final ReactInstance reactInstance = task.getResult().mInstance; + final ReactContext reactContext = task.getResult().mContext; + final boolean isReloading = task.getResult().mIsReloading; + final boolean isManagerResumed = + mReactLifecycleStateManager.getLifecycleState() == LifecycleState.RESUMED; + + /** + * ReactContext.onHostResume() should only be called when the user navigates to the + * first React Native screen. + * + *

During init: The application puts the React manager in a resumed state, when + * the user navigates to a React Native screen. Two types of init: (1) If React + * Native init happens when the user navigates to a React Native screen, the React + * manager will get resumed on init start, so ReactContext.onHostResume() will be + * executed here. (2) If React Native init happens before the user navigates to a + * React Native screen (i.e: React Native is preloaded), the React manager won't be + * in a resumed state here. So ReactContext.onHostResume() won't be executed here. + * But, when the user navigates to their first React Native screen, the application + * will call ReactHost.onHostResume(). That will call ReactContext.onHostResume(). + * + *

During reloads, if the manager isn't resumed, call + * ReactContext.onHostResume(). If React Native is reloading, it seems reasonable to + * assume that: (1) We must have navigated to a React Native screen in the past, or + * (2) We must be on a React Native screen. + */ + if (isReloading && !isManagerResumed) { + mReactLifecycleStateManager.moveToOnHostResume( + reactContext, getCurrentActivity()); + } else { + /** + * Call ReactContext.onHostResume() only when already in the resumed state which + * aligns with the bridge https://fburl.com/diffusion/2qhxmudv. + */ + mReactLifecycleStateManager.resumeReactContextIfHostResumed( + reactContext, getCurrentActivity()); + } - log(method, "Executing ReactInstanceEventListeners"); - ReactInstanceEventListener[] instanceEventListeners; - synchronized (mReactInstanceEventListeners) { - instanceEventListeners = - mReactInstanceEventListeners.toArray(new ReactInstanceEventListener[0]); - } - for (ReactInstanceEventListener listener : instanceEventListeners) { - if (listener != null) { - listener.onReactContextInitialized(reactContext); - } - } - return reactInstance; - }, - mUIExecutor); + log(method, "Executing ReactInstanceEventListeners"); + ReactInstanceEventListener[] instanceEventListeners; + synchronized (mReactInstanceEventListeners) { + instanceEventListeners = + mReactInstanceEventListeners.toArray(new ReactInstanceEventListener[0]); + } + for (ReactInstanceEventListener listener : instanceEventListeners) { + if (listener != null) { + listener.onReactContextInitialized(reactContext); + } + } + return reactInstance; + }; + + if (ReactNativeFeatureFlags.completeReactInstanceCreationOnBgThreadOnAndroid()) { + creationTask.onSuccess(lifecycleUpdateTask, mUIExecutor); + return creationTask.onSuccess( + task -> task.getResult().mInstance, Task.IMMEDIATE_EXECUTOR); + } else { + return creationTask.onSuccess(lifecycleUpdateTask, mUIExecutor); + } }); } diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp index 46d1431650d5..fa825c68adf1 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp +++ b/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<8efce8efb9cc312512b8736ed0073b30>> + * @generated SignedSource<> */ /** @@ -69,6 +69,12 @@ class ReactNativeFeatureFlagsProviderHolder return method(javaProvider_); } + bool completeReactInstanceCreationOnBgThreadOnAndroid() override { + static const auto method = + getReactNativeFeatureFlagsProviderJavaClass()->getMethod("completeReactInstanceCreationOnBgThreadOnAndroid"); + return method(javaProvider_); + } + bool destroyFabricSurfacesInReactInstanceManager() override { static const auto method = getReactNativeFeatureFlagsProviderJavaClass()->getMethod("destroyFabricSurfacesInReactInstanceManager"); @@ -260,6 +266,11 @@ bool JReactNativeFeatureFlagsCxxInterop::changeOrderOfMountingInstructionsOnAndr return ReactNativeFeatureFlags::changeOrderOfMountingInstructionsOnAndroid(); } +bool JReactNativeFeatureFlagsCxxInterop::completeReactInstanceCreationOnBgThreadOnAndroid( + facebook::jni::alias_ref /*unused*/) { + return ReactNativeFeatureFlags::completeReactInstanceCreationOnBgThreadOnAndroid(); +} + bool JReactNativeFeatureFlagsCxxInterop::destroyFabricSurfacesInReactInstanceManager( facebook::jni::alias_ref /*unused*/) { return ReactNativeFeatureFlags::destroyFabricSurfacesInReactInstanceManager(); @@ -427,6 +438,9 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() { makeNativeMethod( "changeOrderOfMountingInstructionsOnAndroid", JReactNativeFeatureFlagsCxxInterop::changeOrderOfMountingInstructionsOnAndroid), + makeNativeMethod( + "completeReactInstanceCreationOnBgThreadOnAndroid", + JReactNativeFeatureFlagsCxxInterop::completeReactInstanceCreationOnBgThreadOnAndroid), makeNativeMethod( "destroyFabricSurfacesInReactInstanceManager", JReactNativeFeatureFlagsCxxInterop::destroyFabricSurfacesInReactInstanceManager), diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h b/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h index 7f180c57cd22..0950344e1825 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h +++ b/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<732d3c3f973e966f958945c566de2870>> */ /** @@ -45,6 +45,9 @@ class JReactNativeFeatureFlagsCxxInterop static bool changeOrderOfMountingInstructionsOnAndroid( facebook::jni::alias_ref); + static bool completeReactInstanceCreationOnBgThreadOnAndroid( + facebook::jni::alias_ref); + static bool destroyFabricSurfacesInReactInstanceManager( facebook::jni::alias_ref); diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp index 22b75fdcd4eb..57b88a764020 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<38c8d62457ec2b8c6333131c68dd4935>> */ /** @@ -41,6 +41,10 @@ bool ReactNativeFeatureFlags::changeOrderOfMountingInstructionsOnAndroid() { return getAccessor().changeOrderOfMountingInstructionsOnAndroid(); } +bool ReactNativeFeatureFlags::completeReactInstanceCreationOnBgThreadOnAndroid() { + return getAccessor().completeReactInstanceCreationOnBgThreadOnAndroid(); +} + bool ReactNativeFeatureFlags::destroyFabricSurfacesInReactInstanceManager() { return getAccessor().destroyFabricSurfacesInReactInstanceManager(); } diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h index a869cf314131..5eda8e84567e 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<5b0c518e45a5c98814c8151870aed591>> + * @generated SignedSource<<64e825121244867e1ee6b1b8e54158f2>> */ /** @@ -62,6 +62,11 @@ class ReactNativeFeatureFlags { */ RN_EXPORT static bool changeOrderOfMountingInstructionsOnAndroid(); + /** + * Do not wait for a main-thread dispatch to complete init to start executing work on the JS thread on Android + */ + RN_EXPORT static bool completeReactInstanceCreationOnBgThreadOnAndroid(); + /** * When enabled, ReactInstanceManager will clean up Fabric surfaces on destroy(). */ diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp index baddfd65feed..97e58fbc5962 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<18ca9d8ecd307861ff00736d18c517f4>> + * @generated SignedSource<> */ /** @@ -119,6 +119,24 @@ bool ReactNativeFeatureFlagsAccessor::changeOrderOfMountingInstructionsOnAndroid return flagValue.value(); } +bool ReactNativeFeatureFlagsAccessor::completeReactInstanceCreationOnBgThreadOnAndroid() { + auto flagValue = completeReactInstanceCreationOnBgThreadOnAndroid_.load(); + + if (!flagValue.has_value()) { + // This block is not exclusive but it is not necessary. + // If multiple threads try to initialize the feature flag, we would only + // be accessing the provider multiple times but the end state of this + // instance and the returned flag value would be the same. + + markFlagAsAccessed(5, "completeReactInstanceCreationOnBgThreadOnAndroid"); + + flagValue = currentProvider_->completeReactInstanceCreationOnBgThreadOnAndroid(); + completeReactInstanceCreationOnBgThreadOnAndroid_ = flagValue; + } + + return flagValue.value(); +} + bool ReactNativeFeatureFlagsAccessor::destroyFabricSurfacesInReactInstanceManager() { auto flagValue = destroyFabricSurfacesInReactInstanceManager_.load(); @@ -128,7 +146,7 @@ bool ReactNativeFeatureFlagsAccessor::destroyFabricSurfacesInReactInstanceManage // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(5, "destroyFabricSurfacesInReactInstanceManager"); + markFlagAsAccessed(6, "destroyFabricSurfacesInReactInstanceManager"); flagValue = currentProvider_->destroyFabricSurfacesInReactInstanceManager(); destroyFabricSurfacesInReactInstanceManager_ = flagValue; @@ -146,7 +164,7 @@ bool ReactNativeFeatureFlagsAccessor::enableAlignItemsBaselineOnFabricIOS() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(6, "enableAlignItemsBaselineOnFabricIOS"); + markFlagAsAccessed(7, "enableAlignItemsBaselineOnFabricIOS"); flagValue = currentProvider_->enableAlignItemsBaselineOnFabricIOS(); enableAlignItemsBaselineOnFabricIOS_ = flagValue; @@ -164,7 +182,7 @@ bool ReactNativeFeatureFlagsAccessor::enableCleanTextInputYogaNode() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(7, "enableCleanTextInputYogaNode"); + markFlagAsAccessed(8, "enableCleanTextInputYogaNode"); flagValue = currentProvider_->enableCleanTextInputYogaNode(); enableCleanTextInputYogaNode_ = flagValue; @@ -182,7 +200,7 @@ bool ReactNativeFeatureFlagsAccessor::enableGranularShadowTreeStateReconciliatio // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(8, "enableGranularShadowTreeStateReconciliation"); + markFlagAsAccessed(9, "enableGranularShadowTreeStateReconciliation"); flagValue = currentProvider_->enableGranularShadowTreeStateReconciliation(); enableGranularShadowTreeStateReconciliation_ = flagValue; @@ -200,7 +218,7 @@ bool ReactNativeFeatureFlagsAccessor::enableLongTaskAPI() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(9, "enableLongTaskAPI"); + markFlagAsAccessed(10, "enableLongTaskAPI"); flagValue = currentProvider_->enableLongTaskAPI(); enableLongTaskAPI_ = flagValue; @@ -218,7 +236,7 @@ bool ReactNativeFeatureFlagsAccessor::enableMicrotasks() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(10, "enableMicrotasks"); + markFlagAsAccessed(11, "enableMicrotasks"); flagValue = currentProvider_->enableMicrotasks(); enableMicrotasks_ = flagValue; @@ -236,7 +254,7 @@ bool ReactNativeFeatureFlagsAccessor::enablePropsUpdateReconciliationAndroid() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(11, "enablePropsUpdateReconciliationAndroid"); + markFlagAsAccessed(12, "enablePropsUpdateReconciliationAndroid"); flagValue = currentProvider_->enablePropsUpdateReconciliationAndroid(); enablePropsUpdateReconciliationAndroid_ = flagValue; @@ -254,7 +272,7 @@ bool ReactNativeFeatureFlagsAccessor::enableSynchronousStateUpdates() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(12, "enableSynchronousStateUpdates"); + markFlagAsAccessed(13, "enableSynchronousStateUpdates"); flagValue = currentProvider_->enableSynchronousStateUpdates(); enableSynchronousStateUpdates_ = flagValue; @@ -272,7 +290,7 @@ bool ReactNativeFeatureFlagsAccessor::enableUIConsistency() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(13, "enableUIConsistency"); + markFlagAsAccessed(14, "enableUIConsistency"); flagValue = currentProvider_->enableUIConsistency(); enableUIConsistency_ = flagValue; @@ -290,7 +308,7 @@ bool ReactNativeFeatureFlagsAccessor::fetchImagesInViewPreallocation() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(14, "fetchImagesInViewPreallocation"); + markFlagAsAccessed(15, "fetchImagesInViewPreallocation"); flagValue = currentProvider_->fetchImagesInViewPreallocation(); fetchImagesInViewPreallocation_ = flagValue; @@ -308,7 +326,7 @@ bool ReactNativeFeatureFlagsAccessor::fixIncorrectScrollViewStateUpdateOnAndroid // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(15, "fixIncorrectScrollViewStateUpdateOnAndroid"); + markFlagAsAccessed(16, "fixIncorrectScrollViewStateUpdateOnAndroid"); flagValue = currentProvider_->fixIncorrectScrollViewStateUpdateOnAndroid(); fixIncorrectScrollViewStateUpdateOnAndroid_ = flagValue; @@ -326,7 +344,7 @@ bool ReactNativeFeatureFlagsAccessor::fixMappingOfEventPrioritiesBetweenFabricAn // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(16, "fixMappingOfEventPrioritiesBetweenFabricAndReact"); + markFlagAsAccessed(17, "fixMappingOfEventPrioritiesBetweenFabricAndReact"); flagValue = currentProvider_->fixMappingOfEventPrioritiesBetweenFabricAndReact(); fixMappingOfEventPrioritiesBetweenFabricAndReact_ = flagValue; @@ -344,7 +362,7 @@ bool ReactNativeFeatureFlagsAccessor::fixMissedFabricStateUpdatesOnAndroid() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(17, "fixMissedFabricStateUpdatesOnAndroid"); + markFlagAsAccessed(18, "fixMissedFabricStateUpdatesOnAndroid"); flagValue = currentProvider_->fixMissedFabricStateUpdatesOnAndroid(); fixMissedFabricStateUpdatesOnAndroid_ = flagValue; @@ -362,7 +380,7 @@ bool ReactNativeFeatureFlagsAccessor::forceBatchingMountItemsOnAndroid() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(18, "forceBatchingMountItemsOnAndroid"); + markFlagAsAccessed(19, "forceBatchingMountItemsOnAndroid"); flagValue = currentProvider_->forceBatchingMountItemsOnAndroid(); forceBatchingMountItemsOnAndroid_ = flagValue; @@ -380,7 +398,7 @@ bool ReactNativeFeatureFlagsAccessor::fuseboxEnabledDebug() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(19, "fuseboxEnabledDebug"); + markFlagAsAccessed(20, "fuseboxEnabledDebug"); flagValue = currentProvider_->fuseboxEnabledDebug(); fuseboxEnabledDebug_ = flagValue; @@ -398,7 +416,7 @@ bool ReactNativeFeatureFlagsAccessor::fuseboxEnabledRelease() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(20, "fuseboxEnabledRelease"); + markFlagAsAccessed(21, "fuseboxEnabledRelease"); flagValue = currentProvider_->fuseboxEnabledRelease(); fuseboxEnabledRelease_ = flagValue; @@ -416,7 +434,7 @@ bool ReactNativeFeatureFlagsAccessor::initEagerTurboModulesOnNativeModulesQueueA // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(21, "initEagerTurboModulesOnNativeModulesQueueAndroid"); + markFlagAsAccessed(22, "initEagerTurboModulesOnNativeModulesQueueAndroid"); flagValue = currentProvider_->initEagerTurboModulesOnNativeModulesQueueAndroid(); initEagerTurboModulesOnNativeModulesQueueAndroid_ = flagValue; @@ -434,7 +452,7 @@ bool ReactNativeFeatureFlagsAccessor::lazyAnimationCallbacks() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(22, "lazyAnimationCallbacks"); + markFlagAsAccessed(23, "lazyAnimationCallbacks"); flagValue = currentProvider_->lazyAnimationCallbacks(); lazyAnimationCallbacks_ = flagValue; @@ -452,7 +470,7 @@ bool ReactNativeFeatureFlagsAccessor::loadVectorDrawablesOnImages() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(23, "loadVectorDrawablesOnImages"); + markFlagAsAccessed(24, "loadVectorDrawablesOnImages"); flagValue = currentProvider_->loadVectorDrawablesOnImages(); loadVectorDrawablesOnImages_ = flagValue; @@ -470,7 +488,7 @@ bool ReactNativeFeatureFlagsAccessor::setAndroidLayoutDirection() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(24, "setAndroidLayoutDirection"); + markFlagAsAccessed(25, "setAndroidLayoutDirection"); flagValue = currentProvider_->setAndroidLayoutDirection(); setAndroidLayoutDirection_ = flagValue; @@ -488,7 +506,7 @@ bool ReactNativeFeatureFlagsAccessor::useImmediateExecutorInAndroidBridgeless() // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(25, "useImmediateExecutorInAndroidBridgeless"); + markFlagAsAccessed(26, "useImmediateExecutorInAndroidBridgeless"); flagValue = currentProvider_->useImmediateExecutorInAndroidBridgeless(); useImmediateExecutorInAndroidBridgeless_ = flagValue; @@ -506,7 +524,7 @@ bool ReactNativeFeatureFlagsAccessor::useModernRuntimeScheduler() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(26, "useModernRuntimeScheduler"); + markFlagAsAccessed(27, "useModernRuntimeScheduler"); flagValue = currentProvider_->useModernRuntimeScheduler(); useModernRuntimeScheduler_ = flagValue; @@ -524,7 +542,7 @@ bool ReactNativeFeatureFlagsAccessor::useNativeViewConfigsInBridgelessMode() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(27, "useNativeViewConfigsInBridgelessMode"); + markFlagAsAccessed(28, "useNativeViewConfigsInBridgelessMode"); flagValue = currentProvider_->useNativeViewConfigsInBridgelessMode(); useNativeViewConfigsInBridgelessMode_ = flagValue; @@ -542,7 +560,7 @@ bool ReactNativeFeatureFlagsAccessor::useNewReactImageViewBackgroundDrawing() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(28, "useNewReactImageViewBackgroundDrawing"); + markFlagAsAccessed(29, "useNewReactImageViewBackgroundDrawing"); flagValue = currentProvider_->useNewReactImageViewBackgroundDrawing(); useNewReactImageViewBackgroundDrawing_ = flagValue; @@ -560,7 +578,7 @@ bool ReactNativeFeatureFlagsAccessor::useRuntimeShadowNodeReferenceUpdate() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(29, "useRuntimeShadowNodeReferenceUpdate"); + markFlagAsAccessed(30, "useRuntimeShadowNodeReferenceUpdate"); flagValue = currentProvider_->useRuntimeShadowNodeReferenceUpdate(); useRuntimeShadowNodeReferenceUpdate_ = flagValue; @@ -578,7 +596,7 @@ bool ReactNativeFeatureFlagsAccessor::useRuntimeShadowNodeReferenceUpdateOnLayou // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(30, "useRuntimeShadowNodeReferenceUpdateOnLayout"); + markFlagAsAccessed(31, "useRuntimeShadowNodeReferenceUpdateOnLayout"); flagValue = currentProvider_->useRuntimeShadowNodeReferenceUpdateOnLayout(); useRuntimeShadowNodeReferenceUpdateOnLayout_ = flagValue; @@ -596,7 +614,7 @@ bool ReactNativeFeatureFlagsAccessor::useStateAlignmentMechanism() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(31, "useStateAlignmentMechanism"); + markFlagAsAccessed(32, "useStateAlignmentMechanism"); flagValue = currentProvider_->useStateAlignmentMechanism(); useStateAlignmentMechanism_ = flagValue; diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h index 8d03c5414541..72904401056f 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<6f05e241733069ee1bacf671365d8390>> + * @generated SignedSource<<34b4357de2df4d7b5a5022c7d29451d3>> */ /** @@ -36,6 +36,7 @@ class ReactNativeFeatureFlagsAccessor { bool allowRecursiveCommitsWithSynchronousMountOnAndroid(); bool batchRenderingUpdatesInEventLoop(); bool changeOrderOfMountingInstructionsOnAndroid(); + bool completeReactInstanceCreationOnBgThreadOnAndroid(); bool destroyFabricSurfacesInReactInstanceManager(); bool enableAlignItemsBaselineOnFabricIOS(); bool enableCleanTextInputYogaNode(); @@ -73,13 +74,14 @@ class ReactNativeFeatureFlagsAccessor { std::unique_ptr currentProvider_; bool wasOverridden_; - std::array, 32> accessedFeatureFlags_; + std::array, 33> accessedFeatureFlags_; std::atomic> commonTestFlag_; std::atomic> allowCollapsableChildren_; std::atomic> allowRecursiveCommitsWithSynchronousMountOnAndroid_; std::atomic> batchRenderingUpdatesInEventLoop_; std::atomic> changeOrderOfMountingInstructionsOnAndroid_; + std::atomic> completeReactInstanceCreationOnBgThreadOnAndroid_; std::atomic> destroyFabricSurfacesInReactInstanceManager_; std::atomic> enableAlignItemsBaselineOnFabricIOS_; std::atomic> enableCleanTextInputYogaNode_; diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h index 08fd5e08631f..0264a02e1edc 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<308807b5ebe2d3d1d17452b73be2d82b>> */ /** @@ -47,6 +47,10 @@ class ReactNativeFeatureFlagsDefaults : public ReactNativeFeatureFlagsProvider { return false; } + bool completeReactInstanceCreationOnBgThreadOnAndroid() override { + return false; + } + bool destroyFabricSurfacesInReactInstanceManager() override { return false; } diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h index 215a3992df4c..3b55a35033dc 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<21fa85ad4854cc37f3699a3adcb15813>> + * @generated SignedSource<<54eb612f9d3cb0c7214ed32263ab9318>> */ /** @@ -30,6 +30,7 @@ class ReactNativeFeatureFlagsProvider { virtual bool allowRecursiveCommitsWithSynchronousMountOnAndroid() = 0; virtual bool batchRenderingUpdatesInEventLoop() = 0; virtual bool changeOrderOfMountingInstructionsOnAndroid() = 0; + virtual bool completeReactInstanceCreationOnBgThreadOnAndroid() = 0; virtual bool destroyFabricSurfacesInReactInstanceManager() = 0; virtual bool enableAlignItemsBaselineOnFabricIOS() = 0; virtual bool enableCleanTextInputYogaNode() = 0; diff --git a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp index 16997bb5f425..5163a2133d5a 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp +++ b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<8240a36100c3657e90d6388afdcf26e8>> + * @generated SignedSource<<601dcb3b536fc5452b51049c96383139>> */ /** @@ -62,6 +62,11 @@ bool NativeReactNativeFeatureFlags::changeOrderOfMountingInstructionsOnAndroid( return ReactNativeFeatureFlags::changeOrderOfMountingInstructionsOnAndroid(); } +bool NativeReactNativeFeatureFlags::completeReactInstanceCreationOnBgThreadOnAndroid( + jsi::Runtime& /*runtime*/) { + return ReactNativeFeatureFlags::completeReactInstanceCreationOnBgThreadOnAndroid(); +} + bool NativeReactNativeFeatureFlags::destroyFabricSurfacesInReactInstanceManager( jsi::Runtime& /*runtime*/) { return ReactNativeFeatureFlags::destroyFabricSurfacesInReactInstanceManager(); diff --git a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h index 4c5d6ddca1b5..0454be1baa42 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h +++ b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<36ba8783cdd7ccb5d745dffb978d13ec>> + * @generated SignedSource<<6514becef3f2e550d7de6d089a2400db>> */ /** @@ -45,6 +45,8 @@ class NativeReactNativeFeatureFlags bool changeOrderOfMountingInstructionsOnAndroid(jsi::Runtime& runtime); + bool completeReactInstanceCreationOnBgThreadOnAndroid(jsi::Runtime& runtime); + bool destroyFabricSurfacesInReactInstanceManager(jsi::Runtime& runtime); bool enableAlignItemsBaselineOnFabricIOS(jsi::Runtime& runtime); diff --git a/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js b/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js index 2288e9e215de..288def4c9963 100644 --- a/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js +++ b/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js @@ -59,6 +59,11 @@ const definitions: FeatureFlagDefinitions = { description: 'When enabled, insert of views on Android will be moved from the beginning of the IntBufferBatchMountItem to be after layout updates.', }, + completeReactInstanceCreationOnBgThreadOnAndroid: { + defaultValue: false, + description: + 'Do not wait for a main-thread dispatch to complete init to start executing work on the JS thread on Android', + }, destroyFabricSurfacesInReactInstanceManager: { defaultValue: false, description: diff --git a/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js b/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js index 04d890884d7e..f16abfd470a7 100644 --- a/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js +++ b/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<7421319910b210753a1eddcf079aa151>> + * @generated SignedSource<<34a6877ad6f40b5a43a833a66b5591ae>> * @flow strict-local */ @@ -48,6 +48,7 @@ export type ReactNativeFeatureFlags = { allowRecursiveCommitsWithSynchronousMountOnAndroid: Getter, batchRenderingUpdatesInEventLoop: Getter, changeOrderOfMountingInstructionsOnAndroid: Getter, + completeReactInstanceCreationOnBgThreadOnAndroid: Getter, destroyFabricSurfacesInReactInstanceManager: Getter, enableAlignItemsBaselineOnFabricIOS: Getter, enableCleanTextInputYogaNode: Getter, @@ -152,6 +153,10 @@ export const batchRenderingUpdatesInEventLoop: Getter = createNativeFla * When enabled, insert of views on Android will be moved from the beginning of the IntBufferBatchMountItem to be after layout updates. */ export const changeOrderOfMountingInstructionsOnAndroid: Getter = createNativeFlagGetter('changeOrderOfMountingInstructionsOnAndroid', false); +/** + * Do not wait for a main-thread dispatch to complete init to start executing work on the JS thread on Android + */ +export const completeReactInstanceCreationOnBgThreadOnAndroid: Getter = createNativeFlagGetter('completeReactInstanceCreationOnBgThreadOnAndroid', false); /** * When enabled, ReactInstanceManager will clean up Fabric surfaces on destroy(). */ diff --git a/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js b/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js index cf0e63335d39..7e3bc8b4d277 100644 --- a/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js +++ b/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<29f4ec3c941708dc99dd38adac52d6dc>> + * @generated SignedSource<> * @flow strict-local */ @@ -28,6 +28,7 @@ export interface Spec extends TurboModule { +allowRecursiveCommitsWithSynchronousMountOnAndroid?: () => boolean; +batchRenderingUpdatesInEventLoop?: () => boolean; +changeOrderOfMountingInstructionsOnAndroid?: () => boolean; + +completeReactInstanceCreationOnBgThreadOnAndroid?: () => boolean; +destroyFabricSurfacesInReactInstanceManager?: () => boolean; +enableAlignItemsBaselineOnFabricIOS?: () => boolean; +enableCleanTextInputYogaNode?: () => boolean;