react-native 0.83.3 → 0.83.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (107) hide show
  1. package/Libraries/Core/ReactNativeVersion.js +1 -1
  2. package/Libraries/Utilities/Appearance.js +6 -1
  3. package/React/Base/RCTVersion.m +1 -1
  4. package/React/DevSupport/RCTFrameTimingsObserver.h +24 -0
  5. package/React/DevSupport/RCTFrameTimingsObserver.mm +298 -0
  6. package/React/FBReactNativeSpec/FBReactNativeSpecJSI.h +16 -0
  7. package/ReactAndroid/api/ReactAndroid.api +0 -9
  8. package/ReactAndroid/gradle.properties +1 -1
  9. package/ReactAndroid/src/main/java/com/facebook/react/devsupport/BridgelessDevSupportManager.kt +2 -2
  10. package/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerBase.kt +7 -7
  11. package/ReactAndroid/src/main/java/com/facebook/react/devsupport/InspectorFlags.kt +4 -0
  12. package/ReactAndroid/src/main/java/com/facebook/react/devsupport/inspector/FrameTimingSequence.kt +16 -0
  13. package/ReactAndroid/src/main/java/com/facebook/react/devsupport/inspector/FrameTimingsObserver.kt +275 -0
  14. package/ReactAndroid/src/main/java/com/facebook/react/devsupport/inspector/TracingState.kt +17 -0
  15. package/ReactAndroid/src/main/java/com/facebook/react/devsupport/inspector/TracingStateListener.kt +15 -0
  16. package/ReactAndroid/src/main/java/com/facebook/react/devsupport/{interfaces → inspector}/TracingStateProvider.kt +1 -1
  17. package/ReactAndroid/src/main/java/com/facebook/react/devsupport/perfmonitor/PerfMonitorInspectorTargetBinding.kt +1 -1
  18. package/ReactAndroid/src/main/java/com/facebook/react/devsupport/perfmonitor/PerfMonitorOverlayManager.kt +4 -4
  19. package/ReactAndroid/src/main/java/com/facebook/react/devsupport/perfmonitor/PerfMonitorOverlayView.kt +3 -3
  20. package/ReactAndroid/src/main/java/com/facebook/react/devsupport/perfmonitor/PerfMonitorUpdateListener.kt +1 -1
  21. package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt +13 -1
  22. package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt +21 -1
  23. package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt +5 -1
  24. package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt +5 -1
  25. package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt +23 -1
  26. package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt +5 -1
  27. package/ReactAndroid/src/main/java/com/facebook/react/internal/tracing/PerformanceTracer.kt +39 -0
  28. package/ReactAndroid/src/main/java/com/facebook/react/modules/blob/BlobModule.kt +1 -1
  29. package/ReactAndroid/src/main/java/com/facebook/react/modules/network/NetworkEventUtil.kt +20 -19
  30. package/ReactAndroid/src/main/java/com/facebook/react/modules/network/NetworkingModule.kt +6 -12
  31. package/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.kt +1 -1
  32. package/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.kt +86 -4
  33. package/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImplDevHelper.kt +3 -3
  34. package/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostInspectorTarget.kt +10 -6
  35. package/ReactAndroid/src/main/jni/react/devsupport/JInspectorFlags.cpp +22 -0
  36. package/ReactAndroid/src/main/jni/react/devsupport/JInspectorFlags.h +2 -0
  37. package/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp +29 -1
  38. package/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h +7 -1
  39. package/ReactAndroid/src/main/jni/react/runtime/jni/JReactHostInspectorTarget.cpp +196 -17
  40. package/ReactAndroid/src/main/jni/react/runtime/jni/JReactHostInspectorTarget.h +168 -18
  41. package/ReactAndroid/src/main/jni/third-party/folly/CMakeLists.txt +1 -0
  42. package/ReactCommon/cxxreact/ReactNativeVersion.h +2 -2
  43. package/ReactCommon/jsinspector-modern/HostAgent.cpp +45 -10
  44. package/ReactCommon/jsinspector-modern/HostAgent.h +2 -2
  45. package/ReactCommon/jsinspector-modern/HostTarget.cpp +14 -7
  46. package/ReactCommon/jsinspector-modern/HostTarget.h +101 -14
  47. package/ReactCommon/jsinspector-modern/HostTargetTraceRecording.cpp +39 -8
  48. package/ReactCommon/jsinspector-modern/HostTargetTraceRecording.h +42 -5
  49. package/ReactCommon/jsinspector-modern/HostTargetTracing.cpp +54 -21
  50. package/ReactCommon/jsinspector-modern/HostTargetTracing.h +89 -0
  51. package/ReactCommon/jsinspector-modern/InspectorFlags.cpp +12 -0
  52. package/ReactCommon/jsinspector-modern/InspectorFlags.h +12 -0
  53. package/ReactCommon/jsinspector-modern/InspectorInterfaces.cpp +3 -7
  54. package/ReactCommon/jsinspector-modern/InstanceAgent.cpp +2 -11
  55. package/ReactCommon/jsinspector-modern/NetworkIOAgent.cpp +1 -1
  56. package/ReactCommon/jsinspector-modern/TracingAgent.cpp +29 -13
  57. package/ReactCommon/jsinspector-modern/TracingAgent.h +5 -4
  58. package/ReactCommon/jsinspector-modern/tests/HostTargetTest.cpp +65 -0
  59. package/ReactCommon/jsinspector-modern/tests/InspectorMocks.h +23 -2
  60. package/ReactCommon/jsinspector-modern/tests/JsiIntegrationTest.cpp +1 -0
  61. package/ReactCommon/jsinspector-modern/tests/NetworkReporterTest.cpp +1 -0
  62. package/ReactCommon/jsinspector-modern/tests/TracingTest.cpp +335 -0
  63. package/ReactCommon/jsinspector-modern/tests/TracingTest.h +95 -0
  64. package/ReactCommon/jsinspector-modern/tests/utils/InspectorFlagOverridesGuard.cpp +10 -0
  65. package/ReactCommon/jsinspector-modern/tests/utils/InspectorFlagOverridesGuard.h +3 -1
  66. package/ReactCommon/jsinspector-modern/tracing/CMakeLists.txt +1 -0
  67. package/ReactCommon/jsinspector-modern/tracing/FrameTimingSequence.h +61 -0
  68. package/ReactCommon/jsinspector-modern/tracing/HostTracingProfile.h +43 -0
  69. package/ReactCommon/jsinspector-modern/tracing/HostTracingProfileSerializer.cpp +165 -0
  70. package/ReactCommon/jsinspector-modern/tracing/HostTracingProfileSerializer.h +50 -0
  71. package/ReactCommon/jsinspector-modern/tracing/PerformanceTracer.cpp +16 -14
  72. package/ReactCommon/jsinspector-modern/tracing/PerformanceTracerSection.h +113 -0
  73. package/ReactCommon/jsinspector-modern/tracing/React-jsinspectortracing.podspec +1 -0
  74. package/ReactCommon/jsinspector-modern/tracing/TimeWindowedBuffer.h +158 -0
  75. package/ReactCommon/jsinspector-modern/tracing/TraceEvent.h +2 -1
  76. package/ReactCommon/jsinspector-modern/tracing/TraceEventGenerator.cpp +100 -0
  77. package/ReactCommon/jsinspector-modern/tracing/TraceEventGenerator.h +60 -0
  78. package/ReactCommon/jsinspector-modern/tracing/TraceEventSerializer.cpp +44 -1
  79. package/ReactCommon/jsinspector-modern/tracing/TraceEventSerializer.h +7 -0
  80. package/ReactCommon/jsinspector-modern/tracing/TraceRecordingState.h +18 -7
  81. package/ReactCommon/jsinspector-modern/tracing/TracingCategory.h +136 -0
  82. package/ReactCommon/jsinspector-modern/tracing/tests/TimeWindowedBufferTest.cpp +352 -0
  83. package/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp +9 -1
  84. package/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h +11 -1
  85. package/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp +65 -29
  86. package/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h +6 -2
  87. package/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h +9 -1
  88. package/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDynamicProvider.h +19 -1
  89. package/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h +3 -1
  90. package/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModule.mm +3 -1
  91. package/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp +11 -1
  92. package/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h +5 -1
  93. package/ReactCommon/react/performance/timeline/PerformanceObserver.cpp +18 -6
  94. package/ReactCommon/react/performance/timeline/PerformanceObserver.h +2 -0
  95. package/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTHost.mm +115 -0
  96. package/ReactCommon/{jsinspector-modern → react/utils}/Base64.h +2 -2
  97. package/gradle/libs.versions.toml +1 -1
  98. package/package.json +8 -8
  99. package/scripts/cocoapods/utils.rb +1 -0
  100. package/src/private/featureflags/ReactNativeFeatureFlags.js +11 -1
  101. package/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js +3 -1
  102. package/third-party-podspecs/RCT-Folly.podspec +1 -1
  103. package/third-party-podspecs/fmt.podspec +2 -2
  104. package/ReactAndroid/src/main/java/com/facebook/react/devsupport/interfaces/TracingState.kt +0 -19
  105. package/ReactCommon/jsinspector-modern/tracing/TraceRecordingStateSerializer.cpp +0 -68
  106. package/ReactCommon/jsinspector-modern/tracing/TraceRecordingStateSerializer.h +0 -42
  107. package/ReactCommon/jsinspector-modern/tracing/TracingState.h +0 -24
@@ -0,0 +1,275 @@
1
+ /*
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ package com.facebook.react.devsupport.inspector
9
+
10
+ import android.graphics.Bitmap
11
+ import android.os.Build
12
+ import android.os.Handler
13
+ import android.os.Looper
14
+ import android.os.Process
15
+ import android.view.FrameMetrics
16
+ import android.view.PixelCopy
17
+ import android.view.Window
18
+ import com.facebook.proguard.annotations.DoNotStripAny
19
+ import java.io.ByteArrayOutputStream
20
+ import java.util.concurrent.Executors
21
+ import java.util.concurrent.atomic.AtomicBoolean
22
+ import java.util.concurrent.atomic.AtomicReference
23
+ import kotlinx.coroutines.CoroutineDispatcher
24
+ import kotlinx.coroutines.CoroutineScope
25
+ import kotlinx.coroutines.Dispatchers
26
+ import kotlinx.coroutines.asCoroutineDispatcher
27
+ import kotlinx.coroutines.launch
28
+
29
+ @DoNotStripAny
30
+ internal class FrameTimingsObserver(
31
+ private val screenshotsEnabled: Boolean,
32
+ private val onFrameTimingSequence: (sequence: FrameTimingSequence) -> Unit,
33
+ ) {
34
+ private val isSupported = Build.VERSION.SDK_INT >= Build.VERSION_CODES.N
35
+ private val mainHandler = Handler(Looper.getMainLooper())
36
+
37
+ // Serial dispatcher for encoding work (single background thread). We limit to 1 thread to
38
+ // minimize the performance impact of screenshot recording.
39
+ private val encodingDispatcher: CoroutineDispatcher =
40
+ Executors.newSingleThreadExecutor().asCoroutineDispatcher()
41
+
42
+ // Stores the most recently captured frame to opportunistically encode after the current frame.
43
+ // Replaced frames are emitted as timings without screenshots.
44
+ private val lastFrameBuffer = AtomicReference<FrameData?>(null)
45
+
46
+ private var frameCounter: Int = 0
47
+ private val encodingInProgress = AtomicBoolean(false)
48
+ @Volatile private var isTracing: Boolean = false
49
+ @Volatile private var currentWindow: Window? = null
50
+
51
+ private data class FrameData(
52
+ val bitmap: Bitmap,
53
+ val frameId: Int,
54
+ val threadId: Int,
55
+ val beginTimestamp: Long,
56
+ val endTimestamp: Long,
57
+ )
58
+
59
+ fun start() {
60
+ if (!isSupported) {
61
+ return
62
+ }
63
+
64
+ frameCounter = 0
65
+ encodingInProgress.set(false)
66
+ lastFrameBuffer.set(null)
67
+ isTracing = true
68
+
69
+ // Emit initial frame event
70
+ val timestamp = System.nanoTime()
71
+ emitFrameTiming(timestamp, timestamp)
72
+
73
+ currentWindow?.addOnFrameMetricsAvailableListener(frameMetricsListener, mainHandler)
74
+ }
75
+
76
+ fun stop() {
77
+ if (!isSupported) {
78
+ return
79
+ }
80
+
81
+ isTracing = false
82
+
83
+ currentWindow?.removeOnFrameMetricsAvailableListener(frameMetricsListener)
84
+ mainHandler.removeCallbacksAndMessages(null)
85
+ lastFrameBuffer.getAndSet(null)?.bitmap?.recycle()
86
+ }
87
+
88
+ fun setCurrentWindow(window: Window?) {
89
+ if (!isSupported || currentWindow === window) {
90
+ return
91
+ }
92
+
93
+ currentWindow?.removeOnFrameMetricsAvailableListener(frameMetricsListener)
94
+ currentWindow = window
95
+ if (isTracing) {
96
+ currentWindow?.addOnFrameMetricsAvailableListener(frameMetricsListener, mainHandler)
97
+ }
98
+ }
99
+
100
+ private val frameMetricsListener =
101
+ Window.OnFrameMetricsAvailableListener { _, frameMetrics, _ ->
102
+ // Guard against calls after stop()
103
+ if (!isTracing) {
104
+ return@OnFrameMetricsAvailableListener
105
+ }
106
+ val beginTimestamp = frameMetrics.getMetric(FrameMetrics.VSYNC_TIMESTAMP)
107
+ val endTimestamp = beginTimestamp + frameMetrics.getMetric(FrameMetrics.TOTAL_DURATION)
108
+ emitFrameTiming(beginTimestamp, endTimestamp)
109
+ }
110
+
111
+ private fun emitFrameTiming(beginTimestamp: Long, endTimestamp: Long) {
112
+ val frameId = frameCounter++
113
+ val threadId = Process.myTid()
114
+
115
+ if (!screenshotsEnabled) {
116
+ // Screenshots disabled - emit without screenshot
117
+ emitFrameEvent(frameId, threadId, beginTimestamp, endTimestamp, null)
118
+ return
119
+ }
120
+
121
+ captureScreenshot(frameId, threadId, beginTimestamp, endTimestamp) { frameData ->
122
+ if (frameData != null) {
123
+ if (encodingInProgress.compareAndSet(false, true)) {
124
+ // Not encoding - encode this frame immediately
125
+ encodeFrame(frameData)
126
+ } else {
127
+ // Encoding thread busy - store current screenshot in buffer for tail-capture
128
+ val oldFrameData = lastFrameBuffer.getAndSet(frameData)
129
+ if (oldFrameData != null) {
130
+ // Skipped frame - emit event without screenshot
131
+ emitFrameEvent(
132
+ oldFrameData.frameId,
133
+ oldFrameData.threadId,
134
+ oldFrameData.beginTimestamp,
135
+ oldFrameData.endTimestamp,
136
+ null,
137
+ )
138
+ oldFrameData.bitmap.recycle()
139
+ }
140
+ }
141
+ } else {
142
+ // Failed to capture (e.g. timeout) - emit without screenshot
143
+ emitFrameEvent(frameId, threadId, beginTimestamp, endTimestamp, null)
144
+ }
145
+ }
146
+ }
147
+
148
+ private fun emitFrameEvent(
149
+ frameId: Int,
150
+ threadId: Int,
151
+ beginTimestamp: Long,
152
+ endTimestamp: Long,
153
+ screenshot: ByteArray?,
154
+ ) {
155
+ CoroutineScope(Dispatchers.Default).launch {
156
+ onFrameTimingSequence(
157
+ FrameTimingSequence(frameId, threadId, beginTimestamp, endTimestamp, screenshot)
158
+ )
159
+ }
160
+ }
161
+
162
+ private fun encodeFrame(frameData: FrameData) {
163
+ CoroutineScope(encodingDispatcher).launch {
164
+ try {
165
+ val screenshot = encodeScreenshot(frameData.bitmap)
166
+ emitFrameEvent(
167
+ frameData.frameId,
168
+ frameData.threadId,
169
+ frameData.beginTimestamp,
170
+ frameData.endTimestamp,
171
+ screenshot,
172
+ )
173
+ } finally {
174
+ frameData.bitmap.recycle()
175
+ }
176
+
177
+ // Clear encoding flag early, allowing new frames to start fresh encoding sessions
178
+ encodingInProgress.set(false)
179
+
180
+ // Opportunistically encode tail frame (if present) without blocking new frames
181
+ val tailFrame = lastFrameBuffer.getAndSet(null)
182
+ if (tailFrame != null) {
183
+ try {
184
+ val screenshot = encodeScreenshot(tailFrame.bitmap)
185
+ emitFrameEvent(
186
+ tailFrame.frameId,
187
+ tailFrame.threadId,
188
+ tailFrame.beginTimestamp,
189
+ tailFrame.endTimestamp,
190
+ screenshot,
191
+ )
192
+ } finally {
193
+ tailFrame.bitmap.recycle()
194
+ }
195
+ }
196
+ }
197
+ }
198
+
199
+ // Must be called from the main thread so that PixelCopy captures the current frame.
200
+ private fun captureScreenshot(
201
+ frameId: Int,
202
+ threadId: Int,
203
+ beginTimestamp: Long,
204
+ endTimestamp: Long,
205
+ callback: (FrameData?) -> Unit,
206
+ ) {
207
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
208
+ // PixelCopy not available
209
+ callback(null)
210
+ return
211
+ }
212
+
213
+ val window = currentWindow
214
+ if (window == null) {
215
+ // No window
216
+ callback(null)
217
+ return
218
+ }
219
+
220
+ val decorView = window.decorView
221
+ val width = decorView.width
222
+ val height = decorView.height
223
+ val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
224
+
225
+ PixelCopy.request(
226
+ window,
227
+ bitmap,
228
+ { copyResult ->
229
+ if (copyResult == PixelCopy.SUCCESS) {
230
+ callback(FrameData(bitmap, frameId, threadId, beginTimestamp, endTimestamp))
231
+ } else {
232
+ bitmap.recycle()
233
+ callback(null)
234
+ }
235
+ },
236
+ mainHandler,
237
+ )
238
+ }
239
+
240
+ private fun encodeScreenshot(bitmap: Bitmap): ByteArray? {
241
+ var scaledBitmap: Bitmap? = null
242
+ return try {
243
+ val window = currentWindow ?: return null
244
+ val width = bitmap.width
245
+ val height = bitmap.height
246
+ val density = window.context.resources.displayMetrics.density
247
+ val scaledWidth = (width / density * SCREENSHOT_SCALE_FACTOR).toInt()
248
+ val scaledHeight = (height / density * SCREENSHOT_SCALE_FACTOR).toInt()
249
+ scaledBitmap = Bitmap.createScaledBitmap(bitmap, scaledWidth, scaledHeight, true)
250
+
251
+ val compressFormat =
252
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) Bitmap.CompressFormat.WEBP_LOSSY
253
+ else Bitmap.CompressFormat.JPEG
254
+
255
+ ByteArrayOutputStream(SCREENSHOT_OUTPUT_SIZE_HINT).use { outputStream ->
256
+ scaledBitmap.compress(compressFormat, SCREENSHOT_QUALITY, outputStream)
257
+ outputStream.toByteArray()
258
+ }
259
+ } catch (e: Exception) {
260
+ null
261
+ } finally {
262
+ scaledBitmap?.recycle()
263
+ }
264
+ }
265
+
266
+ companion object {
267
+ private const val SCREENSHOT_SCALE_FACTOR = 1.0f
268
+ private const val SCREENSHOT_QUALITY = 80
269
+
270
+ // Capacity hint for the ByteArrayOutputStream used during bitmap
271
+ // compression. Sized slightly above typical compressed output to minimise
272
+ // internal buffer resizing.
273
+ private const val SCREENSHOT_OUTPUT_SIZE_HINT = 65536 // 64 KB
274
+ }
275
+ }
@@ -0,0 +1,17 @@
1
+ /*
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ package com.facebook.react.devsupport.inspector
9
+
10
+ import com.facebook.proguard.annotations.DoNotStripAny
11
+
12
+ @DoNotStripAny
13
+ internal enum class TracingState {
14
+ DISABLED, // There is no active trace
15
+ ENABLED_IN_BACKGROUND_MODE, // Trace is currently running in background mode
16
+ ENABLED_IN_CDP_MODE, // Trace is currently running in CDP mode
17
+ }
@@ -0,0 +1,15 @@
1
+ /*
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ package com.facebook.react.devsupport.inspector
9
+
10
+ import com.facebook.proguard.annotations.DoNotStripAny
11
+
12
+ @DoNotStripAny
13
+ internal fun interface TracingStateListener {
14
+ public fun onStateChanged(state: TracingState, screenshotsEnabled: Boolean)
15
+ }
@@ -5,7 +5,7 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
 
8
- package com.facebook.react.devsupport.interfaces
8
+ package com.facebook.react.devsupport.inspector
9
9
 
10
10
  internal interface TracingStateProvider {
11
11
  fun getTracingState(): TracingState
@@ -7,7 +7,7 @@
7
7
 
8
8
  package com.facebook.react.devsupport.perfmonitor
9
9
 
10
- import com.facebook.react.devsupport.interfaces.TracingState
10
+ import com.facebook.react.devsupport.inspector.TracingState
11
11
 
12
12
  /**
13
13
  * [Experimental] Interface implemented by [com.facebook.react.runtime.ReactHostInspectorTarget]
@@ -8,7 +8,7 @@
8
8
  package com.facebook.react.devsupport.perfmonitor
9
9
 
10
10
  import com.facebook.react.bridge.UiThreadUtil
11
- import com.facebook.react.devsupport.interfaces.TracingState
11
+ import com.facebook.react.devsupport.inspector.TracingState
12
12
 
13
13
  internal class PerfMonitorOverlayManager(
14
14
  private val devHelper: PerfMonitorDevHelper,
@@ -21,7 +21,7 @@ internal class PerfMonitorOverlayManager(
21
21
  get() = enabled
22
22
 
23
23
  private var view: PerfMonitorOverlayView? = null
24
- private var tracingState: TracingState = TracingState.ENABLEDINCDPMODE
24
+ private var tracingState: TracingState = TracingState.ENABLED_IN_CDP_MODE
25
25
  private var perfIssueCount: Int = 0
26
26
 
27
27
  /** Enable the Perf Monitor overlay. */
@@ -92,7 +92,7 @@ internal class PerfMonitorOverlayManager(
92
92
 
93
93
  private fun handleRecordingButtonPress() {
94
94
  when (tracingState) {
95
- TracingState.ENABLEDINBACKGROUNDMODE -> {
95
+ TracingState.ENABLED_IN_BACKGROUND_MODE -> {
96
96
  devHelper.inspectorTarget?.let { target ->
97
97
  if (!target.pauseAndAnalyzeBackgroundTrace()) {
98
98
  onRequestOpenDevTools()
@@ -102,7 +102,7 @@ internal class PerfMonitorOverlayManager(
102
102
  TracingState.DISABLED -> {
103
103
  devHelper.inspectorTarget?.resumeBackgroundTrace()
104
104
  }
105
- TracingState.ENABLEDINCDPMODE -> Unit
105
+ TracingState.ENABLED_IN_CDP_MODE -> Unit
106
106
  }
107
107
  }
108
108
  }
@@ -21,7 +21,7 @@ import android.widget.TextView
21
21
  import androidx.core.view.ViewCompat
22
22
  import androidx.core.view.WindowInsetsCompat
23
23
  import com.facebook.react.R
24
- import com.facebook.react.devsupport.interfaces.TracingState
24
+ import com.facebook.react.devsupport.inspector.TracingState
25
25
  import com.facebook.react.uimanager.DisplayMetricsHolder
26
26
  import com.facebook.react.uimanager.PixelUtil
27
27
 
@@ -50,12 +50,12 @@ internal class PerfMonitorOverlayView(
50
50
  }
51
51
 
52
52
  fun updateRecordingState(state: TracingState) {
53
- if (state == TracingState.ENABLEDINCDPMODE) {
53
+ if (state == TracingState.ENABLED_IN_CDP_MODE) {
54
54
  dialog.hide()
55
55
  return
56
56
  }
57
57
 
58
- if (state == TracingState.ENABLEDINBACKGROUNDMODE) {
58
+ if (state == TracingState.ENABLED_IN_BACKGROUND_MODE) {
59
59
  (statusIndicator.background as GradientDrawable).setColor(Color.RED)
60
60
  statusLabel.text = "Profiling Active"
61
61
  tooltipLabel.text =
@@ -7,7 +7,7 @@
7
7
 
8
8
  package com.facebook.react.devsupport.perfmonitor
9
9
 
10
- import com.facebook.react.devsupport.interfaces.TracingState
10
+ import com.facebook.react.devsupport.inspector.TracingState
11
11
 
12
12
  /** [Experimental] An interface for subscribing to updates for the V2 Perf Monitor. */
13
13
  internal interface PerfMonitorUpdateListener {
@@ -4,7 +4,7 @@
4
4
  * This source code is licensed under the MIT license found in the
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  *
7
- * @generated SignedSource<<f350f756268554418a046d0793ee0146>>
7
+ * @generated SignedSource<<a92c35b9527c3954516ee68db651afa7>>
8
8
  */
9
9
 
10
10
  /**
@@ -372,12 +372,24 @@ public object ReactNativeFeatureFlags {
372
372
  @JvmStatic
373
373
  public fun fuseboxEnabledRelease(): Boolean = accessor.fuseboxEnabledRelease()
374
374
 
375
+ /**
376
+ * Enable frame timings and screenshots support in the React Native DevTools CDP backend. This flag is global and should not be changed across React Host lifetimes.
377
+ */
378
+ @JvmStatic
379
+ public fun fuseboxFrameRecordingEnabled(): Boolean = accessor.fuseboxFrameRecordingEnabled()
380
+
375
381
  /**
376
382
  * Enable network inspection support in the React Native DevTools CDP backend. Requires `enableBridgelessArchitecture`. This flag is global and should not be changed across React Host lifetimes.
377
383
  */
378
384
  @JvmStatic
379
385
  public fun fuseboxNetworkInspectionEnabled(): Boolean = accessor.fuseboxNetworkInspectionEnabled()
380
386
 
387
+ /**
388
+ * Enable Page.captureScreenshot CDP method support in the React Native DevTools CDP backend. This flag is global and should not be changed across React Host lifetimes.
389
+ */
390
+ @JvmStatic
391
+ public fun fuseboxScreenshotCaptureEnabled(): Boolean = accessor.fuseboxScreenshotCaptureEnabled()
392
+
381
393
  /**
382
394
  * Hides offscreen VirtualViews on iOS by setting hidden = YES to avoid extra cost of views
383
395
  */
@@ -4,7 +4,7 @@
4
4
  * This source code is licensed under the MIT license found in the
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  *
7
- * @generated SignedSource<<c9a6711220ca600dacaed5754df5caab>>
7
+ * @generated SignedSource<<a9ec10139cccac681fb73d8155377b02>>
8
8
  */
9
9
 
10
10
  /**
@@ -77,7 +77,9 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
77
77
  private var fixMappingOfEventPrioritiesBetweenFabricAndReactCache: Boolean? = null
78
78
  private var fuseboxAssertSingleHostStateCache: Boolean? = null
79
79
  private var fuseboxEnabledReleaseCache: Boolean? = null
80
+ private var fuseboxFrameRecordingEnabledCache: Boolean? = null
80
81
  private var fuseboxNetworkInspectionEnabledCache: Boolean? = null
82
+ private var fuseboxScreenshotCaptureEnabledCache: Boolean? = null
81
83
  private var hideOffscreenVirtualViewsOnIOSCache: Boolean? = null
82
84
  private var overrideBySynchronousMountPropsAtMountingAndroidCache: Boolean? = null
83
85
  private var perfIssuesEnabledCache: Boolean? = null
@@ -619,6 +621,15 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
619
621
  return cached
620
622
  }
621
623
 
624
+ override fun fuseboxFrameRecordingEnabled(): Boolean {
625
+ var cached = fuseboxFrameRecordingEnabledCache
626
+ if (cached == null) {
627
+ cached = ReactNativeFeatureFlagsCxxInterop.fuseboxFrameRecordingEnabled()
628
+ fuseboxFrameRecordingEnabledCache = cached
629
+ }
630
+ return cached
631
+ }
632
+
622
633
  override fun fuseboxNetworkInspectionEnabled(): Boolean {
623
634
  var cached = fuseboxNetworkInspectionEnabledCache
624
635
  if (cached == null) {
@@ -628,6 +639,15 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
628
639
  return cached
629
640
  }
630
641
 
642
+ override fun fuseboxScreenshotCaptureEnabled(): Boolean {
643
+ var cached = fuseboxScreenshotCaptureEnabledCache
644
+ if (cached == null) {
645
+ cached = ReactNativeFeatureFlagsCxxInterop.fuseboxScreenshotCaptureEnabled()
646
+ fuseboxScreenshotCaptureEnabledCache = cached
647
+ }
648
+ return cached
649
+ }
650
+
631
651
  override fun hideOffscreenVirtualViewsOnIOS(): Boolean {
632
652
  var cached = hideOffscreenVirtualViewsOnIOSCache
633
653
  if (cached == null) {
@@ -4,7 +4,7 @@
4
4
  * This source code is licensed under the MIT license found in the
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  *
7
- * @generated SignedSource<<d936abca211ad153f40c44187a1f8867>>
7
+ * @generated SignedSource<<ceb1cf55a1d6b6d71ad27ec7f8594b50>>
8
8
  */
9
9
 
10
10
  /**
@@ -142,8 +142,12 @@ public object ReactNativeFeatureFlagsCxxInterop {
142
142
 
143
143
  @DoNotStrip @JvmStatic public external fun fuseboxEnabledRelease(): Boolean
144
144
 
145
+ @DoNotStrip @JvmStatic public external fun fuseboxFrameRecordingEnabled(): Boolean
146
+
145
147
  @DoNotStrip @JvmStatic public external fun fuseboxNetworkInspectionEnabled(): Boolean
146
148
 
149
+ @DoNotStrip @JvmStatic public external fun fuseboxScreenshotCaptureEnabled(): Boolean
150
+
147
151
  @DoNotStrip @JvmStatic public external fun hideOffscreenVirtualViewsOnIOS(): Boolean
148
152
 
149
153
  @DoNotStrip @JvmStatic public external fun overrideBySynchronousMountPropsAtMountingAndroid(): Boolean
@@ -4,7 +4,7 @@
4
4
  * This source code is licensed under the MIT license found in the
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  *
7
- * @generated SignedSource<<303c55a883b4798288716d168ce82d06>>
7
+ * @generated SignedSource<<fd1d27cb393bb274b44db0bcec73c7f8>>
8
8
  */
9
9
 
10
10
  /**
@@ -137,8 +137,12 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi
137
137
 
138
138
  override fun fuseboxEnabledRelease(): Boolean = false
139
139
 
140
+ override fun fuseboxFrameRecordingEnabled(): Boolean = false
141
+
140
142
  override fun fuseboxNetworkInspectionEnabled(): Boolean = true
141
143
 
144
+ override fun fuseboxScreenshotCaptureEnabled(): Boolean = false
145
+
142
146
  override fun hideOffscreenVirtualViewsOnIOS(): Boolean = false
143
147
 
144
148
  override fun overrideBySynchronousMountPropsAtMountingAndroid(): Boolean = false
@@ -4,7 +4,7 @@
4
4
  * This source code is licensed under the MIT license found in the
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  *
7
- * @generated SignedSource<<98eb8f2d7036cf8a3023a8c560375f6a>>
7
+ * @generated SignedSource<<38e86d50298e5c4199d456f709ac13fc>>
8
8
  */
9
9
 
10
10
  /**
@@ -81,7 +81,9 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
81
81
  private var fixMappingOfEventPrioritiesBetweenFabricAndReactCache: Boolean? = null
82
82
  private var fuseboxAssertSingleHostStateCache: Boolean? = null
83
83
  private var fuseboxEnabledReleaseCache: Boolean? = null
84
+ private var fuseboxFrameRecordingEnabledCache: Boolean? = null
84
85
  private var fuseboxNetworkInspectionEnabledCache: Boolean? = null
86
+ private var fuseboxScreenshotCaptureEnabledCache: Boolean? = null
85
87
  private var hideOffscreenVirtualViewsOnIOSCache: Boolean? = null
86
88
  private var overrideBySynchronousMountPropsAtMountingAndroidCache: Boolean? = null
87
89
  private var perfIssuesEnabledCache: Boolean? = null
@@ -680,6 +682,16 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
680
682
  return cached
681
683
  }
682
684
 
685
+ override fun fuseboxFrameRecordingEnabled(): Boolean {
686
+ var cached = fuseboxFrameRecordingEnabledCache
687
+ if (cached == null) {
688
+ cached = currentProvider.fuseboxFrameRecordingEnabled()
689
+ accessedFeatureFlags.add("fuseboxFrameRecordingEnabled")
690
+ fuseboxFrameRecordingEnabledCache = cached
691
+ }
692
+ return cached
693
+ }
694
+
683
695
  override fun fuseboxNetworkInspectionEnabled(): Boolean {
684
696
  var cached = fuseboxNetworkInspectionEnabledCache
685
697
  if (cached == null) {
@@ -690,6 +702,16 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
690
702
  return cached
691
703
  }
692
704
 
705
+ override fun fuseboxScreenshotCaptureEnabled(): Boolean {
706
+ var cached = fuseboxScreenshotCaptureEnabledCache
707
+ if (cached == null) {
708
+ cached = currentProvider.fuseboxScreenshotCaptureEnabled()
709
+ accessedFeatureFlags.add("fuseboxScreenshotCaptureEnabled")
710
+ fuseboxScreenshotCaptureEnabledCache = cached
711
+ }
712
+ return cached
713
+ }
714
+
693
715
  override fun hideOffscreenVirtualViewsOnIOS(): Boolean {
694
716
  var cached = hideOffscreenVirtualViewsOnIOSCache
695
717
  if (cached == null) {
@@ -4,7 +4,7 @@
4
4
  * This source code is licensed under the MIT license found in the
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  *
7
- * @generated SignedSource<<18744192baedc0d5fa0fc7873adf0422>>
7
+ * @generated SignedSource<<eb09ee29f25cd03df2e7c3d2b3def992>>
8
8
  */
9
9
 
10
10
  /**
@@ -137,8 +137,12 @@ public interface ReactNativeFeatureFlagsProvider {
137
137
 
138
138
  @DoNotStrip public fun fuseboxEnabledRelease(): Boolean
139
139
 
140
+ @DoNotStrip public fun fuseboxFrameRecordingEnabled(): Boolean
141
+
140
142
  @DoNotStrip public fun fuseboxNetworkInspectionEnabled(): Boolean
141
143
 
144
+ @DoNotStrip public fun fuseboxScreenshotCaptureEnabled(): Boolean
145
+
142
146
  @DoNotStrip public fun hideOffscreenVirtualViewsOnIOS(): Boolean
143
147
 
144
148
  @DoNotStrip public fun overrideBySynchronousMountPropsAtMountingAndroid(): Boolean
@@ -23,6 +23,45 @@ public object PerformanceTracer {
23
23
  SoLoader.loadLibrary("react_performancetracerjni")
24
24
  }
25
25
 
26
+ public fun <T> trace(name: String, block: () -> T): T {
27
+ return trace(name, null /* track */, null /* trackGroup */, null /* color */, block)
28
+ }
29
+
30
+ public fun <T> trace(name: String, track: String, block: () -> T): T {
31
+ return trace(name, track, null /* trackGroup */, null /* color */, block)
32
+ }
33
+
34
+ public fun <T> trace(name: String, track: String, trackGroup: String, block: () -> T): T {
35
+ return trace(name, track, trackGroup, null /* color */, block)
36
+ }
37
+
38
+ public fun <T> trace(
39
+ name: String,
40
+ track: String?,
41
+ trackGroup: String?,
42
+ color: String?,
43
+ block: () -> T,
44
+ ): T {
45
+ if (!isTracing()) {
46
+ return block()
47
+ }
48
+
49
+ val startTimeNanos = java.lang.System.nanoTime()
50
+ try {
51
+ return block()
52
+ } finally {
53
+ val endTimeNanos = java.lang.System.nanoTime()
54
+ reportTimeStamp(
55
+ name,
56
+ startTimeNanos,
57
+ endTimeNanos,
58
+ track,
59
+ trackGroup,
60
+ color,
61
+ )
62
+ }
63
+ }
64
+
26
65
  /** Callback interface for tracing state changes. */
27
66
  @DoNotStrip
28
67
  public interface TracingStateCallback {
@@ -63,7 +63,7 @@ public class BlobModule(reactContext: ReactApplicationContext) :
63
63
  }
64
64
  }
65
65
 
66
- private val networkingUriHandler =
66
+ internal val networkingUriHandler =
67
67
  object : NetworkingModule.UriHandler {
68
68
  override fun supports(uri: Uri, responseType: String): Boolean {
69
69
  val scheme = uri.scheme