On IE __proto__ test cases

# David Bruant (6 years ago)

So, there are standard tests now for ES6!

I'd like to discuss some of the __proto__ tests.

3.1.1-10 Object.freeze(Object.prototype) disables __proto__

function testcase() {
   Object.freeze(Object.prototype);
   var a = new Object();
   a.__proto__ = { y: 2 };
   return a.y === undefined;
}

I'm not sure I see why this test should succeed. Freezing "a" should prevent its [[Prototype]] from being changed, but I don't see why it would be the case for Object.prototype.

(same for 3.1.1-9 for Object.seal)

3.1.1-11 [[DefineOwnProperty]] UnderScoreProtoEnabled is set to true when Object.prototype is set with default values

function testcase() {
     Object.defineProperty(Object.prototype, "__proto__", { writable: true, enumerable: false, configurable: true });

     var obj = {};
     obj.__proto__ = { x: 10 };
     return obj.x === 10;
}

I don't fully understand this test case. I think that overriding Object.prototype.__proto__ with a data attribute should remove its magic.

(same for 3.1.1-7, 3.1.2-4-1+bcd )

3.1.1-4 Object.prototype.__proto__ is data property with {writable:true, enumerable:false, configurable:true, value:null} attributes

function testcase() {
     var desc = Object.getOwnPropertyDescriptor(Object.prototype, "__proto__");
     return desc.writable === true &&
         desc.enumerable === false &&
         desc.configurable === true &&
         desc.value === null;
}

... hmm... I admire the sense of humor of whoever wrote that test. TC39 Meeting notes from May 2013:

__proto__ is an accessor on Object.prototype.

3.1.1-6 Modification of Object.prototype.__proto__ causes UnderScoreEnabled to be set to false. Setting it to {}

function testcase() {
     Object.defineProperty(Object.prototype, "__proto__", {});

     var obj = new Object();
     obj.__proto__ = { y: 2 };
     return obj.y === undefined;

}

I believe the Object.defineProperty line is a no-op, so the test should fail.

3.1.2-2-14b [[Put]] __proto__ with value {y:2} on window object

function testcase() {
     window.__proto__ = { y: 2 };
     return window.y === undefined;
}

window is not part of ECMAScript. This test might as well throw a ReferenceError. As far as the global object, I don't think it's status on [[Prototype]] is very clear from a standard standpoint, so I would recommend not having tests for that.

I only looked at the tests failing in Firefox, there are probably other errors. It would be good if the tests were reviewed carefully before becoming part of any sort of "conformance" test suite.

# Erik Arvidsson (6 years ago)

Yeah, these test all look incorrect to me. IE11 implements an older draft where __proto__ was a magic property.

# Andrea Giammarchi (6 years ago)

on 3.1.1-10 AFAIK Object.preventExtension({}) makes proto immutable. Since Object.freeze({}) includes that preventExtension call, immutable should be so no y inherited there.

# Luke Hoban (6 years ago)

From: Erik Arvidsson

Yeah, these test all look incorrect to me. IE11 implements an older draft where __proto__ was a magic property.

That’s right. Our implementation predates the May spec updates that changed the spec for __proto__. We will update the test contributions to tests262 to align with the updated spec.

One question from looking at implications of this change. Is it intentional that there is no longer a way to remove (or customize) the special handling of __proto__ in object literals?

delete Object.prototype.__proto__
var p = { y: 34 } 
var o = { x: 42, __proto__: y }
o.y === 34 // was false, now true
# Mark S. Miller (6 years ago)

Yes, that was intentional. Even though the __proto__: looks related to the __proto__ property initially on Object.prototype, that's only cosmetic. It is now simply part of the object literal syntax, in just the same way that <| used to just be special syntax.

This does seem to leave a hole in the functionality compared to <|, which is, how do you create a normal property named __proto__. The answer is the computed property syntax: {["__proto__"]: ...}.

I don't remember what whether we decided that {"__proto__": ...} means the same thing as {["__proto__"]: ...} or {__proto__: ...}. I think we decided the second, which probably better follows the principle of least surprise. OTOH, the first would have kept JavaScript closes to JSON.

# Allen Wirfs-Brock (6 years ago)

On Jul 11, 2013, at 9:33 PM, Mark S. Miller wrote:

Yes, that was intentional. Even though the "__proto__:" looks related to the "__proto__" property initially on Object.prototype, that's only cosmetic. It is now simply part of the object literal syntax, in just the same way that <| used to just be special syntax.

Agreed, this is intentional.

This does seem to leave a hole in the functionality compared to <|, which is, how do you create a normal property named __proto__. The answer is the computed property syntax: {["__proto__"]: ...}.

I don't remember what whether we decided that {"__proto__": ...} means the same thing as {["__proto__"]: ...} or {__proto__: ...}. I think we decided the second, which probably better follows the principle of least surprise. OTOH, the first would have kept JavaScript closes to JSON.

There are various possible issues here. First, as the spec. is now written {__proto__: ...} and {"__proto__":...} mean exactly the same thing.

Also, I think we still have an issue as to whether or not we want to allow computed property keys (in propName positions) to produce string-valued keys. When we first were considered computed propNames there were some objections (Ollie Hunt??) to allowing string values. My recollection was that it potentially forced turning the static checks for things like duplicate property names in object literals into dynamic checks. My fuzzy recollection is that at that time we decided to disallowed string valued computed propNames (this is before we temporarily eliminated computed propNames in favor of at-names). I think there was some discussion of this at the last meeting but I don't feel that we have adequate re-explored the earlier decisions (?) to not allow string valued propName. So, in the current draft I only allow Symbol valued computed propNames but have it marked as a open issue.

If I turn on string valued computed propNames in the spec, then as currently written {__proto__: ...} and {["__proto__"]: ...} will have the same meaning. We can, of course, change that but it will significant complicate the delta spec. needed in Annex B for __proto__ in object literals.

finally, note that the current spec. only assigns special meaning to __proto__ for the production:

 PropertyDefinition: PropertyName : AssignmentExpression

that means that things like:

let __proto__= { };
( {__proto__})

and

({__proto__ (arg) {}})

produce object with regular own properties named "__proto__".