[[Construct]] respecification (was: Re: (Weak){Set|Map} subclassing)

# Herby Vojčík (13 years ago)

Allen Wirfs-Brock wrote:

On Nov 30, 2012, at 2:20 PM, Jason Orendorff wrote:

The ordinary [[Construct]] internal method (which is what the new operator actually uses) when invoked upon a constructor function performs two steps. It first instantiates a new object instances (and sets its [[Prototype]] internal property). It then calls the constructor function using the new object as the this value so that the constructor can perform initialization.

In the past on this list we have discussed the utility of being able to separately over-ride the [[Construct]] and [[Call]] behavior of a function (and Proxies enable this). What Jason is proposing is a variation of this. Instead of exposing a @@method that completely replaces [[Construct]] he is proposing a method that replaces the allocation step of [[Construct]]. Such a method, in addition to performing actual allocation, could also perform any allocation time initialization that should be separate from the constructor functionality. This permits the constructor function to be super invoked without doing allocation-time initialization upon the subclass instance.

Overall, I like this approach. However, I don't think @@create belongs on the prototype object. This make the @@create functionality for a particular kind of object available to anyone who gets their hands on an instance object of the class. This smells like a capability leak.

Instead, I would make @@create a property of the actual constructor function and I would place the default @@create on Function.prototype, which all functions inherit from.

So roughly speaking, Foo.[Constructor] would be defined as:

  1. Let creator be Foo.[Get] 2 ) Let newObj be creator.call(foo). //Foo is passed as the this value to @@create
  2. Let ctorResult be Foo.[call]
  3. If Type(ctorResult) is Object, return ctorResult
  4. else return newObj

I have just thought about this, and came to similar conclusion, but not using @@create, but by splitting [[Construct]] into [[Alloc]] and [[Init]]. My reasoning was more about speccing that [[Init]] is used instead of [[Call]] in new as well as in super(...). So I don't care if [[Alloc]] is [[Alloc]] or @@create.

But I did not know whether there is will to respecify [[Construct]]. If there is, would it be reasonable to define [[Call]] on functions as well as [[Init]] on constructor functions, as invoke it instead of [[Call]] in [[Construct]] (and also super(...), but there the [[Call]] is buried deeper in some abstract operation)? The default [[Init]] is to delegate to [[Call]], but is potentially different.

===============

As a second step / food for thought, not a part of previous proposal, so please take them separately, thanks, [[Construct]] could be refactored from internal operation ([[...]]) into abstract spec operation, and constructor could be tested by presence of [[Init]].