<p dir="auto">Bug Report:<br>
When extending a native type possibleConstructorReturn helper returns the root prototype, instead of the correctly extended prototype.</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="class ObjX extends Object{
  logKeys(){ 
    console.log(Object.keys(this)); 
  }
}

const exObject = new ObjX;
exObject['key'] = 'val';
exObject.logKeys();"><pre class="notranslate"><span class="pl-k">class</span> <span class="pl-v">ObjX</span> <span class="pl-k">extends</span> <span class="pl-v">Object</span><span class="pl-kos">{</span>
  <span class="pl-en">logKeys</span><span class="pl-kos">(</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-v">Object</span><span class="pl-kos">.</span><span class="pl-en">keys</span><span class="pl-kos">(</span><span class="pl-smi">this</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-k">const</span> <span class="pl-s1">exObject</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-v">ObjX</span><span class="pl-kos">;</span>
<span class="pl-s1">exObject</span><span class="pl-kos">[</span><span class="pl-s">'key'</span><span class="pl-kos">]</span> <span class="pl-c1">=</span> <span class="pl-s">'val'</span><span class="pl-kos">;</span>
<span class="pl-s1">exObject</span><span class="pl-kos">.</span><span class="pl-en">logKeys</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre></div>
<h3 dir="auto">Babel/Babylon 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;presets&quot;:[&quot;es2015&quot;,&quot;stage-1&quot;]
}"><pre class="notranslate"><span class="pl-kos">{</span>
  <span class="pl-s">"presets"</span>:<span class="pl-kos">[</span><span class="pl-s">"es2015"</span><span class="pl-kos">,</span><span class="pl-s">"stage-1"</span><span class="pl-kos">]</span>
<span class="pl-kos">}</span></pre></div>
<h3 dir="auto">Expected Behavior</h3>
<p dir="auto">If you drop the above code directly in your browser console, it will quite happily output an array of <code class="notranslate">['key']</code>.</p>
<p dir="auto">Extending native types, while uncommon has been a standard capability in javascript for a really long time. This behavior should be preserved by babel.</p>
<h3 dir="auto">Current Behavior</h3>
<p dir="auto">Currently, Babel will just bind the native constructor to the extended class. So calling new ObjX results in just a native object (none of the methods or properties of the extended class are preserved).</p>
<h3 dir="auto">Possible Solution</h3>
<p dir="auto">I spent an hour or two digging through Babel core and the flaw in logic is pretty apparent. When you extend a native class, Babel does this:</p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="return _possibleConstructorReturn(this, (ObjX.__proto__ || Object.getPrototypeOf(ObjX)).apply(this, arguments));"><pre class="notranslate"><span class="pl-k">return</span> <span class="pl-en">_possibleConstructorReturn</span><span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">,</span> <span class="pl-kos">(</span><span class="pl-v">ObjX</span><span class="pl-kos">.</span><span class="pl-c1">__proto__</span> <span class="pl-c1">||</span> <span class="pl-v">Object</span><span class="pl-kos">.</span><span class="pl-en">getPrototypeOf</span><span class="pl-kos">(</span><span class="pl-v">ObjX</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">apply</span><span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">,</span> <span class="pl-smi">arguments</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre></div>
<p dir="auto">With possibleConstructorReturn relying on the following:</p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="return call &amp;&amp; (typeof call === &quot;object&quot; || typeof call === &quot;function&quot;) ? call : self;"><pre class="notranslate"><span class="pl-k">return</span> <span class="pl-s1">call</span> <span class="pl-c1">&amp;&amp;</span> <span class="pl-kos">(</span><span class="pl-k">typeof</span> <span class="pl-s1">call</span> <span class="pl-c1">===</span> <span class="pl-s">"object"</span> <span class="pl-c1">||</span> <span class="pl-k">typeof</span> <span class="pl-s1">call</span> <span class="pl-c1">===</span> <span class="pl-s">"function"</span><span class="pl-kos">)</span> ? <span class="pl-s1">call</span> : <span class="pl-s1">self</span><span class="pl-kos">;</span></pre></div>
<p dir="auto">In the case of creating a new class in Babel, the origin class doesn't call possibleConstructorReturn, it just does the classCallCheck. When you extend that, possibleConstructorReturn is called on a class that extends a brand new prototype. In which case, it does its error check and returns nothing, you end up with the 2 arguments, one being the extended prototype, and one being undefined. All works as it should.</p>
<p dir="auto">In the case of extending a native type, by calling apply on the prototype you end up with a newly assigned value, which leaves us with self and call defined in possibleConstructorReturn and the blank native gets returned instead of self, which gives you the native prototype instead of your extended class.</p>
<p dir="auto">It's pretty easy to solve this in a small scope, because when extending a native type it should just return self (in which case everything works fine, in this limited scenario). I was able to play with the logic in possibleConstructorReturn to try to get it to both work, as well as pass all of the current test scenarios, but when I tried it out in practice it obviously impacted other things.</p>
<p dir="auto">This tells me that the logic that currently exists is very purposeful, but is also tightly coupled to handle a lot of scenarios, and it felt like touching this code required somebody more familiar with how/why Babel does classes the way it does.</p>
<p dir="auto">Perhaps a low impact solution would be when generating the code, check to see if the class is extending a native type, in which case skip the possibleConstructorReturn logic when compiling the class?</p>
<p dir="auto">Current Babel transform, when it comes to call the parent</p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="function _possibleConstructorReturn(self, call) {
  if (!self) {
    throw new ReferenceError(&quot;this hasn't been initialised - super() hasn't been called&quot;);
  }
  return call &amp;&amp; (typeof call === &quot;object&quot; || typeof call === &quot;function&quot;) ? call : self;
}"><pre class="notranslate"><span class="pl-k">function</span> <span class="pl-en">_possibleConstructorReturn</span><span class="pl-kos">(</span><span class="pl-s1">self</span><span class="pl-kos">,</span> <span class="pl-s1">call</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">!</span><span class="pl-s1">self</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-k">throw</span> <span class="pl-k">new</span> <span class="pl-v">ReferenceError</span><span class="pl-kos">(</span><span class="pl-s">"this hasn't been initialised - super() hasn't been called"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-kos">}</span>
  <span class="pl-k">return</span> <span class="pl-s1">call</span> <span class="pl-c1">&amp;&amp;</span> <span class="pl-kos">(</span><span class="pl-k">typeof</span> <span class="pl-s1">call</span> <span class="pl-c1">===</span> <span class="pl-s">"object"</span> <span class="pl-c1">||</span> <span class="pl-k">typeof</span> <span class="pl-s1">call</span> <span class="pl-c1">===</span> <span class="pl-s">"function"</span><span class="pl-kos">)</span> ? <span class="pl-s1">call</span> : <span class="pl-s1">self</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">It's a way too poor implementation.</p>
<p dir="auto">If we take the current basic ES6 compat syntax:</p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="class List extends Array {}"><pre class="notranslate"><span class="pl-k">class</span> <span class="pl-v">List</span> <span class="pl-k">extends</span> <span class="pl-v">Array</span> <span class="pl-kos">{</span><span class="pl-kos">}</span></pre></div>
<p dir="auto">We'll realize babel does a bad job.</p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="var l = new List();
l instanceof List; // false"><pre class="notranslate"><span class="pl-k">var</span> <span class="pl-s1">l</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-v">List</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-s1">l</span> <span class="pl-k">instanceof</span> <span class="pl-v">List</span><span class="pl-kos">;</span> <span class="pl-c">// false</span></pre></div>
<p dir="auto">The reason is simple: Babel replace the returns and exit, without caring about userland expectations.</p>
<p dir="auto">This is how above basic extend should desugar:</p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="function List() {
  return Object.setPrototypeOf(
    Array.apply(this, arguments),
    List.prototype
  );
}"><pre class="notranslate"><span class="pl-k">function</span> <span class="pl-v">List</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
  <span class="pl-k">return</span> <span class="pl-v">Object</span><span class="pl-kos">.</span><span class="pl-en">setPrototypeOf</span><span class="pl-kos">(</span>
    <span class="pl-v">Array</span><span class="pl-kos">.</span><span class="pl-en">apply</span><span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">,</span> <span class="pl-smi">arguments</span><span class="pl-kos">)</span><span class="pl-kos">,</span>
    <span class="pl-v">List</span><span class="pl-kos">.</span><span class="pl-c1">prototype</span>
  <span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">It's a very ad-hoc case for the initial example that currently fails, but it's good enough to understand that inheriting the prototype is the least of the problem.</p>
<p dir="auto">Indeed, we have 3 ways to do that within a transpiled code:</p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="// losing the initial prototype
// for polyfilled ES5+ or lower
List.prototype = Object.create(
  Array.prototype,
  {constructor: {
    configurable: true,
    writable: true,
    value: List.prototype
  }}
);

// using a cleaner way
// for ES5+ compliant targets
Object.setPrototypeOf(
  List.prototype,
  Array.prototype
);

// using a cleaner way
// that works well with
// partially polyfilled .setPrototypeOf
List.prototype = Object.setPrototypeOf(
  List.prototype,
  Array.prototype
);"><pre class="notranslate"><span class="pl-c">// losing the initial prototype</span>
<span class="pl-c">// for polyfilled ES5+ or lower</span>
<span class="pl-v">List</span><span class="pl-kos">.</span><span class="pl-c1">prototype</span> <span class="pl-c1">=</span> <span class="pl-v">Object</span><span class="pl-kos">.</span><span class="pl-en">create</span><span class="pl-kos">(</span>
  <span class="pl-v">Array</span><span class="pl-kos">.</span><span class="pl-c1">prototype</span><span class="pl-kos">,</span>
  <span class="pl-kos">{</span><span class="pl-c1">constructor</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">configurable</span>: <span class="pl-c1">true</span><span class="pl-kos">,</span>
    <span class="pl-c1">writable</span>: <span class="pl-c1">true</span><span class="pl-kos">,</span>
    <span class="pl-c1">value</span>: <span class="pl-v">List</span><span class="pl-kos">.</span><span class="pl-c1">prototype</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">// using a cleaner way</span>
<span class="pl-c">// for ES5+ compliant targets</span>
<span class="pl-v">Object</span><span class="pl-kos">.</span><span class="pl-en">setPrototypeOf</span><span class="pl-kos">(</span>
  <span class="pl-v">List</span><span class="pl-kos">.</span><span class="pl-c1">prototype</span><span class="pl-kos">,</span>
  <span class="pl-v">Array</span><span class="pl-kos">.</span><span class="pl-c1">prototype</span>
<span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-c">// using a cleaner way</span>
<span class="pl-c">// that works well with</span>
<span class="pl-c">// partially polyfilled .setPrototypeOf</span>
<span class="pl-v">List</span><span class="pl-kos">.</span><span class="pl-c1">prototype</span> <span class="pl-c1">=</span> <span class="pl-v">Object</span><span class="pl-kos">.</span><span class="pl-en">setPrototypeOf</span><span class="pl-kos">(</span>
  <span class="pl-v">List</span><span class="pl-kos">.</span><span class="pl-c1">prototype</span><span class="pl-kos">,</span>
  <span class="pl-v">Array</span><span class="pl-kos">.</span><span class="pl-c1">prototype</span>
<span class="pl-kos">)</span><span class="pl-kos">;</span></pre></div>
<p dir="auto">Solved the inheritance bit, considering Babel also set the prototype of each constructor,<br>
we need to address cases where a <code class="notranslate">super</code> call might "<em>upgrade</em>" the current context, like it is for <code class="notranslate">HTMLELement</code> or exotic native objects.</p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="// native ES6 static example
class List extends Array {
  constructor(a, b, c) {
    super(a, b);
    this.push(c);
  }
}"><pre class="notranslate"><span class="pl-c">// native ES6 static example</span>
<span class="pl-k">class</span> <span class="pl-v">List</span> <span class="pl-k">extends</span> <span class="pl-v">Array</span> <span class="pl-kos">{</span>
  <span class="pl-en">constructor</span><span class="pl-kos">(</span><span class="pl-s1">a</span><span class="pl-kos">,</span> <span class="pl-s1">b</span><span class="pl-kos">,</span> <span class="pl-s1">c</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-smi">super</span><span class="pl-kos">(</span><span class="pl-s1">a</span><span class="pl-kos">,</span> <span class="pl-s1">b</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">push</span><span class="pl-kos">(</span><span class="pl-s1">c</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">Above case should desugar to something like the follwoing:</p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="function List(a, b, c) {
  // the super bit
  var self = Object.setPrototypeOf(
    Array.call(this, a, b),
    List.prototype
  );
  // the rest with swapped context
  self.push(c);
  // at the end
  return self;
}"><pre class="notranslate"><span class="pl-k">function</span> <span class="pl-v">List</span><span class="pl-kos">(</span><span class="pl-s1">a</span><span class="pl-kos">,</span> <span class="pl-s1">b</span><span class="pl-kos">,</span> <span class="pl-s1">c</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
  <span class="pl-c">// the super bit</span>
  <span class="pl-k">var</span> <span class="pl-s1">self</span> <span class="pl-c1">=</span> <span class="pl-v">Object</span><span class="pl-kos">.</span><span class="pl-en">setPrototypeOf</span><span class="pl-kos">(</span>
    <span class="pl-v">Array</span><span class="pl-kos">.</span><span class="pl-en">call</span><span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">,</span> <span class="pl-s1">a</span><span class="pl-kos">,</span> <span class="pl-s1">b</span><span class="pl-kos">)</span><span class="pl-kos">,</span>
    <span class="pl-v">List</span><span class="pl-kos">.</span><span class="pl-c1">prototype</span>
  <span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-c">// the rest with swapped context</span>
  <span class="pl-s1">self</span><span class="pl-kos">.</span><span class="pl-en">push</span><span class="pl-kos">(</span><span class="pl-s1">c</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-c">// at the end</span>
  <span class="pl-k">return</span> <span class="pl-s1">self</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">which is also ad-hoc example code for the previous example.</p>
<p dir="auto">Considering a transpiler will get the arguments part easily right, this is how previous case could be generically transpiled for arguments used in both constructors:</p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="// to make it as generic as possible
function Child() {

  // the super call bit desugar to ...
  var
    instance = Object.getPrototypeOf(Child)
        .apply(this, arguments),
    type = instance ? typeof instance : '',
    // if Parent overwrote its default return
    self = (type === 'object' || type === 'function') ?
      // upgrade the instance to reflect Child constructor
      Object.setPrototypeOf(instance, Child.prototype) :
      // otherwise use the current context as is
      this
  ;

  // at this point, the rest of the constructor
  // should use `self` instead of `this`
  self.push(c);

  // and return `self` reference at the end
  return self;
}"><pre class="notranslate"><span class="pl-c">// to make it as generic as possible</span>
<span class="pl-k">function</span> <span class="pl-v">Child</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>

  <span class="pl-c">// the super call bit desugar to ...</span>
  <span class="pl-k">var</span>
    <span class="pl-s1">instance</span> <span class="pl-c1">=</span> <span class="pl-v">Object</span><span class="pl-kos">.</span><span class="pl-en">getPrototypeOf</span><span class="pl-kos">(</span><span class="pl-v">Child</span><span class="pl-kos">)</span>
        <span class="pl-kos">.</span><span class="pl-en">apply</span><span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">,</span> <span class="pl-smi">arguments</span><span class="pl-kos">)</span><span class="pl-kos">,</span>
    <span class="pl-s1">type</span> <span class="pl-c1">=</span> <span class="pl-s1">instance</span> ? <span class="pl-k">typeof</span> <span class="pl-s1">instance</span> : <span class="pl-s">''</span><span class="pl-kos">,</span>
    <span class="pl-c">// if Parent overwrote its default return</span>
    <span class="pl-s1">self</span> <span class="pl-c1">=</span> <span class="pl-kos">(</span><span class="pl-s1">type</span> <span class="pl-c1">===</span> <span class="pl-s">'object'</span> <span class="pl-c1">||</span> <span class="pl-s1">type</span> <span class="pl-c1">===</span> <span class="pl-s">'function'</span><span class="pl-kos">)</span> ?
      <span class="pl-c">// upgrade the instance to reflect Child constructor</span>
      <span class="pl-v">Object</span><span class="pl-kos">.</span><span class="pl-en">setPrototypeOf</span><span class="pl-kos">(</span><span class="pl-s1">instance</span><span class="pl-kos">,</span> <span class="pl-v">Child</span><span class="pl-kos">.</span><span class="pl-c1">prototype</span><span class="pl-kos">)</span> :
      <span class="pl-c">// otherwise use the current context as is</span>
      <span class="pl-smi">this</span>
  <span class="pl-kos">;</span>

  <span class="pl-c">// at this point, the rest of the constructor</span>
  <span class="pl-c">// should use `self` instead of `this`</span>
  <span class="pl-s1">self</span><span class="pl-kos">.</span><span class="pl-en">push</span><span class="pl-kos">(</span><span class="pl-s1">c</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

  <span class="pl-c">// and return `self` reference at the end</span>
  <span class="pl-k">return</span> <span class="pl-s1">self</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">The last problem is that modern syntax would use <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect" rel="nofollow">Reflect</a> to create any sort of object, instead of old, ES3 friendly, <code class="notranslate">.call</code> or <code class="notranslate">.apply</code> way.</p>
<p dir="auto">Following a past, present, and even future proof approach:</p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="var
  reConstruct = typeof Reflect === 'object' ?
    Reflect.construct :
    function (Parent, args, Child) {
      return Parent.apply(this, args);
    }
;

function Child() {

  // the super call bit
  var
    instance = reConstruct.call(
      this,
      Object.getPrototypeOf(Child),
      arguments,
      Child
    ),
    type = instance ? typeof instance : '',
    self = (type === 'object' || type === 'function') ?
      Object.setPrototypeOf(instance, Child.prototype) :
      this
  ;

  // the rest of the constructor body
  self.push(c);

  // at the end or instead of empty returns
  return self;
}"><pre class="notranslate"><span class="pl-k">var</span>
  <span class="pl-s1">reConstruct</span> <span class="pl-c1">=</span> <span class="pl-k">typeof</span> <span class="pl-v">Reflect</span> <span class="pl-c1">===</span> <span class="pl-s">'object'</span> ?
    <span class="pl-v">Reflect</span><span class="pl-kos">.</span><span class="pl-c1">construct</span> :
    <span class="pl-k">function</span> <span class="pl-kos">(</span><span class="pl-v">Parent</span><span class="pl-kos">,</span> <span class="pl-s1">args</span><span class="pl-kos">,</span> <span class="pl-v">Child</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
      <span class="pl-k">return</span> <span class="pl-v">Parent</span><span class="pl-kos">.</span><span class="pl-en">apply</span><span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">,</span> <span class="pl-s1">args</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">function</span> <span class="pl-v">Child</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>

  <span class="pl-c">// the super call bit</span>
  <span class="pl-k">var</span>
    <span class="pl-s1">instance</span> <span class="pl-c1">=</span> <span class="pl-s1">reConstruct</span><span class="pl-kos">.</span><span class="pl-en">call</span><span class="pl-kos">(</span>
      <span class="pl-smi">this</span><span class="pl-kos">,</span>
      <span class="pl-v">Object</span><span class="pl-kos">.</span><span class="pl-en">getPrototypeOf</span><span class="pl-kos">(</span><span class="pl-v">Child</span><span class="pl-kos">)</span><span class="pl-kos">,</span>
      <span class="pl-smi">arguments</span><span class="pl-kos">,</span>
      <span class="pl-v">Child</span>
    <span class="pl-kos">)</span><span class="pl-kos">,</span>
    <span class="pl-s1">type</span> <span class="pl-c1">=</span> <span class="pl-s1">instance</span> ? <span class="pl-k">typeof</span> <span class="pl-s1">instance</span> : <span class="pl-s">''</span><span class="pl-kos">,</span>
    <span class="pl-s1">self</span> <span class="pl-c1">=</span> <span class="pl-kos">(</span><span class="pl-s1">type</span> <span class="pl-c1">===</span> <span class="pl-s">'object'</span> <span class="pl-c1">||</span> <span class="pl-s1">type</span> <span class="pl-c1">===</span> <span class="pl-s">'function'</span><span class="pl-kos">)</span> ?
      <span class="pl-v">Object</span><span class="pl-kos">.</span><span class="pl-en">setPrototypeOf</span><span class="pl-kos">(</span><span class="pl-s1">instance</span><span class="pl-kos">,</span> <span class="pl-v">Child</span><span class="pl-kos">.</span><span class="pl-c1">prototype</span><span class="pl-kos">)</span> :
      <span class="pl-smi">this</span>
  <span class="pl-kos">;</span>

  <span class="pl-c">// the rest of the constructor body</span>
  <span class="pl-s1">self</span><span class="pl-kos">.</span><span class="pl-en">push</span><span class="pl-kos">(</span><span class="pl-s1">c</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

  <span class="pl-c">// at the end or instead of empty returns</span>
  <span class="pl-k">return</span> <span class="pl-s1">self</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">Above solution would work with userland, exotic, or DOM constructors, and in both native and transpiled engines.</p>