diff --git a/lib/internal/inspect_repl.js b/lib/internal/inspect_repl.js index 985df0d..d9d3f89 100644 --- a/lib/internal/inspect_repl.js +++ b/lib/internal/inspect_repl.js @@ -25,6 +25,7 @@ const Path = require('path'); const Repl = require('repl'); const util = require('util'); const vm = require('vm'); +const fileURLToPath = require('url').fileURLToPath; const debuglog = util.debuglog('inspect'); @@ -89,9 +90,12 @@ function isNativeUrl(url) { return url.replace('.js', '') in NATIVES || url === 'bootstrap_node.js'; } -function getRelativePath(filename) { +function getRelativePath(filenameOrURL) { const dir = Path.join(Path.resolve(), 'x').slice(0, -1); + const filename = filenameOrURL.startsWith('file://') ? + fileURLToPath(filenameOrURL) : filenameOrURL; + // Change path to relative, if possible if (filename.indexOf(dir) === 0) { return filename.slice(dir.length); diff --git a/test/cli/break.test.js b/test/cli/break.test.js index ce8c8d6..ff71a36 100644 --- a/test/cli/break.test.js +++ b/test/cli/break.test.js @@ -18,12 +18,12 @@ test('stepping through breakpoints', (t) => { .then(() => cli.waitForPrompt()) .then(() => { t.match( - cli.output, - `break in ${script}:1`, + cli.breakInfo, + { filename: script, line: 1 }, 'pauses in the first line of the script'); t.match( cli.output, - /> 1 \(function \([^)]+\) \{ const x = 10;/, + /> 1 (?:\(function \([^)]+\) \{ )?const x = 10;/, 'shows the source and marks the current line'); }) .then(() => cli.stepCommand('n')) diff --git a/test/cli/exceptions.test.js b/test/cli/exceptions.test.js index 18b7f18..69d42d0 100644 --- a/test/cli/exceptions.test.js +++ b/test/cli/exceptions.test.js @@ -17,7 +17,7 @@ test('break on (uncaught) exceptions', (t) => { return cli.waitForInitialBreak() .then(() => cli.waitForPrompt()) .then(() => { - t.match(cli.output, `break in ${script}:1`); + t.match(cli.breakInfo, { filename: script, line: 1 }); }) // making sure it will die by default: .then(() => cli.command('c')) @@ -28,7 +28,7 @@ test('break on (uncaught) exceptions', (t) => { .then(() => cli.stepCommand('r')) .then(() => cli.waitForInitialBreak()) .then(() => { - t.match(cli.output, `break in ${script}:1`); + t.match(cli.breakInfo, { filename: script, line: 1 }); }) .then(() => cli.command('breakOnException')) .then(() => cli.stepCommand('c')) @@ -45,7 +45,7 @@ test('break on (uncaught) exceptions', (t) => { .then(() => cli.stepCommand('r')) // also, the setting survives the restart .then(() => cli.waitForInitialBreak()) .then(() => { - t.match(cli.output, `break in ${script}:1`); + t.match(cli.breakInfo, { filename: script, line: 1 }); }) .then(() => cli.stepCommand('c')) .then(() => { @@ -57,7 +57,7 @@ test('break on (uncaught) exceptions', (t) => { .then(() => cli.stepCommand('r')) .then(() => cli.waitForInitialBreak()) .then(() => { - t.match(cli.output, `break in ${script}:1`); + t.match(cli.breakInfo, { filename: script, line: 1 }); }) .then(() => cli.command('c')) // TODO: Remove FATAL ERROR once node doesn't show a FATAL ERROR anymore diff --git a/test/cli/launch.test.js b/test/cli/launch.test.js index 8808d47..087a46c 100644 --- a/test/cli/launch.test.js +++ b/test/cli/launch.test.js @@ -137,23 +137,23 @@ test('run after quit / restart', (t) => { .then(() => cli.waitForPrompt()) .then(() => { t.match( - cli.output, - `break in ${script}:1`, + cli.breakInfo, + { filename: script, line: 1 }, 'is back at the beginning'); }) .then(() => cli.stepCommand('n')) .then(() => { t.match( - cli.output, - `break in ${script}:2`, + cli.breakInfo, + { filename: script, line: 2 }, 'steps to the 2nd line'); }) .then(() => cli.stepCommand('restart')) .then(() => cli.waitForInitialBreak()) .then(() => { t.match( - cli.output, - `break in ${script}:1`, + cli.breakInfo, + { filename: script, line: 1 }, 'is back at the beginning'); }) .then(() => cli.command('kill')) @@ -167,8 +167,8 @@ test('run after quit / restart', (t) => { .then(() => cli.waitForPrompt()) .then(() => { t.match( - cli.output, - `break in ${script}:1`, + cli.breakInfo, + { filename: script, line: 1 }, 'is back at the beginning'); }) .then(() => cli.quit()) diff --git a/test/cli/low-level.test.js b/test/cli/low-level.test.js index 77e3fc2..2a41359 100644 --- a/test/cli/low-level.test.js +++ b/test/cli/low-level.test.js @@ -24,7 +24,7 @@ test('Debugger agent direct access', (t) => { .then(() => { t.match( cli.output, - /scriptSource: '\(function \(/); + /scriptSource:[ \n]*'(?:\(function \(|let x = 1)/); t.match( cli.output, /let x = 1;/); diff --git a/test/cli/preserve-breaks.test.js b/test/cli/preserve-breaks.test.js index 94f6140..affa3ad 100644 --- a/test/cli/preserve-breaks.test.js +++ b/test/cli/preserve-breaks.test.js @@ -30,20 +30,20 @@ test('run after quit / restart', (t) => { .then(() => cli.stepCommand('c')) // hit line 2 .then(() => cli.stepCommand('c')) // hit line 3 .then(() => { - t.match(cli.output, `break in ${script}:3`); + t.match(cli.breakInfo, { filename: script, line: 3 }); }) .then(() => cli.command('restart')) .then(() => cli.waitForInitialBreak()) .then(() => { - t.match(cli.output, `break in ${script}:1`); + t.match(cli.breakInfo, { filename: script, line: 1 }); }) .then(() => cli.stepCommand('c')) .then(() => { - t.match(cli.output, `break in ${script}:2`); + t.match(cli.breakInfo, { filename: script, line: 2 }); }) .then(() => cli.stepCommand('c')) .then(() => { - t.match(cli.output, `break in ${script}:3`); + t.match(cli.breakInfo, { filename: script, line: 3 }); }) .then(() => cli.command('breakpoints')) .then(() => { diff --git a/test/cli/scripts.test.js b/test/cli/scripts.test.js index 1546b80..f6e3f30 100644 --- a/test/cli/scripts.test.js +++ b/test/cli/scripts.test.js @@ -24,7 +24,7 @@ test('list scripts', (t) => { 'lists the user script'); t.notMatch( cli.output, - /\d+: module\.js /, + /\d+: buffer\.js /, 'omits node-internal scripts'); }) .then(() => cli.command('scripts(true)')) @@ -35,7 +35,7 @@ test('list scripts', (t) => { 'lists the user script'); t.match( cli.output, - /\d+: module\.js /, + /\d+: buffer\.js /, 'includes node-internal scripts'); }) .then(() => cli.quit()) diff --git a/test/cli/start-cli.js b/test/cli/start-cli.js index b086dcd..e2fa5fe 100644 --- a/test/cli/start-cli.js +++ b/test/cli/start-cli.js @@ -16,6 +16,10 @@ const BREAK_MESSAGE = new RegExp('(?:' + [ 'exception', 'other', 'promiseRejection', ].join('|') + ') in', 'i'); +function isPreBreak(output) { + return /Break on start/.test(output) && /1 \(function \(exports/.test(output); +} + function startCLI(args, flags = []) { const child = spawn(process.execPath, [...flags, CLI, ...args]); let isFirstStdoutChunk = true; @@ -101,13 +105,25 @@ function startCLI(args, flags = []) { waitForInitialBreak(timeout = 2000) { return this.waitFor(/break (?:on start )?in/i, timeout) .then(() => { - if (/Break on start/.test(this.output)) { + if (isPreBreak(this.output)) { return this.command('next', false) .then(() => this.waitFor(/break in/, timeout)); } }); }, + get breakInfo() { + const output = this.output; + const breakMatch = + output.match(/break (?:on start )?in ([^\n]+):(\d+)\n/i); + + if (breakMatch === null) { + throw new Error( + `Could not find breakpoint info in ${JSON.stringify(output)}`); + } + return { filename: breakMatch[1], line: +breakMatch[2] }; + }, + ctrlC() { return this.command('.interrupt'); }, @@ -127,19 +143,24 @@ function startCLI(args, flags = []) { .map((match) => +match[1]); }, - command(input, flush = true) { + writeLine(input, flush = true) { if (flush) { this.flushOutput(); } + if (process.env.VERBOSE === '1') { + process.stderr.write(`< ${input}\n`); + } child.stdin.write(input); child.stdin.write('\n'); + }, + + command(input, flush = true) { + this.writeLine(input, flush); return this.waitForPrompt(); }, stepCommand(input) { - this.flushOutput(); - child.stdin.write(input); - child.stdin.write('\n'); + this.writeLine(input, true); return this .waitFor(BREAK_MESSAGE) .then(() => this.waitForPrompt()); diff --git a/test/cli/use-strict.test.js b/test/cli/use-strict.test.js index 780802a..c6dc8f3 100644 --- a/test/cli/use-strict.test.js +++ b/test/cli/use-strict.test.js @@ -17,9 +17,10 @@ test('for whiles that starts with strict directive', (t) => { return cli.waitForInitialBreak() .then(() => cli.waitForPrompt()) .then(() => { + const brk = cli.breakInfo; t.match( - cli.output, - /break in [^:]+:(?:1|2)[^\d]/, + `${brk.line}`, + /^(1|2)$/, 'pauses either on strict directive or first "real" line'); }) .then(() => cli.quit())