Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion packages/react-native/ReactCommon/cxxreact/JSExecutor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,10 @@ double JSExecutor::performanceNow() {
std::unique_ptr<jsinspector_modern::RuntimeAgentDelegate>
JSExecutor::createAgentDelegate(
jsinspector_modern::FrontendChannel frontendChannel,
jsinspector_modern::SessionState& sessionState) {
jsinspector_modern::SessionState& sessionState,
const jsinspector_modern::ExecutionContextDescription&
executionContextDescription) {
(void)executionContextDescription;
return std::make_unique<jsinspector_modern::FallbackRuntimeAgentDelegate>(
std::move(frontendChannel), sessionState, getDescription());
}
Expand Down
4 changes: 3 additions & 1 deletion packages/react-native/ReactCommon/cxxreact/JSExecutor.h
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,9 @@ class RN_EXPORT JSExecutor : public jsinspector_modern::RuntimeTargetDelegate {
virtual std::unique_ptr<jsinspector_modern::RuntimeAgentDelegate>
createAgentDelegate(
jsinspector_modern::FrontendChannel frontendChannel,
jsinspector_modern::SessionState& sessionState) override;
jsinspector_modern::SessionState& sessionState,
const jsinspector_modern::ExecutionContextDescription&
executionContextDescription) override;
};

} // namespace facebook::react
Original file line number Diff line number Diff line change
Expand Up @@ -260,12 +260,15 @@ HermesExecutor::HermesExecutor(
std::unique_ptr<jsinspector_modern::RuntimeAgentDelegate>
HermesExecutor::createAgentDelegate(
jsinspector_modern::FrontendChannel frontendChannel,
jsinspector_modern::SessionState& sessionState) {
jsinspector_modern::SessionState& sessionState,
const jsinspector_modern::ExecutionContextDescription&
executionContextDescription) {
std::shared_ptr<HermesRuntime> hermesRuntimeShared(runtime_, &hermesRuntime_);
return std::unique_ptr<jsinspector_modern::RuntimeAgentDelegate>(
new jsinspector_modern::HermesRuntimeAgentDelegate(
frontendChannel,
sessionState,
executionContextDescription,
hermesRuntimeShared,
[jsQueueWeak = std::weak_ptr(jsQueue_),
runtimeWeak = std::weak_ptr(runtime_)](auto fn) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,9 @@ class HermesExecutor : public JSIExecutor {
virtual std::unique_ptr<jsinspector_modern::RuntimeAgentDelegate>
createAgentDelegate(
jsinspector_modern::FrontendChannel frontendChannel,
jsinspector_modern::SessionState& sessionState) override;
jsinspector_modern::SessionState& sessionState,
const jsinspector_modern::ExecutionContextDescription&
executionContextDescription) override;

private:
JSIScopedTimeoutInvoker timeoutInvoker_;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ class HermesRuntimeAgentDelegateAdapter
*/
class HermesRuntimeAgentDelegate::Impl final : public RuntimeAgentDelegate {
using HermesCDPHandler = hermes::inspector_modern::chrome::CDPHandler;
using HermesExecutionContextDescription =
hermes::inspector_modern::chrome::CDPHandlerExecutionContextDescription;

public:
/**
Expand All @@ -73,6 +75,10 @@ class HermesRuntimeAgentDelegate::Impl final : public RuntimeAgentDelegate {
* \param sessionState The state of the current CDP session. This will only
* be accessed on the main thread (during the constructor, in handleRequest,
* etc).
* \param executionContextDescription A description of the execution context
* represented by this runtime. This is used for disambiguating the
* source/destination of CDP messages when there are multiple runtimes
* (concurrently or over the life of a Page).
* \param runtime The HermesRuntime that this agent is attached to.
* \param runtimeExecutor A callback for scheduling work on the JS thread.
* \c runtimeExecutor may drop scheduled work if the runtime is destroyed
Expand All @@ -81,6 +87,7 @@ class HermesRuntimeAgentDelegate::Impl final : public RuntimeAgentDelegate {
Impl(
FrontendChannel frontendChannel,
SessionState& sessionState,
const ExecutionContextDescription& executionContextDescription,
std::shared_ptr<hermes::HermesRuntime> runtime,
RuntimeExecutor runtimeExecutor)
: hermes_(HermesCDPHandler::create(
Expand All @@ -90,7 +97,13 @@ class HermesRuntimeAgentDelegate::Impl final : public RuntimeAgentDelegate {
/* waitForDebugger */ false,
/* enableConsoleAPICapturing */ false,
/* state */ nullptr,
{.isRuntimeDomainEnabled = sessionState.isRuntimeDomainEnabled})) {
{.isRuntimeDomainEnabled = sessionState.isRuntimeDomainEnabled},
HermesExecutionContextDescription{
.id = executionContextDescription.id,
.origin = executionContextDescription.origin,
.name = executionContextDescription.name,
.auxData = std::nullopt,
.shouldSendNotifications = false})) {
hermes_->registerCallbacks(
/* msgCallback */
[frontendChannel =
Expand Down Expand Up @@ -142,6 +155,7 @@ class HermesRuntimeAgentDelegate::Impl final
Impl(
FrontendChannel frontendChannel,
SessionState& sessionState,
const ExecutionContextDescription&,
std::shared_ptr<hermes::HermesRuntime> runtime,
RuntimeExecutor)
: FallbackRuntimeAgentDelegate(
Expand All @@ -155,11 +169,13 @@ class HermesRuntimeAgentDelegate::Impl final
HermesRuntimeAgentDelegate::HermesRuntimeAgentDelegate(
FrontendChannel frontendChannel,
SessionState& sessionState,
const ExecutionContextDescription& executionContextDescription,
std::shared_ptr<hermes::HermesRuntime> runtime,
RuntimeExecutor runtimeExecutor)
: impl_(std::make_unique<Impl>(
std::move(frontendChannel),
sessionState,
executionContextDescription,
std::move(runtime),
std::move(runtimeExecutor))) {}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ class HermesRuntimeAgentDelegate : public RuntimeAgentDelegate {
* \param sessionState The state of the current CDP session. This will only
* be accessed on the main thread (during the constructor, in handleRequest,
* etc).
* \param executionContextDescription A description of the execution context
* represented by this runtime. This is used for disambiguating the
* source/destination of CDP messages when there are multiple runtimes
* (concurrently or over the life of a Page).
* \param runtime The HermesRuntime that this agent is attached to.
* \param runtimeExecutor A callback for scheduling work on the JS thread.
* \c runtimeExecutor may drop scheduled work if the runtime is destroyed
Expand All @@ -34,6 +38,7 @@ class HermesRuntimeAgentDelegate : public RuntimeAgentDelegate {
HermesRuntimeAgentDelegate(
FrontendChannel frontendChannel,
SessionState& sessionState,
const ExecutionContextDescription& executionContextDescription,
std::shared_ptr<hermes::HermesRuntime> runtime,
RuntimeExecutor runtimeExecutor);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* 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.
*/

#pragma once

#include <cinttypes>
#include <optional>
#include <string>

namespace facebook::react::jsinspector_modern {

struct ExecutionContextDescription {
int32_t id{};
std::string origin{""};
std::string name{"<anonymous>"};
std::optional<std::string> uniqueId;
};

} // namespace facebook::react::jsinspector_modern
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,55 @@ InstanceAgent::InstanceAgent(
}

bool InstanceAgent::handleRequest(const cdp::PreparsedRequest& req) {
if (req.method == "Runtime.enable") {
maybeSendExecutionContextCreatedNotification();
// Fall through
}
if (runtimeAgent_ && runtimeAgent_->handleRequest(req)) {
return true;
}
return false;
}

void InstanceAgent::setCurrentRuntime(RuntimeTarget* runtimeTarget) {
auto previousRuntimeAgent = std::move(runtimeAgent_);
if (runtimeTarget) {
runtimeAgent_ = runtimeTarget->createAgent(frontendChannel_, sessionState_);
} else {
runtimeAgent_.reset();
}
if (!sessionState_.isRuntimeDomainEnabled) {
return;
}
if (previousRuntimeAgent != nullptr) {
auto& previousContext =
previousRuntimeAgent->getExecutionContextDescription();
folly::dynamic params =
folly::dynamic::object("executionContextId", previousContext.id);
if (previousContext.uniqueId.has_value()) {
params["executionContextUniqueId"] = *previousContext.uniqueId;
}
folly::dynamic contextDestroyed = folly::dynamic::object(
"method", "Runtime.executionContextDestroyed")("params", params);
frontendChannel_(folly::toJson(contextDestroyed));
}
maybeSendExecutionContextCreatedNotification();
}

void InstanceAgent::maybeSendExecutionContextCreatedNotification() {
if (runtimeAgent_ != nullptr) {
auto& newContext = runtimeAgent_->getExecutionContextDescription();
folly::dynamic params = folly::dynamic::object(
"context",
folly::dynamic::object("id", newContext.id)(
"origin", newContext.origin)("name", newContext.name));
if (newContext.uniqueId.has_value()) {
params["uniqueId"] = *newContext.uniqueId;
}
folly::dynamic contextCreated = folly::dynamic::object(
"method", "Runtime.executionContextCreated")("params", params);
frontendChannel_(folly::toJson(contextCreated));
}
}

} // namespace facebook::react::jsinspector_modern
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ class InstanceAgent final {
void setCurrentRuntime(RuntimeTarget* runtime);

private:
void maybeSendExecutionContextCreatedNotification();

FrontendChannel frontendChannel_;
InstanceTarget& target_;
std::shared_ptr<RuntimeAgent> runtimeAgent_;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,15 @@ RuntimeTarget& InstanceTarget::registerRuntime(
RuntimeExecutor jsExecutor) {
assert(!currentRuntime_ && "Only one Runtime allowed");
currentRuntime_ = RuntimeTarget::create(
delegate, jsExecutor, makeVoidExecutor(executorFromThis()));
ExecutionContextDescription{
// TODO: IDs should be unique within the current Page.
.id = 1,
.origin = "",
.name = "main",
.uniqueId = std::nullopt},
delegate,
jsExecutor,
makeVoidExecutor(executorFromThis()));

agents_.forEach([currentRuntime = &*currentRuntime_](InstanceAgent& agent) {
agent.setCurrentRuntime(currentRuntime);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#pragma once

#include <jsinspector-modern/ExecutionContext.h>
#include <jsinspector-modern/FallbackRuntimeAgentDelegate.h>
#include <jsinspector-modern/InstanceTarget.h>
#include <jsinspector-modern/PageTarget.h>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@ namespace facebook::react::jsinspector_modern {
RuntimeAgent::RuntimeAgent(
FrontendChannel frontendChannel,
RuntimeTarget& target,
const ExecutionContextDescription& executionContextDescription,
SessionState& sessionState,
std::unique_ptr<RuntimeAgentDelegate> delegate)
: frontendChannel_(std::move(frontendChannel)),
target_(target),
sessionState_(sessionState),
delegate_(std::move(delegate)) {
delegate_(std::move(delegate)),
executionContextDescription_(executionContextDescription) {
(void)target_;
(void)sessionState_;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,18 @@ class RuntimeAgent final {
* \param target The RuntimeTarget that this agent is attached to. The
* caller is responsible for ensuring that the RuntimeTarget outlives this
* object.
* \param executionContextDescription A description of the execution context
* represented by this runtime. This is used for disambiguating the
* source/destination of CDP messages when there are multiple runtimes
* (concurrently or over the life of a Page).
* \param sessionState The state of the session that created this agent.
* \param delegate The RuntimeAgentDelegate providing engine-specific
* CDP functionality.
*/
RuntimeAgent(
FrontendChannel frontendChannel,
RuntimeTarget& target,
const ExecutionContextDescription& executionContextDescription,
SessionState& sessionState,
std::unique_ptr<RuntimeAgentDelegate> delegate);

Expand All @@ -55,11 +60,17 @@ class RuntimeAgent final {
*/
bool handleRequest(const cdp::PreparsedRequest& req);

inline const ExecutionContextDescription& getExecutionContextDescription()
const {
return executionContextDescription_;
}

private:
FrontendChannel frontendChannel_;
RuntimeTarget& target_;
SessionState& sessionState_;
const std::unique_ptr<RuntimeAgentDelegate> delegate_;
const ExecutionContextDescription executionContextDescription_;
};

} // namespace facebook::react::jsinspector_modern
Original file line number Diff line number Diff line change
Expand Up @@ -10,28 +10,34 @@
namespace facebook::react::jsinspector_modern {

std::shared_ptr<RuntimeTarget> RuntimeTarget::create(
const ExecutionContextDescription& executionContextDescription,
RuntimeTargetDelegate& delegate,
RuntimeExecutor jsExecutor,
VoidExecutor selfExecutor) {
std::shared_ptr<RuntimeTarget> runtimeTarget{
new RuntimeTarget(delegate, jsExecutor)};
new RuntimeTarget(executionContextDescription, delegate, jsExecutor)};
runtimeTarget->setExecutor(selfExecutor);
return runtimeTarget;
}

RuntimeTarget::RuntimeTarget(
const ExecutionContextDescription& executionContextDescription,
RuntimeTargetDelegate& delegate,
RuntimeExecutor jsExecutor)
: delegate_(delegate), jsExecutor_(jsExecutor) {}
: executionContextDescription_(executionContextDescription),
delegate_(delegate),
jsExecutor_(jsExecutor) {}

std::shared_ptr<RuntimeAgent> RuntimeTarget::createAgent(
FrontendChannel channel,
SessionState& sessionState) {
auto runtimeAgent = std::make_shared<RuntimeAgent>(
channel,
*this,
executionContextDescription_,
sessionState,
delegate_.createAgentDelegate(channel, sessionState));
delegate_.createAgentDelegate(
channel, sessionState, executionContextDescription_));
agents_.insert(runtimeAgent);
return runtimeAgent;
}
Expand Down
Loading