From 85c2de57e4bcd25b9b61eb9a48e56e8de8c439e7 Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Sat, 15 Nov 2014 02:50:05 +1100 Subject: [PATCH] fix for-head duplication testing and replacement - fixes #162 --- .../transformers/let-scoping.js | 42 ++++++++++++++----- .../let-scoping/exec-block-scoped/exec.js | 6 +++ .../exec.js | 0 .../let-scoping/exec-for-loop-head/exec.js | 5 +++ 4 files changed, 42 insertions(+), 11 deletions(-) create mode 100644 test/fixtures/transformation/let-scoping/exec-block-scoped/exec.js rename test/fixtures/transformation/let-scoping/{duplicate-in-upper-scope => exec-duplicate-in-upper-scope}/exec.js (100%) create mode 100644 test/fixtures/transformation/let-scoping/exec-for-loop-head/exec.js diff --git a/lib/6to5/transformation/transformers/let-scoping.js b/lib/6to5/transformation/transformers/let-scoping.js index b99297a9e6..d31cbd7b84 100644 --- a/lib/6to5/transformation/transformers/let-scoping.js +++ b/lib/6to5/transformation/transformers/let-scoping.js @@ -145,11 +145,25 @@ LetScoping.prototype.noClosure = function () { if (_.isEmpty(replacements)) return; - traverse(block, function (node, parent) { + var replace = function (node, parent) { if (!t.isIdentifier(node)) return; if (!t.isReferenced(node, parent)) return; node.name = replacements[node.name] || node.name; - }); + }; + + var traverseReplace = function (node, parent) { + replace(node, parent); + traverse(node, replace); + }; + + var forParent = this.forParent; + if (forParent) { + traverseReplace(forParent.right, forParent); + traverseReplace(forParent.test, forParent); + traverseReplace(forParent.update, forParent); + } + + traverse(block, replace); }; /** @@ -181,10 +195,23 @@ LetScoping.prototype.getInfo = function () { keys: [] }; + var duplicates = function (id, key) { + var has = scope.parentGet(key); + + if (has && has !== id) { + // there's a variable with this exact name in an upper scope so we need + // to generate a new name + opts.duplicates[key] = id.name = file.generateUid(key, scope); + } + }; + _.each(opts.declarators, function (declar) { opts.declarators.push(declar); - var keys = t.getIds(declar); + var keys = t.getIds(declar, true); + _.each(keys, duplicates); + keys = _.keys(keys); + opts.outsideKeys = opts.outsideKeys.concat(keys); opts.keys = opts.keys.concat(keys); }); @@ -193,14 +220,7 @@ LetScoping.prototype.getInfo = function () { if (!isLet(declar)) return; _.each(t.getIds(declar, true), function (id, key) { - var has = scope.parentGet(key); - - if (has && has !== id) { - // there's a variable with this exact name in an upper scope so we need - // to generate a new name - opts.duplicates[key] = id.name = file.generateUid(key, scope); - } - + duplicates(id, key); opts.keys.push(key); }); }); diff --git a/test/fixtures/transformation/let-scoping/exec-block-scoped/exec.js b/test/fixtures/transformation/let-scoping/exec-block-scoped/exec.js new file mode 100644 index 0000000000..8b1fd6db2b --- /dev/null +++ b/test/fixtures/transformation/let-scoping/exec-block-scoped/exec.js @@ -0,0 +1,6 @@ +let x = 1; +{ + let x = 2; + assert.equal(x, 2); +} +assert.equal(x, 1); diff --git a/test/fixtures/transformation/let-scoping/duplicate-in-upper-scope/exec.js b/test/fixtures/transformation/let-scoping/exec-duplicate-in-upper-scope/exec.js similarity index 100% rename from test/fixtures/transformation/let-scoping/duplicate-in-upper-scope/exec.js rename to test/fixtures/transformation/let-scoping/exec-duplicate-in-upper-scope/exec.js diff --git a/test/fixtures/transformation/let-scoping/exec-for-loop-head/exec.js b/test/fixtures/transformation/let-scoping/exec-for-loop-head/exec.js new file mode 100644 index 0000000000..59aaae854b --- /dev/null +++ b/test/fixtures/transformation/let-scoping/exec-for-loop-head/exec.js @@ -0,0 +1,5 @@ +assert.equal((function(){ + let a = 1; + for (let a = 0; a < 8; a++) {} + return a; +}()), 1);