react-native-tvos 0.85.2-0 → 0.85.3-0

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 (110) hide show
  1. package/Libraries/Core/ReactNativeVersion.js +1 -1
  2. package/Libraries/Utilities/HMRClient.js +28 -1
  3. package/React/Base/RCTVersion.m +1 -1
  4. package/React/CoreModules/RCTJscSafeUrl+Internal.h +23 -0
  5. package/React/CoreModules/RCTJscSafeUrl.mm +38 -0
  6. package/React/CoreModules/RCTRedBox+Internal.h +42 -0
  7. package/React/CoreModules/RCTRedBox.mm +30 -471
  8. package/React/CoreModules/RCTRedBox2AnsiParser+Internal.h +22 -0
  9. package/React/CoreModules/RCTRedBox2AnsiParser.mm +55 -0
  10. package/React/CoreModules/RCTRedBox2Controller+Internal.h +34 -0
  11. package/React/CoreModules/RCTRedBox2Controller.mm +764 -0
  12. package/React/CoreModules/RCTRedBox2ErrorParser+Internal.h +46 -0
  13. package/React/CoreModules/RCTRedBox2ErrorParser.mm +57 -0
  14. package/React/CoreModules/RCTRedBoxController+Internal.h +31 -0
  15. package/React/CoreModules/RCTRedBoxController.mm +447 -0
  16. package/React/CoreModules/RCTRedBoxHMRClient+Internal.h +26 -0
  17. package/React/CoreModules/RCTRedBoxHMRClient.mm +125 -0
  18. package/React/CoreModules/React-CoreModules.podspec +1 -0
  19. package/React/DevSupport/RCTFrameTimingsObserver.h +24 -0
  20. package/React/DevSupport/RCTFrameTimingsObserver.mm +298 -0
  21. package/React/FBReactNativeSpec/FBReactNativeSpecJSI.h +40 -0
  22. package/ReactAndroid/gradle.properties +1 -1
  23. package/ReactAndroid/hermes-engine/build.gradle.kts +17 -0
  24. package/ReactAndroid/publish.gradle +20 -46
  25. package/ReactAndroid/src/main/java/com/facebook/react/devsupport/InspectorFlags.kt +4 -0
  26. package/ReactAndroid/src/main/java/com/facebook/react/devsupport/inspector/FrameTimingSequence.kt +1 -1
  27. package/ReactAndroid/src/main/java/com/facebook/react/devsupport/inspector/FrameTimingsObserver.kt +127 -26
  28. package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt +31 -1
  29. package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt +51 -1
  30. package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt +11 -1
  31. package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt +11 -1
  32. package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt +56 -1
  33. package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt +11 -1
  34. package/ReactAndroid/src/main/java/com/facebook/react/internal/tracing/PerformanceTracer.kt +39 -0
  35. package/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.kt +1 -1
  36. package/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.kt +50 -10
  37. package/ReactAndroid/src/main/jni/CMakeLists.txt +7 -0
  38. package/ReactAndroid/src/main/jni/react/devsupport/JInspectorFlags.cpp +22 -0
  39. package/ReactAndroid/src/main/jni/react/devsupport/JInspectorFlags.h +2 -0
  40. package/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp +71 -1
  41. package/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h +16 -1
  42. package/ReactAndroid/src/main/jni/react/runtime/jni/JReactHostInspectorTarget.cpp +14 -0
  43. package/ReactAndroid/src/main/jni/react/runtime/jni/JReactHostInspectorTarget.h +18 -4
  44. package/ReactCommon/React-Fabric.podspec +6 -0
  45. package/ReactCommon/cxxreact/ReactNativeVersion.h +2 -2
  46. package/ReactCommon/jsinspector-modern/HostAgent.cpp +36 -0
  47. package/ReactCommon/jsinspector-modern/HostTarget.cpp +7 -1
  48. package/ReactCommon/jsinspector-modern/HostTarget.h +25 -0
  49. package/ReactCommon/jsinspector-modern/HostTargetTracing.cpp +1 -1
  50. package/ReactCommon/jsinspector-modern/HostTargetTracing.h +4 -4
  51. package/ReactCommon/jsinspector-modern/InspectorFlags.cpp +12 -0
  52. package/ReactCommon/jsinspector-modern/InspectorFlags.h +12 -0
  53. package/ReactCommon/jsinspector-modern/NetworkIOAgent.cpp +1 -1
  54. package/ReactCommon/jsinspector-modern/RuntimeAgent.cpp +19 -0
  55. package/ReactCommon/jsinspector-modern/RuntimeAgent.h +7 -0
  56. package/ReactCommon/jsinspector-modern/RuntimeTarget.cpp +33 -0
  57. package/ReactCommon/jsinspector-modern/RuntimeTarget.h +6 -0
  58. package/ReactCommon/jsinspector-modern/tests/HostTargetTest.cpp +12 -0
  59. package/ReactCommon/jsinspector-modern/tests/InspectorMocks.h +3 -2
  60. package/ReactCommon/jsinspector-modern/tests/JsiIntegrationTest.cpp +1 -0
  61. package/ReactCommon/jsinspector-modern/tests/NetworkReporterTest.cpp +1 -1
  62. package/ReactCommon/jsinspector-modern/tests/TracingTest.cpp +1 -1
  63. package/ReactCommon/jsinspector-modern/tests/utils/InspectorFlagOverridesGuard.cpp +10 -0
  64. package/ReactCommon/jsinspector-modern/tests/utils/InspectorFlagOverridesGuard.h +3 -1
  65. package/ReactCommon/jsinspector-modern/tracing/CMakeLists.txt +1 -0
  66. package/ReactCommon/jsinspector-modern/tracing/FrameTimingSequence.h +7 -3
  67. package/ReactCommon/jsinspector-modern/tracing/HostTracingProfileSerializer.cpp +52 -29
  68. package/ReactCommon/jsinspector-modern/tracing/HostTracingProfileSerializer.h +6 -6
  69. package/ReactCommon/jsinspector-modern/tracing/PerformanceTracerSection.h +113 -0
  70. package/ReactCommon/jsinspector-modern/tracing/React-jsinspectortracing.podspec +1 -0
  71. package/ReactCommon/jsinspector-modern/tracing/TraceEventGenerator.cpp +12 -5
  72. package/ReactCommon/jsinspector-modern/tracing/TraceEventGenerator.h +3 -1
  73. package/ReactCommon/jsinspector-modern/tracing/TraceEventSerializer.cpp +42 -0
  74. package/ReactCommon/jsinspector-modern/tracing/TraceEventSerializer.h +7 -0
  75. package/ReactCommon/react/debug/CMakeLists.txt +2 -1
  76. package/ReactCommon/react/debug/React-debug.podspec +7 -1
  77. package/ReactCommon/react/debug/redbox/AnsiParser.cpp +139 -0
  78. package/ReactCommon/react/debug/redbox/AnsiParser.h +35 -0
  79. package/ReactCommon/react/debug/redbox/JscSafeUrl.cpp +179 -0
  80. package/ReactCommon/react/debug/redbox/JscSafeUrl.h +27 -0
  81. package/ReactCommon/react/debug/redbox/RedBoxErrorParser.cpp +171 -0
  82. package/ReactCommon/react/debug/redbox/RedBoxErrorParser.h +40 -0
  83. package/ReactCommon/react/debug/redbox/tests/AnsiParserTest.cpp +97 -0
  84. package/ReactCommon/react/debug/redbox/tests/JscSafeUrlTest.cpp +173 -0
  85. package/ReactCommon/react/debug/redbox/tests/RedBoxErrorParserTest.cpp +107 -0
  86. package/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp +21 -1
  87. package/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h +26 -1
  88. package/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp +135 -45
  89. package/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h +12 -2
  90. package/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h +21 -1
  91. package/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDynamicProvider.h +46 -1
  92. package/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h +6 -1
  93. package/ReactCommon/react/nativemodule/defaults/CMakeLists.txt +1 -0
  94. package/ReactCommon/react/nativemodule/defaults/DefaultTurboModules.cpp +7 -0
  95. package/ReactCommon/react/nativemodule/defaults/React-defaultsnativemodule.podspec +1 -0
  96. package/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp +26 -1
  97. package/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h +11 -1
  98. package/ReactCommon/react/nativemodule/mutationobserver/NativeMutationObserver.h +4 -0
  99. package/ReactCommon/react/nativemodule/mutationobserver/React-mutationobservernativemodule.podspec +66 -0
  100. package/ReactCommon/react/performance/timeline/PerformanceObserver.cpp +18 -6
  101. package/ReactCommon/react/performance/timeline/PerformanceObserver.h +2 -0
  102. package/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTHost.mm +115 -0
  103. package/ReactCommon/{jsinspector-modern → react/utils}/Base64.h +2 -2
  104. package/package.json +11 -11
  105. package/scripts/cocoapods/utils.rb +1 -0
  106. package/scripts/react_native_pods.rb +1 -0
  107. package/scripts/replace-rncore-version.js +72 -15
  108. package/src/private/featureflags/ReactNativeFeatureFlags.js +26 -1
  109. package/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js +6 -1
  110. package/src/private/setup/setUpDefaultReactNativeEnvironment.js +6 -0
@@ -3,25 +3,17 @@
3
3
  *
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
- *
7
- * This file is modified from the original Meta source to work in the
8
- * `react-native-ci` project.
9
6
  */
10
- /* groovylint-disable CompileStatic, DuplicateStringLiteral, LineLength, NestedBlockDepth, NoDef, UnusedVariable, VariableTypeRequired */
11
7
 
12
8
  apply plugin: 'maven-publish'
13
9
  apply plugin: 'signing'
14
10
 
15
- def isSnapshot = false
16
- // Rewritten when copying this to ReactAndroid/publish.gradle
17
- def signingKey = findProperty('SIGNING_KEY')
18
- def signingPwd = findProperty('SIGNING_PWD')
19
- def sonatypeUsername = findProperty('SONATYPE_USERNAME')
20
- def sonatypePassword = findProperty('SONATYPE_PASSWORD')
11
+ def isSnapshot = findProperty("isSnapshot")?.toBoolean()
12
+ def signingKey = findProperty("SIGNING_KEY")
13
+ def signingPwd = findProperty("SIGNING_PWD")
21
14
 
22
15
  def reactAndroidProjectDir = project(':packages:react-native:ReactAndroid').projectDir
23
- def mavenTempLocalUrl = 'file:///home/expo/workingdir/build/maven-local'
24
- // Rewritten when copying this to ReactAndroid/publish.gradle
16
+ def mavenTempLocalUrl = "file:///tmp/maven-local"
25
17
 
26
18
  publishing {
27
19
  publications {
@@ -29,7 +21,7 @@ publishing {
29
21
  afterEvaluate {
30
22
  // We do a multi variant release, so for Android libraries
31
23
  // we publish `components.release`
32
- if (plugins.hasPlugin('com.android.library')) {
24
+ if (plugins.hasPlugin("com.android.library")) {
33
25
  from components.default
34
26
  }
35
27
  }
@@ -37,35 +29,35 @@ publishing {
37
29
  // We populate the publishing version using the project version,
38
30
  // appending -SNAPSHOT if on nightly or prerelase.
39
31
  if (isSnapshot) {
40
- version = this.version + '-SNAPSHOT'
32
+ version = this.version + "-SNAPSHOT"
41
33
  } else {
42
34
  version = this.version
43
35
  }
44
36
 
45
37
  pom {
46
- name = 'react-native'
47
- description = 'A framework for building native apps with React'
48
- url = 'https://github.com/facebook/react-native'
38
+ name = "react-native"
39
+ description = "A framework for building native apps with React"
40
+ url = "https://github.com/facebook/react-native"
49
41
 
50
42
  developers {
51
43
  developer {
52
- id = 'facebook'
53
- name = 'Facebook'
44
+ id = "facebook"
45
+ name = "Facebook"
54
46
  }
55
47
  }
56
48
 
57
49
  licenses {
58
50
  license {
59
- name = 'MIT License'
60
- url = 'https://github.com/facebook/react-native/blob/HEAD/LICENSE'
61
- distribution = 'repo'
51
+ name = "MIT License"
52
+ url = "https://github.com/facebook/react-native/blob/HEAD/LICENSE"
53
+ distribution = "repo"
62
54
  }
63
55
  }
64
56
 
65
57
  scm {
66
- url = 'https://github.com/facebook/react-native.git'
67
- connection = 'scm:git:https://github.com/facebook/react-native.git'
68
- developerConnection = 'scm:git:git@github.com:facebook/react-native.git'
58
+ url = "https://github.com/facebook/react-native.git"
59
+ connection = "scm:git:https://github.com/facebook/react-native.git"
60
+ developerConnection = "scm:git:git@github.com:facebook/react-native.git"
69
61
  }
70
62
  }
71
63
  }
@@ -73,36 +65,18 @@ publishing {
73
65
 
74
66
  repositories {
75
67
  maven {
76
- name = 'mavenTempLocal'
68
+ name = "mavenTempLocal"
77
69
  url = mavenTempLocalUrl
78
70
  }
79
- maven {
80
- name = 'sonatypeRelease'
81
- url = 'https://ossrh-staging-api.central.sonatype.com/service/local/staging/deploy/maven2/'
82
- // url = 'https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/'
83
- credentials(PasswordCredentials) {
84
- username = sonatypeUsername
85
- password = sonatypePassword
86
- }
87
- }
88
- maven {
89
- name = 'sonatypeSnapshot'
90
- url = 'https://central.sonatype.com/repository/maven-snapshots/'
91
- // url = 'https://s01.oss.sonatype.org/content/repositories/snapshots/'
92
- credentials(PasswordCredentials) {
93
- username = sonatypeUsername
94
- password = sonatypePassword
95
- }
96
- }
97
71
  }
98
72
 
99
73
  if (signingKey && signingPwd) {
100
- logger.info('PGP Key found - Signing enabled')
74
+ logger.info("PGP Key found - Signing enabled")
101
75
  signing {
102
76
  useInMemoryPgpKeys(signingKey, signingPwd)
103
77
  sign(publishing.publications.release)
104
78
  }
105
79
  } else {
106
- logger.info('Signing disabled as the PGP key was not found')
80
+ logger.info("Signing disabled as the PGP key was not found")
107
81
  }
108
82
  }
@@ -17,7 +17,11 @@ internal object InspectorFlags {
17
17
  SoLoader.loadLibrary("react_devsupportjni")
18
18
  }
19
19
 
20
+ @DoNotStrip @JvmStatic external fun getScreenshotCaptureEnabled(): Boolean
21
+
20
22
  @DoNotStrip @JvmStatic external fun getFuseboxEnabled(): Boolean
21
23
 
22
24
  @DoNotStrip @JvmStatic external fun getIsProfilingBuild(): Boolean
25
+
26
+ @DoNotStrip @JvmStatic external fun getFrameRecordingEnabled(): Boolean
23
27
  }
@@ -12,5 +12,5 @@ internal data class FrameTimingSequence(
12
12
  val threadId: Int,
13
13
  val beginTimestamp: Long,
14
14
  val endTimestamp: Long,
15
- val screenshot: String? = null,
15
+ val screenshot: ByteArray? = null,
16
16
  )
@@ -12,14 +12,18 @@ import android.os.Build
12
12
  import android.os.Handler
13
13
  import android.os.Looper
14
14
  import android.os.Process
15
- import android.util.Base64
16
15
  import android.view.FrameMetrics
17
16
  import android.view.PixelCopy
18
17
  import android.view.Window
19
18
  import com.facebook.proguard.annotations.DoNotStripAny
20
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
21
24
  import kotlinx.coroutines.CoroutineScope
22
25
  import kotlinx.coroutines.Dispatchers
26
+ import kotlinx.coroutines.asCoroutineDispatcher
23
27
  import kotlinx.coroutines.launch
24
28
 
25
29
  @DoNotStripAny
@@ -30,20 +34,39 @@ internal class FrameTimingsObserver(
30
34
  private val isSupported = Build.VERSION.SDK_INT >= Build.VERSION_CODES.N
31
35
  private val mainHandler = Handler(Looper.getMainLooper())
32
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
+
33
46
  private var frameCounter: Int = 0
47
+ private val encodingInProgress = AtomicBoolean(false)
34
48
  @Volatile private var isTracing: Boolean = false
35
49
  @Volatile private var currentWindow: Window? = null
36
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
+
37
59
  fun start() {
38
60
  if (!isSupported) {
39
61
  return
40
62
  }
41
63
 
42
64
  frameCounter = 0
65
+ encodingInProgress.set(false)
66
+ lastFrameBuffer.set(null)
43
67
  isTracing = true
44
68
 
45
- // Capture initial screenshot to ensure there's always at least one frame
46
- // recorded at the start of tracing, even if no UI changes occur
69
+ // Emit initial frame event
47
70
  val timestamp = System.nanoTime()
48
71
  emitFrameTiming(timestamp, timestamp)
49
72
 
@@ -59,6 +82,7 @@ internal class FrameTimingsObserver(
59
82
 
60
83
  currentWindow?.removeOnFrameMetricsAvailableListener(frameMetricsListener)
61
84
  mainHandler.removeCallbacksAndMessages(null)
85
+ lastFrameBuffer.getAndSet(null)?.bitmap?.recycle()
62
86
  }
63
87
 
64
88
  fun setCurrentWindow(window: Window?) {
@@ -75,8 +99,7 @@ internal class FrameTimingsObserver(
75
99
 
76
100
  private val frameMetricsListener =
77
101
  Window.OnFrameMetricsAvailableListener { _, frameMetrics, _ ->
78
- // Guard against calls arriving after stop() has ended tracing. Async work scheduled from
79
- // previous frames will still finish.
102
+ // Guard against calls after stop()
80
103
  if (!isTracing) {
81
104
  return@OnFrameMetricsAvailableListener
82
105
  }
@@ -89,34 +112,107 @@ internal class FrameTimingsObserver(
89
112
  val frameId = frameCounter++
90
113
  val threadId = Process.myTid()
91
114
 
92
- if (screenshotsEnabled) {
93
- // Initiate PixelCopy immediately on the main thread, while still in the current frame,
94
- // then process and emit asynchronously once the copy is complete.
95
- captureScreenshot { screenshot ->
96
- CoroutineScope(Dispatchers.Default).launch {
97
- onFrameTimingSequence(
98
- FrameTimingSequence(frameId, threadId, beginTimestamp, endTimestamp, screenshot)
99
- )
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
+ }
100
140
  }
141
+ } else {
142
+ // Failed to capture (e.g. timeout) - emit without screenshot
143
+ emitFrameEvent(frameId, threadId, beginTimestamp, endTimestamp, null)
101
144
  }
102
- } else {
103
- CoroutineScope(Dispatchers.Default).launch {
104
- onFrameTimingSequence(
105
- FrameTimingSequence(frameId, threadId, beginTimestamp, endTimestamp, null)
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,
106
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
+ }
107
195
  }
108
196
  }
109
197
  }
110
198
 
111
199
  // Must be called from the main thread so that PixelCopy captures the current frame.
112
- private fun captureScreenshot(callback: (String?) -> Unit) {
200
+ private fun captureScreenshot(
201
+ frameId: Int,
202
+ threadId: Int,
203
+ beginTimestamp: Long,
204
+ endTimestamp: Long,
205
+ callback: (FrameData?) -> Unit,
206
+ ) {
113
207
  if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
208
+ // PixelCopy not available
114
209
  callback(null)
115
210
  return
116
211
  }
117
212
 
118
213
  val window = currentWindow
119
214
  if (window == null) {
215
+ // No window
120
216
  callback(null)
121
217
  return
122
218
  }
@@ -131,9 +227,7 @@ internal class FrameTimingsObserver(
131
227
  bitmap,
132
228
  { copyResult ->
133
229
  if (copyResult == PixelCopy.SUCCESS) {
134
- CoroutineScope(Dispatchers.Default).launch {
135
- callback(encodeScreenshot(window, bitmap, width, height))
136
- }
230
+ callback(FrameData(bitmap, frameId, threadId, beginTimestamp, endTimestamp))
137
231
  } else {
138
232
  bitmap.recycle()
139
233
  callback(null)
@@ -143,9 +237,12 @@ internal class FrameTimingsObserver(
143
237
  )
144
238
  }
145
239
 
146
- private fun encodeScreenshot(window: Window, bitmap: Bitmap, width: Int, height: Int): String? {
240
+ private fun encodeScreenshot(bitmap: Bitmap): ByteArray? {
147
241
  var scaledBitmap: Bitmap? = null
148
242
  return try {
243
+ val window = currentWindow ?: return null
244
+ val width = bitmap.width
245
+ val height = bitmap.height
149
246
  val density = window.context.resources.displayMetrics.density
150
247
  val scaledWidth = (width / density * SCREENSHOT_SCALE_FACTOR).toInt()
151
248
  val scaledHeight = (height / density * SCREENSHOT_SCALE_FACTOR).toInt()
@@ -155,20 +252,24 @@ internal class FrameTimingsObserver(
155
252
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) Bitmap.CompressFormat.WEBP_LOSSY
156
253
  else Bitmap.CompressFormat.JPEG
157
254
 
158
- ByteArrayOutputStream().use { outputStream ->
255
+ ByteArrayOutputStream(SCREENSHOT_OUTPUT_SIZE_HINT).use { outputStream ->
159
256
  scaledBitmap.compress(compressFormat, SCREENSHOT_QUALITY, outputStream)
160
- Base64.encodeToString(outputStream.toByteArray(), Base64.NO_WRAP)
257
+ outputStream.toByteArray()
161
258
  }
162
259
  } catch (e: Exception) {
163
260
  null
164
261
  } finally {
165
262
  scaledBitmap?.recycle()
166
- bitmap.recycle()
167
263
  }
168
264
  }
169
265
 
170
266
  companion object {
171
- private const val SCREENSHOT_SCALE_FACTOR = 0.75f
267
+ private const val SCREENSHOT_SCALE_FACTOR = 1.0f
172
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
173
274
  }
174
275
  }
@@ -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<<156d4f5f35037184b6fc61ff1d856028>>
7
+ * @generated SignedSource<<dcedc4c1eba9ea605d96850aebecaf06>>
8
8
  */
9
9
 
10
10
  /**
@@ -276,6 +276,12 @@ public object ReactNativeFeatureFlags {
276
276
  @JvmStatic
277
277
  public fun enableModuleArgumentNSNullConversionIOS(): Boolean = accessor.enableModuleArgumentNSNullConversionIOS()
278
278
 
279
+ /**
280
+ * Enables the MutationObserver Web API in React Native.
281
+ */
282
+ @JvmStatic
283
+ public fun enableMutationObserverByDefault(): Boolean = accessor.enableMutationObserverByDefault()
284
+
279
285
  /**
280
286
  * Parse CSS strings using the Fabric CSS parser instead of ViewConfig processing
281
287
  */
@@ -384,12 +390,24 @@ public object ReactNativeFeatureFlags {
384
390
  @JvmStatic
385
391
  public fun fuseboxEnabledRelease(): Boolean = accessor.fuseboxEnabledRelease()
386
392
 
393
+ /**
394
+ * 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.
395
+ */
396
+ @JvmStatic
397
+ public fun fuseboxFrameRecordingEnabled(): Boolean = accessor.fuseboxFrameRecordingEnabled()
398
+
387
399
  /**
388
400
  * 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.
389
401
  */
390
402
  @JvmStatic
391
403
  public fun fuseboxNetworkInspectionEnabled(): Boolean = accessor.fuseboxNetworkInspectionEnabled()
392
404
 
405
+ /**
406
+ * 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.
407
+ */
408
+ @JvmStatic
409
+ public fun fuseboxScreenshotCaptureEnabled(): Boolean = accessor.fuseboxScreenshotCaptureEnabled()
410
+
393
411
  /**
394
412
  * Hides offscreen VirtualViews on iOS by setting hidden = YES to avoid extra cost of views
395
413
  */
@@ -426,6 +444,18 @@ public object ReactNativeFeatureFlags {
426
444
  @JvmStatic
427
445
  public fun preventShadowTreeCommitExhaustion(): Boolean = accessor.preventShadowTreeCommitExhaustion()
428
446
 
447
+ /**
448
+ * Use the redesigned RedBox error overlay on Android, styled to match the LogBox visual language.
449
+ */
450
+ @JvmStatic
451
+ public fun redBoxV2Android(): Boolean = accessor.redBoxV2Android()
452
+
453
+ /**
454
+ * Use the redesigned RedBox error overlay on iOS, styled to match the LogBox visual language.
455
+ */
456
+ @JvmStatic
457
+ public fun redBoxV2IOS(): Boolean = accessor.redBoxV2IOS()
458
+
429
459
  /**
430
460
  * Function used to enable / disable Pressibility from using W3C Pointer Events for its hover callbacks
431
461
  */
@@ -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<<0875d5e54d884a26d37bb4eb2acc57d5>>
7
+ * @generated SignedSource<<15a8caa185d134716c23c751d54015aa>>
8
8
  */
9
9
 
10
10
  /**
@@ -61,6 +61,7 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
61
61
  private var enableLayoutAnimationsOnIOSCache: Boolean? = null
62
62
  private var enableMainQueueCoordinatorOnIOSCache: Boolean? = null
63
63
  private var enableModuleArgumentNSNullConversionIOSCache: Boolean? = null
64
+ private var enableMutationObserverByDefaultCache: Boolean? = null
64
65
  private var enableNativeCSSParsingCache: Boolean? = null
65
66
  private var enableNetworkEventReportingCache: Boolean? = null
66
67
  private var enablePreparedTextLayoutCache: Boolean? = null
@@ -79,13 +80,17 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
79
80
  private var fixTextClippingAndroid15useBoundsForWidthCache: Boolean? = null
80
81
  private var fuseboxAssertSingleHostStateCache: Boolean? = null
81
82
  private var fuseboxEnabledReleaseCache: Boolean? = null
83
+ private var fuseboxFrameRecordingEnabledCache: Boolean? = null
82
84
  private var fuseboxNetworkInspectionEnabledCache: Boolean? = null
85
+ private var fuseboxScreenshotCaptureEnabledCache: Boolean? = null
83
86
  private var hideOffscreenVirtualViewsOnIOSCache: Boolean? = null
84
87
  private var overrideBySynchronousMountPropsAtMountingAndroidCache: Boolean? = null
85
88
  private var perfIssuesEnabledCache: Boolean? = null
86
89
  private var perfMonitorV2EnabledCache: Boolean? = null
87
90
  private var preparedTextCacheSizeCache: Double? = null
88
91
  private var preventShadowTreeCommitExhaustionCache: Boolean? = null
92
+ private var redBoxV2AndroidCache: Boolean? = null
93
+ private var redBoxV2IOSCache: Boolean? = null
89
94
  private var shouldPressibilityUseW3CPointerEventsForHoverCache: Boolean? = null
90
95
  private var shouldTriggerResponderTransferOnScrollAndroidCache: Boolean? = null
91
96
  private var skipActivityIdentityAssertionOnHostPauseCache: Boolean? = null
@@ -475,6 +480,15 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
475
480
  return cached
476
481
  }
477
482
 
483
+ override fun enableMutationObserverByDefault(): Boolean {
484
+ var cached = enableMutationObserverByDefaultCache
485
+ if (cached == null) {
486
+ cached = ReactNativeFeatureFlagsCxxInterop.enableMutationObserverByDefault()
487
+ enableMutationObserverByDefaultCache = cached
488
+ }
489
+ return cached
490
+ }
491
+
478
492
  override fun enableNativeCSSParsing(): Boolean {
479
493
  var cached = enableNativeCSSParsingCache
480
494
  if (cached == null) {
@@ -637,6 +651,15 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
637
651
  return cached
638
652
  }
639
653
 
654
+ override fun fuseboxFrameRecordingEnabled(): Boolean {
655
+ var cached = fuseboxFrameRecordingEnabledCache
656
+ if (cached == null) {
657
+ cached = ReactNativeFeatureFlagsCxxInterop.fuseboxFrameRecordingEnabled()
658
+ fuseboxFrameRecordingEnabledCache = cached
659
+ }
660
+ return cached
661
+ }
662
+
640
663
  override fun fuseboxNetworkInspectionEnabled(): Boolean {
641
664
  var cached = fuseboxNetworkInspectionEnabledCache
642
665
  if (cached == null) {
@@ -646,6 +669,15 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
646
669
  return cached
647
670
  }
648
671
 
672
+ override fun fuseboxScreenshotCaptureEnabled(): Boolean {
673
+ var cached = fuseboxScreenshotCaptureEnabledCache
674
+ if (cached == null) {
675
+ cached = ReactNativeFeatureFlagsCxxInterop.fuseboxScreenshotCaptureEnabled()
676
+ fuseboxScreenshotCaptureEnabledCache = cached
677
+ }
678
+ return cached
679
+ }
680
+
649
681
  override fun hideOffscreenVirtualViewsOnIOS(): Boolean {
650
682
  var cached = hideOffscreenVirtualViewsOnIOSCache
651
683
  if (cached == null) {
@@ -700,6 +732,24 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
700
732
  return cached
701
733
  }
702
734
 
735
+ override fun redBoxV2Android(): Boolean {
736
+ var cached = redBoxV2AndroidCache
737
+ if (cached == null) {
738
+ cached = ReactNativeFeatureFlagsCxxInterop.redBoxV2Android()
739
+ redBoxV2AndroidCache = cached
740
+ }
741
+ return cached
742
+ }
743
+
744
+ override fun redBoxV2IOS(): Boolean {
745
+ var cached = redBoxV2IOSCache
746
+ if (cached == null) {
747
+ cached = ReactNativeFeatureFlagsCxxInterop.redBoxV2IOS()
748
+ redBoxV2IOSCache = cached
749
+ }
750
+ return cached
751
+ }
752
+
703
753
  override fun shouldPressibilityUseW3CPointerEventsForHover(): Boolean {
704
754
  var cached = shouldPressibilityUseW3CPointerEventsForHoverCache
705
755
  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<<948a9beebe2ff00791a03455eb774eee>>
7
+ * @generated SignedSource<<a648971d8196aa0950b623be31643a14>>
8
8
  */
9
9
 
10
10
  /**
@@ -110,6 +110,8 @@ public object ReactNativeFeatureFlagsCxxInterop {
110
110
 
111
111
  @DoNotStrip @JvmStatic public external fun enableModuleArgumentNSNullConversionIOS(): Boolean
112
112
 
113
+ @DoNotStrip @JvmStatic public external fun enableMutationObserverByDefault(): Boolean
114
+
113
115
  @DoNotStrip @JvmStatic public external fun enableNativeCSSParsing(): Boolean
114
116
 
115
117
  @DoNotStrip @JvmStatic public external fun enableNetworkEventReporting(): Boolean
@@ -146,8 +148,12 @@ public object ReactNativeFeatureFlagsCxxInterop {
146
148
 
147
149
  @DoNotStrip @JvmStatic public external fun fuseboxEnabledRelease(): Boolean
148
150
 
151
+ @DoNotStrip @JvmStatic public external fun fuseboxFrameRecordingEnabled(): Boolean
152
+
149
153
  @DoNotStrip @JvmStatic public external fun fuseboxNetworkInspectionEnabled(): Boolean
150
154
 
155
+ @DoNotStrip @JvmStatic public external fun fuseboxScreenshotCaptureEnabled(): Boolean
156
+
151
157
  @DoNotStrip @JvmStatic public external fun hideOffscreenVirtualViewsOnIOS(): Boolean
152
158
 
153
159
  @DoNotStrip @JvmStatic public external fun overrideBySynchronousMountPropsAtMountingAndroid(): Boolean
@@ -160,6 +166,10 @@ public object ReactNativeFeatureFlagsCxxInterop {
160
166
 
161
167
  @DoNotStrip @JvmStatic public external fun preventShadowTreeCommitExhaustion(): Boolean
162
168
 
169
+ @DoNotStrip @JvmStatic public external fun redBoxV2Android(): Boolean
170
+
171
+ @DoNotStrip @JvmStatic public external fun redBoxV2IOS(): Boolean
172
+
163
173
  @DoNotStrip @JvmStatic public external fun shouldPressibilityUseW3CPointerEventsForHover(): Boolean
164
174
 
165
175
  @DoNotStrip @JvmStatic public external fun shouldTriggerResponderTransferOnScrollAndroid(): 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<<404cef70d58d40565506ab37a4697da8>>
7
+ * @generated SignedSource<<825863c146e8a0dfabe809927af1f0ce>>
8
8
  */
9
9
 
10
10
  /**
@@ -105,6 +105,8 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi
105
105
 
106
106
  override fun enableModuleArgumentNSNullConversionIOS(): Boolean = false
107
107
 
108
+ override fun enableMutationObserverByDefault(): Boolean = false
109
+
108
110
  override fun enableNativeCSSParsing(): Boolean = false
109
111
 
110
112
  override fun enableNetworkEventReporting(): Boolean = true
@@ -141,8 +143,12 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi
141
143
 
142
144
  override fun fuseboxEnabledRelease(): Boolean = false
143
145
 
146
+ override fun fuseboxFrameRecordingEnabled(): Boolean = false
147
+
144
148
  override fun fuseboxNetworkInspectionEnabled(): Boolean = true
145
149
 
150
+ override fun fuseboxScreenshotCaptureEnabled(): Boolean = false
151
+
146
152
  override fun hideOffscreenVirtualViewsOnIOS(): Boolean = false
147
153
 
148
154
  override fun overrideBySynchronousMountPropsAtMountingAndroid(): Boolean = false
@@ -155,6 +161,10 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi
155
161
 
156
162
  override fun preventShadowTreeCommitExhaustion(): Boolean = false
157
163
 
164
+ override fun redBoxV2Android(): Boolean = false
165
+
166
+ override fun redBoxV2IOS(): Boolean = false
167
+
158
168
  override fun shouldPressibilityUseW3CPointerEventsForHover(): Boolean = false
159
169
 
160
170
  override fun shouldTriggerResponderTransferOnScrollAndroid(): Boolean = false