react-native-tvos 0.83.4-2 → 0.83.9-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 (153) hide show
  1. package/Libraries/Core/ReactNativeVersion.js +2 -2
  2. package/Libraries/Utilities/Appearance.js +6 -1
  3. package/Libraries/Utilities/HMRClient.js +28 -1
  4. package/React/Base/RCTVersion.m +2 -2
  5. package/React/CoreModules/RCTDevLoadingView.mm +17 -0
  6. package/React/CoreModules/RCTJscSafeUrl+Internal.h +23 -0
  7. package/React/CoreModules/RCTJscSafeUrl.mm +38 -0
  8. package/React/CoreModules/RCTRedBox+Internal.h +42 -0
  9. package/React/CoreModules/RCTRedBox.mm +30 -471
  10. package/React/CoreModules/RCTRedBox2AnsiParser+Internal.h +22 -0
  11. package/React/CoreModules/RCTRedBox2AnsiParser.mm +55 -0
  12. package/React/CoreModules/RCTRedBox2Controller+Internal.h +34 -0
  13. package/React/CoreModules/RCTRedBox2Controller.mm +764 -0
  14. package/React/CoreModules/RCTRedBox2ErrorParser+Internal.h +46 -0
  15. package/React/CoreModules/RCTRedBox2ErrorParser.mm +57 -0
  16. package/React/CoreModules/RCTRedBoxController+Internal.h +31 -0
  17. package/React/CoreModules/RCTRedBoxController.mm +447 -0
  18. package/React/CoreModules/RCTRedBoxHMRClient+Internal.h +26 -0
  19. package/React/CoreModules/RCTRedBoxHMRClient.mm +125 -0
  20. package/React/CoreModules/React-CoreModules.podspec +1 -0
  21. package/React/DevSupport/RCTFrameTimingsObserver.h +24 -0
  22. package/React/DevSupport/RCTFrameTimingsObserver.mm +298 -0
  23. package/React/FBReactNativeSpec/FBReactNativeSpecJSI.h +40 -0
  24. package/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm +1 -2
  25. package/ReactAndroid/api/ReactAndroid.api +0 -9
  26. package/ReactAndroid/gradle.properties +1 -1
  27. package/ReactAndroid/publish.gradle +20 -46
  28. package/ReactAndroid/src/main/java/com/facebook/react/devsupport/BridgelessDevSupportManager.kt +2 -2
  29. package/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerBase.kt +7 -7
  30. package/ReactAndroid/src/main/java/com/facebook/react/devsupport/InspectorFlags.kt +4 -0
  31. package/ReactAndroid/src/main/java/com/facebook/react/devsupport/inspector/FrameTimingSequence.kt +16 -0
  32. package/ReactAndroid/src/main/java/com/facebook/react/devsupport/inspector/FrameTimingsObserver.kt +275 -0
  33. package/ReactAndroid/src/main/java/com/facebook/react/devsupport/inspector/TracingState.kt +17 -0
  34. package/ReactAndroid/src/main/java/com/facebook/react/devsupport/inspector/TracingStateListener.kt +15 -0
  35. package/ReactAndroid/src/main/java/com/facebook/react/devsupport/{interfaces → inspector}/TracingStateProvider.kt +1 -1
  36. package/ReactAndroid/src/main/java/com/facebook/react/devsupport/perfmonitor/PerfMonitorInspectorTargetBinding.kt +1 -1
  37. package/ReactAndroid/src/main/java/com/facebook/react/devsupport/perfmonitor/PerfMonitorOverlayManager.kt +4 -4
  38. package/ReactAndroid/src/main/java/com/facebook/react/devsupport/perfmonitor/PerfMonitorOverlayView.kt +3 -3
  39. package/ReactAndroid/src/main/java/com/facebook/react/devsupport/perfmonitor/PerfMonitorUpdateListener.kt +1 -1
  40. package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt +31 -1
  41. package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt +51 -1
  42. package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt +11 -1
  43. package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt +11 -1
  44. package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt +56 -1
  45. package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt +11 -1
  46. package/ReactAndroid/src/main/java/com/facebook/react/internal/tracing/PerformanceTracer.kt +39 -0
  47. package/ReactAndroid/src/main/java/com/facebook/react/modules/blob/BlobModule.kt +1 -1
  48. package/ReactAndroid/src/main/java/com/facebook/react/modules/network/NetworkEventUtil.kt +20 -19
  49. package/ReactAndroid/src/main/java/com/facebook/react/modules/network/NetworkingModule.kt +6 -12
  50. package/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.kt +2 -2
  51. package/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.kt +86 -4
  52. package/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImplDevHelper.kt +3 -3
  53. package/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostInspectorTarget.kt +10 -6
  54. package/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java +7 -6
  55. package/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java +21 -3
  56. package/ReactAndroid/src/main/jni/CMakeLists.txt +7 -0
  57. package/ReactAndroid/src/main/jni/react/devsupport/JInspectorFlags.cpp +22 -0
  58. package/ReactAndroid/src/main/jni/react/devsupport/JInspectorFlags.h +2 -0
  59. package/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp +71 -1
  60. package/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h +16 -1
  61. package/ReactAndroid/src/main/jni/react/runtime/jni/JReactHostInspectorTarget.cpp +196 -17
  62. package/ReactAndroid/src/main/jni/react/runtime/jni/JReactHostInspectorTarget.h +168 -18
  63. package/ReactAndroid/src/main/jni/third-party/folly/CMakeLists.txt +1 -0
  64. package/ReactCommon/React-Fabric.podspec +6 -0
  65. package/ReactCommon/cxxreact/ReactNativeVersion.h +3 -3
  66. package/ReactCommon/hermes/inspector-modern/chrome/Registration.cpp +44 -2
  67. package/ReactCommon/jsinspector-modern/HostAgent.cpp +45 -10
  68. package/ReactCommon/jsinspector-modern/HostAgent.h +2 -2
  69. package/ReactCommon/jsinspector-modern/HostTarget.cpp +14 -7
  70. package/ReactCommon/jsinspector-modern/HostTarget.h +101 -14
  71. package/ReactCommon/jsinspector-modern/HostTargetTraceRecording.cpp +39 -8
  72. package/ReactCommon/jsinspector-modern/HostTargetTraceRecording.h +42 -5
  73. package/ReactCommon/jsinspector-modern/HostTargetTracing.cpp +54 -21
  74. package/ReactCommon/jsinspector-modern/HostTargetTracing.h +89 -0
  75. package/ReactCommon/jsinspector-modern/InspectorFlags.cpp +12 -0
  76. package/ReactCommon/jsinspector-modern/InspectorFlags.h +12 -0
  77. package/ReactCommon/jsinspector-modern/InspectorInterfaces.cpp +3 -7
  78. package/ReactCommon/jsinspector-modern/InstanceAgent.cpp +2 -11
  79. package/ReactCommon/jsinspector-modern/NetworkIOAgent.cpp +1 -1
  80. package/ReactCommon/jsinspector-modern/RuntimeAgent.cpp +19 -0
  81. package/ReactCommon/jsinspector-modern/RuntimeAgent.h +7 -0
  82. package/ReactCommon/jsinspector-modern/RuntimeTarget.cpp +33 -0
  83. package/ReactCommon/jsinspector-modern/RuntimeTarget.h +6 -0
  84. package/ReactCommon/jsinspector-modern/TracingAgent.cpp +29 -13
  85. package/ReactCommon/jsinspector-modern/TracingAgent.h +5 -4
  86. package/ReactCommon/jsinspector-modern/tests/HostTargetTest.cpp +65 -0
  87. package/ReactCommon/jsinspector-modern/tests/InspectorMocks.h +23 -2
  88. package/ReactCommon/jsinspector-modern/tests/JsiIntegrationTest.cpp +1 -0
  89. package/ReactCommon/jsinspector-modern/tests/NetworkReporterTest.cpp +1 -0
  90. package/ReactCommon/jsinspector-modern/tests/TracingTest.cpp +335 -0
  91. package/ReactCommon/jsinspector-modern/tests/TracingTest.h +95 -0
  92. package/ReactCommon/jsinspector-modern/tests/utils/InspectorFlagOverridesGuard.cpp +10 -0
  93. package/ReactCommon/jsinspector-modern/tests/utils/InspectorFlagOverridesGuard.h +3 -1
  94. package/ReactCommon/jsinspector-modern/tracing/CMakeLists.txt +1 -0
  95. package/ReactCommon/jsinspector-modern/tracing/FrameTimingSequence.h +61 -0
  96. package/ReactCommon/jsinspector-modern/tracing/HostTracingProfile.h +43 -0
  97. package/ReactCommon/jsinspector-modern/tracing/HostTracingProfileSerializer.cpp +165 -0
  98. package/ReactCommon/jsinspector-modern/tracing/HostTracingProfileSerializer.h +50 -0
  99. package/ReactCommon/jsinspector-modern/tracing/PerformanceTracer.cpp +16 -14
  100. package/ReactCommon/jsinspector-modern/tracing/PerformanceTracerSection.h +113 -0
  101. package/ReactCommon/jsinspector-modern/tracing/React-jsinspectortracing.podspec +1 -0
  102. package/ReactCommon/jsinspector-modern/tracing/TimeWindowedBuffer.h +158 -0
  103. package/ReactCommon/jsinspector-modern/tracing/TraceEvent.h +2 -1
  104. package/ReactCommon/jsinspector-modern/tracing/TraceEventGenerator.cpp +100 -0
  105. package/ReactCommon/jsinspector-modern/tracing/TraceEventGenerator.h +60 -0
  106. package/ReactCommon/jsinspector-modern/tracing/TraceEventSerializer.cpp +44 -1
  107. package/ReactCommon/jsinspector-modern/tracing/TraceEventSerializer.h +7 -0
  108. package/ReactCommon/jsinspector-modern/tracing/TraceRecordingState.h +18 -7
  109. package/ReactCommon/jsinspector-modern/tracing/TracingCategory.h +136 -0
  110. package/ReactCommon/jsinspector-modern/tracing/tests/TimeWindowedBufferTest.cpp +352 -0
  111. package/ReactCommon/react/debug/CMakeLists.txt +2 -1
  112. package/ReactCommon/react/debug/React-debug.podspec +7 -1
  113. package/ReactCommon/react/debug/redbox/AnsiParser.cpp +139 -0
  114. package/ReactCommon/react/debug/redbox/AnsiParser.h +35 -0
  115. package/ReactCommon/react/debug/redbox/JscSafeUrl.cpp +179 -0
  116. package/ReactCommon/react/debug/redbox/JscSafeUrl.h +27 -0
  117. package/ReactCommon/react/debug/redbox/RedBoxErrorParser.cpp +171 -0
  118. package/ReactCommon/react/debug/redbox/RedBoxErrorParser.h +40 -0
  119. package/ReactCommon/react/debug/redbox/tests/AnsiParserTest.cpp +97 -0
  120. package/ReactCommon/react/debug/redbox/tests/JscSafeUrlTest.cpp +173 -0
  121. package/ReactCommon/react/debug/redbox/tests/RedBoxErrorParserTest.cpp +107 -0
  122. package/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp +21 -1
  123. package/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h +26 -1
  124. package/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp +140 -50
  125. package/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h +12 -2
  126. package/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h +21 -1
  127. package/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDynamicProvider.h +46 -1
  128. package/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h +6 -1
  129. package/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModule.mm +3 -1
  130. package/ReactCommon/react/nativemodule/defaults/CMakeLists.txt +1 -0
  131. package/ReactCommon/react/nativemodule/defaults/DefaultTurboModules.cpp +7 -0
  132. package/ReactCommon/react/nativemodule/defaults/React-defaultsnativemodule.podspec +1 -0
  133. package/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp +26 -1
  134. package/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h +11 -1
  135. package/ReactCommon/react/nativemodule/mutationobserver/NativeMutationObserver.h +4 -0
  136. package/ReactCommon/react/nativemodule/mutationobserver/React-mutationobservernativemodule.podspec +66 -0
  137. package/ReactCommon/react/performance/timeline/PerformanceObserver.cpp +18 -6
  138. package/ReactCommon/react/performance/timeline/PerformanceObserver.h +2 -0
  139. package/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTHost.mm +115 -0
  140. package/ReactCommon/{jsinspector-modern → react/utils}/Base64.h +2 -2
  141. package/gradle/libs.versions.toml +1 -1
  142. package/package.json +10 -10
  143. package/scripts/cocoapods/utils.rb +1 -0
  144. package/scripts/react_native_pods.rb +1 -0
  145. package/src/private/featureflags/ReactNativeFeatureFlags.js +26 -1
  146. package/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js +6 -1
  147. package/src/private/setup/setUpDefaultReactNativeEnvironment.js +6 -0
  148. package/third-party-podspecs/RCT-Folly.podspec +1 -1
  149. package/third-party-podspecs/fmt.podspec +2 -2
  150. package/ReactAndroid/src/main/java/com/facebook/react/devsupport/interfaces/TracingState.kt +0 -19
  151. package/ReactCommon/jsinspector-modern/tracing/TraceRecordingStateSerializer.cpp +0 -68
  152. package/ReactCommon/jsinspector-modern/tracing/TraceRecordingStateSerializer.h +0 -42
  153. package/ReactCommon/jsinspector-modern/tracing/TracingState.h +0 -24
@@ -0,0 +1,352 @@
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 <jsinspector-modern/tracing/TimeWindowedBuffer.h>
9
+
10
+ #include <gmock/gmock.h>
11
+ #include <gtest/gtest.h>
12
+
13
+ namespace facebook::react::jsinspector_modern::tracing {
14
+
15
+ // Test structure with timestamp field
16
+ struct TestEvent {
17
+ int value;
18
+ HighResTimeStamp timestamp;
19
+
20
+ bool operator==(const TestEvent& other) const {
21
+ return value == other.value;
22
+ }
23
+ };
24
+
25
+ // ============================================================================
26
+ // Tests for unbounded buffer (no timestamp accessor)
27
+ // ============================================================================
28
+
29
+ TEST(TimeWindowedBufferTest, DefaultConstructorCreatesEmptyBuffer) {
30
+ TimeWindowedBuffer<int> buffer;
31
+ auto result = buffer.pruneExpiredAndExtract();
32
+ EXPECT_EQ(result.size(), 0u);
33
+ }
34
+
35
+ TEST(TimeWindowedBufferTest, PushAddsElementsToUnboundedBuffer) {
36
+ TimeWindowedBuffer<int> buffer;
37
+ buffer.push(1);
38
+ buffer.push(2);
39
+ buffer.push(3);
40
+
41
+ auto result = buffer.pruneExpiredAndExtract();
42
+ EXPECT_EQ(result.size(), 3u);
43
+ EXPECT_EQ(result[0], 1);
44
+ EXPECT_EQ(result[1], 2);
45
+ EXPECT_EQ(result[2], 3);
46
+ }
47
+
48
+ TEST(TimeWindowedBufferTest, UnboundedBufferPreservesAllElements) {
49
+ TimeWindowedBuffer<int> buffer;
50
+ for (int i = 0; i < 100; ++i) {
51
+ buffer.push(i);
52
+ }
53
+
54
+ auto result = buffer.pruneExpiredAndExtract();
55
+ EXPECT_EQ(result.size(), 100u);
56
+ for (int i = 0; i < 100; ++i) {
57
+ EXPECT_EQ(result[i], i);
58
+ }
59
+ }
60
+
61
+ TEST(TimeWindowedBufferTest, ClearEmptiesBuffer) {
62
+ TimeWindowedBuffer<int> buffer;
63
+ buffer.push(1);
64
+ buffer.push(2);
65
+ buffer.push(3);
66
+
67
+ buffer.clear();
68
+
69
+ auto result = buffer.pruneExpiredAndExtract();
70
+ EXPECT_EQ(result.size(), 0u);
71
+ }
72
+
73
+ TEST(TimeWindowedBufferTest, PushRvalueReference) {
74
+ TimeWindowedBuffer<std::string> buffer;
75
+ std::string str = "test";
76
+ buffer.push(std::move(str));
77
+
78
+ auto result = buffer.pruneExpiredAndExtract();
79
+ EXPECT_EQ(result.size(), 1u);
80
+ EXPECT_EQ(result[0], "test");
81
+ }
82
+
83
+ // ============================================================================
84
+ // Tests for time-windowed buffer (with timestamp accessor)
85
+ // ============================================================================
86
+
87
+ TEST(TimeWindowedBufferTest, TimeWindowedBufferCreation) {
88
+ auto timestampAccessor = [](const TestEvent& e) { return e.timestamp; };
89
+ auto windowSize = HighResDuration::fromMilliseconds(100);
90
+
91
+ TimeWindowedBuffer<TestEvent> buffer(timestampAccessor, windowSize);
92
+
93
+ auto result = buffer.pruneExpiredAndExtract();
94
+ EXPECT_EQ(result.size(), 0u);
95
+ }
96
+
97
+ TEST(TimeWindowedBufferTest, TimeWindowedBufferAddsElements) {
98
+ auto timestampAccessor = [](const TestEvent& e) { return e.timestamp; };
99
+ auto windowSize = HighResDuration::fromMilliseconds(1000);
100
+
101
+ TimeWindowedBuffer<TestEvent> buffer(timestampAccessor, windowSize);
102
+
103
+ auto baseTime = HighResTimeStamp::now();
104
+ buffer.push(TestEvent{.value = 1, .timestamp = baseTime});
105
+ buffer.push(
106
+ TestEvent{
107
+ .value = 2,
108
+ .timestamp = baseTime + HighResDuration::fromMilliseconds(100)});
109
+
110
+ auto result = buffer.pruneExpiredAndExtract(baseTime + windowSize);
111
+ EXPECT_EQ(result.size(), 2u);
112
+ EXPECT_EQ(result[0].value, 1);
113
+ EXPECT_EQ(result[1].value, 2);
114
+ }
115
+
116
+ TEST(TimeWindowedBufferTest, ElementsWithinWindowArePreserved) {
117
+ auto timestampAccessor = [](const TestEvent& e) { return e.timestamp; };
118
+ auto windowSize = HighResDuration::fromMilliseconds(500);
119
+
120
+ TimeWindowedBuffer<TestEvent> buffer(timestampAccessor, windowSize);
121
+
122
+ auto baseTime = HighResTimeStamp::now();
123
+ buffer.push(TestEvent{.value = 1, .timestamp = baseTime});
124
+ buffer.push(
125
+ TestEvent{
126
+ .value = 2,
127
+ .timestamp = baseTime + HighResDuration::fromMilliseconds(100)});
128
+ buffer.push(
129
+ TestEvent{
130
+ .value = 3,
131
+ .timestamp = baseTime + HighResDuration::fromMilliseconds(200)});
132
+ buffer.push(
133
+ TestEvent{
134
+ .value = 4,
135
+ .timestamp = baseTime + HighResDuration::fromMilliseconds(300)});
136
+
137
+ // Extract with window [300ms, 800ms] - only event at 300ms should be included
138
+ auto result = buffer.pruneExpiredAndExtract(
139
+ baseTime + HighResDuration::fromMilliseconds(800));
140
+ EXPECT_EQ(result.size(), 1u);
141
+ EXPECT_EQ(result[0].value, 4);
142
+ }
143
+
144
+ TEST(TimeWindowedBufferTest, BufferSwitchingWhenWindowExceeded) {
145
+ auto timestampAccessor = [](const TestEvent& e) { return e.timestamp; };
146
+ auto windowSize = HighResDuration::fromMilliseconds(100);
147
+
148
+ TimeWindowedBuffer<TestEvent> buffer(timestampAccessor, windowSize);
149
+
150
+ auto baseTime = HighResTimeStamp::now();
151
+
152
+ // Add events within first window
153
+ buffer.push(TestEvent{.value = 1, .timestamp = baseTime});
154
+ buffer.push(
155
+ TestEvent{
156
+ .value = 2,
157
+ .timestamp = baseTime + HighResDuration::fromMilliseconds(50)});
158
+
159
+ // Add event that exceeds the window - should trigger buffer switch
160
+ buffer.push(
161
+ TestEvent{
162
+ .value = 3,
163
+ .timestamp = baseTime + HighResDuration::fromMilliseconds(150)});
164
+
165
+ // Extract events within the window using reference point at 250ms
166
+ auto result = buffer.pruneExpiredAndExtract(
167
+ baseTime + HighResDuration::fromMilliseconds(250));
168
+
169
+ // Events from 150ms should be in the window (250 - 100 = 150)
170
+ EXPECT_GE(result.size(), 1u);
171
+ }
172
+
173
+ TEST(TimeWindowedBufferTest, PruneExpiredFiltersOldElements) {
174
+ auto timestampAccessor = [](const TestEvent& e) { return e.timestamp; };
175
+ auto windowSize = HighResDuration::fromMilliseconds(100);
176
+
177
+ TimeWindowedBuffer<TestEvent> buffer(timestampAccessor, windowSize);
178
+
179
+ auto baseTime = HighResTimeStamp::now();
180
+
181
+ // Add events in first window
182
+ buffer.push(TestEvent{.value = 1, .timestamp = baseTime});
183
+ buffer.push(
184
+ TestEvent{
185
+ .value = 2,
186
+ .timestamp = baseTime + HighResDuration::fromMilliseconds(50)});
187
+
188
+ // Move to second window
189
+ buffer.push(
190
+ TestEvent{
191
+ .value = 3,
192
+ .timestamp = baseTime + HighResDuration::fromMilliseconds(150)});
193
+
194
+ // Move to third window
195
+ buffer.push(
196
+ TestEvent{
197
+ .value = 4,
198
+ .timestamp = baseTime + HighResDuration::fromMilliseconds(300)});
199
+
200
+ // Extract with reference at 300ms: window is [200ms, 300ms]
201
+ // Only event 4 at 300ms should be within window
202
+ auto result = buffer.pruneExpiredAndExtract(
203
+ baseTime + HighResDuration::fromMilliseconds(300));
204
+
205
+ EXPECT_EQ(result.size(), 1u);
206
+ EXPECT_EQ(result[0].value, 4);
207
+ }
208
+
209
+ TEST(TimeWindowedBufferTest, OutOfOrderTimestampsAreHandled) {
210
+ auto timestampAccessor = [](const TestEvent& e) { return e.timestamp; };
211
+ auto windowSize = HighResDuration::fromMilliseconds(10000);
212
+
213
+ TimeWindowedBuffer<TestEvent> buffer(timestampAccessor, windowSize);
214
+
215
+ auto baseTime = HighResTimeStamp::now();
216
+
217
+ // Add events out of order (by timestamp)
218
+ buffer.push(
219
+ TestEvent{
220
+ .value = 1,
221
+ .timestamp = baseTime + HighResDuration::fromMilliseconds(100)});
222
+ buffer.push(
223
+ TestEvent{.value = 2, .timestamp = baseTime}); // Earlier timestamp
224
+ buffer.push(
225
+ TestEvent{
226
+ .value = 3,
227
+ .timestamp = baseTime + HighResDuration::fromMilliseconds(200)});
228
+
229
+ // Extract with window [200ms, 10200ms] - only event at 200ms should be
230
+ // included
231
+ auto result = buffer.pruneExpiredAndExtract(
232
+ baseTime + HighResDuration::fromMilliseconds(10200));
233
+ EXPECT_EQ(result.size(), 1u);
234
+ EXPECT_EQ(result[0].value, 3);
235
+ }
236
+
237
+ TEST(TimeWindowedBufferTest, ClearResetsTimeWindowedBuffer) {
238
+ auto timestampAccessor = [](const TestEvent& e) { return e.timestamp; };
239
+ auto windowSize = HighResDuration::fromMilliseconds(100);
240
+
241
+ TimeWindowedBuffer<TestEvent> buffer(timestampAccessor, windowSize);
242
+
243
+ auto baseTime = HighResTimeStamp::now();
244
+ buffer.push(TestEvent{.value = 1, .timestamp = baseTime});
245
+ buffer.push(
246
+ TestEvent{
247
+ .value = 2,
248
+ .timestamp = baseTime + HighResDuration::fromMilliseconds(200)});
249
+
250
+ buffer.clear();
251
+
252
+ auto result = buffer.pruneExpiredAndExtract();
253
+ EXPECT_EQ(result.size(), 0u);
254
+ }
255
+
256
+ // ============================================================================
257
+ // Tests for edge cases
258
+ // ============================================================================
259
+
260
+ TEST(TimeWindowedBufferTest, SingleElementBuffer) {
261
+ TimeWindowedBuffer<int> buffer;
262
+ buffer.push(42);
263
+
264
+ auto result = buffer.pruneExpiredAndExtract();
265
+ EXPECT_EQ(result.size(), 1u);
266
+ EXPECT_EQ(result[0], 42);
267
+ }
268
+
269
+ TEST(TimeWindowedBufferTest, LargeNumberOfElements) {
270
+ TimeWindowedBuffer<int> buffer;
271
+
272
+ const int count = 10000;
273
+ for (int i = 0; i < count; ++i) {
274
+ buffer.push(i);
275
+ }
276
+
277
+ auto result = buffer.pruneExpiredAndExtract();
278
+ EXPECT_EQ(result.size(), static_cast<size_t>(count));
279
+ EXPECT_EQ(result[0], 0);
280
+ EXPECT_EQ(result[count - 1], count - 1);
281
+ }
282
+
283
+ TEST(TimeWindowedBufferTest, VerySmallTimeWindow) {
284
+ auto timestampAccessor = [](const TestEvent& e) { return e.timestamp; };
285
+ auto windowSize = HighResDuration::fromNanoseconds(1000);
286
+
287
+ TimeWindowedBuffer<TestEvent> buffer(timestampAccessor, windowSize);
288
+
289
+ auto baseTime = HighResTimeStamp::now();
290
+ buffer.push(TestEvent{.value = 1, .timestamp = baseTime});
291
+
292
+ // Next event with significant time difference should trigger switch
293
+ buffer.push(
294
+ TestEvent{
295
+ .value = 2,
296
+ .timestamp = baseTime + HighResDuration::fromMilliseconds(1)});
297
+
298
+ auto result = buffer.pruneExpiredAndExtract(
299
+ baseTime + HighResDuration::fromMilliseconds(1));
300
+ EXPECT_GE(result.size(), 1u);
301
+ }
302
+
303
+ TEST(TimeWindowedBufferTest, VeryLargeTimeWindow) {
304
+ auto timestampAccessor = [](const TestEvent& e) { return e.timestamp; };
305
+ auto windowSize = HighResDuration::fromMilliseconds(3600000); // 1 hour
306
+
307
+ TimeWindowedBuffer<TestEvent> buffer(timestampAccessor, windowSize);
308
+
309
+ auto baseTime = HighResTimeStamp::now();
310
+
311
+ // Add many events spread over time
312
+ for (int i = 0; i < 100; ++i) {
313
+ buffer.push(
314
+ TestEvent{
315
+ .value = i,
316
+ .timestamp =
317
+ baseTime + HighResDuration::fromMilliseconds(i * 10000)});
318
+ }
319
+
320
+ // All events should still be in the window
321
+ auto result = buffer.pruneExpiredAndExtract(
322
+ baseTime + HighResDuration::fromMilliseconds(100 * 10000));
323
+ EXPECT_EQ(result.size(), 100u);
324
+ }
325
+
326
+ // ============================================================================
327
+ // Tests for complex types
328
+ // ============================================================================
329
+
330
+ TEST(TimeWindowedBufferTest, WorksWithComplexTypes) {
331
+ struct ComplexType {
332
+ std::string name;
333
+ std::vector<int> data;
334
+ HighResTimeStamp timestamp;
335
+ };
336
+
337
+ auto timestampAccessor = [](const ComplexType& e) { return e.timestamp; };
338
+ auto windowSize = HighResDuration::fromMilliseconds(1000);
339
+
340
+ TimeWindowedBuffer<ComplexType> buffer(timestampAccessor, windowSize);
341
+
342
+ auto baseTime = HighResTimeStamp::now();
343
+ buffer.push(
344
+ ComplexType{.name = "test", .data = {1, 2, 3}, .timestamp = baseTime});
345
+
346
+ auto result = buffer.pruneExpiredAndExtract();
347
+ EXPECT_EQ(result.size(), 1u);
348
+ EXPECT_EQ(result[0].name, "test");
349
+ EXPECT_EQ(result[0].data.size(), 3u);
350
+ }
351
+
352
+ } // 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