diff --git a/doc/api/debugger.markdown b/doc/api/debugger.markdown index 2bbaf9049eb5fb..400192ee00c2da 100644 --- a/doc/api/debugger.markdown +++ b/doc/api/debugger.markdown @@ -84,6 +84,9 @@ The `repl` command allows code to be evaluated remotely. The `next` command steps over to the next line. Type `help` to see what other commands are available. +Pressing `enter` without typing a command will repeat the previous debugger +command. + ## Watchers It is possible to watch expression and variable values while debugging. On diff --git a/lib/_debugger.js b/lib/_debugger.js index e7e24d32a13df0..7b3abec27da277 100644 --- a/lib/_debugger.js +++ b/lib/_debugger.js @@ -674,6 +674,9 @@ var helpMessage = 'Commands: ' + commands.map(function(group) { return group.join(', '); }).join(',\n'); +// Previous command received. Initialize to empty command. +var lastCommand = '\n'; + function SourceUnderline(sourceText, position, repl) { if (!sourceText) return ''; @@ -945,10 +948,10 @@ Interface.prototype.requireConnection = function() { Interface.prototype.controlEval = function(code, context, filename, callback) { try { // Repeat last command if empty line are going to be evaluated - if (this.repl.rli.history && this.repl.rli.history.length > 0) { - if (code === '\n') { - code = this.repl.rli.history[0] + '\n'; - } + if (code === '\n') { + code = lastCommand; + } else { + lastCommand = code; } // exec process.title => exec("process.title"); diff --git a/lib/repl.js b/lib/repl.js index 44aed66a6dd9a0..2db2de9e4496a0 100644 --- a/lib/repl.js +++ b/lib/repl.js @@ -421,7 +421,10 @@ function REPLServer(prompt, } } - if (cmd || self.bufferedCommand) { + // self.context.setBreakpoint exists we are in the debugger. + // If we are in the debugger, then we should process empty lines as they are + // a shortcut for "repeat the previous debugging command". + if (cmd || self.bufferedCommand || self.context.setBreakpoint) { var evalCmd = self.bufferedCommand + cmd; if (/^\s*\{/.test(evalCmd) && /\}\s*$/.test(evalCmd)) { // It's confusing for `{ a : 1 }` to be interpreted as a block diff --git a/test/fixtures/debugger-repeat-last.js b/test/fixtures/debugger-repeat-last.js new file mode 100644 index 00000000000000..86df8eebcb76a7 --- /dev/null +++ b/test/fixtures/debugger-repeat-last.js @@ -0,0 +1,7 @@ +var a = 1; + +var b = 2; + +var c = 3; + +b = c; diff --git a/test/parallel/test-debugger-repeat-last.js b/test/parallel/test-debugger-repeat-last.js new file mode 100644 index 00000000000000..7f0e1e68165019 --- /dev/null +++ b/test/parallel/test-debugger-repeat-last.js @@ -0,0 +1,46 @@ +'use strict'; +const path = require('path'); +const spawn = require('child_process').spawn; +const assert = require('assert'); + +const common = require('../common'); + +const fixture = path.join( + common.fixturesDir, + 'debugger-repeat-last.js' +); + +const args = [ + 'debug', + fixture +]; + +const proc = spawn(process.execPath, args, { stdio: 'pipe' }); +proc.stdout.setEncoding('utf8'); + +var stdout = ''; + +var sentCommand = false; +var sentEmpty = false; +var sentExit = false; + +proc.stdout.on('data', (data) => { + stdout += data; + if (!sentCommand && stdout.includes('> 1')) { + setImmediate(() => {proc.stdin.write('n\n');}); + return sentCommand = true; + } + if (!sentEmpty && stdout.includes('> 3')) { + setImmediate(() => {proc.stdin.write('\n');}); + return sentEmpty = true; + } + if (!sentExit && sentCommand && sentEmpty) { + setTimeout(() => {proc.stdin.write('\n\n\n.exit\n\n\n');}, 1); + return sentExit = true; + } +}); + +process.on('exit', (exitCode) => { + assert.strictEqual(exitCode, 0); + console.log(stdout); +});