We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
There was an error while loading. Please reload this page.
1 parent a101fe6 commit b168ec2Copy full SHA for b168ec2
3 files changed
lib/internal/repl/await.js
@@ -184,7 +184,10 @@ function processTopLevelAwait(src) {
184
'^\n\n' + RegExpPrototypeSymbolReplace(/ \([^)]+\)/, e.message, '');
185
// V8 unexpected token errors include the token string.
186
if (StringPrototypeEndsWith(message, 'Unexpected token'))
187
- message += " '" + src[e.pos - wrapPrefix.length] + "'";
+ message += " '" +
188
+ // Wrapper end may cause acorn to report error position after the source
189
+ (src[e.pos - wrapPrefix.length] ?? src[src.length - 1]) +
190
+ "'";
191
// eslint-disable-next-line no-restricted-syntax
192
throw new SyntaxError(message);
193
}
lib/repl.js
@@ -78,6 +78,7 @@ const {
78
ReflectApply,
79
RegExp,
80
RegExpPrototypeExec,
81
+ RegExpPrototypeSymbolReplace,
82
RegExpPrototypeTest,
83
SafeSet,
84
SafeWeakSet,
@@ -434,8 +435,39 @@ function REPLServer(prompt,
434
435
awaitPromise = true;
436
437
} catch (e) {
- decorateErrorStack(e);
438
- err = e;
+ let recoverableError = false;
439
+ if (e.name === 'SyntaxError') {
440
+ let parentURL;
441
+ try {
442
+ const { pathToFileURL } = require('url');
443
+ // Adding `/repl` prevents dynamic imports from loading relative
444
+ // to the parent of `process.cwd()`.
445
+ parentURL = pathToFileURL(path.join(process.cwd(), 'repl')).href;
446
+ } catch {
447
+ }
448
+
449
+ // Remove all "await"s and attempt running the script
450
+ // in order to detect if error is truly non recoverable
451
+ const fallbackCode = RegExpPrototypeSymbolReplace(/\bawait\b/g, code, '');
452
453
+ vm.createScript(fallbackCode, {
454
+ filename: file,
455
+ displayErrors: true,
456
+ importModuleDynamically: async (specifier) => {
457
+ return asyncESM.ESMLoader.import(specifier, parentURL);
458
459
+ });
460
+ } catch (fallbackError) {
461
+ if (isRecoverableError(fallbackError, fallbackCode)) {
462
+ recoverableError = true;
463
+ err = new Recoverable(e);
464
465
466
467
+ if (!recoverableError) {
468
+ decorateErrorStack(e);
469
+ err = e;
470
471
472
473
test/parallel/test-repl-top-level-await.js
@@ -152,6 +152,36 @@ async function ordinaryTests() {
152
'Unexpected token \'.\'',
153
],
154
155
+ ['for (const x of [1,2,3]) {\nawait x\n}', [
156
+ 'for (const x of [1,2,3]) {\r',
157
+ '... await x\r',
158
+ '... }\r',
159
+ 'undefined',
160
+ ]],
161
+ ['for (const x of [1,2,3]) {\nawait x;\n}', [
162
163
+ '... await x;\r',
164
165
166
167
+ ['for await (const x of [1,2,3]) {\nconsole.log(x)\n}', [
168
+ 'for await (const x of [1,2,3]) {\r',
169
+ '... console.log(x)\r',
170
171
+ '1',
172
+ '2',
173
+ '3',
174
175
176
+ ['for await (const x of [1,2,3]) {\nconsole.log(x);\n}', [
177
178
+ '... console.log(x);\r',
179
180
181
182
183
];
for (const [input, expected = [`${input}\r`], options = {}] of testCases) {
0 commit comments