debugger: run last command on presssing enter
PR-URL: https://github.com/nodejs/node/pull/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: https://github.com/nodejs/node/issues/2895
This commit is contained in:
parent
b68827b1d1
commit
1df84f4f75
@ -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
|
steps over to the next line. Type `help` to see what other commands are
|
||||||
available.
|
available.
|
||||||
|
|
||||||
|
Pressing `enter` without typing a command will repeat the previous debugger
|
||||||
|
command.
|
||||||
|
|
||||||
## Watchers
|
## Watchers
|
||||||
|
|
||||||
It is possible to watch expression and variable values while debugging. On
|
It is possible to watch expression and variable values while debugging. On
|
||||||
|
@ -674,6 +674,9 @@ var helpMessage = 'Commands: ' + commands.map(function(group) {
|
|||||||
return group.join(', ');
|
return group.join(', ');
|
||||||
}).join(',\n');
|
}).join(',\n');
|
||||||
|
|
||||||
|
// Previous command received. Initialize to empty command.
|
||||||
|
var lastCommand = '\n';
|
||||||
|
|
||||||
|
|
||||||
function SourceUnderline(sourceText, position, repl) {
|
function SourceUnderline(sourceText, position, repl) {
|
||||||
if (!sourceText) return '';
|
if (!sourceText) return '';
|
||||||
@ -945,10 +948,10 @@ Interface.prototype.requireConnection = function() {
|
|||||||
Interface.prototype.controlEval = function(code, context, filename, callback) {
|
Interface.prototype.controlEval = function(code, context, filename, callback) {
|
||||||
try {
|
try {
|
||||||
// Repeat last command if empty line are going to be evaluated
|
// 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') {
|
||||||
if (code === '\n') {
|
code = lastCommand;
|
||||||
code = this.repl.rli.history[0] + '\n';
|
} else {
|
||||||
}
|
lastCommand = code;
|
||||||
}
|
}
|
||||||
|
|
||||||
// exec process.title => exec("process.title");
|
// exec process.title => exec("process.title");
|
||||||
|
38
lib/repl.js
38
lib/repl.js
@ -224,6 +224,10 @@ function REPLServer(prompt,
|
|||||||
function defaultEval(code, context, file, cb) {
|
function defaultEval(code, context, file, cb) {
|
||||||
var err, result, retry = false, input = code, wrappedErr;
|
var err, result, retry = false, input = code, wrappedErr;
|
||||||
// first, create the Script object to check the syntax
|
// first, create the Script object to check the syntax
|
||||||
|
|
||||||
|
if (code === '\n')
|
||||||
|
return cb(null);
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
try {
|
try {
|
||||||
if (!/^\s*$/.test(code) &&
|
if (!/^\s*$/.test(code) &&
|
||||||
@ -421,28 +425,24 @@ function REPLServer(prompt,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cmd || self.bufferedCommand) {
|
var evalCmd = self.bufferedCommand + cmd;
|
||||||
var evalCmd = self.bufferedCommand + cmd;
|
if (/^\s*\{/.test(evalCmd) && /\}\s*$/.test(evalCmd)) {
|
||||||
if (/^\s*\{/.test(evalCmd) && /\}\s*$/.test(evalCmd)) {
|
// It's confusing for `{ a : 1 }` to be interpreted as a block
|
||||||
// It's confusing for `{ a : 1 }` to be interpreted as a block
|
// statement rather than an object literal. So, we first try
|
||||||
// statement rather than an object literal. So, we first try
|
// to wrap it in parentheses, so that it will be interpreted as
|
||||||
// to wrap it in parentheses, so that it will be interpreted as
|
// an expression.
|
||||||
// an expression.
|
evalCmd = '(' + evalCmd + ')\n';
|
||||||
evalCmd = '(' + evalCmd + ')\n';
|
self.wrappedCmd = true;
|
||||||
self.wrappedCmd = true;
|
|
||||||
} else {
|
|
||||||
// otherwise we just append a \n so that it will be either
|
|
||||||
// terminated, or continued onto the next expression if it's an
|
|
||||||
// unexpected end of input.
|
|
||||||
evalCmd = evalCmd + '\n';
|
|
||||||
}
|
|
||||||
|
|
||||||
debug('eval %j', evalCmd);
|
|
||||||
self.eval(evalCmd, self.context, 'repl', finish);
|
|
||||||
} else {
|
} else {
|
||||||
finish(null);
|
// otherwise we just append a \n so that it will be either
|
||||||
|
// terminated, or continued onto the next expression if it's an
|
||||||
|
// unexpected end of input.
|
||||||
|
evalCmd = evalCmd + '\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
debug('eval %j', evalCmd);
|
||||||
|
self.eval(evalCmd, self.context, 'repl', finish);
|
||||||
|
|
||||||
function finish(e, ret) {
|
function finish(e, ret) {
|
||||||
debug('finish', e, ret);
|
debug('finish', e, ret);
|
||||||
self.memory(cmd);
|
self.memory(cmd);
|
||||||
|
7
test/fixtures/debugger-repeat-last.js
vendored
Normal file
7
test/fixtures/debugger-repeat-last.js
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
var a = 1;
|
||||||
|
|
||||||
|
var b = 2;
|
||||||
|
|
||||||
|
var c = 3;
|
||||||
|
|
||||||
|
b = c;
|
46
test/parallel/test-debugger-repeat-last.js
Normal file
46
test/parallel/test-debugger-repeat-last.js
Normal file
@ -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);
|
||||||
|
});
|
Loading…
x
Reference in New Issue
Block a user