<p dir="auto">When using the (unofficial) <a href="https://github.com/jridgewell/babel-plugin-transform-for-of-as-array">babel-plugin-transform-for-of-as-array</a> on a <code class="notranslate">for..of</code> loop that iterates over an imported array variable, the AMD (and CommonJS) modules transform fail to rewrite all of the array references.</p>
<p dir="auto">Repro: <a href="https://github.com/MattiasBuelens/babel-for-of-modules-regression">https://github.com/MattiasBuelens/babel-for-of-modules-regression</a></p>
<h3 dir="auto">Input Code</h3>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="import {array} from 'foo';

for (let elem of array) {
    console.log(elem);
}"><pre class="notranslate"><span class="pl-k">import</span> <span class="pl-kos">{</span><span class="pl-s1">array</span><span class="pl-kos">}</span> <span class="pl-k">from</span> <span class="pl-s">'foo'</span><span class="pl-kos">;</span>

<span class="pl-k">for</span> <span class="pl-kos">(</span><span class="pl-k">let</span> <span class="pl-s1">elem</span> <span class="pl-k">of</span> <span class="pl-s1">array</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s1">elem</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span></pre></div>
<h3 dir="auto">Babel Configuration (.babelrc, package.json, cli command)</h3>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="{
  &quot;plugins&quot;: [
    &quot;transform-for-of-as-array&quot;,
    &quot;transform-es2015-modules-amd&quot;
  ]
}"><pre class="notranslate"><span class="pl-kos">{</span>
  <span class="pl-s">"plugins"</span>: <span class="pl-kos">[</span>
    <span class="pl-s">"transform-for-of-as-array"</span><span class="pl-kos">,</span>
    <span class="pl-s">"transform-es2015-modules-amd"</span>
  <span class="pl-kos">]</span>
<span class="pl-kos">}</span></pre></div>
<h3 dir="auto">Expected Behavior</h3>
<p dir="auto">Babel version 7.0.0-beta.0 generates this code:</p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="define([&quot;foo&quot;], function (_foo) {
  &quot;use strict&quot;;

  for (let _i = 0; _i &lt; _foo.array.length; _i++) {
    let elem = _foo.array[_i];
    console.log(elem);
  }
});"><pre class="notranslate"><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-kos">[</span><span class="pl-s">"foo"</span><span class="pl-kos">]</span><span class="pl-kos">,</span> <span class="pl-k">function</span> <span class="pl-kos">(</span><span class="pl-s1">_foo</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
  <span class="pl-s">"use strict"</span><span class="pl-kos">;</span>

  <span class="pl-k">for</span> <span class="pl-kos">(</span><span class="pl-k">let</span> <span class="pl-s1">_i</span> <span class="pl-c1">=</span> <span class="pl-c1">0</span><span class="pl-kos">;</span> <span class="pl-s1">_i</span> <span class="pl-c1">&lt;</span> <span class="pl-s1">_foo</span><span class="pl-kos">.</span><span class="pl-c1">array</span><span class="pl-kos">.</span><span class="pl-c1">length</span><span class="pl-kos">;</span> <span class="pl-s1">_i</span><span class="pl-c1">++</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-k">let</span> <span class="pl-s1">elem</span> <span class="pl-c1">=</span> <span class="pl-s1">_foo</span><span class="pl-kos">.</span><span class="pl-c1">array</span><span class="pl-kos">[</span><span class="pl-s1">_i</span><span class="pl-kos">]</span><span class="pl-kos">;</span>
    <span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s1">elem</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre></div>
<h3 dir="auto">Current Behavior</h3>
<p dir="auto">Babel version 7.0.0-beta.2 generates this code instead:</p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="define([&quot;foo&quot;], function (_foo) {
  &quot;use strict&quot;;

  for (let _i = 0; _i &lt; _foo.array.length; _i++) {
    let elem = array[_i];
    console.log(elem);
  }
});"><pre class="notranslate"><span class="pl-en">define</span><span class="pl-kos">(</span><span class="pl-kos">[</span><span class="pl-s">"foo"</span><span class="pl-kos">]</span><span class="pl-kos">,</span> <span class="pl-k">function</span> <span class="pl-kos">(</span><span class="pl-s1">_foo</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
  <span class="pl-s">"use strict"</span><span class="pl-kos">;</span>

  <span class="pl-k">for</span> <span class="pl-kos">(</span><span class="pl-k">let</span> <span class="pl-s1">_i</span> <span class="pl-c1">=</span> <span class="pl-c1">0</span><span class="pl-kos">;</span> <span class="pl-s1">_i</span> <span class="pl-c1">&lt;</span> <span class="pl-s1">_foo</span><span class="pl-kos">.</span><span class="pl-c1">array</span><span class="pl-kos">.</span><span class="pl-c1">length</span><span class="pl-kos">;</span> <span class="pl-s1">_i</span><span class="pl-c1">++</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-k">let</span> <span class="pl-s1">elem</span> <span class="pl-c1">=</span> <span class="pl-s1">array</span><span class="pl-kos">[</span><span class="pl-s1">_i</span><span class="pl-kos">]</span><span class="pl-kos">;</span>
    <span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s1">elem</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre></div>
<p dir="auto">Note the <code class="notranslate">let elem = array[_i];</code> inside the loop.</p>
<p dir="auto">The same problem also occurs with the CommonJS modules transform, which generates:</p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="&quot;use strict&quot;;

var _foo = require(&quot;foo&quot;);

for (let _i = 0; _i &lt; _foo.array.length; _i++) {
  let elem = array[_i];
  console.log(elem);
}"><pre class="notranslate"><span class="pl-s">"use strict"</span><span class="pl-kos">;</span>

<span class="pl-k">var</span> <span class="pl-s1">_foo</span> <span class="pl-c1">=</span> <span class="pl-en">require</span><span class="pl-kos">(</span><span class="pl-s">"foo"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-k">for</span> <span class="pl-kos">(</span><span class="pl-k">let</span> <span class="pl-s1">_i</span> <span class="pl-c1">=</span> <span class="pl-c1">0</span><span class="pl-kos">;</span> <span class="pl-s1">_i</span> <span class="pl-c1">&lt;</span> <span class="pl-s1">_foo</span><span class="pl-kos">.</span><span class="pl-c1">array</span><span class="pl-kos">.</span><span class="pl-c1">length</span><span class="pl-kos">;</span> <span class="pl-s1">_i</span><span class="pl-c1">++</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
  <span class="pl-k">let</span> <span class="pl-s1">elem</span> <span class="pl-c1">=</span> <span class="pl-s1">array</span><span class="pl-kos">[</span><span class="pl-s1">_i</span><span class="pl-kos">]</span><span class="pl-kos">;</span>
  <span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s1">elem</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span></pre></div>
<h3 dir="auto">Context</h3>
<p dir="auto">Our code base only uses <code class="notranslate">for..of</code> on arrays (or array-like objects), so we'd like to keep using the optimized transformation provided by this unofficial plugin.</p>
<p dir="auto">I've tried to reproduce this issue with the standard <code class="notranslate">for..of</code> transform, but that plugin always creates a temporarily variable for the imported array.</p>
<h3 dir="auto">Your Environment</h3>

<table role="table">
<thead>
<tr>
<th>software</th>
<th>version(s)</th>
</tr>
</thead>
<tbody>
<tr>
<td>Babel</td>
<td>7.0.0-beta.2</td>
</tr>
<tr>
<td>node</td>
<td>7.10.0</td>
</tr>
<tr>
<td>npm</td>
<td>5.4.2</td>
</tr>
<tr>
<td>Operating System</td>
<td>Windows 10</td>
</tr>
</tbody>
</table>
<p dir="auto">Thanks for Babel. I'd love for Babel to be a superset of defs.js so I can deprecate defs eventually. For that reason, I'm going through the defs test suite and will open up issues (for bugs and improvement) as I find them.</p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="~/projects/defs.js/tests % cat var-inside-let.js
&quot;use strict&quot;;

// all three var x|y|z = 4 should be errors I believe so we error on all
//   v8 --harmony allows the first but not the second and last (2015-08-24: this has now been fixed in v8 so all errors)

if (true) {
    let x = 3;
    if (true) {
        var x = 4;
    }
}

let y = 3;
if (true) {
    var y = 4;
}

(function() {
    if (true) {
        let z = 3;
        if (true) {
            var z = 4;
        }
    }
})();"><pre class="notranslate"><span class="pl-c1">~</span><span class="pl-pds"><span class="pl-c1">/</span>projects<span class="pl-c1">/</span>defs</span><span class="pl-kos">.</span><span class="pl-c1">js</span><span class="pl-c1">/</span><span class="pl-s1">tests</span> <span class="pl-c1">%</span> <span class="pl-s1">cat</span> <span class="pl-s1">var</span><span class="pl-c1">-</span><span class="pl-s1">inside</span><span class="pl-c1">-</span><span class="pl-s1">let</span><span class="pl-kos">.</span><span class="pl-c1">js</span>
<span class="pl-s">"use strict"</span><span class="pl-kos">;</span>

<span class="pl-c">// all three var x|y|z = 4 should be errors I believe so we error on all</span>
<span class="pl-c">//   v8 --harmony allows the first but not the second and last (2015-08-24: this has now been fixed in v8 so all errors)</span>

<span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-c1">true</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-k">let</span> <span class="pl-s1">x</span> <span class="pl-c1">=</span> <span class="pl-c1">3</span><span class="pl-kos">;</span>
    <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-c1">true</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-k">var</span> <span class="pl-s1">x</span> <span class="pl-c1">=</span> <span class="pl-c1">4</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span>
<span class="pl-kos">}</span>

<span class="pl-k">let</span> <span class="pl-s1">y</span> <span class="pl-c1">=</span> <span class="pl-c1">3</span><span class="pl-kos">;</span>
<span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-c1">true</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-k">var</span> <span class="pl-s1">y</span> <span class="pl-c1">=</span> <span class="pl-c1">4</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span>

<span class="pl-kos">(</span><span class="pl-k">function</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-c1">true</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-k">let</span> <span class="pl-s1">z</span> <span class="pl-c1">=</span> <span class="pl-c1">3</span><span class="pl-kos">;</span>
        <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-c1">true</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
            <span class="pl-k">var</span> <span class="pl-s1">z</span> <span class="pl-c1">=</span> <span class="pl-c1">4</span><span class="pl-kos">;</span>
        <span class="pl-kos">}</span>
    <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre></div>
<p dir="auto">Babel should error on all three redeclaration, here you can see the output from defs.js.</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="~/projects/defs.js/tests % cat var-inside-let-stderr
line 9: x is already declared
line 15: y is already declared
line 22: z is already declared"><pre class="notranslate"><code class="notranslate">~/projects/defs.js/tests % cat var-inside-let-stderr
line 9: x is already declared
line 15: y is already declared
line 22: z is already declared
</code></pre></div>
<p dir="auto">However, Babel only errors on the middle one <code class="notranslate">TypeError: var-inside-let-copy.js: Line 15: Duplicate declaration "y"</code></p>