react-native 0.85.2 → 0.85.3

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 (108) 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 -454
  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/src/main/java/com/facebook/react/devsupport/InspectorFlags.kt +4 -0
  24. package/ReactAndroid/src/main/java/com/facebook/react/devsupport/inspector/FrameTimingSequence.kt +1 -1
  25. package/ReactAndroid/src/main/java/com/facebook/react/devsupport/inspector/FrameTimingsObserver.kt +127 -26
  26. package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt +31 -1
  27. package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt +51 -1
  28. package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt +11 -1
  29. package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt +11 -1
  30. package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt +56 -1
  31. package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt +11 -1
  32. package/ReactAndroid/src/main/java/com/facebook/react/internal/tracing/PerformanceTracer.kt +39 -0
  33. package/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.kt +1 -1
  34. package/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.kt +50 -10
  35. package/ReactAndroid/src/main/jni/CMakeLists.txt +7 -0
  36. package/ReactAndroid/src/main/jni/react/devsupport/JInspectorFlags.cpp +22 -0
  37. package/ReactAndroid/src/main/jni/react/devsupport/JInspectorFlags.h +2 -0
  38. package/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp +71 -1
  39. package/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h +16 -1
  40. package/ReactAndroid/src/main/jni/react/runtime/jni/JReactHostInspectorTarget.cpp +14 -0
  41. package/ReactAndroid/src/main/jni/react/runtime/jni/JReactHostInspectorTarget.h +18 -4
  42. package/ReactCommon/React-Fabric.podspec +6 -0
  43. package/ReactCommon/cxxreact/ReactNativeVersion.h +2 -2
  44. package/ReactCommon/jsinspector-modern/HostAgent.cpp +36 -0
  45. package/ReactCommon/jsinspector-modern/HostTarget.cpp +7 -1
  46. package/ReactCommon/jsinspector-modern/HostTarget.h +25 -0
  47. package/ReactCommon/jsinspector-modern/HostTargetTracing.cpp +1 -1
  48. package/ReactCommon/jsinspector-modern/HostTargetTracing.h +4 -4
  49. package/ReactCommon/jsinspector-modern/InspectorFlags.cpp +12 -0
  50. package/ReactCommon/jsinspector-modern/InspectorFlags.h +12 -0
  51. package/ReactCommon/jsinspector-modern/NetworkIOAgent.cpp +1 -1
  52. package/ReactCommon/jsinspector-modern/RuntimeAgent.cpp +19 -0
  53. package/ReactCommon/jsinspector-modern/RuntimeAgent.h +7 -0
  54. package/ReactCommon/jsinspector-modern/RuntimeTarget.cpp +33 -0
  55. package/ReactCommon/jsinspector-modern/RuntimeTarget.h +6 -0
  56. package/ReactCommon/jsinspector-modern/tests/HostTargetTest.cpp +12 -0
  57. package/ReactCommon/jsinspector-modern/tests/InspectorMocks.h +3 -2
  58. package/ReactCommon/jsinspector-modern/tests/JsiIntegrationTest.cpp +1 -0
  59. package/ReactCommon/jsinspector-modern/tests/NetworkReporterTest.cpp +1 -1
  60. package/ReactCommon/jsinspector-modern/tests/TracingTest.cpp +1 -1
  61. package/ReactCommon/jsinspector-modern/tests/utils/InspectorFlagOverridesGuard.cpp +10 -0
  62. package/ReactCommon/jsinspector-modern/tests/utils/InspectorFlagOverridesGuard.h +3 -1
  63. package/ReactCommon/jsinspector-modern/tracing/CMakeLists.txt +1 -0
  64. package/ReactCommon/jsinspector-modern/tracing/FrameTimingSequence.h +7 -3
  65. package/ReactCommon/jsinspector-modern/tracing/HostTracingProfileSerializer.cpp +52 -29
  66. package/ReactCommon/jsinspector-modern/tracing/HostTracingProfileSerializer.h +6 -6
  67. package/ReactCommon/jsinspector-modern/tracing/PerformanceTracerSection.h +113 -0
  68. package/ReactCommon/jsinspector-modern/tracing/React-jsinspectortracing.podspec +1 -0
  69. package/ReactCommon/jsinspector-modern/tracing/TraceEventGenerator.cpp +12 -5
  70. package/ReactCommon/jsinspector-modern/tracing/TraceEventGenerator.h +3 -1
  71. package/ReactCommon/jsinspector-modern/tracing/TraceEventSerializer.cpp +42 -0
  72. package/ReactCommon/jsinspector-modern/tracing/TraceEventSerializer.h +7 -0
  73. package/ReactCommon/react/debug/CMakeLists.txt +2 -1
  74. package/ReactCommon/react/debug/React-debug.podspec +7 -1
  75. package/ReactCommon/react/debug/redbox/AnsiParser.cpp +139 -0
  76. package/ReactCommon/react/debug/redbox/AnsiParser.h +35 -0
  77. package/ReactCommon/react/debug/redbox/JscSafeUrl.cpp +179 -0
  78. package/ReactCommon/react/debug/redbox/JscSafeUrl.h +27 -0
  79. package/ReactCommon/react/debug/redbox/RedBoxErrorParser.cpp +171 -0
  80. package/ReactCommon/react/debug/redbox/RedBoxErrorParser.h +40 -0
  81. package/ReactCommon/react/debug/redbox/tests/AnsiParserTest.cpp +97 -0
  82. package/ReactCommon/react/debug/redbox/tests/JscSafeUrlTest.cpp +173 -0
  83. package/ReactCommon/react/debug/redbox/tests/RedBoxErrorParserTest.cpp +107 -0
  84. package/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp +21 -1
  85. package/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h +26 -1
  86. package/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp +135 -45
  87. package/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h +12 -2
  88. package/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h +21 -1
  89. package/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDynamicProvider.h +46 -1
  90. package/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h +6 -1
  91. package/ReactCommon/react/nativemodule/defaults/CMakeLists.txt +1 -0
  92. package/ReactCommon/react/nativemodule/defaults/DefaultTurboModules.cpp +7 -0
  93. package/ReactCommon/react/nativemodule/defaults/React-defaultsnativemodule.podspec +1 -0
  94. package/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp +26 -1
  95. package/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h +11 -1
  96. package/ReactCommon/react/nativemodule/mutationobserver/NativeMutationObserver.h +4 -0
  97. package/ReactCommon/react/nativemodule/mutationobserver/React-mutationobservernativemodule.podspec +66 -0
  98. package/ReactCommon/react/performance/timeline/PerformanceObserver.cpp +18 -6
  99. package/ReactCommon/react/performance/timeline/PerformanceObserver.h +2 -0
  100. package/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTHost.mm +115 -0
  101. package/ReactCommon/{jsinspector-modern → react/utils}/Base64.h +2 -2
  102. package/package.json +11 -11
  103. package/scripts/cocoapods/utils.rb +1 -0
  104. package/scripts/react_native_pods.rb +1 -0
  105. package/scripts/replace-rncore-version.js +72 -15
  106. package/src/private/featureflags/ReactNativeFeatureFlags.js +26 -1
  107. package/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js +6 -1
  108. package/src/private/setup/setUpDefaultReactNativeEnvironment.js +6 -0
@@ -93,7 +93,7 @@ void HostTarget::recordFrameTimings(
93
93
  std::lock_guard lock(tracingMutex_);
94
94
 
95
95
  if (traceRecording_) {
96
- traceRecording_->recordFrameTimings(frameTimingSequence);
96
+ traceRecording_->recordFrameTimings(std::move(frameTimingSequence));
97
97
  } else {
98
98
  assert(
99
99
  false &&
@@ -35,10 +35,10 @@ void emitNotificationsForTracingProfile(
35
35
  std::convertible_to<std::ranges::range_value_t<ChannelsRange>, FrontendChannel>
36
36
  {
37
37
  /**
38
- * Threshold for the size Trace Event chunk, that will be flushed out with
39
- * Tracing.dataCollected event.
38
+ * Maximum serialized byte size of a Trace Event chunk before it is flushed
39
+ * with a Tracing.dataCollected event.
40
40
  */
41
- static constexpr uint16_t TRACE_EVENT_CHUNK_SIZE = 1000;
41
+ static constexpr size_t TRACE_EVENT_CHUNK_MAX_BYTES = 10 * 1024 * 1024; // 10 MiB
42
42
 
43
43
  /**
44
44
  * The maximum number of ProfileChunk trace events
@@ -65,7 +65,7 @@ void emitNotificationsForTracingProfile(
65
65
  cdp::jsonNotification("Tracing.dataCollected", folly::dynamic::object("value", serializedChunk)));
66
66
  }
67
67
  },
68
- TRACE_EVENT_CHUNK_SIZE,
68
+ TRACE_EVENT_CHUNK_MAX_BYTES,
69
69
  PROFILE_TRACE_EVENT_CHUNK_SIZE);
70
70
 
71
71
  for (auto &frontendChannel : channels) {
@@ -21,6 +21,14 @@ bool InspectorFlags::getAssertSingleHostState() const {
21
21
  return loadFlagsAndAssertUnchanged().assertSingleHostState;
22
22
  }
23
23
 
24
+ bool InspectorFlags::getScreenshotCaptureEnabled() const {
25
+ return loadFlagsAndAssertUnchanged().screenshotCaptureEnabled;
26
+ }
27
+
28
+ bool InspectorFlags::getFrameRecordingEnabled() const {
29
+ return loadFlagsAndAssertUnchanged().frameRecordingEnabled;
30
+ }
31
+
24
32
  bool InspectorFlags::getFuseboxEnabled() const {
25
33
  if (fuseboxDisabledForTest_) {
26
34
  return false;
@@ -54,6 +62,10 @@ const InspectorFlags::Values& InspectorFlags::loadFlagsAndAssertUnchanged()
54
62
  InspectorFlags::Values newValues = {
55
63
  .assertSingleHostState =
56
64
  ReactNativeFeatureFlags::fuseboxAssertSingleHostState(),
65
+ .screenshotCaptureEnabled =
66
+ ReactNativeFeatureFlags::fuseboxScreenshotCaptureEnabled(),
67
+ .frameRecordingEnabled =
68
+ ReactNativeFeatureFlags::fuseboxFrameRecordingEnabled(),
57
69
  .fuseboxEnabled =
58
70
  #if defined(REACT_NATIVE_DEBUGGER_ENABLED)
59
71
  true,
@@ -36,6 +36,16 @@ class InspectorFlags {
36
36
  */
37
37
  bool getIsProfilingBuild() const;
38
38
 
39
+ /**
40
+ * Flag determining if Page.captureScreenshot CDP method is enabled.
41
+ */
42
+ bool getScreenshotCaptureEnabled() const;
43
+
44
+ /**
45
+ * Flag determining if frame recording (timings + screenshots) is enabled.
46
+ */
47
+ bool getFrameRecordingEnabled() const;
48
+
39
49
  /**
40
50
  * Flag determining if network inspection is enabled.
41
51
  */
@@ -61,6 +71,8 @@ class InspectorFlags {
61
71
  private:
62
72
  struct Values {
63
73
  bool assertSingleHostState;
74
+ bool screenshotCaptureEnabled;
75
+ bool frameRecordingEnabled;
64
76
  bool fuseboxEnabled;
65
77
  bool isProfilingBuild;
66
78
  bool networkInspectionEnabled;
@@ -8,10 +8,10 @@
8
8
  #include "NetworkIOAgent.h"
9
9
  #include "InspectorFlags.h"
10
10
 
11
- #include "Base64.h"
12
11
  #include "Utf8.h"
13
12
 
14
13
  #include <jsinspector-modern/network/NetworkHandler.h>
14
+ #include <react/utils/Base64.h>
15
15
 
16
16
  #include <sstream>
17
17
  #include <tuple>
@@ -8,6 +8,10 @@
8
8
  #include "RuntimeAgent.h"
9
9
  #include "SessionState.h"
10
10
 
11
+ #include <folly/dynamic.h>
12
+ #include <jsinspector-modern/cdp/CdpJson.h>
13
+
14
+ #include <chrono>
11
15
  #include <utility>
12
16
 
13
17
  namespace facebook::react::jsinspector_modern {
@@ -119,6 +123,21 @@ void RuntimeAgent::notifyBindingCalled(
119
123
  "name", bindingName)("payload", payload)));
120
124
  }
121
125
 
126
+ void RuntimeAgent::notifyFastRefreshComplete() {
127
+ if (!sessionState_.isReactNativeApplicationDomainEnabled) {
128
+ return;
129
+ }
130
+ folly::dynamic params = folly::dynamic::object(
131
+ "timestamp",
132
+ std::chrono::duration_cast<std::chrono::milliseconds>(
133
+ std::chrono::system_clock::now().time_since_epoch())
134
+ .count());
135
+ frontendChannel_(
136
+ cdp::jsonNotification(
137
+ "ReactNativeApplication.unstable_fastRefreshComplete",
138
+ std::move(params)));
139
+ }
140
+
122
141
  RuntimeAgent::ExportedState RuntimeAgent::getExportedState() {
123
142
  return {
124
143
  .delegateState = delegate_ ? delegate_->getExportedState() : nullptr,
@@ -72,6 +72,13 @@ class RuntimeAgent final {
72
72
 
73
73
  void notifyBindingCalled(const std::string &bindingName, const std::string &payload);
74
74
 
75
+ /**
76
+ * Called by RuntimeTarget when JS calls __notifyFastRefreshComplete().
77
+ * Emits a ReactNativeApplication.unstable_fastRefreshComplete CDP
78
+ * notification if the ReactNativeApplication domain is enabled.
79
+ */
80
+ void notifyFastRefreshComplete();
81
+
75
82
  struct ExportedState {
76
83
  std::unique_ptr<RuntimeAgentDelegate::ExportedState> delegateState;
77
84
  };
@@ -47,6 +47,8 @@ void RuntimeTarget::installGlobals() {
47
47
  // NOTE: RuntimeTarget::installNetworkReporterAPI is in
48
48
  // RuntimeTargetNetwork.cpp
49
49
  installNetworkReporterAPI();
50
+
51
+ installFastRefreshHandler();
50
52
  }
51
53
 
52
54
  std::shared_ptr<RuntimeAgent> RuntimeTarget::createAgent(
@@ -128,6 +130,37 @@ void RuntimeTarget::installBindingHandler(const std::string& bindingName) {
128
130
  });
129
131
  }
130
132
 
133
+ void RuntimeTarget::installFastRefreshHandler() {
134
+ jsExecutor_([selfExecutor = executorFromThis()](jsi::Runtime& runtime) {
135
+ auto globalObj = runtime.global();
136
+ try {
137
+ auto name =
138
+ jsi::PropNameID::forUtf8(runtime, "__notifyFastRefreshComplete");
139
+ globalObj.setProperty(
140
+ runtime,
141
+ name,
142
+ jsi::Function::createFromHostFunction(
143
+ runtime,
144
+ name,
145
+ 0,
146
+ [selfExecutor](
147
+ jsi::Runtime& /*rt*/,
148
+ const jsi::Value&,
149
+ const jsi::Value*,
150
+ size_t) -> jsi::Value {
151
+ selfExecutor([](auto& self) {
152
+ self.agents_.forEach(
153
+ [](auto& agent) { agent.notifyFastRefreshComplete(); });
154
+ });
155
+
156
+ return jsi::Value::undefined();
157
+ }));
158
+ } catch (jsi::JSError&) {
159
+ // Swallow JavaScript exceptions that occur while setting up the global.
160
+ }
161
+ });
162
+ }
163
+
131
164
  void RuntimeTarget::emitDebuggerSessionCreated() {
132
165
  jsExecutor_([selfExecutor = executorFromThis()](jsi::Runtime& runtime) {
133
166
  try {
@@ -295,6 +295,12 @@ class JSINSPECTOR_EXPORT RuntimeTarget : public EnableExecutorFromThis<RuntimeTa
295
295
  */
296
296
  void installGlobals();
297
297
 
298
+ /**
299
+ * Installs __notifyFastRefreshComplete on the runtime's global object.
300
+ * When called from JS, dispatches to all connected RuntimeAgents.
301
+ */
302
+ void installFastRefreshHandler();
303
+
298
304
  /**
299
305
  * Install the console API handler.
300
306
  */
@@ -1579,4 +1579,16 @@ TEST_F(HostTargetTest, TracingDelegateIsNotifiedOnDirectTracingCall) {
1579
1579
  page_->stopTracing();
1580
1580
  }
1581
1581
 
1582
+ TEST_F(HostTargetProtocolTest, CaptureScreenshotNotSupportedWhenFlagDisabled) {
1583
+ EXPECT_CALL(
1584
+ fromPage(),
1585
+ onMessage(JsonParsed(AllOf(
1586
+ AtJsonPtr("/error/code", Eq(-32601)), AtJsonPtr("/id", Eq(1))))))
1587
+ .RetiresOnSaturation();
1588
+ toPage_->sendMessage(R"({
1589
+ "id": 1,
1590
+ "method": "Page.captureScreenshot"
1591
+ })");
1592
+ }
1593
+
1582
1594
  } // namespace facebook::react::jsinspector_modern
@@ -87,13 +87,13 @@ class MockInspectorPackagerConnectionDelegate : public InspectorPackagerConnecti
87
87
  explicit MockInspectorPackagerConnectionDelegate(folly::Executor &executor) : executor_(executor)
88
88
  {
89
89
  using namespace testing;
90
- ON_CALL(*this, scheduleCallback(_, _)).WillByDefault(Invoke<>([this](auto callback, auto delay) {
90
+ ON_CALL(*this, scheduleCallback(_, _)).WillByDefault([this](auto callback, auto delay) {
91
91
  if (auto scheduledExecutor = dynamic_cast<folly::ScheduledExecutor *>(&executor_)) {
92
92
  scheduledExecutor->scheduleAt(callback, scheduledExecutor->now() + delay);
93
93
  } else {
94
94
  executor_.add(callback);
95
95
  }
96
- }));
96
+ });
97
97
  EXPECT_CALL(*this, scheduleCallback(_, _)).Times(AnyNumber());
98
98
  }
99
99
 
@@ -137,6 +137,7 @@ class MockHostTargetDelegate : public HostTargetDelegate {
137
137
  loadNetworkResource,
138
138
  (const LoadNetworkResourceRequest &params, ScopedExecutor<NetworkRequestListener> executor),
139
139
  (override));
140
+ MOCK_METHOD(std::optional<std::string>, captureScreenshot, (const PageCaptureScreenshotRequest &request), (override));
140
141
 
141
142
  HostTargetTracingDelegate *getTracingDelegate() override
142
143
  {
@@ -358,6 +358,7 @@ TYPED_TEST(JsiIntegrationPortableTest, ReactNativeApplicationEnable) {
358
358
  "method": "ReactNativeApplication.metadataUpdated",
359
359
  "params": {
360
360
  "integrationName": "JsiIntegrationTest",
361
+ "unstable_frameRecordingEnabled": false,
361
362
  "unstable_isProfilingBuild": false,
362
363
  "unstable_networkInspectionEnabled": false
363
364
  }
@@ -38,10 +38,10 @@ class NetworkReporterTestBase : public TracingTestBase<
38
38
  protected:
39
39
  NetworkReporterTestBase()
40
40
  : TracingTestBase({
41
- .networkInspectionEnabled = true,
42
41
  .enableNetworkEventReporting =
43
42
  WithParamInterface<Params>::GetParam()
44
43
  .enableNetworkEventReporting,
44
+ .networkInspectionEnabled = true,
45
45
  }) {}
46
46
 
47
47
  void SetUp() override {
@@ -103,7 +103,7 @@ TEST_F(TracingTest, EmitsScreenshotEventWhenScreenshotValuePassed) {
103
103
  11, // threadId
104
104
  now,
105
105
  now + HighResDuration::fromNanoseconds(50),
106
- "base64EncodedScreenshotData"));
106
+ std::vector<uint8_t>{}));
107
107
 
108
108
  auto allTraceEvents = endTracingAndCollectEvents();
109
109
  EXPECT_THAT(allTraceEvents, Contains(AtJsonPtr("/name", "Screenshot")));
@@ -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)
@@ -11,6 +11,10 @@
11
11
 
12
12
  #include <react/timing/primitives.h>
13
13
 
14
+ #include <cstdint>
15
+ #include <optional>
16
+ #include <vector>
17
+
14
18
  namespace facebook::react::jsinspector_modern::tracing {
15
19
 
16
20
  using FrameSequenceId = uint64_t;
@@ -26,7 +30,7 @@ struct FrameTimingSequence {
26
30
  ThreadId threadId,
27
31
  HighResTimeStamp beginTimestamp,
28
32
  HighResTimeStamp endTimestamp,
29
- std::optional<std::string> screenshot = std::nullopt)
33
+ std::optional<std::vector<uint8_t>> screenshot = std::nullopt)
30
34
  : id(id),
31
35
  threadId(threadId),
32
36
  beginTimestamp(beginTimestamp),
@@ -49,9 +53,9 @@ struct FrameTimingSequence {
49
53
  HighResTimeStamp endTimestamp;
50
54
 
51
55
  /**
52
- * Optional screenshot data (base64 encoded) captured during the frame.
56
+ * Optional screenshot data captured during the frame.
53
57
  */
54
- std::optional<std::string> screenshot;
58
+ std::optional<std::vector<uint8_t>> screenshot;
55
59
  };
56
60
 
57
61
  } // namespace facebook::react::jsinspector_modern::tracing
@@ -14,13 +14,6 @@ namespace facebook::react::jsinspector_modern::tracing {
14
14
 
15
15
  namespace {
16
16
 
17
- folly::dynamic generateNewChunk(uint16_t chunkSize) {
18
- folly::dynamic chunk = folly::dynamic::array();
19
- chunk.reserve(chunkSize);
20
-
21
- return chunk;
22
- }
23
-
24
17
  /**
25
18
  * Hardcoded layer tree ID for all recorded frames.
26
19
  * https://chromedevtools.github.io/devtools-protocol/tot/LayerTree/
@@ -32,14 +25,14 @@ constexpr int FALLBACK_LAYER_TREE_ID = 1;
32
25
  /* static */ void HostTracingProfileSerializer::emitAsDataCollectedChunks(
33
26
  HostTracingProfile&& hostTracingProfile,
34
27
  const std::function<void(folly::dynamic&&)>& chunkCallback,
35
- uint16_t traceEventsChunkSize,
28
+ size_t maxChunkBytes,
36
29
  uint16_t profileTraceEventsChunkSize) {
37
30
  emitFrameTimings(
38
31
  std::move(hostTracingProfile.frameTimings),
39
32
  hostTracingProfile.processId,
40
33
  hostTracingProfile.startTime,
41
34
  chunkCallback,
42
- traceEventsChunkSize);
35
+ maxChunkBytes);
43
36
 
44
37
  auto instancesProfiles =
45
38
  std::move(hostTracingProfile.instanceTracingProfiles);
@@ -49,7 +42,7 @@ constexpr int FALLBACK_LAYER_TREE_ID = 1;
49
42
  emitPerformanceTraceEvents(
50
43
  std::move(instanceProfile.performanceTraceEvents),
51
44
  chunkCallback,
52
- traceEventsChunkSize);
45
+ maxChunkBytes);
53
46
  }
54
47
 
55
48
  RuntimeSamplingProfileTraceEventSerializer::serializeAndDispatch(
@@ -63,16 +56,22 @@ constexpr int FALLBACK_LAYER_TREE_ID = 1;
63
56
  /* static */ void HostTracingProfileSerializer::emitPerformanceTraceEvents(
64
57
  std::vector<TraceEvent>&& events,
65
58
  const std::function<void(folly::dynamic&&)>& chunkCallback,
66
- uint16_t chunkSize) {
67
- folly::dynamic chunk = generateNewChunk(chunkSize);
59
+ size_t maxChunkBytes) {
60
+ folly::dynamic chunk = folly::dynamic::array();
61
+ size_t currentChunkBytes = 0;
68
62
 
69
63
  for (auto& event : events) {
70
- if (chunk.size() == chunkSize) {
64
+ auto serializedEvent = TraceEventSerializer::serialize(std::move(event));
65
+ size_t eventBytes = TraceEventSerializer::estimateJsonSize(serializedEvent);
66
+
67
+ if (currentChunkBytes + eventBytes > maxChunkBytes && !chunk.empty()) {
71
68
  chunkCallback(std::move(chunk));
72
- chunk = generateNewChunk(chunkSize);
69
+ chunk = folly::dynamic::array();
70
+ currentChunkBytes = 0;
73
71
  }
74
72
 
75
- chunk.push_back(TraceEventSerializer::serialize(std::move(event)));
73
+ chunk.push_back(std::move(serializedEvent));
74
+ currentChunkBytes += eventBytes;
76
75
  }
77
76
 
78
77
  if (!chunk.empty()) {
@@ -85,26 +84,30 @@ constexpr int FALLBACK_LAYER_TREE_ID = 1;
85
84
  ProcessId processId,
86
85
  HighResTimeStamp recordingStartTimestamp,
87
86
  const std::function<void(folly::dynamic&& chunk)>& chunkCallback,
88
- uint16_t chunkSize) {
87
+ size_t maxChunkBytes) {
89
88
  if (frameTimings.empty()) {
90
89
  return;
91
90
  }
92
91
 
93
- folly::dynamic chunk = generateNewChunk(chunkSize);
92
+ folly::dynamic chunk = folly::dynamic::array();
93
+ size_t currentChunkBytes = 0;
94
+
94
95
  auto setLayerTreeIdEvent = TraceEventGenerator::createSetLayerTreeIdEvent(
95
96
  "", // Hardcoded frame name for the default (and only) layer.
96
97
  FALLBACK_LAYER_TREE_ID,
97
98
  processId,
98
99
  frameTimings.front().threadId,
99
100
  recordingStartTimestamp);
100
- chunk.push_back(
101
- TraceEventSerializer::serialize(std::move(setLayerTreeIdEvent)));
101
+ auto serializedSetLayerTreeId =
102
+ TraceEventSerializer::serialize(std::move(setLayerTreeIdEvent));
103
+ currentChunkBytes +=
104
+ TraceEventSerializer::estimateJsonSize(serializedSetLayerTreeId);
105
+ chunk.push_back(std::move(serializedSetLayerTreeId));
102
106
 
103
107
  for (auto&& frameTimingSequence : frameTimings) {
104
- if (chunk.size() >= chunkSize) {
105
- chunkCallback(std::move(chunk));
106
- chunk = generateNewChunk(chunkSize);
107
- }
108
+ // Serialize all events for this frame.
109
+ folly::dynamic frameEvents = folly::dynamic::array();
110
+ size_t totalFrameBytes = 0;
108
111
 
109
112
  auto [beginDrawingEvent, endDrawingEvent] =
110
113
  TraceEventGenerator::createFrameTimingsEvents(
@@ -115,10 +118,15 @@ constexpr int FALLBACK_LAYER_TREE_ID = 1;
115
118
  processId,
116
119
  frameTimingSequence.threadId);
117
120
 
118
- chunk.push_back(
119
- TraceEventSerializer::serialize(std::move(beginDrawingEvent)));
120
- chunk.push_back(
121
- TraceEventSerializer::serialize(std::move(endDrawingEvent)));
121
+ auto serializedBegin =
122
+ TraceEventSerializer::serialize(std::move(beginDrawingEvent));
123
+ totalFrameBytes += TraceEventSerializer::estimateJsonSize(serializedBegin);
124
+ frameEvents.push_back(std::move(serializedBegin));
125
+
126
+ auto serializedEnd =
127
+ TraceEventSerializer::serialize(std::move(endDrawingEvent));
128
+ totalFrameBytes += TraceEventSerializer::estimateJsonSize(serializedEnd);
129
+ frameEvents.push_back(std::move(serializedEnd));
122
130
 
123
131
  if (frameTimingSequence.screenshot.has_value()) {
124
132
  auto screenshotEvent = TraceEventGenerator::createScreenshotEvent(
@@ -129,9 +137,24 @@ constexpr int FALLBACK_LAYER_TREE_ID = 1;
129
137
  processId,
130
138
  frameTimingSequence.threadId);
131
139
 
132
- chunk.push_back(
133
- TraceEventSerializer::serialize(std::move(screenshotEvent)));
140
+ auto serializedScreenshot =
141
+ TraceEventSerializer::serialize(std::move(screenshotEvent));
142
+ totalFrameBytes +=
143
+ TraceEventSerializer::estimateJsonSize(serializedScreenshot);
144
+ frameEvents.push_back(std::move(serializedScreenshot));
145
+ }
146
+
147
+ // Flush current chunk if adding this frame would exceed the limit.
148
+ if (currentChunkBytes + totalFrameBytes > maxChunkBytes && !chunk.empty()) {
149
+ chunkCallback(std::move(chunk));
150
+ chunk = folly::dynamic::array();
151
+ currentChunkBytes = 0;
152
+ }
153
+
154
+ for (auto& frameEvent : frameEvents) {
155
+ chunk.push_back(std::move(frameEvent));
134
156
  }
157
+ currentChunkBytes += totalFrameBytes;
135
158
  }
136
159
 
137
160
  if (!chunk.empty()) {
@@ -24,27 +24,27 @@ class HostTracingProfileSerializer {
24
24
  public:
25
25
  /**
26
26
  * Transforms the profile into a sequence of serialized Trace Events, which
27
- * is split in chunks of sizes \p traceEventsChunkSize or
28
- * \p profileTraceEventsChunkSize, depending on type, and sent with \p
29
- * chunkCallback.
27
+ * is split in chunks of at most \p maxChunkBytes serialized bytes or
28
+ * \p profileTraceEventsChunkSize events, depending on type, and sent with
29
+ * \p chunkCallback.
30
30
  */
31
31
  static void emitAsDataCollectedChunks(
32
32
  HostTracingProfile &&hostTracingProfile,
33
33
  const std::function<void(folly::dynamic &&chunk)> &chunkCallback,
34
- uint16_t traceEventsChunkSize,
34
+ size_t maxChunkBytes,
35
35
  uint16_t profileTraceEventsChunkSize);
36
36
 
37
37
  static void emitPerformanceTraceEvents(
38
38
  std::vector<TraceEvent> &&events,
39
39
  const std::function<void(folly::dynamic &&chunk)> &chunkCallback,
40
- uint16_t chunkSize);
40
+ size_t maxChunkBytes);
41
41
 
42
42
  static void emitFrameTimings(
43
43
  std::vector<FrameTimingSequence> &&frameTimings,
44
44
  ProcessId processId,
45
45
  HighResTimeStamp recordingStartTimestamp,
46
46
  const std::function<void(folly::dynamic &&chunk)> &chunkCallback,
47
- uint16_t chunkSize);
47
+ size_t maxChunkBytes);
48
48
  };
49
49
 
50
50
  } // namespace facebook::react::jsinspector_modern::tracing
@@ -0,0 +1,113 @@
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 <folly/dynamic.h>
11
+
12
+ #include <jsinspector-modern/tracing/PerformanceTracer.h>
13
+
14
+ #include <string_view>
15
+
16
+ namespace facebook::react::jsinspector_modern::tracing {
17
+
18
+ /**
19
+ * This is a RAII class that reports a timeStamp block to the React Native
20
+ * Performance Tracer.
21
+ *
22
+ * @example
23
+ * {
24
+ * PerformanceTracerSection s("name", "track", "track group");
25
+ * // do something
26
+ * }
27
+ */
28
+ template <typename... Args>
29
+ class PerformanceTracerSection {
30
+ public:
31
+ explicit PerformanceTracerSection(
32
+ const char *name,
33
+ const char *track = nullptr,
34
+ const char *trackGroup = nullptr,
35
+ const char *color = nullptr,
36
+ Args... args) noexcept
37
+ : name_(name), track_(track), trackGroup_(trackGroup), color_(color), args_(std::move(args)...)
38
+ {
39
+ static_assert(
40
+ sizeof...(Args) % 2 == 0,
41
+ "PerformanceTracerSection expects an even number of variadic args representing [name, value] pairs.");
42
+ }
43
+
44
+ // Non-movable
45
+ PerformanceTracerSection(const PerformanceTracerSection &) = delete;
46
+ PerformanceTracerSection(PerformanceTracerSection &&) = delete;
47
+
48
+ // Non-copyable
49
+ PerformanceTracerSection &operator=(const PerformanceTracerSection &) = delete;
50
+ PerformanceTracerSection &operator=(PerformanceTracerSection &&) = delete;
51
+
52
+ ~PerformanceTracerSection() noexcept
53
+ {
54
+ auto &tracer = PerformanceTracer::getInstance();
55
+ if (!tracer.isTracing()) {
56
+ return;
57
+ }
58
+
59
+ auto endTime = HighResTimeStamp::now();
60
+
61
+ // Slow path when passing properties
62
+ if constexpr (sizeof...(Args) > 0) {
63
+ auto properties = folly::dynamic::array();
64
+ std::apply(
65
+ [&](const auto &...elems) {
66
+ size_t idx = 0;
67
+ (((idx % 2 == 0) ? properties.push_back(folly::dynamic::array(elems))
68
+ : properties[properties.size() - 1].push_back(elems),
69
+ ++idx),
70
+ ...);
71
+ },
72
+ args_);
73
+
74
+ folly::dynamic devtools = folly::dynamic::object();
75
+ devtools["properties"] = std::move(properties);
76
+
77
+ if (track_ != nullptr) {
78
+ devtools["track"] = track_;
79
+ }
80
+
81
+ if (trackGroup_ != nullptr) {
82
+ devtools["trackGroup"] = trackGroup_;
83
+ }
84
+
85
+ if (color_ != nullptr) {
86
+ devtools["color"] = color_;
87
+ }
88
+
89
+ folly::dynamic detail = folly::dynamic::object();
90
+ detail["devtools"] = std::move(devtools);
91
+
92
+ tracer.reportMeasure(std::string(name_), startTime_, endTime - startTime_, std::move(detail));
93
+ } else {
94
+ tracer.reportTimeStamp(
95
+ std::string(name_),
96
+ startTime_,
97
+ endTime,
98
+ track_ != nullptr ? std::optional{track_} : std::nullopt,
99
+ trackGroup_ != nullptr ? std::optional{trackGroup_} : std::nullopt,
100
+ color_ != nullptr ? getConsoleTimeStampColorFromString(color_) : std::nullopt);
101
+ }
102
+ }
103
+
104
+ private:
105
+ HighResTimeStamp startTime_{HighResTimeStamp::now()};
106
+ std::string_view name_;
107
+ const char *track_;
108
+ const char *trackGroup_;
109
+ const char *color_;
110
+ std::tuple<Args...> args_;
111
+ };
112
+
113
+ } // namespace facebook::react::jsinspector_modern::tracing
@@ -47,6 +47,7 @@ Pod::Spec.new do |s|
47
47
  s.dependency "React-jsi"
48
48
  s.dependency "React-oscompat"
49
49
  s.dependency "React-timing"
50
+ add_dependency(s, "React-utils", :additional_framework_paths => ["react/utils/platform/ios"])
50
51
 
51
52
  if use_hermes()
52
53
  s.dependency "hermes-engine"