Allen Wirfs-Brock (2015-02-06T20:02:15.000Z)
On Feb 6, 2015, at 9:04 AM, Ben Newman wrote:

> The specific line in rev32 of the spec that prevents [[Call]]ing "classConstructor" functions is 9.2.2.2:
> 
> 2. If F’s [[FunctionKind]] internal slot is "classConstructor", throw a TypeError exception.
> 
> From my reading of the spec, I think the idiomatic Foo.call(this) pattern that Luke Scott described would work if we simply changed that line to something slightly weaker:
> 
> 2. If F’s [[FunctionKind]] internal slot is "classConstructor" and InstanceofOperator(thisArgument, F) is false, throw a TypeError exception.
> 
> This mirrors an assertion discipline that has saved me from many bugs due to forgetting the new operator:
> 
> function Base() {
>   assert.ok(this instanceof Base);
>   ...
> }
> 
> function Derived() {
>   assert.ok(this instanceof Derived);
>   Base.call(this);
>   ...
> }
> 
> Derived.prototype = Object.create(Base.prototype, {
>   constructor: { value: Derived, ... }
> });
> 
> Is the addition of the instanceof check naive? Would it invalidate any of the assumptions involved in the invocation of F?
> 
> I'm happy to file a bug if this change merits further consideration.

There is nothing about  ES6 classes or subclassing built-ins that inherently requires line 2 above.  Without it, calling a class would work just fine and new.target would even give you a way to distinguish [[Call]] invocation from a [[Construct]] invocation.

Line 2 exists because sone TC39 members wanted to future proof for things they want to experiment with for future editions.  These things may include:
   1) Someway to provide a separate function body that is used when the constructor is [[Call]]'ed 
   2) Allowing unqualified using of 'super()' in "called" constructor to mean the same thing as 'super.constructor()'
   3) (maybe making "calling" a constructor equivalent to "newing" the onstructor

Allowing calls of class constructors would allow people to start writing code that might create legacy issues for such future features.

I think it would take more than a bug to change this now.

> 
> It may be worth noting that only constructors created by class 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 class syntax in order to know whether the Foo.call(this) pattern is safe.

yup

Allen

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20150206/5472e2c5/attachment.html>
d at domenic.me (2015-02-17T18:14:34.364Z)
On Feb 6, 2015, at 9:04 AM, Ben Newman wrote:

> Is the addition of the instanceof check naive? Would it invalidate any of the assumptions involved in the invocation of F?
> 
> I'm happy to file a bug if this change merits further consideration.

There is nothing about  ES6 classes or subclassing built-ins that inherently requires line 2 above.  Without it, calling a class would work just fine and `new.target` would even give you a way to distinguish [[Call]] invocation from a [[Construct]] invocation.

Line 2 exists because some TC39 members wanted to future proof for things they want to experiment with for future editions.  These things may include:

1. Some way to provide a separate function body that is used when the constructor is [[Call]]'ed 
2. Allowing unqualified using of `super()` in "called" constructor to mean the same thing as `super.constructor()`
3. Maybe making "calling" a constructor equivalent to "newing" the constructor

Allowing calls of class constructors would allow people to start writing code that might create legacy issues for such future features.

I think it would take more than a bug to change this now.

> It may be worth noting that only constructors created by class 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 class syntax in order to know whether the Foo.call(this) pattern is safe.

yup