|
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