From 1a5db884f698d22ed19d02b52ba42e852da55d99 Mon Sep 17 00:00:00 2001 From: "jh.xiong" Date: Tue, 13 Oct 2026 07:23:13 -0700 Subject: [PATCH 1/8] Preserve lazy ViewManager initialization in UIManager (#58097) Summary: - Preserve lazy ViewManager property descriptors when composing UIManager. - Avoid eagerly invoking lazy ViewManager getters and unnecessary getConstantsForViewManager calls during Bridgeless initialization. - Add regression coverage for lazy, own, enumerable and one-time getter behavior. - Platform scope: This targets the Android Bridgeless lazy ViewManager path. iOS does not currently expose this lazy getter path, so no iOS runtime behavior or performance change is expected. [ANDROID] [FIXED] - Avoid unnecessary getConstantsForViewManager calls during UIManager initialization. Pull Request resolved: https://github.com/react/react-native/pull/58097 Test Plan: - `yarn flow-check` - `yarn test packages/react-native/Libraries/ReactNative --runInBand` - `yarn lint --quiet` - `yarn format-check` - Verified with Android RNTester offlineDebug that startup no longer triggers eager getConstantsForViewManager calls. Reviewed By: cipolleschi Differential Revision: D124967747 Pulled By: javache fbshipit-source-id: 1a4daf139b555ed266d5a7d3a0b90ebb02cfe5be --- .../Libraries/ReactNative/UIManager.js | 39 +++++++++- .../ReactNative/__tests__/UIManager-test.js | 74 +++++++++++++++++++ 2 files changed, 110 insertions(+), 3 deletions(-) create mode 100644 packages/react-native/Libraries/ReactNative/__tests__/UIManager-test.js diff --git a/packages/react-native/Libraries/ReactNative/UIManager.js b/packages/react-native/Libraries/ReactNative/UIManager.js index 3d2729530286..80e63bbaa1fa 100644 --- a/packages/react-native/Libraries/ReactNative/UIManager.js +++ b/packages/react-native/Libraries/ReactNative/UIManager.js @@ -8,6 +8,7 @@ * @format */ +import type {UnsafeObject} from '../Types/CodegenTypes'; import type {UIManagerJSInterface} from '../Types/UIManagerJSInterface'; import {getFabricUIManager} from './FabricUIManager'; @@ -23,9 +24,26 @@ const UIManagerImpl: UIManagerJSInterface = ? require('./BridgelessUIManager').default : require('./PaperUIManager').default; -// $FlowFixMe[cannot-spread-interface] -const UIManager: UIManagerJSInterface = { - ...UIManagerImpl, +const UIManagerOverrides = { + /** + * Determines the location on screen, width, and height of the given view and + * returns the values via an async callback. If successful, the callback will + * be called with the following arguments: + * + * - x + * - y + * - width + * - height + * - pageX + * - pageY + * + * Note that these measurements are not available until after the rendering + * has been completed in native. If you need the measurements as soon as + * possible, consider using the [`onLayout` + * prop](docs/view.html#onlayout) instead. + * + * @deprecated Use `ref.measure` instead. + */ measure( reactTag: number, callback: ( @@ -190,4 +208,19 @@ const UIManager: UIManagerJSInterface = { }, }; +// Copy property descriptors instead of spreading UIManagerImpl. In Bridgeless +// mode, UIManagerImpl may define enumerable lazy ViewManager getters. Spreading +// the object would invoke every getter during module initialization. +// $FlowFixMe[incompatible-type] Flow cannot infer properties from descriptors. +const UIManager: UIManagerJSInterface = Object.create( + Object.getPrototypeOf(UIManagerImpl), + { + ...Object.getOwnPropertyDescriptors( + // $FlowFixMe[class-object-subtyping] UIManagerImpl is a runtime object. + UIManagerImpl, + ), + ...Object.getOwnPropertyDescriptors(UIManagerOverrides), + }, +); + export default UIManager; diff --git a/packages/react-native/Libraries/ReactNative/__tests__/UIManager-test.js b/packages/react-native/Libraries/ReactNative/__tests__/UIManager-test.js new file mode 100644 index 000000000000..9e2633eb48be --- /dev/null +++ b/packages/react-native/Libraries/ReactNative/__tests__/UIManager-test.js @@ -0,0 +1,74 @@ +/** + * 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. + * + * @flow strict-local + * @format + */ + +'use strict'; + +jest.mock('../../Utilities/Platform', () => ({ + OS: 'android', + select: spec => spec.android ?? spec.native ?? spec.default, +})); +jest.unmock('../UIManager'); + +describe('UIManager', () => { + it('preserves lazy ViewManager getters when composing the Bridgeless implementation', () => { + const originalBridgelessValue = global.RN$Bridgeless; + const originalGetConstants = global.RN$LegacyInterop_UIManager_getConstants; + const originalGetConstantsForViewManager = + global.RN$LegacyInterop_UIManager_getConstantsForViewManager; + const originalGetDefaultEventTypes = + global.RN$LegacyInterop_UIManager_getDefaultEventTypes; + const viewManagerConfig = {Commands: {focus: 1}}; + const getConstants = jest.fn(() => ({ + LazyViewManagersEnabled: true, + ViewManagerNames: ['RCTTestView'], + })); + const getConstantsForViewManager = jest.fn(() => viewManagerConfig); + + jest.resetModules(); + try { + // $FlowExpectedError[cannot-write] + global.RN$Bridgeless = true; + // $FlowExpectedError[cannot-write] + global.RN$LegacyInterop_UIManager_getConstants = getConstants; + // $FlowExpectedError[cannot-write] + global.RN$LegacyInterop_UIManager_getConstantsForViewManager = + getConstantsForViewManager; + // $FlowExpectedError[cannot-write] + global.RN$LegacyInterop_UIManager_getDefaultEventTypes = jest.fn( + () => ({}), + ); + + const UIManager = require('../UIManager').default; + + expect(getConstants).toHaveBeenCalledTimes(1); + expect(getConstantsForViewManager).not.toHaveBeenCalled(); + expect( + Object.getOwnPropertyDescriptor(UIManager, 'RCTTestView'), + ).toBeDefined(); + expect(Object.keys(UIManager)).toContain('RCTTestView'); + + expect(Reflect.get(UIManager, 'RCTTestView')).toBe(viewManagerConfig); + expect(Reflect.get(UIManager, 'RCTTestView')).toBe(viewManagerConfig); + expect(getConstantsForViewManager).toHaveBeenCalledTimes(1); + } finally { + // $FlowExpectedError[cannot-write] + global.RN$Bridgeless = originalBridgelessValue; + // $FlowExpectedError[cannot-write] + global.RN$LegacyInterop_UIManager_getConstants = originalGetConstants; + // $FlowExpectedError[cannot-write] + global.RN$LegacyInterop_UIManager_getConstantsForViewManager = + originalGetConstantsForViewManager; + // $FlowExpectedError[cannot-write] + global.RN$LegacyInterop_UIManager_getDefaultEventTypes = + originalGetDefaultEventTypes; + jest.resetModules(); + } + }); +}); From edfe42e3471af6bf96f8d65b55be19df0ee0b90d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hanno=20J=2E=20Go=CC=88decke?= Date: Thu, 15 Oct 2026 10:46:47 +0200 Subject: [PATCH 2/8] add discordUiManagerLazyPropertiesOptimization feature flag --- .../featureflags/ReactNativeFeatureFlags.kt | 8 +- .../ReactNativeFeatureFlagsCxxAccessor.kt | 12 +- .../ReactNativeFeatureFlagsCxxInterop.kt | 4 +- .../ReactNativeFeatureFlagsDefaults.kt | 4 +- .../ReactNativeFeatureFlagsLocalAccessor.kt | 13 +- .../ReactNativeFeatureFlagsProvider.kt | 4 +- .../JReactNativeFeatureFlagsCxxInterop.cpp | 16 +- .../JReactNativeFeatureFlagsCxxInterop.h | 5 +- .../featureflags/ReactNativeFeatureFlags.cpp | 6 +- .../featureflags/ReactNativeFeatureFlags.h | 7 +- .../ReactNativeFeatureFlagsAccessor.cpp | 196 ++++++++++-------- .../ReactNativeFeatureFlagsAccessor.h | 6 +- .../ReactNativeFeatureFlagsDefaults.h | 6 +- .../ReactNativeFeatureFlagsDynamicProvider.h | 11 +- .../ReactNativeFeatureFlagsProvider.h | 3 +- .../NativeReactNativeFeatureFlags.cpp | 7 +- .../NativeReactNativeFeatureFlags.h | 4 +- .../ReactNativeFeatureFlags.config.js | 11 + .../featureflags/ReactNativeFeatureFlags.js | 7 +- .../specs/NativeReactNativeFeatureFlags.js | 3 +- 20 files changed, 225 insertions(+), 108 deletions(-) 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 e1828664c363..531b7ea34700 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<<85428eb50bc67ecf13b7a1adb13fcffa>> + * @generated SignedSource<<5754d26f893644b57e7efd2103516c15>> */ /** @@ -90,6 +90,12 @@ public object ReactNativeFeatureFlags { @JvmStatic public fun disableViewPreallocationAndroid(): Boolean = accessor.disableViewPreallocationAndroid() + /** + * Optimize lazy properties in UIManager. + */ + @JvmStatic + public fun discordUiManagerLazyPropertiesOptimization(): Boolean = accessor.discordUiManagerLazyPropertiesOptimization() + /** * When enabled, the accessibilityOrder prop will propagate to native platforms and define the accessibility order. */ 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 6b13d5a0a4da..ef88fca5716c 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<> + * @generated SignedSource<<802bfc9a2e103a88b992558886064b3f>> */ /** @@ -30,6 +30,7 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces private var disableSubviewClippingAndroidCache: Boolean? = null private var disableTextLayoutManagerCacheAndroidCache: Boolean? = null private var disableViewPreallocationAndroidCache: Boolean? = null + private var discordUiManagerLazyPropertiesOptimizationCache: Boolean? = null private var enableAccessibilityOrderCache: Boolean? = null private var enableAccumulatedUpdatesInRawPropsAndroidCache: Boolean? = null private var enableAndroidTextMeasurementOptimizationsCache: Boolean? = null @@ -209,6 +210,15 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces return cached } + override fun discordUiManagerLazyPropertiesOptimization(): Boolean { + var cached = discordUiManagerLazyPropertiesOptimizationCache + if (cached == null) { + cached = ReactNativeFeatureFlagsCxxInterop.discordUiManagerLazyPropertiesOptimization() + discordUiManagerLazyPropertiesOptimizationCache = cached + } + return cached + } + override fun enableAccessibilityOrder(): Boolean { var cached = enableAccessibilityOrderCache 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 fe79bbe1fa89..5b36e4071b90 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<> + * @generated SignedSource<> */ /** @@ -48,6 +48,8 @@ public object ReactNativeFeatureFlagsCxxInterop { @DoNotStrip @JvmStatic public external fun disableViewPreallocationAndroid(): Boolean + @DoNotStrip @JvmStatic public external fun discordUiManagerLazyPropertiesOptimization(): Boolean + @DoNotStrip @JvmStatic public external fun enableAccessibilityOrder(): Boolean @DoNotStrip @JvmStatic public external fun enableAccumulatedUpdatesInRawPropsAndroid(): 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 344c2d8d230c..0f5f19f10daf 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<<8e8b9dacb0ff4927016bf33eaa102005>> + * @generated SignedSource<> */ /** @@ -43,6 +43,8 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi override fun disableViewPreallocationAndroid(): Boolean = false + override fun discordUiManagerLazyPropertiesOptimization(): Boolean = false + override fun enableAccessibilityOrder(): Boolean = false override fun enableAccumulatedUpdatesInRawPropsAndroid(): Boolean = true 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 fdbbe2c1c78e..5a545d2178d6 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<<1d918610fc6dcc5a1448b2dec2234e82>> + * @generated SignedSource<<1afc0b84e52c5cb0743597d5d1247c79>> */ /** @@ -34,6 +34,7 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc private var disableSubviewClippingAndroidCache: Boolean? = null private var disableTextLayoutManagerCacheAndroidCache: Boolean? = null private var disableViewPreallocationAndroidCache: Boolean? = null + private var discordUiManagerLazyPropertiesOptimizationCache: Boolean? = null private var enableAccessibilityOrderCache: Boolean? = null private var enableAccumulatedUpdatesInRawPropsAndroidCache: Boolean? = null private var enableAndroidTextMeasurementOptimizationsCache: Boolean? = null @@ -223,6 +224,16 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc return cached } + override fun discordUiManagerLazyPropertiesOptimization(): Boolean { + var cached = discordUiManagerLazyPropertiesOptimizationCache + if (cached == null) { + cached = currentProvider.discordUiManagerLazyPropertiesOptimization() + accessedFeatureFlags.add("discordUiManagerLazyPropertiesOptimization") + discordUiManagerLazyPropertiesOptimizationCache = cached + } + return cached + } + override fun enableAccessibilityOrder(): Boolean { var cached = enableAccessibilityOrderCache 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 158836790ad4..1f3029e0c687 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<<6e4676a533128c0d692510669c9a69d3>> + * @generated SignedSource<<81fbfaaada3a546a79b93fd97c96f656>> */ /** @@ -43,6 +43,8 @@ public interface ReactNativeFeatureFlagsProvider { @DoNotStrip public fun disableViewPreallocationAndroid(): Boolean + @DoNotStrip public fun discordUiManagerLazyPropertiesOptimization(): Boolean + @DoNotStrip public fun enableAccessibilityOrder(): Boolean @DoNotStrip public fun enableAccumulatedUpdatesInRawPropsAndroid(): 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 bee73efa498a..01dd4c5b17b8 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<<22e430660a18eb259806cad2c5644b48>> + * @generated SignedSource<<47eea5c86d3f5bddedd0f4fb00b32aab>> */ /** @@ -99,6 +99,12 @@ class ReactNativeFeatureFlagsJavaProvider return method(javaProvider_); } + bool discordUiManagerLazyPropertiesOptimization() override { + static const auto method = + getReactNativeFeatureFlagsProviderJavaClass()->getMethod("discordUiManagerLazyPropertiesOptimization"); + return method(javaProvider_); + } + bool enableAccessibilityOrder() override { static const auto method = getReactNativeFeatureFlagsProviderJavaClass()->getMethod("enableAccessibilityOrder"); @@ -681,6 +687,11 @@ bool JReactNativeFeatureFlagsCxxInterop::disableViewPreallocationAndroid( return ReactNativeFeatureFlags::disableViewPreallocationAndroid(); } +bool JReactNativeFeatureFlagsCxxInterop::discordUiManagerLazyPropertiesOptimization( + facebook::jni::alias_ref /*unused*/) { + return ReactNativeFeatureFlags::discordUiManagerLazyPropertiesOptimization(); +} + bool JReactNativeFeatureFlagsCxxInterop::enableAccessibilityOrder( facebook::jni::alias_ref /*unused*/) { return ReactNativeFeatureFlags::enableAccessibilityOrder(); @@ -1182,6 +1193,9 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() { makeNativeMethod( "disableViewPreallocationAndroid", JReactNativeFeatureFlagsCxxInterop::disableViewPreallocationAndroid), + makeNativeMethod( + "discordUiManagerLazyPropertiesOptimization", + JReactNativeFeatureFlagsCxxInterop::discordUiManagerLazyPropertiesOptimization), makeNativeMethod( "enableAccessibilityOrder", JReactNativeFeatureFlagsCxxInterop::enableAccessibilityOrder), 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 e8d285ad68f3..ba510e3a8298 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<<6caac4983daec1354baec9e589b5684e>> + * @generated SignedSource<<9e727309ab94fe32fee937502251b4b0>> */ /** @@ -60,6 +60,9 @@ class JReactNativeFeatureFlagsCxxInterop static bool disableViewPreallocationAndroid( facebook::jni::alias_ref); + static bool discordUiManagerLazyPropertiesOptimization( + facebook::jni::alias_ref); + static bool enableAccessibilityOrder( 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 57b3166bc9c4..2012cf058463 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<81476221c28efc73ed084d2ed04b380d>> */ /** @@ -66,6 +66,10 @@ bool ReactNativeFeatureFlags::disableViewPreallocationAndroid() { return getAccessor().disableViewPreallocationAndroid(); } +bool ReactNativeFeatureFlags::discordUiManagerLazyPropertiesOptimization() { + return getAccessor().discordUiManagerLazyPropertiesOptimization(); +} + bool ReactNativeFeatureFlags::enableAccessibilityOrder() { return getAccessor().enableAccessibilityOrder(); } diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h index 0e84e4d263ea..40b71a65d0f3 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<> */ /** @@ -89,6 +89,11 @@ class ReactNativeFeatureFlags { */ RN_EXPORT static bool disableViewPreallocationAndroid(); + /** + * Optimize lazy properties in UIManager. + */ + RN_EXPORT static bool discordUiManagerLazyPropertiesOptimization(); + /** * When enabled, the accessibilityOrder prop will propagate to native platforms and define the accessibility order. */ diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp index 720185d62521..cf852b33a96b 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<<2b7dcf61f7016c4823f7d99d797e8b19>> + * @generated SignedSource<<3169c783d2059d89e0942a07fe20b042>> */ /** @@ -209,6 +209,24 @@ bool ReactNativeFeatureFlagsAccessor::disableViewPreallocationAndroid() { return flagValue.value(); } +bool ReactNativeFeatureFlagsAccessor::discordUiManagerLazyPropertiesOptimization() { + auto flagValue = discordUiManagerLazyPropertiesOptimization_.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, "discordUiManagerLazyPropertiesOptimization"); + + flagValue = currentProvider_->discordUiManagerLazyPropertiesOptimization(); + discordUiManagerLazyPropertiesOptimization_ = flagValue; + } + + return flagValue.value(); +} + bool ReactNativeFeatureFlagsAccessor::enableAccessibilityOrder() { auto flagValue = enableAccessibilityOrder_.load(); @@ -218,7 +236,7 @@ bool ReactNativeFeatureFlagsAccessor::enableAccessibilityOrder() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(10, "enableAccessibilityOrder"); + markFlagAsAccessed(11, "enableAccessibilityOrder"); flagValue = currentProvider_->enableAccessibilityOrder(); enableAccessibilityOrder_ = flagValue; @@ -236,7 +254,7 @@ bool ReactNativeFeatureFlagsAccessor::enableAccumulatedUpdatesInRawPropsAndroid( // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(11, "enableAccumulatedUpdatesInRawPropsAndroid"); + markFlagAsAccessed(12, "enableAccumulatedUpdatesInRawPropsAndroid"); flagValue = currentProvider_->enableAccumulatedUpdatesInRawPropsAndroid(); enableAccumulatedUpdatesInRawPropsAndroid_ = flagValue; @@ -254,7 +272,7 @@ bool ReactNativeFeatureFlagsAccessor::enableAndroidTextMeasurementOptimizations( // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(12, "enableAndroidTextMeasurementOptimizations"); + markFlagAsAccessed(13, "enableAndroidTextMeasurementOptimizations"); flagValue = currentProvider_->enableAndroidTextMeasurementOptimizations(); enableAndroidTextMeasurementOptimizations_ = flagValue; @@ -272,7 +290,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(13, "enableBridgelessArchitecture"); + markFlagAsAccessed(14, "enableBridgelessArchitecture"); flagValue = currentProvider_->enableBridgelessArchitecture(); enableBridgelessArchitecture_ = flagValue; @@ -290,7 +308,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(14, "enableCppPropsIteratorSetter"); + markFlagAsAccessed(15, "enableCppPropsIteratorSetter"); flagValue = currentProvider_->enableCppPropsIteratorSetter(); enableCppPropsIteratorSetter_ = flagValue; @@ -308,7 +326,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(15, "enableCustomFocusSearchOnClippedElementsAndroid"); + markFlagAsAccessed(16, "enableCustomFocusSearchOnClippedElementsAndroid"); flagValue = currentProvider_->enableCustomFocusSearchOnClippedElementsAndroid(); enableCustomFocusSearchOnClippedElementsAndroid_ = flagValue; @@ -326,7 +344,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(16, "enableDestroyShadowTreeRevisionAsync"); + markFlagAsAccessed(17, "enableDestroyShadowTreeRevisionAsync"); flagValue = currentProvider_->enableDestroyShadowTreeRevisionAsync(); enableDestroyShadowTreeRevisionAsync_ = flagValue; @@ -344,7 +362,7 @@ bool ReactNativeFeatureFlagsAccessor::enableDifferentiatorMutationVectorPrealloc // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(17, "enableDifferentiatorMutationVectorPreallocation"); + markFlagAsAccessed(18, "enableDifferentiatorMutationVectorPreallocation"); flagValue = currentProvider_->enableDifferentiatorMutationVectorPreallocation(); enableDifferentiatorMutationVectorPreallocation_ = flagValue; @@ -362,7 +380,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(18, "enableDoubleMeasurementFixAndroid"); + markFlagAsAccessed(19, "enableDoubleMeasurementFixAndroid"); flagValue = currentProvider_->enableDoubleMeasurementFixAndroid(); enableDoubleMeasurementFixAndroid_ = flagValue; @@ -380,7 +398,7 @@ bool ReactNativeFeatureFlagsAccessor::enableEagerMainQueueModulesOnIOS() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(19, "enableEagerMainQueueModulesOnIOS"); + markFlagAsAccessed(20, "enableEagerMainQueueModulesOnIOS"); flagValue = currentProvider_->enableEagerMainQueueModulesOnIOS(); enableEagerMainQueueModulesOnIOS_ = flagValue; @@ -398,7 +416,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(20, "enableEagerRootViewAttachment"); + markFlagAsAccessed(21, "enableEagerRootViewAttachment"); flagValue = currentProvider_->enableEagerRootViewAttachment(); enableEagerRootViewAttachment_ = flagValue; @@ -416,7 +434,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(21, "enableExclusivePropsUpdateAndroid"); + markFlagAsAccessed(22, "enableExclusivePropsUpdateAndroid"); flagValue = currentProvider_->enableExclusivePropsUpdateAndroid(); enableExclusivePropsUpdateAndroid_ = flagValue; @@ -434,7 +452,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(22, "enableFabricCommitBranching"); + markFlagAsAccessed(23, "enableFabricCommitBranching"); flagValue = currentProvider_->enableFabricCommitBranching(); enableFabricCommitBranching_ = flagValue; @@ -452,7 +470,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(23, "enableFabricLogs"); + markFlagAsAccessed(24, "enableFabricLogs"); flagValue = currentProvider_->enableFabricLogs(); enableFabricLogs_ = flagValue; @@ -470,7 +488,7 @@ bool ReactNativeFeatureFlagsAccessor::enableFabricRenderer() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(24, "enableFabricRenderer"); + markFlagAsAccessed(25, "enableFabricRenderer"); flagValue = currentProvider_->enableFabricRenderer(); enableFabricRenderer_ = flagValue; @@ -488,7 +506,7 @@ bool ReactNativeFeatureFlagsAccessor::enableFixForParentTagDuringReparenting() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(25, "enableFixForParentTagDuringReparenting"); + markFlagAsAccessed(26, "enableFixForParentTagDuringReparenting"); flagValue = currentProvider_->enableFixForParentTagDuringReparenting(); enableFixForParentTagDuringReparenting_ = flagValue; @@ -506,7 +524,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(26, "enableFontScaleChangesUpdatingLayout"); + markFlagAsAccessed(27, "enableFontScaleChangesUpdatingLayout"); flagValue = currentProvider_->enableFontScaleChangesUpdatingLayout(); enableFontScaleChangesUpdatingLayout_ = flagValue; @@ -524,7 +542,7 @@ bool ReactNativeFeatureFlagsAccessor::enableIOSExperimentalAutoFocusImplementati // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(27, "enableIOSExperimentalAutoFocusImplementation"); + markFlagAsAccessed(28, "enableIOSExperimentalAutoFocusImplementation"); flagValue = currentProvider_->enableIOSExperimentalAutoFocusImplementation(); enableIOSExperimentalAutoFocusImplementation_ = flagValue; @@ -542,7 +560,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(28, "enableIOSTextBaselineOffsetPerLine"); + markFlagAsAccessed(29, "enableIOSTextBaselineOffsetPerLine"); flagValue = currentProvider_->enableIOSTextBaselineOffsetPerLine(); enableIOSTextBaselineOffsetPerLine_ = flagValue; @@ -560,7 +578,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(29, "enableIOSViewClipToPaddingBox"); + markFlagAsAccessed(30, "enableIOSViewClipToPaddingBox"); flagValue = currentProvider_->enableIOSViewClipToPaddingBox(); enableIOSViewClipToPaddingBox_ = flagValue; @@ -578,7 +596,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(30, "enableImagePrefetchingAndroid"); + markFlagAsAccessed(31, "enableImagePrefetchingAndroid"); flagValue = currentProvider_->enableImagePrefetchingAndroid(); enableImagePrefetchingAndroid_ = flagValue; @@ -596,7 +614,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(31, "enableImmediateUpdateModeForContentOffsetChanges"); + markFlagAsAccessed(32, "enableImmediateUpdateModeForContentOffsetChanges"); flagValue = currentProvider_->enableImmediateUpdateModeForContentOffsetChanges(); enableImmediateUpdateModeForContentOffsetChanges_ = flagValue; @@ -614,7 +632,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(32, "enableImperativeFocus"); + markFlagAsAccessed(33, "enableImperativeFocus"); flagValue = currentProvider_->enableImperativeFocus(); enableImperativeFocus_ = flagValue; @@ -632,7 +650,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(33, "enableInteropViewManagerClassLookUpOptimizationIOS"); + markFlagAsAccessed(34, "enableInteropViewManagerClassLookUpOptimizationIOS"); flagValue = currentProvider_->enableInteropViewManagerClassLookUpOptimizationIOS(); enableInteropViewManagerClassLookUpOptimizationIOS_ = flagValue; @@ -650,7 +668,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(34, "enableIntersectionObserverByDefault"); + markFlagAsAccessed(35, "enableIntersectionObserverByDefault"); flagValue = currentProvider_->enableIntersectionObserverByDefault(); enableIntersectionObserverByDefault_ = flagValue; @@ -668,7 +686,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(35, "enableKeyEvents"); + markFlagAsAccessed(36, "enableKeyEvents"); flagValue = currentProvider_->enableKeyEvents(); enableKeyEvents_ = flagValue; @@ -686,7 +704,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(36, "enableLayoutAnimationsOnAndroid"); + markFlagAsAccessed(37, "enableLayoutAnimationsOnAndroid"); flagValue = currentProvider_->enableLayoutAnimationsOnAndroid(); enableLayoutAnimationsOnAndroid_ = flagValue; @@ -704,7 +722,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(37, "enableLayoutAnimationsOnIOS"); + markFlagAsAccessed(38, "enableLayoutAnimationsOnIOS"); flagValue = currentProvider_->enableLayoutAnimationsOnIOS(); enableLayoutAnimationsOnIOS_ = flagValue; @@ -722,7 +740,7 @@ bool ReactNativeFeatureFlagsAccessor::enableMainQueueCoordinatorOnIOS() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(38, "enableMainQueueCoordinatorOnIOS"); + markFlagAsAccessed(39, "enableMainQueueCoordinatorOnIOS"); flagValue = currentProvider_->enableMainQueueCoordinatorOnIOS(); enableMainQueueCoordinatorOnIOS_ = flagValue; @@ -740,7 +758,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(39, "enableModuleArgumentNSNullConversionIOS"); + markFlagAsAccessed(40, "enableModuleArgumentNSNullConversionIOS"); flagValue = currentProvider_->enableModuleArgumentNSNullConversionIOS(); enableModuleArgumentNSNullConversionIOS_ = flagValue; @@ -758,7 +776,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(40, "enableMutationObserverByDefault"); + markFlagAsAccessed(41, "enableMutationObserverByDefault"); flagValue = currentProvider_->enableMutationObserverByDefault(); enableMutationObserverByDefault_ = flagValue; @@ -776,7 +794,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(41, "enableNativeCSSParsing"); + markFlagAsAccessed(42, "enableNativeCSSParsing"); flagValue = currentProvider_->enableNativeCSSParsing(); enableNativeCSSParsing_ = flagValue; @@ -794,7 +812,7 @@ bool ReactNativeFeatureFlagsAccessor::enableNativeViewPropTransformations() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(42, "enableNativeViewPropTransformations"); + markFlagAsAccessed(43, "enableNativeViewPropTransformations"); flagValue = currentProvider_->enableNativeViewPropTransformations(); enableNativeViewPropTransformations_ = flagValue; @@ -812,7 +830,7 @@ bool ReactNativeFeatureFlagsAccessor::enableNetworkEventReporting() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(43, "enableNetworkEventReporting"); + markFlagAsAccessed(44, "enableNetworkEventReporting"); flagValue = currentProvider_->enableNetworkEventReporting(); enableNetworkEventReporting_ = flagValue; @@ -830,7 +848,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(44, "enablePreparedTextLayout"); + markFlagAsAccessed(45, "enablePreparedTextLayout"); flagValue = currentProvider_->enablePreparedTextLayout(); enablePreparedTextLayout_ = flagValue; @@ -848,7 +866,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(45, "enablePropsUpdateReconciliationAndroid"); + markFlagAsAccessed(46, "enablePropsUpdateReconciliationAndroid"); flagValue = currentProvider_->enablePropsUpdateReconciliationAndroid(); enablePropsUpdateReconciliationAndroid_ = flagValue; @@ -866,7 +884,7 @@ bool ReactNativeFeatureFlagsAccessor::enableSchedulerDelegateInvalidation() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(46, "enableSchedulerDelegateInvalidation"); + markFlagAsAccessed(47, "enableSchedulerDelegateInvalidation"); flagValue = currentProvider_->enableSchedulerDelegateInvalidation(); enableSchedulerDelegateInvalidation_ = flagValue; @@ -884,7 +902,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(47, "enableSwiftUIBasedFilters"); + markFlagAsAccessed(48, "enableSwiftUIBasedFilters"); flagValue = currentProvider_->enableSwiftUIBasedFilters(); enableSwiftUIBasedFilters_ = flagValue; @@ -902,7 +920,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(48, "enableViewCulling"); + markFlagAsAccessed(49, "enableViewCulling"); flagValue = currentProvider_->enableViewCulling(); enableViewCulling_ = flagValue; @@ -920,7 +938,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(49, "enableViewRecycling"); + markFlagAsAccessed(50, "enableViewRecycling"); flagValue = currentProvider_->enableViewRecycling(); enableViewRecycling_ = flagValue; @@ -938,7 +956,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(50, "enableViewRecyclingForImage"); + markFlagAsAccessed(51, "enableViewRecyclingForImage"); flagValue = currentProvider_->enableViewRecyclingForImage(); enableViewRecyclingForImage_ = flagValue; @@ -956,7 +974,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(51, "enableViewRecyclingForScrollView"); + markFlagAsAccessed(52, "enableViewRecyclingForScrollView"); flagValue = currentProvider_->enableViewRecyclingForScrollView(); enableViewRecyclingForScrollView_ = flagValue; @@ -974,7 +992,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(52, "enableViewRecyclingForText"); + markFlagAsAccessed(53, "enableViewRecyclingForText"); flagValue = currentProvider_->enableViewRecyclingForText(); enableViewRecyclingForText_ = flagValue; @@ -992,7 +1010,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(53, "enableViewRecyclingForView"); + markFlagAsAccessed(54, "enableViewRecyclingForView"); flagValue = currentProvider_->enableViewRecyclingForView(); enableViewRecyclingForView_ = flagValue; @@ -1010,7 +1028,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(54, "enableVirtualViewContainerStateExperimental"); + markFlagAsAccessed(55, "enableVirtualViewContainerStateExperimental"); flagValue = currentProvider_->enableVirtualViewContainerStateExperimental(); enableVirtualViewContainerStateExperimental_ = flagValue; @@ -1028,7 +1046,7 @@ bool ReactNativeFeatureFlagsAccessor::enableVirtualViewDebugFeatures() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(55, "enableVirtualViewDebugFeatures"); + markFlagAsAccessed(56, "enableVirtualViewDebugFeatures"); flagValue = currentProvider_->enableVirtualViewDebugFeatures(); enableVirtualViewDebugFeatures_ = flagValue; @@ -1046,7 +1064,7 @@ bool ReactNativeFeatureFlagsAccessor::fixDifferentiatorParentTagForUnflattenCase // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(56, "fixDifferentiatorParentTagForUnflattenCase"); + markFlagAsAccessed(57, "fixDifferentiatorParentTagForUnflattenCase"); flagValue = currentProvider_->fixDifferentiatorParentTagForUnflattenCase(); fixDifferentiatorParentTagForUnflattenCase_ = flagValue; @@ -1064,7 +1082,7 @@ bool ReactNativeFeatureFlagsAccessor::fixFindShadowNodeByTagRaceCondition() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(57, "fixFindShadowNodeByTagRaceCondition"); + markFlagAsAccessed(58, "fixFindShadowNodeByTagRaceCondition"); flagValue = currentProvider_->fixFindShadowNodeByTagRaceCondition(); fixFindShadowNodeByTagRaceCondition_ = 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::fuseboxNetworkInspectionEnabled() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(63, "fuseboxNetworkInspectionEnabled"); + markFlagAsAccessed(64, "fuseboxNetworkInspectionEnabled"); flagValue = currentProvider_->fuseboxNetworkInspectionEnabled(); fuseboxNetworkInspectionEnabled_ = flagValue; @@ -1190,7 +1208,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(64, "fuseboxScreenshotCaptureEnabled"); + markFlagAsAccessed(65, "fuseboxScreenshotCaptureEnabled"); flagValue = currentProvider_->fuseboxScreenshotCaptureEnabled(); fuseboxScreenshotCaptureEnabled_ = flagValue; @@ -1208,7 +1226,7 @@ bool ReactNativeFeatureFlagsAccessor::hideOffscreenVirtualViewsOnIOS() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(65, "hideOffscreenVirtualViewsOnIOS"); + markFlagAsAccessed(66, "hideOffscreenVirtualViewsOnIOS"); flagValue = currentProvider_->hideOffscreenVirtualViewsOnIOS(); hideOffscreenVirtualViewsOnIOS_ = 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::runtimeCrashUiThreadUtils() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(74, "runtimeCrashUiThreadUtils"); + markFlagAsAccessed(75, "runtimeCrashUiThreadUtils"); flagValue = currentProvider_->runtimeCrashUiThreadUtils(); runtimeCrashUiThreadUtils_ = flagValue; @@ -1388,7 +1406,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(75, "shouldTriggerResponderTransferOnScrollAndroid"); + markFlagAsAccessed(76, "shouldTriggerResponderTransferOnScrollAndroid"); flagValue = currentProvider_->shouldTriggerResponderTransferOnScrollAndroid(); shouldTriggerResponderTransferOnScrollAndroid_ = flagValue; @@ -1406,7 +1424,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(76, "skipActivityIdentityAssertionOnHostPause"); + markFlagAsAccessed(77, "skipActivityIdentityAssertionOnHostPause"); flagValue = currentProvider_->skipActivityIdentityAssertionOnHostPause(); skipActivityIdentityAssertionOnHostPause_ = flagValue; @@ -1424,7 +1442,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(77, "syncAndroidClipBoundsWithOverflow"); + markFlagAsAccessed(78, "syncAndroidClipBoundsWithOverflow"); flagValue = currentProvider_->syncAndroidClipBoundsWithOverflow(); syncAndroidClipBoundsWithOverflow_ = flagValue; @@ -1442,7 +1460,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(78, "traceTurboModulePromiseRejectionsOnAndroid"); + markFlagAsAccessed(79, "traceTurboModulePromiseRejectionsOnAndroid"); flagValue = currentProvider_->traceTurboModulePromiseRejectionsOnAndroid(); traceTurboModulePromiseRejectionsOnAndroid_ = flagValue; @@ -1460,7 +1478,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(79, "updateRuntimeShadowNodeReferencesOnCommit"); + markFlagAsAccessed(80, "updateRuntimeShadowNodeReferencesOnCommit"); flagValue = currentProvider_->updateRuntimeShadowNodeReferencesOnCommit(); updateRuntimeShadowNodeReferencesOnCommit_ = flagValue; @@ -1478,7 +1496,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(80, "updateRuntimeShadowNodeReferencesOnCommitThread"); + markFlagAsAccessed(81, "updateRuntimeShadowNodeReferencesOnCommitThread"); flagValue = currentProvider_->updateRuntimeShadowNodeReferencesOnCommitThread(); updateRuntimeShadowNodeReferencesOnCommitThread_ = flagValue; @@ -1496,7 +1514,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(81, "useAlwaysAvailableJSErrorHandling"); + markFlagAsAccessed(82, "useAlwaysAvailableJSErrorHandling"); flagValue = currentProvider_->useAlwaysAvailableJSErrorHandling(); useAlwaysAvailableJSErrorHandling_ = flagValue; @@ -1514,7 +1532,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(82, "useFabricInterop"); + markFlagAsAccessed(83, "useFabricInterop"); flagValue = currentProvider_->useFabricInterop(); useFabricInterop_ = flagValue; @@ -1532,7 +1550,7 @@ bool ReactNativeFeatureFlagsAccessor::useLISAlgorithmInDifferentiator() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(83, "useLISAlgorithmInDifferentiator"); + markFlagAsAccessed(84, "useLISAlgorithmInDifferentiator"); flagValue = currentProvider_->useLISAlgorithmInDifferentiator(); useLISAlgorithmInDifferentiator_ = flagValue; @@ -1550,7 +1568,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(84, "useNativeViewConfigsInBridgelessMode"); + markFlagAsAccessed(85, "useNativeViewConfigsInBridgelessMode"); flagValue = currentProvider_->useNativeViewConfigsInBridgelessMode(); useNativeViewConfigsInBridgelessMode_ = flagValue; @@ -1568,7 +1586,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(85, "useNestedScrollViewAndroid"); + markFlagAsAccessed(86, "useNestedScrollViewAndroid"); flagValue = currentProvider_->useNestedScrollViewAndroid(); useNestedScrollViewAndroid_ = flagValue; @@ -1586,7 +1604,7 @@ bool ReactNativeFeatureFlagsAccessor::useOptimizedViewRegistryOnAndroid() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(86, "useOptimizedViewRegistryOnAndroid"); + markFlagAsAccessed(87, "useOptimizedViewRegistryOnAndroid"); flagValue = currentProvider_->useOptimizedViewRegistryOnAndroid(); useOptimizedViewRegistryOnAndroid_ = flagValue; @@ -1604,7 +1622,7 @@ bool ReactNativeFeatureFlagsAccessor::usePullModelOnAndroid() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(87, "usePullModelOnAndroid"); + markFlagAsAccessed(88, "usePullModelOnAndroid"); flagValue = currentProvider_->usePullModelOnAndroid(); usePullModelOnAndroid_ = flagValue; @@ -1622,7 +1640,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(88, "useSharedAnimatedBackend"); + markFlagAsAccessed(89, "useSharedAnimatedBackend"); flagValue = currentProvider_->useSharedAnimatedBackend(); useSharedAnimatedBackend_ = flagValue; @@ -1640,7 +1658,7 @@ bool ReactNativeFeatureFlagsAccessor::useSilenceErrorSMMViewNotFound() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(89, "useSilenceErrorSMMViewNotFound"); + markFlagAsAccessed(90, "useSilenceErrorSMMViewNotFound"); flagValue = currentProvider_->useSilenceErrorSMMViewNotFound(); useSilenceErrorSMMViewNotFound_ = flagValue; @@ -1658,7 +1676,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(90, "useTraitHiddenOnAndroid"); + markFlagAsAccessed(91, "useTraitHiddenOnAndroid"); flagValue = currentProvider_->useTraitHiddenOnAndroid(); useTraitHiddenOnAndroid_ = flagValue; @@ -1676,7 +1694,7 @@ bool ReactNativeFeatureFlagsAccessor::useTraitHiddenOnIOS() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(91, "useTraitHiddenOnIOS"); + markFlagAsAccessed(92, "useTraitHiddenOnIOS"); flagValue = currentProvider_->useTraitHiddenOnIOS(); useTraitHiddenOnIOS_ = flagValue; @@ -1694,7 +1712,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(92, "useTurboModuleInterop"); + markFlagAsAccessed(93, "useTurboModuleInterop"); flagValue = currentProvider_->useTurboModuleInterop(); useTurboModuleInterop_ = flagValue; @@ -1712,7 +1730,7 @@ bool ReactNativeFeatureFlagsAccessor::useTurboModules() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(93, "useTurboModules"); + markFlagAsAccessed(94, "useTurboModules"); flagValue = currentProvider_->useTurboModules(); useTurboModules_ = flagValue; @@ -1730,7 +1748,7 @@ bool ReactNativeFeatureFlagsAccessor::useUnorderedMapInDifferentiator() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(94, "useUnorderedMapInDifferentiator"); + markFlagAsAccessed(95, "useUnorderedMapInDifferentiator"); flagValue = currentProvider_->useUnorderedMapInDifferentiator(); useUnorderedMapInDifferentiator_ = flagValue; @@ -1748,7 +1766,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(95, "viewCullingOutsetRatio"); + markFlagAsAccessed(96, "viewCullingOutsetRatio"); flagValue = currentProvider_->viewCullingOutsetRatio(); viewCullingOutsetRatio_ = flagValue; @@ -1766,7 +1784,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(96, "viewTransitionEnabled"); + markFlagAsAccessed(97, "viewTransitionEnabled"); flagValue = currentProvider_->viewTransitionEnabled(); viewTransitionEnabled_ = flagValue; @@ -1784,7 +1802,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(97, "virtualViewPrerenderRatio"); + markFlagAsAccessed(98, "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 edf42f230ac6..9ab487459bb6 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<<7183652511b3f309064e93573cccc532>> + * @generated SignedSource<> */ /** @@ -42,6 +42,7 @@ class ReactNativeFeatureFlagsAccessor { bool disableSubviewClippingAndroid(); bool disableTextLayoutManagerCacheAndroid(); bool disableViewPreallocationAndroid(); + bool discordUiManagerLazyPropertiesOptimization(); bool enableAccessibilityOrder(); bool enableAccumulatedUpdatesInRawPropsAndroid(); bool enableAndroidTextMeasurementOptimizations(); @@ -141,7 +142,7 @@ class ReactNativeFeatureFlagsAccessor { std::unique_ptr currentProvider_; bool wasOverridden_; - std::array, 98> accessedFeatureFlags_; + std::array, 99> accessedFeatureFlags_; std::atomic> commonTestFlag_; std::atomic> cdpInteractionMetricsEnabled_; @@ -153,6 +154,7 @@ class ReactNativeFeatureFlagsAccessor { std::atomic> disableSubviewClippingAndroid_; std::atomic> disableTextLayoutManagerCacheAndroid_; std::atomic> disableViewPreallocationAndroid_; + std::atomic> discordUiManagerLazyPropertiesOptimization_; std::atomic> enableAccessibilityOrder_; std::atomic> enableAccumulatedUpdatesInRawPropsAndroid_; std::atomic> enableAndroidTextMeasurementOptimizations_; diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h index b211a1b7950a..a6d05aefa6a2 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<<9321638ff105b0a6eb0e2a594f579cda>> + * @generated SignedSource<<66ead7997c8d11a41bdab30e4380cd9d>> */ /** @@ -67,6 +67,10 @@ class ReactNativeFeatureFlagsDefaults : public ReactNativeFeatureFlagsProvider { return false; } + bool discordUiManagerLazyPropertiesOptimization() override { + return false; + } + bool enableAccessibilityOrder() override { return false; } diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDynamicProvider.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDynamicProvider.h index b45750e9a666..f32e72cba439 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<<1ae797d05b1fac9f396c3a5593107752>> + * @generated SignedSource<> */ /** @@ -135,6 +135,15 @@ class ReactNativeFeatureFlagsDynamicProvider : public ReactNativeFeatureFlagsDef return ReactNativeFeatureFlagsDefaults::disableViewPreallocationAndroid(); } + bool discordUiManagerLazyPropertiesOptimization() override { + auto value = values_["discordUiManagerLazyPropertiesOptimization"]; + if (!value.isNull()) { + return value.getBool(); + } + + return ReactNativeFeatureFlagsDefaults::discordUiManagerLazyPropertiesOptimization(); + } + bool enableAccessibilityOrder() override { auto value = values_["enableAccessibilityOrder"]; if (!value.isNull()) { diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h index 43b9b700d135..2ba60fc1a9cf 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<<7656937149112e9f38b96bae3d4ca808>> */ /** @@ -35,6 +35,7 @@ class ReactNativeFeatureFlagsProvider { virtual bool disableSubviewClippingAndroid() = 0; virtual bool disableTextLayoutManagerCacheAndroid() = 0; virtual bool disableViewPreallocationAndroid() = 0; + virtual bool discordUiManagerLazyPropertiesOptimization() = 0; virtual bool enableAccessibilityOrder() = 0; virtual bool enableAccumulatedUpdatesInRawPropsAndroid() = 0; virtual bool enableAndroidTextMeasurementOptimizations() = 0; diff --git a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp index 4c9b39d393cc..1283df700098 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<<1cdcc92d96eeb14eb91a704211ff0767>> */ /** @@ -94,6 +94,11 @@ bool NativeReactNativeFeatureFlags::disableViewPreallocationAndroid( return ReactNativeFeatureFlags::disableViewPreallocationAndroid(); } +bool NativeReactNativeFeatureFlags::discordUiManagerLazyPropertiesOptimization( + jsi::Runtime& /*runtime*/) { + return ReactNativeFeatureFlags::discordUiManagerLazyPropertiesOptimization(); +} + bool NativeReactNativeFeatureFlags::enableAccessibilityOrder( jsi::Runtime& /*runtime*/) { return ReactNativeFeatureFlags::enableAccessibilityOrder(); diff --git a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h index 2787ce743865..ea8ebf6ac2f8 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<<5084830f5f476750cd522a526bf15055>> + * @generated SignedSource<<6bc2590b37f390d7faeabe0351e65e19>> */ /** @@ -56,6 +56,8 @@ class NativeReactNativeFeatureFlags bool disableViewPreallocationAndroid(jsi::Runtime& runtime); + bool discordUiManagerLazyPropertiesOptimization(jsi::Runtime& runtime); + bool enableAccessibilityOrder(jsi::Runtime& runtime); bool enableAccumulatedUpdatesInRawPropsAndroid(jsi::Runtime& runtime); diff --git a/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js b/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js index 4732805fdf00..f9bb69e6c340 100644 --- a/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js +++ b/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js @@ -158,6 +158,17 @@ const definitions: FeatureFlagDefinitions = { }, ossReleaseStage: 'none', }, + discordUiManagerLazyPropertiesOptimization: { + defaultValue: false, + metadata: { + dateAdded: '2026-10-15', + description: + 'Optimize lazy properties in UIManager.', + expectedReleaseValue: true, + purpose: 'experimentation', + }, + ossReleaseStage: 'none', + }, enableAccessibilityOrder: { defaultValue: false, metadata: { diff --git a/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js b/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js index 1589f23a8af0..a98f3d098819 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<<985615d1d3e193ee5eb60177bb7de994>> + * @generated SignedSource<<75a3ec634814792bfbd93b637a61e957>> * @flow strict * @noformat */ @@ -57,6 +57,7 @@ export type ReactNativeFeatureFlags = $ReadOnly<{ disableSubviewClippingAndroid: Getter, disableTextLayoutManagerCacheAndroid: Getter, disableViewPreallocationAndroid: Getter, + discordUiManagerLazyPropertiesOptimization: Getter, enableAccessibilityOrder: Getter, enableAccumulatedUpdatesInRawPropsAndroid: Getter, enableAndroidTextMeasurementOptimizations: Getter, @@ -251,6 +252,10 @@ export const disableTextLayoutManagerCacheAndroid: Getter = createNativ * Force disable view preallocation triggered from createNode off the main thread on Android */ export const disableViewPreallocationAndroid: Getter = createNativeFlagGetter('disableViewPreallocationAndroid', false); +/** + * Optimize lazy properties in UIManager. + */ +export const discordUiManagerLazyPropertiesOptimization: Getter = createNativeFlagGetter('discordUiManagerLazyPropertiesOptimization', false); /** * When enabled, the accessibilityOrder prop will propagate to native platforms and define the accessibility order. */ diff --git a/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js b/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js index 131a074c32e7..1c2d216d81ae 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<<1b452370c6697f787256c3e338702371>> + * @generated SignedSource<<5ef557e4ec067e69bf5f3e5ec3f651c9>> * @flow strict * @noformat */ @@ -35,6 +35,7 @@ export interface Spec extends TurboModule { +disableSubviewClippingAndroid?: () => boolean; +disableTextLayoutManagerCacheAndroid?: () => boolean; +disableViewPreallocationAndroid?: () => boolean; + +discordUiManagerLazyPropertiesOptimization?: () => boolean; +enableAccessibilityOrder?: () => boolean; +enableAccumulatedUpdatesInRawPropsAndroid?: () => boolean; +enableAndroidTextMeasurementOptimizations?: () => boolean; From 7ecc8558d4603b4a4ff5bb2514c8780101fafa64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hanno=20J=2E=20Go=CC=88decke?= Date: Thu, 15 Oct 2026 10:50:54 +0200 Subject: [PATCH 3/8] read feature flag in uimanagerbidning + inject --- .../react/renderer/uimanager/UIManagerBinding.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/packages/react-native/ReactCommon/react/renderer/uimanager/UIManagerBinding.cpp b/packages/react-native/ReactCommon/react/renderer/uimanager/UIManagerBinding.cpp index 044d7bad5622..6bb021d5d4cf 100644 --- a/packages/react-native/ReactCommon/react/renderer/uimanager/UIManagerBinding.cpp +++ b/packages/react-native/ReactCommon/react/renderer/uimanager/UIManagerBinding.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -30,6 +31,12 @@ void UIManagerBinding::createAndInstallIfNeeded( auto uiManagerValue = runtime.global().getProperty(runtime, uiManagerModuleName); if (uiManagerValue.isUndefined()) { + // Discord: inject feature flag value to global runtime object. The feature flag + // is set on the native side at app start. This way JS can read its value immediately. + if (ReactNativeFeatureFlags::discordUiManagerLazyPropertiesOptimization()) { + runtime.global().setProperty(runtime, "discordUiManagerLazyPropertiesOptimization", true); + } + // The global namespace does not have an instance of the binding; // we need to create, install and return it. auto uiManagerBinding = std::make_shared(uiManager); From 47d58fb5ca1c186d75e1edf02f9f3a76d5836d18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hanno=20J=2E=20Go=CC=88decke?= Date: Thu, 15 Oct 2026 10:53:58 +0200 Subject: [PATCH 4/8] gate optimization behind global flag --- .../Libraries/ReactNative/UIManager.js | 37 +++++++++++-------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/packages/react-native/Libraries/ReactNative/UIManager.js b/packages/react-native/Libraries/ReactNative/UIManager.js index 80e63bbaa1fa..ffd28e2d5819 100644 --- a/packages/react-native/Libraries/ReactNative/UIManager.js +++ b/packages/react-native/Libraries/ReactNative/UIManager.js @@ -8,7 +8,6 @@ * @format */ -import type {UnsafeObject} from '../Types/CodegenTypes'; import type {UIManagerJSInterface} from '../Types/UIManagerJSInterface'; import {getFabricUIManager} from './FabricUIManager'; @@ -208,19 +207,27 @@ const UIManagerOverrides = { }, }; -// Copy property descriptors instead of spreading UIManagerImpl. In Bridgeless -// mode, UIManagerImpl may define enumerable lazy ViewManager getters. Spreading -// the object would invoke every getter during module initialization. -// $FlowFixMe[incompatible-type] Flow cannot infer properties from descriptors. -const UIManager: UIManagerJSInterface = Object.create( - Object.getPrototypeOf(UIManagerImpl), - { - ...Object.getOwnPropertyDescriptors( - // $FlowFixMe[class-object-subtyping] UIManagerImpl is a runtime object. - UIManagerImpl, - ), - ...Object.getOwnPropertyDescriptors(UIManagerOverrides), - }, -); +let UIManager: UIManagerJSInterface; +if (global.discordUiManagerLazyPropertiesOptimization) { + // Copy property descriptors instead of spreading UIManagerImpl. In Bridgeless + // mode, UIManagerImpl may define enumerable lazy ViewManager getters. Spreading + // the object would invoke every getter during module initialization. + // $FlowFixMe[incompatible-type] Flow cannot infer properties from descriptors. + UIManager = Object.create( + Object.getPrototypeOf(UIManagerImpl), + { + ...Object.getOwnPropertyDescriptors( + // $FlowFixMe[class-object-subtyping] UIManagerImpl is a runtime object. + UIManagerImpl, + ), + ...Object.getOwnPropertyDescriptors(UIManagerOverrides), + }, + ); +} else { + UIManager = { + ...UIManagerImpl, + ...UIManagerOverrides, + }; +} export default UIManager; From 3c0aa304ae4fa9bdc2ba7d1457fd97f941dbccbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hanno=20J=2E=20Go=CC=88decke?= Date: Thu, 15 Oct 2026 11:01:49 +0200 Subject: [PATCH 5/8] clang format --- .../react/renderer/uimanager/UIManagerBinding.cpp | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/packages/react-native/ReactCommon/react/renderer/uimanager/UIManagerBinding.cpp b/packages/react-native/ReactCommon/react/renderer/uimanager/UIManagerBinding.cpp index 6bb021d5d4cf..0c49b5bf8532 100644 --- a/packages/react-native/ReactCommon/react/renderer/uimanager/UIManagerBinding.cpp +++ b/packages/react-native/ReactCommon/react/renderer/uimanager/UIManagerBinding.cpp @@ -31,10 +31,12 @@ void UIManagerBinding::createAndInstallIfNeeded( auto uiManagerValue = runtime.global().getProperty(runtime, uiManagerModuleName); if (uiManagerValue.isUndefined()) { - // Discord: inject feature flag value to global runtime object. The feature flag - // is set on the native side at app start. This way JS can read its value immediately. + // Discord: inject feature flag value to global runtime object. The feature + // flag is set on the native side at app start. This way JS can read its + // value immediately. if (ReactNativeFeatureFlags::discordUiManagerLazyPropertiesOptimization()) { - runtime.global().setProperty(runtime, "discordUiManagerLazyPropertiesOptimization", true); + runtime.global().setProperty( + runtime, "discordUiManagerLazyPropertiesOptimization", true); } // The global namespace does not have an instance of the binding; @@ -488,13 +490,16 @@ jsi::Value UIManagerBinding::get( auto shadowNodeList = shadowNodeListFromValue(runtime, arguments[1]); static const clock::time_point t0 = clock::now(); - const bool isWithinFirst5s = (clock::now() - t0) < std::chrono::seconds(5); + const bool isWithinFirst5s = + (clock::now() - t0) < std::chrono::seconds(5); uiManager->completeSurface( surfaceId, shadowNodeList, {.enableStateReconciliation = true, - .mountSynchronously = isWithinFirst5s, // make sure we push first render as soon as possible otherwise we observe 200ms delay + .mountSynchronously = + isWithinFirst5s, // make sure we push first render as soon as + // possible otherwise we observe 200ms delay .source = ShadowTree::CommitSource::React}); return jsi::Value::undefined(); From 1c51406606839854e123cf9e67ffd7b163119685 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hanno=20J=2E=20Go=CC=88decke?= Date: Thu, 15 Oct 2026 11:11:58 +0200 Subject: [PATCH 6/8] we need to move it to an earlier place so its available when we evaluate the bundle --- .../Libraries/ReactNative/UIManager.js | 20 ++- .../ReactNative/__tests__/UIManager-test.js | 120 +++++++++++------- .../renderer/uimanager/UIManagerBinding.cpp | 9 -- .../react/runtime/ReactInstance.cpp | 12 ++ .../runtime/tests/cxx/ReactInstanceTest.cpp | 13 ++ packages/react-native/flow/global.js | 1 + 6 files changed, 107 insertions(+), 68 deletions(-) diff --git a/packages/react-native/Libraries/ReactNative/UIManager.js b/packages/react-native/Libraries/ReactNative/UIManager.js index ffd28e2d5819..d4deb72836be 100644 --- a/packages/react-native/Libraries/ReactNative/UIManager.js +++ b/packages/react-native/Libraries/ReactNative/UIManager.js @@ -208,22 +208,20 @@ const UIManagerOverrides = { }; let UIManager: UIManagerJSInterface; -if (global.discordUiManagerLazyPropertiesOptimization) { +if (global.RN$discordUiManagerLazyPropertiesOptimization === true) { // Copy property descriptors instead of spreading UIManagerImpl. In Bridgeless // mode, UIManagerImpl may define enumerable lazy ViewManager getters. Spreading // the object would invoke every getter during module initialization. // $FlowFixMe[incompatible-type] Flow cannot infer properties from descriptors. - UIManager = Object.create( - Object.getPrototypeOf(UIManagerImpl), - { - ...Object.getOwnPropertyDescriptors( - // $FlowFixMe[class-object-subtyping] UIManagerImpl is a runtime object. - UIManagerImpl, - ), - ...Object.getOwnPropertyDescriptors(UIManagerOverrides), - }, - ); + UIManager = Object.create(Object.getPrototypeOf(UIManagerImpl), { + ...Object.getOwnPropertyDescriptors( + // $FlowFixMe[class-object-subtyping] UIManagerImpl is a runtime object. + UIManagerImpl, + ), + ...Object.getOwnPropertyDescriptors(UIManagerOverrides), + }); } else { + // $FlowFixMe[cannot-spread-interface] UIManager = { ...UIManagerImpl, ...UIManagerOverrides, diff --git a/packages/react-native/Libraries/ReactNative/__tests__/UIManager-test.js b/packages/react-native/Libraries/ReactNative/__tests__/UIManager-test.js index 9e2633eb48be..67428ea0e49f 100644 --- a/packages/react-native/Libraries/ReactNative/__tests__/UIManager-test.js +++ b/packages/react-native/Libraries/ReactNative/__tests__/UIManager-test.js @@ -17,58 +17,82 @@ jest.mock('../../Utilities/Platform', () => ({ jest.unmock('../UIManager'); describe('UIManager', () => { - it('preserves lazy ViewManager getters when composing the Bridgeless implementation', () => { - const originalBridgelessValue = global.RN$Bridgeless; - const originalGetConstants = global.RN$LegacyInterop_UIManager_getConstants; - const originalGetConstantsForViewManager = - global.RN$LegacyInterop_UIManager_getConstantsForViewManager; - const originalGetDefaultEventTypes = - global.RN$LegacyInterop_UIManager_getDefaultEventTypes; - const viewManagerConfig = {Commands: {focus: 1}}; - const getConstants = jest.fn(() => ({ - LazyViewManagersEnabled: true, - ViewManagerNames: ['RCTTestView'], - })); - const getConstantsForViewManager = jest.fn(() => viewManagerConfig); + const originalBridgelessValue = global.RN$Bridgeless; + const originalLazyPropertiesOptimization = + global.RN$discordUiManagerLazyPropertiesOptimization; + const originalGetConstants = global.RN$LegacyInterop_UIManager_getConstants; + const originalGetConstantsForViewManager = + global.RN$LegacyInterop_UIManager_getConstantsForViewManager; + const originalGetDefaultEventTypes = + global.RN$LegacyInterop_UIManager_getDefaultEventTypes; + const viewManagerConfig = {Commands: {focus: 1}}; + const getConstants = jest.fn(() => ({ + LazyViewManagersEnabled: true, + ViewManagerNames: ['RCTTestView'], + })); + const getConstantsForViewManager = jest.fn(() => viewManagerConfig); + + beforeEach(() => { + jest.resetModules(); + getConstants.mockClear(); + getConstantsForViewManager.mockClear(); + // $FlowExpectedError[cannot-write] + global.RN$Bridgeless = true; + // $FlowExpectedError[cannot-write] + global.RN$LegacyInterop_UIManager_getConstants = getConstants; + // $FlowExpectedError[cannot-write] + global.RN$LegacyInterop_UIManager_getConstantsForViewManager = + getConstantsForViewManager; + // $FlowExpectedError[cannot-write] + global.RN$LegacyInterop_UIManager_getDefaultEventTypes = jest.fn( + () => ({}), + ); + }); + + afterEach(() => { + // $FlowExpectedError[cannot-write] + global.RN$Bridgeless = originalBridgelessValue; + // $FlowExpectedError[cannot-write] + global.RN$discordUiManagerLazyPropertiesOptimization = + originalLazyPropertiesOptimization; + // $FlowExpectedError[cannot-write] + global.RN$LegacyInterop_UIManager_getConstants = originalGetConstants; + // $FlowExpectedError[cannot-write] + global.RN$LegacyInterop_UIManager_getConstantsForViewManager = + originalGetConstantsForViewManager; + // $FlowExpectedError[cannot-write] + global.RN$LegacyInterop_UIManager_getDefaultEventTypes = + originalGetDefaultEventTypes; jest.resetModules(); - try { - // $FlowExpectedError[cannot-write] - global.RN$Bridgeless = true; - // $FlowExpectedError[cannot-write] - global.RN$LegacyInterop_UIManager_getConstants = getConstants; - // $FlowExpectedError[cannot-write] - global.RN$LegacyInterop_UIManager_getConstantsForViewManager = - getConstantsForViewManager; - // $FlowExpectedError[cannot-write] - global.RN$LegacyInterop_UIManager_getDefaultEventTypes = jest.fn( - () => ({}), - ); + }); + + it('preserves lazy ViewManager getters when composing the Bridgeless implementation', () => { + // $FlowExpectedError[cannot-write] + global.RN$discordUiManagerLazyPropertiesOptimization = true; + + const UIManager = require('../UIManager').default; + + expect(getConstants).toHaveBeenCalledTimes(1); + expect(getConstantsForViewManager).not.toHaveBeenCalled(); + expect( + Object.getOwnPropertyDescriptor(UIManager, 'RCTTestView'), + ).toBeDefined(); + expect(Object.keys(UIManager)).toContain('RCTTestView'); + + expect(Reflect.get(UIManager, 'RCTTestView')).toBe(viewManagerConfig); + expect(Reflect.get(UIManager, 'RCTTestView')).toBe(viewManagerConfig); + expect(getConstantsForViewManager).toHaveBeenCalledTimes(1); + }); - const UIManager = require('../UIManager').default; + it('eagerly reads ViewManager getters when the optimization is disabled', () => { + // $FlowExpectedError[cannot-write] + global.RN$discordUiManagerLazyPropertiesOptimization = false; - expect(getConstants).toHaveBeenCalledTimes(1); - expect(getConstantsForViewManager).not.toHaveBeenCalled(); - expect( - Object.getOwnPropertyDescriptor(UIManager, 'RCTTestView'), - ).toBeDefined(); - expect(Object.keys(UIManager)).toContain('RCTTestView'); + const UIManager = require('../UIManager').default; - expect(Reflect.get(UIManager, 'RCTTestView')).toBe(viewManagerConfig); - expect(Reflect.get(UIManager, 'RCTTestView')).toBe(viewManagerConfig); - expect(getConstantsForViewManager).toHaveBeenCalledTimes(1); - } finally { - // $FlowExpectedError[cannot-write] - global.RN$Bridgeless = originalBridgelessValue; - // $FlowExpectedError[cannot-write] - global.RN$LegacyInterop_UIManager_getConstants = originalGetConstants; - // $FlowExpectedError[cannot-write] - global.RN$LegacyInterop_UIManager_getConstantsForViewManager = - originalGetConstantsForViewManager; - // $FlowExpectedError[cannot-write] - global.RN$LegacyInterop_UIManager_getDefaultEventTypes = - originalGetDefaultEventTypes; - jest.resetModules(); - } + expect(getConstants).toHaveBeenCalledTimes(1); + expect(getConstantsForViewManager).toHaveBeenCalledTimes(1); + expect(Reflect.get(UIManager, 'RCTTestView')).toBe(viewManagerConfig); }); }); diff --git a/packages/react-native/ReactCommon/react/renderer/uimanager/UIManagerBinding.cpp b/packages/react-native/ReactCommon/react/renderer/uimanager/UIManagerBinding.cpp index 0c49b5bf8532..4591bd8dd92f 100644 --- a/packages/react-native/ReactCommon/react/renderer/uimanager/UIManagerBinding.cpp +++ b/packages/react-native/ReactCommon/react/renderer/uimanager/UIManagerBinding.cpp @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include @@ -31,14 +30,6 @@ void UIManagerBinding::createAndInstallIfNeeded( auto uiManagerValue = runtime.global().getProperty(runtime, uiManagerModuleName); if (uiManagerValue.isUndefined()) { - // Discord: inject feature flag value to global runtime object. The feature - // flag is set on the native side at app start. This way JS can read its - // value immediately. - if (ReactNativeFeatureFlags::discordUiManagerLazyPropertiesOptimization()) { - runtime.global().setProperty( - runtime, "discordUiManagerLazyPropertiesOptimization", true); - } - // The global namespace does not have an instance of the binding; // we need to create, install and return it. auto uiManagerBinding = std::make_shared(uiManager); diff --git a/packages/react-native/ReactCommon/react/runtime/ReactInstance.cpp b/packages/react-native/ReactCommon/react/runtime/ReactInstance.cpp index 0e792803be45..084e75248473 100644 --- a/packages/react-native/ReactCommon/react/runtime/ReactInstance.cpp +++ b/packages/react-native/ReactCommon/react/runtime/ReactInstance.cpp @@ -393,6 +393,18 @@ void defineReactInstanceFlags( const ReactInstance::JSRuntimeFlags& options) noexcept { defineReadOnlyGlobal(runtime, "RN$Bridgeless", jsi::Value(true)); + // Discord: inject feature flag value to global runtime object. The feature + // flag is set on the native side at app start. This way JS can read its + // value immediately. + const auto uiManagerLazyPropertiesOptimizationEnabled = + ReactNativeFeatureFlags::discordUiManagerLazyPropertiesOptimization(); + auto uiManagerLazyPropertiesOptimizationValue = + jsi::Value(uiManagerLazyPropertiesOptimizationEnabled); + defineReadOnlyGlobal( + runtime, + "RN$discordUiManagerLazyPropertiesOptimization", + std::move(uiManagerLazyPropertiesOptimizationValue)); + if (options.isProfiling) { defineReadOnlyGlobal(runtime, "__RCTProfileIsProfiling", jsi::Value(true)); } diff --git a/packages/react-native/ReactCommon/react/runtime/tests/cxx/ReactInstanceTest.cpp b/packages/react-native/ReactCommon/react/runtime/tests/cxx/ReactInstanceTest.cpp index 8d39ace3f5f7..115ff938b350 100644 --- a/packages/react-native/ReactCommon/react/runtime/tests/cxx/ReactInstanceTest.cpp +++ b/packages/react-native/ReactCommon/react/runtime/tests/cxx/ReactInstanceTest.cpp @@ -231,6 +231,19 @@ TEST_F(ReactInstanceTest, testBridgelessFlagIsSet) { EXPECT_EQ(val.getBool(), true); } +TEST_F( + ReactInstanceTest, + testUiManagerLazyPropertiesOptimizationFlagIsSetBeforeBundle) { + initializeRuntimeWithScript(R"( + globalThis.uiManagerLazyPropertiesOptimizationFlagWasDefined = + typeof RN$discordUiManagerLazyPropertiesOptimization === 'boolean'; + )"); + + auto val = + eval("globalThis.uiManagerLazyPropertiesOptimizationFlagWasDefined"); + EXPECT_EQ(val.getBool(), true); +} + TEST_F(ReactInstanceTest, testProfilingFlag) { auto valBefore = tryEval("__RCTProfileIsProfiling === true", "false"); EXPECT_EQ(valBefore.getBool(), false); diff --git a/packages/react-native/flow/global.js b/packages/react-native/flow/global.js index dc6de666ec02..1d1148f3743f 100644 --- a/packages/react-native/flow/global.js +++ b/packages/react-native/flow/global.js @@ -78,6 +78,7 @@ declare var global: { // Internal-specific +__DEV__?: boolean, +RN$Bridgeless?: boolean, + +RN$discordUiManagerLazyPropertiesOptimization?: boolean, // setupDOM +DOMRect: typeof DOMRect, From d17fc2585ca1dc29966ee04518153f72fb092716 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hanno=20J=2E=20Go=CC=88decke?= Date: Thu, 15 Oct 2026 11:26:48 +0200 Subject: [PATCH 7/8] make experiment three tiered --- .../ReactNative/BridgelessUIManager.js | 21 +++++- .../Libraries/ReactNative/UIManager.js | 6 +- .../ReactNative/__tests__/UIManager-test.js | 66 +++++++++++++++---- .../getNativeComponentAttributes.js | 16 +++++ .../featureflags/ReactNativeFeatureFlags.kt | 6 +- .../ReactNativeFeatureFlagsCxxAccessor.kt | 12 ++-- .../ReactNativeFeatureFlagsCxxInterop.kt | 4 +- .../ReactNativeFeatureFlagsDefaults.kt | 4 +- .../ReactNativeFeatureFlagsLocalAccessor.kt | 14 ++-- .../ReactNativeFeatureFlagsProvider.kt | 4 +- .../JReactNativeFeatureFlagsCxxInterop.cpp | 14 ++-- .../JReactNativeFeatureFlagsCxxInterop.h | 4 +- .../featureflags/ReactNativeFeatureFlags.cpp | 6 +- .../featureflags/ReactNativeFeatureFlags.h | 6 +- .../ReactNativeFeatureFlagsAccessor.cpp | 12 ++-- .../ReactNativeFeatureFlagsAccessor.h | 6 +- .../ReactNativeFeatureFlagsDefaults.h | 6 +- .../ReactNativeFeatureFlagsDynamicProvider.h | 10 +-- .../ReactNativeFeatureFlagsProvider.h | 4 +- .../NativeReactNativeFeatureFlags.cpp | 6 +- .../NativeReactNativeFeatureFlags.h | 4 +- .../react/runtime/ReactInstance.cpp | 11 ++-- .../runtime/tests/cxx/ReactInstanceTest.cpp | 11 ++-- packages/react-native/flow/global.js | 2 +- .../ReactNativeFeatureFlags.config.js | 8 +-- .../featureflags/ReactNativeFeatureFlags.js | 8 +-- .../specs/NativeReactNativeFeatureFlags.js | 4 +- 27 files changed, 176 insertions(+), 99 deletions(-) diff --git a/packages/react-native/Libraries/ReactNative/BridgelessUIManager.js b/packages/react-native/Libraries/ReactNative/BridgelessUIManager.js index 0db6d3415496..45b71f3b6b91 100644 --- a/packages/react-native/Libraries/ReactNative/BridgelessUIManager.js +++ b/packages/react-native/Libraries/ReactNative/BridgelessUIManager.js @@ -47,6 +47,10 @@ const getConstantsForViewManager: ?(viewManagerName: string) => ?Object = const getDefaultEventTypes: ?() => Object = global.RN$LegacyInterop_UIManager_getDefaultEventTypes; +const uiManagerOptimization = global.RN$discordUiManagerOptimization ?? 0; +const shouldLoadViewManagerConstantsOnDemand = + uiManagerOptimization === 2 || uiManagerOptimization === 3; + const getDefaultEventTypesCached = (function () { let wasCalledOnce = false; let result = null; @@ -260,6 +264,10 @@ const UIManagerJSPlatformAPIs = Platform.select({ }, }); +// Building every eagerly registered view manager's constants up front is slow. +// In the on-demand experiment, cache only the view managers JS actually uses. +const viewManagerConfigs: {[viewManagerName: string]: ?Object} = {}; + const UIManagerJS: UIManagerJSInterface & {[string]: any} = { ...UIManagerJSOverridenAPIs, ...UIManagerJSDeprecatedPlatformAPIs, @@ -267,6 +275,17 @@ const UIManagerJS: UIManagerJSInterface & {[string]: any} = { ...UIManagerJSUnusedInNewArchAPIs, getViewManagerConfig: (viewManagerName: string): unknown => { if (getUIManagerConstants) { + if (shouldLoadViewManagerConstantsOnDemand) { + if ( + viewManagerConfigs[viewManagerName] == null && + UIManagerJS.getConstantsForViewManager + ) { + viewManagerConfigs[viewManagerName] = + UIManagerJS.getConstantsForViewManager(viewManagerName); + } + return viewManagerConfigs[viewManagerName]; + } + const constants = getUIManagerConstantsCached(); if ( !constants[viewManagerName] && @@ -396,7 +415,7 @@ const UIManagerJS: UIManagerJSInterface & {[string]: any} = { }, }; -if (getUIManagerConstants) { +if (getUIManagerConstants && !shouldLoadViewManagerConstantsOnDemand) { Object.keys(getUIManagerConstantsCached()).forEach(viewConfigName => { UIManagerJS[viewConfigName] = getUIManagerConstantsCached()[viewConfigName]; }); diff --git a/packages/react-native/Libraries/ReactNative/UIManager.js b/packages/react-native/Libraries/ReactNative/UIManager.js index d4deb72836be..f19eeda71ade 100644 --- a/packages/react-native/Libraries/ReactNative/UIManager.js +++ b/packages/react-native/Libraries/ReactNative/UIManager.js @@ -208,7 +208,11 @@ const UIManagerOverrides = { }; let UIManager: UIManagerJSInterface; -if (global.RN$discordUiManagerLazyPropertiesOptimization === true) { +const uiManagerOptimization = global.RN$discordUiManagerOptimization ?? 0; +const shouldPreserveLazyProperties = + uiManagerOptimization === 1 || uiManagerOptimization === 3; + +if (shouldPreserveLazyProperties) { // Copy property descriptors instead of spreading UIManagerImpl. In Bridgeless // mode, UIManagerImpl may define enumerable lazy ViewManager getters. Spreading // the object would invoke every getter during module initialization. diff --git a/packages/react-native/Libraries/ReactNative/__tests__/UIManager-test.js b/packages/react-native/Libraries/ReactNative/__tests__/UIManager-test.js index 67428ea0e49f..61f64448616a 100644 --- a/packages/react-native/Libraries/ReactNative/__tests__/UIManager-test.js +++ b/packages/react-native/Libraries/ReactNative/__tests__/UIManager-test.js @@ -18,24 +18,25 @@ jest.unmock('../UIManager'); describe('UIManager', () => { const originalBridgelessValue = global.RN$Bridgeless; - const originalLazyPropertiesOptimization = - global.RN$discordUiManagerLazyPropertiesOptimization; + const originalUIManagerOptimization = global.RN$discordUiManagerOptimization; const originalGetConstants = global.RN$LegacyInterop_UIManager_getConstants; const originalGetConstantsForViewManager = global.RN$LegacyInterop_UIManager_getConstantsForViewManager; const originalGetDefaultEventTypes = global.RN$LegacyInterop_UIManager_getDefaultEventTypes; - const viewManagerConfig = {Commands: {focus: 1}}; + const viewManagerConfig = {Commands: {focus: 1}, NativeProps: {}}; const getConstants = jest.fn(() => ({ LazyViewManagersEnabled: true, ViewManagerNames: ['RCTTestView'], })); const getConstantsForViewManager = jest.fn(() => viewManagerConfig); + const getDefaultEventTypes = jest.fn(() => ({})); beforeEach(() => { jest.resetModules(); getConstants.mockClear(); getConstantsForViewManager.mockClear(); + getDefaultEventTypes.mockClear(); // $FlowExpectedError[cannot-write] global.RN$Bridgeless = true; @@ -45,17 +46,15 @@ describe('UIManager', () => { global.RN$LegacyInterop_UIManager_getConstantsForViewManager = getConstantsForViewManager; // $FlowExpectedError[cannot-write] - global.RN$LegacyInterop_UIManager_getDefaultEventTypes = jest.fn( - () => ({}), - ); + global.RN$LegacyInterop_UIManager_getDefaultEventTypes = + getDefaultEventTypes; }); afterEach(() => { // $FlowExpectedError[cannot-write] global.RN$Bridgeless = originalBridgelessValue; // $FlowExpectedError[cannot-write] - global.RN$discordUiManagerLazyPropertiesOptimization = - originalLazyPropertiesOptimization; + global.RN$discordUiManagerOptimization = originalUIManagerOptimization; // $FlowExpectedError[cannot-write] global.RN$LegacyInterop_UIManager_getConstants = originalGetConstants; // $FlowExpectedError[cannot-write] @@ -67,9 +66,9 @@ describe('UIManager', () => { jest.resetModules(); }); - it('preserves lazy ViewManager getters when composing the Bridgeless implementation', () => { + it('preserves lazy ViewManager getters in optimization mode 1', () => { // $FlowExpectedError[cannot-write] - global.RN$discordUiManagerLazyPropertiesOptimization = true; + global.RN$discordUiManagerOptimization = 1; const UIManager = require('../UIManager').default; @@ -85,9 +84,9 @@ describe('UIManager', () => { expect(getConstantsForViewManager).toHaveBeenCalledTimes(1); }); - it('eagerly reads ViewManager getters when the optimization is disabled', () => { + it('eagerly reads ViewManager getters in optimization mode 0', () => { // $FlowExpectedError[cannot-write] - global.RN$discordUiManagerLazyPropertiesOptimization = false; + global.RN$discordUiManagerOptimization = 0; const UIManager = require('../UIManager').default; @@ -95,4 +94,47 @@ describe('UIManager', () => { expect(getConstantsForViewManager).toHaveBeenCalledTimes(1); expect(Reflect.get(UIManager, 'RCTTestView')).toBe(viewManagerConfig); }); + + it.each([2, 3])( + 'loads and caches individual ViewManager configs on demand in optimization mode %s', + optimization => { + // $FlowExpectedError[cannot-write] + global.RN$discordUiManagerOptimization = optimization; + + const UIManager = require('../UIManager').default; + + expect(getConstants).not.toHaveBeenCalled(); + expect(getConstantsForViewManager).not.toHaveBeenCalled(); + + expect(UIManager.getViewManagerConfig('RCTTestView')).toBe( + viewManagerConfig, + ); + expect(UIManager.getViewManagerConfig('RCTTestView')).toBe( + viewManagerConfig, + ); + expect(getConstantsForViewManager).toHaveBeenCalledTimes(1); + + expect(UIManager.getConstants()).toEqual({ + LazyViewManagersEnabled: true, + ViewManagerNames: ['RCTTestView'], + }); + expect(getConstants).toHaveBeenCalledTimes(1); + }, + ); + + it.each([2, 3])( + 'does not load all constants when attaching default event types in optimization mode %s', + optimization => { + // $FlowExpectedError[cannot-write] + global.RN$discordUiManagerOptimization = optimization; + + const getNativeComponentAttributes = + require('../getNativeComponentAttributes').default; + getNativeComponentAttributes('RCTTestView'); + + expect(getConstants).not.toHaveBeenCalled(); + expect(getConstantsForViewManager).toHaveBeenCalledTimes(1); + expect(getDefaultEventTypes).toHaveBeenCalledTimes(1); + }, + ); }); diff --git a/packages/react-native/Libraries/ReactNative/getNativeComponentAttributes.js b/packages/react-native/Libraries/ReactNative/getNativeComponentAttributes.js index 26846a19c551..c6fdc40cf6f5 100644 --- a/packages/react-native/Libraries/ReactNative/getNativeComponentAttributes.js +++ b/packages/react-native/Libraries/ReactNative/getNativeComponentAttributes.js @@ -33,6 +33,10 @@ const sizesDiffer = require('../Utilities/differ/sizesDiffer').default; const UIManager = require('./UIManager').default; const nullthrows = require('nullthrows'); +const uiManagerOptimization = global.RN$discordUiManagerOptimization ?? 0; +const shouldLoadViewManagerConstantsOnDemand = + uiManagerOptimization === 2 || uiManagerOptimization === 3; + function getNativeComponentAttributes(uiViewClassName: string): any { const viewConfig = UIManager.getViewManagerConfig(uiViewClassName); @@ -113,6 +117,18 @@ function attachDefaultEventTypes(viewConfig: any) { // This is supported on UIManager platforms (ex: Android), // as lazy view managers are not implemented for all platforms. // See [UIManager] for details on constants and implementations. + if ( + global.RN$Bridgeless === true && + shouldLoadViewManagerConstantsOnDemand && + UIManager.getDefaultEventTypes != null + ) { + // The narrow native API avoids materializing every view manager's constants + // just to determine which default event types should be attached. + const defaultEventTypes = UIManager.getDefaultEventTypes(); + merge(viewConfig, defaultEventTypes); + return; + } + const constants = UIManager.getConstants(); if (constants.ViewManagerNames || constants.LazyViewManagersEnabled) { // Lazy view managers enabled. 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 531b7ea34700..cb1817cb1efb 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<<5754d26f893644b57e7efd2103516c15>> + * @generated SignedSource<> */ /** @@ -91,10 +91,10 @@ public object ReactNativeFeatureFlags { public fun disableViewPreallocationAndroid(): Boolean = accessor.disableViewPreallocationAndroid() /** - * Optimize lazy properties in UIManager. + * Select UIManager optimizations: 0 = none, 1 = preserve lazy properties, 2 = load view manager constants on demand, 3 = enable both. */ @JvmStatic - public fun discordUiManagerLazyPropertiesOptimization(): Boolean = accessor.discordUiManagerLazyPropertiesOptimization() + public fun discordUiManagerOptimization(): Double = accessor.discordUiManagerOptimization() /** * When enabled, the accessibilityOrder prop will propagate to native platforms and define the accessibility order. 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 ef88fca5716c..d86c4d22365e 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<<802bfc9a2e103a88b992558886064b3f>> + * @generated SignedSource<<10c483c7007076bb3c1cee1197c20c89>> */ /** @@ -30,7 +30,7 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces private var disableSubviewClippingAndroidCache: Boolean? = null private var disableTextLayoutManagerCacheAndroidCache: Boolean? = null private var disableViewPreallocationAndroidCache: Boolean? = null - private var discordUiManagerLazyPropertiesOptimizationCache: Boolean? = null + private var discordUiManagerOptimizationCache: Double? = null private var enableAccessibilityOrderCache: Boolean? = null private var enableAccumulatedUpdatesInRawPropsAndroidCache: Boolean? = null private var enableAndroidTextMeasurementOptimizationsCache: Boolean? = null @@ -210,11 +210,11 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces return cached } - override fun discordUiManagerLazyPropertiesOptimization(): Boolean { - var cached = discordUiManagerLazyPropertiesOptimizationCache + override fun discordUiManagerOptimization(): Double { + var cached = discordUiManagerOptimizationCache if (cached == null) { - cached = ReactNativeFeatureFlagsCxxInterop.discordUiManagerLazyPropertiesOptimization() - discordUiManagerLazyPropertiesOptimizationCache = cached + cached = ReactNativeFeatureFlagsCxxInterop.discordUiManagerOptimization() + discordUiManagerOptimizationCache = cached } return cached } 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 5b36e4071b90..40bd79a50391 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<> + * @generated SignedSource<<1492421cd4b9bca791ee9ad5f87507a3>> */ /** @@ -48,7 +48,7 @@ public object ReactNativeFeatureFlagsCxxInterop { @DoNotStrip @JvmStatic public external fun disableViewPreallocationAndroid(): Boolean - @DoNotStrip @JvmStatic public external fun discordUiManagerLazyPropertiesOptimization(): Boolean + @DoNotStrip @JvmStatic public external fun discordUiManagerOptimization(): Double @DoNotStrip @JvmStatic public external fun enableAccessibilityOrder(): 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 0f5f19f10daf..dc51cbe04a22 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<> + * @generated SignedSource<<462ac270e53d73922c29341d2bf557cc>> */ /** @@ -43,7 +43,7 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi override fun disableViewPreallocationAndroid(): Boolean = false - override fun discordUiManagerLazyPropertiesOptimization(): Boolean = false + override fun discordUiManagerOptimization(): Double = 0.0 override fun enableAccessibilityOrder(): 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 5a545d2178d6..2e25e6b8118f 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<<1afc0b84e52c5cb0743597d5d1247c79>> + * @generated SignedSource<> */ /** @@ -34,7 +34,7 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc private var disableSubviewClippingAndroidCache: Boolean? = null private var disableTextLayoutManagerCacheAndroidCache: Boolean? = null private var disableViewPreallocationAndroidCache: Boolean? = null - private var discordUiManagerLazyPropertiesOptimizationCache: Boolean? = null + private var discordUiManagerOptimizationCache: Double? = null private var enableAccessibilityOrderCache: Boolean? = null private var enableAccumulatedUpdatesInRawPropsAndroidCache: Boolean? = null private var enableAndroidTextMeasurementOptimizationsCache: Boolean? = null @@ -224,12 +224,12 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc return cached } - override fun discordUiManagerLazyPropertiesOptimization(): Boolean { - var cached = discordUiManagerLazyPropertiesOptimizationCache + override fun discordUiManagerOptimization(): Double { + var cached = discordUiManagerOptimizationCache if (cached == null) { - cached = currentProvider.discordUiManagerLazyPropertiesOptimization() - accessedFeatureFlags.add("discordUiManagerLazyPropertiesOptimization") - discordUiManagerLazyPropertiesOptimizationCache = cached + cached = currentProvider.discordUiManagerOptimization() + accessedFeatureFlags.add("discordUiManagerOptimization") + discordUiManagerOptimizationCache = cached } return cached } 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 1f3029e0c687..c988df91b592 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<<81fbfaaada3a546a79b93fd97c96f656>> + * @generated SignedSource<> */ /** @@ -43,7 +43,7 @@ public interface ReactNativeFeatureFlagsProvider { @DoNotStrip public fun disableViewPreallocationAndroid(): Boolean - @DoNotStrip public fun discordUiManagerLazyPropertiesOptimization(): Boolean + @DoNotStrip public fun discordUiManagerOptimization(): Double @DoNotStrip public fun enableAccessibilityOrder(): 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 01dd4c5b17b8..26ac3a63c5dd 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<<47eea5c86d3f5bddedd0f4fb00b32aab>> + * @generated SignedSource<> */ /** @@ -99,9 +99,9 @@ class ReactNativeFeatureFlagsJavaProvider return method(javaProvider_); } - bool discordUiManagerLazyPropertiesOptimization() override { + double discordUiManagerOptimization() override { static const auto method = - getReactNativeFeatureFlagsProviderJavaClass()->getMethod("discordUiManagerLazyPropertiesOptimization"); + getReactNativeFeatureFlagsProviderJavaClass()->getMethod("discordUiManagerOptimization"); return method(javaProvider_); } @@ -687,9 +687,9 @@ bool JReactNativeFeatureFlagsCxxInterop::disableViewPreallocationAndroid( return ReactNativeFeatureFlags::disableViewPreallocationAndroid(); } -bool JReactNativeFeatureFlagsCxxInterop::discordUiManagerLazyPropertiesOptimization( +double JReactNativeFeatureFlagsCxxInterop::discordUiManagerOptimization( facebook::jni::alias_ref /*unused*/) { - return ReactNativeFeatureFlags::discordUiManagerLazyPropertiesOptimization(); + return ReactNativeFeatureFlags::discordUiManagerOptimization(); } bool JReactNativeFeatureFlagsCxxInterop::enableAccessibilityOrder( @@ -1194,8 +1194,8 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() { "disableViewPreallocationAndroid", JReactNativeFeatureFlagsCxxInterop::disableViewPreallocationAndroid), makeNativeMethod( - "discordUiManagerLazyPropertiesOptimization", - JReactNativeFeatureFlagsCxxInterop::discordUiManagerLazyPropertiesOptimization), + "discordUiManagerOptimization", + JReactNativeFeatureFlagsCxxInterop::discordUiManagerOptimization), makeNativeMethod( "enableAccessibilityOrder", JReactNativeFeatureFlagsCxxInterop::enableAccessibilityOrder), 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 ba510e3a8298..16bd68e9c28a 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<<9e727309ab94fe32fee937502251b4b0>> + * @generated SignedSource<<584ebd805c4a72383eb1e07ef28d490b>> */ /** @@ -60,7 +60,7 @@ class JReactNativeFeatureFlagsCxxInterop static bool disableViewPreallocationAndroid( facebook::jni::alias_ref); - static bool discordUiManagerLazyPropertiesOptimization( + static double discordUiManagerOptimization( facebook::jni::alias_ref); static bool enableAccessibilityOrder( diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp index 2012cf058463..16a8faf3033e 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<<81476221c28efc73ed084d2ed04b380d>> + * @generated SignedSource<<8a37279e2d9a281cdeb43356993ec0a9>> */ /** @@ -66,8 +66,8 @@ bool ReactNativeFeatureFlags::disableViewPreallocationAndroid() { return getAccessor().disableViewPreallocationAndroid(); } -bool ReactNativeFeatureFlags::discordUiManagerLazyPropertiesOptimization() { - return getAccessor().discordUiManagerLazyPropertiesOptimization(); +double ReactNativeFeatureFlags::discordUiManagerOptimization() { + return getAccessor().discordUiManagerOptimization(); } bool ReactNativeFeatureFlags::enableAccessibilityOrder() { diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h index 40b71a65d0f3..817e3be545b2 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<> */ /** @@ -90,9 +90,9 @@ class ReactNativeFeatureFlags { RN_EXPORT static bool disableViewPreallocationAndroid(); /** - * Optimize lazy properties in UIManager. + * Select UIManager optimizations: 0 = none, 1 = preserve lazy properties, 2 = load view manager constants on demand, 3 = enable both. */ - RN_EXPORT static bool discordUiManagerLazyPropertiesOptimization(); + RN_EXPORT static double discordUiManagerOptimization(); /** * When enabled, the accessibilityOrder prop will propagate to native platforms and define the accessibility order. diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp index cf852b33a96b..231a308c61e1 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<<3169c783d2059d89e0942a07fe20b042>> + * @generated SignedSource<> */ /** @@ -209,8 +209,8 @@ bool ReactNativeFeatureFlagsAccessor::disableViewPreallocationAndroid() { return flagValue.value(); } -bool ReactNativeFeatureFlagsAccessor::discordUiManagerLazyPropertiesOptimization() { - auto flagValue = discordUiManagerLazyPropertiesOptimization_.load(); +double ReactNativeFeatureFlagsAccessor::discordUiManagerOptimization() { + auto flagValue = discordUiManagerOptimization_.load(); if (!flagValue.has_value()) { // This block is not exclusive but it is not necessary. @@ -218,10 +218,10 @@ bool ReactNativeFeatureFlagsAccessor::discordUiManagerLazyPropertiesOptimization // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(10, "discordUiManagerLazyPropertiesOptimization"); + markFlagAsAccessed(10, "discordUiManagerOptimization"); - flagValue = currentProvider_->discordUiManagerLazyPropertiesOptimization(); - discordUiManagerLazyPropertiesOptimization_ = flagValue; + flagValue = currentProvider_->discordUiManagerOptimization(); + discordUiManagerOptimization_ = flagValue; } return flagValue.value(); diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h index 9ab487459bb6..da03826909f6 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<<4d3705bd5161ff7635e97ae248c74868>> */ /** @@ -42,7 +42,7 @@ class ReactNativeFeatureFlagsAccessor { bool disableSubviewClippingAndroid(); bool disableTextLayoutManagerCacheAndroid(); bool disableViewPreallocationAndroid(); - bool discordUiManagerLazyPropertiesOptimization(); + double discordUiManagerOptimization(); bool enableAccessibilityOrder(); bool enableAccumulatedUpdatesInRawPropsAndroid(); bool enableAndroidTextMeasurementOptimizations(); @@ -154,7 +154,7 @@ class ReactNativeFeatureFlagsAccessor { std::atomic> disableSubviewClippingAndroid_; std::atomic> disableTextLayoutManagerCacheAndroid_; std::atomic> disableViewPreallocationAndroid_; - std::atomic> discordUiManagerLazyPropertiesOptimization_; + std::atomic> discordUiManagerOptimization_; std::atomic> enableAccessibilityOrder_; std::atomic> enableAccumulatedUpdatesInRawPropsAndroid_; std::atomic> enableAndroidTextMeasurementOptimizations_; diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h index a6d05aefa6a2..bb7a36bc0125 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<<66ead7997c8d11a41bdab30e4380cd9d>> + * @generated SignedSource<> */ /** @@ -67,8 +67,8 @@ class ReactNativeFeatureFlagsDefaults : public ReactNativeFeatureFlagsProvider { return false; } - bool discordUiManagerLazyPropertiesOptimization() override { - return false; + double discordUiManagerOptimization() override { + return 0.0; } bool enableAccessibilityOrder() override { diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDynamicProvider.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDynamicProvider.h index f32e72cba439..4d215ccd3a15 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<> + * @generated SignedSource<<0ce2303f050c763a34ac4998192c78af>> */ /** @@ -135,13 +135,13 @@ class ReactNativeFeatureFlagsDynamicProvider : public ReactNativeFeatureFlagsDef return ReactNativeFeatureFlagsDefaults::disableViewPreallocationAndroid(); } - bool discordUiManagerLazyPropertiesOptimization() override { - auto value = values_["discordUiManagerLazyPropertiesOptimization"]; + double discordUiManagerOptimization() override { + auto value = values_["discordUiManagerOptimization"]; if (!value.isNull()) { - return value.getBool(); + return value.getDouble(); } - return ReactNativeFeatureFlagsDefaults::discordUiManagerLazyPropertiesOptimization(); + return ReactNativeFeatureFlagsDefaults::discordUiManagerOptimization(); } bool enableAccessibilityOrder() override { diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h index 2ba60fc1a9cf..e7c2fc710792 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<<7656937149112e9f38b96bae3d4ca808>> + * @generated SignedSource<<4386eff150cd9570d98c0ca4fe9a90ac>> */ /** @@ -35,7 +35,7 @@ class ReactNativeFeatureFlagsProvider { virtual bool disableSubviewClippingAndroid() = 0; virtual bool disableTextLayoutManagerCacheAndroid() = 0; virtual bool disableViewPreallocationAndroid() = 0; - virtual bool discordUiManagerLazyPropertiesOptimization() = 0; + virtual double discordUiManagerOptimization() = 0; virtual bool enableAccessibilityOrder() = 0; virtual bool enableAccumulatedUpdatesInRawPropsAndroid() = 0; virtual bool enableAndroidTextMeasurementOptimizations() = 0; diff --git a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp index 1283df700098..b2048a2ce519 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<<1cdcc92d96eeb14eb91a704211ff0767>> + * @generated SignedSource<<6e3d7aa0a7bbccd61549ca3e5dd26020>> */ /** @@ -94,9 +94,9 @@ bool NativeReactNativeFeatureFlags::disableViewPreallocationAndroid( return ReactNativeFeatureFlags::disableViewPreallocationAndroid(); } -bool NativeReactNativeFeatureFlags::discordUiManagerLazyPropertiesOptimization( +double NativeReactNativeFeatureFlags::discordUiManagerOptimization( jsi::Runtime& /*runtime*/) { - return ReactNativeFeatureFlags::discordUiManagerLazyPropertiesOptimization(); + return ReactNativeFeatureFlags::discordUiManagerOptimization(); } bool NativeReactNativeFeatureFlags::enableAccessibilityOrder( diff --git a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h index ea8ebf6ac2f8..21bda15bca87 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<<6bc2590b37f390d7faeabe0351e65e19>> + * @generated SignedSource<<380250279c76aca0f139fdd0eac141db>> */ /** @@ -56,7 +56,7 @@ class NativeReactNativeFeatureFlags bool disableViewPreallocationAndroid(jsi::Runtime& runtime); - bool discordUiManagerLazyPropertiesOptimization(jsi::Runtime& runtime); + double discordUiManagerOptimization(jsi::Runtime& runtime); bool enableAccessibilityOrder(jsi::Runtime& runtime); diff --git a/packages/react-native/ReactCommon/react/runtime/ReactInstance.cpp b/packages/react-native/ReactCommon/react/runtime/ReactInstance.cpp index 084e75248473..6315c279de78 100644 --- a/packages/react-native/ReactCommon/react/runtime/ReactInstance.cpp +++ b/packages/react-native/ReactCommon/react/runtime/ReactInstance.cpp @@ -396,14 +396,13 @@ void defineReactInstanceFlags( // Discord: inject feature flag value to global runtime object. The feature // flag is set on the native side at app start. This way JS can read its // value immediately. - const auto uiManagerLazyPropertiesOptimizationEnabled = - ReactNativeFeatureFlags::discordUiManagerLazyPropertiesOptimization(); - auto uiManagerLazyPropertiesOptimizationValue = - jsi::Value(uiManagerLazyPropertiesOptimizationEnabled); + const auto uiManagerOptimization = + ReactNativeFeatureFlags::discordUiManagerOptimization(); + auto uiManagerOptimizationValue = jsi::Value(uiManagerOptimization); defineReadOnlyGlobal( runtime, - "RN$discordUiManagerLazyPropertiesOptimization", - std::move(uiManagerLazyPropertiesOptimizationValue)); + "RN$discordUiManagerOptimization", + std::move(uiManagerOptimizationValue)); if (options.isProfiling) { defineReadOnlyGlobal(runtime, "__RCTProfileIsProfiling", jsi::Value(true)); diff --git a/packages/react-native/ReactCommon/react/runtime/tests/cxx/ReactInstanceTest.cpp b/packages/react-native/ReactCommon/react/runtime/tests/cxx/ReactInstanceTest.cpp index 115ff938b350..41901726fa7d 100644 --- a/packages/react-native/ReactCommon/react/runtime/tests/cxx/ReactInstanceTest.cpp +++ b/packages/react-native/ReactCommon/react/runtime/tests/cxx/ReactInstanceTest.cpp @@ -231,16 +231,13 @@ TEST_F(ReactInstanceTest, testBridgelessFlagIsSet) { EXPECT_EQ(val.getBool(), true); } -TEST_F( - ReactInstanceTest, - testUiManagerLazyPropertiesOptimizationFlagIsSetBeforeBundle) { +TEST_F(ReactInstanceTest, testUiManagerOptimizationFlagIsSetBeforeBundle) { initializeRuntimeWithScript(R"( - globalThis.uiManagerLazyPropertiesOptimizationFlagWasDefined = - typeof RN$discordUiManagerLazyPropertiesOptimization === 'boolean'; + globalThis.uiManagerOptimizationFlagWasDefined = + typeof RN$discordUiManagerOptimization === 'number'; )"); - auto val = - eval("globalThis.uiManagerLazyPropertiesOptimizationFlagWasDefined"); + auto val = eval("globalThis.uiManagerOptimizationFlagWasDefined"); EXPECT_EQ(val.getBool(), true); } diff --git a/packages/react-native/flow/global.js b/packages/react-native/flow/global.js index 1d1148f3743f..027e5a82ebf4 100644 --- a/packages/react-native/flow/global.js +++ b/packages/react-native/flow/global.js @@ -78,7 +78,7 @@ declare var global: { // Internal-specific +__DEV__?: boolean, +RN$Bridgeless?: boolean, - +RN$discordUiManagerLazyPropertiesOptimization?: boolean, + +RN$discordUiManagerOptimization?: number, // setupDOM +DOMRect: typeof DOMRect, diff --git a/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js b/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js index f9bb69e6c340..073ea2203540 100644 --- a/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js +++ b/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js @@ -158,13 +158,13 @@ const definitions: FeatureFlagDefinitions = { }, ossReleaseStage: 'none', }, - discordUiManagerLazyPropertiesOptimization: { - defaultValue: false, + discordUiManagerOptimization: { + defaultValue: 0, metadata: { dateAdded: '2026-10-15', description: - 'Optimize lazy properties in UIManager.', - expectedReleaseValue: true, + 'Select UIManager optimizations: 0 = none, 1 = preserve lazy properties, 2 = load view manager constants on demand, 3 = enable both.', + expectedReleaseValue: 3, purpose: 'experimentation', }, ossReleaseStage: 'none', diff --git a/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js b/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js index a98f3d098819..e99695171b4d 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<<75a3ec634814792bfbd93b637a61e957>> + * @generated SignedSource<<857952a326f15422d1d9f70892ff1003>> * @flow strict * @noformat */ @@ -57,7 +57,7 @@ export type ReactNativeFeatureFlags = $ReadOnly<{ disableSubviewClippingAndroid: Getter, disableTextLayoutManagerCacheAndroid: Getter, disableViewPreallocationAndroid: Getter, - discordUiManagerLazyPropertiesOptimization: Getter, + discordUiManagerOptimization: Getter, enableAccessibilityOrder: Getter, enableAccumulatedUpdatesInRawPropsAndroid: Getter, enableAndroidTextMeasurementOptimizations: Getter, @@ -253,9 +253,9 @@ export const disableTextLayoutManagerCacheAndroid: Getter = createNativ */ export const disableViewPreallocationAndroid: Getter = createNativeFlagGetter('disableViewPreallocationAndroid', false); /** - * Optimize lazy properties in UIManager. + * Select UIManager optimizations: 0 = none, 1 = preserve lazy properties, 2 = load view manager constants on demand, 3 = enable both. */ -export const discordUiManagerLazyPropertiesOptimization: Getter = createNativeFlagGetter('discordUiManagerLazyPropertiesOptimization', false); +export const discordUiManagerOptimization: Getter = createNativeFlagGetter('discordUiManagerOptimization', 0); /** * When enabled, the accessibilityOrder prop will propagate to native platforms and define the accessibility order. */ diff --git a/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js b/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js index 1c2d216d81ae..94154d6cd621 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<<5ef557e4ec067e69bf5f3e5ec3f651c9>> + * @generated SignedSource<> * @flow strict * @noformat */ @@ -35,7 +35,7 @@ export interface Spec extends TurboModule { +disableSubviewClippingAndroid?: () => boolean; +disableTextLayoutManagerCacheAndroid?: () => boolean; +disableViewPreallocationAndroid?: () => boolean; - +discordUiManagerLazyPropertiesOptimization?: () => boolean; + +discordUiManagerOptimization?: () => number; +enableAccessibilityOrder?: () => boolean; +enableAccumulatedUpdatesInRawPropsAndroid?: () => boolean; +enableAndroidTextMeasurementOptimizations?: () => boolean; From c4393ac1aadf810cab3c21df4e8f464a2d1730c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hanno=20J=2E=20Go=CC=88decke?= Date: Thu, 15 Oct 2026 18:13:51 +0200 Subject: [PATCH 8/8] refactor(react-native): remove redundant UIManager experiment arm --- .../ReactNative/BridgelessUIManager.js | 3 +- .../Libraries/ReactNative/UIManager.js | 3 +- .../ReactNative/__tests__/UIManager-test.js | 78 +++++++++---------- .../getNativeComponentAttributes.js | 3 +- .../featureflags/ReactNativeFeatureFlags.kt | 4 +- .../featureflags/ReactNativeFeatureFlags.h | 4 +- .../ReactNativeFeatureFlags.config.js | 4 +- .../featureflags/ReactNativeFeatureFlags.js | 4 +- 8 files changed, 47 insertions(+), 56 deletions(-) diff --git a/packages/react-native/Libraries/ReactNative/BridgelessUIManager.js b/packages/react-native/Libraries/ReactNative/BridgelessUIManager.js index 45b71f3b6b91..f9009af428a7 100644 --- a/packages/react-native/Libraries/ReactNative/BridgelessUIManager.js +++ b/packages/react-native/Libraries/ReactNative/BridgelessUIManager.js @@ -48,8 +48,7 @@ const getDefaultEventTypes: ?() => Object = global.RN$LegacyInterop_UIManager_getDefaultEventTypes; const uiManagerOptimization = global.RN$discordUiManagerOptimization ?? 0; -const shouldLoadViewManagerConstantsOnDemand = - uiManagerOptimization === 2 || uiManagerOptimization === 3; +const shouldLoadViewManagerConstantsOnDemand = uiManagerOptimization === 2; const getDefaultEventTypesCached = (function () { let wasCalledOnce = false; diff --git a/packages/react-native/Libraries/ReactNative/UIManager.js b/packages/react-native/Libraries/ReactNative/UIManager.js index f19eeda71ade..933e978194b5 100644 --- a/packages/react-native/Libraries/ReactNative/UIManager.js +++ b/packages/react-native/Libraries/ReactNative/UIManager.js @@ -209,8 +209,7 @@ const UIManagerOverrides = { let UIManager: UIManagerJSInterface; const uiManagerOptimization = global.RN$discordUiManagerOptimization ?? 0; -const shouldPreserveLazyProperties = - uiManagerOptimization === 1 || uiManagerOptimization === 3; +const shouldPreserveLazyProperties = uiManagerOptimization === 1; if (shouldPreserveLazyProperties) { // Copy property descriptors instead of spreading UIManagerImpl. In Bridgeless diff --git a/packages/react-native/Libraries/ReactNative/__tests__/UIManager-test.js b/packages/react-native/Libraries/ReactNative/__tests__/UIManager-test.js index 61f64448616a..273bb87bc210 100644 --- a/packages/react-native/Libraries/ReactNative/__tests__/UIManager-test.js +++ b/packages/react-native/Libraries/ReactNative/__tests__/UIManager-test.js @@ -95,46 +95,40 @@ describe('UIManager', () => { expect(Reflect.get(UIManager, 'RCTTestView')).toBe(viewManagerConfig); }); - it.each([2, 3])( - 'loads and caches individual ViewManager configs on demand in optimization mode %s', - optimization => { - // $FlowExpectedError[cannot-write] - global.RN$discordUiManagerOptimization = optimization; - - const UIManager = require('../UIManager').default; - - expect(getConstants).not.toHaveBeenCalled(); - expect(getConstantsForViewManager).not.toHaveBeenCalled(); - - expect(UIManager.getViewManagerConfig('RCTTestView')).toBe( - viewManagerConfig, - ); - expect(UIManager.getViewManagerConfig('RCTTestView')).toBe( - viewManagerConfig, - ); - expect(getConstantsForViewManager).toHaveBeenCalledTimes(1); - - expect(UIManager.getConstants()).toEqual({ - LazyViewManagersEnabled: true, - ViewManagerNames: ['RCTTestView'], - }); - expect(getConstants).toHaveBeenCalledTimes(1); - }, - ); - - it.each([2, 3])( - 'does not load all constants when attaching default event types in optimization mode %s', - optimization => { - // $FlowExpectedError[cannot-write] - global.RN$discordUiManagerOptimization = optimization; - - const getNativeComponentAttributes = - require('../getNativeComponentAttributes').default; - getNativeComponentAttributes('RCTTestView'); - - expect(getConstants).not.toHaveBeenCalled(); - expect(getConstantsForViewManager).toHaveBeenCalledTimes(1); - expect(getDefaultEventTypes).toHaveBeenCalledTimes(1); - }, - ); + it('loads and caches individual ViewManager configs on demand in optimization mode 2', () => { + // $FlowExpectedError[cannot-write] + global.RN$discordUiManagerOptimization = 2; + + const UIManager = require('../UIManager').default; + + expect(getConstants).not.toHaveBeenCalled(); + expect(getConstantsForViewManager).not.toHaveBeenCalled(); + + expect(UIManager.getViewManagerConfig('RCTTestView')).toBe( + viewManagerConfig, + ); + expect(UIManager.getViewManagerConfig('RCTTestView')).toBe( + viewManagerConfig, + ); + expect(getConstantsForViewManager).toHaveBeenCalledTimes(1); + + expect(UIManager.getConstants()).toEqual({ + LazyViewManagersEnabled: true, + ViewManagerNames: ['RCTTestView'], + }); + expect(getConstants).toHaveBeenCalledTimes(1); + }); + + it('does not load all constants when attaching default event types in optimization mode 2', () => { + // $FlowExpectedError[cannot-write] + global.RN$discordUiManagerOptimization = 2; + + const getNativeComponentAttributes = + require('../getNativeComponentAttributes').default; + getNativeComponentAttributes('RCTTestView'); + + expect(getConstants).not.toHaveBeenCalled(); + expect(getConstantsForViewManager).toHaveBeenCalledTimes(1); + expect(getDefaultEventTypes).toHaveBeenCalledTimes(1); + }); }); diff --git a/packages/react-native/Libraries/ReactNative/getNativeComponentAttributes.js b/packages/react-native/Libraries/ReactNative/getNativeComponentAttributes.js index c6fdc40cf6f5..8900ebe8452a 100644 --- a/packages/react-native/Libraries/ReactNative/getNativeComponentAttributes.js +++ b/packages/react-native/Libraries/ReactNative/getNativeComponentAttributes.js @@ -34,8 +34,7 @@ const UIManager = require('./UIManager').default; const nullthrows = require('nullthrows'); const uiManagerOptimization = global.RN$discordUiManagerOptimization ?? 0; -const shouldLoadViewManagerConstantsOnDemand = - uiManagerOptimization === 2 || uiManagerOptimization === 3; +const shouldLoadViewManagerConstantsOnDemand = uiManagerOptimization === 2; function getNativeComponentAttributes(uiViewClassName: string): any { const viewConfig = UIManager.getViewManagerConfig(uiViewClassName); 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 cb1817cb1efb..4cdc98f29d6d 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<> + * @generated SignedSource<<652b195c21ffe47263fcfbe77a898aa1>> */ /** @@ -91,7 +91,7 @@ public object ReactNativeFeatureFlags { public fun disableViewPreallocationAndroid(): Boolean = accessor.disableViewPreallocationAndroid() /** - * Select UIManager optimizations: 0 = none, 1 = preserve lazy properties, 2 = load view manager constants on demand, 3 = enable both. + * Select UIManager optimizations: 0 = none, 1 = preserve lazy properties, 2 = load view manager constants on demand. */ @JvmStatic public fun discordUiManagerOptimization(): Double = accessor.discordUiManagerOptimization() diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h index 817e3be545b2..3c4c8d10d271 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<01cfdab8946e251169d6a69ed712d57e>> */ /** @@ -90,7 +90,7 @@ class ReactNativeFeatureFlags { RN_EXPORT static bool disableViewPreallocationAndroid(); /** - * Select UIManager optimizations: 0 = none, 1 = preserve lazy properties, 2 = load view manager constants on demand, 3 = enable both. + * Select UIManager optimizations: 0 = none, 1 = preserve lazy properties, 2 = load view manager constants on demand. */ RN_EXPORT static double discordUiManagerOptimization(); diff --git a/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js b/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js index 073ea2203540..15646b06830a 100644 --- a/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js +++ b/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js @@ -163,8 +163,8 @@ const definitions: FeatureFlagDefinitions = { metadata: { dateAdded: '2026-10-15', description: - 'Select UIManager optimizations: 0 = none, 1 = preserve lazy properties, 2 = load view manager constants on demand, 3 = enable both.', - expectedReleaseValue: 3, + 'Select UIManager optimizations: 0 = none, 1 = preserve lazy properties, 2 = load view manager constants on demand.', + expectedReleaseValue: 2, purpose: 'experimentation', }, ossReleaseStage: 'none', diff --git a/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js b/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js index e99695171b4d..a632cb0a4eb1 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<<857952a326f15422d1d9f70892ff1003>> + * @generated SignedSource<> * @flow strict * @noformat */ @@ -253,7 +253,7 @@ export const disableTextLayoutManagerCacheAndroid: Getter = createNativ */ export const disableViewPreallocationAndroid: Getter = createNativeFlagGetter('disableViewPreallocationAndroid', false); /** - * Select UIManager optimizations: 0 = none, 1 = preserve lazy properties, 2 = load view manager constants on demand, 3 = enable both. + * Select UIManager optimizations: 0 = none, 1 = preserve lazy properties, 2 = load view manager constants on demand. */ export const discordUiManagerOptimization: Getter = createNativeFlagGetter('discordUiManagerOptimization', 0); /**