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 ccddca4abb1..9650cafef4b 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<<9a33a6bc10cdb2b0f9fcb15805a06982>> + * @generated SignedSource<> */ /** @@ -100,6 +100,12 @@ public object ReactNativeFeatureFlags { @JvmStatic public fun fixMappingOfEventPrioritiesBetweenFabricAndReact(): Boolean = accessor.fixMappingOfEventPrioritiesBetweenFabricAndReact() + /** + * Enables a fix to prevent the possibility of state updates in Fabric being missed due to race conditions with previous state updates. + */ + @JvmStatic + public fun fixMissedFabricStateUpdatesOnAndroid(): Boolean = accessor.fixMissedFabricStateUpdatesOnAndroid() + /** * Fixes a leak in SurfaceMountingManager.mRemoveDeleteTreeUIFrameCallback */ 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 884795d8109..444f6937c4d 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<<5d67280406c16b01ba71b7b75e814a79>> + * @generated SignedSource<<92ebcb510939039fc157e0f85b08073e>> */ /** @@ -32,6 +32,7 @@ public class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAccesso private var enableSynchronousStateUpdatesCache: Boolean? = null private var enableUIConsistencyCache: Boolean? = null private var fixMappingOfEventPrioritiesBetweenFabricAndReactCache: Boolean? = null + private var fixMissedFabricStateUpdatesOnAndroidCache: Boolean? = null private var fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeakCache: Boolean? = null private var forceBatchingMountItemsOnAndroidCache: Boolean? = null private var fuseboxEnabledDebugCache: Boolean? = null @@ -154,6 +155,15 @@ public class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAccesso return cached } + override fun fixMissedFabricStateUpdatesOnAndroid(): Boolean { + var cached = fixMissedFabricStateUpdatesOnAndroidCache + if (cached == null) { + cached = ReactNativeFeatureFlagsCxxInterop.fixMissedFabricStateUpdatesOnAndroid() + fixMissedFabricStateUpdatesOnAndroidCache = cached + } + return cached + } + override fun fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak(): Boolean { var cached = fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeakCache 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 9abef85cb31..8d2e3d244e0 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<<154baea748cdf7b8e05a1e4448053673>> + * @generated SignedSource<<2434a09bc40a30291c642a26453f939f>> */ /** @@ -52,6 +52,8 @@ public object ReactNativeFeatureFlagsCxxInterop { @DoNotStrip @JvmStatic public external fun fixMappingOfEventPrioritiesBetweenFabricAndReact(): Boolean + @DoNotStrip @JvmStatic public external fun fixMissedFabricStateUpdatesOnAndroid(): Boolean + @DoNotStrip @JvmStatic public external fun fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak(): Boolean @DoNotStrip @JvmStatic public external fun forceBatchingMountItemsOnAndroid(): 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 04d17b77e8c..935248b2e16 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<<34bbd584a612fa88cc6adf2d2bc51b92>> + * @generated SignedSource<> */ /** @@ -47,6 +47,8 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi override fun fixMappingOfEventPrioritiesBetweenFabricAndReact(): Boolean = false + override fun fixMissedFabricStateUpdatesOnAndroid(): Boolean = false + override fun fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak(): Boolean = false override fun forceBatchingMountItemsOnAndroid(): 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 9d3d163dc48..8d20e04f5cc 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<> + * @generated SignedSource<<65a88218f057b56211d84b6d473e8a90>> */ /** @@ -36,6 +36,7 @@ public class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcces private var enableSynchronousStateUpdatesCache: Boolean? = null private var enableUIConsistencyCache: Boolean? = null private var fixMappingOfEventPrioritiesBetweenFabricAndReactCache: Boolean? = null + private var fixMissedFabricStateUpdatesOnAndroidCache: Boolean? = null private var fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeakCache: Boolean? = null private var forceBatchingMountItemsOnAndroidCache: Boolean? = null private var fuseboxEnabledDebugCache: Boolean? = null @@ -170,6 +171,16 @@ public class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcces return cached } + override fun fixMissedFabricStateUpdatesOnAndroid(): Boolean { + var cached = fixMissedFabricStateUpdatesOnAndroidCache + if (cached == null) { + cached = currentProvider.fixMissedFabricStateUpdatesOnAndroid() + accessedFeatureFlags.add("fixMissedFabricStateUpdatesOnAndroid") + fixMissedFabricStateUpdatesOnAndroidCache = cached + } + return cached + } + override fun fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak(): Boolean { var cached = fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeakCache 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 eb3e21e1278..9809e6de524 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<<3a0f547e2b68072a76b1eabc28c371cb>> */ /** @@ -47,6 +47,8 @@ public interface ReactNativeFeatureFlagsProvider { @DoNotStrip public fun fixMappingOfEventPrioritiesBetweenFabricAndReact(): Boolean + @DoNotStrip public fun fixMissedFabricStateUpdatesOnAndroid(): Boolean + @DoNotStrip public fun fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak(): Boolean @DoNotStrip public fun forceBatchingMountItemsOnAndroid(): 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 ab08744f65e..13124ea84be 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 @@ -540,7 +540,7 @@ void FabricMountingManager::executeMount( if (mountItem.newChildShadowView.state != nullptr) { javaStateWrapper = StateWrapperImpl::newObjectJavaArgs(); StateWrapperImpl* cStateWrapper = cthis(javaStateWrapper); - cStateWrapper->state_ = mountItem.newChildShadowView.state; + cStateWrapper->setState(mountItem.newChildShadowView.state); } // Do not hold a reference to javaEventEmitter from the C++ side. @@ -615,7 +615,7 @@ void FabricMountingManager::executeMount( if (state != nullptr) { javaStateWrapper = StateWrapperImpl::newObjectJavaArgs(); StateWrapperImpl* cStateWrapper = cthis(javaStateWrapper); - cStateWrapper->state_ = state; + cStateWrapper->setState(state); } (*objBufferArray)[objBufferPosition++] = @@ -823,7 +823,7 @@ void FabricMountingManager::preallocateShadowView( if (shadowView.state != nullptr) { javaStateWrapper = StateWrapperImpl::newObjectJavaArgs(); StateWrapperImpl* cStateWrapper = cthis(javaStateWrapper); - cStateWrapper->state_ = shadowView.state; + cStateWrapper->setState(shadowView.state); } // Do not hold a reference to javaEventEmitter from the C++ side. diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/StateWrapperImpl.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/StateWrapperImpl.cpp index bf5c18e5dd9..6ea03ff22e8 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/StateWrapperImpl.cpp +++ b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/StateWrapperImpl.cpp @@ -7,6 +7,7 @@ #include "StateWrapperImpl.h" #include +#include #include #include #include @@ -25,30 +26,65 @@ jni::local_ref StateWrapperImpl::initHybrid( jni::local_ref StateWrapperImpl::getStateDataImpl() { - if (auto state = state_.lock()) { - folly::dynamic map = state->getDynamic(); - return ReadableNativeMap::newObjectCxxArgs(std::move(map)); + if (ReactNativeFeatureFlags::fixMissedFabricStateUpdatesOnAndroid()) { + if (state_) { + folly::dynamic map = state_->getDynamic(); + return ReadableNativeMap::newObjectCxxArgs(std::move(map)); + } else { + return nullptr; + } } else { - return nullptr; + if (auto state = weakState_.lock()) { + folly::dynamic map = state->getDynamic(); + return ReadableNativeMap::newObjectCxxArgs(std::move(map)); + } else { + return nullptr; + } } } jni::local_ref StateWrapperImpl::getStateMapBufferDataImpl() { - if (auto state = state_.lock()) { - MapBuffer map = state->getMapBuffer(); - return JReadableMapBuffer::createWithContents(std::move(map)); + if (ReactNativeFeatureFlags::fixMissedFabricStateUpdatesOnAndroid()) { + if (state_) { + MapBuffer map = state_->getMapBuffer(); + return JReadableMapBuffer::createWithContents(std::move(map)); + } else { + return nullptr; + } } else { - return nullptr; + if (auto state = weakState_.lock()) { + MapBuffer map = state->getMapBuffer(); + return JReadableMapBuffer::createWithContents(std::move(map)); + } else { + return nullptr; + } } } void StateWrapperImpl::updateStateImpl(NativeMap* map) { - if (auto state = state_.lock()) { - // Get folly::dynamic from map - auto dynamicMap = map->consume(); - // Set state - state->updateState(std::move(dynamicMap)); + if (ReactNativeFeatureFlags::fixMissedFabricStateUpdatesOnAndroid()) { + if (state_) { + // Get folly::dynamic from map + auto dynamicMap = map->consume(); + // Set state + state_->updateState(std::move(dynamicMap)); + } + } else { + if (auto state = weakState_.lock()) { + // Get folly::dynamic from map + auto dynamicMap = map->consume(); + // Set state + state->updateState(std::move(dynamicMap)); + } + } +} + +void StateWrapperImpl::setState(std::shared_ptr state) { + if (ReactNativeFeatureFlags::fixMissedFabricStateUpdatesOnAndroid()) { + state_ = state; + } else { + weakState_ = state; } } diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/StateWrapperImpl.h b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/StateWrapperImpl.h index 3aac2e0a7e9..542f78c69ae 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/StateWrapperImpl.h +++ b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/StateWrapperImpl.h @@ -28,11 +28,12 @@ class StateWrapperImpl : public jni::HybridClass { jni::local_ref getStateMapBufferDataImpl(); jni::local_ref getStateDataImpl(); void updateStateImpl(NativeMap* map); - - std::weak_ptr state_; + void setState(std::shared_ptr state); private: jni::alias_ref jhybridobject_; + std::weak_ptr weakState_; + std::shared_ptr state_; static jni::local_ref initHybrid(jni::alias_ref); }; 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 d5ad1a7f1c8..864feb38252 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<<88f5b83b8a3d7902eaab333246b59ed3>> + * @generated SignedSource<> */ /** @@ -111,6 +111,12 @@ class ReactNativeFeatureFlagsProviderHolder return method(javaProvider_); } + bool fixMissedFabricStateUpdatesOnAndroid() override { + static const auto method = + getReactNativeFeatureFlagsProviderJavaClass()->getMethod("fixMissedFabricStateUpdatesOnAndroid"); + return method(javaProvider_); + } + bool fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak() override { static const auto method = getReactNativeFeatureFlagsProviderJavaClass()->getMethod("fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak"); @@ -253,6 +259,11 @@ bool JReactNativeFeatureFlagsCxxInterop::fixMappingOfEventPrioritiesBetweenFabri return ReactNativeFeatureFlags::fixMappingOfEventPrioritiesBetweenFabricAndReact(); } +bool JReactNativeFeatureFlagsCxxInterop::fixMissedFabricStateUpdatesOnAndroid( + facebook::jni::alias_ref /*unused*/) { + return ReactNativeFeatureFlags::fixMissedFabricStateUpdatesOnAndroid(); +} + bool JReactNativeFeatureFlagsCxxInterop::fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak( facebook::jni::alias_ref /*unused*/) { return ReactNativeFeatureFlags::fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak(); @@ -371,6 +382,9 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() { makeNativeMethod( "fixMappingOfEventPrioritiesBetweenFabricAndReact", JReactNativeFeatureFlagsCxxInterop::fixMappingOfEventPrioritiesBetweenFabricAndReact), + makeNativeMethod( + "fixMissedFabricStateUpdatesOnAndroid", + JReactNativeFeatureFlagsCxxInterop::fixMissedFabricStateUpdatesOnAndroid), makeNativeMethod( "fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak", JReactNativeFeatureFlagsCxxInterop::fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak), 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 f9e1381671a..c56d27ac581 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<<66b47850d8e211f78b3e3dd40b6cc37e>> + * @generated SignedSource<<7e9c48995f6a5f4e0a56c0f2ec784def>> */ /** @@ -66,6 +66,9 @@ class JReactNativeFeatureFlagsCxxInterop static bool fixMappingOfEventPrioritiesBetweenFabricAndReact( facebook::jni::alias_ref); + static bool fixMissedFabricStateUpdatesOnAndroid( + facebook::jni::alias_ref); + static bool fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak( 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 ce3f391dffb..0e5aa5d0d3c 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<<91a56189178d461874bfff11b14ca318>> */ /** @@ -69,6 +69,10 @@ bool ReactNativeFeatureFlags::fixMappingOfEventPrioritiesBetweenFabricAndReact() return getAccessor().fixMappingOfEventPrioritiesBetweenFabricAndReact(); } +bool ReactNativeFeatureFlags::fixMissedFabricStateUpdatesOnAndroid() { + return getAccessor().fixMissedFabricStateUpdatesOnAndroid(); +} + bool ReactNativeFeatureFlags::fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak() { return getAccessor().fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak(); } diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h index 014c5142092..6d285f927f7 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<> + * @generated SignedSource<<6683bcf499d88e4449f570f38b7d8b2f>> */ /** @@ -97,6 +97,11 @@ class ReactNativeFeatureFlags { */ RN_EXPORT static bool fixMappingOfEventPrioritiesBetweenFabricAndReact(); + /** + * Enables a fix to prevent the possibility of state updates in Fabric being missed due to race conditions with previous state updates. + */ + RN_EXPORT static bool fixMissedFabricStateUpdatesOnAndroid(); + /** * Fixes a leak in SurfaceMountingManager.mRemoveDeleteTreeUIFrameCallback */ diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp index 179d23099e1..88938c188ba 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<<44087cc6e946a05884c8761987878183>> + * @generated SignedSource<> */ /** @@ -245,6 +245,24 @@ bool ReactNativeFeatureFlagsAccessor::fixMappingOfEventPrioritiesBetweenFabricAn return flagValue.value(); } +bool ReactNativeFeatureFlagsAccessor::fixMissedFabricStateUpdatesOnAndroid() { + auto flagValue = fixMissedFabricStateUpdatesOnAndroid_.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(12, "fixMissedFabricStateUpdatesOnAndroid"); + + flagValue = currentProvider_->fixMissedFabricStateUpdatesOnAndroid(); + fixMissedFabricStateUpdatesOnAndroid_ = flagValue; + } + + return flagValue.value(); +} + bool ReactNativeFeatureFlagsAccessor::fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak() { auto flagValue = fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak_.load(); @@ -254,7 +272,7 @@ bool ReactNativeFeatureFlagsAccessor::fixStoppedSurfaceRemoveDeleteTreeUIFrameCa // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(12, "fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak"); + markFlagAsAccessed(13, "fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak"); flagValue = currentProvider_->fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak(); fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak_ = flagValue; @@ -272,7 +290,7 @@ bool ReactNativeFeatureFlagsAccessor::forceBatchingMountItemsOnAndroid() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(13, "forceBatchingMountItemsOnAndroid"); + markFlagAsAccessed(14, "forceBatchingMountItemsOnAndroid"); flagValue = currentProvider_->forceBatchingMountItemsOnAndroid(); forceBatchingMountItemsOnAndroid_ = flagValue; @@ -290,7 +308,7 @@ bool ReactNativeFeatureFlagsAccessor::fuseboxEnabledDebug() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(14, "fuseboxEnabledDebug"); + markFlagAsAccessed(15, "fuseboxEnabledDebug"); flagValue = currentProvider_->fuseboxEnabledDebug(); fuseboxEnabledDebug_ = flagValue; @@ -308,7 +326,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(15, "fuseboxEnabledRelease"); + markFlagAsAccessed(16, "fuseboxEnabledRelease"); flagValue = currentProvider_->fuseboxEnabledRelease(); fuseboxEnabledRelease_ = flagValue; @@ -326,7 +344,7 @@ bool ReactNativeFeatureFlagsAccessor::lazyAnimationCallbacks() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(16, "lazyAnimationCallbacks"); + markFlagAsAccessed(17, "lazyAnimationCallbacks"); flagValue = currentProvider_->lazyAnimationCallbacks(); lazyAnimationCallbacks_ = flagValue; @@ -344,7 +362,7 @@ bool ReactNativeFeatureFlagsAccessor::preventDoubleTextMeasure() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(17, "preventDoubleTextMeasure"); + markFlagAsAccessed(18, "preventDoubleTextMeasure"); flagValue = currentProvider_->preventDoubleTextMeasure(); preventDoubleTextMeasure_ = flagValue; @@ -362,7 +380,7 @@ bool ReactNativeFeatureFlagsAccessor::setAndroidLayoutDirection() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(18, "setAndroidLayoutDirection"); + markFlagAsAccessed(19, "setAndroidLayoutDirection"); flagValue = currentProvider_->setAndroidLayoutDirection(); setAndroidLayoutDirection_ = flagValue; @@ -380,7 +398,7 @@ bool ReactNativeFeatureFlagsAccessor::useImmediateExecutorInAndroidBridgeless() // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(19, "useImmediateExecutorInAndroidBridgeless"); + markFlagAsAccessed(20, "useImmediateExecutorInAndroidBridgeless"); flagValue = currentProvider_->useImmediateExecutorInAndroidBridgeless(); useImmediateExecutorInAndroidBridgeless_ = flagValue; @@ -398,7 +416,7 @@ bool ReactNativeFeatureFlagsAccessor::useModernRuntimeScheduler() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(20, "useModernRuntimeScheduler"); + markFlagAsAccessed(21, "useModernRuntimeScheduler"); flagValue = currentProvider_->useModernRuntimeScheduler(); useModernRuntimeScheduler_ = flagValue; @@ -416,7 +434,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(21, "useNativeViewConfigsInBridgelessMode"); + markFlagAsAccessed(22, "useNativeViewConfigsInBridgelessMode"); flagValue = currentProvider_->useNativeViewConfigsInBridgelessMode(); useNativeViewConfigsInBridgelessMode_ = flagValue; @@ -434,7 +452,7 @@ bool ReactNativeFeatureFlagsAccessor::useRuntimeShadowNodeReferenceUpdate() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(22, "useRuntimeShadowNodeReferenceUpdate"); + markFlagAsAccessed(23, "useRuntimeShadowNodeReferenceUpdate"); flagValue = currentProvider_->useRuntimeShadowNodeReferenceUpdate(); useRuntimeShadowNodeReferenceUpdate_ = flagValue; @@ -452,7 +470,7 @@ bool ReactNativeFeatureFlagsAccessor::useRuntimeShadowNodeReferenceUpdateOnLayou // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(23, "useRuntimeShadowNodeReferenceUpdateOnLayout"); + markFlagAsAccessed(24, "useRuntimeShadowNodeReferenceUpdateOnLayout"); flagValue = currentProvider_->useRuntimeShadowNodeReferenceUpdateOnLayout(); useRuntimeShadowNodeReferenceUpdateOnLayout_ = flagValue; @@ -470,7 +488,7 @@ bool ReactNativeFeatureFlagsAccessor::useStateAlignmentMechanism() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(24, "useStateAlignmentMechanism"); + markFlagAsAccessed(25, "useStateAlignmentMechanism"); flagValue = currentProvider_->useStateAlignmentMechanism(); useStateAlignmentMechanism_ = flagValue; diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h index 092b983a4ce..15292516808 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<<45258896e458cce165b403e043356eb9>> + * @generated SignedSource<> */ /** @@ -43,6 +43,7 @@ class ReactNativeFeatureFlagsAccessor { bool enableSynchronousStateUpdates(); bool enableUIConsistency(); bool fixMappingOfEventPrioritiesBetweenFabricAndReact(); + bool fixMissedFabricStateUpdatesOnAndroid(); bool fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak(); bool forceBatchingMountItemsOnAndroid(); bool fuseboxEnabledDebug(); @@ -66,7 +67,7 @@ class ReactNativeFeatureFlagsAccessor { std::unique_ptr currentProvider_; bool wasOverridden_; - std::array, 25> accessedFeatureFlags_; + std::array, 26> accessedFeatureFlags_; std::atomic> commonTestFlag_; std::atomic> allowCollapsableChildren_; @@ -80,6 +81,7 @@ class ReactNativeFeatureFlagsAccessor { std::atomic> enableSynchronousStateUpdates_; std::atomic> enableUIConsistency_; std::atomic> fixMappingOfEventPrioritiesBetweenFabricAndReact_; + std::atomic> fixMissedFabricStateUpdatesOnAndroid_; std::atomic> fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak_; std::atomic> forceBatchingMountItemsOnAndroid_; std::atomic> fuseboxEnabledDebug_; diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h index 8af86e0d738..71f85258530 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<<0f6ca616cc516096ec250d61be440952>> + * @generated SignedSource<> */ /** @@ -75,6 +75,10 @@ class ReactNativeFeatureFlagsDefaults : public ReactNativeFeatureFlagsProvider { return false; } + bool fixMissedFabricStateUpdatesOnAndroid() override { + return false; + } + bool fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak() override { return false; } diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h index 87d9985fa20..c1d0b662c97 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<<3da295d89796e905588eb863a51c2054>> + * @generated SignedSource<<57b9e4f683df27a7a5770633e88f8b22>> */ /** @@ -37,6 +37,7 @@ class ReactNativeFeatureFlagsProvider { virtual bool enableSynchronousStateUpdates() = 0; virtual bool enableUIConsistency() = 0; virtual bool fixMappingOfEventPrioritiesBetweenFabricAndReact() = 0; + virtual bool fixMissedFabricStateUpdatesOnAndroid() = 0; virtual bool fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak() = 0; virtual bool forceBatchingMountItemsOnAndroid() = 0; virtual bool fuseboxEnabledDebug() = 0; diff --git a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp index 6951bd60316..7dab29de35d 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<<82399968da4f450b87c908031466a38a>> + * @generated SignedSource<<58b0c0c49dc6cf2ecdbc2c3038395e4e>> */ /** @@ -97,6 +97,11 @@ bool NativeReactNativeFeatureFlags::fixMappingOfEventPrioritiesBetweenFabricAndR return ReactNativeFeatureFlags::fixMappingOfEventPrioritiesBetweenFabricAndReact(); } +bool NativeReactNativeFeatureFlags::fixMissedFabricStateUpdatesOnAndroid( + jsi::Runtime& /*runtime*/) { + return ReactNativeFeatureFlags::fixMissedFabricStateUpdatesOnAndroid(); +} + bool NativeReactNativeFeatureFlags::fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak( jsi::Runtime& /*runtime*/) { return ReactNativeFeatureFlags::fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak(); diff --git a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h index 2266b229203..01e02bc2063 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<<6b8504e42d72611f4d4b6606d69c42aa>> + * @generated SignedSource<> */ /** @@ -59,6 +59,8 @@ class NativeReactNativeFeatureFlags bool fixMappingOfEventPrioritiesBetweenFabricAndReact(jsi::Runtime& runtime); + bool fixMissedFabricStateUpdatesOnAndroid(jsi::Runtime& runtime); + bool fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak(jsi::Runtime& runtime); bool forceBatchingMountItemsOnAndroid(jsi::Runtime& runtime); diff --git a/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js b/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js index 79884fb2b25..8ae591d78f3 100644 --- a/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js +++ b/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js @@ -93,6 +93,11 @@ const definitions: FeatureFlagDefinitions = { description: 'Uses the default event priority instead of the discreet event priority by default when dispatching events from Fabric to React.', }, + fixMissedFabricStateUpdatesOnAndroid: { + defaultValue: false, + description: + 'Enables a fix to prevent the possibility of state updates in Fabric being missed due to race conditions with previous state updates.', + }, fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak: { defaultValue: false, description: diff --git a/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js b/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js index 56cb85ac155..0e252406c64 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<<522f11a571457cb932f451cf81bd384a>> + * @generated SignedSource<<95a692d91055d05301a06fd33636d3fa>> * @flow strict-local */ @@ -53,6 +53,7 @@ export type ReactNativeFeatureFlags = { enableSynchronousStateUpdates: Getter, enableUIConsistency: Getter, fixMappingOfEventPrioritiesBetweenFabricAndReact: Getter, + fixMissedFabricStateUpdatesOnAndroid: Getter, fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak: Getter, forceBatchingMountItemsOnAndroid: Getter, fuseboxEnabledDebug: Getter, @@ -161,6 +162,10 @@ export const enableUIConsistency: Getter = createNativeFlagGetter('enab * Uses the default event priority instead of the discreet event priority by default when dispatching events from Fabric to React. */ export const fixMappingOfEventPrioritiesBetweenFabricAndReact: Getter = createNativeFlagGetter('fixMappingOfEventPrioritiesBetweenFabricAndReact', false); +/** + * Enables a fix to prevent the possibility of state updates in Fabric being missed due to race conditions with previous state updates. + */ +export const fixMissedFabricStateUpdatesOnAndroid: Getter = createNativeFlagGetter('fixMissedFabricStateUpdatesOnAndroid', false); /** * Fixes a leak in SurfaceMountingManager.mRemoveDeleteTreeUIFrameCallback */ diff --git a/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js b/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js index 475f8fd79cf..c826385896b 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<<6715ba4954b31464c591597c53a2a0de>> + * @generated SignedSource<> * @flow strict-local */ @@ -35,6 +35,7 @@ export interface Spec extends TurboModule { +enableSynchronousStateUpdates?: () => boolean; +enableUIConsistency?: () => boolean; +fixMappingOfEventPrioritiesBetweenFabricAndReact?: () => boolean; + +fixMissedFabricStateUpdatesOnAndroid?: () => boolean; +fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak?: () => boolean; +forceBatchingMountItemsOnAndroid?: () => boolean; +fuseboxEnabledDebug?: () => boolean;