Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

inspector: support extra contexts when connected #13826

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions src/env-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,15 @@ inline void Environment::TickInfo::set_index(uint32_t value) {

inline void Environment::AssignToContext(v8::Local<v8::Context> context) {
context->SetAlignedPointerInEmbedderData(kContextEmbedderDataIndex, this);
#if HAVE_INSPECTOR
inspector_agent()->ContextCreated(context);
#endif // HAVE_INSPECTOR
}

inline void Environment::UnassignFromContext(v8::Local<v8::Context> context) {
#if HAVE_INSPECTOR
inspector_agent()->ContextDestroyed(context);
#endif // HAVE_INSPECTOR
}

inline Environment* Environment::GetCurrent(v8::Isolate* isolate) {
Expand Down
1 change: 1 addition & 0 deletions src/env.h
Original file line number Diff line number Diff line change
Expand Up @@ -530,6 +530,7 @@ class Environment {
const char* const* exec_argv,
bool start_profiler_idle_notifier);
void AssignToContext(v8::Local<v8::Context> context);
void UnassignFromContext(v8::Local<v8::Context> context);
void CleanupHandles();

void StartProfilerIdleNotifier();
Expand Down
32 changes: 31 additions & 1 deletion src/inspector_agent.cc
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@

#include "libplatform/libplatform.h"

#include <algorithm>
#include <string.h>
#include <sstream>
#include <vector>

#ifdef __POSIX__
Expand Down Expand Up @@ -539,7 +541,8 @@ class NodeInspectorClient : public v8_inspector::V8InspectorClient {
Agent::Agent(Environment* env) : parent_env_(env),
client_(nullptr),
platform_(nullptr),
enabled_(false) {}
enabled_(false),
next_context_number_(1) {}

// Destructor needs to be defined here in implementation file as the header
// does not have full definition of some classes.
Expand Down Expand Up @@ -606,6 +609,13 @@ bool Agent::StartIoThread(bool wait_for_connect) {
MakeCallback(parent_env_->isolate(), process_object, emit_fn.As<Function>(),
arraysize(argv), argv, 0, 0);

// Send contexts to inspector client that were created before connecting
for (auto const& context : contexts_) {
std::ostringstream name;
name << "VM Context " << next_context_number_++;
client_->contextCreated(context, name.str());
}

return true;
}

Expand Down Expand Up @@ -669,6 +679,26 @@ void Agent::PauseOnNextJavascriptStatement(const std::string& reason) {
channel->schedulePauseOnNextStatement(reason);
}

void Agent::ContextCreated(Local<Context> context) {
if (!IsStarted()) // This happens for a main context
return;
if (IsConnected()) {
std::ostringstream name;
name << "VM Context " << next_context_number_++;
client_->contextCreated(context, name.str());
}
contexts_.push_back(context);
}

void Agent::ContextDestroyed(Local<Context> context) {
CHECK_NE(client_, nullptr);
auto it = std::find(contexts_.begin(), contexts_.end(), context);
if (it != contexts_.end()) {
client_->contextDestroyed(context);
contexts_.erase(it);
}
}

void Open(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
inspector::Agent* agent = env->inspector_agent();
Expand Down
6 changes: 6 additions & 0 deletions src/inspector_agent.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#define SRC_INSPECTOR_AGENT_H_

#include <memory>
#include <vector>

#include <stddef.h>

Expand Down Expand Up @@ -79,6 +80,9 @@ class Agent {
bool enabled() { return enabled_; }
void PauseOnNextJavascriptStatement(const std::string& reason);

void ContextCreated(v8::Local<v8::Context> context);
void ContextDestroyed(v8::Local<v8::Context> context);

// Initialize 'inspector' module bindings
static void InitInspector(v8::Local<v8::Object> target,
v8::Local<v8::Value> unused,
Expand All @@ -105,6 +109,8 @@ class Agent {
bool enabled_;
std::string path_;
DebugOptions debug_options_;
std::vector<v8::Local<v8::Context>> contexts_;
int next_context_number_;
};

} // namespace inspector
Expand Down
2 changes: 2 additions & 0 deletions src/node_contextify.cc
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,8 @@ class ContextifyContext {

static void WeakCallback(const WeakCallbackInfo<ContextifyContext>& data) {
ContextifyContext* context = data.GetParameter();
context->env()->UnassignFromContext(context->context());

delete context;
}

Expand Down
47 changes: 47 additions & 0 deletions test/inspector/test-contexts.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
'use strict';
const common = require('../common');
common.skipIfInspectorDisabled();
const assert = require('assert');
const helper = require('./inspector-helper.js');

function setupExpectBreakInContext() {
return function(message) {
if ('Debugger.paused' === message['method']) {
const callFrame = message['params']['callFrames'][0];
assert.strictEqual(callFrame['functionName'], 'testfn');
return true;
}
};
}

function testBreakpointInContext(session) {
console.log('[test]',
'Verifying debugger stops on start (--inspect-brk option)');
const commands = [
{ 'method': 'Runtime.enable' },
{ 'method': 'Debugger.enable' },
{ 'method': 'Runtime.runIfWaitingForDebugger' }
];
session
.sendInspectorCommands(commands)
.expectMessages(setupExpectBreakInContext());
}

function resume(session) {
session
.sendInspectorCommands({ 'method': 'Debugger.resume'})
.disconnect(true);
}

function runTests(harness) {
harness
.runFrontendSession([
testBreakpointInContext,
resume,
]).expectShutDown(0);
}

const script = 'require("vm").runInNewContext(' +
'"function testfn() {debugger};testfn();")';

helper.startNodeForInspectorTest(runTests, '--inspect-brk', script);