diff --git a/src/env-inl.h b/src/env-inl.h index 74e427e40353d9..9e8db822c66580 100644 --- a/src/env-inl.h +++ b/src/env-inl.h @@ -175,7 +175,7 @@ inline Environment::Environment(IsolateData* isolate_data, debugger_agent_(this), #if HAVE_INSPECTOR inspector_agent_(this), -#endif +#endif // HAVE_INSPECTOR handle_cleanup_waiting_(0), http_parser_buffer_(nullptr), context_(context->GetIsolate(), context) { @@ -356,6 +356,29 @@ inline IsolateData* Environment::isolate_data() const { return isolate_data_; } +#if HAVE_INSPECTOR +inline void Environment::ContextCreated(node::inspector::ContextInfo* info) { + contexts()->push_back(info); + if (inspector_agent()->IsStarted()) { + inspector_agent()->ContextCreated(info); + } +} +inline void Environment::ContextDestroyed(v8::Local context) { + for (auto i = std::begin(*contexts()); i != std::end(*contexts()); ++i) { + auto it = *i; + if (it->context(isolate()) == context) { + delete it; + contexts()->erase(i); + if (inspector_agent()->IsStarted()) { + inspector_agent()->ContextDestroyed(context); + } + return; + } + } +} + +#endif // HAVE_INSPECTOR + inline void Environment::ThrowError(const char* errmsg) { ThrowError(v8::Exception::Error, errmsg); } diff --git a/src/env.cc b/src/env.cc index efa2d53f0435b2..ec94e98e645582 100644 --- a/src/env.cc +++ b/src/env.cc @@ -12,6 +12,10 @@ #include +#if HAVE_INSPECTOR +#include "inspector_agent.h" +#endif + namespace node { using v8::Context; @@ -30,6 +34,11 @@ void Environment::Start(int argc, HandleScope handle_scope(isolate()); Context::Scope context_scope(context()); +#if HAVE_INSPECTOR + ContextCreated( + new node::inspector::ContextInfo(context(), 1, "NodeJS Main Context")); +#endif + uv_check_init(event_loop(), immediate_check_handle()); uv_unref(reinterpret_cast(immediate_check_handle())); diff --git a/src/env.h b/src/env.h index fe49ac0c876a47..77d46c1c6912cc 100644 --- a/src/env.h +++ b/src/env.h @@ -7,6 +7,7 @@ #include "debug-agent.h" #if HAVE_INSPECTOR #include "inspector_agent.h" +#include #endif #include "handle_wrap.h" #include "req-wrap.h" @@ -528,6 +529,12 @@ class Environment { inline inspector::Agent* inspector_agent() { return &inspector_agent_; } + + inline void ContextCreated(node::inspector::ContextInfo* info); + inline void ContextDestroyed(v8::Local context); + inline std::vector* contexts() { + return &contexts_; + } #endif typedef ListHead HandleWrapQueue; @@ -564,6 +571,7 @@ class Environment { debugger::Agent debugger_agent_; #if HAVE_INSPECTOR inspector::Agent inspector_agent_; + std::vector contexts_; #endif HandleWrapQueue handle_wrap_queue_; diff --git a/src/inspector_agent.cc b/src/inspector_agent.cc index 3f3d548de4cdf6..ffca94a839751a 100644 --- a/src/inspector_agent.cc +++ b/src/inspector_agent.cc @@ -191,6 +191,8 @@ class AgentImpl { bool Start(v8::Platform* platform, const char* path, int port, bool wait); // Stop the inspector agent void Stop(); + void ContextCreated(const node::inspector::ContextInfo* info); + void ContextDestroyed(v8::Local context); bool IsStarted(); bool IsConnected() { return state_ == State::kConnected; } @@ -323,8 +325,22 @@ class V8NodeInspector : public v8_inspector::V8InspectorClient { terminated_(false), running_nested_loop_(false), inspector_(V8Inspector::create(env->isolate(), this)) { - inspector_->contextCreated( - v8_inspector::V8ContextInfo(env->context(), 1, "NodeJS Main Context")); + v8::HandleScope handles(env_->isolate()); + for (auto it : *env->contexts()) { + contextCreated(it); + } + } + + void contextCreated(const node::inspector::ContextInfo* info) { + inspector()->contextCreated( + v8_inspector::V8ContextInfo( + info->context(env_->isolate()), + info->groupId(), + info->name())); + } + + void contextDestroyed(v8::Local context) { + inspector()->contextDestroyed(context); } void runMessageLoopOnPause(int context_group_id) override { @@ -510,6 +526,13 @@ void AgentImpl::Stop() { delete inspector_; } +void AgentImpl::ContextCreated(const node::inspector::ContextInfo* info) { + inspector_->contextCreated(info); +} +void AgentImpl::ContextDestroyed(v8::Local context) { + inspector_->contextDestroyed(context); +} + bool AgentImpl::IsStarted() { return !!platform_; } @@ -865,6 +888,13 @@ void Agent::Stop() { impl->Stop(); } +void Agent::ContextCreated(const node::inspector::ContextInfo* info) { + impl->ContextCreated(info); +} +void Agent::ContextDestroyed(v8::Local context) { + impl->ContextDestroyed(context); +} + bool Agent::IsStarted() { return impl->IsStarted(); } diff --git a/src/inspector_agent.h b/src/inspector_agent.h index 3607cffba5d21f..8667ab664bf038 100644 --- a/src/inspector_agent.h +++ b/src/inspector_agent.h @@ -5,6 +5,8 @@ #error("This header can only be used when inspector is enabled") #endif +#include "platform/v8_inspector/public/V8Inspector.h" + // Forward declaration to break recursive dependency chain with src/env.h. namespace node { class Environment; @@ -23,6 +25,25 @@ namespace inspector { class AgentImpl; +class ContextInfo { + public: + explicit ContextInfo(v8::Local context, const int groupId, + const char* name) + : group_id_(groupId), + name_(name) { + context_.Reset(context->GetIsolate(), context); + } + inline v8::Local context(v8::Isolate* isolate) const { + return context_.Get(isolate); + } + int groupId() const { return group_id_; } + const char* name() const { return name_; } + private: + v8::Persistent context_; + const int group_id_; + const char* name_; +}; + class Agent { public: explicit Agent(node::Environment* env); @@ -33,6 +54,9 @@ class Agent { // Stop the inspector agent void Stop(); + void ContextCreated(const ContextInfo* info); + void ContextDestroyed(v8::Local context); + bool IsStarted(); bool IsConnected(); void WaitForDisconnect(); diff --git a/src/node_contextify.cc b/src/node_contextify.cc index d74b01ea0da371..29ad29947925d0 100644 --- a/src/node_contextify.cc +++ b/src/node_contextify.cc @@ -9,6 +9,10 @@ #include "util-inl.h" #include "v8-debug.h" +#if HAVE_INSPECTOR +#include "inspector_agent.h" +#endif + namespace node { using v8::Array; @@ -207,6 +211,10 @@ class ContextifyContext { object_template->SetHandler(config); Local ctx = Context::New(env->isolate(), nullptr, object_template); +#if HAVE_INSPECTOR + env->ContextCreated( + new node::inspector::ContextInfo(ctx, 1, "vm Module Context")); +#endif if (ctx.IsEmpty()) { env->ThrowError("Could not instantiate context"); @@ -323,6 +331,9 @@ class ContextifyContext { static void WeakCallback(const WeakCallbackInfo& data) { ContextifyContext* context = data.GetParameter(); +#if HAVE_INSPECTOR + context->env()->ContextDestroyed(context->context()); +#endif delete context; }