From f64c9205bd8382289660aa677d3ac192a9c81fd5 Mon Sep 17 00:00:00 2001 From: Josh Gavant Date: Mon, 27 Mar 2017 17:14:00 -0700 Subject: [PATCH 01/12] doc: add profile and heap to help --- lib/internal/inspect_repl.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lib/internal/inspect_repl.js b/lib/internal/inspect_repl.js index 2de86b2..937c184 100644 --- a/lib/internal/inspect_repl.js +++ b/lib/internal/inspect_repl.js @@ -67,6 +67,15 @@ repl Enter a debug repl that works like exec scripts List application scripts that are currently loaded scripts(true) List all scripts (including node-internals) + +profile Start CPU profiling session. +profileEnd Stop current CPU profiling session. +profiles Array of completed CPU profiling sessions. +profiles[n].save(filepath = 'node.cpuprofile') + Save CPU profiling session to disk as JSON. + +takeHeapSnapshot(filepath = 'node.heapsnapshot') + Take a heap snapshot and save to disk as JSON. `.trim(); const FUNCTION_NAME_PATTERN = /^(?:function\*? )?([^(\s]+)\(/; From 41148d74a2d563eea3b7ad5463622b6b9fd4c46e Mon Sep 17 00:00:00 2001 From: Jan Krems Date: Wed, 15 Mar 2017 12:11:13 -0700 Subject: [PATCH 02/12] test: Remove outdated test --- package.json | 2 +- test/cli/start-cli.js | 5 +++++ test/node-inspect.test.js | 9 --------- 3 files changed, 6 insertions(+), 10 deletions(-) delete mode 100644 test/node-inspect.test.js diff --git a/package.json b/package.json index 536a525..1834956 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ }, "scripts": { "pretest": "eslint --rulesdir=tools/eslint-rules lib test", - "test": "tap \"test/**/*.test.js\"", + "test": "tap test", "posttest": "nlm verify" }, "nlm": { diff --git a/test/cli/start-cli.js b/test/cli/start-cli.js index 267aac5..5a652e3 100644 --- a/test/cli/start-cli.js +++ b/test/cli/start-cli.js @@ -1,6 +1,11 @@ 'use strict'; const spawn = require('child_process').spawn; +// This allows us to keep the helper inside of `test/` without tap warning +// about "pending" test files. +const tap = require('tap'); +tap.test('startCLI', (t) => t.end()); + const CLI = process.env.USE_EMBEDDED_NODE_INSPECT === '1' ? 'inspect' : diff --git a/test/node-inspect.test.js b/test/node-inspect.test.js deleted file mode 100644 index 12e7313..0000000 --- a/test/node-inspect.test.js +++ /dev/null @@ -1,9 +0,0 @@ -'use strict'; -const tap = require('tap'); - -const nodeInspect = require('../'); - -tap.equal( - 9229, - nodeInspect.port, - 'Uses the --inspect default port'); From 2c224c551619e386e80fc3154cc14562cac063b9 Mon Sep 17 00:00:00 2001 From: Jan Krems Date: Mon, 3 Apr 2017 13:04:01 -0700 Subject: [PATCH 03/12] test: Accept any kind of "break" --- test/cli/backtrace.test.js | 2 +- test/cli/break.test.js | 24 ++++++++++++------------ test/cli/exceptions.test.js | 10 +++++----- test/cli/exec.test.js | 4 ++-- test/cli/help.test.js | 2 +- test/cli/launch.test.js | 4 ++-- test/cli/low-level.test.js | 2 +- test/cli/preserve-breaks.test.js | 2 +- test/cli/profile.test.js | 2 +- test/cli/scripts.test.js | 2 +- test/cli/start-cli.js | 4 ++++ test/cli/use-strict.test.js | 2 +- test/cli/watchers.test.js | 2 +- 13 files changed, 33 insertions(+), 29 deletions(-) diff --git a/test/cli/backtrace.test.js b/test/cli/backtrace.test.js index 9cd8a82..127ea56 100644 --- a/test/cli/backtrace.test.js +++ b/test/cli/backtrace.test.js @@ -14,7 +14,7 @@ test('display and navigate backtrace', (t) => { throw error; } - return cli.waitFor(/break/) + return cli.waitForInitialBreak() .then(() => cli.waitForPrompt()) .then(() => cli.stepCommand('c')) .then(() => cli.command('bt')) diff --git a/test/cli/break.test.js b/test/cli/break.test.js index 1c662d6..5de3e52 100644 --- a/test/cli/break.test.js +++ b/test/cli/break.test.js @@ -14,12 +14,12 @@ test('stepping through breakpoints', (t) => { throw error; } - return cli.waitFor(/break/) + return cli.waitForInitialBreak() .then(() => cli.waitForPrompt()) .then(() => { t.match( cli.output, - `break in ${script}:1`, + ` in ${script}:1`, 'pauses in the first line of the script'); t.match( cli.output, @@ -30,7 +30,7 @@ test('stepping through breakpoints', (t) => { .then(() => { t.match( cli.output, - `break in ${script}:2`, + ` in ${script}:2`, 'pauses in next line of the script'); t.match( cli.output, @@ -41,7 +41,7 @@ test('stepping through breakpoints', (t) => { .then(() => { t.match( cli.output, - `break in ${script}:3`, + ` in ${script}:3`, 'pauses in next line of the script'); t.match( cli.output, @@ -52,7 +52,7 @@ test('stepping through breakpoints', (t) => { .then(() => { t.match( cli.output, - `break in ${script}:10`, + ` in ${script}:10`, 'pauses on the next breakpoint'); t.match( cli.output, @@ -94,21 +94,21 @@ test('stepping through breakpoints', (t) => { .then(() => { t.match( cli.output, - 'break in timers.js', + ' in timers.js', 'entered timers.js'); }) .then(() => cli.stepCommand('cont')) .then(() => { t.match( cli.output, - `break in ${script}:16`, + ` in ${script}:16`, 'found breakpoint we set above w/ line number only'); }) .then(() => cli.stepCommand('cont')) .then(() => { t.match( cli.output, - `break in ${script}:6`, + ` in ${script}:6`, 'found breakpoint we set above w/ line number & script'); }) .then(() => cli.stepCommand('')) @@ -132,7 +132,7 @@ test('sb before loading file', (t) => { throw error; } - return cli.waitFor(/break/) + return cli.waitForInitialBreak() .then(() => cli.waitForPrompt()) .then(() => cli.command('sb("other.js", 3)')) .then(() => { @@ -145,7 +145,7 @@ test('sb before loading file', (t) => { .then(() => { t.match( cli.output, - `break in ${otherScript}:3`, + ` in ${otherScript}:3`, 'found breakpoint in file that was not loaded yet'); }) .then(() => cli.quit()) @@ -161,7 +161,7 @@ test('clearBreakpoint', (t) => { throw error; } - return cli.waitFor(/break/) + return cli.waitForInitialBreak() .then(() => cli.waitForPrompt()) .then(() => cli.command('sb("break.js", 3)')) .then(() => cli.command('sb("break.js", 9)')) @@ -187,7 +187,7 @@ test('clearBreakpoint', (t) => { .then(() => { t.match( cli.output, - `break in ${script}:9`, + ` in ${script}:9`, 'hits the 2nd breakpoint because the 1st was cleared'); }) .then(() => cli.quit()) diff --git a/test/cli/exceptions.test.js b/test/cli/exceptions.test.js index b66c09f..5a9f814 100644 --- a/test/cli/exceptions.test.js +++ b/test/cli/exceptions.test.js @@ -14,10 +14,10 @@ test('break on (uncaught) exceptions', (t) => { throw error; } - return cli.waitFor(/break/) + return cli.waitForInitialBreak() .then(() => cli.waitForPrompt()) .then(() => { - t.match(cli.output, `break in ${script}:1`); + t.match(cli.output, ` in ${script}:1`); }) // making sure it will die by default: .then(() => cli.command('c')) @@ -26,7 +26,7 @@ test('break on (uncaught) exceptions', (t) => { // Next run: With `breakOnException` it pauses in both places .then(() => cli.stepCommand('r')) .then(() => { - t.match(cli.output, `break in ${script}:1`); + t.match(cli.output, ` in ${script}:1`); }) .then(() => cli.command('breakOnException')) .then(() => cli.stepCommand('c')) @@ -42,7 +42,7 @@ test('break on (uncaught) exceptions', (t) => { .then(() => cli.command('breakOnUncaught')) .then(() => cli.stepCommand('r')) // also, the setting survives the restart .then(() => { - t.match(cli.output, `break in ${script}:1`); + t.match(cli.output, ` in ${script}:1`); }) .then(() => cli.stepCommand('c')) .then(() => { @@ -53,7 +53,7 @@ test('break on (uncaught) exceptions', (t) => { .then(() => cli.command('breakOnNone')) .then(() => cli.stepCommand('r')) .then(() => { - t.match(cli.output, `break in ${script}:1`); + t.match(cli.output, ` in ${script}:1`); }) .then(() => cli.command('c')) .then(() => cli.waitFor(/disconnect/)) diff --git a/test/cli/exec.test.js b/test/cli/exec.test.js index 5c64713..acfd6e3 100644 --- a/test/cli/exec.test.js +++ b/test/cli/exec.test.js @@ -11,7 +11,7 @@ test('examples/alive.js', (t) => { throw error; } - return cli.waitFor(/break/) + return cli.waitForInitialBreak() .then(() => cli.waitForPrompt()) .then(() => cli.command('exec [typeof heartbeat, typeof process.exit]')) .then(() => { @@ -60,7 +60,7 @@ test('exec .scope', (t) => { throw error; } - return cli.waitFor(/break/) + return cli.waitForInitialBreak() .then(() => cli.waitForPrompt()) .then(() => cli.stepCommand('c')) .then(() => cli.command('exec .scope')) diff --git a/test/cli/help.test.js b/test/cli/help.test.js index 11a9358..9f0c081 100644 --- a/test/cli/help.test.js +++ b/test/cli/help.test.js @@ -11,7 +11,7 @@ test('examples/empty.js', (t) => { throw error; } - return cli.waitFor(/break/) + return cli.waitForInitialBreak() .then(() => cli.waitForPrompt()) .then(() => cli.command('help')) .then(() => { diff --git a/test/cli/launch.test.js b/test/cli/launch.test.js index 99c6ce0..0af27b1 100644 --- a/test/cli/launch.test.js +++ b/test/cli/launch.test.js @@ -9,7 +9,7 @@ test('examples/empty.js', (t) => { const script = Path.join('examples', 'empty.js'); const cli = startCLI([script]); - return cli.waitFor(/break/) + return cli.waitForInitialBreak() .then(() => cli.waitForPrompt()) .then(() => { t.match(cli.output, 'debug>', 'prints a prompt'); @@ -45,7 +45,7 @@ test('run after quit / restart', (t) => { throw error; } - return cli.waitFor(/break/) + return cli.waitForInitialBreak() .then(() => cli.waitForPrompt()) .then(() => cli.stepCommand('n')) .then(() => { diff --git a/test/cli/low-level.test.js b/test/cli/low-level.test.js index b6301b2..966bed5 100644 --- a/test/cli/low-level.test.js +++ b/test/cli/low-level.test.js @@ -12,7 +12,7 @@ test('Debugger agent direct access', (t) => { throw error; } - return cli.waitFor(/break/) + return cli.waitForInitialBreak() .then(() => cli.waitForPrompt()) .then(() => cli.command('scripts')) .then(() => { diff --git a/test/cli/preserve-breaks.test.js b/test/cli/preserve-breaks.test.js index 8de8227..17d7976 100644 --- a/test/cli/preserve-breaks.test.js +++ b/test/cli/preserve-breaks.test.js @@ -14,7 +14,7 @@ test('run after quit / restart', (t) => { throw error; } - return cli.waitFor(/break/) + return cli.waitForInitialBreak() .then(() => cli.waitForPrompt()) .then(() => cli.command('breakpoints')) .then(() => { diff --git a/test/cli/profile.test.js b/test/cli/profile.test.js index 3ef1896..0f900c5 100644 --- a/test/cli/profile.test.js +++ b/test/cli/profile.test.js @@ -15,7 +15,7 @@ test('profiles', (t) => { throw error; } - return cli.waitFor(/break/) + return cli.waitForInitialBreak() .then(() => cli.waitForPrompt()) .then(() => cli.command('exec console.profile()')) .then(() => { diff --git a/test/cli/scripts.test.js b/test/cli/scripts.test.js index cd26411..ed36705 100644 --- a/test/cli/scripts.test.js +++ b/test/cli/scripts.test.js @@ -14,7 +14,7 @@ test('list scripts', (t) => { throw error; } - return cli.waitFor(/break/) + return cli.waitForInitialBreak() .then(() => cli.waitForPrompt()) .then(() => cli.command('scripts')) .then(() => { diff --git a/test/cli/start-cli.js b/test/cli/start-cli.js index 5a652e3..74c9481 100644 --- a/test/cli/start-cli.js +++ b/test/cli/start-cli.js @@ -93,6 +93,10 @@ function startCLI(args) { return this.waitFor(/>\s+$/, timeout); }, + waitForInitialBreak(timeout = 2000) { + return this.waitFor(/break/i, timeout); + }, + ctrlC() { return this.command('.interrupt'); }, diff --git a/test/cli/use-strict.test.js b/test/cli/use-strict.test.js index 81f4d91..780802a 100644 --- a/test/cli/use-strict.test.js +++ b/test/cli/use-strict.test.js @@ -14,7 +14,7 @@ test('for whiles that starts with strict directive', (t) => { throw error; } - return cli.waitFor(/break/) + return cli.waitForInitialBreak() .then(() => cli.waitForPrompt()) .then(() => { t.match( diff --git a/test/cli/watchers.test.js b/test/cli/watchers.test.js index d66f008..46bcde1 100644 --- a/test/cli/watchers.test.js +++ b/test/cli/watchers.test.js @@ -11,7 +11,7 @@ test('stepping through breakpoints', (t) => { throw error; } - return cli.waitFor(/break/) + return cli.waitForInitialBreak() .then(() => cli.waitForPrompt()) .then(() => cli.command('watch("x")')) .then(() => cli.command('watch("\\"Hello\\"")')) From 22bf349bc86d7bf6fd449791c9d1e7eaf66c2681 Mon Sep 17 00:00:00 2001 From: Jan Krems Date: Mon, 3 Apr 2017 13:47:31 -0700 Subject: [PATCH 04/12] test: Adjust for v8 5.7 --- test/cli/exceptions.test.js | 6 ++++-- test/cli/launch.test.js | 11 +++++------ test/cli/low-level.test.js | 9 ++++++--- test/cli/preserve-breaks.test.js | 3 +-- test/cli/scripts.test.js | 6 +++--- test/cli/start-cli.js | 17 +++++++++++++---- 6 files changed, 32 insertions(+), 20 deletions(-) diff --git a/test/cli/exceptions.test.js b/test/cli/exceptions.test.js index 5a9f814..338c937 100644 --- a/test/cli/exceptions.test.js +++ b/test/cli/exceptions.test.js @@ -21,7 +21,8 @@ test('break on (uncaught) exceptions', (t) => { }) // making sure it will die by default: .then(() => cli.command('c')) - .then(() => cli.waitFor(/disconnect/)) + // TODO: Remove FATAL ERROR once node doesn't show a FATAL ERROR anymore + .then(() => cli.waitFor(/disconnect|FATAL ERROR/)) // Next run: With `breakOnException` it pauses in both places .then(() => cli.stepCommand('r')) @@ -56,7 +57,8 @@ test('break on (uncaught) exceptions', (t) => { t.match(cli.output, ` in ${script}:1`); }) .then(() => cli.command('c')) - .then(() => cli.waitFor(/disconnect/)) + // TODO: Remove FATAL ERROR once node doesn't show a FATAL ERROR anymore + .then(() => cli.waitFor(/disconnect|FATAL ERROR/)) .then(() => cli.quit()) .then(null, onFatal); diff --git a/test/cli/launch.test.js b/test/cli/launch.test.js index 0af27b1..b57c08a 100644 --- a/test/cli/launch.test.js +++ b/test/cli/launch.test.js @@ -5,18 +5,14 @@ const { test } = require('tap'); const startCLI = require('./start-cli'); -test('examples/empty.js', (t) => { - const script = Path.join('examples', 'empty.js'); +test('examples/three-lines.js', (t) => { + const script = Path.join('examples', 'three-lines.js'); const cli = startCLI([script]); return cli.waitForInitialBreak() .then(() => cli.waitForPrompt()) .then(() => { t.match(cli.output, 'debug>', 'prints a prompt'); - t.match( - cli.output, - '< Debugger listening on port 9229', - 'forwards child output'); }) .then(() => cli.command('["hello", "world"].join(" ")')) .then(() => { @@ -72,6 +68,7 @@ test('run after quit / restart', (t) => { t.match(cli.output, 'Use `run` to start the app again'); }) .then(() => cli.stepCommand('run')) + .then(() => cli.waitForInitialBreak()) .then(() => cli.waitForPrompt()) .then(() => { t.match( @@ -87,6 +84,7 @@ test('run after quit / restart', (t) => { 'steps to the 2nd line'); }) .then(() => cli.stepCommand('restart')) + .then(() => cli.waitForInitialBreak()) .then(() => { t.match( cli.output, @@ -100,6 +98,7 @@ test('run after quit / restart', (t) => { t.match(cli.output, 'Use `run` to start the app again'); }) .then(() => cli.stepCommand('run')) + .then(() => cli.waitForInitialBreak()) .then(() => cli.waitForPrompt()) .then(() => { t.match( diff --git a/test/cli/low-level.test.js b/test/cli/low-level.test.js index 966bed5..77e3fc2 100644 --- a/test/cli/low-level.test.js +++ b/test/cli/low-level.test.js @@ -4,8 +4,8 @@ const { test } = require('tap'); const startCLI = require('./start-cli'); test('Debugger agent direct access', (t) => { - const cli = startCLI(['examples/empty.js']); - const scriptPattern = /^\* (\d+): examples(?:\/|\\)empty.js/; + const cli = startCLI(['examples/three-lines.js']); + const scriptPattern = /^\* (\d+): examples(?:\/|\\)three-lines.js/; function onFatal(error) { cli.quit(); @@ -24,7 +24,10 @@ test('Debugger agent direct access', (t) => { .then(() => { t.match( cli.output, - /scriptSource: '\(function \([^)]+\) \{ \\n}\);'/); + /scriptSource: '\(function \(/); + t.match( + cli.output, + /let x = 1;/); }) .then(() => cli.quit()) .then(null, onFatal); diff --git a/test/cli/preserve-breaks.test.js b/test/cli/preserve-breaks.test.js index 17d7976..94f6140 100644 --- a/test/cli/preserve-breaks.test.js +++ b/test/cli/preserve-breaks.test.js @@ -33,8 +33,7 @@ test('run after quit / restart', (t) => { t.match(cli.output, `break in ${script}:3`); }) .then(() => cli.command('restart')) - .then(() => cli.waitFor([/break in examples/, /breakpoints restored/])) - .then(() => cli.waitForPrompt()) + .then(() => cli.waitForInitialBreak()) .then(() => { t.match(cli.output, `break in ${script}:1`); }) diff --git a/test/cli/scripts.test.js b/test/cli/scripts.test.js index ed36705..1546b80 100644 --- a/test/cli/scripts.test.js +++ b/test/cli/scripts.test.js @@ -6,7 +6,7 @@ const { test } = require('tap'); const startCLI = require('./start-cli'); test('list scripts', (t) => { - const script = Path.join('examples', 'empty.js'); + const script = Path.join('examples', 'three-lines.js'); const cli = startCLI([script]); function onFatal(error) { @@ -20,7 +20,7 @@ test('list scripts', (t) => { .then(() => { t.match( cli.output, - /^\* \d+: examples(?:\/|\\)empty\.js/, + /^\* \d+: examples(?:\/|\\)three-lines\.js/, 'lists the user script'); t.notMatch( cli.output, @@ -31,7 +31,7 @@ test('list scripts', (t) => { .then(() => { t.match( cli.output, - /\* \d+: examples(?:\/|\\)empty\.js/, + /\* \d+: examples(?:\/|\\)three-lines\.js/, 'lists the user script'); t.match( cli.output, diff --git a/test/cli/start-cli.js b/test/cli/start-cli.js index 74c9481..56c3e25 100644 --- a/test/cli/start-cli.js +++ b/test/cli/start-cli.js @@ -11,6 +11,11 @@ const CLI = 'inspect' : require.resolve('../../cli.js'); +const BREAK_MESSAGE = new RegExp('(?:' + [ + 'assert', 'break', 'break on start', 'debugCommand', + 'exception', 'other', 'promiseRejection', +].join('|') + ') in', 'i'); + function startCLI(args) { const child = spawn(process.execPath, [CLI, ...args]); let isFirstStdoutChunk = true; @@ -94,7 +99,13 @@ function startCLI(args) { }, waitForInitialBreak(timeout = 2000) { - return this.waitFor(/break/i, timeout); + return this.waitFor(/break (?:on start )?in/i, timeout) + .then(() => { + if (/Break on start/.test(this.output)) { + return this.command('n') + .then(() => this.waitFor(/break in/, timeout)); + } + }); }, ctrlC() { @@ -128,9 +139,7 @@ function startCLI(args) { child.stdin.write(input); child.stdin.write('\n'); return this - .waitFor( - /(?:assert|break|debugCommand|exception|other|promiseRejection) in/ - ) + .waitFor(BREAK_MESSAGE) .then(() => this.waitForPrompt()); }, From 6ce8c165c45a491bea8cfb3c67d2ae80e7c34dcb Mon Sep 17 00:00:00 2001 From: Jan Krems Date: Mon, 3 Apr 2017 14:13:22 -0700 Subject: [PATCH 05/12] test: Revert to old assertions --- test/cli/break.test.js | 18 +++++++++--------- test/cli/exceptions.test.js | 11 +++++++---- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/test/cli/break.test.js b/test/cli/break.test.js index 5de3e52..59b12cd 100644 --- a/test/cli/break.test.js +++ b/test/cli/break.test.js @@ -19,7 +19,7 @@ test('stepping through breakpoints', (t) => { .then(() => { t.match( cli.output, - ` in ${script}:1`, + `break in ${script}:1`, 'pauses in the first line of the script'); t.match( cli.output, @@ -30,7 +30,7 @@ test('stepping through breakpoints', (t) => { .then(() => { t.match( cli.output, - ` in ${script}:2`, + `break in ${script}:2`, 'pauses in next line of the script'); t.match( cli.output, @@ -41,7 +41,7 @@ test('stepping through breakpoints', (t) => { .then(() => { t.match( cli.output, - ` in ${script}:3`, + `break in ${script}:3`, 'pauses in next line of the script'); t.match( cli.output, @@ -52,7 +52,7 @@ test('stepping through breakpoints', (t) => { .then(() => { t.match( cli.output, - ` in ${script}:10`, + `break in ${script}:10`, 'pauses on the next breakpoint'); t.match( cli.output, @@ -94,21 +94,21 @@ test('stepping through breakpoints', (t) => { .then(() => { t.match( cli.output, - ' in timers.js', + 'break in timers.js', 'entered timers.js'); }) .then(() => cli.stepCommand('cont')) .then(() => { t.match( cli.output, - ` in ${script}:16`, + `break in ${script}:16`, 'found breakpoint we set above w/ line number only'); }) .then(() => cli.stepCommand('cont')) .then(() => { t.match( cli.output, - ` in ${script}:6`, + `break in ${script}:6`, 'found breakpoint we set above w/ line number & script'); }) .then(() => cli.stepCommand('')) @@ -145,7 +145,7 @@ test('sb before loading file', (t) => { .then(() => { t.match( cli.output, - ` in ${otherScript}:3`, + `break in ${otherScript}:3`, 'found breakpoint in file that was not loaded yet'); }) .then(() => cli.quit()) @@ -187,7 +187,7 @@ test('clearBreakpoint', (t) => { .then(() => { t.match( cli.output, - ` in ${script}:9`, + `break in ${script}:9`, 'hits the 2nd breakpoint because the 1st was cleared'); }) .then(() => cli.quit()) diff --git a/test/cli/exceptions.test.js b/test/cli/exceptions.test.js index 338c937..18b7f18 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, ` in ${script}:1`); + t.match(cli.output, `break in ${script}:1`); }) // making sure it will die by default: .then(() => cli.command('c')) @@ -26,8 +26,9 @@ test('break on (uncaught) exceptions', (t) => { // Next run: With `breakOnException` it pauses in both places .then(() => cli.stepCommand('r')) + .then(() => cli.waitForInitialBreak()) .then(() => { - t.match(cli.output, ` in ${script}:1`); + t.match(cli.output, `break in ${script}:1`); }) .then(() => cli.command('breakOnException')) .then(() => cli.stepCommand('c')) @@ -42,8 +43,9 @@ test('break on (uncaught) exceptions', (t) => { // Next run: With `breakOnUncaught` it only pauses on the 2nd exception .then(() => cli.command('breakOnUncaught')) .then(() => cli.stepCommand('r')) // also, the setting survives the restart + .then(() => cli.waitForInitialBreak()) .then(() => { - t.match(cli.output, ` in ${script}:1`); + t.match(cli.output, `break in ${script}:1`); }) .then(() => cli.stepCommand('c')) .then(() => { @@ -53,8 +55,9 @@ test('break on (uncaught) exceptions', (t) => { // Next run: Back to the initial state! It should die again. .then(() => cli.command('breakOnNone')) .then(() => cli.stepCommand('r')) + .then(() => cli.waitForInitialBreak()) .then(() => { - t.match(cli.output, ` in ${script}:1`); + t.match(cli.output, `break in ${script}:1`); }) .then(() => cli.command('c')) // TODO: Remove FATAL ERROR once node doesn't show a FATAL ERROR anymore From e3a489f23b089d3d57a25d5efe40daf06de63e23 Mon Sep 17 00:00:00 2001 From: Josh Gavant Date: Mon, 27 Mar 2017 16:58:00 -0700 Subject: [PATCH 06/12] test: custom port --- lib/_inspect.js | 15 +++++++-------- test/cli/launch.test.js | 25 +++++++++++++++++++++++++ test/cli/start-cli.js | 8 +++++--- 3 files changed, 37 insertions(+), 11 deletions(-) diff --git a/lib/_inspect.js b/lib/_inspect.js index ac32e0a..afc0cbd 100644 --- a/lib/_inspect.js +++ b/lib/_inspect.js @@ -42,7 +42,7 @@ const [ InspectClient, createRepl ] = const debuglog = util.debuglog('inspect'); -const DEBUG_PORT_PATTERN = /^--(?:debug|inspect)-port=(\d+)$/; +const DEBUG_PORT_PATTERN = /^--(?:debug|inspect)(?:-port|-brk)?=(\d{1,5})$/; function getDefaultPort() { for (const arg of process.execArgv) { const match = arg.match(DEBUG_PORT_PATTERN); @@ -56,8 +56,7 @@ function getDefaultPort() { function runScript(script, scriptArgs, inspectPort, childPrint) { return new Promise((resolve) => { const args = [ - '--inspect', - `--debug-brk=${inspectPort}`, + `--inspect-brk=${inspectPort}`, ].concat([script], scriptArgs); const child = spawn(process.execPath, args); child.stdout.setEncoding('utf8'); @@ -68,7 +67,7 @@ function runScript(script, scriptArgs, inspectPort, childPrint) { let output = ''; function waitForListenHint(text) { output += text; - if (/chrome-devtools:\/\//.test(output)) { + if (/^Debugger listening on/.test(output)) { child.stderr.removeListener('data', waitForListenHint); resolve(child); } @@ -295,6 +294,7 @@ function parseArgv([target, ...args]) { const hostMatch = target.match(/^([^:]+):(\d+)$/); const portMatch = target.match(/^--port=(\d+)$/); + if (hostMatch) { // Connecting to remote debugger // `node-inspect localhost:9229` @@ -303,16 +303,15 @@ function parseArgv([target, ...args]) { isRemote = true; script = null; } else if (portMatch) { - // Start debugger on custom port - // `node debug --port=8058 app.js` + // start debugee on custom port + // `node inspect --port=9230 script.js` port = parseInt(portMatch[1], 10); script = args[0]; scriptArgs = args.slice(1); } return { - host, port, - isRemote, script, scriptArgs, + host, port, isRemote, script, scriptArgs, }; } diff --git a/test/cli/launch.test.js b/test/cli/launch.test.js index b57c08a..0690cc4 100644 --- a/test/cli/launch.test.js +++ b/test/cli/launch.test.js @@ -5,6 +5,27 @@ const { test } = require('tap'); const startCLI = require('./start-cli'); +test('custom port', (t) => { + const CUSTOM_PORT = '9230'; + const script = Path.join('examples', 'three-lines.js'); + + const cli = startCLI([`--port=${CUSTOM_PORT}`, script]); + + return cli.waitForInitialBreak() + .then(() => cli.waitForPrompt()) + .then(() => { + t.match(cli.output, 'debug>', 'prints a prompt'); + t.match( + cli.output, + new RegExp(`< Debugger listening on [^\n]*${CUSTOM_PORT}`), + 'forwards child output'); + }) + .then(() => cli.quit()) + .then((code) => { + t.equal(code, 0, 'exits with success'); + }); +}); + test('examples/three-lines.js', (t) => { const script = Path.join('examples', 'three-lines.js'); const cli = startCLI([script]); @@ -13,6 +34,10 @@ test('examples/three-lines.js', (t) => { .then(() => cli.waitForPrompt()) .then(() => { t.match(cli.output, 'debug>', 'prints a prompt'); + t.match( + cli.output, + new RegExp(`< Debugger listening on [^\n]*9229`), + 'forwards child output'); }) .then(() => cli.command('["hello", "world"].join(" ")')) .then(() => { diff --git a/test/cli/start-cli.js b/test/cli/start-cli.js index 56c3e25..ae90430 100644 --- a/test/cli/start-cli.js +++ b/test/cli/start-cli.js @@ -102,7 +102,7 @@ function startCLI(args) { return this.waitFor(/break (?:on start )?in/i, timeout) .then(() => { if (/Break on start/.test(this.output)) { - return this.command('n') + return this.command('next', false) .then(() => this.waitFor(/break in/, timeout)); } }); @@ -127,8 +127,10 @@ function startCLI(args) { .map((match) => +match[1]); }, - command(input) { - this.flushOutput(); + command(input, flush = true) { + if (flush) { + this.flushOutput(); + } child.stdin.write(input); child.stdin.write('\n'); return this.waitForPrompt(); From 4179506a4d546bac2c93b2a7ff491b1fa4494fd9 Mon Sep 17 00:00:00 2001 From: Jan Krems Date: Wed, 15 Mar 2017 17:20:30 -0700 Subject: [PATCH 07/12] feat: Support for debugging a pid --- lib/_inspect.js | 121 +++++++++++++++++++++++----------------- test/cli/launch.test.js | 2 +- test/cli/pid.test.js | 52 +++++++++++++++++ 3 files changed, 122 insertions(+), 53 deletions(-) create mode 100644 test/cli/pid.test.js diff --git a/lib/_inspect.js b/lib/_inspect.js index afc0cbd..dab1062 100644 --- a/lib/_inspect.js +++ b/lib/_inspect.js @@ -53,52 +53,6 @@ function getDefaultPort() { return 9229; } -function runScript(script, scriptArgs, inspectPort, childPrint) { - return new Promise((resolve) => { - const args = [ - `--inspect-brk=${inspectPort}`, - ].concat([script], scriptArgs); - const child = spawn(process.execPath, args); - child.stdout.setEncoding('utf8'); - child.stderr.setEncoding('utf8'); - child.stdout.on('data', childPrint); - child.stderr.on('data', childPrint); - - let output = ''; - function waitForListenHint(text) { - output += text; - if (/^Debugger listening on/.test(output)) { - child.stderr.removeListener('data', waitForListenHint); - resolve(child); - } - } - - child.stderr.on('data', waitForListenHint); - }); -} - -function createAgentProxy(domain, client) { - const agent = new EventEmitter(); - agent.then = (...args) => { - // TODO: potentially fetch the protocol and pretty-print it here. - const descriptor = { - [util.inspect.custom](depth, { stylize }) { - return stylize(`[Agent ${domain}]`, 'special'); - }, - }; - return Promise.resolve(descriptor).then(...args); - }; - - return new Proxy(agent, { - get(target, name) { - if (name in target) return target[name]; - return function callVirtualMethod(params) { - return client.callMethod(`${domain}.${name}`, params); - }; - }, - }); -} - function portIsFree(host, port, timeout = 2000) { const retryDelay = 150; let didTimeOut = false; @@ -138,6 +92,56 @@ function portIsFree(host, port, timeout = 2000) { }); } +function runScript(script, scriptArgs, inspectHost, inspectPort, childPrint) { + return portIsFree(inspectHost, inspectPort) + .then(() => { + return new Promise((resolve) => { + const args = [ + '--inspect', + `--debug-brk=${inspectPort}`, + ].concat([script], scriptArgs); + const child = spawn(process.execPath, args); + child.stdout.setEncoding('utf8'); + child.stderr.setEncoding('utf8'); + child.stdout.on('data', childPrint); + child.stderr.on('data', childPrint); + + let output = ''; + function waitForListenHint(text) { + output += text; + if (/chrome-devtools:\/\//.test(output)) { + child.stderr.removeListener('data', waitForListenHint); + resolve(child); + } + } + + child.stderr.on('data', waitForListenHint); + }); + }); +} + +function createAgentProxy(domain, client) { + const agent = new EventEmitter(); + agent.then = (...args) => { + // TODO: potentially fetch the protocol and pretty-print it here. + const descriptor = { + [util.inspect.custom](depth, { stylize }) { + return stylize(`[Agent ${domain}]`, 'special'); + }, + }; + return Promise.resolve(descriptor).then(...args); + }; + + return new Proxy(agent, { + get(target, name) { + if (name in target) return target[name]; + return function callVirtualMethod(params) { + return client.callMethod(`${domain}.${name}`, params); + }; + }, + }); +} + class NodeInspector { constructor(options, stdin, stdout) { this.options = options; @@ -151,6 +155,7 @@ class NodeInspector { this._runScript = runScript.bind(null, options.script, options.scriptArgs, + options.host, options.port, this.childPrint.bind(this)); } else { @@ -219,12 +224,7 @@ class NodeInspector { this.killChild(); const { host, port } = this.options; - const runOncePortIsFree = () => { - return portIsFree(host, port) - .then(() => this._runScript()); - }; - - return runOncePortIsFree().then((child) => { + return this._runScript().then((child) => { this.child = child; let connectionAttempts = 0; @@ -308,6 +308,22 @@ function parseArgv([target, ...args]) { port = parseInt(portMatch[1], 10); script = args[0]; scriptArgs = args.slice(1); + } else if (args.length === 1 && /^\d+$/.test(args[0]) && target === '-p') { + // Start debugger against a given pid + const pid = parseInt(args[0], 10); + try { + process._debugProcess(pid); + } catch (e) { + if (e.code === 'ESRCH') { + /* eslint-disable no-console */ + console.error(`Target process: ${pid} doesn't exist.`); + /* eslint-enable no-console */ + process.exit(1); + } + throw e; + } + script = null; + isRemote = true; } return { @@ -326,6 +342,7 @@ function startInspect(argv = process.argv.slice(2), console.error(`Usage: ${invokedAs} script.js`); console.error(` ${invokedAs} :`); + console.error(` ${invokedAs} -p `); process.exit(1); } diff --git a/test/cli/launch.test.js b/test/cli/launch.test.js index 0690cc4..f7efc6e 100644 --- a/test/cli/launch.test.js +++ b/test/cli/launch.test.js @@ -36,7 +36,7 @@ test('examples/three-lines.js', (t) => { t.match(cli.output, 'debug>', 'prints a prompt'); t.match( cli.output, - new RegExp(`< Debugger listening on [^\n]*9229`), + /< Debugger listening on [^\n]*9229/, 'forwards child output'); }) .then(() => cli.command('["hello", "world"].join(" ")')) diff --git a/test/cli/pid.test.js b/test/cli/pid.test.js new file mode 100644 index 0000000..15d7fde --- /dev/null +++ b/test/cli/pid.test.js @@ -0,0 +1,52 @@ +'use strict'; +const { spawn } = require('child_process'); +const Path = require('path'); + +const { test } = require('tap'); + +const startCLI = require('./start-cli'); + +function launchTarget(...args) { + const childProc = spawn(process.execPath, args); + return Promise.resolve(childProc); +} + +// process.debugPort is our proxy for "the version of node used to run this +// test suite doesn't support SIGUSR1 for enabling --inspect for a process". +const defaultsToOldProtocol = process.debugPort === 5858; + +test('examples/alive.js', { skip: defaultsToOldProtocol }, (t) => { + const script = Path.join('examples', 'alive.js'); + let cli = null; + let target = null; + + function cleanup(error) { + if (cli) { + cli.quit(); + cli = null; + } + if (target) { + target.kill(); + target = null; + } + if (error) throw error; + } + + return launchTarget(script) + .then((childProc) => { + target = childProc; + cli = startCLI(['-p', `${target.pid}`]); + return cli.waitForPrompt(); + }) + .then(() => cli.command('sb("alive.js", 3)')) + .then(() => cli.waitFor(/break/)) + .then(() => cli.waitForPrompt()) + .then(() => { + t.match( + cli.output, + '> 3 ++x;', + 'marks the 3rd line'); + }) + .then(() => cleanup()) + .then(null, cleanup); +}); From f4ff6ae3d6a0435b96a32f470630f24d5f355277 Mon Sep 17 00:00:00 2001 From: nlm Date: Tue, 4 Apr 2017 08:40:11 -0700 Subject: [PATCH 08/12] v1.11.0 --- CHANGELOG.md | 15 +++++++++++++++ package.json | 2 +- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dc217a5..107485a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,18 @@ +### 1.11.0 + +* doc: add profile and heap to help - **[@joshgav](https://github.com/joshgav)** [#39](https://github.com/nodejs/node-inspect/pull/39) + - [`f64c920`](https://github.com/nodejs/node-inspect/commit/f64c9205bd8382289660aa677d3ac192a9c81fd5) **doc:** add profile and heap to help +* Update test suite to pass on latest nightly - **[@jkrems](https://github.com/jkrems)** [#36](https://github.com/nodejs/node-inspect/pull/36) + - [`41148d7`](https://github.com/nodejs/node-inspect/commit/41148d74a2d563eea3b7ad5463622b6b9fd4c46e) **test:** Remove outdated test + - [`2c224c5`](https://github.com/nodejs/node-inspect/commit/2c224c551619e386e80fc3154cc14562cac063b9) **test:** Accept any kind of "break" + - [`22bf349`](https://github.com/nodejs/node-inspect/commit/22bf349bc86d7bf6fd449791c9d1e7eaf66c2681) **test:** Adjust for v8 5.7 + - [`6ce8c16`](https://github.com/nodejs/node-inspect/commit/6ce8c165c45a491bea8cfb3c67d2ae80e7c34dcb) **test:** Revert to old assertions +* Verify custom port support - **[@jkrems](https://github.com/jkrems)** [#41](https://github.com/nodejs/node-inspect/pull/41) + - [`e3a489f`](https://github.com/nodejs/node-inspect/commit/e3a489f23b089d3d57a25d5efe40daf06de63e23) **test:** custom port +* Support for debugging a pid - **[@jkrems](https://github.com/jkrems)** [#37](https://github.com/nodejs/node-inspect/pull/37) + - [`4179506`](https://github.com/nodejs/node-inspect/commit/4179506a4d546bac2c93b2a7ff491b1fa4494fd9) **feat:** Support for debugging a pid + + ### 1.10.6 * chore: Fix usage text for embedded mode - **[@addaleax](https://github.com/addaleax)** [#20](https://github.com/nodejs/node-inspect/pull/20) diff --git a/package.json b/package.json index 1834956..2e8d7f4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "node-inspect", - "version": "1.10.6", + "version": "1.11.0", "description": "Node Inspect", "license": "MIT", "main": "lib/_inspect.js", From 2c1ed27ee44d9aebb3c5ac50039abae8166a54e3 Mon Sep 17 00:00:00 2001 From: Ali Ijaz Sheikh Date: Thu, 6 Apr 2017 09:05:05 -0700 Subject: [PATCH 09/12] fix: use --inspect-brk with Node 8+ Node 8.x no longer has --debug-brk. --- lib/_inspect.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/_inspect.js b/lib/_inspect.js index dab1062..062cd12 100644 --- a/lib/_inspect.js +++ b/lib/_inspect.js @@ -96,10 +96,11 @@ function runScript(script, scriptArgs, inspectHost, inspectPort, childPrint) { return portIsFree(inspectHost, inspectPort) .then(() => { return new Promise((resolve) => { - const args = [ - '--inspect', - `--debug-brk=${inspectPort}`, - ].concat([script], scriptArgs); + const needDebugBrk = process.version.match(/^v(6|7)\./); + const args = (needDebugBrk ? + ['--inspect', `--debug-brk=${inspectPort}`] : + [`--inspect-brk=${inspectPort}`]) + .concat([script], scriptArgs); const child = spawn(process.execPath, args); child.stdout.setEncoding('utf8'); child.stderr.setEncoding('utf8'); From ad0dd3cf26ba5ff8a0f73767d579d6bb1a2927cf Mon Sep 17 00:00:00 2001 From: nlm Date: Thu, 6 Apr 2017 12:15:00 -0700 Subject: [PATCH 10/12] v1.11.1 --- CHANGELOG.md | 6 ++++++ package.json | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 107485a..07a601d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +### 1.11.1 + +* Prefer --inspect-brk over --debug-brk - **[@ofrobots](https://github.com/ofrobots)** [#43](https://github.com/nodejs/node-inspect/pull/43) + - [`2c1ed27`](https://github.com/nodejs/node-inspect/commit/2c1ed27ee44d9aebb3c5ac50039abae8166a54e3) **fix:** use --inspect-brk with Node 8+ + + ### 1.11.0 * doc: add profile and heap to help - **[@joshgav](https://github.com/joshgav)** [#39](https://github.com/nodejs/node-inspect/pull/39) diff --git a/package.json b/package.json index 2e8d7f4..e2aabd7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "node-inspect", - "version": "1.11.0", + "version": "1.11.1", "description": "Node Inspect", "license": "MIT", "main": "lib/_inspect.js", From 42e0cd111d89ed09faba1c0ec45089b0b44de011 Mon Sep 17 00:00:00 2001 From: Josh Gavant Date: Fri, 14 Apr 2017 09:32:39 -0700 Subject: [PATCH 11/12] fix: look for generic hint text --- lib/_inspect.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/_inspect.js b/lib/_inspect.js index 062cd12..2691227 100644 --- a/lib/_inspect.js +++ b/lib/_inspect.js @@ -110,7 +110,7 @@ function runScript(script, scriptArgs, inspectHost, inspectPort, childPrint) { let output = ''; function waitForListenHint(text) { output += text; - if (/chrome-devtools:\/\//.test(output)) { + if (/Debugger listening on/.test(output)) { child.stderr.removeListener('data', waitForListenHint); resolve(child); } From 9f00e6e3bb0d527e9560533ff0b790661065aae7 Mon Sep 17 00:00:00 2001 From: nlm Date: Fri, 14 Apr 2017 10:06:15 -0700 Subject: [PATCH 12/12] v1.11.2 --- CHANGELOG.md | 5 +++++ package.json | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 07a601d..41ed928 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +### 1.11.2 + +* [`42e0cd1`](https://github.com/nodejs/node-inspect/commit/42e0cd111d89ed09faba1c0ec45089b0b44de011) **fix:** look for generic hint text + + ### 1.11.1 * Prefer --inspect-brk over --debug-brk - **[@ofrobots](https://github.com/ofrobots)** [#43](https://github.com/nodejs/node-inspect/pull/43) diff --git a/package.json b/package.json index e2aabd7..070abfa 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "node-inspect", - "version": "1.11.1", + "version": "1.11.2", "description": "Node Inspect", "license": "MIT", "main": "lib/_inspect.js",