Skip to content

Commit

Permalink
repl: add fallback error detection after processTopLevelAwait error
Browse files Browse the repository at this point in the history
  • Loading branch information
ejose19 committed Jul 6, 2021
1 parent 4de6f20 commit 02ead45
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 3 deletions.
5 changes: 4 additions & 1 deletion lib/internal/repl/await.js
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,10 @@ function processTopLevelAwait(src) {
'^\n\n' + RegExpPrototypeSymbolReplace(/ \([^)]+\)/, e.message, '');
// V8 unexpected token errors include the token string.
if (StringPrototypeEndsWith(message, 'Unexpected token'))
message += " '" + src[e.pos - wrapPrefix.length] + "'";
message += " '" +
// Wrapper end may cause acorn to report error position after the source
(src[e.pos - wrapPrefix.length] ?? src[src.length - 1]) +
"'";
// eslint-disable-next-line no-restricted-syntax
throw new SyntaxError(message);
}
Expand Down
27 changes: 25 additions & 2 deletions lib/repl.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ const {
ReflectApply,
RegExp,
RegExpPrototypeExec,
RegExpPrototypeSymbolReplace,
RegExpPrototypeTest,
SafeSet,
SafeWeakSet,
Expand Down Expand Up @@ -434,8 +435,30 @@ function REPLServer(prompt,
awaitPromise = true;
}
} catch (e) {
decorateErrorStack(e);
err = e;
let recoverableError = false;
if (e.name === 'SyntaxError') {
// Remove all "await"s and attempt running the script
// in order to detect if error is truly non recoverable
const fallbackCode = RegExpPrototypeSymbolReplace(/\bawait\b/g, code, '');
try {
vm.createScript(fallbackCode, {
filename: file,
displayErrors: true,
importModuleDynamically: async (specifier) => {
return asyncESM.ESMLoader.import(specifier, parentURL);
}
});
} catch (fallbackError) {
if (isRecoverableError(fallbackError, fallbackCode)) {
recoverableError = true;
err = new Recoverable(e);
}
}
}
if (!recoverableError) {
decorateErrorStack(e);
err = e;
}
}
}

Expand Down
30 changes: 30 additions & 0 deletions test/parallel/test-repl-top-level-await.js
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,36 @@ async function ordinaryTests() {
'Unexpected token \'.\'',
],
],
['for (const x of [1,2,3]) {\nawait x\n}', [
'for (const x of [1,2,3]) {\r',
'... await x\r',
'... }\r',
'undefined'
]],
['for (const x of [1,2,3]) {\nawait x;\n}', [
'for (const x of [1,2,3]) {\r',
'... await x;\r',
'... }\r',
'undefined'
]],
['for await (const x of [1,2,3]) {\nconsole.log(x)\n}', [
'for await (const x of [1,2,3]) {\r',
'... console.log(x)\r',
'... }\r',
'1',
'2',
'3',
'undefined'
]],
['for await (const x of [1,2,3]) {\nconsole.log(x);\n}', [
'for await (const x of [1,2,3]) {\r',
'... console.log(x);\r',
'... }\r',
'1',
'2',
'3',
'undefined'
]],
];

for (const [input, expected = [`${input}\r`], options = {}] of testCases) {
Expand Down

0 comments on commit 02ead45

Please sign in to comment.