99 lines
3.5 KiB
C++
99 lines
3.5 KiB
C++
/*
|
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*/
|
|
|
|
#include <jsinspector-modern/InspectorFlags.h>
|
|
#include <jsinspector-modern/RuntimeTarget.h>
|
|
#include <jsinspector-modern/network/NetworkHandler.h>
|
|
|
|
#include <react/utils/Uuid.h>
|
|
|
|
using namespace facebook::jsi;
|
|
using namespace std::string_literals;
|
|
|
|
namespace facebook::react::jsinspector_modern {
|
|
|
|
namespace {
|
|
|
|
/**
|
|
* JS `Object.create()`
|
|
*/
|
|
Object objectCreate(Runtime& runtime, Value prototype) {
|
|
auto objectGlobal = runtime.global().getPropertyAsObject(runtime, "Object");
|
|
auto createFn = objectGlobal.getPropertyAsFunction(runtime, "create");
|
|
return createFn.callWithThis(runtime, objectGlobal, prototype)
|
|
.getObject(runtime);
|
|
}
|
|
|
|
/**
|
|
* JS `Object.freeze()`
|
|
*/
|
|
Object objectFreeze(Runtime& runtime, Object object) {
|
|
auto objectGlobal = runtime.global().getPropertyAsObject(runtime, "Object");
|
|
auto freezeFn = objectGlobal.getPropertyAsFunction(runtime, "freeze");
|
|
return freezeFn.callWithThis(runtime, objectGlobal, object)
|
|
.getObject(runtime);
|
|
}
|
|
|
|
} // namespace
|
|
|
|
void RuntimeTarget::installNetworkReporterAPI() {
|
|
if (!InspectorFlags::getInstance().getNetworkInspectionEnabled()) {
|
|
return;
|
|
}
|
|
auto jsiCreateDevToolsRequestId = [selfWeak = weak_from_this()](
|
|
Runtime& runtime,
|
|
const Value& /*thisVal*/,
|
|
const Value* /*args*/,
|
|
size_t /*count*/) -> Value {
|
|
std::optional<std::string> devToolsRequestId;
|
|
tryExecuteSync(selfWeak, [&](RuntimeTarget& self) {
|
|
devToolsRequestId = self.createNetworkRequestId();
|
|
if (self.isDomainEnabled(Domain::Network)) {
|
|
// Q: Why is it safe to use self.delegate_ here?
|
|
// A: Because the caller of InspectorTarget::registerRuntime
|
|
// is explicitly required to guarantee that the delegate not
|
|
// only outlives the target, but also outlives all JS code
|
|
// execution that occurs on the JS thread.
|
|
auto stackTrace = self.delegate_.captureStackTrace(runtime);
|
|
auto cdpStackTrace = self.delegate_.serializeStackTrace(*stackTrace);
|
|
if (cdpStackTrace) {
|
|
NetworkHandler::getInstance().recordRequestInitiatorStack(
|
|
*devToolsRequestId, std::move(*cdpStackTrace));
|
|
}
|
|
}
|
|
});
|
|
if (!devToolsRequestId) {
|
|
throw JSError(runtime, "React Native Runtime is shutting down");
|
|
}
|
|
return String::createFromUtf8(runtime, *devToolsRequestId);
|
|
};
|
|
|
|
jsExecutor_([selfWeak = weak_from_this(),
|
|
selfExecutor = executorFromThis(),
|
|
jsiCreateDevToolsRequestId =
|
|
std::move(jsiCreateDevToolsRequestId)](Runtime& runtime) {
|
|
auto globalObj = runtime.global();
|
|
auto networkReporterApi = objectCreate(runtime, nullptr);
|
|
networkReporterApi.setProperty(
|
|
runtime,
|
|
"createDevToolsRequestId",
|
|
Function::createFromHostFunction(
|
|
runtime,
|
|
PropNameID::forAscii(runtime, "createDevToolsRequestId"),
|
|
0,
|
|
jsiCreateDevToolsRequestId));
|
|
networkReporterApi = objectFreeze(runtime, std::move(networkReporterApi));
|
|
globalObj.setProperty(runtime, "__NETWORK_REPORTER__", networkReporterApi);
|
|
});
|
|
}
|
|
|
|
std::string RuntimeTarget::createNetworkRequestId() {
|
|
return generateRandomUuidString();
|
|
}
|
|
|
|
} // namespace facebook::react::jsinspector_modern
|