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 468ebfe32d13b1..a7c3a340378ed9 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<<7a9f9d29e1d5f01df33a0893e143a6db>> + * @generated SignedSource<<1bcedffb675f2649666ec7f88752cf53>> */ /** @@ -162,6 +162,12 @@ public object ReactNativeFeatureFlags { @JvmStatic public fun enableExclusivePropsUpdateAndroid(): Boolean = accessor.enableExclusivePropsUpdateAndroid() + /** + * Enables Fabric commit branching to fix starvation problems and atomic JS updates. + */ + @JvmStatic + public fun enableFabricCommitBranching(): Boolean = accessor.enableFabricCommitBranching() + /** * This feature flag enables logs for Fabric. */ 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 476f2e30daf243..570adee5e20d4a 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<> */ /** @@ -42,6 +42,7 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces private var enableEagerMainQueueModulesOnIOSCache: Boolean? = null private var enableEagerRootViewAttachmentCache: Boolean? = null private var enableExclusivePropsUpdateAndroidCache: Boolean? = null + private var enableFabricCommitBranchingCache: Boolean? = null private var enableFabricLogsCache: Boolean? = null private var enableFabricRendererCache: Boolean? = null private var enableFontScaleChangesUpdatingLayoutCache: Boolean? = null @@ -297,6 +298,15 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces return cached } + override fun enableFabricCommitBranching(): Boolean { + var cached = enableFabricCommitBranchingCache + if (cached == null) { + cached = ReactNativeFeatureFlagsCxxInterop.enableFabricCommitBranching() + enableFabricCommitBranchingCache = cached + } + return cached + } + override fun enableFabricLogs(): Boolean { var cached = enableFabricLogsCache 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 525fb9a86b1efa..2dbe99fafa31a9 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<> */ /** @@ -72,6 +72,8 @@ public object ReactNativeFeatureFlagsCxxInterop { @DoNotStrip @JvmStatic public external fun enableExclusivePropsUpdateAndroid(): Boolean + @DoNotStrip @JvmStatic public external fun enableFabricCommitBranching(): Boolean + @DoNotStrip @JvmStatic public external fun enableFabricLogs(): Boolean @DoNotStrip @JvmStatic public external fun enableFabricRenderer(): 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 4a9e42bbe3d3fc..220077657e6464 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<6f46cc2bd1ea42d9e78563e61286b55c>> */ /** @@ -67,6 +67,8 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi override fun enableExclusivePropsUpdateAndroid(): Boolean = false + override fun enableFabricCommitBranching(): Boolean = false + override fun enableFabricLogs(): Boolean = false override fun enableFabricRenderer(): 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 4b6b0bd24b9dd9..707d25b0fb7f39 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<<44f52bff0ecd0f26c2173581b09dccce>> + * @generated SignedSource<> */ /** @@ -46,6 +46,7 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc private var enableEagerMainQueueModulesOnIOSCache: Boolean? = null private var enableEagerRootViewAttachmentCache: Boolean? = null private var enableExclusivePropsUpdateAndroidCache: Boolean? = null + private var enableFabricCommitBranchingCache: Boolean? = null private var enableFabricLogsCache: Boolean? = null private var enableFabricRendererCache: Boolean? = null private var enableFontScaleChangesUpdatingLayoutCache: Boolean? = null @@ -323,6 +324,16 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc return cached } + override fun enableFabricCommitBranching(): Boolean { + var cached = enableFabricCommitBranchingCache + if (cached == null) { + cached = currentProvider.enableFabricCommitBranching() + accessedFeatureFlags.add("enableFabricCommitBranching") + enableFabricCommitBranchingCache = cached + } + return cached + } + override fun enableFabricLogs(): Boolean { var cached = enableFabricLogsCache 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 69eae3cdac01f7..13e403f16d5e3c 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<<2bc1b7c78ced990301722e1c1dcc2dcf>> + * @generated SignedSource<> */ /** @@ -67,6 +67,8 @@ public interface ReactNativeFeatureFlagsProvider { @DoNotStrip public fun enableExclusivePropsUpdateAndroid(): Boolean + @DoNotStrip public fun enableFabricCommitBranching(): Boolean + @DoNotStrip public fun enableFabricLogs(): Boolean @DoNotStrip public fun enableFabricRenderer(): 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 14679e254340bb..64669f578ed826 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<<89d63e717ae8634f32613243bcbe2c40>> + * @generated SignedSource<> */ /** @@ -171,6 +171,12 @@ class ReactNativeFeatureFlagsJavaProvider return method(javaProvider_); } + bool enableFabricCommitBranching() override { + static const auto method = + getReactNativeFeatureFlagsProviderJavaClass()->getMethod("enableFabricCommitBranching"); + return method(javaProvider_); + } + bool enableFabricLogs() override { static const auto method = getReactNativeFeatureFlagsProviderJavaClass()->getMethod("enableFabricLogs"); @@ -621,6 +627,11 @@ bool JReactNativeFeatureFlagsCxxInterop::enableExclusivePropsUpdateAndroid( return ReactNativeFeatureFlags::enableExclusivePropsUpdateAndroid(); } +bool JReactNativeFeatureFlagsCxxInterop::enableFabricCommitBranching( + facebook::jni::alias_ref /*unused*/) { + return ReactNativeFeatureFlags::enableFabricCommitBranching(); +} + bool JReactNativeFeatureFlagsCxxInterop::enableFabricLogs( facebook::jni::alias_ref /*unused*/) { return ReactNativeFeatureFlags::enableFabricLogs(); @@ -998,6 +1009,9 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() { makeNativeMethod( "enableExclusivePropsUpdateAndroid", JReactNativeFeatureFlagsCxxInterop::enableExclusivePropsUpdateAndroid), + makeNativeMethod( + "enableFabricCommitBranching", + JReactNativeFeatureFlagsCxxInterop::enableFabricCommitBranching), makeNativeMethod( "enableFabricLogs", JReactNativeFeatureFlagsCxxInterop::enableFabricLogs), 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 2e92ce6725d83b..4a0dbc06ebf074 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<<1cf1c6d1d2a98a495db315e0e7edcc32>> + * @generated SignedSource<<178ac10d3bb50b5265a9c876408a1ce4>> */ /** @@ -96,6 +96,9 @@ class JReactNativeFeatureFlagsCxxInterop static bool enableExclusivePropsUpdateAndroid( facebook::jni::alias_ref); + static bool enableFabricCommitBranching( + facebook::jni::alias_ref); + static bool enableFabricLogs( 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 1ac8889482e27c..3527da5d41e127 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<<3435395a9b7e728dbdf4f05cdfb1ef0c>> */ /** @@ -114,6 +114,10 @@ bool ReactNativeFeatureFlags::enableExclusivePropsUpdateAndroid() { return getAccessor().enableExclusivePropsUpdateAndroid(); } +bool ReactNativeFeatureFlags::enableFabricCommitBranching() { + return getAccessor().enableFabricCommitBranching(); +} + bool ReactNativeFeatureFlags::enableFabricLogs() { return getAccessor().enableFabricLogs(); } diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h index b61f3b259d85a9..a60ff738ce21c6 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<<0741bbc608bc7d7fdd242d33197057b7>> + * @generated SignedSource<<49186e1c0a2f74379bf6b0292bb9031d>> */ /** @@ -149,6 +149,11 @@ class ReactNativeFeatureFlags { */ RN_EXPORT static bool enableExclusivePropsUpdateAndroid(); + /** + * Enables Fabric commit branching to fix starvation problems and atomic JS updates. + */ + RN_EXPORT static bool enableFabricCommitBranching(); + /** * This feature flag enables logs for Fabric. */ diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp index d967c9511d36f1..abd6c97d2c6199 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<<06632eb42486a31e016dd920f2c1a5c2>> */ /** @@ -425,6 +425,24 @@ bool ReactNativeFeatureFlagsAccessor::enableExclusivePropsUpdateAndroid() { return flagValue.value(); } +bool ReactNativeFeatureFlagsAccessor::enableFabricCommitBranching() { + auto flagValue = enableFabricCommitBranching_.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(22, "enableFabricCommitBranching"); + + flagValue = currentProvider_->enableFabricCommitBranching(); + enableFabricCommitBranching_ = flagValue; + } + + return flagValue.value(); +} + bool ReactNativeFeatureFlagsAccessor::enableFabricLogs() { auto flagValue = enableFabricLogs_.load(); @@ -434,7 +452,7 @@ bool ReactNativeFeatureFlagsAccessor::enableFabricLogs() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(22, "enableFabricLogs"); + markFlagAsAccessed(23, "enableFabricLogs"); flagValue = currentProvider_->enableFabricLogs(); enableFabricLogs_ = flagValue; @@ -452,7 +470,7 @@ bool ReactNativeFeatureFlagsAccessor::enableFabricRenderer() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(23, "enableFabricRenderer"); + markFlagAsAccessed(24, "enableFabricRenderer"); flagValue = currentProvider_->enableFabricRenderer(); enableFabricRenderer_ = flagValue; @@ -470,7 +488,7 @@ bool ReactNativeFeatureFlagsAccessor::enableFontScaleChangesUpdatingLayout() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(24, "enableFontScaleChangesUpdatingLayout"); + markFlagAsAccessed(25, "enableFontScaleChangesUpdatingLayout"); flagValue = currentProvider_->enableFontScaleChangesUpdatingLayout(); enableFontScaleChangesUpdatingLayout_ = flagValue; @@ -488,7 +506,7 @@ bool ReactNativeFeatureFlagsAccessor::enableIOSTextBaselineOffsetPerLine() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(25, "enableIOSTextBaselineOffsetPerLine"); + markFlagAsAccessed(26, "enableIOSTextBaselineOffsetPerLine"); flagValue = currentProvider_->enableIOSTextBaselineOffsetPerLine(); enableIOSTextBaselineOffsetPerLine_ = flagValue; @@ -506,7 +524,7 @@ bool ReactNativeFeatureFlagsAccessor::enableIOSViewClipToPaddingBox() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(26, "enableIOSViewClipToPaddingBox"); + markFlagAsAccessed(27, "enableIOSViewClipToPaddingBox"); flagValue = currentProvider_->enableIOSViewClipToPaddingBox(); enableIOSViewClipToPaddingBox_ = flagValue; @@ -524,7 +542,7 @@ bool ReactNativeFeatureFlagsAccessor::enableImagePrefetchingAndroid() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(27, "enableImagePrefetchingAndroid"); + markFlagAsAccessed(28, "enableImagePrefetchingAndroid"); flagValue = currentProvider_->enableImagePrefetchingAndroid(); enableImagePrefetchingAndroid_ = flagValue; @@ -542,7 +560,7 @@ bool ReactNativeFeatureFlagsAccessor::enableImagePrefetchingJNIBatchingAndroid() // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(28, "enableImagePrefetchingJNIBatchingAndroid"); + markFlagAsAccessed(29, "enableImagePrefetchingJNIBatchingAndroid"); flagValue = currentProvider_->enableImagePrefetchingJNIBatchingAndroid(); enableImagePrefetchingJNIBatchingAndroid_ = flagValue; @@ -560,7 +578,7 @@ bool ReactNativeFeatureFlagsAccessor::enableImagePrefetchingOnUiThreadAndroid() // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(29, "enableImagePrefetchingOnUiThreadAndroid"); + markFlagAsAccessed(30, "enableImagePrefetchingOnUiThreadAndroid"); flagValue = currentProvider_->enableImagePrefetchingOnUiThreadAndroid(); enableImagePrefetchingOnUiThreadAndroid_ = flagValue; @@ -578,7 +596,7 @@ bool ReactNativeFeatureFlagsAccessor::enableImmediateUpdateModeForContentOffsetC // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(30, "enableImmediateUpdateModeForContentOffsetChanges"); + markFlagAsAccessed(31, "enableImmediateUpdateModeForContentOffsetChanges"); flagValue = currentProvider_->enableImmediateUpdateModeForContentOffsetChanges(); enableImmediateUpdateModeForContentOffsetChanges_ = flagValue; @@ -596,7 +614,7 @@ bool ReactNativeFeatureFlagsAccessor::enableImperativeFocus() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(31, "enableImperativeFocus"); + markFlagAsAccessed(32, "enableImperativeFocus"); flagValue = currentProvider_->enableImperativeFocus(); enableImperativeFocus_ = flagValue; @@ -614,7 +632,7 @@ bool ReactNativeFeatureFlagsAccessor::enableInteropViewManagerClassLookUpOptimiz // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(32, "enableInteropViewManagerClassLookUpOptimizationIOS"); + markFlagAsAccessed(33, "enableInteropViewManagerClassLookUpOptimizationIOS"); flagValue = currentProvider_->enableInteropViewManagerClassLookUpOptimizationIOS(); enableInteropViewManagerClassLookUpOptimizationIOS_ = flagValue; @@ -632,7 +650,7 @@ bool ReactNativeFeatureFlagsAccessor::enableIntersectionObserverByDefault() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(33, "enableIntersectionObserverByDefault"); + markFlagAsAccessed(34, "enableIntersectionObserverByDefault"); flagValue = currentProvider_->enableIntersectionObserverByDefault(); enableIntersectionObserverByDefault_ = flagValue; @@ -650,7 +668,7 @@ bool ReactNativeFeatureFlagsAccessor::enableKeyEvents() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(34, "enableKeyEvents"); + markFlagAsAccessed(35, "enableKeyEvents"); flagValue = currentProvider_->enableKeyEvents(); enableKeyEvents_ = flagValue; @@ -668,7 +686,7 @@ bool ReactNativeFeatureFlagsAccessor::enableLayoutAnimationsOnAndroid() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(35, "enableLayoutAnimationsOnAndroid"); + markFlagAsAccessed(36, "enableLayoutAnimationsOnAndroid"); flagValue = currentProvider_->enableLayoutAnimationsOnAndroid(); enableLayoutAnimationsOnAndroid_ = flagValue; @@ -686,7 +704,7 @@ bool ReactNativeFeatureFlagsAccessor::enableLayoutAnimationsOnIOS() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(36, "enableLayoutAnimationsOnIOS"); + markFlagAsAccessed(37, "enableLayoutAnimationsOnIOS"); flagValue = currentProvider_->enableLayoutAnimationsOnIOS(); enableLayoutAnimationsOnIOS_ = flagValue; @@ -704,7 +722,7 @@ bool ReactNativeFeatureFlagsAccessor::enableMainQueueCoordinatorOnIOS() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(37, "enableMainQueueCoordinatorOnIOS"); + markFlagAsAccessed(38, "enableMainQueueCoordinatorOnIOS"); flagValue = currentProvider_->enableMainQueueCoordinatorOnIOS(); enableMainQueueCoordinatorOnIOS_ = flagValue; @@ -722,7 +740,7 @@ bool ReactNativeFeatureFlagsAccessor::enableModuleArgumentNSNullConversionIOS() // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(38, "enableModuleArgumentNSNullConversionIOS"); + markFlagAsAccessed(39, "enableModuleArgumentNSNullConversionIOS"); flagValue = currentProvider_->enableModuleArgumentNSNullConversionIOS(); enableModuleArgumentNSNullConversionIOS_ = flagValue; @@ -740,7 +758,7 @@ bool ReactNativeFeatureFlagsAccessor::enableNativeCSSParsing() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(39, "enableNativeCSSParsing"); + markFlagAsAccessed(40, "enableNativeCSSParsing"); flagValue = currentProvider_->enableNativeCSSParsing(); enableNativeCSSParsing_ = flagValue; @@ -758,7 +776,7 @@ bool ReactNativeFeatureFlagsAccessor::enableNetworkEventReporting() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(40, "enableNetworkEventReporting"); + markFlagAsAccessed(41, "enableNetworkEventReporting"); flagValue = currentProvider_->enableNetworkEventReporting(); enableNetworkEventReporting_ = flagValue; @@ -776,7 +794,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(41, "enablePreparedTextLayout"); + markFlagAsAccessed(42, "enablePreparedTextLayout"); flagValue = currentProvider_->enablePreparedTextLayout(); enablePreparedTextLayout_ = flagValue; @@ -794,7 +812,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(42, "enablePropsUpdateReconciliationAndroid"); + markFlagAsAccessed(43, "enablePropsUpdateReconciliationAndroid"); flagValue = currentProvider_->enablePropsUpdateReconciliationAndroid(); enablePropsUpdateReconciliationAndroid_ = flagValue; @@ -812,7 +830,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(43, "enableSwiftUIBasedFilters"); + markFlagAsAccessed(44, "enableSwiftUIBasedFilters"); flagValue = currentProvider_->enableSwiftUIBasedFilters(); enableSwiftUIBasedFilters_ = flagValue; @@ -830,7 +848,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(44, "enableViewCulling"); + markFlagAsAccessed(45, "enableViewCulling"); flagValue = currentProvider_->enableViewCulling(); enableViewCulling_ = flagValue; @@ -848,7 +866,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(45, "enableViewRecycling"); + markFlagAsAccessed(46, "enableViewRecycling"); flagValue = currentProvider_->enableViewRecycling(); enableViewRecycling_ = flagValue; @@ -866,7 +884,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(46, "enableViewRecyclingForImage"); + markFlagAsAccessed(47, "enableViewRecyclingForImage"); flagValue = currentProvider_->enableViewRecyclingForImage(); enableViewRecyclingForImage_ = flagValue; @@ -884,7 +902,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(47, "enableViewRecyclingForScrollView"); + markFlagAsAccessed(48, "enableViewRecyclingForScrollView"); flagValue = currentProvider_->enableViewRecyclingForScrollView(); enableViewRecyclingForScrollView_ = flagValue; @@ -902,7 +920,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(48, "enableViewRecyclingForText"); + markFlagAsAccessed(49, "enableViewRecyclingForText"); flagValue = currentProvider_->enableViewRecyclingForText(); enableViewRecyclingForText_ = flagValue; @@ -920,7 +938,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(49, "enableViewRecyclingForView"); + markFlagAsAccessed(50, "enableViewRecyclingForView"); flagValue = currentProvider_->enableViewRecyclingForView(); enableViewRecyclingForView_ = flagValue; @@ -938,7 +956,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(50, "enableVirtualViewContainerStateExperimental"); + markFlagAsAccessed(51, "enableVirtualViewContainerStateExperimental"); flagValue = currentProvider_->enableVirtualViewContainerStateExperimental(); enableVirtualViewContainerStateExperimental_ = flagValue; @@ -956,7 +974,7 @@ bool ReactNativeFeatureFlagsAccessor::enableVirtualViewDebugFeatures() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(51, "enableVirtualViewDebugFeatures"); + markFlagAsAccessed(52, "enableVirtualViewDebugFeatures"); flagValue = currentProvider_->enableVirtualViewDebugFeatures(); enableVirtualViewDebugFeatures_ = flagValue; @@ -974,7 +992,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(52, "fixMappingOfEventPrioritiesBetweenFabricAndReact"); + markFlagAsAccessed(53, "fixMappingOfEventPrioritiesBetweenFabricAndReact"); flagValue = currentProvider_->fixMappingOfEventPrioritiesBetweenFabricAndReact(); fixMappingOfEventPrioritiesBetweenFabricAndReact_ = flagValue; @@ -992,7 +1010,7 @@ bool ReactNativeFeatureFlagsAccessor::fixTextClippingAndroid15useBoundsForWidth( // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(53, "fixTextClippingAndroid15useBoundsForWidth"); + markFlagAsAccessed(54, "fixTextClippingAndroid15useBoundsForWidth"); flagValue = currentProvider_->fixTextClippingAndroid15useBoundsForWidth(); fixTextClippingAndroid15useBoundsForWidth_ = flagValue; @@ -1010,7 +1028,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(54, "fuseboxAssertSingleHostState"); + markFlagAsAccessed(55, "fuseboxAssertSingleHostState"); flagValue = currentProvider_->fuseboxAssertSingleHostState(); fuseboxAssertSingleHostState_ = flagValue; @@ -1028,7 +1046,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(55, "fuseboxEnabledRelease"); + markFlagAsAccessed(56, "fuseboxEnabledRelease"); flagValue = currentProvider_->fuseboxEnabledRelease(); fuseboxEnabledRelease_ = flagValue; @@ -1046,7 +1064,7 @@ bool ReactNativeFeatureFlagsAccessor::fuseboxNetworkInspectionEnabled() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(56, "fuseboxNetworkInspectionEnabled"); + markFlagAsAccessed(57, "fuseboxNetworkInspectionEnabled"); flagValue = currentProvider_->fuseboxNetworkInspectionEnabled(); fuseboxNetworkInspectionEnabled_ = flagValue; @@ -1064,7 +1082,7 @@ bool ReactNativeFeatureFlagsAccessor::hideOffscreenVirtualViewsOnIOS() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(57, "hideOffscreenVirtualViewsOnIOS"); + markFlagAsAccessed(58, "hideOffscreenVirtualViewsOnIOS"); flagValue = currentProvider_->hideOffscreenVirtualViewsOnIOS(); hideOffscreenVirtualViewsOnIOS_ = flagValue; @@ -1082,7 +1100,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(58, "overrideBySynchronousMountPropsAtMountingAndroid"); + markFlagAsAccessed(59, "overrideBySynchronousMountPropsAtMountingAndroid"); flagValue = currentProvider_->overrideBySynchronousMountPropsAtMountingAndroid(); overrideBySynchronousMountPropsAtMountingAndroid_ = flagValue; @@ -1100,7 +1118,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(59, "perfIssuesEnabled"); + markFlagAsAccessed(60, "perfIssuesEnabled"); flagValue = currentProvider_->perfIssuesEnabled(); perfIssuesEnabled_ = flagValue; @@ -1118,7 +1136,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(60, "perfMonitorV2Enabled"); + markFlagAsAccessed(61, "perfMonitorV2Enabled"); flagValue = currentProvider_->perfMonitorV2Enabled(); perfMonitorV2Enabled_ = flagValue; @@ -1136,7 +1154,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(61, "preparedTextCacheSize"); + markFlagAsAccessed(62, "preparedTextCacheSize"); flagValue = currentProvider_->preparedTextCacheSize(); preparedTextCacheSize_ = flagValue; @@ -1154,7 +1172,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(62, "preventShadowTreeCommitExhaustion"); + markFlagAsAccessed(63, "preventShadowTreeCommitExhaustion"); flagValue = currentProvider_->preventShadowTreeCommitExhaustion(); preventShadowTreeCommitExhaustion_ = flagValue; @@ -1172,7 +1190,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(63, "shouldPressibilityUseW3CPointerEventsForHover"); + markFlagAsAccessed(64, "shouldPressibilityUseW3CPointerEventsForHover"); flagValue = currentProvider_->shouldPressibilityUseW3CPointerEventsForHover(); shouldPressibilityUseW3CPointerEventsForHover_ = flagValue; @@ -1190,7 +1208,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(64, "shouldTriggerResponderTransferOnScrollAndroid"); + markFlagAsAccessed(65, "shouldTriggerResponderTransferOnScrollAndroid"); flagValue = currentProvider_->shouldTriggerResponderTransferOnScrollAndroid(); shouldTriggerResponderTransferOnScrollAndroid_ = flagValue; @@ -1208,7 +1226,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(65, "skipActivityIdentityAssertionOnHostPause"); + markFlagAsAccessed(66, "skipActivityIdentityAssertionOnHostPause"); flagValue = currentProvider_->skipActivityIdentityAssertionOnHostPause(); skipActivityIdentityAssertionOnHostPause_ = flagValue; @@ -1226,7 +1244,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(66, "traceTurboModulePromiseRejectionsOnAndroid"); + markFlagAsAccessed(67, "traceTurboModulePromiseRejectionsOnAndroid"); flagValue = currentProvider_->traceTurboModulePromiseRejectionsOnAndroid(); traceTurboModulePromiseRejectionsOnAndroid_ = flagValue; @@ -1244,7 +1262,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(67, "updateRuntimeShadowNodeReferencesOnCommit"); + markFlagAsAccessed(68, "updateRuntimeShadowNodeReferencesOnCommit"); flagValue = currentProvider_->updateRuntimeShadowNodeReferencesOnCommit(); updateRuntimeShadowNodeReferencesOnCommit_ = flagValue; @@ -1262,7 +1280,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(68, "useAlwaysAvailableJSErrorHandling"); + markFlagAsAccessed(69, "useAlwaysAvailableJSErrorHandling"); flagValue = currentProvider_->useAlwaysAvailableJSErrorHandling(); useAlwaysAvailableJSErrorHandling_ = flagValue; @@ -1280,7 +1298,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(69, "useFabricInterop"); + markFlagAsAccessed(70, "useFabricInterop"); flagValue = currentProvider_->useFabricInterop(); useFabricInterop_ = flagValue; @@ -1298,7 +1316,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(70, "useNativeViewConfigsInBridgelessMode"); + markFlagAsAccessed(71, "useNativeViewConfigsInBridgelessMode"); flagValue = currentProvider_->useNativeViewConfigsInBridgelessMode(); useNativeViewConfigsInBridgelessMode_ = flagValue; @@ -1316,7 +1334,7 @@ bool ReactNativeFeatureFlagsAccessor::useShadowNodeStateOnClone() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(71, "useShadowNodeStateOnClone"); + markFlagAsAccessed(72, "useShadowNodeStateOnClone"); flagValue = currentProvider_->useShadowNodeStateOnClone(); useShadowNodeStateOnClone_ = flagValue; @@ -1334,7 +1352,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(72, "useSharedAnimatedBackend"); + markFlagAsAccessed(73, "useSharedAnimatedBackend"); flagValue = currentProvider_->useSharedAnimatedBackend(); useSharedAnimatedBackend_ = flagValue; @@ -1352,7 +1370,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(73, "useTraitHiddenOnAndroid"); + markFlagAsAccessed(74, "useTraitHiddenOnAndroid"); flagValue = currentProvider_->useTraitHiddenOnAndroid(); useTraitHiddenOnAndroid_ = flagValue; @@ -1370,7 +1388,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(74, "useTurboModuleInterop"); + markFlagAsAccessed(75, "useTurboModuleInterop"); flagValue = currentProvider_->useTurboModuleInterop(); useTurboModuleInterop_ = flagValue; @@ -1388,7 +1406,7 @@ bool ReactNativeFeatureFlagsAccessor::useTurboModules() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(75, "useTurboModules"); + markFlagAsAccessed(76, "useTurboModules"); flagValue = currentProvider_->useTurboModules(); useTurboModules_ = flagValue; @@ -1406,7 +1424,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(76, "viewCullingOutsetRatio"); + markFlagAsAccessed(77, "viewCullingOutsetRatio"); flagValue = currentProvider_->viewCullingOutsetRatio(); viewCullingOutsetRatio_ = flagValue; @@ -1424,7 +1442,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(77, "virtualViewPrerenderRatio"); + markFlagAsAccessed(78, "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 277146234d1ff7..eb3b50cac48f3b 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<<0a3237b70685886405ea47d3a8c83280>> + * @generated SignedSource<<1379ac6607444dbde65b113221edaf27>> */ /** @@ -54,6 +54,7 @@ class ReactNativeFeatureFlagsAccessor { bool enableEagerMainQueueModulesOnIOS(); bool enableEagerRootViewAttachment(); bool enableExclusivePropsUpdateAndroid(); + bool enableFabricCommitBranching(); bool enableFabricLogs(); bool enableFabricRenderer(); bool enableFontScaleChangesUpdatingLayout(); @@ -121,7 +122,7 @@ class ReactNativeFeatureFlagsAccessor { std::unique_ptr currentProvider_; bool wasOverridden_; - std::array, 78> accessedFeatureFlags_; + std::array, 79> accessedFeatureFlags_; std::atomic> commonTestFlag_; std::atomic> cdpInteractionMetricsEnabled_; @@ -145,6 +146,7 @@ class ReactNativeFeatureFlagsAccessor { std::atomic> enableEagerMainQueueModulesOnIOS_; std::atomic> enableEagerRootViewAttachment_; std::atomic> enableExclusivePropsUpdateAndroid_; + std::atomic> enableFabricCommitBranching_; std::atomic> enableFabricLogs_; std::atomic> enableFabricRenderer_; std::atomic> enableFontScaleChangesUpdatingLayout_; diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h index a657551f6227f6..4ea65ba857620b 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<<4d8ad520eb6442e7d68b739889cc57ce>> + * @generated SignedSource<<8951c3a0a96fb3b725bd1ff2de7789e9>> */ /** @@ -115,6 +115,10 @@ class ReactNativeFeatureFlagsDefaults : public ReactNativeFeatureFlagsProvider { return false; } + bool enableFabricCommitBranching() override { + return false; + } + bool enableFabricLogs() override { return false; } diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDynamicProvider.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDynamicProvider.h index b811f17a2b2409..7431df64f42018 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<<5d268976bbf89c50ed0fac1913925803>> + * @generated SignedSource<<7f558deb28dc82b25567426240b2e6d5>> */ /** @@ -243,6 +243,15 @@ class ReactNativeFeatureFlagsDynamicProvider : public ReactNativeFeatureFlagsDef return ReactNativeFeatureFlagsDefaults::enableExclusivePropsUpdateAndroid(); } + bool enableFabricCommitBranching() override { + auto value = values_["enableFabricCommitBranching"]; + if (!value.isNull()) { + return value.getBool(); + } + + return ReactNativeFeatureFlagsDefaults::enableFabricCommitBranching(); + } + bool enableFabricLogs() override { auto value = values_["enableFabricLogs"]; if (!value.isNull()) { diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h index 41c360d3e10ca1..774920072a4217 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<<91470639697953f6ab45237b1bb72090>> */ /** @@ -47,6 +47,7 @@ class ReactNativeFeatureFlagsProvider { virtual bool enableEagerMainQueueModulesOnIOS() = 0; virtual bool enableEagerRootViewAttachment() = 0; virtual bool enableExclusivePropsUpdateAndroid() = 0; + virtual bool enableFabricCommitBranching() = 0; virtual bool enableFabricLogs() = 0; virtual bool enableFabricRenderer() = 0; virtual bool enableFontScaleChangesUpdatingLayout() = 0; diff --git a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp index 89413bab54e27e..9ee35de9c249cf 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<<3d7f32a7be7944a149b788ffe38f89d1>> + * @generated SignedSource<> */ /** @@ -154,6 +154,11 @@ bool NativeReactNativeFeatureFlags::enableExclusivePropsUpdateAndroid( return ReactNativeFeatureFlags::enableExclusivePropsUpdateAndroid(); } +bool NativeReactNativeFeatureFlags::enableFabricCommitBranching( + jsi::Runtime& /*runtime*/) { + return ReactNativeFeatureFlags::enableFabricCommitBranching(); +} + bool NativeReactNativeFeatureFlags::enableFabricLogs( jsi::Runtime& /*runtime*/) { return ReactNativeFeatureFlags::enableFabricLogs(); diff --git a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h index e75ea83757b696..5c4232ccaef764 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<<0fdc53b52abd242240617cabe47477b3>> + * @generated SignedSource<<1fc9204eab22c1eba27a3dd90f14c2a3>> */ /** @@ -80,6 +80,8 @@ class NativeReactNativeFeatureFlags bool enableExclusivePropsUpdateAndroid(jsi::Runtime& runtime); + bool enableFabricCommitBranching(jsi::Runtime& runtime); + bool enableFabricLogs(jsi::Runtime& runtime); bool enableFabricRenderer(jsi::Runtime& runtime); diff --git a/packages/react-native/ReactCommon/react/renderer/mounting/ShadowTree.cpp b/packages/react-native/ReactCommon/react/renderer/mounting/ShadowTree.cpp index 58c5bbaa4e0844..a4c4ca0f234a56 100644 --- a/packages/react-native/ReactCommon/react/renderer/mounting/ShadowTree.cpp +++ b/packages/react-native/ReactCommon/react/renderer/mounting/ShadowTree.cpp @@ -286,18 +286,32 @@ CommitStatus ShadowTree::tryCommit( const CommitOptions& commitOptions) const { TraceSection s("ShadowTree::commit"); + auto isReactBranch = ReactNativeFeatureFlags::enableFabricCommitBranching() && + commitOptions.source == CommitSource::React; + + // Commits on the JS branch are never synchronous. + react_native_assert(!isReactBranch || !commitOptions.mountSynchronously); + auto telemetry = TransactionTelemetry{}; telemetry.willCommit(); CommitMode commitMode; auto oldRevision = ShadowTreeRevision{}; + auto oldRevisionForStateProgression = ShadowTreeRevision{}; auto newRevision = ShadowTreeRevision{}; { // Reading `currentRevision_` in shared manner. SharedLock lock = sharedCommitLock(); commitMode = commitMode_; - oldRevision = currentRevision_; + + if (isReactBranch && currentReactRevision_.has_value()) { + oldRevision = currentReactRevision_.value(); + } else { + oldRevision = currentRevision_; + } + + oldRevisionForStateProgression = currentRevision_; } const auto& oldRootShadowNode = oldRevision.rootShadowNode; @@ -308,8 +322,8 @@ CommitStatus ShadowTree::tryCommit( } if (commitOptions.enableStateReconciliation) { - auto updatedNewRootShadowNode = - progressState(*newRootShadowNode, *oldRootShadowNode); + auto updatedNewRootShadowNode = progressState( + *newRootShadowNode, *oldRevisionForStateProgression.rootShadowNode); if (updatedNewRootShadowNode) { newRootShadowNode = std::static_pointer_cast(updatedNewRootShadowNode); @@ -336,9 +350,10 @@ CommitStatus ShadowTree::tryCommit( { // Updating `currentRevision_` in unique manner if it hasn't changed. - UniqueLock lock = uniqueCommitLock(); + UniqueLock lock = uniqueCommitLock( + /*defer*/ isReactBranch); - if (currentRevision_.number != oldRevision.number) { + if (!isReactBranch && currentRevision_.number != oldRevision.number) { return CommitStatus::Failed; } @@ -364,12 +379,19 @@ CommitStatus ShadowTree::tryCommit( .number = newRevisionNumber, .telemetry = telemetry}; - currentRevision_ = newRevision; + if (isReactBranch) { + auto promotionLock = std::unique_lock{promotedRevisionMutex_}; + currentReactRevision_ = newRevision; + } else { + currentRevision_ = newRevision; + } } emitLayoutEvents(affectedLayoutableNodes); - if (commitMode == CommitMode::Normal) { + if (isReactBranch) { + scheduleReactRevisionPromotion(); + } else if (commitMode == CommitMode::Normal) { mount(std::move(newRevision), commitOptions.mountSynchronously); } @@ -381,6 +403,10 @@ ShadowTreeRevision ShadowTree::getCurrentRevision() const { return currentRevision_; } +std::optional ShadowTree::getCurrentReactRevision() const { + return currentReactRevision_; +} + void ShadowTree::mount(ShadowTreeRevision revision, bool mountSynchronously) const { mountingCoordinator_->push(std::move(revision)); @@ -388,6 +414,47 @@ void ShadowTree::mount(ShadowTreeRevision revision, bool mountSynchronously) mountingCoordinator_, mountSynchronously); } +void ShadowTree::mergeReactRevision() const { + auto lock = std::unique_lock{promotedRevisionMutex_}; + + if (!reactRevisionToBePromoted_.has_value()) { + return; + } + + { + UniqueLock commitLock = uniqueCommitLock( + /*defer*/ false); + + if (currentReactRevision_.has_value() && + reactRevisionToBePromoted_.value().number == + currentReactRevision_.value().number) { + currentReactRevision_.reset(); + } + } + + this->commit( + [revision = + std::exchange(reactRevisionToBePromoted_, std::nullopt).value()]( + const RootShadowNode& /*oldRootShadowNode*/) { + return std::make_shared( + *revision.rootShadowNode, ShadowNodeFragment{}); + }, + { + .enableStateReconciliation = true, + .mountSynchronously = true, + .source = CommitSource::ReactRevisionMerge, + }); +} + +void ShadowTree::promoteReactRevision() const { + auto lock = std::unique_lock{promotedRevisionMutex_}; + reactRevisionToBePromoted_ = currentReactRevision_.value(); +} + +void ShadowTree::scheduleReactRevisionPromotion() const { + delegate_.shadowTreeDidFinishReactCommit(*this); +} + void ShadowTree::commitEmptyTree() const { commit( [](const RootShadowNode& oldRootShadowNode) @@ -426,11 +493,13 @@ void ShadowTree::notifyDelegatesOfUpdates() const { delegate_.shadowTreeDidFinishTransaction(mountingCoordinator_, true); } -inline ShadowTree::UniqueLock ShadowTree::uniqueCommitLock() const { +inline ShadowTree::UniqueLock ShadowTree::uniqueCommitLock(bool defer) const { if (ReactNativeFeatureFlags::preventShadowTreeCommitExhaustion()) { - return std::unique_lock{commitMutexRecursive_}; + return defer ? std::unique_lock{commitMutexRecursive_, std::defer_lock} + : std::unique_lock{commitMutexRecursive_}; } else { - return std::unique_lock{commitMutex_}; + return defer ? std::unique_lock{commitMutex_, std::defer_lock} + : std::unique_lock{commitMutex_}; } } diff --git a/packages/react-native/ReactCommon/react/renderer/mounting/ShadowTree.h b/packages/react-native/ReactCommon/react/renderer/mounting/ShadowTree.h index c1f51fc1a91e82..c8672d533bf114 100644 --- a/packages/react-native/ReactCommon/react/renderer/mounting/ShadowTree.h +++ b/packages/react-native/ReactCommon/react/renderer/mounting/ShadowTree.h @@ -51,6 +51,7 @@ enum class ShadowTreeCommitSource { Unknown, React, AnimationEndSync, + ReactRevisionMerge, }; struct ShadowTreeCommitOptions { @@ -124,6 +125,12 @@ class ShadowTree final { */ ShadowTreeRevision getCurrentRevision() const; + /* + * Returns a `ShadowTreeRevision` representing the momentary state of + * the `ShadowTree` in the JS thread. + */ + std::optional getCurrentReactRevision() const; + /* * Commit an empty tree (a new `RootShadowNode` with no children). */ @@ -137,6 +144,18 @@ class ShadowTree final { std::shared_ptr getMountingCoordinator() const; + /** + * Promotes the current React revision to be merged into the main branch of the + * ShadowTree. + */ + void promoteReactRevision() const; + + /** + * Commits the currently promoted React revision to the "main" branch of the + * ShadowTree. No-op if the promoted React revision doesn't exist. + */ + void mergeReactRevision() const; + private: constexpr static ShadowTreeRevision::Number INITIAL_REVISION{0}; @@ -144,18 +163,23 @@ class ShadowTree final { void emitLayoutEvents(std::vector &affectedLayoutableNodes) const; + void scheduleReactRevisionPromotion() const; + const SurfaceId surfaceId_; const ShadowTreeDelegate &delegate_; mutable std::shared_mutex commitMutex_; + mutable std::shared_mutex promotedRevisionMutex_; mutable std::recursive_mutex commitMutexRecursive_; mutable CommitMode commitMode_{CommitMode::Normal}; // Protected by `commitMutex_`. mutable ShadowTreeRevision currentRevision_; // Protected by `commitMutex_`. + mutable std::optional currentReactRevision_; // Only updated from JS thread. + mutable std::optional reactRevisionToBePromoted_; // Protected by `promotedRevisionMutex_`. std::shared_ptr mountingCoordinator_; using UniqueLock = std::variant, std::unique_lock>; using SharedLock = std::variant, std::unique_lock>; - inline UniqueLock uniqueCommitLock() const; + inline UniqueLock uniqueCommitLock(bool defer = false) const; inline SharedLock sharedCommitLock() const; }; diff --git a/packages/react-native/ReactCommon/react/renderer/mounting/ShadowTreeDelegate.h b/packages/react-native/ReactCommon/react/renderer/mounting/ShadowTreeDelegate.h index 650d898a6f3453..40e610911a28e8 100644 --- a/packages/react-native/ReactCommon/react/renderer/mounting/ShadowTreeDelegate.h +++ b/packages/react-native/ReactCommon/react/renderer/mounting/ShadowTreeDelegate.h @@ -38,6 +38,11 @@ class ShadowTreeDelegate { std::shared_ptr mountingCoordinator, bool mountSynchronously) const = 0; + /* + * Called right after Shadow Tree commits a new JS revision of the tree. + */ + virtual void shadowTreeDidFinishReactCommit(const ShadowTree &shadowTree) const = 0; + virtual ~ShadowTreeDelegate() noexcept = default; }; diff --git a/packages/react-native/ReactCommon/react/renderer/mounting/tests/StateReconciliationTest.cpp b/packages/react-native/ReactCommon/react/renderer/mounting/tests/StateReconciliationTest.cpp index 7290d76cc637cb..a9c553e4f84fd9 100644 --- a/packages/react-native/ReactCommon/react/renderer/mounting/tests/StateReconciliationTest.cpp +++ b/packages/react-native/ReactCommon/react/renderer/mounting/tests/StateReconciliationTest.cpp @@ -37,6 +37,9 @@ class DummyShadowTreeDelegate : public ShadowTreeDelegate { void shadowTreeDidFinishTransaction( std::shared_ptr mountingCoordinator, bool /*mountSynchronously*/) const override {} + + void shadowTreeDidFinishReactCommit( + const ShadowTree& /*shadowTree*/) const override {} }; namespace { diff --git a/packages/react-native/ReactCommon/react/renderer/scheduler/Scheduler.cpp b/packages/react-native/ReactCommon/react/renderer/scheduler/Scheduler.cpp index 8c42afc52964cd..39513698234e0f 100644 --- a/packages/react-native/ReactCommon/react/renderer/scheduler/Scheduler.cpp +++ b/packages/react-native/ReactCommon/react/renderer/scheduler/Scheduler.cpp @@ -355,6 +355,18 @@ void Scheduler::uiManagerShouldRemoveEventListener( removeEventListener(listener); } +void Scheduler::uiManagerDidFinishJSCommit(const ShadowTree& shadowTree) { + auto surfaceId = shadowTree.getSurfaceId(); + runtimeScheduler_->scheduleRenderingUpdate( + surfaceId, [surfaceId, uiManager = uiManager_]() { + uiManager->getShadowTreeRegistry().visit( + surfaceId, [](const ShadowTree& tree) { + tree.promoteReactRevision(); + tree.mergeReactRevision(); + }); + }); +} + void Scheduler::uiManagerDidStartSurface(const ShadowTree& shadowTree) { std::shared_lock lock(onSurfaceStartCallbackMutex_); if (onSurfaceStartCallback_) { diff --git a/packages/react-native/ReactCommon/react/renderer/scheduler/Scheduler.h b/packages/react-native/ReactCommon/react/renderer/scheduler/Scheduler.h index c324655da7255a..611faa69eca34e 100644 --- a/packages/react-native/ReactCommon/react/renderer/scheduler/Scheduler.h +++ b/packages/react-native/ReactCommon/react/renderer/scheduler/Scheduler.h @@ -97,6 +97,7 @@ class Scheduler final : public UIManagerDelegate { void uiManagerDidUpdateShadowTree(const std::unordered_map &tagToProps) override; void uiManagerShouldAddEventListener(std::shared_ptr listener) final; void uiManagerShouldRemoveEventListener(const std::shared_ptr &listener) final; + void uiManagerDidFinishJSCommit(const ShadowTree &shadowTree) override; void uiManagerDidStartSurface(const ShadowTree &shadowTree) override; #pragma mark - ContextContainer diff --git a/packages/react-native/ReactCommon/react/renderer/uimanager/UIManager.cpp b/packages/react-native/ReactCommon/react/renderer/uimanager/UIManager.cpp index 931bfce1c1e10a..f7b2f46fd8646d 100644 --- a/packages/react-native/ReactCommon/react/renderer/uimanager/UIManager.cpp +++ b/packages/react-native/ReactCommon/react/renderer/uimanager/UIManager.cpp @@ -188,8 +188,10 @@ void UIManager::completeSurface( ShadowTree::CommitOptions commitOptions) { TraceSection s("UIManager::completeSurface", "surfaceId", surfaceId); + ShadowTree::CommitStatus result; + shadowTreeRegistry_.visit(surfaceId, [&](const ShadowTree& shadowTree) { - auto result = shadowTree.commit( + result = shadowTree.commit( [&](const RootShadowNode& oldRootShadowNode) { return std::make_shared( oldRootShadowNode, @@ -199,20 +201,19 @@ void UIManager::completeSurface( }); }, commitOptions); + }); - if (result == ShadowTree::CommitStatus::Succeeded) { - // It's safe to update the visible revision of the shadow tree immediately - // after we commit a specific one. - lazyShadowTreeRevisionConsistencyManager_->updateCurrentRevision( - surfaceId, shadowTree.getCurrentRevision().rootShadowNode); + if (result == ShadowTree::CommitStatus::Succeeded) { + // It's safe to update the visible revision of the shadow tree immediately + // after we commit a specific one. + lazyShadowTreeRevisionConsistencyManager_->updateCurrentRevision(surfaceId); - if (ReactNativeFeatureFlags::useSharedAnimatedBackend()) { - if (auto animationBackend = animationBackend_.lock()) { - animationBackend->clearRegistry(surfaceId); - } + if (ReactNativeFeatureFlags::useSharedAnimatedBackend()) { + if (auto animationBackend = animationBackend_.lock()) { + animationBackend->clearRegistry(surfaceId); } } - }); + } } void UIManager::setIsJSResponder( @@ -645,6 +646,13 @@ void UIManager::shadowTreeDidFinishTransaction( } } +void UIManager::shadowTreeDidFinishReactCommit( + const ShadowTree& shadowTree) const { + if (delegate_ != nullptr) { + delegate_->uiManagerDidFinishJSCommit(shadowTree); + } +} + void UIManager::reportMount(SurfaceId surfaceId) const { TraceSection s("UIManager::reportMount"); diff --git a/packages/react-native/ReactCommon/react/renderer/uimanager/UIManager.h b/packages/react-native/ReactCommon/react/renderer/uimanager/UIManager.h index 794a5559a553fe..e61ed6c6c2b718 100644 --- a/packages/react-native/ReactCommon/react/renderer/uimanager/UIManager.h +++ b/packages/react-native/ReactCommon/react/renderer/uimanager/UIManager.h @@ -135,6 +135,8 @@ class UIManager final : public ShadowTreeDelegate { const RootShadowNode::Unshared &newRootShadowNode, const ShadowTree::CommitOptions &commitOptions) const override; + void shadowTreeDidFinishReactCommit(const ShadowTree &shadowTree) const override; + std::shared_ptr createNode( Tag tag, const std::string &componentName, diff --git a/packages/react-native/ReactCommon/react/renderer/uimanager/UIManagerDelegate.h b/packages/react-native/ReactCommon/react/renderer/uimanager/UIManagerDelegate.h index 32df5c92f10992..13d71d9d2859c5 100644 --- a/packages/react-native/ReactCommon/react/renderer/uimanager/UIManagerDelegate.h +++ b/packages/react-native/ReactCommon/react/renderer/uimanager/UIManagerDelegate.h @@ -84,6 +84,11 @@ class UIManagerDelegate { */ virtual void uiManagerDidStartSurface(const ShadowTree &shadowTree) = 0; + /* + * Called after a new JS revision of the shadow tree is committed. + */ + virtual void uiManagerDidFinishJSCommit(const ShadowTree &shadowTree) = 0; + using OnSurfaceStartCallback = std::function; virtual void uiManagerShouldSetOnSurfaceStartCallback(OnSurfaceStartCallback &&callback) = 0; diff --git a/packages/react-native/ReactCommon/react/renderer/uimanager/consistency/LazyShadowTreeRevisionConsistencyManager.cpp b/packages/react-native/ReactCommon/react/renderer/uimanager/consistency/LazyShadowTreeRevisionConsistencyManager.cpp index 85cd9cd5158a23..cf11c7f9d28e64 100644 --- a/packages/react-native/ReactCommon/react/renderer/uimanager/consistency/LazyShadowTreeRevisionConsistencyManager.cpp +++ b/packages/react-native/ReactCommon/react/renderer/uimanager/consistency/LazyShadowTreeRevisionConsistencyManager.cpp @@ -15,22 +15,34 @@ LazyShadowTreeRevisionConsistencyManager:: ShadowTreeRegistry& shadowTreeRegistry) : shadowTreeRegistry_(shadowTreeRegistry) {} -void LazyShadowTreeRevisionConsistencyManager::updateCurrentRevision( - SurfaceId surfaceId, - RootShadowNode::Shared rootShadowNode) { +std::shared_ptr +LazyShadowTreeRevisionConsistencyManager::updateCurrentRevision( + SurfaceId surfaceId) { + // This method is only going to be called from JS, so we don't need to protect + // the access to the shadow tree registry as well. + // If this was multi-threaded, we would need to protect it to avoid capturing + // root shadow nodes concurrently. + RootShadowNode::Shared rootShadowNode; + shadowTreeRegistry_.visit(surfaceId, [&](const ShadowTree& shadowTree) { + auto reactRevision = shadowTree.getCurrentReactRevision(); + rootShadowNode = + reactRevision.value_or(shadowTree.getCurrentRevision()).rootShadowNode; + }); + std::unique_lock lock(capturedRootShadowNodesForConsistencyMutex_); // We don't need to store the revision if we haven't locked. // We can resolve lazily when requested. if (lockCount > 0) { - capturedRootShadowNodesForConsistency_[surfaceId] = - std::move(rootShadowNode); + capturedRootShadowNodesForConsistency_[surfaceId] = rootShadowNode; } + + return rootShadowNode; } #pragma mark - ShadowTreeRevisionProvider -RootShadowNode::Shared +std::shared_ptr LazyShadowTreeRevisionConsistencyManager::getCurrentRevision( SurfaceId surfaceId) { { @@ -43,23 +55,7 @@ LazyShadowTreeRevisionConsistencyManager::getCurrentRevision( } } - // This method is only going to be called from JS, so we don't need to protect - // the access to the shadow tree registry as well. - // If this was multi-threaded, we would need to protect it to avoid capturing - // root shadow nodes concurrently. - RootShadowNode::Shared rootShadowNode; - shadowTreeRegistry_.visit(surfaceId, [&](const ShadowTree& shadowTree) { - rootShadowNode = shadowTree.getCurrentRevision().rootShadowNode; - }); - - { - std::unique_lock lock(capturedRootShadowNodesForConsistencyMutex_); - if (lockCount > 0) { - capturedRootShadowNodesForConsistency_[surfaceId] = rootShadowNode; - } - } - - return rootShadowNode; + return updateCurrentRevision(surfaceId); } #pragma mark - ConsistentShadowTreeRevisionProvider diff --git a/packages/react-native/ReactCommon/react/renderer/uimanager/consistency/LazyShadowTreeRevisionConsistencyManager.h b/packages/react-native/ReactCommon/react/renderer/uimanager/consistency/LazyShadowTreeRevisionConsistencyManager.h index 96c7537ed28d2c..c7ab5af7fac2ad 100644 --- a/packages/react-native/ReactCommon/react/renderer/uimanager/consistency/LazyShadowTreeRevisionConsistencyManager.h +++ b/packages/react-native/ReactCommon/react/renderer/uimanager/consistency/LazyShadowTreeRevisionConsistencyManager.h @@ -13,7 +13,6 @@ #include #include #include -#include namespace facebook::react { @@ -28,11 +27,11 @@ class LazyShadowTreeRevisionConsistencyManager : public ShadowTreeRevisionConsis public: explicit LazyShadowTreeRevisionConsistencyManager(ShadowTreeRegistry &shadowTreeRegistry); - void updateCurrentRevision(SurfaceId surfaceId, RootShadowNode::Shared rootShadowNode); + std::shared_ptr updateCurrentRevision(SurfaceId surfaceId); #pragma mark - ShadowTreeRevisionProvider - RootShadowNode::Shared getCurrentRevision(SurfaceId surfaceId) override; + std::shared_ptr getCurrentRevision(SurfaceId surfaceId) override; #pragma mark - ShadowTreeRevisionConsistencyManager diff --git a/packages/react-native/ReactCommon/react/renderer/uimanager/consistency/tests/LazyShadowTreeRevisionConsistencyManagerTest.cpp b/packages/react-native/ReactCommon/react/renderer/uimanager/consistency/tests/LazyShadowTreeRevisionConsistencyManagerTest.cpp index 01d43d096c55c8..d17ce99c0c17c1 100644 --- a/packages/react-native/ReactCommon/react/renderer/uimanager/consistency/tests/LazyShadowTreeRevisionConsistencyManagerTest.cpp +++ b/packages/react-native/ReactCommon/react/renderer/uimanager/consistency/tests/LazyShadowTreeRevisionConsistencyManagerTest.cpp @@ -27,6 +27,9 @@ class FakeShadowTreeDelegate : public ShadowTreeDelegate { void shadowTreeDidFinishTransaction( std::shared_ptr mountingCoordinator, bool /*mountSynchronously*/) const override {} + + void shadowTreeDidFinishReactCommit( + const ShadowTree& /*shadowTree*/) const override {} }; class LazyShadowTreeRevisionConsistencyManagerTest : public ::testing::Test { @@ -141,7 +144,7 @@ TEST_F( EXPECT_EQ(consistencyManager_.getCurrentRevision(0), nullptr); - consistencyManager_.updateCurrentRevision(0, newRootShadowNode); + consistencyManager_.updateCurrentRevision(0); EXPECT_NE(consistencyManager_.getCurrentRevision(0), nullptr); EXPECT_EQ( @@ -176,7 +179,7 @@ TEST_F( EXPECT_EQ(consistencyManager_.getCurrentRevision(0), nullptr); - consistencyManager_.updateCurrentRevision(0, newRootShadowNode); + consistencyManager_.updateCurrentRevision(0); EXPECT_EQ( consistencyManager_.getCurrentRevision(0).get(), newRootShadowNode.get()); @@ -192,7 +195,7 @@ TEST_F( {}); }); - consistencyManager_.updateCurrentRevision(0, newRootShadowNode2); + consistencyManager_.updateCurrentRevision(0); EXPECT_EQ( consistencyManager_.getCurrentRevision(0).get(), @@ -265,7 +268,7 @@ TEST_F( EXPECT_EQ( consistencyManager_.getCurrentRevision(0).get(), newRootShadowNode.get()); - consistencyManager_.updateCurrentRevision(0, newRootShadowNode2); + consistencyManager_.updateCurrentRevision(0); // Updated EXPECT_EQ( @@ -344,7 +347,9 @@ TEST_F(LazyShadowTreeRevisionConsistencyManagerTest, testUpdateToUnmounted) { EXPECT_EQ( consistencyManager_.getCurrentRevision(0).get(), newRootShadowNode.get()); - consistencyManager_.updateCurrentRevision(0, nullptr); + shadowTreeRegistry_.remove(0); + + consistencyManager_.updateCurrentRevision(0); // Updated EXPECT_EQ(consistencyManager_.getCurrentRevision(0).get(), nullptr); diff --git a/packages/react-native/ReactCxxPlatform/react/runtime/ReactHost.cpp b/packages/react-native/ReactCxxPlatform/react/runtime/ReactHost.cpp index ca1f38300f3824..20384946fafa55 100644 --- a/packages/react-native/ReactCxxPlatform/react/runtime/ReactHost.cpp +++ b/packages/react-native/ReactCxxPlatform/react/runtime/ReactHost.cpp @@ -305,6 +305,9 @@ void ReactHost::destroyReactInstance() { reactInstanceData_->contextContainer->erase(RuntimeSchedulerKey); reactInstanceData_->mountingManager->setSchedulerTaskExecutor(nullptr); + reactInstanceData_->mountingManager = nullptr; + reactInstanceData_->contextContainer = nullptr; + reactInstanceData_->turboModuleProviders.clear(); reactInstance_ = nullptr; reactInstanceData_->messageQueueThread = nullptr; } diff --git a/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js b/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js index 501e5c2197b669..03695ea39e506b 100644 --- a/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js +++ b/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js @@ -286,6 +286,16 @@ const definitions: FeatureFlagDefinitions = { }, ossReleaseStage: 'none', }, + enableFabricCommitBranching: { + defaultValue: false, + metadata: { + description: + 'Enables Fabric commit branching to fix starvation problems and atomic JS updates.', + expectedReleaseValue: true, + purpose: 'release', + }, + ossReleaseStage: 'none', + }, enableFabricLogs: { defaultValue: false, metadata: { diff --git a/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js b/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js index be04495dc73b62..2671948a34549c 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<<0acb1755465fae151917d6043a737331>> + * @generated SignedSource<<78d732e45f4de66ed5313fc925783022>> * @flow strict * @noformat */ @@ -69,6 +69,7 @@ export type ReactNativeFeatureFlags = $ReadOnly<{ enableEagerMainQueueModulesOnIOS: Getter, enableEagerRootViewAttachment: Getter, enableExclusivePropsUpdateAndroid: Getter, + enableFabricCommitBranching: Getter, enableFabricLogs: Getter, enableFabricRenderer: Getter, enableFontScaleChangesUpdatingLayout: Getter, @@ -279,6 +280,10 @@ export const enableEagerRootViewAttachment: Getter = createNativeFlagGe * When enabled, Android will disable Props 1.5 raw value merging when Props 2.0 is available. */ export const enableExclusivePropsUpdateAndroid: Getter = createNativeFlagGetter('enableExclusivePropsUpdateAndroid', false); +/** + * Enables Fabric commit branching to fix starvation problems and atomic JS updates. + */ +export const enableFabricCommitBranching: Getter = createNativeFlagGetter('enableFabricCommitBranching', false); /** * This feature flag enables logs for Fabric. */ diff --git a/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js b/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js index b38207f4a883cb..0ee31f6b7d0aa8 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<<3540142c0e0e90aaffeb7ea02812e7b1>> + * @generated SignedSource<> * @flow strict * @noformat */ @@ -47,6 +47,7 @@ export interface Spec extends TurboModule { +enableEagerMainQueueModulesOnIOS?: () => boolean; +enableEagerRootViewAttachment?: () => boolean; +enableExclusivePropsUpdateAndroid?: () => boolean; + +enableFabricCommitBranching?: () => boolean; +enableFabricLogs?: () => boolean; +enableFabricRenderer?: () => boolean; +enableFontScaleChangesUpdatingLayout?: () => boolean;