|
2 | 2 |
|
3 | 3 | #include "inspector/main_thread_interface.h"
|
4 | 4 | #include "inspector/node_string.h"
|
| 5 | +#include "inspector/runtime_agent.h" |
5 | 6 | #include "inspector/tracing_agent.h"
|
6 | 7 | #include "inspector/worker_agent.h"
|
7 | 8 | #include "inspector/worker_inspector.h"
|
@@ -221,21 +222,26 @@ class ChannelImpl final : public v8_inspector::V8Inspector::Channel,
|
221 | 222 | std::unique_ptr<InspectorSessionDelegate> delegate,
|
222 | 223 | std::shared_ptr<MainThreadHandle> main_thread_,
|
223 | 224 | bool prevent_shutdown)
|
224 |
| - : delegate_(std::move(delegate)), prevent_shutdown_(prevent_shutdown) { |
| 225 | + : delegate_(std::move(delegate)), prevent_shutdown_(prevent_shutdown), |
| 226 | + retaining_context_(false) { |
225 | 227 | session_ = inspector->connect(1, this, StringView());
|
226 | 228 | node_dispatcher_ = std::make_unique<protocol::UberDispatcher>(this);
|
227 | 229 | tracing_agent_ =
|
228 | 230 | std::make_unique<protocol::TracingAgent>(env, main_thread_);
|
229 | 231 | tracing_agent_->Wire(node_dispatcher_.get());
|
230 | 232 | worker_agent_ = std::make_unique<protocol::WorkerAgent>(worker_manager);
|
231 | 233 | worker_agent_->Wire(node_dispatcher_.get());
|
| 234 | + runtime_agent_ = std::make_unique<protocol::RuntimeAgent>(env); |
| 235 | + runtime_agent_->Wire(node_dispatcher_.get()); |
232 | 236 | }
|
233 | 237 |
|
234 | 238 | ~ChannelImpl() override {
|
235 | 239 | tracing_agent_->disable();
|
236 | 240 | tracing_agent_.reset(); // Dispose before the dispatchers
|
237 | 241 | worker_agent_->disable();
|
238 | 242 | worker_agent_.reset(); // Dispose before the dispatchers
|
| 243 | + runtime_agent_->disable(); |
| 244 | + runtime_agent_.reset(); // Dispose before the dispatchers |
239 | 245 | }
|
240 | 246 |
|
241 | 247 | void dispatchProtocolMessage(const StringView& message) {
|
@@ -264,6 +270,15 @@ class ChannelImpl final : public v8_inspector::V8Inspector::Channel,
|
264 | 270 | return prevent_shutdown_;
|
265 | 271 | }
|
266 | 272 |
|
| 273 | + bool notifyWaitingForDisconnect() { |
| 274 | + retaining_context_ = runtime_agent_->notifyWaitingForDisconnect(); |
| 275 | + return retaining_context_; |
| 276 | + } |
| 277 | + |
| 278 | + bool retainingContext() { |
| 279 | + return retaining_context_; |
| 280 | + } |
| 281 | + |
267 | 282 | private:
|
268 | 283 | void sendResponse(
|
269 | 284 | int callId,
|
@@ -303,12 +318,14 @@ class ChannelImpl final : public v8_inspector::V8Inspector::Channel,
|
303 | 318 | DCHECK(false);
|
304 | 319 | }
|
305 | 320 |
|
| 321 | + std::unique_ptr<protocol::RuntimeAgent> runtime_agent_; |
306 | 322 | std::unique_ptr<protocol::TracingAgent> tracing_agent_;
|
307 | 323 | std::unique_ptr<protocol::WorkerAgent> worker_agent_;
|
308 | 324 | std::unique_ptr<InspectorSessionDelegate> delegate_;
|
309 | 325 | std::unique_ptr<v8_inspector::V8InspectorSession> session_;
|
310 | 326 | std::unique_ptr<protocol::UberDispatcher> node_dispatcher_;
|
311 | 327 | bool prevent_shutdown_;
|
| 328 | + bool retaining_context_; |
312 | 329 | };
|
313 | 330 |
|
314 | 331 | class InspectorTimer {
|
@@ -511,7 +528,18 @@ class NodeInspectorClient : public V8InspectorClient {
|
511 | 528 | }
|
512 | 529 |
|
513 | 530 | void disconnectFrontend(int session_id) {
|
514 |
| - channels_.erase(session_id); |
| 531 | + auto it = channels_.find(session_id); |
| 532 | + if (it == channels_.end()) |
| 533 | + return; |
| 534 | + bool retaining_context = it->second->retainingContext(); |
| 535 | + channels_.erase(it); |
| 536 | + if (retaining_context) { |
| 537 | + for (const auto& id_channel : channels_) { |
| 538 | + if (id_channel.second->retainingContext()) |
| 539 | + return; |
| 540 | + } |
| 541 | + contextDestroyed(env_->context()); |
| 542 | + } |
515 | 543 | }
|
516 | 544 |
|
517 | 545 | void dispatchMessageFromFrontend(int session_id, const StringView& message) {
|
@@ -608,6 +636,15 @@ class NodeInspectorClient : public V8InspectorClient {
|
608 | 636 | return false;
|
609 | 637 | }
|
610 | 638 |
|
| 639 | + bool notifyWaitingForDisconnect() { |
| 640 | + bool retaining_context = false; |
| 641 | + for (const auto& id_channel : channels_) { |
| 642 | + if (id_channel.second->notifyWaitingForDisconnect()) |
| 643 | + retaining_context = true; |
| 644 | + } |
| 645 | + return retaining_context; |
| 646 | + } |
| 647 | + |
611 | 648 | std::shared_ptr<MainThreadHandle> getThreadHandle() {
|
612 | 649 | if (interface_ == nullptr) {
|
613 | 650 | interface_.reset(new MainThreadInterface(
|
@@ -774,9 +811,8 @@ void Agent::WaitForDisconnect() {
|
774 | 811 | fprintf(stderr, "Waiting for the debugger to disconnect...\n");
|
775 | 812 | fflush(stderr);
|
776 | 813 | }
|
777 |
| - // TODO(addaleax): Maybe this should use an at-exit hook for the Environment |
778 |
| - // or something similar? |
779 |
| - client_->contextDestroyed(parent_env_->context()); |
| 814 | + if (!client_->notifyWaitingForDisconnect()) |
| 815 | + client_->contextDestroyed(parent_env_->context()); |
780 | 816 | if (io_ != nullptr) {
|
781 | 817 | io_->StopAcceptingNewConnections();
|
782 | 818 | client_->waitForIoShutdown();
|
|
0 commit comments