Skip to content

Commit

Permalink
refactor: raise AwaitNotInAsyncContext when an AwaitExpression will b…
Browse files Browse the repository at this point in the history
…e 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
  • Loading branch information
JLHwung authored Feb 1, 2021
1 parent 8cf0a75 commit 108564f
Show file tree
Hide file tree
Showing 15 changed files with 158 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -420,7 +420,13 @@ export default function (
delete task.options.throws;

assert.throws(runTask, function (err) {
return throwMsg === true || err.message.indexOf(throwMsg) >= 0;
assert.ok(
throwMsg === true || err.message.includes(throwMsg),
`
Expected Error: ${throwMsg}
Actual Error: ${err.message}`,
);
return true;
});
} else {
if (task.exec.code) {
Expand Down
37 changes: 37 additions & 0 deletions packages/babel-parser/src/parser/error.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ type ErrorContext = {
code?: string,
};

export type ParsingError = SyntaxError & ErrorContext;

export { ErrorMessages as Errors } from "./error-message.js";

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

/**
* Raise a parsing error on given postion pos. If errorRecovery is true,
* it will first search current errors and overwrite the error thrown on the exact
* position before with the new error message. If errorRecovery is false, it
* fallbacks to `raise`.
*
* @param {number} pos
* @param {string} errorTemplate
* @param {...any} params
* @returns {(Error | empty)}
* @memberof ParserError
*/
raiseOverwrite(
pos: number,
errorTemplate: string,
...params: any
): Error | empty {
const loc = this.getLocationForPosition(pos);
const message =
errorTemplate.replace(/%(\d+)/g, (_, i: number) => params[i]) +
` (${loc.line}:${loc.column})`;
if (this.options.errorRecovery) {
const errors = this.state.errors;
for (let i = errors.length - 1; i >= 0; i--) {
const error = errors[i];
if (error.pos === pos) {
return Object.assign(error, { message });
} else if (error.pos < pos) {
break;
}
}
}
return this._raise({ loc, pos }, message);
}

raiseWithData(
pos: number,
data?: {
Expand Down
26 changes: 8 additions & 18 deletions packages/babel-parser/src/parser/expression.js
Original file line number Diff line number Diff line change
Expand Up @@ -534,19 +534,19 @@ export default class ExpressionParser extends LValParser {

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

const startsExpr = this.hasPlugin("v8intrinsic")
? this.state.type.startsExpr
: this.state.type.startsExpr && !this.match(tt.modulo);
if (isAwait && startsExpr && !this.isAmbiguousAwait()) {
if (!this.state.invalidAwaitErrors.has(startPos)) {
this.raise(
if (isAwait) {
const startsExpr = this.hasPlugin("v8intrinsic")
? this.state.type.startsExpr
: this.state.type.startsExpr && !this.match(tt.modulo);
if (startsExpr && !this.isAmbiguousAwait()) {
this.raiseOverwrite(
startPos,
this.hasPlugin("topLevelAwait")
? Errors.AwaitNotInAsyncContext
: Errors.AwaitNotInAsyncFunction,
);
return this.parseAwait(startPos, startLoc);
}
return this.parseAwait(startPos, startLoc);
}

return expr;
Expand Down Expand Up @@ -2348,17 +2348,7 @@ export default class ExpressionParser extends LValParser {
: isStrictReservedWord;

if (reservedTest(word, this.inModule)) {
if (!this.prodParam.hasAwait && word === "await") {
this.raise(
startLoc,
this.hasPlugin("topLevelAwait")
? Errors.AwaitNotInAsyncContext
: Errors.AwaitNotInAsyncFunction,
);
this.state.invalidAwaitErrors.add(startLoc);
} else {
this.raise(startLoc, Errors.UnexpectedReservedWord, word);
}
this.raise(startLoc, Errors.UnexpectedReservedWord, word);
}
}

Expand Down
6 changes: 2 additions & 4 deletions packages/babel-parser/src/tokenizer/state.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { Position } from "../util/location";

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

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

errors: SyntaxError[] = [];
errors: ParsingError[] = [];

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

// Positions of invalid await errors
invalidAwaitErrors: Set<number> = new Set();

curPosition(): Position {
return new Position(this.curLine, this.pos - this.lineStart);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"type": "File",
"start":0,"end":14,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":14}},
"errors": [
"SyntaxError: 'await' is only allowed within async functions (1:0)"
"SyntaxError: Unexpected reserved word 'await' (1:0)"
],
"program": {
"type": "Program",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"type": "File",
"start":0,"end":20,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":20}},
"errors": [
"SyntaxError: 'await' is only allowed within async functions (1:6)"
"SyntaxError: Unexpected reserved word 'await' (1:6)"
],
"program": {
"type": "Program",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"type": "File",
"start":0,"end":24,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":24}},
"errors": [
"SyntaxError: 'await' is only allowed within async functions (1:8)"
"SyntaxError: Unexpected reserved word 'await' (1:8)"
],
"program": {
"type": "Program",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"type": "File",
"start":0,"end":26,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":26}},
"errors": [
"SyntaxError: 'await' is only allowed within async functions (1:15)"
"SyntaxError: Unexpected reserved word 'await' (1:15)"
],
"program": {
"type": "Program",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"type": "File",
"start":0,"end":19,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":19}},
"errors": [
"SyntaxError: 'await' is only allowed within async functions (1:9)"
"SyntaxError: Unexpected reserved word 'await' (1:9)"
],
"program": {
"type": "Program",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"type": "File",
"start":0,"end":14,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":14}},
"errors": [
"SyntaxError: 'await' is only allowed within async functions (1:6)"
"SyntaxError: Unexpected reserved word 'await' (1:6)"
],
"program": {
"type": "Program",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,5 @@
"plugins": [
"topLevelAwait"
],
"sourceType": "module",
"errorRecovery": false,
"throws": "'await' is only allowed within async functions and at the top levels of modules (1:6)"
}
"sourceType": "module"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
"type": "File",
"start":0,"end":14,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":14}},
"errors": [
"SyntaxError: 'await' is only allowed within async functions and at the top levels of modules (1:6)"
],
"program": {
"type": "Program",
"start":0,"end":14,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":14}},
"sourceType": "module",
"interpreter": null,
"body": [
{
"type": "ExpressionStatement",
"start":0,"end":14,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":14}},
"expression": {
"type": "ArrowFunctionExpression",
"start":0,"end":13,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":13}},
"id": null,
"generator": false,
"async": false,
"params": [],
"body": {
"type": "AwaitExpression",
"start":6,"end":13,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":13}},
"argument": {
"type": "NumericLiteral",
"start":12,"end":13,"loc":{"start":{"line":1,"column":12},"end":{"line":1,"column":13}},
"extra": {
"rawValue": 0,
"raw": "0"
},
"value": 0
}
}
}
}
],
"directives": []
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,5 @@
"plugins": [
"topLevelAwait"
],
"sourceType": "module",
"errorRecovery": false,
"throws": "'await' is only allowed within async functions and at the top levels of modules (2:2)"
}
"sourceType": "module"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
{
"type": "File",
"start":0,"end":28,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}},
"errors": [
"SyntaxError: 'await' is only allowed within async functions and at the top levels of modules (2:2)"
],
"program": {
"type": "Program",
"start":0,"end":28,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}},
"sourceType": "module",
"interpreter": null,
"body": [
{
"type": "FunctionDeclaration",
"start":0,"end":28,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}},
"id": {
"type": "Identifier",
"start":9,"end":11,"loc":{"start":{"line":1,"column":9},"end":{"line":1,"column":11},"identifierName":"fn"},
"name": "fn"
},
"generator": false,
"async": false,
"params": [],
"body": {
"type": "BlockStatement",
"start":14,"end":28,"loc":{"start":{"line":1,"column":14},"end":{"line":3,"column":1}},
"body": [
{
"type": "ExpressionStatement",
"start":18,"end":26,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":10}},
"expression": {
"type": "AwaitExpression",
"start":18,"end":25,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":9}},
"argument": {
"type": "NumericLiteral",
"start":24,"end":25,"loc":{"start":{"line":2,"column":8},"end":{"line":2,"column":9}},
"extra": {
"rawValue": 0,
"raw": "0"
},
"value": 0
}
}
}
],
"directives": []
}
}
],
"directives": []
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@
"supportsTopLevelAwait": false
},
"presets": ["env"],
"throws": "'await' is only allowed within async functions (1:0)"
"throws": "Unexpected reserved word 'await' (1:0)"
}

0 comments on commit 108564f

Please sign in to comment.