Set up experiment to fix the mapping of event priorities between Fabric and React (#45013)

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

Changelog: [internal]

## Context

We recently realized that in the majority of events dispatched to React from Fabric, passive effects were being mounted synchronously, blocking paint instead of in a separate task after paint.

The reason for that is that in React, passive effects for discrete events are mounted synchronously by design (see https://github.com/reactwg/react-18/discussions/128), and Fabric is currently assigning the discrete event priority to most current events (including things like layout events).

## Changes

This creates a feature flag to opt into a more granular control over event priorities in React Native. Instead of assigning the discrete event priority to events by default, this would assign the "default" event priority by default, except for events dispatched during continuous events that would also be considered continuous.

This would also fix the priority for continuous events, that it was currently being assigned as "default" incorrectly.

Reviewed By: christophpurrer, javache, sammy-SC

Differential Revision: D58677191

fbshipit-source-id: c65a8dc2118ed028e1e895adec54f9072b7e55a6
This commit is contained in:
Rubén Norte
2024-06-18 05:24:57 -07:00
committed by Facebook GitHub Bot
parent 43d69ee26c
commit 404f323359
20 changed files with 168 additions and 43 deletions
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<177f05d7b2fadcfffa32cb5a7a21c76b>>
* @generated SignedSource<<9a33a6bc10cdb2b0f9fcb15805a06982>>
*/
/**
@@ -94,6 +94,12 @@ public object ReactNativeFeatureFlags {
@JvmStatic
public fun enableUIConsistency(): Boolean = accessor.enableUIConsistency()
/**
* Uses the default event priority instead of the discreet event priority by default when dispatching events from Fabric to React.
*/
@JvmStatic
public fun fixMappingOfEventPrioritiesBetweenFabricAndReact(): Boolean = accessor.fixMappingOfEventPrioritiesBetweenFabricAndReact()
/**
* Fixes a leak in SurfaceMountingManager.mRemoveDeleteTreeUIFrameCallback
*/
@@ -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<<492902f307361b8f7b7d42973561a3b4>>
* @generated SignedSource<<5d67280406c16b01ba71b7b75e814a79>>
*/
/**
@@ -31,6 +31,7 @@ public class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAccesso
private var enableMicrotasksCache: Boolean? = null
private var enableSynchronousStateUpdatesCache: Boolean? = null
private var enableUIConsistencyCache: Boolean? = null
private var fixMappingOfEventPrioritiesBetweenFabricAndReactCache: Boolean? = null
private var fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeakCache: Boolean? = null
private var forceBatchingMountItemsOnAndroidCache: Boolean? = null
private var fuseboxEnabledDebugCache: Boolean? = null
@@ -144,6 +145,15 @@ public class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAccesso
return cached
}
override fun fixMappingOfEventPrioritiesBetweenFabricAndReact(): Boolean {
var cached = fixMappingOfEventPrioritiesBetweenFabricAndReactCache
if (cached == null) {
cached = ReactNativeFeatureFlagsCxxInterop.fixMappingOfEventPrioritiesBetweenFabricAndReact()
fixMappingOfEventPrioritiesBetweenFabricAndReactCache = cached
}
return cached
}
override fun fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak(): Boolean {
var cached = fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeakCache
if (cached == null) {
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<05bf91e1b2a64cdc48615137deec627a>>
* @generated SignedSource<<154baea748cdf7b8e05a1e4448053673>>
*/
/**
@@ -50,6 +50,8 @@ public object ReactNativeFeatureFlagsCxxInterop {
@DoNotStrip @JvmStatic public external fun enableUIConsistency(): Boolean
@DoNotStrip @JvmStatic public external fun fixMappingOfEventPrioritiesBetweenFabricAndReact(): Boolean
@DoNotStrip @JvmStatic public external fun fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak(): Boolean
@DoNotStrip @JvmStatic public external fun forceBatchingMountItemsOnAndroid(): Boolean
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<7c95ebf976344317cd8904d71ea22fe5>>
* @generated SignedSource<<34bbd584a612fa88cc6adf2d2bc51b92>>
*/
/**
@@ -45,6 +45,8 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi
override fun enableUIConsistency(): Boolean = false
override fun fixMappingOfEventPrioritiesBetweenFabricAndReact(): Boolean = false
override fun fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak(): Boolean = false
override fun forceBatchingMountItemsOnAndroid(): Boolean = false
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<d23d2a5f44f2b2068dde9e85e5b1ce9f>>
* @generated SignedSource<<d991cac9311ee91e5e9401b143b69145>>
*/
/**
@@ -35,6 +35,7 @@ public class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcces
private var enableMicrotasksCache: Boolean? = null
private var enableSynchronousStateUpdatesCache: Boolean? = null
private var enableUIConsistencyCache: Boolean? = null
private var fixMappingOfEventPrioritiesBetweenFabricAndReactCache: Boolean? = null
private var fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeakCache: Boolean? = null
private var forceBatchingMountItemsOnAndroidCache: Boolean? = null
private var fuseboxEnabledDebugCache: Boolean? = null
@@ -159,6 +160,16 @@ public class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcces
return cached
}
override fun fixMappingOfEventPrioritiesBetweenFabricAndReact(): Boolean {
var cached = fixMappingOfEventPrioritiesBetweenFabricAndReactCache
if (cached == null) {
cached = currentProvider.fixMappingOfEventPrioritiesBetweenFabricAndReact()
accessedFeatureFlags.add("fixMappingOfEventPrioritiesBetweenFabricAndReact")
fixMappingOfEventPrioritiesBetweenFabricAndReactCache = cached
}
return cached
}
override fun fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak(): Boolean {
var cached = fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeakCache
if (cached == null) {
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<d84816a13ad49b6e1c69c968a8503385>>
* @generated SignedSource<<aae9b8936680c1cd6db2c1c0135e1cef>>
*/
/**
@@ -45,6 +45,8 @@ public interface ReactNativeFeatureFlagsProvider {
@DoNotStrip public fun enableUIConsistency(): Boolean
@DoNotStrip public fun fixMappingOfEventPrioritiesBetweenFabricAndReact(): Boolean
@DoNotStrip public fun fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak(): Boolean
@DoNotStrip public fun forceBatchingMountItemsOnAndroid(): Boolean
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<2af7a8ae4860f81b46e48afb17ee54b6>>
* @generated SignedSource<<88f5b83b8a3d7902eaab333246b59ed3>>
*/
/**
@@ -105,6 +105,12 @@ class ReactNativeFeatureFlagsProviderHolder
return method(javaProvider_);
}
bool fixMappingOfEventPrioritiesBetweenFabricAndReact() override {
static const auto method =
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("fixMappingOfEventPrioritiesBetweenFabricAndReact");
return method(javaProvider_);
}
bool fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak() override {
static const auto method =
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak");
@@ -242,6 +248,11 @@ bool JReactNativeFeatureFlagsCxxInterop::enableUIConsistency(
return ReactNativeFeatureFlags::enableUIConsistency();
}
bool JReactNativeFeatureFlagsCxxInterop::fixMappingOfEventPrioritiesBetweenFabricAndReact(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
return ReactNativeFeatureFlags::fixMappingOfEventPrioritiesBetweenFabricAndReact();
}
bool JReactNativeFeatureFlagsCxxInterop::fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
return ReactNativeFeatureFlags::fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak();
@@ -357,6 +368,9 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() {
makeNativeMethod(
"enableUIConsistency",
JReactNativeFeatureFlagsCxxInterop::enableUIConsistency),
makeNativeMethod(
"fixMappingOfEventPrioritiesBetweenFabricAndReact",
JReactNativeFeatureFlagsCxxInterop::fixMappingOfEventPrioritiesBetweenFabricAndReact),
makeNativeMethod(
"fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak",
JReactNativeFeatureFlagsCxxInterop::fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak),
@@ -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<<1d1422d073ae40ee4bbc788dc222cc28>>
* @generated SignedSource<<66b47850d8e211f78b3e3dd40b6cc37e>>
*/
/**
@@ -63,6 +63,9 @@ class JReactNativeFeatureFlagsCxxInterop
static bool enableUIConsistency(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
static bool fixMappingOfEventPrioritiesBetweenFabricAndReact(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
static bool fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<ec12fd62d1dc2109e52a95094d7ad167>>
* @generated SignedSource<<dd5872a21f84a41bea247e137541ddfc>>
*/
/**
@@ -65,6 +65,10 @@ bool ReactNativeFeatureFlags::enableUIConsistency() {
return getAccessor().enableUIConsistency();
}
bool ReactNativeFeatureFlags::fixMappingOfEventPrioritiesBetweenFabricAndReact() {
return getAccessor().fixMappingOfEventPrioritiesBetweenFabricAndReact();
}
bool ReactNativeFeatureFlags::fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak() {
return getAccessor().fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak();
}
@@ -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<<5f1ae3edfe01ee0545bd89137c5cb3e9>>
* @generated SignedSource<<e45c35dee2c9e2135995ccf2c8a6def3>>
*/
/**
@@ -92,6 +92,11 @@ class ReactNativeFeatureFlags {
*/
RN_EXPORT static bool enableUIConsistency();
/**
* Uses the default event priority instead of the discreet event priority by default when dispatching events from Fabric to React.
*/
RN_EXPORT static bool fixMappingOfEventPrioritiesBetweenFabricAndReact();
/**
* Fixes a leak in SurfaceMountingManager.mRemoveDeleteTreeUIFrameCallback
*/
@@ -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<<6d08fc8ff31f1db50cb4b14edb6b690f>>
* @generated SignedSource<<44087cc6e946a05884c8761987878183>>
*/
/**
@@ -227,6 +227,24 @@ bool ReactNativeFeatureFlagsAccessor::enableUIConsistency() {
return flagValue.value();
}
bool ReactNativeFeatureFlagsAccessor::fixMappingOfEventPrioritiesBetweenFabricAndReact() {
auto flagValue = fixMappingOfEventPrioritiesBetweenFabricAndReact_.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(11, "fixMappingOfEventPrioritiesBetweenFabricAndReact");
flagValue = currentProvider_->fixMappingOfEventPrioritiesBetweenFabricAndReact();
fixMappingOfEventPrioritiesBetweenFabricAndReact_ = flagValue;
}
return flagValue.value();
}
bool ReactNativeFeatureFlagsAccessor::fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak() {
auto flagValue = fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak_.load();
@@ -236,7 +254,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(11, "fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak");
markFlagAsAccessed(12, "fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak");
flagValue = currentProvider_->fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak();
fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak_ = flagValue;
@@ -254,7 +272,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(12, "forceBatchingMountItemsOnAndroid");
markFlagAsAccessed(13, "forceBatchingMountItemsOnAndroid");
flagValue = currentProvider_->forceBatchingMountItemsOnAndroid();
forceBatchingMountItemsOnAndroid_ = flagValue;
@@ -272,7 +290,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(13, "fuseboxEnabledDebug");
markFlagAsAccessed(14, "fuseboxEnabledDebug");
flagValue = currentProvider_->fuseboxEnabledDebug();
fuseboxEnabledDebug_ = flagValue;
@@ -290,7 +308,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(14, "fuseboxEnabledRelease");
markFlagAsAccessed(15, "fuseboxEnabledRelease");
flagValue = currentProvider_->fuseboxEnabledRelease();
fuseboxEnabledRelease_ = flagValue;
@@ -308,7 +326,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(15, "lazyAnimationCallbacks");
markFlagAsAccessed(16, "lazyAnimationCallbacks");
flagValue = currentProvider_->lazyAnimationCallbacks();
lazyAnimationCallbacks_ = flagValue;
@@ -326,7 +344,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(16, "preventDoubleTextMeasure");
markFlagAsAccessed(17, "preventDoubleTextMeasure");
flagValue = currentProvider_->preventDoubleTextMeasure();
preventDoubleTextMeasure_ = flagValue;
@@ -344,7 +362,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(17, "setAndroidLayoutDirection");
markFlagAsAccessed(18, "setAndroidLayoutDirection");
flagValue = currentProvider_->setAndroidLayoutDirection();
setAndroidLayoutDirection_ = flagValue;
@@ -362,7 +380,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(18, "useImmediateExecutorInAndroidBridgeless");
markFlagAsAccessed(19, "useImmediateExecutorInAndroidBridgeless");
flagValue = currentProvider_->useImmediateExecutorInAndroidBridgeless();
useImmediateExecutorInAndroidBridgeless_ = flagValue;
@@ -380,7 +398,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(19, "useModernRuntimeScheduler");
markFlagAsAccessed(20, "useModernRuntimeScheduler");
flagValue = currentProvider_->useModernRuntimeScheduler();
useModernRuntimeScheduler_ = flagValue;
@@ -398,7 +416,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(20, "useNativeViewConfigsInBridgelessMode");
markFlagAsAccessed(21, "useNativeViewConfigsInBridgelessMode");
flagValue = currentProvider_->useNativeViewConfigsInBridgelessMode();
useNativeViewConfigsInBridgelessMode_ = flagValue;
@@ -416,7 +434,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(21, "useRuntimeShadowNodeReferenceUpdate");
markFlagAsAccessed(22, "useRuntimeShadowNodeReferenceUpdate");
flagValue = currentProvider_->useRuntimeShadowNodeReferenceUpdate();
useRuntimeShadowNodeReferenceUpdate_ = flagValue;
@@ -434,7 +452,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(22, "useRuntimeShadowNodeReferenceUpdateOnLayout");
markFlagAsAccessed(23, "useRuntimeShadowNodeReferenceUpdateOnLayout");
flagValue = currentProvider_->useRuntimeShadowNodeReferenceUpdateOnLayout();
useRuntimeShadowNodeReferenceUpdateOnLayout_ = flagValue;
@@ -452,7 +470,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(23, "useStateAlignmentMechanism");
markFlagAsAccessed(24, "useStateAlignmentMechanism");
flagValue = currentProvider_->useStateAlignmentMechanism();
useStateAlignmentMechanism_ = flagValue;
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<3be4d7eb8694603de9fb5885562d5a78>>
* @generated SignedSource<<45258896e458cce165b403e043356eb9>>
*/
/**
@@ -42,6 +42,7 @@ class ReactNativeFeatureFlagsAccessor {
bool enableMicrotasks();
bool enableSynchronousStateUpdates();
bool enableUIConsistency();
bool fixMappingOfEventPrioritiesBetweenFabricAndReact();
bool fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak();
bool forceBatchingMountItemsOnAndroid();
bool fuseboxEnabledDebug();
@@ -65,7 +66,7 @@ class ReactNativeFeatureFlagsAccessor {
std::unique_ptr<ReactNativeFeatureFlagsProvider> currentProvider_;
bool wasOverridden_;
std::array<std::atomic<const char*>, 24> accessedFeatureFlags_;
std::array<std::atomic<const char*>, 25> accessedFeatureFlags_;
std::atomic<std::optional<bool>> commonTestFlag_;
std::atomic<std::optional<bool>> allowCollapsableChildren_;
@@ -78,6 +79,7 @@ class ReactNativeFeatureFlagsAccessor {
std::atomic<std::optional<bool>> enableMicrotasks_;
std::atomic<std::optional<bool>> enableSynchronousStateUpdates_;
std::atomic<std::optional<bool>> enableUIConsistency_;
std::atomic<std::optional<bool>> fixMappingOfEventPrioritiesBetweenFabricAndReact_;
std::atomic<std::optional<bool>> fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak_;
std::atomic<std::optional<bool>> forceBatchingMountItemsOnAndroid_;
std::atomic<std::optional<bool>> fuseboxEnabledDebug_;
@@ -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<<97c824bb63734389fae8eea61b92d440>>
* @generated SignedSource<<0f6ca616cc516096ec250d61be440952>>
*/
/**
@@ -71,6 +71,10 @@ class ReactNativeFeatureFlagsDefaults : public ReactNativeFeatureFlagsProvider {
return false;
}
bool fixMappingOfEventPrioritiesBetweenFabricAndReact() override {
return false;
}
bool fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak() override {
return false;
}
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<454a55db4c97f9c28c0a8427d4c0bd57>>
* @generated SignedSource<<3da295d89796e905588eb863a51c2054>>
*/
/**
@@ -36,6 +36,7 @@ class ReactNativeFeatureFlagsProvider {
virtual bool enableMicrotasks() = 0;
virtual bool enableSynchronousStateUpdates() = 0;
virtual bool enableUIConsistency() = 0;
virtual bool fixMappingOfEventPrioritiesBetweenFabricAndReact() = 0;
virtual bool fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak() = 0;
virtual bool forceBatchingMountItemsOnAndroid() = 0;
virtual bool fuseboxEnabledDebug() = 0;
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<81d9543c4231939f31dc5c9bb06c942c>>
* @generated SignedSource<<82399968da4f450b87c908031466a38a>>
*/
/**
@@ -92,6 +92,11 @@ bool NativeReactNativeFeatureFlags::enableUIConsistency(
return ReactNativeFeatureFlags::enableUIConsistency();
}
bool NativeReactNativeFeatureFlags::fixMappingOfEventPrioritiesBetweenFabricAndReact(
jsi::Runtime& /*runtime*/) {
return ReactNativeFeatureFlags::fixMappingOfEventPrioritiesBetweenFabricAndReact();
}
bool NativeReactNativeFeatureFlags::fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak(
jsi::Runtime& /*runtime*/) {
return ReactNativeFeatureFlags::fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak();
@@ -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<<e13caa80ac317feb98cf4db5ac89be79>>
* @generated SignedSource<<6b8504e42d72611f4d4b6606d69c42aa>>
*/
/**
@@ -57,6 +57,8 @@ class NativeReactNativeFeatureFlags
bool enableUIConsistency(jsi::Runtime& runtime);
bool fixMappingOfEventPrioritiesBetweenFabricAndReact(jsi::Runtime& runtime);
bool fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak(jsi::Runtime& runtime);
bool forceBatchingMountItemsOnAndroid(jsi::Runtime& runtime);
@@ -7,6 +7,7 @@
#include <cxxreact/JSExecutor.h>
#include <logger/react_native_log.h>
#include <react/featureflags/ReactNativeFeatureFlags.h>
#include "EventEmitter.h"
#include "EventLogger.h"
#include "EventQueue.h"
@@ -38,20 +39,42 @@ void EventQueueProcessor::flushEvents(
}
for (const auto& event : events) {
if (event.category == RawEvent::Category::ContinuousEnd) {
hasContinuousEventStarted_ = false;
}
auto reactPriority = ReactEventPriority::Default;
auto reactPriority = hasContinuousEventStarted_
? ReactEventPriority::Default
: ReactEventPriority::Discrete;
if (ReactNativeFeatureFlags::
fixMappingOfEventPrioritiesBetweenFabricAndReact()) {
reactPriority = [&]() {
switch (event.category) {
case RawEvent::Category::Discrete:
return ReactEventPriority::Discrete;
case RawEvent::Category::ContinuousStart:
hasContinuousEventStarted_ = true;
return ReactEventPriority::Discrete;
case RawEvent::Category::ContinuousEnd:
hasContinuousEventStarted_ = false;
return ReactEventPriority::Discrete;
case RawEvent::Category::Continuous:
return ReactEventPriority::Continuous;
case RawEvent::Category::Unspecified:
return hasContinuousEventStarted_ ? ReactEventPriority::Continuous
: ReactEventPriority::Default;
}
}();
} else {
if (event.category == RawEvent::Category::ContinuousEnd) {
hasContinuousEventStarted_ = false;
}
if (event.category == RawEvent::Category::Continuous) {
reactPriority = ReactEventPriority::Default;
}
reactPriority = hasContinuousEventStarted_ ? ReactEventPriority::Default
: ReactEventPriority::Discrete;
if (event.category == RawEvent::Category::Discrete) {
reactPriority = ReactEventPriority::Discrete;
if (event.category == RawEvent::Category::Continuous) {
reactPriority = ReactEventPriority::Default;
}
if (event.category == RawEvent::Category::Discrete) {
reactPriority = ReactEventPriority::Discrete;
}
}
auto eventLogger = eventLogger_.lock();
@@ -88,6 +88,11 @@ const definitions: FeatureFlagDefinitions = {
description:
'Ensures that JavaScript always has a consistent view of the state of the UI (e.g.: commits done in other threads are not immediately propagated to JS during its execution).',
},
fixMappingOfEventPrioritiesBetweenFabricAndReact: {
defaultValue: false,
description:
'Uses the default event priority instead of the discreet event priority by default when dispatching events from Fabric to React.',
},
fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak: {
defaultValue: false,
description:
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<870e25c844e692bb04ee49fe20cd3baf>>
* @generated SignedSource<<edd8917cdda9c37bbe84d036f62a36ba>>
* @flow strict-local
*/
@@ -51,6 +51,7 @@ export type ReactNativeFeatureFlags = {
enableMicrotasks: Getter<boolean>,
enableSynchronousStateUpdates: Getter<boolean>,
enableUIConsistency: Getter<boolean>,
fixMappingOfEventPrioritiesBetweenFabricAndReact: Getter<boolean>,
fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak: Getter<boolean>,
forceBatchingMountItemsOnAndroid: Getter<boolean>,
fuseboxEnabledDebug: Getter<boolean>,
@@ -150,6 +151,10 @@ export const enableSynchronousStateUpdates: Getter<boolean> = createNativeFlagGe
* Ensures that JavaScript always has a consistent view of the state of the UI (e.g.: commits done in other threads are not immediately propagated to JS during its execution).
*/
export const enableUIConsistency: Getter<boolean> = createNativeFlagGetter('enableUIConsistency', false);
/**
* Uses the default event priority instead of the discreet event priority by default when dispatching events from Fabric to React.
*/
export const fixMappingOfEventPrioritiesBetweenFabricAndReact: Getter<boolean> = createNativeFlagGetter('fixMappingOfEventPrioritiesBetweenFabricAndReact', false);
/**
* Fixes a leak in SurfaceMountingManager.mRemoveDeleteTreeUIFrameCallback
*/
@@ -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<<6922b452333fc62a263bd77d42afbbbe>>
* @generated SignedSource<<6715ba4954b31464c591597c53a2a0de>>
* @flow strict-local
*/
@@ -34,6 +34,7 @@ export interface Spec extends TurboModule {
+enableMicrotasks?: () => boolean;
+enableSynchronousStateUpdates?: () => boolean;
+enableUIConsistency?: () => boolean;
+fixMappingOfEventPrioritiesBetweenFabricAndReact?: () => boolean;
+fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak?: () => boolean;
+forceBatchingMountItemsOnAndroid?: () => boolean;
+fuseboxEnabledDebug?: () => boolean;