mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
c4a6bbc8fd
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/45324 Improve concurrency during startup of bridgeless by concurrently initializing eager native modules and triggering bundle load. Changelog: [Android][Changed] Modules marked with needsEagerInit = true will now be created on the mqt_native thread. Reviewed By: mdvacca Differential Revision: D59465977 fbshipit-source-id: 55cc0f0359bafcf32dc538f4346c6a5d5546f658
594 lines
21 KiB
C++
594 lines
21 KiB
C++
/*
|
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*
|
|
* @generated SignedSource<<23169873ef7f5c07f5c07f59a7440d47>>
|
|
*/
|
|
|
|
/**
|
|
* IMPORTANT: Do NOT modify this file directly.
|
|
*
|
|
* To change the definition of the flags, edit
|
|
* packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js.
|
|
*
|
|
* To regenerate this code, run the following script from the repo root:
|
|
* yarn featureflags-update
|
|
*/
|
|
|
|
#include <react/featureflags/ReactNativeFeatureFlagsDefaults.h>
|
|
#include <sstream>
|
|
#include <stdexcept>
|
|
#include <string>
|
|
#include "ReactNativeFeatureFlags.h"
|
|
|
|
namespace facebook::react {
|
|
|
|
ReactNativeFeatureFlagsAccessor::ReactNativeFeatureFlagsAccessor()
|
|
: currentProvider_(std::make_unique<ReactNativeFeatureFlagsDefaults>()),
|
|
wasOverridden_(false) {}
|
|
|
|
bool ReactNativeFeatureFlagsAccessor::commonTestFlag() {
|
|
auto flagValue = commonTestFlag_.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(0, "commonTestFlag");
|
|
|
|
flagValue = currentProvider_->commonTestFlag();
|
|
commonTestFlag_ = flagValue;
|
|
}
|
|
|
|
return flagValue.value();
|
|
}
|
|
|
|
bool ReactNativeFeatureFlagsAccessor::allowCollapsableChildren() {
|
|
auto flagValue = allowCollapsableChildren_.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(1, "allowCollapsableChildren");
|
|
|
|
flagValue = currentProvider_->allowCollapsableChildren();
|
|
allowCollapsableChildren_ = flagValue;
|
|
}
|
|
|
|
return flagValue.value();
|
|
}
|
|
|
|
bool ReactNativeFeatureFlagsAccessor::allowRecursiveCommitsWithSynchronousMountOnAndroid() {
|
|
auto flagValue = allowRecursiveCommitsWithSynchronousMountOnAndroid_.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(2, "allowRecursiveCommitsWithSynchronousMountOnAndroid");
|
|
|
|
flagValue = currentProvider_->allowRecursiveCommitsWithSynchronousMountOnAndroid();
|
|
allowRecursiveCommitsWithSynchronousMountOnAndroid_ = flagValue;
|
|
}
|
|
|
|
return flagValue.value();
|
|
}
|
|
|
|
bool ReactNativeFeatureFlagsAccessor::batchRenderingUpdatesInEventLoop() {
|
|
auto flagValue = batchRenderingUpdatesInEventLoop_.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(3, "batchRenderingUpdatesInEventLoop");
|
|
|
|
flagValue = currentProvider_->batchRenderingUpdatesInEventLoop();
|
|
batchRenderingUpdatesInEventLoop_ = flagValue;
|
|
}
|
|
|
|
return flagValue.value();
|
|
}
|
|
|
|
bool ReactNativeFeatureFlagsAccessor::destroyFabricSurfacesInReactInstanceManager() {
|
|
auto flagValue = destroyFabricSurfacesInReactInstanceManager_.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(4, "destroyFabricSurfacesInReactInstanceManager");
|
|
|
|
flagValue = currentProvider_->destroyFabricSurfacesInReactInstanceManager();
|
|
destroyFabricSurfacesInReactInstanceManager_ = flagValue;
|
|
}
|
|
|
|
return flagValue.value();
|
|
}
|
|
|
|
bool ReactNativeFeatureFlagsAccessor::enableAlignItemsBaselineOnFabricIOS() {
|
|
auto flagValue = enableAlignItemsBaselineOnFabricIOS_.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(5, "enableAlignItemsBaselineOnFabricIOS");
|
|
|
|
flagValue = currentProvider_->enableAlignItemsBaselineOnFabricIOS();
|
|
enableAlignItemsBaselineOnFabricIOS_ = flagValue;
|
|
}
|
|
|
|
return flagValue.value();
|
|
}
|
|
|
|
bool ReactNativeFeatureFlagsAccessor::enableCleanTextInputYogaNode() {
|
|
auto flagValue = enableCleanTextInputYogaNode_.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(6, "enableCleanTextInputYogaNode");
|
|
|
|
flagValue = currentProvider_->enableCleanTextInputYogaNode();
|
|
enableCleanTextInputYogaNode_ = flagValue;
|
|
}
|
|
|
|
return flagValue.value();
|
|
}
|
|
|
|
bool ReactNativeFeatureFlagsAccessor::enableGranularShadowTreeStateReconciliation() {
|
|
auto flagValue = enableGranularShadowTreeStateReconciliation_.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(7, "enableGranularShadowTreeStateReconciliation");
|
|
|
|
flagValue = currentProvider_->enableGranularShadowTreeStateReconciliation();
|
|
enableGranularShadowTreeStateReconciliation_ = flagValue;
|
|
}
|
|
|
|
return flagValue.value();
|
|
}
|
|
|
|
bool ReactNativeFeatureFlagsAccessor::enableMicrotasks() {
|
|
auto flagValue = enableMicrotasks_.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(8, "enableMicrotasks");
|
|
|
|
flagValue = currentProvider_->enableMicrotasks();
|
|
enableMicrotasks_ = flagValue;
|
|
}
|
|
|
|
return flagValue.value();
|
|
}
|
|
|
|
bool ReactNativeFeatureFlagsAccessor::enableSynchronousStateUpdates() {
|
|
auto flagValue = enableSynchronousStateUpdates_.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(9, "enableSynchronousStateUpdates");
|
|
|
|
flagValue = currentProvider_->enableSynchronousStateUpdates();
|
|
enableSynchronousStateUpdates_ = flagValue;
|
|
}
|
|
|
|
return flagValue.value();
|
|
}
|
|
|
|
bool ReactNativeFeatureFlagsAccessor::enableUIConsistency() {
|
|
auto flagValue = enableUIConsistency_.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(10, "enableUIConsistency");
|
|
|
|
flagValue = currentProvider_->enableUIConsistency();
|
|
enableUIConsistency_ = flagValue;
|
|
}
|
|
|
|
return flagValue.value();
|
|
}
|
|
|
|
bool ReactNativeFeatureFlagsAccessor::fetchImagesInViewPreallocation() {
|
|
auto flagValue = fetchImagesInViewPreallocation_.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, "fetchImagesInViewPreallocation");
|
|
|
|
flagValue = currentProvider_->fetchImagesInViewPreallocation();
|
|
fetchImagesInViewPreallocation_ = flagValue;
|
|
}
|
|
|
|
return flagValue.value();
|
|
}
|
|
|
|
bool ReactNativeFeatureFlagsAccessor::fixIncorrectScrollViewStateUpdateOnAndroid() {
|
|
auto flagValue = fixIncorrectScrollViewStateUpdateOnAndroid_.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, "fixIncorrectScrollViewStateUpdateOnAndroid");
|
|
|
|
flagValue = currentProvider_->fixIncorrectScrollViewStateUpdateOnAndroid();
|
|
fixIncorrectScrollViewStateUpdateOnAndroid_ = flagValue;
|
|
}
|
|
|
|
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(13, "fixMappingOfEventPrioritiesBetweenFabricAndReact");
|
|
|
|
flagValue = currentProvider_->fixMappingOfEventPrioritiesBetweenFabricAndReact();
|
|
fixMappingOfEventPrioritiesBetweenFabricAndReact_ = flagValue;
|
|
}
|
|
|
|
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(14, "fixMissedFabricStateUpdatesOnAndroid");
|
|
|
|
flagValue = currentProvider_->fixMissedFabricStateUpdatesOnAndroid();
|
|
fixMissedFabricStateUpdatesOnAndroid_ = flagValue;
|
|
}
|
|
|
|
return flagValue.value();
|
|
}
|
|
|
|
bool ReactNativeFeatureFlagsAccessor::fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak() {
|
|
auto flagValue = fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak_.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, "fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak");
|
|
|
|
flagValue = currentProvider_->fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak();
|
|
fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak_ = flagValue;
|
|
}
|
|
|
|
return flagValue.value();
|
|
}
|
|
|
|
bool ReactNativeFeatureFlagsAccessor::forceBatchingMountItemsOnAndroid() {
|
|
auto flagValue = forceBatchingMountItemsOnAndroid_.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(16, "forceBatchingMountItemsOnAndroid");
|
|
|
|
flagValue = currentProvider_->forceBatchingMountItemsOnAndroid();
|
|
forceBatchingMountItemsOnAndroid_ = flagValue;
|
|
}
|
|
|
|
return flagValue.value();
|
|
}
|
|
|
|
bool ReactNativeFeatureFlagsAccessor::fuseboxEnabledDebug() {
|
|
auto flagValue = fuseboxEnabledDebug_.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(17, "fuseboxEnabledDebug");
|
|
|
|
flagValue = currentProvider_->fuseboxEnabledDebug();
|
|
fuseboxEnabledDebug_ = flagValue;
|
|
}
|
|
|
|
return flagValue.value();
|
|
}
|
|
|
|
bool ReactNativeFeatureFlagsAccessor::fuseboxEnabledRelease() {
|
|
auto flagValue = fuseboxEnabledRelease_.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(18, "fuseboxEnabledRelease");
|
|
|
|
flagValue = currentProvider_->fuseboxEnabledRelease();
|
|
fuseboxEnabledRelease_ = flagValue;
|
|
}
|
|
|
|
return flagValue.value();
|
|
}
|
|
|
|
bool ReactNativeFeatureFlagsAccessor::initEagerTurboModulesOnNativeModulesQueueAndroid() {
|
|
auto flagValue = initEagerTurboModulesOnNativeModulesQueueAndroid_.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(19, "initEagerTurboModulesOnNativeModulesQueueAndroid");
|
|
|
|
flagValue = currentProvider_->initEagerTurboModulesOnNativeModulesQueueAndroid();
|
|
initEagerTurboModulesOnNativeModulesQueueAndroid_ = flagValue;
|
|
}
|
|
|
|
return flagValue.value();
|
|
}
|
|
|
|
bool ReactNativeFeatureFlagsAccessor::lazyAnimationCallbacks() {
|
|
auto flagValue = lazyAnimationCallbacks_.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(20, "lazyAnimationCallbacks");
|
|
|
|
flagValue = currentProvider_->lazyAnimationCallbacks();
|
|
lazyAnimationCallbacks_ = flagValue;
|
|
}
|
|
|
|
return flagValue.value();
|
|
}
|
|
|
|
bool ReactNativeFeatureFlagsAccessor::setAndroidLayoutDirection() {
|
|
auto flagValue = setAndroidLayoutDirection_.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(21, "setAndroidLayoutDirection");
|
|
|
|
flagValue = currentProvider_->setAndroidLayoutDirection();
|
|
setAndroidLayoutDirection_ = flagValue;
|
|
}
|
|
|
|
return flagValue.value();
|
|
}
|
|
|
|
bool ReactNativeFeatureFlagsAccessor::useImmediateExecutorInAndroidBridgeless() {
|
|
auto flagValue = useImmediateExecutorInAndroidBridgeless_.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, "useImmediateExecutorInAndroidBridgeless");
|
|
|
|
flagValue = currentProvider_->useImmediateExecutorInAndroidBridgeless();
|
|
useImmediateExecutorInAndroidBridgeless_ = flagValue;
|
|
}
|
|
|
|
return flagValue.value();
|
|
}
|
|
|
|
bool ReactNativeFeatureFlagsAccessor::useModernRuntimeScheduler() {
|
|
auto flagValue = useModernRuntimeScheduler_.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(23, "useModernRuntimeScheduler");
|
|
|
|
flagValue = currentProvider_->useModernRuntimeScheduler();
|
|
useModernRuntimeScheduler_ = flagValue;
|
|
}
|
|
|
|
return flagValue.value();
|
|
}
|
|
|
|
bool ReactNativeFeatureFlagsAccessor::useNativeViewConfigsInBridgelessMode() {
|
|
auto flagValue = useNativeViewConfigsInBridgelessMode_.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(24, "useNativeViewConfigsInBridgelessMode");
|
|
|
|
flagValue = currentProvider_->useNativeViewConfigsInBridgelessMode();
|
|
useNativeViewConfigsInBridgelessMode_ = flagValue;
|
|
}
|
|
|
|
return flagValue.value();
|
|
}
|
|
|
|
bool ReactNativeFeatureFlagsAccessor::useNewReactImageViewBackgroundDrawing() {
|
|
auto flagValue = useNewReactImageViewBackgroundDrawing_.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(25, "useNewReactImageViewBackgroundDrawing");
|
|
|
|
flagValue = currentProvider_->useNewReactImageViewBackgroundDrawing();
|
|
useNewReactImageViewBackgroundDrawing_ = flagValue;
|
|
}
|
|
|
|
return flagValue.value();
|
|
}
|
|
|
|
bool ReactNativeFeatureFlagsAccessor::useRuntimeShadowNodeReferenceUpdate() {
|
|
auto flagValue = useRuntimeShadowNodeReferenceUpdate_.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(26, "useRuntimeShadowNodeReferenceUpdate");
|
|
|
|
flagValue = currentProvider_->useRuntimeShadowNodeReferenceUpdate();
|
|
useRuntimeShadowNodeReferenceUpdate_ = flagValue;
|
|
}
|
|
|
|
return flagValue.value();
|
|
}
|
|
|
|
bool ReactNativeFeatureFlagsAccessor::useRuntimeShadowNodeReferenceUpdateOnLayout() {
|
|
auto flagValue = useRuntimeShadowNodeReferenceUpdateOnLayout_.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(27, "useRuntimeShadowNodeReferenceUpdateOnLayout");
|
|
|
|
flagValue = currentProvider_->useRuntimeShadowNodeReferenceUpdateOnLayout();
|
|
useRuntimeShadowNodeReferenceUpdateOnLayout_ = flagValue;
|
|
}
|
|
|
|
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(28, "useStateAlignmentMechanism");
|
|
|
|
flagValue = currentProvider_->useStateAlignmentMechanism();
|
|
useStateAlignmentMechanism_ = flagValue;
|
|
}
|
|
|
|
return flagValue.value();
|
|
}
|
|
|
|
void ReactNativeFeatureFlagsAccessor::override(
|
|
std::unique_ptr<ReactNativeFeatureFlagsProvider> provider) {
|
|
if (wasOverridden_) {
|
|
throw std::runtime_error(
|
|
"Feature flags cannot be overridden more than once");
|
|
}
|
|
|
|
ensureFlagsNotAccessed();
|
|
wasOverridden_ = true;
|
|
currentProvider_ = std::move(provider);
|
|
}
|
|
|
|
void ReactNativeFeatureFlagsAccessor::markFlagAsAccessed(
|
|
int position,
|
|
const char* flagName) {
|
|
accessedFeatureFlags_[position] = flagName;
|
|
}
|
|
|
|
void ReactNativeFeatureFlagsAccessor::ensureFlagsNotAccessed() {
|
|
std::ostringstream featureFlagListBuilder;
|
|
for (const auto& featureFlagName : accessedFeatureFlags_) {
|
|
if (featureFlagName != nullptr) {
|
|
featureFlagListBuilder << featureFlagName << ", ";
|
|
}
|
|
}
|
|
|
|
std::string accessedFeatureFlagNames = featureFlagListBuilder.str();
|
|
if (!accessedFeatureFlagNames.empty()) {
|
|
accessedFeatureFlagNames =
|
|
accessedFeatureFlagNames.substr(0, accessedFeatureFlagNames.size() - 2);
|
|
}
|
|
|
|
if (!accessedFeatureFlagNames.empty()) {
|
|
throw std::runtime_error(
|
|
"Feature flags were accessed before being overridden: " +
|
|
accessedFeatureFlagNames);
|
|
}
|
|
}
|
|
|
|
} // namespace facebook::react
|