/* * 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 #include #include #include 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 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