Skip to content

Commit 108564f

Browse files
authored
refactor: raise AwaitNotInAsyncContext when an AwaitExpression will be parsed (#12716)
* refactor: raise AwaitNotInAsyncContext when an AwaitExpression will be parsed * tweak logic * early exit when errors are before thrown error position * fix: always return true in assert.throws callback See https://nodejs.org/api/assert.html#assert_assert_throws_fn_error_message * update test fixtures * fix flow error
1 parent 8cf0a75 commit 108564f

File tree

15 files changed

+158
-38
lines changed

15 files changed

+158
-38
lines changed

packages/babel-helper-transform-fixture-test-runner/src/index.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -420,7 +420,13 @@ export default function (
420420
delete task.options.throws;
421421

422422
assert.throws(runTask, function (err) {
423-
return throwMsg === true || err.message.indexOf(throwMsg) >= 0;
423+
assert.ok(
424+
throwMsg === true || err.message.includes(throwMsg),
425+
`
426+
Expected Error: ${throwMsg}
427+
Actual Error: ${err.message}`,
428+
);
429+
return true;
424430
});
425431
} else {
426432
if (task.exec.code) {

packages/babel-parser/src/parser/error.js

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ type ErrorContext = {
1616
code?: string,
1717
};
1818

19+
export type ParsingError = SyntaxError & ErrorContext;
20+
1921
export { ErrorMessages as Errors } from "./error-message.js";
2022

2123
export default class ParserError extends CommentsParser {
@@ -39,6 +41,41 @@ export default class ParserError extends CommentsParser {
3941
return this.raiseWithData(pos, undefined, errorTemplate, ...params);
4042
}
4143

44+
/**
45+
* Raise a parsing error on given postion pos. If errorRecovery is true,
46+
* it will first search current errors and overwrite the error thrown on the exact
47+
* position before with the new error message. If errorRecovery is false, it
48+
* fallbacks to `raise`.
49+
*
50+
* @param {number} pos
51+
* @param {string} errorTemplate
52+
* @param {...any} params
53+
* @returns {(Error | empty)}
54+
* @memberof ParserError
55+
*/
56+
raiseOverwrite(
57+
pos: number,
58+
errorTemplate: string,
59+
...params: any
60+
): Error | empty {
61+
const loc = this.getLocationForPosition(pos);
62+
const message =
63+
errorTemplate.replace(/%(\d+)/g, (_, i: number) => params[i]) +
64+
` (${loc.line}:${loc.column})`;
65+
if (this.options.errorRecovery) {
66+
const errors = this.state.errors;
67+
for (let i = errors.length - 1; i >= 0; i--) {
68+
const error = errors[i];
69+
if (error.pos === pos) {
70+
return Object.assign(error, { message });
71+
} else if (error.pos < pos) {
72+
break;
73+
}
74+
}
75+
}
76+
return this._raise({ loc, pos }, message);
77+
}
78+
4279
raiseWithData(
4380
pos: number,
4481
data?: {

packages/babel-parser/src/parser/expression.js

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -534,19 +534,19 @@ export default class ExpressionParser extends LValParser {
534534

535535
const expr = this.parseUpdate(node, update, refExpressionErrors);
536536

537-
const startsExpr = this.hasPlugin("v8intrinsic")
538-
? this.state.type.startsExpr
539-
: this.state.type.startsExpr && !this.match(tt.modulo);
540-
if (isAwait && startsExpr && !this.isAmbiguousAwait()) {
541-
if (!this.state.invalidAwaitErrors.has(startPos)) {
542-
this.raise(
537+
if (isAwait) {
538+
const startsExpr = this.hasPlugin("v8intrinsic")
539+
? this.state.type.startsExpr
540+
: this.state.type.startsExpr && !this.match(tt.modulo);
541+
if (startsExpr && !this.isAmbiguousAwait()) {
542+
this.raiseOverwrite(
543543
startPos,
544544
this.hasPlugin("topLevelAwait")
545545
? Errors.AwaitNotInAsyncContext
546546
: Errors.AwaitNotInAsyncFunction,
547547
);
548+
return this.parseAwait(startPos, startLoc);
548549
}
549-
return this.parseAwait(startPos, startLoc);
550550
}
551551

552552
return expr;
@@ -2348,17 +2348,7 @@ export default class ExpressionParser extends LValParser {
23482348
: isStrictReservedWord;
23492349

23502350
if (reservedTest(word, this.inModule)) {
2351-
if (!this.prodParam.hasAwait && word === "await") {
2352-
this.raise(
2353-
startLoc,
2354-
this.hasPlugin("topLevelAwait")
2355-
? Errors.AwaitNotInAsyncContext
2356-
: Errors.AwaitNotInAsyncFunction,
2357-
);
2358-
this.state.invalidAwaitErrors.add(startLoc);
2359-
} else {
2360-
this.raise(startLoc, Errors.UnexpectedReservedWord, word);
2361-
}
2351+
this.raise(startLoc, Errors.UnexpectedReservedWord, word);
23622352
}
23632353
}
23642354

packages/babel-parser/src/tokenizer/state.js

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { Position } from "../util/location";
66

77
import { types as ct, type TokContext } from "./context";
88
import { types as tt, type TokenType } from "./types";
9+
import type { ParsingError } from "../parser/error";
910

1011
type TopicContextState = {
1112
// When a topic binding has been currently established,
@@ -37,7 +38,7 @@ export default class State {
3738
this.startLoc = this.endLoc = this.curPosition();
3839
}
3940

40-
errors: SyntaxError[] = [];
41+
errors: ParsingError[] = [];
4142

4243
// Used to signify the start of a potential arrow function
4344
potentialArrowAt: number = -1;
@@ -155,9 +156,6 @@ export default class State {
155156
// Tokens length in token store
156157
tokensLength: number = 0;
157158

158-
// Positions of invalid await errors
159-
invalidAwaitErrors: Set<number> = new Set();
160-
161159
curPosition(): Position {
162160
return new Position(this.curLine, this.pos - this.lineStart);
163161
}

packages/babel-parser/test/fixtures/es2015/uncategorised/357/output.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"type": "File",
33
"start":0,"end":14,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":14}},
44
"errors": [
5-
"SyntaxError: 'await' is only allowed within async functions (1:0)"
5+
"SyntaxError: Unexpected reserved word 'await' (1:0)"
66
],
77
"program": {
88
"type": "Program",

packages/babel-parser/test/fixtures/es2015/uncategorised/359/output.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"type": "File",
33
"start":0,"end":20,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":20}},
44
"errors": [
5-
"SyntaxError: 'await' is only allowed within async functions (1:6)"
5+
"SyntaxError: Unexpected reserved word 'await' (1:6)"
66
],
77
"program": {
88
"type": "Program",

packages/babel-parser/test/fixtures/es2015/uncategorised/361/output.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"type": "File",
33
"start":0,"end":24,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":24}},
44
"errors": [
5-
"SyntaxError: 'await' is only allowed within async functions (1:8)"
5+
"SyntaxError: Unexpected reserved word 'await' (1:8)"
66
],
77
"program": {
88
"type": "Program",

packages/babel-parser/test/fixtures/es2015/uncategorised/363/output.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"type": "File",
33
"start":0,"end":26,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":26}},
44
"errors": [
5-
"SyntaxError: 'await' is only allowed within async functions (1:15)"
5+
"SyntaxError: Unexpected reserved word 'await' (1:15)"
66
],
77
"program": {
88
"type": "Program",

packages/babel-parser/test/fixtures/es2015/uncategorised/365/output.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"type": "File",
33
"start":0,"end":19,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":19}},
44
"errors": [
5-
"SyntaxError: 'await' is only allowed within async functions (1:9)"
5+
"SyntaxError: Unexpected reserved word 'await' (1:9)"
66
],
77
"program": {
88
"type": "Program",

packages/babel-parser/test/fixtures/es2015/uncategorised/367/output.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"type": "File",
33
"start":0,"end":14,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":14}},
44
"errors": [
5-
"SyntaxError: 'await' is only allowed within async functions (1:6)"
5+
"SyntaxError: Unexpected reserved word 'await' (1:6)"
66
],
77
"program": {
88
"type": "Program",

0 commit comments

Comments
 (0)