Must built-in prototypes also be valid instances? (Was: Why DataView.prototype object's [[Class]] is "Object"?)

Andreas Rossberg rossberg at google.com
Mon Oct 1 02:43:08 PDT 2012


On 30 September 2012 02:17, Brendan Eich <brendan at mozilla.org> wrote:
> Failing to consult with implementors will just make editing churn. I don't
> remember much discussion on this change, if any -- we did talk about the
> general problem of prototype objects being firstborns of their class, and
> how this makes them sometimes not just basis cases but degenerate cases.
>
> However, Map is prototyped in SpiderMonkey and V8. In SpiderMonkey, the
> prototype is a Map, not an Object:

Er, from my reading that's clearly not what the Wiki says for WeakMap.
And it also is not what V8 implements, for either WeakMap or Map.


> js> Object.prototype.toString.call(Map.prototype).slice(8, -1)
> "Map"
>
> but you can't get, has, set, size, or iterate Map.prototype:
>
> js> Map.prototype.get('x')
> typein:2:0 TypeError: get method called on incompatible Map
> js> Map.prototype.has('x')
> typein:3:0 TypeError: has method called on incompatible Map
> js> Map.prototype.set('x', 42)
> typein:4:0 TypeError: set method called on incompatible Map
> js> Map.prototype.size()
> typein:5:0 TypeError: size method called on incompatible Map
> js> for (var [k, v] of Map.prototype) ;
> typein:6:13 TypeError: iterator method called on incompatible Map
>
> The error message is suboptimal but what's going on here is that
> Map.prototype has the SpiderMonkey equivalent of [[Class]] == "Map" (or the
> ES6 equivalent). This is important since all the builtins in ES3 + Reality
> (including RegExp; ES3 deviated there) make the prototype for built-in class
> C be of class C.
>
> Your change requires implementations to provide a different built-in class
> (constructor/prototype) initialization path. That's not desirable _per se_.
> Neither IMHO is the user-facing semantic split among "old" and "new"
> constructors.
>
> There are two separate issues here:
>
> 1. Should Map.prototype be an instance (firstborn for its realm) of class
> Map?
>
> 2. Should Map.prototype be a key/value store that can be used or abused as
> any other Map could be?
>
> We should not mix these up. SpiderMonkey (and possibly V8, I haven't tested)
> says "yes" to 1 and "no" to 2.

V8 says no to both. And I fail to see what benefit there is to
separating the two. In fact, it seems hostile to programmers to do so.

I think Allen is absolutely right that the magic incest of current
built-ins is not going to scale, is semantically questionable, and
should best be abandoned.


>>    I did not specify that Map.prototype is a Map instance.  While it has
>> the methods that are applicable to Map instances it does not the internal
>> state that is necessary for those methods to actually work.  For example, if
>> you try to store a value into Map.prototype by calling its set method, you
>> will get a TypeErrior according to the specification. May.prototype can not
>> be used as a map object.
>
> That doesn't mean Map.prototype should not be classified as a Map per 1
> above.

But seriously, what's the advantage of doing otherwise? What purpose
would it serve? I must be missing something.

/Andreas


More information about the es-discuss mailing list