Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RN] Move feature flags for the event loop to ReactNativeFeatureFlags #42434

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
"flow": "flow",
"format-check": "prettier --list-different \"./**/*.{js,md,yml,ts,tsx}\"",
"format": "npm run prettier && npm run clang-format",
"featureflags-check": "cd packages/react-native && yarn featureflags-check",
"featureflags-update": "cd packages/react-native && yarn featureflags-update",
"lint-ci": "./scripts/circleci/analyze_code.sh && yarn shellcheck",
"lint-java": "node ./scripts/lint-java.js",
"lint": "eslint .",
Expand Down
1 change: 1 addition & 0 deletions packages/react-native/React-Core.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ Pod::Spec.new do |s|
s.dependency "React-jsi"
s.dependency "React-jsiexecutor"
s.dependency "React-utils"
s.dependency "React-featureflags"
s.dependency "SocketRocket", socket_rocket_version
s.dependency "React-runtimescheduler"
s.dependency "Yoga"
Expand Down
1 change: 0 additions & 1 deletion packages/react-native/ReactAndroid/api/ReactAndroid.api
Original file line number Diff line number Diff line change
Expand Up @@ -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 <init> ()V
Expand Down
2 changes: 2 additions & 0 deletions packages/react-native/ReactAndroid/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,7 @@ android {
"runtimeexecutor",
"react_codegen_rncore",
"react_debug",
"react_featureflags",
"react_utils",
"react_render_componentregistry",
"react_newarchdefaults",
Expand All @@ -540,6 +541,7 @@ android {
"jsi",
"glog",
"fabricjni",
"featureflagsjni",
"react_render_mapbuffer",
"yoga",
"folly_runtime",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<52367278b4d0fdf7f436bd8c511d4ffe>>
*/

/**
* IMPORTANT: Do NOT modify this file directly.
*
* To change the definition of the flags, edit
* packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.json.
*
* To regenerate this code, run the following script from the repo root:
* yarn featureflags-update
*/

package com.facebook.react.internal.featureflags

/**
* This object provides access to internal React Native feature flags.
*
* All the methods are thread-safe if you handle `override` correctly.
*/
object ReactNativeFeatureFlags {
private var accessorProvider: () -> ReactNativeFeatureFlagsAccessor = { ReactNativeFeatureFlagsCxxAccessor() }
private var accessor: ReactNativeFeatureFlagsAccessor = accessorProvider()

/**
* Common flag for testing. Do NOT modify.
*/
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`).
*
* This method must be called before you initialize the React Native runtime.
*
* @example
*
* ```
* ReactNativeFeatureFlags.override(object : ReactNativeFeatureFlagsDefaults() {
* override fun someFlag(): Boolean = true // or a dynamic value
* })
* ```
*/
fun override(provider: ReactNativeFeatureFlagsProvider) = accessor.override(provider)

/**
* Removes the overridden feature flags and makes the API return default
* values again.
*
* This should only be called if you destroy the React Native runtime and
* need to create a new one with different overrides. In that case,
* call `dangerouslyReset` after destroying the runtime and `override`
* again before initializing the new one.
*/
fun dangerouslyReset() {
// This is necessary when the accessor interops with C++ and we need to
// remove the overrides set there.
accessor.dangerouslyReset()

// This discards the cached values and the overrides set in the JVM.
accessor = accessorProvider()
}

/**
* This is just used to replace the default ReactNativeFeatureFlagsCxxAccessor
* that uses JNI with a version that doesn't, to simplify testing.
*/
internal fun setAccessorProvider(newAccessorProvider: () -> ReactNativeFeatureFlagsAccessor) {
accessorProvider = newAccessorProvider
accessor = accessorProvider()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

package com.facebook.react.internal.featureflags

interface ReactNativeFeatureFlagsAccessor : ReactNativeFeatureFlagsProvider {
fun override(provider: ReactNativeFeatureFlagsProvider)

fun dangerouslyReset()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<920bb26d238f935f63a77943df7ef6e2>>
*/

/**
* IMPORTANT: Do NOT modify this file directly.
*
* To change the definition of the flags, edit
* packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.json.
*
* To regenerate this code, run the following script from the repo root:
* yarn featureflags-update
*/

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
if (cached == null) {
cached = ReactNativeFeatureFlagsCxxInterop.commonTestFlag()
commonTestFlagCache = cached
}
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)

override fun dangerouslyReset() = ReactNativeFeatureFlagsCxxInterop.dangerouslyReset()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<07894609de6f9d34f7d25d372fd0e6ef>>
*/

/**
* IMPORTANT: Do NOT modify this file directly.
*
* To change the definition of the flags, edit
* packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.json.
*
* To regenerate this code, run the following script from the repo root:
* yarn featureflags-update
*/

package com.facebook.react.internal.featureflags

import com.facebook.proguard.annotations.DoNotStrip
import com.facebook.soloader.SoLoader

@DoNotStrip
object ReactNativeFeatureFlagsCxxInterop {
init {
SoLoader.loadLibrary("reactfeatureflagsjni")
}

@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)

@DoNotStrip @JvmStatic external fun dangerouslyReset()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<8c97f44276e919fc32eea07408441404>>
*/

/**
* IMPORTANT: Do NOT modify this file directly.
*
* To change the definition of the flags, edit
* packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.json.
*
* To regenerate this code, run the following script from the repo root:
* yarn featureflags-update
*/

package com.facebook.react.internal.featureflags

open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvider {
// We could use JNI to get the defaults from C++,
// 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
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

package com.facebook.react.internal.featureflags

object ReactNativeFeatureFlagsForTests {
fun setUp() {
ReactNativeFeatureFlags.setAccessorProvider({ ReactNativeFeatureFlagsLocalAccessor() })
}
}
Loading
Loading