Jan 29 TC39 Meeting Notes

Claude Pache claude.pache at gmail.com
Fri Feb 8 10:15:19 PST 2013


Le 8 févr. 2013 à 16:00, David Bruant <bruant.d at gmail.com> a écrit :

> Le 07/02/2013 18:42, Andreas Rossberg a écrit :
>> On 7 February 2013 18:36, David Bruant <bruant.d at gmail.com> wrote:
>>> I hardly understand the benefit of an inconditionally-throwing setter over a
>>> __proto__ as data property, but I'm fine with either.
>> Well, it _is_ a setter, and even one that modifies its receiver, not
>> its holder. What would be the benefit of pretending it's not?
> It _is_ an abomination (arguably, it even __is__ an abomination). Any resemblance to real ECMAScript construct, living or dead (?), is purely coincidental.
> 
> From the notes, a quote from Allen is "involves magic". I don't think I will surprise anyone if I say that whatever is decided for __proto__, there will be magic involved.
> 
> An idea that I don't think has been suggested is to stop pretending __proto__ is something else than magic:
> $> Object.getOwnPropertyDescriptor(Object.prototype, '__proto__');
> {
>    magic: true,
>    enumerable: false,
>    configurable: true
> }
> 
> Quite exotic but very clear. At will, replace "magic" with "abomination", "de facto standard", "wildcard", "don't use __proto__" or "Why did you call Object.getOwnPropertyDescriptor on __proto__ anyway?". Other better suggestions are welcome, obviously.
> Admittedly, the last idea may be a bit long, but that's a string, so that can be an property name. I wouldn't rule it out too quickly ;-)
> 
> David
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss

The magic is not in the form of the '__proto__' property of the Object.prototype object, but in the action that its setter performs. Precisely, as implemented in the latest versions of Safari and Firefox (I haven't tested other browsers), Object.prototype.__proto__ acts as if it has been defined as follows:

;(function() {
    var getPrototypeOf = Object.getPrototypeOf
    Object.defineProperty(Object.prototype, '__proto__', {
            get: function() { return getPrototypeOf(this) }
          , set: function(p) { __setPrototypeOf__(this, p) }
          , configurable: true
          , enumerable: false
    })
})()

where  __setPrototypeOf__(obj, p) is some function that does the following (note the second bullet):

* throws an error if obj is not an object; otherwise,
* throws an error if obj is not extensible; otherwise,
* fails if p is not an object; otherwise,
* throws an error if obj is equal to p or is in the prototype chain of p (to avoid cycles); otherwise,
* replaces the prototype of obj with p.

The only part not user-implementable (and the only magic, if any,) is in the "replaces the prototype of obj with p" part above.

However, I would find reasonable to treat __proto__ similarly to eval: so that the aforementioned __setPrototypeOf__ function is allowed to fail when it has not been called with the exact syntax obj.__proto__ = something. Anything else, including obj['__proto__'] = something, could fail. Admittedly, THAT would be black magic, but again, it is not in form the property descriptor, but in the definition of __setPrototypeOf__.

—Claude



More information about the es-discuss mailing list