Fix await in function name and parameters (#7727)
* Disallow await in function parameters * Fix await as function name * Update test whitelists
This commit is contained in:
@@ -522,10 +522,15 @@ export default class ExpressionParser extends LValParser {
|
||||
}
|
||||
return this.finishNode(node, "MemberExpression");
|
||||
} else if (!noCalls && this.match(tt.parenL)) {
|
||||
const oldMaybeInArrowParameters = this.state.maybeInArrowParameters;
|
||||
const oldYOAIPAP = this.state.yieldOrAwaitInPossibleArrowParameters;
|
||||
this.state.maybeInArrowParameters = true;
|
||||
this.state.yieldOrAwaitInPossibleArrowParameters = null;
|
||||
|
||||
const possibleAsync = this.atPossibleAsync(base);
|
||||
this.next();
|
||||
|
||||
const node = this.startNodeAt(startPos, startLoc);
|
||||
let node = this.startNodeAt(startPos, startLoc);
|
||||
node.callee = base;
|
||||
|
||||
// TODO: Clean up/merge this into `this.state` or a class like acorn's
|
||||
@@ -554,13 +559,22 @@ export default class ExpressionParser extends LValParser {
|
||||
);
|
||||
}
|
||||
|
||||
return this.parseAsyncArrowFromCallExpression(
|
||||
node = this.parseAsyncArrowFromCallExpression(
|
||||
this.startNodeAt(startPos, startLoc),
|
||||
node,
|
||||
);
|
||||
this.state.yieldOrAwaitInPossibleArrowParameters = oldYOAIPAP;
|
||||
} else {
|
||||
this.toReferencedList(node.arguments);
|
||||
|
||||
// We keep the old value if it isn't null, for cases like
|
||||
// (x = async(yield)) => {}
|
||||
this.state.yieldOrAwaitInPossibleArrowParameters =
|
||||
this.state.yieldOrAwaitInPossibleArrowParameters || oldYOAIPAP;
|
||||
}
|
||||
|
||||
this.state.maybeInArrowParameters = oldMaybeInArrowParameters;
|
||||
|
||||
return node;
|
||||
} else if (this.match(tt.backQuote)) {
|
||||
return this.parseTaggedTemplateExpression(
|
||||
@@ -685,11 +699,8 @@ export default class ExpressionParser extends LValParser {
|
||||
node: N.ArrowFunctionExpression,
|
||||
call: N.CallExpression,
|
||||
): N.ArrowFunctionExpression {
|
||||
const oldYield = this.state.yieldInPossibleArrowParameters;
|
||||
this.state.yieldInPossibleArrowParameters = null;
|
||||
this.expect(tt.arrow);
|
||||
this.parseArrowExpression(node, call.arguments, true);
|
||||
this.state.yieldInPossibleArrowParameters = oldYield;
|
||||
return node;
|
||||
}
|
||||
|
||||
@@ -800,21 +811,24 @@ export default class ExpressionParser extends LValParser {
|
||||
id.name === "async" &&
|
||||
this.match(tt.name)
|
||||
) {
|
||||
const oldYield = this.state.yieldInPossibleArrowParameters;
|
||||
this.state.yieldInPossibleArrowParameters = null;
|
||||
const oldYOAIPAP = this.state.yieldOrAwaitInPossibleArrowParameters;
|
||||
const oldInAsync = this.state.inAsync;
|
||||
this.state.yieldOrAwaitInPossibleArrowParameters = null;
|
||||
this.state.inAsync = true;
|
||||
const params = [this.parseIdentifier()];
|
||||
this.expect(tt.arrow);
|
||||
// let foo = async bar => {};
|
||||
this.parseArrowExpression(node, params, true);
|
||||
this.state.yieldInPossibleArrowParameters = oldYield;
|
||||
this.state.yieldOrAwaitInPossibleArrowParameters = oldYOAIPAP;
|
||||
this.state.inAsync = oldInAsync;
|
||||
return node;
|
||||
}
|
||||
|
||||
if (canBeArrow && !this.canInsertSemicolon() && this.eat(tt.arrow)) {
|
||||
const oldYield = this.state.yieldInPossibleArrowParameters;
|
||||
this.state.yieldInPossibleArrowParameters = null;
|
||||
const oldYOAIPAP = this.state.yieldOrAwaitInPossibleArrowParameters;
|
||||
this.state.yieldOrAwaitInPossibleArrowParameters = null;
|
||||
this.parseArrowExpression(node, [id]);
|
||||
this.state.yieldInPossibleArrowParameters = oldYield;
|
||||
this.state.yieldOrAwaitInPossibleArrowParameters = oldYOAIPAP;
|
||||
return node;
|
||||
}
|
||||
|
||||
@@ -1049,9 +1063,9 @@ export default class ExpressionParser extends LValParser {
|
||||
this.expect(tt.parenL);
|
||||
|
||||
const oldMaybeInArrowParameters = this.state.maybeInArrowParameters;
|
||||
const oldYield = this.state.yieldInPossibleArrowParameters;
|
||||
const oldYOAIPAP = this.state.yieldOrAwaitInPossibleArrowParameters;
|
||||
this.state.maybeInArrowParameters = true;
|
||||
this.state.yieldInPossibleArrowParameters = null;
|
||||
this.state.yieldOrAwaitInPossibleArrowParameters = null;
|
||||
|
||||
const innerStartPos = this.state.start;
|
||||
const innerStartLoc = this.state.startLoc;
|
||||
@@ -1124,11 +1138,14 @@ export default class ExpressionParser extends LValParser {
|
||||
}
|
||||
|
||||
this.parseArrowExpression(arrowNode, exprList);
|
||||
this.state.yieldInPossibleArrowParameters = oldYield;
|
||||
this.state.yieldOrAwaitInPossibleArrowParameters = oldYOAIPAP;
|
||||
return arrowNode;
|
||||
}
|
||||
|
||||
this.state.yieldInPossibleArrowParameters = oldYield;
|
||||
// We keep the old value if it isn't null, for cases like
|
||||
// (x = (yield)) => {}
|
||||
this.state.yieldOrAwaitInPossibleArrowParameters =
|
||||
this.state.yieldOrAwaitInPossibleArrowParameters || oldYOAIPAP;
|
||||
|
||||
if (!exprList.length) {
|
||||
this.unexpected(this.state.lastTokStart);
|
||||
@@ -1620,9 +1637,11 @@ export default class ExpressionParser extends LValParser {
|
||||
): T {
|
||||
const oldInFunc = this.state.inFunction;
|
||||
const oldInMethod = this.state.inMethod;
|
||||
const oldInAsync = this.state.inAsync;
|
||||
const oldInGenerator = this.state.inGenerator;
|
||||
this.state.inFunction = true;
|
||||
this.state.inMethod = node.kind || true;
|
||||
this.state.inAsync = isAsync;
|
||||
this.state.inGenerator = isGenerator;
|
||||
|
||||
this.initFunction(node, isAsync);
|
||||
@@ -1633,6 +1652,7 @@ export default class ExpressionParser extends LValParser {
|
||||
|
||||
this.state.inFunction = oldInFunc;
|
||||
this.state.inMethod = oldInMethod;
|
||||
this.state.inAsync = oldInAsync;
|
||||
this.state.inGenerator = oldInGenerator;
|
||||
|
||||
return node;
|
||||
@@ -1648,12 +1668,21 @@ export default class ExpressionParser extends LValParser {
|
||||
): N.ArrowFunctionExpression {
|
||||
// if we got there, it's no more "yield in possible arrow parameters";
|
||||
// it's just "yield in arrow parameters"
|
||||
if (this.state.yieldInPossibleArrowParameters) {
|
||||
this.raise(
|
||||
this.state.yieldInPossibleArrowParameters.start,
|
||||
"yield is not allowed in the parameters of an arrow function" +
|
||||
" inside a generator",
|
||||
);
|
||||
const yOAIPAP = this.state.yieldOrAwaitInPossibleArrowParameters;
|
||||
if (yOAIPAP) {
|
||||
if (yOAIPAP.type === "YieldExpression") {
|
||||
this.raise(
|
||||
yOAIPAP.start,
|
||||
"yield is not allowed in the parameters of an arrow function" +
|
||||
" inside a generator",
|
||||
);
|
||||
} else {
|
||||
this.raise(
|
||||
yOAIPAP.start,
|
||||
"await is not allowed in the parameters of an arrow function" +
|
||||
" inside an async function",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const oldInFunc = this.state.inFunction;
|
||||
@@ -1661,11 +1690,14 @@ export default class ExpressionParser extends LValParser {
|
||||
this.initFunction(node, isAsync);
|
||||
if (params) this.setArrowFunctionParameters(node, params);
|
||||
|
||||
const oldInAsync = this.state.inAsync;
|
||||
const oldInGenerator = this.state.inGenerator;
|
||||
const oldMaybeInArrowParameters = this.state.maybeInArrowParameters;
|
||||
this.state.inAsync = true;
|
||||
this.state.inGenerator = false;
|
||||
this.state.maybeInArrowParameters = false;
|
||||
this.parseFunctionBody(node, true);
|
||||
this.state.inAsync = oldInAsync;
|
||||
this.state.inGenerator = oldInGenerator;
|
||||
this.state.inFunction = oldInFunc;
|
||||
this.state.maybeInArrowParameters = oldMaybeInArrowParameters;
|
||||
@@ -1713,9 +1745,7 @@ export default class ExpressionParser extends LValParser {
|
||||
const isExpression = allowExpression && !this.match(tt.braceL);
|
||||
|
||||
const oldInParameters = this.state.inParameters;
|
||||
const oldInAsync = this.state.inAsync;
|
||||
this.state.inParameters = false;
|
||||
this.state.inAsync = node.async;
|
||||
|
||||
if (isExpression) {
|
||||
node.body = this.parseMaybeAssign();
|
||||
@@ -1733,7 +1763,6 @@ export default class ExpressionParser extends LValParser {
|
||||
this.state.inGenerator = oldInGen;
|
||||
this.state.labels = oldLabels;
|
||||
}
|
||||
this.state.inAsync = oldInAsync;
|
||||
|
||||
this.checkFunctionNameAndParams(node, allowExpression);
|
||||
this.state.inParameters = oldInParameters;
|
||||
@@ -1910,12 +1939,27 @@ export default class ExpressionParser extends LValParser {
|
||||
) {
|
||||
this.unexpected();
|
||||
}
|
||||
if (this.state.inParameters) {
|
||||
this.raise(
|
||||
node.start,
|
||||
"await is not allowed in async function parameters",
|
||||
);
|
||||
}
|
||||
if (this.match(tt.star)) {
|
||||
this.raise(
|
||||
node.start,
|
||||
"await* has been removed from the async functions proposal. Use Promise.all() instead.",
|
||||
);
|
||||
}
|
||||
if (
|
||||
this.state.maybeInArrowParameters &&
|
||||
// We only set yieldOrAwaitInPossibleArrowParameters if we haven't already
|
||||
// found a possible invalid AwaitExpression.
|
||||
!this.state.yieldOrAwaitInPossibleArrowParameters
|
||||
) {
|
||||
this.state.yieldOrAwaitInPossibleArrowParameters = node;
|
||||
}
|
||||
|
||||
node.argument = this.parseMaybeUnary();
|
||||
return this.finishNode(node, "AwaitExpression");
|
||||
}
|
||||
@@ -1930,11 +1974,11 @@ export default class ExpressionParser extends LValParser {
|
||||
}
|
||||
if (
|
||||
this.state.maybeInArrowParameters &&
|
||||
// We only set yieldInPossibleArrowParameters if we haven't already
|
||||
// We only set yieldOrAwaitInPossibleArrowParameters if we haven't already
|
||||
// found a possible invalid YieldExpression.
|
||||
!this.state.yieldInPossibleArrowParameters
|
||||
!this.state.yieldOrAwaitInPossibleArrowParameters
|
||||
) {
|
||||
this.state.yieldInPossibleArrowParameters = node;
|
||||
this.state.yieldOrAwaitInPossibleArrowParameters = node;
|
||||
}
|
||||
|
||||
this.next();
|
||||
|
||||
@@ -842,6 +842,7 @@ export default class StatementParser extends ExpressionParser {
|
||||
): T {
|
||||
const oldInFunc = this.state.inFunction;
|
||||
const oldInMethod = this.state.inMethod;
|
||||
const oldInAsync = this.state.inAsync;
|
||||
const oldInGenerator = this.state.inGenerator;
|
||||
const oldInClassProperty = this.state.inClassProperty;
|
||||
this.state.inFunction = true;
|
||||
@@ -872,11 +873,18 @@ export default class StatementParser extends ExpressionParser {
|
||||
// valid because yield is parsed as if it was outside the generator.
|
||||
// Therefore, this.state.inGenerator is set before or after parsing the
|
||||
// function id according to the "isStatement" parameter.
|
||||
if (!isStatement) this.state.inGenerator = node.generator;
|
||||
// The same applies to await & async functions.
|
||||
if (!isStatement) {
|
||||
this.state.inAsync = isAsync;
|
||||
this.state.inGenerator = node.generator;
|
||||
}
|
||||
if (this.match(tt.name) || this.match(tt._yield)) {
|
||||
node.id = this.parseBindingIdentifier();
|
||||
}
|
||||
if (isStatement) this.state.inGenerator = node.generator;
|
||||
if (isStatement) {
|
||||
this.state.inAsync = isAsync;
|
||||
this.state.inGenerator = node.generator;
|
||||
}
|
||||
|
||||
this.parseFunctionParams(node);
|
||||
this.parseFunctionBodyAndFinish(
|
||||
@@ -887,6 +895,7 @@ export default class StatementParser extends ExpressionParser {
|
||||
|
||||
this.state.inFunction = oldInFunc;
|
||||
this.state.inMethod = oldInMethod;
|
||||
this.state.inAsync = oldInAsync;
|
||||
this.state.inGenerator = oldInGenerator;
|
||||
this.state.inClassProperty = oldInClassProperty;
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ export default class State {
|
||||
|
||||
this.decoratorStack = [[]];
|
||||
|
||||
this.yieldInPossibleArrowParameters = null;
|
||||
this.yieldOrAwaitInPossibleArrowParameters = null;
|
||||
|
||||
this.tokens = [];
|
||||
|
||||
@@ -126,10 +126,10 @@ export default class State {
|
||||
// where @foo belongs to the outer class and @bar to the inner
|
||||
decoratorStack: Array<Array<N.Decorator>>;
|
||||
|
||||
// The first yield expression inside parenthesized expressions and arrow
|
||||
// function parameters. It is used to disallow yield in arrow function
|
||||
// parameters.
|
||||
yieldInPossibleArrowParameters: ?N.YieldExpression;
|
||||
// The first yield or await expression inside parenthesized expressions
|
||||
// and arrow function parameters. It is used to disallow yield and await in
|
||||
// arrow function parameters.
|
||||
yieldOrAwaitInPossibleArrowParameters: ?N.YieldExpression;
|
||||
|
||||
// Token store.
|
||||
tokens: Array<Token | N.Comment>;
|
||||
|
||||
Reference in New Issue
Block a user