B.3.1 The __proto__ pseudo property

Allen Wirfs-Brock allen at wirfs-brock.com
Sun Apr 21 18:11:01 PDT 2013


On Apr 21, 2013, at 1:37 PM, Brendan Eich wrote:

> Allen Wirfs-Brock wrote:
>> On Apr 21, 2013, at 12:31 PM, Brendan Eich wrote:
>> >  You don't want that to affect object literals evaluated in the same realm after such a deletion. Why not?
>> 
>> Why should it?
> 
> ... because it did in ES5-conforming implementations that support __proto__ as a de-facto standard *and* allow delete Object.prototype.__proto__.

Was that intentional WRT object literals or an un intended consequence of using [[Put]] in processing that property.  Prior, to the ES6 discussions over the last year was that even the case?  For each major implementation how long has deleting Object.prototype.__proto__ (if it was even possible has that behavior).

The point is that I don't think there is any long standing behavior in this regard relating to object literals and deleting Object.prototype.__proto__ that the web is dependent upon.  We are free to specify a semantics that will make sense, now and for the long term.

> 
>>   We already used the existence of {__proto__: whatever} got rid of<| as declarative syntax for defining an object literal with a [[Prototype]] other than object prototype.  Making {__proto__: whatever}  only work some of the times means it isn't a reliable declarative syntax.
> 
> What?
> 
> Mark insists on delete Object.prototype.__proto__ making the magic go away. (Summoning Mark.)

The major is foo.__proto__ = bar changing foo's dynamically changing foo's [[Prototype]].  There is nothing magic about an object literal that uses some weird syntax to specify the [[Prototype]] that a newly allocated object will have. 

> 
> Triangle died for several reasons, and I'm surprised to hear it here. Grinding an axe?

Not at all!  You frequently have said that standardizing __proto__ takes the wind out of other features that support various use cases of defining/manipulating an object's [[Prototype]].  One of those features is using an object literal as a way to declaratively describe an object that inherits from something other than Object.prototype (including null).

So, if {__proto__: null} is a solution for that use case it should be specified with reasonable semantics and not be a conditional feature whose availability is tied to something else that many consider undesirable.   There is no need for any magic here and no need to introduce additional imperative behavior by calling [[Set]].  It is just creating an object with a syntactically provided [[Prototype]] value. 

Specifying it as doing a [[Set]] just opens the door for people inserting their own accessor.

In ES5 we explicitly change object literals to be immune from such tampering and with apparently no ill-effect.  I don't see why we would want to re-open such an avenue.  It certainly is necessary from a specification perspective and it isn't going to have a big implementation impact to do it right.

> 
>>   Why would we want to do that?  There is arguably a good motivation wanting disable the ability to dynamically __proto__ modify arbitrary pare-existing objects. But what is the motifacation for doing that on newly created objects?
> 
> I will tag Mark in here, but first make my own move:
> 
> Answer: because the clear way to implement this in ES5-conforming implementations that support __proto__ is to call [[Put]] not [[DefineOwnProperty]] if the name of the property being initialized in the object literal is '__proto__', and that's what engines implement.

I'd say that the clearest conforming way is to just create the new object with the [[Prototype]] value that was provided using the literal.  [[Put]] isn't needed.  [[SetInhertiance]] also isn't really need, but it is semantically much closer than dong an operation that invokes an arbitrary set accessor.
> 
> That makes a new de-facto standard, which you should not be wasting energy trying to break!

I don't think there currently is a de facto standard at these edges.  Our job is to sort it out and make the best possible language for the long run. 
> 
>>> SpiderMonkey at least goes out of its way to do [[Set]] (let's call it) not [[DefineOwnProperty]] for 'o = {__proto__: 42}', so why wouldn't [[Set]] create a fresh property, seeing nothing on Object.prototype named '__proto__' with a setter to run?
>> 
>> Because the semantics that says you can't use [[DefineOwnProperty]] may say to go out of the way to do something else.
> 
> Too late, ES5+reality happened. You are now proposing to break the web, at the limit. JS implementors will not go for that, so you are wasting your time.

No both, FF and V8 apparently have been evolving in this area over the last year and IE hasn't even entered the field yet.  Show me any significant, browser interoperable code on the web that is observably dependent upon object literals doing an observable [[Put]].

> 
>>   It my strawman spec. it says use [[SetInhertiance]] rather than [[Put]].  Either is a special case semantics and [[SetInheritance]] is a much more direct expression of the likely user intent.
> 
> Direct, schmirect.
> 
> This is about compatibility and consistency, not what you can edit into a draft. Please reconsider. Must we put this on the next meeting's agenda?

I have to respectfully disagree.  So me the code that would break and explain why what ever consistency you are imaging is worth making object literals that specify a [[Prototype]] a unreliable features.  How is that better for anyone?

yes, I intended to put this on the agenda since I now have sold spec. language to review.

Allen




More information about the es-discuss mailing list