diff --git a/packages/react-native/ReactAndroid/api/ReactAndroid.api b/packages/react-native/ReactAndroid/api/ReactAndroid.api index a6cbbc6d8d7966..31ca94e1501734 100644 --- a/packages/react-native/ReactAndroid/api/ReactAndroid.api +++ b/packages/react-native/ReactAndroid/api/ReactAndroid.api @@ -1918,7 +1918,6 @@ public class com/facebook/react/config/ReactFeatureFlags { public static field unstable_useFabricInterop Z public static field unstable_useTurboModuleInterop Z public static field unstable_useTurboModuleInteropForAllTurboModules Z - public static field useModernRuntimeScheduler Z public static field useNativeViewConfigsInBridgelessMode Z public static field useTurboModules Z public fun ()V diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/config/ReactFeatureFlags.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/config/ReactFeatureFlags.java index dc656c3143b672..f372d0bc7bc166 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/config/ReactFeatureFlags.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/config/ReactFeatureFlags.java @@ -130,12 +130,6 @@ public class ReactFeatureFlags { /** When enabled, rawProps in Props will not include Yoga specific props. */ public static boolean excludeYogaFromRawProps = false; - /** - * When enabled, it uses the modern fork of RuntimeScheduler that allows scheduling tasks with - * priorities from any thread. - */ - public static boolean useModernRuntimeScheduler = false; - /** * Enables storing js caller stack when creating promise in native module. This is useful in case * of Promise rejection and tracing the cause. 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 1707a7591b1ced..580bbde3a5306f 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<<52367278b4d0fdf7f436bd8c511d4ffe>> */ /** @@ -33,6 +33,21 @@ object ReactNativeFeatureFlags { */ fun commonTestFlag() = accessor.commonTestFlag() + /** + * When enabled, it uses the modern fork of RuntimeScheduler that allows scheduling tasks with priorities from any thread. + */ + fun useModernRuntimeScheduler() = accessor.useModernRuntimeScheduler() + + /** + * Enables the use of microtasks in Hermes (scheduling) and RuntimeScheduler (execution). + */ + fun enableMicrotasks() = accessor.enableMicrotasks() + + /** + * When enabled, the RuntimeScheduler processing the event loop will batch all rendering updates and dispatch them together at the end of each iteration of the loop. + */ + fun batchRenderingUpdatesInEventLoop() = accessor.batchRenderingUpdatesInEventLoop() + /** * Overrides the feature flags with the ones provided by the given provider * (generally one that extends `ReactNativeFeatureFlagsDefaults`). 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 c3521e833ebced..ed422f43ff68a6 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<<961f1fb0a7ad802a492437f15b1f2dcb>> + * @generated SignedSource<<920bb26d238f935f63a77943df7ef6e2>> */ /** @@ -21,6 +21,9 @@ package com.facebook.react.internal.featureflags class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAccessor { private var commonTestFlagCache: Boolean? = null + private var useModernRuntimeSchedulerCache: Boolean? = null + private var enableMicrotasksCache: Boolean? = null + private var batchRenderingUpdatesInEventLoopCache: Boolean? = null override fun commonTestFlag(): Boolean { var cached = commonTestFlagCache @@ -31,6 +34,33 @@ class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAccessor { return cached } + override fun useModernRuntimeScheduler(): Boolean { + var cached = useModernRuntimeSchedulerCache + if (cached == null) { + cached = ReactNativeFeatureFlagsCxxInterop.useModernRuntimeScheduler() + useModernRuntimeSchedulerCache = cached + } + return cached + } + + override fun enableMicrotasks(): Boolean { + var cached = enableMicrotasksCache + if (cached == null) { + cached = ReactNativeFeatureFlagsCxxInterop.enableMicrotasks() + enableMicrotasksCache = cached + } + return cached + } + + override fun batchRenderingUpdatesInEventLoop(): Boolean { + var cached = batchRenderingUpdatesInEventLoopCache + if (cached == null) { + cached = ReactNativeFeatureFlagsCxxInterop.batchRenderingUpdatesInEventLoop() + batchRenderingUpdatesInEventLoopCache = cached + } + return cached + } + override fun override(provider: ReactNativeFeatureFlagsProvider) = ReactNativeFeatureFlagsCxxInterop.override(provider as Any) 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 cb65ae352fba59..3f8f3dcce81ec0 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<<07894609de6f9d34f7d25d372fd0e6ef>> */ /** @@ -29,6 +29,9 @@ object ReactNativeFeatureFlagsCxxInterop { } @DoNotStrip @JvmStatic external fun commonTestFlag(): Boolean + @DoNotStrip @JvmStatic external fun useModernRuntimeScheduler(): Boolean + @DoNotStrip @JvmStatic external fun enableMicrotasks(): Boolean + @DoNotStrip @JvmStatic external fun batchRenderingUpdatesInEventLoop(): Boolean @DoNotStrip @JvmStatic external fun override(provider: Any) 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 363a9990b44a06..25b0522daa8d93 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<<8c97f44276e919fc32eea07408441404>> */ /** @@ -24,4 +24,7 @@ open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvider { // but that is more expensive than just duplicating the defaults here. override fun commonTestFlag(): Boolean = false + override fun useModernRuntimeScheduler(): Boolean = false + override fun enableMicrotasks(): Boolean = false + override fun batchRenderingUpdatesInEventLoop(): 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 bc622a3d70955c..8ff0a2c2778df3 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<<8bbd7e8cc2c50cfbf44ba6671d095f23>> + * @generated SignedSource<<6254686d99a8bfd0531ed629655cf673>> */ /** @@ -25,6 +25,9 @@ class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAccessor { private val accessedFeatureFlags = mutableSetOf() private var commonTestFlagCache: Boolean? = null + private var useModernRuntimeSchedulerCache: Boolean? = null + private var enableMicrotasksCache: Boolean? = null + private var batchRenderingUpdatesInEventLoopCache: Boolean? = null override fun commonTestFlag(): Boolean { var cached = commonTestFlagCache @@ -36,6 +39,36 @@ class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAccessor { return cached } + override fun useModernRuntimeScheduler(): Boolean { + var cached = useModernRuntimeSchedulerCache + if (cached == null) { + cached = currentProvider.useModernRuntimeScheduler() + accessedFeatureFlags.add("useModernRuntimeScheduler") + useModernRuntimeSchedulerCache = cached + } + return cached + } + + override fun enableMicrotasks(): Boolean { + var cached = enableMicrotasksCache + if (cached == null) { + cached = currentProvider.enableMicrotasks() + accessedFeatureFlags.add("enableMicrotasks") + enableMicrotasksCache = cached + } + return cached + } + + override fun batchRenderingUpdatesInEventLoop(): Boolean { + var cached = batchRenderingUpdatesInEventLoopCache + if (cached == null) { + cached = currentProvider.batchRenderingUpdatesInEventLoop() + accessedFeatureFlags.add("batchRenderingUpdatesInEventLoop") + batchRenderingUpdatesInEventLoopCache = cached + } + return cached + } + override fun override(provider: ReactNativeFeatureFlagsProvider) { if (accessedFeatureFlags.isNotEmpty()) { val accessedFeatureFlagsStr = accessedFeatureFlags.joinToString(separator = ", ") { it } 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 23cd91d0da34dc..604ffee96ba49c 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<> + * @generated SignedSource<<42a6943246197e110c58027b285bdde5>> */ /** @@ -21,4 +21,7 @@ package com.facebook.react.internal.featureflags interface ReactNativeFeatureFlagsProvider { fun commonTestFlag(): Boolean + fun useModernRuntimeScheduler(): Boolean + fun enableMicrotasks(): Boolean + fun batchRenderingUpdatesInEventLoop(): Boolean } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactInstance.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactInstance.java index da24155a6758f3..f9191d23d5b81d 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactInstance.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactInstance.java @@ -170,9 +170,6 @@ public void onHostDestroy() { // Notify JS if profiling is enabled boolean isProfiling = Systrace.isTracing(Systrace.TRACE_TAG_REACT_APPS | Systrace.TRACE_TAG_REACT_JS_VM_CALLS); - // TODO(T166383606): Remove this parameter when we remove the legacy runtime scheduler or we - // have access to ReactNativeConfig before we initialize it. - boolean useModernRuntimeScheduler = ReactFeatureFlags.useModernRuntimeScheduler; mHybridData = initHybrid( jsRuntimeFactory, @@ -182,8 +179,7 @@ public void onHostDestroy() { jsTimerExecutor, reactExceptionManager, bindingsInstaller, - isProfiling, - useModernRuntimeScheduler); + isProfiling); // Set up TurboModules Systrace.beginSection( @@ -457,8 +453,7 @@ private native HybridData initHybrid( JSTimerExecutor jsTimerExecutor, ReactJsExceptionHandler jReactExceptionsManager, @Nullable BindingsInstaller jBindingsInstaller, - boolean isProfiling, - boolean useModernRuntimeScheduler); + boolean isProfiling); @DoNotStrip private static native JSTimerExecutor createJSTimerExecutor(); 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 ea67eac8841533..4a123e471a4686 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<> */ /** @@ -28,6 +28,21 @@ bool JReactNativeFeatureFlagsCxxInterop::commonTestFlag( return ReactNativeFeatureFlags::commonTestFlag(); } +bool JReactNativeFeatureFlagsCxxInterop::useModernRuntimeScheduler( + facebook::jni::alias_ref /*unused*/) { + return ReactNativeFeatureFlags::useModernRuntimeScheduler(); +} + +bool JReactNativeFeatureFlagsCxxInterop::enableMicrotasks( + facebook::jni::alias_ref /*unused*/) { + return ReactNativeFeatureFlags::enableMicrotasks(); +} + +bool JReactNativeFeatureFlagsCxxInterop::batchRenderingUpdatesInEventLoop( + facebook::jni::alias_ref /*unused*/) { + return ReactNativeFeatureFlags::batchRenderingUpdatesInEventLoop(); +} + void JReactNativeFeatureFlagsCxxInterop::override( facebook::jni::alias_ref /*unused*/, jni::alias_ref provider) { @@ -48,6 +63,15 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() { makeNativeMethod( "commonTestFlag", JReactNativeFeatureFlagsCxxInterop::commonTestFlag), + makeNativeMethod( + "useModernRuntimeScheduler", + JReactNativeFeatureFlagsCxxInterop::useModernRuntimeScheduler), + makeNativeMethod( + "enableMicrotasks", + JReactNativeFeatureFlagsCxxInterop::enableMicrotasks), + makeNativeMethod( + "batchRenderingUpdatesInEventLoop", + JReactNativeFeatureFlagsCxxInterop::batchRenderingUpdatesInEventLoop), }); } 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 0c02ca2f5ef89b..0a2e6b9c7f2318 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<> */ /** @@ -33,6 +33,15 @@ class JReactNativeFeatureFlagsCxxInterop static bool commonTestFlag( facebook::jni::alias_ref); + static bool useModernRuntimeScheduler( + facebook::jni::alias_ref); + + static bool enableMicrotasks( + facebook::jni::alias_ref); + + static bool batchRenderingUpdatesInEventLoop( + facebook::jni::alias_ref); + static void override( facebook::jni::alias_ref, jni::alias_ref provider); diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/ReactNativeFeatureFlagsProviderHolder.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/ReactNativeFeatureFlagsProviderHolder.cpp index 99ded3d88d1a60..e155ac51d61bc6 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/ReactNativeFeatureFlagsProviderHolder.cpp +++ b/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/ReactNativeFeatureFlagsProviderHolder.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<<7a019bd967a22f93cd9e2e0ddb5201e3>> + * @generated SignedSource<> */ /** @@ -29,4 +29,28 @@ bool ReactNativeFeatureFlagsProviderHolder::commonTestFlag() { return method(javaProvider_); } +bool ReactNativeFeatureFlagsProviderHolder::useModernRuntimeScheduler() { + static const auto method = + facebook::jni::findClassStatic( + "com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider") + ->getMethod("useModernRuntimeScheduler"); + return method(javaProvider_); +} + +bool ReactNativeFeatureFlagsProviderHolder::enableMicrotasks() { + static const auto method = + facebook::jni::findClassStatic( + "com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider") + ->getMethod("enableMicrotasks"); + return method(javaProvider_); +} + +bool ReactNativeFeatureFlagsProviderHolder::batchRenderingUpdatesInEventLoop() { + static const auto method = + facebook::jni::findClassStatic( + "com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider") + ->getMethod("batchRenderingUpdatesInEventLoop"); + return method(javaProvider_); +} + } // namespace facebook::react diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/ReactNativeFeatureFlagsProviderHolder.h b/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/ReactNativeFeatureFlagsProviderHolder.h index 6b22df569e8862..056c4ae634fab7 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/ReactNativeFeatureFlagsProviderHolder.h +++ b/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/ReactNativeFeatureFlagsProviderHolder.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<<9a2d162cbd83f3b5122d0eb86f6f9177>> + * @generated SignedSource<<3550f7ee28a53a4024a48301ee38ce7e>> */ /** @@ -36,6 +36,9 @@ class ReactNativeFeatureFlagsProviderHolder : javaProvider_(make_global(javaProvider)){}; bool commonTestFlag() override; + bool useModernRuntimeScheduler() override; + bool enableMicrotasks() override; + bool batchRenderingUpdatesInEventLoop() override; private: jni::global_ref javaProvider_; diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/runtime/jni/JReactInstance.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/runtime/jni/JReactInstance.cpp index 09a46dc4e58c90..0adccf64d7f1c1 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/runtime/jni/JReactInstance.cpp +++ b/packages/react-native/ReactAndroid/src/main/jni/react/runtime/jni/JReactInstance.cpp @@ -36,8 +36,7 @@ JReactInstance::JReactInstance( jni::alias_ref jsTimerExecutor, jni::alias_ref jReactExceptionManager, jni::alias_ref jBindingsInstaller, - bool isProfiling, - bool useModernRuntimeScheduler) noexcept { + bool isProfiling) noexcept { // TODO(janzer): Lazily create runtime auto sharedJSMessageQueueThread = std::make_shared(jsMessageQueueThread); @@ -65,8 +64,7 @@ JReactInstance::JReactInstance( jsRuntimeFactory->cthis()->createJSRuntime(sharedJSMessageQueueThread), sharedJSMessageQueueThread, timerManager, - std::move(jsErrorHandlingFunc), - useModernRuntimeScheduler); + std::move(jsErrorHandlingFunc)); auto bufferedRuntimeExecutor = instance_->getBufferedRuntimeExecutor(); timerManager->setRuntimeExecutor(bufferedRuntimeExecutor); @@ -117,8 +115,7 @@ jni::local_ref JReactInstance::initHybrid( jni::alias_ref jsTimerExecutor, jni::alias_ref jReactExceptionManager, jni::alias_ref jBindingsInstaller, - bool isProfiling, - bool useModernRuntimeScheduler) { + bool isProfiling) { return makeCxxInstance( jsRuntimeFactory, jsMessageQueueThread, @@ -127,8 +124,7 @@ jni::local_ref JReactInstance::initHybrid( jsTimerExecutor, jReactExceptionManager, jBindingsInstaller, - isProfiling, - useModernRuntimeScheduler); + isProfiling); } void JReactInstance::loadJSBundleFromAssets( diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/runtime/jni/JReactInstance.h b/packages/react-native/ReactAndroid/src/main/jni/react/runtime/jni/JReactInstance.h index 41ea4891bd50bf..b07ed7377fdfeb 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/runtime/jni/JReactInstance.h +++ b/packages/react-native/ReactAndroid/src/main/jni/react/runtime/jni/JReactInstance.h @@ -45,8 +45,7 @@ class JReactInstance : public jni::HybridClass { jni::alias_ref jsTimerExecutor, jni::alias_ref jReactExceptionManager, jni::alias_ref jBindingsInstaller, - bool isProfiling, - bool useModernRuntimeScheduler); + bool isProfiling); /* * Instantiates and returns an instance of `JSTimerExecutor`. @@ -91,8 +90,7 @@ class JReactInstance : public jni::HybridClass { jni::alias_ref jsTimerExecutor, jni::alias_ref jReactExceptionManager, jni::alias_ref jBindingsInstaller, - bool isProfiling, - bool useModernRuntimeScheduler) noexcept; + bool isProfiling) noexcept; jni::alias_ref getJSCallInvokerHolder(); jni::alias_ref diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp index 5325717c0f38b9..b524ab794b6f15 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<<85960128b845159e7de70d0e85910dd9>> + * @generated SignedSource<> */ /** @@ -25,6 +25,18 @@ bool ReactNativeFeatureFlags::commonTestFlag() { return getAccessor().commonTestFlag(); } +bool ReactNativeFeatureFlags::useModernRuntimeScheduler() { + return getAccessor().useModernRuntimeScheduler(); +} + +bool ReactNativeFeatureFlags::enableMicrotasks() { + return getAccessor().enableMicrotasks(); +} + +bool ReactNativeFeatureFlags::batchRenderingUpdatesInEventLoop() { + return getAccessor().batchRenderingUpdatesInEventLoop(); +} + void ReactNativeFeatureFlags::override( std::unique_ptr provider) { getAccessor().override(std::move(provider)); diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h index 96bf37fdf01503..74a859aa35c722 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<<502f6e74853b5bf526e42e682d4ca890>> + * @generated SignedSource<> */ /** @@ -37,6 +37,21 @@ class ReactNativeFeatureFlags { */ static bool commonTestFlag(); + /** + * When enabled, it uses the modern fork of RuntimeScheduler that allows scheduling tasks with priorities from any thread. + */ + static bool useModernRuntimeScheduler(); + + /** + * Enables the use of microtasks in Hermes (scheduling) and RuntimeScheduler (execution). + */ + static bool enableMicrotasks(); + + /** + * When enabled, the RuntimeScheduler processing the event loop will batch all rendering updates and dispatch them together at the end of each iteration of the loop. + */ + static bool batchRenderingUpdatesInEventLoop(); + /** * Overrides the feature flags with the ones provided by the given provider * (generally one that extends `ReactNativeFeatureFlagsDefaults`). diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp index 28bd0bc1a4502d..566c870dee004d 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<<7f8b2ae5c0b18aceeaac0ee60e53bdbb>> + * @generated SignedSource<<5df50987338c0541436b11cd5433013c>> */ /** @@ -45,6 +45,57 @@ bool ReactNativeFeatureFlagsAccessor::commonTestFlag() { return commonTestFlag_.value(); } +bool ReactNativeFeatureFlagsAccessor::useModernRuntimeScheduler() { + if (!useModernRuntimeScheduler_.has_value()) { + // Mark the flag as accessed. + static const char* flagName = "useModernRuntimeScheduler"; + if (std::find( + accessedFeatureFlags_.begin(), + accessedFeatureFlags_.end(), + flagName) == accessedFeatureFlags_.end()) { + accessedFeatureFlags_.push_back(flagName); + } + + useModernRuntimeScheduler_.emplace(currentProvider_->useModernRuntimeScheduler()); + } + + return useModernRuntimeScheduler_.value(); +} + +bool ReactNativeFeatureFlagsAccessor::enableMicrotasks() { + if (!enableMicrotasks_.has_value()) { + // Mark the flag as accessed. + static const char* flagName = "enableMicrotasks"; + if (std::find( + accessedFeatureFlags_.begin(), + accessedFeatureFlags_.end(), + flagName) == accessedFeatureFlags_.end()) { + accessedFeatureFlags_.push_back(flagName); + } + + enableMicrotasks_.emplace(currentProvider_->enableMicrotasks()); + } + + return enableMicrotasks_.value(); +} + +bool ReactNativeFeatureFlagsAccessor::batchRenderingUpdatesInEventLoop() { + if (!batchRenderingUpdatesInEventLoop_.has_value()) { + // Mark the flag as accessed. + static const char* flagName = "batchRenderingUpdatesInEventLoop"; + if (std::find( + accessedFeatureFlags_.begin(), + accessedFeatureFlags_.end(), + flagName) == accessedFeatureFlags_.end()) { + accessedFeatureFlags_.push_back(flagName); + } + + batchRenderingUpdatesInEventLoop_.emplace(currentProvider_->batchRenderingUpdatesInEventLoop()); + } + + return batchRenderingUpdatesInEventLoop_.value(); +} + void ReactNativeFeatureFlagsAccessor::override( std::unique_ptr provider) { if (!accessedFeatureFlags_.empty()) { diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h index 8c869a3c5c4c45..e6d2e177599a2c 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<<3fa0171b372cf6aae150b2ec159fc41e>> + * @generated SignedSource<<11335a9c0d793a3a5a0dfdb01cd43efd>> */ /** @@ -31,6 +31,9 @@ class ReactNativeFeatureFlagsAccessor { ReactNativeFeatureFlagsAccessor(); bool commonTestFlag(); + bool useModernRuntimeScheduler(); + bool enableMicrotasks(); + bool batchRenderingUpdatesInEventLoop(); void override(std::unique_ptr provider); @@ -39,6 +42,9 @@ class ReactNativeFeatureFlagsAccessor { std::vector accessedFeatureFlags_; std::optional commonTestFlag_; + std::optional useModernRuntimeScheduler_; + std::optional enableMicrotasks_; + std::optional batchRenderingUpdatesInEventLoop_; }; } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h index 5b196a5a5d073c..6e9965979bbb80 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<<76033e9fb87174da88e0ee922df28701>> + * @generated SignedSource<> */ /** @@ -30,6 +30,18 @@ class ReactNativeFeatureFlagsDefaults : public ReactNativeFeatureFlagsProvider { bool commonTestFlag() override { return false; } + + bool useModernRuntimeScheduler() override { + return false; + } + + bool enableMicrotasks() override { + return false; + } + + bool batchRenderingUpdatesInEventLoop() override { + return false; + } }; } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h index 5c1c30c24d5825..68c16ecad83ea2 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<<20dfc971dddc23a6d0cc55938b0d65b7>> + * @generated SignedSource<<6bf1fc0d7b32a36041c2371fe191792b>> */ /** @@ -26,6 +26,9 @@ class ReactNativeFeatureFlagsProvider { virtual ~ReactNativeFeatureFlagsProvider() = default; virtual bool commonTestFlag() = 0; + virtual bool useModernRuntimeScheduler() = 0; + virtual bool enableMicrotasks() = 0; + virtual bool batchRenderingUpdatesInEventLoop() = 0; }; } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp index 63bd0852c036a8..421e4b3925f437 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<<01b940f6716765f9359c42180db497c0>> */ /** @@ -40,4 +40,19 @@ bool NativeReactNativeFeatureFlags::commonTestFlag( return ReactNativeFeatureFlags::commonTestFlag(); } +bool NativeReactNativeFeatureFlags::useModernRuntimeScheduler( + jsi::Runtime& /*runtime*/) { + return ReactNativeFeatureFlags::useModernRuntimeScheduler(); +} + +bool NativeReactNativeFeatureFlags::enableMicrotasks( + jsi::Runtime& /*runtime*/) { + return ReactNativeFeatureFlags::enableMicrotasks(); +} + +bool NativeReactNativeFeatureFlags::batchRenderingUpdatesInEventLoop( + jsi::Runtime& /*runtime*/) { + return ReactNativeFeatureFlags::batchRenderingUpdatesInEventLoop(); +} + } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h index 44bb7771143fa9..d3f46b1a667e91 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<<18a3543b75c44e00bdf73ca2f12d230c>> + * @generated SignedSource<<200fe2cf84a044164c60f6dd3c5569dd>> */ /** @@ -31,6 +31,12 @@ class NativeReactNativeFeatureFlags NativeReactNativeFeatureFlags(std::shared_ptr jsInvoker); bool commonTestFlag(jsi::Runtime& runtime); + + bool useModernRuntimeScheduler(jsi::Runtime& runtime); + + bool enableMicrotasks(jsi::Runtime& runtime); + + bool batchRenderingUpdatesInEventLoop(jsi::Runtime& runtime); }; } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/renderer/runtimescheduler/CMakeLists.txt b/packages/react-native/ReactCommon/react/renderer/runtimescheduler/CMakeLists.txt index b8ad2984c8e563..7c7ec30f4ebf7a 100644 --- a/packages/react-native/ReactCommon/react/renderer/runtimescheduler/CMakeLists.txt +++ b/packages/react-native/ReactCommon/react/renderer/runtimescheduler/CMakeLists.txt @@ -26,4 +26,5 @@ target_link_libraries(react_render_runtimescheduler react_render_core react_render_debug react_utils + react_featureflags runtimeexecutor) diff --git a/packages/react-native/ReactCommon/react/renderer/runtimescheduler/React-runtimescheduler.podspec b/packages/react-native/ReactCommon/react/renderer/runtimescheduler/React-runtimescheduler.podspec index 3d44f25c8b2e06..642d71980a948b 100644 --- a/packages/react-native/ReactCommon/react/renderer/runtimescheduler/React-runtimescheduler.podspec +++ b/packages/react-native/ReactCommon/react/renderer/runtimescheduler/React-runtimescheduler.podspec @@ -56,6 +56,7 @@ Pod::Spec.new do |s| s.dependency "React-cxxreact" s.dependency "React-rendererdebug" s.dependency "React-utils" + s.dependency "React-featureflags" s.dependency "glog" s.dependency "RCT-Folly", folly_version s.dependency "React-jsi" diff --git a/packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler.cpp b/packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler.cpp index df44f0523a6639..79be477d2c240a 100644 --- a/packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler.cpp +++ b/packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler.cpp @@ -10,6 +10,7 @@ #include "RuntimeScheduler_Modern.h" #include "SchedulerPriorityUtils.h" +#include #include #include #include "ErrorUtils.h" @@ -19,9 +20,8 @@ namespace facebook::react { namespace { std::unique_ptr getRuntimeSchedulerImplementation( RuntimeExecutor runtimeExecutor, - bool useModernRuntimeScheduler, std::function now) { - if (useModernRuntimeScheduler) { + if (ReactNativeFeatureFlags::useModernRuntimeScheduler()) { return std::make_unique( std::move(runtimeExecutor), std::move(now)); } else { @@ -33,11 +33,9 @@ std::unique_ptr getRuntimeSchedulerImplementation( RuntimeScheduler::RuntimeScheduler( RuntimeExecutor runtimeExecutor, - bool useModernRuntimeScheduler, std::function now) : runtimeSchedulerImpl_(getRuntimeSchedulerImplementation( std::move(runtimeExecutor), - useModernRuntimeScheduler, std::move(now))) {} void RuntimeScheduler::scheduleWork(RawCallback&& callback) noexcept { diff --git a/packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler.h b/packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler.h index 40482a9872a838..26c2c336202df2 100644 --- a/packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler.h +++ b/packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler.h @@ -44,7 +44,6 @@ class RuntimeScheduler final : RuntimeSchedulerBase { public: explicit RuntimeScheduler( RuntimeExecutor runtimeExecutor, - bool useModernRuntimeScheduler = false, std::function now = RuntimeSchedulerClock::now); diff --git a/packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler_Modern.cpp b/packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler_Modern.cpp index 033d5a2219e451..4a30a2ff5c4034 100644 --- a/packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler_Modern.cpp +++ b/packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler_Modern.cpp @@ -9,8 +9,8 @@ #include "SchedulerPriorityUtils.h" #include +#include #include -#include #include #include "ErrorUtils.h" @@ -173,7 +173,7 @@ void RuntimeScheduler_Modern::executeNowOnTheSameThread( void RuntimeScheduler_Modern::callExpiredTasks(jsi::Runtime& runtime) { // If we have first-class support for microtasks, this a no-op. - if (CoreFeatures::enableMicrotasks) { + if (ReactNativeFeatureFlags::enableMicrotasks()) { return; } @@ -185,7 +185,7 @@ void RuntimeScheduler_Modern::scheduleRenderingUpdate( RuntimeSchedulerRenderingUpdate&& renderingUpdate) { SystraceSection s("RuntimeScheduler::scheduleRenderingUpdate"); - if (CoreFeatures::blockPaintForUseLayoutEffect) { + if (ReactNativeFeatureFlags::batchRenderingUpdatesInEventLoop()) { pendingRenderingUpdates_.push(renderingUpdate); } else { if (renderingUpdate != nullptr) { @@ -296,12 +296,12 @@ void RuntimeScheduler_Modern::executeTask( executeMacrotask(runtime, task, didUserCallbackTimeout); - if (CoreFeatures::enableMicrotasks) { + if (ReactNativeFeatureFlags::enableMicrotasks()) { // "Perform a microtask checkpoint" step. executeMicrotasks(runtime); } - if (CoreFeatures::blockPaintForUseLayoutEffect) { + if (ReactNativeFeatureFlags::batchRenderingUpdatesInEventLoop()) { // "Update the rendering" step. updateRendering(); } diff --git a/packages/react-native/ReactCommon/react/renderer/runtimescheduler/tests/RuntimeSchedulerTest.cpp b/packages/react-native/ReactCommon/react/renderer/runtimescheduler/tests/RuntimeSchedulerTest.cpp index 8897a223d05b87..0eb595cca89a80 100644 --- a/packages/react-native/ReactCommon/react/renderer/runtimescheduler/tests/RuntimeSchedulerTest.cpp +++ b/packages/react-native/ReactCommon/react/renderer/runtimescheduler/tests/RuntimeSchedulerTest.cpp @@ -8,8 +8,9 @@ #include #include #include +#include +#include #include -#include #include #include @@ -21,19 +22,41 @@ namespace facebook::react { using namespace std::chrono_literals; +static bool forcedBatchRenderingUpdatesInEventLoop = false; + +class RuntimeSchedulerTestFeatureFlags + : public ReactNativeFeatureFlagsDefaults { + public: + RuntimeSchedulerTestFeatureFlags(bool useModernRuntimeScheduler) + : useModernRuntimeScheduler_(useModernRuntimeScheduler) {} + + bool useModernRuntimeScheduler() override { + return useModernRuntimeScheduler_; + } + + bool enableMicrotasks() override { + return useModernRuntimeScheduler_; + } + + bool batchRenderingUpdatesInEventLoop() override { + return forcedBatchRenderingUpdatesInEventLoop; + } + + private: + bool useModernRuntimeScheduler_; +}; + class RuntimeSchedulerTest : public testing::TestWithParam { protected: void SetUp() override { hostFunctionCallCount_ = 0; - auto useModernRuntimeScheduler = GetParam(); - - CoreFeatures::enableMicrotasks = useModernRuntimeScheduler; + ReactNativeFeatureFlags::override( + std::make_unique(GetParam())); // Configuration that enables microtasks ::hermes::vm::RuntimeConfig::Builder runtimeConfigBuilder = - ::hermes::vm::RuntimeConfig::Builder().withMicrotaskQueue( - useModernRuntimeScheduler); + ::hermes::vm::RuntimeConfig::Builder().withMicrotaskQueue(GetParam()); runtime_ = facebook::hermes::makeHermesRuntime(runtimeConfigBuilder.build()); @@ -54,8 +77,12 @@ class RuntimeSchedulerTest : public testing::TestWithParam { return stubClock_->getNow(); }; - runtimeScheduler_ = std::make_unique( - runtimeExecutor, useModernRuntimeScheduler, stubNow); + runtimeScheduler_ = + std::make_unique(runtimeExecutor, stubNow); + } + + void TearDown() override { + ReactNativeFeatureFlags::reset(); } jsi::Function createHostFunctionFromLambda( @@ -125,7 +152,7 @@ TEST_P(RuntimeSchedulerTest, scheduleSingleTask) { } TEST_P(RuntimeSchedulerTest, scheduleNonBatchedRenderingUpdate) { - CoreFeatures::blockPaintForUseLayoutEffect = false; + forcedBatchRenderingUpdatesInEventLoop = false; bool didRunRenderingUpdate = false; @@ -143,7 +170,7 @@ TEST_P( return; } - CoreFeatures::blockPaintForUseLayoutEffect = true; + forcedBatchRenderingUpdatesInEventLoop = true; uint nextOperationPosition = 1; diff --git a/packages/react-native/ReactCommon/react/renderer/scheduler/Scheduler.cpp b/packages/react-native/ReactCommon/react/renderer/scheduler/Scheduler.cpp index 3c08d80aa3de4d..b5493677cd007e 100644 --- a/packages/react-native/ReactCommon/react/renderer/scheduler/Scheduler.cpp +++ b/packages/react-native/ReactCommon/react/renderer/scheduler/Scheduler.cpp @@ -142,17 +142,6 @@ Scheduler::Scheduler( "react_fabric:remove_outstanding_surfaces_on_destruction_ios"); #endif -#ifdef ANDROID - CoreFeatures::enableMicrotasks = - reactNativeConfig_->getBool("react_fabric:enable_microtasks_android"); -#else - CoreFeatures::enableMicrotasks = - reactNativeConfig_->getBool("react_fabric:enable_microtasks_ios"); -#endif - - CoreFeatures::blockPaintForUseLayoutEffect = reactNativeConfig_->getBool( - "react_fabric:block_paint_for_use_layout_effect"); - CoreFeatures::cacheLastTextMeasurement = reactNativeConfig_->getBool("react_fabric:enable_text_measure_cache"); diff --git a/packages/react-native/ReactCommon/react/runtime/CMakeLists.txt b/packages/react-native/ReactCommon/react/runtime/CMakeLists.txt index 85cd27912630aa..712f8c0cf858b8 100644 --- a/packages/react-native/ReactCommon/react/runtime/CMakeLists.txt +++ b/packages/react-native/ReactCommon/react/runtime/CMakeLists.txt @@ -37,4 +37,5 @@ target_link_libraries( jsireact react_utils jsinspector + react_featureflags ) diff --git a/packages/react-native/ReactCommon/react/runtime/React-RuntimeCore.podspec b/packages/react-native/ReactCommon/react/runtime/React-RuntimeCore.podspec index d75f5ea1cd8fe2..93f5f2f120eb1e 100644 --- a/packages/react-native/ReactCommon/react/runtime/React-RuntimeCore.podspec +++ b/packages/react-native/ReactCommon/react/runtime/React-RuntimeCore.podspec @@ -55,6 +55,7 @@ Pod::Spec.new do |s| s.dependency "React-jserrorhandler" s.dependency "React-runtimescheduler" s.dependency "React-utils" + s.dependency "React-featureflags" if ENV["USE_HERMES"] == nil || ENV["USE_HERMES"] == "1" s.dependency "hermes-engine" diff --git a/packages/react-native/ReactCommon/react/runtime/React-RuntimeHermes.podspec b/packages/react-native/ReactCommon/react/runtime/React-RuntimeHermes.podspec index 6fb5d40b348b37..15ba2bde3eafa8 100644 --- a/packages/react-native/ReactCommon/react/runtime/React-RuntimeHermes.podspec +++ b/packages/react-native/ReactCommon/react/runtime/React-RuntimeHermes.podspec @@ -50,6 +50,7 @@ Pod::Spec.new do |s| s.dependency "React-utils" s.dependency "React-jsi" s.dependency "React-RuntimeCore" + s.dependency "React-featureflags" if ENV["USE_HERMES"] == nil || ENV["USE_HERMES"] == "1" s.dependency "hermes-engine" diff --git a/packages/react-native/ReactCommon/react/runtime/ReactInstance.cpp b/packages/react-native/ReactCommon/react/runtime/ReactInstance.cpp index 76b8029d258e46..75960335f68daf 100644 --- a/packages/react-native/ReactCommon/react/runtime/ReactInstance.cpp +++ b/packages/react-native/ReactCommon/react/runtime/ReactInstance.cpp @@ -15,8 +15,8 @@ #include #include #include +#include #include -#include #include #include @@ -29,8 +29,7 @@ ReactInstance::ReactInstance( std::unique_ptr runtime, std::shared_ptr jsMessageQueueThread, std::shared_ptr timerManager, - JsErrorHandler::JsErrorHandlingFunc jsErrorHandlingFunc, - bool useModernRuntimeScheduler) + JsErrorHandler::JsErrorHandlingFunc jsErrorHandlingFunc) : runtime_(std::move(runtime)), jsMessageQueueThread_(jsMessageQueueThread), timerManager_(std::move(timerManager)), @@ -70,7 +69,7 @@ ReactInstance::ReactInstance( // If we have first-class support for microtasks, // they would've been called as part of the previous callback. - if (!CoreFeatures::enableMicrotasks) { + if (!ReactNativeFeatureFlags::enableMicrotasks()) { if (auto strongTimerManager = weakTimerManager.lock()) { strongTimerManager->callReactNativeMicrotasks(jsiRuntime); } @@ -83,8 +82,8 @@ ReactInstance::ReactInstance( } }; - runtimeScheduler_ = std::make_shared( - std::move(runtimeExecutor), useModernRuntimeScheduler); + runtimeScheduler_ = + std::make_shared(std::move(runtimeExecutor)); auto pipedRuntimeExecutor = [runtimeScheduler = runtimeScheduler_.get()]( diff --git a/packages/react-native/ReactCommon/react/runtime/ReactInstance.h b/packages/react-native/ReactCommon/react/runtime/ReactInstance.h index caad761b7f07f5..b33bef28db0a23 100644 --- a/packages/react-native/ReactCommon/react/runtime/ReactInstance.h +++ b/packages/react-native/ReactCommon/react/runtime/ReactInstance.h @@ -33,8 +33,7 @@ class ReactInstance final { std::unique_ptr runtime, std::shared_ptr jsMessageQueueThread, std::shared_ptr timerManager, - JsErrorHandler::JsErrorHandlingFunc JsErrorHandlingFunc, - bool useModernRuntimeScheduler = false); + JsErrorHandler::JsErrorHandlingFunc JsErrorHandlingFunc); RuntimeExecutor getUnbufferedRuntimeExecutor() noexcept; diff --git a/packages/react-native/ReactCommon/react/runtime/hermes/CMakeLists.txt b/packages/react-native/ReactCommon/react/runtime/hermes/CMakeLists.txt index e46f159bd12f96..cbca9d9ba948fb 100644 --- a/packages/react-native/ReactCommon/react/runtime/hermes/CMakeLists.txt +++ b/packages/react-native/ReactCommon/react/runtime/hermes/CMakeLists.txt @@ -23,6 +23,7 @@ target_link_libraries(bridgelesshermes jsi hermes_executor_common bridgeless + react_featureflags ) if(${CMAKE_BUILD_TYPE} MATCHES Debug) diff --git a/packages/react-native/ReactCommon/react/runtime/hermes/HermesInstance.cpp b/packages/react-native/ReactCommon/react/runtime/hermes/HermesInstance.cpp index 6938f93b400814..50ec845f41cf61 100644 --- a/packages/react-native/ReactCommon/react/runtime/hermes/HermesInstance.cpp +++ b/packages/react-native/ReactCommon/react/runtime/hermes/HermesInstance.cpp @@ -9,6 +9,7 @@ #include #include +#include #ifdef HERMES_ENABLE_DEBUGGER #include @@ -107,16 +108,6 @@ std::unique_ptr HermesInstance::createJSRuntime( ? static_cast<::hermes::vm::gcheapsize_t>(heapSizeConfig) : 3072; -#ifdef ANDROID - bool enableMicrotasks = reactNativeConfig - ? reactNativeConfig->getBool("react_fabric:enable_microtasks_android") - : false; -#else - bool enableMicrotasks = reactNativeConfig - ? reactNativeConfig->getBool("react_fabric:enable_microtasks_ios") - : false; -#endif - ::hermes::vm::RuntimeConfig::Builder runtimeConfigBuilder = ::hermes::vm::RuntimeConfig::Builder() .withGCConfig(::hermes::vm::GCConfig::Builder() @@ -131,7 +122,7 @@ std::unique_ptr HermesInstance::createJSRuntime( .build()) .withES6Proxy(false) .withEnableSampleProfiling(true) - .withMicrotaskQueue(enableMicrotasks) + .withMicrotaskQueue(ReactNativeFeatureFlags::enableMicrotasks()) .withVMExperimentFlags(vmExperimentFlags); if (cm) { diff --git a/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTHost.h b/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTHost.h index 124504a638f997..6b869377a836a5 100644 --- a/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTHost.h +++ b/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTHost.h @@ -35,18 +35,6 @@ NS_ASSUME_NONNULL_BEGIN @end -/** - * This is a private protocol used to configure internal behavior of the runtime. - * DO NOT USE THIS OUTSIDE OF THE REACT NATIVE CODEBASE. - */ -@protocol RCTHostDelegateInternal - -// TODO(T166383606): Remove this method when we remove the legacy runtime scheduler or we have access to -// ReactNativeConfig before we initialize it. -- (BOOL)useModernRuntimeScheduler:(RCTHost *)host; - -@end - @protocol RCTHostRuntimeDelegate - (void)host:(RCTHost *)host didInitializeRuntime:(facebook::jsi::Runtime &)runtime; diff --git a/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTHost.mm b/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTHost.mm index 6b7cc6111412aa..16f9426e2a7125 100644 --- a/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTHost.mm +++ b/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTHost.mm @@ -42,7 +42,7 @@ void onReload(const PageReloadRequest &request) override __weak RCTHost *host_; }; -@interface RCTHost () +@interface RCTHost () @end @implementation RCTHost { @@ -299,17 +299,6 @@ - (void)instance:(RCTInstance *)instance didInitializeRuntime:(facebook::jsi::Ru [self.runtimeDelegate host:self didInitializeRuntime:runtime]; } -#pragma mark - RCTInstanceDelegateInternal - -- (BOOL)useModernRuntimeScheduler:(RCTHost *)host -{ - if ([_hostDelegate respondsToSelector:@selector(useModernRuntimeScheduler:)]) { - return [(id)_hostDelegate useModernRuntimeScheduler:self]; - } - - return NO; -} - #pragma mark - RCTContextContainerHandling - (void)didCreateContextContainer:(std::shared_ptr)contextContainer diff --git a/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTInstance.h b/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTInstance.h index 047dc38af97774..befe718b0535be 100644 --- a/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTInstance.h +++ b/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTInstance.h @@ -46,18 +46,6 @@ RCT_EXTERN void RCTInstanceSetRuntimeDiagnosticFlags(NSString *_Nullable flags); @end -/** - * This is a private protocol used to configure internal behavior of the runtime. - * DO NOT USE THIS OUTSIDE OF THE REACT NATIVE CODEBASE. - */ -@protocol RCTInstanceDelegateInternal - -// TODO(T166383606): Remove this method when we remove the legacy runtime scheduler or we have access to -// ReactNativeConfig before we initialize it. -- (BOOL)useModernRuntimeScheduler:(RCTInstance *)instance; - -@end - typedef void (^_Null_unspecified RCTInstanceInitialBundleLoadCompletionBlock)(); /** 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 6ed73ed4d85814..03d6d9a25ae47f 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 @@ -216,18 +216,12 @@ - (void)_start __weak __typeof(self) weakSelf = self; auto jsErrorHandlingFunc = [=](MapBuffer errorMap) { [weakSelf _handleJSErrorMap:std::move(errorMap)]; }; - auto useModernRuntimeScheduler = false; - if ([_delegate respondsToSelector:@selector(useModernRuntimeScheduler:)]) { - useModernRuntimeScheduler = [(id)_delegate useModernRuntimeScheduler:self]; - } - // Create the React Instance _reactInstance = std::make_unique( _jsRuntimeFactory->createJSRuntime(_jsThreadManager.jsMessageThread), _jsThreadManager.jsMessageThread, timerManager, - jsErrorHandlingFunc, - useModernRuntimeScheduler); + jsErrorHandlingFunc); _valid = true; RuntimeExecutor bufferedRuntimeExecutor = _reactInstance->getBufferedRuntimeExecutor(); diff --git a/packages/react-native/ReactCommon/react/utils/CoreFeatures.cpp b/packages/react-native/ReactCommon/react/utils/CoreFeatures.cpp index fcdc92e97f9941..19b3535c5473c1 100644 --- a/packages/react-native/ReactCommon/react/utils/CoreFeatures.cpp +++ b/packages/react-native/ReactCommon/react/utils/CoreFeatures.cpp @@ -10,7 +10,6 @@ namespace facebook::react { bool CoreFeatures::enablePropIteratorSetter = false; -bool CoreFeatures::blockPaintForUseLayoutEffect = false; bool CoreFeatures::cacheLastTextMeasurement = false; bool CoreFeatures::cancelImageDownloadsOnRecycle = false; bool CoreFeatures::enableGranularScrollViewStateUpdatesIOS = false; @@ -19,7 +18,6 @@ bool CoreFeatures::enableGranularShadowTreeStateReconciliation = false; bool CoreFeatures::enableDefaultAsyncBatchedPriority = false; bool CoreFeatures::enableClonelessStateProgression = false; bool CoreFeatures::excludeYogaFromRawProps = false; -bool CoreFeatures::enableMicrotasks = false; bool CoreFeatures::enableReportEventPaintTime = false; } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/utils/CoreFeatures.h b/packages/react-native/ReactCommon/react/utils/CoreFeatures.h index 2af28d74a10b9e..7e94452c58d56a 100644 --- a/packages/react-native/ReactCommon/react/utils/CoreFeatures.h +++ b/packages/react-native/ReactCommon/react/utils/CoreFeatures.h @@ -19,11 +19,6 @@ class CoreFeatures { // Specifies whether the iterator-style prop parsing is enabled. static bool enablePropIteratorSetter; - // When enabled, Fabric will block paint to allow for state updates in - // useLayoutEffect hooks to be processed. This changes affects scheduling of - // when a transaction is mounted. - static bool blockPaintForUseLayoutEffect; - // Yoga might measure multiple times the same Text with the same constraints // This flag enables a caching mechanism to avoid subsequents measurements // of the same Text with the same constrainst. @@ -54,10 +49,6 @@ class CoreFeatures { // When enabled, rawProps in Props will not include Yoga specific props. static bool excludeYogaFromRawProps; - // Enables the use of microtasks in Hermes (scheduling) and RuntimeScheduler - // (execution). - static bool enableMicrotasks; - // Report paint time inside the Event Timing API implementation // (PerformanceObserver). static bool enableReportEventPaintTime; diff --git a/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.json b/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.json index 974c2f6fce5c13..dc94424def4951 100644 --- a/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.json +++ b/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.json @@ -3,6 +3,18 @@ "commonTestFlag": { "description": "Common flag for testing. Do NOT modify.", "defaultValue": false + }, + "useModernRuntimeScheduler": { + "description": "When enabled, it uses the modern fork of RuntimeScheduler that allows scheduling tasks with priorities from any thread.", + "defaultValue": false + }, + "enableMicrotasks": { + "description": "Enables the use of microtasks in Hermes (scheduling) and RuntimeScheduler (execution).", + "defaultValue": false + }, + "batchRenderingUpdatesInEventLoop": { + "description": "When enabled, the RuntimeScheduler processing the event loop will batch all rendering updates and dispatch them together at the end of each iteration of the loop.", + "defaultValue": false } }, "jsOnly": { diff --git a/packages/react-native/src/private/featureflags/NativeReactNativeFeatureFlags.js b/packages/react-native/src/private/featureflags/NativeReactNativeFeatureFlags.js index 3132692c948d21..f7f7cfc43347bf 100644 --- a/packages/react-native/src/private/featureflags/NativeReactNativeFeatureFlags.js +++ b/packages/react-native/src/private/featureflags/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<> + * @generated SignedSource<<564159837241d197ebc3084ff9e72b7c>> * @flow strict-local */ @@ -24,6 +24,9 @@ import * as TurboModuleRegistry from '../../../Libraries/TurboModule/TurboModule export interface Spec extends TurboModule { +commonTestFlag?: () => boolean; + +useModernRuntimeScheduler?: () => boolean; + +enableMicrotasks?: () => boolean; + +batchRenderingUpdatesInEventLoop?: () => boolean; } const NativeReactNativeFeatureFlags: ?Spec = TurboModuleRegistry.get( diff --git a/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js b/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js index 8495e3af234525..09fa4b1a8c6807 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<<4e4ce58c1ce1a95355bba0dfe099e26e>> * @flow strict-local */ @@ -34,6 +34,9 @@ export type ReactNativeFeatureFlagsJsOnlyOverrides = Partial, + useModernRuntimeScheduler: Getter, + enableMicrotasks: Getter, + batchRenderingUpdatesInEventLoop: Getter, } /** @@ -45,6 +48,18 @@ export const jsOnlyTestFlag: Getter = createJavaScriptFlagGetter('jsOnl * Common flag for testing. Do NOT modify. */ export const commonTestFlag: Getter = createNativeFlagGetter('commonTestFlag', false); +/** + * When enabled, it uses the modern fork of RuntimeScheduler that allows scheduling tasks with priorities from any thread. + */ +export const useModernRuntimeScheduler: Getter = createNativeFlagGetter('useModernRuntimeScheduler', false); +/** + * Enables the use of microtasks in Hermes (scheduling) and RuntimeScheduler (execution). + */ +export const enableMicrotasks: Getter = createNativeFlagGetter('enableMicrotasks', false); +/** + * When enabled, the RuntimeScheduler processing the event loop will batch all rendering updates and dispatch them together at the end of each iteration of the loop. + */ +export const batchRenderingUpdatesInEventLoop: Getter = createNativeFlagGetter('batchRenderingUpdatesInEventLoop', false); /** * Overrides the feature flags with the provided methods.