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,335 @@
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
+ #include "TracingTest.h"
9
+ #include "engines/JsiIntegrationTestHermesEngineAdapter.h"
10
+
11
+ #include <folly/executors/QueuedImmediateExecutor.h>
12
+ #include <jsinspector-modern/InspectorFlags.h>
13
+ #include <react/featureflags/ReactNativeFeatureFlags.h>
14
+ #include <react/networking/NetworkReporter.h>
15
+
16
+ using namespace ::testing;
17
+
18
+ namespace facebook::react::jsinspector_modern {
19
+
20
+ class TracingTest : public TracingTestBase<
21
+ JsiIntegrationTestHermesEngineAdapter,
22
+ folly::QueuedImmediateExecutor> {
23
+ protected:
24
+ TracingTest() : TracingTestBase() {}
25
+
26
+ void SetUp() override {
27
+ JsiIntegrationPortableTestBase::SetUp();
28
+ connect();
29
+ EXPECT_CALL(
30
+ fromPage(),
31
+ onMessage(
32
+ JsonParsed(AllOf(AtJsonPtr("/method", "Debugger.scriptParsed")))))
33
+ .Times(AnyNumber());
34
+ }
35
+ };
36
+
37
+ TEST_F(TracingTest, EnablesSamplingProfilerOnlyCategoryIsSpecified) {
38
+ InSequence s;
39
+
40
+ startTracing({});
41
+ auto allTraceEvents = endTracingAndCollectEvents();
42
+
43
+ EXPECT_THAT(
44
+ allTraceEvents,
45
+ Not(Contains(AllOf(
46
+ AtJsonPtr("/name", "Profile"),
47
+ AtJsonPtr("/cat", "disabled-by-default-v8.cpu_profiler")))));
48
+
49
+ startTracing({tracing::Category::JavaScriptSampling});
50
+ allTraceEvents = endTracingAndCollectEvents();
51
+
52
+ EXPECT_THAT(
53
+ allTraceEvents,
54
+ Contains(AllOf(
55
+ AtJsonPtr("/name", "Profile"),
56
+ AtJsonPtr("/cat", "disabled-by-default-v8.cpu_profiler"))));
57
+ }
58
+
59
+ TEST_F(TracingTest, RecordsFrameTimings) {
60
+ InSequence s;
61
+
62
+ page_->startTracing(tracing::Mode::Background, {tracing::Category::Timeline});
63
+
64
+ auto now = HighResTimeStamp::now();
65
+ auto frameTimingSequence = tracing::FrameTimingSequence(
66
+ 1, // id
67
+ 11, // threadId
68
+ now,
69
+ now + HighResDuration::fromNanoseconds(50));
70
+
71
+ page_->recordFrameTimings(frameTimingSequence);
72
+
73
+ auto tracingProfile = page_->stopTracing();
74
+ EXPECT_EQ(tracingProfile.frameTimings.size(), 1u);
75
+ EXPECT_EQ(tracingProfile.frameTimings[0].id, frameTimingSequence.id);
76
+ }
77
+
78
+ TEST_F(TracingTest, EmitsRecordedFrameTimingSequences) {
79
+ InSequence s;
80
+
81
+ startTracing();
82
+ auto now = HighResTimeStamp::now();
83
+ page_->recordFrameTimings(
84
+ tracing::FrameTimingSequence(
85
+ 1, // id
86
+ 11, // threadId
87
+ now,
88
+ now + HighResDuration::fromNanoseconds(50)));
89
+
90
+ auto allTraceEvents = endTracingAndCollectEvents();
91
+ EXPECT_THAT(allTraceEvents, Contains(AtJsonPtr("/name", "BeginFrame")));
92
+ EXPECT_THAT(allTraceEvents, Contains(AtJsonPtr("/name", "DrawFrame")));
93
+ }
94
+
95
+ TEST_F(TracingTest, EmitsScreenshotEventWhenScreenshotValuePassed) {
96
+ InSequence s;
97
+
98
+ startTracing({tracing::Category::Screenshot});
99
+ auto now = HighResTimeStamp::now();
100
+ page_->recordFrameTimings(
101
+ tracing::FrameTimingSequence(
102
+ 1, // id
103
+ 11, // threadId
104
+ now,
105
+ now + HighResDuration::fromNanoseconds(50),
106
+ std::vector<uint8_t>{}));
107
+
108
+ auto allTraceEvents = endTracingAndCollectEvents();
109
+ EXPECT_THAT(allTraceEvents, Contains(AtJsonPtr("/name", "Screenshot")));
110
+ }
111
+
112
+ TEST_F(
113
+ TracingTest,
114
+ SecondSessionTracingStartIsRejectedWhileFirstSessionIsTracing) {
115
+ auto secondary = connectSecondary();
116
+ InSequence s;
117
+
118
+ // Session 1 starts tracing successfully
119
+ startTracing();
120
+
121
+ // Session 2 tries to start tracing - should get error
122
+ EXPECT_CALL(
123
+ secondary.fromPage(),
124
+ onMessage(JsonParsed(AllOf(
125
+ AtJsonPtr("/id", 2),
126
+ AtJsonPtr("/error/message", "Tracing has already been started")))));
127
+ secondary.toPage().sendMessage(R"({"id": 2, "method": "Tracing.start"})");
128
+
129
+ // Session 1 ends tracing normally
130
+ endTracingAndCollectEvents();
131
+
132
+ // Now Session 2 can start tracing
133
+ EXPECT_CALL(
134
+ secondary.fromPage(), onMessage(JsonEq(R"({"id": 3, "result": {}})")));
135
+ secondary.toPage().sendMessage(R"({"id": 3, "method": "Tracing.start"})");
136
+
137
+ // Clean up - end secondary's tracing
138
+ EXPECT_CALL(
139
+ secondary.fromPage(), onMessage(JsonEq(R"({"id": 4, "result": {}})")));
140
+ EXPECT_CALL(
141
+ secondary.fromPage(),
142
+ onMessage(JsonParsed(AtJsonPtr("/method", "Tracing.dataCollected"))))
143
+ .Times(AtLeast(1));
144
+ EXPECT_CALL(
145
+ secondary.fromPage(),
146
+ onMessage(JsonParsed(AtJsonPtr("/method", "Tracing.tracingComplete"))));
147
+ secondary.toPage().sendMessage(R"({"id": 4, "method": "Tracing.end"})");
148
+ }
149
+
150
+ TEST_F(TracingTest, CDPTracingPreemptsBackgroundTracing) {
151
+ InSequence s;
152
+
153
+ // Start background tracing directly
154
+ page_->startTracing(tracing::Mode::Background, {});
155
+
156
+ // CDP Tracing.start should preempt background (succeed, not fail)
157
+ startTracing();
158
+
159
+ // End tracing normally
160
+ endTracingAndCollectEvents();
161
+ }
162
+
163
+ TEST_F(TracingTest, BackgroundTracingIsRejectedWhileCDPTracingIsRunning) {
164
+ InSequence s;
165
+
166
+ // Start CDP tracing
167
+ startTracing();
168
+
169
+ // Background tracing should be rejected
170
+ bool started = page_->startTracing(tracing::Mode::Background, {});
171
+ EXPECT_FALSE(started);
172
+
173
+ // End CDP tracing
174
+ endTracingAndCollectEvents();
175
+
176
+ // Now background tracing should succeed
177
+ started = page_->startTracing(tracing::Mode::Background, {});
178
+ EXPECT_TRUE(started);
179
+
180
+ // Clean up
181
+ page_->stopTracing();
182
+ }
183
+
184
+ TEST_F(TracingTest, EmitsToAllSessionsWithReactNativeApplicationDomainEnabled) {
185
+ auto secondaryFusebox = this->connectSecondary();
186
+ auto secondaryNonFusebox = this->connectSecondary();
187
+
188
+ // Enable ReactNativeApplication domain on primary and secondaryFusebox
189
+ // sessions (but NOT on secondaryNonFusebox)
190
+ {
191
+ InSequence s;
192
+ EXPECT_CALL(
193
+ this->fromPage(),
194
+ onMessage(JsonParsed(
195
+ AtJsonPtr("/method", "ReactNativeApplication.metadataUpdated"))));
196
+ EXPECT_CALL(
197
+ this->fromPage(), onMessage(JsonEq(R"({"id": 1, "result": {}})")));
198
+ }
199
+ this->toPage_->sendMessage(
200
+ R"({"id": 1, "method": "ReactNativeApplication.enable"})");
201
+
202
+ {
203
+ InSequence s;
204
+ EXPECT_CALL(
205
+ secondaryFusebox.fromPage(),
206
+ onMessage(JsonParsed(
207
+ AtJsonPtr("/method", "ReactNativeApplication.metadataUpdated"))));
208
+ EXPECT_CALL(
209
+ secondaryFusebox.fromPage(),
210
+ onMessage(JsonEq(R"({"id": 1, "result": {}})")));
211
+ }
212
+ secondaryFusebox.toPage().sendMessage(
213
+ R"({"id": 1, "method": "ReactNativeApplication.enable"})");
214
+
215
+ // Start background tracing
216
+ this->page_->startTracing(
217
+ tracing::Mode::Background, {tracing::Category::Timeline});
218
+
219
+ // Record some frame timings
220
+ auto now = HighResTimeStamp::now();
221
+ this->page_->recordFrameTimings(
222
+ tracing::FrameTimingSequence(
223
+ 1, // id
224
+ 11, // threadId
225
+ now,
226
+ now + HighResDuration::fromNanoseconds(50)));
227
+
228
+ // Primary and secondaryFusebox sessions should receive the trace.
229
+ // Events within each session are ordered, but order between sessions is
230
+ // arbitrary.
231
+ Sequence primarySeq;
232
+ Sequence secondarySeq;
233
+
234
+ EXPECT_CALL(
235
+ this->fromPage(),
236
+ onMessage(JsonParsed(
237
+ AtJsonPtr("/method", "ReactNativeApplication.traceRequested"))))
238
+ .InSequence(primarySeq);
239
+ EXPECT_CALL(
240
+ this->fromPage(),
241
+ onMessage(JsonParsed(AtJsonPtr("/method", "Tracing.dataCollected"))))
242
+ .Times(AtLeast(1))
243
+ .InSequence(primarySeq);
244
+ EXPECT_CALL(
245
+ this->fromPage(),
246
+ onMessage(JsonParsed(AtJsonPtr("/method", "Tracing.tracingComplete"))))
247
+ .InSequence(primarySeq);
248
+
249
+ EXPECT_CALL(
250
+ secondaryFusebox.fromPage(),
251
+ onMessage(JsonParsed(
252
+ AtJsonPtr("/method", "ReactNativeApplication.traceRequested"))))
253
+ .InSequence(secondarySeq);
254
+ EXPECT_CALL(
255
+ secondaryFusebox.fromPage(),
256
+ onMessage(JsonParsed(AtJsonPtr("/method", "Tracing.dataCollected"))))
257
+ .Times(AtLeast(1))
258
+ .InSequence(secondarySeq);
259
+ EXPECT_CALL(
260
+ secondaryFusebox.fromPage(),
261
+ onMessage(JsonParsed(AtJsonPtr("/method", "Tracing.tracingComplete"))))
262
+ .InSequence(secondarySeq);
263
+
264
+ // secondaryNonFusebox should NOT receive anything (it did not enable the
265
+ // domain)
266
+ EXPECT_CALL(secondaryNonFusebox.fromPage(), onMessage(_)).Times(0);
267
+
268
+ // Stop tracing and emit to all eligible sessions
269
+ EXPECT_TRUE(this->page_->stopAndMaybeEmitBackgroundTrace());
270
+ }
271
+
272
+ TEST_F(TracingTest, StashedTraceIsEmittedOnlyToFirstEligibleSession) {
273
+ // Start background tracing with no sessions having ReactNativeApplication
274
+ // enabled
275
+ this->page_->startTracing(
276
+ tracing::Mode::Background, {tracing::Category::Timeline});
277
+
278
+ // Record some frame timings
279
+ auto now = HighResTimeStamp::now();
280
+ this->page_->recordFrameTimings(
281
+ tracing::FrameTimingSequence(
282
+ 1, // id
283
+ 11, // threadId
284
+ now,
285
+ now + HighResDuration::fromNanoseconds(50)));
286
+
287
+ // Stop tracing - no eligible sessions exist, so the trace is stashed
288
+ EXPECT_FALSE(this->page_->stopAndMaybeEmitBackgroundTrace());
289
+
290
+ // Now the primary session enables ReactNativeApplication - it should receive
291
+ // the stashed trace. Events within a session are ordered.
292
+ Sequence primarySeq;
293
+ EXPECT_CALL(
294
+ this->fromPage(),
295
+ onMessage(JsonParsed(
296
+ AtJsonPtr("/method", "ReactNativeApplication.metadataUpdated"))))
297
+ .InSequence(primarySeq);
298
+ EXPECT_CALL(
299
+ this->fromPage(),
300
+ onMessage(JsonParsed(
301
+ AtJsonPtr("/method", "ReactNativeApplication.traceRequested"))))
302
+ .InSequence(primarySeq);
303
+ EXPECT_CALL(
304
+ this->fromPage(),
305
+ onMessage(JsonParsed(AtJsonPtr("/method", "Tracing.dataCollected"))))
306
+ .Times(AtLeast(1))
307
+ .InSequence(primarySeq);
308
+ EXPECT_CALL(
309
+ this->fromPage(),
310
+ onMessage(JsonParsed(AtJsonPtr("/method", "Tracing.tracingComplete"))))
311
+ .InSequence(primarySeq);
312
+ EXPECT_CALL(this->fromPage(), onMessage(JsonEq(R"({"id": 1, "result": {}})")))
313
+ .InSequence(primarySeq);
314
+ this->toPage_->sendMessage(
315
+ R"({"id": 1, "method": "ReactNativeApplication.enable"})");
316
+
317
+ // Connect a secondary session and enable ReactNativeApplication - it should
318
+ // NOT receive the already-emitted stashed trace
319
+ auto secondary = this->connectSecondary();
320
+ Sequence secondarySeq;
321
+ EXPECT_CALL(
322
+ secondary.fromPage(),
323
+ onMessage(JsonParsed(
324
+ AtJsonPtr("/method", "ReactNativeApplication.metadataUpdated"))))
325
+ .InSequence(secondarySeq);
326
+ // No traceRequested, dataCollected, or tracingComplete expected for
327
+ // secondary
328
+ EXPECT_CALL(
329
+ secondary.fromPage(), onMessage(JsonEq(R"({"id": 1, "result": {}})")))
330
+ .InSequence(secondarySeq);
331
+ secondary.toPage().sendMessage(
332
+ R"({"id": 1, "method": "ReactNativeApplication.enable"})");
333
+ }
334
+
335
+ } // namespace facebook::react::jsinspector_modern
@@ -0,0 +1,95 @@
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
+ #pragma once
9
+
10
+ #include "FollyDynamicMatchers.h"
11
+ #include "JsiIntegrationTest.h"
12
+
13
+ #include <fmt/format.h>
14
+ #include <folly/dynamic.h>
15
+ #include <folly/json.h>
16
+ #include <gmock/gmock.h>
17
+
18
+ #include <set>
19
+ #include <vector>
20
+
21
+ namespace facebook::react::jsinspector_modern {
22
+
23
+ /**
24
+ * Base test class providing tracing-related test utilities for tests.
25
+ */
26
+ template <typename EngineAdapter, typename Executor>
27
+ class TracingTestBase : public JsiIntegrationPortableTestBase<EngineAdapter, Executor> {
28
+ protected:
29
+ using JsiIntegrationPortableTestBase<EngineAdapter, Executor>::JsiIntegrationPortableTestBase;
30
+
31
+ /**
32
+ * Helper method to start tracing via Tracing.start CDP command.
33
+ */
34
+ void startTracing(
35
+ const std::set<tracing::Category> &enabledCategories = {
36
+ tracing::Category::HiddenTimeline,
37
+ tracing::Category::JavaScriptSampling,
38
+ tracing::Category::RuntimeExecution,
39
+ tracing::Category::Timeline,
40
+ tracing::Category::UserTiming,
41
+ })
42
+ {
43
+ this->expectMessageFromPage(JsonEq(R"({
44
+ "id": 1,
45
+ "result": {}
46
+ })"));
47
+
48
+ this->toPage_->sendMessage(
49
+ fmt::format(
50
+ R"({{
51
+ "id": 1,
52
+ "method": "Tracing.start",
53
+ "params": {{ "categories": "{0}" }}
54
+ }})",
55
+ tracing::serializeTracingCategories(enabledCategories)));
56
+ }
57
+
58
+ /**
59
+ * Helper method to end tracing and collect all trace events from potentially
60
+ * multiple chunked Tracing.dataCollected messages.
61
+ * \returns A vector containing all collected trace events
62
+ */
63
+ std::vector<folly::dynamic> endTracingAndCollectEvents()
64
+ {
65
+ testing::InSequence s;
66
+
67
+ this->expectMessageFromPage(JsonEq(R"({
68
+ "id": 1,
69
+ "result": {}
70
+ })"));
71
+
72
+ std::vector<folly::dynamic> allTraceEvents;
73
+
74
+ EXPECT_CALL(this->fromPage(), onMessage(JsonParsed(AtJsonPtr("/method", "Tracing.dataCollected"))))
75
+ .Times(testing::AtLeast(1))
76
+ .WillRepeatedly(testing::Invoke([&allTraceEvents](const std::string &message) {
77
+ auto parsedMessage = folly::parseJson(message);
78
+ auto &events = parsedMessage.at("params").at("value");
79
+ allTraceEvents.insert(
80
+ allTraceEvents.end(), std::make_move_iterator(events.begin()), std::make_move_iterator(events.end()));
81
+ }));
82
+
83
+ this->expectMessageFromPage(JsonParsed(
84
+ testing::AllOf(AtJsonPtr("/method", "Tracing.tracingComplete"), AtJsonPtr("/params/dataLossOccurred", false))));
85
+
86
+ this->toPage_->sendMessage(R"({
87
+ "id": 1,
88
+ "method": "Tracing.end"
89
+ })");
90
+
91
+ return allTraceEvents;
92
+ }
93
+ };
94
+
95
+ } // namespace facebook::react::jsinspector_modern
@@ -26,11 +26,21 @@ class ReactNativeFeatureFlagsOverrides
26
26
  const InspectorFlagOverrides& overrides)
27
27
  : overrides_(overrides) {}
28
28
 
29
+ bool fuseboxScreenshotCaptureEnabled() override {
30
+ return overrides_.screenshotCaptureEnabled.value_or(
31
+ ReactNativeFeatureFlagsDefaults::fuseboxScreenshotCaptureEnabled());
32
+ }
33
+
29
34
  bool fuseboxEnabledRelease() override {
30
35
  return overrides_.fuseboxEnabledRelease.value_or(
31
36
  ReactNativeFeatureFlagsDefaults::fuseboxEnabledRelease());
32
37
  }
33
38
 
39
+ bool fuseboxFrameRecordingEnabled() override {
40
+ return overrides_.frameRecordingEnabled.value_or(
41
+ ReactNativeFeatureFlagsDefaults::fuseboxFrameRecordingEnabled());
42
+ }
43
+
34
44
  bool fuseboxNetworkInspectionEnabled() override {
35
45
  return overrides_.networkInspectionEnabled.value_or(
36
46
  ReactNativeFeatureFlagsDefaults::fuseboxNetworkInspectionEnabled());
@@ -19,9 +19,11 @@ namespace facebook::react::jsinspector_modern {
19
19
  struct InspectorFlagOverrides {
20
20
  // NOTE: Keep these entries in sync with ReactNativeFeatureFlagsOverrides in
21
21
  // the implementation file.
22
+ std::optional<bool> screenshotCaptureEnabled;
23
+ std::optional<bool> enableNetworkEventReporting;
24
+ std::optional<bool> frameRecordingEnabled;
22
25
  std::optional<bool> fuseboxEnabledRelease;
23
26
  std::optional<bool> networkInspectionEnabled;
24
- std::optional<bool> enableNetworkEventReporting;
25
27
  };
26
28
 
27
29
  /**
@@ -22,6 +22,7 @@ target_link_libraries(jsinspector_tracing
22
22
  jsinspector_network
23
23
  oscompat
24
24
  react_timing
25
+ react_utils
25
26
  )
26
27
  target_compile_reactnative_options(jsinspector_tracing PRIVATE)
27
28
  target_compile_options(jsinspector_tracing PRIVATE -Wpedantic)
@@ -0,0 +1,61 @@
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
+ #pragma once
9
+
10
+ #include "TraceEvent.h"
11
+
12
+ #include <react/timing/primitives.h>
13
+
14
+ #include <cstdint>
15
+ #include <optional>
16
+ #include <vector>
17
+
18
+ namespace facebook::react::jsinspector_modern::tracing {
19
+
20
+ using FrameSequenceId = uint64_t;
21
+
22
+ /**
23
+ * A struct representing a sequence of frame timings that happened on the Host side.
24
+ */
25
+ struct FrameTimingSequence {
26
+ FrameTimingSequence() = delete;
27
+
28
+ FrameTimingSequence(
29
+ FrameSequenceId id,
30
+ ThreadId threadId,
31
+ HighResTimeStamp beginTimestamp,
32
+ HighResTimeStamp endTimestamp,
33
+ std::optional<std::vector<uint8_t>> screenshot = std::nullopt)
34
+ : id(id),
35
+ threadId(threadId),
36
+ beginTimestamp(beginTimestamp),
37
+ endTimestamp(endTimestamp),
38
+ screenshot(std::move(screenshot))
39
+ {
40
+ }
41
+
42
+ /**
43
+ * Unique ID of the sequence, used by Chrome DevTools Frontend to identify the events that form one sequence.
44
+ */
45
+ FrameSequenceId id;
46
+
47
+ /**
48
+ * The ID of the native thread that is associated with the frame.
49
+ */
50
+ ThreadId threadId;
51
+
52
+ HighResTimeStamp beginTimestamp;
53
+ HighResTimeStamp endTimestamp;
54
+
55
+ /**
56
+ * Optional screenshot data captured during the frame.
57
+ */
58
+ std::optional<std::vector<uint8_t>> screenshot;
59
+ };
60
+
61
+ } // namespace facebook::react::jsinspector_modern::tracing
@@ -0,0 +1,43 @@
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
+ #pragma once
9
+
10
+ #include "FrameTimingSequence.h"
11
+ #include "InstanceTracingProfile.h"
12
+ #include "RuntimeSamplingProfile.h"
13
+
14
+ #include <react/timing/primitives.h>
15
+
16
+ #include <vector>
17
+
18
+ namespace facebook::react::jsinspector_modern::tracing {
19
+
20
+ /**
21
+ * The final tracing profile for the given HostTarget.
22
+ * Contains all necessary information that is required to be be emitted as a series of Tracing.dataCollected CDP
23
+ * messages.
24
+ */
25
+ struct HostTracingProfile {
26
+ // The ID of the OS-level process that this Trace Recording is associated
27
+ // with.
28
+ ProcessId processId;
29
+
30
+ // The timestamp at which this Trace Recording started.
31
+ HighResTimeStamp startTime;
32
+
33
+ // Frame timings captured on the Host side.
34
+ std::vector<FrameTimingSequence> frameTimings;
35
+
36
+ // All captured Instance Tracing Profiles during this Trace Recording.
37
+ std::vector<InstanceTracingProfile> instanceTracingProfiles;
38
+
39
+ // All captured Runtime Sampling Profiles during this Trace Recording.
40
+ std::vector<RuntimeSamplingProfile> runtimeSamplingProfiles;
41
+ };
42
+
43
+ } // namespace facebook::react::jsinspector_modern::tracing