react-native-tvos 0.85.0-0rc5 → 0.85.3-0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (154) hide show
  1. package/Libraries/Components/ScrollView/AndroidHorizontalScrollViewNativeComponent.js +1 -0
  2. package/Libraries/Components/ScrollView/ScrollView.d.ts +7 -0
  3. package/Libraries/Components/ScrollView/ScrollView.js +6 -0
  4. package/Libraries/Components/ScrollView/ScrollViewNativeComponent.js +2 -0
  5. package/Libraries/Components/ScrollView/ScrollViewNativeComponentType.js +1 -0
  6. package/Libraries/Components/TextInput/AndroidTextInputNativeComponent.js +5 -1
  7. package/Libraries/Components/TextInput/TextInput.flow.js +1 -0
  8. package/Libraries/Core/ReactNativeVersion.js +2 -2
  9. package/Libraries/Utilities/HMRClient.js +28 -1
  10. package/README.md +52 -0
  11. package/React/Base/RCTVersion.m +2 -2
  12. package/React/CoreModules/RCTDevLoadingView.mm +17 -0
  13. package/React/CoreModules/RCTJscSafeUrl+Internal.h +23 -0
  14. package/React/CoreModules/RCTJscSafeUrl.mm +38 -0
  15. package/React/CoreModules/RCTRedBox+Internal.h +42 -0
  16. package/React/CoreModules/RCTRedBox.mm +30 -471
  17. package/React/CoreModules/RCTRedBox2AnsiParser+Internal.h +22 -0
  18. package/React/CoreModules/RCTRedBox2AnsiParser.mm +55 -0
  19. package/React/CoreModules/RCTRedBox2Controller+Internal.h +34 -0
  20. package/React/CoreModules/RCTRedBox2Controller.mm +764 -0
  21. package/React/CoreModules/RCTRedBox2ErrorParser+Internal.h +46 -0
  22. package/React/CoreModules/RCTRedBox2ErrorParser.mm +57 -0
  23. package/React/CoreModules/RCTRedBoxController+Internal.h +31 -0
  24. package/React/CoreModules/RCTRedBoxController.mm +447 -0
  25. package/React/CoreModules/RCTRedBoxHMRClient+Internal.h +26 -0
  26. package/React/CoreModules/RCTRedBoxHMRClient.mm +125 -0
  27. package/React/CoreModules/React-CoreModules.podspec +1 -0
  28. package/React/DevSupport/RCTFrameTimingsObserver.h +24 -0
  29. package/React/DevSupport/RCTFrameTimingsObserver.mm +298 -0
  30. package/React/FBReactNativeSpec/FBReactNativeSpecJSI.h +40 -0
  31. package/React/Fabric/Mounting/ComponentViews/ScrollView/RCTEnhancedScrollView.h +1 -0
  32. package/React/Fabric/Mounting/ComponentViews/ScrollView/RCTEnhancedScrollView.mm +78 -0
  33. package/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm +32 -6
  34. package/React/Views/ScrollView/RCTScrollViewManager.m +1 -0
  35. package/ReactAndroid/build.gradle.kts +2 -0
  36. package/ReactAndroid/gradle.properties +1 -1
  37. package/ReactAndroid/hermes-engine/build.gradle.kts +17 -0
  38. package/ReactAndroid/publish.gradle +20 -46
  39. package/ReactAndroid/src/main/java/com/facebook/react/devsupport/InspectorFlags.kt +4 -0
  40. package/ReactAndroid/src/main/java/com/facebook/react/devsupport/inspector/FrameTimingSequence.kt +1 -1
  41. package/ReactAndroid/src/main/java/com/facebook/react/devsupport/inspector/FrameTimingsObserver.kt +127 -26
  42. package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt +31 -1
  43. package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt +51 -1
  44. package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt +11 -1
  45. package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt +12 -2
  46. package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt +56 -1
  47. package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsOverrides_RNOSS_Experimental_Android.kt +5 -1
  48. package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt +11 -1
  49. package/ReactAndroid/src/main/java/com/facebook/react/internal/tracing/PerformanceTracer.kt +39 -0
  50. package/ReactAndroid/src/main/java/com/facebook/react/modules/network/NetworkEventUtil.kt +8 -0
  51. package/ReactAndroid/src/main/java/com/facebook/react/modules/network/RequestBodyUtil.kt +2 -0
  52. package/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.kt +2 -2
  53. package/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.kt +50 -10
  54. package/ReactAndroid/src/main/java/com/facebook/react/views/common/UiModeUtils.kt +20 -0
  55. package/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java +57 -8
  56. package/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollViewManager.kt +5 -0
  57. package/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java +48 -2
  58. package/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewManager.kt +5 -0
  59. package/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextView.java +28 -3
  60. package/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.kt +5 -0
  61. package/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputSubmitEditingEvent.kt +6 -1
  62. package/ReactAndroid/src/main/jni/CMakeLists.txt +7 -0
  63. package/ReactAndroid/src/main/jni/react/devsupport/JInspectorFlags.cpp +22 -0
  64. package/ReactAndroid/src/main/jni/react/devsupport/JInspectorFlags.h +2 -0
  65. package/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp +71 -1
  66. package/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h +16 -1
  67. package/ReactAndroid/src/main/jni/react/runtime/jni/JReactHostInspectorTarget.cpp +14 -0
  68. package/ReactAndroid/src/main/jni/react/runtime/jni/JReactHostInspectorTarget.h +18 -4
  69. package/ReactCommon/React-Fabric.podspec +7 -0
  70. package/ReactCommon/cxxreact/ReactNativeVersion.h +3 -3
  71. package/ReactCommon/jsinspector-modern/HostAgent.cpp +36 -0
  72. package/ReactCommon/jsinspector-modern/HostTarget.cpp +7 -1
  73. package/ReactCommon/jsinspector-modern/HostTarget.h +25 -0
  74. package/ReactCommon/jsinspector-modern/HostTargetTracing.cpp +1 -1
  75. package/ReactCommon/jsinspector-modern/HostTargetTracing.h +4 -4
  76. package/ReactCommon/jsinspector-modern/InspectorFlags.cpp +12 -0
  77. package/ReactCommon/jsinspector-modern/InspectorFlags.h +12 -0
  78. package/ReactCommon/jsinspector-modern/NetworkIOAgent.cpp +1 -1
  79. package/ReactCommon/jsinspector-modern/RuntimeAgent.cpp +19 -0
  80. package/ReactCommon/jsinspector-modern/RuntimeAgent.h +7 -0
  81. package/ReactCommon/jsinspector-modern/RuntimeTarget.cpp +33 -0
  82. package/ReactCommon/jsinspector-modern/RuntimeTarget.h +6 -0
  83. package/ReactCommon/jsinspector-modern/tests/HostTargetTest.cpp +12 -0
  84. package/ReactCommon/jsinspector-modern/tests/InspectorMocks.h +3 -2
  85. package/ReactCommon/jsinspector-modern/tests/JsiIntegrationTest.cpp +1 -0
  86. package/ReactCommon/jsinspector-modern/tests/NetworkReporterTest.cpp +1 -1
  87. package/ReactCommon/jsinspector-modern/tests/TracingTest.cpp +1 -1
  88. package/ReactCommon/jsinspector-modern/tests/utils/InspectorFlagOverridesGuard.cpp +10 -0
  89. package/ReactCommon/jsinspector-modern/tests/utils/InspectorFlagOverridesGuard.h +3 -1
  90. package/ReactCommon/jsinspector-modern/tracing/CMakeLists.txt +1 -0
  91. package/ReactCommon/jsinspector-modern/tracing/FrameTimingSequence.h +7 -3
  92. package/ReactCommon/jsinspector-modern/tracing/HostTracingProfileSerializer.cpp +52 -29
  93. package/ReactCommon/jsinspector-modern/tracing/HostTracingProfileSerializer.h +6 -6
  94. package/ReactCommon/jsinspector-modern/tracing/PerformanceTracerSection.h +113 -0
  95. package/ReactCommon/jsinspector-modern/tracing/React-jsinspectortracing.podspec +1 -0
  96. package/ReactCommon/jsinspector-modern/tracing/TraceEventGenerator.cpp +12 -5
  97. package/ReactCommon/jsinspector-modern/tracing/TraceEventGenerator.h +3 -1
  98. package/ReactCommon/jsinspector-modern/tracing/TraceEventSerializer.cpp +42 -0
  99. package/ReactCommon/jsinspector-modern/tracing/TraceEventSerializer.h +7 -0
  100. package/ReactCommon/react/debug/CMakeLists.txt +2 -1
  101. package/ReactCommon/react/debug/React-debug.podspec +7 -1
  102. package/ReactCommon/react/debug/redbox/AnsiParser.cpp +139 -0
  103. package/ReactCommon/react/debug/redbox/AnsiParser.h +35 -0
  104. package/ReactCommon/react/debug/redbox/JscSafeUrl.cpp +179 -0
  105. package/ReactCommon/react/debug/redbox/JscSafeUrl.h +27 -0
  106. package/ReactCommon/react/debug/redbox/RedBoxErrorParser.cpp +171 -0
  107. package/ReactCommon/react/debug/redbox/RedBoxErrorParser.h +40 -0
  108. package/ReactCommon/react/debug/redbox/tests/AnsiParserTest.cpp +97 -0
  109. package/ReactCommon/react/debug/redbox/tests/JscSafeUrlTest.cpp +173 -0
  110. package/ReactCommon/react/debug/redbox/tests/RedBoxErrorParserTest.cpp +107 -0
  111. package/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp +21 -1
  112. package/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h +26 -1
  113. package/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp +135 -45
  114. package/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h +12 -2
  115. package/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h +22 -2
  116. package/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDynamicProvider.h +46 -1
  117. package/ReactCommon/react/featureflags/ReactNativeFeatureFlagsOverridesOSSExperimental.h +9 -1
  118. package/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h +6 -1
  119. package/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModule.mm +3 -1
  120. package/ReactCommon/react/nativemodule/defaults/CMakeLists.txt +1 -0
  121. package/ReactCommon/react/nativemodule/defaults/DefaultTurboModules.cpp +7 -0
  122. package/ReactCommon/react/nativemodule/defaults/React-defaultsnativemodule.podspec +1 -0
  123. package/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp +26 -1
  124. package/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h +11 -1
  125. package/ReactCommon/react/nativemodule/mutationobserver/NativeMutationObserver.h +4 -0
  126. package/ReactCommon/react/nativemodule/mutationobserver/React-mutationobservernativemodule.podspec +66 -0
  127. package/ReactCommon/react/performance/timeline/PerformanceObserver.cpp +18 -6
  128. package/ReactCommon/react/performance/timeline/PerformanceObserver.h +2 -0
  129. package/ReactCommon/react/renderer/animated/NativeAnimatedNodesManager.cpp +4 -1
  130. package/ReactCommon/react/renderer/animationbackend/AnimationBackend.cpp +58 -25
  131. package/ReactCommon/react/renderer/animationbackend/AnimationBackend.h +9 -0
  132. package/ReactCommon/react/renderer/animationbackend/AnimationChoreographer.h +5 -0
  133. package/ReactCommon/react/renderer/components/scrollview/BaseScrollViewProps.cpp +10 -0
  134. package/ReactCommon/react/renderer/components/scrollview/BaseScrollViewProps.h +1 -0
  135. package/ReactCommon/react/renderer/uimanager/UIManagerAnimationBackend.h +1 -0
  136. package/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTHost.mm +115 -0
  137. package/ReactCommon/{jsinspector-modern → react/utils}/Base64.h +2 -2
  138. package/package.json +11 -11
  139. package/scripts/cocoapods/utils.rb +1 -0
  140. package/scripts/codegen/generate-artifacts-executor/generateAppDependencyProvider.js +4 -4
  141. package/scripts/codegen/generate-artifacts-executor/generateCustomURLHandlers.js +3 -3
  142. package/scripts/codegen/generate-artifacts-executor/generateNativeCode.js +2 -3
  143. package/scripts/codegen/generate-artifacts-executor/generatePackageSwift.js +2 -2
  144. package/scripts/codegen/generate-artifacts-executor/generateRCTModuleProviders.js +3 -2
  145. package/scripts/codegen/generate-artifacts-executor/generateRCTThirdPartyComponents.js +3 -2
  146. package/scripts/codegen/generate-artifacts-executor/generateReactCodegenPodspec.js +2 -2
  147. package/scripts/codegen/generate-artifacts-executor/generateUnstableModulesRequiringMainQueueSetupProvider.js +3 -3
  148. package/scripts/codegen/generate-artifacts-executor/utils.js +48 -0
  149. package/scripts/react_native_pods.rb +1 -0
  150. package/scripts/replace-rncore-version.js +72 -15
  151. package/src/private/featureflags/ReactNativeFeatureFlags.js +27 -2
  152. package/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js +6 -1
  153. package/src/private/setup/setUpDefaultReactNativeEnvironment.js +6 -0
  154. package/types/public/ReactNativeTVTypes.d.ts +8 -0
@@ -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"
@@ -9,6 +9,8 @@
9
9
  #include "Timing.h"
10
10
  #include "TracingCategory.h"
11
11
 
12
+ #include <react/utils/Base64.h>
13
+
12
14
  namespace facebook::react::jsinspector_modern::tracing {
13
15
 
14
16
  /* static */ TraceEvent TraceEventGenerator::createSetLayerTreeIdEvent(
@@ -70,14 +72,19 @@ TraceEventGenerator::createFrameTimingsEvents(
70
72
  /* static */ TraceEvent TraceEventGenerator::createScreenshotEvent(
71
73
  FrameSequenceId frameSequenceId,
72
74
  int sourceId,
73
- std::string&& snapshot,
75
+ std::vector<uint8_t>&& snapshot,
74
76
  HighResTimeStamp expectedDisplayTime,
75
77
  ProcessId processId,
76
78
  ThreadId threadId) {
77
- folly::dynamic args = folly::dynamic::object("snapshot", std::move(snapshot))(
78
- "source_id", sourceId)("frame_sequence", frameSequenceId)(
79
- "expected_display_time",
80
- highResTimeStampToTracingClockTimeStamp(expectedDisplayTime));
79
+ // Convert binary data to string for Base64 encoding
80
+ std::string snapshotBytes(snapshot.begin(), snapshot.end());
81
+ std::string base64Snapshot = base64Encode(snapshotBytes);
82
+
83
+ folly::dynamic args =
84
+ folly::dynamic::object("snapshot", std::move(base64Snapshot))(
85
+ "source_id", sourceId)("frame_sequence", frameSequenceId)(
86
+ "expected_display_time",
87
+ highResTimeStampToTracingClockTimeStamp(expectedDisplayTime));
81
88
 
82
89
  return TraceEvent{
83
90
  .name = "Screenshot",
@@ -12,7 +12,9 @@
12
12
  #include <jsinspector-modern/tracing/FrameTimingSequence.h>
13
13
  #include <react/timing/primitives.h>
14
14
 
15
+ #include <cstdint>
15
16
  #include <utility>
17
+ #include <vector>
16
18
 
17
19
  namespace facebook::react::jsinspector_modern::tracing {
18
20
 
@@ -49,7 +51,7 @@ class TraceEventGenerator {
49
51
  static TraceEvent createScreenshotEvent(
50
52
  FrameSequenceId frameSequenceId,
51
53
  int sourceId,
52
- std::string &&snapshot,
54
+ std::vector<uint8_t> &&snapshot,
53
55
  HighResTimeStamp expectedDisplayTime,
54
56
  ProcessId processId,
55
57
  ThreadId threadId);
@@ -112,4 +112,46 @@ TraceEventSerializer::serializeProfileChunkCPUProfileNodeCallFrame(
112
112
  return dynamicCallFrame;
113
113
  }
114
114
 
115
+ /* static */ size_t TraceEventSerializer::estimateJsonSize(
116
+ const folly::dynamic& value) {
117
+ switch (value.type()) {
118
+ case folly::dynamic::Type::NULLT:
119
+ return 4; // null
120
+ case folly::dynamic::Type::BOOL:
121
+ return 5; // false
122
+ case folly::dynamic::Type::INT64:
123
+ case folly::dynamic::Type::DOUBLE:
124
+ return 20; // conservative max for numeric values
125
+ case folly::dynamic::Type::STRING:
126
+ return value.stringPiece().size() + 2; // quotes
127
+ case folly::dynamic::Type::ARRAY: {
128
+ size_t size = 2; // []
129
+ bool first = true;
130
+ for (const auto& element : value) {
131
+ if (!first) {
132
+ size += 1; // comma
133
+ }
134
+ first = false;
135
+ size += estimateJsonSize(element);
136
+ }
137
+ return size;
138
+ }
139
+ case folly::dynamic::Type::OBJECT: {
140
+ size_t size = 2; // {}
141
+ bool first = true;
142
+ for (const auto& [key, val] : value.items()) {
143
+ if (!first) {
144
+ size += 1; // comma
145
+ }
146
+ first = false;
147
+ // key size + quotes + colon
148
+ size += key.stringPiece().size() + 3;
149
+ size += estimateJsonSize(val);
150
+ }
151
+ return size;
152
+ }
153
+ }
154
+ return 0;
155
+ }
156
+
115
157
  } // namespace facebook::react::jsinspector_modern::tracing
@@ -84,6 +84,13 @@ class TraceEventSerializer {
84
84
  */
85
85
  static folly::dynamic serializeProfileChunkCPUProfileNodeCallFrame(
86
86
  TraceEventProfileChunk::CPUProfile::Node::CallFrame &&callFrame);
87
+
88
+ /**
89
+ * Estimates the JSON-serialized byte size of a folly::dynamic value.
90
+ * This is a rough but conservative estimate to avoid the cost of
91
+ * double-serialization (once to measure, once to emit).
92
+ */
93
+ static size_t estimateJsonSize(const folly::dynamic &value);
87
94
  };
88
95
 
89
96
  } // namespace facebook::react::jsinspector_modern::tracing
@@ -9,7 +9,8 @@ set(CMAKE_VERBOSE_MAKEFILE on)
9
9
  include(${REACT_COMMON_DIR}/cmake-utils/react-native-flags.cmake)
10
10
 
11
11
  file(GLOB react_debug_SRC CONFIGURE_DEPENDS *.cpp)
12
- add_library(react_debug OBJECT ${react_debug_SRC})
12
+ file(GLOB react_debug_redbox_SRC CONFIGURE_DEPENDS redbox/*.cpp)
13
+ add_library(react_debug OBJECT ${react_debug_SRC} ${react_debug_redbox_SRC})
13
14
 
14
15
  target_include_directories(react_debug PUBLIC ${REACT_COMMON_DIR})
15
16
 
@@ -25,10 +25,16 @@ Pod::Spec.new do |s|
25
25
  s.author = "Meta Platforms, Inc. and its affiliates"
26
26
  s.platforms = min_supported_versions
27
27
  s.source = source
28
- s.source_files = podspec_sources("**/*.{cpp,h}", "**/*.h")
28
+ s.source_files = podspec_sources("*.{cpp,h}", "*.h")
29
29
  s.header_dir = "react/debug"
30
30
  s.pod_target_xcconfig = { "CLANG_CXX_LANGUAGE_STANDARD" => rct_cxx_language_standard(),
31
31
  "DEFINES_MODULE" => "YES" }
32
32
 
33
33
  resolve_use_frameworks(s, header_mappings_dir: "../..", module_name: "React_debug")
34
+
35
+ s.subspec "redbox" do |ss|
36
+ ss.source_files = podspec_sources("redbox/*.{cpp,h}", "redbox/*.h")
37
+ ss.exclude_files = "redbox/tests/**/*.{cpp,h}"
38
+ ss.header_dir = "react/debug/redbox"
39
+ end
34
40
  end
@@ -0,0 +1,139 @@
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 "AnsiParser.h"
9
+
10
+ #include <optional>
11
+
12
+ #include <regex> // NOLINT(facebook-hte-BadInclude-regex)
13
+
14
+ // @lint-ignore-every CLANGTIDY facebook-hte-StdRegexIsAwful
15
+ namespace facebook::react::unstable_redbox {
16
+
17
+ namespace {
18
+
19
+ // Afterglow theme colors (matching AnsiHighlight.js)
20
+ std::optional<AnsiColor> ansiColor(int code) {
21
+ switch (code) {
22
+ case 30:
23
+ return AnsiColor{.r = 27, .g = 27, .b = 27}; // black
24
+ case 31:
25
+ return AnsiColor{.r = 187, .g = 86, .b = 83}; // red
26
+ case 32:
27
+ return AnsiColor{.r = 144, .g = 157, .b = 98}; // green
28
+ case 33:
29
+ return AnsiColor{.r = 234, .g = 193, .b = 121}; // yellow
30
+ case 34:
31
+ return AnsiColor{.r = 125, .g = 169, .b = 199}; // blue
32
+ case 35:
33
+ return AnsiColor{.r = 176, .g = 101, .b = 151}; // magenta
34
+ case 36:
35
+ return AnsiColor{.r = 140, .g = 220, .b = 216}; // cyan
36
+ case 37:
37
+ return std::nullopt; // white = default
38
+ case 90:
39
+ return AnsiColor{.r = 98, .g = 98, .b = 98}; // bright black
40
+ case 91:
41
+ return AnsiColor{.r = 187, .g = 86, .b = 83}; // bright red
42
+ case 92:
43
+ return AnsiColor{.r = 144, .g = 157, .b = 98}; // bright green
44
+ case 93:
45
+ return AnsiColor{.r = 234, .g = 193, .b = 121}; // bright yellow
46
+ case 94:
47
+ return AnsiColor{.r = 125, .g = 169, .b = 199}; // bright blue
48
+ case 95:
49
+ return AnsiColor{.r = 176, .g = 101, .b = 151}; // bright magenta
50
+ case 96:
51
+ return AnsiColor{.r = 140, .g = 220, .b = 216}; // bright cyan
52
+ case 97:
53
+ return AnsiColor{.r = 247, .g = 247, .b = 247}; // bright white
54
+ default:
55
+ return std::nullopt;
56
+ }
57
+ }
58
+
59
+ const std::regex& ansiRegex() {
60
+ static const std::regex re(R"(\x1b\[([0-9;]*)m)");
61
+ return re;
62
+ }
63
+
64
+ int parseSgrCode(const std::string& params, size_t& pos) {
65
+ size_t next = params.find(';', pos);
66
+ if (next == std::string::npos) {
67
+ next = params.size();
68
+ }
69
+ int code = 0;
70
+ for (size_t i = pos; i < next; ++i) {
71
+ code = code * 10 + (params[i] - '0');
72
+ }
73
+ pos = next + 1;
74
+ return code;
75
+ }
76
+
77
+ } // namespace
78
+
79
+ std::vector<AnsiSpan> parseAnsi(const std::string& text) {
80
+ std::vector<AnsiSpan> spans;
81
+ std::optional<AnsiColor> currentFg;
82
+ std::optional<AnsiColor> currentBg;
83
+ auto it = std::sregex_iterator(text.begin(), text.end(), ansiRegex());
84
+ auto end = std::sregex_iterator();
85
+ size_t lastEnd = 0;
86
+
87
+ for (; it != end; ++it) {
88
+ const auto& match = *it;
89
+ auto matchStart = static_cast<size_t>(match.position());
90
+
91
+ if (matchStart > lastEnd) {
92
+ spans.push_back(
93
+ AnsiSpan{
94
+ .text = text.substr(lastEnd, matchStart - lastEnd),
95
+ .foregroundColor = currentFg,
96
+ .backgroundColor = currentBg});
97
+ }
98
+ lastEnd = matchStart + match.length();
99
+
100
+ std::string params = match[1].str();
101
+ // ESC[m (no params) is equivalent to ESC[0m (reset all attributes)
102
+ if (params.empty()) {
103
+ currentFg = std::nullopt;
104
+ currentBg = std::nullopt;
105
+ }
106
+ size_t pos = 0;
107
+ while (pos < params.size()) {
108
+ int code = parseSgrCode(params, pos);
109
+ if (code == 0) {
110
+ currentFg = std::nullopt;
111
+ currentBg = std::nullopt;
112
+ } else if ((code >= 30 && code <= 37) || (code >= 90 && code <= 97)) {
113
+ currentFg = ansiColor(code);
114
+ } else if ((code >= 40 && code <= 47) || (code >= 100 && code <= 107)) {
115
+ currentBg = ansiColor(code - 10);
116
+ } else if (code == 39) {
117
+ currentFg = std::nullopt;
118
+ } else if (code == 49) {
119
+ currentBg = std::nullopt;
120
+ }
121
+ }
122
+ }
123
+
124
+ if (lastEnd < text.size()) {
125
+ spans.push_back(
126
+ AnsiSpan{
127
+ .text = text.substr(lastEnd),
128
+ .foregroundColor = currentFg,
129
+ .backgroundColor = currentBg});
130
+ }
131
+
132
+ return spans;
133
+ }
134
+
135
+ std::string stripAnsi(const std::string& text) {
136
+ return std::regex_replace(text, ansiRegex(), "");
137
+ }
138
+
139
+ } // namespace facebook::react::unstable_redbox
@@ -0,0 +1,35 @@
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 <optional>
11
+ #include <string>
12
+ #include <vector>
13
+
14
+ namespace facebook::react::unstable_redbox {
15
+
16
+ struct AnsiColor {
17
+ uint8_t r, g, b;
18
+ };
19
+
20
+ struct AnsiSpan {
21
+ std::string text;
22
+ std::optional<AnsiColor> foregroundColor;
23
+ std::optional<AnsiColor> backgroundColor;
24
+ };
25
+
26
+ /**
27
+ * Parse ANSI escape sequences in text and produce a list of styled spans.
28
+ * Uses the Afterglow color theme (matching LogBox's AnsiHighlight.js).
29
+ */
30
+ std::vector<AnsiSpan> parseAnsi(const std::string &text);
31
+
32
+ /** Strip all ANSI escape sequences from text. */
33
+ std::string stripAnsi(const std::string &text);
34
+
35
+ } // namespace facebook::react::unstable_redbox