move to unified feature flag system for new state reconciliation algorithm (#44022)

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

changelog: [internal]

move the new state reconciliation algorithm to the unified feature flag system.

Reviewed By: rubennorte

Differential Revision: D55965530

fbshipit-source-id: 3edde0858a670e86dc2d1cb561f03f584ff21896
This commit is contained in:
Samuel Susla
2024-04-12 02:47:01 -07:00
committed by Facebook GitHub Bot
parent 4d9b11b45d
commit 2ef59c988d
27 changed files with 148 additions and 36 deletions
@@ -264,10 +264,6 @@ static BackgroundExecutor RCTGetBackgroundExecutor()
CoreFeatures::enableGranularScrollViewStateUpdatesIOS = true;
}
if (reactNativeConfig && reactNativeConfig->getBool("react_fabric:enable_cloneless_state_progression")) {
CoreFeatures::enableClonelessStateProgression = true;
}
auto componentRegistryFactory =
[factory = wrapManagedObject(_mountingManager.componentViewRegistry.componentViewFactory)](
const EventDispatcher::Weak &eventDispatcher, const ContextContainer::Shared &contextContainer) {
@@ -1962,7 +1962,6 @@ public class com/facebook/react/config/ReactFeatureFlags {
public static field dispatchPointerEvents Z
public static field enableBridgelessArchitecture Z
public static field enableBridgelessArchitectureNewCreateReloadDestroy Z
public static field enableClonelessStateProgression Z
public static field enableCppPropsIteratorSetter Z
public static field enableEagerRootViewAttachment Z
public static field enableFabricLogs Z
@@ -101,9 +101,6 @@ public class ReactFeatureFlags {
*/
public static boolean enableRemoveDeleteTreeInstruction = false;
/** When enabled, Fabric will avoid cloning notes to perform state progression. */
public static boolean enableClonelessStateProgression = false;
/** When enabled, rawProps in Props will not include Yoga specific props. */
public static boolean excludeYogaFromRawProps = 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<<a9793334f77cea07b88a74103da09f72>>
* @generated SignedSource<<7c2d825e15fc7e442034a598eebb6e25>>
*/
/**
@@ -118,6 +118,12 @@ public object ReactNativeFeatureFlags {
@JvmStatic
public fun useNativeViewConfigsInBridgelessMode(): Boolean = accessor.useNativeViewConfigsInBridgelessMode()
/**
* When enabled, it uses optimised state reconciliation algorithm.
*/
@JvmStatic
public fun useStateAlignmentMechanism(): Boolean = accessor.useStateAlignmentMechanism()
/**
* Overrides the feature flags with the ones provided by the given provider
* (generally one that extends `ReactNativeFeatureFlagsDefaults`).
@@ -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<<51d66e841a09638375b1849043c9886a>>
* @generated SignedSource<<eb3ae68166b3ec7f797a0db4b2ec1f5b>>
*/
/**
@@ -35,6 +35,7 @@ public class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAccesso
private var inspectorEnableModernCDPRegistryCache: Boolean? = null
private var useModernRuntimeSchedulerCache: Boolean? = null
private var useNativeViewConfigsInBridgelessModeCache: Boolean? = null
private var useStateAlignmentMechanismCache: Boolean? = null
override fun commonTestFlag(): Boolean {
var cached = commonTestFlagCache
@@ -171,6 +172,15 @@ public class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAccesso
return cached
}
override fun useStateAlignmentMechanism(): Boolean {
var cached = useStateAlignmentMechanismCache
if (cached == null) {
cached = ReactNativeFeatureFlagsCxxInterop.useStateAlignmentMechanism()
useStateAlignmentMechanismCache = cached
}
return cached
}
override fun override(provider: ReactNativeFeatureFlagsProvider): Unit =
ReactNativeFeatureFlagsCxxInterop.override(provider as Any)
@@ -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<<4422f7984f27638cc2fb18230a6d042e>>
* @generated SignedSource<<0b1377acc1a7a2bed8bd6448a54ec91a>>
*/
/**
@@ -58,6 +58,8 @@ public object ReactNativeFeatureFlagsCxxInterop {
@DoNotStrip @JvmStatic public external fun useNativeViewConfigsInBridgelessMode(): Boolean
@DoNotStrip @JvmStatic public external fun useStateAlignmentMechanism(): Boolean
@DoNotStrip @JvmStatic public external fun override(provider: Any)
@DoNotStrip @JvmStatic public external fun dangerouslyReset()
@@ -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<<acf4e79f18c3b33bcca452a99265dfcf>>
* @generated SignedSource<<545ef5d7c16c2d6599f15a747c53cf3f>>
*/
/**
@@ -52,4 +52,6 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi
override fun useModernRuntimeScheduler(): Boolean = false
override fun useNativeViewConfigsInBridgelessMode(): Boolean = false
override fun useStateAlignmentMechanism(): 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<<46793ec55ed15661090a9b9998806bcc>>
* @generated SignedSource<<aa359470a22488b45abfa18b0edadb18>>
*/
/**
@@ -39,6 +39,7 @@ public class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcces
private var inspectorEnableModernCDPRegistryCache: Boolean? = null
private var useModernRuntimeSchedulerCache: Boolean? = null
private var useNativeViewConfigsInBridgelessModeCache: Boolean? = null
private var useStateAlignmentMechanismCache: Boolean? = null
override fun commonTestFlag(): Boolean {
var cached = commonTestFlagCache
@@ -190,6 +191,16 @@ public class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcces
return cached
}
override fun useStateAlignmentMechanism(): Boolean {
var cached = useStateAlignmentMechanismCache
if (cached == null) {
cached = currentProvider.useStateAlignmentMechanism()
accessedFeatureFlags.add("useStateAlignmentMechanism")
useStateAlignmentMechanismCache = cached
}
return cached
}
override fun override(provider: ReactNativeFeatureFlagsProvider) {
if (accessedFeatureFlags.isNotEmpty()) {
val accessedFeatureFlagsStr = accessedFeatureFlags.joinToString(separator = ", ") { it }
@@ -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<<dd6d7b39eb1dc066dd6801b22846e431>>
* @generated SignedSource<<e2eef1313051abddc31e4a3340e72c1c>>
*/
/**
@@ -52,4 +52,6 @@ public interface ReactNativeFeatureFlagsProvider {
@DoNotStrip public fun useModernRuntimeScheduler(): Boolean
@DoNotStrip public fun useNativeViewConfigsInBridgelessMode(): Boolean
@DoNotStrip public fun useStateAlignmentMechanism(): Boolean
}
@@ -406,8 +406,6 @@ void Binding::installFabricUIManager(
CoreFeatures::enablePropIteratorSetter =
getFeatureFlagValue("enableCppPropsIteratorSetter");
CoreFeatures::enableClonelessStateProgression =
getFeatureFlagValue("enableClonelessStateProgression");
CoreFeatures::excludeYogaFromRawProps =
getFeatureFlagValue("excludeYogaFromRawProps");
@@ -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<<3a7d633de9e6fd6862864c202d56523a>>
* @generated SignedSource<<82163a04d1e3cb54d6c5125173ab807f>>
*/
/**
@@ -129,6 +129,12 @@ class ReactNativeFeatureFlagsProviderHolder
return method(javaProvider_);
}
bool useStateAlignmentMechanism() override {
static const auto method =
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("useStateAlignmentMechanism");
return method(javaProvider_);
}
private:
jni::global_ref<jobject> javaProvider_;
};
@@ -208,6 +214,11 @@ bool JReactNativeFeatureFlagsCxxInterop::useNativeViewConfigsInBridgelessMode(
return ReactNativeFeatureFlags::useNativeViewConfigsInBridgelessMode();
}
bool JReactNativeFeatureFlagsCxxInterop::useStateAlignmentMechanism(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
return ReactNativeFeatureFlags::useStateAlignmentMechanism();
}
void JReactNativeFeatureFlagsCxxInterop::override(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/,
jni::alias_ref<jobject> provider) {
@@ -270,6 +281,9 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() {
makeNativeMethod(
"useNativeViewConfigsInBridgelessMode",
JReactNativeFeatureFlagsCxxInterop::useNativeViewConfigsInBridgelessMode),
makeNativeMethod(
"useStateAlignmentMechanism",
JReactNativeFeatureFlagsCxxInterop::useStateAlignmentMechanism),
});
}
@@ -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<<7237412cb02dad9468f144a050bd78e3>>
* @generated SignedSource<<48e337d37416ab988ea747050bf207f3>>
*/
/**
@@ -75,6 +75,9 @@ class JReactNativeFeatureFlagsCxxInterop
static bool useNativeViewConfigsInBridgelessMode(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
static bool useStateAlignmentMechanism(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
static void override(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>,
jni::alias_ref<jobject> provider);
@@ -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<<e589683db0f9a9fbf812fefd4a1c3f96>>
* @generated SignedSource<<ddb65722ccc0d584d105b07a621e6871>>
*/
/**
@@ -81,6 +81,10 @@ bool ReactNativeFeatureFlags::useNativeViewConfigsInBridgelessMode() {
return getAccessor().useNativeViewConfigsInBridgelessMode();
}
bool ReactNativeFeatureFlags::useStateAlignmentMechanism() {
return getAccessor().useStateAlignmentMechanism();
}
void ReactNativeFeatureFlags::override(
std::unique_ptr<ReactNativeFeatureFlagsProvider> provider) {
getAccessor().override(std::move(provider));
@@ -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<<38881afec04f45eff46edd99ce9443da>>
* @generated SignedSource<<8804fc52ad516ba82c0db6fcdea5f110>>
*/
/**
@@ -112,6 +112,11 @@ class ReactNativeFeatureFlags {
*/
RN_EXPORT static bool useNativeViewConfigsInBridgelessMode();
/**
* When enabled, it uses optimised state reconciliation algorithm.
*/
RN_EXPORT static bool useStateAlignmentMechanism();
/**
* Overrides the feature flags with the ones provided by the given provider
* (generally one that extends `ReactNativeFeatureFlagsDefaults`).
@@ -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<<21980ab4688bc93c5573012a228e3997>>
* @generated SignedSource<<9f5c5313e139b450449e2716735c26e7>>
*/
/**
@@ -299,6 +299,24 @@ bool ReactNativeFeatureFlagsAccessor::useNativeViewConfigsInBridgelessMode() {
return flagValue.value();
}
bool ReactNativeFeatureFlagsAccessor::useStateAlignmentMechanism() {
auto flagValue = useStateAlignmentMechanism_.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(15, "useStateAlignmentMechanism");
flagValue = currentProvider_->useStateAlignmentMechanism();
useStateAlignmentMechanism_ = flagValue;
}
return flagValue.value();
}
void ReactNativeFeatureFlagsAccessor::override(
std::unique_ptr<ReactNativeFeatureFlagsProvider> provider) {
if (wasOverridden_) {
@@ -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<<fe45466cd2b60fe856aa811ccc2365bd>>
* @generated SignedSource<<de8d2a8416c3ad914df01b765c8df907>>
*/
/**
@@ -46,6 +46,7 @@ class ReactNativeFeatureFlagsAccessor {
bool inspectorEnableModernCDPRegistry();
bool useModernRuntimeScheduler();
bool useNativeViewConfigsInBridgelessMode();
bool useStateAlignmentMechanism();
void override(std::unique_ptr<ReactNativeFeatureFlagsProvider> provider);
@@ -56,7 +57,7 @@ class ReactNativeFeatureFlagsAccessor {
std::unique_ptr<ReactNativeFeatureFlagsProvider> currentProvider_;
bool wasOverridden_;
std::array<std::atomic<const char*>, 15> accessedFeatureFlags_;
std::array<std::atomic<const char*>, 16> accessedFeatureFlags_;
std::atomic<std::optional<bool>> commonTestFlag_;
std::atomic<std::optional<bool>> batchRenderingUpdatesInEventLoop_;
@@ -73,6 +74,7 @@ class ReactNativeFeatureFlagsAccessor {
std::atomic<std::optional<bool>> inspectorEnableModernCDPRegistry_;
std::atomic<std::optional<bool>> useModernRuntimeScheduler_;
std::atomic<std::optional<bool>> useNativeViewConfigsInBridgelessMode_;
std::atomic<std::optional<bool>> useStateAlignmentMechanism_;
};
} // namespace facebook::react
@@ -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<<72058f22fd21f03e66136929306d5974>>
* @generated SignedSource<<008818e7f2d8b9e295704cccc33758e7>>
*/
/**
@@ -86,6 +86,10 @@ class ReactNativeFeatureFlagsDefaults : public ReactNativeFeatureFlagsProvider {
bool useNativeViewConfigsInBridgelessMode() override {
return false;
}
bool useStateAlignmentMechanism() override {
return false;
}
};
} // namespace facebook::react
@@ -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<<21fb3f2ea9db49ea4710a13807c7512a>>
* @generated SignedSource<<270291da73cb3e4eddc7bd5cdc9a9470>>
*/
/**
@@ -40,6 +40,7 @@ class ReactNativeFeatureFlagsProvider {
virtual bool inspectorEnableModernCDPRegistry() = 0;
virtual bool useModernRuntimeScheduler() = 0;
virtual bool useNativeViewConfigsInBridgelessMode() = 0;
virtual bool useStateAlignmentMechanism() = 0;
};
} // namespace facebook::react
@@ -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<<55ee96b1902071c987c70b5f07f670e4>>
* @generated SignedSource<<1abf19f9d1352105511e86c0f217de7a>>
*/
/**
@@ -112,4 +112,9 @@ bool NativeReactNativeFeatureFlags::useNativeViewConfigsInBridgelessMode(
return ReactNativeFeatureFlags::useNativeViewConfigsInBridgelessMode();
}
bool NativeReactNativeFeatureFlags::useStateAlignmentMechanism(
jsi::Runtime& /*runtime*/) {
return ReactNativeFeatureFlags::useStateAlignmentMechanism();
}
} // namespace facebook::react
@@ -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<<f8f1ff1a05b772b861856d027659848a>>
* @generated SignedSource<<7a2a41f80549322a7f4255d193dc0b7b>>
*/
/**
@@ -64,6 +64,8 @@ class NativeReactNativeFeatureFlags
bool useModernRuntimeScheduler(jsi::Runtime& runtime);
bool useNativeViewConfigsInBridgelessMode(jsi::Runtime& runtime);
bool useStateAlignmentMechanism(jsi::Runtime& runtime);
};
} // namespace facebook::react
@@ -8,6 +8,7 @@
#include "ShadowTree.h"
#include <react/debug/react_native_assert.h>
#include <react/featureflags/ReactNativeFeatureFlags.h>
#include <react/renderer/components/root/RootComponentDescriptor.h>
#include <react/renderer/components/view/ViewShadowNode.h>
#include <react/renderer/core/LayoutContext.h>
@@ -453,7 +454,7 @@ CommitStatus ShadowTree::tryCommit(
}
if (commitOptions.enableStateReconciliation) {
if (CoreFeatures::enableClonelessStateProgression) {
if (ReactNativeFeatureFlags::useStateAlignmentMechanism()) {
progressStateIfNecessary(*newRootShadowNode, *oldRootShadowNode);
} else {
auto updatedNewRootShadowNode =
@@ -9,6 +9,8 @@
#include <gtest/gtest.h>
#include <react/featureflags/ReactNativeFeatureFlags.h>
#include <react/featureflags/ReactNativeFeatureFlagsDefaults.h>
#include <react/renderer/componentregistry/ComponentDescriptorProviderRegistry.h>
#include <react/renderer/components/view/ViewComponentDescriptor.h>
#include <react/renderer/core/PropsParserContext.h>
@@ -22,6 +24,20 @@
using namespace facebook::react;
class StateReconciliationTestFeatureFlags
: public ReactNativeFeatureFlagsDefaults {
public:
explicit StateReconciliationTestFeatureFlags(bool useStateAlignmentMechanism)
: useStateAlignmentMechanism_(useStateAlignmentMechanism) {}
bool useStateAlignmentMechanism() override {
return useStateAlignmentMechanism_;
}
private:
bool useStateAlignmentMechanism_;
};
class DummyShadowTreeDelegate : public ShadowTreeDelegate {
public:
RootShadowNode::Unshared shadowTreeWillCommit(
@@ -64,8 +80,15 @@ const ShadowNode* findDescendantNode(
class StateReconciliationTest : public ::testing::TestWithParam<bool> {
public:
StateReconciliationTest() : builder_(simpleComponentBuilder()) {
CoreFeatures::enableClonelessStateProgression = GetParam();
StateReconciliationTest() : builder_(simpleComponentBuilder()) {}
void SetUp() override {
ReactNativeFeatureFlags::override(
std::make_unique<StateReconciliationTestFeatureFlags>(GetParam()));
}
void TearDown() override {
ReactNativeFeatureFlags::dangerouslyReset();
}
ComponentBuilder builder_;
@@ -12,7 +12,6 @@ namespace facebook::react {
bool CoreFeatures::enablePropIteratorSetter = false;
bool CoreFeatures::enableGranularScrollViewStateUpdatesIOS = false;
bool CoreFeatures::enableGranularShadowTreeStateReconciliation = false;
bool CoreFeatures::enableClonelessStateProgression = false;
bool CoreFeatures::excludeYogaFromRawProps = false;
bool CoreFeatures::enableReportEventPaintTime = false;
@@ -27,9 +27,6 @@ class CoreFeatures {
// state and the last commit that updated state changed before committing.
static bool enableGranularShadowTreeStateReconciliation;
// When enabled, Fabric will avoid cloning notes to perform state progression.
static bool enableClonelessStateProgression;
// When enabled, rawProps in Props will not include Yoga specific props.
static bool excludeYogaFromRawProps;
@@ -101,6 +101,11 @@ const definitions: FeatureFlagDefinitions = {
description:
'When enabled, the native view configs are used in bridgeless mode.',
},
useStateAlignmentMechanism: {
defaultValue: false,
description:
'When enabled, it uses optimised state reconciliation algorithm.',
},
},
jsOnly: {
@@ -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<<45969617730126d45f35820ee3bd5853>>
* @generated SignedSource<<39fd96ed670e0acae857e7fce3377452>>
* @flow strict-local
*/
@@ -55,6 +55,7 @@ export type ReactNativeFeatureFlags = {
inspectorEnableModernCDPRegistry: Getter<boolean>,
useModernRuntimeScheduler: Getter<boolean>,
useNativeViewConfigsInBridgelessMode: Getter<boolean>,
useStateAlignmentMechanism: Getter<boolean>,
}
/**
@@ -157,6 +158,10 @@ export const useModernRuntimeScheduler: Getter<boolean> = createNativeFlagGetter
* When enabled, the native view configs are used in bridgeless mode.
*/
export const useNativeViewConfigsInBridgelessMode: Getter<boolean> = createNativeFlagGetter('useNativeViewConfigsInBridgelessMode', false);
/**
* When enabled, it uses optimised state reconciliation algorithm.
*/
export const useStateAlignmentMechanism: Getter<boolean> = createNativeFlagGetter('useStateAlignmentMechanism', false);
/**
* Overrides the feature flags with the provided methods.
@@ -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<<22dd9936df00ce7a53a5aa4a2c331279>>
* @generated SignedSource<<99ddb55dadff7adfb02c105984d47cbf>>
* @flow strict-local
*/
@@ -38,6 +38,7 @@ export interface Spec extends TurboModule {
+inspectorEnableModernCDPRegistry?: () => boolean;
+useModernRuntimeScheduler?: () => boolean;
+useNativeViewConfigsInBridgelessMode?: () => boolean;
+useStateAlignmentMechanism?: () => boolean;
}
const NativeReactNativeFeatureFlags: ?Spec = TurboModuleRegistry.get<Spec>(