diff --git a/README.md b/README.md index 4e5a45e1fa..06704f7b00 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,8 @@ # acorn-6to5 +**acorn-6to5** is not supported outside of 6to5 usage. Do not expect support if +you use this in your own applications. + Deviates from [acorn](https://github.com/marijnh/acorn) in the following ways: * JSX support via [acorn-jsx](https://github.com/RReverser/acorn-jsx) @@ -7,3 +10,4 @@ Deviates from [acorn](https://github.com/marijnh/acorn) in the following ways: * [ES7 Async/await](https://github.com/lukehoban/ecmascript-asyncawait) * [ES7 Exponentiation operator](https://github.com/rwaldron/exponentiation-operator) * [ES7 Object rest/spread](https://github.com/sebmarkbage/ecmascript-rest-spread) + * [6to5 Playground features](https://6to5.github.io/playground.html) diff --git a/acorn.js b/acorn.js index 19bf0b0b08..84e3da283c 100644 --- a/acorn.js +++ b/acorn.js @@ -52,6 +52,7 @@ // the parser process. These options are recognized: var defaultOptions = exports.defaultOptions = { + playground: false, // `ecmaVersion` indicates the ECMAScript version to parse. Must // be either 3, or 5, or 6. This influences support for strict // mode, the set of reserved words, support for getters and @@ -2364,6 +2365,13 @@ var expr = parseExprOps(noIn); if (eat(_question)) { var node = startNodeAt(start); + if (eat(_eq)) { + var left = node.left = toAssignable(expr); + if (left.type !== "MemberExpression") raise(left.start, "You can only use member expressions in memoization assignment"); + node.right = parseMaybeAssign(noIn); + node.operator = "?="; + return finishNode(node, "AssignmentExpression"); + } node.test = expr; node.consequent = parseExpression(true); expect(_colon); @@ -2447,7 +2455,17 @@ } function parseSubscripts(base, start, noCalls) { - if (eat(_doubleColon)) { + if (options.playground && eat(_colon)) { + var node = startNodeAt(start); + node.object = base; + node.property = parseIdent(true); + if (eat(_parenL)) { + node.arguments = parseExprList(_parenR, false); + } else { + node.arguments = []; + } + return parseSubscripts(finishNode(node, "BindMemberExpression"), start, noCalls); + } else if (eat(_doubleColon)) { var node = startNodeAt(start); node.object = base; node.property = parseIdent(true); diff --git a/package.json b/package.json index 6a707fd72e..c83a0a970b 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "acorn-6to5", "description": "Acorn fork used by 6to5", "main": "acorn.js", - "version": "0.9.1-7", + "version": "0.9.1-8", "maintainers": [ { "name": "Marijn Haverbeke", diff --git a/test/driver.js b/test/driver.js index c76b8f91a4..37f36dcb99 100644 --- a/test/driver.js +++ b/test/driver.js @@ -60,7 +60,7 @@ else callback("fail", test.code, "Expected error message: " + test.error + "\nGot error message: " + e.message); } else { - callback("error", test.code, e.message || e.toString()); + callback("error", test.code, e.stack || e.toString()); } } } diff --git a/test/run.js b/test/run.js index 13809aa265..b6608b8dd7 100644 --- a/test/run.js +++ b/test/run.js @@ -7,6 +7,7 @@ require("./tests-harmony.js"); require("./tests-jsx.js"); require("./tests-6to5.js"); + require("./tests-6to5-playground.js"); } else { driver = window; } diff --git a/test/tests-6to5-playground.js b/test/tests-6to5-playground.js new file mode 100644 index 0000000000..d5085b9dcb --- /dev/null +++ b/test/tests-6to5-playground.js @@ -0,0 +1,310 @@ +if (typeof exports != "undefined") { + var test = require("./driver.js").test; + var testFail = require("./driver.js").testFail; + var testAssert = require("./driver.js").testAssert; +} + +// Memoization assignment operator + +testFail("obj ?= 2;", "You can only use member expressions in memoization assignment (1:0)"); + +test("obj.x ?= 2;", { + type: "Program", + start: 0, + end: 11, + body: [{ + type: "ExpressionStatement", + start: 0, + end: 11, + expression: { + type: "AssignmentExpression", + start: 0, + end: 10, + left: { + type: "MemberExpression", + start: 0, + end: 5, + object: { + type: "Identifier", + start: 0, + end: 3, + name: "obj" + }, + property: { + type: "Identifier", + start: 4, + end: 5, + name: "x" + }, + computed: false + }, + right: { + type: "Literal", + start: 9, + end: 10, + value: 2, + raw: "2" + }, + operator: "?=" + } + }] +}, { + playground: true +}); + +// Method binding + +test("var fn = obj:method", { + type: "Program", + start: 0, + end: 19, + body: [{ + type: "VariableDeclaration", + start: 0, + end: 19, + declarations: [{ + type: "VariableDeclarator", + start: 4, + end: 19, + id: { + type: "Identifier", + start: 4, + end: 6, + name: "fn" + }, + init: { + type: "BindMemberExpression", + start: 9, + end: 19, + object: { + type: "Identifier", + start: 9, + end: 12, + name: "obj" + }, + property: { + type: "Identifier", + start: 13, + end: 19, + name: "method" + }, + arguments: [] + } + }], + kind: "var" + }] +}, { + playground: true +}); + +test("var fn = obj:method('foo', 5)", { + type: "Program", + start: 0, + end: 29, + body: [{ + type: "VariableDeclaration", + start: 0, + end: 29, + declarations: [{ + type: "VariableDeclarator", + start: 4, + end: 29, + id: { + type: "Identifier", + start: 4, + end: 6, + name: "fn" + }, + init: { + type: "BindMemberExpression", + start: 9, + end: 29, + object: { + type: "Identifier", + start: 9, + end: 12, + name: "obj" + }, + property: { + type: "Identifier", + start: 13, + end: 19, + name: "method" + }, + arguments: [ + { + type: "Literal", + start: 20, + end: 25, + value: "foo", + raw: "'foo'" + }, + { + type: "Literal", + start: 27, + end: 28, + value: 5, + raw: "5" + } + ] + } + }], + kind: "var" + }] +}, { + playground: true +}); + +test("var fn = obj[foob]:method('foo', 5)", { + type: "Program", + start: 0, + end: 35, + body: [{ + type: "VariableDeclaration", + start: 0, + end: 35, + declarations: [{ + type: "VariableDeclarator", + start: 4, + end: 35, + id: { + type: "Identifier", + start: 4, + end: 6, + name: "fn" + }, + init: { + type: "BindMemberExpression", + start: 9, + end: 35, + object: { + type: "MemberExpression", + start: 9, + end: 18, + object: { + type: "Identifier", + start: 9, + end: 12, + name: "obj" + }, + property: { + type: "Identifier", + start: 13, + end: 17, + name: "foob" + }, + computed: true + }, + property: { + type: "Identifier", + start: 19, + end: 25, + name: "method" + }, + arguments: [ + { + type: "Literal", + start: 26, + end: 31, + value: "foo", + raw: "'foo'" + }, + { + type: "Literal", + start: 33, + end: 34, + value: 5, + raw: "5" + } + ] + } + }], + kind: "var" + }] +}, { + playground: true +}); + +test("var fn = obj[foob].test:method('foo', 5)", { + type: "Program", + start: 0, + end: 40, + body: [{ + type: "VariableDeclaration", + start: 0, + end: 40, + declarations: [ + { + type: "VariableDeclarator", + start: 4, + end: 40, + id: { + type: "Identifier", + start: 4, + end: 6, + name: "fn" + }, + init: { + type: "BindMemberExpression", + start: 9, + end: 40, + object: { + type: "MemberExpression", + start: 9, + end: 23, + object: { + type: "MemberExpression", + start: 9, + end: 18, + object: { + type: "Identifier", + start: 9, + end: 12, + name: "obj" + }, + property: { + type: "Identifier", + start: 13, + end: 17, + name: "foob" + }, + computed: true + }, + property: { + type: "Identifier", + start: 19, + end: 23, + name: "test" + }, + computed: false + }, + property: { + type: "Identifier", + start: 24, + end: 30, + name: "method" + }, + arguments: [ + { + type: "Literal", + start: 31, + end: 36, + value: "foo", + raw: "'foo'" + }, + { + type: "Literal", + start: 38, + end: 39, + value: 5, + raw: "5" + } + ] + } + } + ], + kind: "var" + }] +}, { + playground: true +}); diff --git a/test/tests-6to5.js b/test/tests-6to5.js index 6ce7d4f733..183ae8e6ef 100644 --- a/test/tests-6to5.js +++ b/test/tests-6to5.js @@ -480,6 +480,10 @@ test('({x, ...y, a, ...b, c})', { // ES7: Async Functions +testFail("function foo(promise) { await promise; }", "Unexpected token (1:30)", {ecmaVersion: 7}); + +testFail("async function* foo(promise) { await promise; }", "Unexpected token (1:14)", {ecmaVersion: 7}); + test('async function foo(promise) { await promise; }', { type: "Program", body: [{ @@ -1243,236 +1247,6 @@ test('f(async function(promise) { await promise })', { locations: true }); -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} - } - }, - arguments: [ - { - type: "Identifier", - name: "a", - loc: { - start: {line: 1, column: 2}, - end: {line: 1, column: 3} - } - }, - { - type: "CallExpression", - callee: { - type: "Identifier", - name: "async", - loc: { - start: {line: 1, column: 5}, - end: {line: 1, column: 10} - } - }, - arguments: [ - { - type: "Literal", - value: 1, - loc: { - start: {line: 1,column: 11}, - end: {line: 1,column: 12} - } - }, - { - type: "Literal", - value: 2, - loc: { - start: {line: 1,column: 14}, - end: {line: 1,column: 15} - } - } - ], - 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} - } - }, - loc: { - start: {line: 1,column: 0}, - end: {line: 1,column: 20} - } - }] -}, { - ecmaVersion: 7, - locations: true -}); - -test("var ok = async(x);", { - type: "Program", - body: [{ - type: "VariableDeclaration", - declarations: [ - { - type: "VariableDeclarator", - id: { - type: "Identifier", - name: "ok", - loc: { - start: {line: 1,column: 4}, - end: {line: 1,column: 6} - } - }, - init: { - type: "CallExpression", - callee: { - type: "Identifier", - name: "async", - loc: { - start: {line: 1,column: 9}, - end: {line: 1,column: 14} - } - }, - arguments: [ - { - type: "Identifier", - name: "x", - loc: { - start: {line: 1,column: 15}, - end: {line: 1,column: 16} - } - } - ], - loc: { - start: {line: 1,column: 9}, - end: {line: 1,column: 17} - } - }, - loc: { - start: {line: 1,column: 4}, - end: {line: 1,column: 17} - } - } - ], - kind: "var", - loc: { - start: {line: 1,column: 0}, - end: {line: 1,column: 17} - } - }] -}, { - ecmaVersion: 7, - locations: true -}); - -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} - } - }, - init: null, - loc: { - start: {line: 1,column: 18}, - end: {line: 1,column: 23} - } - } - ], - kind: "var", - loc: { - start: {line: 1,column: 14}, - end: {line: 1,column: 24} - } - }, - { - type: "ExpressionStatement", - expression: { - type: "AssignmentExpression", - operator: "=", - left: { - type: "Identifier", - name: "async", - loc: { - start: {line: 1,column: 25}, - end: {line: 1,column: 30} - } - }, - right: { - type: "Literal", - value: 10, - loc: { - start: {line: 1,column: 33}, - end: {line: 1,column: 35} - } - }, - loc: { - start: {line: 1,column: 25}, - end: {line: 1,column: 35} - } - }, - loc: { - start: {line: 1,column: 25}, - end: {line: 1,column: 36} - } - } - ], - 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 -}); - // ES7: Abstract references test('foo::bar;', { @@ -1660,8 +1434,3 @@ test('delete foo::bar;', { }, { ecmaVersion: 7 }); - - -testFail("function foo(promise) { await promise; }", "Unexpected token (1:30)", {ecmaVersion: 7}); - -testFail("async function* foo(promise) { await promise; }", "Unexpected token (1:14)", {ecmaVersion: 7});