react-native-tvos 0.85.2-0 → 0.85.3-0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Libraries/Core/ReactNativeVersion.js +1 -1
- package/Libraries/Utilities/HMRClient.js +28 -1
- package/React/Base/RCTVersion.m +1 -1
- 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/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 +1 -1
- package/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.kt +50 -10
- 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 +2 -2
- 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/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
|
@@ -190,6 +190,12 @@ Pod::Spec.new do |s|
|
|
|
190
190
|
sss.exclude_files = "react/renderer/observers/intersection/tests"
|
|
191
191
|
sss.header_dir = "react/renderer/observers/intersection"
|
|
192
192
|
end
|
|
193
|
+
|
|
194
|
+
ss.subspec "mutation" do |sss|
|
|
195
|
+
sss.source_files = podspec_sources("react/renderer/observers/mutation/**/*.{m,mm,cpp,h}", "react/renderer/observers/mutation/**/*.h")
|
|
196
|
+
sss.exclude_files = "react/renderer/observers/mutation/tests"
|
|
197
|
+
sss.header_dir = "react/renderer/observers/mutation"
|
|
198
|
+
end
|
|
193
199
|
end
|
|
194
200
|
|
|
195
201
|
s.subspec "telemetry" do |ss|
|
|
@@ -14,14 +14,14 @@
|
|
|
14
14
|
|
|
15
15
|
#define REACT_NATIVE_VERSION_MAJOR 0
|
|
16
16
|
#define REACT_NATIVE_VERSION_MINOR 85
|
|
17
|
-
#define REACT_NATIVE_VERSION_PATCH
|
|
17
|
+
#define REACT_NATIVE_VERSION_PATCH 3
|
|
18
18
|
|
|
19
19
|
namespace facebook::react {
|
|
20
20
|
|
|
21
21
|
struct ReactNativeVersionType {
|
|
22
22
|
int32_t Major = 0;
|
|
23
23
|
int32_t Minor = 85;
|
|
24
|
-
int32_t Patch =
|
|
24
|
+
int32_t Patch = 3;
|
|
25
25
|
std::string_view Prerelease = "0";
|
|
26
26
|
};
|
|
27
27
|
|
|
@@ -198,6 +198,42 @@ class HostAgent::Impl final {
|
|
|
198
198
|
.shouldSendOKResponse = true,
|
|
199
199
|
};
|
|
200
200
|
}
|
|
201
|
+
if (InspectorFlags::getInstance().getScreenshotCaptureEnabled()) {
|
|
202
|
+
if (req.method == "Page.captureScreenshot") {
|
|
203
|
+
std::optional<std::string> format;
|
|
204
|
+
std::optional<int> quality;
|
|
205
|
+
|
|
206
|
+
if (req.params.isObject()) {
|
|
207
|
+
if (req.params.count("format") != 0u) {
|
|
208
|
+
format = req.params.at("format").asString();
|
|
209
|
+
}
|
|
210
|
+
if (req.params.count("quality") != 0u) {
|
|
211
|
+
quality = static_cast<int>(req.params.at("quality").asInt());
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
auto base64Data = targetController_.getDelegate().captureScreenshot(
|
|
216
|
+
{.format = format, .quality = quality});
|
|
217
|
+
|
|
218
|
+
if (base64Data.has_value()) {
|
|
219
|
+
frontendChannel_(
|
|
220
|
+
cdp::jsonResult(
|
|
221
|
+
req.id,
|
|
222
|
+
folly::dynamic::object("data", std::move(*base64Data))));
|
|
223
|
+
} else {
|
|
224
|
+
frontendChannel_(
|
|
225
|
+
cdp::jsonError(
|
|
226
|
+
req.id,
|
|
227
|
+
cdp::ErrorCode::InternalError,
|
|
228
|
+
"Failed to capture screenshot"));
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
return {
|
|
232
|
+
.isFinishedHandlingRequest = true,
|
|
233
|
+
.shouldSendOKResponse = false,
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
}
|
|
201
237
|
if (req.method == "Overlay.setPausedInDebuggerMessage") {
|
|
202
238
|
auto message =
|
|
203
239
|
req.params.isObject() && (req.params.count("message") != 0u)
|
|
@@ -328,6 +328,7 @@ namespace {
|
|
|
328
328
|
struct StaticHostTargetMetadata {
|
|
329
329
|
std::optional<bool> isProfilingBuild;
|
|
330
330
|
std::optional<bool> networkInspectionEnabled;
|
|
331
|
+
std::optional<bool> frameRecordingEnabled;
|
|
331
332
|
};
|
|
332
333
|
|
|
333
334
|
StaticHostTargetMetadata getStaticHostMetadata() {
|
|
@@ -335,7 +336,8 @@ StaticHostTargetMetadata getStaticHostMetadata() {
|
|
|
335
336
|
|
|
336
337
|
return {
|
|
337
338
|
.isProfilingBuild = inspectorFlags.getIsProfilingBuild(),
|
|
338
|
-
.networkInspectionEnabled = inspectorFlags.getNetworkInspectionEnabled()
|
|
339
|
+
.networkInspectionEnabled = inspectorFlags.getNetworkInspectionEnabled(),
|
|
340
|
+
.frameRecordingEnabled = inspectorFlags.getFrameRecordingEnabled()};
|
|
339
341
|
}
|
|
340
342
|
|
|
341
343
|
} // namespace
|
|
@@ -370,6 +372,10 @@ folly::dynamic createHostMetadataPayload(const HostTargetMetadata& metadata) {
|
|
|
370
372
|
result["unstable_networkInspectionEnabled"] =
|
|
371
373
|
staticMetadata.networkInspectionEnabled.value();
|
|
372
374
|
}
|
|
375
|
+
if (staticMetadata.frameRecordingEnabled) {
|
|
376
|
+
result["unstable_frameRecordingEnabled"] =
|
|
377
|
+
staticMetadata.frameRecordingEnabled.value();
|
|
378
|
+
}
|
|
373
379
|
|
|
374
380
|
return result;
|
|
375
381
|
}
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
#include "ScopedExecutor.h"
|
|
17
17
|
#include "WeakList.h"
|
|
18
18
|
|
|
19
|
+
#include <functional>
|
|
19
20
|
#include <optional>
|
|
20
21
|
#include <set>
|
|
21
22
|
#include <string>
|
|
@@ -134,6 +135,19 @@ class HostTargetDelegate : public LoadNetworkResourceDelegate {
|
|
|
134
135
|
}
|
|
135
136
|
};
|
|
136
137
|
|
|
138
|
+
struct PageCaptureScreenshotRequest {
|
|
139
|
+
/**
|
|
140
|
+
* Image compression format. Defaults to "png".
|
|
141
|
+
* Allowed values: "jpeg", "png", "webp".
|
|
142
|
+
*/
|
|
143
|
+
std::optional<std::string> format;
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Compression quality from range [0..100] (jpeg only).
|
|
147
|
+
*/
|
|
148
|
+
std::optional<int> quality;
|
|
149
|
+
};
|
|
150
|
+
|
|
137
151
|
virtual ~HostTargetDelegate() override;
|
|
138
152
|
|
|
139
153
|
/**
|
|
@@ -181,6 +195,17 @@ class HostTargetDelegate : public LoadNetworkResourceDelegate {
|
|
|
181
195
|
"LoadNetworkResourceDelegate.loadNetworkResource is not implemented by this host target delegate.");
|
|
182
196
|
}
|
|
183
197
|
|
|
198
|
+
/**
|
|
199
|
+
* Called when the debugger requests a screenshot of the current page via
|
|
200
|
+
* @cdp Page.captureScreenshot. The delegate should capture the current
|
|
201
|
+
* view, encode it to the requested format, and return base64-encoded
|
|
202
|
+
* image data. Return std::nullopt on failure.
|
|
203
|
+
*/
|
|
204
|
+
virtual std::optional<std::string> captureScreenshot(const PageCaptureScreenshotRequest & /*request*/)
|
|
205
|
+
{
|
|
206
|
+
return std::nullopt;
|
|
207
|
+
}
|
|
208
|
+
|
|
184
209
|
/**
|
|
185
210
|
* An optional delegate that will be used by HostTarget to notify about tracing-related events.
|
|
186
211
|
*/
|
|
@@ -93,7 +93,7 @@ void HostTarget::recordFrameTimings(
|
|
|
93
93
|
std::lock_guard lock(tracingMutex_);
|
|
94
94
|
|
|
95
95
|
if (traceRecording_) {
|
|
96
|
-
traceRecording_->recordFrameTimings(frameTimingSequence);
|
|
96
|
+
traceRecording_->recordFrameTimings(std::move(frameTimingSequence));
|
|
97
97
|
} else {
|
|
98
98
|
assert(
|
|
99
99
|
false &&
|
|
@@ -35,10 +35,10 @@ void emitNotificationsForTracingProfile(
|
|
|
35
35
|
std::convertible_to<std::ranges::range_value_t<ChannelsRange>, FrontendChannel>
|
|
36
36
|
{
|
|
37
37
|
/**
|
|
38
|
-
*
|
|
39
|
-
* Tracing.dataCollected event.
|
|
38
|
+
* Maximum serialized byte size of a Trace Event chunk before it is flushed
|
|
39
|
+
* with a Tracing.dataCollected event.
|
|
40
40
|
*/
|
|
41
|
-
static constexpr
|
|
41
|
+
static constexpr size_t TRACE_EVENT_CHUNK_MAX_BYTES = 10 * 1024 * 1024; // 10 MiB
|
|
42
42
|
|
|
43
43
|
/**
|
|
44
44
|
* The maximum number of ProfileChunk trace events
|
|
@@ -65,7 +65,7 @@ void emitNotificationsForTracingProfile(
|
|
|
65
65
|
cdp::jsonNotification("Tracing.dataCollected", folly::dynamic::object("value", serializedChunk)));
|
|
66
66
|
}
|
|
67
67
|
},
|
|
68
|
-
|
|
68
|
+
TRACE_EVENT_CHUNK_MAX_BYTES,
|
|
69
69
|
PROFILE_TRACE_EVENT_CHUNK_SIZE);
|
|
70
70
|
|
|
71
71
|
for (auto &frontendChannel : channels) {
|
|
@@ -21,6 +21,14 @@ bool InspectorFlags::getAssertSingleHostState() const {
|
|
|
21
21
|
return loadFlagsAndAssertUnchanged().assertSingleHostState;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
+
bool InspectorFlags::getScreenshotCaptureEnabled() const {
|
|
25
|
+
return loadFlagsAndAssertUnchanged().screenshotCaptureEnabled;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
bool InspectorFlags::getFrameRecordingEnabled() const {
|
|
29
|
+
return loadFlagsAndAssertUnchanged().frameRecordingEnabled;
|
|
30
|
+
}
|
|
31
|
+
|
|
24
32
|
bool InspectorFlags::getFuseboxEnabled() const {
|
|
25
33
|
if (fuseboxDisabledForTest_) {
|
|
26
34
|
return false;
|
|
@@ -54,6 +62,10 @@ const InspectorFlags::Values& InspectorFlags::loadFlagsAndAssertUnchanged()
|
|
|
54
62
|
InspectorFlags::Values newValues = {
|
|
55
63
|
.assertSingleHostState =
|
|
56
64
|
ReactNativeFeatureFlags::fuseboxAssertSingleHostState(),
|
|
65
|
+
.screenshotCaptureEnabled =
|
|
66
|
+
ReactNativeFeatureFlags::fuseboxScreenshotCaptureEnabled(),
|
|
67
|
+
.frameRecordingEnabled =
|
|
68
|
+
ReactNativeFeatureFlags::fuseboxFrameRecordingEnabled(),
|
|
57
69
|
.fuseboxEnabled =
|
|
58
70
|
#if defined(REACT_NATIVE_DEBUGGER_ENABLED)
|
|
59
71
|
true,
|
|
@@ -36,6 +36,16 @@ class InspectorFlags {
|
|
|
36
36
|
*/
|
|
37
37
|
bool getIsProfilingBuild() const;
|
|
38
38
|
|
|
39
|
+
/**
|
|
40
|
+
* Flag determining if Page.captureScreenshot CDP method is enabled.
|
|
41
|
+
*/
|
|
42
|
+
bool getScreenshotCaptureEnabled() const;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Flag determining if frame recording (timings + screenshots) is enabled.
|
|
46
|
+
*/
|
|
47
|
+
bool getFrameRecordingEnabled() const;
|
|
48
|
+
|
|
39
49
|
/**
|
|
40
50
|
* Flag determining if network inspection is enabled.
|
|
41
51
|
*/
|
|
@@ -61,6 +71,8 @@ class InspectorFlags {
|
|
|
61
71
|
private:
|
|
62
72
|
struct Values {
|
|
63
73
|
bool assertSingleHostState;
|
|
74
|
+
bool screenshotCaptureEnabled;
|
|
75
|
+
bool frameRecordingEnabled;
|
|
64
76
|
bool fuseboxEnabled;
|
|
65
77
|
bool isProfilingBuild;
|
|
66
78
|
bool networkInspectionEnabled;
|
|
@@ -8,6 +8,10 @@
|
|
|
8
8
|
#include "RuntimeAgent.h"
|
|
9
9
|
#include "SessionState.h"
|
|
10
10
|
|
|
11
|
+
#include <folly/dynamic.h>
|
|
12
|
+
#include <jsinspector-modern/cdp/CdpJson.h>
|
|
13
|
+
|
|
14
|
+
#include <chrono>
|
|
11
15
|
#include <utility>
|
|
12
16
|
|
|
13
17
|
namespace facebook::react::jsinspector_modern {
|
|
@@ -119,6 +123,21 @@ void RuntimeAgent::notifyBindingCalled(
|
|
|
119
123
|
"name", bindingName)("payload", payload)));
|
|
120
124
|
}
|
|
121
125
|
|
|
126
|
+
void RuntimeAgent::notifyFastRefreshComplete() {
|
|
127
|
+
if (!sessionState_.isReactNativeApplicationDomainEnabled) {
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
folly::dynamic params = folly::dynamic::object(
|
|
131
|
+
"timestamp",
|
|
132
|
+
std::chrono::duration_cast<std::chrono::milliseconds>(
|
|
133
|
+
std::chrono::system_clock::now().time_since_epoch())
|
|
134
|
+
.count());
|
|
135
|
+
frontendChannel_(
|
|
136
|
+
cdp::jsonNotification(
|
|
137
|
+
"ReactNativeApplication.unstable_fastRefreshComplete",
|
|
138
|
+
std::move(params)));
|
|
139
|
+
}
|
|
140
|
+
|
|
122
141
|
RuntimeAgent::ExportedState RuntimeAgent::getExportedState() {
|
|
123
142
|
return {
|
|
124
143
|
.delegateState = delegate_ ? delegate_->getExportedState() : nullptr,
|
|
@@ -72,6 +72,13 @@ class RuntimeAgent final {
|
|
|
72
72
|
|
|
73
73
|
void notifyBindingCalled(const std::string &bindingName, const std::string &payload);
|
|
74
74
|
|
|
75
|
+
/**
|
|
76
|
+
* Called by RuntimeTarget when JS calls __notifyFastRefreshComplete().
|
|
77
|
+
* Emits a ReactNativeApplication.unstable_fastRefreshComplete CDP
|
|
78
|
+
* notification if the ReactNativeApplication domain is enabled.
|
|
79
|
+
*/
|
|
80
|
+
void notifyFastRefreshComplete();
|
|
81
|
+
|
|
75
82
|
struct ExportedState {
|
|
76
83
|
std::unique_ptr<RuntimeAgentDelegate::ExportedState> delegateState;
|
|
77
84
|
};
|
|
@@ -47,6 +47,8 @@ void RuntimeTarget::installGlobals() {
|
|
|
47
47
|
// NOTE: RuntimeTarget::installNetworkReporterAPI is in
|
|
48
48
|
// RuntimeTargetNetwork.cpp
|
|
49
49
|
installNetworkReporterAPI();
|
|
50
|
+
|
|
51
|
+
installFastRefreshHandler();
|
|
50
52
|
}
|
|
51
53
|
|
|
52
54
|
std::shared_ptr<RuntimeAgent> RuntimeTarget::createAgent(
|
|
@@ -128,6 +130,37 @@ void RuntimeTarget::installBindingHandler(const std::string& bindingName) {
|
|
|
128
130
|
});
|
|
129
131
|
}
|
|
130
132
|
|
|
133
|
+
void RuntimeTarget::installFastRefreshHandler() {
|
|
134
|
+
jsExecutor_([selfExecutor = executorFromThis()](jsi::Runtime& runtime) {
|
|
135
|
+
auto globalObj = runtime.global();
|
|
136
|
+
try {
|
|
137
|
+
auto name =
|
|
138
|
+
jsi::PropNameID::forUtf8(runtime, "__notifyFastRefreshComplete");
|
|
139
|
+
globalObj.setProperty(
|
|
140
|
+
runtime,
|
|
141
|
+
name,
|
|
142
|
+
jsi::Function::createFromHostFunction(
|
|
143
|
+
runtime,
|
|
144
|
+
name,
|
|
145
|
+
0,
|
|
146
|
+
[selfExecutor](
|
|
147
|
+
jsi::Runtime& /*rt*/,
|
|
148
|
+
const jsi::Value&,
|
|
149
|
+
const jsi::Value*,
|
|
150
|
+
size_t) -> jsi::Value {
|
|
151
|
+
selfExecutor([](auto& self) {
|
|
152
|
+
self.agents_.forEach(
|
|
153
|
+
[](auto& agent) { agent.notifyFastRefreshComplete(); });
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
return jsi::Value::undefined();
|
|
157
|
+
}));
|
|
158
|
+
} catch (jsi::JSError&) {
|
|
159
|
+
// Swallow JavaScript exceptions that occur while setting up the global.
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
|
|
131
164
|
void RuntimeTarget::emitDebuggerSessionCreated() {
|
|
132
165
|
jsExecutor_([selfExecutor = executorFromThis()](jsi::Runtime& runtime) {
|
|
133
166
|
try {
|
|
@@ -295,6 +295,12 @@ class JSINSPECTOR_EXPORT RuntimeTarget : public EnableExecutorFromThis<RuntimeTa
|
|
|
295
295
|
*/
|
|
296
296
|
void installGlobals();
|
|
297
297
|
|
|
298
|
+
/**
|
|
299
|
+
* Installs __notifyFastRefreshComplete on the runtime's global object.
|
|
300
|
+
* When called from JS, dispatches to all connected RuntimeAgents.
|
|
301
|
+
*/
|
|
302
|
+
void installFastRefreshHandler();
|
|
303
|
+
|
|
298
304
|
/**
|
|
299
305
|
* Install the console API handler.
|
|
300
306
|
*/
|
|
@@ -1579,4 +1579,16 @@ TEST_F(HostTargetTest, TracingDelegateIsNotifiedOnDirectTracingCall) {
|
|
|
1579
1579
|
page_->stopTracing();
|
|
1580
1580
|
}
|
|
1581
1581
|
|
|
1582
|
+
TEST_F(HostTargetProtocolTest, CaptureScreenshotNotSupportedWhenFlagDisabled) {
|
|
1583
|
+
EXPECT_CALL(
|
|
1584
|
+
fromPage(),
|
|
1585
|
+
onMessage(JsonParsed(AllOf(
|
|
1586
|
+
AtJsonPtr("/error/code", Eq(-32601)), AtJsonPtr("/id", Eq(1))))))
|
|
1587
|
+
.RetiresOnSaturation();
|
|
1588
|
+
toPage_->sendMessage(R"({
|
|
1589
|
+
"id": 1,
|
|
1590
|
+
"method": "Page.captureScreenshot"
|
|
1591
|
+
})");
|
|
1592
|
+
}
|
|
1593
|
+
|
|
1582
1594
|
} // namespace facebook::react::jsinspector_modern
|
|
@@ -87,13 +87,13 @@ class MockInspectorPackagerConnectionDelegate : public InspectorPackagerConnecti
|
|
|
87
87
|
explicit MockInspectorPackagerConnectionDelegate(folly::Executor &executor) : executor_(executor)
|
|
88
88
|
{
|
|
89
89
|
using namespace testing;
|
|
90
|
-
ON_CALL(*this, scheduleCallback(_, _)).WillByDefault(
|
|
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()) {
|