diff --git a/lib/6to5/transform.js b/lib/6to5/transform.js index 9ca0d31d7f..42cd8bfde8 100644 --- a/lib/6to5/transform.js +++ b/lib/6to5/transform.js @@ -31,15 +31,13 @@ transform.test = function (task, assert) { actualCode = recast.prettyPrint(actualAst).code; if (task.options.exec) { - try { - var fn = new Function("assert", actualCode); - fn(assert); - } catch (err) { - console.log(actualCode); - throw err; - } - } else { - var expectCode = expect.code.trim(); + var fn = new Function("assert", actualCode); + fn(assert); + } + + var expectCode = expect.code.trim(); + + if (!task.options.exec || (task.options.exec && expectCode)) { var expectAst = util.parse(expect, expectCode); var expectResult = recast.prettyPrint(expectAst); expectCode = expectResult.code; @@ -64,7 +62,7 @@ transform.test = function (task, assert) { transform._ensureTransformerNames = function (type, keys) { _.each(keys, function (key) { - if (!transform.transformers[key]) { + if (key[0] === "_" || !transform.transformers[key]) { throw new ReferenceError("unknown transformer " + key + " specified in " + type); } }); @@ -87,5 +85,7 @@ transform.transformers = { restParameters: require("./transformers/rest-parameters"), destructuring: require("./transformers/destructuring"), forOf: require("./transformers/for-of"), - unicodeRegex: require("./transformers/unicode-regex") + unicodeRegex: require("./transformers/unicode-regex"), + + _aliasFunctions: require("./transformers/_alias-functions") }; diff --git a/lib/6to5/transformers/_alias-functions.js b/lib/6to5/transformers/_alias-functions.js new file mode 100644 index 0000000000..4f9d5251e2 --- /dev/null +++ b/lib/6to5/transformers/_alias-functions.js @@ -0,0 +1,77 @@ +var traverse = require("../traverse"); +var util = require("../util"); +var b = require("ast-types").builders; + +var go = function (getBody, node, file) { + var argumentsId; + var thisId; + + var getArgumentsId = function () { + return argumentsId = argumentsId || b.identifier(file.generateUid("arguments")); + }; + + var getThisId = function () { + return thisId = thisId || b.identifier(file.generateUid("this")); + }; + + // traverse the function and find all alias functions so we can alias + // arguments and this if neccesary + traverse(node, function (node) { + if (!node._aliasFunction) { + if (traverse.isFunction(node)) { + // stop traversal of this node as it'll be hit again by this transformer + return false; + } else { + return; + } + } + + // traverse all child nodes of this function and find arguments and this + traverse(node, function (node, parent) { + var getId; + + if (node.type === "Identifier" && node.name === "arguments") { + getId = getArgumentsId; + } else if (node.type === "ThisExpression") { + getId = getThisId; + } else { + return; + } + + if (util.isReferenced(node, parent)) return getId(); + }, node._aliasFunctionStopNonArrowFunctions && ["FunctionExpression", "FunctionDeclaration"]); + + return false; + }); + + var body; + + var pushDeclaration = function (id, init) { + body = body || getBody(); + body.unshift(b.variableDeclaration("var", [ + b.variableDeclarator(id, init) + ])); + }; + + if (argumentsId) { + pushDeclaration(argumentsId, b.identifier("arguments")); + } + + if (thisId) { + pushDeclaration(thisId, b.identifier("this")); + } +}; + +exports.Program = function (node, parent, file) { + go(function () { + return node.body; + }, node, file); +}; + +exports.FunctionDeclaration = +exports.FunctionExpression = function (node, parent, file) { + go(function () { + util.ensureBlock(node); + return node.body.body; + }, node, file); +}; diff --git a/lib/6to5/transformers/array-comprehension.js b/lib/6to5/transformers/array-comprehension.js index e7eb3de107..175ab37ec1 100644 --- a/lib/6to5/transformers/array-comprehension.js +++ b/lib/6to5/transformers/array-comprehension.js @@ -9,12 +9,14 @@ var single = function (node) { var templateName = "array-comprehension-map"; if (node.filter) templateName = "array-comprehension-filter"; - return util.template(templateName, { + var result = util.template(templateName, { STATEMENT: node.body, FILTER: node.filter, ARRAY: block.right, KEY: block.left }); + result._aliasFunction = true; + return result; }; var multiple = function (node, file) { @@ -23,6 +25,7 @@ var multiple = function (node, file) { var container = util.template("array-comprehension-container", { KEY: uid }); + container._aliasFunction = true; var block = container.callee.body; var body = block.body; @@ -47,7 +50,10 @@ var multiple = function (node, file) { var filter = util.template("if", { STATEMENT: node.filter }); + + // set if body filter.consequent.body = [child]; + child = filter; } } @@ -56,7 +62,10 @@ var multiple = function (node, file) { ARRAY: self.right, KEY: self.left }, true); + + // set function body container2.expression.arguments[0].body.body = [child]; + return container2; }; diff --git a/lib/6to5/transformers/arrow-functions.js b/lib/6to5/transformers/arrow-functions.js index 1ad17d27f7..34c1e07200 100644 --- a/lib/6to5/transformers/arrow-functions.js +++ b/lib/6to5/transformers/arrow-functions.js @@ -1,58 +1,12 @@ -var traverse = require("../traverse"); -var util = require("../util"); -var b = require("ast-types").builders; +var util = require("../util"); -exports.ArrowFunctionExpression = function (node, parent, file) { +exports.ArrowFunctionExpression = function (node) { util.ensureBlock(node); + node._aliasFunction = true; + node._aliasFunctionStopNonArrowFunctions = true; node.expression = false; node.type = "FunctionExpression"; - if (traverse.hasType(node, "ThisExpression")) { - return util.template("function-bind-this", { - FUNCTION: node - }); - } else { - return node; - } -}; - -exports.FunctionDeclaration = -exports.FunctionExpression = function (node, parent, file) { - var argumentsId; - - var isArgumentIdentifier = function (node) { - return node.type === "Identifier" && node.name === "arguments"; - }; - - var getId = function () { - return argumentsId = argumentsId || b.identifier(file.generateUid("arguments")); - }; - - // traverse the function and find all arrow functions so we can alias - // arguments if neccesary - traverse(node, function (node) { - if (node.type !== "ArrowFunctionExpression") return; - - // traverse all child nodes of this arrow function and find a sole arguments - // identifier - traverse(node, function (node, parent) { - if (isArgumentIdentifier(node) && parent.type !== "MemberExpression") { - return getId(); - } else if (node.type === "MemberExpression" && isArgumentIdentifier(node.object)) { - node.object = getId(); - } else { - return; - } - }, traverse.FUNCTION_TYPES); - - return false; - }, ["FunctionDeclaration", "FunctionExpression"]); - - if (argumentsId) { - util.ensureBlock(node); - node.body.body.unshift(b.variableDeclaration("var", [ - b.variableDeclarator(argumentsId, b.identifier("arguments")) - ])); - } + return node; }; diff --git a/lib/6to5/transformers/let-scoping.js b/lib/6to5/transformers/let-scoping.js index bc33a2a1c7..0b5f77485c 100644 --- a/lib/6to5/transformers/let-scoping.js +++ b/lib/6to5/transformers/let-scoping.js @@ -23,19 +23,7 @@ exports.VariableDeclaration = function (node, parent, file) { var id = ids[node.name]; if (!id) return; - // we're a property key - if (parent.type === "Property" && parent.key === node) return; - - var isMemberExpression = parent.type === "MemberExpression"; - - // we're in a member expression and we're the computed property so we're referenced - var isComputedProperty = isMemberExpression && parent.property === node && parent.computed; - - // we're in a member expression and we're the object so we're referenced - var isObject = isMemberExpression && parent.object === node; - - // we are referenced - if (!isMemberExpression || isComputedProperty || isObject) return id; + if (util.isReferenced(node, parent)) return id; }; var replace = function (node, parent) { @@ -55,7 +43,7 @@ exports.VariableDeclaration = function (node, parent, file) { b.returnStatement(node) ] ) - ), letReferences) + ), letReferences); } else { return false; } diff --git a/test/fixtures/syntax/array-comprehension/arguments/expected.js b/test/fixtures/syntax/array-comprehension/arguments/expected.js index 598f846d11..4756c8e512 100644 --- a/test/fixtures/syntax/array-comprehension/arguments/expected.js +++ b/test/fixtures/syntax/array-comprehension/arguments/expected.js @@ -1,6 +1,6 @@ function add() { var _arguments = arguments; - return [1, 2, 3].map(function () { + return [1, 2, 3].map(function (i) { return i * _arguments[0]; }); } diff --git a/test/fixtures/syntax/array-comprehension/this/expected.js b/test/fixtures/syntax/array-comprehension/this/expected.js index 202ecc703f..c2875a91e0 100644 --- a/test/fixtures/syntax/array-comprehension/this/expected.js +++ b/test/fixtures/syntax/array-comprehension/this/expected.js @@ -1,6 +1,6 @@ function add() { var _this = this; - return [1, 2, 3].map(function () { + return [1, 2, 3].map(function (i) { return i * _this.multiplier; }); } diff --git a/test/fixtures/syntax/arrow-functions/arguments/actual.js b/test/fixtures/syntax/arrow-functions/arguments/actual.js index c9b59181c4..198ac999f6 100644 --- a/test/fixtures/syntax/arrow-functions/arguments/actual.js +++ b/test/fixtures/syntax/arrow-functions/arguments/actual.js @@ -32,3 +32,14 @@ function five(obj) { return fn(); } five({ arguments: ["foo"] }); + +function six(obj) { + var fn = () => { + var fn2 = function () { + return arguments[0]; + }; + return fn2("foobar"); + }; + return fn(); +} +six(); diff --git a/test/fixtures/syntax/arrow-functions/arguments/expected.js b/test/fixtures/syntax/arrow-functions/arguments/expected.js index 304a3d2694..cdaea83b94 100644 --- a/test/fixtures/syntax/arrow-functions/arguments/expected.js +++ b/test/fixtures/syntax/arrow-functions/arguments/expected.js @@ -43,3 +43,14 @@ function five(obj) { return fn(); } five({ arguments: ["foo"] }); + +function six(obj) { + var fn = function () { + var fn2 = function () { + return arguments[0]; + }; + return fn2("foobar"); + }; + return fn(); +} +six(); diff --git a/test/fixtures/syntax/arrow-functions/this/expected.js b/test/fixtures/syntax/arrow-functions/this/expected.js index eda0cd71f4..3a88dcf154 100644 --- a/test/fixtures/syntax/arrow-functions/this/expected.js +++ b/test/fixtures/syntax/arrow-functions/this/expected.js @@ -1,3 +1,4 @@ +var _this = this; var t = function (x) { - return this.x + x; -}.bind(this); + return _this.x + x; +};