From 061174c150ad05e0ea3fad3cdddb44df9710c337 Mon Sep 17 00:00:00 2001 From: Ramanpreet Nara Date: Wed, 19 Mar 2025 21:16:05 -0700 Subject: [PATCH] Bridgeless: Implement main queue setup api in turbo modules (#50040) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/50040 This diff implements main queue module setup. Sometimes, people need to capture uikit things, and use them from javascript. In those cases, people can write main queue modules. These modules will be eagerly initialized on the main queue, during react native init. ## On Necessity **Sync** dispatches to the main thread from the js thread can deadlock react native. And **async** dispatches to the main thread from the js thread sometimes might not be enough: it could lead to flickery rendering. So, we need to allow people to capture ui thread things, before any js executes. ## Caveat This api is dangerous and discouraged. All react native surfaces will pay the cost of one surface introducing a main queue module. It could also slow down common/critical interactions in your app, if you're not careful. We will introduce performance logging for this infrastructure. So that we can monitor and file tasks, when main queue module init starts taking "too long." Changelog: [General][Breaking]: Introduce beforeload callback arg into ReactInstance::loadScript Reviewed By: mdvacca Differential Revision: D71084243 fbshipit-source-id: 8fdb84761ac69468afc428f4f79eff6322449e3c --- .../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 | 74 ++++++++++++------- .../ReactNativeFeatureFlagsAccessor.h | 6 +- .../ReactNativeFeatureFlagsDefaults.h | 6 +- .../ReactNativeFeatureFlagsDynamicProvider.h | 11 ++- ...eactNativeFeatureFlagsOverridesOSSCanary.h | 4 +- ...tiveFeatureFlagsOverridesOSSExperimental.h | 4 +- .../ReactNativeFeatureFlagsProvider.h | 3 +- .../NativeReactNativeFeatureFlags.cpp | 7 +- .../NativeReactNativeFeatureFlags.h | 4 +- .../react/runtime/ReactInstance.cpp | 13 +++- .../ReactCommon/react/runtime/ReactInstance.h | 3 +- .../platform/ios/ReactCommon/RCTInstance.mm | 39 +++++++++- .../ReactNativeFeatureFlags.config.js | 10 +++ .../featureflags/ReactNativeFeatureFlags.js | 7 +- .../specs/NativeReactNativeFeatureFlags.js | 3 +- 25 files changed, 217 insertions(+), 56 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 f7c5264dda7..7ff9e196fcd 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<<49a61b2330d748fc05bd5e8ce042bf72>> */ /** @@ -118,6 +118,12 @@ public object ReactNativeFeatureFlags { @JvmStatic public fun enableLongTaskAPI(): Boolean = accessor.enableLongTaskAPI() + /** + * Makes modules requiring main queue setup initialize on the main thread, during React Native init. + */ + @JvmStatic + public fun enableMainQueueModulesOnIOS(): Boolean = accessor.enableMainQueueModulesOnIOS() + /** * Parse CSS strings using the Fabric CSS parser instead of ViewConfig processing */ 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 a7f7bee1fe6..ebec84ceb91 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<<9813fd15c7f54d69d3de6084f733c3a6>> + * @generated SignedSource<<86fe1d1217f974eb9cbe2fc6b556b6f3>> */ /** @@ -35,6 +35,7 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces private var enableLayoutAnimationsOnAndroidCache: Boolean? = null private var enableLayoutAnimationsOnIOSCache: Boolean? = null private var enableLongTaskAPICache: Boolean? = null + private var enableMainQueueModulesOnIOSCache: Boolean? = null private var enableNativeCSSParsingCache: Boolean? = null private var enableNewBackgroundAndBorderDrawablesCache: Boolean? = null private var enablePropsUpdateReconciliationAndroidCache: Boolean? = null @@ -198,6 +199,15 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces return cached } + override fun enableMainQueueModulesOnIOS(): Boolean { + var cached = enableMainQueueModulesOnIOSCache + if (cached == null) { + cached = ReactNativeFeatureFlagsCxxInterop.enableMainQueueModulesOnIOS() + enableMainQueueModulesOnIOSCache = cached + } + return cached + } + override fun enableNativeCSSParsing(): Boolean { var cached = enableNativeCSSParsingCache 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 0f0bdfe2b6b..5607cab41a6 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<<06c5ef75b624d953e7a8d9297feaf816>> + * @generated SignedSource<> */ /** @@ -58,6 +58,8 @@ public object ReactNativeFeatureFlagsCxxInterop { @DoNotStrip @JvmStatic public external fun enableLongTaskAPI(): Boolean + @DoNotStrip @JvmStatic public external fun enableMainQueueModulesOnIOS(): Boolean + @DoNotStrip @JvmStatic public external fun enableNativeCSSParsing(): Boolean @DoNotStrip @JvmStatic public external fun enableNewBackgroundAndBorderDrawables(): 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 d7f4afb4a83..ce0e00a74f5 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<> */ /** @@ -53,6 +53,8 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi override fun enableLongTaskAPI(): Boolean = false + override fun enableMainQueueModulesOnIOS(): Boolean = false + override fun enableNativeCSSParsing(): Boolean = false override fun enableNewBackgroundAndBorderDrawables(): 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 a958b7c90cb..6552ac9f737 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<<0fb76e329360157ea9772a0d8bebc873>> + * @generated SignedSource<<5fc2a365b51c5e14f99ec1d3b162f4e3>> */ /** @@ -39,6 +39,7 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc private var enableLayoutAnimationsOnAndroidCache: Boolean? = null private var enableLayoutAnimationsOnIOSCache: Boolean? = null private var enableLongTaskAPICache: Boolean? = null + private var enableMainQueueModulesOnIOSCache: Boolean? = null private var enableNativeCSSParsingCache: Boolean? = null private var enableNewBackgroundAndBorderDrawablesCache: Boolean? = null private var enablePropsUpdateReconciliationAndroidCache: Boolean? = null @@ -217,6 +218,16 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc return cached } + override fun enableMainQueueModulesOnIOS(): Boolean { + var cached = enableMainQueueModulesOnIOSCache + if (cached == null) { + cached = currentProvider.enableMainQueueModulesOnIOS() + accessedFeatureFlags.add("enableMainQueueModulesOnIOS") + enableMainQueueModulesOnIOSCache = cached + } + return cached + } + override fun enableNativeCSSParsing(): Boolean { var cached = enableNativeCSSParsingCache 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 9d194b9ce6a..24795a5698b 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<<0c16f7af743a6c4d7aaabf010c1c7327>> + * @generated SignedSource<<1db9978c9096c9775fd7cd7d37637c8c>> */ /** @@ -53,6 +53,8 @@ public interface ReactNativeFeatureFlagsProvider { @DoNotStrip public fun enableLongTaskAPI(): Boolean + @DoNotStrip public fun enableMainQueueModulesOnIOS(): Boolean + @DoNotStrip public fun enableNativeCSSParsing(): Boolean @DoNotStrip public fun enableNewBackgroundAndBorderDrawables(): 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 c720ea8b1bc..52ae0e0e2bb 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<> + * @generated SignedSource<<696c541ad3725d2d39eaaf8b9b4a317c>> */ /** @@ -129,6 +129,12 @@ class ReactNativeFeatureFlagsProviderHolder return method(javaProvider_); } + bool enableMainQueueModulesOnIOS() override { + static const auto method = + getReactNativeFeatureFlagsProviderJavaClass()->getMethod("enableMainQueueModulesOnIOS"); + return method(javaProvider_); + } + bool enableNativeCSSParsing() override { static const auto method = getReactNativeFeatureFlagsProviderJavaClass()->getMethod("enableNativeCSSParsing"); @@ -370,6 +376,11 @@ bool JReactNativeFeatureFlagsCxxInterop::enableLongTaskAPI( return ReactNativeFeatureFlags::enableLongTaskAPI(); } +bool JReactNativeFeatureFlagsCxxInterop::enableMainQueueModulesOnIOS( + facebook::jni::alias_ref /*unused*/) { + return ReactNativeFeatureFlags::enableMainQueueModulesOnIOS(); +} + bool JReactNativeFeatureFlagsCxxInterop::enableNativeCSSParsing( facebook::jni::alias_ref /*unused*/) { return ReactNativeFeatureFlags::enableNativeCSSParsing(); @@ -581,6 +592,9 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() { makeNativeMethod( "enableLongTaskAPI", JReactNativeFeatureFlagsCxxInterop::enableLongTaskAPI), + makeNativeMethod( + "enableMainQueueModulesOnIOS", + JReactNativeFeatureFlagsCxxInterop::enableMainQueueModulesOnIOS), makeNativeMethod( "enableNativeCSSParsing", JReactNativeFeatureFlagsCxxInterop::enableNativeCSSParsing), 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 08f10d5dad3..381b3596d9c 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<> + * @generated SignedSource<> */ /** @@ -75,6 +75,9 @@ class JReactNativeFeatureFlagsCxxInterop static bool enableLongTaskAPI( facebook::jni::alias_ref); + static bool enableMainQueueModulesOnIOS( + facebook::jni::alias_ref); + static bool enableNativeCSSParsing( 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 ece27d06f80..c375c6fb0aa 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<<4d47f61435ba3a74e84752a02def81c2>> + * @generated SignedSource<<07e6cf68cec4f7c7d61de4958b11ff4f>> */ /** @@ -86,6 +86,10 @@ bool ReactNativeFeatureFlags::enableLongTaskAPI() { return getAccessor().enableLongTaskAPI(); } +bool ReactNativeFeatureFlags::enableMainQueueModulesOnIOS() { + return getAccessor().enableMainQueueModulesOnIOS(); +} + bool ReactNativeFeatureFlags::enableNativeCSSParsing() { return getAccessor().enableNativeCSSParsing(); } diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h index e6536c2895e..7d9a1c44a56 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<<29cdbefbe02064df4fb65388e64f95a4>> + * @generated SignedSource<> */ /** @@ -114,6 +114,11 @@ class ReactNativeFeatureFlags { */ RN_EXPORT static bool enableLongTaskAPI(); + /** + * Makes modules requiring main queue setup initialize on the main thread, during React Native init. + */ + RN_EXPORT static bool enableMainQueueModulesOnIOS(); + /** * Parse CSS strings using the Fabric CSS parser instead of ViewConfig processing */ diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp index 91bf73707b4..d335d93a816 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<<353677101629176192534f1f234e2de4>> + * @generated SignedSource<<40daa9d9fc429b26ec6c178a6d9f6c5d>> */ /** @@ -299,6 +299,24 @@ bool ReactNativeFeatureFlagsAccessor::enableLongTaskAPI() { return flagValue.value(); } +bool ReactNativeFeatureFlagsAccessor::enableMainQueueModulesOnIOS() { + auto flagValue = enableMainQueueModulesOnIOS_.load(); + + if (!flagValue.has_value()) { + // This block is not exclusive but it is not necessary. + // If multiple threads try to initialize the feature flag, we would only + // be accessing the provider multiple times but the end state of this + // instance and the returned flag value would be the same. + + markFlagAsAccessed(15, "enableMainQueueModulesOnIOS"); + + flagValue = currentProvider_->enableMainQueueModulesOnIOS(); + enableMainQueueModulesOnIOS_ = flagValue; + } + + return flagValue.value(); +} + bool ReactNativeFeatureFlagsAccessor::enableNativeCSSParsing() { auto flagValue = enableNativeCSSParsing_.load(); @@ -308,7 +326,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(15, "enableNativeCSSParsing"); + markFlagAsAccessed(16, "enableNativeCSSParsing"); flagValue = currentProvider_->enableNativeCSSParsing(); enableNativeCSSParsing_ = flagValue; @@ -326,7 +344,7 @@ bool ReactNativeFeatureFlagsAccessor::enableNewBackgroundAndBorderDrawables() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(16, "enableNewBackgroundAndBorderDrawables"); + markFlagAsAccessed(17, "enableNewBackgroundAndBorderDrawables"); flagValue = currentProvider_->enableNewBackgroundAndBorderDrawables(); enableNewBackgroundAndBorderDrawables_ = flagValue; @@ -344,7 +362,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(17, "enablePropsUpdateReconciliationAndroid"); + markFlagAsAccessed(18, "enablePropsUpdateReconciliationAndroid"); flagValue = currentProvider_->enablePropsUpdateReconciliationAndroid(); enablePropsUpdateReconciliationAndroid_ = flagValue; @@ -362,7 +380,7 @@ bool ReactNativeFeatureFlagsAccessor::enableReportEventPaintTime() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(18, "enableReportEventPaintTime"); + markFlagAsAccessed(19, "enableReportEventPaintTime"); flagValue = currentProvider_->enableReportEventPaintTime(); enableReportEventPaintTime_ = flagValue; @@ -380,7 +398,7 @@ bool ReactNativeFeatureFlagsAccessor::enableSynchronousStateUpdates() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(19, "enableSynchronousStateUpdates"); + markFlagAsAccessed(20, "enableSynchronousStateUpdates"); flagValue = currentProvider_->enableSynchronousStateUpdates(); enableSynchronousStateUpdates_ = flagValue; @@ -398,7 +416,7 @@ bool ReactNativeFeatureFlagsAccessor::enableUIConsistency() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(20, "enableUIConsistency"); + markFlagAsAccessed(21, "enableUIConsistency"); flagValue = currentProvider_->enableUIConsistency(); enableUIConsistency_ = flagValue; @@ -416,7 +434,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(21, "enableViewCulling"); + markFlagAsAccessed(22, "enableViewCulling"); flagValue = currentProvider_->enableViewCulling(); enableViewCulling_ = flagValue; @@ -434,7 +452,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(22, "enableViewRecycling"); + markFlagAsAccessed(23, "enableViewRecycling"); flagValue = currentProvider_->enableViewRecycling(); enableViewRecycling_ = flagValue; @@ -452,7 +470,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(23, "enableViewRecyclingForText"); + markFlagAsAccessed(24, "enableViewRecyclingForText"); flagValue = currentProvider_->enableViewRecyclingForText(); enableViewRecyclingForText_ = flagValue; @@ -470,7 +488,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(24, "enableViewRecyclingForView"); + markFlagAsAccessed(25, "enableViewRecyclingForView"); flagValue = currentProvider_->enableViewRecyclingForView(); enableViewRecyclingForView_ = flagValue; @@ -488,7 +506,7 @@ bool ReactNativeFeatureFlagsAccessor::fixDifferentiatorEmittingUpdatesWithWrongP // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(25, "fixDifferentiatorEmittingUpdatesWithWrongParentTag"); + markFlagAsAccessed(26, "fixDifferentiatorEmittingUpdatesWithWrongParentTag"); flagValue = currentProvider_->fixDifferentiatorEmittingUpdatesWithWrongParentTag(); fixDifferentiatorEmittingUpdatesWithWrongParentTag_ = flagValue; @@ -506,7 +524,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(26, "fixMappingOfEventPrioritiesBetweenFabricAndReact"); + markFlagAsAccessed(27, "fixMappingOfEventPrioritiesBetweenFabricAndReact"); flagValue = currentProvider_->fixMappingOfEventPrioritiesBetweenFabricAndReact(); fixMappingOfEventPrioritiesBetweenFabricAndReact_ = flagValue; @@ -524,7 +542,7 @@ bool ReactNativeFeatureFlagsAccessor::fixMountingCoordinatorReportedPendingTrans // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(27, "fixMountingCoordinatorReportedPendingTransactionsOnAndroid"); + markFlagAsAccessed(28, "fixMountingCoordinatorReportedPendingTransactionsOnAndroid"); flagValue = currentProvider_->fixMountingCoordinatorReportedPendingTransactionsOnAndroid(); fixMountingCoordinatorReportedPendingTransactionsOnAndroid_ = flagValue; @@ -542,7 +560,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(28, "fuseboxEnabledRelease"); + markFlagAsAccessed(29, "fuseboxEnabledRelease"); flagValue = currentProvider_->fuseboxEnabledRelease(); fuseboxEnabledRelease_ = flagValue; @@ -560,7 +578,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(29, "fuseboxNetworkInspectionEnabled"); + markFlagAsAccessed(30, "fuseboxNetworkInspectionEnabled"); flagValue = currentProvider_->fuseboxNetworkInspectionEnabled(); fuseboxNetworkInspectionEnabled_ = flagValue; @@ -578,7 +596,7 @@ bool ReactNativeFeatureFlagsAccessor::lazyAnimationCallbacks() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(30, "lazyAnimationCallbacks"); + markFlagAsAccessed(31, "lazyAnimationCallbacks"); flagValue = currentProvider_->lazyAnimationCallbacks(); lazyAnimationCallbacks_ = flagValue; @@ -596,7 +614,7 @@ bool ReactNativeFeatureFlagsAccessor::removeTurboModuleManagerDelegateMutex() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(31, "removeTurboModuleManagerDelegateMutex"); + markFlagAsAccessed(32, "removeTurboModuleManagerDelegateMutex"); flagValue = currentProvider_->removeTurboModuleManagerDelegateMutex(); removeTurboModuleManagerDelegateMutex_ = flagValue; @@ -614,7 +632,7 @@ bool ReactNativeFeatureFlagsAccessor::throwExceptionInsteadOfDeadlockOnTurboModu // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(32, "throwExceptionInsteadOfDeadlockOnTurboModuleSetupDuringSyncRenderIOS"); + markFlagAsAccessed(33, "throwExceptionInsteadOfDeadlockOnTurboModuleSetupDuringSyncRenderIOS"); flagValue = currentProvider_->throwExceptionInsteadOfDeadlockOnTurboModuleSetupDuringSyncRenderIOS(); throwExceptionInsteadOfDeadlockOnTurboModuleSetupDuringSyncRenderIOS_ = flagValue; @@ -632,7 +650,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(33, "traceTurboModulePromiseRejectionsOnAndroid"); + markFlagAsAccessed(34, "traceTurboModulePromiseRejectionsOnAndroid"); flagValue = currentProvider_->traceTurboModulePromiseRejectionsOnAndroid(); traceTurboModulePromiseRejectionsOnAndroid_ = flagValue; @@ -650,7 +668,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(34, "useAlwaysAvailableJSErrorHandling"); + markFlagAsAccessed(35, "useAlwaysAvailableJSErrorHandling"); flagValue = currentProvider_->useAlwaysAvailableJSErrorHandling(); useAlwaysAvailableJSErrorHandling_ = flagValue; @@ -668,7 +686,7 @@ bool ReactNativeFeatureFlagsAccessor::useEditTextStockAndroidFocusBehavior() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(35, "useEditTextStockAndroidFocusBehavior"); + markFlagAsAccessed(36, "useEditTextStockAndroidFocusBehavior"); flagValue = currentProvider_->useEditTextStockAndroidFocusBehavior(); useEditTextStockAndroidFocusBehavior_ = flagValue; @@ -686,7 +704,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(36, "useFabricInterop"); + markFlagAsAccessed(37, "useFabricInterop"); flagValue = currentProvider_->useFabricInterop(); useFabricInterop_ = flagValue; @@ -704,7 +722,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(37, "useNativeViewConfigsInBridgelessMode"); + markFlagAsAccessed(38, "useNativeViewConfigsInBridgelessMode"); flagValue = currentProvider_->useNativeViewConfigsInBridgelessMode(); useNativeViewConfigsInBridgelessMode_ = flagValue; @@ -722,7 +740,7 @@ bool ReactNativeFeatureFlagsAccessor::useOptimizedEventBatchingOnAndroid() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(38, "useOptimizedEventBatchingOnAndroid"); + markFlagAsAccessed(39, "useOptimizedEventBatchingOnAndroid"); flagValue = currentProvider_->useOptimizedEventBatchingOnAndroid(); useOptimizedEventBatchingOnAndroid_ = flagValue; @@ -740,7 +758,7 @@ bool ReactNativeFeatureFlagsAccessor::useRawPropsJsiValue() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(39, "useRawPropsJsiValue"); + markFlagAsAccessed(40, "useRawPropsJsiValue"); flagValue = currentProvider_->useRawPropsJsiValue(); useRawPropsJsiValue_ = flagValue; @@ -758,7 +776,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(40, "useTurboModuleInterop"); + markFlagAsAccessed(41, "useTurboModuleInterop"); flagValue = currentProvider_->useTurboModuleInterop(); useTurboModuleInterop_ = flagValue; @@ -776,7 +794,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(41, "useTurboModules"); + markFlagAsAccessed(42, "useTurboModules"); flagValue = currentProvider_->useTurboModules(); useTurboModules_ = flagValue; diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h index 1d0e986c4b4..cd53f268d2b 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<<00f623d5f3920895eb2c1b530dce6a7d>> + * @generated SignedSource<<54364d504177fce95cc2cbbc2b55cb65>> */ /** @@ -47,6 +47,7 @@ class ReactNativeFeatureFlagsAccessor { bool enableLayoutAnimationsOnAndroid(); bool enableLayoutAnimationsOnIOS(); bool enableLongTaskAPI(); + bool enableMainQueueModulesOnIOS(); bool enableNativeCSSParsing(); bool enableNewBackgroundAndBorderDrawables(); bool enablePropsUpdateReconciliationAndroid(); @@ -85,7 +86,7 @@ class ReactNativeFeatureFlagsAccessor { std::unique_ptr currentProvider_; bool wasOverridden_; - std::array, 42> accessedFeatureFlags_; + std::array, 43> accessedFeatureFlags_; std::atomic> commonTestFlag_; std::atomic> animatedShouldSignalBatch_; @@ -102,6 +103,7 @@ class ReactNativeFeatureFlagsAccessor { std::atomic> enableLayoutAnimationsOnAndroid_; std::atomic> enableLayoutAnimationsOnIOS_; std::atomic> enableLongTaskAPI_; + std::atomic> enableMainQueueModulesOnIOS_; std::atomic> enableNativeCSSParsing_; std::atomic> enableNewBackgroundAndBorderDrawables_; std::atomic> enablePropsUpdateReconciliationAndroid_; diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h index 4cb62cd067f..8bcbc0dd95b 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<<140e6580100dab5806194e780610f122>> + * @generated SignedSource<> */ /** @@ -87,6 +87,10 @@ class ReactNativeFeatureFlagsDefaults : public ReactNativeFeatureFlagsProvider { return false; } + bool enableMainQueueModulesOnIOS() override { + return false; + } + bool enableNativeCSSParsing() override { return false; } diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDynamicProvider.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDynamicProvider.h index bfd2a802d94..e3c119f7dad 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<<28915a06a3c24b532384b481cc91d863>> */ /** @@ -180,6 +180,15 @@ class ReactNativeFeatureFlagsDynamicProvider : public ReactNativeFeatureFlagsDef return ReactNativeFeatureFlagsDefaults::enableLongTaskAPI(); } + bool enableMainQueueModulesOnIOS() override { + auto value = values_["enableMainQueueModulesOnIOS"]; + if (!value.isNull()) { + return value.getBool(); + } + + return ReactNativeFeatureFlagsDefaults::enableMainQueueModulesOnIOS(); + } + bool enableNativeCSSParsing() override { auto value = values_["enableNativeCSSParsing"]; if (!value.isNull()) { diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsOverridesOSSCanary.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsOverridesOSSCanary.h index 3dbcd2356cc..55ad9008b61 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsOverridesOSSCanary.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsOverridesOSSCanary.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<<53c858fa9ec8c4e3b9849f7513fdb441>> */ /** @@ -100,6 +100,8 @@ class ReactNativeFeatureFlagsOverridesOSSCanary : public ReactNativeFeatureFlags + + diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsOverridesOSSExperimental.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsOverridesOSSExperimental.h index 0d63daa28ba..6925f5f629f 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsOverridesOSSExperimental.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsOverridesOSSExperimental.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<> */ /** @@ -107,6 +107,8 @@ class ReactNativeFeatureFlagsOverridesOSSExperimental : public ReactNativeFeatur + + diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h index e9ddbd4c1c9..e05009ab0ef 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<<0845c9b1618ac1e18ce4aeb5d03a70f5>> + * @generated SignedSource<<3d6eb54a5f64b0d5c72dae44e669052e>> */ /** @@ -40,6 +40,7 @@ class ReactNativeFeatureFlagsProvider { virtual bool enableLayoutAnimationsOnAndroid() = 0; virtual bool enableLayoutAnimationsOnIOS() = 0; virtual bool enableLongTaskAPI() = 0; + virtual bool enableMainQueueModulesOnIOS() = 0; virtual bool enableNativeCSSParsing() = 0; virtual bool enableNewBackgroundAndBorderDrawables() = 0; virtual bool enablePropsUpdateReconciliationAndroid() = 0; diff --git a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp index 4f831b521d9..061eb797c46 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<<7493403280d2ac7ec348eb3d78d915c2>> + * @generated SignedSource<> */ /** @@ -119,6 +119,11 @@ bool NativeReactNativeFeatureFlags::enableLongTaskAPI( return ReactNativeFeatureFlags::enableLongTaskAPI(); } +bool NativeReactNativeFeatureFlags::enableMainQueueModulesOnIOS( + jsi::Runtime& /*runtime*/) { + return ReactNativeFeatureFlags::enableMainQueueModulesOnIOS(); +} + bool NativeReactNativeFeatureFlags::enableNativeCSSParsing( jsi::Runtime& /*runtime*/) { return ReactNativeFeatureFlags::enableNativeCSSParsing(); diff --git a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h index 831c819ed98..619b45d88fb 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<<36b55f5cfd86d9aaad26c760dec7c875>> + * @generated SignedSource<> */ /** @@ -67,6 +67,8 @@ class NativeReactNativeFeatureFlags bool enableLongTaskAPI(jsi::Runtime& runtime); + bool enableMainQueueModulesOnIOS(jsi::Runtime& runtime); + bool enableNativeCSSParsing(jsi::Runtime& runtime); bool enableNewBackgroundAndBorderDrawables(jsi::Runtime& runtime); diff --git a/packages/react-native/ReactCommon/react/runtime/ReactInstance.cpp b/packages/react-native/ReactCommon/react/runtime/ReactInstance.cpp index 94ae9fe18b1..db92e3e75ca 100644 --- a/packages/react-native/ReactCommon/react/runtime/ReactInstance.cpp +++ b/packages/react-native/ReactCommon/react/runtime/ReactInstance.cpp @@ -215,7 +215,8 @@ std::string simpleBasename(const std::string& path) { void ReactInstance::loadScript( std::unique_ptr script, const std::string& sourceURL, - std::function&& completion) { + std::function&& beforeLoad, + std::function&& afterLoad) { auto buffer = std::make_shared(std::move(script)); std::string scriptName = simpleBasename(sourceURL); @@ -226,7 +227,11 @@ void ReactInstance::loadScript( weakBufferedRuntimeExecuter = std::weak_ptr( bufferedRuntimeExecutor_), - completion](jsi::Runtime& runtime) { + beforeLoad, + afterLoad](jsi::Runtime& runtime) { + if (beforeLoad) { + beforeLoad(runtime); + } TraceSection s("ReactInstance::loadScript"); bool hasLogger(ReactMarker::logTaggedMarkerBridgelessImpl); if (hasLogger) { @@ -255,8 +260,8 @@ void ReactInstance::loadScript( weakBufferedRuntimeExecuter.lock()) { strongBufferedRuntimeExecuter->flush(); } - if (completion) { - completion(runtime); + if (afterLoad) { + afterLoad(runtime); } }); } diff --git a/packages/react-native/ReactCommon/react/runtime/ReactInstance.h b/packages/react-native/ReactCommon/react/runtime/ReactInstance.h index a1e40537ecc..51709eebcd7 100644 --- a/packages/react-native/ReactCommon/react/runtime/ReactInstance.h +++ b/packages/react-native/ReactCommon/react/runtime/ReactInstance.h @@ -50,7 +50,8 @@ class ReactInstance final : private jsinspector_modern::InstanceTargetDelegate { void loadScript( std::unique_ptr script, const std::string& sourceURL, - std::function&& completion = nullptr); + std::function&& beforeLoad = nullptr, + std::function&& afterLoad = nullptr); void registerSegment(uint32_t segmentId, const std::string& segmentPath); diff --git a/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTInstance.mm b/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTInstance.mm index 74f8178a029..e06167df964 100644 --- a/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTInstance.mm +++ b/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTInstance.mm @@ -85,6 +85,7 @@ void RCTInstanceSetRuntimeDiagnosticFlags(NSString *flags) std::atomic _valid; RCTJSThreadManager *_jsThreadManager; NSDictionary *_launchOptions; + void (^_waitUntilModuleSetupComplete)(); // APIs supporting interop with native modules and view managers RCTBridgeModuleDecorator *_bridgeModuleDecorator; @@ -314,6 +315,33 @@ void RCTInstanceSetRuntimeDiagnosticFlags(NSString *flags) // Initialize RCTModuleRegistry so that TurboModules can require other TurboModules. [_bridgeModuleDecorator.moduleRegistry setTurboModuleRegistry:_turboModuleManager]; + if (ReactNativeFeatureFlags::enableMainQueueModulesOnIOS()) { + /** + * Some native modules need to capture uikit objects on the main thread. + * Start initializing those modules on the main queue here. The JavaScript thread + * will wait until this module init finishes, before executing the js bundle. + */ + NSArray *modulesRequiringMainQueueSetup = [_delegate unstableModulesRequiringMainQueueSetup]; + if ([modulesRequiringMainQueueSetup count] > 0) { + dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); + _waitUntilModuleSetupComplete = ^{ + if (dispatch_semaphore_wait(semaphore, dispatch_time(DISPATCH_TIME_NOW, 10 * NSEC_PER_SEC))) { + RCTLogError( + @"Timed out waiting for native modules to be setup on the main queue: %@", + modulesRequiringMainQueueSetup); + }; + }; + + // TODO(T218039767): Integrate perf logging into main queue module init + RCTExecuteOnMainQueue(^{ + for (NSString *moduleName in modulesRequiringMainQueueSetup) { + [self->_bridgeModuleDecorator.moduleRegistry moduleForName:[moduleName UTF8String]]; + } + dispatch_semaphore_signal(semaphore); + }); + } + } + RCTLogSetBridgelessModuleRegistry(_bridgeModuleDecorator.moduleRegistry); RCTLogSetBridgelessCallableJSModules(_bridgeModuleDecorator.callableJSModules); @@ -496,9 +524,16 @@ void RCTInstanceSetRuntimeDiagnosticFlags(NSString *flags) auto script = std::make_unique(source.data); const auto *url = deriveSourceURL(source.url).UTF8String; - _reactInstance->loadScript(std::move(script), url, [](jsi::Runtime &_) { + + auto beforeLoad = [waitUntilModuleSetupComplete = self->_waitUntilModuleSetupComplete](jsi::Runtime &_) { + if (waitUntilModuleSetupComplete) { + waitUntilModuleSetupComplete(); + } + }; + auto afterLoad = [](jsi::Runtime &_) { [[NSNotificationCenter defaultCenter] postNotificationName:@"RCTInstanceDidLoadBundle" object:nil]; - }); + }; + _reactInstance->loadScript(std::move(script), url, beforeLoad, afterLoad); } - (void)_handleJSError:(const JsErrorHandler::ProcessedError &)error withRuntime:(jsi::Runtime &)runtime diff --git a/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js b/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js index 59962f380d8..d45d788fb62 100644 --- a/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js +++ b/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js @@ -202,6 +202,16 @@ const definitions: FeatureFlagDefinitions = { }, ossReleaseStage: 'none', }, + enableMainQueueModulesOnIOS: { + defaultValue: false, + metadata: { + description: + 'Makes modules requiring main queue setup initialize on the main thread, during React Native init.', + expectedReleaseValue: true, + purpose: 'release', + }, + ossReleaseStage: 'none', + }, enableNativeCSSParsing: { defaultValue: false, metadata: { diff --git a/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js b/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js index 34b354dd330..02926ad1bed 100644 --- a/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js +++ b/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<8e4f25dbb96b6c7a9fe645d67172d0ab>> * @flow strict */ @@ -62,6 +62,7 @@ export type ReactNativeFeatureFlags = $ReadOnly<{ enableLayoutAnimationsOnAndroid: Getter, enableLayoutAnimationsOnIOS: Getter, enableLongTaskAPI: Getter, + enableMainQueueModulesOnIOS: Getter, enableNativeCSSParsing: Getter, enableNewBackgroundAndBorderDrawables: Getter, enablePropsUpdateReconciliationAndroid: Getter, @@ -220,6 +221,10 @@ export const enableLayoutAnimationsOnIOS: Getter = createNativeFlagGett * Enables the reporting of long tasks through `PerformanceObserver`. Only works if the event loop is enabled. */ export const enableLongTaskAPI: Getter = createNativeFlagGetter('enableLongTaskAPI', false); +/** + * Makes modules requiring main queue setup initialize on the main thread, during React Native init. + */ +export const enableMainQueueModulesOnIOS: Getter = createNativeFlagGetter('enableMainQueueModulesOnIOS', false); /** * Parse CSS strings using the Fabric CSS parser instead of ViewConfig processing */ diff --git a/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js b/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js index 52291574329..a571a2d2450 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<<22d8e7623a2eee5182c786f2ec914401>> + * @generated SignedSource<> * @flow strict */ @@ -39,6 +39,7 @@ export interface Spec extends TurboModule { +enableLayoutAnimationsOnAndroid?: () => boolean; +enableLayoutAnimationsOnIOS?: () => boolean; +enableLongTaskAPI?: () => boolean; + +enableMainQueueModulesOnIOS?: () => boolean; +enableNativeCSSParsing?: () => boolean; +enableNewBackgroundAndBorderDrawables?: () => boolean; +enablePropsUpdateReconciliationAndroid?: () => boolean;