Skip to content

Commit 16f7f52

Browse files
eugeneotargos
authored andcommitted
inspector: workers debugging
Introduce a NodeTarget inspector domain modelled after ChromeDevTools Target domain. It notifies inspector frontend attached to a main V8 isolate when workers are starting and allows passing messages to inspectors on their isolates. All inspector functionality is enabled on worker isolates. Backport-PR-URL: #22954 PR-URL: #21364 Reviewed-By: Aleksei Koziatinskii <[email protected]> Reviewed-By: Jan Krems <[email protected]> Reviewed-By: Anna Henningsen <[email protected]>
1 parent c29e5ac commit 16f7f52

11 files changed

+775
-10
lines changed

node.gyp

+6
Original file line numberDiff line numberDiff line change
@@ -510,14 +510,18 @@
510510
'src/inspector_socket.cc',
511511
'src/inspector_socket_server.cc',
512512
'src/inspector/main_thread_interface.cc',
513+
'src/inspector/worker_inspector.cc',
513514
'src/inspector/node_string.cc',
515+
'src/inspector/worker_agent.cc',
514516
'src/inspector/tracing_agent.cc',
515517
'src/inspector_agent.h',
516518
'src/inspector_io.h',
517519
'src/inspector_socket.h',
518520
'src/inspector_socket_server.h',
519521
'src/inspector/main_thread_interface.h',
522+
'src/inspector/worker_inspector.h',
520523
'src/inspector/node_string.h',
524+
'src/inspector/worker_agent.h',
521525
'src/inspector/tracing_agent.h',
522526
'<@(node_inspector_generated_sources)'
523527
],
@@ -1067,6 +1071,8 @@
10671071
'<(SHARED_INTERMEDIATE_DIR)/src/node/inspector/protocol/Forward.h',
10681072
'<(SHARED_INTERMEDIATE_DIR)/src/node/inspector/protocol/Protocol.cpp',
10691073
'<(SHARED_INTERMEDIATE_DIR)/src/node/inspector/protocol/Protocol.h',
1074+
'<(SHARED_INTERMEDIATE_DIR)/src/node/inspector/protocol/NodeWorker.cpp',
1075+
'<(SHARED_INTERMEDIATE_DIR)/src/node/inspector/protocol/NodeWorker.h',
10701076
'<(SHARED_INTERMEDIATE_DIR)/src/node/inspector/protocol/NodeTracing.cpp',
10711077
'<(SHARED_INTERMEDIATE_DIR)/src/node/inspector/protocol/NodeTracing.h',
10721078
],

src/inspector/node_protocol.pdl

+55
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,58 @@ experimental domain NodeTracing
3737
# Signals that tracing is stopped and there is no trace buffers pending flush, all data were
3838
# delivered via dataCollected events.
3939
event tracingComplete
40+
41+
# Support for sending messages to Node worker Inspector instances.
42+
experimental domain NodeWorker
43+
44+
type WorkerID extends string
45+
46+
# Unique identifier of attached debugging session.
47+
type SessionID extends string
48+
49+
type WorkerInfo extends object
50+
properties
51+
WorkerID workerId
52+
string type
53+
string title
54+
string url
55+
56+
# Sends protocol message over session with given id.
57+
command sendMessageToWorker
58+
parameters
59+
string message
60+
# Identifier of the session.
61+
SessionID sessionId
62+
63+
# Instructs the inspector to attach to running workers. Will also attach to new workers
64+
# as they start
65+
command enable
66+
parameters
67+
# Whether to new workers should be paused until the frontend sends `Runtime.runIfWaitingForDebugger`
68+
# message to run them.
69+
boolean waitForDebuggerOnStart
70+
71+
# Detaches from all running workers and disables attaching to new workers as they are started.
72+
command disable
73+
74+
# Issued when attached to a worker.
75+
event attachedToWorker
76+
parameters
77+
# Identifier assigned to the session used to send/receive messages.
78+
SessionID sessionId
79+
WorkerInfo workerInfo
80+
boolean waitingForDebugger
81+
82+
# Issued when detached from the worker.
83+
event detachedFromWorker
84+
parameters
85+
# Detached session identifier.
86+
SessionID sessionId
87+
88+
# Notifies about a new protocol message received from the session
89+
# (session ID is provided in attachedToWorker notification).
90+
event receivedMessageFromWorker
91+
parameters
92+
# Identifier of a session which sends a message.
93+
SessionID sessionId
94+
string message

src/inspector/node_protocol_config.json

+1-6
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,7 @@
33
"path": "node_protocol.json",
44
"package": "src/node/inspector/protocol",
55
"output": "node/inspector/protocol",
6-
"namespace": ["node", "inspector", "protocol"],
7-
"options": [
8-
{
9-
"domain": "NodeTracing"
10-
}
11-
]
6+
"namespace": ["node", "inspector", "protocol"]
127
},
138
"exported": {
149
"package": "include/inspector",

src/inspector/worker_agent.cc

+154
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
#include "worker_agent.h"
2+
3+
#include "main_thread_interface.h"
4+
#include "worker_inspector.h"
5+
6+
namespace node {
7+
namespace inspector {
8+
namespace protocol {
9+
10+
class NodeWorkers
11+
: public std::enable_shared_from_this<NodeWorkers> {
12+
public:
13+
explicit NodeWorkers(std::weak_ptr<NodeWorker::Frontend> frontend,
14+
std::shared_ptr<MainThreadHandle> thread)
15+
: frontend_(frontend), thread_(thread) {}
16+
void WorkerCreated(const std::string& title,
17+
const std::string& url,
18+
bool waiting,
19+
std::shared_ptr<MainThreadHandle> target);
20+
void Receive(const std::string& id, const std::string& message);
21+
void Send(const std::string& id, const std::string& message);
22+
void Detached(const std::string& id);
23+
24+
private:
25+
std::weak_ptr<NodeWorker::Frontend> frontend_;
26+
std::shared_ptr<MainThreadHandle> thread_;
27+
std::unordered_map<std::string, std::unique_ptr<InspectorSession>> sessions_;
28+
int next_target_id_ = 0;
29+
};
30+
31+
namespace {
32+
class AgentWorkerInspectorDelegate : public WorkerDelegate {
33+
public:
34+
explicit AgentWorkerInspectorDelegate(std::shared_ptr<NodeWorkers> workers)
35+
: workers_(workers) {}
36+
37+
void WorkerCreated(const std::string& title,
38+
const std::string& url,
39+
bool waiting,
40+
std::shared_ptr<MainThreadHandle> target) override {
41+
workers_->WorkerCreated(title, url, waiting, target);
42+
}
43+
44+
private:
45+
std::shared_ptr<NodeWorkers> workers_;
46+
};
47+
48+
class ParentInspectorSessionDelegate : public InspectorSessionDelegate {
49+
public:
50+
ParentInspectorSessionDelegate(const std::string& id,
51+
std::shared_ptr<NodeWorkers> workers)
52+
: id_(id), workers_(workers) {}
53+
54+
~ParentInspectorSessionDelegate() override {
55+
workers_->Detached(id_);
56+
}
57+
58+
void SendMessageToFrontend(const v8_inspector::StringView& msg) override {
59+
std::string message = protocol::StringUtil::StringViewToUtf8(msg);
60+
workers_->Send(id_, message);
61+
}
62+
63+
private:
64+
std::string id_;
65+
std::shared_ptr<NodeWorkers> workers_;
66+
};
67+
68+
std::unique_ptr<NodeWorker::WorkerInfo> WorkerInfo(const std::string& id,
69+
const std::string& title,
70+
const std::string& url) {
71+
return NodeWorker::WorkerInfo::create()
72+
.setWorkerId(id)
73+
.setTitle(title)
74+
.setUrl(url)
75+
.setType("worker").build();
76+
}
77+
} // namespace
78+
79+
WorkerAgent::WorkerAgent(std::weak_ptr<WorkerManager> manager)
80+
: manager_(manager) {}
81+
82+
83+
void WorkerAgent::Wire(UberDispatcher* dispatcher) {
84+
frontend_.reset(new NodeWorker::Frontend(dispatcher->channel()));
85+
NodeWorker::Dispatcher::wire(dispatcher, this);
86+
auto manager = manager_.lock();
87+
CHECK_NOT_NULL(manager);
88+
workers_ =
89+
std::make_shared<NodeWorkers>(frontend_, manager->MainThread());
90+
}
91+
92+
DispatchResponse WorkerAgent::sendMessageToWorker(const String& message,
93+
const String& sessionId) {
94+
workers_->Receive(sessionId, message);
95+
return DispatchResponse::OK();
96+
}
97+
98+
DispatchResponse WorkerAgent::enable(bool waitForDebuggerOnStart) {
99+
auto manager = manager_.lock();
100+
if (!manager) {
101+
return DispatchResponse::OK();
102+
}
103+
if (!event_handle_) {
104+
std::unique_ptr<AgentWorkerInspectorDelegate> delegate(
105+
new AgentWorkerInspectorDelegate(workers_));
106+
event_handle_ = manager->SetAutoAttach(std::move(delegate));
107+
}
108+
event_handle_->SetWaitOnStart(waitForDebuggerOnStart);
109+
return DispatchResponse::OK();
110+
}
111+
112+
DispatchResponse WorkerAgent::disable() {
113+
event_handle_.reset();
114+
return DispatchResponse::OK();
115+
}
116+
117+
void NodeWorkers::WorkerCreated(const std::string& title,
118+
const std::string& url,
119+
bool waiting,
120+
std::shared_ptr<MainThreadHandle> target) {
121+
auto frontend = frontend_.lock();
122+
if (!frontend)
123+
return;
124+
std::string id = std::to_string(++next_target_id_);
125+
auto delegate = thread_->MakeDelegateThreadSafe(
126+
std::unique_ptr<InspectorSessionDelegate>(
127+
new ParentInspectorSessionDelegate(id, shared_from_this())));
128+
sessions_[id] = target->Connect(std::move(delegate), true);
129+
frontend->attachedToWorker(id, WorkerInfo(id, title, url), waiting);
130+
}
131+
132+
void NodeWorkers::Send(const std::string& id, const std::string& message) {
133+
auto frontend = frontend_.lock();
134+
if (frontend)
135+
frontend->receivedMessageFromWorker(id, message);
136+
}
137+
138+
void NodeWorkers::Receive(const std::string& id, const std::string& message) {
139+
auto it = sessions_.find(id);
140+
if (it != sessions_.end())
141+
it->second->Dispatch(Utf8ToStringView(message)->string());
142+
}
143+
144+
void NodeWorkers::Detached(const std::string& id) {
145+
if (sessions_.erase(id) == 0)
146+
return;
147+
auto frontend = frontend_.lock();
148+
if (frontend) {
149+
frontend->detachedFromWorker(id);
150+
}
151+
}
152+
} // namespace protocol
153+
} // namespace inspector
154+
} // namespace node

src/inspector/worker_agent.h

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#ifndef SRC_INSPECTOR_WORKER_AGENT_H_
2+
#define SRC_INSPECTOR_WORKER_AGENT_H_
3+
4+
#include "node/inspector/protocol/NodeWorker.h"
5+
#include "v8.h"
6+
7+
8+
namespace node {
9+
namespace inspector {
10+
class WorkerManagerEventHandle;
11+
class WorkerManager;
12+
13+
namespace protocol {
14+
class NodeWorkers;
15+
16+
class WorkerAgent : public NodeWorker::Backend {
17+
public:
18+
explicit WorkerAgent(std::weak_ptr<WorkerManager> manager);
19+
~WorkerAgent() override = default;
20+
21+
void Wire(UberDispatcher* dispatcher);
22+
23+
DispatchResponse sendMessageToWorker(const String& message,
24+
const String& sessionId) override;
25+
26+
DispatchResponse enable(bool waitForDebuggerOnStart) override;
27+
DispatchResponse disable() override;
28+
29+
private:
30+
std::shared_ptr<NodeWorker::Frontend> frontend_;
31+
std::weak_ptr<WorkerManager> manager_;
32+
std::unique_ptr<WorkerManagerEventHandle> event_handle_;
33+
std::shared_ptr<NodeWorkers> workers_;
34+
};
35+
} // namespace protocol
36+
} // namespace inspector
37+
} // namespace node
38+
39+
#endif // SRC_INSPECTOR_WORKER_AGENT_H_

0 commit comments

Comments
 (0)