diff --git a/bin/6to5/index.js b/bin/6to5/index.js index d79fe08162..a1c88877ba 100755 --- a/bin/6to5/index.js +++ b/bin/6to5/index.js @@ -12,6 +12,7 @@ commander.option("-f, --filename [filename]", "Filename to use when reading from commander.option("-w, --watch", "Recompile files on changes"); commander.option("-r, --runtime", "Replace 6to5 declarations with references to a runtime"); commander.option("-e, --experimental", "Enable experimental support for proposed ES7 features"); +commander.option("-p, --playground", "Enable playground support"); commander.option("-m, --modules [modules]", "Module formatter type to use [common]", "common"); commander.option("-w, --whitelist [whitelist]", "Whitelist of transformers to ONLY use", util.list); @@ -90,6 +91,7 @@ exports.opts = { sourceMapName: commander.outFile, amdModuleIds: commander.amdModuleIds, experimental: commander.experimental, + playground: commander.playground, blacklist: commander.blacklist, whitelist: commander.whitelist, sourceMap: commander.sourceMaps || commander.sourceMapsInline, diff --git a/bin/_6to5-node b/bin/_6to5-node index dd7216d35a..62d30b0512 100644 --- a/bin/_6to5-node +++ b/bin/_6to5-node @@ -13,6 +13,7 @@ commander.option("-p, --print", "Evaluate script and print result"); commander.option("-i, --ignore [regex]", "Ignore all files that match this regex when using the require hook"); commander.option("-x, --extensions [extensions]", "List of extensions to hook into [.es6,.js]"); commander.option("-r, --experimental", "Enable experimental support for proposed ES7 features"); +commander.option("-g, --playground", "Enable playground support"); var pkg = require("../package.json"); commander.version(pkg.version); diff --git a/doc/playground.md b/doc/playground.md new file mode 100644 index 0000000000..d98717a664 --- /dev/null +++ b/doc/playground.md @@ -0,0 +1,63 @@ +# Playground + +**Playground** is a proving ground for possible ES7 proposals. + +**NOTE: These features are in no way endrosed by Ecma International and are not currently being proposed for any version of ECMAScript.** This may change in the future however. + +## Usage + + $ 6to5 --playground + +```javascript +to5.transform("code", { playground: true }); +``` + +## Features + + * [Memoization operator](#memoization-operator) + * [Method binding](#method-binding) + +### Memoization assignment operator + +```javascript +var obj = {}; +obj.x ?= 2; +obj.x; // 2 + +obj = { x: 1 }; +obj.x ?= 2; +obj.x; // 1 + +obj = { x: undefined } +obj.x ?= 2; +obj.x; // undefined +``` + +```javascript +var obj = {}; +obj.x ?= 2; +``` + +equivalent to: + +```javascript +var obj = {}; +if (Object.prototype.hasOwnProperty.call(obj, "x")) obj.x = 2; +``` + +### Method binding expression. + +```javascript +var fn = obj:method; +var fn = obj:method("foob"); +``` + +equivalent to: + +```javascript +var fn = obj.method.bind(obj); +var fn = obj.method.bind(obj, "foob"); +``` + +**NOTE:** Method binding can **only** be used as an **expression** and not as +statement. diff --git a/lib/6to5/file.js b/lib/6to5/file.js index 73c24af8e8..32e8f62384 100644 --- a/lib/6to5/file.js +++ b/lib/6to5/file.js @@ -23,7 +23,9 @@ File.declarations = [ "interop-require", "to-array", "arguments-to-array", - "object-spread" + "object-spread", + "has-own", + "slice" ]; File.normaliseOptions = function (opts) { @@ -31,6 +33,7 @@ File.normaliseOptions = function (opts) { _.defaults(opts, { experimental: false, + playground: false, whitespace: true, blacklist: [], whitelist: [], @@ -135,7 +138,11 @@ File.prototype.addDeclaration = function (name) { } var uid = this.generateUidIdentifier(name); - this.scope.push(name, uid, ref); + this.scope.push({ + key: name, + id: uid, + init: ref + }); return uid; }; diff --git a/lib/6to5/generation/generator.js b/lib/6to5/generation/generator.js index 73511ec6a6..bf7a57223c 100644 --- a/lib/6to5/generation/generator.js +++ b/lib/6to5/generation/generator.js @@ -53,6 +53,7 @@ CodeGenerator.generators = { comprehensions: require("./generators/comprehensions"), expressions: require("./generators/expressions"), statements: require("./generators/statements"), + playground: require("./generators/playground"), classes: require("./generators/classes"), methods: require("./generators/methods"), modules: require("./generators/modules"), diff --git a/lib/6to5/generation/generators/playground.js b/lib/6to5/generation/generators/playground.js new file mode 100644 index 0000000000..3742aa9f86 --- /dev/null +++ b/lib/6to5/generation/generators/playground.js @@ -0,0 +1,7 @@ +var _ = require("lodash"); + +_.each(["BindMemberExpression"], function (type) { + exports[type] = function () { + throw new ReferenceError("Trying to render non-standard playground node " + JSON.stringify(type)); + }; +}); diff --git a/lib/6to5/patch.js b/lib/6to5/patch.js index d0f428c9d2..a6049df532 100644 --- a/lib/6to5/patch.js +++ b/lib/6to5/patch.js @@ -30,6 +30,14 @@ def("VirtualPropertyExpression") .field("object", def("Expression")) .field("property", or(def("Identifier"), def("Expression"))); +// Playground +def("BindMemberExpression") + .bases("Expression") + .build("object", "property", "arguments") + .field("object", def("Expression")) + .field("property", or(def("Identifier"), def("Expression"))) + .field("arguments", [def("Expression")]); + types.finalize(); var estraverse = require("estraverse"); diff --git a/lib/6to5/templates/has-own.js b/lib/6to5/templates/has-own.js new file mode 100644 index 0000000000..9a4caad24a --- /dev/null +++ b/lib/6to5/templates/has-own.js @@ -0,0 +1 @@ +Object.prototype.hasOwnProperty; diff --git a/lib/6to5/templates/slice.js b/lib/6to5/templates/slice.js new file mode 100644 index 0000000000..f35f3b503b --- /dev/null +++ b/lib/6to5/templates/slice.js @@ -0,0 +1 @@ +Array.prototype.slice; diff --git a/lib/6to5/transformation/transform.js b/lib/6to5/transformation/transform.js index 4629a8bb76..d2117bde7d 100644 --- a/lib/6to5/transformation/transform.js +++ b/lib/6to5/transformation/transform.js @@ -36,7 +36,6 @@ _.each({ arrowFunctions: require("./transformers/es6-arrow-functions"), classes: require("./transformers/es6-classes"), - _propertyLiterals: require("./transformers/_property-literals"), computedPropertyNames: require("./transformers/es6-computed-property-names"), objectSpread: require("./transformers/es7-object-spread"), @@ -57,12 +56,18 @@ _.each({ generators: require("./transformers/es6-generators"), + // plyground + methodBinding: require("./transformers/playground-method-binding"), + memoizationOperator: require("./transformers/playground-memoization-operator"), + _blockHoist: require("./transformers/_block-hoist"), _declarations: require("./transformers/_declarations"), _aliasFunctions: require("./transformers/_alias-functions"), useStrict: require("./transformers/use-strict"), + _propertyLiterals: require("./transformers/_property-literals"), + _memberExpressioLiterals: require("./transformers/_member-expression-literals"), _memberExpressionKeywords: require("./transformers/_member-expression-keywords"), _moduleFormatter: require("./transformers/_module-formatter") }, function (transformer, key) { diff --git a/lib/6to5/transformation/transformers/_declarations.js b/lib/6to5/transformation/transformers/_declarations.js index 9b7626aadc..6ccda90a1c 100644 --- a/lib/6to5/transformation/transformers/_declarations.js +++ b/lib/6to5/transformation/transformers/_declarations.js @@ -3,9 +3,21 @@ var _ = require("lodash"); exports.BlockStatement = exports.Program = function (node) { + var kinds = {}; + _.each(node._declarations, function (declar) { - node.body.unshift(t.variableDeclaration("var", [ - t.variableDeclarator(declar.id, declar.init) - ])); + var kind = declar.kind || "var"; + var declarNode = t.variableDeclarator(declar.id, declar.init); + + if (!declar.init) { + kinds[kind] = kinds[kind] || []; + kinds[kind].push(declarNode); + } else { + node.body.unshift(t.variableDeclaration(kind, [declarNode])); + } + }); + + _.each(kinds, function (declars, kind) { + node.body.unshift(t.variableDeclaration(kind, declars)); }); }; diff --git a/lib/6to5/transformation/transformers/_member-expression-keywords.js b/lib/6to5/transformation/transformers/_member-expression-keywords.js index feaaadaae0..46fb8b082f 100644 --- a/lib/6to5/transformation/transformers/_member-expression-keywords.js +++ b/lib/6to5/transformation/transformers/_member-expression-keywords.js @@ -1,5 +1,5 @@ var esutils = require("esutils"); -var t = require("../../types"); +var t = require("../../types"); exports.MemberExpression = function (node) { var prop = node.property; diff --git a/lib/6to5/transformation/transformers/_member-expression-literals.js b/lib/6to5/transformation/transformers/_member-expression-literals.js new file mode 100644 index 0000000000..0c784e8615 --- /dev/null +++ b/lib/6to5/transformation/transformers/_member-expression-literals.js @@ -0,0 +1,10 @@ +var t = require("../../types"); + +exports.MemberExpression = function (node, parent) { + var prop = node.property; + if (node.computed && t.isLiteral(prop) && t.isValidIdentifier(prop.value)) { + // computed literal that is a valid identifier + node.property = t.identifier(prop.value); + node.computed = false; + } +}; diff --git a/lib/6to5/transformation/transformers/_property-literals.js b/lib/6to5/transformation/transformers/_property-literals.js index 2a80e3134f..a7b8313b25 100644 --- a/lib/6to5/transformation/transformers/_property-literals.js +++ b/lib/6to5/transformation/transformers/_property-literals.js @@ -3,13 +3,14 @@ var t = require("../../types"); var _ = require("lodash"); exports.Property = function (node) { - // ignore key literals that are valid identifiers var key = node.key; - if (t.isLiteral(key) && _.isString(key.value) && esutils.keyword.isIdentifierName(key.value)) { - key.type = "Identifier"; - key.name = key.value; - delete key.value; - + if (t.isLiteral(key) && t.isValidIdentifier(key.value)) { + // property key is a literal but a valid identifier + node.key = t.identifier(key.value); node.computed = false; + } else if (t.isIdentifier(key) && esutils.keyword.isKeywordES6(key.name, true)) { + // property key is a keyword + node.key = t.literal(key.name); + node.computed = true; } }; diff --git a/lib/6to5/transformation/transformers/es6-destructuring.js b/lib/6to5/transformation/transformers/es6-destructuring.js index 3747bc95b2..29d81afc97 100644 --- a/lib/6to5/transformation/transformers/es6-destructuring.js +++ b/lib/6to5/transformation/transformers/es6-destructuring.js @@ -3,11 +3,14 @@ var t = require("../../types"); var _ = require("lodash"); -var buildVariableAssign = function (kind, id, init) { - if (kind === false) { +var buildVariableAssign = function (opts, id, init) { + var op = opts.operator; + if (t.isMemberExpression(id)) op = "="; + + if (op) { return t.expressionStatement(t.assignmentExpression("=", id, init)); } else { - return t.variableDeclaration(kind, [ + return t.variableDeclaration(opts.kind, [ t.variableDeclarator(id, init) ]); } @@ -18,10 +21,8 @@ var push = function (opts, nodes, elem, parentId) { pushObjectPattern(opts, nodes, elem, parentId); } else if (t.isArrayPattern(elem)) { pushArrayPattern(opts, nodes, elem, parentId); - } else if (t.isMemberExpression(elem)) { - nodes.push(buildVariableAssign(false, elem, parentId)); } else { - nodes.push(buildVariableAssign(opts.kind, elem, parentId)); + nodes.push(buildVariableAssign(opts, elem, parentId)); } }; @@ -43,7 +44,7 @@ var pushObjectPattern = function (opts, nodes, pattern, parentId) { keys = t.arrayExpression(keys); var value = t.callExpression(opts.file.addDeclaration("object-spread"), [parentId, keys]); - nodes.push(buildVariableAssign(opts.kind, prop.argument, value)); + nodes.push(buildVariableAssign(opts, prop.argument, value)); } else { var pattern2 = prop.value; var patternId2 = t.memberExpression(parentId, prop.key, prop.computed); @@ -51,7 +52,7 @@ var pushObjectPattern = function (opts, nodes, pattern, parentId) { if (t.isPattern(pattern2)) { push(opts, nodes, pattern2, patternId2); } else { - nodes.push(buildVariableAssign(opts.kind, pattern2, patternId2)); + nodes.push(buildVariableAssign(opts, pattern2, patternId2)); } } }); @@ -177,7 +178,7 @@ exports.ExpressionStatement = function (node, parent, file, scope) { ])); push({ - kind: false, + operator: expr.operator, file: file, scope: scope }, nodes, expr.left, ref); @@ -190,33 +191,24 @@ exports.AssignmentExpression = function (node, parent, file, scope) { if (!t.isPattern(node.left)) return; var tempName = file.generateUid("temp", scope); - var temp = t.identifier(tempName); - scope.push(tempName, temp); - - var nodes = []; - nodes.push(t.assignmentExpression("=", temp, node.right)); - - push({ - kind: false, - file: file, - scope: scope - }, nodes, node.left, temp); - - nodes.push(temp); - - nodes = nodes.map(function (node) { - if (t.isExpressionStatement(node)) { - return node.expression; - } else if (t.isVariableDeclaration(node)) { - var declar = node.declarations[0]; - scope.push(declar.id.name, declar.id); - return t.assignmentExpression("=", declar.id, declar.init); - } else { - return node; - } + var ref = t.identifier(tempName); + scope.push({ + key: tempName, + id: ref }); - return t.sequenceExpression(nodes); + var nodes = []; + nodes.push(t.assignmentExpression("=", ref, node.right)); + + push({ + operator: node.operator, + file: file, + scope: scope + }, nodes, node.left, ref); + + nodes.push(ref); + + return t.toSequenceExpression(nodes, scope); }; exports.VariableDeclaration = function (node, parent, file, scope) { @@ -236,17 +228,18 @@ exports.VariableDeclaration = function (node, parent, file, scope) { _.each(node.declarations, function (declar) { var patternId = declar.init; var pattern = declar.id; + var opts = { + kind: node.kind, + nodes: nodes, + pattern: pattern, + id: patternId, + file: file, + scope: scope + }; if (t.isPattern(pattern) && patternId) { - pushPattern({ - kind: node.kind, - nodes: nodes, - pattern: pattern, - id: patternId, - file: file, - scope: scope - }); + pushPattern(opts); } else { - nodes.push(buildVariableAssign(node.kind, declar.id, declar.init)); + nodes.push(buildVariableAssign(opts, declar.id, declar.init)); } }); @@ -268,4 +261,3 @@ exports.VariableDeclaration = function (node, parent, file, scope) { return nodes; }; - diff --git a/lib/6to5/transformation/transformers/es7-abstract-references.js b/lib/6to5/transformation/transformers/es7-abstract-references.js index 6128710ed8..66720d18ac 100644 --- a/lib/6to5/transformation/transformers/es7-abstract-references.js +++ b/lib/6to5/transformation/transformers/es7-abstract-references.js @@ -32,7 +32,10 @@ exports.AssignmentExpression = function (node, parent, file, scope) { if (t.isDynamic(value)) { var tempName = file.generateUid("temp"); temp = value = t.identifier(tempName); - scope.push(tempName, temp); + scope.push({ + key: tempName, + id: temp + }); } } @@ -74,7 +77,10 @@ exports.CallExpression = function (node, parent, file, scope) { // we need to save `callee.object` so we can call it again var tempName = file.generateUid("temp"); temp = t.identifier(tempName); - scope.push(tempName, temp); + scope.push({ + key: tempName, + id: temp + }); } var call = util.template("abstract-expression-call", { diff --git a/lib/6to5/transformation/transformers/playground-memoization-operator.js b/lib/6to5/transformation/transformers/playground-memoization-operator.js new file mode 100644 index 0000000000..5d6ec25ade --- /dev/null +++ b/lib/6to5/transformation/transformers/playground-memoization-operator.js @@ -0,0 +1,90 @@ +var t = require("../../types"); + +var isMemo = function (node) { + var is = t.isAssignmentExpression(node) && node.operator === "?="; + if (is) t.assertMemberExpression(node.left); + return is; +}; + +var getPropRef = function (nodes, prop, file, scope) { + if (t.isIdentifier(prop)) { + return t.literal(prop.name); + } else { + var temp = file.generateUidIdentifier("propKey", scope); + nodes.push(t.variableDeclaration("var", [ + t.variableDeclarator(temp, prop) + ])); + return temp; + } +}; + +var getObjRef = function (nodes, obj, file, scope) { + if (t.isDynamic(obj)) { + var temp = file.generateUidIdentifier("obj", scope); + nodes.push(t.variableDeclaration("var", [ + t.variableDeclarator(temp, obj) + ])); + return temp; + } else { + return obj; + } +}; + +var buildHasOwn = function (obj, prop, file) { + return t.unaryExpression( + "!", + t.callExpression( + t.memberExpression(file.addDeclaration("has-own"), t.identifier("call")), + [obj, prop] + ), + true + ); +}; + +var buildAbsoluteRef = function (left, obj, prop) { + var computed = left.computed || t.isLiteral(prop); + return t.memberExpression(obj, prop, computed); +}; + +var buildAssignment = function (expr, obj, prop) { + return t.assignmentExpression("=", buildAbsoluteRef(expr.left, obj, prop), expr.right); +}; + +exports.ExpressionStatement = function (node, parent, file, scope) { + var expr = node.expression; + if (!isMemo(expr)) return; + + var nodes = []; + + var left = expr.left; + var obj = getObjRef(nodes, left.object, file, scope); + var prop = getPropRef(nodes, left.property, file, scope); + + nodes.push(t.ifStatement( + buildHasOwn(obj, prop, file), + t.expressionStatement(buildAssignment(expr, obj, prop)) + )); + + return nodes; +}; + +exports.AssignmentExpression = function (node, parent, file, scope) { + if (t.isExpressionStatement(parent)) return; + if (!isMemo(node)) return; + + var nodes = []; + + var left = node.left; + var obj = getObjRef(nodes, left.object, file, scope); + var prop = getPropRef(nodes, left.property, file, scope); + + nodes.push(t.logicalExpression( + "&&", + buildHasOwn(obj, prop, file), + buildAssignment(node, obj, prop) + )); + + nodes.push(buildAbsoluteRef(left, obj, prop)); + + return t.toSequenceExpression(nodes, scope); +}; diff --git a/lib/6to5/transformation/transformers/playground-method-binding.js b/lib/6to5/transformation/transformers/playground-method-binding.js new file mode 100644 index 0000000000..2faad64af9 --- /dev/null +++ b/lib/6to5/transformation/transformers/playground-method-binding.js @@ -0,0 +1,30 @@ +var t = require("../../types"); + +exports.BindMemberExpression = function (node, parent, file, scope) { + var object = node.object; + var prop = node.property; + + var temp; + if (t.isDynamic(object)) { + var tempName = file.generateUid("temp", scope); + temp = object = t.identifier(tempName); + scope.push({ + key: tempName, + id: temp + }); + } + + var call = t.callExpression( + t.memberExpression(t.memberExpression(object, prop), t.identifier("bind")), + [object].concat(node.arguments) + ); + + if (temp) { + return t.sequenceExpression([ + t.assignmentExpression("=", temp, node.object), + call + ]); + } else { + return call; + } +}; diff --git a/lib/6to5/traverse/scope.js b/lib/6to5/traverse/scope.js index d20b5aba56..9666edafa3 100644 --- a/lib/6to5/traverse/scope.js +++ b/lib/6to5/traverse/scope.js @@ -101,7 +101,7 @@ Scope.prototype.getReferences = function () { return references; }; -Scope.prototype.push = function (name, id, init) { +Scope.prototype.push = function (opts) { var block = this.block; if (t.isFor(block) || t.isCatchClause(block) || t.isFunction(block)) { @@ -111,9 +111,10 @@ Scope.prototype.push = function (name, id, init) { if (t.isBlockStatement(block) || t.isProgram(block)) { block._declarations = block._declarations || {}; - block._declarations[name] = { - id: id, - init: init + block._declarations[opts.key] = { + kind: opts.kind, + id: opts.id, + init: opts.init }; } else { throw new TypeError("cannot add a declaration here in node type " + block.type); diff --git a/lib/6to5/types/builder-keys.json b/lib/6to5/types/builder-keys.json index 91527d5b2a..45c315a50b 100644 --- a/lib/6to5/types/builder-keys.json +++ b/lib/6to5/types/builder-keys.json @@ -11,6 +11,7 @@ "Identifier": ["name"], "IfStatement": ["test", "consequent", "alternate"], "Literal": ["value"], + "LogicalExpression": ["operator", "left", "right"], "MemberExpression": ["object", "property", "computed"], "NewExpression": ["callee", "arguments"], "ObjectExpression": ["properties"], diff --git a/lib/6to5/types/index.js b/lib/6to5/types/index.js index 82f4af15d3..3ed12a6e47 100644 --- a/lib/6to5/types/index.js +++ b/lib/6to5/types/index.js @@ -1,4 +1,5 @@ -var _ = require("lodash"); +var esutils = require("esutils"); +var _ = require("lodash"); var t = exports; @@ -71,6 +72,31 @@ addAssert("Expression", t.isExpression); // +t.toSequenceExpression = function (nodes, scope) { + var exprs = []; + + _.each(nodes, function (node) { + if (t.isExpression(node)) { + exprs.push(node); + } if (t.isExpressionStatement(node)) { + exprs.push(node.expression); + } else if (t.isVariableDeclaration(node)) { + _.each(node.declarations, function (declar) { + scope.push({ + kind: node.kind, + key: declar.id.name, + id: declar.id + }); + exprs.push(t.assignmentExpression("=", declar.id, declar.init)); + }); + } + }); + + return t.sequenceExpression(exprs); +}; + +// + t.shallowEqual = function (actual, expected) { var same = true; @@ -135,6 +161,10 @@ t.toIdentifier = function (name) { return name; }; +t.isValidIdentifier = function (name) { + return _.isString(name) && esutils.keyword.isIdentifierName(name) && !esutils.keyword.isKeywordES6(name, true); +}; + t.ensureBlock = function (node) { node.body = t.toBlock(node.body, node); }; diff --git a/lib/6to5/types/visitor-keys.json b/lib/6to5/types/visitor-keys.json index 02808567f5..79a3902c5f 100644 --- a/lib/6to5/types/visitor-keys.json +++ b/lib/6to5/types/visitor-keys.json @@ -5,6 +5,7 @@ "AssignmentExpression": ["left", "right"], "AwaitExpression": ["argument"], "BinaryExpression": ["left", "right"], + "BindMemberExpression": ["object", "property", "arguments"], "BlockStatement": ["body"], "BreakStatement": ["label"], "CallExpression": ["callee", "arguments"], diff --git a/lib/6to5/util.js b/lib/6to5/util.js index e698078268..244ab28cab 100644 --- a/lib/6to5/util.js +++ b/lib/6to5/util.js @@ -219,6 +219,7 @@ exports.parse = function (opts, code, callback) { allowReturnOutsideFunction: true, preserveParens: true, ecmaVersion: opts.experimental ? 7 : 6, + playground: opts.playground, strictMode: true, onComment: comments, locations: true, diff --git a/package.json b/package.json index 76b9745829..3b140220b3 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "chokidar": "0.11.1", "source-map-support": "0.2.8", "esutils": "1.1.6", - "acorn-6to5": "0.9.1-7", + "acorn-6to5": "0.9.1-8", "estraverse": "1.8.0", "private": "0.1.6" }, diff --git a/test/fixtures/transformation/api/blacklist/actual.js b/test/fixtures/transformation/api/blacklist/actual.js index deaf9a91ef..8ec84a062e 100644 --- a/test/fixtures/transformation/api/blacklist/actual.js +++ b/test/fixtures/transformation/api/blacklist/actual.js @@ -1,5 +1,5 @@ class Test { constructor() { - arr.map(x => x * x); + arr.map(x => x * x); } } diff --git a/test/fixtures/transformation/api/blacklist/untitled b/test/fixtures/transformation/api/blacklist/untitled deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/test/fixtures/transformation/es6-destructuring/assignment-expression/expected.js b/test/fixtures/transformation/es6-destructuring/assignment-expression/expected.js index 882a44fb84..ff82bc596a 100644 --- a/test/fixtures/transformation/es6-destructuring/assignment-expression/expected.js +++ b/test/fixtures/transformation/es6-destructuring/assignment-expression/expected.js @@ -1,9 +1,8 @@ "use strict"; -var _ref; +var _temp, _ref; var _toArray = function (arr) { return Array.isArray(arr) ? arr : Array.from(arr); }; -var _temp; console.log((_temp = [123], _ref = _toArray(_temp), x = _ref[0], _temp)); diff --git a/test/fixtures/transformation/misc/_member-expression-keywords/expected.js b/test/fixtures/transformation/misc/_member-expression-keywords/expected.js index e603ba03f8..fdd217784a 100644 --- a/test/fixtures/transformation/misc/_member-expression-keywords/expected.js +++ b/test/fixtures/transformation/misc/_member-expression-keywords/expected.js @@ -1,6 +1,6 @@ "use strict"; test["catch"]; -test["catch"]["foo"]; +test["catch"].foo; test["catch"]; -test["catch"]["foo"]; +test["catch"].foo; diff --git a/test/fixtures/transformation/misc/_member-expression-literals/actual.js b/test/fixtures/transformation/misc/_member-expression-literals/actual.js new file mode 100644 index 0000000000..c855363128 --- /dev/null +++ b/test/fixtures/transformation/misc/_member-expression-literals/actual.js @@ -0,0 +1 @@ +obj["x"] = 2; diff --git a/test/fixtures/transformation/misc/_member-expression-literals/expected.js b/test/fixtures/transformation/misc/_member-expression-literals/expected.js new file mode 100644 index 0000000000..0a18f3d810 --- /dev/null +++ b/test/fixtures/transformation/misc/_member-expression-literals/expected.js @@ -0,0 +1,3 @@ +"use strict"; + +obj.x = 2; diff --git a/test/fixtures/transformation/playground/memoization-assignment-operator/actual.js b/test/fixtures/transformation/playground/memoization-assignment-operator/actual.js new file mode 100644 index 0000000000..b2d1521e2c --- /dev/null +++ b/test/fixtures/transformation/playground/memoization-assignment-operator/actual.js @@ -0,0 +1,13 @@ +var obj = {}; + +obj.x ?= 2; + +console.log(obj.x ?= 2); + +obj[x()] ?= 2; + +console.log(obj[x()] ?= 2); + +obj[y()][x()] ?= 2; + +console.log(obj[y()][x()] ?= 2); diff --git a/test/fixtures/transformation/playground/memoization-assignment-operator/exec.js b/test/fixtures/transformation/playground/memoization-assignment-operator/exec.js new file mode 100644 index 0000000000..3e528c641d --- /dev/null +++ b/test/fixtures/transformation/playground/memoization-assignment-operator/exec.js @@ -0,0 +1,20 @@ +var obj = {}; +obj.x ?= 2; +assert.equal(obj.x, 2); + +obj = {}; +assert.equal(obj.x ?= 2, 2); + +obj = { x: 1 }; +obj.x ?= 2; +assert.equal(obj.x, 1); + +obj = { x: 1 }; +assert.equal(obj.x ?= 2, 1); + +obj = { x: undefined } +obj.x ?= 2; +assert.equal(obj.x, undefined); + +obj = { x: undefined } +assert.equal(obj.x ?= 2, undefined); diff --git a/test/fixtures/transformation/playground/memoization-assignment-operator/expected.js b/test/fixtures/transformation/playground/memoization-assignment-operator/expected.js new file mode 100644 index 0000000000..e00aea8c5e --- /dev/null +++ b/test/fixtures/transformation/playground/memoization-assignment-operator/expected.js @@ -0,0 +1,25 @@ +"use strict"; + +var _propKey2, _obj2, _propKey4; +var _hasOwn = Object.prototype.hasOwnProperty; +var obj = {}; + +if (!_hasOwn.call(obj, "x")) obj.x = 2; + + +console.log((!_hasOwn.call(obj, "x") && (obj.x = 2), obj.x)); + +var _propKey = x(); + +if (!_hasOwn.call(obj, _propKey)) obj[_propKey] = 2; + + +console.log((_propKey2 = x(), !_hasOwn.call(obj, _propKey2) && (obj[_propKey2] = 2), obj[_propKey2])); + +var _obj = obj[y()]; +var _propKey3 = x(); + +if (!_hasOwn.call(_obj, _propKey3)) _obj[_propKey3] = 2; + + +console.log((_obj2 = obj[y()], _propKey4 = x(), !_hasOwn.call(_obj2, _propKey4) && (_obj2[_propKey4] = 2), _obj2[_propKey4])); diff --git a/test/fixtures/transformation/playground/method-binding/actual.js b/test/fixtures/transformation/playground/method-binding/actual.js new file mode 100644 index 0000000000..c3f896ba9a --- /dev/null +++ b/test/fixtures/transformation/playground/method-binding/actual.js @@ -0,0 +1,5 @@ +var fn = obj:method; +var fn = obj:method("foob"); +var fn = obj[foo]:method; +var fn = obj.foo:method; +var fn = obj[foo()]:method; diff --git a/test/fixtures/transformation/playground/method-binding/exec.js b/test/fixtures/transformation/playground/method-binding/exec.js new file mode 100644 index 0000000000..3446ce1a25 --- /dev/null +++ b/test/fixtures/transformation/playground/method-binding/exec.js @@ -0,0 +1,22 @@ +var obj = { + foo: "foo", + bar: "bar", + getFoo: function () { + return this.foo; + }, + getBar: function (arg) { + return arg + " " + this.bar; + }, + getZoo: function (a, b) { + return this.foo + " " + this.bar + " " + a + " " + b; + } +}; + +var foo = obj:getFoo; +assert.equal(foo(), "foo"); + +var bar = obj:getBar("foo"); +assert.equal(bar(), "foo bar"); + +var zoo = obj:getZoo("foo"); +assert.equal(zoo("bar"), "foo bar foo bar"); diff --git a/test/fixtures/transformation/playground/method-binding/expected.js b/test/fixtures/transformation/playground/method-binding/expected.js new file mode 100644 index 0000000000..eed4dfd16e --- /dev/null +++ b/test/fixtures/transformation/playground/method-binding/expected.js @@ -0,0 +1,8 @@ +"use strict"; + +var _temp; +var fn = obj.method.bind(obj); +var fn = obj.method.bind(obj, "foob"); +var fn = obj[foo].method.bind(obj[foo]); +var fn = obj.foo.method.bind(obj.foo); +var fn = (_temp = obj[foo()], _temp.method.bind(_temp)); diff --git a/test/fixtures/transformation/playground/options.json b/test/fixtures/transformation/playground/options.json new file mode 100644 index 0000000000..e68df25688 --- /dev/null +++ b/test/fixtures/transformation/playground/options.json @@ -0,0 +1,3 @@ +{ + "playground": true +} diff --git a/test/transformation.js b/test/transformation.js index dc9d54c125..388097e447 100644 --- a/test/transformation.js +++ b/test/transformation.js @@ -37,10 +37,11 @@ var run = function (task, done) { err.message += util.codeFrame(execCode); throw err; } - } else { - var actualCode = actual.code; - var expectCode = expect.code; + } + var actualCode = actual.code; + var expectCode = expect.code; + if (!execCode || actualCode) { result = transform(actualCode, getOpts(actual)); actualCode = result.code;