(Weak){Set|Map} subclassing

Herby Vojčík herby at mailbox.sk
Tue Dec 4 10:51:34 PST 2012



Allen Wirfs-Brock wrote:
> 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

Some of the builtins do that (though it is a weak argument). But drawing 
from their example, one may want to create a class so that new 
Foo(...args) creates and Foo(obj) can do something else, like 
adapt/transform.

I meant [[Init]] not as a spec-only thing for the already existing 
precedents, but to allow user to distinguish [[Call]] and [[Construct]] 
behaviour, like:

class Foo [extends ...] {
   [init]() { .... }
   [call]() { .... }
   // [create]() { .... }
   ...
}

and use [init]/[call] (or __init__/__call__ if the 
do-not-bring-in-computed-name-just-for-iterator mentioned in "Comments 
on Meeting Notes" thread wins) to specify [[Init]] and [[Call]] 
behaviour, with fallbacks to use when only one is present ([init] -> 
[call] if [init] not present; [call] fails with "Initializer only" when 
not present).

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

So you know if function is a constructor or not. You need something that 
bears authority for this, and without [[Construct]] it is [[Init]].

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

If they can, fine; but there definitely are non-constructor functions, 
and you should be able to detect if something is a constructor.

> Allen

Herby


More information about the es-discuss mailing list