From 3c258c47169c059bae29819aadf3fc10c7f15de5 Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Wed, 21 Jan 2015 10:17:52 +1100 Subject: [PATCH] add proper ordering to function param logic - fixes #549 --- lib/6to5/transformation/transform.js | 2 +- .../transformers/es6-default-parameters.js | 15 ++++-- .../transformers/es6-destructuring.js | 51 +++++++++++-------- .../optional-undeclared-variable-check.js | 2 - .../destructuring/exec.js | 19 +++++++ 5 files changed, 60 insertions(+), 29 deletions(-) create mode 100644 test/fixtures/transformation/es6-default-parameters/destructuring/exec.js diff --git a/lib/6to5/transformation/transform.js b/lib/6to5/transformation/transform.js index a98b0fe820..d7006f32ce 100644 --- a/lib/6to5/transformation/transform.js +++ b/lib/6to5/transformation/transform.js @@ -71,8 +71,8 @@ _.each({ templateLiterals: require("./transformers/es6-template-literals"), propertyMethodAssignment: require("./transformers/es6-property-method-assignment"), computedPropertyNames: require("./transformers/es6-computed-property-names"), - destructuring: require("./transformers/es6-destructuring"), defaultParameters: require("./transformers/es6-default-parameters"), + destructuring: require("./transformers/es6-destructuring"), forOf: require("./transformers/es6-for-of"), unicodeRegex: require("./transformers/es6-unicode-regex"), abstractReferences: require("./transformers/es7-abstract-references"), diff --git a/lib/6to5/transformation/transformers/es6-default-parameters.js b/lib/6to5/transformation/transformers/es6-default-parameters.js index af1b163e5b..3e942eb68c 100644 --- a/lib/6to5/transformation/transformers/es6-default-parameters.js +++ b/lib/6to5/transformation/transformers/es6-default-parameters.js @@ -15,7 +15,7 @@ exports.Function = function (node, parent, scope, context, file) { var iife = false; var def; - var checkTDZ = function (ids) { + var checkTDZ = function (param, def, ids) { var check = function (node, parent) { if (!t.isReferencedIdentifier(node, parent)) return; @@ -29,7 +29,10 @@ exports.Function = function (node, parent, scope, context, file) { }; check(def, node); - traverse(def, { enter: check }); + + if (!t.isPattern(param)) { + traverse(def, { enter: check }); + } }; for (var i = 0; i < node.defaults.length; i++) { @@ -42,7 +45,7 @@ exports.Function = function (node, parent, scope, context, file) { // are to the right - ie. uninitialized parameters var rightIds = ids.slice(i); for (var i2 = 0; i2 < rightIds.length; i2++) { - checkTDZ(rightIds[i2]); + checkTDZ(param, def, rightIds[i2]); } // we're accessing a variable that's already defined within this function @@ -66,12 +69,14 @@ exports.Function = function (node, parent, scope, context, file) { continue; } - body.push(util.template("default-parameter", { + var def = util.template("default-parameter", { VARIABLE_NAME: node.params[i], DEFAULT_VALUE: def, ARGUMENT_KEY: t.literal(+i), ARGUMENTS: argsIdentifier - }, true)); + }, true); + def._blockHoist = node.defaults.length - i; + body.push(def); } // we need to cut off all trailing default parameters diff --git a/lib/6to5/transformation/transformers/es6-destructuring.js b/lib/6to5/transformation/transformers/es6-destructuring.js index 3a3e27c4b5..35d5ae886b 100644 --- a/lib/6to5/transformation/transformers/es6-destructuring.js +++ b/lib/6to5/transformation/transformers/es6-destructuring.js @@ -8,13 +8,27 @@ var buildVariableAssign = function (opts, id, init) { var op = opts.operator; if (t.isMemberExpression(id)) op = "="; + var node; + if (op) { - return t.expressionStatement(t.assignmentExpression(op, id, init)); + node = t.expressionStatement(t.assignmentExpression(op, id, init)); } else { - return t.variableDeclaration(opts.kind, [ + node = t.variableDeclaration(opts.kind, [ t.variableDeclarator(id, init) ]); } + + node._blockHoist = opts.blockHoist; + + return node; +}; + +var buildVariableDeclar = function (opts, id, init) { + var declar = t.variableDeclaration("var", [ + t.variableDeclarator(id, init) + ]); + declar._blockHoist = opts.blockHoist; + return declar; }; var push = function (opts, nodes, elem, parentId) { @@ -100,9 +114,7 @@ var pushArrayPattern = function (opts, nodes, pattern, parentId) { var toArray = opts.file.toArray(parentId, !hasSpreadElement && pattern.elements.length); var _parentId = opts.scope.generateUidBasedOnNode(parentId, opts.file); - nodes.push(t.variableDeclaration("var", [ - t.variableDeclarator(_parentId, toArray) - ])); + nodes.push(buildVariableDeclar(opts, _parentId, toArray)); parentId = _parentId; for (i = 0; i < pattern.elements.length; i++) { @@ -138,11 +150,7 @@ var pushPattern = function (opts) { if (!t.isArrayExpression(parentId) && !t.isMemberExpression(parentId) && !t.isIdentifier(parentId)) { var key = scope.generateUidBasedOnNode(parentId, file); - - nodes.push(t.variableDeclaration("var", [ - t.variableDeclarator(key, parentId) - ])); - + nodes.push(buildVariableDeclar(opts, key, parentId)); parentId = key; } @@ -181,19 +189,20 @@ exports.Function = function (node, parent, scope, context, file) { var hasDestructuring = false; - node.params = node.params.map(function (pattern) { + node.params = node.params.map(function (pattern, i) { if (!t.isPattern(pattern)) return pattern; hasDestructuring = true; var parentId = file.generateUidIdentifier("ref", scope); pushPattern({ - kind: "var", - nodes: nodes, - pattern: pattern, - id: parentId, - file: file, - scope: scope + blockHoist: node.params.length - i, + pattern: pattern, + nodes: nodes, + scope: scope, + file: file, + kind: "var", + id: parentId }); return parentId; @@ -294,12 +303,12 @@ exports.VariableDeclaration = function (node, parent, scope, context, file) { var patternId = declar.init; var pattern = declar.id; var opts = { - kind: node.kind, - nodes: nodes, pattern: pattern, - id: patternId, + nodes: nodes, + scope: scope, + kind: node.kind, file: file, - scope: scope + id: patternId, }; if (t.isPattern(pattern) && patternId) { diff --git a/lib/6to5/transformation/transformers/optional-undeclared-variable-check.js b/lib/6to5/transformation/transformers/optional-undeclared-variable-check.js index 6640c0217f..ad6dbeb06c 100644 --- a/lib/6to5/transformation/transformers/optional-undeclared-variable-check.js +++ b/lib/6to5/transformation/transformers/optional-undeclared-variable-check.js @@ -1,5 +1,3 @@ -var t = require("../../types"); - exports.optional = true; exports.Identifier = function (node, parent, scope, context, file) { diff --git a/test/fixtures/transformation/es6-default-parameters/destructuring/exec.js b/test/fixtures/transformation/es6-default-parameters/destructuring/exec.js new file mode 100644 index 0000000000..3148c98145 --- /dev/null +++ b/test/fixtures/transformation/es6-default-parameters/destructuring/exec.js @@ -0,0 +1,19 @@ +function required(msg) { + throw new Error(msg); +} + +function sum( + { arr = required('arr is required') } = { arr: arr = [] }, + length = arr.length +) { + let i = 0; + let acc = 0; + for (let item of arr) { + if (i >= length) return acc; + acc += item; + i++; + } + return acc; +} + +assert.equal(sum({arr:[1,2]}), 3);