From a5dd56f7d0571729fa62717e9f3d6eae8ec5caf3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Norte?= Date: Wed, 18 Sep 2024 09:10:00 -0700 Subject: [PATCH] Create flag to disable reentrancy in MountItemDispatcher (#46561) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/46561 Changelog: [internal] We have some logic in `MountItemDispatcher.tryDispatchMountItems` to recursively call itself for as long as there are new items to mount in the general queue. This queue is copied and processed every time `tryDispatchMountItems` is called, but it's possible that during this time new mount operations are added (either from JS or from the mount operations themselves). This logic can cause frame drops, as we could be finish processing the current frame without processing new mount items (we could do that in the next frame, and in many cases it's just pre-rendering work and state updates that the user can't perceive anyway). This creates a feature flag to test disabling this behavior and only process whatever mount items are queued at the start of the frame. Reviewed By: sammy-SC Differential Revision: D62958009 fbshipit-source-id: ca038c827715411375410215deb5d5e374f5fdb4 --- .../fabric/mounting/MountItemDispatcher.java | 31 +++++++------ .../featureflags/ReactNativeFeatureFlags.kt | 8 +++- .../ReactNativeFeatureFlagsCxxAccessor.kt | 12 ++++- .../ReactNativeFeatureFlagsCxxInterop.kt | 4 +- .../ReactNativeFeatureFlagsDefaults.kt | 4 +- .../ReactNativeFeatureFlagsLocalAccessor.kt | 13 +++++- .../ReactNativeFeatureFlagsProvider.kt | 4 +- .../JReactNativeFeatureFlagsCxxInterop.cpp | 16 ++++++- .../JReactNativeFeatureFlagsCxxInterop.h | 5 +- .../featureflags/ReactNativeFeatureFlags.cpp | 6 ++- .../featureflags/ReactNativeFeatureFlags.h | 7 ++- .../ReactNativeFeatureFlagsAccessor.cpp | 46 +++++++++++++------ .../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, 151 insertions(+), 46 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/MountItemDispatcher.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/MountItemDispatcher.java index 967795de306a9a..73288476370821 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/MountItemDispatcher.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/MountItemDispatcher.java @@ -137,22 +137,25 @@ public void tryDispatchMountItems() { // scheduled mItemDispatchListener.didDispatchMountItems(); - // Decide if we want to try reentering - if (mReDispatchCounter < 10 && didDispatchItems) { - // Executing twice in a row is normal. Only log after that point. - if (mReDispatchCounter > 2) { - ReactSoftExceptionLogger.logSoftException( - TAG, - new ReactNoCrashSoftException( - "Re-dispatched " - + mReDispatchCounter - + " times. This indicates setState (?) is likely being called too many times" - + " during mounting.")); - } + if (!ReactNativeFeatureFlags.removeNestedCallsToDispatchMountItemsOnAndroid()) { + // Decide if we want to try reentering + if (mReDispatchCounter < 10 && didDispatchItems) { + // Executing twice in a row is normal. Only log after that point. + if (mReDispatchCounter > 2) { + ReactSoftExceptionLogger.logSoftException( + TAG, + new ReactNoCrashSoftException( + "Re-dispatched " + + mReDispatchCounter + + " times. This indicates setState (?) is likely being called too many" + + " times during mounting.")); + } - mReDispatchCounter++; - tryDispatchMountItems(); + mReDispatchCounter++; + tryDispatchMountItems(); + } } + mReDispatchCounter = 0; } } 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 162a8ee8a52724..36c1dfb8c6127d 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<> + * @generated SignedSource<<60fcb02736ca814a842225291e3a55b1>> */ /** @@ -244,6 +244,12 @@ public object ReactNativeFeatureFlags { @JvmStatic public fun loadVectorDrawablesOnImages(): Boolean = accessor.loadVectorDrawablesOnImages() + /** + * Removes nested calls to MountItemDispatcher.dispatchMountItems on Android, so we do less work per frame on the UI thread. + */ + @JvmStatic + public fun removeNestedCallsToDispatchMountItemsOnAndroid(): Boolean = accessor.removeNestedCallsToDispatchMountItemsOnAndroid() + /** * Propagate layout direction to Android views. */ 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 c3e8cb7380b873..d45e432c70b5c6 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<> + * @generated SignedSource<> */ /** @@ -56,6 +56,7 @@ public class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAccesso private var initEagerTurboModulesOnNativeModulesQueueAndroidCache: Boolean? = null private var lazyAnimationCallbacksCache: Boolean? = null private var loadVectorDrawablesOnImagesCache: Boolean? = null + private var removeNestedCallsToDispatchMountItemsOnAndroidCache: Boolean? = null private var setAndroidLayoutDirectionCache: Boolean? = null private var traceTurboModulePromiseRejectionsOnAndroidCache: Boolean? = null private var useFabricInteropCache: Boolean? = null @@ -394,6 +395,15 @@ public class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAccesso return cached } + override fun removeNestedCallsToDispatchMountItemsOnAndroid(): Boolean { + var cached = removeNestedCallsToDispatchMountItemsOnAndroidCache + if (cached == null) { + cached = ReactNativeFeatureFlagsCxxInterop.removeNestedCallsToDispatchMountItemsOnAndroid() + removeNestedCallsToDispatchMountItemsOnAndroidCache = cached + } + return cached + } + override fun setAndroidLayoutDirection(): Boolean { var cached = setAndroidLayoutDirectionCache 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 8c34e6625bf710..8cbae2ba7c24f9 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<<31fb0e1bcd77d57f41d69cdbbdd15af4>> + * @generated SignedSource<<03618f182004add50655a88e6e65e96d>> */ /** @@ -100,6 +100,8 @@ public object ReactNativeFeatureFlagsCxxInterop { @DoNotStrip @JvmStatic public external fun loadVectorDrawablesOnImages(): Boolean + @DoNotStrip @JvmStatic public external fun removeNestedCallsToDispatchMountItemsOnAndroid(): Boolean + @DoNotStrip @JvmStatic public external fun setAndroidLayoutDirection(): Boolean @DoNotStrip @JvmStatic public external fun traceTurboModulePromiseRejectionsOnAndroid(): 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 993bc509566e0a..712e8919b792a0 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<<06791e428f1e199b718f11c6bc1f1414>> + * @generated SignedSource<> */ /** @@ -95,6 +95,8 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi override fun loadVectorDrawablesOnImages(): Boolean = false + override fun removeNestedCallsToDispatchMountItemsOnAndroid(): Boolean = false + override fun setAndroidLayoutDirection(): Boolean = false override fun traceTurboModulePromiseRejectionsOnAndroid(): Boolean = false 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 a04c1b4e0e25f9..099a9ae121baf7 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<<3c321dea3f540266bec3769031460128>> + * @generated SignedSource<<0dbb1f1a08649132955698ac51050e62>> */ /** @@ -60,6 +60,7 @@ public class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcces private var initEagerTurboModulesOnNativeModulesQueueAndroidCache: Boolean? = null private var lazyAnimationCallbacksCache: Boolean? = null private var loadVectorDrawablesOnImagesCache: Boolean? = null + private var removeNestedCallsToDispatchMountItemsOnAndroidCache: Boolean? = null private var setAndroidLayoutDirectionCache: Boolean? = null private var traceTurboModulePromiseRejectionsOnAndroidCache: Boolean? = null private var useFabricInteropCache: Boolean? = null @@ -434,6 +435,16 @@ public class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcces return cached } + override fun removeNestedCallsToDispatchMountItemsOnAndroid(): Boolean { + var cached = removeNestedCallsToDispatchMountItemsOnAndroidCache + if (cached == null) { + cached = currentProvider.removeNestedCallsToDispatchMountItemsOnAndroid() + accessedFeatureFlags.add("removeNestedCallsToDispatchMountItemsOnAndroid") + removeNestedCallsToDispatchMountItemsOnAndroidCache = cached + } + return cached + } + override fun setAndroidLayoutDirection(): Boolean { var cached = setAndroidLayoutDirectionCache 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 d8b7458b2e0f83..35fef93bc86857 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<> + * @generated SignedSource<<79cd9812257f42d553b49a3f6d3d4989>> */ /** @@ -95,6 +95,8 @@ public interface ReactNativeFeatureFlagsProvider { @DoNotStrip public fun loadVectorDrawablesOnImages(): Boolean + @DoNotStrip public fun removeNestedCallsToDispatchMountItemsOnAndroid(): Boolean + @DoNotStrip public fun setAndroidLayoutDirection(): Boolean @DoNotStrip public fun traceTurboModulePromiseRejectionsOnAndroid(): Boolean 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 8df111f2ef4ab7..4beafbe1177bb5 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<> + * @generated SignedSource<<9e891a5d26221136d7334982fc2e99d3>> */ /** @@ -255,6 +255,12 @@ class ReactNativeFeatureFlagsProviderHolder return method(javaProvider_); } + bool removeNestedCallsToDispatchMountItemsOnAndroid() override { + static const auto method = + getReactNativeFeatureFlagsProviderJavaClass()->getMethod("removeNestedCallsToDispatchMountItemsOnAndroid"); + return method(javaProvider_); + } + bool setAndroidLayoutDirection() override { static const auto method = getReactNativeFeatureFlagsProviderJavaClass()->getMethod("setAndroidLayoutDirection"); @@ -517,6 +523,11 @@ bool JReactNativeFeatureFlagsCxxInterop::loadVectorDrawablesOnImages( return ReactNativeFeatureFlags::loadVectorDrawablesOnImages(); } +bool JReactNativeFeatureFlagsCxxInterop::removeNestedCallsToDispatchMountItemsOnAndroid( + facebook::jni::alias_ref /*unused*/) { + return ReactNativeFeatureFlags::removeNestedCallsToDispatchMountItemsOnAndroid(); +} + bool JReactNativeFeatureFlagsCxxInterop::setAndroidLayoutDirection( facebook::jni::alias_ref /*unused*/) { return ReactNativeFeatureFlags::setAndroidLayoutDirection(); @@ -707,6 +718,9 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() { makeNativeMethod( "loadVectorDrawablesOnImages", JReactNativeFeatureFlagsCxxInterop::loadVectorDrawablesOnImages), + makeNativeMethod( + "removeNestedCallsToDispatchMountItemsOnAndroid", + JReactNativeFeatureFlagsCxxInterop::removeNestedCallsToDispatchMountItemsOnAndroid), makeNativeMethod( "setAndroidLayoutDirection", JReactNativeFeatureFlagsCxxInterop::setAndroidLayoutDirection), 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 a53885b54788b0..4bc95edb2d6f6c 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<<70edc4176da74aed5eaa1561a907a7ee>> */ /** @@ -138,6 +138,9 @@ class JReactNativeFeatureFlagsCxxInterop static bool loadVectorDrawablesOnImages( facebook::jni::alias_ref); + static bool removeNestedCallsToDispatchMountItemsOnAndroid( + facebook::jni::alias_ref); + static bool setAndroidLayoutDirection( 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 b293d623b88eb4..a088e4b628fdea 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<<80b130f32b0bc59b9a9605777537feeb>> */ /** @@ -165,6 +165,10 @@ bool ReactNativeFeatureFlags::loadVectorDrawablesOnImages() { return getAccessor().loadVectorDrawablesOnImages(); } +bool ReactNativeFeatureFlags::removeNestedCallsToDispatchMountItemsOnAndroid() { + return getAccessor().removeNestedCallsToDispatchMountItemsOnAndroid(); +} + bool ReactNativeFeatureFlags::setAndroidLayoutDirection() { return getAccessor().setAndroidLayoutDirection(); } diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h index f410d2ae0082b1..a169c62b74b1f1 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<<8d28b4f3ffac32a287c9b858d62e39e1>> + * @generated SignedSource<<3b5ff29faaf1575c051131bdf24a3237>> */ /** @@ -217,6 +217,11 @@ class ReactNativeFeatureFlags { */ RN_EXPORT static bool loadVectorDrawablesOnImages(); + /** + * Removes nested calls to MountItemDispatcher.dispatchMountItems on Android, so we do less work per frame on the UI thread. + */ + RN_EXPORT static bool removeNestedCallsToDispatchMountItemsOnAndroid(); + /** * Propagate layout direction to Android views. */ diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp index 43b80ba5c4f16a..5932d2a9b92716 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<> + * @generated SignedSource<<4e91fe2df3304f2aa03b41dcbf4a7599>> */ /** @@ -677,6 +677,24 @@ bool ReactNativeFeatureFlagsAccessor::loadVectorDrawablesOnImages() { return flagValue.value(); } +bool ReactNativeFeatureFlagsAccessor::removeNestedCallsToDispatchMountItemsOnAndroid() { + auto flagValue = removeNestedCallsToDispatchMountItemsOnAndroid_.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(36, "removeNestedCallsToDispatchMountItemsOnAndroid"); + + flagValue = currentProvider_->removeNestedCallsToDispatchMountItemsOnAndroid(); + removeNestedCallsToDispatchMountItemsOnAndroid_ = flagValue; + } + + return flagValue.value(); +} + bool ReactNativeFeatureFlagsAccessor::setAndroidLayoutDirection() { auto flagValue = setAndroidLayoutDirection_.load(); @@ -686,7 +704,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(36, "setAndroidLayoutDirection"); + markFlagAsAccessed(37, "setAndroidLayoutDirection"); flagValue = currentProvider_->setAndroidLayoutDirection(); setAndroidLayoutDirection_ = flagValue; @@ -704,7 +722,7 @@ bool ReactNativeFeatureFlagsAccessor::traceTurboModulePromiseRejectionsOnAndroid // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(37, "traceTurboModulePromiseRejectionsOnAndroid"); + markFlagAsAccessed(38, "traceTurboModulePromiseRejectionsOnAndroid"); flagValue = currentProvider_->traceTurboModulePromiseRejectionsOnAndroid(); traceTurboModulePromiseRejectionsOnAndroid_ = flagValue; @@ -722,7 +740,7 @@ bool ReactNativeFeatureFlagsAccessor::useFabricInterop() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(38, "useFabricInterop"); + markFlagAsAccessed(39, "useFabricInterop"); flagValue = currentProvider_->useFabricInterop(); useFabricInterop_ = flagValue; @@ -740,7 +758,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(39, "useImmediateExecutorInAndroidBridgeless"); + markFlagAsAccessed(40, "useImmediateExecutorInAndroidBridgeless"); flagValue = currentProvider_->useImmediateExecutorInAndroidBridgeless(); useImmediateExecutorInAndroidBridgeless_ = flagValue; @@ -758,7 +776,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(40, "useModernRuntimeScheduler"); + markFlagAsAccessed(41, "useModernRuntimeScheduler"); flagValue = currentProvider_->useModernRuntimeScheduler(); useModernRuntimeScheduler_ = flagValue; @@ -776,7 +794,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(41, "useNativeViewConfigsInBridgelessMode"); + markFlagAsAccessed(42, "useNativeViewConfigsInBridgelessMode"); flagValue = currentProvider_->useNativeViewConfigsInBridgelessMode(); useNativeViewConfigsInBridgelessMode_ = flagValue; @@ -794,7 +812,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(42, "useNewReactImageViewBackgroundDrawing"); + markFlagAsAccessed(43, "useNewReactImageViewBackgroundDrawing"); flagValue = currentProvider_->useNewReactImageViewBackgroundDrawing(); useNewReactImageViewBackgroundDrawing_ = flagValue; @@ -812,7 +830,7 @@ bool ReactNativeFeatureFlagsAccessor::useOptimisedViewPreallocationOnAndroid() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(43, "useOptimisedViewPreallocationOnAndroid"); + markFlagAsAccessed(44, "useOptimisedViewPreallocationOnAndroid"); flagValue = currentProvider_->useOptimisedViewPreallocationOnAndroid(); useOptimisedViewPreallocationOnAndroid_ = flagValue; @@ -830,7 +848,7 @@ bool ReactNativeFeatureFlagsAccessor::useOptimizedEventBatchingOnAndroid() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(44, "useOptimizedEventBatchingOnAndroid"); + markFlagAsAccessed(45, "useOptimizedEventBatchingOnAndroid"); flagValue = currentProvider_->useOptimizedEventBatchingOnAndroid(); useOptimizedEventBatchingOnAndroid_ = flagValue; @@ -848,7 +866,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(45, "useRuntimeShadowNodeReferenceUpdate"); + markFlagAsAccessed(46, "useRuntimeShadowNodeReferenceUpdate"); flagValue = currentProvider_->useRuntimeShadowNodeReferenceUpdate(); useRuntimeShadowNodeReferenceUpdate_ = flagValue; @@ -866,7 +884,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(46, "useRuntimeShadowNodeReferenceUpdateOnLayout"); + markFlagAsAccessed(47, "useRuntimeShadowNodeReferenceUpdateOnLayout"); flagValue = currentProvider_->useRuntimeShadowNodeReferenceUpdateOnLayout(); useRuntimeShadowNodeReferenceUpdateOnLayout_ = flagValue; @@ -884,7 +902,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(47, "useStateAlignmentMechanism"); + markFlagAsAccessed(48, "useStateAlignmentMechanism"); flagValue = currentProvider_->useStateAlignmentMechanism(); useStateAlignmentMechanism_ = flagValue; @@ -902,7 +920,7 @@ bool ReactNativeFeatureFlagsAccessor::useTurboModuleInterop() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(48, "useTurboModuleInterop"); + markFlagAsAccessed(49, "useTurboModuleInterop"); flagValue = currentProvider_->useTurboModuleInterop(); useTurboModuleInterop_ = flagValue; diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h index 15744294f34e2a..819a18a46e0d1a 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<<81fc3492769dc1f8d239f628a35d1b00>> + * @generated SignedSource<> */ /** @@ -67,6 +67,7 @@ class ReactNativeFeatureFlagsAccessor { bool initEagerTurboModulesOnNativeModulesQueueAndroid(); bool lazyAnimationCallbacks(); bool loadVectorDrawablesOnImages(); + bool removeNestedCallsToDispatchMountItemsOnAndroid(); bool setAndroidLayoutDirection(); bool traceTurboModulePromiseRejectionsOnAndroid(); bool useFabricInterop(); @@ -90,7 +91,7 @@ class ReactNativeFeatureFlagsAccessor { std::unique_ptr currentProvider_; bool wasOverridden_; - std::array, 49> accessedFeatureFlags_; + std::array, 50> accessedFeatureFlags_; std::atomic> commonTestFlag_; std::atomic> allowRecursiveCommitsWithSynchronousMountOnAndroid_; @@ -128,6 +129,7 @@ class ReactNativeFeatureFlagsAccessor { std::atomic> initEagerTurboModulesOnNativeModulesQueueAndroid_; std::atomic> lazyAnimationCallbacks_; std::atomic> loadVectorDrawablesOnImages_; + std::atomic> removeNestedCallsToDispatchMountItemsOnAndroid_; std::atomic> setAndroidLayoutDirection_; std::atomic> traceTurboModulePromiseRejectionsOnAndroid_; std::atomic> useFabricInterop_; diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h index e627bd409d0496..118926799e8ec3 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<<5cef66cb54312e8454c7781e3bb96aa3>> + * @generated SignedSource<> */ /** @@ -171,6 +171,10 @@ class ReactNativeFeatureFlagsDefaults : public ReactNativeFeatureFlagsProvider { return false; } + bool removeNestedCallsToDispatchMountItemsOnAndroid() override { + return false; + } + bool setAndroidLayoutDirection() override { return false; } diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h index 38b68b863376c1..859bffe5631efd 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<<80169565fecd1ed75b23d07523538e8e>> + * @generated SignedSource<<43f360d769690622252f3051f71e78ab>> */ /** @@ -61,6 +61,7 @@ class ReactNativeFeatureFlagsProvider { virtual bool initEagerTurboModulesOnNativeModulesQueueAndroid() = 0; virtual bool lazyAnimationCallbacks() = 0; virtual bool loadVectorDrawablesOnImages() = 0; + virtual bool removeNestedCallsToDispatchMountItemsOnAndroid() = 0; virtual bool setAndroidLayoutDirection() = 0; virtual bool traceTurboModulePromiseRejectionsOnAndroid() = 0; virtual bool useFabricInterop() = 0; diff --git a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp index 49444ea2311d5c..f2d3fc3adcff7d 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<<3c04d494bdbf5d3fe63023617e9134f4>> + * @generated SignedSource<<7df4018785f9aefb615b8671abf71454>> */ /** @@ -217,6 +217,11 @@ bool NativeReactNativeFeatureFlags::loadVectorDrawablesOnImages( return ReactNativeFeatureFlags::loadVectorDrawablesOnImages(); } +bool NativeReactNativeFeatureFlags::removeNestedCallsToDispatchMountItemsOnAndroid( + jsi::Runtime& /*runtime*/) { + return ReactNativeFeatureFlags::removeNestedCallsToDispatchMountItemsOnAndroid(); +} + bool NativeReactNativeFeatureFlags::setAndroidLayoutDirection( jsi::Runtime& /*runtime*/) { return ReactNativeFeatureFlags::setAndroidLayoutDirection(); diff --git a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h index b970fc16291bbb..84c154b4ab27f7 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<<6cce043e2e23a01d32b5fe8fc93a2e01>> + * @generated SignedSource<<4404c58578548e8dcb909fb9c6629d44>> */ /** @@ -107,6 +107,8 @@ class NativeReactNativeFeatureFlags bool loadVectorDrawablesOnImages(jsi::Runtime& runtime); + bool removeNestedCallsToDispatchMountItemsOnAndroid(jsi::Runtime& runtime); + bool setAndroidLayoutDirection(jsi::Runtime& runtime); bool traceTurboModulePromiseRejectionsOnAndroid(jsi::Runtime& runtime); diff --git a/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js b/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js index def31a0a99ad52..ee67559c0f2214 100644 --- a/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js +++ b/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js @@ -210,6 +210,11 @@ const definitions: FeatureFlagDefinitions = { description: 'Adds support for loading vector drawable assets in the Image component (only on Android)', }, + removeNestedCallsToDispatchMountItemsOnAndroid: { + defaultValue: false, + description: + 'Removes nested calls to MountItemDispatcher.dispatchMountItems on Android, so we do less work per frame on the UI thread.', + }, setAndroidLayoutDirection: { defaultValue: false, description: 'Propagate layout direction to Android views.', diff --git a/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js b/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js index 4bbbaa9f8eae8e..396a2c1b05a63b 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<<9d8783e80d0d82c086d9477aeb58d033>> + * @generated SignedSource<<0bc6eb9982c84fc359957413cc26dd12>> * @flow strict */ @@ -84,6 +84,7 @@ export type ReactNativeFeatureFlags = { initEagerTurboModulesOnNativeModulesQueueAndroid: Getter, lazyAnimationCallbacks: Getter, loadVectorDrawablesOnImages: Getter, + removeNestedCallsToDispatchMountItemsOnAndroid: Getter, setAndroidLayoutDirection: Getter, traceTurboModulePromiseRejectionsOnAndroid: Getter, useFabricInterop: Getter, @@ -318,6 +319,10 @@ export const lazyAnimationCallbacks: Getter = createNativeFlagGetter('l * Adds support for loading vector drawable assets in the Image component (only on Android) */ export const loadVectorDrawablesOnImages: Getter = createNativeFlagGetter('loadVectorDrawablesOnImages', false); +/** + * Removes nested calls to MountItemDispatcher.dispatchMountItems on Android, so we do less work per frame on the UI thread. + */ +export const removeNestedCallsToDispatchMountItemsOnAndroid: Getter = createNativeFlagGetter('removeNestedCallsToDispatchMountItemsOnAndroid', false); /** * Propagate layout direction to Android views. */ diff --git a/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js b/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js index e5e0dbcfe623e3..8832b8de6eecca 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<> + * @generated SignedSource<<039fde6acab2250f771634a7c350bbb7>> * @flow strict */ @@ -59,6 +59,7 @@ export interface Spec extends TurboModule { +initEagerTurboModulesOnNativeModulesQueueAndroid?: () => boolean; +lazyAnimationCallbacks?: () => boolean; +loadVectorDrawablesOnImages?: () => boolean; + +removeNestedCallsToDispatchMountItemsOnAndroid?: () => boolean; +setAndroidLayoutDirection?: () => boolean; +traceTurboModulePromiseRejectionsOnAndroid?: () => boolean; +useFabricInterop?: () => boolean;