react-native-tvos 0.85.2-0 → 0.85.3-1
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/Components/ScrollView/ScrollView.d.ts +1 -1
- package/Libraries/Components/ScrollView/ScrollView.js +1 -1
- package/Libraries/Components/TV/TVViewPropTypes.js +9 -0
- package/Libraries/Components/View/View.js +7 -3
- package/Libraries/Core/ReactNativeVersion.js +2 -2
- package/Libraries/NativeComponent/TVViewConfig.js +1 -0
- package/Libraries/Utilities/HMRClient.js +28 -1
- package/README.md +13 -1
- package/React/Base/RCTVersion.m +2 -2
- 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/ScrollView/RCTScrollViewComponentView.mm +35 -15
- package/ReactAndroid/gradle.properties +1 -1
- package/ReactAndroid/hermes-engine/build.gradle.kts +17 -0
- package/ReactAndroid/publish.gradle +20 -46
- 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 +1 -1
- package/ReactAndroid/src/main/java/com/facebook/react/devsupport/inspector/FrameTimingsObserver.kt +127 -26
- 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/systeminfo/ReactNativeVersion.kt +2 -2
- package/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.kt +50 -10
- package/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java +14 -4
- package/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java +14 -4
- package/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewHelper.kt +46 -6
- package/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.kt +1 -0
- package/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewManager.kt +5 -0
- 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 +14 -0
- package/ReactAndroid/src/main/jni/react/runtime/jni/JReactHostInspectorTarget.h +18 -4
- package/ReactCommon/React-Fabric.podspec +6 -0
- package/ReactCommon/cxxreact/ReactNativeVersion.h +3 -3
- package/ReactCommon/jsinspector-modern/HostAgent.cpp +36 -0
- package/ReactCommon/jsinspector-modern/HostTarget.cpp +7 -1
- package/ReactCommon/jsinspector-modern/HostTarget.h +25 -0
- package/ReactCommon/jsinspector-modern/HostTargetTracing.cpp +1 -1
- package/ReactCommon/jsinspector-modern/HostTargetTracing.h +4 -4
- package/ReactCommon/jsinspector-modern/InspectorFlags.cpp +12 -0
- package/ReactCommon/jsinspector-modern/InspectorFlags.h +12 -0
- 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/tests/HostTargetTest.cpp +12 -0
- package/ReactCommon/jsinspector-modern/tests/InspectorMocks.h +3 -2
- package/ReactCommon/jsinspector-modern/tests/JsiIntegrationTest.cpp +1 -0
- package/ReactCommon/jsinspector-modern/tests/NetworkReporterTest.cpp +1 -1
- package/ReactCommon/jsinspector-modern/tests/TracingTest.cpp +1 -1
- 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 +7 -3
- package/ReactCommon/jsinspector-modern/tracing/HostTracingProfileSerializer.cpp +52 -29
- package/ReactCommon/jsinspector-modern/tracing/HostTracingProfileSerializer.h +6 -6
- package/ReactCommon/jsinspector-modern/tracing/PerformanceTracerSection.h +113 -0
- package/ReactCommon/jsinspector-modern/tracing/React-jsinspectortracing.podspec +1 -0
- package/ReactCommon/jsinspector-modern/tracing/TraceEventGenerator.cpp +12 -5
- package/ReactCommon/jsinspector-modern/tracing/TraceEventGenerator.h +3 -1
- package/ReactCommon/jsinspector-modern/tracing/TraceEventSerializer.cpp +42 -0
- package/ReactCommon/jsinspector-modern/tracing/TraceEventSerializer.h +7 -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 +135 -45
- 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/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/renderer/components/view/BaseViewProps.cpp +7 -0
- package/ReactCommon/react/renderer/components/view/BaseViewProps.h +1 -0
- package/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/HostPlatformViewProps.cpp +18 -0
- package/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/HostPlatformViewProps.h +1 -0
- package/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTHost.mm +115 -0
- package/ReactCommon/{jsinspector-modern → react/utils}/Base64.h +2 -2
- package/package.json +11 -11
- package/scripts/cocoapods/utils.rb +1 -0
- package/scripts/react_native_pods.rb +1 -0
- package/scripts/replace-rncore-version.js +72 -15
- 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/types/public/ReactNativeTVTypes.d.ts +9 -0
|
@@ -87,13 +87,13 @@ class MockInspectorPackagerConnectionDelegate : public InspectorPackagerConnecti
|
|
|
87
87
|
explicit MockInspectorPackagerConnectionDelegate(folly::Executor &executor) : executor_(executor)
|
|
88
88
|
{
|
|
89
89
|
using namespace testing;
|
|
90
|
-
ON_CALL(*this, scheduleCallback(_, _)).WillByDefault(
|
|
90
|
+
ON_CALL(*this, scheduleCallback(_, _)).WillByDefault([this](auto callback, auto delay) {
|
|
91
91
|
if (auto scheduledExecutor = dynamic_cast<folly::ScheduledExecutor *>(&executor_)) {
|
|
92
92
|
scheduledExecutor->scheduleAt(callback, scheduledExecutor->now() + delay);
|
|
93
93
|
} else {
|
|
94
94
|
executor_.add(callback);
|
|
95
95
|
}
|
|
96
|
-
})
|
|
96
|
+
});
|
|
97
97
|
EXPECT_CALL(*this, scheduleCallback(_, _)).Times(AnyNumber());
|
|
98
98
|
}
|
|
99
99
|
|
|
@@ -137,6 +137,7 @@ class MockHostTargetDelegate : public HostTargetDelegate {
|
|
|
137
137
|
loadNetworkResource,
|
|
138
138
|
(const LoadNetworkResourceRequest ¶ms, ScopedExecutor<NetworkRequestListener> executor),
|
|
139
139
|
(override));
|
|
140
|
+
MOCK_METHOD(std::optional<std::string>, captureScreenshot, (const PageCaptureScreenshotRequest &request), (override));
|
|
140
141
|
|
|
141
142
|
HostTargetTracingDelegate *getTracingDelegate() override
|
|
142
143
|
{
|
|
@@ -358,6 +358,7 @@ TYPED_TEST(JsiIntegrationPortableTest, ReactNativeApplicationEnable) {
|
|
|
358
358
|
"method": "ReactNativeApplication.metadataUpdated",
|
|
359
359
|
"params": {
|
|
360
360
|
"integrationName": "JsiIntegrationTest",
|
|
361
|
+
"unstable_frameRecordingEnabled": false,
|
|
361
362
|
"unstable_isProfilingBuild": false,
|
|
362
363
|
"unstable_networkInspectionEnabled": false
|
|
363
364
|
}
|
|
@@ -38,10 +38,10 @@ class NetworkReporterTestBase : public TracingTestBase<
|
|
|
38
38
|
protected:
|
|
39
39
|
NetworkReporterTestBase()
|
|
40
40
|
: TracingTestBase({
|
|
41
|
-
.networkInspectionEnabled = true,
|
|
42
41
|
.enableNetworkEventReporting =
|
|
43
42
|
WithParamInterface<Params>::GetParam()
|
|
44
43
|
.enableNetworkEventReporting,
|
|
44
|
+
.networkInspectionEnabled = true,
|
|
45
45
|
}) {}
|
|
46
46
|
|
|
47
47
|
void SetUp() override {
|
|
@@ -103,7 +103,7 @@ TEST_F(TracingTest, EmitsScreenshotEventWhenScreenshotValuePassed) {
|
|
|
103
103
|
11, // threadId
|
|
104
104
|
now,
|
|
105
105
|
now + HighResDuration::fromNanoseconds(50),
|
|
106
|
-
|
|
106
|
+
std::vector<uint8_t>{}));
|
|
107
107
|
|
|
108
108
|
auto allTraceEvents = endTracingAndCollectEvents();
|
|
109
109
|
EXPECT_THAT(allTraceEvents, Contains(AtJsonPtr("/name", "Screenshot")));
|
|
@@ -26,11 +26,21 @@ class ReactNativeFeatureFlagsOverrides
|
|
|
26
26
|
const InspectorFlagOverrides& overrides)
|
|
27
27
|
: overrides_(overrides) {}
|
|
28
28
|
|
|
29
|
+
bool fuseboxScreenshotCaptureEnabled() override {
|
|
30
|
+
return overrides_.screenshotCaptureEnabled.value_or(
|
|
31
|
+
ReactNativeFeatureFlagsDefaults::fuseboxScreenshotCaptureEnabled());
|
|
32
|
+
}
|
|
33
|
+
|
|
29
34
|
bool fuseboxEnabledRelease() override {
|
|
30
35
|
return overrides_.fuseboxEnabledRelease.value_or(
|
|
31
36
|
ReactNativeFeatureFlagsDefaults::fuseboxEnabledRelease());
|
|
32
37
|
}
|
|
33
38
|
|
|
39
|
+
bool fuseboxFrameRecordingEnabled() override {
|
|
40
|
+
return overrides_.frameRecordingEnabled.value_or(
|
|
41
|
+
ReactNativeFeatureFlagsDefaults::fuseboxFrameRecordingEnabled());
|
|
42
|
+
}
|
|
43
|
+
|
|
34
44
|
bool fuseboxNetworkInspectionEnabled() override {
|
|
35
45
|
return overrides_.networkInspectionEnabled.value_or(
|
|
36
46
|
ReactNativeFeatureFlagsDefaults::fuseboxNetworkInspectionEnabled());
|
|
@@ -19,9 +19,11 @@ namespace facebook::react::jsinspector_modern {
|
|
|
19
19
|
struct InspectorFlagOverrides {
|
|
20
20
|
// NOTE: Keep these entries in sync with ReactNativeFeatureFlagsOverrides in
|
|
21
21
|
// the implementation file.
|
|
22
|
+
std::optional<bool> screenshotCaptureEnabled;
|
|
23
|
+
std::optional<bool> enableNetworkEventReporting;
|
|
24
|
+
std::optional<bool> frameRecordingEnabled;
|
|
22
25
|
std::optional<bool> fuseboxEnabledRelease;
|
|
23
26
|
std::optional<bool> networkInspectionEnabled;
|
|
24
|
-
std::optional<bool> enableNetworkEventReporting;
|
|
25
27
|
};
|
|
26
28
|
|
|
27
29
|
/**
|
|
@@ -11,6 +11,10 @@
|
|
|
11
11
|
|
|
12
12
|
#include <react/timing/primitives.h>
|
|
13
13
|
|
|
14
|
+
#include <cstdint>
|
|
15
|
+
#include <optional>
|
|
16
|
+
#include <vector>
|
|
17
|
+
|
|
14
18
|
namespace facebook::react::jsinspector_modern::tracing {
|
|
15
19
|
|
|
16
20
|
using FrameSequenceId = uint64_t;
|
|
@@ -26,7 +30,7 @@ struct FrameTimingSequence {
|
|
|
26
30
|
ThreadId threadId,
|
|
27
31
|
HighResTimeStamp beginTimestamp,
|
|
28
32
|
HighResTimeStamp endTimestamp,
|
|
29
|
-
std::optional<std::
|
|
33
|
+
std::optional<std::vector<uint8_t>> screenshot = std::nullopt)
|
|
30
34
|
: id(id),
|
|
31
35
|
threadId(threadId),
|
|
32
36
|
beginTimestamp(beginTimestamp),
|
|
@@ -49,9 +53,9 @@ struct FrameTimingSequence {
|
|
|
49
53
|
HighResTimeStamp endTimestamp;
|
|
50
54
|
|
|
51
55
|
/**
|
|
52
|
-
* Optional screenshot data
|
|
56
|
+
* Optional screenshot data captured during the frame.
|
|
53
57
|
*/
|
|
54
|
-
std::optional<std::
|
|
58
|
+
std::optional<std::vector<uint8_t>> screenshot;
|
|
55
59
|
};
|
|
56
60
|
|
|
57
61
|
} // namespace facebook::react::jsinspector_modern::tracing
|
|
@@ -14,13 +14,6 @@ namespace facebook::react::jsinspector_modern::tracing {
|
|
|
14
14
|
|
|
15
15
|
namespace {
|
|
16
16
|
|
|
17
|
-
folly::dynamic generateNewChunk(uint16_t chunkSize) {
|
|
18
|
-
folly::dynamic chunk = folly::dynamic::array();
|
|
19
|
-
chunk.reserve(chunkSize);
|
|
20
|
-
|
|
21
|
-
return chunk;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
17
|
/**
|
|
25
18
|
* Hardcoded layer tree ID for all recorded frames.
|
|
26
19
|
* https://chromedevtools.github.io/devtools-protocol/tot/LayerTree/
|
|
@@ -32,14 +25,14 @@ constexpr int FALLBACK_LAYER_TREE_ID = 1;
|
|
|
32
25
|
/* static */ void HostTracingProfileSerializer::emitAsDataCollectedChunks(
|
|
33
26
|
HostTracingProfile&& hostTracingProfile,
|
|
34
27
|
const std::function<void(folly::dynamic&&)>& chunkCallback,
|
|
35
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
67
|
-
folly::dynamic chunk =
|
|
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
|
-
|
|
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 =
|
|
69
|
+
chunk = folly::dynamic::array();
|
|
70
|
+
currentChunkBytes = 0;
|
|
73
71
|
}
|
|
74
72
|
|
|
75
|
-
chunk.push_back(
|
|
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
|
-
|
|
87
|
+
size_t maxChunkBytes) {
|
|
89
88
|
if (frameTimings.empty()) {
|
|
90
89
|
return;
|
|
91
90
|
}
|
|
92
91
|
|
|
93
|
-
folly::dynamic chunk =
|
|
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
|
-
|
|
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
|
-
|
|
105
|
-
|
|
106
|
-
|
|
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
|
-
|
|
119
|
-
TraceEventSerializer::serialize(std::move(beginDrawingEvent))
|
|
120
|
-
|
|
121
|
-
|
|
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
|
-
|
|
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
|
|
28
|
-
* \p profileTraceEventsChunkSize, depending on type, and sent with
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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::
|
|
75
|
+
std::vector<uint8_t>&& snapshot,
|
|
74
76
|
HighResTimeStamp expectedDisplayTime,
|
|
75
77
|
ProcessId processId,
|
|
76
78
|
ThreadId threadId) {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
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::
|
|
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
|
-
|
|
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
|