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

fbshipit-source-id: dd6a6fe093a32144ef6823bde5ac94a61d268fd2
This commit is contained in:
Pieter De Baets
2024-07-22 04:04:40 -07:00
committed by Facebook GitHub Bot
parent 5bf1a77a0b
commit 235e84ccae
20 changed files with 271 additions and 148 deletions
@@ -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().
*/
@@ -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<<a80c0d6190fe0222bfdd4a39d7116908>>
*/
/**
@@ -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) {
@@ -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<<af43467b1d1c4cd6d1f42a597a791899>>
*/
/**
@@ -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
@@ -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<<a42ecd51ef7f12eb8758dbd029a2d67b>>
* @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
@@ -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<<bf73788f1e8314232f880108b8a7c671>>
*/
/**
@@ -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) {
@@ -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
@@ -62,6 +62,7 @@ import com.facebook.react.modules.appearance.AppearanceModule;
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 @@ public class ReactHostImpl implements ReactHost {
.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 @@ public class ReactHostImpl implements ReactHost {
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 @@ public class ReactHostImpl implements ReactHost {
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<ReactInstance> getOrCreateReactInstanceTask() {
final String method = "getOrCreateReactInstanceTask()";
@@ -1064,116 +1083,118 @@ public class ReactHostImpl implements ReactHost {
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);
Task<CreationResult> 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;
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);
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();
// 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, "Loading JS Bundle");
instance.loadJSBundle(bundleLoader);
log(
method,
"Calling DevSupportManagerBase.onNewReactContextCreated(reactContext)");
devSupportManager.onNewReactContextCreated(reactContext);
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);
});
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);
});
class Result {
final ReactInstance mInstance = instance;
final ReactContext mContext = reactContext;
final boolean mIsReloading = mReloadTask != null;
}
return new CreationResult(instance, reactContext, mReloadTask != null);
},
mBGExecutor);
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;
Continuation<CreationResult, ReactInstance> 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.
*
* <p>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().
*
* <p>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());
}
/**
* ReactContext.onHostResume() should only be called when the user navigates to the
* first React Native screen.
*
* <p>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().
*
* <p>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);
}
});
}
@@ -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<<b0e927861b19d02b77609527f6290d07>>
*/
/**
@@ -69,6 +69,12 @@ class ReactNativeFeatureFlagsProviderHolder
return method(javaProvider_);
}
bool completeReactInstanceCreationOnBgThreadOnAndroid() override {
static const auto method =
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("completeReactInstanceCreationOnBgThreadOnAndroid");
return method(javaProvider_);
}
bool destroyFabricSurfacesInReactInstanceManager() override {
static const auto method =
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("destroyFabricSurfacesInReactInstanceManager");
@@ -260,6 +266,11 @@ bool JReactNativeFeatureFlagsCxxInterop::changeOrderOfMountingInstructionsOnAndr
return ReactNativeFeatureFlags::changeOrderOfMountingInstructionsOnAndroid();
}
bool JReactNativeFeatureFlagsCxxInterop::completeReactInstanceCreationOnBgThreadOnAndroid(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
return ReactNativeFeatureFlags::completeReactInstanceCreationOnBgThreadOnAndroid();
}
bool JReactNativeFeatureFlagsCxxInterop::destroyFabricSurfacesInReactInstanceManager(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
return ReactNativeFeatureFlags::destroyFabricSurfacesInReactInstanceManager();
@@ -427,6 +438,9 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() {
makeNativeMethod(
"changeOrderOfMountingInstructionsOnAndroid",
JReactNativeFeatureFlagsCxxInterop::changeOrderOfMountingInstructionsOnAndroid),
makeNativeMethod(
"completeReactInstanceCreationOnBgThreadOnAndroid",
JReactNativeFeatureFlagsCxxInterop::completeReactInstanceCreationOnBgThreadOnAndroid),
makeNativeMethod(
"destroyFabricSurfacesInReactInstanceManager",
JReactNativeFeatureFlagsCxxInterop::destroyFabricSurfacesInReactInstanceManager),
@@ -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<<d7599e61abcedfa8a7f3270f2b0cd9ef>>
* @generated SignedSource<<732d3c3f973e966f958945c566de2870>>
*/
/**
@@ -45,6 +45,9 @@ class JReactNativeFeatureFlagsCxxInterop
static bool changeOrderOfMountingInstructionsOnAndroid(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
static bool completeReactInstanceCreationOnBgThreadOnAndroid(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
static bool destroyFabricSurfacesInReactInstanceManager(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
@@ -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<<ce0749b4f2ccf11b420cb9762012c02b>>
* @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();
}
@@ -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().
*/
@@ -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<<c78a2d92deb635804ef3c01f970247e1>>
*/
/**
@@ -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;
@@ -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<ReactNativeFeatureFlagsProvider> currentProvider_;
bool wasOverridden_;
std::array<std::atomic<const char*>, 32> accessedFeatureFlags_;
std::array<std::atomic<const char*>, 33> accessedFeatureFlags_;
std::atomic<std::optional<bool>> commonTestFlag_;
std::atomic<std::optional<bool>> allowCollapsableChildren_;
std::atomic<std::optional<bool>> allowRecursiveCommitsWithSynchronousMountOnAndroid_;
std::atomic<std::optional<bool>> batchRenderingUpdatesInEventLoop_;
std::atomic<std::optional<bool>> changeOrderOfMountingInstructionsOnAndroid_;
std::atomic<std::optional<bool>> completeReactInstanceCreationOnBgThreadOnAndroid_;
std::atomic<std::optional<bool>> destroyFabricSurfacesInReactInstanceManager_;
std::atomic<std::optional<bool>> enableAlignItemsBaselineOnFabricIOS_;
std::atomic<std::optional<bool>> enableCleanTextInputYogaNode_;
@@ -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<<c6b9aaa642199af1c7669d78054b061d>>
* @generated SignedSource<<308807b5ebe2d3d1d17452b73be2d82b>>
*/
/**
@@ -47,6 +47,10 @@ class ReactNativeFeatureFlagsDefaults : public ReactNativeFeatureFlagsProvider {
return false;
}
bool completeReactInstanceCreationOnBgThreadOnAndroid() override {
return false;
}
bool destroyFabricSurfacesInReactInstanceManager() override {
return false;
}
@@ -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;
@@ -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();
@@ -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);
@@ -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:
@@ -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<boolean>,
batchRenderingUpdatesInEventLoop: Getter<boolean>,
changeOrderOfMountingInstructionsOnAndroid: Getter<boolean>,
completeReactInstanceCreationOnBgThreadOnAndroid: Getter<boolean>,
destroyFabricSurfacesInReactInstanceManager: Getter<boolean>,
enableAlignItemsBaselineOnFabricIOS: Getter<boolean>,
enableCleanTextInputYogaNode: Getter<boolean>,
@@ -152,6 +153,10 @@ export const batchRenderingUpdatesInEventLoop: Getter<boolean> = 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<boolean> = 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<boolean> = createNativeFlagGetter('completeReactInstanceCreationOnBgThreadOnAndroid', false);
/**
* When enabled, ReactInstanceManager will clean up Fabric surfaces on destroy().
*/
@@ -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<<d37bff5e86581b4a0b1aedd8870d6302>>
* @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;