<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Feb 6, 2015, at 10:35 AM, Claude Pache <<a href="mailto:claude.pache@gmail.com" class="">claude.pache@gmail.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><blockquote type="cite" class=""><div class=""><br class="Apple-interchange-newline">Le 6 févr. 2015 à 18:04, Ben Newman <<a href="mailto:benjamin@cs.stanford.edu" class="">benjamin@cs.stanford.edu</a>> a écrit :</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" class="">The specific line in rev32 of the spec that prevents [[Call]]ing "classConstructor" functions is<span class="Apple-converted-space"> </span><a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-ecmascript-function-objects-call-thisargument-argumentslist" target="_blank" class="">9.2.2.2</a>:<br class=""><br class=""><blockquote class="" style="margin: 0px 0px 0px 40px; border: none; padding: 0px;"><div class=""><span class="" style="color: rgb(51, 51, 51); font-family: Cambria, 'Palatino Linotype', Palatino, 'Liberation Serif', serif; line-height: 22.9500007629395px; background-color: rgb(253, 253, 252);">2. If </span><i class="" style="color: rgb(51, 51, 51); font-family: Cambria, 'Palatino Linotype', Palatino, 'Liberation Serif', serif; line-height: 22.9500007629395px; background-color: rgb(253, 253, 252);">F</i><span class="" style="color: rgb(51, 51, 51); font-family: Cambria, 'Palatino Linotype', Palatino, 'Liberation Serif', serif; line-height: 22.9500007629395px; background-color: rgb(253, 253, 252);">’s [[FunctionKind]]</span><span class="" style="color: rgb(51, 51, 51); font-family: Cambria, 'Palatino Linotype', Palatino, 'Liberation Serif', serif; line-height: 22.9500007629395px; background-color: rgb(253, 253, 252);"> </span><a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object-internal-methods-and-internal-slots" class="" style="font-family: Cambria, 'Palatino Linotype', Palatino, 'Liberation Serif', serif; line-height: 22.9500007629395px; text-decoration: none; color: rgb(51, 51, 187); background-color: rgb(253, 253, 252);">internal slot</a><span class="" style="color: rgb(51, 51, 51); font-family: Cambria, 'Palatino Linotype', Palatino, 'Liberation Serif', serif; line-height: 22.9500007629395px; background-color: rgb(253, 253, 252);"> </span><span class="" style="color: rgb(51, 51, 51); font-family: Cambria, 'Palatino Linotype', Palatino, 'Liberation Serif', serif; line-height: 22.9500007629395px; background-color: rgb(253, 253, 252);">is "</span><code class="" style="line-height: 22.9500007629395px; color: rgb(85, 85, 85); font-weight: bold; font-family: 'Courier New', monospace; white-space: nowrap; background-color: rgb(253, 253, 252);">classConstructor</code><span class="" style="color: rgb(51, 51, 51); font-family: Cambria, 'Palatino Linotype', Palatino, 'Liberation Serif', serif; line-height: 22.9500007629395px; background-color: rgb(253, 253, 252);">", throw a</span><span class="" style="color: rgb(51, 51, 51); font-family: Cambria, 'Palatino Linotype', Palatino, 'Liberation Serif', serif; line-height: 22.9500007629395px; background-color: rgb(253, 253, 252);"> </span><b class="" style="font-family: Cambria, 'Palatino Linotype', Palatino, 'Liberation Serif', serif; line-height: 22.9500007629395px; color: rgb(85, 85, 85); background-color: rgb(253, 253, 252);">TypeError</b><span class="" style="color: rgb(51, 51, 51); font-family: Cambria, 'Palatino Linotype', Palatino, 'Liberation Serif', serif; line-height: 22.9500007629395px; background-color: rgb(253, 253, 252);"> </span><span class="" style="color: rgb(51, 51, 51); font-family: Cambria, 'Palatino Linotype', Palatino, 'Liberation Serif', serif; line-height: 22.9500007629395px; background-color: rgb(253, 253, 252);">exception.</span></div></blockquote><div class=""><br class=""></div><div class="">From my reading of the spec, I think the idiomatic<span class="Apple-converted-space"> </span><font face="monospace, monospace" class="">Foo.call(this)</font><span class="Apple-converted-space"> </span>pattern that Luke Scott described would work if we simply changed that line to something slightly weaker:</div><div class=""><blockquote class="" style="margin: 0px 0px 0px 40px; border: none; padding: 0px;"><span class="" style="color: rgb(51, 51, 51); font-family: Cambria, 'Palatino Linotype', Palatino, 'Liberation Serif', serif; line-height: 22.9500007629395px; background-color: rgb(253, 253, 252);"><br class="">2. If </span><i class="" style="color: rgb(51, 51, 51); font-family: Cambria, 'Palatino Linotype', Palatino, 'Liberation Serif', serif; line-height: 22.9500007629395px; background-color: rgb(253, 253, 252);">F</i><span class="" style="color: rgb(51, 51, 51); font-family: Cambria, 'Palatino Linotype', Palatino, 'Liberation Serif', serif; line-height: 22.9500007629395px; background-color: rgb(253, 253, 252);">’s [[FunctionKind]]</span><span class="" style="color: rgb(51, 51, 51); font-family: Cambria, 'Palatino Linotype', Palatino, 'Liberation Serif', serif; line-height: 22.9500007629395px; background-color: rgb(253, 253, 252);"> </span><a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object-internal-methods-and-internal-slots" class="" style="color: rgb(51, 51, 187); font-family: Cambria, 'Palatino Linotype', Palatino, 'Liberation Serif', serif; line-height: 22.9500007629395px; text-decoration: none; background-color: rgb(253, 253, 252);">internal slot</a><span class="" style="color: rgb(51, 51, 51); font-family: Cambria, 'Palatino Linotype', Palatino, 'Liberation Serif', serif; line-height: 22.9500007629395px; background-color: rgb(253, 253, 252);"> </span><span class="" style="color: rgb(51, 51, 51); font-family: Cambria, 'Palatino Linotype', Palatino, 'Liberation Serif', serif; line-height: 22.9500007629395px; background-color: rgb(253, 253, 252);">is "</span><code class="" style="line-height: 22.9500007629395px; color: rgb(85, 85, 85); font-weight: bold; font-family: 'Courier New', monospace; white-space: nowrap; background-color: rgb(253, 253, 252);">classConstructor</code><span class="" style="color: rgb(51, 51, 51); font-family: Cambria, 'Palatino Linotype', Palatino, 'Liberation Serif', serif; line-height: 22.9500007629395px; background-color: rgb(253, 253, 252);">" and</span><span class="" style="color: rgb(51, 51, 51); font-family: Cambria, 'Palatino Linotype', Palatino, 'Liberation Serif', serif; line-height: 22.9500007629395px; background-color: rgb(253, 253, 252);"> </span><a href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-instanceofoperator" class="" style="text-decoration: none; color: rgb(51, 51, 187); font-family: Cambria, 'Palatino Linotype', Palatino, 'Liberation Serif', serif; line-height: 22.9500007629395px; background-color: rgb(253, 253, 252);">InstanceofOperator</a><span class="" style="color: rgb(51, 51, 51); font-family: Cambria, 'Palatino Linotype', Palatino, 'Liberation Serif', serif; line-height: 22.9500007629395px; background-color: rgb(253, 253, 252);">(</span><i class="" style="color: rgb(51, 51, 51); font-family: Cambria, 'Palatino Linotype', Palatino, 'Liberation Serif', serif; line-height: 22.9500007629395px; background-color: rgb(253, 253, 252);">thisArgument</i><span class="" style="color: rgb(51, 51, 51); font-family: Cambria, 'Palatino Linotype', Palatino, 'Liberation Serif', serif; line-height: 22.9500007629395px; background-color: rgb(253, 253, 252);">, </span><i class="" style="color: rgb(51, 51, 51); font-family: Cambria, 'Palatino Linotype', Palatino, 'Liberation Serif', serif; line-height: 22.9500007629395px; background-color: rgb(253, 253, 252);">F</i><span class="" style="color: rgb(51, 51, 51); font-family: Cambria, 'Palatino Linotype', Palatino, 'Liberation Serif', serif; line-height: 22.9500007629395px; background-color: rgb(253, 253, 252);">)</span><span class="" style="color: rgb(51, 51, 51); font-family: Cambria, 'Palatino Linotype', Palatino, 'Liberation Serif', serif; line-height: 22.9500007629395px; background-color: rgb(253, 253, 252);"> is<span class="Apple-converted-space"> </span><b class="">false,</b><span class="Apple-converted-space"> </span>throw a</span><span class="" style="color: rgb(51, 51, 51); font-family: Cambria, 'Palatino Linotype', Palatino, 'Liberation Serif', serif; line-height: 22.9500007629395px; background-color: rgb(253, 253, 252);"> </span><b class="" style="font-family: Cambria, 'Palatino Linotype', Palatino, 'Liberation Serif', serif; line-height: 22.9500007629395px; color: rgb(85, 85, 85); background-color: rgb(253, 253, 252);">TypeError</b><span class="" style="color: rgb(51, 51, 51); font-family: Cambria, 'Palatino Linotype', Palatino, 'Liberation Serif', serif; line-height: 22.9500007629395px; background-color: rgb(253, 253, 252);"> </span><span class="" style="color: rgb(51, 51, 51); font-family: Cambria, 'Palatino Linotype', Palatino, 'Liberation Serif', serif; line-height: 22.9500007629395px; background-color: rgb(253, 253, 252);">exception.</span></blockquote></div><div class=""><br class=""></div><div class="">This mirrors an assertion discipline that has saved me from many bugs due to forgetting the<span class="Apple-converted-space"> </span><font face="monospace, monospace" class="">new</font><span class="Apple-converted-space"> </span>operator:</div><div class=""><br class=""></div><div class=""><blockquote class="" style="margin: 0px 0px 0px 40px; border: none; padding: 0px;"><font face="monospace, monospace" class="">function Base() {<br class=""> <span class="Apple-converted-space"> </span><b class="">assert.ok(this instanceof Base);</b><br class="">  ...<br class="">}<br class=""><br class="">function Derived() {<br class=""> <span class="Apple-converted-space"> </span><b class="">assert.ok(this instanceof Derived);</b><br class="">  Base.call(this);<br class="">  ...<br class="">}<br class=""><br class="">Derived.prototype = Object.create(Base.prototype, {<br class="">  constructor: { value: Derived, ... }<br class="">});</font></blockquote></div><div class=""><br class=""></div><div class="">Is the addition of the<span class="Apple-converted-space"> </span><font face="monospace, monospace" class="">instanceof</font><span class="Apple-converted-space"> </span>check naive? Would it invalidate any of the assumptions involved in the invocation of F?</div><div class=""><br class=""></div><div class="">I'm happy to file a bug if this change merits further consideration.</div><div class=""><br class=""></div><div class="">It may be worth noting that only constructors created by<span class="Apple-converted-space"> </span><font face="monospace, monospace" class="">class</font><span class="Apple-converted-space"> </span>syntax will have their [[FunctionKind]] internal slot set to "classConstructor", so (even with the current spec) you can still invoke ordinary constructor functions using [[Call]]. However, it seems regrettable that you have to know whether a constructor was created by<span class="Apple-converted-space"> </span><font face="monospace, monospace" class="">class</font><span class="Apple-converted-space"> </span>syntax in order to know whether the<span class="Apple-converted-space"> </span><font face="monospace, monospace" class="">Foo.call(this)</font><span class="Apple-converted-space"> </span>pattern is safe.</div></div></div></blockquote><br class=""></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><div class="">The issue is deeper. In short, you cannot feed an ES6-class constructor with an already allocated object, whatever that object is.</div><div class=""><br class=""></div><div class="">With a user-defined good ol' pre-ES6 constructor:</div><div class=""><div class=""><br class=""></div><div class="">    foo = new Foo // allocate a Foo object and initialise it</div><div class="">    </div><div class="">is usually equivalent to:</div><div class=""><br class=""></div><div class="">    foo = Object.create(Foo.prototype) // allocate a Foo object ...</div><div class="">    Foo.call(foo) // ... and initilise it</div><div class=""><br class=""></div><div class="">With the new ES6-class semantics, for the sake of subclassability of builtins, it is, on purpose, not possible to separate allocation from initialisation that way. Even before ES6, builtin classes, did not support such a pattern, e.g.,</div><div class=""><br class=""></div><div class="">    arr = new Array(2, 3) // allocate a new array and initialise it</div><div class=""><br class=""></div><div class="">is in no way equivalent to:</div><div class=""><br class=""></div><div class="">    arr = Object.create(Array.prototype) // allocate an new object, but it won't be an array...</div><div class="">    Array.call(arr, 2, 3) // ... and don't initialise it, but create uselessly a new Array</div><div class="">    </div><div class="">And it appeared that introducing the possibility for builtins to have separate allocation and initialisation phases was problematic.</div><div class=""><br class=""></div><div class="">—Claude</div></div></div></div></blockquote><div><br class=""></div>The following should be sufficient with the current ES6, spec, right? It currently works in 6to5.</div><div><br class=""></div><div>function mixin(classObject, …traits) {</div><div>    var newClassObject = class extends classObject{}</div><div>    // … fill in prototype here</div><div>}</div><div><br class=""></div><div>Below is a possible workaround for pre-ES6 code (without being transpired), provided that an Object.isClass is added (checks for internal classConstructor flag), which would always return false in pollyfills.</div><div><br class=""></div><div><div>function mixin(classObject, traits) {</div><div>    var newClassObject;</div><div>    if (Object.isClass(classObject)) {</div><div>        newClassObject = eval("class extends classObject{}”);</div><div>    } else {</div><div>        newClassObject = function() {classObject.apply(this, arguments);};</div><div>        newClassObject.prototype = Object.create(classObject.prototype);</div><div>        newClassObject.prototype.constructor = newClassObject;</div><div>    }</div><div>    // … fill in prototype here</div><div>}</div><div><br class=""></div><div>It’s an ugly hack. Unfortunately the eval is necessary because Chrome throws “Unexpected reserved word” for the class keyword.</div><div><br class=""></div><div>--</div><div>Luke</div><div><br class=""></div></div></body></html>