Skip to content

Commit 3e6858e

Browse files
princejwesleyMylesBorins
authored andcommitted
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: #18915 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Shingo Inoue <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Ruben Bridgewater <[email protected]>
1 parent 8e88a18 commit 3e6858e

File tree

2 files changed

+75
-10
lines changed

2 files changed

+75
-10
lines changed

lib/repl.js

+6-5
Original file line numberDiff line numberDiff line change
@@ -1375,14 +1375,15 @@ function isRecoverableError(e, code) {
13751375
if (e && e.name === 'SyntaxError') {
13761376
var message = e.message;
13771377
if (message === 'Unterminated template literal' ||
1378-
message === 'Missing } in template expression') {
1378+
message === 'Unexpected end of input') {
13791379
return true;
13801380
}
13811381

1382-
if (message.startsWith('Unexpected end of input') ||
1383-
message.startsWith('missing ) after argument list') ||
1384-
message.startsWith('Unexpected token'))
1385-
return true;
1382+
if (message === 'missing ) after argument list') {
1383+
const frames = e.stack.split(/\r?\n/);
1384+
const pos = frames.findIndex((f) => f.match(/^\s*\^+$/));
1385+
return pos > 0 && frames[pos - 1].length === frames[pos].length;
1386+
}
13861387

13871388
if (message === 'Invalid or unexpected token')
13881389
return isCodeRecoverable(code);

test/parallel/test-repl.js

+69-5
Original file line numberDiff line numberDiff line change
@@ -165,13 +165,23 @@ const errorTests = [
165165
send: '.break',
166166
expect: ''
167167
},
168-
// Template expressions can cross lines
168+
// Template expressions
169169
{
170170
send: '`io.js ${"1.0"',
171+
expect: [
172+
kSource,
173+
kArrow,
174+
'',
175+
/^SyntaxError: /,
176+
''
177+
]
178+
},
179+
{
180+
send: '`io.js ${',
171181
expect: '... '
172182
},
173183
{
174-
send: '+ ".2"}`',
184+
send: '"1.0" + ".2"}`',
175185
expect: '\'io.js 1.0.2\''
176186
},
177187
// Dot prefix in multiline commands aren't treated as commands
@@ -636,14 +646,68 @@ const errorTests = [
636646
},
637647
// Do not parse `...[]` as a REPL keyword
638648
{
639-
send: '...[]\n',
640-
expect: '... ... '
649+
send: '...[]',
650+
expect: [
651+
kSource,
652+
kArrow,
653+
'',
654+
/^SyntaxError: /,
655+
''
656+
]
641657
},
642658
// bring back the repl to prompt
643659
{
644660
send: '.break',
645661
expect: ''
646-
}
662+
},
663+
{
664+
send: 'console.log("Missing comma in arg list" process.version)',
665+
expect: [
666+
kSource,
667+
kArrow,
668+
'',
669+
/^SyntaxError: /,
670+
''
671+
]
672+
},
673+
{
674+
send: 'x = {\nfield\n{',
675+
expect: [
676+
'... ... {',
677+
kArrow,
678+
'',
679+
/^SyntaxError: /,
680+
''
681+
]
682+
},
683+
{
684+
send: '(2 + 3))',
685+
expect: [
686+
kSource,
687+
kArrow,
688+
'',
689+
/^SyntaxError: /,
690+
''
691+
]
692+
},
693+
{
694+
send: 'if (typeof process === "object"); {',
695+
expect: '... '
696+
},
697+
{
698+
send: 'console.log("process is defined");',
699+
expect: '... '
700+
},
701+
{
702+
send: '} else {',
703+
expect: [
704+
kSource,
705+
kArrow,
706+
'',
707+
/^SyntaxError: /,
708+
''
709+
]
710+
},
647711
];
648712

649713
const tcpTests = [

0 commit comments

Comments
 (0)