repl: better handling of recoverable errors

Below syntax errors are handled without force .break/clear
  - Unexpected Token (prefix errors)
  - missing ) after argument list

In the multiline expression, recoverable errors are truly
recoverable, otherwise syntax error will be thrown.

PR-URL: https://github.com/nodejs/node/pull/18915
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Shingo Inoue <leko.noor@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
This commit is contained in:
Prince J Wesley 2018-02-21 17:48:23 +05:30 committed by Ruben Bridgewater
parent 1ed36aeb53
commit ebfa8b1464
No known key found for this signature in database
GPG Key ID: F07496B3EB3C1762
2 changed files with 75 additions and 10 deletions

View File

@ -1473,14 +1473,15 @@ function isRecoverableError(e, code) {
if (e && e.name === 'SyntaxError') { if (e && e.name === 'SyntaxError') {
var message = e.message; var message = e.message;
if (message === 'Unterminated template literal' || if (message === 'Unterminated template literal' ||
message === 'Missing } in template expression') { message === 'Unexpected end of input') {
return true; return true;
} }
if (message.startsWith('Unexpected end of input') || if (message === 'missing ) after argument list') {
message.startsWith('missing ) after argument list') || const frames = e.stack.split(/\r?\n/);
message.startsWith('Unexpected token')) const pos = frames.findIndex((f) => f.match(/^\s*\^+$/));
return true; return pos > 0 && frames[pos - 1].length === frames[pos].length;
}
if (message === 'Invalid or unexpected token') if (message === 'Invalid or unexpected token')
return isCodeRecoverable(code); return isCodeRecoverable(code);

View File

@ -163,13 +163,23 @@ const errorTests = [
send: '.break', send: '.break',
expect: '' expect: ''
}, },
// Template expressions can cross lines // Template expressions
{ {
send: '`io.js ${"1.0"', send: '`io.js ${"1.0"',
expect: [
kSource,
kArrow,
'',
/^SyntaxError: /,
''
]
},
{
send: '`io.js ${',
expect: '... ' expect: '... '
}, },
{ {
send: '+ ".2"}`', send: '"1.0" + ".2"}`',
expect: '\'io.js 1.0.2\'' expect: '\'io.js 1.0.2\''
}, },
// Dot prefix in multiline commands aren't treated as commands // Dot prefix in multiline commands aren't treated as commands
@ -644,14 +654,68 @@ const errorTests = [
}, },
// Do not parse `...[]` as a REPL keyword // Do not parse `...[]` as a REPL keyword
{ {
send: '...[]\n', send: '...[]',
expect: '... ... ' expect: [
kSource,
kArrow,
'',
/^SyntaxError: /,
''
]
}, },
// bring back the repl to prompt // bring back the repl to prompt
{ {
send: '.break', send: '.break',
expect: '' expect: ''
} },
{
send: 'console.log("Missing comma in arg list" process.version)',
expect: [
kSource,
kArrow,
'',
/^SyntaxError: /,
''
]
},
{
send: 'x = {\nfield\n{',
expect: [
'... ... {',
kArrow,
'',
/^SyntaxError: /,
''
]
},
{
send: '(2 + 3))',
expect: [
kSource,
kArrow,
'',
/^SyntaxError: /,
''
]
},
{
send: 'if (typeof process === "object"); {',
expect: '... '
},
{
send: 'console.log("process is defined");',
expect: '... '
},
{
send: '} else {',
expect: [
kSource,
kArrow,
'',
/^SyntaxError: /,
''
]
},
]; ];
const tcpTests = [ const tcpTests = [