Skip to content

Commit

Permalink
Implement GlobalLexicalScopeNamesRequest
Browse files Browse the repository at this point in the history
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
  • Loading branch information
mattbfb authored and facebook-github-bot committed Jul 28, 2022
1 parent e24ce70 commit b716427
Show file tree
Hide file tree
Showing 5 changed files with 165 additions and 2 deletions.
40 changes: 40 additions & 0 deletions ReactCommon/hermes/inspector/chrome/Connection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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()) {
Expand Down
54 changes: 53 additions & 1 deletion ReactCommon/hermes/inspector/chrome/MessageTypes.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Copyright (c) Meta Platforms, Inc. and affiliates. All Rights Reserved.
// @generated SignedSource<<f6f9a72f332587809b4e50ab054e0a74>>
// @generated SignedSource<<d10e11c5f88b40149af7ace19008d0fc>>

#include "MessageTypes.h"

Expand Down Expand Up @@ -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>},
};
Expand Down Expand Up @@ -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") {}

Expand Down Expand Up @@ -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") {}
Expand Down
24 changes: 23 additions & 1 deletion ReactCommon/hermes/inspector/chrome/MessageTypes.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Copyright (c) Meta Platforms, Inc. and affiliates. All Rights Reserved.
// @generated SignedSource<<fcbcfeecbc72ca30c8ed005ad47839bb>>
// @generated SignedSource<<dafd583635231e17c0264beb38610499>>

#pragma once

Expand Down Expand Up @@ -63,6 +63,8 @@ struct GetHeapUsageRequest;
struct GetHeapUsageResponse;
struct GetPropertiesRequest;
struct GetPropertiesResponse;
struct GlobalLexicalScopeNamesRequest;
struct GlobalLexicalScopeNamesResponse;
struct InternalPropertyDescriptor;
struct PropertyDescriptor;
struct RemoteObject;
Expand Down Expand Up @@ -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;
};

Expand Down Expand Up @@ -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 {}
};

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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();
Expand Down
48 changes: 48 additions & 0 deletions ReactCommon/hermes/inspector/chrome/tests/ConnectionTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions ReactCommon/hermes/inspector/tools/message_types.txt
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,4 @@ Runtime.executionContextCreated
Runtime.getHeapUsage
Runtime.getProperties
Runtime.runIfWaitingForDebugger
Runtime.globalLexicalScopeNames

0 comments on commit b716427

Please sign in to comment.