fix parser bug where arrow functions have a higher precedence than they should - fixes #2118
This commit is contained in:
@@ -221,12 +221,18 @@ pp.parseMaybeUnary = function (refShorthandDefaultPos) {
|
||||
|
||||
pp.parseExprSubscripts = function (refShorthandDefaultPos) {
|
||||
let startPos = this.state.start, startLoc = this.state.startLoc;
|
||||
let potentialArrowAt = this.state.potentialArrowAt;
|
||||
let expr = this.parseExprAtom(refShorthandDefaultPos);
|
||||
|
||||
if (expr.type === "ArrowFunctionExpression" && expr.start === potentialArrowAt) {
|
||||
return expr;
|
||||
}
|
||||
|
||||
if (refShorthandDefaultPos && refShorthandDefaultPos.start) {
|
||||
return expr;
|
||||
} else {
|
||||
return this.parseSubscripts(expr, startPos, startLoc);
|
||||
}
|
||||
|
||||
return this.parseSubscripts(expr, startPos, startLoc);
|
||||
};
|
||||
|
||||
pp.parseSubscripts = function (base, startPos, startLoc, noCalls) {
|
||||
@@ -250,7 +256,7 @@ pp.parseSubscripts = function (base, startPos, startLoc, noCalls) {
|
||||
this.expect(tt.bracketR);
|
||||
base = this.finishNode(node, "MemberExpression");
|
||||
} else if (!noCalls && this.match(tt.parenL)) {
|
||||
let possibleAsync = base.type === "Identifier" && base.name === "async" && !this.canInsertSemicolon();
|
||||
let possibleAsync = this.state.potentialArrowAt === base.start && base.type === "Identifier" && base.name === "async" && !this.canInsertSemicolon();
|
||||
this.next();
|
||||
|
||||
let node = this.startNodeAt(startPos, startLoc);
|
||||
@@ -677,7 +683,7 @@ pp.parseObj = function (isPattern, refShorthandDefaultPos) {
|
||||
if (prop.shorthand) {
|
||||
this.addExtra(prop, "shorthand", true);
|
||||
}
|
||||
|
||||
|
||||
node.properties.push(prop);
|
||||
}
|
||||
|
||||
@@ -915,6 +921,9 @@ pp.parseIdentifier = function (liberal) {
|
||||
// Parses await expression inside async function.
|
||||
|
||||
pp.parseAwait = function (node) {
|
||||
if (!this.state.inAsync) {
|
||||
this.unexpected();
|
||||
}
|
||||
if (this.isLineTerminator()) {
|
||||
this.unexpected();
|
||||
}
|
||||
|
||||
@@ -128,7 +128,8 @@ pp.parseStatement = function (declaration, topLevel) {
|
||||
// simply start parsing an expression, and afterwards, if the
|
||||
// next token is a colon and the expression was a simple
|
||||
// Identifier node, we switch to interpreting it as a label.
|
||||
let maybeName = this.state.value, expr = this.parseExpression();
|
||||
let maybeName = this.state.value;
|
||||
let expr = this.parseExpression();
|
||||
|
||||
if (starttype === tt.name && expr.type === "Identifier" && this.eat(tt.colon)) {
|
||||
return this.parseLabeledStatement(node, maybeName, expr);
|
||||
|
||||
@@ -653,6 +653,7 @@ export default function (instance) {
|
||||
|
||||
instance.extend("parseParenItem", function () {
|
||||
return function (node, startLoc, startPos, forceArrow?) {
|
||||
let canBeArrow = this.state.potentialArrowAt = startPos;
|
||||
if (this.match(tt.colon)) {
|
||||
let typeCastNode = this.startNodeAt(startLoc, startPos);
|
||||
typeCastNode.expression = node;
|
||||
@@ -662,7 +663,7 @@ export default function (instance) {
|
||||
this.unexpected();
|
||||
}
|
||||
|
||||
if (this.eat(tt.arrow)) {
|
||||
if (canBeArrow && this.eat(tt.arrow)) {
|
||||
// ((lol): number => {});
|
||||
let func = this.parseArrowExpression(this.startNodeAt(startLoc, startPos), [node]);
|
||||
func.returnType = typeCastNode.typeAnnotation;
|
||||
@@ -952,7 +953,7 @@ export default function (instance) {
|
||||
startPos = startPos || this.state.start;
|
||||
startLoc = startLoc || this.state.startLoc;
|
||||
|
||||
if (this.lookahead().type === tt.parenR) {
|
||||
if (canBeArrow && this.lookahead().type === tt.parenR) {
|
||||
// let foo = (): number => {};
|
||||
this.expect(tt.parenL);
|
||||
this.expect(tt.parenR);
|
||||
|
||||
Reference in New Issue
Block a user