Skip to content

Commit 1df84f4

Browse files
committed
debugger: run last command on presssing enter
PR-URL: #6090 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: bnoordhuis - Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Myles Borins <myles.borins@gmail.com> Reviewed-By: Claudio Rodriguez <cjrodr@yahoo.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Fixes: #2895
1 parent b68827b commit 1df84f4

File tree

5 files changed

+82
-23
lines changed

5 files changed

+82
-23
lines changed

doc/api/debugger.markdown

+3
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,9 @@ The `repl` command allows code to be evaluated remotely. The `next` command
8484
steps over to the next line. Type `help` to see what other commands are
8585
available.
8686

87+
Pressing `enter` without typing a command will repeat the previous debugger
88+
command.
89+
8790
## Watchers
8891

8992
It is possible to watch expression and variable values while debugging. On

lib/_debugger.js

+7-4
Original file line numberDiff line numberDiff line change
@@ -674,6 +674,9 @@ var helpMessage = 'Commands: ' + commands.map(function(group) {
674674
return group.join(', ');
675675
}).join(',\n');
676676

677+
// Previous command received. Initialize to empty command.
678+
var lastCommand = '\n';
679+
677680

678681
function SourceUnderline(sourceText, position, repl) {
679682
if (!sourceText) return '';
@@ -945,10 +948,10 @@ Interface.prototype.requireConnection = function() {
945948
Interface.prototype.controlEval = function(code, context, filename, callback) {
946949
try {
947950
// Repeat last command if empty line are going to be evaluated
948-
if (this.repl.rli.history && this.repl.rli.history.length > 0) {
949-
if (code === '\n') {
950-
code = this.repl.rli.history[0] + '\n';
951-
}
951+
if (code === '\n') {
952+
code = lastCommand;
953+
} else {
954+
lastCommand = code;
952955
}
953956

954957
// exec process.title => exec("process.title");

lib/repl.js

+19-19
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,10 @@ function REPLServer(prompt,
224224
function defaultEval(code, context, file, cb) {
225225
var err, result, retry = false, input = code, wrappedErr;
226226
// first, create the Script object to check the syntax
227+
228+
if (code === '\n')
229+
return cb(null);
230+
227231
while (true) {
228232
try {
229233
if (!/^\s*$/.test(code) &&
@@ -421,28 +425,24 @@ function REPLServer(prompt,
421425
}
422426
}
423427

424-
if (cmd || self.bufferedCommand) {
425-
var evalCmd = self.bufferedCommand + cmd;
426-
if (/^\s*\{/.test(evalCmd) && /\}\s*$/.test(evalCmd)) {
427-
// It's confusing for `{ a : 1 }` to be interpreted as a block
428-
// statement rather than an object literal. So, we first try
429-
// to wrap it in parentheses, so that it will be interpreted as
430-
// an expression.
431-
evalCmd = '(' + evalCmd + ')\n';
432-
self.wrappedCmd = true;
433-
} else {
434-
// otherwise we just append a \n so that it will be either
435-
// terminated, or continued onto the next expression if it's an
436-
// unexpected end of input.
437-
evalCmd = evalCmd + '\n';
438-
}
439-
440-
debug('eval %j', evalCmd);
441-
self.eval(evalCmd, self.context, 'repl', finish);
428+
var evalCmd = self.bufferedCommand + cmd;
429+
if (/^\s*\{/.test(evalCmd) && /\}\s*$/.test(evalCmd)) {
430+
// It's confusing for `{ a : 1 }` to be interpreted as a block
431+
// statement rather than an object literal. So, we first try
432+
// to wrap it in parentheses, so that it will be interpreted as
433+
// an expression.
434+
evalCmd = '(' + evalCmd + ')\n';
435+
self.wrappedCmd = true;
442436
} else {
443-
finish(null);
437+
// otherwise we just append a \n so that it will be either
438+
// terminated, or continued onto the next expression if it's an
439+
// unexpected end of input.
440+
evalCmd = evalCmd + '\n';
444441
}
445442

443+
debug('eval %j', evalCmd);
444+
self.eval(evalCmd, self.context, 'repl', finish);
445+
446446
function finish(e, ret) {
447447
debug('finish', e, ret);
448448
self.memory(cmd);

test/fixtures/debugger-repeat-last.js

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
var a = 1;
2+
3+
var b = 2;
4+
5+
var c = 3;
6+
7+
b = c;
+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
'use strict';
2+
const path = require('path');
3+
const spawn = require('child_process').spawn;
4+
const assert = require('assert');
5+
6+
const common = require('../common');
7+
8+
const fixture = path.join(
9+
common.fixturesDir,
10+
'debugger-repeat-last.js'
11+
);
12+
13+
const args = [
14+
'debug',
15+
fixture
16+
];
17+
18+
const proc = spawn(process.execPath, args, { stdio: 'pipe' });
19+
proc.stdout.setEncoding('utf8');
20+
21+
var stdout = '';
22+
23+
var sentCommand = false;
24+
var sentEmpty = false;
25+
var sentExit = false;
26+
27+
proc.stdout.on('data', (data) => {
28+
stdout += data;
29+
if (!sentCommand && stdout.includes('> 1')) {
30+
setImmediate(() => {proc.stdin.write('n\n');});
31+
return sentCommand = true;
32+
}
33+
if (!sentEmpty && stdout.includes('> 3')) {
34+
setImmediate(() => {proc.stdin.write('\n');});
35+
return sentEmpty = true;
36+
}
37+
if (!sentExit && sentCommand && sentEmpty) {
38+
setTimeout(() => {proc.stdin.write('\n\n\n.exit\n\n\n');}, 1);
39+
return sentExit = true;
40+
}
41+
});
42+
43+
process.on('exit', (exitCode) => {
44+
assert.strictEqual(exitCode, 0);
45+
console.log(stdout);
46+
});

0 commit comments

Comments
 (0)