(Weak){Set|Map} subclassing

Allen Wirfs-Brock allen at wirfs-brock.com
Tue Dec 4 09:18:32 PST 2012

On Dec 4, 2012, at 5:37 AM, Herby Vojčík wrote:

> Allen Wirfs-Brock wrote:
> >
> > So roughly speaking, Foo.[[Constructor]](...args) would be defined as:
> > 1) Let creator be Foo.[[Get]](@@create)
> > 2 ) Let newObj be creator.call(foo). //Foo is passed as the this value
> > to @@create
> > 3) Let ctorResult be Foo.[[call]](newObj,args)
> > 4) If Type(ctorResult) is Object, return ctorResult
> > 5) 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.

super(...) is just shorthand for super.constructor(...) (when it occurs in a constructor) so it is just a use of [[Call]]. No magic.

Making the allocation step a regular method call is good because it eliminates the need to expand the MOP to include an additional internal method/trap.  My assumption here is that it generally better to do things at the object level than at the meta-object level and to only use the meta-object level for things that are impossible to accomplish using regular objects properties. 

It isn't clear to me if there is a general need to distinguish [[Init]] (ie, called via the new operator) from [[Call]]  (ie, called any other way).  I need to take a close look at the chapter 15 functions that have differed "called as a constructor" and "called as a function" behaviors in order to see if we can discriminate those cases some other way 

> ===============
> 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]].

I don't see a major benefit of getting rid of [[Construct]] and adding [[Init]].  That doesn't reduce the width of the MOP.  However, we've both noted that [[Construct]] could potentially be replaced with an abstract operation (or just inlined as part of the semantics of the new operator). 

The real question is whether there are any existing use cases (probably in the DOM) that requires intervention prior to the call to @@create.  If so, we need [[Construct]].  If not, we probably could eliminate it.

A secondary question, if we only have @@create and [[Call]] what is the IsConstructor test criteria.  Or perhaps IsConstructor isn't need at all.  It is new in the ES6 spec. and only has two uses, both of which look like they could probably be eliminated.


More information about the es-discuss mailing list