Fix support for flow optional parameters in arrow functions T7096

This overwrites the conditional handling in babylon for flow to support
optional parameters in arrow functions.
This commit is contained in:
Daniel Tschinder 2016-04-10 12:56:21 +02:00
parent b926e401c6
commit e6c11a0673
8 changed files with 409 additions and 4 deletions

View File

@ -88,7 +88,7 @@ pp.parseExpression = function (noIn, refShorthandDefaultPos) {
// Parse an assignment expression. This includes applications of
// operators like `+=`.
pp.parseMaybeAssign = function (noIn, refShorthandDefaultPos, afterLeftParse) {
pp.parseMaybeAssign = function (noIn, refShorthandDefaultPos, afterLeftParse, refNeedsArrowPos) {
if (this.match(tt._yield) && this.state.inGenerator) {
return this.parseYield();
}
@ -108,7 +108,7 @@ pp.parseMaybeAssign = function (noIn, refShorthandDefaultPos, afterLeftParse) {
this.state.potentialArrowAt = this.state.start;
}
let left = this.parseMaybeConditional(noIn, refShorthandDefaultPos);
let left = this.parseMaybeConditional(noIn, refShorthandDefaultPos, refNeedsArrowPos);
if (afterLeftParse) left = afterLeftParse.call(this, left, startPos, startLoc);
if (this.state.type.isAssign) {
let node = this.startNodeAt(startPos, startLoc);
@ -142,10 +142,15 @@ pp.parseMaybeAssign = function (noIn, refShorthandDefaultPos, afterLeftParse) {
// Parse a ternary conditional (`?:`) operator.
pp.parseMaybeConditional = function (noIn, refShorthandDefaultPos) {
pp.parseMaybeConditional = function (noIn, refShorthandDefaultPos, refNeedsArrowPos) {
let startPos = this.state.start, startLoc = this.state.startLoc;
let expr = this.parseExprOps(noIn, refShorthandDefaultPos);
if (refShorthandDefaultPos && refShorthandDefaultPos.start) return expr;
return this.parseConditional(expr, noIn, startPos, startLoc, refNeedsArrowPos);
};
pp.parseConditional = function (expr, noIn, startPos, startLoc) {
if (this.eat(tt.question)) {
let node = this.startNodeAt(startPos, startLoc);
node.test = expr;
@ -541,6 +546,7 @@ pp.parseParenAndDistinguishExpression = function (startPos, startLoc, canBeArrow
let innerStartPos = this.state.start, innerStartLoc = this.state.startLoc;
let exprList = [], first = true;
let refShorthandDefaultPos = { start: 0 }, spreadStart, optionalCommaStart;
let refNeedsArrowPos = { start: 0 };
while (!this.match(tt.parenR)) {
if (first) {
first = false;
@ -558,7 +564,7 @@ pp.parseParenAndDistinguishExpression = function (startPos, startLoc, canBeArrow
exprList.push(this.parseParenItem(this.parseRest(), spreadNodeStartLoc, spreadNodeStartPos));
break;
} else {
exprList.push(this.parseMaybeAssign(false, refShorthandDefaultPos, this.parseParenItem));
exprList.push(this.parseMaybeAssign(false, refShorthandDefaultPos, this.parseParenItem, refNeedsArrowPos));
}
}
@ -584,6 +590,7 @@ pp.parseParenAndDistinguishExpression = function (startPos, startLoc, canBeArrow
if (optionalCommaStart && !allowOptionalCommaStart) this.unexpected(optionalCommaStart);
if (spreadStart) this.unexpected(spreadStart);
if (refShorthandDefaultPos.start) this.unexpected(refShorthandDefaultPos.start);
if (refNeedsArrowPos.start) this.unexpected(refNeedsArrowPos.start);
if (exprList.length > 1) {
val = this.startNodeAt(innerStartPos, innerStartLoc);

View File

@ -717,9 +717,30 @@ export default function (instance) {
};
});
instance.extend("parseConditional", function (inner) {
return function (expr, noIn, startPos, startLoc, refNeedsArrowPos) {
const state = this.state.clone();
try {
return inner.call(this, expr, noIn, startPos, startLoc);
} catch (err) {
if (refNeedsArrowPos && err instanceof SyntaxError) {
this.state = state;
refNeedsArrowPos.start = this.state.start;
return expr;
} else {
throw err;
}
}
};
});
instance.extend("parseParenItem", function () {
return function (node, startLoc, startPos, forceArrow?) {
let canBeArrow = this.state.potentialArrowAt = startPos;
if (this.eat(tt.question)) {
node.optional = true;
}
if (this.match(tt.colon)) {
let typeCastNode = this.startNodeAt(startLoc, startPos);
typeCastNode.expression = node;

View File

@ -0,0 +1 @@
const f = (x?) => {}

View File

@ -0,0 +1,138 @@
{
"type": "File",
"start": 0,
"end": 20,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 20
}
},
"program": {
"type": "Program",
"start": 0,
"end": 20,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 20
}
},
"sourceType": "module",
"body": [
{
"type": "VariableDeclaration",
"start": 0,
"end": 20,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 20
}
},
"declarations": [
{
"type": "VariableDeclarator",
"start": 6,
"end": 20,
"loc": {
"start": {
"line": 1,
"column": 6
},
"end": {
"line": 1,
"column": 20
}
},
"id": {
"type": "Identifier",
"start": 6,
"end": 7,
"loc": {
"start": {
"line": 1,
"column": 6
},
"end": {
"line": 1,
"column": 7
}
},
"name": "f"
},
"init": {
"type": "ArrowFunctionExpression",
"start": 10,
"end": 20,
"loc": {
"start": {
"line": 1,
"column": 10
},
"end": {
"line": 1,
"column": 20
}
},
"id": null,
"generator": false,
"expression": false,
"async": false,
"params": [
{
"type": "Identifier",
"start": 11,
"end": 12,
"loc": {
"start": {
"line": 1,
"column": 11
},
"end": {
"line": 1,
"column": 12
}
},
"name": "x",
"optional": true
}
],
"body": {
"type": "BlockStatement",
"start": 18,
"end": 20,
"loc": {
"start": {
"line": 1,
"column": 18
},
"end": {
"line": 1,
"column": 20
}
},
"body": [],
"directives": []
}
}
}
],
"kind": "const"
}
],
"directives": []
}
}

View File

@ -0,0 +1 @@
const f = (x?)

View File

@ -0,0 +1,3 @@
{
"throws": "Unexpected token (1:12)"
}

View File

@ -0,0 +1 @@
const f = (x?, y?:Object = {}) => {}

View File

@ -0,0 +1,233 @@
{
"type": "File",
"start": 0,
"end": 36,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 36
}
},
"program": {
"type": "Program",
"start": 0,
"end": 36,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 36
}
},
"sourceType": "module",
"body": [
{
"type": "VariableDeclaration",
"start": 0,
"end": 36,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 36
}
},
"declarations": [
{
"type": "VariableDeclarator",
"start": 6,
"end": 36,
"loc": {
"start": {
"line": 1,
"column": 6
},
"end": {
"line": 1,
"column": 36
}
},
"id": {
"type": "Identifier",
"start": 6,
"end": 7,
"loc": {
"start": {
"line": 1,
"column": 6
},
"end": {
"line": 1,
"column": 7
}
},
"name": "f"
},
"init": {
"type": "ArrowFunctionExpression",
"start": 10,
"end": 36,
"loc": {
"start": {
"line": 1,
"column": 10
},
"end": {
"line": 1,
"column": 36
}
},
"id": null,
"generator": false,
"expression": false,
"async": false,
"params": [
{
"type": "Identifier",
"start": 11,
"end": 12,
"loc": {
"start": {
"line": 1,
"column": 11
},
"end": {
"line": 1,
"column": 12
}
},
"name": "x",
"optional": true
},
{
"type": "AssignmentPattern",
"start": 15,
"end": 29,
"loc": {
"start": {
"line": 1,
"column": 15
},
"end": {
"line": 1,
"column": 29
}
},
"left": {
"type": "Identifier",
"start": 15,
"end": 16,
"loc": {
"start": {
"line": 1,
"column": 15
},
"end": {
"line": 1,
"column": 16
}
},
"name": "y",
"optional": true,
"typeAnnotation": {
"type": "TypeAnnotation",
"start": 17,
"end": 24,
"loc": {
"start": {
"line": 1,
"column": 17
},
"end": {
"line": 1,
"column": 24
}
},
"typeAnnotation": {
"type": "GenericTypeAnnotation",
"start": 18,
"end": 24,
"loc": {
"start": {
"line": 1,
"column": 18
},
"end": {
"line": 1,
"column": 24
}
},
"typeParameters": null,
"id": {
"type": "Identifier",
"start": 18,
"end": 24,
"loc": {
"start": {
"line": 1,
"column": 18
},
"end": {
"line": 1,
"column": 24
}
},
"name": "Object"
}
}
}
},
"right": {
"type": "ObjectExpression",
"start": 27,
"end": 29,
"loc": {
"start": {
"line": 1,
"column": 27
},
"end": {
"line": 1,
"column": 29
}
},
"properties": []
}
}
],
"body": {
"type": "BlockStatement",
"start": 34,
"end": 36,
"loc": {
"start": {
"line": 1,
"column": 34
},
"end": {
"line": 1,
"column": 36
}
},
"body": [],
"directives": []
}
}
}
],
"kind": "const"
}
],
"directives": []
}
}