<p dir="auto">Note this is the step before actual compilation occurs.  I'm not sure how to debug it, but below is the output for the compilation.</p>
<p dir="auto">Here is my babelrc</p>
<div class="highlight highlight-source-json notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="{
  &quot;presets&quot;: [&quot;es2015&quot;, &quot;react&quot;, &quot;stage-0&quot;]
}"><pre class="notranslate">{
  <span class="pl-ent">"presets"</span>: [<span class="pl-s"><span class="pl-pds">"</span>es2015<span class="pl-pds">"</span></span>, <span class="pl-s"><span class="pl-pds">"</span>react<span class="pl-pds">"</span></span>, <span class="pl-s"><span class="pl-pds">"</span>stage-0<span class="pl-pds">"</span></span>]
}</pre></div>
<p dir="auto">Here is the output running with <code class="notranslate">DEBUG=babel</code></p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="❯ time DEBUG=babel babel -d blah button-test.js icon-test.js
  babel [BABEL] button-test.js: Parse start +0ms
  babel [BABEL] button-test.js: Parse stop +17ms
  babel [BABEL] button-test.js: Start set AST +2ms
  babel [BABEL] button-test.js: End set AST +12ms
  babel [BABEL] button-test.js: Start transform traverse +0ms
  babel [BABEL] button-test.js: End transform traverse +36ms
  babel [BABEL] button-test.js: Generation start +1ms
  babel [BABEL] button-test.js: Generation end +8ms
button-test.js -&gt; blah/button-test.js
  babel [BABEL] icon-test.js: Parse start +4ms
  babel [BABEL] icon-test.js: Parse stop +6ms
  babel [BABEL] icon-test.js: Start set AST +0ms
  babel [BABEL] icon-test.js: End set AST +5ms
  babel [BABEL] icon-test.js: Start transform traverse +1ms
  babel [BABEL] icon-test.js: End transform traverse +7ms
  babel [BABEL] icon-test.js: Generation start +0ms
  babel [BABEL] icon-test.js: Generation end +3ms
icon-test.js -&gt; blah/icon-test.js
DEBUG=babel babel -d blah button-test.js icon-test.js  6.40s user 1.09s system 23% cpu 31.996 total"><pre class="notranslate"><code class="notranslate">❯ time DEBUG=babel babel -d blah button-test.js icon-test.js
  babel [BABEL] button-test.js: Parse start +0ms
  babel [BABEL] button-test.js: Parse stop +17ms
  babel [BABEL] button-test.js: Start set AST +2ms
  babel [BABEL] button-test.js: End set AST +12ms
  babel [BABEL] button-test.js: Start transform traverse +0ms
  babel [BABEL] button-test.js: End transform traverse +36ms
  babel [BABEL] button-test.js: Generation start +1ms
  babel [BABEL] button-test.js: Generation end +8ms
button-test.js -&gt; blah/button-test.js
  babel [BABEL] icon-test.js: Parse start +4ms
  babel [BABEL] icon-test.js: Parse stop +6ms
  babel [BABEL] icon-test.js: Start set AST +0ms
  babel [BABEL] icon-test.js: End set AST +5ms
  babel [BABEL] icon-test.js: Start transform traverse +1ms
  babel [BABEL] icon-test.js: End transform traverse +7ms
  babel [BABEL] icon-test.js: Generation start +0ms
  babel [BABEL] icon-test.js: Generation end +3ms
icon-test.js -&gt; blah/icon-test.js
DEBUG=babel babel -d blah button-test.js icon-test.js  6.40s user 1.09s system 23% cpu 31.996 total
</code></pre></div>
<p dir="auto">How can I provide better information on what's happening before compilation?</p>
<p dir="auto">Inspired by <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="191777331" data-permission-text="Title is private" data-url="https://github.com/babel/minify/issues/300" data-hovercard-type="issue" data-hovercard-url="/babel/minify/issues/300/hovercard" href="https://github.com/babel/minify/issues/300">babel/minify#300</a>, <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="200782687" data-permission-text="Title is private" data-url="https://github.com/babel/minify/issues/375" data-hovercard-type="pull_request" data-hovercard-url="/babel/minify/pull/375/hovercard" href="https://github.com/babel/minify/pull/375">babel/minify#375</a> and <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="191804361" data-permission-text="Title is private" data-url="https://github.com/babel/babel/issues/4896" data-hovercard-type="pull_request" data-hovercard-url="/babel/babel/pull/4896/hovercard" href="https://github.com/babel/babel/pull/4896">#4896</a> I was thinking how to properly solve all this cases. Here a short introduction to the problem:</p>
<p dir="auto">Assuming this code:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="active ? a() : b();"><pre class="notranslate"><code class="notranslate">active ? a() : b();
</code></pre></div>
<p dir="auto">Now assuming a transform removes all <code class="notranslate">a()</code> calls, and the resulting code gets</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="active ? : b();"><pre class="notranslate"><code class="notranslate">active ? : b();
</code></pre></div>
<p dir="auto">This is not valid js syntax anymore and babel currently throws somewhere after calling <code class="notranslate">path.remove()</code> in this case.</p>
<p dir="auto">Currently we have babel handling some of this cases (loops, and arrow functions) but not all of them. Instead of adding more and more rules how to delete certain nodes with certain parents I propose a breaking change to the remove functionality of paths:</p>
<h3 dir="auto">Changing path.remove()</h3>
<p dir="auto">I propose changing <code class="notranslate">path.remove()</code> to do what it says, removal of a node/path. If the resulting  AST is not valid it should throw. Also remove the current removal-hooks for loops and arrow functions and throw instead if for example a loop ends up with the body node being <code class="notranslate">null</code>.</p>
<h3 dir="auto">Introduce path.isRemovable()</h3>
<p dir="auto">A boolean method that returns true if it is safe to remove the path or false if not.</p>
<h3 dir="auto">Introduce path.getSafeReplacement()</h3>
<p dir="auto">A function that returns a safe replacement for the current node. It would return a new node that is a "nullable" variant for the current node (<code class="notranslate">Identifier&lt;"undefined"&gt;</code>, <code class="notranslate">BlockStatement</code>, ...) or throw if it is not possible (like <code class="notranslate">var a = 1;</code> Remove Identifier <code class="notranslate">a</code> here)</p>
<h3 dir="auto">Introduce path.removeOrReplace();</h3>
<p dir="auto">This would more be a sum of the 3 methods I mentioned before and might not be necessary at all, but could be easier to use for plugin authors.</p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="removeOrReplace() {
   if (this.isRemovable()) {
      this.remove();
   } else {
      this.replaceWith(this.getSafeReplacement());
   }
}"><pre class="notranslate"><span class="pl-en">removeOrReplace</span><span class="pl-kos">(</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-smi">this</span><span class="pl-kos">.</span><span class="pl-en">isRemovable</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
      <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">remove</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
   <span class="pl-kos">}</span> <span class="pl-k">else</span> <span class="pl-kos">{</span>
      <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">replaceWith</span><span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">getSafeReplacement</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">The new functions could be added in 6.x and the change to <code class="notranslate">remove()</code> in 7.0, so that people can migrate.</p>
<p dir="auto">The ultimate goal of this proposal is to make <code class="notranslate">remove()</code> do what it name says and give plugin authors the tools to handle all the edge cases where remove is not as easy and not every plugin should handle all this cases on their own and duplicate the logic of <code class="notranslate">if-parent-is-ternary-operator then-replace-with-undefined otherwise-if-...</code>.</p>
<p dir="auto">All of this is just a proposal and I would like to hear what you think about it. If you have better ideas or what you don't like about it.</p>
<p dir="auto">I want to do more research and see how other handle that (estraverse for example).</p>
<p dir="auto"><a class="user-mention notranslate" data-hovercard-type="user" data-hovercard-url="/users/boopathi/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/boopathi">@boopathi</a> <a class="user-mention notranslate" data-hovercard-type="user" data-hovercard-url="/users/kangax/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/kangax">@kangax</a> <a class="user-mention notranslate" data-hovercard-type="user" data-hovercard-url="/users/loganfsmyth/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/loganfsmyth">@loganfsmyth</a> <a class="user-mention notranslate" data-hovercard-type="user" data-hovercard-url="/users/DrewML/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/DrewML">@DrewML</a></p>