<h2 dir="auto">Bug Report</h2>

<ul class="contains-task-list">
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox"> I would like to work on a fix!</li>
</ul>

<p dir="auto"><strong>Current behavior</strong></p>
<p dir="auto">When using the programmatic API, babel always throws an error when I use <code class="notranslate">path.buildCodeFrameError</code>.</p>
<p dir="auto"><strong>Input Code</strong></p>
<p dir="auto">A simple example:</p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="const { parseAsync, traverse } = require('@babel/core');

async function demo() {
  const parsed = await parseAsync('foo.bar()', { sourceFileName: 'foo.js' });
  traverse(parsed, {
    enter(path) {
      path.buildCodeFrameError('some error');
    }
  })
}

demo().catch(console.error);"><pre class="notranslate"><span class="pl-k">const</span> <span class="pl-kos">{</span> parseAsync<span class="pl-kos">,</span> traverse <span class="pl-kos">}</span> <span class="pl-c1">=</span> <span class="pl-en">require</span><span class="pl-kos">(</span><span class="pl-s">'@babel/core'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-k">async</span> <span class="pl-k">function</span> <span class="pl-en">demo</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
  <span class="pl-k">const</span> <span class="pl-s1">parsed</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-en">parseAsync</span><span class="pl-kos">(</span><span class="pl-s">'foo.bar()'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">sourceFileName</span>: <span class="pl-s">'foo.js'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-en">traverse</span><span class="pl-kos">(</span><span class="pl-s1">parsed</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
    <span class="pl-en">enter</span><span class="pl-kos">(</span><span class="pl-s1">path</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
      <span class="pl-s1">path</span><span class="pl-kos">.</span><span class="pl-en">buildCodeFrameError</span><span class="pl-kos">(</span><span class="pl-s">'some error'</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-en">demo</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">catch</span><span class="pl-kos">(</span><span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-c1">error</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre></div>
<p dir="auto"><strong>Expected behavior</strong><br>
I would expect an awesomely formatted code frame error.</p>
<p dir="auto"><strong>Babel Configuration (babel.config.js, .babelrc, package.json#babel, cli command, .eslintrc)</strong><br>
<em>none</em></p>
<p dir="auto"><strong>Environment</strong></p>

<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="
  System:
    OS: Windows 10 10.0.19041
  Binaries:
    Node: 12.16.1 - C:\Program Files\nodejs\node.EXE
    Yarn: 1.22.4 - ~\AppData\Roaming\npm\yarn.CMD
    npm: 6.14.5 - C:\Program Files\nodejs\npm.CMD
  npmPackages:
    @babel/core: ^7.9.6 =&gt; 7.10.4
    @babel/generator: ^7.9.6 =&gt; 7.10.4
    @babel/parser: ^7.9.6 =&gt; 7.10.4
    @babel/plugin-proposal-decorators: ^7.8.3 =&gt; 7.10.4
    @babel/preset-react: ^7.9.4 =&gt; 7.10.4
    @babel/preset-typescript: ^7.9.0 =&gt; 7.10.4
    babel-plugin-transform-decorators-legacy: ^1.3.5 =&gt; 1.3.5"><pre class="notranslate"><code class="notranslate">
  System:
    OS: Windows 10 10.0.19041
  Binaries:
    Node: 12.16.1 - C:\Program Files\nodejs\node.EXE
    Yarn: 1.22.4 - ~\AppData\Roaming\npm\yarn.CMD
    npm: 6.14.5 - C:\Program Files\nodejs\npm.CMD
  npmPackages:
    @babel/core: ^7.9.6 =&gt; 7.10.4
    @babel/generator: ^7.9.6 =&gt; 7.10.4
    @babel/parser: ^7.9.6 =&gt; 7.10.4
    @babel/plugin-proposal-decorators: ^7.8.3 =&gt; 7.10.4
    @babel/preset-react: ^7.9.4 =&gt; 7.10.4
    @babel/preset-typescript: ^7.9.0 =&gt; 7.10.4
    babel-plugin-transform-decorators-legacy: ^1.3.5 =&gt; 1.3.5
</code></pre></div>
<h2 dir="auto">Bug Report</h2>
<p dir="auto">This related to <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="356502875" data-permission-text="Title is private" data-url="https://github.com/babel/babel/issues/8617" data-hovercard-type="issue" data-hovercard-url="/babel/babel/issues/8617/hovercard" href="https://github.com/babel/babel/issues/8617">#8617</a></p>

<ul class="contains-task-list">
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> I would like to work on a fix!</li>
</ul>

<p dir="auto"><strong>Current Behavior</strong><br>
<code class="notranslate">@babel/parser</code> has a different behavior when <code class="notranslate">estree</code> enabled, and when not.</p>
<p dir="auto"><strong>Input Code</strong><br>
When <code class="notranslate">estree</code> disabled code with <code class="notranslate">Duplicated variable declaration</code> throws while parsing:</p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="const {parse} = require('@babel/parser');
const traverse = require('@babel/traverse').default;

const code = `function square(n) {
  const n = 1;
}`;

// crash with an error: Identifier 'n' has already been declared (1:16)
const ast = parse(code);"><pre class="notranslate"><span class="pl-k">const</span> <span class="pl-kos">{</span>parse<span class="pl-kos">}</span> <span class="pl-c1">=</span> <span class="pl-en">require</span><span class="pl-kos">(</span><span class="pl-s">'@babel/parser'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">const</span> <span class="pl-s1">traverse</span> <span class="pl-c1">=</span> <span class="pl-en">require</span><span class="pl-kos">(</span><span class="pl-s">'@babel/traverse'</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-c1">default</span><span class="pl-kos">;</span>

<span class="pl-k">const</span> <span class="pl-s1">code</span> <span class="pl-c1">=</span> <span class="pl-s">`function square(n) {</span>
<span class="pl-s">  const n = 1;</span>
<span class="pl-s">}`</span><span class="pl-kos">;</span>

<span class="pl-c">// crash with an error: Identifier 'n' has already been declared (1:16)</span>
<span class="pl-k">const</span> <span class="pl-s1">ast</span> <span class="pl-c1">=</span> <span class="pl-en">parse</span><span class="pl-kos">(</span><span class="pl-s1">code</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre></div>
<p dir="auto">When <code class="notranslate">estree</code> mode enabled code is parsed, but can't be traversed because of <code class="notranslate">this.hub</code> is undefined:</p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="const {parse} = require('@babel/parser');
const traverse = require('@babel/traverse').default;

const code = `function square(n) {
  const n = 1;
}`;

const ast = parse(code, {
    plugins: [
        'estree',
    ]
});

traverse(ast, {
  enter(path) {
      console.log('n');
  }
});

/*
    throw this.hub.buildError(id, `Duplicate declaration &quot;${name}&quot;`, TypeError);
                     ^

TypeError: Cannot read property 'buildError' of undefined
    at Scope.checkBlockScopedCollisions (/home/coderaiser/node_modules/@babel/traverse/lib/scope/index.js:402:22)
*/"><pre class="notranslate"><span class="pl-k">const</span> <span class="pl-kos">{</span>parse<span class="pl-kos">}</span> <span class="pl-c1">=</span> <span class="pl-en">require</span><span class="pl-kos">(</span><span class="pl-s">'@babel/parser'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">const</span> <span class="pl-s1">traverse</span> <span class="pl-c1">=</span> <span class="pl-en">require</span><span class="pl-kos">(</span><span class="pl-s">'@babel/traverse'</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-c1">default</span><span class="pl-kos">;</span>

<span class="pl-k">const</span> <span class="pl-s1">code</span> <span class="pl-c1">=</span> <span class="pl-s">`function square(n) {</span>
<span class="pl-s">  const n = 1;</span>
<span class="pl-s">}`</span><span class="pl-kos">;</span>

<span class="pl-k">const</span> <span class="pl-s1">ast</span> <span class="pl-c1">=</span> <span class="pl-en">parse</span><span class="pl-kos">(</span><span class="pl-s1">code</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
    <span class="pl-c1">plugins</span>: <span class="pl-kos">[</span>
        <span class="pl-s">'estree'</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-s1">traverse</span><span class="pl-kos">(</span><span class="pl-s1">ast</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-en">enter</span><span class="pl-kos">(</span><span class="pl-s1">path</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-s">'n'</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-c">/*</span>
<span class="pl-c">    throw this.hub.buildError(id, `Duplicate declaration "${name}"`, TypeError);</span>
<span class="pl-c">                     ^</span>
<span class="pl-c"></span>
<span class="pl-c">TypeError: Cannot read property 'buildError' of undefined</span>
<span class="pl-c">    at Scope.checkBlockScopedCollisions (/home/coderaiser/node_modules/@babel/traverse/lib/scope/index.js:402:22)</span>
<span class="pl-c">*/</span></pre></div>
<p dir="auto">Same result when instead of <code class="notranslate">estree</code> plugin, <code class="notranslate">errorRecovery</code> enabled.</p>
<p dir="auto"><strong>Expected behavior/code</strong><br>
Would be great if in <code class="notranslate">estree</code> mode <code class="notranslate">babel</code> throws while parsing and/or can throw while traversing<br>
about <code class="notranslate">Duplicate declaration</code>.</p>
<p dir="auto"><strong>Environment</strong></p>
<ul dir="auto">
<li>Babel version(s): <code class="notranslate">v7.9.4</code></li>
<li>Node/npm version: Node 12(13)/npm 6</li>
<li>OS: <code class="notranslate">Ubuntu</code></li>
<li>Monorepo: no</li>
<li>How you are using Babel: <code class="notranslate">parse</code>, <code class="notranslate">traverse</code></li>
</ul>
<p dir="auto"><strong>Possible Solution</strong></p>
<p dir="auto">I suggest to use <code class="notranslate">TypeError</code>, because this is what <a href="https://github.com/babel/babel/blob/f6c7bf36cec81baaba8c37e572985bb59ca334b1/packages/babel-traverse/src/hub.js">hub actually does</a>, this way:</p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="throw TypeError(`Duplicate declaration &quot;${name}&quot;`);"><pre class="notranslate"><span class="pl-k">throw</span> <span class="pl-v">TypeError</span><span class="pl-kos">(</span><span class="pl-s">`Duplicate declaration "<span class="pl-s1"><span class="pl-kos">${</span><span class="pl-s1">name</span><span class="pl-kos">}</span></span>"`</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre></div>
<p dir="auto">If of course <code class="notranslate">buildError</code> doesn't used in development purpose to set breakpoint on error building, anyways <code class="notranslate">Chrome Developer Tools</code> debugger already suggest similar feature <code class="notranslate">pause on exceptions</code> (caught and uncaught).</p>