mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Create wrapper class for Hermes CDPAgent + CDPDebugAPI (#43352)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43352 ## Context We are migrating to the new Hermes `CDPAgent` and `CDPDebugAPI` APIs in the modern CDP server (previously `HermesCDPHandler`). ## This diff Adds the `HermesRuntimeAgentDelegateNew` class to provide a swap-in replacement for the existing `HermesRuntimeAgentDelegate` when we enable this via an incoming feature flag. Changelog: [Internal] Reviewed By: motiz88 Differential Revision: D53810356 fbshipit-source-id: c63684252230a747ecf0bd8cbb6f4e22052ed9bf
This commit is contained in:
committed by
Facebook GitHub Bot
parent
52bd8418d8
commit
166fdc5125
@@ -36,7 +36,7 @@ jobs:
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: packages/rn-tester/Pods
|
||||
key: v1-${{ runner.os }}-RNTesterPods-${{ hashFiles('packages/rn-tester/Podfile.lock') }}-${{ hashFiles('packages/rn-tester/Podfile') }}-${{ hashFiles('tmp/hermes/hermesversion') }}
|
||||
key: v2-${{ runner.os }}-RNTesterPods-${{ hashFiles('packages/rn-tester/Podfile.lock') }}-${{ hashFiles('packages/rn-tester/Podfile') }}-${{ hashFiles('tmp/hermes/hermesversion') }}
|
||||
- name: Pod Install
|
||||
run: |
|
||||
cd packages/rn-tester
|
||||
|
||||
+132
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* 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 "HermesRuntimeAgentDelegateNew.h"
|
||||
|
||||
// If HERMES_ENABLE_DEBUGGER isn't defined, we can't access any Hermes
|
||||
// CDP headers or types.
|
||||
|
||||
#ifdef HERMES_ENABLE_DEBUGGER
|
||||
#include <hermes/AsyncDebuggerAPI.h>
|
||||
#include <hermes/cdp/CDPAgent.h>
|
||||
#include <hermes/inspector/RuntimeAdapter.h>
|
||||
#else // HERMES_ENABLE_DEBUGGER
|
||||
#include <jsinspector-modern/FallbackRuntimeAgentDelegate.h>
|
||||
#endif // HERMES_ENABLE_DEBUGGER
|
||||
|
||||
#include <hermes/hermes.h>
|
||||
#include <jsinspector-modern/ReactCdp.h>
|
||||
|
||||
using namespace facebook::hermes;
|
||||
|
||||
namespace facebook::react::jsinspector_modern {
|
||||
|
||||
#ifdef HERMES_ENABLE_DEBUGGER
|
||||
|
||||
class HermesRuntimeAgentDelegateNew::Impl final : public RuntimeAgentDelegate {
|
||||
public:
|
||||
Impl(
|
||||
FrontendChannel frontendChannel,
|
||||
SessionState& /*unused*/,
|
||||
std::unique_ptr<RuntimeAgentDelegate::ExportedState>
|
||||
previouslyExportedState,
|
||||
const ExecutionContextDescription& executionContextDescription,
|
||||
HermesRuntime& runtime,
|
||||
HermesRuntimeTargetDelegate& runtimeTargetDelegate,
|
||||
const RuntimeExecutor& runtimeExecutor)
|
||||
: hermes_(hermes::cdp::CDPAgent::create(
|
||||
executionContextDescription.id,
|
||||
runtimeTargetDelegate.getCDPDebugAPI(),
|
||||
// RuntimeTask takes a HermesRuntime whereas our RuntimeExecutor
|
||||
// takes a jsi::Runtime.
|
||||
[runtimeExecutor,
|
||||
&runtime](facebook::hermes::debugger::RuntimeTask fn) {
|
||||
runtimeExecutor(
|
||||
[&runtime, fn = std::move(fn)](auto&) { fn(runtime); });
|
||||
},
|
||||
std::move(frontendChannel))) {
|
||||
// TODO(T178858701): Pass previouslyExportedState to CDPAgent
|
||||
(void)previouslyExportedState;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a CDP request. The response will be sent over the provided
|
||||
* \c FrontendChannel synchronously or asynchronously.
|
||||
* \param req The parsed request.
|
||||
* \returns true if this agent has responded, or will respond asynchronously,
|
||||
* to the request (with either a success or error message). False if the
|
||||
* agent expects another agent to respond to the request instead.
|
||||
*/
|
||||
bool handleRequest(const cdp::PreparsedRequest& req) override {
|
||||
// TODO: Change to string::starts_with when we're on C++20.
|
||||
if (req.method.rfind("Log.", 0) == 0) {
|
||||
// Since we know Hermes doesn't do anything useful with Log messages, but
|
||||
// our containing PageAgent will, just bail out early.
|
||||
// TODO: We need a way to negotiate this more dynamically with Hermes
|
||||
// through the API.
|
||||
return false;
|
||||
}
|
||||
// Forward everything else to Hermes's CDPAgent.
|
||||
hermes_->handleCommand(req.toJson());
|
||||
// Let the call know that this request is handled (i.e. it is Hermes's
|
||||
// responsibility to respond with either success or an error).
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<hermes::cdp::CDPAgent> hermes_;
|
||||
};
|
||||
|
||||
#else // !HERMES_ENABLE_DEBUGGER
|
||||
|
||||
/**
|
||||
* A stub for HermesRuntimeAgentDelegateNew when Hermes is compiled without
|
||||
* debugging support.
|
||||
*/
|
||||
class HermesRuntimeAgentDelegateNew::Impl final
|
||||
: public FallbackRuntimeAgentDelegate {
|
||||
public:
|
||||
Impl(
|
||||
FrontendChannel frontendChannel,
|
||||
SessionState& sessionState,
|
||||
std::unique_ptr<RuntimeAgentDelegate::ExportedState>,
|
||||
const ExecutionContextDescription&,
|
||||
HermesRuntime& runtime,
|
||||
HermesRuntimeTargetDelegate& runtimeTargetDelegate,
|
||||
RuntimeExecutor)
|
||||
: FallbackRuntimeAgentDelegate(
|
||||
std::move(frontendChannel),
|
||||
sessionState,
|
||||
runtime.description()) {}
|
||||
};
|
||||
|
||||
#endif // HERMES_ENABLE_DEBUGGER
|
||||
|
||||
HermesRuntimeAgentDelegateNew::HermesRuntimeAgentDelegateNew(
|
||||
FrontendChannel frontendChannel,
|
||||
SessionState& sessionState,
|
||||
std::unique_ptr<RuntimeAgentDelegate::ExportedState>
|
||||
previouslyExportedState,
|
||||
const ExecutionContextDescription& executionContextDescription,
|
||||
HermesRuntime& runtime,
|
||||
HermesRuntimeTargetDelegate& runtimeTargetDelegate,
|
||||
RuntimeExecutor runtimeExecutor)
|
||||
: impl_(std::make_unique<Impl>(
|
||||
std::move(frontendChannel),
|
||||
sessionState,
|
||||
std::move(previouslyExportedState),
|
||||
executionContextDescription,
|
||||
runtime,
|
||||
runtimeTargetDelegate,
|
||||
std::move(runtimeExecutor))) {}
|
||||
|
||||
bool HermesRuntimeAgentDelegateNew::handleRequest(
|
||||
const cdp::PreparsedRequest& req) {
|
||||
return impl_->handleRequest(req);
|
||||
}
|
||||
|
||||
} // namespace facebook::react::jsinspector_modern
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* 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 "HermesRuntimeTargetDelegate.h"
|
||||
|
||||
#include <ReactCommon/RuntimeExecutor.h>
|
||||
#include <hermes/hermes.h>
|
||||
#include <jsinspector-modern/ReactCdp.h>
|
||||
|
||||
namespace facebook::react::jsinspector_modern {
|
||||
|
||||
/**
|
||||
* A RuntimeAgentDelegate that handles requests from the Chrome DevTools
|
||||
* Protocol for an instance of Hermes, using the new CDPAgent API.
|
||||
*/
|
||||
class HermesRuntimeAgentDelegateNew : public RuntimeAgentDelegate {
|
||||
public:
|
||||
/**
|
||||
* \param frontendChannel A channel used to send responses and events to the
|
||||
* frontend.
|
||||
* \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 previouslyExportedState The exported state from a previous instance
|
||||
* of RuntimeAgentDelegate (NOT necessarily HermesRuntimeAgentDelegateNew).
|
||||
* This may be nullptr, and if not nullptr it may be of any concrete type that
|
||||
* implements RuntimeAgentDelegate::ExportedState.
|
||||
* \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. The caller
|
||||
* is responsible for keeping this object alive for the duration of the
|
||||
* \c HermesRuntimeAgentDelegateNew lifetime.
|
||||
* \param runtimeTargetDelegate The \c HermesRuntimeTargetDelegate object
|
||||
* object for the passed runtime.
|
||||
* \param runtimeExecutor A callback for scheduling work on the JS thread.
|
||||
* \c runtimeExecutor may drop scheduled work if the runtime is destroyed
|
||||
* first.
|
||||
*/
|
||||
HermesRuntimeAgentDelegateNew(
|
||||
FrontendChannel frontendChannel,
|
||||
SessionState& sessionState,
|
||||
std::unique_ptr<RuntimeAgentDelegate::ExportedState>
|
||||
previouslyExportedState,
|
||||
const ExecutionContextDescription& executionContextDescription,
|
||||
hermes::HermesRuntime& runtime,
|
||||
HermesRuntimeTargetDelegate& runtimeTargetDelegate,
|
||||
RuntimeExecutor runtimeExecutor);
|
||||
|
||||
/**
|
||||
* Handle a CDP request. The response will be sent over the provided
|
||||
* \c FrontendChannel synchronously or asynchronously.
|
||||
* \param req The parsed request.
|
||||
* \returns true if this agent has responded, or will respond asynchronously,
|
||||
* to the request (with either a success or error message). False if the
|
||||
* agent expects another agent to respond to the request instead.
|
||||
*/
|
||||
bool handleRequest(const cdp::PreparsedRequest& req) override;
|
||||
|
||||
private:
|
||||
// We use the private implementation idiom to keep HERMES_ENABLE_DEBUGGER
|
||||
// checks out of the header.
|
||||
class Impl;
|
||||
|
||||
const std::unique_ptr<Impl> impl_;
|
||||
};
|
||||
|
||||
} // namespace facebook::react::jsinspector_modern
|
||||
+26
@@ -8,6 +8,12 @@
|
||||
#include "HermesRuntimeTargetDelegate.h"
|
||||
#include "HermesRuntimeAgentDelegate.h"
|
||||
|
||||
#ifdef HERMES_ENABLE_DEBUGGER
|
||||
#include <hermes/cdp/CDPDebugAPI.h>
|
||||
|
||||
using namespace facebook::hermes::cdp;
|
||||
#endif // HERMES_ENABLE_DEBUGGER
|
||||
|
||||
#include <utility>
|
||||
|
||||
using namespace facebook::hermes;
|
||||
@@ -16,8 +22,18 @@ namespace facebook::react::jsinspector_modern {
|
||||
|
||||
class HermesRuntimeTargetDelegate::Impl : public RuntimeTargetDelegate {
|
||||
public:
|
||||
#ifdef HERMES_ENABLE_DEBUGGER
|
||||
explicit Impl(std::shared_ptr<HermesRuntime> hermesRuntime)
|
||||
: runtime_(std::move(hermesRuntime)),
|
||||
cdpDebugAPI_(CDPDebugAPI::create(*runtime_)) {}
|
||||
|
||||
CDPDebugAPI& getCDPDebugAPI() {
|
||||
return *cdpDebugAPI_;
|
||||
}
|
||||
#else
|
||||
explicit Impl(std::shared_ptr<HermesRuntime> hermesRuntime)
|
||||
: runtime_(std::move(hermesRuntime)) {}
|
||||
#endif
|
||||
|
||||
// RuntimeTargetDelegate methods
|
||||
|
||||
@@ -39,6 +55,10 @@ class HermesRuntimeTargetDelegate::Impl : public RuntimeTargetDelegate {
|
||||
|
||||
private:
|
||||
std::shared_ptr<HermesRuntime> runtime_;
|
||||
|
||||
#ifdef HERMES_ENABLE_DEBUGGER
|
||||
const std::unique_ptr<CDPDebugAPI> cdpDebugAPI_;
|
||||
#endif
|
||||
};
|
||||
|
||||
HermesRuntimeTargetDelegate::HermesRuntimeTargetDelegate(
|
||||
@@ -63,4 +83,10 @@ HermesRuntimeTargetDelegate::createAgentDelegate(
|
||||
std::move(runtimeExecutor));
|
||||
}
|
||||
|
||||
#ifdef HERMES_ENABLE_DEBUGGER
|
||||
CDPDebugAPI& HermesRuntimeTargetDelegate::getCDPDebugAPI() {
|
||||
return impl_->getCDPDebugAPI();
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace facebook::react::jsinspector_modern
|
||||
|
||||
+16
@@ -13,6 +13,10 @@
|
||||
#include <hermes/hermes.h>
|
||||
#include <jsinspector-modern/ReactCdp.h>
|
||||
|
||||
#ifdef HERMES_ENABLE_DEBUGGER
|
||||
#include <hermes/cdp/CDPDebugAPI.h>
|
||||
#endif
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace facebook::react::jsinspector_modern {
|
||||
@@ -42,8 +46,20 @@ class HermesRuntimeTargetDelegate : public RuntimeTargetDelegate {
|
||||
RuntimeExecutor runtimeExecutor) override;
|
||||
|
||||
private:
|
||||
// We use the private implementation idiom to ensure this class has the same
|
||||
// layout regardless of whether HERMES_ENABLE_DEBUGGER is defined. The net
|
||||
// effect is that callers can include HermesRuntimeTargetDelegate.h without
|
||||
// setting HERMES_ENABLE_DEBUGGER one way or the other.
|
||||
class Impl;
|
||||
|
||||
// Callers within this library may set HERMES_ENABLE_DEBUGGER to see this extra
|
||||
// API.
|
||||
#ifdef HERMES_ENABLE_DEBUGGER
|
||||
friend class HermesRuntimeAgentDelegateNew;
|
||||
|
||||
hermes::cdp::CDPDebugAPI& getCDPDebugAPI();
|
||||
#endif
|
||||
|
||||
std::unique_ptr<Impl> impl_;
|
||||
};
|
||||
|
||||
|
||||
@@ -79,6 +79,12 @@ Pod::Spec.new do |spec|
|
||||
ss.header_dir = 'hermes'
|
||||
end
|
||||
|
||||
spec.subspec 'cdp' do |ss|
|
||||
ss.source_files = ''
|
||||
ss.public_header_files = 'API/hermes/cdp/*.h'
|
||||
ss.header_dir = 'hermes/cdp'
|
||||
end
|
||||
|
||||
spec.subspec 'inspector' do |ss|
|
||||
ss.source_files = ''
|
||||
ss.public_header_files = 'API/hermes/inspector/*.h'
|
||||
|
||||
@@ -135,6 +135,9 @@ function build_apple_framework {
|
||||
mkdir -p destroot/include/hermes
|
||||
cp API/hermes/*.h destroot/include/hermes
|
||||
|
||||
mkdir -p destroot/include/hermes/cdp
|
||||
cp API/hermes/cdp/*.h destroot/include/hermes/cdp
|
||||
|
||||
mkdir -p destroot/include/hermes/inspector
|
||||
cp API/hermes/inspector/*.h destroot/include/hermes/inspector
|
||||
|
||||
@@ -162,6 +165,9 @@ function prepare_dest_root_for_ci {
|
||||
mkdir -p destroot/include/hermes
|
||||
cp API/hermes/*.h destroot/include/hermes
|
||||
|
||||
mkdir -p destroot/include/hermes/cdp
|
||||
cp API/hermes/cdp/*.h destroot/include/hermes/cdp
|
||||
|
||||
mkdir -p destroot/include/hermes/inspector
|
||||
cp API/hermes/inspector/*.h destroot/include/hermes/inspector
|
||||
|
||||
|
||||
Reference in New Issue
Block a user