From 8a13c12738909d5e603efdf2113beded855cc9ac Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Sat, 24 Jan 2015 16:31:43 +1100 Subject: [PATCH] switch rest and default parameters to new ast type --- lib/6to5/transformation/transform.js | 6 +- .../transformers/es6/classes.js | 2 - .../transformers/es6/parameters.default.js | 86 ++++++------------- .../transformers/es6/parameters.rest.js | 11 ++- lib/6to5/traverse/scope.js | 1 - lib/6to5/types/index.js | 10 ++- .../es6-parameters.default/tdz-2/actual.js | 1 - .../es6-parameters.default/tdz-2/options.json | 3 - .../es6-parameters.default/tdz/actual.js | 1 - .../es6-parameters.default/tdz/options.json | 3 - .../{tdz-3 => wrapper}/exec.js | 0 11 files changed, 44 insertions(+), 80 deletions(-) delete mode 100644 test/fixtures/transformation/es6-parameters.default/tdz-2/actual.js delete mode 100644 test/fixtures/transformation/es6-parameters.default/tdz-2/options.json delete mode 100644 test/fixtures/transformation/es6-parameters.default/tdz/actual.js delete mode 100644 test/fixtures/transformation/es6-parameters.default/tdz/options.json rename test/fixtures/transformation/es6-parameters.default/{tdz-3 => wrapper}/exec.js (100%) diff --git a/lib/6to5/transformation/transform.js b/lib/6to5/transformation/transform.js index 2cea841086..1a0ff4e5e8 100644 --- a/lib/6to5/transformation/transform.js +++ b/lib/6to5/transformation/transform.js @@ -59,9 +59,6 @@ _.each({ "playground.memoizationOperator": require("./transformers/playground/memoization-operator"), "playground.objectGetterMemoization": require("./transformers/playground/object-getter-memoization"), - asyncToGenerator: require("./transformers/other/async-to-generator"), - bluebirdCoroutines: require("./transformers/other/bluebird-coroutines"), - react: require("./transformers/other/react"), // needs to be before `_blockHoist` due to function hoisting etc @@ -76,6 +73,9 @@ _.each({ "es6.classes": require("./transformers/es6/classes"), + asyncToGenerator: require("./transformers/other/async-to-generator"), + bluebirdCoroutines: require("./transformers/other/bluebird-coroutines"), + "es7.objectSpread": require("./transformers/es7/object-spread"), "es7.exponentiationOperator": require("./transformers/es7/exponentiation-operator"), "es6.spread": require("./transformers/es6/spread"), diff --git a/lib/6to5/transformation/transformers/es6/classes.js b/lib/6to5/transformation/transformers/es6/classes.js index db4d8a34b7..7f639b401f 100644 --- a/lib/6to5/transformation/transformers/es6/classes.js +++ b/lib/6to5/transformation/transformers/es6/classes.js @@ -253,8 +253,6 @@ Class.prototype.pushConstructor = function (method) { t.inheritsComments(construct, method); construct._ignoreUserWhitespace = true; - construct.defaults = fn.defaults; construct.params = fn.params; construct.body = fn.body; - construct.rest = fn.rest; }; diff --git a/lib/6to5/transformation/transformers/es6/parameters.default.js b/lib/6to5/transformation/transformers/es6/parameters.default.js index 04eb2da942..c4b715fd85 100644 --- a/lib/6to5/transformation/transformers/es6/parameters.default.js +++ b/lib/6to5/transformation/transformers/es6/parameters.default.js @@ -4,63 +4,19 @@ var traverse = require("../../../traverse"); var util = require("../../../util"); var t = require("../../../types"); -function checkTDZ(node, parent, scope, context, state) { - if (!t.isReferencedIdentifier(node, parent)) return; - - if (state.ids.indexOf(node.name) >= 0) { - throw state.file.errorWithNode(node, "Temporal dead zone - accessing a variable before it's initialized"); +var hasDefaults = function (node) { + for (var i = 0; i < node.params.length; i++) { + if (t.isAssignmentPattern(node.params[i])) return true; } - - if (scope.has(node.name, true)) { - state.iife = true; - } -} - -var checkTDZVisitor = { - enter: checkTDZ + return false; }; exports.Function = function (node, parent, scope, context, file) { - if (!node.defaults || !node.defaults.length) return; + if (!hasDefaults(node)) return; + t.ensureBlock(node); - var ids = node.params.map(function (param) { - return t.getIds(param); - }); - - var def; - var state = { - file: file, - iife: false - }; - - for (var i = 0; i < node.defaults.length; i++) { - def = node.defaults[i]; - if (!def) continue; - - var param = node.params[i]; - - // temporal dead zone check - here we prevent accessing of params that - // are to the right - ie. uninitialized parameters - var rightIds = ids.slice(i); - - for (var i2 = 0; i2 < rightIds.length; i2++) { - state.ids = rightIds[i2]; - - checkTDZ(def, node, scope, context, state); - - if (!t.isPattern(param)) { - traverse(def, checkTDZVisitor, scope, state); - } - } - - // we're accessing a variable that's already defined within this function - var has = scope.get(param.name, true); - if (has && node.params.indexOf(has) < 0) { - state.iife = true; - } - } - + var iife = false; var body = []; var argsIdentifier = t.identifier("arguments"); @@ -68,27 +24,39 @@ exports.Function = function (node, parent, scope, context, file) { var lastNonDefaultParam = 0; - for (i = 0; i < node.defaults.length; i++) { - def = node.defaults[i]; - if (!def) { + for (var i = 0; i < node.params.length; i++) { + var param = node.params[i]; + + if (!t.isAssignmentPattern(param)) { lastNonDefaultParam = +i + 1; continue; } + var left = param.left; + var right = param.right; + + node.params[i] = scope.generateUidIdentifier("x") + + // we're accessing a variable that's already defined within this function + var localDeclar = scope.get(left.name, true); + if (localDeclar !== left) { + iife = true; + } + var defNode = util.template("default-parameter", { - VARIABLE_NAME: node.params[i], - DEFAULT_VALUE: def, + VARIABLE_NAME: left, + DEFAULT_VALUE: right, ARGUMENT_KEY: t.literal(+i), ARGUMENTS: argsIdentifier }, true); - defNode._blockHoist = node.defaults.length - i; + defNode._blockHoist = node.params.length - i; body.push(defNode); } // we need to cut off all trailing default parameters node.params = node.params.slice(0, lastNonDefaultParam); - if (state.iife) { + if (iife) { var container = t.functionExpression(null, [], node.body, node.generator); container._aliasFunction = true; @@ -98,6 +66,4 @@ exports.Function = function (node, parent, scope, context, file) { } else { node.body.body = body.concat(node.body.body); } - - node.defaults = []; }; diff --git a/lib/6to5/transformation/transformers/es6/parameters.rest.js b/lib/6to5/transformation/transformers/es6/parameters.rest.js index f2519d2e70..9ca249628c 100644 --- a/lib/6to5/transformation/transformers/es6/parameters.rest.js +++ b/lib/6to5/transformation/transformers/es6/parameters.rest.js @@ -3,11 +3,14 @@ var util = require("../../../util"); var t = require("../../../types"); -exports.Function = function (node, parent, scope) { - if (!node.rest) return; +var hasRest = function (node) { + return t.isRestElement(node.params[node.params.length - 1]); +}; - var rest = node.rest; - node.rest = null; +exports.Function = function (node, parent, scope) { + if (!hasRest(node)) return; + + var rest = node.params.pop().argument; t.ensureBlock(node); diff --git a/lib/6to5/traverse/scope.js b/lib/6to5/traverse/scope.js index 927c71f0e9..deb8e06099 100644 --- a/lib/6to5/traverse/scope.js +++ b/lib/6to5/traverse/scope.js @@ -250,7 +250,6 @@ Scope.prototype.getInfo = function () { // Function - params, rest if (t.isFunction(block)) { - if (block.rest) add(block.rest); _.each(block.params, function (param) { add(param); }); diff --git a/lib/6to5/types/index.js b/lib/6to5/types/index.js index 3779a44a94..1f33acb85a 100644 --- a/lib/6to5/types/index.js +++ b/lib/6to5/types/index.js @@ -237,8 +237,14 @@ t.isReferenced = function (node, parent) { // we're a function param if (_.contains(parent.params, node)) return false; - // we're a rest parameter - if (parent.rest === node) return false; + for (var i = 0; i < parent.params.length; i++) { + var param = parent.params[i]; + if (param === node) { + return false; + } else if (t.isRestElement(param) && param.argument === node) { + return false; + } + } } if (t.isMethodDefinition(parent) && parent.key === node && !parent.computed) { diff --git a/test/fixtures/transformation/es6-parameters.default/tdz-2/actual.js b/test/fixtures/transformation/es6-parameters.default/tdz-2/actual.js deleted file mode 100644 index 4249062965..0000000000 --- a/test/fixtures/transformation/es6-parameters.default/tdz-2/actual.js +++ /dev/null @@ -1 +0,0 @@ -function foo(a=b, b) {} diff --git a/test/fixtures/transformation/es6-parameters.default/tdz-2/options.json b/test/fixtures/transformation/es6-parameters.default/tdz-2/options.json deleted file mode 100644 index faba38c879..0000000000 --- a/test/fixtures/transformation/es6-parameters.default/tdz-2/options.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "throws": "Temporal dead zone - accessing a variable before it's initialized" -} diff --git a/test/fixtures/transformation/es6-parameters.default/tdz/actual.js b/test/fixtures/transformation/es6-parameters.default/tdz/actual.js deleted file mode 100644 index 3095e9c769..0000000000 --- a/test/fixtures/transformation/es6-parameters.default/tdz/actual.js +++ /dev/null @@ -1 +0,0 @@ -function foo(a=a) {} diff --git a/test/fixtures/transformation/es6-parameters.default/tdz/options.json b/test/fixtures/transformation/es6-parameters.default/tdz/options.json deleted file mode 100644 index faba38c879..0000000000 --- a/test/fixtures/transformation/es6-parameters.default/tdz/options.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "throws": "Temporal dead zone - accessing a variable before it's initialized" -} diff --git a/test/fixtures/transformation/es6-parameters.default/tdz-3/exec.js b/test/fixtures/transformation/es6-parameters.default/wrapper/exec.js similarity index 100% rename from test/fixtures/transformation/es6-parameters.default/tdz-3/exec.js rename to test/fixtures/transformation/es6-parameters.default/wrapper/exec.js