mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Compare commits
10
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a702256079 | ||
|
|
813b9441ca | ||
|
|
cf5040b4f8 | ||
|
|
019a553ea4 | ||
|
|
2ae5a74f06 | ||
|
|
3d4a4caac8 | ||
|
|
cdc4a8ead4 | ||
|
|
226d2ba160 | ||
|
|
a16c6c9477 | ||
|
|
59b8974d3c |
@@ -1,5 +1,37 @@
|
||||
# Changelog
|
||||
|
||||
## v0.82.0-rc.1
|
||||
|
||||
### Added
|
||||
|
||||
#### Android specific
|
||||
|
||||
- **Hermes V1:** Added opt-in to use the new Hermes ([3e9990f860](https://github.com/facebook/react-native/commit/3e9990f860eb9380837ef431ca02def32c4261ad) by [@j-piasecki](https://github.com/j-piasecki))
|
||||
|
||||
#### iOS specific
|
||||
|
||||
- **Hermes V1:** Added opt-in to use the new Hermes ([e9cdc308b4](https://github.com/facebook/react-native/commit/e9cdc308b4c04753d85757e8877ac00c3c687b95) by [@j-piasecki](https://github.com/j-piasecki))
|
||||
|
||||
### Changed
|
||||
|
||||
- **Hermes V1:** Changed the source of hermesc binary to be an npm package ([2e0bd13a25](https://github.com/facebook/react-native/commit/2e0bd13a2533fe7ab64125a95b9215b806018c6e) by [@j-piasecki](https://github.com/j-piasecki))
|
||||
|
||||
### Deprecated
|
||||
|
||||
- **APIs:** Deprecate legacy javascript react native apis ([e7aeea26bd](https://github.com/facebook/react-native/commit/e7aeea26bde6e9cda0a3a0a55fc2a0421fb0c0e5) by [@RSNara](https://github.com/RSNara))
|
||||
|
||||
### Fixed
|
||||
|
||||
#### Android specific
|
||||
|
||||
- **Build From Source:** Fix build from source due to missing folder error on Gradle 9.0 ([9fbce3eff1](https://github.com/facebook/react-native/commit/9fbce3eff18060f16e796badc415ba733ede19af) by [@cortinico](https://github.com/cortinico))
|
||||
|
||||
#### iOS specific
|
||||
|
||||
- **RCTAlertController:** Simplify RCTAlertController, don't create additional UIWindow ([05c4321b19](https://github.com/facebook/react-native/commit/05c4321b194c3d0e146b6085bcaccc75acd3fd67) by [@okwasniewski](https://github.com/okwasniewski))
|
||||
- **Prebuild:** Fix Node scripts related to prebuilt tarball extraction for paths containing whitespaces ([9731e8ebc5](https://github.com/facebook/react-native/commit/9731e8ebc5ea87526a91b9903172639e062cd920) by [@kitten](https://github.com/kitten))
|
||||
- **Prebuild:** Use autolinking-generated react-native-config output in second step of cocoapods linking that generates artifacts and generated source ([f170db412b](https://github.com/facebook/react-native/commit/f170db412b3ab46fd0894d5d66431d9c230cd3a8) by [@kitten](https://github.com/kitten))
|
||||
|
||||
## v0.82.0-rc.0
|
||||
|
||||
### Breaking
|
||||
|
||||
+6
-1
@@ -23,6 +23,7 @@ import com.facebook.react.utils.PropertyUtils.SCOPED_USE_THIRD_PARTY_JSC
|
||||
import com.facebook.react.utils.PropertyUtils.USE_THIRD_PARTY_JSC
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.file.DirectoryProperty
|
||||
import org.jetbrains.kotlin.gradle.plugin.extraProperties
|
||||
|
||||
internal object ProjectUtils {
|
||||
|
||||
@@ -75,7 +76,11 @@ internal object ProjectUtils {
|
||||
(project.hasProperty(HERMES_V1_ENABLED) &&
|
||||
project.property(HERMES_V1_ENABLED).toString().toBoolean()) ||
|
||||
(project.hasProperty(SCOPED_HERMES_V1_ENABLED) &&
|
||||
project.property(SCOPED_HERMES_V1_ENABLED).toString().toBoolean())
|
||||
project.property(SCOPED_HERMES_V1_ENABLED).toString().toBoolean()) ||
|
||||
(project.extraProperties.has(HERMES_V1_ENABLED) &&
|
||||
project.extraProperties.get(HERMES_V1_ENABLED).toString().toBoolean()) ||
|
||||
(project.extraProperties.has(SCOPED_HERMES_V1_ENABLED) &&
|
||||
project.extraProperties.get(SCOPED_HERMES_V1_ENABLED).toString().toBoolean())
|
||||
|
||||
internal fun Project.needsCodegenFromPackageJson(rootProperty: DirectoryProperty): Boolean {
|
||||
val parsedPackageJson = readPackageJsonFile(this, rootProperty)
|
||||
|
||||
+3
-3
@@ -33,9 +33,9 @@ class GeneratePackageListTaskTest {
|
||||
val inputFile = tempFolder.newFile("config.json")
|
||||
|
||||
val task =
|
||||
createTestTask<GeneratePackageListTask> {
|
||||
it.generatedOutputDirectory.set(outputFolder)
|
||||
it.autolinkInputFile.set(inputFile)
|
||||
createTestTask<GeneratePackageListTask> { testTask ->
|
||||
testTask.generatedOutputDirectory.set(outputFolder)
|
||||
testTask.autolinkInputFile.set(inputFile)
|
||||
}
|
||||
|
||||
assertThat(task.inputs.files.singleFile).isEqualTo(inputFile)
|
||||
|
||||
+5
-5
@@ -82,11 +82,11 @@ class PrepareGflagsTaskTest {
|
||||
val gflagsThirdPartyPath = tempFolder.newFolder("gflagspath/jni")
|
||||
val output = tempFolder.newFolder("output")
|
||||
val task =
|
||||
createTestTask<PrepareGflagsTask> {
|
||||
it.gflagsPath.setFrom(gflagspath)
|
||||
it.gflagsThirdPartyPath.set(gflagsThirdPartyPath)
|
||||
it.gflagsVersion.set("1.0.0")
|
||||
it.outputDir.set(output)
|
||||
createTestTask<PrepareGflagsTask> { taskConfig ->
|
||||
taskConfig.gflagsPath.setFrom(gflagspath)
|
||||
taskConfig.gflagsThirdPartyPath.set(gflagsThirdPartyPath)
|
||||
taskConfig.gflagsVersion.set("1.0.0")
|
||||
taskConfig.outputDir.set(output)
|
||||
}
|
||||
File(gflagspath, "gflags-1.0.0/src/gflags_declare.h.in").apply {
|
||||
parentFile.mkdirs()
|
||||
|
||||
@@ -67,7 +67,7 @@ template <typename T>
|
||||
facebook::react::LazyVector<T> RCTBridgingToVec(id value, T (^ctor)(id element))
|
||||
{
|
||||
NSArray *array = RCTBridgingToArray(value);
|
||||
typedef typename facebook::react::LazyVector<T>::size_type _size_t;
|
||||
using _size_t = typename facebook::react::LazyVector<T>::size_type;
|
||||
_size_t size = static_cast<_size_t>(array.count);
|
||||
return facebook::react::LazyVector<T>::fromUnsafeRawValue(array, size, ctor);
|
||||
}
|
||||
|
||||
@@ -316,6 +316,13 @@ let reactIdleCallbacksNativeModule = RNTarget(
|
||||
dependencies: [.reactNativeDependencies, .reactDebug, .reactFeatureFlags, .reactUtils, .reactPerfLogger, .reactCxxReact, .reactTurboModuleCore]
|
||||
)
|
||||
|
||||
/// React-webperformance.podspec
|
||||
let reactWebPerformanceNativeModule = RNTarget(
|
||||
name: .reactWebPerformanceNativeModule,
|
||||
path: "ReactCommon/react/nativemodule/webperformance",
|
||||
dependencies: [.reactNativeDependencies, .reactCxxReact, .reactTurboModuleCore, .reactPerformanceTimeline]
|
||||
)
|
||||
|
||||
/// React-featureflagnativemodule.podspec
|
||||
let reactFeatureflagsNativemodule = RNTarget(
|
||||
name: .reactFeatureflagsNativemodule,
|
||||
@@ -603,6 +610,7 @@ let targets = [
|
||||
reactTurboModuleCoreDefaults,
|
||||
reactTurboModuleCoreMicrotasks,
|
||||
reactIdleCallbacksNativeModule,
|
||||
reactWebPerformanceNativeModule,
|
||||
reactFeatureflagsNativemodule,
|
||||
reactNativeModuleDom,
|
||||
reactAppDelegate,
|
||||
@@ -778,6 +786,7 @@ extension String {
|
||||
static let reactTurboModuleCoreDefaults = "ReactCommon/turbomodule/core/defaults"
|
||||
static let reactTurboModuleCoreMicrotasks = "ReactCommon/turbomodule/core/microtasks"
|
||||
static let reactIdleCallbacksNativeModule = "React-idlecallbacksnativemodule"
|
||||
static let reactWebPerformanceNativeModule = "React-webperformancenativemodule"
|
||||
static let reactFeatureflagsNativemodule = "React-featureflagsnativemodule"
|
||||
static let reactNativeModuleDom = "React-domnativemodule"
|
||||
static let reactAppDelegate = "React-RCTAppDelegate"
|
||||
|
||||
@@ -721,13 +721,13 @@ NSData *__nullable RCTGzipData(NSData *__nullable input, float level)
|
||||
|
||||
void *libz = dlopen("/usr/lib/libz.dylib", RTLD_LAZY);
|
||||
|
||||
typedef int (*DeflateInit2_)(z_streamp, int, int, int, int, int, const char *, int);
|
||||
using DeflateInit2_ = int (*)(z_streamp, int, int, int, int, int, const char *, int);
|
||||
DeflateInit2_ deflateInit2_ = (DeflateInit2_)dlsym(libz, "deflateInit2_");
|
||||
|
||||
typedef int (*Deflate)(z_streamp, int);
|
||||
using Deflate = int (*)(z_streamp, int);
|
||||
Deflate deflate = (Deflate)dlsym(libz, "deflate");
|
||||
|
||||
typedef int (*DeflateEnd)(z_streamp);
|
||||
using DeflateEnd = int (*)(z_streamp);
|
||||
DeflateEnd deflateEnd = (DeflateEnd)dlsym(libz, "deflateEnd");
|
||||
|
||||
z_stream stream;
|
||||
|
||||
+1
-1
@@ -83,6 +83,6 @@ internal class BridgelessDevSupportManager(
|
||||
}
|
||||
|
||||
fun tracingState(): TracingState {
|
||||
return TracingState.DISABLED
|
||||
return TracingState.ENABLEDINCDPMODE
|
||||
}
|
||||
}
|
||||
|
||||
+12
-8
@@ -68,6 +68,7 @@ import com.facebook.react.devsupport.interfaces.StackFrame
|
||||
import com.facebook.react.devsupport.interfaces.TracingState
|
||||
import com.facebook.react.devsupport.interfaces.TracingStateProvider
|
||||
import com.facebook.react.devsupport.perfmonitor.PerfMonitorDevHelper
|
||||
import com.facebook.react.devsupport.perfmonitor.PerfMonitorOverlayManager
|
||||
import com.facebook.react.internal.featureflags.ReactNativeFeatureFlags
|
||||
import com.facebook.react.internal.featureflags.ReactNativeNewArchitectureFeatureFlags
|
||||
import com.facebook.react.modules.core.RCTNativeAppEventEmitter
|
||||
@@ -77,6 +78,7 @@ import java.io.File
|
||||
import java.net.MalformedURLException
|
||||
import java.net.URL
|
||||
import java.util.Locale
|
||||
import javax.inject.Provider
|
||||
|
||||
public abstract class DevSupportManagerBase(
|
||||
protected val applicationContext: Context,
|
||||
@@ -182,7 +184,7 @@ public abstract class DevSupportManagerBase(
|
||||
null
|
||||
}
|
||||
|
||||
private var perfMonitorOverlayManager: PerfMonitorOverlayViewManager? = null
|
||||
private var perfMonitorOverlayManager: PerfMonitorOverlayManager? = null
|
||||
private var tracingStateProvider: TracingStateProvider? = null
|
||||
|
||||
init {
|
||||
@@ -215,19 +217,19 @@ public abstract class DevSupportManagerBase(
|
||||
if (
|
||||
ReactNativeNewArchitectureFeatureFlags.enableBridgelessArchitecture() &&
|
||||
ReactNativeFeatureFlags.perfMonitorV2Enabled() &&
|
||||
reactInstanceDevHelper is PerfMonitorDevHelper &&
|
||||
perfMonitorOverlayManager == null
|
||||
reactInstanceDevHelper is PerfMonitorDevHelper
|
||||
) {
|
||||
perfMonitorOverlayManager =
|
||||
PerfMonitorOverlayViewManager(
|
||||
Supplier {
|
||||
PerfMonitorOverlayManager(
|
||||
reactInstanceDevHelper,
|
||||
Provider {
|
||||
val context = reactInstanceDevHelper.currentActivity
|
||||
if (context == null || context.isFinishing) {
|
||||
return@Supplier null
|
||||
return@Provider null
|
||||
}
|
||||
context
|
||||
},
|
||||
reactInstanceDevHelper.inspectorTarget,
|
||||
{ openDebugger(DebuggerFrontendPanelName.PERFORMANCE.toString()) },
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -548,10 +550,11 @@ public abstract class DevSupportManagerBase(
|
||||
override fun onNewReactContextCreated(reactContext: ReactContext) {
|
||||
resetCurrentContext(reactContext)
|
||||
|
||||
if (perfMonitorOverlayManager != null && reactInstanceDevHelper is PerfMonitorDevHelper) {
|
||||
if (reactInstanceDevHelper is PerfMonitorDevHelper) {
|
||||
perfMonitorOverlayManager?.let { manager ->
|
||||
reactInstanceDevHelper.inspectorTarget?.addPerfMonitorListener(manager)
|
||||
}
|
||||
perfMonitorOverlayManager?.enable()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -882,6 +885,7 @@ public abstract class DevSupportManagerBase(
|
||||
|
||||
override fun onPackagerDisconnected() {
|
||||
isPackagerConnected = false
|
||||
perfMonitorOverlayManager?.disable()
|
||||
}
|
||||
|
||||
override fun onPackagerReloadCommand() {
|
||||
|
||||
-20
@@ -1,20 +0,0 @@
|
||||
/*
|
||||
* 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.devsupport.interfaces
|
||||
|
||||
/** [Experimental] Interface to manage the V2 Perf Monitor overlay. */
|
||||
internal interface PerfMonitorOverlayManager {
|
||||
/** Enable the Perf Monitor overlay. Will be shown when updates are received. */
|
||||
public fun enable()
|
||||
|
||||
/** Disable the Perf Monitor overlay. Will remain hidden when updates are received. */
|
||||
public fun disable()
|
||||
|
||||
/** Reset the Perf Monitor overlay, e.g. after a reload. */
|
||||
public fun reset()
|
||||
}
|
||||
+5
@@ -7,11 +7,16 @@
|
||||
|
||||
package com.facebook.react.devsupport.perfmonitor
|
||||
|
||||
import com.facebook.react.devsupport.interfaces.TracingState
|
||||
|
||||
/**
|
||||
* [Experimental] Interface implemented by [com.facebook.react.runtime.ReactHostInspectorTarget]
|
||||
* exposing actions for the V2 Perf Monitor.
|
||||
*/
|
||||
internal interface PerfMonitorInspectorTargetBinding {
|
||||
/** Get the current CDP or background performance tracing state. */
|
||||
public fun getTracingState(): TracingState
|
||||
|
||||
/** Attempt to pause the current background performance trace, and open in DevTools. */
|
||||
public fun pauseAndAnalyzeBackgroundTrace()
|
||||
|
||||
|
||||
+86
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* 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.devsupport.perfmonitor
|
||||
|
||||
import android.content.Context
|
||||
import com.facebook.react.bridge.UiThreadUtil
|
||||
import com.facebook.react.devsupport.interfaces.TracingState
|
||||
import javax.inject.Provider
|
||||
|
||||
internal class PerfMonitorOverlayManager(
|
||||
private val devHelper: PerfMonitorDevHelper,
|
||||
private val contextProvider: Provider<Context?>,
|
||||
private val onRequestOpenDevTools: () -> Unit,
|
||||
) : PerfMonitorUpdateListener {
|
||||
private var enabled: Boolean = false
|
||||
private var initialized: Boolean = false
|
||||
private var view: PerfMonitorOverlayView? = null
|
||||
private var tracingState: TracingState = TracingState.ENABLEDINCDPMODE
|
||||
|
||||
private fun init() {
|
||||
if (initialized || !enabled) {
|
||||
return
|
||||
}
|
||||
|
||||
UiThreadUtil.runOnUiThread {
|
||||
val context = contextProvider.get() ?: return@runOnUiThread
|
||||
view = PerfMonitorOverlayView(context, ::handleRecordingButtonPress)
|
||||
|
||||
// Start background tracing
|
||||
devHelper.inspectorTarget?.resumeBackgroundTrace()
|
||||
|
||||
view?.show()
|
||||
initialized = true
|
||||
}
|
||||
}
|
||||
|
||||
/** Enable the Perf Monitor overlay. Will be shown when updates are received. */
|
||||
fun enable() {
|
||||
enabled = true
|
||||
init()
|
||||
UiThreadUtil.runOnUiThread { view?.show() }
|
||||
}
|
||||
|
||||
/** Disable the Perf Monitor overlay. Will remain hidden when updates are received. */
|
||||
fun disable() {
|
||||
UiThreadUtil.runOnUiThread { view?.hide() }
|
||||
enabled = false
|
||||
}
|
||||
|
||||
/** Reset the Perf Monitor overlay, e.g. after a reload. */
|
||||
fun reset() {
|
||||
UiThreadUtil.runOnUiThread { view?.resetState() }
|
||||
|
||||
// Update with current recording state
|
||||
onRecordingStateChanged(
|
||||
devHelper.inspectorTarget?.getTracingState() ?: TracingState.ENABLEDINCDPMODE
|
||||
)
|
||||
}
|
||||
|
||||
override fun onNewFocusedEvent(data: PerfMonitorUpdateListener.LongTaskEventData) {
|
||||
view?.updateFocusedEvent(data)
|
||||
}
|
||||
|
||||
override fun onRecordingStateChanged(state: TracingState) {
|
||||
tracingState = state
|
||||
view?.updateRecordingState(state)
|
||||
}
|
||||
|
||||
private fun handleRecordingButtonPress() {
|
||||
when (tracingState) {
|
||||
TracingState.ENABLEDINBACKGROUNDMODE -> {
|
||||
devHelper.inspectorTarget?.pauseAndAnalyzeBackgroundTrace()
|
||||
onRequestOpenDevTools()
|
||||
}
|
||||
TracingState.DISABLED -> {
|
||||
devHelper.inspectorTarget?.resumeBackgroundTrace()
|
||||
}
|
||||
TracingState.ENABLEDINCDPMODE -> Unit
|
||||
}
|
||||
}
|
||||
}
|
||||
+142
-108
@@ -5,7 +5,7 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
package com.facebook.react.devsupport
|
||||
package com.facebook.react.devsupport.perfmonitor
|
||||
|
||||
import android.app.Dialog
|
||||
import android.content.Context
|
||||
@@ -20,107 +20,110 @@ import android.view.Window
|
||||
import android.view.WindowManager
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import androidx.core.util.Supplier
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
import com.facebook.react.R
|
||||
import com.facebook.react.bridge.UiThreadUtil
|
||||
import com.facebook.react.devsupport.interfaces.PerfMonitorOverlayManager
|
||||
import com.facebook.react.devsupport.interfaces.TracingState
|
||||
import com.facebook.react.devsupport.perfmonitor.PerfMonitorInspectorTargetBinding
|
||||
import com.facebook.react.devsupport.perfmonitor.PerfMonitorUpdateListener
|
||||
import com.facebook.react.uimanager.DisplayMetricsHolder
|
||||
import com.facebook.react.uimanager.PixelUtil
|
||||
import java.util.Locale
|
||||
|
||||
internal class PerfMonitorOverlayViewManager(
|
||||
private val contextSupplier: Supplier<Context?>,
|
||||
private val inspectorTarget: PerfMonitorInspectorTargetBinding?,
|
||||
) : PerfMonitorOverlayManager, PerfMonitorUpdateListener {
|
||||
private var initialized: Boolean = false
|
||||
private var enabled: Boolean = false
|
||||
private var hasInteractionData: Boolean = false
|
||||
private var interactionDialog: Dialog? = null
|
||||
private var buttonDialog: Dialog? = null
|
||||
private var durationLabel: TextView? = null
|
||||
internal class PerfMonitorOverlayView(
|
||||
private val context: Context,
|
||||
private val onButtonPress: () -> Unit,
|
||||
) {
|
||||
private var hidden: Boolean = true
|
||||
private var hasEventData: Boolean = false
|
||||
private val metricsDialog: Dialog
|
||||
private val toolbarDialog: Dialog
|
||||
private val tooltipDialog: Dialog
|
||||
private lateinit var buttonLabel: TextView
|
||||
private lateinit var recordingStateLabel: TextView
|
||||
private lateinit var durationLabel: TextView
|
||||
private lateinit var tooltipLabel: TextView
|
||||
private var ttl: Int = 0
|
||||
private var hideAfterTimeoutHandler: Handler? = null
|
||||
|
||||
override fun enable() {
|
||||
UiThreadUtil.runOnUiThread {
|
||||
enabled = true
|
||||
if (hasInteractionData) {
|
||||
showOverlay()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun disable() {
|
||||
UiThreadUtil.runOnUiThread {
|
||||
enabled = false
|
||||
hideOverlay()
|
||||
}
|
||||
}
|
||||
|
||||
override fun reset() {
|
||||
UiThreadUtil.runOnUiThread {
|
||||
hasInteractionData = false
|
||||
hideOverlay()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onRecordingStateChanged(state: TracingState) {
|
||||
// recordingState = state
|
||||
// view?.updateRecordingState(state)
|
||||
}
|
||||
|
||||
override fun onNewFocusedEvent(data: PerfMonitorUpdateListener.LongTaskEventData) {
|
||||
UiThreadUtil.runOnUiThread {
|
||||
ensureInitialized()
|
||||
durationLabel?.text = String.format(Locale.US, "%d ms", data.durationMs)
|
||||
durationLabel?.setTextColor(getDurationHighlightColor(data.responsivenessScore))
|
||||
hasInteractionData = true
|
||||
ttl = data.ttl
|
||||
|
||||
hideAfterTimeoutHandler?.removeCallbacksAndMessages(null)
|
||||
|
||||
if (enabled) {
|
||||
showOverlay()
|
||||
|
||||
// Schedule hiding overlay after ttl milliseconds
|
||||
if (ttl > 0) {
|
||||
if (hideAfterTimeoutHandler == null) {
|
||||
hideAfterTimeoutHandler = Handler(Looper.getMainLooper())
|
||||
}
|
||||
hideAfterTimeoutHandler?.postDelayed({ hideOverlay() }, ttl.toLong())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun ensureInitialized() {
|
||||
if (initialized) {
|
||||
return
|
||||
}
|
||||
val context = contextSupplier.get() ?: return
|
||||
init {
|
||||
DisplayMetricsHolder.initDisplayMetricsIfNotInitialized(context)
|
||||
createDialog(context)
|
||||
createButton(context)
|
||||
initialized = true
|
||||
tooltipDialog = createTooltipDialog()
|
||||
metricsDialog = createMetricsDialog()
|
||||
toolbarDialog = createToolbarDialog()
|
||||
}
|
||||
|
||||
private fun showOverlay() {
|
||||
interactionDialog?.show()
|
||||
buttonDialog?.show()
|
||||
fun show() {
|
||||
toolbarDialog.show()
|
||||
tooltipDialog.show()
|
||||
if (hasEventData) {
|
||||
toolbarDialog.window?.decorView?.post { updateMetricsDialogPosition() }
|
||||
metricsDialog.show()
|
||||
}
|
||||
hidden = false
|
||||
}
|
||||
|
||||
private fun hideOverlay() {
|
||||
interactionDialog?.hide()
|
||||
buttonDialog?.hide()
|
||||
fun hide() {
|
||||
metricsDialog.hide()
|
||||
toolbarDialog.hide()
|
||||
tooltipDialog.hide()
|
||||
hidden = true
|
||||
}
|
||||
|
||||
private fun createDialog(context: Context) {
|
||||
val containerLayout = createInnerLayout(context)
|
||||
fun resetState() {
|
||||
hasEventData = false
|
||||
metricsDialog.hide()
|
||||
}
|
||||
|
||||
fun updateFocusedEvent(data: PerfMonitorUpdateListener.LongTaskEventData) {
|
||||
durationLabel.text = String.format(Locale.US, "%d ms", data.durationMs)
|
||||
durationLabel.setTextColor(getDurationHighlightColor(data.responsivenessScore))
|
||||
hasEventData = true
|
||||
ttl = data.ttl
|
||||
|
||||
hideAfterTimeoutHandler?.removeCallbacksAndMessages(null)
|
||||
|
||||
if (!hidden) {
|
||||
metricsDialog.show()
|
||||
|
||||
// Schedule hiding metrics overlay after ttl milliseconds
|
||||
if (ttl > 0) {
|
||||
if (hideAfterTimeoutHandler == null) {
|
||||
hideAfterTimeoutHandler = Handler(Looper.getMainLooper())
|
||||
}
|
||||
hideAfterTimeoutHandler?.postDelayed({ metricsDialog.hide() }, ttl.toLong())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun updateRecordingState(state: TracingState) {
|
||||
recordingStateLabel.text =
|
||||
when (state) {
|
||||
TracingState.ENABLEDINBACKGROUNDMODE -> "Profiling: ON"
|
||||
TracingState.DISABLED -> "Profiling: OFF"
|
||||
TracingState.ENABLEDINCDPMODE -> "Profiling: DISABLED"
|
||||
}
|
||||
buttonLabel.text =
|
||||
when (state) {
|
||||
TracingState.ENABLEDINBACKGROUNDMODE -> "Open ↗️"
|
||||
TracingState.DISABLED -> "Start"
|
||||
TracingState.ENABLEDINCDPMODE -> ""
|
||||
}
|
||||
tooltipLabel.text =
|
||||
when (state) {
|
||||
TracingState.ENABLEDINBACKGROUNDMODE -> "Dev Menu > Finish performance trace"
|
||||
TracingState.DISABLED -> "Dev Menu > Start performance trace"
|
||||
TracingState.ENABLEDINCDPMODE -> ""
|
||||
}
|
||||
if (state == TracingState.ENABLEDINCDPMODE) {
|
||||
tooltipDialog.hide()
|
||||
} else {
|
||||
tooltipDialog.show()
|
||||
}
|
||||
|
||||
toolbarDialog.window?.decorView?.post { updateMetricsDialogPosition() }
|
||||
}
|
||||
|
||||
private fun createMetricsDialog(): Dialog {
|
||||
val containerLayout = createInnerLayout()
|
||||
val longTaskLabel =
|
||||
TextView(context).apply {
|
||||
textSize = TEXT_SIZE_PRIMARY
|
||||
@@ -138,7 +141,7 @@ internal class PerfMonitorOverlayViewManager(
|
||||
containerLayout.addView(durationLabel)
|
||||
|
||||
val dialog =
|
||||
createAnchoredDialog(context, dpToPx(140f), dpToPx(16f)).apply {
|
||||
createAnchoredDialog(getMetricsDialogOffsetX(), dpToPx(16f)).apply {
|
||||
setContentView(containerLayout)
|
||||
}
|
||||
dialog.window?.apply {
|
||||
@@ -151,30 +154,25 @@ internal class PerfMonitorOverlayViewManager(
|
||||
}
|
||||
}
|
||||
|
||||
this.interactionDialog = dialog
|
||||
return dialog
|
||||
}
|
||||
|
||||
fun updateRecordingState(state: TracingState) {}
|
||||
|
||||
private fun createButton(context: Context) {
|
||||
val buttonInner = createInnerLayout(context)
|
||||
buttonInner.addView(
|
||||
private fun createToolbarDialog(): Dialog {
|
||||
val buttonInner = createInnerLayout()
|
||||
recordingStateLabel =
|
||||
TextView(context).apply {
|
||||
text = "Analyze"
|
||||
textSize = TEXT_SIZE_PRIMARY
|
||||
setTextColor(Color.WHITE)
|
||||
typeface = TYPEFACE_BOLD
|
||||
}
|
||||
)
|
||||
buttonInner.addView(
|
||||
buttonInner.addView(recordingStateLabel)
|
||||
buttonLabel =
|
||||
TextView(context).apply {
|
||||
text = "cmd + A"
|
||||
textSize = TEXT_SIZE_ACCESSORY
|
||||
setTextColor(Color.WHITE)
|
||||
alpha = 0.7f
|
||||
textSize = TEXT_SIZE_PRIMARY
|
||||
setTextColor(COLOR_TEXT_BLUE)
|
||||
typeface = TYPEFACE_BOLD
|
||||
}
|
||||
)
|
||||
buttonInner.addView(buttonLabel)
|
||||
val buttonView =
|
||||
LinearLayout(context).apply {
|
||||
orientation = LinearLayout.VERTICAL
|
||||
@@ -185,19 +183,43 @@ internal class PerfMonitorOverlayViewManager(
|
||||
dpToPx(8f).toInt(),
|
||||
)
|
||||
addView(buttonInner)
|
||||
setOnClickListener { inspectorTarget?.pauseAndAnalyzeBackgroundTrace() }
|
||||
setOnClickListener { onButtonPress() }
|
||||
}
|
||||
val dialog =
|
||||
createAnchoredDialog(context, dpToPx(0f), dpToPx(0f)).apply { setContentView(buttonView) }
|
||||
|
||||
val dialog = createAnchoredDialog(dpToPx(0f), dpToPx(0f)).apply { setContentView(buttonView) }
|
||||
dialog.window?.apply {
|
||||
attributes =
|
||||
attributes?.apply { flags = flags or WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE }
|
||||
}
|
||||
|
||||
this.buttonDialog = dialog
|
||||
return dialog
|
||||
}
|
||||
|
||||
private fun createAnchoredDialog(context: Context, offsetX: Float, offsetY: Float): Dialog {
|
||||
private fun createTooltipDialog(): Dialog {
|
||||
val containerLayout = createInnerLayout()
|
||||
tooltipLabel =
|
||||
TextView(context).apply {
|
||||
textSize = TEXT_SIZE_ACCESSORY
|
||||
setTextColor(Color.WHITE)
|
||||
}
|
||||
containerLayout.addView(tooltipLabel)
|
||||
|
||||
val dialog =
|
||||
createAnchoredDialog(dpToPx(16f), dpToPx(52f)).apply { setContentView(containerLayout) }
|
||||
dialog.window?.apply {
|
||||
attributes =
|
||||
attributes?.apply {
|
||||
flags =
|
||||
flags or
|
||||
WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE or
|
||||
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
|
||||
}
|
||||
}
|
||||
|
||||
return dialog
|
||||
}
|
||||
|
||||
private fun createAnchoredDialog(offsetX: Float, offsetY: Float): Dialog {
|
||||
val dialog =
|
||||
Dialog(context, R.style.NoAnimationDialog).apply {
|
||||
requestWindowFeature(Window.FEATURE_NO_TITLE)
|
||||
@@ -228,12 +250,12 @@ internal class PerfMonitorOverlayViewManager(
|
||||
return dialog
|
||||
}
|
||||
|
||||
private fun createInnerLayout(context: Context): LinearLayout {
|
||||
private fun createInnerLayout(): LinearLayout {
|
||||
return LinearLayout(context).apply {
|
||||
orientation = LinearLayout.HORIZONTAL
|
||||
gravity = Gravity.CENTER_VERTICAL
|
||||
val paddingHorizontal = dpToPx(14f).toInt()
|
||||
val paddingVertical = dpToPx(8f).toInt()
|
||||
val paddingVertical = dpToPx(7f).toInt()
|
||||
setPadding(paddingHorizontal, paddingVertical, paddingHorizontal, paddingVertical)
|
||||
layoutParams =
|
||||
LinearLayout.LayoutParams(
|
||||
@@ -256,10 +278,21 @@ internal class PerfMonitorOverlayViewManager(
|
||||
}
|
||||
}
|
||||
|
||||
private fun getMetricsDialogOffsetX(): Float {
|
||||
val toolbarWidth = toolbarDialog?.window?.decorView?.width ?: 0
|
||||
return toolbarWidth.toFloat()
|
||||
}
|
||||
|
||||
private fun updateMetricsDialogPosition() {
|
||||
metricsDialog?.window?.apply {
|
||||
attributes = attributes?.apply { x = getMetricsDialogOffsetX().toInt() }
|
||||
}
|
||||
}
|
||||
|
||||
private fun getDurationHighlightColor(responsivenessScore: Int): Int {
|
||||
return when (responsivenessScore) {
|
||||
3 -> COLOR_TEXT_RED
|
||||
2 -> COLOR_TEXT_YELLOW
|
||||
2 -> COLOR_TEXT_RED
|
||||
1 -> COLOR_TEXT_YELLOW
|
||||
else -> COLOR_TEXT_GREEN
|
||||
}
|
||||
}
|
||||
@@ -270,6 +303,7 @@ internal class PerfMonitorOverlayViewManager(
|
||||
private val COLOR_TEXT_GREEN = Color.parseColor("#4AEB2F")
|
||||
private val COLOR_TEXT_YELLOW = Color.parseColor("#FFAA00")
|
||||
private val COLOR_TEXT_RED = Color.parseColor("#FF0000")
|
||||
private val COLOR_TEXT_BLUE = Color.parseColor("#00B0FF")
|
||||
private val COLOR_OVERLAY_BORDER = Color.parseColor("#6C6C6C")
|
||||
private val TEXT_SIZE_PRIMARY = 13f
|
||||
private val TEXT_SIZE_ACCESSORY = 9f
|
||||
+7
-1
@@ -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<<c217318f9f313103ca31d8e7698851d8>>
|
||||
* @generated SignedSource<<8300eb10fb4906468cd5f04afd8e16cd>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -300,6 +300,12 @@ public object ReactNativeFeatureFlags {
|
||||
@JvmStatic
|
||||
public fun enableVirtualViewWindowFocusDetection(): Boolean = accessor.enableVirtualViewWindowFocusDetection()
|
||||
|
||||
/**
|
||||
* Enable Web Performance APIs (Performance Timeline, User Timings, etc.) by default.
|
||||
*/
|
||||
@JvmStatic
|
||||
public fun enableWebPerformanceAPIsByDefault(): Boolean = accessor.enableWebPerformanceAPIsByDefault()
|
||||
|
||||
/**
|
||||
* Uses the default event priority instead of the discreet event priority by default when dispatching events from Fabric to React.
|
||||
*/
|
||||
|
||||
+11
-1
@@ -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<<4ed350d8dfa42caf27d346dfcfbed974>>
|
||||
* @generated SignedSource<<ea5133af611c4d1e7e70155a3a74492d>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -65,6 +65,7 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
|
||||
private var enableVirtualViewDebugFeaturesCache: Boolean? = null
|
||||
private var enableVirtualViewRenderStateCache: Boolean? = null
|
||||
private var enableVirtualViewWindowFocusDetectionCache: Boolean? = null
|
||||
private var enableWebPerformanceAPIsByDefaultCache: Boolean? = null
|
||||
private var fixMappingOfEventPrioritiesBetweenFabricAndReactCache: Boolean? = null
|
||||
private var fuseboxEnabledReleaseCache: Boolean? = null
|
||||
private var fuseboxNetworkInspectionEnabledCache: Boolean? = null
|
||||
@@ -496,6 +497,15 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
|
||||
return cached
|
||||
}
|
||||
|
||||
override fun enableWebPerformanceAPIsByDefault(): Boolean {
|
||||
var cached = enableWebPerformanceAPIsByDefaultCache
|
||||
if (cached == null) {
|
||||
cached = ReactNativeFeatureFlagsCxxInterop.enableWebPerformanceAPIsByDefault()
|
||||
enableWebPerformanceAPIsByDefaultCache = cached
|
||||
}
|
||||
return cached
|
||||
}
|
||||
|
||||
override fun fixMappingOfEventPrioritiesBetweenFabricAndReact(): Boolean {
|
||||
var cached = fixMappingOfEventPrioritiesBetweenFabricAndReactCache
|
||||
if (cached == null) {
|
||||
|
||||
+3
-1
@@ -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<<6c201de02071a834e411b6761d7f863b>>
|
||||
* @generated SignedSource<<cf5b9f099846d4f954304905f77ebe17>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -118,6 +118,8 @@ public object ReactNativeFeatureFlagsCxxInterop {
|
||||
|
||||
@DoNotStrip @JvmStatic public external fun enableVirtualViewWindowFocusDetection(): Boolean
|
||||
|
||||
@DoNotStrip @JvmStatic public external fun enableWebPerformanceAPIsByDefault(): Boolean
|
||||
|
||||
@DoNotStrip @JvmStatic public external fun fixMappingOfEventPrioritiesBetweenFabricAndReact(): Boolean
|
||||
|
||||
@DoNotStrip @JvmStatic public external fun fuseboxEnabledRelease(): Boolean
|
||||
|
||||
+3
-1
@@ -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<<7c4c3bf6b720f3e15fb97d8f1a4d74ba>>
|
||||
* @generated SignedSource<<305496047314dc97352a6e0dad0bba54>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -113,6 +113,8 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi
|
||||
|
||||
override fun enableVirtualViewWindowFocusDetection(): Boolean = false
|
||||
|
||||
override fun enableWebPerformanceAPIsByDefault(): Boolean = false
|
||||
|
||||
override fun fixMappingOfEventPrioritiesBetweenFabricAndReact(): Boolean = false
|
||||
|
||||
override fun fuseboxEnabledRelease(): Boolean = false
|
||||
|
||||
+12
-1
@@ -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<<57fca2370d6b3f1edf7045a0b4c94350>>
|
||||
* @generated SignedSource<<f3798eada96337cf98715fa580823b30>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -69,6 +69,7 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
|
||||
private var enableVirtualViewDebugFeaturesCache: Boolean? = null
|
||||
private var enableVirtualViewRenderStateCache: Boolean? = null
|
||||
private var enableVirtualViewWindowFocusDetectionCache: Boolean? = null
|
||||
private var enableWebPerformanceAPIsByDefaultCache: Boolean? = null
|
||||
private var fixMappingOfEventPrioritiesBetweenFabricAndReactCache: Boolean? = null
|
||||
private var fuseboxEnabledReleaseCache: Boolean? = null
|
||||
private var fuseboxNetworkInspectionEnabledCache: Boolean? = null
|
||||
@@ -545,6 +546,16 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
|
||||
return cached
|
||||
}
|
||||
|
||||
override fun enableWebPerformanceAPIsByDefault(): Boolean {
|
||||
var cached = enableWebPerformanceAPIsByDefaultCache
|
||||
if (cached == null) {
|
||||
cached = currentProvider.enableWebPerformanceAPIsByDefault()
|
||||
accessedFeatureFlags.add("enableWebPerformanceAPIsByDefault")
|
||||
enableWebPerformanceAPIsByDefaultCache = cached
|
||||
}
|
||||
return cached
|
||||
}
|
||||
|
||||
override fun fixMappingOfEventPrioritiesBetweenFabricAndReact(): Boolean {
|
||||
var cached = fixMappingOfEventPrioritiesBetweenFabricAndReactCache
|
||||
if (cached == null) {
|
||||
|
||||
+3
-1
@@ -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<<ef31518f0fe8ff6f6a5c15936cab9d87>>
|
||||
* @generated SignedSource<<c36e7ac588eb68660f000e7792ec2384>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -113,6 +113,8 @@ public interface ReactNativeFeatureFlagsProvider {
|
||||
|
||||
@DoNotStrip public fun enableVirtualViewWindowFocusDetection(): Boolean
|
||||
|
||||
@DoNotStrip public fun enableWebPerformanceAPIsByDefault(): Boolean
|
||||
|
||||
@DoNotStrip public fun fixMappingOfEventPrioritiesBetweenFabricAndReact(): Boolean
|
||||
|
||||
@DoNotStrip public fun fuseboxEnabledRelease(): Boolean
|
||||
|
||||
+2
-2
@@ -310,8 +310,8 @@ public open class JavaTimerManager(
|
||||
}
|
||||
}
|
||||
}
|
||||
timersToCall?.let {
|
||||
javaScriptTimerExecutor.callTimers(it)
|
||||
timersToCall?.let { timers ->
|
||||
javaScriptTimerExecutor.callTimers(timers)
|
||||
timersToCall = null
|
||||
}
|
||||
reactChoreographer.postFrameCallback(ReactChoreographer.CallbackType.TIMERS_EVENTS, this)
|
||||
|
||||
+1
-1
@@ -81,6 +81,6 @@ internal class ReactHostImplDevHelper(private val delegate: ReactHostImpl) :
|
||||
delegate.loadBundle(bundleLoader)
|
||||
|
||||
override fun getTracingState(): TracingState {
|
||||
return delegate.reactHostInspectorTarget?.tracingState() ?: TracingState.DISABLED
|
||||
return delegate.reactHostInspectorTarget?.getTracingState() ?: TracingState.ENABLEDINCDPMODE
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -43,7 +43,7 @@ internal class ReactHostInspectorTarget(reactHostImpl: ReactHostImpl) :
|
||||
|
||||
external fun tracingStateAsInt(): Int
|
||||
|
||||
fun tracingState(): TracingState {
|
||||
override fun getTracingState(): TracingState {
|
||||
return TracingState.entries[tracingStateAsInt()]
|
||||
}
|
||||
|
||||
|
||||
@@ -124,6 +124,7 @@ add_react_common_subdir(react/nativemodule/dom)
|
||||
add_react_common_subdir(react/nativemodule/featureflags)
|
||||
add_react_common_subdir(react/nativemodule/microtasks)
|
||||
add_react_common_subdir(react/nativemodule/idlecallbacks)
|
||||
add_react_common_subdir(react/nativemodule/webperformance)
|
||||
add_react_common_subdir(react/networking)
|
||||
add_react_common_subdir(jserrorhandler)
|
||||
add_react_common_subdir(react/runtime)
|
||||
@@ -191,6 +192,7 @@ add_library(reactnative
|
||||
$<TARGET_OBJECTS:react_nativemodule_featureflags>
|
||||
$<TARGET_OBJECTS:react_nativemodule_idlecallbacks>
|
||||
$<TARGET_OBJECTS:react_nativemodule_microtasks>
|
||||
$<TARGET_OBJECTS:react_nativemodule_webperformance>
|
||||
$<TARGET_OBJECTS:react_networking>
|
||||
$<TARGET_OBJECTS:react_newarchdefaults>
|
||||
$<TARGET_OBJECTS:react_performance_cdpmetrics>
|
||||
@@ -281,6 +283,7 @@ target_include_directories(reactnative
|
||||
$<TARGET_PROPERTY:react_nativemodule_featureflags,INTERFACE_INCLUDE_DIRECTORIES>
|
||||
$<TARGET_PROPERTY:react_nativemodule_idlecallbacks,INTERFACE_INCLUDE_DIRECTORIES>
|
||||
$<TARGET_PROPERTY:react_nativemodule_microtasks,INTERFACE_INCLUDE_DIRECTORIES>
|
||||
$<TARGET_PROPERTY:react_nativemodule_webperformance,INTERFACE_INCLUDE_DIRECTORIES>
|
||||
$<TARGET_PROPERTY:react_networking,INTERFACE_INCLUDE_DIRECTORIES>
|
||||
$<TARGET_PROPERTY:react_newarchdefaults,INTERFACE_INCLUDE_DIRECTORIES>
|
||||
$<TARGET_PROPERTY:react_performance_cdpmetrics,INTERFACE_INCLUDE_DIRECTORIES>
|
||||
|
||||
+15
-1
@@ -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<<846db2d7c3c6020dec04789fe2784f8a>>
|
||||
* @generated SignedSource<<be39ff0cb3b7c5881510b1528c17465a>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -309,6 +309,12 @@ class ReactNativeFeatureFlagsJavaProvider
|
||||
return method(javaProvider_);
|
||||
}
|
||||
|
||||
bool enableWebPerformanceAPIsByDefault() override {
|
||||
static const auto method =
|
||||
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("enableWebPerformanceAPIsByDefault");
|
||||
return method(javaProvider_);
|
||||
}
|
||||
|
||||
bool fixMappingOfEventPrioritiesBetweenFabricAndReact() override {
|
||||
static const auto method =
|
||||
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("fixMappingOfEventPrioritiesBetweenFabricAndReact");
|
||||
@@ -688,6 +694,11 @@ bool JReactNativeFeatureFlagsCxxInterop::enableVirtualViewWindowFocusDetection(
|
||||
return ReactNativeFeatureFlags::enableVirtualViewWindowFocusDetection();
|
||||
}
|
||||
|
||||
bool JReactNativeFeatureFlagsCxxInterop::enableWebPerformanceAPIsByDefault(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
|
||||
return ReactNativeFeatureFlags::enableWebPerformanceAPIsByDefault();
|
||||
}
|
||||
|
||||
bool JReactNativeFeatureFlagsCxxInterop::fixMappingOfEventPrioritiesBetweenFabricAndReact(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
|
||||
return ReactNativeFeatureFlags::fixMappingOfEventPrioritiesBetweenFabricAndReact();
|
||||
@@ -979,6 +990,9 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() {
|
||||
makeNativeMethod(
|
||||
"enableVirtualViewWindowFocusDetection",
|
||||
JReactNativeFeatureFlagsCxxInterop::enableVirtualViewWindowFocusDetection),
|
||||
makeNativeMethod(
|
||||
"enableWebPerformanceAPIsByDefault",
|
||||
JReactNativeFeatureFlagsCxxInterop::enableWebPerformanceAPIsByDefault),
|
||||
makeNativeMethod(
|
||||
"fixMappingOfEventPrioritiesBetweenFabricAndReact",
|
||||
JReactNativeFeatureFlagsCxxInterop::fixMappingOfEventPrioritiesBetweenFabricAndReact),
|
||||
|
||||
+4
-1
@@ -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<<e4d45c3e12ab378a5b99d14f7f0ed4fd>>
|
||||
* @generated SignedSource<<8cd0afd7badb6739b4e8f9b0e630677c>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -165,6 +165,9 @@ class JReactNativeFeatureFlagsCxxInterop
|
||||
static bool enableVirtualViewWindowFocusDetection(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
|
||||
|
||||
static bool enableWebPerformanceAPIsByDefault(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
|
||||
|
||||
static bool fixMappingOfEventPrioritiesBetweenFabricAndReact(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
|
||||
|
||||
|
||||
@@ -50,7 +50,8 @@ void PerfMonitorUpdateHandler::handlePerfMetricsUpdate(
|
||||
}
|
||||
|
||||
auto responsivenessScore = getInteractionScore(duration);
|
||||
auto ttl = responsivenessScore == InteractionResponsivenessScore::Poor
|
||||
auto ttl =
|
||||
responsivenessScore == InteractionResponsivenessScore::NeedsImprovement
|
||||
? BAD_EVENT_TTL
|
||||
: DEFAULT_TTL;
|
||||
|
||||
|
||||
@@ -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<<fd6af2db2dd4735d70d888bc9fd9487d>>
|
||||
* @generated SignedSource<<a4fb74cf8a68181f509794e387bf666d>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -206,6 +206,10 @@ bool ReactNativeFeatureFlags::enableVirtualViewWindowFocusDetection() {
|
||||
return getAccessor().enableVirtualViewWindowFocusDetection();
|
||||
}
|
||||
|
||||
bool ReactNativeFeatureFlags::enableWebPerformanceAPIsByDefault() {
|
||||
return getAccessor().enableWebPerformanceAPIsByDefault();
|
||||
}
|
||||
|
||||
bool ReactNativeFeatureFlags::fixMappingOfEventPrioritiesBetweenFabricAndReact() {
|
||||
return getAccessor().fixMappingOfEventPrioritiesBetweenFabricAndReact();
|
||||
}
|
||||
|
||||
@@ -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<<8979be03db13b9f45d313018192c0c35>>
|
||||
* @generated SignedSource<<a4a98649c527be3c936c859ddc59cb33>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -264,6 +264,11 @@ class ReactNativeFeatureFlags {
|
||||
*/
|
||||
RN_EXPORT static bool enableVirtualViewWindowFocusDetection();
|
||||
|
||||
/**
|
||||
* Enable Web Performance APIs (Performance Timeline, User Timings, etc.) by default.
|
||||
*/
|
||||
RN_EXPORT static bool enableWebPerformanceAPIsByDefault();
|
||||
|
||||
/**
|
||||
* Uses the default event priority instead of the discreet event priority by default when dispatching events from Fabric to React.
|
||||
*/
|
||||
|
||||
+44
-26
@@ -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<<b0477d29ce6ef9b30118341e2980a93a>>
|
||||
* @generated SignedSource<<91188495ce43a1e1c820cdc3d6302bda>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -839,6 +839,24 @@ bool ReactNativeFeatureFlagsAccessor::enableVirtualViewWindowFocusDetection() {
|
||||
return flagValue.value();
|
||||
}
|
||||
|
||||
bool ReactNativeFeatureFlagsAccessor::enableWebPerformanceAPIsByDefault() {
|
||||
auto flagValue = enableWebPerformanceAPIsByDefault_.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(45, "enableWebPerformanceAPIsByDefault");
|
||||
|
||||
flagValue = currentProvider_->enableWebPerformanceAPIsByDefault();
|
||||
enableWebPerformanceAPIsByDefault_ = flagValue;
|
||||
}
|
||||
|
||||
return flagValue.value();
|
||||
}
|
||||
|
||||
bool ReactNativeFeatureFlagsAccessor::fixMappingOfEventPrioritiesBetweenFabricAndReact() {
|
||||
auto flagValue = fixMappingOfEventPrioritiesBetweenFabricAndReact_.load();
|
||||
|
||||
@@ -848,7 +866,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(45, "fixMappingOfEventPrioritiesBetweenFabricAndReact");
|
||||
markFlagAsAccessed(46, "fixMappingOfEventPrioritiesBetweenFabricAndReact");
|
||||
|
||||
flagValue = currentProvider_->fixMappingOfEventPrioritiesBetweenFabricAndReact();
|
||||
fixMappingOfEventPrioritiesBetweenFabricAndReact_ = flagValue;
|
||||
@@ -866,7 +884,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(46, "fuseboxEnabledRelease");
|
||||
markFlagAsAccessed(47, "fuseboxEnabledRelease");
|
||||
|
||||
flagValue = currentProvider_->fuseboxEnabledRelease();
|
||||
fuseboxEnabledRelease_ = flagValue;
|
||||
@@ -884,7 +902,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(47, "fuseboxNetworkInspectionEnabled");
|
||||
markFlagAsAccessed(48, "fuseboxNetworkInspectionEnabled");
|
||||
|
||||
flagValue = currentProvider_->fuseboxNetworkInspectionEnabled();
|
||||
fuseboxNetworkInspectionEnabled_ = flagValue;
|
||||
@@ -902,7 +920,7 @@ bool ReactNativeFeatureFlagsAccessor::hideOffscreenVirtualViewsOnIOS() {
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(48, "hideOffscreenVirtualViewsOnIOS");
|
||||
markFlagAsAccessed(49, "hideOffscreenVirtualViewsOnIOS");
|
||||
|
||||
flagValue = currentProvider_->hideOffscreenVirtualViewsOnIOS();
|
||||
hideOffscreenVirtualViewsOnIOS_ = flagValue;
|
||||
@@ -920,7 +938,7 @@ bool ReactNativeFeatureFlagsAccessor::overrideBySynchronousMountPropsAtMountingA
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(49, "overrideBySynchronousMountPropsAtMountingAndroid");
|
||||
markFlagAsAccessed(50, "overrideBySynchronousMountPropsAtMountingAndroid");
|
||||
|
||||
flagValue = currentProvider_->overrideBySynchronousMountPropsAtMountingAndroid();
|
||||
overrideBySynchronousMountPropsAtMountingAndroid_ = flagValue;
|
||||
@@ -938,7 +956,7 @@ bool ReactNativeFeatureFlagsAccessor::perfMonitorV2Enabled() {
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(50, "perfMonitorV2Enabled");
|
||||
markFlagAsAccessed(51, "perfMonitorV2Enabled");
|
||||
|
||||
flagValue = currentProvider_->perfMonitorV2Enabled();
|
||||
perfMonitorV2Enabled_ = flagValue;
|
||||
@@ -956,7 +974,7 @@ double ReactNativeFeatureFlagsAccessor::preparedTextCacheSize() {
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(51, "preparedTextCacheSize");
|
||||
markFlagAsAccessed(52, "preparedTextCacheSize");
|
||||
|
||||
flagValue = currentProvider_->preparedTextCacheSize();
|
||||
preparedTextCacheSize_ = flagValue;
|
||||
@@ -974,7 +992,7 @@ bool ReactNativeFeatureFlagsAccessor::preventShadowTreeCommitExhaustion() {
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(52, "preventShadowTreeCommitExhaustion");
|
||||
markFlagAsAccessed(53, "preventShadowTreeCommitExhaustion");
|
||||
|
||||
flagValue = currentProvider_->preventShadowTreeCommitExhaustion();
|
||||
preventShadowTreeCommitExhaustion_ = flagValue;
|
||||
@@ -992,7 +1010,7 @@ bool ReactNativeFeatureFlagsAccessor::shouldPressibilityUseW3CPointerEventsForHo
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(53, "shouldPressibilityUseW3CPointerEventsForHover");
|
||||
markFlagAsAccessed(54, "shouldPressibilityUseW3CPointerEventsForHover");
|
||||
|
||||
flagValue = currentProvider_->shouldPressibilityUseW3CPointerEventsForHover();
|
||||
shouldPressibilityUseW3CPointerEventsForHover_ = flagValue;
|
||||
@@ -1010,7 +1028,7 @@ bool ReactNativeFeatureFlagsAccessor::skipActivityIdentityAssertionOnHostPause()
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(54, "skipActivityIdentityAssertionOnHostPause");
|
||||
markFlagAsAccessed(55, "skipActivityIdentityAssertionOnHostPause");
|
||||
|
||||
flagValue = currentProvider_->skipActivityIdentityAssertionOnHostPause();
|
||||
skipActivityIdentityAssertionOnHostPause_ = flagValue;
|
||||
@@ -1028,7 +1046,7 @@ bool ReactNativeFeatureFlagsAccessor::sweepActiveTouchOnChildNativeGesturesAndro
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(55, "sweepActiveTouchOnChildNativeGesturesAndroid");
|
||||
markFlagAsAccessed(56, "sweepActiveTouchOnChildNativeGesturesAndroid");
|
||||
|
||||
flagValue = currentProvider_->sweepActiveTouchOnChildNativeGesturesAndroid();
|
||||
sweepActiveTouchOnChildNativeGesturesAndroid_ = flagValue;
|
||||
@@ -1046,7 +1064,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(56, "traceTurboModulePromiseRejectionsOnAndroid");
|
||||
markFlagAsAccessed(57, "traceTurboModulePromiseRejectionsOnAndroid");
|
||||
|
||||
flagValue = currentProvider_->traceTurboModulePromiseRejectionsOnAndroid();
|
||||
traceTurboModulePromiseRejectionsOnAndroid_ = flagValue;
|
||||
@@ -1064,7 +1082,7 @@ bool ReactNativeFeatureFlagsAccessor::updateRuntimeShadowNodeReferencesOnCommit(
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(57, "updateRuntimeShadowNodeReferencesOnCommit");
|
||||
markFlagAsAccessed(58, "updateRuntimeShadowNodeReferencesOnCommit");
|
||||
|
||||
flagValue = currentProvider_->updateRuntimeShadowNodeReferencesOnCommit();
|
||||
updateRuntimeShadowNodeReferencesOnCommit_ = flagValue;
|
||||
@@ -1082,7 +1100,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(58, "useAlwaysAvailableJSErrorHandling");
|
||||
markFlagAsAccessed(59, "useAlwaysAvailableJSErrorHandling");
|
||||
|
||||
flagValue = currentProvider_->useAlwaysAvailableJSErrorHandling();
|
||||
useAlwaysAvailableJSErrorHandling_ = flagValue;
|
||||
@@ -1100,7 +1118,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(59, "useFabricInterop");
|
||||
markFlagAsAccessed(60, "useFabricInterop");
|
||||
|
||||
flagValue = currentProvider_->useFabricInterop();
|
||||
useFabricInterop_ = flagValue;
|
||||
@@ -1118,7 +1136,7 @@ bool ReactNativeFeatureFlagsAccessor::useNativeEqualsInNativeReadableArrayAndroi
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(60, "useNativeEqualsInNativeReadableArrayAndroid");
|
||||
markFlagAsAccessed(61, "useNativeEqualsInNativeReadableArrayAndroid");
|
||||
|
||||
flagValue = currentProvider_->useNativeEqualsInNativeReadableArrayAndroid();
|
||||
useNativeEqualsInNativeReadableArrayAndroid_ = flagValue;
|
||||
@@ -1136,7 +1154,7 @@ bool ReactNativeFeatureFlagsAccessor::useNativeTransformHelperAndroid() {
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(61, "useNativeTransformHelperAndroid");
|
||||
markFlagAsAccessed(62, "useNativeTransformHelperAndroid");
|
||||
|
||||
flagValue = currentProvider_->useNativeTransformHelperAndroid();
|
||||
useNativeTransformHelperAndroid_ = flagValue;
|
||||
@@ -1154,7 +1172,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(62, "useNativeViewConfigsInBridgelessMode");
|
||||
markFlagAsAccessed(63, "useNativeViewConfigsInBridgelessMode");
|
||||
|
||||
flagValue = currentProvider_->useNativeViewConfigsInBridgelessMode();
|
||||
useNativeViewConfigsInBridgelessMode_ = flagValue;
|
||||
@@ -1172,7 +1190,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(63, "useOptimizedEventBatchingOnAndroid");
|
||||
markFlagAsAccessed(64, "useOptimizedEventBatchingOnAndroid");
|
||||
|
||||
flagValue = currentProvider_->useOptimizedEventBatchingOnAndroid();
|
||||
useOptimizedEventBatchingOnAndroid_ = flagValue;
|
||||
@@ -1190,7 +1208,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(64, "useRawPropsJsiValue");
|
||||
markFlagAsAccessed(65, "useRawPropsJsiValue");
|
||||
|
||||
flagValue = currentProvider_->useRawPropsJsiValue();
|
||||
useRawPropsJsiValue_ = flagValue;
|
||||
@@ -1208,7 +1226,7 @@ bool ReactNativeFeatureFlagsAccessor::useShadowNodeStateOnClone() {
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(65, "useShadowNodeStateOnClone");
|
||||
markFlagAsAccessed(66, "useShadowNodeStateOnClone");
|
||||
|
||||
flagValue = currentProvider_->useShadowNodeStateOnClone();
|
||||
useShadowNodeStateOnClone_ = flagValue;
|
||||
@@ -1226,7 +1244,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(66, "useTurboModuleInterop");
|
||||
markFlagAsAccessed(67, "useTurboModuleInterop");
|
||||
|
||||
flagValue = currentProvider_->useTurboModuleInterop();
|
||||
useTurboModuleInterop_ = flagValue;
|
||||
@@ -1244,7 +1262,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(67, "useTurboModules");
|
||||
markFlagAsAccessed(68, "useTurboModules");
|
||||
|
||||
flagValue = currentProvider_->useTurboModules();
|
||||
useTurboModules_ = flagValue;
|
||||
@@ -1262,7 +1280,7 @@ double ReactNativeFeatureFlagsAccessor::virtualViewHysteresisRatio() {
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(68, "virtualViewHysteresisRatio");
|
||||
markFlagAsAccessed(69, "virtualViewHysteresisRatio");
|
||||
|
||||
flagValue = currentProvider_->virtualViewHysteresisRatio();
|
||||
virtualViewHysteresisRatio_ = flagValue;
|
||||
@@ -1280,7 +1298,7 @@ double ReactNativeFeatureFlagsAccessor::virtualViewPrerenderRatio() {
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(69, "virtualViewPrerenderRatio");
|
||||
markFlagAsAccessed(70, "virtualViewPrerenderRatio");
|
||||
|
||||
flagValue = currentProvider_->virtualViewPrerenderRatio();
|
||||
virtualViewPrerenderRatio_ = flagValue;
|
||||
|
||||
+4
-2
@@ -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<<f4faac6988510cde5066898603e2332e>>
|
||||
* @generated SignedSource<<17f7a8577d05b191010622fb58ba27f8>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -77,6 +77,7 @@ class ReactNativeFeatureFlagsAccessor {
|
||||
bool enableVirtualViewDebugFeatures();
|
||||
bool enableVirtualViewRenderState();
|
||||
bool enableVirtualViewWindowFocusDetection();
|
||||
bool enableWebPerformanceAPIsByDefault();
|
||||
bool fixMappingOfEventPrioritiesBetweenFabricAndReact();
|
||||
bool fuseboxEnabledRelease();
|
||||
bool fuseboxNetworkInspectionEnabled();
|
||||
@@ -113,7 +114,7 @@ class ReactNativeFeatureFlagsAccessor {
|
||||
std::unique_ptr<ReactNativeFeatureFlagsProvider> currentProvider_;
|
||||
bool wasOverridden_;
|
||||
|
||||
std::array<std::atomic<const char*>, 70> accessedFeatureFlags_;
|
||||
std::array<std::atomic<const char*>, 71> accessedFeatureFlags_;
|
||||
|
||||
std::atomic<std::optional<bool>> commonTestFlag_;
|
||||
std::atomic<std::optional<bool>> cdpInteractionMetricsEnabled_;
|
||||
@@ -160,6 +161,7 @@ class ReactNativeFeatureFlagsAccessor {
|
||||
std::atomic<std::optional<bool>> enableVirtualViewDebugFeatures_;
|
||||
std::atomic<std::optional<bool>> enableVirtualViewRenderState_;
|
||||
std::atomic<std::optional<bool>> enableVirtualViewWindowFocusDetection_;
|
||||
std::atomic<std::optional<bool>> enableWebPerformanceAPIsByDefault_;
|
||||
std::atomic<std::optional<bool>> fixMappingOfEventPrioritiesBetweenFabricAndReact_;
|
||||
std::atomic<std::optional<bool>> fuseboxEnabledRelease_;
|
||||
std::atomic<std::optional<bool>> fuseboxNetworkInspectionEnabled_;
|
||||
|
||||
+5
-1
@@ -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<<68b40caf4c7d5d92cb5d5eb7bde74ab3>>
|
||||
* @generated SignedSource<<f387394359fc15af1ecad288f08fefe7>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -207,6 +207,10 @@ class ReactNativeFeatureFlagsDefaults : public ReactNativeFeatureFlagsProvider {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool enableWebPerformanceAPIsByDefault() override {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool fixMappingOfEventPrioritiesBetweenFabricAndReact() override {
|
||||
return false;
|
||||
}
|
||||
|
||||
+10
-1
@@ -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<<742e5536d6d174e42a71b205789f93fd>>
|
||||
* @generated SignedSource<<e70173d99a68270c77447cd13c556f6d>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -450,6 +450,15 @@ class ReactNativeFeatureFlagsDynamicProvider : public ReactNativeFeatureFlagsDef
|
||||
return ReactNativeFeatureFlagsDefaults::enableVirtualViewWindowFocusDetection();
|
||||
}
|
||||
|
||||
bool enableWebPerformanceAPIsByDefault() override {
|
||||
auto value = values_["enableWebPerformanceAPIsByDefault"];
|
||||
if (!value.isNull()) {
|
||||
return value.getBool();
|
||||
}
|
||||
|
||||
return ReactNativeFeatureFlagsDefaults::enableWebPerformanceAPIsByDefault();
|
||||
}
|
||||
|
||||
bool fixMappingOfEventPrioritiesBetweenFabricAndReact() override {
|
||||
auto value = values_["fixMappingOfEventPrioritiesBetweenFabricAndReact"];
|
||||
if (!value.isNull()) {
|
||||
|
||||
+2
-1
@@ -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<<40a8180c5d1ebf49c72e6f0fea4201c9>>
|
||||
* @generated SignedSource<<d8b57edf1ba256965238058533a2ea7d>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -70,6 +70,7 @@ class ReactNativeFeatureFlagsProvider {
|
||||
virtual bool enableVirtualViewDebugFeatures() = 0;
|
||||
virtual bool enableVirtualViewRenderState() = 0;
|
||||
virtual bool enableVirtualViewWindowFocusDetection() = 0;
|
||||
virtual bool enableWebPerformanceAPIsByDefault() = 0;
|
||||
virtual bool fixMappingOfEventPrioritiesBetweenFabricAndReact() = 0;
|
||||
virtual bool fuseboxEnabledRelease() = 0;
|
||||
virtual bool fuseboxNetworkInspectionEnabled() = 0;
|
||||
|
||||
@@ -21,6 +21,7 @@ target_link_libraries(react_nativemodule_defaults
|
||||
react_nativemodule_featureflags
|
||||
react_nativemodule_microtasks
|
||||
react_nativemodule_idlecallbacks
|
||||
react_nativemodule_webperformance
|
||||
)
|
||||
target_compile_reactnative_options(react_nativemodule_defaults PRIVATE)
|
||||
target_compile_options(react_nativemodule_defaults PRIVATE -Wpedantic)
|
||||
|
||||
@@ -6,10 +6,12 @@
|
||||
*/
|
||||
|
||||
#include "DefaultTurboModules.h"
|
||||
#include <react/featureflags/ReactNativeFeatureFlags.h>
|
||||
#include <react/nativemodule/dom/NativeDOM.h>
|
||||
#include <react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h>
|
||||
#include <react/nativemodule/idlecallbacks/NativeIdleCallbacks.h>
|
||||
#include <react/nativemodule/microtasks/NativeMicrotasks.h>
|
||||
#include <react/nativemodule/webperformance/NativePerformance.h>
|
||||
|
||||
#ifdef REACT_NATIVE_DEBUGGER_ENABLED_DEVONLY
|
||||
#include <react/nativemodule/devtoolsruntimesettings/DevToolsRuntimeSettingsModule.h>
|
||||
@@ -36,6 +38,12 @@ namespace facebook::react {
|
||||
return std::make_shared<NativeDOM>(jsInvoker);
|
||||
}
|
||||
|
||||
if (ReactNativeFeatureFlags::enableWebPerformanceAPIsByDefault()) {
|
||||
if (name == NativePerformance::kModuleName) {
|
||||
return std::make_shared<NativePerformance>(jsInvoker);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef REACT_NATIVE_DEBUGGER_ENABLED_DEVONLY
|
||||
if (name == DevToolsRuntimeSettingsModule::kModuleName) {
|
||||
return std::make_shared<DevToolsRuntimeSettingsModule>(jsInvoker);
|
||||
|
||||
+1
@@ -50,5 +50,6 @@ Pod::Spec.new do |s|
|
||||
s.dependency "React-featureflagsnativemodule"
|
||||
s.dependency "React-microtasksnativemodule"
|
||||
s.dependency "React-idlecallbacksnativemodule"
|
||||
s.dependency "React-webperformancenativemodule"
|
||||
add_dependency(s, "React-RCTFBReactNativeSpec")
|
||||
end
|
||||
|
||||
+6
-1
@@ -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<<95f3b1a29280420bf97cdadbcf9f11da>>
|
||||
* @generated SignedSource<<702c4023cfafdd477cba85c6efe94d93>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -269,6 +269,11 @@ bool NativeReactNativeFeatureFlags::enableVirtualViewWindowFocusDetection(
|
||||
return ReactNativeFeatureFlags::enableVirtualViewWindowFocusDetection();
|
||||
}
|
||||
|
||||
bool NativeReactNativeFeatureFlags::enableWebPerformanceAPIsByDefault(
|
||||
jsi::Runtime& /*runtime*/) {
|
||||
return ReactNativeFeatureFlags::enableWebPerformanceAPIsByDefault();
|
||||
}
|
||||
|
||||
bool NativeReactNativeFeatureFlags::fixMappingOfEventPrioritiesBetweenFabricAndReact(
|
||||
jsi::Runtime& /*runtime*/) {
|
||||
return ReactNativeFeatureFlags::fixMappingOfEventPrioritiesBetweenFabricAndReact();
|
||||
|
||||
+3
-1
@@ -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<<fe8e1bef9e0c34dc88b5edb604ded048>>
|
||||
* @generated SignedSource<<96e93863588a9878db7c812435564603>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -126,6 +126,8 @@ class NativeReactNativeFeatureFlags
|
||||
|
||||
bool enableVirtualViewWindowFocusDetection(jsi::Runtime& runtime);
|
||||
|
||||
bool enableWebPerformanceAPIsByDefault(jsi::Runtime& runtime);
|
||||
|
||||
bool fixMappingOfEventPrioritiesBetweenFabricAndReact(jsi::Runtime& runtime);
|
||||
|
||||
bool fuseboxEnabledRelease(jsi::Runtime& runtime);
|
||||
|
||||
@@ -7,13 +7,13 @@ cmake_minimum_required(VERSION 3.13)
|
||||
set(CMAKE_VERBOSE_MAKEFILE on)
|
||||
|
||||
include(${REACT_COMMON_DIR}/cmake-utils/react-native-flags.cmake)
|
||||
|
||||
file(GLOB react_nativemodule_webperformance_SRC CONFIGURE_DEPENDS *.cpp)
|
||||
add_library(react_nativemodule_webperformance OBJECT ${react_nativemodule_webperformance_SRC})
|
||||
|
||||
target_include_directories(react_nativemodule_webperformance PUBLIC ${REACT_COMMON_DIR})
|
||||
|
||||
target_link_libraries(react_nativemodule_webperformance
|
||||
react_performance_timeline
|
||||
react_codegen_rncore
|
||||
react_cxxreact
|
||||
)
|
||||
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
# 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.
|
||||
|
||||
require "json"
|
||||
|
||||
package = JSON.parse(File.read(File.join(__dir__, "..", "..", "..", "..", "package.json")))
|
||||
version = package['version']
|
||||
|
||||
source = { :git => 'https://github.com/facebook/react-native.git' }
|
||||
if version == '1000.0.0'
|
||||
# This is an unpublished version, use the latest commit hash of the react-native repo, which we’re presumably in.
|
||||
source[:commit] = `git rev-parse HEAD`.strip if system("git rev-parse --git-dir > /dev/null 2>&1")
|
||||
else
|
||||
source[:tag] = "v#{version}"
|
||||
end
|
||||
|
||||
header_search_paths = []
|
||||
|
||||
if ENV['USE_FRAMEWORKS']
|
||||
header_search_paths << "\"$(PODS_TARGET_SRCROOT)/../../..\"" # this is needed to allow the module access its own files
|
||||
end
|
||||
|
||||
Pod::Spec.new do |s|
|
||||
s.name = "React-webperformancenativemodule"
|
||||
s.version = version
|
||||
s.summary = "React Native idle callbacks native module"
|
||||
s.homepage = "https://reactnative.dev/"
|
||||
s.license = package["license"]
|
||||
s.author = "Meta Platforms, Inc. and its affiliates"
|
||||
s.platforms = min_supported_versions
|
||||
s.source = source
|
||||
s.source_files = podspec_sources("*.{cpp,h}", "*.h")
|
||||
s.header_dir = "react/nativemodule/webperformance"
|
||||
s.pod_target_xcconfig = { "CLANG_CXX_LANGUAGE_STANDARD" => rct_cxx_language_standard(),
|
||||
"HEADER_SEARCH_PATHS" => header_search_paths.join(' '),
|
||||
"OTHER_CFLAGS" => "$(inherited)",
|
||||
"DEFINES_MODULE" => "YES" }
|
||||
|
||||
if ENV['USE_FRAMEWORKS']
|
||||
s.module_name = "webperformancenativemodule"
|
||||
s.header_mappings_dir = "../.."
|
||||
end
|
||||
|
||||
s.dependency "React-jsi"
|
||||
s.dependency "React-jsiexecutor"
|
||||
|
||||
depend_on_js_engine(s)
|
||||
add_rn_third_party_dependencies(s)
|
||||
add_rncore_dependency(s)
|
||||
|
||||
s.dependency "ReactCommon/turbomodule/core"
|
||||
add_dependency(s, "React-RCTFBReactNativeSpec")
|
||||
add_dependency(s, "React-performancetimeline")
|
||||
add_dependency(s, "React-runtimeexecutor", :additional_framework_paths => ["platform/ios"])
|
||||
|
||||
end
|
||||
@@ -27,10 +27,10 @@ std::optional<double> DynamicEventPayload::extractValue(
|
||||
auto dynamic = payload_;
|
||||
for (auto& key : path) {
|
||||
auto type = dynamic.type();
|
||||
if ((type == folly::dynamic::Type::OBJECT ||
|
||||
type == folly::dynamic::Type::ARRAY) &&
|
||||
!dynamic.empty()) {
|
||||
if (type == folly::dynamic::Type::OBJECT && !dynamic.empty()) {
|
||||
dynamic = folly::dynamic(dynamic[key]);
|
||||
} else if (type == folly::dynamic::Type::ARRAY && !dynamic.empty()) {
|
||||
dynamic = folly::dynamic(dynamic[std::stoi(key)]);
|
||||
}
|
||||
}
|
||||
if (dynamic.type() == folly::dynamic::Type::DOUBLE) {
|
||||
|
||||
@@ -527,6 +527,16 @@ const definitions: FeatureFlagDefinitions = {
|
||||
},
|
||||
ossReleaseStage: 'none',
|
||||
},
|
||||
enableWebPerformanceAPIsByDefault: {
|
||||
defaultValue: false,
|
||||
metadata: {
|
||||
description:
|
||||
'Enable Web Performance APIs (Performance Timeline, User Timings, etc.) by default.',
|
||||
expectedReleaseValue: true,
|
||||
purpose: 'release',
|
||||
},
|
||||
ossReleaseStage: 'none',
|
||||
},
|
||||
fixMappingOfEventPrioritiesBetweenFabricAndReact: {
|
||||
defaultValue: false,
|
||||
metadata: {
|
||||
|
||||
@@ -142,6 +142,7 @@ def use_react_native! (
|
||||
pod 'React-featureflagsnativemodule', :path => "#{prefix}/ReactCommon/react/nativemodule/featureflags"
|
||||
pod 'React-microtasksnativemodule', :path => "#{prefix}/ReactCommon/react/nativemodule/microtasks"
|
||||
pod 'React-idlecallbacksnativemodule', :path => "#{prefix}/ReactCommon/react/nativemodule/idlecallbacks"
|
||||
pod 'React-webperformancenativemodule', :path => "#{prefix}/ReactCommon/react/nativemodule/webperformance"
|
||||
pod 'React-domnativemodule', :path => "#{prefix}/ReactCommon/react/nativemodule/dom"
|
||||
pod 'React-defaultsnativemodule', :path => "#{prefix}/ReactCommon/react/nativemodule/defaults"
|
||||
pod 'React-Mapbuffer', :path => "#{prefix}/ReactCommon"
|
||||
|
||||
-1
@@ -4,7 +4,6 @@
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @fantom_react_fb_flags enableEagerAlternateStateNodeCleanup:true
|
||||
* @flow strict-local
|
||||
* @format
|
||||
*/
|
||||
|
||||
@@ -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<<1a00c3c154cd9e8afac7ad9333152ac6>>
|
||||
* @generated SignedSource<<08b6cc65abf58a5e1018f861f9f2a5c8>>
|
||||
* @flow strict
|
||||
* @noformat
|
||||
*/
|
||||
@@ -95,6 +95,7 @@ export type ReactNativeFeatureFlags = $ReadOnly<{
|
||||
enableVirtualViewDebugFeatures: Getter<boolean>,
|
||||
enableVirtualViewRenderState: Getter<boolean>,
|
||||
enableVirtualViewWindowFocusDetection: Getter<boolean>,
|
||||
enableWebPerformanceAPIsByDefault: Getter<boolean>,
|
||||
fixMappingOfEventPrioritiesBetweenFabricAndReact: Getter<boolean>,
|
||||
fuseboxEnabledRelease: Getter<boolean>,
|
||||
fuseboxNetworkInspectionEnabled: Getter<boolean>,
|
||||
@@ -381,6 +382,10 @@ export const enableVirtualViewRenderState: Getter<boolean> = createNativeFlagGet
|
||||
* Enables window focus detection for prioritizing VirtualView events.
|
||||
*/
|
||||
export const enableVirtualViewWindowFocusDetection: Getter<boolean> = createNativeFlagGetter('enableVirtualViewWindowFocusDetection', false);
|
||||
/**
|
||||
* Enable Web Performance APIs (Performance Timeline, User Timings, etc.) by default.
|
||||
*/
|
||||
export const enableWebPerformanceAPIsByDefault: Getter<boolean> = createNativeFlagGetter('enableWebPerformanceAPIsByDefault', false);
|
||||
/**
|
||||
* Uses the default event priority instead of the discreet event priority by default when dispatching events from Fabric to React.
|
||||
*/
|
||||
|
||||
+2
-1
@@ -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<<bd27a3abd64ea3bedf5c178ce3a8aa64>>
|
||||
* @generated SignedSource<<3e23fd36db655942220a765e2054f01f>>
|
||||
* @flow strict
|
||||
* @noformat
|
||||
*/
|
||||
@@ -70,6 +70,7 @@ export interface Spec extends TurboModule {
|
||||
+enableVirtualViewDebugFeatures?: () => boolean;
|
||||
+enableVirtualViewRenderState?: () => boolean;
|
||||
+enableVirtualViewWindowFocusDetection?: () => boolean;
|
||||
+enableWebPerformanceAPIsByDefault?: () => boolean;
|
||||
+fixMappingOfEventPrioritiesBetweenFabricAndReact?: () => boolean;
|
||||
+fuseboxEnabledRelease?: () => boolean;
|
||||
+fuseboxNetworkInspectionEnabled?: () => boolean;
|
||||
|
||||
@@ -0,0 +1,270 @@
|
||||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow strict-local
|
||||
* @format
|
||||
*/
|
||||
|
||||
import type {RNTesterModuleExample} from '../../types/RNTesterTypes';
|
||||
import type Performance from 'react-native/src/private/webapis/performance/Performance';
|
||||
|
||||
import RNTesterText from '../../components/RNTesterText';
|
||||
import * as React from 'react';
|
||||
import {useEffect} from 'react';
|
||||
import {Button, StyleSheet, View} from 'react-native';
|
||||
|
||||
declare var performance: Performance;
|
||||
|
||||
const {useState, useCallback} = React;
|
||||
|
||||
function MemoryExample(): React.Node {
|
||||
// Memory API testing
|
||||
const [memoryInfo, setMemoryInfo] =
|
||||
useState<?typeof performance.memory>(null);
|
||||
const onGetMemoryInfo = useCallback(() => {
|
||||
// performance.memory is not included in bom.js yet.
|
||||
// Once we release the change in flow this can be removed.
|
||||
setMemoryInfo(performance.memory);
|
||||
}, []);
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<Button onPress={onGetMemoryInfo} title="Click to update memory info" />
|
||||
<View>
|
||||
<RNTesterText>
|
||||
{`jsHeapSizeLimit: ${String(memoryInfo?.jsHeapSizeLimit)} bytes`}
|
||||
</RNTesterText>
|
||||
<RNTesterText>
|
||||
{`totalJSHeapSize: ${String(memoryInfo?.totalJSHeapSize)} bytes`}
|
||||
</RNTesterText>
|
||||
<RNTesterText>
|
||||
{`usedJSHeapSize: ${String(memoryInfo?.usedJSHeapSize)} bytes`}
|
||||
</RNTesterText>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
function StartupTimingExample(): React.Node {
|
||||
// React Startup Timing API testing
|
||||
const [startUpTiming, setStartUpTiming] =
|
||||
useState<?typeof performance.rnStartupTiming>(null);
|
||||
const onGetStartupTiming = useCallback(() => {
|
||||
// performance.reactNativeStartupTiming is not included in bom.js yet.
|
||||
// Once we release the change in flow this can be removed.
|
||||
setStartUpTiming(performance.rnStartupTiming);
|
||||
}, []);
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<Button
|
||||
onPress={onGetStartupTiming}
|
||||
title="Click to update React startup timing"
|
||||
/>
|
||||
<View>
|
||||
<RNTesterText>{`startTime: ${String(startUpTiming?.startTime)} ms`}</RNTesterText>
|
||||
<RNTesterText>{`initializeRuntimeStart: ${String(
|
||||
startUpTiming?.initializeRuntimeStart,
|
||||
)} ms`}</RNTesterText>
|
||||
<RNTesterText>
|
||||
{`executeJavaScriptBundleEntryPointStart: ${String(
|
||||
startUpTiming?.executeJavaScriptBundleEntryPointStart,
|
||||
)} ms`}
|
||||
</RNTesterText>
|
||||
<RNTesterText>{`executeJavaScriptBundleEntryPointEnd: ${String(
|
||||
startUpTiming?.executeJavaScriptBundleEntryPointEnd,
|
||||
)} ms`}</RNTesterText>
|
||||
<RNTesterText>{`initializeRuntimeEnd: ${String(
|
||||
startUpTiming?.initializeRuntimeEnd,
|
||||
)} ms`}</RNTesterText>
|
||||
<RNTesterText>{`endTime: ${String(startUpTiming?.endTime)} ms`}</RNTesterText>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
function PerformanceObserverUserTimingExample(): React.Node {
|
||||
const [entries, setEntries] = useState<$ReadOnlyArray<PerformanceEntry>>([]);
|
||||
|
||||
useEffect(() => {
|
||||
const observer = new PerformanceObserver(list => {
|
||||
const newEntries = list
|
||||
.getEntries()
|
||||
.filter(entry => entry.name.startsWith('rntester-'));
|
||||
if (newEntries.length > 0) {
|
||||
setEntries(newEntries);
|
||||
}
|
||||
});
|
||||
|
||||
observer.observe({entryTypes: ['mark', 'measure']});
|
||||
|
||||
return () => observer.disconnect();
|
||||
}, []);
|
||||
|
||||
const onPress = useCallback(() => {
|
||||
performance.mark('rntester-mark1');
|
||||
performance.mark('rntester-mark2');
|
||||
performance.measure(
|
||||
'rntester-measure1',
|
||||
'rntester-mark1',
|
||||
'rntester-mark2',
|
||||
);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<Button onPress={onPress} title="Click to log some marks and measures" />
|
||||
<View>
|
||||
{entries.map((entry, index) =>
|
||||
entry.entryType === 'mark' ? (
|
||||
<RNTesterText key={index}>
|
||||
Mark {entry.name}: {entry.startTime.toFixed(2)}
|
||||
</RNTesterText>
|
||||
) : (
|
||||
<RNTesterText key={index}>
|
||||
Measure {entry.name}: {entry.startTime.toFixed(2)} -{' '}
|
||||
{(entry.startTime + entry.duration).toFixed(2)} (
|
||||
{entry.duration.toFixed(2)}ms)
|
||||
</RNTesterText>
|
||||
),
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
function PerformanceObserverEventTimingExample(): React.Node {
|
||||
const [count, setCount] = useState(0);
|
||||
|
||||
const [entries, setEntries] = useState<
|
||||
$ReadOnlyArray<PerformanceEventTiming>,
|
||||
>([]);
|
||||
|
||||
useEffect(() => {
|
||||
const observer = new PerformanceObserver(list => {
|
||||
const newEntries: $ReadOnlyArray<PerformanceEventTiming> =
|
||||
// $FlowExpectedError[incompatible-type] This is guaranteed because we're only observing `event` entry types.
|
||||
list.getEntries();
|
||||
setEntries(newEntries);
|
||||
});
|
||||
|
||||
observer.observe({type: 'event'});
|
||||
|
||||
return () => observer.disconnect();
|
||||
}, []);
|
||||
|
||||
const onPress = useCallback(() => {
|
||||
busyWait(500);
|
||||
// Force a state update to show how/if we're reporting paint times as well.
|
||||
setCount(currentCount => currentCount + 1);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<Button
|
||||
onPress={onPress}
|
||||
title={`Click to force a slow event (clicked ${count} times)`}
|
||||
/>
|
||||
<View>
|
||||
{entries.map((entry, index) => (
|
||||
<RNTesterText key={index}>
|
||||
Event: {entry.name}
|
||||
{'\n'}
|
||||
Start: {entry.startTime.toFixed(2)}
|
||||
{'\n'}
|
||||
End: {(entry.startTime + entry.duration).toFixed(2)}
|
||||
{'\n'}
|
||||
Duration: {entry.duration.toFixed(2)}ms{'\n'}
|
||||
Processing start: {entry.processingStart.toFixed(2)} (delay:{' '}
|
||||
{(entry.processingStart - entry.startTime).toFixed(2)}ms){'\n'}
|
||||
Processing end: {entry.processingEnd.toFixed(2)} (duration:{' '}
|
||||
{(entry.processingEnd - entry.processingStart).toFixed(2)}ms){'\n'}
|
||||
</RNTesterText>
|
||||
))}
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
function PerformanceObserverLongtaskExample(): React.Node {
|
||||
const [entries, setEntries] = useState<$ReadOnlyArray<PerformanceEntry>>([]);
|
||||
|
||||
useEffect(() => {
|
||||
const observer = new PerformanceObserver(list => {
|
||||
setEntries(list.getEntries());
|
||||
});
|
||||
|
||||
observer.observe({entryTypes: ['longtask']});
|
||||
|
||||
return () => observer.disconnect();
|
||||
}, []);
|
||||
|
||||
const onPress = useCallback(() => {
|
||||
// Wait 1s to force a long task
|
||||
busyWait(1000);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<Button onPress={onPress} title="Click to force a long task" />
|
||||
<View>
|
||||
{entries.map((entry, index) => (
|
||||
<RNTesterText key={index}>
|
||||
Long task {entry.name}: {entry.startTime} -{' '}
|
||||
{entry.startTime + entry.duration} ({entry.duration}ms)
|
||||
</RNTesterText>
|
||||
))}
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
function busyWait(ms: number): void {
|
||||
const end = performance.now() + ms;
|
||||
while (performance.now() < end) {}
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
padding: 10,
|
||||
},
|
||||
});
|
||||
|
||||
export const title = 'Performance API Examples';
|
||||
export const category = 'Basic';
|
||||
export const description = 'Shows the performance API provided in React Native';
|
||||
export const examples: Array<RNTesterModuleExample> = ([
|
||||
{
|
||||
title: 'performance.memory',
|
||||
render: (): React.Node => {
|
||||
return <MemoryExample />;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'performance.reactNativeStartupTiming',
|
||||
render: (): React.Node => {
|
||||
return <StartupTimingExample />;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'PerformanceObserver (marks and measures)',
|
||||
render: (): React.Node => {
|
||||
return <PerformanceObserverUserTimingExample />;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'PerformanceObserver (events)',
|
||||
render: (): React.Node => {
|
||||
return <PerformanceObserverEventTimingExample />;
|
||||
},
|
||||
},
|
||||
PerformanceObserver.supportedEntryTypes.includes('longtask')
|
||||
? {
|
||||
title: 'PerformanceObserver (long tasks)',
|
||||
render: (): React.Node => {
|
||||
return <PerformanceObserverLongtaskExample />;
|
||||
},
|
||||
}
|
||||
: null,
|
||||
]: Array<?RNTesterModuleExample>).filter(Boolean);
|
||||
@@ -363,6 +363,16 @@ const APIs: Array<RNTesterModuleInfo> = ([
|
||||
category: 'Basic',
|
||||
module: require('../examples/TurboModule/TurboCxxModuleExample'),
|
||||
},
|
||||
// Basic check to detect the availability of the modern Performance API.
|
||||
...(typeof performance.getEntries === 'function'
|
||||
? [
|
||||
{
|
||||
key: 'PerformanceApiExample',
|
||||
category: 'Basic',
|
||||
module: require('../examples/Performance/PerformanceApiExample'),
|
||||
},
|
||||
]
|
||||
: []),
|
||||
...RNTesterListFbInternal.APIs,
|
||||
]: Array<?RNTesterModuleInfo>).filter(Boolean);
|
||||
|
||||
|
||||
@@ -337,6 +337,16 @@ const APIs: Array<RNTesterModuleInfo> = ([
|
||||
key: 'XHRExample',
|
||||
module: require('../examples/XHR/XHRExample'),
|
||||
},
|
||||
// Basic check to detect the availability of the modern Performance API.
|
||||
...(typeof performance.getEntries === 'function'
|
||||
? [
|
||||
{
|
||||
key: 'PerformanceApiExample',
|
||||
category: 'Basic',
|
||||
module: require('../examples/Performance/PerformanceApiExample'),
|
||||
},
|
||||
]
|
||||
: []),
|
||||
...RNTesterListFbInternal.APIs,
|
||||
]: Array<?RNTesterModuleInfo>).filter(Boolean);
|
||||
|
||||
|
||||
@@ -44,3 +44,26 @@ configure<com.facebook.react.ReactSettingsExtension> {
|
||||
lockFiles = files("yarn.lock"),
|
||||
)
|
||||
}
|
||||
|
||||
// Gradle properties defined in `gradle.properties` are not inherited by
|
||||
// included builds, see https://github.com/gradle/gradle/issues/2534.
|
||||
// This is a workaround to read the configuration from the consuming project,
|
||||
// and apply relevant properties to the :react-native project.
|
||||
buildscript {
|
||||
val properties = java.util.Properties()
|
||||
val propertiesToInherit = listOf("hermesV1Enabled", "react.hermesV1Enabled")
|
||||
|
||||
try {
|
||||
file("../../android/gradle.properties").inputStream().use { properties.load(it) }
|
||||
|
||||
gradle.rootProject {
|
||||
propertiesToInherit.forEach { property ->
|
||||
if (properties.containsKey(property)) {
|
||||
gradle.rootProject.extra.set(property, properties.getProperty(property))
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
// fail silently
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user