diff --git a/lib/internal/debugger/inspect_probe.js b/lib/internal/debugger/inspect_probe.js index c7c2d4627e4ae2..e7abc2e48cd365 100644 --- a/lib/internal/debugger/inspect_probe.js +++ b/lib/internal/debugger/inspect_probe.js @@ -624,6 +624,10 @@ class ProbeInspectorSession { async handlePaused(params) { if (this.finished) { return; } + // Ignore pauses that arrive before breakpoint setup is complete. Once + // startup is marked complete, `Runtime.runIfWaitingForDebugger` may surface + // the initial --inspect-brk pause, which the normal resume path handles. + if (!this.started) { return; } const hitBreakpoints = params.hitBreakpoints; if (hitBreakpoints === undefined || hitBreakpoints.length === 0) { @@ -1025,5 +1029,6 @@ async function runProbeMode(stdout, probeOptions) { module.exports = { parseProbeTokens, + ProbeInspectorSession, runProbeMode, }; diff --git a/test/parallel/test-debugger-probe-startup-pause.js b/test/parallel/test-debugger-probe-startup-pause.js new file mode 100644 index 00000000000000..917026bf13fe0f --- /dev/null +++ b/test/parallel/test-debugger-probe-startup-pause.js @@ -0,0 +1,32 @@ +// Flags: --expose-internals +// This tests that probe mode ignores pauses until startup has finished binding +// breakpoints. +'use strict'; + +const common = require('../common'); +common.skipIfInspectorDisabled(); + +const assert = require('assert'); +const { ProbeInspectorSession } = require('internal/debugger/inspect_probe'); + +const session = new ProbeInspectorSession({ + probes: [], +}); + +const cdpCalls = []; +session.client = { + callMethod: common.mustCall(async (method) => { + cdpCalls.push(method); + }), +}; + +async function testStartupPauseHandling() { + await session.handlePaused({}); + assert.deepStrictEqual(cdpCalls, []); + + session.started = true; + await session.handlePaused({}); + assert.deepStrictEqual(cdpCalls, ['Debugger.resume']); +} + +testStartupPauseHandling().then(common.mustCall());