Skip to content

Commit e62f2ec

Browse files
committed
inspector: support for worker inspection in chrome devtools
Fixes: #56343
1 parent bade7a1 commit e62f2ec

File tree

11 files changed

+307
-10
lines changed

11 files changed

+307
-10
lines changed

doc/api/cli.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1136,6 +1136,18 @@ added: v22.4.0
11361136

11371137
Enable experimental [`Web Storage`][] support.
11381138

1139+
### `--experimental-worker-inspection`
1140+
1141+
<!-- YAML
1142+
added:
1143+
- v22.14.0
1144+
- v20.19.0
1145+
-->
1146+
1147+
> Stability: 1 - Experimental
1148+
1149+
Enable experimental support for the worker inspection with Chrome DevTools.
1150+
11391151
### `--expose-gc`
11401152

11411153
<!-- YAML

src/inspector/main_thread_interface.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,13 @@ class MainThreadHandle : public std::enable_shared_from_this<MainThreadHandle> {
5757
std::unique_ptr<InspectorSessionDelegate> MakeDelegateThreadSafe(
5858
std::unique_ptr<InspectorSessionDelegate> delegate);
5959
bool Expired();
60+
void SetTargetSessionId(int target_session_id) {
61+
target_session_id_ = target_session_id;
62+
}
63+
std::optional<int> GetTargetSessionId() {
64+
return target_session_id_;
65+
}
66+
6067

6168
private:
6269
void Reset();
@@ -65,6 +72,7 @@ class MainThreadHandle : public std::enable_shared_from_this<MainThreadHandle> {
6572
Mutex block_lock_;
6673
int next_session_id_ = 0;
6774
std::atomic_int next_object_id_ = {1};
75+
std::optional<int> target_session_id_ = std::nullopt;
6876

6977
friend class MainThreadInterface;
7078
};

src/inspector/node_inspector.gypi

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@
2727
'src/inspector/network_inspector.h',
2828
'src/inspector/network_agent.cc',
2929
'src/inspector/network_agent.h',
30+
'src/inspector/network_agent.h',
31+
'src/inspector/target_agent.cc',
32+
'src/inspector/target_agent.h',
3033
'src/inspector/worker_inspector.cc',
3134
'src/inspector/worker_inspector.h',
3235
],
@@ -42,6 +45,8 @@
4245
'<(SHARED_INTERMEDIATE_DIR)/src/node/inspector/protocol/NodeRuntime.h',
4346
'<(SHARED_INTERMEDIATE_DIR)/src/node/inspector/protocol/Network.cpp',
4447
'<(SHARED_INTERMEDIATE_DIR)/src/node/inspector/protocol/Network.h',
48+
'<(SHARED_INTERMEDIATE_DIR)/src/node/inspector/protocol/Target.cpp',
49+
'<(SHARED_INTERMEDIATE_DIR)/src/node/inspector/protocol/Target.h',
4550
],
4651
'node_protocol_files': [
4752
'<(protocol_tool_path)/lib/Allocator_h.template',

src/inspector/node_protocol.pdl

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,3 +220,25 @@ experimental domain NodeRuntime
220220
# This event is fired when the runtime is waiting for the debugger. For
221221
# example, when inspector.waitingForDebugger is called
222222
event waitingForDebugger
223+
224+
# https://chromedevtools.github.io/devtools-protocol/1-3/Target/
225+
experimental domain Target
226+
type SessionID extends string
227+
type TargetID extends string
228+
type TargetInfo extends object
229+
properties
230+
TargetID targetId
231+
string type
232+
string title
233+
string url
234+
boolean attached
235+
boolean canAccessOpener
236+
event targetCreated
237+
parameters
238+
TargetInfo targetInfo
239+
event attachedToTarget
240+
parameters
241+
SessionID sessionId
242+
TargetInfo targetInfo
243+
boolean waitingForDebugger
244+

src/inspector/target_agent.cc

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
#include "target_agent.h"
2+
#include <iostream>
3+
#include <memory>
4+
#include <set>
5+
#include <string>
6+
#include <tuple>
7+
#include <utility>
8+
#include "inspector/node_string.h"
9+
#include "inspector/worker_inspector.h"
10+
#include "main_thread_interface.h"
11+
12+
namespace node {
13+
namespace inspector {
14+
namespace protocol {
15+
16+
std::unordered_map<int,std::shared_ptr<MainThreadHandle>> TargetAgent::target_session_id_worker_map_ = std::unordered_map<int, std::shared_ptr<MainThreadHandle>>();
17+
18+
19+
class WorkerTargetDelegate : public WorkerDelegate {
20+
public:
21+
explicit WorkerTargetDelegate(std::shared_ptr<TargetAgent> target_agent)
22+
: target_agent_(target_agent) {}
23+
24+
25+
void WorkerCreated(const std::string& title,
26+
const std::string& url,
27+
bool waiting,
28+
std::shared_ptr<MainThreadHandle> worker) override {
29+
std::string target_id = std::to_string(target_agent_->getNextTargetId());
30+
std::string type = "worker";
31+
32+
target_agent_->targetCreated(target_id, type, title, url);
33+
target_agent_->attachedToTarget(worker,target_id, type, title, url);
34+
}
35+
36+
private:
37+
const std::shared_ptr<TargetAgent> target_agent_;
38+
};
39+
40+
std::unique_ptr<Target::TargetInfo> createTargetInfo(
41+
const String& target_id,
42+
const String& type,
43+
const String& title,
44+
const String& url) {
45+
return Target::TargetInfo::create()
46+
.setTargetId(target_id)
47+
.setType(type)
48+
.setTitle(title)
49+
.setUrl(url)
50+
.setAttached(false)
51+
.setCanAccessOpener(true)
52+
.build();
53+
}
54+
55+
void TargetAgent::Wire(UberDispatcher* dispatcher) {
56+
frontend_ = std::make_unique<Target::Frontend>(dispatcher->channel());
57+
Target::Dispatcher::wire(dispatcher, this);
58+
}
59+
60+
void TargetAgent::listenWorker(std::weak_ptr<WorkerManager> worker_manager) {
61+
auto manager = worker_manager.lock();
62+
if (!manager) {
63+
return;
64+
}
65+
std::unique_ptr<WorkerDelegate> delegate(new WorkerTargetDelegate(shared_from_this()));
66+
worker_event_handle_ = manager->SetAutoAttach(std::move(delegate));
67+
}
68+
69+
void TargetAgent::reset() {
70+
if (worker_event_handle_) {
71+
worker_event_handle_.reset();
72+
}
73+
}
74+
75+
void TargetAgent::targetCreated(const std::string &target_id,const std::string &type,const std::string &title,const std::string &url) {
76+
frontend_->targetCreated(createTargetInfo(target_id, type, title, url));
77+
}
78+
79+
int TargetAgent::getNextSessionId() {
80+
return next_session_id_++;
81+
}
82+
83+
int TargetAgent::getNextTargetId() {
84+
return next_target_id_++;
85+
}
86+
87+
void TargetAgent::attachedToTarget(std::shared_ptr<MainThreadHandle> worker,const std::string &target_id, const std::string &type,const std::string &title,const std::string &url) {
88+
int session_id = getNextSessionId();
89+
target_session_id_worker_map_[session_id] = worker;
90+
worker->SetTargetSessionId(session_id);
91+
frontend_->attachedToTarget(std::to_string(session_id), createTargetInfo(target_id, type, title, url), true);
92+
}
93+
94+
} // namespace protocol
95+
} // namespace inspector
96+
} // namespace node

src/inspector/target_agent.h

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#ifndef SRC_INSPECTOR_TARGET_AGENT_H_
2+
#define SRC_INSPECTOR_TARGET_AGENT_H_
3+
4+
#include "inspector/worker_inspector.h"
5+
#include "node/inspector/protocol/Target.h"
6+
7+
#include <memory>
8+
#include <string>
9+
#include <thread>
10+
#include <unordered_map>
11+
12+
namespace node {
13+
14+
namespace inspector {
15+
class TargetInspector;
16+
17+
namespace protocol {
18+
19+
class TargetAgent : public Target::Backend, public std::enable_shared_from_this<TargetAgent>
20+
{
21+
public:
22+
explicit TargetAgent() {}
23+
24+
void Wire(UberDispatcher* dispatcher);
25+
26+
27+
void targetCreated(const std::string &target_id, const std::string &type,const std::string &title,const std::string &url);
28+
void attachedToTarget(std::shared_ptr<MainThreadHandle> worker,const std::string &target_id, const std::string &type,const std::string &title,const std::string &url);
29+
30+
int getNextTargetId();
31+
32+
void listenWorker(std::weak_ptr<WorkerManager> worker_manager);
33+
void reset();
34+
static std::unordered_map<int,std::shared_ptr<MainThreadHandle>> target_session_id_worker_map_;
35+
private:
36+
int getNextSessionId();
37+
std::shared_ptr<Target::Frontend> frontend_;
38+
std::weak_ptr<WorkerManager> worker_manager_;
39+
int next_session_id_ = 1;
40+
int next_target_id_ = 1;
41+
std::unique_ptr<WorkerManagerEventHandle> worker_event_handle_ = nullptr;
42+
};
43+
44+
} // namespace protocol
45+
} // namespace inspector
46+
} // namespace node
47+
48+
#endif // SRC_INSPECTOR_TARGET_AGENT_H_
49+

src/inspector_agent.cc

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
#include "inspector_agent.h"
2+
#include <string>
23

34
#include "env-inl.h"
45
#include "inspector/main_thread_interface.h"
56
#include "inspector/network_inspector.h"
67
#include "inspector/node_string.h"
78
#include "inspector/runtime_agent.h"
9+
#include "inspector/target_agent.h"
810
#include "inspector/tracing_agent.h"
911
#include "inspector/worker_agent.h"
1012
#include "inspector/worker_inspector.h"
@@ -18,6 +20,7 @@
1820
#include "permission/permission.h"
1921
#include "timer_wrap-inl.h"
2022
#include "util-inl.h"
23+
#include "util.h"
2124
#include "v8-inspector.h"
2225
#include "v8-platform.h"
2326

@@ -216,8 +219,9 @@ class ChannelImpl final : public v8_inspector::V8Inspector::Channel,
216219
std::unique_ptr<InspectorSessionDelegate> delegate,
217220
std::shared_ptr<MainThreadHandle> main_thread_,
218221
bool prevent_shutdown)
219-
: delegate_(std::move(delegate)), prevent_shutdown_(prevent_shutdown),
220-
retaining_context_(false) {
222+
: delegate_(std::move(delegate)), main_thread_(main_thread_),
223+
prevent_shutdown_(prevent_shutdown), retaining_context_(false)
224+
{
221225
session_ = inspector->connect(CONTEXT_GROUP_ID,
222226
this,
223227
StringView(),
@@ -234,6 +238,11 @@ class ChannelImpl final : public v8_inspector::V8Inspector::Channel,
234238
runtime_agent_->Wire(node_dispatcher_.get());
235239
network_inspector_ = std::make_unique<NetworkInspector>(env);
236240
network_inspector_->Wire(node_dispatcher_.get());
241+
if(env->options()->experimental_worker_inspection) {
242+
target_agent_ = std::make_shared<protocol::TargetAgent>();
243+
target_agent_->Wire(node_dispatcher_.get());
244+
target_agent_->listenWorker(worker_manager);
245+
}
237246
}
238247

239248
~ChannelImpl() override {
@@ -247,6 +256,9 @@ class ChannelImpl final : public v8_inspector::V8Inspector::Channel,
247256
runtime_agent_.reset(); // Dispose before the dispatchers
248257
network_inspector_->Disable();
249258
network_inspector_.reset(); // Dispose before the dispatchers
259+
if(target_agent_) {
260+
target_agent_->reset();
261+
}
250262
}
251263

252264
void emitNotificationFromBackend(const StringView& event,
@@ -329,6 +341,17 @@ class ChannelImpl final : public v8_inspector::V8Inspector::Channel,
329341
"[inspector send] %s\n",
330342
raw_message);
331343
}
344+
std::optional<int> target_session_id = main_thread_->GetTargetSessionId();
345+
if (target_session_id.has_value()) {
346+
std::string raw_message = protocol::StringUtil::StringViewToUtf8(message);
347+
std::unique_ptr<protocol::DictionaryValue> value =
348+
protocol::DictionaryValue::cast(
349+
protocol::StringUtil::parseJSON(raw_message));
350+
std::string target_session_id_str = std::to_string(*target_session_id);
351+
value->setString("sessionId", target_session_id_str);
352+
delegate_->SendMessageToFrontend(Utf8ToStringView(value->serializeToJSON())->string());
353+
}
354+
332355
delegate_->SendMessageToFrontend(message);
333356
}
334357

@@ -356,10 +379,12 @@ class ChannelImpl final : public v8_inspector::V8Inspector::Channel,
356379
std::unique_ptr<protocol::RuntimeAgent> runtime_agent_;
357380
std::unique_ptr<protocol::TracingAgent> tracing_agent_;
358381
std::unique_ptr<protocol::WorkerAgent> worker_agent_;
382+
std::shared_ptr<protocol::TargetAgent> target_agent_;
359383
std::unique_ptr<NetworkInspector> network_inspector_;
360384
std::unique_ptr<InspectorSessionDelegate> delegate_;
361385
std::unique_ptr<v8_inspector::V8InspectorSession> session_;
362386
std::unique_ptr<protocol::UberDispatcher> node_dispatcher_;
387+
std::shared_ptr<MainThreadHandle> main_thread_;
363388
bool prevent_shutdown_;
364389
bool retaining_context_;
365390
};

0 commit comments

Comments
 (0)