Skip to content

Commit 2b4390e

Browse files
mattbfbfacebook-github-bot
authored andcommitted
Implement Runtime.compileScript
Summary: Implement Runtime.compileScript, which is a dev tools request to compile a given script, optionally persisting the compiled result. There are 3 main cases: - Unsuccessful compilation, populates the exception details output. (We could retrieve the line and column number from the exception message, but it felt a bit too hacky.) - Successful unpersisted output, returns an empty result, indicating success - Successful persisted output, returns a result with a unique scriptID that identifies the prepared script. The script IDs end with an index that can be used to infer the location in the vector storing persisted scripts. Changelog: [Internal] Reviewed By: jpporto Differential Revision: D38761119 fbshipit-source-id: 504faad0149d1637682fa11d285f71736c3133e5
1 parent a45eeea commit 2b4390e

File tree

4 files changed

+124
-2
lines changed

4 files changed

+124
-2
lines changed

ReactCommon/hermes/inspector/chrome/Connection.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ namespace m = ::facebook::hermes::inspector::chrome::message;
4040
static const char *const kVirtualBreakpointPrefix = "virtualbreakpoint-";
4141
static const char *const kBeforeScriptWithSourceMapExecution =
4242
"beforeScriptWithSourceMapExecution";
43+
static const char *const kUserEnteredScriptPrefix = "userScript";
4344

4445
/*
4546
* Connection::Impl
@@ -104,6 +105,7 @@ class Connection::Impl : public inspector::InspectorObserver,
104105
void handle(const m::profiler::StartRequest &req) override;
105106
void handle(const m::profiler::StopRequest &req) override;
106107
void handle(const m::runtime::CallFunctionOnRequest &req) override;
108+
void handle(const m::runtime::CompileScriptRequest &req) override;
107109
void handle(const m::runtime::EvaluateRequest &req) override;
108110
void handle(const m::runtime::GetHeapUsageRequest &req) override;
109111
void handle(const m::runtime::GetPropertiesRequest &req) override;
@@ -160,6 +162,10 @@ class Connection::Impl : public inspector::InspectorObserver,
160162
std::mutex parsedScriptsMutex_;
161163
std::vector<std::string> parsedScripts_;
162164

165+
// preparedScripts_ stores user-entered scripts that have been prepared for
166+
// execution, and may be invoked by a later command.
167+
std::vector<std::shared_ptr<const jsi::PreparedJavaScript>> preparedScripts_;
168+
163169
// Some events are represented as a mode in Hermes but a breakpoint in CDP,
164170
// e.g. "beforeScriptExecution" and "beforeScriptWithSourceMapExecution".
165171
// Keep track of these separately. The caller should lock the
@@ -1092,6 +1098,42 @@ void Connection::Impl::handle(const m::runtime::CallFunctionOnRequest &req) {
10921098
.thenError<std::exception>(sendErrorToClient(req.id));
10931099
}
10941100

1101+
void Connection::Impl::handle(const m::runtime::CompileScriptRequest &req) {
1102+
auto resp = std::make_shared<m::runtime::CompileScriptResponse>();
1103+
resp->id = req.id;
1104+
1105+
inspector_
1106+
->executeIfEnabled(
1107+
"Runtime.compileScriptRequest",
1108+
[this, req, resp](const debugger::ProgramState &state) {
1109+
if (req.executionContextId.hasValue() &&
1110+
req.executionContextId.value() != kHermesExecutionContextId) {
1111+
throw std::invalid_argument("Invalid execution context");
1112+
}
1113+
1114+
auto source = std::make_shared<jsi::StringBuffer>(req.expression);
1115+
std::shared_ptr<const jsi::PreparedJavaScript> preparedScript;
1116+
try {
1117+
preparedScript =
1118+
getRuntime().prepareJavaScript(source, req.sourceURL);
1119+
} catch (const facebook::jsi::JSIException &err) {
1120+
resp->exceptionDetails = m::runtime::ExceptionDetails();
1121+
resp->exceptionDetails->text = err.what();
1122+
return;
1123+
}
1124+
1125+
if (req.persistScript) {
1126+
auto scriptId = folly::to<std::string>(
1127+
kUserEnteredScriptPrefix, preparedScripts_.size());
1128+
preparedScripts_.push_back(std::move(preparedScript));
1129+
resp->scriptId = scriptId;
1130+
}
1131+
})
1132+
.via(executor_.get())
1133+
.thenValue([this, resp](auto &&) { sendResponseToClient(*resp); })
1134+
.thenError<std::exception>(sendErrorToClient(req.id));
1135+
}
1136+
10951137
void Connection::Impl::handle(const m::runtime::EvaluateRequest &req) {
10961138
auto remoteObjPtr = std::make_shared<m::runtime::RemoteObject>();
10971139

ReactCommon/hermes/inspector/chrome/MessageTypes.cpp

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// Copyright (c) Meta Platforms, Inc. and affiliates. All Rights Reserved.
2-
// @generated SignedSource<<d10e11c5f88b40149af7ace19008d0fc>>
2+
// @generated SignedSource<<8397f2428e68a26e014f91fdb77c1eb3>>
33

44
#include "MessageTypes.h"
55

@@ -63,6 +63,7 @@ std::unique_ptr<Request> Request::fromJsonThrowOnError(const std::string &str) {
6363
{"Profiler.start", makeUnique<profiler::StartRequest>},
6464
{"Profiler.stop", makeUnique<profiler::StopRequest>},
6565
{"Runtime.callFunctionOn", makeUnique<runtime::CallFunctionOnRequest>},
66+
{"Runtime.compileScript", makeUnique<runtime::CompileScriptRequest>},
6667
{"Runtime.evaluate", makeUnique<runtime::EvaluateRequest>},
6768
{"Runtime.getHeapUsage", makeUnique<runtime::GetHeapUsageRequest>},
6869
{"Runtime.getProperties", makeUnique<runtime::GetPropertiesRequest>},
@@ -1112,6 +1113,39 @@ void runtime::CallFunctionOnRequest::accept(RequestHandler &handler) const {
11121113
handler.handle(*this);
11131114
}
11141115

1116+
runtime::CompileScriptRequest::CompileScriptRequest()
1117+
: Request("Runtime.compileScript") {}
1118+
1119+
runtime::CompileScriptRequest::CompileScriptRequest(const dynamic &obj)
1120+
: Request("Runtime.compileScript") {
1121+
assign(id, obj, "id");
1122+
assign(method, obj, "method");
1123+
1124+
dynamic params = obj.at("params");
1125+
assign(expression, params, "expression");
1126+
assign(sourceURL, params, "sourceURL");
1127+
assign(persistScript, params, "persistScript");
1128+
assign(executionContextId, params, "executionContextId");
1129+
}
1130+
1131+
dynamic runtime::CompileScriptRequest::toDynamic() const {
1132+
dynamic params = dynamic::object;
1133+
put(params, "expression", expression);
1134+
put(params, "sourceURL", sourceURL);
1135+
put(params, "persistScript", persistScript);
1136+
put(params, "executionContextId", executionContextId);
1137+
1138+
dynamic obj = dynamic::object;
1139+
put(obj, "id", id);
1140+
put(obj, "method", method);
1141+
put(obj, "params", std::move(params));
1142+
return obj;
1143+
}
1144+
1145+
void runtime::CompileScriptRequest::accept(RequestHandler &handler) const {
1146+
handler.handle(*this);
1147+
}
1148+
11151149
runtime::EvaluateRequest::EvaluateRequest() : Request("Runtime.evaluate") {}
11161150

11171151
runtime::EvaluateRequest::EvaluateRequest(const dynamic &obj)
@@ -1456,6 +1490,25 @@ dynamic runtime::CallFunctionOnResponse::toDynamic() const {
14561490
return obj;
14571491
}
14581492

1493+
runtime::CompileScriptResponse::CompileScriptResponse(const dynamic &obj) {
1494+
assign(id, obj, "id");
1495+
1496+
dynamic res = obj.at("result");
1497+
assign(scriptId, res, "scriptId");
1498+
assign(exceptionDetails, res, "exceptionDetails");
1499+
}
1500+
1501+
dynamic runtime::CompileScriptResponse::toDynamic() const {
1502+
dynamic res = dynamic::object;
1503+
put(res, "scriptId", scriptId);
1504+
put(res, "exceptionDetails", exceptionDetails);
1505+
1506+
dynamic obj = dynamic::object;
1507+
put(obj, "id", id);
1508+
put(obj, "result", std::move(res));
1509+
return obj;
1510+
}
1511+
14591512
runtime::EvaluateResponse::EvaluateResponse(const dynamic &obj) {
14601513
assign(id, obj, "id");
14611514

ReactCommon/hermes/inspector/chrome/MessageTypes.h

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// Copyright (c) Meta Platforms, Inc. and affiliates. All Rights Reserved.
2-
// @generated SignedSource<<dafd583635231e17c0264beb38610499>>
2+
// @generated SignedSource<<2bada3d9c303c840ddcc292c7ba52604>>
33

44
#pragma once
55

@@ -52,6 +52,8 @@ struct CallArgument;
5252
struct CallFrame;
5353
struct CallFunctionOnRequest;
5454
struct CallFunctionOnResponse;
55+
struct CompileScriptRequest;
56+
struct CompileScriptResponse;
5557
struct ConsoleAPICalledNotification;
5658
struct EvaluateRequest;
5759
struct EvaluateResponse;
@@ -141,6 +143,7 @@ struct RequestHandler {
141143
virtual void handle(const profiler::StartRequest &req) = 0;
142144
virtual void handle(const profiler::StopRequest &req) = 0;
143145
virtual void handle(const runtime::CallFunctionOnRequest &req) = 0;
146+
virtual void handle(const runtime::CompileScriptRequest &req) = 0;
144147
virtual void handle(const runtime::EvaluateRequest &req) = 0;
145148
virtual void handle(const runtime::GetHeapUsageRequest &req) = 0;
146149
virtual void handle(const runtime::GetPropertiesRequest &req) = 0;
@@ -180,6 +183,7 @@ struct NoopRequestHandler : public RequestHandler {
180183
void handle(const profiler::StartRequest &req) override {}
181184
void handle(const profiler::StopRequest &req) override {}
182185
void handle(const runtime::CallFunctionOnRequest &req) override {}
186+
void handle(const runtime::CompileScriptRequest &req) override {}
183187
void handle(const runtime::EvaluateRequest &req) override {}
184188
void handle(const runtime::GetHeapUsageRequest &req) override {}
185189
void handle(const runtime::GetPropertiesRequest &req) override {}
@@ -654,6 +658,19 @@ struct runtime::CallFunctionOnRequest : public Request {
654658
folly::Optional<std::string> objectGroup;
655659
};
656660

661+
struct runtime::CompileScriptRequest : public Request {
662+
CompileScriptRequest();
663+
explicit CompileScriptRequest(const folly::dynamic &obj);
664+
665+
folly::dynamic toDynamic() const override;
666+
void accept(RequestHandler &handler) const override;
667+
668+
std::string expression;
669+
std::string sourceURL;
670+
bool persistScript{};
671+
folly::Optional<runtime::ExecutionContextId> executionContextId;
672+
};
673+
657674
struct runtime::EvaluateRequest : public Request {
658675
EvaluateRequest();
659676
explicit EvaluateRequest(const folly::dynamic &obj);
@@ -801,6 +818,15 @@ struct runtime::CallFunctionOnResponse : public Response {
801818
folly::Optional<runtime::ExceptionDetails> exceptionDetails;
802819
};
803820

821+
struct runtime::CompileScriptResponse : public Response {
822+
CompileScriptResponse() = default;
823+
explicit CompileScriptResponse(const folly::dynamic &obj);
824+
folly::dynamic toDynamic() const override;
825+
826+
folly::Optional<runtime::ScriptId> scriptId;
827+
folly::Optional<runtime::ExceptionDetails> exceptionDetails;
828+
};
829+
804830
struct runtime::EvaluateResponse : public Response {
805831
EvaluateResponse() = default;
806832
explicit EvaluateResponse(const folly::dynamic &obj);

ReactCommon/hermes/inspector/tools/message_types.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,4 @@ Runtime.getHeapUsage
3838
Runtime.getProperties
3939
Runtime.runIfWaitingForDebugger
4040
Runtime.globalLexicalScopeNames
41+
Runtime.compileScript

0 commit comments

Comments
 (0)