Implement GlobalLexicalScopeNamesRequest

Summary:
Implement the `GlobalLexicalScopeNames` request and response:

> Returns all let, const and class variables from global scope.

The returned elements are filtered to remove internal entries that are prefixed with `?`: https://www.internalfb.com/code/fbsource/[4398b6a77500984e8536c06d58c691cd7c591477][history]/xplat/hermes/lib/IRGen/ESTreeIRGen-func.cpp?lines=49&base=da0d9de8a0d2

Changelog: [Internal]

Reviewed By: jpporto

Differential Revision: D38119568

fbshipit-source-id: 5c74dc7fa58d8dbc784bf39ac5baf85788a3df7a
This commit is contained in:
Matt Blagden 2022-07-28 10:08:56 -07:00 коммит произвёл Facebook GitHub Bot
Родитель e24ce708ab
Коммит b7164278cf
5 изменённых файлов: 165 добавлений и 2 удалений

Просмотреть файл

@ -107,6 +107,7 @@ class Connection::Impl : public inspector::InspectorObserver,
void handle(const m::runtime::EvaluateRequest &req) override;
void handle(const m::runtime::GetHeapUsageRequest &req) override;
void handle(const m::runtime::GetPropertiesRequest &req) override;
void handle(const m::runtime::GlobalLexicalScopeNamesRequest &req) override;
void handle(const m::runtime::RunIfWaitingForDebuggerRequest &req) override;
private:
@ -1451,6 +1452,45 @@ void Connection::Impl::handle(const m::runtime::GetPropertiesRequest &req) {
.thenError<std::exception>(sendErrorToClient(req.id));
}
void Connection::Impl::handle(
const m::runtime::GlobalLexicalScopeNamesRequest &req) {
auto resp = std::make_shared<m::runtime::GlobalLexicalScopeNamesResponse>();
resp->id = req.id;
inspector_
->executeIfEnabled(
"Runtime.globalLexicalScopeNames",
[req, resp](const debugger::ProgramState &state) {
if (req.executionContextId.hasValue() &&
req.executionContextId.value() != kHermesExecutionContextId) {
throw std::invalid_argument("Invalid execution context");
}
const debugger::LexicalInfo &lexicalInfo = state.getLexicalInfo(0);
debugger::ScopeDepth scopeCount = lexicalInfo.getScopesCount();
if (scopeCount == 0) {
return;
}
const debugger::ScopeDepth globalScopeIndex = scopeCount - 1;
uint32_t variableCount =
lexicalInfo.getVariablesCountInScope(globalScopeIndex);
resp->names.reserve(variableCount);
for (uint32_t i = 0; i < variableCount; i++) {
debugger::String name =
state.getVariableInfo(0, globalScopeIndex, i).name;
// The global scope has some entries prefixed with '?', which are
// not valid identifiers.
if (!name.empty() && name.front() != '?') {
resp->names.push_back(name);
}
}
})
.via(executor_.get())
.thenValue([this, resp](auto &&) { sendResponseToClient(*resp); })
.thenError<std::exception>(sendErrorToClient(req.id));
}
void Connection::Impl::handle(
const m::runtime::RunIfWaitingForDebuggerRequest &req) {
if (inspector_->isAwaitingDebuggerOnStart()) {

Просмотреть файл

@ -1,5 +1,5 @@
// Copyright (c) Meta Platforms, Inc. and affiliates. All Rights Reserved.
// @generated SignedSource<<f6f9a72f332587809b4e50ab054e0a74>>
// @generated SignedSource<<d10e11c5f88b40149af7ace19008d0fc>>
#include "MessageTypes.h"
@ -66,6 +66,8 @@ std::unique_ptr<Request> Request::fromJsonThrowOnError(const std::string &str) {
{"Runtime.evaluate", makeUnique<runtime::EvaluateRequest>},
{"Runtime.getHeapUsage", makeUnique<runtime::GetHeapUsageRequest>},
{"Runtime.getProperties", makeUnique<runtime::GetPropertiesRequest>},
{"Runtime.globalLexicalScopeNames",
makeUnique<runtime::GlobalLexicalScopeNamesRequest>},
{"Runtime.runIfWaitingForDebugger",
makeUnique<runtime::RunIfWaitingForDebuggerRequest>},
};
@ -1199,6 +1201,38 @@ void runtime::GetPropertiesRequest::accept(RequestHandler &handler) const {
handler.handle(*this);
}
runtime::GlobalLexicalScopeNamesRequest::GlobalLexicalScopeNamesRequest()
: Request("Runtime.globalLexicalScopeNames") {}
runtime::GlobalLexicalScopeNamesRequest::GlobalLexicalScopeNamesRequest(
const dynamic &obj)
: Request("Runtime.globalLexicalScopeNames") {
assign(id, obj, "id");
assign(method, obj, "method");
auto it = obj.find("params");
if (it != obj.items().end()) {
dynamic params = it->second;
assign(executionContextId, params, "executionContextId");
}
}
dynamic runtime::GlobalLexicalScopeNamesRequest::toDynamic() const {
dynamic params = dynamic::object;
put(params, "executionContextId", executionContextId);
dynamic obj = dynamic::object;
put(obj, "id", id);
put(obj, "method", method);
put(obj, "params", std::move(params));
return obj;
}
void runtime::GlobalLexicalScopeNamesRequest::accept(
RequestHandler &handler) const {
handler.handle(*this);
}
runtime::RunIfWaitingForDebuggerRequest::RunIfWaitingForDebuggerRequest()
: Request("Runtime.runIfWaitingForDebugger") {}
@ -1481,6 +1515,24 @@ dynamic runtime::GetPropertiesResponse::toDynamic() const {
return obj;
}
runtime::GlobalLexicalScopeNamesResponse::GlobalLexicalScopeNamesResponse(
const dynamic &obj) {
assign(id, obj, "id");
dynamic res = obj.at("result");
assign(names, res, "names");
}
dynamic runtime::GlobalLexicalScopeNamesResponse::toDynamic() const {
dynamic res = dynamic::object;
put(res, "names", names);
dynamic obj = dynamic::object;
put(obj, "id", id);
put(obj, "result", std::move(res));
return obj;
}
/// Notifications
debugger::BreakpointResolvedNotification::BreakpointResolvedNotification()
: Notification("Debugger.breakpointResolved") {}

Просмотреть файл

@ -1,5 +1,5 @@
// Copyright (c) Meta Platforms, Inc. and affiliates. All Rights Reserved.
// @generated SignedSource<<fcbcfeecbc72ca30c8ed005ad47839bb>>
// @generated SignedSource<<dafd583635231e17c0264beb38610499>>
#pragma once
@ -63,6 +63,8 @@ struct GetHeapUsageRequest;
struct GetHeapUsageResponse;
struct GetPropertiesRequest;
struct GetPropertiesResponse;
struct GlobalLexicalScopeNamesRequest;
struct GlobalLexicalScopeNamesResponse;
struct InternalPropertyDescriptor;
struct PropertyDescriptor;
struct RemoteObject;
@ -142,6 +144,7 @@ struct RequestHandler {
virtual void handle(const runtime::EvaluateRequest &req) = 0;
virtual void handle(const runtime::GetHeapUsageRequest &req) = 0;
virtual void handle(const runtime::GetPropertiesRequest &req) = 0;
virtual void handle(const runtime::GlobalLexicalScopeNamesRequest &req) = 0;
virtual void handle(const runtime::RunIfWaitingForDebuggerRequest &req) = 0;
};
@ -180,6 +183,7 @@ struct NoopRequestHandler : public RequestHandler {
void handle(const runtime::EvaluateRequest &req) override {}
void handle(const runtime::GetHeapUsageRequest &req) override {}
void handle(const runtime::GetPropertiesRequest &req) override {}
void handle(const runtime::GlobalLexicalScopeNamesRequest &req) override {}
void handle(const runtime::RunIfWaitingForDebuggerRequest &req) override {}
};
@ -686,6 +690,16 @@ struct runtime::GetPropertiesRequest : public Request {
folly::Optional<bool> ownProperties;
};
struct runtime::GlobalLexicalScopeNamesRequest : public Request {
GlobalLexicalScopeNamesRequest();
explicit GlobalLexicalScopeNamesRequest(const folly::dynamic &obj);
folly::dynamic toDynamic() const override;
void accept(RequestHandler &handler) const override;
folly::Optional<runtime::ExecutionContextId> executionContextId;
};
struct runtime::RunIfWaitingForDebuggerRequest : public Request {
RunIfWaitingForDebuggerRequest();
explicit RunIfWaitingForDebuggerRequest(const folly::dynamic &obj);
@ -816,6 +830,14 @@ struct runtime::GetPropertiesResponse : public Response {
folly::Optional<runtime::ExceptionDetails> exceptionDetails;
};
struct runtime::GlobalLexicalScopeNamesResponse : public Response {
GlobalLexicalScopeNamesResponse() = default;
explicit GlobalLexicalScopeNamesResponse(const folly::dynamic &obj);
folly::dynamic toDynamic() const override;
std::vector<std::string> names;
};
/// Notifications
struct debugger::BreakpointResolvedNotification : public Notification {
BreakpointResolvedNotification();

Просмотреть файл

@ -2884,6 +2884,54 @@ TEST(ConnectionTests, testBasicProfilerOperation) {
asyncRuntime.stop();
}
TEST(ConnectionTests, testGlobalLexicalScopeNames) {
TestContext context;
AsyncHermesRuntime &asyncRuntime = context.runtime();
SyncConnection &conn = context.conn();
int msgId = 1;
asyncRuntime.executeScriptAsync(R"(
let globalLet = "let";
const globalConst = "const";
var globalVar = "var";
let func1 = () => {
let local1 = 111;
func2();
}
function func2() {
let func3 = () => {
let local3 = 333;
debugger;
}
let local2 = 222;
func3();
}
func1();
)");
send<m::debugger::EnableRequest>(conn, msgId++);
expectExecutionContextCreated(conn);
expectNotification<m::debugger::ScriptParsedNotification>(conn);
expectNotification<m::debugger::PausedNotification>(conn);
m::runtime::GlobalLexicalScopeNamesRequest req;
req.id = msgId;
req.executionContextId = 1;
conn.send(req.toJson());
auto resp =
expectResponse<m::runtime::GlobalLexicalScopeNamesResponse>(conn, msgId);
EXPECT_EQ(resp.id, msgId++);
std::sort(resp.names.begin(), resp.names.end());
std::vector<std::string> expectedNames{"func1", "globalConst", "globalLet"};
EXPECT_EQ(resp.names, expectedNames);
send<m::debugger::ResumeRequest>(conn, msgId++);
expectNotification<m::debugger::ResumedNotification>(conn);
}
} // namespace chrome
} // namespace inspector
} // namespace hermes

Просмотреть файл

@ -37,3 +37,4 @@ Runtime.executionContextCreated
Runtime.getHeapUsage
Runtime.getProperties
Runtime.runIfWaitingForDebugger
Runtime.globalLexicalScopeNames