Allow recursive calls to schedulerShouldRenderTransactions without deadlocks (#44725)

Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/44725

Changelog: [internal]

## Context

We're currently testing synchronous state updates in Fabric (committing shadow trees for state updates synchronously in the thread where they were dispatched, instead of always scheduling it in the JS thread).

In these experiments we saw a problem caused by a recent change in the Android mounting layer (done to fix a problem with the Event Loop) where we were doing the mount operations inside a mutex lock. The problem is that we didn't have recursive commit+mount operations (because we were dispatching state updates in the JS thread) but now that we do we get a deadlock here.

 {F1659804385}

These recursive commit+mount operations happen because it's possible to trigger state updates while we mount changes in the host platform (e.g.: we create the scroll view and we update the state to set the content offset). Those state updates trigger more mount operations, which deadlock in the mentioned place.

## Changes

This fixes the described issue by restricting the lock only to access the list of pending operations, but not to apply them. In the current implementation, `mountingManager->executeMount` is protected by the lock, whereas in the new version it isn't (so it can be safely called recursively). The synchronization of the mount operations is done directly at the mounting layer on Android.

Reviewed By: sammy-SC

Differential Revision: D57968936

fbshipit-source-id: 52f996d212cad691646610632b03b5223e7e90ca
This commit is contained in:
Rubén Norte
2024-05-30 12:37:17 -07:00
committed by Facebook GitHub Bot
parent 958c2e840a
commit d1c72016c1
20 changed files with 160 additions and 41 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<<84f45a19bf93a62da7ce904a2682fc51>>
* @generated SignedSource<<4e30b8a42dfe7e041ecb30a386b54e50>>
*/
/**
@@ -40,6 +40,12 @@ public object ReactNativeFeatureFlags {
@JvmStatic
public fun allowCollapsableChildren(): Boolean = accessor.allowCollapsableChildren()
/**
* Adds support for recursively processing commits that mount synchronously (Android only).
*/
@JvmStatic
public fun allowRecursiveCommitsWithSynchronousMountOnAndroid(): Boolean = accessor.allowRecursiveCommitsWithSynchronousMountOnAndroid()
/**
* When enabled, the RuntimeScheduler processing the event loop will batch all rendering updates and dispatch them together at the end of each iteration of the loop.
*/
@@ -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<<2f84a5455d747e14324f7b79cbbdc763>>
* @generated SignedSource<<944fabed27a371ce2e1a86e367312c1f>>
*/
/**
@@ -22,6 +22,7 @@ package com.facebook.react.internal.featureflags
public class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAccessor {
private var commonTestFlagCache: Boolean? = null
private var allowCollapsableChildrenCache: Boolean? = null
private var allowRecursiveCommitsWithSynchronousMountOnAndroidCache: Boolean? = null
private var batchRenderingUpdatesInEventLoopCache: Boolean? = null
private var destroyFabricSurfacesInReactInstanceManagerCache: Boolean? = null
private var enableBackgroundExecutorCache: Boolean? = null
@@ -59,6 +60,15 @@ public class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAccesso
return cached
}
override fun allowRecursiveCommitsWithSynchronousMountOnAndroid(): Boolean {
var cached = allowRecursiveCommitsWithSynchronousMountOnAndroidCache
if (cached == null) {
cached = ReactNativeFeatureFlagsCxxInterop.allowRecursiveCommitsWithSynchronousMountOnAndroid()
allowRecursiveCommitsWithSynchronousMountOnAndroidCache = cached
}
return cached
}
override fun batchRenderingUpdatesInEventLoop(): Boolean {
var cached = batchRenderingUpdatesInEventLoopCache
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<<c82dca47362f4798dfcebda31b2fe2d6>>
* @generated SignedSource<<d2ccaef4c75979c26327963aeee0b0ad>>
*/
/**
@@ -32,6 +32,8 @@ public object ReactNativeFeatureFlagsCxxInterop {
@DoNotStrip @JvmStatic public external fun allowCollapsableChildren(): Boolean
@DoNotStrip @JvmStatic public external fun allowRecursiveCommitsWithSynchronousMountOnAndroid(): Boolean
@DoNotStrip @JvmStatic public external fun batchRenderingUpdatesInEventLoop(): Boolean
@DoNotStrip @JvmStatic public external fun destroyFabricSurfacesInReactInstanceManager(): 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<<1ea3b574063dca0256494361423ce63e>>
* @generated SignedSource<<c74b5434945f63cf42551b188b9f7a48>>
*/
/**
@@ -27,6 +27,8 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi
override fun allowCollapsableChildren(): Boolean = true
override fun allowRecursiveCommitsWithSynchronousMountOnAndroid(): Boolean = false
override fun batchRenderingUpdatesInEventLoop(): Boolean = false
override fun destroyFabricSurfacesInReactInstanceManager(): Boolean = 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<<a66642e4f6027ab0f5280baa2169d901>>
* @generated SignedSource<<3b94757d58e6adb2bccf4ddfb86e2080>>
*/
/**
@@ -26,6 +26,7 @@ public class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcces
private var commonTestFlagCache: Boolean? = null
private var allowCollapsableChildrenCache: Boolean? = null
private var allowRecursiveCommitsWithSynchronousMountOnAndroidCache: Boolean? = null
private var batchRenderingUpdatesInEventLoopCache: Boolean? = null
private var destroyFabricSurfacesInReactInstanceManagerCache: Boolean? = null
private var enableBackgroundExecutorCache: Boolean? = null
@@ -65,6 +66,16 @@ public class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcces
return cached
}
override fun allowRecursiveCommitsWithSynchronousMountOnAndroid(): Boolean {
var cached = allowRecursiveCommitsWithSynchronousMountOnAndroidCache
if (cached == null) {
cached = currentProvider.allowRecursiveCommitsWithSynchronousMountOnAndroid()
accessedFeatureFlags.add("allowRecursiveCommitsWithSynchronousMountOnAndroid")
allowRecursiveCommitsWithSynchronousMountOnAndroidCache = cached
}
return cached
}
override fun batchRenderingUpdatesInEventLoop(): Boolean {
var cached = batchRenderingUpdatesInEventLoopCache
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<<7a63b1fc14ccc86efb0929452755744d>>
* @generated SignedSource<<68ec2c046868a2cb1d2d88e4fdd9d993>>
*/
/**
@@ -27,6 +27,8 @@ public interface ReactNativeFeatureFlagsProvider {
@DoNotStrip public fun allowCollapsableChildren(): Boolean
@DoNotStrip public fun allowRecursiveCommitsWithSynchronousMountOnAndroid(): Boolean
@DoNotStrip public fun batchRenderingUpdatesInEventLoop(): Boolean
@DoNotStrip public fun destroyFabricSurfacesInReactInstanceManager(): Boolean
@@ -487,11 +487,28 @@ void Binding::schedulerShouldRenderTransactions(
return;
}
std::unique_lock<std::mutex> lock(pendingTransactionsMutex_);
for (auto& transaction : pendingTransactions_) {
mountingManager->executeMount(transaction);
if (ReactNativeFeatureFlags::
allowRecursiveCommitsWithSynchronousMountOnAndroid()) {
std::vector<MountingTransaction> pendingTransactions;
{
// Retain the lock to access the pending transactions but not to execute
// the mount operations because that method can call into this method
// again.
std::unique_lock<std::mutex> lock(pendingTransactionsMutex_);
pendingTransactions_.swap(pendingTransactions);
}
for (auto& transaction : pendingTransactions) {
mountingManager->executeMount(transaction);
}
} else {
std::unique_lock<std::mutex> lock(pendingTransactionsMutex_);
for (auto& transaction : pendingTransactions_) {
mountingManager->executeMount(transaction);
}
pendingTransactions_.clear();
}
pendingTransactions_.clear();
}
void Binding::schedulerDidRequestPreliminaryViewAllocation(
@@ -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<<82d20aa409496b17df21a077088894a6>>
* @generated SignedSource<<318ea35c5b58c968d7026dbe547200e4>>
*/
/**
@@ -51,6 +51,12 @@ class ReactNativeFeatureFlagsProviderHolder
return method(javaProvider_);
}
bool allowRecursiveCommitsWithSynchronousMountOnAndroid() override {
static const auto method =
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("allowRecursiveCommitsWithSynchronousMountOnAndroid");
return method(javaProvider_);
}
bool batchRenderingUpdatesInEventLoop() override {
static const auto method =
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("batchRenderingUpdatesInEventLoop");
@@ -173,6 +179,11 @@ bool JReactNativeFeatureFlagsCxxInterop::allowCollapsableChildren(
return ReactNativeFeatureFlags::allowCollapsableChildren();
}
bool JReactNativeFeatureFlagsCxxInterop::allowRecursiveCommitsWithSynchronousMountOnAndroid(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
return ReactNativeFeatureFlags::allowRecursiveCommitsWithSynchronousMountOnAndroid();
}
bool JReactNativeFeatureFlagsCxxInterop::batchRenderingUpdatesInEventLoop(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
return ReactNativeFeatureFlags::batchRenderingUpdatesInEventLoop();
@@ -286,6 +297,9 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() {
makeNativeMethod(
"allowCollapsableChildren",
JReactNativeFeatureFlagsCxxInterop::allowCollapsableChildren),
makeNativeMethod(
"allowRecursiveCommitsWithSynchronousMountOnAndroid",
JReactNativeFeatureFlagsCxxInterop::allowRecursiveCommitsWithSynchronousMountOnAndroid),
makeNativeMethod(
"batchRenderingUpdatesInEventLoop",
JReactNativeFeatureFlagsCxxInterop::batchRenderingUpdatesInEventLoop),
@@ -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<<08463d4f487df81332c79c8e85b4dac8>>
* @generated SignedSource<<4d557dc4399d46888205165ee7ae4ab2>>
*/
/**
@@ -36,6 +36,9 @@ class JReactNativeFeatureFlagsCxxInterop
static bool allowCollapsableChildren(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
static bool allowRecursiveCommitsWithSynchronousMountOnAndroid(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
static bool batchRenderingUpdatesInEventLoop(
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<<c51ddd57ad10e748d6e2c5f444ea3765>>
* @generated SignedSource<<2a748a0a1b92cb0514fec83668ed8b0f>>
*/
/**
@@ -29,6 +29,10 @@ bool ReactNativeFeatureFlags::allowCollapsableChildren() {
return getAccessor().allowCollapsableChildren();
}
bool ReactNativeFeatureFlags::allowRecursiveCommitsWithSynchronousMountOnAndroid() {
return getAccessor().allowRecursiveCommitsWithSynchronousMountOnAndroid();
}
bool ReactNativeFeatureFlags::batchRenderingUpdatesInEventLoop() {
return getAccessor().batchRenderingUpdatesInEventLoop();
}
@@ -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<<705dba656bfb228227399bcda638c404>>
* @generated SignedSource<<a75464f590c4f55e64ad2e33cfc52989>>
*/
/**
@@ -47,6 +47,11 @@ class ReactNativeFeatureFlags {
*/
RN_EXPORT static bool allowCollapsableChildren();
/**
* Adds support for recursively processing commits that mount synchronously (Android only).
*/
RN_EXPORT static bool allowRecursiveCommitsWithSynchronousMountOnAndroid();
/**
* When enabled, the RuntimeScheduler processing the event loop will batch all rendering updates and dispatch them together at the end of each iteration of the loop.
*/
@@ -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<<53617e29d537989ca3ac0f314a278e4b>>
* @generated SignedSource<<3e5cb385f51ebc9f53010a901ccbb6a2>>
*/
/**
@@ -65,6 +65,24 @@ bool ReactNativeFeatureFlagsAccessor::allowCollapsableChildren() {
return flagValue.value();
}
bool ReactNativeFeatureFlagsAccessor::allowRecursiveCommitsWithSynchronousMountOnAndroid() {
auto flagValue = allowRecursiveCommitsWithSynchronousMountOnAndroid_.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(2, "allowRecursiveCommitsWithSynchronousMountOnAndroid");
flagValue = currentProvider_->allowRecursiveCommitsWithSynchronousMountOnAndroid();
allowRecursiveCommitsWithSynchronousMountOnAndroid_ = flagValue;
}
return flagValue.value();
}
bool ReactNativeFeatureFlagsAccessor::batchRenderingUpdatesInEventLoop() {
auto flagValue = batchRenderingUpdatesInEventLoop_.load();
@@ -74,7 +92,7 @@ bool ReactNativeFeatureFlagsAccessor::batchRenderingUpdatesInEventLoop() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(2, "batchRenderingUpdatesInEventLoop");
markFlagAsAccessed(3, "batchRenderingUpdatesInEventLoop");
flagValue = currentProvider_->batchRenderingUpdatesInEventLoop();
batchRenderingUpdatesInEventLoop_ = flagValue;
@@ -92,7 +110,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(3, "destroyFabricSurfacesInReactInstanceManager");
markFlagAsAccessed(4, "destroyFabricSurfacesInReactInstanceManager");
flagValue = currentProvider_->destroyFabricSurfacesInReactInstanceManager();
destroyFabricSurfacesInReactInstanceManager_ = flagValue;
@@ -110,7 +128,7 @@ bool ReactNativeFeatureFlagsAccessor::enableBackgroundExecutor() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(4, "enableBackgroundExecutor");
markFlagAsAccessed(5, "enableBackgroundExecutor");
flagValue = currentProvider_->enableBackgroundExecutor();
enableBackgroundExecutor_ = flagValue;
@@ -128,7 +146,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(5, "enableCleanTextInputYogaNode");
markFlagAsAccessed(6, "enableCleanTextInputYogaNode");
flagValue = currentProvider_->enableCleanTextInputYogaNode();
enableCleanTextInputYogaNode_ = flagValue;
@@ -146,7 +164,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(6, "enableGranularShadowTreeStateReconciliation");
markFlagAsAccessed(7, "enableGranularShadowTreeStateReconciliation");
flagValue = currentProvider_->enableGranularShadowTreeStateReconciliation();
enableGranularShadowTreeStateReconciliation_ = flagValue;
@@ -164,7 +182,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(7, "enableMicrotasks");
markFlagAsAccessed(8, "enableMicrotasks");
flagValue = currentProvider_->enableMicrotasks();
enableMicrotasks_ = flagValue;
@@ -182,7 +200,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(8, "enableSynchronousStateUpdates");
markFlagAsAccessed(9, "enableSynchronousStateUpdates");
flagValue = currentProvider_->enableSynchronousStateUpdates();
enableSynchronousStateUpdates_ = flagValue;
@@ -200,7 +218,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(9, "enableUIConsistency");
markFlagAsAccessed(10, "enableUIConsistency");
flagValue = currentProvider_->enableUIConsistency();
enableUIConsistency_ = flagValue;
@@ -218,7 +236,7 @@ bool ReactNativeFeatureFlagsAccessor::fixStoppedSurfaceRemoveDeleteTreeUIFrameCa
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(10, "fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak");
markFlagAsAccessed(11, "fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak");
flagValue = currentProvider_->fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak();
fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak_ = flagValue;
@@ -236,7 +254,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(11, "forceBatchingMountItemsOnAndroid");
markFlagAsAccessed(12, "forceBatchingMountItemsOnAndroid");
flagValue = currentProvider_->forceBatchingMountItemsOnAndroid();
forceBatchingMountItemsOnAndroid_ = flagValue;
@@ -254,7 +272,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(12, "fuseboxEnabledDebug");
markFlagAsAccessed(13, "fuseboxEnabledDebug");
flagValue = currentProvider_->fuseboxEnabledDebug();
fuseboxEnabledDebug_ = flagValue;
@@ -272,7 +290,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(13, "fuseboxEnabledRelease");
markFlagAsAccessed(14, "fuseboxEnabledRelease");
flagValue = currentProvider_->fuseboxEnabledRelease();
fuseboxEnabledRelease_ = flagValue;
@@ -290,7 +308,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(14, "lazyAnimationCallbacks");
markFlagAsAccessed(15, "lazyAnimationCallbacks");
flagValue = currentProvider_->lazyAnimationCallbacks();
lazyAnimationCallbacks_ = flagValue;
@@ -308,7 +326,7 @@ bool ReactNativeFeatureFlagsAccessor::preventDoubleTextMeasure() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(15, "preventDoubleTextMeasure");
markFlagAsAccessed(16, "preventDoubleTextMeasure");
flagValue = currentProvider_->preventDoubleTextMeasure();
preventDoubleTextMeasure_ = flagValue;
@@ -326,7 +344,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(16, "setAndroidLayoutDirection");
markFlagAsAccessed(17, "setAndroidLayoutDirection");
flagValue = currentProvider_->setAndroidLayoutDirection();
setAndroidLayoutDirection_ = flagValue;
@@ -344,7 +362,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(17, "useModernRuntimeScheduler");
markFlagAsAccessed(18, "useModernRuntimeScheduler");
flagValue = currentProvider_->useModernRuntimeScheduler();
useModernRuntimeScheduler_ = flagValue;
@@ -362,7 +380,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(18, "useNativeViewConfigsInBridgelessMode");
markFlagAsAccessed(19, "useNativeViewConfigsInBridgelessMode");
flagValue = currentProvider_->useNativeViewConfigsInBridgelessMode();
useNativeViewConfigsInBridgelessMode_ = flagValue;
@@ -380,7 +398,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(19, "useStateAlignmentMechanism");
markFlagAsAccessed(20, "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<<eb1c2343ad44d6cb5e771bff1e7d3969>>
* @generated SignedSource<<f4950ca8555466a584af00c972a38f1d>>
*/
/**
@@ -33,6 +33,7 @@ class ReactNativeFeatureFlagsAccessor {
bool commonTestFlag();
bool allowCollapsableChildren();
bool allowRecursiveCommitsWithSynchronousMountOnAndroid();
bool batchRenderingUpdatesInEventLoop();
bool destroyFabricSurfacesInReactInstanceManager();
bool enableBackgroundExecutor();
@@ -61,10 +62,11 @@ class ReactNativeFeatureFlagsAccessor {
std::unique_ptr<ReactNativeFeatureFlagsProvider> currentProvider_;
bool wasOverridden_;
std::array<std::atomic<const char*>, 20> accessedFeatureFlags_;
std::array<std::atomic<const char*>, 21> 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>> destroyFabricSurfacesInReactInstanceManager_;
std::atomic<std::optional<bool>> enableBackgroundExecutor_;
@@ -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<<c5ec848c8bda7048dffa3d9bd49813ae>>
* @generated SignedSource<<5c78cdf7676d56996ea174f08bf4b8a6>>
*/
/**
@@ -35,6 +35,10 @@ class ReactNativeFeatureFlagsDefaults : public ReactNativeFeatureFlagsProvider {
return true;
}
bool allowRecursiveCommitsWithSynchronousMountOnAndroid() override {
return false;
}
bool batchRenderingUpdatesInEventLoop() 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<<c0b634ae91683a44ebbbfe3f21b762d1>>
* @generated SignedSource<<a7cdc61b76e5db55c4fc54c0d93f426c>>
*/
/**
@@ -27,6 +27,7 @@ class ReactNativeFeatureFlagsProvider {
virtual bool commonTestFlag() = 0;
virtual bool allowCollapsableChildren() = 0;
virtual bool allowRecursiveCommitsWithSynchronousMountOnAndroid() = 0;
virtual bool batchRenderingUpdatesInEventLoop() = 0;
virtual bool destroyFabricSurfacesInReactInstanceManager() = 0;
virtual bool enableBackgroundExecutor() = 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<<e050c6ce3466ad5c14ee94e61eca189e>>
* @generated SignedSource<<4c02b68cc3b46ec214fe4552f136c5f0>>
*/
/**
@@ -47,6 +47,11 @@ bool NativeReactNativeFeatureFlags::allowCollapsableChildren(
return ReactNativeFeatureFlags::allowCollapsableChildren();
}
bool NativeReactNativeFeatureFlags::allowRecursiveCommitsWithSynchronousMountOnAndroid(
jsi::Runtime& /*runtime*/) {
return ReactNativeFeatureFlags::allowRecursiveCommitsWithSynchronousMountOnAndroid();
}
bool NativeReactNativeFeatureFlags::batchRenderingUpdatesInEventLoop(
jsi::Runtime& /*runtime*/) {
return ReactNativeFeatureFlags::batchRenderingUpdatesInEventLoop();
@@ -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<<a13aa1f123eb1f90039bc08436349c83>>
* @generated SignedSource<<de8e0cd16d4190afde8280f67f6d92d8>>
*/
/**
@@ -39,6 +39,8 @@ class NativeReactNativeFeatureFlags
bool allowCollapsableChildren(jsi::Runtime& runtime);
bool allowRecursiveCommitsWithSynchronousMountOnAndroid(jsi::Runtime& runtime);
bool batchRenderingUpdatesInEventLoop(jsi::Runtime& runtime);
bool destroyFabricSurfacesInReactInstanceManager(jsi::Runtime& runtime);
@@ -44,6 +44,11 @@ const definitions: FeatureFlagDefinitions = {
description:
'Enables the differentiator to understand the "collapsableChildren" prop',
},
allowRecursiveCommitsWithSynchronousMountOnAndroid: {
defaultValue: false,
description:
'Adds support for recursively processing commits that mount synchronously (Android only).',
},
batchRenderingUpdatesInEventLoop: {
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<<0a8bc71d703e92e1aaba25203e0211b3>>
* @generated SignedSource<<1cf3f0841a0523baddea551747c425ca>>
* @flow strict-local
*/
@@ -42,6 +42,7 @@ export type ReactNativeFeatureFlags = {
...ReactNativeFeatureFlagsJsOnly,
commonTestFlag: Getter<boolean>,
allowCollapsableChildren: Getter<boolean>,
allowRecursiveCommitsWithSynchronousMountOnAndroid: Getter<boolean>,
batchRenderingUpdatesInEventLoop: Getter<boolean>,
destroyFabricSurfacesInReactInstanceManager: Getter<boolean>,
enableBackgroundExecutor: Getter<boolean>,
@@ -110,6 +111,10 @@ export const commonTestFlag: Getter<boolean> = createNativeFlagGetter('commonTes
* Enables the differentiator to understand the "collapsableChildren" prop
*/
export const allowCollapsableChildren: Getter<boolean> = createNativeFlagGetter('allowCollapsableChildren', true);
/**
* Adds support for recursively processing commits that mount synchronously (Android only).
*/
export const allowRecursiveCommitsWithSynchronousMountOnAndroid: Getter<boolean> = createNativeFlagGetter('allowRecursiveCommitsWithSynchronousMountOnAndroid', false);
/**
* When enabled, the RuntimeScheduler processing the event loop will batch all rendering updates and dispatch them together at the end of each iteration of the loop.
*/
@@ -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<<13b6d24c994e1ac758d2a76f759f5363>>
* @generated SignedSource<<613d748b087fde71cc07a7cd5acf888e>>
* @flow strict-local
*/
@@ -25,6 +25,7 @@ import * as TurboModuleRegistry from '../../../../Libraries/TurboModule/TurboMod
export interface Spec extends TurboModule {
+commonTestFlag?: () => boolean;
+allowCollapsableChildren?: () => boolean;
+allowRecursiveCommitsWithSynchronousMountOnAndroid?: () => boolean;
+batchRenderingUpdatesInEventLoop?: () => boolean;
+destroyFabricSurfacesInReactInstanceManager?: () => boolean;
+enableBackgroundExecutor?: () => boolean;