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
@@ -16,6 +16,36 @@ using namespace facebook::jni;
16
16
  using namespace facebook::react::jsinspector_modern;
17
17
 
18
18
  namespace facebook::react {
19
+
20
+ namespace {
21
+ jni::local_ref<JTracingState::javaobject> convertCPPTracingStateToJava(
22
+ TracingState tracingState) {
23
+ auto tracingStateClass = jni::findClassLocal(
24
+ "com/facebook/react/devsupport/inspector/TracingState");
25
+ auto valueOfMethod =
26
+ tracingStateClass->getStaticMethod<JTracingState(jstring)>("valueOf");
27
+
28
+ switch (tracingState) {
29
+ case TracingState::Disabled:
30
+ return valueOfMethod(
31
+ tracingStateClass, jni::make_jstring("DISABLED").get());
32
+
33
+ case TracingState::EnabledInBackgroundMode:
34
+ return valueOfMethod(
35
+ tracingStateClass,
36
+ jni::make_jstring("ENABLED_IN_BACKGROUND_MODE").get());
37
+
38
+ case TracingState::EnabledInCDPMode:
39
+ return valueOfMethod(
40
+ tracingStateClass, jni::make_jstring("ENABLED_IN_CDP_MODE").get());
41
+
42
+ default:
43
+ jni::throwNewJavaException(
44
+ "java/lang/IllegalStateException", "Unexpected new TracingState.");
45
+ }
46
+ }
47
+ } // namespace
48
+
19
49
  JReactHostInspectorTarget::JReactHostInspectorTarget(
20
50
  alias_ref<JReactHostInspectorTarget::javaobject> jobj,
21
51
  alias_ref<JReactHostImpl> reactHostImpl,
@@ -29,7 +59,8 @@ JReactHostInspectorTarget::JReactHostInspectorTarget(
29
59
  std::function<void()>&& callback) mutable {
30
60
  auto jrunnable = JNativeRunnable::newObjectCxxArgs(std::move(callback));
31
61
  javaExecutor->execute(jrunnable);
32
- }) {
62
+ }),
63
+ tracingDelegate_(std::make_unique<TracingDelegate>()) {
33
64
  auto& inspectorFlags = InspectorFlags::getInstance();
34
65
  if (inspectorFlags.getFuseboxEnabled()) {
35
66
  inspectorTarget_ = HostTarget::create(*this, inspectorExecutor_);
@@ -140,13 +171,34 @@ void JReactHostInspectorTarget::loadNetworkResource(
140
171
  }
141
172
  }
142
173
 
174
+ std::optional<std::string> JReactHostInspectorTarget::captureScreenshot(
175
+ const jsinspector_modern::HostTargetDelegate::PageCaptureScreenshotRequest&
176
+ request) {
177
+ if (auto javaReactHostImplStrong = javaReactHostImpl_->get()) {
178
+ std::string format = request.format.value_or("png");
179
+ int quality = request.quality.value_or(-1);
180
+ auto result = javaReactHostImplStrong->captureScreenshot(format, quality);
181
+ if (result) {
182
+ return result->toStdString();
183
+ }
184
+ }
185
+ return std::nullopt;
186
+ }
187
+
143
188
  HostTarget* JReactHostInspectorTarget::getInspectorTarget() {
144
189
  return inspectorTarget_ ? inspectorTarget_.get() : nullptr;
145
190
  }
146
191
 
147
192
  bool JReactHostInspectorTarget::startBackgroundTrace() {
148
193
  if (inspectorTarget_) {
149
- return inspectorTarget_->startTracing(tracing::Mode::Background);
194
+ return inspectorTarget_->startTracing(
195
+ tracing::Mode::Background,
196
+ {
197
+ tracing::Category::HiddenTimeline,
198
+ tracing::Category::RuntimeExecution,
199
+ tracing::Category::Timeline,
200
+ tracing::Category::UserTiming,
201
+ });
150
202
  } else {
151
203
  jni::throwNewJavaException(
152
204
  "java/lang/IllegalStateException",
@@ -154,7 +206,7 @@ bool JReactHostInspectorTarget::startBackgroundTrace() {
154
206
  }
155
207
  }
156
208
 
157
- tracing::TraceRecordingState JReactHostInspectorTarget::stopTracing() {
209
+ tracing::HostTracingProfile JReactHostInspectorTarget::stopTracing() {
158
210
  if (inspectorTarget_) {
159
211
  return inspectorTarget_->stopTracing();
160
212
  } else {
@@ -167,12 +219,12 @@ tracing::TraceRecordingState JReactHostInspectorTarget::stopTracing() {
167
219
  jboolean JReactHostInspectorTarget::stopAndMaybeEmitBackgroundTrace() {
168
220
  auto capturedTrace = inspectorTarget_->stopTracing();
169
221
  if (inspectorTarget_->hasActiveSessionWithFuseboxClient()) {
170
- inspectorTarget_->emitTraceRecordingForFirstFuseboxClient(
222
+ inspectorTarget_->emitTracingProfileForFirstFuseboxClient(
171
223
  std::move(capturedTrace));
172
224
  return jboolean(true);
173
225
  }
174
226
 
175
- stashTraceRecordingState(std::move(capturedTrace));
227
+ stashTracingProfile(std::move(capturedTrace));
176
228
  return jboolean(false);
177
229
  }
178
230
 
@@ -180,16 +232,16 @@ void JReactHostInspectorTarget::stopAndDiscardBackgroundTrace() {
180
232
  inspectorTarget_->stopTracing();
181
233
  }
182
234
 
183
- void JReactHostInspectorTarget::stashTraceRecordingState(
184
- tracing::TraceRecordingState&& state) {
185
- stashedTraceRecordingState_ = std::move(state);
235
+ void JReactHostInspectorTarget::stashTracingProfile(
236
+ tracing::HostTracingProfile&& hostTracingProfile) {
237
+ stashedTracingProfile_ = std::move(hostTracingProfile);
186
238
  }
187
239
 
188
- std::optional<tracing::TraceRecordingState> JReactHostInspectorTarget::
189
- unstable_getTraceRecordingThatWillBeEmittedOnInitialization() {
190
- auto state = std::move(stashedTraceRecordingState_);
191
- stashedTraceRecordingState_.reset();
192
- return state;
240
+ std::optional<tracing::HostTracingProfile> JReactHostInspectorTarget::
241
+ unstable_getHostTracingProfileThatWillBeEmittedOnInitialization() {
242
+ auto tracingProfile = std::move(stashedTracingProfile_);
243
+ stashedTracingProfile_.reset();
244
+ return tracingProfile;
193
245
  }
194
246
 
195
247
  void JReactHostInspectorTarget::registerNatives() {
@@ -208,13 +260,140 @@ void JReactHostInspectorTarget::registerNatives() {
208
260
  "stopAndDiscardBackgroundTrace",
209
261
  JReactHostInspectorTarget::stopAndDiscardBackgroundTrace),
210
262
  makeNativeMethod(
211
- "tracingStateAsInt", JReactHostInspectorTarget::tracingState),
263
+ "getTracingState", JReactHostInspectorTarget::getTracingState),
264
+ makeNativeMethod(
265
+ "registerTracingStateListener",
266
+ JReactHostInspectorTarget::registerTracingStateListener),
267
+ makeNativeMethod(
268
+ "unregisterTracingStateListener",
269
+ JReactHostInspectorTarget::unregisterTracingStateListener),
270
+ makeNativeMethod(
271
+ "recordFrameTimings", JReactHostInspectorTarget::recordFrameTimings),
272
+ });
273
+ }
274
+
275
+ jni::local_ref<JTracingState::javaobject>
276
+ JReactHostInspectorTarget::getTracingState() {
277
+ return convertCPPTracingStateToJava(tracingDelegate_->getTracingState());
278
+ }
279
+
280
+ jlong JReactHostInspectorTarget::registerTracingStateListener(
281
+ jni::alias_ref<JTracingStateListener::javaobject> listener) {
282
+ auto cppListener = [globalRef = make_global(listener)](
283
+ TracingState state, bool screenshotsEnabled) {
284
+ static auto method =
285
+ globalRef->getClass()
286
+ ->getMethod<void(
287
+ jni::local_ref<JTracingState::javaobject>, jboolean)>(
288
+ "onStateChanged");
289
+
290
+ method(
291
+ globalRef,
292
+ convertCPPTracingStateToJava(state),
293
+ static_cast<jboolean>(screenshotsEnabled));
294
+ };
295
+
296
+ return static_cast<jlong>(
297
+ tracingDelegate_->registerTracingStateListener(std::move(cppListener)));
298
+ }
299
+
300
+ void JReactHostInspectorTarget::unregisterTracingStateListener(
301
+ jlong subscriptionId) {
302
+ tracingDelegate_->unregisterTracingStateListener(subscriptionId);
303
+ }
304
+
305
+ HostTargetTracingDelegate* JReactHostInspectorTarget::getTracingDelegate() {
306
+ return tracingDelegate_.get();
307
+ }
308
+
309
+ void JReactHostInspectorTarget::recordFrameTimings(
310
+ jni::alias_ref<JFrameTimingSequence::javaobject> frameTimingSequence) {
311
+ inspectorTarget_->recordFrameTimings({
312
+ frameTimingSequence->getId(),
313
+ frameTimingSequence->getThreadId(),
314
+ frameTimingSequence->getBeginTimestamp(),
315
+ frameTimingSequence->getEndTimestamp(),
316
+ frameTimingSequence->getScreenshot(),
212
317
  });
213
318
  }
214
319
 
215
- jint JReactHostInspectorTarget::tracingState() {
216
- auto state = inspectorTarget_->tracingState();
217
- return static_cast<jint>(state);
320
+ void TracingDelegate::onTracingStarted(
321
+ tracing::Mode tracingMode,
322
+ bool screenshotsCategoryEnabled) {
323
+ TracingState nextState = TracingState::Disabled;
324
+ switch (tracingMode) {
325
+ case tracing::Mode::CDP:
326
+ nextState = TracingState::EnabledInCDPMode;
327
+ break;
328
+ case tracing::Mode::Background:
329
+ nextState = TracingState::EnabledInBackgroundMode;
330
+ break;
331
+ default:
332
+ throw std::logic_error("Unexpected new Tracing Mode");
333
+ }
334
+
335
+ std::vector<TracingStateListener> listeners;
336
+ {
337
+ std::lock_guard<std::mutex> lock(mutex_);
338
+
339
+ tracingState_ = nextState;
340
+ listeners = copySubscribedListeners();
341
+ }
342
+
343
+ notifyListeners(listeners, nextState, screenshotsCategoryEnabled);
344
+ }
345
+
346
+ void TracingDelegate::onTracingStopped() {
347
+ std::vector<TracingStateListener> listeners;
348
+ {
349
+ std::lock_guard<std::mutex> lock(mutex_);
350
+
351
+ tracingState_ = TracingState::Disabled;
352
+ listeners = copySubscribedListeners();
353
+ }
354
+
355
+ notifyListeners(listeners, TracingState::Disabled, false);
356
+ }
357
+
358
+ TracingState TracingDelegate::getTracingState() {
359
+ std::lock_guard<std::mutex> lock(mutex_);
360
+
361
+ return tracingState_;
362
+ }
363
+
364
+ size_t TracingDelegate::registerTracingStateListener(
365
+ TracingStateListener listener) {
366
+ std::lock_guard<std::mutex> lock(mutex_);
367
+
368
+ auto id = nextSubscriptionId_++;
369
+ subscriptions_[id] = std::move(listener);
370
+ return id;
371
+ }
372
+
373
+ void TracingDelegate::unregisterTracingStateListener(size_t subscriptionId) {
374
+ std::lock_guard<std::mutex> lock(mutex_);
375
+
376
+ subscriptions_.erase(subscriptionId);
377
+ }
378
+
379
+ std::vector<TracingStateListener> TracingDelegate::copySubscribedListeners() {
380
+ std::vector<TracingStateListener> listeners;
381
+ listeners.reserve(subscriptions_.size());
382
+
383
+ for (auto& [_, listener] : subscriptions_) {
384
+ listeners.push_back(listener);
385
+ }
386
+
387
+ return listeners;
388
+ }
389
+
390
+ void TracingDelegate::notifyListeners(
391
+ const std::vector<TracingStateListener>& listeners,
392
+ TracingState state,
393
+ bool screenshotsCategoryEnabled) {
394
+ for (const auto& listener : listeners) {
395
+ listener(state, screenshotsCategoryEnabled);
396
+ }
218
397
  }
219
398
 
220
399
  } // namespace facebook::react
@@ -7,11 +7,17 @@
7
7
 
8
8
  #pragma once
9
9
 
10
+ #include <fbjni/ByteBuffer.h>
10
11
  #include <fbjni/fbjni.h>
12
+
11
13
  #include <jsinspector-modern/HostTarget.h>
12
14
  #include <react/jni/InspectorNetworkRequestListener.h>
13
15
  #include <react/jni/JExecutor.h>
16
+
17
+ #include <mutex>
18
+ #include <optional>
14
19
  #include <string>
20
+ #include <vector>
15
21
 
16
22
  namespace facebook::react {
17
23
 
@@ -20,7 +26,56 @@ struct JTaskInterface : public jni::JavaClass<JTaskInterface> {
20
26
  };
21
27
 
22
28
  struct JTracingState : public jni::JavaClass<JTracingState> {
23
- static constexpr auto kJavaDescriptor = "Lcom/facebook/react/devsupport/TracingState;";
29
+ static constexpr auto kJavaDescriptor = "Lcom/facebook/react/devsupport/inspector/TracingState;";
30
+ };
31
+
32
+ struct JTracingStateListener : public jni::JavaClass<JTracingStateListener> {
33
+ static constexpr auto kJavaDescriptor = "Lcom/facebook/react/devsupport/inspector/TracingStateListener;";
34
+ };
35
+
36
+ struct JFrameTimingSequence : public jni::JavaClass<JFrameTimingSequence> {
37
+ static constexpr auto kJavaDescriptor = "Lcom/facebook/react/devsupport/inspector/FrameTimingSequence;";
38
+
39
+ uint64_t getId() const
40
+ {
41
+ auto field = javaClassStatic()->getField<jint>("id");
42
+ return static_cast<uint64_t>(getFieldValue(field));
43
+ }
44
+
45
+ uint64_t getThreadId() const
46
+ {
47
+ auto field = javaClassStatic()->getField<jint>("threadId");
48
+ return static_cast<uint64_t>(getFieldValue(field));
49
+ }
50
+
51
+ HighResTimeStamp getBeginTimestamp() const
52
+ {
53
+ auto field = javaClassStatic()->getField<jlong>("beginTimestamp");
54
+ return HighResTimeStamp::fromChronoSteadyClockTimePoint(
55
+ std::chrono::steady_clock::time_point(std::chrono::nanoseconds(getFieldValue(field))));
56
+ }
57
+
58
+ HighResTimeStamp getEndTimestamp() const
59
+ {
60
+ auto field = javaClassStatic()->getField<jlong>("endTimestamp");
61
+ return HighResTimeStamp::fromChronoSteadyClockTimePoint(
62
+ std::chrono::steady_clock::time_point(std::chrono::nanoseconds(getFieldValue(field))));
63
+ }
64
+
65
+ std::optional<std::vector<uint8_t>> getScreenshot() const
66
+ {
67
+ auto field = javaClassStatic()->getField<jbyteArray>("screenshot");
68
+ auto javaScreenshot = getFieldValue(field);
69
+ if (javaScreenshot) {
70
+ auto size = static_cast<size_t>(javaScreenshot->size());
71
+ if (size > 0) {
72
+ std::vector<uint8_t> result(size);
73
+ javaScreenshot->getRegion(0, javaScreenshot->size(), reinterpret_cast<jbyte *>(result.data()));
74
+ return result;
75
+ }
76
+ }
77
+ return std::nullopt;
78
+ }
24
79
  };
25
80
 
26
81
  struct JReactHostImpl : public jni::JavaClass<JReactHostImpl> {
@@ -53,6 +108,78 @@ struct JReactHostImpl : public jni::JavaClass<JReactHostImpl> {
53
108
  "loadNetworkResource");
54
109
  return method(self(), jni::make_jstring(url), listener);
55
110
  }
111
+
112
+ jni::local_ref<jni::JString> captureScreenshot(const std::string &format, int quality) const
113
+ {
114
+ auto method = javaClassStatic()->getMethod<jni::local_ref<jni::JString>(jni::local_ref<jni::JString>, jint)>(
115
+ "captureScreenshot");
116
+ return method(self(), jni::make_jstring(format), static_cast<jint>(quality));
117
+ }
118
+ };
119
+
120
+ enum class TracingState {
121
+ Disabled,
122
+ EnabledInBackgroundMode,
123
+ EnabledInCDPMode,
124
+ };
125
+
126
+ /**
127
+ * A callback that will be invoked when tracing state has changed.
128
+ */
129
+ using TracingStateListener = std::function<void(TracingState state, bool screenshotsCategoryEnabled)>;
130
+
131
+ class TracingDelegate : public jsinspector_modern::HostTargetTracingDelegate {
132
+ public:
133
+ void onTracingStarted(jsinspector_modern::tracing::Mode tracingMode, bool screenshotsCategoryEnabled) override;
134
+ void onTracingStopped() override;
135
+
136
+ /**
137
+ * A synchronous way to get the current tracing state.
138
+ * Could be called from any thread.
139
+ */
140
+ TracingState getTracingState();
141
+ /**
142
+ * Register a listener that will be notified when the tracing state changes.
143
+ * Could be called from any thread.
144
+ */
145
+ size_t registerTracingStateListener(TracingStateListener listener);
146
+ /**
147
+ * Unregister previously registered listener with the id returned from
148
+ * TracingDelegate::registerTracingStateListener().
149
+ */
150
+ void unregisterTracingStateListener(size_t subscriptionId);
151
+
152
+ private:
153
+ /**
154
+ * Covers read / write operations on tracingState_ and subscriptions_.
155
+ */
156
+ std::mutex mutex_;
157
+ /**
158
+ * Since HostInspectorTarget creates HostTarget, the default value is Disabled.
159
+ * However, the TracingDelegate is subscribed at the construction of HostTarget, so it will be notified as early as
160
+ * possible.
161
+ */
162
+ TracingState tracingState_ = TracingState::Disabled;
163
+ /**
164
+ * Map of subscription ID to listener.
165
+ */
166
+ std::unordered_map<size_t, TracingStateListener> subscriptions_;
167
+ /**
168
+ * A counter for generating unique subscription IDs.
169
+ */
170
+ uint64_t nextSubscriptionId_ = 0;
171
+ /**
172
+ * Returns a collection of listeners that are subscribed at the time of the call.
173
+ * Expected to be only called with mutex_ locked.
174
+ */
175
+ std::vector<TracingStateListener> copySubscribedListeners();
176
+ /**
177
+ * Notifies specified listeners about the state change.
178
+ */
179
+ void notifyListeners(
180
+ const std::vector<TracingStateListener> &listeners,
181
+ TracingState state,
182
+ bool screenshotsCategoryEnabled);
56
183
  };
57
184
 
58
185
  class JReactHostInspectorTarget : public jni::HybridClass<JReactHostInspectorTarget>,
@@ -70,14 +197,6 @@ class JReactHostInspectorTarget : public jni::HybridClass<JReactHostInspectorTar
70
197
  static void registerNatives();
71
198
  void sendDebuggerResumeCommand();
72
199
 
73
- /**
74
- * Get the state of the background trace: running, stopped, or disabled
75
- * Background tracing will be disabled if there is no metro connection or if
76
- * there is a CDP initiate trace in progress.
77
- *
78
- * \return the background trace state
79
- */
80
- jint tracingState();
81
200
  /**
82
201
  * Starts a background trace recording for this HostTarget.
83
202
  *
@@ -99,6 +218,31 @@ class JReactHostInspectorTarget : public jni::HybridClass<JReactHostInspectorTar
99
218
 
100
219
  jsinspector_modern::HostTarget *getInspectorTarget();
101
220
 
221
+ /**
222
+ * Get the current tracing state. Could be called from any thread.
223
+ */
224
+ jni::local_ref<JTracingState::javaobject> getTracingState();
225
+
226
+ /**
227
+ * Register a listener that will be notified when the tracing state changes.
228
+ * Could be called from any thread.
229
+ *
230
+ * \return A unique subscription ID to use for unregistering the listener.
231
+ */
232
+ jlong registerTracingStateListener(jni::alias_ref<JTracingStateListener::javaobject> listener);
233
+
234
+ /**
235
+ * Unregister a previously registered tracing state listener.
236
+ *
237
+ * \param subscriptionId The subscription ID returned from JReactHostInspectorTarget::registerTracingStateListener.
238
+ */
239
+ void unregisterTracingStateListener(jlong subscriptionId);
240
+
241
+ /**
242
+ * Propagate frame timings information to the Inspector's Tracing subsystem.
243
+ */
244
+ void recordFrameTimings(jni::alias_ref<JFrameTimingSequence::javaobject> frameTimingSequence);
245
+
102
246
  // HostTargetDelegate methods
103
247
  jsinspector_modern::HostTargetMetadata getMetadata() override;
104
248
  void onReload(const PageReloadRequest &request) override;
@@ -107,8 +251,11 @@ class JReactHostInspectorTarget : public jni::HybridClass<JReactHostInspectorTar
107
251
  void loadNetworkResource(
108
252
  const jsinspector_modern::LoadNetworkResourceRequest &params,
109
253
  jsinspector_modern::ScopedExecutor<jsinspector_modern::NetworkRequestListener> executor) override;
110
- std::optional<jsinspector_modern::tracing::TraceRecordingState>
111
- unstable_getTraceRecordingThatWillBeEmittedOnInitialization() override;
254
+ std::optional<std::string> captureScreenshot(
255
+ const jsinspector_modern::HostTargetDelegate::PageCaptureScreenshotRequest &request) override;
256
+ std::optional<jsinspector_modern::tracing::HostTracingProfile>
257
+ unstable_getHostTracingProfileThatWillBeEmittedOnInitialization() override;
258
+ jsinspector_modern::HostTargetTracingDelegate *getTracingDelegate() override;
112
259
 
113
260
  private:
114
261
  JReactHostInspectorTarget(
@@ -126,20 +273,23 @@ class JReactHostInspectorTarget : public jni::HybridClass<JReactHostInspectorTar
126
273
  std::optional<int> inspectorPageId_;
127
274
 
128
275
  /**
129
- * Stops previously started trace recording and returns the captured trace.
276
+ * Stops previously started trace recording and returns the captured HostTracingProfile.
130
277
  */
131
- jsinspector_modern::tracing::TraceRecordingState stopTracing();
278
+ jsinspector_modern::tracing::HostTracingProfile stopTracing();
132
279
  /**
133
- * Stashes previously recorded trace recording state that will be emitted when
280
+ * Stashes previously recorded HostTracingProfile that will be emitted when
134
281
  * CDP session is created. Once emitted, the value will be cleared from this
135
282
  * instance.
136
283
  */
137
- void stashTraceRecordingState(jsinspector_modern::tracing::TraceRecordingState &&state);
284
+ void stashTracingProfile(jsinspector_modern::tracing::HostTracingProfile &&hostTracingProfile);
285
+ /**
286
+ * Previously recorded HostTracingProfile that will be emitted when CDP session is created.
287
+ */
288
+ std::optional<jsinspector_modern::tracing::HostTracingProfile> stashedTracingProfile_;
138
289
  /**
139
- * Previously recorded trace recording state that will be emitted when
140
- * CDP session is created.
290
+ * Encapsulates the logic around tracing for this HostInspectorTarget.
141
291
  */
142
- std::optional<jsinspector_modern::tracing::TraceRecordingState> stashedTraceRecordingState_;
292
+ std::unique_ptr<TracingDelegate> tracingDelegate_;
143
293
 
144
294
  friend HybridBase;
145
295
  };
@@ -43,6 +43,7 @@ SET(folly_runtime_SRC
43
43
  folly/json/json_pointer.cpp
44
44
  folly/json/json.cpp
45
45
  folly/lang/CString.cpp
46
+ folly/lang/Exception.cpp
46
47
  folly/lang/SafeAssert.cpp
47
48
  folly/lang/ToAscii.cpp
48
49
  folly/memory/detail/MallocImpl.cpp
@@ -14,14 +14,14 @@
14
14
 
15
15
  #define REACT_NATIVE_VERSION_MAJOR 0
16
16
  #define REACT_NATIVE_VERSION_MINOR 83
17
- #define REACT_NATIVE_VERSION_PATCH 3
17
+ #define REACT_NATIVE_VERSION_PATCH 5
18
18
 
19
19
  namespace facebook::react {
20
20
 
21
21
  constexpr struct {
22
22
  int32_t Major = 0;
23
23
  int32_t Minor = 83;
24
- int32_t Patch = 3;
24
+ int32_t Patch = 5;
25
25
  std::string_view Prerelease = "";
26
26
  } ReactNativeVersion;
27
27
 
@@ -198,6 +198,42 @@ class HostAgent::Impl final {
198
198
  .shouldSendOKResponse = true,
199
199
  };
200
200
  }
201
+ if (InspectorFlags::getInstance().getScreenshotCaptureEnabled()) {
202
+ if (req.method == "Page.captureScreenshot") {
203
+ std::optional<std::string> format;
204
+ std::optional<int> quality;
205
+
206
+ if (req.params.isObject()) {
207
+ if (req.params.count("format") != 0u) {
208
+ format = req.params.at("format").asString();
209
+ }
210
+ if (req.params.count("quality") != 0u) {
211
+ quality = static_cast<int>(req.params.at("quality").asInt());
212
+ }
213
+ }
214
+
215
+ auto base64Data = targetController_.getDelegate().captureScreenshot(
216
+ {.format = format, .quality = quality});
217
+
218
+ if (base64Data.has_value()) {
219
+ frontendChannel_(
220
+ cdp::jsonResult(
221
+ req.id,
222
+ folly::dynamic::object("data", std::move(*base64Data))));
223
+ } else {
224
+ frontendChannel_(
225
+ cdp::jsonError(
226
+ req.id,
227
+ cdp::ErrorCode::InternalError,
228
+ "Failed to capture screenshot"));
229
+ }
230
+
231
+ return {
232
+ .isFinishedHandlingRequest = true,
233
+ .shouldSendOKResponse = false,
234
+ };
235
+ }
236
+ }
201
237
  if (req.method == "Overlay.setPausedInDebuggerMessage") {
202
238
  auto message =
203
239
  req.params.isObject() && (req.params.count("message") != 0u)
@@ -238,9 +274,9 @@ class HostAgent::Impl final {
238
274
 
239
275
  auto stashedTraceRecording =
240
276
  targetController_.getDelegate()
241
- .unstable_getTraceRecordingThatWillBeEmittedOnInitialization();
277
+ .unstable_getHostTracingProfileThatWillBeEmittedOnInitialization();
242
278
  if (stashedTraceRecording.has_value()) {
243
- tracingAgent_.emitExternalTraceRecording(
279
+ tracingAgent_.emitExternalHostTracingProfile(
244
280
  std::move(stashedTraceRecording.value()));
245
281
  }
246
282
 
@@ -385,12 +421,12 @@ class HostAgent::Impl final {
385
421
  return fuseboxClientType_ == FuseboxClientType::Fusebox;
386
422
  }
387
423
 
388
- void emitExternalTraceRecording(
389
- tracing::TraceRecordingState traceRecording) const {
424
+ void emitExternalTracingProfile(
425
+ tracing::HostTracingProfile tracingProfile) const {
390
426
  assert(
391
427
  hasFuseboxClientConnected() &&
392
428
  "Attempted to emit a trace recording to a non-Fusebox client");
393
- tracingAgent_.emitExternalTraceRecording(std::move(traceRecording));
429
+ tracingAgent_.emitExternalHostTracingProfile(std::move(tracingProfile));
394
430
  }
395
431
 
396
432
  void emitSystemStateChanged(bool isSingleHost) {
@@ -506,8 +542,7 @@ class HostAgent::Impl final {
506
542
  bool hasFuseboxClientConnected() const {
507
543
  return false;
508
544
  }
509
- void emitExternalTraceRecording(tracing::TraceRecordingState traceRecording) {
510
- }
545
+ void emitExternalTracingProfile(tracing::HostTracingProfile tracingProfile) {}
511
546
  void emitSystemStateChanged(bool isSingleHost) {}
512
547
  };
513
548
 
@@ -543,9 +578,9 @@ bool HostAgent::hasFuseboxClientConnected() const {
543
578
  return impl_->hasFuseboxClientConnected();
544
579
  }
545
580
 
546
- void HostAgent::emitExternalTraceRecording(
547
- tracing::TraceRecordingState traceRecording) const {
548
- impl_->emitExternalTraceRecording(std::move(traceRecording));
581
+ void HostAgent::emitExternalTracingProfile(
582
+ tracing::HostTracingProfile tracingProfile) const {
583
+ impl_->emitExternalTracingProfile(std::move(tracingProfile));
549
584
  }
550
585
 
551
586
  void HostAgent::emitSystemStateChanged(bool isSingleHost) const {
@@ -74,10 +74,10 @@ class HostAgent final {
74
74
  bool hasFuseboxClientConnected() const;
75
75
 
76
76
  /**
77
- * Emits the trace recording that was captured externally, not via the
77
+ * Emits the HostTracingProfile that was captured externally, not via the
78
78
  * CDP-initiated request.
79
79
  */
80
- void emitExternalTraceRecording(tracing::TraceRecordingState traceRecording) const;
80
+ void emitExternalTracingProfile(tracing::HostTracingProfile tracingProfile) const;
81
81
 
82
82
  /**
83
83
  * Emits a system state changed event when the number of ReactHost instances