Skip to content
Open
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
12 changes: 7 additions & 5 deletions lib/internal/debugger/inspect_repl.js
Original file line number Diff line number Diff line change
Expand Up @@ -945,6 +945,11 @@ function createRepl(inspector) {
);
});

async function runAndInit() {
await inspector.run();
await initAfterStart();
}

function initializeContext(context) {
ArrayPrototypeForEach(inspector.domainNames, (domain) => {
ObjectDefineProperty(context, domain, {
Expand All @@ -962,15 +967,15 @@ function createRepl(inspector) {
},

get run() {
return inspector.run();
return runAndInit();
},

get kill() {
return inspector.killChild();
},

get restart() {
return inspector.run();
return runAndInit();
},

get cont() {
Expand Down Expand Up @@ -1196,9 +1201,6 @@ function createRepl(inspector) {
inspector.client.on('close', () => {
resetOnStart();
});
inspector.client.on('ready', () => {
initAfterStart();
});

// Init once for the initial connection
await initAfterStart();
Expand Down
119 changes: 119 additions & 0 deletions test/parallel/test-debugger-run-restart-init.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
// Flags: --expose-internals
'use strict';

const common = require('../common');

common.skipIfInspectorDisabled();

const assert = require('assert');
const { EventEmitter } = require('events');
const { PassThrough } = require('stream');
const createRepl = require('internal/debugger/inspect_repl');

function createGate() {
let resolve;
const promise = new Promise((res) => {
resolve = res;
});
return { promise, resolve };
}

function createAgent(domain, calls, gates) {
const agent = new EventEmitter();
const method = (name) => async () => {
calls.push(`${domain}.${name}`);
if (domain === 'Runtime' && name === 'runIfWaitingForDebugger') {
const gate = gates.shift();
if (gate) {
await gate.promise;
}
}
};

agent.enable = method('enable');
agent.setSamplingInterval = method('setSamplingInterval');
agent.setAsyncCallStackDepth = method('setAsyncCallStackDepth');
agent.setBlackboxPatterns = method('setBlackboxPatterns');
agent.setPauseOnExceptions = method('setPauseOnExceptions');
agent.runIfWaitingForDebugger = method('runIfWaitingForDebugger');
return agent;
}

function evalCommand(repl, command) {
return new Promise((resolve, reject) => {
repl.eval(
command,
repl.context,
'debugger-repl-test',
(error, result) => {
if (error) {
reject(error);
} else {
resolve(result);
}
},
);
});
}

async function assertCommandWaitsForInit(repl, command, gate, calls) {
let settled = false;
const promise = evalCommand(repl, command).then(() => {
settled = true;
});

await new Promise(setImmediate);
assert.strictEqual(
settled,
false,
`${command} resolved before post-connect initialization completed: ${calls}`,
);

gate.resolve();
await promise;
assert.strictEqual(settled, true);
}

(async () => {
const calls = [];
const runGate = createGate();
const restartGate = createGate();
const gates = [null, runGate, restartGate];
const inspector = {
client: new EventEmitter(),
domainNames: ['Debugger', 'HeapProfiler', 'Profiler', 'Runtime'],
stdin: new PassThrough(),
stdout: new PassThrough(),
run: common.mustCall(async () => {
calls.push('inspector.run');
}, 2),
suspendReplWhile(fn) {
return fn();
},
};

for (const domain of inspector.domainNames) {
inspector[domain] = createAgent(domain, calls, gates);
}

const repl = await createRepl(inspector)();

await assertCommandWaitsForInit(repl, 'run', runGate, calls);
await assertCommandWaitsForInit(repl, 'restart', restartGate, calls);

assert.deepStrictEqual(
calls.filter((call) => (
call === 'inspector.run' ||
call === 'Runtime.runIfWaitingForDebugger'
)),
[
'Runtime.runIfWaitingForDebugger',
'inspector.run',
'Runtime.runIfWaitingForDebugger',
'inspector.run',
'Runtime.runIfWaitingForDebugger',
],
);

repl.close();
})().then(common.mustCall());
Loading