diff --git a/lib/6to5/transformation/helpers/build-binary-assignment-operator-transformer.js b/lib/6to5/transformation/helpers/build-binary-assignment-operator-transformer.js new file mode 100644 index 0000000000..59e9f53107 --- /dev/null +++ b/lib/6to5/transformation/helpers/build-binary-assignment-operator-transformer.js @@ -0,0 +1,43 @@ +var explode = require("./explode-assignable-expression"); +var t = require("../../types"); + +module.exports = function (exports, opts) { + var isAssignment = function (node) { + return node.operator === opts.operator + "="; + }; + + var buildAssignment = function (left, right) { + return t.assignmentExpression("=", left, right); + }; + + exports.ExpressionStatement = function (node, parent, scope, context, file) { + var expr = node.expression; + if (!isAssignment(expr)) return; + + var nodes = []; + var exploded = explode(expr.left, nodes, file, scope); + + nodes.push(t.expressionStatement( + buildAssignment(exploded.ref, opts.build(exploded.uid, expr.right)) + )); + + return nodes; + }; + + exports.AssignmentExpression = function (node, parent, scope, context, file) { + if (t.isExpressionStatement(parent)) return; + if (!isAssignment(node)) return; + + var nodes = []; + var exploded = explode(node.left, nodes, file, scope); + nodes.push(opts.build(exploded.uid, node.right)); + nodes.push(exploded.ref); + + return t.toSequenceExpression(nodes, scope); + }; + + exports.BinaryExpression = function (node) { + if (node.operator !== opts.operator) return; + return opts.build(node.left, node.right); + }; +}; diff --git a/lib/6to5/transformation/helpers/build-conditional-assignment-operator-transformer.js b/lib/6to5/transformation/helpers/build-conditional-assignment-operator-transformer.js index a3bad77c73..154588db85 100644 --- a/lib/6to5/transformation/helpers/build-conditional-assignment-operator-transformer.js +++ b/lib/6to5/transformation/helpers/build-conditional-assignment-operator-transformer.js @@ -1,53 +1,22 @@ -var t = require("../../types"); - -module.exports = function (opts) { - var getObjRef = function (node, nodes, file, scope) { - var obj = node.object; - var temp = scope.generateUidBasedOnNode(obj, file); - nodes.push(t.variableDeclaration("var", [ - t.variableDeclarator(temp, obj) - ])); - return temp; - }; - - var getPropRef = function (node, nodes, file, scope) { - var prop = node.property; - var key = t.toComputedKey(node, prop); - if (t.isLiteral(key)) return key; - - var temp = scope.generateUidBasedOnNode(prop, file); - nodes.push(t.variableDeclaration("var", [ - t.variableDeclarator(temp, prop) - ])); - return temp; - }; - - var buildAbsoluteRef = function (node, nodes, file, scope) { - if (t.isIdentifier(node)) return node; - - var obj = getObjRef(node, nodes, file, scope); - var prop = getPropRef(node, nodes, file, scope); - - var computed = node.computed || t.isLiteral(prop); - return t.memberExpression(obj, prop, computed); - }; +var explode = require("./explode-assignable-expression"); +var t = require("../../types"); +module.exports = function (exports, opts) { var buildAssignment = function (left, right) { return t.assignmentExpression("=", left, right); }; - var exports = {}; - exports.ExpressionStatement = function (node, parent, scope, context, file) { var expr = node.expression; - if (!opts.is(expr)) return; + if (!opts.is(expr, file)) return; var nodes = []; - var left = buildAbsoluteRef(expr.left, nodes, file, scope); + + var exploded = explode(expr.left, nodes, file, scope); nodes.push(t.ifStatement( - opts.build(left, file), - t.expressionStatement(buildAssignment(left, expr.right)) + opts.build(exploded.uid, file), + t.expressionStatement(buildAssignment(exploded.ref, expr.right)) )); return nodes; @@ -55,21 +24,19 @@ module.exports = function (opts) { exports.AssignmentExpression = function (node, parent, scope, context, file) { if (t.isExpressionStatement(parent)) return; - if (!opts.is(node)) return; + if (!opts.is(node, file)) return; - var nodes = []; - var left = buildAbsoluteRef(node.left, nodes, file, scope); + var nodes = []; + var exploded = explode(node.left, nodes, file, scope); nodes.push(t.logicalExpression( "&&", - opts.build(left, file), - buildAssignment(left, node.right) + opts.build(exploded.uid, file), + buildAssignment(exploded.ref, node.right) )); - nodes.push(left); + nodes.push(exploded.ref); return t.toSequenceExpression(nodes, scope); }; - - return exports; }; diff --git a/lib/6to5/transformation/helpers/explode-assignable-expression.js b/lib/6to5/transformation/helpers/explode-assignable-expression.js new file mode 100644 index 0000000000..8b0e47d879 --- /dev/null +++ b/lib/6to5/transformation/helpers/explode-assignable-expression.js @@ -0,0 +1,49 @@ +var t = require("../../types"); + +var getObjRef = function (node, nodes, file, scope) { + var ref; + if (t.isIdentifier(node)) { + ref = node; + } else if (t.isMemberExpression(node)) { + ref = node.object; + } else { + throw new Error("We can't explode this node type " + node.type); + } + + var temp = scope.generateUidBasedOnNode(ref, file); + nodes.push(t.variableDeclaration("var", [ + t.variableDeclarator(temp, ref) + ])); + return temp; +}; + +var getPropRef = function (node, nodes, file, scope) { + var prop = node.property; + var key = t.toComputedKey(node, prop); + if (t.isLiteral(key)) return key; + + var temp = scope.generateUidBasedOnNode(prop, file); + nodes.push(t.variableDeclaration("var", [ + t.variableDeclarator(temp, prop) + ])); + return temp; +}; + +module.exports = function (node, nodes, file, scope) { + var obj = getObjRef(node, nodes, file, scope); + var ref, uid; + + if (t.isIdentifier(node)) { + ref = node; + uid = obj; + } else { + var prop = getPropRef(node, nodes, file, scope); + var computed = node.computed || t.isLiteral(prop); + uid = ref = t.memberExpression(obj, prop, computed); + } + + return { + uid: uid, + ref: ref + }; +}; diff --git a/lib/6to5/transformation/helpers/explode-unary.js b/lib/6to5/transformation/helpers/explode-unary.js deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/lib/6to5/transformation/transformers/es7-exponentiation-operator.js b/lib/6to5/transformation/transformers/es7-exponentiation-operator.js index f5825967ee..1310700c18 100644 --- a/lib/6to5/transformation/transformers/es7-exponentiation-operator.js +++ b/lib/6to5/transformation/transformers/es7-exponentiation-operator.js @@ -2,17 +2,15 @@ exports.experimental = true; -var t = require("../../types"); -var pow = t.memberExpression(t.identifier("Math"), t.identifier("pow")); +var build = require("../helpers/build-binary-assignment-operator-transformer"); +var t = require("../../types"); -exports.AssignmentExpression = function (node) { - if (node.operator !== "**=") return; - node.operator = "="; - node.right = t.callExpression(pow, [node.left, node.right]); -}; +var MATH_POW = t.memberExpression(t.identifier("Math"), t.identifier("pow")); -exports.BinaryExpression = function (node) { - if (node.operator !== "**") return; +build(exports, { + operator: "**", - return t.callExpression(pow, [node.left, node.right]); -}; + build: function (left, right) { + return t.callExpression(MATH_POW, [left, right]); + } +}); diff --git a/lib/6to5/transformation/transformers/playground-mallet-operator.js b/lib/6to5/transformation/transformers/playground-mallet-operator.js index 16333c82e5..559cbde1ed 100644 --- a/lib/6to5/transformation/transformers/playground-mallet-operator.js +++ b/lib/6to5/transformation/transformers/playground-mallet-operator.js @@ -1,12 +1,13 @@ -var t = require("../../types"); +var build = require("../helpers/build-conditional-assignment-operator-transformer"); +var t = require("../../types"); -module.exports = require("../helpers/build-conditional-assignment-operator-transformer")({ - is: function (node) { +build(exports, { + is: function (node, file) { var is = t.isAssignmentExpression(node) && node.operator === "||="; if (is) { var left = node.left; if (!t.isMemberExpression(left) && !t.isIdentifier(left)) { - throw new Error("Expected type MemeberExpression or Identifier"); + throw file.errorWithNode(left, "Expected type MemeberExpression or Identifier"); } return true; } diff --git a/lib/6to5/transformation/transformers/playground-memoization-operator.js b/lib/6to5/transformation/transformers/playground-memoization-operator.js index 06c5f32405..822692bcee 100644 --- a/lib/6to5/transformation/transformers/playground-memoization-operator.js +++ b/lib/6to5/transformation/transformers/playground-memoization-operator.js @@ -1,6 +1,7 @@ -var t = require("../../types"); +var build = require("../helpers/build-conditional-assignment-operator-transformer"); +var t = require("../../types"); -module.exports = require("../helpers/build-conditional-assignment-operator-transformer")({ +build(exports, { is: function (node) { var is = t.isAssignmentExpression(node) && node.operator === "?="; if (is) t.assertMemberExpression(node.left);