Better async/await support

This commit is contained in:
Richard Eames 2014-11-18 13:08:24 -07:00
parent 61810eef8d
commit 68acfb7cc5
3 changed files with 674 additions and 158 deletions

View File

@ -2028,8 +2028,9 @@
if (options.ecmaVersion < 7) {
unexpected();
}
next();
var start = storeCurrentPos();
var retNode = startNodeAt(start);
var finishedAsync = parseIdent(true);
switch (tokType) {
case _function:
@ -2057,11 +2058,37 @@
if (metParenL === oldParenL && eat(_arrow)) {
return parseArrowExpression(node, exprList, true);
}
retNode.callee = finishedAsync;
retNode.arguments = exprList;
retNode = parseSubscripts(finishNode(retNode, "CallExpression"), start);
break;
default:
if (isStatement) {
if (tokType.beforeExpr) {
// Probably using async as an ident
if (tokType.isAssign) {
retNode.operator = tokVal;
retNode.left = tokType === _eq ? toAssignable(finishedAsync) : finishedAsync;
checkLVal(finishedAsync);
next();
retNode.right = parseMaybeAssign();
retNode = finishNode(retNode, "AssignmentExpression");
}
else {
unexpected
}
semicolon();
}
else {
unexpected();
}
}
else {
retNode = finishedAsync;
}
}
return retNode;
}
function parseIfStatement(node) {
next();
@ -2615,19 +2642,65 @@
} else first = false;
var prop = startNode(), isGenerator, isAsync;
if (options.ecmaVersion >= 7) {
isAsync = eat(_async);
if (isAsync && tokType === _star) unexpected();
if (tokType == _async) { // "async" is a valid key
prop.computed = false;
prop.key = parseIdent(true);
isAsync = true;
}
if (options.ecmaVersion >= 6) {
isGenerator = eat(_star);
}
if (tokType === _name || tokType.keyword) {
// possibly an async function
if (isAsync && options.ecmaVersion < 7) {
unexpected();
}
if (isAsync && isGenerator) {
unexpected();
}
if (options.ecmaVersion >= 6) {
prop.method = false;
prop.shorthand = false;
isGenerator = eat(_star);
}
parsePropertyName(prop);
}
else if (tokType === _colon) {
// key could be "async"
if (options.ecmaVersion >= 6) {
prop.method = false;
prop.shorthand = false;
}
isAsync = false;
}
else if (tokType === _bracketL) {
// could be async computed
if (isAsync && isGenerator) {
unexpected();
}
parsePropertyName(prop);
}
else if (tokType === _braceR) {
// object unpack, and key could be == "async"
if (isAsync) {
isAsync = false;
prop.computed = false;
}
else {
parsePropertyName(prop);
}
}
else {
//unexpected();
isAsync = false;
parsePropertyName(prop);
}
if (eat(_colon)) {
prop.value = parseExpression(true);
prop.kind = "init";
if (isAsync) {
unexpected();
}
} else if (options.ecmaVersion >= 6 && tokType === _parenL) {
prop.kind = "init";
prop.method = true;

View File

@ -20,6 +20,7 @@ for (var i = 2; i < process.argv.length; ++i) {
else if (arg == "--ecma3") options.ecmaVersion = 3;
else if (arg == "--ecma5") options.ecmaVersion = 5;
else if (arg == "--ecma6") options.ecmaVersion = 6;
else if (arg == "--ecma7") options.ecmaVersion = 7;
else if (arg == "--strictSemicolons") options.strictSemicolons = true;
else if (arg == "--locations") options.locations = true;
else if (arg == "--silent") silent = true;

View File

@ -14371,81 +14371,170 @@ test('f(async function(promise) { await promise })', {
});
test("f(a, async(1, 2), b);", {
type: "Program",
body: [{
type: "ExpressionStatement",
expression: {
type: "CallExpression",
callee: {
type: "Identifier",
name: "f",
loc: {
start: {line: 1, column: 0},
end: {line: 1, column: 1}
"type": "Program",
"start": 0,
"end": 21,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 21
}
},
arguments: [
"body": [
{
type: "Identifier",
name: "a",
loc: {
start: {line: 1, column: 2},
end: {line: 1, column: 3}
"type": "ExpressionStatement",
"start": 0,
"end": 21,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 21
}
},
"expression": {
"type": "CallExpression",
"start": 0,
"end": 20,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 20
}
},
"callee": {
"type": "Identifier",
"start": 0,
"end": 1,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 1
}
},
"name": "f"
},
"arguments": [
{
"type": "Identifier",
"start": 2,
"end": 3,
"loc": {
"start": {
"line": 1,
"column": 2
},
"end": {
"line": 1,
"column": 3
}
},
"name": "a"
},
{
type: "CallExpression",
callee: {
type: "Identifier",
name: "async",
loc: {
start: {line: 1, column: 5},
end: {line: 1, column: 10}
"type": "CallExpression",
"start": 5,
"end": 16,
"loc": {
"start": {
"line": 1,
"column": 5
},
"end": {
"line": 1,
"column": 16
}
},
arguments: [
{
type: "Literal",
value: 1,
loc: {
start: {line: 1,column: 11},
end: {line: 1,column: 12}
"callee": {
"type": "Identifier",
"start": 5,
"end": 10,
"loc": {
"start": {
"line": 1,
"column": 5
},
"end": {
"line": 1,
"column": 10
}
},
"name": "async"
},
"arguments": [
{
"type": "Literal",
"start": 11,
"end": 12,
"loc": {
"start": {
"line": 1,
"column": 11
},
"end": {
"line": 1,
"column": 12
}
},
"value": 1,
"raw": "1"
},
{
type: "Literal",
value: 2,
loc: {
start: {line: 1,column: 14},
end: {line: 1,column: 15}
"type": "Literal",
"start": 14,
"end": 15,
"loc": {
"start": {
"line": 1,
"column": 14
},
"end": {
"line": 1,
"column": 15
}
},
"value": 2,
"raw": "2"
}
],
loc: {
start: {line: 1,column: 5},
end: {line: 1,column: 16}
}
]
},
{
type: "Identifier",
name: "b",
loc: {
start: {line: 1,column: 18},
end: {line: 1,column: 19}
}
}
],
loc: {
start: {line: 1,column: 0},
end: {line: 1,column: 20}
"type": "Identifier",
"start": 18,
"end": 19,
"loc": {
"start": {
"line": 1,
"column": 18
},
"end": {
"line": 1,
"column": 19
}
},
loc: {
start: {line: 1,column: 0},
end: {line: 1,column: 20}
"name": "b"
}
}]
}, {
]
}
}
]
}
, {
ecmaVersion: 7,
locations: true
});
@ -14499,7 +14588,7 @@ test("var ok = async(x);", {
kind: "var",
loc: {
start: {line: 1,column: 0},
end: {line: 1,column: 17}
end: {line: 1,column: 18}
}
}]
}, {
@ -14508,98 +14597,448 @@ test("var ok = async(x);", {
});
test("var async; async = 10;", {
type: "Program",
body: [{
type: "ExpressionStatement",
expression: {
type: "FunctionExpression",
id: null,
params: [],
defaults: [],
body: {
type: "BlockStatement",
body: [
{
type: "VariableDeclaration",
declarations: [
{
type: "VariableDeclarator",
id: {
type: "Identifier",
name: "async",
loc: {
start: {line: 1,column: 18},
end: {line: 1,column: 23}
"type": "Program",
"start": 0,
"end": 22,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 22
}
},
init: null,
loc: {
start: {line: 1,column: 18},
end: {line: 1,column: 23}
"body": [
{
"type": "VariableDeclaration",
"start": 0,
"end": 10,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 10
}
},
"declarations": [
{
"type": "VariableDeclarator",
"start": 4,
"end": 9,
"loc": {
"start": {
"line": 1,
"column": 4
},
"end": {
"line": 1,
"column": 9
}
},
"id": {
"type": "Identifier",
"start": 4,
"end": 9,
"loc": {
"start": {
"line": 1,
"column": 4
},
"end": {
"line": 1,
"column": 9
}
},
"name": "async"
},
"init": null
}
],
kind: "var",
loc: {
start: {line: 1,column: 14},
end: {line: 1,column: 24}
}
"kind": "var"
},
{
type: "ExpressionStatement",
expression: {
type: "AssignmentExpression",
operator: "=",
left: {
type: "Identifier",
name: "async",
loc: {
start: {line: 1,column: 25},
end: {line: 1,column: 30}
"type": "AssignmentExpression",
"start": 11,
"end": 21,
"loc": {
"start": {
"line": 1,
"column": 11
},
"end": {
"line": 1,
"column": 21
}
},
right: {
type: "Literal",
value: 10,
loc: {
start: {line: 1,column: 33},
end: {line: 1,column: 35}
"operator": "=",
"left": {
"type": "Identifier",
"start": 11,
"end": 16,
"loc": {
"start": {
"line": 1,
"column": 11
},
"end": {
"line": 1,
"column": 16
}
},
loc: {
start: {line: 1,column: 25},
end: {line: 1,column: 35}
"name": "async"
},
"right": {
"type": "Literal",
"start": 19,
"end": 21,
"loc": {
"start": {
"line": 1,
"column": 19
},
"end": {
"line": 1,
"column": 21
}
},
loc: {
start: {line: 1,column: 25},
end: {line: 1,column: 36}
"value": 10,
"raw": "10"
}
}
],
loc: {
start: {line: 1,column: 12},
end: {line: 1,column: 37}
}
},
rest: null,
generator: false,
expression: false,
loc: {
start: {line: 1,column: 1},
end: {line: 1,column: 37}
}
},
loc: {
start: {line: 1,column: 0},
end: {line: 1,column: 38}
}
}]
]
}, {
ecmaVersion: 7,
locations: true
});
test("var {a, async} = b;" {
"type": "Program",
"start": 0,
"end": 19,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 19
}
},
"body": [
{
"type": "VariableDeclaration",
"start": 0,
"end": 19,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 19
}
},
"declarations": [
{
"type": "VariableDeclarator",
"start": 4,
"end": 18,
"loc": {
"start": {
"line": 1,
"column": 4
},
"end": {
"line": 1,
"column": 18
}
},
"id": {
"type": "ObjectPattern",
"start": 4,
"end": 14,
"loc": {
"start": {
"line": 1,
"column": 4
},
"end": {
"line": 1,
"column": 14
}
},
"properties": [
{
"type": "Property",
"start": 5,
"end": 6,
"loc": {
"start": {
"line": 1,
"column": 5
},
"end": {
"line": 1,
"column": 6
}
},
"method": false,
"shorthand": true,
"computed": false,
"key": {
"type": "Identifier",
"start": 5,
"end": 6,
"loc": {
"start": {
"line": 1,
"column": 5
},
"end": {
"line": 1,
"column": 6
}
},
"name": "a"
},
"kind": "init",
"value": {
"type": "Identifier",
"start": 5,
"end": 6,
"loc": {
"start": {
"line": 1,
"column": 5
},
"end": {
"line": 1,
"column": 6
}
},
"name": "a"
}
},
{
"type": "Property",
"start": 8,
"end": 13,
"loc": {
"start": {
"line": 1,
"column": 8
},
"end": {
"line": 1,
"column": 13
}
},
"computed": false,
"key": {
"type": "Identifier",
"start": 8,
"end": 13,
"loc": {
"start": {
"line": 1,
"column": 8
},
"end": {
"line": 1,
"column": 13
}
},
"name": "async"
},
"kind": "init",
"value": {
"type": "Identifier",
"start": 8,
"end": 13,
"loc": {
"start": {
"line": 1,
"column": 8
},
"end": {
"line": 1,
"column": 13
}
},
"name": "async"
},
"shorthand": true
}
]
},
"init": {
"type": "Identifier",
"start": 17,
"end": 18,
"loc": {
"start": {
"line": 1,
"column": 17
},
"end": {
"line": 1,
"column": 18
}
},
"name": "b"
}
}
],
"kind": "var"
}
]
}, {
ecmaVersion: 7,
locations: true
});
test("var x = { async: true };", {
"type": "Program",
"start": 0,
"end": 24,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 24
}
},
"body": [
{
"type": "VariableDeclaration",
"start": 0,
"end": 24,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 24
}
},
"declarations": [
{
"type": "VariableDeclarator",
"start": 4,
"end": 23,
"loc": {
"start": {
"line": 1,
"column": 4
},
"end": {
"line": 1,
"column": 23
}
},
"id": {
"type": "Identifier",
"start": 4,
"end": 5,
"loc": {
"start": {
"line": 1,
"column": 4
},
"end": {
"line": 1,
"column": 5
}
},
"name": "x"
},
"init": {
"type": "ObjectExpression",
"start": 8,
"end": 23,
"loc": {
"start": {
"line": 1,
"column": 8
},
"end": {
"line": 1,
"column": 23
}
},
"properties": [
{
"type": "Property",
"start": 10,
"end": 21,
"loc": {
"start": {
"line": 1,
"column": 10
},
"end": {
"line": 1,
"column": 21
}
},
"computed": false,
"key": {
"type": "Identifier",
"start": 10,
"end": 15,
"loc": {
"start": {
"line": 1,
"column": 10
},
"end": {
"line": 1,
"column": 15
}
},
"name": "async"
},
"method": false,
"shorthand": false,
"value": {
"type": "Literal",
"start": 17,
"end": 21,
"loc": {
"start": {
"line": 1,
"column": 17
},
"end": {
"line": 1,
"column": 21
}
},
"value": true,
"raw": "true"
},
"kind": "init"
}
]
}
}
],
"kind": "var"
}
]
}, {ecmaVersion: 7, locations: true});
// Harmony Invalid syntax
testFail("0o", "Expected number in radix 8 (1:2)", {ecmaVersion: 6});
@ -14716,6 +15155,9 @@ testFail("function foo(promise) { await promise; }", "Unexpected token (1:30)",
testFail("async function* foo(promise) { await promise; }", "Unexpected token (1:14)", {ecmaVersion: 7});
testFail("var a = { async ['a']: true }", "Unexpected token (1:28)", {ecmaVersion: 7});
testFail("var a = { async *['a'](){} }", "Unexpected token (1:17)", {ecmaVersion: 7});
testFail("yield v", "Unexpected token (1:6)", {ecmaVersion: 6});
testFail("yield 10", "Unexpected token (1:6)", {ecmaVersion: 6});