Refactor Hermes CDP integrations into HermesRuntimeTargetDelegate (#43326)

Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43326

Changelog: [Internal]

Extracts the common parts of `HermesJSRuntime` (Bridgeless) and `HermesExecutor` (Bridge) that pertain to integration with the modern CDP backend into a new `HermesRuntimeTargetDelegate` class. This also makes the `HermesRuntimeAgentDelegate` class fully private.

As a followup, we *might* want to change `JSRuntime` and `JSExecutor` so they don't *implement* `RuntimeTargetDelegate` but are required to expose a `RuntimeTargetDelegate& getRuntimeTargetDelegate()` method instead. That would remove some of the boilerplate required for our current "aggregation" approach.

Reviewed By: huntie

Differential Revision: D54537844

fbshipit-source-id: f8c51fda0dbf28add1daeb95c991a34670f6854f
This commit is contained in:
Moti Zilberman
2024-03-06 02:18:48 -08:00
committed by Facebook GitHub Bot
parent 702aa25870
commit 1caa0a9ea9
7 changed files with 183 additions and 62 deletions
@@ -15,7 +15,6 @@
#include <jsi/decorator.h>
#include <jsinspector-modern/InspectorFlags.h>
#include <hermes/inspector-modern/chrome/HermesRuntimeAgentDelegate.h>
#include <hermes/inspector-modern/chrome/Registration.h>
#include <hermes/inspector/RuntimeAdapter.h>
@@ -253,9 +252,10 @@ HermesExecutor::HermesExecutor(
RuntimeInstaller runtimeInstaller,
HermesRuntime& hermesRuntime)
: JSIExecutor(runtime, delegate, timeoutInvoker, runtimeInstaller),
jsQueue_(jsQueue),
runtime_(runtime),
hermesRuntime_(hermesRuntime) {}
targetDelegate_(
std::shared_ptr<HermesRuntime>(runtime_, &hermesRuntime),
std::move(jsQueue)) {}
std::unique_ptr<jsinspector_modern::RuntimeAgentDelegate>
HermesExecutor::createAgentDelegate(
@@ -265,28 +265,11 @@ HermesExecutor::createAgentDelegate(
previouslyExportedState,
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,
std::move(previouslyExportedState),
executionContextDescription,
hermesRuntimeShared,
[jsQueueWeak = std::weak_ptr(jsQueue_),
runtimeWeak = std::weak_ptr(runtime_)](auto fn) {
auto jsQueue = jsQueueWeak.lock();
if (!jsQueue) {
return;
}
jsQueue->runOnQueue([runtimeWeak, fn]() {
auto runtime = runtimeWeak.lock();
if (!runtime) {
return;
}
fn(*runtime);
});
}));
return targetDelegate_.createAgentDelegate(
std::move(frontendChannel),
sessionState,
std::move(previouslyExportedState),
executionContextDescription);
}
} // namespace facebook::react
@@ -8,6 +8,7 @@
#pragma once
#include <hermes/hermes.h>
#include <hermes/inspector-modern/chrome/HermesRuntimeTargetDelegate.h>
#include <jsireact/JSIExecutor.h>
#include <utility>
@@ -65,9 +66,8 @@ class HermesExecutor : public JSIExecutor {
private:
JSIScopedTimeoutInvoker timeoutInvoker_;
std::shared_ptr<MessageQueueThread> jsQueue_;
std::shared_ptr<jsi::Runtime> runtime_;
hermes::HermesRuntime& hermesRuntime_;
jsinspector_modern::HermesRuntimeTargetDelegate targetDelegate_;
};
} // namespace facebook::react
@@ -0,0 +1,97 @@
/*
* 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 "HermesRuntimeTargetDelegate.h"
#include "HermesRuntimeAgentDelegate.h"
#include <utility>
using namespace facebook::hermes;
namespace facebook::react::jsinspector_modern {
class HermesRuntimeTargetDelegate::Impl : public RuntimeTargetDelegate {
public:
Impl(
std::shared_ptr<HermesRuntime> hermesRuntime,
std::shared_ptr<MessageQueueThread> jsMessageQueueThread)
: Impl(
hermesRuntime,
[msgQueueThreadWeak = std::weak_ptr(jsMessageQueueThread),
runtimeWeak = std::weak_ptr(hermesRuntime)](auto fn) {
auto msgQueueThread = msgQueueThreadWeak.lock();
if (!msgQueueThread) {
return;
}
msgQueueThread->runOnQueue([runtimeWeak, fn]() {
auto runtime = runtimeWeak.lock();
if (!runtime) {
return;
}
fn(*runtime);
});
}) {}
Impl(
std::shared_ptr<HermesRuntime> hermesRuntime,
RuntimeExecutor runtimeExecutor)
: runtime_(std::move(hermesRuntime)),
runtimeExecutor_(std::move(runtimeExecutor)) {}
// RuntimeTargetDelegate methods
std::unique_ptr<RuntimeAgentDelegate> createAgentDelegate(
FrontendChannel frontendChannel,
SessionState& sessionState,
std::unique_ptr<RuntimeAgentDelegate::ExportedState>
previouslyExportedState,
const ExecutionContextDescription& executionContextDescription) override {
return std::unique_ptr<RuntimeAgentDelegate>(new HermesRuntimeAgentDelegate(
frontendChannel,
sessionState,
std::move(previouslyExportedState),
executionContextDescription,
runtime_,
runtimeExecutor_));
}
private:
std::shared_ptr<HermesRuntime> runtime_;
RuntimeExecutor runtimeExecutor_;
};
HermesRuntimeTargetDelegate::HermesRuntimeTargetDelegate(
std::shared_ptr<HermesRuntime> hermesRuntime,
std::shared_ptr<MessageQueueThread> jsMessageQueueThread)
: impl_(std::make_unique<Impl>(
std::move(hermesRuntime),
std::move(jsMessageQueueThread))) {}
HermesRuntimeTargetDelegate::HermesRuntimeTargetDelegate(
std::shared_ptr<HermesRuntime> hermesRuntime,
RuntimeExecutor runtimeExecutor)
: impl_(std::make_unique<Impl>(
std::move(hermesRuntime),
std::move(runtimeExecutor))) {}
HermesRuntimeTargetDelegate::~HermesRuntimeTargetDelegate() = default;
std::unique_ptr<RuntimeAgentDelegate>
HermesRuntimeTargetDelegate::createAgentDelegate(
FrontendChannel frontendChannel,
SessionState& sessionState,
std::unique_ptr<RuntimeAgentDelegate::ExportedState>
previouslyExportedState,
const ExecutionContextDescription& executionContextDescription) {
return impl_->createAgentDelegate(
frontendChannel,
sessionState,
std::move(previouslyExportedState),
executionContextDescription);
}
} // namespace facebook::react::jsinspector_modern
@@ -0,0 +1,58 @@
/*
* 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 <ReactCommon/RuntimeExecutor.h>
#include <cxxreact/MessageQueueThread.h>
#include <hermes/hermes.h>
#include <jsinspector-modern/ReactCdp.h>
#include <memory>
namespace facebook::react::jsinspector_modern {
/**
* A RuntimeTargetDelegate that enables debugging a Hermes runtime over CDP.
*/
class HermesRuntimeTargetDelegate : public RuntimeTargetDelegate {
public:
/**
* Creates a HermesRuntimeTargetDelegate for the given runtime and message
* queue thread.
*/
HermesRuntimeTargetDelegate(
std::shared_ptr<hermes::HermesRuntime> hermesRuntime,
std::shared_ptr<MessageQueueThread> jsMessageQueueThread);
/**
* Creates a HermesRuntimeTargetDelegate for the given runtime and executor.
*/
HermesRuntimeTargetDelegate(
std::shared_ptr<hermes::HermesRuntime> hermesRuntime,
RuntimeExecutor runtimeExecutor);
~HermesRuntimeTargetDelegate() override;
// RuntimeTargetDelegate methods
std::unique_ptr<jsinspector_modern::RuntimeAgentDelegate> createAgentDelegate(
jsinspector_modern::FrontendChannel frontendChannel,
jsinspector_modern::SessionState& sessionState,
std::unique_ptr<jsinspector_modern::RuntimeAgentDelegate::ExportedState>
previouslyExportedState,
const jsinspector_modern::ExecutionContextDescription&
executionContextDescription) override;
private:
class Impl;
std::unique_ptr<Impl> impl_;
};
} // namespace facebook::react::jsinspector_modern
@@ -7,8 +7,6 @@
#include <folly/executors/QueuedImmediateExecutor.h>
#include <hermes/inspector-modern/chrome/HermesRuntimeAgentDelegate.h>
#include "JsiIntegrationTestHermesEngineAdapter.h"
using facebook::hermes::makeHermesRuntime;
@@ -17,7 +15,9 @@ namespace facebook::react::jsinspector_modern {
JsiIntegrationTestHermesEngineAdapter::JsiIntegrationTestHermesEngineAdapter(
folly::Executor& jsExecutor)
: runtime_{hermes::makeHermesRuntime()}, jsExecutor_{jsExecutor} {}
: runtime_{hermes::makeHermesRuntime()},
jsExecutor_{jsExecutor},
targetDelegate_(runtime_, getRuntimeExecutor()) {}
std::unique_ptr<RuntimeAgentDelegate>
JsiIntegrationTestHermesEngineAdapter::createAgentDelegate(
@@ -26,14 +26,11 @@ JsiIntegrationTestHermesEngineAdapter::createAgentDelegate(
std::unique_ptr<RuntimeAgentDelegate::ExportedState>
previouslyExportedState,
const ExecutionContextDescription& executionContextDescription) {
return std::unique_ptr<jsinspector_modern::RuntimeAgentDelegate>(
new HermesRuntimeAgentDelegate(
frontendChannel,
sessionState,
std::move(previouslyExportedState),
executionContextDescription,
runtime_,
getRuntimeExecutor()));
return targetDelegate_.createAgentDelegate(
std::move(frontendChannel),
sessionState,
std::move(previouslyExportedState),
executionContextDescription);
}
jsi::Runtime& JsiIntegrationTestHermesEngineAdapter::getRuntime()
@@ -11,6 +11,7 @@
#include <folly/executors/QueuedImmediateExecutor.h>
#include <hermes/hermes.h>
#include <hermes/inspector-modern/chrome/HermesRuntimeTargetDelegate.h>
#include <jsi/jsi.h>
#include <memory>
@@ -39,6 +40,7 @@ class JsiIntegrationTestHermesEngineAdapter : public RuntimeTargetDelegate {
private:
std::shared_ptr<facebook::hermes::HermesRuntime> runtime_;
folly::Executor& jsExecutor_;
HermesRuntimeTargetDelegate targetDelegate_;
};
} // namespace facebook::react::jsinspector_modern
@@ -7,7 +7,7 @@
#include "HermesInstance.h"
#include <hermes/inspector-modern/chrome/HermesRuntimeAgentDelegate.h>
#include <hermes/inspector-modern/chrome/HermesRuntimeTargetDelegate.h>
#include <jsi/jsilib.h>
#include <jsinspector-modern/InspectorFlags.h>
#include <react/featureflags/ReactNativeFeatureFlags.h>
@@ -98,7 +98,7 @@ class HermesJSRuntime : public JSRuntime {
std::unique_ptr<HermesRuntime> runtime,
std::shared_ptr<MessageQueueThread> msgQueueThread)
: runtime_(std::move(runtime)),
msgQueueThread_(std::move(msgQueueThread)) {}
targetDelegate_(runtime_, std::move(msgQueueThread)) {}
jsi::Runtime& getRuntime() noexcept override {
return *runtime_;
@@ -111,32 +111,16 @@ class HermesJSRuntime : public JSRuntime {
previouslyExportedState,
const jsinspector_modern::ExecutionContextDescription&
executionContextDescription) override {
return std::unique_ptr<jsinspector_modern::RuntimeAgentDelegate>(
new jsinspector_modern::HermesRuntimeAgentDelegate(
frontendChannel,
sessionState,
std::move(previouslyExportedState),
executionContextDescription,
runtime_,
[msgQueueThreadWeak = std::weak_ptr(msgQueueThread_),
runtimeWeak = std::weak_ptr(runtime_)](auto fn) {
auto msgQueueThread = msgQueueThreadWeak.lock();
if (!msgQueueThread) {
return;
}
msgQueueThread->runOnQueue([runtimeWeak, fn]() {
auto runtime = runtimeWeak.lock();
if (!runtime) {
return;
}
fn(*runtime);
});
}));
return targetDelegate_.createAgentDelegate(
std::move(frontendChannel),
sessionState,
std::move(previouslyExportedState),
executionContextDescription);
}
private:
std::shared_ptr<HermesRuntime> runtime_;
std::shared_ptr<MessageQueueThread> msgQueueThread_;
jsinspector_modern::HermesRuntimeTargetDelegate targetDelegate_;
};
std::unique_ptr<JSRuntime> HermesInstance::createJSRuntime(