diff options
author | Eugene Ostroukhov <eostroukhov@google.com> | 2018-09-08 19:45:10 -0700 |
---|---|---|
committer | Eugene Ostroukhov <eostroukhov@google.com> | 2018-09-18 09:01:33 -0700 |
commit | f28c6f7eef58e7c3133bb2cd457d05b986194ba3 (patch) | |
tree | b8e8583ff735a3b0721831af51c4f92d967849f1 /src | |
parent | ba0b4e43e442926bfb9389a42aa7393f91e6748a (diff) | |
download | node-new-f28c6f7eef58e7c3133bb2cd457d05b986194ba3.tar.gz |
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.
PR-URL: https://github.com/nodejs/node/pull/21364
Reviewed-By: Aleksei Koziatinskii <ak239spb@gmail.com>
Reviewed-By: Jan Krems <jan.krems@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Diffstat (limited to 'src')
-rw-r--r-- | src/inspector/node_protocol.pdl | 55 | ||||
-rw-r--r-- | src/inspector/node_protocol_config.json | 7 | ||||
-rw-r--r-- | src/inspector/worker_agent.cc | 154 | ||||
-rw-r--r-- | src/inspector/worker_agent.h | 39 | ||||
-rw-r--r-- | src/inspector/worker_inspector.cc | 128 | ||||
-rw-r--r-- | src/inspector/worker_inspector.h | 98 | ||||
-rw-r--r-- | src/inspector_agent.cc | 48 | ||||
-rw-r--r-- | src/inspector_agent.h | 8 | ||||
-rw-r--r-- | src/node_worker.cc | 14 |
9 files changed, 541 insertions, 10 deletions
diff --git a/src/inspector/node_protocol.pdl b/src/inspector/node_protocol.pdl index 27b3d814c8..9fb9f1c55f 100644 --- a/src/inspector/node_protocol.pdl +++ b/src/inspector/node_protocol.pdl @@ -37,3 +37,58 @@ experimental domain NodeTracing # Signals that tracing is stopped and there is no trace buffers pending flush, all data were # delivered via dataCollected events. event tracingComplete + +# Support for sending messages to Node worker Inspector instances. +experimental domain NodeWorker + + type WorkerID extends string + + # Unique identifier of attached debugging session. + type SessionID extends string + + type WorkerInfo extends object + properties + WorkerID workerId + string type + string title + string url + + # Sends protocol message over session with given id. + command sendMessageToWorker + parameters + string message + # Identifier of the session. + SessionID sessionId + + # Instructs the inspector to attach to running workers. Will also attach to new workers + # as they start + command enable + parameters + # Whether to new workers should be paused until the frontend sends `Runtime.runIfWaitingForDebugger` + # message to run them. + boolean waitForDebuggerOnStart + + # Detaches from all running workers and disables attaching to new workers as they are started. + command disable + + # Issued when attached to a worker. + event attachedToWorker + parameters + # Identifier assigned to the session used to send/receive messages. + SessionID sessionId + WorkerInfo workerInfo + boolean waitingForDebugger + + # Issued when detached from the worker. + event detachedFromWorker + parameters + # Detached session identifier. + SessionID sessionId + + # Notifies about a new protocol message received from the session + # (session ID is provided in attachedToWorker notification). + event receivedMessageFromWorker + parameters + # Identifier of a session which sends a message. + SessionID sessionId + string message diff --git a/src/inspector/node_protocol_config.json b/src/inspector/node_protocol_config.json index 7cea20ae93..4ef3785606 100644 --- a/src/inspector/node_protocol_config.json +++ b/src/inspector/node_protocol_config.json @@ -3,12 +3,7 @@ "path": "node_protocol.json", "package": "src/node/inspector/protocol", "output": "node/inspector/protocol", - "namespace": ["node", "inspector", "protocol"], - "options": [ - { - "domain": "NodeTracing" - } - ] + "namespace": ["node", "inspector", "protocol"] }, "exported": { "package": "include/inspector", diff --git a/src/inspector/worker_agent.cc b/src/inspector/worker_agent.cc new file mode 100644 index 0000000000..fccd6d57a5 --- /dev/null +++ b/src/inspector/worker_agent.cc @@ -0,0 +1,154 @@ +#include "worker_agent.h" + +#include "main_thread_interface.h" +#include "worker_inspector.h" + +namespace node { +namespace inspector { +namespace protocol { + +class NodeWorkers + : public std::enable_shared_from_this<NodeWorkers> { + public: + explicit NodeWorkers(std::weak_ptr<NodeWorker::Frontend> frontend, + std::shared_ptr<MainThreadHandle> thread) + : frontend_(frontend), thread_(thread) {} + void WorkerCreated(const std::string& title, + const std::string& url, + bool waiting, + std::shared_ptr<MainThreadHandle> target); + void Receive(const std::string& id, const std::string& message); + void Send(const std::string& id, const std::string& message); + void Detached(const std::string& id); + + private: + std::weak_ptr<NodeWorker::Frontend> frontend_; + std::shared_ptr<MainThreadHandle> thread_; + std::unordered_map<std::string, std::unique_ptr<InspectorSession>> sessions_; + int next_target_id_ = 0; +}; + +namespace { +class AgentWorkerInspectorDelegate : public WorkerDelegate { + public: + explicit AgentWorkerInspectorDelegate(std::shared_ptr<NodeWorkers> workers) + : workers_(workers) {} + + void WorkerCreated(const std::string& title, + const std::string& url, + bool waiting, + std::shared_ptr<MainThreadHandle> target) override { + workers_->WorkerCreated(title, url, waiting, target); + } + + private: + std::shared_ptr<NodeWorkers> workers_; +}; + +class ParentInspectorSessionDelegate : public InspectorSessionDelegate { + public: + ParentInspectorSessionDelegate(const std::string& id, + std::shared_ptr<NodeWorkers> workers) + : id_(id), workers_(workers) {} + + ~ParentInspectorSessionDelegate() override { + workers_->Detached(id_); + } + + void SendMessageToFrontend(const v8_inspector::StringView& msg) override { + std::string message = protocol::StringUtil::StringViewToUtf8(msg); + workers_->Send(id_, message); + } + + private: + std::string id_; + std::shared_ptr<NodeWorkers> workers_; +}; + +std::unique_ptr<NodeWorker::WorkerInfo> WorkerInfo(const std::string& id, + const std::string& title, + const std::string& url) { + return NodeWorker::WorkerInfo::create() + .setWorkerId(id) + .setTitle(title) + .setUrl(url) + .setType("worker").build(); +} +} // namespace + +WorkerAgent::WorkerAgent(std::weak_ptr<WorkerManager> manager) + : manager_(manager) {} + + +void WorkerAgent::Wire(UberDispatcher* dispatcher) { + frontend_.reset(new NodeWorker::Frontend(dispatcher->channel())); + NodeWorker::Dispatcher::wire(dispatcher, this); + auto manager = manager_.lock(); + CHECK_NOT_NULL(manager); + workers_ = + std::make_shared<NodeWorkers>(frontend_, manager->MainThread()); +} + +DispatchResponse WorkerAgent::sendMessageToWorker(const String& message, + const String& sessionId) { + workers_->Receive(sessionId, message); + return DispatchResponse::OK(); +} + +DispatchResponse WorkerAgent::enable(bool waitForDebuggerOnStart) { + auto manager = manager_.lock(); + if (!manager) { + return DispatchResponse::OK(); + } + if (!event_handle_) { + std::unique_ptr<AgentWorkerInspectorDelegate> delegate( + new AgentWorkerInspectorDelegate(workers_)); + event_handle_ = manager->SetAutoAttach(std::move(delegate)); + } + event_handle_->SetWaitOnStart(waitForDebuggerOnStart); + return DispatchResponse::OK(); +} + +DispatchResponse WorkerAgent::disable() { + event_handle_.reset(); + return DispatchResponse::OK(); +} + +void NodeWorkers::WorkerCreated(const std::string& title, + const std::string& url, + bool waiting, + std::shared_ptr<MainThreadHandle> target) { + auto frontend = frontend_.lock(); + if (!frontend) + return; + std::string id = std::to_string(++next_target_id_); + auto delegate = thread_->MakeDelegateThreadSafe( + std::unique_ptr<InspectorSessionDelegate>( + new ParentInspectorSessionDelegate(id, shared_from_this()))); + sessions_[id] = target->Connect(std::move(delegate), true); + frontend->attachedToWorker(id, WorkerInfo(id, title, url), waiting); +} + +void NodeWorkers::Send(const std::string& id, const std::string& message) { + auto frontend = frontend_.lock(); + if (frontend) + frontend->receivedMessageFromWorker(id, message); +} + +void NodeWorkers::Receive(const std::string& id, const std::string& message) { + auto it = sessions_.find(id); + if (it != sessions_.end()) + it->second->Dispatch(Utf8ToStringView(message)->string()); +} + +void NodeWorkers::Detached(const std::string& id) { + if (sessions_.erase(id) == 0) + return; + auto frontend = frontend_.lock(); + if (frontend) { + frontend->detachedFromWorker(id); + } +} +} // namespace protocol +} // namespace inspector +} // namespace node diff --git a/src/inspector/worker_agent.h b/src/inspector/worker_agent.h new file mode 100644 index 0000000000..402c719416 --- /dev/null +++ b/src/inspector/worker_agent.h @@ -0,0 +1,39 @@ +#ifndef SRC_INSPECTOR_WORKER_AGENT_H_ +#define SRC_INSPECTOR_WORKER_AGENT_H_ + +#include "node/inspector/protocol/NodeWorker.h" +#include "v8.h" + + +namespace node { +namespace inspector { +class WorkerManagerEventHandle; +class WorkerManager; + +namespace protocol { +class NodeWorkers; + +class WorkerAgent : public NodeWorker::Backend { + public: + explicit WorkerAgent(std::weak_ptr<WorkerManager> manager); + ~WorkerAgent() override = default; + + void Wire(UberDispatcher* dispatcher); + + DispatchResponse sendMessageToWorker(const String& message, + const String& sessionId) override; + + DispatchResponse enable(bool waitForDebuggerOnStart) override; + DispatchResponse disable() override; + + private: + std::shared_ptr<NodeWorker::Frontend> frontend_; + std::weak_ptr<WorkerManager> manager_; + std::unique_ptr<WorkerManagerEventHandle> event_handle_; + std::shared_ptr<NodeWorkers> workers_; +}; +} // namespace protocol +} // namespace inspector +} // namespace node + +#endif // SRC_INSPECTOR_WORKER_AGENT_H_ diff --git a/src/inspector/worker_inspector.cc b/src/inspector/worker_inspector.cc new file mode 100644 index 0000000000..52e71a562d --- /dev/null +++ b/src/inspector/worker_inspector.cc @@ -0,0 +1,128 @@ +#include "worker_inspector.h" + +#include "main_thread_interface.h" + +namespace node { +namespace inspector { +namespace { + +class WorkerStartedRequest : public Request { + public: + WorkerStartedRequest( + int id, + const std::string& url, + std::shared_ptr<node::inspector::MainThreadHandle> worker_thread, + bool waiting) + : id_(id), + info_(BuildWorkerTitle(id), url, worker_thread), + waiting_(waiting) {} + void Call(MainThreadInterface* thread) override { + auto manager = thread->inspector_agent()->GetWorkerManager(); + manager->WorkerStarted(id_, info_, waiting_); + } + + private: + static std::string BuildWorkerTitle(int id) { + return "Worker " + std::to_string(id); + } + + int id_; + WorkerInfo info_; + bool waiting_; +}; + + +void Report(const std::unique_ptr<WorkerDelegate>& delegate, + const WorkerInfo& info, bool waiting) { + if (info.worker_thread) + delegate->WorkerCreated(info.title, info.url, waiting, info.worker_thread); +} + +class WorkerFinishedRequest : public Request { + public: + explicit WorkerFinishedRequest(int worker_id) : worker_id_(worker_id) {} + + void Call(MainThreadInterface* thread) override { + thread->inspector_agent()->GetWorkerManager()->WorkerFinished(worker_id_); + } + + private: + int worker_id_; +}; +} // namespace + + +ParentInspectorHandle::ParentInspectorHandle( + int id, const std::string& url, + std::shared_ptr<MainThreadHandle> parent_thread, bool wait_for_connect) + : id_(id), url_(url), parent_thread_(parent_thread), + wait_(wait_for_connect) {} + +ParentInspectorHandle::~ParentInspectorHandle() { + parent_thread_->Post( + std::unique_ptr<Request>(new WorkerFinishedRequest(id_))); +} + +void ParentInspectorHandle::WorkerStarted( + std::shared_ptr<MainThreadHandle> worker_thread, bool waiting) { + std::unique_ptr<Request> request( + new WorkerStartedRequest(id_, url_, worker_thread, waiting)); + parent_thread_->Post(std::move(request)); +} + +void WorkerManager::WorkerFinished(int session_id) { + children_.erase(session_id); +} + +void WorkerManager::WorkerStarted(int session_id, + const WorkerInfo& info, + bool waiting) { + if (info.worker_thread->Expired()) + return; + children_.emplace(session_id, info); + for (const auto& delegate : delegates_) { + Report(delegate.second, info, waiting); + } +} + +std::unique_ptr<ParentInspectorHandle> +WorkerManager::NewParentHandle(int thread_id, const std::string& url) { + bool wait = !delegates_waiting_on_start_.empty(); + return std::unique_ptr<ParentInspectorHandle>( + new ParentInspectorHandle(thread_id, url, thread_, wait)); +} + +void WorkerManager::RemoveAttachDelegate(int id) { + delegates_.erase(id); + delegates_waiting_on_start_.erase(id); +} + +std::unique_ptr<WorkerManagerEventHandle> WorkerManager::SetAutoAttach( + std::unique_ptr<WorkerDelegate> attach_delegate) { + int id = ++next_delegate_id_; + delegates_[id] = std::move(attach_delegate); + const auto& delegate = delegates_[id]; + for (const auto& worker : children_) { + // Waiting is only reported when a worker is started, same as browser + Report(delegate, worker.second, false); + } + return std::unique_ptr<WorkerManagerEventHandle>( + new WorkerManagerEventHandle(shared_from_this(), id)); +} + +void WorkerManager::SetWaitOnStartForDelegate(int id, bool wait) { + if (wait) + delegates_waiting_on_start_.insert(id); + else + delegates_waiting_on_start_.erase(id); +} + +void WorkerManagerEventHandle::SetWaitOnStart(bool wait_on_start) { + manager_->SetWaitOnStartForDelegate(id_, wait_on_start); +} + +WorkerManagerEventHandle::~WorkerManagerEventHandle() { + manager_->RemoveAttachDelegate(id_); +} +} // namespace inspector +} // namespace node diff --git a/src/inspector/worker_inspector.h b/src/inspector/worker_inspector.h new file mode 100644 index 0000000000..e3c96cf62f --- /dev/null +++ b/src/inspector/worker_inspector.h @@ -0,0 +1,98 @@ +#ifndef SRC_INSPECTOR_WORKER_INSPECTOR_H_ +#define SRC_INSPECTOR_WORKER_INSPECTOR_H_ + +#if !HAVE_INSPECTOR +#error("This header can only be used when inspector is enabled") +#endif + +#include <memory> +#include <string> +#include <unordered_map> +#include <unordered_set> + +namespace node { +namespace inspector { +class MainThreadHandle; +class WorkerManager; + +class WorkerDelegate { + public: + virtual void WorkerCreated(const std::string& title, + const std::string& url, + bool waiting, + std::shared_ptr<MainThreadHandle> worker) = 0; +}; + +class WorkerManagerEventHandle { + public: + explicit WorkerManagerEventHandle(std::shared_ptr<WorkerManager> manager, + int id) + : manager_(manager), id_(id) {} + void SetWaitOnStart(bool wait_on_start); + ~WorkerManagerEventHandle(); + + private: + std::shared_ptr<WorkerManager> manager_; + int id_; +}; + +struct WorkerInfo { + WorkerInfo(const std::string& target_title, + const std::string& target_url, + std::shared_ptr<MainThreadHandle> worker_thread) + : title(target_title), + url(target_url), + worker_thread(worker_thread) {} + std::string title; + std::string url; + std::shared_ptr<MainThreadHandle> worker_thread; +}; + +class ParentInspectorHandle { + public: + ParentInspectorHandle(int id, const std::string& url, + std::shared_ptr<MainThreadHandle> parent_thread, + bool wait_for_connect); + ~ParentInspectorHandle(); + void WorkerStarted(std::shared_ptr<MainThreadHandle> worker_thread, + bool waiting); + bool WaitForConnect() { + return wait_; + } + + private: + int id_; + std::string url_; + std::shared_ptr<MainThreadHandle> parent_thread_; + bool wait_; +}; + +class WorkerManager : public std::enable_shared_from_this<WorkerManager> { + public: + explicit WorkerManager(std::shared_ptr<MainThreadHandle> thread) + : thread_(thread) {} + + std::unique_ptr<ParentInspectorHandle> NewParentHandle( + int thread_id, const std::string& url); + void WorkerStarted(int session_id, const WorkerInfo& info, bool waiting); + void WorkerFinished(int session_id); + std::unique_ptr<WorkerManagerEventHandle> SetAutoAttach( + std::unique_ptr<WorkerDelegate> attach_delegate); + void SetWaitOnStartForDelegate(int id, bool wait); + void RemoveAttachDelegate(int id); + std::shared_ptr<MainThreadHandle> MainThread() { + return thread_; + } + + private: + std::shared_ptr<MainThreadHandle> thread_; + std::unordered_map<int, WorkerInfo> children_; + std::unordered_map<int, std::unique_ptr<WorkerDelegate>> delegates_; + // If any one needs it, workers stop for all + std::unordered_set<int> delegates_waiting_on_start_; + int next_delegate_id_ = 0; +}; +} // namespace inspector +} // namespace node + +#endif // SRC_INSPECTOR_WORKER_INSPECTOR_H_ diff --git a/src/inspector_agent.cc b/src/inspector_agent.cc index 63b9266353..ebb7b7d5bc 100644 --- a/src/inspector_agent.cc +++ b/src/inspector_agent.cc @@ -4,6 +4,8 @@ #include "inspector/main_thread_interface.h" #include "inspector/node_string.h" #include "inspector/tracing_agent.h" +#include "inspector/worker_agent.h" +#include "inspector/worker_inspector.h" #include "node/inspector/protocol/Protocol.h" #include "node_internals.h" #include "node_url.h" @@ -201,6 +203,7 @@ class ChannelImpl final : public v8_inspector::V8Inspector::Channel, public: explicit ChannelImpl(Environment* env, const std::unique_ptr<V8Inspector>& inspector, + std::shared_ptr<WorkerManager> worker_manager, std::unique_ptr<InspectorSessionDelegate> delegate, bool prevent_shutdown) : delegate_(std::move(delegate)), @@ -209,11 +212,15 @@ class ChannelImpl final : public v8_inspector::V8Inspector::Channel, node_dispatcher_.reset(new protocol::UberDispatcher(this)); tracing_agent_.reset(new protocol::TracingAgent(env)); tracing_agent_->Wire(node_dispatcher_.get()); + worker_agent_.reset(new protocol::WorkerAgent(worker_manager)); + worker_agent_->Wire(node_dispatcher_.get()); } virtual ~ChannelImpl() { tracing_agent_->disable(); tracing_agent_.reset(); // Dispose before the dispatchers + worker_agent_->disable(); + worker_agent_.reset(); // Dispose before the dispatchers } std::string dispatchProtocolMessage(const StringView& message) { @@ -273,6 +280,7 @@ class ChannelImpl final : public v8_inspector::V8Inspector::Channel, } std::unique_ptr<protocol::TracingAgent> tracing_agent_; + std::unique_ptr<protocol::WorkerAgent> worker_agent_; std::unique_ptr<InspectorSessionDelegate> delegate_; std::unique_ptr<v8_inspector::V8InspectorSession> session_; std::unique_ptr<protocol::UberDispatcher> node_dispatcher_; @@ -469,7 +477,8 @@ class NodeInspectorClient : public V8InspectorClient { // TODO(addaleax): Revert back to using make_unique once we get issues // with CI resolved (i.e. revert the patch that added this comment). channels_[session_id].reset( - new ChannelImpl(env_, client_, std::move(delegate), prevent_shutdown)); + new ChannelImpl(env_, client_, getWorkerManager(), + std::move(delegate), prevent_shutdown)); return session_id; } @@ -589,6 +598,14 @@ class NodeInspectorClient : public V8InspectorClient { return interface_->GetHandle(); } + std::shared_ptr<WorkerManager> getWorkerManager() { + if (worker_manager_ == nullptr) { + worker_manager_ = + std::make_shared<WorkerManager>(getThreadHandle()); + } + return worker_manager_; + } + bool IsActive() { return !channels_.empty(); } @@ -646,6 +663,7 @@ class NodeInspectorClient : public V8InspectorClient { bool waiting_for_io_shutdown_ = false; // Allows accessing Inspector from non-main threads std::unique_ptr<MainThreadInterface> interface_; + std::shared_ptr<WorkerManager> worker_manager_; }; Agent::Agent(Environment* env) @@ -680,7 +698,10 @@ bool Agent::Start(const std::string& path, } bool wait_for_connect = options->wait_for_connect(); - if (!options->inspector_enabled || !StartIoThread()) { + if (parent_handle_) { + wait_for_connect = parent_handle_->WaitForConnect(); + parent_handle_->WorkerStarted(client_->getThreadHandle(), wait_for_connect); + } else if (!options->inspector_enabled || !StartIoThread()) { return false; } if (wait_for_connect) { @@ -727,7 +748,9 @@ std::unique_ptr<InspectorSession> Agent::Connect( void Agent::WaitForDisconnect() { CHECK_NOT_NULL(client_); - if (client_->hasConnectedSessions()) { + bool is_worker = parent_handle_ != nullptr; + parent_handle_.reset(); + if (client_->hasConnectedSessions() && !is_worker) { fprintf(stderr, "Waiting for the debugger to disconnect...\n"); fflush(stderr); } @@ -842,7 +865,11 @@ void Agent::ContextCreated(Local<Context> context, const ContextInfo& info) { } bool Agent::WillWaitForConnect() { - return debug_options_->wait_for_connect(); + if (debug_options_->wait_for_connect()) + return true; + if (parent_handle_) + return parent_handle_->WaitForConnect(); + return false; } bool Agent::IsActive() { @@ -851,11 +878,24 @@ bool Agent::IsActive() { return io_ != nullptr || client_->IsActive(); } +void Agent::AddWorkerInspector(int thread_id, + const std::string& url, + Agent* agent) { + CHECK_NOT_NULL(client_); + agent->parent_handle_ = + client_->getWorkerManager()->NewParentHandle(thread_id, url); +} + void Agent::WaitForConnect() { CHECK_NOT_NULL(client_); client_->waitForFrontend(); } +std::shared_ptr<WorkerManager> Agent::GetWorkerManager() { + CHECK_NOT_NULL(client_); + return client_->getWorkerManager(); +} + SameThreadInspectorSession::~SameThreadInspectorSession() { auto client = client_.lock(); if (client) diff --git a/src/inspector_agent.h b/src/inspector_agent.h index 79ae8d4cd9..e926ccaa92 100644 --- a/src/inspector_agent.h +++ b/src/inspector_agent.h @@ -26,7 +26,9 @@ struct ContextInfo; namespace inspector { class InspectorIo; +class ParentInspectorHandle; class NodeInspectorClient; +class WorkerManager; class InspectorSession { public: @@ -82,6 +84,8 @@ class Agent { void EnableAsyncHook(); void DisableAsyncHook(); + void AddWorkerInspector(int thread_id, const std::string& url, Agent* agent); + // Called to create inspector sessions that can be used from the main thread. // The inspector responds by using the delegate to send messages back. std::unique_ptr<InspectorSession> Connect( @@ -103,6 +107,9 @@ class Agent { std::shared_ptr<DebugOptions> options() { return debug_options_; } void ContextCreated(v8::Local<v8::Context> context, const ContextInfo& info); + // Interface for interacting with inspectors in worker threads + std::shared_ptr<WorkerManager> GetWorkerManager(); + private: void ToggleAsyncHook(v8::Isolate* isolate, const node::Persistent<v8::Function>& fn); @@ -112,6 +119,7 @@ class Agent { std::shared_ptr<NodeInspectorClient> client_; // Interface for transports, e.g. WebSocket server std::unique_ptr<InspectorIo> io_; + std::unique_ptr<ParentInspectorHandle> parent_handle_; std::string path_; std::shared_ptr<DebugOptions> debug_options_; diff --git a/src/node_worker.cc b/src/node_worker.cc index 1a90e3a64f..209b7a4d09 100644 --- a/src/node_worker.cc +++ b/src/node_worker.cc @@ -40,6 +40,14 @@ void StartWorkerInspector(Environment* child, const std::string& url) { child->inspector_agent()->Start(url, nullptr, false); } +void AddWorkerInspector(Environment* parent, + Environment* child, + int id, + const std::string& url) { + parent->inspector_agent()->AddWorkerInspector(id, url, + child->inspector_agent()); +} + void WaitForWorkerInspectorToStop(Environment* child) { child->inspector_agent()->WaitForDisconnect(); child->inspector_agent()->Stop(); @@ -48,6 +56,10 @@ void WaitForWorkerInspectorToStop(Environment* child) { #else // No-ops void StartWorkerInspector(Environment* child, const std::string& url) {} +void AddWorkerInspector(Environment* parent, + Environment* child, + int id, + const std::string& url) {} void WaitForWorkerInspectorToStop(Environment* child) {} #endif @@ -115,6 +127,8 @@ Worker::Worker(Environment* env, Local<Object> wrap, const std::string& url) env_->Start(std::vector<std::string>{}, std::vector<std::string>{}, env->profiler_idle_notifier_started()); + // Done while on the parent thread + AddWorkerInspector(env, env_.get(), thread_id_, url_); } // The new isolate won't be bothered on this thread again. |