From 232edb99565d33f30c912964eb0d1d1762397d22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20B=C5=82oniarz?= Date: Wed, 30 Sep 2026 02:41:19 +0200 Subject: [PATCH] Send only changed props on Insert of preallocated views with accumulated raw props With enableAccumulatedUpdatesInRawPropsAndroid, every Insert emits UpdateProps({}, new) and sends the view's full props again, although the view already received them at preallocation or from its Create item. So every inserted view's props are serialized and applied twice. Under the pull model both happen on the UI thread. With Props 2.0 the second payload is diffed against default props, so a prop reset to its default between preallocation and mount is never sent. Behind the new enablePreallocatedPropsDiffOnInsertAndroid flag, the allocated view registry keeps the props a view was preallocated with until its first Insert. That Insert sends the difference between the preallocated and inserted props, and nothing for views created by a Create item. --- .../featureflags/ReactNativeFeatureFlags.kt | 8 +- .../ReactNativeFeatureFlagsCxxAccessor.kt | 12 +- .../ReactNativeFeatureFlagsCxxInterop.kt | 4 +- .../ReactNativeFeatureFlagsDefaults.kt | 4 +- .../ReactNativeFeatureFlagsLocalAccessor.kt | 13 ++- .../ReactNativeFeatureFlagsProvider.kt | 4 +- .../react/fabric/FabricMountingManager.cpp | 54 ++++++--- .../jni/react/fabric/FabricMountingManager.h | 9 +- .../JReactNativeFeatureFlagsCxxInterop.cpp | 16 ++- .../JReactNativeFeatureFlagsCxxInterop.h | 5 +- .../featureflags/ReactNativeFeatureFlags.cpp | 6 +- .../featureflags/ReactNativeFeatureFlags.h | 7 +- .../ReactNativeFeatureFlagsAccessor.cpp | 108 ++++++++++-------- .../ReactNativeFeatureFlagsAccessor.h | 6 +- .../ReactNativeFeatureFlagsDefaults.h | 6 +- .../ReactNativeFeatureFlagsDynamicProvider.h | 11 +- .../ReactNativeFeatureFlagsProvider.h | 3 +- .../NativeReactNativeFeatureFlags.cpp | 7 +- .../NativeReactNativeFeatureFlags.h | 4 +- .../ReactNativeFeatureFlags.config.js | 11 ++ .../featureflags/ReactNativeFeatureFlags.js | 7 +- .../specs/NativeReactNativeFeatureFlags.js | 3 +- 22 files changed, 226 insertions(+), 82 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt index b4cf39c69be..79092ab4a78 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<<86390dbd6b2c57cb4f8cdd7cb73cc1f7>> */ /** @@ -300,6 +300,12 @@ public object ReactNativeFeatureFlags { @JvmStatic public fun enableNativeCSSParsing(): Boolean = accessor.enableNativeCSSParsing() + /** + * When enabled together with `enableAccumulatedUpdatesInRawPropsAndroid`, the Insert of a preallocated view only sends the difference between the props the view was preallocated with and the inserted props, instead of sending all props again on every Insert. + */ + @JvmStatic + public fun enablePreallocatedPropsDiffOnInsertAndroid(): Boolean = accessor.enablePreallocatedPropsDiffOnInsertAndroid() + /** * Enables caching text layout artifacts for later reuse */ 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 352d4a2d358..535c60b7e06 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<<3e939eebe846d12cab15905db8efba18>> */ /** @@ -65,6 +65,7 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces private var enableMountingCoordinatorPullModelAndroidCache: Boolean? = null private var enableMutationObserverByDefaultCache: Boolean? = null private var enableNativeCSSParsingCache: Boolean? = null + private var enablePreallocatedPropsDiffOnInsertAndroidCache: Boolean? = null private var enablePreparedTextLayoutCache: Boolean? = null private var enablePropsUpdateReconciliationAndroidCache: Boolean? = null private var enableResizeObserverByDefaultCache: Boolean? = null @@ -515,6 +516,15 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces return cached } + override fun enablePreallocatedPropsDiffOnInsertAndroid(): Boolean { + var cached = enablePreallocatedPropsDiffOnInsertAndroidCache + if (cached == null) { + cached = ReactNativeFeatureFlagsCxxInterop.enablePreallocatedPropsDiffOnInsertAndroid() + enablePreallocatedPropsDiffOnInsertAndroidCache = cached + } + return cached + } + override fun enablePreparedTextLayout(): Boolean { var cached = enablePreparedTextLayoutCache 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 92be8ae1426..586fec5afb5 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<> + * @generated SignedSource<> */ /** @@ -118,6 +118,8 @@ public object ReactNativeFeatureFlagsCxxInterop { @DoNotStrip @JvmStatic public external fun enableNativeCSSParsing(): Boolean + @DoNotStrip @JvmStatic public external fun enablePreallocatedPropsDiffOnInsertAndroid(): Boolean + @DoNotStrip @JvmStatic public external fun enablePreparedTextLayout(): Boolean @DoNotStrip @JvmStatic public external fun enablePropsUpdateReconciliationAndroid(): 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 c9ea95e2763..067d6fe4f12 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<<890e204b6cf8afef481f64de44766edf>> + * @generated SignedSource<<0f4c074c11c564f05950eab73a8fd452>> */ /** @@ -113,6 +113,8 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi override fun enableNativeCSSParsing(): Boolean = false + override fun enablePreallocatedPropsDiffOnInsertAndroid(): Boolean = false + override fun enablePreparedTextLayout(): Boolean = false override fun enablePropsUpdateReconciliationAndroid(): 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 4cbaa0d49b1..0d473e108d0 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<<9044f0df865ba9d7668f9ff391d21911>> + * @generated SignedSource<<013790bd2c3fa8b9ff03e8c5e924bf91>> */ /** @@ -69,6 +69,7 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc private var enableMountingCoordinatorPullModelAndroidCache: Boolean? = null private var enableMutationObserverByDefaultCache: Boolean? = null private var enableNativeCSSParsingCache: Boolean? = null + private var enablePreallocatedPropsDiffOnInsertAndroidCache: Boolean? = null private var enablePreparedTextLayoutCache: Boolean? = null private var enablePropsUpdateReconciliationAndroidCache: Boolean? = null private var enableResizeObserverByDefaultCache: Boolean? = null @@ -564,6 +565,16 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc return cached } + override fun enablePreallocatedPropsDiffOnInsertAndroid(): Boolean { + var cached = enablePreallocatedPropsDiffOnInsertAndroidCache + if (cached == null) { + cached = currentProvider.enablePreallocatedPropsDiffOnInsertAndroid() + accessedFeatureFlags.add("enablePreallocatedPropsDiffOnInsertAndroid") + enablePreallocatedPropsDiffOnInsertAndroidCache = cached + } + return cached + } + override fun enablePreparedTextLayout(): Boolean { var cached = enablePreparedTextLayoutCache 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 5fd66c91d1a..cdf1a804818 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<<6607c8678df2693c361f6d8091483662>> */ /** @@ -113,6 +113,8 @@ public interface ReactNativeFeatureFlagsProvider { @DoNotStrip public fun enableNativeCSSParsing(): Boolean + @DoNotStrip public fun enablePreallocatedPropsDiffOnInsertAndroid(): Boolean + @DoNotStrip public fun enablePreparedTextLayout(): Boolean @DoNotStrip public fun enablePropsUpdateReconciliationAndroid(): Boolean diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/FabricMountingManager.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/FabricMountingManager.cpp index f1e15694da6..bcedfa1e440 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/FabricMountingManager.cpp +++ b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/FabricMountingManager.cpp @@ -46,7 +46,7 @@ FabricMountingManager::~FabricMountingManager() { void FabricMountingManager::onSurfaceStart(SurfaceId surfaceId) { std::lock_guard lock(allocatedViewsMutex_); allocatedViewRegistry_.emplace( - surfaceId, std::unordered_set({surfaceId})); + surfaceId, std::unordered_map{{surfaceId, nullptr}}); } void FabricMountingManager::onSurfaceStop(SurfaceId surfaceId) { @@ -311,6 +311,11 @@ inline float scale(Float value, Float pointScaleFactor) { return result; } +bool shouldDiffInsertPropsAgainstPreallocatedProps() { + return ReactNativeFeatureFlags::enableAccumulatedUpdatesInRawPropsAndroid() && + ReactNativeFeatureFlags::enablePreallocatedPropsDiffOnInsertAndroid(); +} + jni::local_ref getProps( const ShadowView& oldShadowView, const ShadowView& newShadowView) { @@ -609,12 +614,12 @@ void FabricMountingManager::executeMount( std::lock_guard allocatedViewsLock(allocatedViewsMutex_); auto allocatedViewsIterator = allocatedViewRegistry_.find(surfaceId); - auto defaultAllocatedViews = std::unordered_set{}; + auto defaultAllocatedViews = std::unordered_map{}; // Do not remove `defaultAllocatedViews` or initialize - // `std::unordered_set{}` inline in below ternary expression - if falsy - // operand is a value type, the compiler will decide the expression to be a - // value type, an unnecessary (sometimes expensive) copy will happen as a - // result. + // `std::unordered_map{}` inline in below ternary + // expression - if falsy operand is a value type, the compiler will decide + // the expression to be a value type, an unnecessary (sometimes expensive) + // copy will happen as a result. auto& allocatedViewTags = allocatedViewsIterator != allocatedViewRegistry_.end() ? allocatedViewsIterator->second @@ -640,7 +645,7 @@ void FabricMountingManager::executeMount( if (shouldCreateView) { cppCommonMountItems.push_back( CppMountItem::CreateMountItem(newChildShadowView)); - allocatedViewTags.insert(newChildShadowView.tag); + allocatedViewTags.emplace(newChildShadowView.tag, nullptr); } break; } @@ -734,19 +739,34 @@ void FabricMountingManager::executeMount( CppMountItem::InsertMountItem( parentTag, newChildShadowView, index)); - bool shouldCreateView = - !allocatedViewTags.contains(newChildShadowView.tag); + auto allocatedView = allocatedViewTags.find(newChildShadowView.tag); + bool shouldCreateView = allocatedView == allocatedViewTags.end(); if (ReactNativeFeatureFlags:: enableAccumulatedUpdatesInRawPropsAndroid()) { if (shouldCreateView) { LOG(ERROR) << "Emitting insert for unallocated view " << newChildShadowView.tag; } - (maintainMutationOrder ? cppCommonMountItems - : cppUpdatePropsMountItems) - .push_back( - CppMountItem::UpdatePropsMountItem( - {}, newChildShadowView)); + if (shouldCreateView || + !shouldDiffInsertPropsAgainstPreallocatedProps()) { + (maintainMutationOrder ? cppCommonMountItems + : cppUpdatePropsMountItems) + .push_back( + CppMountItem::UpdatePropsMountItem( + {}, newChildShadowView)); + } else if (auto& preallocatedProps = allocatedView->second; + preallocatedProps != nullptr) { + if (preallocatedProps != newChildShadowView.props) { + auto preallocatedShadowView = newChildShadowView; + preallocatedShadowView.props = preallocatedProps; + (maintainMutationOrder ? cppCommonMountItems + : cppUpdatePropsMountItems) + .push_back( + CppMountItem::UpdatePropsMountItem( + preallocatedShadowView, newChildShadowView)); + } + preallocatedProps = nullptr; + } } else { if (shouldCreateView) { LOG(ERROR) << "Emitting insert for unallocated view " @@ -1107,8 +1127,10 @@ void FabricMountingManager::preallocateShadowView( if (allocatedViewsIterator == allocatedViewRegistry_.end()) { return; } - const auto [_, inserted] = - allocatedViewsIterator->second.insert(shadowView.tag); + const auto [_, inserted] = allocatedViewsIterator->second.emplace( + shadowView.tag, + shouldDiffInsertPropsAgainstPreallocatedProps() ? shadowView.props + : nullptr); if (!inserted) { return; } diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/FabricMountingManager.h b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/FabricMountingManager.h index 3d31c58db7e..7ed9262f660 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/FabricMountingManager.h +++ b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/FabricMountingManager.h @@ -9,10 +9,10 @@ #include #include -#include #include #include +#include #include namespace facebook::react { @@ -109,7 +109,12 @@ class FabricMountingManager final { */ std::vector preallocatedViewsQueue_{}; - std::unordered_map> allocatedViewRegistry_{}; + /* + * Allocated tags per surface. With enablePreallocatedPropsDiffOnInsertAndroid + * a preallocated tag maps to the props it was preallocated with until its + * first Insert; every other tag maps to nullptr. + */ + std::unordered_map> allocatedViewRegistry_{}; std::recursive_mutex allocatedViewsMutex_; }; 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 bb2a2fa0da1..e1824f6ca0b 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<> */ /** @@ -309,6 +309,12 @@ class ReactNativeFeatureFlagsJavaProvider return method(javaProvider_); } + bool enablePreallocatedPropsDiffOnInsertAndroid() override { + static const auto method = + getReactNativeFeatureFlagsProviderJavaClass()->getMethod("enablePreallocatedPropsDiffOnInsertAndroid"); + return method(javaProvider_); + } + bool enablePreparedTextLayout() override { static const auto method = getReactNativeFeatureFlagsProviderJavaClass()->getMethod("enablePreparedTextLayout"); @@ -802,6 +808,11 @@ bool JReactNativeFeatureFlagsCxxInterop::enableNativeCSSParsing( return ReactNativeFeatureFlags::enableNativeCSSParsing(); } +bool JReactNativeFeatureFlagsCxxInterop::enablePreallocatedPropsDiffOnInsertAndroid( + facebook::jni::alias_ref /*unused*/) { + return ReactNativeFeatureFlags::enablePreallocatedPropsDiffOnInsertAndroid(); +} + bool JReactNativeFeatureFlagsCxxInterop::enablePreparedTextLayout( facebook::jni::alias_ref /*unused*/) { return ReactNativeFeatureFlags::enablePreparedTextLayout(); @@ -1188,6 +1199,9 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() { makeNativeMethod( "enableNativeCSSParsing", JReactNativeFeatureFlagsCxxInterop::enableNativeCSSParsing), + makeNativeMethod( + "enablePreallocatedPropsDiffOnInsertAndroid", + JReactNativeFeatureFlagsCxxInterop::enablePreallocatedPropsDiffOnInsertAndroid), makeNativeMethod( "enablePreparedTextLayout", JReactNativeFeatureFlagsCxxInterop::enablePreparedTextLayout), 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 c6ca35483ec..1b6f4ee6646 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<<25d66101785e737822e86d218789912d>> + * @generated SignedSource<<7a9a9c1938c3e01f589e05fffe349ad3>> */ /** @@ -165,6 +165,9 @@ class JReactNativeFeatureFlagsCxxInterop static bool enableNativeCSSParsing( facebook::jni::alias_ref); + static bool enablePreallocatedPropsDiffOnInsertAndroid( + facebook::jni::alias_ref); + static bool enablePreparedTextLayout( 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 d5fd9043821..fdc1b47a2d6 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<<8b8b80ac3744a205b20cfd0627856fba>> + * @generated SignedSource<<8b23b6ea5f2d377f8126adffd753dae7>> */ /** @@ -206,6 +206,10 @@ bool ReactNativeFeatureFlags::enableNativeCSSParsing() { return getAccessor().enableNativeCSSParsing(); } +bool ReactNativeFeatureFlags::enablePreallocatedPropsDiffOnInsertAndroid() { + return getAccessor().enablePreallocatedPropsDiffOnInsertAndroid(); +} + bool ReactNativeFeatureFlags::enablePreparedTextLayout() { return getAccessor().enablePreparedTextLayout(); } diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h index f16f57306b3..1437e361ec6 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<<4c93a39dd2a8ee5ba24f3f8bc99ac1ae>> + * @generated SignedSource<> */ /** @@ -266,6 +266,11 @@ class ReactNativeFeatureFlags { */ RN_EXPORT static bool enableNativeCSSParsing(); + /** + * When enabled together with `enableAccumulatedUpdatesInRawPropsAndroid`, the Insert of a preallocated view only sends the difference between the props the view was preallocated with and the inserted props, instead of sending all props again on every Insert. + */ + RN_EXPORT static bool enablePreallocatedPropsDiffOnInsertAndroid(); + /** * Enables caching text layout artifacts for later reuse */ diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp index 9bb52b98e80..ab9754f2662 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<> */ /** @@ -839,6 +839,24 @@ bool ReactNativeFeatureFlagsAccessor::enableNativeCSSParsing() { return flagValue.value(); } +bool ReactNativeFeatureFlagsAccessor::enablePreallocatedPropsDiffOnInsertAndroid() { + auto flagValue = enablePreallocatedPropsDiffOnInsertAndroid_.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(45, "enablePreallocatedPropsDiffOnInsertAndroid"); + + flagValue = currentProvider_->enablePreallocatedPropsDiffOnInsertAndroid(); + enablePreallocatedPropsDiffOnInsertAndroid_ = flagValue; + } + + return flagValue.value(); +} + bool ReactNativeFeatureFlagsAccessor::enablePreparedTextLayout() { auto flagValue = enablePreparedTextLayout_.load(); @@ -848,7 +866,7 @@ bool ReactNativeFeatureFlagsAccessor::enablePreparedTextLayout() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(45, "enablePreparedTextLayout"); + markFlagAsAccessed(46, "enablePreparedTextLayout"); flagValue = currentProvider_->enablePreparedTextLayout(); enablePreparedTextLayout_ = flagValue; @@ -866,7 +884,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(46, "enablePropsUpdateReconciliationAndroid"); + markFlagAsAccessed(47, "enablePropsUpdateReconciliationAndroid"); flagValue = currentProvider_->enablePropsUpdateReconciliationAndroid(); enablePropsUpdateReconciliationAndroid_ = flagValue; @@ -884,7 +902,7 @@ bool ReactNativeFeatureFlagsAccessor::enableResizeObserverByDefault() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(47, "enableResizeObserverByDefault"); + markFlagAsAccessed(48, "enableResizeObserverByDefault"); flagValue = currentProvider_->enableResizeObserverByDefault(); enableResizeObserverByDefault_ = flagValue; @@ -902,7 +920,7 @@ bool ReactNativeFeatureFlagsAccessor::enableSwiftUIBasedFilters() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(48, "enableSwiftUIBasedFilters"); + markFlagAsAccessed(49, "enableSwiftUIBasedFilters"); flagValue = currentProvider_->enableSwiftUIBasedFilters(); enableSwiftUIBasedFilters_ = flagValue; @@ -920,7 +938,7 @@ bool ReactNativeFeatureFlagsAccessor::enableViewCulling() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(49, "enableViewCulling"); + markFlagAsAccessed(50, "enableViewCulling"); flagValue = currentProvider_->enableViewCulling(); enableViewCulling_ = flagValue; @@ -938,7 +956,7 @@ bool ReactNativeFeatureFlagsAccessor::enableViewRecycling() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(50, "enableViewRecycling"); + markFlagAsAccessed(51, "enableViewRecycling"); flagValue = currentProvider_->enableViewRecycling(); enableViewRecycling_ = flagValue; @@ -956,7 +974,7 @@ bool ReactNativeFeatureFlagsAccessor::enableViewRecyclingForImage() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(51, "enableViewRecyclingForImage"); + markFlagAsAccessed(52, "enableViewRecyclingForImage"); flagValue = currentProvider_->enableViewRecyclingForImage(); enableViewRecyclingForImage_ = flagValue; @@ -974,7 +992,7 @@ bool ReactNativeFeatureFlagsAccessor::enableViewRecyclingForScrollView() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(52, "enableViewRecyclingForScrollView"); + markFlagAsAccessed(53, "enableViewRecyclingForScrollView"); flagValue = currentProvider_->enableViewRecyclingForScrollView(); enableViewRecyclingForScrollView_ = flagValue; @@ -992,7 +1010,7 @@ bool ReactNativeFeatureFlagsAccessor::enableViewRecyclingForText() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(53, "enableViewRecyclingForText"); + markFlagAsAccessed(54, "enableViewRecyclingForText"); flagValue = currentProvider_->enableViewRecyclingForText(); enableViewRecyclingForText_ = flagValue; @@ -1010,7 +1028,7 @@ bool ReactNativeFeatureFlagsAccessor::enableViewRecyclingForView() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(54, "enableViewRecyclingForView"); + markFlagAsAccessed(55, "enableViewRecyclingForView"); flagValue = currentProvider_->enableViewRecyclingForView(); enableViewRecyclingForView_ = flagValue; @@ -1028,7 +1046,7 @@ bool ReactNativeFeatureFlagsAccessor::enableVirtualViewContainerStateExperimenta // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(55, "enableVirtualViewContainerStateExperimental"); + markFlagAsAccessed(56, "enableVirtualViewContainerStateExperimental"); flagValue = currentProvider_->enableVirtualViewContainerStateExperimental(); enableVirtualViewContainerStateExperimental_ = flagValue; @@ -1046,7 +1064,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(56, "fixMappingOfEventPrioritiesBetweenFabricAndReact"); + markFlagAsAccessed(57, "fixMappingOfEventPrioritiesBetweenFabricAndReact"); flagValue = currentProvider_->fixMappingOfEventPrioritiesBetweenFabricAndReact(); fixMappingOfEventPrioritiesBetweenFabricAndReact_ = flagValue; @@ -1064,7 +1082,7 @@ bool ReactNativeFeatureFlagsAccessor::fixYogaFlexBasisFitContentInMainAxis() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(57, "fixYogaFlexBasisFitContentInMainAxis"); + markFlagAsAccessed(58, "fixYogaFlexBasisFitContentInMainAxis"); flagValue = currentProvider_->fixYogaFlexBasisFitContentInMainAxis(); fixYogaFlexBasisFitContentInMainAxis_ = flagValue; @@ -1082,7 +1100,7 @@ bool ReactNativeFeatureFlagsAccessor::fuseboxAssertSingleHostState() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(58, "fuseboxAssertSingleHostState"); + markFlagAsAccessed(59, "fuseboxAssertSingleHostState"); flagValue = currentProvider_->fuseboxAssertSingleHostState(); fuseboxAssertSingleHostState_ = flagValue; @@ -1100,7 +1118,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(59, "fuseboxEnabledRelease"); + markFlagAsAccessed(60, "fuseboxEnabledRelease"); flagValue = currentProvider_->fuseboxEnabledRelease(); fuseboxEnabledRelease_ = flagValue; @@ -1118,7 +1136,7 @@ bool ReactNativeFeatureFlagsAccessor::fuseboxFrameRecordingEnabled() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(60, "fuseboxFrameRecordingEnabled"); + markFlagAsAccessed(61, "fuseboxFrameRecordingEnabled"); flagValue = currentProvider_->fuseboxFrameRecordingEnabled(); fuseboxFrameRecordingEnabled_ = flagValue; @@ -1136,7 +1154,7 @@ bool ReactNativeFeatureFlagsAccessor::fuseboxScreenshotCaptureEnabled() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(61, "fuseboxScreenshotCaptureEnabled"); + markFlagAsAccessed(62, "fuseboxScreenshotCaptureEnabled"); flagValue = currentProvider_->fuseboxScreenshotCaptureEnabled(); fuseboxScreenshotCaptureEnabled_ = flagValue; @@ -1154,7 +1172,7 @@ bool ReactNativeFeatureFlagsAccessor::fuseboxWebSocketEventsEnabled() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(62, "fuseboxWebSocketEventsEnabled"); + markFlagAsAccessed(63, "fuseboxWebSocketEventsEnabled"); flagValue = currentProvider_->fuseboxWebSocketEventsEnabled(); fuseboxWebSocketEventsEnabled_ = flagValue; @@ -1172,7 +1190,7 @@ bool ReactNativeFeatureFlagsAccessor::optimizedAnimatedPropUpdates() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(63, "optimizedAnimatedPropUpdates"); + markFlagAsAccessed(64, "optimizedAnimatedPropUpdates"); flagValue = currentProvider_->optimizedAnimatedPropUpdates(); optimizedAnimatedPropUpdates_ = flagValue; @@ -1190,7 +1208,7 @@ bool ReactNativeFeatureFlagsAccessor::overrideBySynchronousMountPropsAtMountingA // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(64, "overrideBySynchronousMountPropsAtMountingAndroid"); + markFlagAsAccessed(65, "overrideBySynchronousMountPropsAtMountingAndroid"); flagValue = currentProvider_->overrideBySynchronousMountPropsAtMountingAndroid(); overrideBySynchronousMountPropsAtMountingAndroid_ = flagValue; @@ -1208,7 +1226,7 @@ bool ReactNativeFeatureFlagsAccessor::perfIssuesEnabled() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(65, "perfIssuesEnabled"); + markFlagAsAccessed(66, "perfIssuesEnabled"); flagValue = currentProvider_->perfIssuesEnabled(); perfIssuesEnabled_ = flagValue; @@ -1226,7 +1244,7 @@ bool ReactNativeFeatureFlagsAccessor::perfMonitorV2Enabled() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(66, "perfMonitorV2Enabled"); + markFlagAsAccessed(67, "perfMonitorV2Enabled"); flagValue = currentProvider_->perfMonitorV2Enabled(); perfMonitorV2Enabled_ = flagValue; @@ -1244,7 +1262,7 @@ double ReactNativeFeatureFlagsAccessor::preparedTextCacheSize() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(67, "preparedTextCacheSize"); + markFlagAsAccessed(68, "preparedTextCacheSize"); flagValue = currentProvider_->preparedTextCacheSize(); preparedTextCacheSize_ = flagValue; @@ -1262,7 +1280,7 @@ bool ReactNativeFeatureFlagsAccessor::preventShadowTreeCommitExhaustion() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(68, "preventShadowTreeCommitExhaustion"); + markFlagAsAccessed(69, "preventShadowTreeCommitExhaustion"); flagValue = currentProvider_->preventShadowTreeCommitExhaustion(); preventShadowTreeCommitExhaustion_ = flagValue; @@ -1280,7 +1298,7 @@ bool ReactNativeFeatureFlagsAccessor::redBoxV2Android() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(69, "redBoxV2Android"); + markFlagAsAccessed(70, "redBoxV2Android"); flagValue = currentProvider_->redBoxV2Android(); redBoxV2Android_ = flagValue; @@ -1298,7 +1316,7 @@ bool ReactNativeFeatureFlagsAccessor::redBoxV2IOS() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(70, "redBoxV2IOS"); + markFlagAsAccessed(71, "redBoxV2IOS"); flagValue = currentProvider_->redBoxV2IOS(); redBoxV2IOS_ = flagValue; @@ -1316,7 +1334,7 @@ bool ReactNativeFeatureFlagsAccessor::shouldPressibilityUseW3CPointerEventsForHo // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(71, "shouldPressibilityUseW3CPointerEventsForHover"); + markFlagAsAccessed(72, "shouldPressibilityUseW3CPointerEventsForHover"); flagValue = currentProvider_->shouldPressibilityUseW3CPointerEventsForHover(); shouldPressibilityUseW3CPointerEventsForHover_ = flagValue; @@ -1334,7 +1352,7 @@ bool ReactNativeFeatureFlagsAccessor::shouldTriggerResponderTransferOnScrollAndr // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(72, "shouldTriggerResponderTransferOnScrollAndroid"); + markFlagAsAccessed(73, "shouldTriggerResponderTransferOnScrollAndroid"); flagValue = currentProvider_->shouldTriggerResponderTransferOnScrollAndroid(); shouldTriggerResponderTransferOnScrollAndroid_ = flagValue; @@ -1352,7 +1370,7 @@ bool ReactNativeFeatureFlagsAccessor::skipActivityIdentityAssertionOnHostPause() // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(73, "skipActivityIdentityAssertionOnHostPause"); + markFlagAsAccessed(74, "skipActivityIdentityAssertionOnHostPause"); flagValue = currentProvider_->skipActivityIdentityAssertionOnHostPause(); skipActivityIdentityAssertionOnHostPause_ = flagValue; @@ -1370,7 +1388,7 @@ bool ReactNativeFeatureFlagsAccessor::syncAndroidClipBoundsWithOverflow() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(74, "syncAndroidClipBoundsWithOverflow"); + markFlagAsAccessed(75, "syncAndroidClipBoundsWithOverflow"); flagValue = currentProvider_->syncAndroidClipBoundsWithOverflow(); syncAndroidClipBoundsWithOverflow_ = flagValue; @@ -1388,7 +1406,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(75, "traceTurboModulePromiseRejectionsOnAndroid"); + markFlagAsAccessed(76, "traceTurboModulePromiseRejectionsOnAndroid"); flagValue = currentProvider_->traceTurboModulePromiseRejectionsOnAndroid(); traceTurboModulePromiseRejectionsOnAndroid_ = flagValue; @@ -1406,7 +1424,7 @@ bool ReactNativeFeatureFlagsAccessor::updateRuntimeShadowNodeReferencesOnCommit( // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(76, "updateRuntimeShadowNodeReferencesOnCommit"); + markFlagAsAccessed(77, "updateRuntimeShadowNodeReferencesOnCommit"); flagValue = currentProvider_->updateRuntimeShadowNodeReferencesOnCommit(); updateRuntimeShadowNodeReferencesOnCommit_ = flagValue; @@ -1424,7 +1442,7 @@ bool ReactNativeFeatureFlagsAccessor::updateRuntimeShadowNodeReferencesOnCommitT // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(77, "updateRuntimeShadowNodeReferencesOnCommitThread"); + markFlagAsAccessed(78, "updateRuntimeShadowNodeReferencesOnCommitThread"); flagValue = currentProvider_->updateRuntimeShadowNodeReferencesOnCommitThread(); updateRuntimeShadowNodeReferencesOnCommitThread_ = flagValue; @@ -1442,7 +1460,7 @@ bool ReactNativeFeatureFlagsAccessor::useAlwaysAvailableJSErrorHandling() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(78, "useAlwaysAvailableJSErrorHandling"); + markFlagAsAccessed(79, "useAlwaysAvailableJSErrorHandling"); flagValue = currentProvider_->useAlwaysAvailableJSErrorHandling(); useAlwaysAvailableJSErrorHandling_ = flagValue; @@ -1460,7 +1478,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(79, "useFabricInterop"); + markFlagAsAccessed(80, "useFabricInterop"); flagValue = currentProvider_->useFabricInterop(); useFabricInterop_ = flagValue; @@ -1478,7 +1496,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(80, "useNativeViewConfigsInBridgelessMode"); + markFlagAsAccessed(81, "useNativeViewConfigsInBridgelessMode"); flagValue = currentProvider_->useNativeViewConfigsInBridgelessMode(); useNativeViewConfigsInBridgelessMode_ = flagValue; @@ -1496,7 +1514,7 @@ bool ReactNativeFeatureFlagsAccessor::useNestedScrollViewAndroid() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(81, "useNestedScrollViewAndroid"); + markFlagAsAccessed(82, "useNestedScrollViewAndroid"); flagValue = currentProvider_->useNestedScrollViewAndroid(); useNestedScrollViewAndroid_ = flagValue; @@ -1514,7 +1532,7 @@ bool ReactNativeFeatureFlagsAccessor::useSharedAnimatedBackend() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(82, "useSharedAnimatedBackend"); + markFlagAsAccessed(83, "useSharedAnimatedBackend"); flagValue = currentProvider_->useSharedAnimatedBackend(); useSharedAnimatedBackend_ = flagValue; @@ -1532,7 +1550,7 @@ bool ReactNativeFeatureFlagsAccessor::useTraitHiddenOnAndroid() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(83, "useTraitHiddenOnAndroid"); + markFlagAsAccessed(84, "useTraitHiddenOnAndroid"); flagValue = currentProvider_->useTraitHiddenOnAndroid(); useTraitHiddenOnAndroid_ = flagValue; @@ -1550,7 +1568,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(84, "useTurboModuleInterop"); + markFlagAsAccessed(85, "useTurboModuleInterop"); flagValue = currentProvider_->useTurboModuleInterop(); useTurboModuleInterop_ = flagValue; @@ -1568,7 +1586,7 @@ double ReactNativeFeatureFlagsAccessor::viewCullingOutsetRatio() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(85, "viewCullingOutsetRatio"); + markFlagAsAccessed(86, "viewCullingOutsetRatio"); flagValue = currentProvider_->viewCullingOutsetRatio(); viewCullingOutsetRatio_ = flagValue; @@ -1586,7 +1604,7 @@ bool ReactNativeFeatureFlagsAccessor::viewTransitionEnabled() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(86, "viewTransitionEnabled"); + markFlagAsAccessed(87, "viewTransitionEnabled"); flagValue = currentProvider_->viewTransitionEnabled(); viewTransitionEnabled_ = flagValue; @@ -1604,7 +1622,7 @@ bool ReactNativeFeatureFlagsAccessor::viewTransitionUseHardwareBitmapAndroid() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(87, "viewTransitionUseHardwareBitmapAndroid"); + markFlagAsAccessed(88, "viewTransitionUseHardwareBitmapAndroid"); flagValue = currentProvider_->viewTransitionUseHardwareBitmapAndroid(); viewTransitionUseHardwareBitmapAndroid_ = flagValue; @@ -1622,7 +1640,7 @@ double ReactNativeFeatureFlagsAccessor::virtualViewPrerenderRatio() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(88, "virtualViewPrerenderRatio"); + markFlagAsAccessed(89, "virtualViewPrerenderRatio"); flagValue = currentProvider_->virtualViewPrerenderRatio(); virtualViewPrerenderRatio_ = flagValue; diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h index 2bf0443bbf3..6cbf6d88937 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<<3e557788d6bd43975af8dcb392beef94>> + * @generated SignedSource<> */ /** @@ -79,6 +79,7 @@ class ReactNativeFeatureFlagsAccessor { bool enableMountingCoordinatorPullModelAndroid(); bool enableMutationObserverByDefault(); bool enableNativeCSSParsing(); + bool enablePreallocatedPropsDiffOnInsertAndroid(); bool enablePreparedTextLayout(); bool enablePropsUpdateReconciliationAndroid(); bool enableResizeObserverByDefault(); @@ -134,7 +135,7 @@ class ReactNativeFeatureFlagsAccessor { std::unique_ptr currentProvider_; bool wasOverridden_; - std::array, 89> accessedFeatureFlags_; + std::array, 90> accessedFeatureFlags_; std::atomic> commonTestFlag_; std::atomic> cdpInteractionMetricsEnabled_; @@ -181,6 +182,7 @@ class ReactNativeFeatureFlagsAccessor { std::atomic> enableMountingCoordinatorPullModelAndroid_; std::atomic> enableMutationObserverByDefault_; std::atomic> enableNativeCSSParsing_; + std::atomic> enablePreallocatedPropsDiffOnInsertAndroid_; std::atomic> enablePreparedTextLayout_; std::atomic> enablePropsUpdateReconciliationAndroid_; std::atomic> enableResizeObserverByDefault_; diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h index 6406564a965..e5ea88af00f 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<<07754aa6f05f6219f95a7b9a2e83ba49>> + * @generated SignedSource<<6abef654d3dd784b7211ac8874069020>> */ /** @@ -209,6 +209,10 @@ class ReactNativeFeatureFlagsDefaults : public ReactNativeFeatureFlagsProvider { return false; } + bool enablePreallocatedPropsDiffOnInsertAndroid() override { + return false; + } + bool enablePreparedTextLayout() override { return false; } diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDynamicProvider.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDynamicProvider.h index 0afb0a1f6d6..fc4a49a0eda 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDynamicProvider.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDynamicProvider.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<<625c7c4f1d55e7ca5c226793fe982c7b>> */ /** @@ -452,6 +452,15 @@ class ReactNativeFeatureFlagsDynamicProvider : public ReactNativeFeatureFlagsDef return ReactNativeFeatureFlagsDefaults::enableNativeCSSParsing(); } + bool enablePreallocatedPropsDiffOnInsertAndroid() override { + auto value = values_["enablePreallocatedPropsDiffOnInsertAndroid"]; + if (!value.isNull()) { + return value.getBool(); + } + + return ReactNativeFeatureFlagsDefaults::enablePreallocatedPropsDiffOnInsertAndroid(); + } + bool enablePreparedTextLayout() override { auto value = values_["enablePreparedTextLayout"]; if (!value.isNull()) { diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h index 497876aa4fc..95808868310 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<> + * @generated SignedSource<<428c475acbb4baed380207f0b08b4e26>> */ /** @@ -72,6 +72,7 @@ class ReactNativeFeatureFlagsProvider { virtual bool enableMountingCoordinatorPullModelAndroid() = 0; virtual bool enableMutationObserverByDefault() = 0; virtual bool enableNativeCSSParsing() = 0; + virtual bool enablePreallocatedPropsDiffOnInsertAndroid() = 0; virtual bool enablePreparedTextLayout() = 0; virtual bool enablePropsUpdateReconciliationAndroid() = 0; virtual bool enableResizeObserverByDefault() = 0; diff --git a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp index fc948c8f01c..bb691d5b335 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<<1bfe886891d4d195940b57548e3fcc6e>> + * @generated SignedSource<> */ /** @@ -269,6 +269,11 @@ bool NativeReactNativeFeatureFlags::enableNativeCSSParsing( return ReactNativeFeatureFlags::enableNativeCSSParsing(); } +bool NativeReactNativeFeatureFlags::enablePreallocatedPropsDiffOnInsertAndroid( + jsi::Runtime& /*runtime*/) { + return ReactNativeFeatureFlags::enablePreallocatedPropsDiffOnInsertAndroid(); +} + bool NativeReactNativeFeatureFlags::enablePreparedTextLayout( jsi::Runtime& /*runtime*/) { return ReactNativeFeatureFlags::enablePreparedTextLayout(); diff --git a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h index bc2e6c36a91..16c7dec0a06 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<> + * @generated SignedSource<> */ /** @@ -128,6 +128,8 @@ class NativeReactNativeFeatureFlags bool enableNativeCSSParsing(jsi::Runtime& runtime); + bool enablePreallocatedPropsDiffOnInsertAndroid(jsi::Runtime& runtime); + bool enablePreparedTextLayout(jsi::Runtime& runtime); bool enablePropsUpdateReconciliationAndroid(jsi::Runtime& runtime); diff --git a/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js b/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js index 9d776f20b10..9f8be49d36a 100644 --- a/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js +++ b/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js @@ -531,6 +531,17 @@ const definitions: FeatureFlagDefinitions = { }, ossReleaseStage: 'none', }, + enablePreallocatedPropsDiffOnInsertAndroid: { + defaultValue: false, + metadata: { + dateAdded: '2026-09-30', + description: + 'When enabled together with `enableAccumulatedUpdatesInRawPropsAndroid`, the Insert of a preallocated view only sends the difference between the props the view was preallocated with and the inserted props, instead of sending all props again on every Insert.', + expectedReleaseValue: true, + purpose: 'experimentation', + }, + ossReleaseStage: 'none', + }, enablePreparedTextLayout: { defaultValue: false, metadata: { diff --git a/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js b/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js index b06551330c2..f94c96edd29 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<<6e73a99aafb36218e1d679637bb80c82>> + * @generated SignedSource<<8075ab58916ce356d5acac15888aff7a>> * @flow strict * @noformat */ @@ -94,6 +94,7 @@ export type ReactNativeFeatureFlags = Readonly<{ enableMountingCoordinatorPullModelAndroid: Getter, enableMutationObserverByDefault: Getter, enableNativeCSSParsing: Getter, + enablePreallocatedPropsDiffOnInsertAndroid: Getter, enablePreparedTextLayout: Getter, enablePropsUpdateReconciliationAndroid: Getter, enableResizeObserverByDefault: Getter, @@ -394,6 +395,10 @@ export const enableMutationObserverByDefault: Getter = createNativeFlag * Parse CSS strings using the Fabric CSS parser instead of ViewConfig processing */ export const enableNativeCSSParsing: Getter = createNativeFlagGetter('enableNativeCSSParsing', false); +/** + * When enabled together with `enableAccumulatedUpdatesInRawPropsAndroid`, the Insert of a preallocated view only sends the difference between the props the view was preallocated with and the inserted props, instead of sending all props again on every Insert. + */ +export const enablePreallocatedPropsDiffOnInsertAndroid: Getter = createNativeFlagGetter('enablePreallocatedPropsDiffOnInsertAndroid', false); /** * Enables caching text layout artifacts for later reuse */ diff --git a/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js b/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js index f843d04a95b..591e4ef1ae1 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<> * @flow strict * @noformat */ @@ -70,6 +70,7 @@ export interface Spec extends TurboModule { readonly enableMountingCoordinatorPullModelAndroid?: () => boolean; readonly enableMutationObserverByDefault?: () => boolean; readonly enableNativeCSSParsing?: () => boolean; + readonly enablePreallocatedPropsDiffOnInsertAndroid?: () => boolean; readonly enablePreparedTextLayout?: () => boolean; readonly enablePropsUpdateReconciliationAndroid?: () => boolean; readonly enableResizeObserverByDefault?: () => boolean;