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

Allen Wirfs-Brock allen at wirfs-brock.com
Mon Oct 1 21:49:08 PDT 2012


On Oct 1, 2012, at 9:02 PM, Brendan Eich wrote:

> Mark S. Miller wrote:
>> On Mon, Oct 1, 2012 at 8:17 PM, Brendan Eich <brendan at mozilla.com <mailto:brendan at mozilla.com>> wrote:
>> 
>>    Mark S. Miller wrote:
>> 
>>        Regarding the integrity of original
>>        Object.prototype.toString.call as a branding mechanism, I
>>        agree we need a new more general branding mechanism. WeakMaps
>>        and Symbols both give us a place to hang this, but we need a
>>        concrete proposal. The proposal should work both with builtins
>>        and with classes. If a better branding proposal waits till
>>        ES7, then we need to preserve integrity of original
>>        Object.prototype.toString.call as a branding mechanism through
>>        ES6. If this is preserved through ES6, then it probably
>>        becomes too entrenched to consider retiring.
>> 
>>        Were there other questions for me that I missed?
>> 
>> 
>>    Yes. Should (per the latest draft, 15.2.4.2
>>    Object.prototype.toString) the following names:
>> 
>> 
>>    "Arguments", "Array", "Boolean", "Date", "Error", "Function",
>>    "JSON", "Math", "Number", "Object", "RegExp", or "String"
>> 
>>    and "Object" (per Allen here), and only these names, be prefixed
>>    with "~" when returned via [[Get]](@@toStringTag) where
>>    @@toStringTag denotes a spec-internal (implementation-internal)
>>    symbol?
>> 
>> 
>> The "~" looks very ugly to me. As I state above, I would rather we invent a more general branding mechanism and then stop making this requirement on original Object.prototype.toString.call.
> 
> Agreed, let's do it.
> 
>> Relaxing this requirement would still technically be a breaking change from ES5 so we need to be cautious. But I bet we can get away with it if we do it by ES6. By ES7 it will probably be too late.
> 
> I doubt it'll be too late. In part I am skeptical because I do not believe any engine actually prevents host objects from spoofing the 13 class names listed above. Anyone know of an engine that does?
> 
> Words on paper still carry force but they do not necessarily have prompt effects, or any effects. It depends on the people reading them and implementing, and trying to follow the rules. Those people are much more likely to audit their (closed, per release, typically) set of host objects and fix any spoofers.


The point of the  the the spoofing protection isn't about existing or even future "host objects".   It about everyday code that user could write if me make Obj.proto.toString extensible via @@toStringTag.

I think using toString as a nominal type test is a crock that we should perpetuate.  But we know that code exists that uses it that way for the tags that are defined by ES<=5.1. If we think it is ok to allow future ES programmer to invalidate such existing code by using strings like "Function" and "Array" as @@toStringTag values, then we don't need to do any spoof protection such as the "~" prefix. 

> ...
> But the @@toStringTag idea is a win. Why not use it uniformly, tag all the natives and use advisory language to require that only implementation(s) of objects that satisfy, e.g., the function contract, can use "Function"?
> 

Because such advisory language would have no practical effect on developer writing ES code.  Most would probably not even be away of such a restriction if there isn't some enforcement.

We can try to tell ES implementors that they must do certain things in order to be in conformance but that really doesn't work for code written by users of the language. 

...

Allen


More information about the es-discuss mailing list