diff --git a/packages/react-native/Libraries/Settings/RCTSettingsManager.mm b/packages/react-native/Libraries/Settings/RCTSettingsManager.mm index af0bd521f02e..95308a9713d9 100644 --- a/packages/react-native/Libraries/Settings/RCTSettingsManager.mm +++ b/packages/react-native/Libraries/Settings/RCTSettingsManager.mm @@ -11,16 +11,24 @@ #import #import #import +#import #import +#include +#include + #import "RCTSettingsPlugins.h" -@interface RCTSettingsManager () +@interface RCTSettingsManager () @end @implementation RCTSettingsManager { - BOOL _ignoringUpdates; + std::atomic _ignoringUpdates; + std::atomic _updateScheduled; + std::atomic _invalidated; + bool _useAsyncUpdates; NSUserDefaults *_defaults; + dispatch_queue_t _methodQueue; } @synthesize moduleRegistry = _moduleRegistry; @@ -40,7 +48,14 @@ - (instancetype)init - (instancetype)initWithUserDefaults:(NSUserDefaults *)defaults { if ((self = [super init]) != nullptr) { + _ignoringUpdates = false; + _updateScheduled = false; + _invalidated = false; _defaults = defaults; + _useAsyncUpdates = facebook::react::ReactNativeFeatureFlags::enableAsyncSettingsManagerUpdatesIOS(); + if (_useAsyncUpdates) { + _methodQueue = dispatch_queue_create("com.facebook.react.SettingsManager", DISPATCH_QUEUE_SERIAL); + } [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(userDefaultsDidChange:) @@ -61,18 +76,71 @@ - (instancetype)initWithUserDefaults:(NSUserDefaults *)defaults {.settings = RCTJSONClean([_defaults dictionaryRepresentation])}); } +- (dispatch_queue_t)methodQueue +{ + return _methodQueue; +} + +- (BOOL)respondsToSelector:(SEL)selector +{ + if (selector == @selector(invalidate) && !_useAsyncUpdates) { + return NO; + } + return [super respondsToSelector:selector]; +} + +- (void)invalidate +{ + if (!_useAsyncUpdates) { + return; + } + _invalidated = true; + [[NSNotificationCenter defaultCenter] removeObserver:self name:NSUserDefaultsDidChangeNotification object:_defaults]; +} + - (void)userDefaultsDidChange:(NSNotification *)note { if (_ignoringUpdates) { return; } + if (!_useAsyncUpdates) { + NSDictionary *settings = RCTJSONClean([_defaults dictionaryRepresentation]); +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + [[_moduleRegistry moduleForName:"EventDispatcher"] sendDeviceEventWithName:@"settingsUpdated" body:settings]; +#pragma clang diagnostic pop + return; + } + + if (_invalidated || _updateScheduled.exchange(true)) { + return; + } + + __weak RCTSettingsManager *weakSelf = self; + dispatch_async(_methodQueue, ^{ + RCTSettingsManager *strongSelf = weakSelf; + if (strongSelf == nil) { + return; + } + + // Clear before reading so a notification during the snapshot schedules a trailing update. + strongSelf->_updateScheduled = false; + if (strongSelf->_invalidated) { + return; + } + + NSDictionary *settings = RCTJSONClean([strongSelf->_defaults dictionaryRepresentation]); + if (strongSelf->_invalidated) { + return; + } + #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" - [[_moduleRegistry moduleForName:"EventDispatcher"] - sendDeviceEventWithName:@"settingsUpdated" - body:RCTJSONClean([_defaults dictionaryRepresentation])]; + [[strongSelf->_moduleRegistry moduleForName:"EventDispatcher"] sendDeviceEventWithName:@"settingsUpdated" + body:settings]; #pragma clang diagnostic pop + }); } /** diff --git a/packages/react-native/React/Tests/Settings/RCTSettingsManagerTests.mm b/packages/react-native/React/Tests/Settings/RCTSettingsManagerTests.mm new file mode 100644 index 000000000000..a74861367663 --- /dev/null +++ b/packages/react-native/React/Tests/Settings/RCTSettingsManagerTests.mm @@ -0,0 +1,454 @@ +/* + * 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. + */ + +#import +#import +#import +#import +#import + +#include +#include +#include + +@interface RCTSettingsManager () +@end + +@interface RCTSettingsTestDefaults : NSUserDefaults +@property (nonatomic, strong) NSMutableDictionary *values; +@property (atomic, assign) BOOL readOnMainThread; +@property (atomic, assign) NSTimeInterval snapshotDelay; +@property (atomic, assign) NSUInteger snapshotCount; +@property (nonatomic, copy) void (^onSnapshot)(NSDictionary *); +@end + +@implementation RCTSettingsTestDefaults + +- (instancetype)init +{ + if ((self = [super init])) { + _values = [NSMutableDictionary new]; + } + return self; +} + +- (NSDictionary *)dictionaryRepresentation +{ + self.readOnMainThread = [NSThread isMainThread]; + [NSThread sleepForTimeInterval:self.snapshotDelay]; + NSDictionary *snapshot; + @synchronized(self) { + self.snapshotCount++; + snapshot = [self.values copy]; + } + if (self.onSnapshot != nil) { + self.onSnapshot(snapshot); + } + return snapshot; +} + +- (void)setObject:(id)value forKey:(NSString *)key +{ + @synchronized(self) { + self.values[key] = value; + } + [[NSNotificationCenter defaultCenter] postNotificationName:NSUserDefaultsDidChangeNotification object:self]; +} + +- (void)removeObjectForKey:(NSString *)key +{ + @synchronized(self) { + [self.values removeObjectForKey:key]; + } + [[NSNotificationCenter defaultCenter] postNotificationName:NSUserDefaultsDidChangeNotification object:self]; +} + +- (BOOL)synchronize +{ + return YES; +} + +@end + +@interface RCTSettingsTestEventDispatcher : NSObject +@property (nonatomic, copy) void (^onEvent)(NSString *, NSDictionary *); +@end + +@implementation RCTSettingsTestEventDispatcher + +- (void)sendDeviceEventWithName:(NSString *)name body:(NSDictionary *)body +{ + self.onEvent(name, body); +} + +@end + +@interface RCTSettingsTestModuleRegistry : RCTModuleRegistry +@property (nonatomic, strong) RCTSettingsTestEventDispatcher *dispatcher; +@end + +@implementation RCTSettingsTestModuleRegistry + +- (id)moduleForName:(const char *)moduleName +{ + return self.dispatcher; +} + +@end + +@interface RCTSettingsManagerTests : XCTestCase +@end + +@implementation RCTSettingsManagerTests { + RCTSettingsTestDefaults *_defaults; + RCTSettingsManager *_manager; + RCTSettingsTestModuleRegistry *_registry; +} + +- (void)setUp +{ + [super setUp]; + class AsyncSettingsFlags : public facebook::react::ReactNativeFeatureFlagsDefaults { + public: + bool enableAsyncSettingsManagerUpdatesIOS() override + { + return true; + } + }; + facebook::react::ReactNativeFeatureFlags::dangerouslyReset(); + facebook::react::ReactNativeFeatureFlags::override(std::make_unique()); + _defaults = [RCTSettingsTestDefaults new]; + _manager = [[RCTSettingsManager alloc] initWithUserDefaults:_defaults]; + _registry = [RCTSettingsTestModuleRegistry new]; + _registry.dispatcher = [RCTSettingsTestEventDispatcher new]; + _manager.moduleRegistry = _registry; + XCTAssertTrue([_manager respondsToSelector:@selector(invalidate)]); +} + +- (void)tearDown +{ + [_manager invalidate]; + if (_manager.methodQueue != nil) { + dispatch_sync( + _manager.methodQueue, + ^{ + }); + } + _manager = nil; + facebook::react::ReactNativeFeatureFlags::dangerouslyReset(); + [super tearDown]; +} + +- (void)useDefaultFeatureFlags +{ + [_manager invalidate]; + _manager = nil; + facebook::react::ReactNativeFeatureFlags::dangerouslyReset(); + _manager = [[RCTSettingsManager alloc] initWithUserDefaults:_defaults]; + _manager.moduleRegistry = _registry; +} + +- (void)testFlagDisabledPreservesSynchronousUpdates +{ + [self useDefaultFeatureFlags]; + XCTAssertFalse(facebook::react::ReactNativeFeatureFlags::enableAsyncSettingsManagerUpdatesIOS()); + _defaults.snapshotDelay = 0.2; + _defaults.values[@"date"] = [NSDate dateWithTimeIntervalSince1970:0]; + __block BOOL delivered = NO; + _registry.dispatcher.onEvent = ^(NSString *name, NSDictionary *body) { + XCTAssertTrue([NSThread isMainThread]); + XCTAssertEqualObjects(name, @"settingsUpdated"); + XCTAssertEqualObjects(body[@"token"], @"new-token"); + XCTAssertEqualObjects(body[@"date"], [NSNull null]); + delivered = YES; + }; + void (^write)(void) = ^{ + NSTimeInterval start = [NSDate timeIntervalSinceReferenceDate]; + [self->_defaults setObject:@"new-token" forKey:@"token"]; + XCTAssertTrue(delivered); + XCTAssertGreaterThanOrEqual([NSDate timeIntervalSinceReferenceDate] - start, 0.15); + }; + if ([NSThread isMainThread]) { + write(); + } else { + dispatch_sync(dispatch_get_main_queue(), write); + } + XCTAssertTrue(_defaults.readOnMainThread); + XCTAssertEqual(_defaults.snapshotCount, 1u); +} + +- (void)testFlagDisabledPreservesEveryIntermediateUpdate +{ + [self useDefaultFeatureFlags]; + NSMutableArray *updates = [NSMutableArray new]; + _registry.dispatcher.onEvent = ^(NSString *name, NSDictionary *body) { + [updates addObject:body[@"external"] ?: [NSNull null]]; + }; + [_defaults setObject:@"A" forKey:@"external"]; + [_defaults setObject:@"B" forKey:@"external"]; + [_defaults setObject:@"A" forKey:@"external"]; + XCTAssertEqualObjects(updates, (@[ @"A", @"B", @"A" ])); + XCTAssertEqual(_defaults.snapshotCount, 3u); +} + +- (void)testFlagDisabledPreservesDefaultMethodQueue +{ + [self useDefaultFeatureFlags]; + XCTAssertFalse([_manager respondsToSelector:@selector(invalidate)]); + XCTAssertNil(_manager.methodQueue); + dispatch_queue_t queue = dispatch_queue_create("com.facebook.react.SettingsManagerTests", DISPATCH_QUEUE_SERIAL); + [_manager setValue:queue forKey:@"methodQueue"]; + XCTAssertEqual(_manager.methodQueue, queue); +} + +- (void)testFlagDisabledDoesNotEchoJavaScriptWrites +{ + [self useDefaultFeatureFlags]; + __block NSUInteger eventCount = 0; + _registry.dispatcher.onEvent = ^(NSString *name, NSDictionary *body) { + eventCount++; + }; + [_manager setValues:@{@"local" : @"value"}]; + XCTAssertEqualObjects(_defaults.values[@"local"], @"value"); + [_manager deleteValues:@[ @"local" ]]; + XCTAssertNil(_defaults.values[@"local"]); + XCTAssertEqual(eventCount, 0u); + XCTAssertEqual(_defaults.snapshotCount, 0u); +} + +- (void)testFlagDisabledPreservesNotificationsAfterInvalidation +{ + [self useDefaultFeatureFlags]; + __block NSUInteger eventCount = 0; + _registry.dispatcher.onEvent = ^(NSString *name, NSDictionary *body) { + eventCount++; + }; + [_manager invalidate]; + [_defaults setObject:@"value" forKey:@"external"]; + XCTAssertEqual(eventCount, 1u); + XCTAssertEqual(_defaults.snapshotCount, 1u); +} + +- (void)testNotificationDoesNotBlockPostingThread +{ + _defaults.snapshotDelay = 0.2; + XCTestExpectation *event = [self expectationWithDescription:@"settingsUpdated"]; + _registry.dispatcher.onEvent = ^(NSString *name, NSDictionary *body) { + XCTAssertEqualObjects(name, @"settingsUpdated"); + XCTAssertEqualObjects(body[@"token"], @"new-token"); + [event fulfill]; + }; + + __block NSTimeInterval duration; + void (^write)(void) = ^{ + NSTimeInterval start = [NSDate timeIntervalSinceReferenceDate]; + [self->_defaults setObject:@"new-token" forKey:@"token"]; + duration = [NSDate timeIntervalSinceReferenceDate] - start; + }; + if ([NSThread isMainThread]) { + write(); + } else { + dispatch_sync(dispatch_get_main_queue(), write); + } + [self waitForExpectations:@[ event ] timeout:5]; + XCTAssertLessThan(duration, 0.1); + XCTAssertFalse(_defaults.readOnMainThread); +} + +- (void)testLargeNestedSettingsAreCleanedOffMainThread +{ + NSMutableDictionary *entries = [NSMutableDictionary new]; + for (NSUInteger index = 0; index < 5000; index++) { + entries[[NSString stringWithFormat:@"entry-%lu", (unsigned long)index]] = + @{@"nested" : @{@"string" : @"value", @"number" : @42, @"date" : [NSDate dateWithTimeIntervalSince1970:0]}}; + } + _defaults.values[@"config"] = entries; + XCTestExpectation *event = [self expectationWithDescription:@"cleaned settings"]; + _registry.dispatcher.onEvent = ^(NSString *name, NSDictionary *body) { + XCTAssertEqual([body[@"config"] count], 5000u); + XCTAssertEqualObjects(body[@"config"][@"entry-0"][@"nested"][@"date"], [NSNull null]); + XCTAssertEqualObjects(body[@"config"][@"entry-4999"][@"nested"][@"number"], @42); + [event fulfill]; + }; + void (^write)(void) = ^{ + [self->_defaults setObject:@"new-token" forKey:@"token"]; + }; + if ([NSThread isMainThread]) { + write(); + } else { + dispatch_sync(dispatch_get_main_queue(), write); + } + [self waitForExpectations:@[ event ] timeout:5]; + XCTAssertFalse(_defaults.readOnMainThread); +} + +- (void)testJavaScriptWritesDoNotEchoUpdates +{ + XCTestExpectation *event = [self expectationWithDescription:@"no settingsUpdated echo"]; + event.inverted = YES; + _registry.dispatcher.onEvent = ^(NSString *name, NSDictionary *body) { + [event fulfill]; + }; + dispatch_sync(_manager.methodQueue, ^{ + [self->_manager setValues:@{@"local" : @"value"}]; + XCTAssertEqualObjects(self->_defaults.values[@"local"], @"value"); + [self->_manager deleteValues:@[ @"local" ]]; + XCTAssertNil(self->_defaults.values[@"local"]); + }); + XCTAssertEqual(_defaults.snapshotCount, 0u); + [self waitForExpectations:@[ event ] timeout:0.3]; +} + +- (void)testBackgroundNotificationStillDeliversSettings +{ + XCTestExpectation *event = [self expectationWithDescription:@"background settings"]; + _registry.dispatcher.onEvent = ^(NSString *name, NSDictionary *body) { + XCTAssertEqualObjects(body[@"background"], @YES); + [event fulfill]; + }; + dispatch_queue_t queue = dispatch_queue_create("com.facebook.react.SettingsManagerTests", DISPATCH_QUEUE_SERIAL); + dispatch_async(queue, ^{ + [self->_defaults setObject:@YES forKey:@"background"]; + }); + [self waitForExpectations:@[ event ] timeout:5]; +} + +- (void)testMainQueueRemainsResponsiveDuringSnapshot +{ + dispatch_semaphore_t releaseSnapshot = dispatch_semaphore_create(0); + XCTestExpectation *snapshot = [self expectationWithDescription:@"snapshot entered"]; + XCTestExpectation *heartbeat = [self expectationWithDescription:@"main queue heartbeat"]; + XCTestExpectation *event = [self expectationWithDescription:@"settings delivered"]; + _defaults.onSnapshot = ^(NSDictionary *body) { + XCTAssertFalse([NSThread isMainThread]); + [snapshot fulfill]; + XCTAssertEqual(dispatch_semaphore_wait(releaseSnapshot, dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC)), 0); + }; + _registry.dispatcher.onEvent = ^(NSString *name, NSDictionary *body) { + XCTAssertFalse([NSThread isMainThread]); + [event fulfill]; + }; + dispatch_async(dispatch_get_main_queue(), ^{ + [self->_defaults setObject:@"value" forKey:@"external"]; + dispatch_async(dispatch_get_main_queue(), ^{ + [heartbeat fulfill]; + }); + }); + [self waitForExpectations:@[ snapshot, heartbeat ] timeout:3]; + dispatch_semaphore_signal(releaseSnapshot); + [self waitForExpectations:@[ event ] timeout:3]; +} + +- (void)testBurstNotificationsCoalesceToLatestSettings +{ + dispatch_semaphore_t releaseQueue = dispatch_semaphore_create(0); + XCTestExpectation *blocked = [self expectationWithDescription:@"queue blocked"]; + dispatch_async(_manager.methodQueue, ^{ + [blocked fulfill]; + XCTAssertEqual(dispatch_semaphore_wait(releaseQueue, dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC)), 0); + }); + [self waitForExpectations:@[ blocked ] timeout:3]; + + XCTestExpectation *event = [self expectationWithDescription:@"latest settings"]; + __block NSUInteger eventCount = 0; + _registry.dispatcher.onEvent = ^(NSString *name, NSDictionary *body) { + eventCount++; + XCTAssertEqualObjects(body[@"external"], @99); + [event fulfill]; + }; + for (NSUInteger index = 0; index < 100; index++) { + [_defaults setObject:@(index) forKey:@"external"]; + } + dispatch_semaphore_signal(releaseQueue); + [self waitForExpectations:@[ event ] timeout:3]; + dispatch_sync( + _manager.methodQueue, + ^{ + }); + XCTAssertEqual(eventCount, 1u); + XCTAssertEqual(_defaults.snapshotCount, 1u); +} + +- (void)testNotificationDuringSnapshotSchedulesTrailingUpdate +{ + dispatch_semaphore_t releaseSnapshot = dispatch_semaphore_create(0); + XCTestExpectation *snapshot = [self expectationWithDescription:@"first snapshot captured"]; + XCTestExpectation *events = [self expectationWithDescription:@"ordered updates"]; + events.expectedFulfillmentCount = 2; + __block NSUInteger snapshotCount = 0; + _defaults.onSnapshot = ^(NSDictionary *body) { + if (++snapshotCount == 1) { + [snapshot fulfill]; + XCTAssertEqual(dispatch_semaphore_wait(releaseSnapshot, dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC)), 0); + } + }; + __block NSUInteger eventCount = 0; + _registry.dispatcher.onEvent = ^(NSString *name, NSDictionary *body) { + XCTAssertEqualObjects(body[@"external"], @(++eventCount)); + [events fulfill]; + }; + [_defaults setObject:@1 forKey:@"external"]; + [self waitForExpectations:@[ snapshot ] timeout:3]; + [_defaults setObject:@2 forKey:@"external"]; + dispatch_semaphore_signal(releaseSnapshot); + [self waitForExpectations:@[ events ] timeout:3]; + dispatch_sync( + _manager.methodQueue, + ^{ + }); + XCTAssertEqual(eventCount, 2u); + XCTAssertEqual(_defaults.snapshotCount, 2u); +} + +- (void)testInvalidationDropsPendingUpdate +{ + dispatch_semaphore_t releaseQueue = dispatch_semaphore_create(0); + XCTestExpectation *blocked = [self expectationWithDescription:@"queue blocked"]; + dispatch_async(_manager.methodQueue, ^{ + [blocked fulfill]; + XCTAssertEqual(dispatch_semaphore_wait(releaseQueue, dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC)), 0); + }); + [self waitForExpectations:@[ blocked ] timeout:3]; + __block NSUInteger eventCount = 0; + _registry.dispatcher.onEvent = ^(NSString *name, NSDictionary *body) { + eventCount++; + }; + [_defaults setObject:@1 forKey:@"external"]; + [_manager invalidate]; + [_defaults setObject:@2 forKey:@"external"]; + dispatch_semaphore_signal(releaseQueue); + dispatch_sync( + _manager.methodQueue, + ^{ + }); + XCTAssertEqual(eventCount, 0u); + XCTAssertEqual(_defaults.snapshotCount, 0u); +} + +- (void)testPendingUpdateDoesNotRetainManager +{ + dispatch_queue_t queue = _manager.methodQueue; + dispatch_semaphore_t releaseQueue = dispatch_semaphore_create(0); + XCTestExpectation *blocked = [self expectationWithDescription:@"queue blocked"]; + dispatch_async(queue, ^{ + [blocked fulfill]; + XCTAssertEqual(dispatch_semaphore_wait(releaseQueue, dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC)), 0); + }); + [self waitForExpectations:@[ blocked ] timeout:3]; + [_defaults setObject:@1 forKey:@"external"]; + __weak RCTSettingsManager *weakManager = _manager; + _manager = nil; + XCTAssertNil(weakManager); + dispatch_semaphore_signal(releaseQueue); + dispatch_sync( + queue, + ^{ + }); + XCTAssertEqual(_defaults.snapshotCount, 0u); +} + +@end 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 07ef963a6612..df972590cb62 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<<72ad53973a7de132705b9ec1a72aac08>> + * @generated SignedSource<<419f5268e3cb03e505af8fe32154fb42>> */ /** @@ -126,6 +126,12 @@ public object ReactNativeFeatureFlags { @JvmStatic public fun enableAsyncDiskCacheCheckInMultiSourceImageAndroid(): Boolean = accessor.enableAsyncDiskCacheCheckInMultiSourceImageAndroid() + /** + * Process SettingsManager defaults notifications on a dedicated serial queue on iOS. + */ + @JvmStatic + public fun enableAsyncSettingsManagerUpdatesIOS(): Boolean = accessor.enableAsyncSettingsManagerUpdatesIOS() + /** * Feature flag to enable the new bridgeless architecture. */ 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 31815488c19a..5702facd1dd8 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<<60051ebbc387ff06db855ed661340217>> + * @generated SignedSource<> */ /** @@ -36,6 +36,7 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces private var enableAndroidAutoOffscreenCompositingForElevationCache: Boolean? = null private var enableAndroidTextMeasurementOptimizationsCache: Boolean? = null private var enableAsyncDiskCacheCheckInMultiSourceImageAndroidCache: Boolean? = null + private var enableAsyncSettingsManagerUpdatesIOSCache: Boolean? = null private var enableBridgelessArchitectureCache: Boolean? = null private var enableCppPropsIteratorSetterCache: Boolean? = null private var enableCustomFocusSearchOnClippedElementsAndroidCache: Boolean? = null @@ -256,6 +257,15 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces return cached } + override fun enableAsyncSettingsManagerUpdatesIOS(): Boolean { + var cached = enableAsyncSettingsManagerUpdatesIOSCache + if (cached == null) { + cached = ReactNativeFeatureFlagsCxxInterop.enableAsyncSettingsManagerUpdatesIOS() + enableAsyncSettingsManagerUpdatesIOSCache = cached + } + return cached + } + override fun enableBridgelessArchitecture(): Boolean { var cached = enableBridgelessArchitectureCache 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 88728162c941..55a263e2061a 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<<9ed55c4c14d640c0fb2bd6c8fb7ef557>> + * @generated SignedSource<<9d8d6d33a151f5956fae23edc44108a5>> */ /** @@ -60,6 +60,8 @@ public object ReactNativeFeatureFlagsCxxInterop { @DoNotStrip @JvmStatic public external fun enableAsyncDiskCacheCheckInMultiSourceImageAndroid(): Boolean + @DoNotStrip @JvmStatic public external fun enableAsyncSettingsManagerUpdatesIOS(): Boolean + @DoNotStrip @JvmStatic public external fun enableBridgelessArchitecture(): Boolean @DoNotStrip @JvmStatic public external fun enableCppPropsIteratorSetter(): 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 b80430013c55..bfb6d1439624 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<<2170527111c8b3c34c213c24a9948931>> + * @generated SignedSource<<5f7b160241f08f962a0358ce69d914ef>> */ /** @@ -55,6 +55,8 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi override fun enableAsyncDiskCacheCheckInMultiSourceImageAndroid(): Boolean = false + override fun enableAsyncSettingsManagerUpdatesIOS(): Boolean = false + override fun enableBridgelessArchitecture(): Boolean = true override fun enableCppPropsIteratorSetter(): 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 ddef18a5642f..87083e886766 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<<1ebd0bb8e98c1b31518c8eba05be919c>> */ /** @@ -40,6 +40,7 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc private var enableAndroidAutoOffscreenCompositingForElevationCache: Boolean? = null private var enableAndroidTextMeasurementOptimizationsCache: Boolean? = null private var enableAsyncDiskCacheCheckInMultiSourceImageAndroidCache: Boolean? = null + private var enableAsyncSettingsManagerUpdatesIOSCache: Boolean? = null private var enableBridgelessArchitectureCache: Boolean? = null private var enableCppPropsIteratorSetterCache: Boolean? = null private var enableCustomFocusSearchOnClippedElementsAndroidCache: Boolean? = null @@ -276,6 +277,16 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc return cached } + override fun enableAsyncSettingsManagerUpdatesIOS(): Boolean { + var cached = enableAsyncSettingsManagerUpdatesIOSCache + if (cached == null) { + cached = currentProvider.enableAsyncSettingsManagerUpdatesIOS() + accessedFeatureFlags.add("enableAsyncSettingsManagerUpdatesIOS") + enableAsyncSettingsManagerUpdatesIOSCache = cached + } + return cached + } + override fun enableBridgelessArchitecture(): Boolean { var cached = enableBridgelessArchitectureCache 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 399cbb4f0f91..8ff722b6876a 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<<256b97731c59551616a8e0cbc777f3fa>> + * @generated SignedSource<<02ba59febfe006256c838500cc9bbf61>> */ /** @@ -55,6 +55,8 @@ public interface ReactNativeFeatureFlagsProvider { @DoNotStrip public fun enableAsyncDiskCacheCheckInMultiSourceImageAndroid(): Boolean + @DoNotStrip public fun enableAsyncSettingsManagerUpdatesIOS(): Boolean + @DoNotStrip public fun enableBridgelessArchitecture(): Boolean @DoNotStrip public fun enableCppPropsIteratorSetter(): Boolean diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp index 1c7c222ebe99..33e78e125605 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<<2b4f896552dd54c3ec858ca788ab4254>> + * @generated SignedSource<> */ /** @@ -135,6 +135,12 @@ class ReactNativeFeatureFlagsJavaProvider return method(javaProvider_); } + bool enableAsyncSettingsManagerUpdatesIOS() override { + static const auto method = + getReactNativeFeatureFlagsProviderJavaClass()->getMethod("enableAsyncSettingsManagerUpdatesIOS"); + return method(javaProvider_); + } + bool enableBridgelessArchitecture() override { static const auto method = getReactNativeFeatureFlagsProviderJavaClass()->getMethod("enableBridgelessArchitecture"); @@ -669,6 +675,11 @@ bool JReactNativeFeatureFlagsCxxInterop::enableAsyncDiskCacheCheckInMultiSourceI return ReactNativeFeatureFlags::enableAsyncDiskCacheCheckInMultiSourceImageAndroid(); } +bool JReactNativeFeatureFlagsCxxInterop::enableAsyncSettingsManagerUpdatesIOS( + facebook::jni::alias_ref /*unused*/) { + return ReactNativeFeatureFlags::enableAsyncSettingsManagerUpdatesIOS(); +} + bool JReactNativeFeatureFlagsCxxInterop::enableBridgelessArchitecture( facebook::jni::alias_ref /*unused*/) { return ReactNativeFeatureFlags::enableBridgelessArchitecture(); @@ -1123,6 +1134,9 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() { makeNativeMethod( "enableAsyncDiskCacheCheckInMultiSourceImageAndroid", JReactNativeFeatureFlagsCxxInterop::enableAsyncDiskCacheCheckInMultiSourceImageAndroid), + makeNativeMethod( + "enableAsyncSettingsManagerUpdatesIOS", + JReactNativeFeatureFlagsCxxInterop::enableAsyncSettingsManagerUpdatesIOS), makeNativeMethod( "enableBridgelessArchitecture", JReactNativeFeatureFlagsCxxInterop::enableBridgelessArchitecture), 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 1cc1567097c5..1419e6551f2d 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<<228fff4f0ef0e530bf50203050adb9b0>> + * @generated SignedSource<<9916203529aef50a87192d70176bf624>> */ /** @@ -78,6 +78,9 @@ class JReactNativeFeatureFlagsCxxInterop static bool enableAsyncDiskCacheCheckInMultiSourceImageAndroid( facebook::jni::alias_ref); + static bool enableAsyncSettingsManagerUpdatesIOS( + facebook::jni::alias_ref); + static bool enableBridgelessArchitecture( 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 a3c89045c15e..c31b0b377592 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<<2c4c3259015438d07cc137e9288db04a>> + * @generated SignedSource<> */ /** @@ -90,6 +90,10 @@ bool ReactNativeFeatureFlags::enableAsyncDiskCacheCheckInMultiSourceImageAndroid return getAccessor().enableAsyncDiskCacheCheckInMultiSourceImageAndroid(); } +bool ReactNativeFeatureFlags::enableAsyncSettingsManagerUpdatesIOS() { + return getAccessor().enableAsyncSettingsManagerUpdatesIOS(); +} + bool ReactNativeFeatureFlags::enableBridgelessArchitecture() { return getAccessor().enableBridgelessArchitecture(); } diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h index 937527653893..520ba940bdad 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<<73ae8b45c0961bc60eeb804d4d40bd07>> + * @generated SignedSource<<7b78cfdbd41f5405c3222a23ab1dd5b8>> */ /** @@ -121,6 +121,11 @@ class ReactNativeFeatureFlags { */ RN_EXPORT static bool enableAsyncDiskCacheCheckInMultiSourceImageAndroid(); + /** + * Process SettingsManager defaults notifications on a dedicated serial queue on iOS. + */ + RN_EXPORT static bool enableAsyncSettingsManagerUpdatesIOS(); + /** * Feature flag to enable the new bridgeless architecture. */ diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp index 0f3cf823a5a1..678767f0c266 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<<46fc995d3bb226c417f9c6f8f8089360>> + * @generated SignedSource<<29e19cbfd6645bcf3ca47559a2b581e3>> */ /** @@ -317,6 +317,24 @@ bool ReactNativeFeatureFlagsAccessor::enableAsyncDiskCacheCheckInMultiSourceImag return flagValue.value(); } +bool ReactNativeFeatureFlagsAccessor::enableAsyncSettingsManagerUpdatesIOS() { + auto flagValue = enableAsyncSettingsManagerUpdatesIOS_.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, "enableAsyncSettingsManagerUpdatesIOS"); + + flagValue = currentProvider_->enableAsyncSettingsManagerUpdatesIOS(); + enableAsyncSettingsManagerUpdatesIOS_ = flagValue; + } + + return flagValue.value(); +} + bool ReactNativeFeatureFlagsAccessor::enableBridgelessArchitecture() { auto flagValue = enableBridgelessArchitecture_.load(); @@ -326,7 +344,7 @@ bool ReactNativeFeatureFlagsAccessor::enableBridgelessArchitecture() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(16, "enableBridgelessArchitecture"); + markFlagAsAccessed(17, "enableBridgelessArchitecture"); flagValue = currentProvider_->enableBridgelessArchitecture(); enableBridgelessArchitecture_ = flagValue; @@ -344,7 +362,7 @@ bool ReactNativeFeatureFlagsAccessor::enableCppPropsIteratorSetter() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(17, "enableCppPropsIteratorSetter"); + markFlagAsAccessed(18, "enableCppPropsIteratorSetter"); flagValue = currentProvider_->enableCppPropsIteratorSetter(); enableCppPropsIteratorSetter_ = flagValue; @@ -362,7 +380,7 @@ bool ReactNativeFeatureFlagsAccessor::enableCustomFocusSearchOnClippedElementsAn // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(18, "enableCustomFocusSearchOnClippedElementsAndroid"); + markFlagAsAccessed(19, "enableCustomFocusSearchOnClippedElementsAndroid"); flagValue = currentProvider_->enableCustomFocusSearchOnClippedElementsAndroid(); enableCustomFocusSearchOnClippedElementsAndroid_ = flagValue; @@ -380,7 +398,7 @@ bool ReactNativeFeatureFlagsAccessor::enableDestroyShadowTreeRevisionAsync() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(19, "enableDestroyShadowTreeRevisionAsync"); + markFlagAsAccessed(20, "enableDestroyShadowTreeRevisionAsync"); flagValue = currentProvider_->enableDestroyShadowTreeRevisionAsync(); enableDestroyShadowTreeRevisionAsync_ = flagValue; @@ -398,7 +416,7 @@ bool ReactNativeFeatureFlagsAccessor::enableDoubleMeasurementFixAndroid() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(20, "enableDoubleMeasurementFixAndroid"); + markFlagAsAccessed(21, "enableDoubleMeasurementFixAndroid"); flagValue = currentProvider_->enableDoubleMeasurementFixAndroid(); enableDoubleMeasurementFixAndroid_ = flagValue; @@ -416,7 +434,7 @@ bool ReactNativeFeatureFlagsAccessor::enableEagerRootViewAttachment() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(21, "enableEagerRootViewAttachment"); + markFlagAsAccessed(22, "enableEagerRootViewAttachment"); flagValue = currentProvider_->enableEagerRootViewAttachment(); enableEagerRootViewAttachment_ = flagValue; @@ -434,7 +452,7 @@ bool ReactNativeFeatureFlagsAccessor::enableExclusivePropsUpdateAndroid() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(22, "enableExclusivePropsUpdateAndroid"); + markFlagAsAccessed(23, "enableExclusivePropsUpdateAndroid"); flagValue = currentProvider_->enableExclusivePropsUpdateAndroid(); enableExclusivePropsUpdateAndroid_ = flagValue; @@ -452,7 +470,7 @@ bool ReactNativeFeatureFlagsAccessor::enableFabricCommitBranching() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(23, "enableFabricCommitBranching"); + markFlagAsAccessed(24, "enableFabricCommitBranching"); flagValue = currentProvider_->enableFabricCommitBranching(); enableFabricCommitBranching_ = flagValue; @@ -470,7 +488,7 @@ bool ReactNativeFeatureFlagsAccessor::enableFabricCommitBranchingMergeOnMainThre // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(24, "enableFabricCommitBranchingMergeOnMainThread"); + markFlagAsAccessed(25, "enableFabricCommitBranchingMergeOnMainThread"); flagValue = currentProvider_->enableFabricCommitBranchingMergeOnMainThread(); enableFabricCommitBranchingMergeOnMainThread_ = flagValue; @@ -488,7 +506,7 @@ bool ReactNativeFeatureFlagsAccessor::enableFabricLogs() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(25, "enableFabricLogs"); + markFlagAsAccessed(26, "enableFabricLogs"); flagValue = currentProvider_->enableFabricLogs(); enableFabricLogs_ = flagValue; @@ -506,7 +524,7 @@ bool ReactNativeFeatureFlagsAccessor::enableFlexboxAutoMinSizeInStrictMode() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(26, "enableFlexboxAutoMinSizeInStrictMode"); + markFlagAsAccessed(27, "enableFlexboxAutoMinSizeInStrictMode"); flagValue = currentProvider_->enableFlexboxAutoMinSizeInStrictMode(); enableFlexboxAutoMinSizeInStrictMode_ = flagValue; @@ -524,7 +542,7 @@ bool ReactNativeFeatureFlagsAccessor::enableFontScaleChangesUpdatingLayout() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(27, "enableFontScaleChangesUpdatingLayout"); + markFlagAsAccessed(28, "enableFontScaleChangesUpdatingLayout"); flagValue = currentProvider_->enableFontScaleChangesUpdatingLayout(); enableFontScaleChangesUpdatingLayout_ = flagValue; @@ -542,7 +560,7 @@ bool ReactNativeFeatureFlagsAccessor::enableIOSCompressedTextFrameAdjustment() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(28, "enableIOSCompressedTextFrameAdjustment"); + markFlagAsAccessed(29, "enableIOSCompressedTextFrameAdjustment"); flagValue = currentProvider_->enableIOSCompressedTextFrameAdjustment(); enableIOSCompressedTextFrameAdjustment_ = flagValue; @@ -560,7 +578,7 @@ bool ReactNativeFeatureFlagsAccessor::enableIOSTextBaselineOffsetPerLine() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(29, "enableIOSTextBaselineOffsetPerLine"); + markFlagAsAccessed(30, "enableIOSTextBaselineOffsetPerLine"); flagValue = currentProvider_->enableIOSTextBaselineOffsetPerLine(); enableIOSTextBaselineOffsetPerLine_ = flagValue; @@ -578,7 +596,7 @@ bool ReactNativeFeatureFlagsAccessor::enableIOSViewClipToPaddingBox() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(30, "enableIOSViewClipToPaddingBox"); + markFlagAsAccessed(31, "enableIOSViewClipToPaddingBox"); flagValue = currentProvider_->enableIOSViewClipToPaddingBox(); enableIOSViewClipToPaddingBox_ = flagValue; @@ -596,7 +614,7 @@ bool ReactNativeFeatureFlagsAccessor::enableImagePrefetchingAndroid() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(31, "enableImagePrefetchingAndroid"); + markFlagAsAccessed(32, "enableImagePrefetchingAndroid"); flagValue = currentProvider_->enableImagePrefetchingAndroid(); enableImagePrefetchingAndroid_ = flagValue; @@ -614,7 +632,7 @@ bool ReactNativeFeatureFlagsAccessor::enableImageTransparentTintColor() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(32, "enableImageTransparentTintColor"); + markFlagAsAccessed(33, "enableImageTransparentTintColor"); flagValue = currentProvider_->enableImageTransparentTintColor(); enableImageTransparentTintColor_ = flagValue; @@ -632,7 +650,7 @@ bool ReactNativeFeatureFlagsAccessor::enableImmediateUpdateModeForContentOffsetC // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(33, "enableImmediateUpdateModeForContentOffsetChanges"); + markFlagAsAccessed(34, "enableImmediateUpdateModeForContentOffsetChanges"); flagValue = currentProvider_->enableImmediateUpdateModeForContentOffsetChanges(); enableImmediateUpdateModeForContentOffsetChanges_ = flagValue; @@ -650,7 +668,7 @@ bool ReactNativeFeatureFlagsAccessor::enableImperativeEvents() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(34, "enableImperativeEvents"); + markFlagAsAccessed(35, "enableImperativeEvents"); flagValue = currentProvider_->enableImperativeEvents(); enableImperativeEvents_ = flagValue; @@ -668,7 +686,7 @@ bool ReactNativeFeatureFlagsAccessor::enableImperativeFocus() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(35, "enableImperativeFocus"); + markFlagAsAccessed(36, "enableImperativeFocus"); flagValue = currentProvider_->enableImperativeFocus(); enableImperativeFocus_ = flagValue; @@ -686,7 +704,7 @@ bool ReactNativeFeatureFlagsAccessor::enableInteropViewManagerClassLookUpOptimiz // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(36, "enableInteropViewManagerClassLookUpOptimizationIOS"); + markFlagAsAccessed(37, "enableInteropViewManagerClassLookUpOptimizationIOS"); flagValue = currentProvider_->enableInteropViewManagerClassLookUpOptimizationIOS(); enableInteropViewManagerClassLookUpOptimizationIOS_ = flagValue; @@ -704,7 +722,7 @@ bool ReactNativeFeatureFlagsAccessor::enableIntersectionObserverByDefault() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(37, "enableIntersectionObserverByDefault"); + markFlagAsAccessed(38, "enableIntersectionObserverByDefault"); flagValue = currentProvider_->enableIntersectionObserverByDefault(); enableIntersectionObserverByDefault_ = flagValue; @@ -722,7 +740,7 @@ bool ReactNativeFeatureFlagsAccessor::enableKeyEvents() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(38, "enableKeyEvents"); + markFlagAsAccessed(39, "enableKeyEvents"); flagValue = currentProvider_->enableKeyEvents(); enableKeyEvents_ = flagValue; @@ -740,7 +758,7 @@ bool ReactNativeFeatureFlagsAccessor::enableLayoutAnimationsOnAndroid() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(39, "enableLayoutAnimationsOnAndroid"); + markFlagAsAccessed(40, "enableLayoutAnimationsOnAndroid"); flagValue = currentProvider_->enableLayoutAnimationsOnAndroid(); enableLayoutAnimationsOnAndroid_ = flagValue; @@ -758,7 +776,7 @@ bool ReactNativeFeatureFlagsAccessor::enableLayoutAnimationsOnIOS() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(40, "enableLayoutAnimationsOnIOS"); + markFlagAsAccessed(41, "enableLayoutAnimationsOnIOS"); flagValue = currentProvider_->enableLayoutAnimationsOnIOS(); enableLayoutAnimationsOnIOS_ = flagValue; @@ -776,7 +794,7 @@ bool ReactNativeFeatureFlagsAccessor::enableModuleArgumentNSNullConversionIOS() // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(41, "enableModuleArgumentNSNullConversionIOS"); + markFlagAsAccessed(42, "enableModuleArgumentNSNullConversionIOS"); flagValue = currentProvider_->enableModuleArgumentNSNullConversionIOS(); enableModuleArgumentNSNullConversionIOS_ = flagValue; @@ -794,7 +812,7 @@ bool ReactNativeFeatureFlagsAccessor::enableMountingCoordinatorPullModelAndroid( // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(42, "enableMountingCoordinatorPullModelAndroid"); + markFlagAsAccessed(43, "enableMountingCoordinatorPullModelAndroid"); flagValue = currentProvider_->enableMountingCoordinatorPullModelAndroid(); enableMountingCoordinatorPullModelAndroid_ = flagValue; @@ -812,7 +830,7 @@ bool ReactNativeFeatureFlagsAccessor::enableMutationObserverByDefault() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(43, "enableMutationObserverByDefault"); + markFlagAsAccessed(44, "enableMutationObserverByDefault"); flagValue = currentProvider_->enableMutationObserverByDefault(); enableMutationObserverByDefault_ = flagValue; @@ -830,7 +848,7 @@ bool ReactNativeFeatureFlagsAccessor::enableNativeCSSParsing() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(44, "enableNativeCSSParsing"); + markFlagAsAccessed(45, "enableNativeCSSParsing"); flagValue = currentProvider_->enableNativeCSSParsing(); enableNativeCSSParsing_ = flagValue; @@ -848,7 +866,7 @@ bool ReactNativeFeatureFlagsAccessor::enablePreallocatedPropsDiffOnInsertAndroid // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(45, "enablePreallocatedPropsDiffOnInsertAndroid"); + markFlagAsAccessed(46, "enablePreallocatedPropsDiffOnInsertAndroid"); flagValue = currentProvider_->enablePreallocatedPropsDiffOnInsertAndroid(); enablePreallocatedPropsDiffOnInsertAndroid_ = flagValue; @@ -866,7 +884,7 @@ bool ReactNativeFeatureFlagsAccessor::enablePreparedTextLayout() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(46, "enablePreparedTextLayout"); + markFlagAsAccessed(47, "enablePreparedTextLayout"); flagValue = currentProvider_->enablePreparedTextLayout(); enablePreparedTextLayout_ = flagValue; @@ -884,7 +902,7 @@ bool ReactNativeFeatureFlagsAccessor::enablePropsUpdateReconciliationAndroid() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(47, "enablePropsUpdateReconciliationAndroid"); + markFlagAsAccessed(48, "enablePropsUpdateReconciliationAndroid"); flagValue = currentProvider_->enablePropsUpdateReconciliationAndroid(); enablePropsUpdateReconciliationAndroid_ = flagValue; @@ -902,7 +920,7 @@ bool ReactNativeFeatureFlagsAccessor::enableResizeObserverByDefault() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(48, "enableResizeObserverByDefault"); + markFlagAsAccessed(49, "enableResizeObserverByDefault"); flagValue = currentProvider_->enableResizeObserverByDefault(); enableResizeObserverByDefault_ = flagValue; @@ -920,7 +938,7 @@ bool ReactNativeFeatureFlagsAccessor::enableSwiftUIBasedFilters() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(49, "enableSwiftUIBasedFilters"); + markFlagAsAccessed(50, "enableSwiftUIBasedFilters"); flagValue = currentProvider_->enableSwiftUIBasedFilters(); enableSwiftUIBasedFilters_ = flagValue; @@ -938,7 +956,7 @@ bool ReactNativeFeatureFlagsAccessor::enableViewCulling() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(50, "enableViewCulling"); + markFlagAsAccessed(51, "enableViewCulling"); flagValue = currentProvider_->enableViewCulling(); enableViewCulling_ = flagValue; @@ -956,7 +974,7 @@ bool ReactNativeFeatureFlagsAccessor::enableViewRecycling() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(51, "enableViewRecycling"); + markFlagAsAccessed(52, "enableViewRecycling"); flagValue = currentProvider_->enableViewRecycling(); enableViewRecycling_ = flagValue; @@ -974,7 +992,7 @@ bool ReactNativeFeatureFlagsAccessor::enableViewRecyclingForImage() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(52, "enableViewRecyclingForImage"); + markFlagAsAccessed(53, "enableViewRecyclingForImage"); flagValue = currentProvider_->enableViewRecyclingForImage(); enableViewRecyclingForImage_ = flagValue; @@ -992,7 +1010,7 @@ bool ReactNativeFeatureFlagsAccessor::enableViewRecyclingForScrollView() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(53, "enableViewRecyclingForScrollView"); + markFlagAsAccessed(54, "enableViewRecyclingForScrollView"); flagValue = currentProvider_->enableViewRecyclingForScrollView(); enableViewRecyclingForScrollView_ = flagValue; @@ -1010,7 +1028,7 @@ bool ReactNativeFeatureFlagsAccessor::enableViewRecyclingForText() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(54, "enableViewRecyclingForText"); + markFlagAsAccessed(55, "enableViewRecyclingForText"); flagValue = currentProvider_->enableViewRecyclingForText(); enableViewRecyclingForText_ = flagValue; @@ -1028,7 +1046,7 @@ bool ReactNativeFeatureFlagsAccessor::enableViewRecyclingForView() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(55, "enableViewRecyclingForView"); + markFlagAsAccessed(56, "enableViewRecyclingForView"); flagValue = currentProvider_->enableViewRecyclingForView(); enableViewRecyclingForView_ = flagValue; @@ -1046,7 +1064,7 @@ bool ReactNativeFeatureFlagsAccessor::enableVirtualViewContainerStateExperimenta // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(56, "enableVirtualViewContainerStateExperimental"); + markFlagAsAccessed(57, "enableVirtualViewContainerStateExperimental"); flagValue = currentProvider_->enableVirtualViewContainerStateExperimental(); enableVirtualViewContainerStateExperimental_ = flagValue; @@ -1064,7 +1082,7 @@ bool ReactNativeFeatureFlagsAccessor::fixBorderlessRippleAndroid() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(57, "fixBorderlessRippleAndroid"); + markFlagAsAccessed(58, "fixBorderlessRippleAndroid"); flagValue = currentProvider_->fixBorderlessRippleAndroid(); fixBorderlessRippleAndroid_ = flagValue; @@ -1082,7 +1100,7 @@ bool ReactNativeFeatureFlagsAccessor::fixMappingOfEventPrioritiesBetweenFabricAn // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(58, "fixMappingOfEventPrioritiesBetweenFabricAndReact"); + markFlagAsAccessed(59, "fixMappingOfEventPrioritiesBetweenFabricAndReact"); flagValue = currentProvider_->fixMappingOfEventPrioritiesBetweenFabricAndReact(); fixMappingOfEventPrioritiesBetweenFabricAndReact_ = flagValue; @@ -1100,7 +1118,7 @@ bool ReactNativeFeatureFlagsAccessor::fixYogaFlexBasisFitContentInMainAxis() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(59, "fixYogaFlexBasisFitContentInMainAxis"); + markFlagAsAccessed(60, "fixYogaFlexBasisFitContentInMainAxis"); flagValue = currentProvider_->fixYogaFlexBasisFitContentInMainAxis(); fixYogaFlexBasisFitContentInMainAxis_ = flagValue; @@ -1118,7 +1136,7 @@ bool ReactNativeFeatureFlagsAccessor::fuseboxAssertSingleHostState() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(60, "fuseboxAssertSingleHostState"); + markFlagAsAccessed(61, "fuseboxAssertSingleHostState"); flagValue = currentProvider_->fuseboxAssertSingleHostState(); fuseboxAssertSingleHostState_ = flagValue; @@ -1136,7 +1154,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(61, "fuseboxEnabledRelease"); + markFlagAsAccessed(62, "fuseboxEnabledRelease"); flagValue = currentProvider_->fuseboxEnabledRelease(); fuseboxEnabledRelease_ = flagValue; @@ -1154,7 +1172,7 @@ bool ReactNativeFeatureFlagsAccessor::fuseboxFrameRecordingEnabled() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(62, "fuseboxFrameRecordingEnabled"); + markFlagAsAccessed(63, "fuseboxFrameRecordingEnabled"); flagValue = currentProvider_->fuseboxFrameRecordingEnabled(); fuseboxFrameRecordingEnabled_ = flagValue; @@ -1172,7 +1190,7 @@ bool ReactNativeFeatureFlagsAccessor::fuseboxScreenshotCaptureEnabled() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(63, "fuseboxScreenshotCaptureEnabled"); + markFlagAsAccessed(64, "fuseboxScreenshotCaptureEnabled"); flagValue = currentProvider_->fuseboxScreenshotCaptureEnabled(); fuseboxScreenshotCaptureEnabled_ = flagValue; @@ -1190,7 +1208,7 @@ bool ReactNativeFeatureFlagsAccessor::fuseboxWebSocketEventsEnabled() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(64, "fuseboxWebSocketEventsEnabled"); + markFlagAsAccessed(65, "fuseboxWebSocketEventsEnabled"); flagValue = currentProvider_->fuseboxWebSocketEventsEnabled(); fuseboxWebSocketEventsEnabled_ = flagValue; @@ -1208,7 +1226,7 @@ bool ReactNativeFeatureFlagsAccessor::optimizedAnimatedPropUpdates() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(65, "optimizedAnimatedPropUpdates"); + markFlagAsAccessed(66, "optimizedAnimatedPropUpdates"); flagValue = currentProvider_->optimizedAnimatedPropUpdates(); optimizedAnimatedPropUpdates_ = flagValue; @@ -1226,7 +1244,7 @@ bool ReactNativeFeatureFlagsAccessor::overrideBySynchronousMountPropsAtMountingA // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(66, "overrideBySynchronousMountPropsAtMountingAndroid"); + markFlagAsAccessed(67, "overrideBySynchronousMountPropsAtMountingAndroid"); flagValue = currentProvider_->overrideBySynchronousMountPropsAtMountingAndroid(); overrideBySynchronousMountPropsAtMountingAndroid_ = flagValue; @@ -1244,7 +1262,7 @@ bool ReactNativeFeatureFlagsAccessor::perfIssuesEnabled() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(67, "perfIssuesEnabled"); + markFlagAsAccessed(68, "perfIssuesEnabled"); flagValue = currentProvider_->perfIssuesEnabled(); perfIssuesEnabled_ = flagValue; @@ -1262,7 +1280,7 @@ bool ReactNativeFeatureFlagsAccessor::perfMonitorV2Enabled() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(68, "perfMonitorV2Enabled"); + markFlagAsAccessed(69, "perfMonitorV2Enabled"); flagValue = currentProvider_->perfMonitorV2Enabled(); perfMonitorV2Enabled_ = flagValue; @@ -1280,7 +1298,7 @@ double ReactNativeFeatureFlagsAccessor::preparedTextCacheSize() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(69, "preparedTextCacheSize"); + markFlagAsAccessed(70, "preparedTextCacheSize"); flagValue = currentProvider_->preparedTextCacheSize(); preparedTextCacheSize_ = flagValue; @@ -1298,7 +1316,7 @@ bool ReactNativeFeatureFlagsAccessor::preventShadowTreeCommitExhaustion() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(70, "preventShadowTreeCommitExhaustion"); + markFlagAsAccessed(71, "preventShadowTreeCommitExhaustion"); flagValue = currentProvider_->preventShadowTreeCommitExhaustion(); preventShadowTreeCommitExhaustion_ = flagValue; @@ -1316,7 +1334,7 @@ bool ReactNativeFeatureFlagsAccessor::redBoxV2Android() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(71, "redBoxV2Android"); + markFlagAsAccessed(72, "redBoxV2Android"); flagValue = currentProvider_->redBoxV2Android(); redBoxV2Android_ = flagValue; @@ -1334,7 +1352,7 @@ bool ReactNativeFeatureFlagsAccessor::redBoxV2IOS() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(72, "redBoxV2IOS"); + markFlagAsAccessed(73, "redBoxV2IOS"); flagValue = currentProvider_->redBoxV2IOS(); redBoxV2IOS_ = flagValue; @@ -1352,7 +1370,7 @@ bool ReactNativeFeatureFlagsAccessor::shouldPressibilityUseW3CPointerEventsForHo // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(73, "shouldPressibilityUseW3CPointerEventsForHover"); + markFlagAsAccessed(74, "shouldPressibilityUseW3CPointerEventsForHover"); flagValue = currentProvider_->shouldPressibilityUseW3CPointerEventsForHover(); shouldPressibilityUseW3CPointerEventsForHover_ = flagValue; @@ -1370,7 +1388,7 @@ bool ReactNativeFeatureFlagsAccessor::shouldTriggerResponderTransferOnScrollAndr // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(74, "shouldTriggerResponderTransferOnScrollAndroid"); + markFlagAsAccessed(75, "shouldTriggerResponderTransferOnScrollAndroid"); flagValue = currentProvider_->shouldTriggerResponderTransferOnScrollAndroid(); shouldTriggerResponderTransferOnScrollAndroid_ = flagValue; @@ -1388,7 +1406,7 @@ bool ReactNativeFeatureFlagsAccessor::skipActivityIdentityAssertionOnHostPause() // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(75, "skipActivityIdentityAssertionOnHostPause"); + markFlagAsAccessed(76, "skipActivityIdentityAssertionOnHostPause"); flagValue = currentProvider_->skipActivityIdentityAssertionOnHostPause(); skipActivityIdentityAssertionOnHostPause_ = flagValue; @@ -1406,7 +1424,7 @@ bool ReactNativeFeatureFlagsAccessor::syncAndroidClipBoundsWithOverflow() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(76, "syncAndroidClipBoundsWithOverflow"); + markFlagAsAccessed(77, "syncAndroidClipBoundsWithOverflow"); flagValue = currentProvider_->syncAndroidClipBoundsWithOverflow(); syncAndroidClipBoundsWithOverflow_ = flagValue; @@ -1424,7 +1442,7 @@ bool ReactNativeFeatureFlagsAccessor::traceTurboModulePromiseRejectionsOnAndroid // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(77, "traceTurboModulePromiseRejectionsOnAndroid"); + markFlagAsAccessed(78, "traceTurboModulePromiseRejectionsOnAndroid"); flagValue = currentProvider_->traceTurboModulePromiseRejectionsOnAndroid(); traceTurboModulePromiseRejectionsOnAndroid_ = flagValue; @@ -1442,7 +1460,7 @@ bool ReactNativeFeatureFlagsAccessor::updateRuntimeShadowNodeReferencesOnCommit( // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(78, "updateRuntimeShadowNodeReferencesOnCommit"); + markFlagAsAccessed(79, "updateRuntimeShadowNodeReferencesOnCommit"); flagValue = currentProvider_->updateRuntimeShadowNodeReferencesOnCommit(); updateRuntimeShadowNodeReferencesOnCommit_ = flagValue; @@ -1460,7 +1478,7 @@ bool ReactNativeFeatureFlagsAccessor::updateRuntimeShadowNodeReferencesOnCommitT // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(79, "updateRuntimeShadowNodeReferencesOnCommitThread"); + markFlagAsAccessed(80, "updateRuntimeShadowNodeReferencesOnCommitThread"); flagValue = currentProvider_->updateRuntimeShadowNodeReferencesOnCommitThread(); updateRuntimeShadowNodeReferencesOnCommitThread_ = flagValue; @@ -1478,7 +1496,7 @@ bool ReactNativeFeatureFlagsAccessor::useAlwaysAvailableJSErrorHandling() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(80, "useAlwaysAvailableJSErrorHandling"); + markFlagAsAccessed(81, "useAlwaysAvailableJSErrorHandling"); flagValue = currentProvider_->useAlwaysAvailableJSErrorHandling(); useAlwaysAvailableJSErrorHandling_ = flagValue; @@ -1496,7 +1514,7 @@ bool ReactNativeFeatureFlagsAccessor::useFabricInterop() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(81, "useFabricInterop"); + markFlagAsAccessed(82, "useFabricInterop"); flagValue = currentProvider_->useFabricInterop(); useFabricInterop_ = flagValue; @@ -1514,7 +1532,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(82, "useNativeViewConfigsInBridgelessMode"); + markFlagAsAccessed(83, "useNativeViewConfigsInBridgelessMode"); flagValue = currentProvider_->useNativeViewConfigsInBridgelessMode(); useNativeViewConfigsInBridgelessMode_ = flagValue; @@ -1532,7 +1550,7 @@ bool ReactNativeFeatureFlagsAccessor::useNestedScrollViewAndroid() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(83, "useNestedScrollViewAndroid"); + markFlagAsAccessed(84, "useNestedScrollViewAndroid"); flagValue = currentProvider_->useNestedScrollViewAndroid(); useNestedScrollViewAndroid_ = flagValue; @@ -1550,7 +1568,7 @@ bool ReactNativeFeatureFlagsAccessor::useSharedAnimatedBackend() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(84, "useSharedAnimatedBackend"); + markFlagAsAccessed(85, "useSharedAnimatedBackend"); flagValue = currentProvider_->useSharedAnimatedBackend(); useSharedAnimatedBackend_ = flagValue; @@ -1568,7 +1586,7 @@ bool ReactNativeFeatureFlagsAccessor::useTraitHiddenOnAndroid() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(85, "useTraitHiddenOnAndroid"); + markFlagAsAccessed(86, "useTraitHiddenOnAndroid"); flagValue = currentProvider_->useTraitHiddenOnAndroid(); useTraitHiddenOnAndroid_ = flagValue; @@ -1586,7 +1604,7 @@ bool ReactNativeFeatureFlagsAccessor::useTurboModuleInterop() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(86, "useTurboModuleInterop"); + markFlagAsAccessed(87, "useTurboModuleInterop"); flagValue = currentProvider_->useTurboModuleInterop(); useTurboModuleInterop_ = flagValue; @@ -1604,7 +1622,7 @@ double ReactNativeFeatureFlagsAccessor::viewCullingOutsetRatio() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(87, "viewCullingOutsetRatio"); + markFlagAsAccessed(88, "viewCullingOutsetRatio"); flagValue = currentProvider_->viewCullingOutsetRatio(); viewCullingOutsetRatio_ = flagValue; @@ -1622,7 +1640,7 @@ bool ReactNativeFeatureFlagsAccessor::viewTransitionEnabled() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(88, "viewTransitionEnabled"); + markFlagAsAccessed(89, "viewTransitionEnabled"); flagValue = currentProvider_->viewTransitionEnabled(); viewTransitionEnabled_ = flagValue; @@ -1640,7 +1658,7 @@ bool ReactNativeFeatureFlagsAccessor::viewTransitionUseHardwareBitmapAndroid() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(89, "viewTransitionUseHardwareBitmapAndroid"); + markFlagAsAccessed(90, "viewTransitionUseHardwareBitmapAndroid"); flagValue = currentProvider_->viewTransitionUseHardwareBitmapAndroid(); viewTransitionUseHardwareBitmapAndroid_ = flagValue; @@ -1658,7 +1676,7 @@ double ReactNativeFeatureFlagsAccessor::virtualViewPrerenderRatio() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(90, "virtualViewPrerenderRatio"); + markFlagAsAccessed(91, "virtualViewPrerenderRatio"); flagValue = currentProvider_->virtualViewPrerenderRatio(); virtualViewPrerenderRatio_ = flagValue; diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h index 5233e208552e..b3a4d3a1dd85 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<> + * @generated SignedSource<<8a2af1b0fe78648b4ded0504f1b05b27>> */ /** @@ -50,6 +50,7 @@ class ReactNativeFeatureFlagsAccessor { bool enableAndroidAutoOffscreenCompositingForElevation(); bool enableAndroidTextMeasurementOptimizations(); bool enableAsyncDiskCacheCheckInMultiSourceImageAndroid(); + bool enableAsyncSettingsManagerUpdatesIOS(); bool enableBridgelessArchitecture(); bool enableCppPropsIteratorSetter(); bool enableCustomFocusSearchOnClippedElementsAndroid(); @@ -136,7 +137,7 @@ class ReactNativeFeatureFlagsAccessor { std::unique_ptr currentProvider_; bool wasOverridden_; - std::array, 91> accessedFeatureFlags_; + std::array, 92> accessedFeatureFlags_; std::atomic> commonTestFlag_; std::atomic> cdpInteractionMetricsEnabled_; @@ -154,6 +155,7 @@ class ReactNativeFeatureFlagsAccessor { std::atomic> enableAndroidAutoOffscreenCompositingForElevation_; std::atomic> enableAndroidTextMeasurementOptimizations_; std::atomic> enableAsyncDiskCacheCheckInMultiSourceImageAndroid_; + std::atomic> enableAsyncSettingsManagerUpdatesIOS_; std::atomic> enableBridgelessArchitecture_; std::atomic> enableCppPropsIteratorSetter_; std::atomic> enableCustomFocusSearchOnClippedElementsAndroid_; diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h index 18e5f25979bc..0948fe29bcee 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<<9218c0c441b0b937737d2fae33fd1e35>> + * @generated SignedSource<> */ /** @@ -93,6 +93,10 @@ class ReactNativeFeatureFlagsDefaults : public ReactNativeFeatureFlagsProvider { return false; } + bool enableAsyncSettingsManagerUpdatesIOS() override { + return false; + } + bool enableBridgelessArchitecture() override { return true; } diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDynamicProvider.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDynamicProvider.h index 9113ffb35fdc..e0d968cef153 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDynamicProvider.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDynamicProvider.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<419516aab11d7e44485bb29e696a75dd>> + * @generated SignedSource<> */ /** @@ -191,6 +191,15 @@ class ReactNativeFeatureFlagsDynamicProvider : public ReactNativeFeatureFlagsDef return ReactNativeFeatureFlagsDefaults::enableAsyncDiskCacheCheckInMultiSourceImageAndroid(); } + bool enableAsyncSettingsManagerUpdatesIOS() override { + auto value = values_["enableAsyncSettingsManagerUpdatesIOS"]; + if (!value.isNull()) { + return value.getBool(); + } + + return ReactNativeFeatureFlagsDefaults::enableAsyncSettingsManagerUpdatesIOS(); + } + bool enableBridgelessArchitecture() override { auto value = values_["enableBridgelessArchitecture"]; if (!value.isNull()) { diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h index a29aacbef32e..85fb6ca9f379 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<20cd3794c25292e956b0cf3bad90a6f4>> */ /** @@ -43,6 +43,7 @@ class ReactNativeFeatureFlagsProvider { virtual bool enableAndroidAutoOffscreenCompositingForElevation() = 0; virtual bool enableAndroidTextMeasurementOptimizations() = 0; virtual bool enableAsyncDiskCacheCheckInMultiSourceImageAndroid() = 0; + virtual bool enableAsyncSettingsManagerUpdatesIOS() = 0; virtual bool enableBridgelessArchitecture() = 0; virtual bool enableCppPropsIteratorSetter() = 0; virtual bool enableCustomFocusSearchOnClippedElementsAndroid() = 0; diff --git a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp index 65dad77ae6f4..6637a118b9bd 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<> + * @generated SignedSource<> */ /** @@ -124,6 +124,11 @@ bool NativeReactNativeFeatureFlags::enableAsyncDiskCacheCheckInMultiSourceImageA return ReactNativeFeatureFlags::enableAsyncDiskCacheCheckInMultiSourceImageAndroid(); } +bool NativeReactNativeFeatureFlags::enableAsyncSettingsManagerUpdatesIOS( + jsi::Runtime& /*runtime*/) { + return ReactNativeFeatureFlags::enableAsyncSettingsManagerUpdatesIOS(); +} + bool NativeReactNativeFeatureFlags::enableBridgelessArchitecture( jsi::Runtime& /*runtime*/) { return ReactNativeFeatureFlags::enableBridgelessArchitecture(); diff --git a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h index 9e1273933741..c4de7f755db4 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<> + * @generated SignedSource<<8c268a7135862b4565c9976f30c607a7>> */ /** @@ -70,6 +70,8 @@ class NativeReactNativeFeatureFlags bool enableAsyncDiskCacheCheckInMultiSourceImageAndroid(jsi::Runtime& runtime); + bool enableAsyncSettingsManagerUpdatesIOS(jsi::Runtime& runtime); + bool enableBridgelessArchitecture(jsi::Runtime& runtime); bool enableCppPropsIteratorSetter(jsi::Runtime& runtime); diff --git a/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js b/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js index 592bc1dc87ec..67400552c4bb 100644 --- a/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js +++ b/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js @@ -225,6 +225,17 @@ const definitions: FeatureFlagDefinitions = { }, ossReleaseStage: 'none', }, + enableAsyncSettingsManagerUpdatesIOS: { + defaultValue: false, + metadata: { + dateAdded: '2026-10-10', + description: + 'Process SettingsManager defaults notifications on a dedicated serial queue on iOS.', + expectedReleaseValue: true, + purpose: 'experimentation', + }, + ossReleaseStage: 'none', + }, enableBridgelessArchitecture: { defaultValue: true, metadata: { diff --git a/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js b/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js index 958225bf8e88..02c9c7a5b392 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<> + * @generated SignedSource<> * @flow strict * @noformat */ @@ -66,6 +66,7 @@ export type ReactNativeFeatureFlags = Readonly<{ enableAndroidAutoOffscreenCompositingForElevation: Getter, enableAndroidTextMeasurementOptimizations: Getter, enableAsyncDiskCacheCheckInMultiSourceImageAndroid: Getter, + enableAsyncSettingsManagerUpdatesIOS: Getter, enableBridgelessArchitecture: Getter, enableCppPropsIteratorSetter: Getter, enableCustomFocusSearchOnClippedElementsAndroid: Getter, @@ -286,6 +287,10 @@ export const enableAndroidTextMeasurementOptimizations: Getter = create * Runs multi-source image disk-cache checks asynchronously on Android. */ export const enableAsyncDiskCacheCheckInMultiSourceImageAndroid: Getter = createNativeFlagGetter('enableAsyncDiskCacheCheckInMultiSourceImageAndroid', false); +/** + * Process SettingsManager defaults notifications on a dedicated serial queue on iOS. + */ +export const enableAsyncSettingsManagerUpdatesIOS: Getter = createNativeFlagGetter('enableAsyncSettingsManagerUpdatesIOS', false); /** * Feature flag to enable the new bridgeless architecture. */ diff --git a/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js b/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js index b5585a64a217..82eb167d78c4 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<<26f30821669e81ddb8c654ea71bbaca6>> + * @generated SignedSource<> * @flow strict * @noformat */ @@ -41,6 +41,7 @@ export interface Spec extends TurboModule { readonly enableAndroidAutoOffscreenCompositingForElevation?: () => boolean; readonly enableAndroidTextMeasurementOptimizations?: () => boolean; readonly enableAsyncDiskCacheCheckInMultiSourceImageAndroid?: () => boolean; + readonly enableAsyncSettingsManagerUpdatesIOS?: () => boolean; readonly enableBridgelessArchitecture?: () => boolean; readonly enableCppPropsIteratorSetter?: () => boolean; readonly enableCustomFocusSearchOnClippedElementsAndroid?: () => boolean;