forked from facebook/react-native
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Create HermesRuntimeAgent (facebook#42747)
Summary: Changelog: [Internal] Implements a `RuntimeAgent` (D51231326) for Hermes for the modern CDP backend, based on the `CDPHandler` API that Hermes exposes currently. ## A note on `console` We unfortunately have to disable `console` interception (D51234334 / equivalently D52971652) because `CDPHandler`'s current implementation is not aligned with the Agent concept: * Agents are only created once a session has started, but the `console` interceptor needs to be injected at VM startup. * Agents should not clobber each other's shared state (nor consume excessive resources per Agent), but each `CDPHandler` would install its own independent `console` interceptor if enabled. We will enable CDP `console` support in the modern backend in future work. This will require either some additional plumbing in RN (e.g. to safely access JSI from an Agent/Target) or some additional work in Hermes. Reviewed By: huntie Differential Revision: D51234333
- Loading branch information
1 parent
78f5002
commit 8a19709
Showing
7 changed files
with
281 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
100 changes: 100 additions & 0 deletions
100
packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeAgent.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
/* | ||
* 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 "HermesRuntimeAgent.h" | ||
|
||
using namespace facebook::hermes; | ||
|
||
namespace facebook::react::jsinspector_modern { | ||
|
||
#ifdef HERMES_ENABLE_DEBUGGER | ||
|
||
namespace { | ||
|
||
/** | ||
* An implementation of the Hermes RuntimeAdapter interface (part of | ||
* Hermes's CDPHandler API) for use within a React Native RuntimeAgent. | ||
*/ | ||
class HermesRuntimeAgentAdapter : public HermesRuntimeAdapter { | ||
public: | ||
HermesRuntimeAgentAdapter( | ||
std::shared_ptr<hermes::HermesRuntime> runtime, | ||
RuntimeExecutor runtimeExecutor) | ||
: runtime_(runtime), runtimeExecutor_(runtimeExecutor) {} | ||
|
||
HermesRuntime& getRuntime() override { | ||
return *runtime_; | ||
} | ||
|
||
void tickleJs() override { | ||
runtimeExecutor_([](jsi::Runtime& runtime) { | ||
jsi::Function func = | ||
runtime.global().getPropertyAsFunction(runtime, "__tickleJs"); | ||
func.call(runtime); | ||
}); | ||
} | ||
|
||
private: | ||
std::shared_ptr<hermes::HermesRuntime> runtime_; | ||
RuntimeExecutor runtimeExecutor_; | ||
}; | ||
|
||
} // namespace | ||
|
||
HermesRuntimeAgent::HermesRuntimeAgent( | ||
FrontendChannel frontendChannel, | ||
SessionState& sessionState, | ||
std::shared_ptr<hermes::HermesRuntime> runtime, | ||
RuntimeExecutor runtimeExecutor) | ||
: hermes_(HermesCDPHandler::create( | ||
std::make_unique<HermesRuntimeAgentAdapter>(runtime, runtimeExecutor), | ||
/* waitForDebugger */ false, | ||
/* enableConsoleAPICapturing */ false, | ||
/* state */ nullptr, | ||
{.isRuntimeDomainEnabled = sessionState.isRuntimeDomainEnabled})) { | ||
hermes_->registerCallbacks( | ||
/* msgCallback */ | ||
[frontendChannel = | ||
std::move(frontendChannel)](const std::string& messageFromHermes) { | ||
frontendChannel(messageFromHermes); | ||
; | ||
}, | ||
/* onUnregister */ | ||
[]() {}); | ||
} | ||
|
||
bool HermesRuntimeAgent::handleRequest(const cdp::PreparsedRequest& req) { | ||
// 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 CDPHandler. | ||
hermes_->handle(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; | ||
} | ||
|
||
#else // !HERMES_ENABLE_DEBUGGER | ||
|
||
HermesRuntimeAgent::HermesRuntimeAgent( | ||
FrontendChannel frontendChannel, | ||
SessionState& sessionState, | ||
std::shared_ptr<hermes::HermesRuntime> runtime, | ||
RuntimeExecutor runtimeExecutor) | ||
: FallbackRuntimeAgent( | ||
std::move(frontendChannel), | ||
sessionState, | ||
runtime->description()) {} | ||
|
||
#endif // HERMES_ENABLE_DEBUGGER | ||
|
||
} // namespace facebook::react::jsinspector_modern |
77 changes: 77 additions & 0 deletions
77
packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeAgent.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
/* | ||
* 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> | ||
|
||
// If HERMES_ENABLE_DEBUGGER isn't defined, we can't access any Hermes | ||
// CDPHandler headers or types. | ||
|
||
#ifdef HERMES_ENABLE_DEBUGGER | ||
#include <hermes/inspector/RuntimeAdapter.h> | ||
#include <hermes/inspector/chrome/CDPHandler.h> | ||
#else // HERMES_ENABLE_DEBUGGER | ||
#include <jsinspector-modern/FallbackRuntimeAgent.h> | ||
#endif // HERMES_ENABLE_DEBUGGER | ||
|
||
#include <hermes/API/hermes/hermes.h> | ||
#include <jsinspector-modern/ReactCdp.h> | ||
|
||
namespace facebook::react::jsinspector_modern { | ||
|
||
#ifdef HERMES_ENABLE_DEBUGGER | ||
using HermesCDPHandler = hermes::inspector_modern::chrome::CDPHandler; | ||
using HermesRuntimeAdapter = hermes::inspector_modern::RuntimeAdapter; | ||
#endif // HERMES_ENABLE_DEBUGGER | ||
|
||
/** | ||
* A RuntimeAgent that handles requests from the Chrome DevTools Protocol for | ||
* an instance of Hermes. | ||
*/ | ||
class HermesRuntimeAgent : | ||
#ifdef HERMES_ENABLE_DEBUGGER | ||
public RuntimeAgent | ||
#else // HERMES_ENABLE_DEBUGGER | ||
public FallbackRuntimeAgent | ||
#endif // HERMES_ENABLE_DEBUGGER | ||
{ | ||
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 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 | ||
* first. | ||
*/ | ||
HermesRuntimeAgent( | ||
FrontendChannel frontendChannel, | ||
SessionState& sessionState, | ||
std::shared_ptr<hermes::HermesRuntime> runtime, | ||
RuntimeExecutor runtimeExecutor); | ||
|
||
#ifdef HERMES_ENABLE_DEBUGGER | ||
/** | ||
* 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: | ||
std::shared_ptr<HermesCDPHandler> hermes_; | ||
#endif | ||
}; | ||
|
||
} // namespace facebook::react::jsinspector_modern |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters