fix parser bug where arrow functions have a higher precedence than they should - fixes #2118
This commit is contained in:
parent
37159fbc7d
commit
7012116f4e
@ -20,6 +20,7 @@ See [CHANGELOG - 6to5](CHANGELOG-6to5.md) for the pre-4.0.0 version changelog.
|
|||||||
* Ensure that invalid identifier JSX attribute keys are quoted when transforming to calls.
|
* Ensure that invalid identifier JSX attribute keys are quoted when transforming to calls.
|
||||||
* Fix ES3 property literal plugin.
|
* Fix ES3 property literal plugin.
|
||||||
* Fix parameters after defaults in arrow functions refering to the wrong `arguments`.
|
* Fix parameters after defaults in arrow functions refering to the wrong `arguments`.
|
||||||
|
* Fix parser bug where arrow functions have a higher precedence than they should.
|
||||||
|
|
||||||
## 6.0.13
|
## 6.0.13
|
||||||
|
|
||||||
|
|||||||
@ -221,12 +221,18 @@ pp.parseMaybeUnary = function (refShorthandDefaultPos) {
|
|||||||
|
|
||||||
pp.parseExprSubscripts = function (refShorthandDefaultPos) {
|
pp.parseExprSubscripts = function (refShorthandDefaultPos) {
|
||||||
let startPos = this.state.start, startLoc = this.state.startLoc;
|
let startPos = this.state.start, startLoc = this.state.startLoc;
|
||||||
|
let potentialArrowAt = this.state.potentialArrowAt;
|
||||||
let expr = this.parseExprAtom(refShorthandDefaultPos);
|
let expr = this.parseExprAtom(refShorthandDefaultPos);
|
||||||
|
|
||||||
|
if (expr.type === "ArrowFunctionExpression" && expr.start === potentialArrowAt) {
|
||||||
|
return expr;
|
||||||
|
}
|
||||||
|
|
||||||
if (refShorthandDefaultPos && refShorthandDefaultPos.start) {
|
if (refShorthandDefaultPos && refShorthandDefaultPos.start) {
|
||||||
return expr;
|
return expr;
|
||||||
} else {
|
|
||||||
return this.parseSubscripts(expr, startPos, startLoc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return this.parseSubscripts(expr, startPos, startLoc);
|
||||||
};
|
};
|
||||||
|
|
||||||
pp.parseSubscripts = function (base, startPos, startLoc, noCalls) {
|
pp.parseSubscripts = function (base, startPos, startLoc, noCalls) {
|
||||||
@ -250,7 +256,7 @@ pp.parseSubscripts = function (base, startPos, startLoc, noCalls) {
|
|||||||
this.expect(tt.bracketR);
|
this.expect(tt.bracketR);
|
||||||
base = this.finishNode(node, "MemberExpression");
|
base = this.finishNode(node, "MemberExpression");
|
||||||
} else if (!noCalls && this.match(tt.parenL)) {
|
} 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();
|
this.next();
|
||||||
|
|
||||||
let node = this.startNodeAt(startPos, startLoc);
|
let node = this.startNodeAt(startPos, startLoc);
|
||||||
@ -677,7 +683,7 @@ pp.parseObj = function (isPattern, refShorthandDefaultPos) {
|
|||||||
if (prop.shorthand) {
|
if (prop.shorthand) {
|
||||||
this.addExtra(prop, "shorthand", true);
|
this.addExtra(prop, "shorthand", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
node.properties.push(prop);
|
node.properties.push(prop);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -915,6 +921,9 @@ pp.parseIdentifier = function (liberal) {
|
|||||||
// Parses await expression inside async function.
|
// Parses await expression inside async function.
|
||||||
|
|
||||||
pp.parseAwait = function (node) {
|
pp.parseAwait = function (node) {
|
||||||
|
if (!this.state.inAsync) {
|
||||||
|
this.unexpected();
|
||||||
|
}
|
||||||
if (this.isLineTerminator()) {
|
if (this.isLineTerminator()) {
|
||||||
this.unexpected();
|
this.unexpected();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -128,7 +128,8 @@ pp.parseStatement = function (declaration, topLevel) {
|
|||||||
// simply start parsing an expression, and afterwards, if the
|
// simply start parsing an expression, and afterwards, if the
|
||||||
// next token is a colon and the expression was a simple
|
// next token is a colon and the expression was a simple
|
||||||
// Identifier node, we switch to interpreting it as a label.
|
// 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)) {
|
if (starttype === tt.name && expr.type === "Identifier" && this.eat(tt.colon)) {
|
||||||
return this.parseLabeledStatement(node, maybeName, expr);
|
return this.parseLabeledStatement(node, maybeName, expr);
|
||||||
|
|||||||
@ -653,6 +653,7 @@ export default function (instance) {
|
|||||||
|
|
||||||
instance.extend("parseParenItem", function () {
|
instance.extend("parseParenItem", function () {
|
||||||
return function (node, startLoc, startPos, forceArrow?) {
|
return function (node, startLoc, startPos, forceArrow?) {
|
||||||
|
let canBeArrow = this.state.potentialArrowAt = startPos;
|
||||||
if (this.match(tt.colon)) {
|
if (this.match(tt.colon)) {
|
||||||
let typeCastNode = this.startNodeAt(startLoc, startPos);
|
let typeCastNode = this.startNodeAt(startLoc, startPos);
|
||||||
typeCastNode.expression = node;
|
typeCastNode.expression = node;
|
||||||
@ -662,7 +663,7 @@ export default function (instance) {
|
|||||||
this.unexpected();
|
this.unexpected();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.eat(tt.arrow)) {
|
if (canBeArrow && this.eat(tt.arrow)) {
|
||||||
// ((lol): number => {});
|
// ((lol): number => {});
|
||||||
let func = this.parseArrowExpression(this.startNodeAt(startLoc, startPos), [node]);
|
let func = this.parseArrowExpression(this.startNodeAt(startLoc, startPos), [node]);
|
||||||
func.returnType = typeCastNode.typeAnnotation;
|
func.returnType = typeCastNode.typeAnnotation;
|
||||||
@ -952,7 +953,7 @@ export default function (instance) {
|
|||||||
startPos = startPos || this.state.start;
|
startPos = startPos || this.state.start;
|
||||||
startLoc = startLoc || this.state.startLoc;
|
startLoc = startLoc || this.state.startLoc;
|
||||||
|
|
||||||
if (this.lookahead().type === tt.parenR) {
|
if (canBeArrow && this.lookahead().type === tt.parenR) {
|
||||||
// let foo = (): number => {};
|
// let foo = (): number => {};
|
||||||
this.expect(tt.parenL);
|
this.expect(tt.parenL);
|
||||||
this.expect(tt.parenR);
|
this.expect(tt.parenR);
|
||||||
|
|||||||
1
packages/babylon/test/fixtures/experimental/async-functions/expression-statement/actual.js
vendored
Normal file
1
packages/babylon/test/fixtures/experimental/async-functions/expression-statement/actual.js
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
async () => {}
|
||||||
86
packages/babylon/test/fixtures/experimental/async-functions/expression-statement/expected.json
vendored
Normal file
86
packages/babylon/test/fixtures/experimental/async-functions/expression-statement/expected.json
vendored
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
{
|
||||||
|
"type": "File",
|
||||||
|
"start": 0,
|
||||||
|
"end": 14,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 1,
|
||||||
|
"column": 0
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 1,
|
||||||
|
"column": 14
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"program": {
|
||||||
|
"type": "Program",
|
||||||
|
"start": 0,
|
||||||
|
"end": 14,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 1,
|
||||||
|
"column": 0
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 1,
|
||||||
|
"column": 14
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sourceType": "script",
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"type": "ExpressionStatement",
|
||||||
|
"start": 0,
|
||||||
|
"end": 14,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 1,
|
||||||
|
"column": 0
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 1,
|
||||||
|
"column": 14
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"expression": {
|
||||||
|
"type": "ArrowFunctionExpression",
|
||||||
|
"start": 0,
|
||||||
|
"end": 14,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 1,
|
||||||
|
"column": 0
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 1,
|
||||||
|
"column": 14
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"id": null,
|
||||||
|
"generator": false,
|
||||||
|
"expression": false,
|
||||||
|
"async": true,
|
||||||
|
"params": [],
|
||||||
|
"body": {
|
||||||
|
"type": "BlockStatement",
|
||||||
|
"start": 12,
|
||||||
|
"end": 14,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 1,
|
||||||
|
"column": 12
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 1,
|
||||||
|
"column": 14
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"body": [],
|
||||||
|
"directives": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"directives": []
|
||||||
|
}
|
||||||
|
}
|
||||||
1
packages/babylon/test/fixtures/experimental/async-functions/no-callee/actual.js
vendored
Normal file
1
packages/babylon/test/fixtures/experimental/async-functions/no-callee/actual.js
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
async () => {}()
|
||||||
3
packages/babylon/test/fixtures/experimental/async-functions/no-callee/options.json
vendored
Normal file
3
packages/babylon/test/fixtures/experimental/async-functions/no-callee/options.json
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"throws": "Unexpected token (1:14)"
|
||||||
|
}
|
||||||
1
packages/babylon/test/fixtures/flow/regression/issue-2154/actual.js
vendored
Normal file
1
packages/babylon/test/fixtures/flow/regression/issue-2154/actual.js
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
!()=>0
|
||||||
3
packages/babylon/test/fixtures/flow/regression/issue-2154/options.json
vendored
Normal file
3
packages/babylon/test/fixtures/flow/regression/issue-2154/options.json
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"throws": "Unexpected token (1:2)"
|
||||||
|
}
|
||||||
@ -1 +1 @@
|
|||||||
var foo = bar ? (foo) : number => {} : baz;
|
var foo = bar ? (foo) : number => {} : baz;
|
||||||
|
|||||||
1
packages/babylon/test/fixtures/harmony/arrow-functions/no-callee/actual.js
vendored
Normal file
1
packages/babylon/test/fixtures/harmony/arrow-functions/no-callee/actual.js
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
() => {}()
|
||||||
3
packages/babylon/test/fixtures/harmony/arrow-functions/no-callee/options.json
vendored
Normal file
3
packages/babylon/test/fixtures/harmony/arrow-functions/no-callee/options.json
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"throws": "Unexpected token (1:8)"
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user