diff --git a/acorn.js b/acorn.js index 0205d2e25f..f9321ecfe7 100644 --- a/acorn.js +++ b/acorn.js @@ -167,13 +167,7 @@ if (options.strictMode) { strict = true; } - if (options.ecmaVersion >= 7) { - isKeyword = isEcma7Keyword; - } else if (options.ecmaVersion === 6) { - isKeyword = isEcma6Keyword; - } else { - isKeyword = isEcma5AndLessKeyword; - } + isKeyword = options.ecmaVersion >= 6 ? isEcma6Keyword : isEcma5AndLessKeyword; } // The `getLineInfo` function is mostly useful when the @@ -298,7 +292,7 @@ // that `break` and `continue` have somewhere to jump to, and // `strict` indicates whether strict mode is on. - var inFunction, inGenerator, inAsync, labels, strict, + var inFunction, inGenerator, labels, strict, inXJSChild, inXJSTag, inXJSChildExpression; // This counter is used for checking that arrow expressions did @@ -315,7 +309,7 @@ function initParserState() { lastStart = lastEnd = tokPos; if (options.locations) lastEndLoc = new Position; - inFunction = inGenerator = inAsync = strict = false; + inFunction = inGenerator = strict = false; labels = []; readToken(); } @@ -382,7 +376,6 @@ var _class = {keyword: "class"}, _extends = {keyword: "extends", beforeExpr: true}; var _export = {keyword: "export"}, _import = {keyword: "import"}; var _yield = {keyword: "yield", beforeExpr: true}; - var _async = {keyword: "async"}, _await = {keyword: "await", beforeExpr: true}; // The keywords that denote values. @@ -409,8 +402,7 @@ "void": {keyword: "void", prefix: true, beforeExpr: true}, "delete": {keyword: "delete", prefix: true, beforeExpr: true}, "class": _class, "extends": _extends, - "export": _export, "import": _import, "yield": _yield, - "await": _await, "async": _async}; + "export": _export, "import": _import, "yield": _yield}; // Punctuation token types. Again, the `type` property is purely for debugging. @@ -538,11 +530,7 @@ var isEcma5AndLessKeyword = makePredicate(ecma5AndLessKeywords); - var ecma6AndLessKeywords = ecma5AndLessKeywords + " let const class extends export import yield"; - - var isEcma6Keyword = makePredicate(ecma6AndLessKeywords); - - var isEcma7Keyword = makePredicate(ecma6AndLessKeywords + " async await"); + var isEcma6Keyword = makePredicate(ecma5AndLessKeywords + " let const class extends export import yield"); var isKeyword = isEcma5AndLessKeyword; @@ -1908,7 +1896,6 @@ case _debugger: return parseDebuggerStatement(node); case _do: return parseDoStatement(node); case _for: return parseForStatement(node); - case _async: return parseAsync(node, true); case _function: return parseFunctionStatement(node); case _class: return parseClass(node, true); case _if: return parseIfStatement(node); @@ -2010,46 +1997,7 @@ function parseFunctionStatement(node) { next(); - return parseFunction(node, true, false); - } - - function parseAsync(node, isStatement) { - if (options.ecmaVersion < 7) { - unexpected(); - } - - next(); - - switch (tokType) { - case _function: - next(); - return parseFunction(node, isStatement, true); - - if (!isStatement) unexpected(); - - case _name: - var id = parseIdent(tokType !== _name); - if (eat(_arrow)) { - return parseArrowExpression(node, [id], true); - } - - case _parenL: - var oldParenL = ++metParenL; - var exprList = []; - next(); - if (tokType !== _parenR) { - var val = parseExpression(); - exprList = val.type === "SequenceExpression" ? val.expressions : [val]; - } - expect(_parenR); - // if '=>' follows '(...)', convert contents to arguments - if (metParenL === oldParenL && eat(_arrow)) { - return parseArrowExpression(node, exprList, true); - } - - default: - unexpected(); - } + return parseFunction(node, true); } function parseIfStatement(node) { @@ -2432,9 +2380,6 @@ case _yield: if (inGenerator) return parseYield(); - case _await: - if (inAsync) return parseAwait(); - case _name: var start = storeCurrentPos(); var id = parseIdent(tokType !== _name); @@ -2516,13 +2461,10 @@ case _braceL: return parseObj(); - case _async: - return parseAsync(startNode(), false); - case _function: var node = startNode(); next(); - return parseFunction(node, false, false); + return parseFunction(node, false); case _class: return parseClass(startNode(), false); @@ -2610,11 +2552,7 @@ if (options.allowTrailingCommas && eat(_braceR)) break; } else first = false; - var prop = startNode(), isGenerator, isAsync; - if (options.ecmaVersion >= 7) { - isAsync = eat(_async); - if (tokType === _star) unexpected(); - } + var prop = startNode(), isGenerator; if (options.ecmaVersion >= 6) { prop.method = false; prop.shorthand = false; @@ -2627,13 +2565,13 @@ } else if (options.ecmaVersion >= 6 && tokType === _parenL) { prop.kind = "init"; prop.method = true; - prop.value = parseMethod(isGenerator, isAsync); + prop.value = parseMethod(isGenerator); } else if (options.ecmaVersion >= 5 && !prop.computed && prop.key.type === "Identifier" && (prop.key.name === "get" || prop.key.name === "set")) { - if (isGenerator || isAsync) unexpected(); + if (isGenerator) unexpected(); prop.kind = prop.key.name; parsePropertyName(prop); - prop.value = parseMethod(false, false); + prop.value = parseMethod(false); } else if (options.ecmaVersion >= 6 && !prop.computed && prop.key.type === "Identifier") { prop.kind = "init"; prop.value = prop.key; @@ -2662,26 +2600,22 @@ // Initialize empty function node. - function initFunction(node, isAsync) { + function initFunction(node) { node.id = null; node.params = []; if (options.ecmaVersion >= 6) { node.defaults = []; node.rest = null; node.generator = false; - } - if (options.ecmaVersion >= 7) { - node.async = isAsync; - } + } } // Parse a function declaration or literal (depending on the // `isStatement` parameter). - function parseFunction(node, isStatement, isAsync, allowExpressionBody) { - initFunction(node, isAsync); + function parseFunction(node, isStatement, allowExpressionBody) { + initFunction(node); if (options.ecmaVersion >= 6) { - if (node.async && tokType === _star) unexpected(); node.generator = eat(_star); } if (isStatement || tokType === _name) { @@ -2694,9 +2628,9 @@ // Parse object or class method. - function parseMethod(isGenerator, isAsync) { + function parseMethod(isGenerator) { var node = startNode(); - initFunction(node, isAsync); + initFunction(node); parseFunctionParams(node); var allowExpressionBody; if (options.ecmaVersion >= 6) { @@ -2711,8 +2645,8 @@ // Parse arrow function expression with given parameters. - function parseArrowExpression(node, params, isAsync) { - initFunction(node, isAsync); + function parseArrowExpression(node, params) { + initFunction(node); var defaults = node.defaults, hasDefaults = false; @@ -2780,9 +2714,7 @@ function parseFunctionBody(node, allowExpression) { var isExpression = allowExpression && tokType !== _braceL; - - var oldInAsync = inAsync; - inAsync = node.async; + if (isExpression) { node.body = parseExpression(true); node.expression = true; @@ -2795,7 +2727,6 @@ node.expression = false; inFunction = oldInFunc; inGenerator = oldInGen; labels = oldLabels; } - inAsync = oldInAsync; // If this is a strict mode function, verify that argument names // are not repeated, and it does not try to bind the words `eval` @@ -2829,22 +2760,17 @@ } else { method['static'] = false; } - var isAsync = false; - if (options.ecmaVersion >= 7) { - isAsync = eat(_async); - if (tokType === _star) unexpected(); - } var isGenerator = eat(_star); parsePropertyName(method); if (tokType !== _parenL && !method.computed && method.key.type === "Identifier" && (method.key.name === "get" || method.key.name === "set")) { - if (isGenerator || isAsync) unexpected(); + if (isGenerator) unexpected(); method.kind = method.key.name; parsePropertyName(method); } else { method.kind = ""; } - method.value = parseMethod(isGenerator, isAsync); + method.value = parseMethod(isGenerator); classBody.body.push(finishNode(method, "MethodDefinition")); eat(_semi); } @@ -3049,19 +2975,6 @@ return finishNode(node, "YieldExpression"); } - // Parses await expression inside async function. - - function parseAwait() { - var node = startNode(); - next(); - if (eat(_semi) || canInsertSemicolon()) { - unexpected(); - } - node.delegate = eat(_star); - node.argument = parseExpression(true); - return finishNode(node, "AwaitExpression"); - } - // Parses array and generator comprehensions. function parseComprehension(node, isGenerator) { diff --git a/test/tests-harmony.js b/test/tests-harmony.js index abe47b1d0f..2302f58f60 100644 --- a/test/tests-harmony.js +++ b/test/tests-harmony.js @@ -13558,771 +13558,6 @@ test("/[a-z]/u", { ecmaVersion: 6 }); -// ES7: Async Functions - -test('async function foo(promise) { await promise; }', { - type: "Program", - body: [{ - type: "FunctionDeclaration", - id: { - type: "Identifier", - name: "foo", - loc: { - start: {line: 1, column: 15}, - end: {line: 1, column: 18} - } - }, - params: [{ - type: "Identifier", - name: "promise", - loc: { - start: {line: 1, column: 19}, - end: {line: 1, column: 26} - } - }], - defaults: [], - body: { - type: "BlockStatement", - body: [{ - type: "ExpressionStatement", - expression: { - type: "AwaitExpression", - argument: { - type: "Identifier", - name: "promise", - loc: { - start: {line: 1, column: 36}, - end: {line: 1, column: 43} - } - }, - loc: { - start: {line: 1, column: 30}, - end: {line: 1, column: 43} - } - }, - loc: { - start: {line: 1, column: 30}, - end: {line: 1, column: 44} - } - }], - loc: { - start: {line: 1, column: 28}, - end: {line: 1, column: 46} - } - }, - rest: null, - generator: false, - expression: false, - async: true, - loc: { - start: {line: 1, column: 0}, - end: {line: 1, column: 46} - } - }] -}, { - ecmaVersion: 7, - locations: true -}); - -test('(function(x) { async function inner() { await x } })', { - type: "Program", - body: [{ - type: "ExpressionStatement", - expression: { - type: "FunctionExpression", - id: null, - params: [ - { - type: "Identifier", - name: "x", - loc: { - start: {line: 1, column: 10}, - end: {line: 1, column: 11} - } - } - ], - defaults: [], - body: { - type: "BlockStatement", - body: [ - { - type: "FunctionDeclaration", - id: { - type: "Identifier", - name: "inner", - loc: { - start: {line: 1, column: 30}, - end: {line: 1, column: 35} - } - }, - params: [], - defaults: [], - body: { - type: "BlockStatement", - body: [ - { - type: "ExpressionStatement", - expression: { - type: "AwaitExpression", - argument: { - type: "Identifier", - name: "x", - loc: { - start: {line: 1, column: 46}, - end: {line: 1, column: 47} - } - }, - loc: { - start: {line: 1, column: 40}, - end: {line: 1, column: 47} - } - }, - loc: { - start: {line: 1, column: 40}, - end: {line: 1, column: 47} - } - } - ], - loc: { - start: {line: 1, column: 38}, - end: {line: 1, column: 49} - } - }, - rest: null, - generator: false, - expression: false, - async: true, - loc: { - start: {line: 1, column: 15}, - end: {line: 1, column: 49} - } - } - ], - loc: { - start: {line: 1, column: 13}, - end: {line: 1, column: 51} - } - }, - rest: null, - generator: false, - expression: false, - loc: { - start: {line: 1, column: 1}, - end: {line: 1, column: 51} - } - }, - loc: { - start: {line: 1, column: 0}, - end: {line: 1, column: 52} - } - }] -}, { - ecmaVersion: 7, - locations: true -}); - -test('var foo = async function(promise) { await promise; }', { - type: "Program", - body: [{ - type: "VariableDeclaration", - declarations: [ - { - type: "VariableDeclarator", - id: { - type: "Identifier", - name: "foo", - loc: { - start: {line: 1, column: 4}, - end: {line: 1, column: 7} - } - }, - init: { - type: "FunctionExpression", - id: null, - params: [ - { - type: "Identifier", - name: "promise", - loc: { - start: {line: 1, column: 25}, - end: {line: 1, column: 32} - } - } - ], - defaults: [], - body: { - type: "BlockStatement", - body: [ - { - type: "ExpressionStatement", - expression: { - type: "AwaitExpression", - argument: { - type: "Identifier", - name: "promise", - loc: { - start: {line: 1, column: 42}, - end: {line: 1, column: 49} - } - }, - loc: { - start: {line: 1, column: 36}, - end: {line: 1, column: 49} - } - }, - loc: { - start: {line: 1, column: 36}, - end: {line: 1, column: 50} - } - } - ], - loc: { - start: {line: 1, column: 34}, - end: {line: 1, column: 52} - } - }, - rest: null, - generator: false, - expression: false, - async: true, - loc: { - start: {line: 1, column: 10}, - end: {line: 1, column: 52} - } - }, - loc: { - start: {line: 1, column: 4}, - end: {line: 1, column: 52} - } - } - ], - kind: "var", - loc: { - start: {line: 1, column: 0}, - end: {line: 1, column: 52} - } - }] -}, { - ecmaVersion: 7, - locations: true -}); - -test('var o = { a: 1, async foo(promise) { await promise } }', { - type: "Program", - body: [{ - type: "VariableDeclaration", - declarations: [ - { - type: "VariableDeclarator", - id: { - type: "Identifier", - name: "o", - loc: { - start: {line: 1, column: 4}, - end: {line: 1, column: 5} - } - }, - init: { - type: "ObjectExpression", - properties: [ - { - type: "Property", - key: { - type: "Identifier", - name: "a", - loc: { - start: {line: 1, column: 10}, - end: {line: 1, column: 11} - } - }, - value: { - type: "Literal", - value: 1, - loc: { - start: {line: 1, column: 13}, - end: {line: 1, column: 14} - } - }, - kind: "init", - method: false, - shorthand: false, - computed: false, - loc: { - start: {line: 1, column: 10}, - end: {line: 1, column: 14} - } - }, - { - type: "Property", - key: { - type: "Identifier", - name: "foo", - loc: { - start: {line: 1, column: 22}, - end: {line: 1, column: 25} - } - }, - value: { - type: "FunctionExpression", - id: null, - params: [ - { - type: "Identifier", - name: "promise", - loc: { - start: {line: 1, column: 26}, - end: {line: 1, column: 33} - } - } - ], - defaults: [], - body: { - type: "BlockStatement", - body: [ - { - type: "ExpressionStatement", - expression: { - type: "AwaitExpression", - argument: { - type: "Identifier", - name: "promise", - loc: { - start: {line: 1, column: 43}, - end: {line: 1, column: 50} - } - }, - loc: { - start: {line: 1, column: 37}, - end: {line: 1, column: 50} - } - }, - loc: { - start: {line: 1, column: 37}, - end: {line: 1, column: 50} - } - } - ], - loc: { - start: {line: 1, column: 35}, - end: {line: 1, column: 52} - } - }, - rest: null, - generator: false, - expression: false, - async: true, - loc: { - start: {line: 1, column: 25}, - end: {line: 1, column: 52} - } - }, - kind: "init", - method: true, - shorthand: false, - computed: false, - loc: { - start: {line: 1, column: 16}, - end: {line: 1, column: 52} - } - } - ], - loc: { - start: {line: 1, column: 8}, - end: {line: 1, column: 54} - } - }, - loc: { - start: {line: 1, column: 4}, - end: {line: 1, column: 54} - } - } - ], - kind: "var", - loc: { - start: {line: 1, column: 0}, - end: {line: 1, column: 54} - } - }] -}, { - ecmaVersion: 7, - locations: true -}); - -test('class Foo { async bar(promise) { await promise } }', { - type: "Program", - body: [{ - type: "ClassDeclaration", - id: { - type: "Identifier", - name: "Foo", - loc: { - start: {line: 1, column: 6}, - end: {line: 1, column: 9} - } - }, - superClass: null, - body: { - type: "ClassBody", - body: [ - { - type: "MethodDefinition", - key: { - type: "Identifier", - name: "bar", - loc: { - start: {line: 1, column: 18}, - end: {line: 1, column: 21} - } - }, - value: { - type: "FunctionExpression", - id: null, - params: [ - { - type: "Identifier", - name: "promise", - loc: { - start: {line: 1, column: 22}, - end: {line: 1, column: 29} - } - } - ], - defaults: [], - body: { - type: "BlockStatement", - body: [ - { - type: "ExpressionStatement", - expression: { - type: "AwaitExpression", - argument: { - type: "Identifier", - name: "promise", - loc: { - start: {line: 1, column: 39}, - end: {line: 1, column: 46} - } - }, - loc: { - start: {line: 1, column: 33}, - end: {line: 1, column: 46} - } - }, - loc: { - start: {line: 1, column: 33}, - end: {line: 1, column: 46} - } - } - ], - loc: { - start: {line: 1, column: 31}, - end: {line: 1, column: 48} - } - }, - rest: null, - generator: false, - expression: false, - async: true, - loc: { - start: {line: 1, column: 21}, - end: {line: 1, column: 48} - } - }, - kind: "", - static: false, - loc: { - start: {line: 1, column: 12}, - end: {line: 1, column: 48} - } - } - ], - loc: { - start: {line: 1, column: 10}, - end: {line: 1, column: 50} - } - }, - loc: { - start: {line: 1, column: 0}, - end: {line: 1, column: 50} - } - }] -}, { - ecmaVersion: 7, - locations: true -}); - -test('f(a, async promise => await promise)', { - type: "Program", - body: [{ - type: "ExpressionStatement", - expression: { - type: "CallExpression", - callee: { - type: "Identifier", - name: "f", - loc: { - start: {line: 1, column: 0}, - end: {line: 1, column: 1} - } - }, - arguments: [ - { - type: "Identifier", - name: "a", - loc: { - start: {line: 1, column: 2}, - end: {line: 1, column: 3} - } - }, - { - type: "ArrowFunctionExpression", - id: null, - params: [ - { - type: "Identifier", - name: "promise", - loc: { - start: {line: 1, column: 11}, - end: {line: 1, column: 18} - } - } - ], - defaults: [], - body: { - type: "AwaitExpression", - argument: { - type: "Identifier", - name: "promise", - loc: { - start: {line: 1, column: 28}, - end: {line: 1, column: 35} - } - }, - loc: { - start: {line: 1, column: 22}, - end: {line: 1, column: 35} - } - }, - rest: null, - generator: false, - expression: true, - async: true, - loc: { - start: {line: 1, column: 5}, - end: {line: 1, column: 35} - } - } - ], - loc: { - start: {line: 1, column: 0}, - end: {line: 1, column: 36} - } - }, - loc: { - start: {line: 1, column: 0}, - end: {line: 1, column: 36} - } - }] -}, { - ecmaVersion: 7, - locations: true -}); - -test('f(a, async(x, y) => await [x, y], 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} - } - }, - arguments: [ - { - type: "Identifier", - name: "a", - loc: { - start: {line: 1, column: 2}, - end: {line: 1, column: 3} - } - }, - { - type: "ArrowFunctionExpression", - id: null, - params: [ - { - type: "Identifier", - name: "x", - loc: { - start: {line: 1, column: 11}, - end: {line: 1, column: 12} - } - }, - { - type: "Identifier", - name: "y", - loc: { - start: {line: 1, column: 14}, - end: {line: 1, column: 15} - } - } - ], - defaults: [], - body: { - type: "AwaitExpression", - argument: { - type: "ArrayExpression", - elements: [ - { - type: "Identifier", - name: "x", - loc: { - start: {line: 1, column: 27}, - end: {line: 1, column: 28} - } - }, - { - type: "Identifier", - name: "y", - loc: { - start: {line: 1, column: 30}, - end: {line: 1, column: 31} - } - } - ], - loc: { - start: {line: 1, column: 26}, - end: {line: 1, column: 32} - } - }, - loc: { - start: {line: 1, column: 20}, - end: {line: 1, column: 32} - } - }, - rest: null, - generator: false, - expression: true, - async: true, - loc: { - start: {line: 1, column: 5}, - end: {line: 1, column: 32} - } - }, - { - type: "Identifier", - name: "b", - loc: { - start: {line: 1, column: 34}, - end: {line: 1, column: 35} - } - } - ], - loc: { - start: {line: 1, column: 0}, - end: {line: 1, column: 36} - } - }, - loc: { - start: {line: 1, column: 0}, - end: {line: 1, column: 36} - } - }] -}, { - ecmaVersion: 7, - locations: true -}); - -test('f(async function(promise) { await promise })', { - type: "Program", - body: [{ - type: "ExpressionStatement", - expression: { - type: "CallExpression", - callee: { - type: "Identifier", - name: "f", - loc: { - start: {line: 1, column: 0}, - end: {line: 1, column: 1} - } - }, - arguments: [ - { - type: "FunctionExpression", - id: null, - params: [ - { - type: "Identifier", - name: "promise", - loc: { - start: {line: 1, column: 17}, - end: {line: 1, column: 24} - } - } - ], - defaults: [], - body: { - type: "BlockStatement", - body: [ - { - type: "ExpressionStatement", - expression: { - type: "AwaitExpression", - argument: { - type: "Identifier", - name: "promise", - loc: { - start: {line: 1, column: 34}, - end: {line: 1, column: 41} - } - }, - loc: { - start: {line: 1, column: 28}, - end: {line: 1, column: 41} - } - }, - loc: { - start: {line: 1, column: 28}, - end: {line: 1, column: 41} - } - } - ], - loc: { - start: {line: 1, column: 26}, - end: {line: 1, column: 43} - } - }, - rest: null, - generator: false, - expression: false, - async: true, - loc: { - start: {line: 1, column: 2}, - end: {line: 1, column: 43} - } - } - ], - loc: { - start: {line: 1, column: 0}, - end: {line: 1, column: 44} - } - }, - loc: { - start: {line: 1, column: 0}, - end: {line: 1, column: 44} - } - }] -}, { - ecmaVersion: 7, - locations: true -}); - // Harmony Invalid syntax testFail("0o", "Expected number in radix 8 (1:2)", {ecmaVersion: 6}); @@ -14435,8 +13670,6 @@ testFail("(10) => 00", "Unexpected token (1:1)", {ecmaVersion: 6}); testFail("(10, 20) => 00", "Unexpected token (1:1)", {ecmaVersion: 6}); -testFail("function foo(promise) { await promise; }", "Unexpected token (1:30)", {ecmaVersion: 7}); - testFail("yield v", "Unexpected token (1:6)", {ecmaVersion: 6}); testFail("yield 10", "Unexpected token (1:6)", {ecmaVersion: 6});