mirror of
https://github.com/nodejs/node.git
synced 2024-11-21 10:59:27 +00:00
0161ad0baf
`NodeRuntime.waitingForDebugger` is a new Inspector Protocol event that will fire when the process being inspected is waiting for the debugger (for example, when `inspector.waitForDebugger()` is called). This allows inspecting processes to know when the inspected process is waiting for a `Runtime.runIfWaitingForDebugger` message to resume execution. It allows tooling to resume execution of the inspected process as soon as it deems necessary, without having to guess if the inspected process is waiting or not, making the workflow more deterministic. With a more deterministic workflow, it is possible to update Node.js core tests to avoid race conditions that can cause flakiness. Therefore, tests were also changed as following: * Remove no-op Runtime.runIfWaitingForDebugger from tests that don't need it * Use NodeRuntime.waitingForDebugger in all tests that need Runtime.runIfWaitingForDebugger, to ensure order of operations is predictable and correct * Simplify test-inspector-multisession-ws There might be value in adding `NodeWorker.waitingForDebugger` in a future patch, but as of right now, no Node.js core inspector tests using worker threads are not failing due to race conditions. Fixes: https://github.com/nodejs/node/issues/34730 PR-URL: https://github.com/nodejs/node/pull/51560 Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: Franziska Hinkelmann <franziska.hinkelmann@gmail.com> Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
79 lines
3.2 KiB
JavaScript
79 lines
3.2 KiB
JavaScript
'use strict';
|
|
const common = require('../common');
|
|
|
|
common.skipIfInspectorDisabled();
|
|
|
|
const assert = require('assert');
|
|
const { NodeInstance } = require('../common/inspector-helper.js');
|
|
|
|
async function runTests() {
|
|
const child = new NodeInstance(['-e', `(${main.toString()})()`], '', '');
|
|
const session = await child.connectInspectorSession();
|
|
await session.send({ method: 'Runtime.enable' });
|
|
// Check that there is only one console message received.
|
|
await session.waitForConsoleOutput('log', 'before wait for debugger');
|
|
assert.ok(!session.unprocessedNotifications()
|
|
.some((n) => n.method === 'Runtime.consoleAPICalled'));
|
|
// Check that inspector.url() is available between inspector.open() and
|
|
// inspector.waitForDebugger()
|
|
const { result: { value } } = await session.send({
|
|
method: 'Runtime.evaluate',
|
|
params: {
|
|
expression: 'process._ws',
|
|
includeCommandLineAPI: true
|
|
}
|
|
});
|
|
assert.ok(value.startsWith('ws://'));
|
|
await session.send({ method: 'NodeRuntime.enable' });
|
|
child.write('first');
|
|
await session.waitForNotification('NodeRuntime.waitingForDebugger');
|
|
await session.send({ method: 'Runtime.runIfWaitingForDebugger' });
|
|
await session.send({ method: 'NodeRuntime.disable' });
|
|
// Check that messages after first and before second waitForDebugger are
|
|
// received
|
|
await session.waitForConsoleOutput('log', 'after wait for debugger');
|
|
await session.waitForConsoleOutput('log', 'before second wait for debugger');
|
|
assert.ok(!session.unprocessedNotifications()
|
|
.some((n) => n.method === 'Runtime.consoleAPICalled'));
|
|
const secondSession = await child.connectInspectorSession();
|
|
// Check that inspector.waitForDebugger can be resumed from another session
|
|
await session.send({ method: 'NodeRuntime.enable' });
|
|
child.write('second');
|
|
await session.waitForNotification('NodeRuntime.waitingForDebugger');
|
|
await session.send({ method: 'Runtime.runIfWaitingForDebugger' });
|
|
await session.send({ method: 'NodeRuntime.disable' });
|
|
await session.waitForConsoleOutput('log', 'after second wait for debugger');
|
|
assert.ok(!session.unprocessedNotifications()
|
|
.some((n) => n.method === 'Runtime.consoleAPICalled'));
|
|
secondSession.disconnect();
|
|
session.disconnect();
|
|
|
|
function main(prefix) {
|
|
const inspector = require('inspector');
|
|
inspector.open(0, undefined, false);
|
|
process._ws = inspector.url();
|
|
console.log('before wait for debugger');
|
|
process.stdin.once('data', (data) => {
|
|
if (data.toString() === 'first') {
|
|
inspector.waitForDebugger();
|
|
console.log('after wait for debugger');
|
|
console.log('before second wait for debugger');
|
|
process.stdin.once('data', (data) => {
|
|
if (data.toString() === 'second') {
|
|
inspector.waitForDebugger();
|
|
console.log('after second wait for debugger');
|
|
process.exit();
|
|
}
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
// Check that inspector.waitForDebugger throws if there is no active
|
|
// inspector
|
|
const re = /^Error \[ERR_INSPECTOR_NOT_ACTIVE\]: Inspector is not active$/;
|
|
assert.throws(() => require('inspector').waitForDebugger(), re);
|
|
}
|
|
|
|
runTests().then(common.mustCall());
|