reimplement async function type parameters backfix - fixes #2028

This commit is contained in:
Sebastian McKenzie 2015-07-21 01:13:35 +01:00
parent 0ca73d2474
commit 7f34827a72
4 changed files with 160 additions and 39 deletions

View File

@ -68,6 +68,7 @@ pp.parseExpression = function (noIn, refShorthandDefaultPos) {
while (this.eat(tt.comma)) {
node.expressions.push(this.parseMaybeAssign(noIn, refShorthandDefaultPos));
}
this.toReferencedList(node.expressions);
return this.finishNode(node, "SequenceExpression");
}
return expr;
@ -89,8 +90,9 @@ pp.parseMaybeAssign = function (noIn, refShorthandDefaultPos, afterLeftParse) {
failOnShorthandAssign = false;
}
let startPos = this.start, startLoc = this.startLoc;
if (this.type === tt.parenL || this.type === tt.name)
if (this.type === tt.parenL || this.type === tt.name) {
this.potentialArrowAt = this.start;
}
let left = this.parseMaybeConditional(noIn, refShorthandDefaultPos);
if (afterLeftParse) left = afterLeftParse.call(this, left, startPos, startLoc);
if (this.type.isAssign) {
@ -245,6 +247,8 @@ pp.parseSubscripts = function(base, startPos, startLoc, noCalls) {
if (possibleAsync && (this.type === tt.colon || this.type === tt.arrow)) {
base = this.parseAsyncArrowFromCallExpression(this.startNodeAt(startPos, startLoc), node);
} else {
this.toReferencedList(node.arguments);
}
} else if (this.type === tt.backQuote) {
let node = this.startNodeAt(startPos, startLoc);
@ -323,8 +327,9 @@ pp.parseExprAtom = function (refShorthandDefaultPos) {
}
}
if (canBeArrow && !this.canInsertSemicolon() && this.eat(tt.arrow))
if (canBeArrow && !this.canInsertSemicolon() && this.eat(tt.arrow)) {
return this.parseArrowExpression(node, [id]);
}
return id;
@ -339,7 +344,7 @@ pp.parseExprAtom = function (refShorthandDefaultPos) {
case tt._null: case tt._true: case tt._false:
node = this.startNode();
node.value = this.type === tt._null ? null : this.type === tt._true;
node.rawValue = node.value = this.type === tt._null ? null : this.type === tt._true;
node.raw = this.type.keyword;
this.next();
return this.finishNode(node, "Literal");
@ -355,6 +360,7 @@ pp.parseExprAtom = function (refShorthandDefaultPos) {
return this.parseComprehension(node, false);
}
node.elements = this.parseExprList(tt.bracketR, true, true, refShorthandDefaultPos);
this.toReferencedList(node.elements);
return this.finishNode(node, "ArrayExpression");
case tt.braceL:
@ -446,12 +452,13 @@ pp.parseParenAndDistinguishExpression = function (startPos, startLoc, canBeArrow
exprList.push(this.parseMaybeAssign(false, refShorthandDefaultPos, this.parseParenItem));
}
}
let innerEndPos = this.start, innerEndLoc = this.startLoc;
let innerEndPos = this.start;
let innerEndLoc = this.startLoc;
this.expect(tt.parenR);
if (canBeArrow && !this.canInsertSemicolon() && this.eat(tt.arrow)) {
if (innerParenStart) this.unexpected(innerParenStart);
return this.parseParenArrowList(startPos, startLoc, exprList, isAsync);
return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), exprList, isAsync);
}
if (!exprList.length) {
@ -468,6 +475,7 @@ pp.parseParenAndDistinguishExpression = function (startPos, startLoc, canBeArrow
if (exprList.length > 1) {
val = this.startNodeAt(innerStartPos, innerStartLoc);
val.expressions = exprList;
this.toReferencedList(val.expressions);
this.finishNodeAt(val, "SequenceExpression", innerEndPos, innerEndLoc);
} else {
val = exprList[0];
@ -477,10 +485,6 @@ pp.parseParenAndDistinguishExpression = function (startPos, startLoc, canBeArrow
return val;
};
pp.parseParenArrowList = function (startPos, startLoc, exprList, isAsync) {
return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), exprList, isAsync);
};
pp.parseParenItem = function (node) {
return node;
};
@ -508,6 +512,7 @@ pp.parseNew = function () {
if (this.eat(tt.parenL)) {
node.arguments = this.parseExprList(tt.parenR, this.options.features["es7.trailingFunctionCommas"]);
this.toReferencedList(node.arguments);
} else {
node.arguments = [];
}
@ -742,26 +747,29 @@ pp.parseExprList = function (close, allowTrailingComma, allowEmpty, refShorthand
if (allowTrailingComma && this.afterTrailingComma(close)) break;
}
let elt;
if (allowEmpty && this.type === tt.comma) {
elt = null;
} else if (this.type === tt.ellipsis) {
elt = this.parseSpread(refShorthandDefaultPos);
} else {
elt = this.parseMaybeAssign(false, refShorthandDefaultPos);
}
elts.push(elt);
elts.push(this.parseExprListItem(allowEmpty, refShorthandDefaultPos));
}
return elts;
};
pp.parseExprListItem = function (allowEmpty, refShorthandDefaultPos) {
let elt;
if (allowEmpty && this.type === tt.comma) {
elt = null;
} else if (this.type === tt.ellipsis) {
elt = this.parseSpread(refShorthandDefaultPos);
} else {
elt = this.parseMaybeAssign(false, refShorthandDefaultPos);
}
return elt;
};
// Parse the next token as an identifier. If `liberal` is true (used
// when parsing properties), it will also convert keywords into
// identifiers.
pp.parseIdent = function (liberal) {
let node = this.startNode();
if (liberal && this.options.allowReserved === "never") liberal = false;
if (this.type === tt.name) {
if (!liberal &&
((!this.options.allowReserved && this.isReservedWord(this.value)) ||

View File

@ -75,6 +75,12 @@ pp.toAssignableList = function (exprList, isBinding) {
return exprList;
};
// Convert list of expression atoms to a list of
pp.toReferencedList = function (exprList) {
return exprList;
};
// Parses spread element.
pp.parseSpread = function (refShorthandDefaultPos) {

View File

@ -3,18 +3,6 @@ import { Parser } from "../state";
var pp = Parser.prototype;
pp.isRelational = function (op) {
return this.type === tt.relational && this.value === op;
};
pp.expectRelational = function (op) {
if (this.isRelational(op)) {
this.next();
} else {
this.unexpected();
}
};
pp.flowParseTypeInitialiser = function (tok) {
var oldInType = this.inType;
this.inType = true;
@ -707,17 +695,55 @@ export default function (instance) {
};
});
instance.extend("parseParenArrowList", function (inner) {
return function (startPos, startLoc, exprList, isAsync) {
function typeCastToParameter(node) {
node.expression.typeAnnotation = node.typeAnnotation;
return node.expression;
}
instance.extend("toAssignableList", function (inner) {
return function (exprList, isBinding) {
for (var i = 0; i < exprList.length; i++) {
var listItem = exprList[i];
if (listItem.type === "TypeCastExpression") {
var expr = listItem.expression;
expr.typeAnnotation = listItem.typeAnnotation;
exprList[i] = expr;
var expr = exprList[i];
if (expr && expr.type === "TypeCastExpression") {
exprList[i] = typeCastToParameter(expr);
}
}
return inner.call(this, startPos, startLoc, exprList, isAsync);
return inner.call(this, exprList, isBinding);
};
});
instance.extend("toReferencedList", function () {
return function (exprList) {
var foundTypeCast = false;
for (var i = 0; i < exprList.length; i++) {
var expr = exprList[i];
if (expr && expr._exprListItem && expr.type === "TypeCastExpression") {
if (foundTypeCast) {
this.unexpected(expr.start, "Unexpected type cast");
} else {
foundTypeCast = true;
}
}
}
return exprList;
};
});
instance.extend("parseExprListItem", function (inner) {
return function (allowEmpty, refShorthandDefaultPos) {
var node = inner.call(this, allowEmpty, refShorthandDefaultPos);
if (this.type === tt.colon) {
return {
type: "TypeCastExpression",
_exprListItem: true,
expression: node,
typeAnnotation: this.flowParseTypeAnnotation()
};
} else {
return node;
}
};
});

View File

@ -5971,6 +5971,86 @@ var fbTestFixture = {
}
}]
},
"var foo = async (foo: bar, bar: foo) => {}": {
type: "VariableDeclaration",
kind: "var",
start: 0,
end: 42,
declarations: [{
type: "VariableDeclarator",
start: 4,
end: 42,
id: {
type: "Identifier",
start: 4,
end: 7,
name: "foo"
},
init: {
type: "ArrowFunctionExpression",
start: 10,
end: 42,
id: null,
generator: false,
expression: false,
async: true,
params: [
{
type: "Identifier",
start: 17,
end: 20,
name: "foo",
typeAnnotation: {
type: "TypeAnnotation",
start: 20,
end: 25,
typeAnnotation: {
type: "GenericTypeAnnotation",
start: 22,
end: 25,
typeParameters: null,
id: {
type: "Identifier",
start: 22,
end: 25,
name: "bar"
}
}
}
},
{
type: "Identifier",
start: 27,
end: 30,
name: "bar",
typeAnnotation: {
type: "TypeAnnotation",
start: 30,
end: 35,
typeAnnotation: {
type: "GenericTypeAnnotation",
start: 32,
end: 35,
typeParameters: null,
id: {
type: "Identifier",
start: 32,
end: 35,
name: "foo"
}
}
}
}
],
body: {
type: "BlockStatement",
start: 40,
end: 42,
body: []
}
}
}]
},
"var foo = async (): number => bar;": {
type: "VariableDeclaration",
kind: "var",
@ -11978,6 +12058,7 @@ var fbTestFixture = {
if (typeof exports !== "undefined") {
var test = require("./driver.js").test;
var testFail = require("./driver.js").testFail;
}
for (var ns in fbTestFixture) {