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.
- package/Libraries/Core/ReactNativeVersion.js +2 -2
- package/Libraries/Utilities/Appearance.js +6 -1
- package/Libraries/Utilities/HMRClient.js +28 -1
- package/React/Base/RCTVersion.m +2 -2
- package/React/CoreModules/RCTDevLoadingView.mm +17 -0
- package/React/CoreModules/RCTJscSafeUrl+Internal.h +23 -0
- package/React/CoreModules/RCTJscSafeUrl.mm +38 -0
- package/React/CoreModules/RCTRedBox+Internal.h +42 -0
- package/React/CoreModules/RCTRedBox.mm +30 -471
- package/React/CoreModules/RCTRedBox2AnsiParser+Internal.h +22 -0
- package/React/CoreModules/RCTRedBox2AnsiParser.mm +55 -0
- package/React/CoreModules/RCTRedBox2Controller+Internal.h +34 -0
- package/React/CoreModules/RCTRedBox2Controller.mm +764 -0
- package/React/CoreModules/RCTRedBox2ErrorParser+Internal.h +46 -0
- package/React/CoreModules/RCTRedBox2ErrorParser.mm +57 -0
- package/React/CoreModules/RCTRedBoxController+Internal.h +31 -0
- package/React/CoreModules/RCTRedBoxController.mm +447 -0
- package/React/CoreModules/RCTRedBoxHMRClient+Internal.h +26 -0
- package/React/CoreModules/RCTRedBoxHMRClient.mm +125 -0
- package/React/CoreModules/React-CoreModules.podspec +1 -0
- package/React/DevSupport/RCTFrameTimingsObserver.h +24 -0
- package/React/DevSupport/RCTFrameTimingsObserver.mm +298 -0
- package/React/FBReactNativeSpec/FBReactNativeSpecJSI.h +40 -0
- package/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm +1 -2
- package/ReactAndroid/api/ReactAndroid.api +0 -9
- package/ReactAndroid/gradle.properties +1 -1
- package/ReactAndroid/publish.gradle +20 -46
- package/ReactAndroid/src/main/java/com/facebook/react/devsupport/BridgelessDevSupportManager.kt +2 -2
- package/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerBase.kt +7 -7
- package/ReactAndroid/src/main/java/com/facebook/react/devsupport/InspectorFlags.kt +4 -0
- package/ReactAndroid/src/main/java/com/facebook/react/devsupport/inspector/FrameTimingSequence.kt +16 -0
- package/ReactAndroid/src/main/java/com/facebook/react/devsupport/inspector/FrameTimingsObserver.kt +275 -0
- package/ReactAndroid/src/main/java/com/facebook/react/devsupport/inspector/TracingState.kt +17 -0
- package/ReactAndroid/src/main/java/com/facebook/react/devsupport/inspector/TracingStateListener.kt +15 -0
- package/ReactAndroid/src/main/java/com/facebook/react/devsupport/{interfaces → inspector}/TracingStateProvider.kt +1 -1
- package/ReactAndroid/src/main/java/com/facebook/react/devsupport/perfmonitor/PerfMonitorInspectorTargetBinding.kt +1 -1
- package/ReactAndroid/src/main/java/com/facebook/react/devsupport/perfmonitor/PerfMonitorOverlayManager.kt +4 -4
- package/ReactAndroid/src/main/java/com/facebook/react/devsupport/perfmonitor/PerfMonitorOverlayView.kt +3 -3
- package/ReactAndroid/src/main/java/com/facebook/react/devsupport/perfmonitor/PerfMonitorUpdateListener.kt +1 -1
- package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt +31 -1
- package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt +51 -1
- package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt +11 -1
- package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt +11 -1
- package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt +56 -1
- package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt +11 -1
- package/ReactAndroid/src/main/java/com/facebook/react/internal/tracing/PerformanceTracer.kt +39 -0
- package/ReactAndroid/src/main/java/com/facebook/react/modules/blob/BlobModule.kt +1 -1
- package/ReactAndroid/src/main/java/com/facebook/react/modules/network/NetworkEventUtil.kt +20 -19
- package/ReactAndroid/src/main/java/com/facebook/react/modules/network/NetworkingModule.kt +6 -12
- package/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.kt +2 -2
- package/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.kt +86 -4
- package/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImplDevHelper.kt +3 -3
- package/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostInspectorTarget.kt +10 -6
- package/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java +7 -6
- package/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java +21 -3
- package/ReactAndroid/src/main/jni/CMakeLists.txt +7 -0
- package/ReactAndroid/src/main/jni/react/devsupport/JInspectorFlags.cpp +22 -0
- package/ReactAndroid/src/main/jni/react/devsupport/JInspectorFlags.h +2 -0
- package/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp +71 -1
- package/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h +16 -1
- package/ReactAndroid/src/main/jni/react/runtime/jni/JReactHostInspectorTarget.cpp +196 -17
- package/ReactAndroid/src/main/jni/react/runtime/jni/JReactHostInspectorTarget.h +168 -18
- package/ReactAndroid/src/main/jni/third-party/folly/CMakeLists.txt +1 -0
- package/ReactCommon/React-Fabric.podspec +6 -0
- package/ReactCommon/cxxreact/ReactNativeVersion.h +3 -3
- package/ReactCommon/hermes/inspector-modern/chrome/Registration.cpp +44 -2
- package/ReactCommon/jsinspector-modern/HostAgent.cpp +45 -10
- package/ReactCommon/jsinspector-modern/HostAgent.h +2 -2
- package/ReactCommon/jsinspector-modern/HostTarget.cpp +14 -7
- package/ReactCommon/jsinspector-modern/HostTarget.h +101 -14
- package/ReactCommon/jsinspector-modern/HostTargetTraceRecording.cpp +39 -8
- package/ReactCommon/jsinspector-modern/HostTargetTraceRecording.h +42 -5
- package/ReactCommon/jsinspector-modern/HostTargetTracing.cpp +54 -21
- package/ReactCommon/jsinspector-modern/HostTargetTracing.h +89 -0
- package/ReactCommon/jsinspector-modern/InspectorFlags.cpp +12 -0
- package/ReactCommon/jsinspector-modern/InspectorFlags.h +12 -0
- package/ReactCommon/jsinspector-modern/InspectorInterfaces.cpp +3 -7
- package/ReactCommon/jsinspector-modern/InstanceAgent.cpp +2 -11
- package/ReactCommon/jsinspector-modern/NetworkIOAgent.cpp +1 -1
- package/ReactCommon/jsinspector-modern/RuntimeAgent.cpp +19 -0
- package/ReactCommon/jsinspector-modern/RuntimeAgent.h +7 -0
- package/ReactCommon/jsinspector-modern/RuntimeTarget.cpp +33 -0
- package/ReactCommon/jsinspector-modern/RuntimeTarget.h +6 -0
- package/ReactCommon/jsinspector-modern/TracingAgent.cpp +29 -13
- package/ReactCommon/jsinspector-modern/TracingAgent.h +5 -4
- package/ReactCommon/jsinspector-modern/tests/HostTargetTest.cpp +65 -0
- package/ReactCommon/jsinspector-modern/tests/InspectorMocks.h +23 -2
- package/ReactCommon/jsinspector-modern/tests/JsiIntegrationTest.cpp +1 -0
- package/ReactCommon/jsinspector-modern/tests/NetworkReporterTest.cpp +1 -0
- package/ReactCommon/jsinspector-modern/tests/TracingTest.cpp +335 -0
- package/ReactCommon/jsinspector-modern/tests/TracingTest.h +95 -0
- package/ReactCommon/jsinspector-modern/tests/utils/InspectorFlagOverridesGuard.cpp +10 -0
- package/ReactCommon/jsinspector-modern/tests/utils/InspectorFlagOverridesGuard.h +3 -1
- package/ReactCommon/jsinspector-modern/tracing/CMakeLists.txt +1 -0
- package/ReactCommon/jsinspector-modern/tracing/FrameTimingSequence.h +61 -0
- package/ReactCommon/jsinspector-modern/tracing/HostTracingProfile.h +43 -0
- package/ReactCommon/jsinspector-modern/tracing/HostTracingProfileSerializer.cpp +165 -0
- package/ReactCommon/jsinspector-modern/tracing/HostTracingProfileSerializer.h +50 -0
- package/ReactCommon/jsinspector-modern/tracing/PerformanceTracer.cpp +16 -14
- package/ReactCommon/jsinspector-modern/tracing/PerformanceTracerSection.h +113 -0
- package/ReactCommon/jsinspector-modern/tracing/React-jsinspectortracing.podspec +1 -0
- package/ReactCommon/jsinspector-modern/tracing/TimeWindowedBuffer.h +158 -0
- package/ReactCommon/jsinspector-modern/tracing/TraceEvent.h +2 -1
- package/ReactCommon/jsinspector-modern/tracing/TraceEventGenerator.cpp +100 -0
- package/ReactCommon/jsinspector-modern/tracing/TraceEventGenerator.h +60 -0
- package/ReactCommon/jsinspector-modern/tracing/TraceEventSerializer.cpp +44 -1
- package/ReactCommon/jsinspector-modern/tracing/TraceEventSerializer.h +7 -0
- package/ReactCommon/jsinspector-modern/tracing/TraceRecordingState.h +18 -7
- package/ReactCommon/jsinspector-modern/tracing/TracingCategory.h +136 -0
- package/ReactCommon/jsinspector-modern/tracing/tests/TimeWindowedBufferTest.cpp +352 -0
- package/ReactCommon/react/debug/CMakeLists.txt +2 -1
- package/ReactCommon/react/debug/React-debug.podspec +7 -1
- package/ReactCommon/react/debug/redbox/AnsiParser.cpp +139 -0
- package/ReactCommon/react/debug/redbox/AnsiParser.h +35 -0
- package/ReactCommon/react/debug/redbox/JscSafeUrl.cpp +179 -0
- package/ReactCommon/react/debug/redbox/JscSafeUrl.h +27 -0
- package/ReactCommon/react/debug/redbox/RedBoxErrorParser.cpp +171 -0
- package/ReactCommon/react/debug/redbox/RedBoxErrorParser.h +40 -0
- package/ReactCommon/react/debug/redbox/tests/AnsiParserTest.cpp +97 -0
- package/ReactCommon/react/debug/redbox/tests/JscSafeUrlTest.cpp +173 -0
- package/ReactCommon/react/debug/redbox/tests/RedBoxErrorParserTest.cpp +107 -0
- package/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp +21 -1
- package/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h +26 -1
- package/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp +140 -50
- package/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h +12 -2
- package/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h +21 -1
- package/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDynamicProvider.h +46 -1
- package/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h +6 -1
- package/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModule.mm +3 -1
- package/ReactCommon/react/nativemodule/defaults/CMakeLists.txt +1 -0
- package/ReactCommon/react/nativemodule/defaults/DefaultTurboModules.cpp +7 -0
- package/ReactCommon/react/nativemodule/defaults/React-defaultsnativemodule.podspec +1 -0
- package/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp +26 -1
- package/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h +11 -1
- package/ReactCommon/react/nativemodule/mutationobserver/NativeMutationObserver.h +4 -0
- package/ReactCommon/react/nativemodule/mutationobserver/React-mutationobservernativemodule.podspec +66 -0
- package/ReactCommon/react/performance/timeline/PerformanceObserver.cpp +18 -6
- package/ReactCommon/react/performance/timeline/PerformanceObserver.h +2 -0
- package/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTHost.mm +115 -0
- package/ReactCommon/{jsinspector-modern → react/utils}/Base64.h +2 -2
- package/gradle/libs.versions.toml +1 -1
- package/package.json +10 -10
- package/scripts/cocoapods/utils.rb +1 -0
- package/scripts/react_native_pods.rb +1 -0
- package/src/private/featureflags/ReactNativeFeatureFlags.js +26 -1
- package/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js +6 -1
- package/src/private/setup/setUpDefaultReactNativeEnvironment.js +6 -0
- package/third-party-podspecs/RCT-Folly.podspec +1 -1
- package/third-party-podspecs/fmt.podspec +2 -2
- package/ReactAndroid/src/main/java/com/facebook/react/devsupport/interfaces/TracingState.kt +0 -19
- package/ReactCommon/jsinspector-modern/tracing/TraceRecordingStateSerializer.cpp +0 -68
- package/ReactCommon/jsinspector-modern/tracing/TraceRecordingStateSerializer.h +0 -42
- 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
|
-
|
|
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("
|
|
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
|