Closed Bug 837630 Opened 13 years ago Closed 11 years ago

Mysterious __proto__ property on object with null as prototype

Categories

(Core :: JavaScript Engine, defect)

x86
Linux
defect
Not set
normal

Tracking

()

RESOLVED FIXED
mozilla39
Tracking Status
firefox39 --- fixed

People

(Reporter: bruant.d, Assigned: evilpies)

References

(Blocks 1 open bug)

Details

Attachments

(1 file, 1 obsolete file)

From Twitter https://twitter.com/olov/status/298395329945030657 var o = Object.create(null); o.__proto__ = 1; console.log(Object.getOwnPropertyNames(o)); // [] console.log(Object.getPrototypeOf(o)); // null console.log(o.__proto__) // 1 Expected: either not 1 on o.__proto__ or report '__proto__' in Object.getOwnPropertyNames. I'm not sure yet which is the best. May be worth asking what ES6 will say about __proto__ (I think it'll be reporting '__proto__' in Object.getOwnPropertyNames)
Another observation: console.log(Object.prototype.hasOwnProperty.call(o, "__proto__")); // true
We filter __proto__ out of properties on objects without a [[Prototype]], because we don't want to expose it to the web. Or at least that was the intent at the time, especially since no other browser exposed the property on Object.prototype that way, and there was a chance at killing __proto__. I still have some hope that __proto__ can be killed, myself; others disagree.
(In reply to Jeff Walden [:Waldo] (remove +bmo to email) from comment #2) > Or at least that was the > intent at the time, especially since no other browser exposed the property > on Object.prototype that way, and there was a chance at killing __proto__. > I still have some hope that __proto__ can be killed, myself; others disagree. I am sorry to announce the news, but __proto__ is in the ES6 drafts since the Feb 27th draft, so "others" include TC39 :-s I wish I could say otherwise but __proto__... is here to stay. If that was just me, I'd burn it, but I guess the web matters more than my opinion :-)
Yes, and I think ES6/TC39 are wrong about that. Old hat, not really interested in getting into the argument now.
'__proto__' should be treated as a completely normal property now. SpiderMonkey gets this correct in every way except for censoring it from keys/getOwnPropertyNames. V8 has been showing it in `Object.getOwnPropertyNames(Object.prototype)` for a while now, so it's at least not a "break the web" issue.
var obj1 = Object.create(null); obj1.__proto__ = "abc"; Object.keys(obj1); // ==> [] var obj2 = {}; Object.defineProperty(obj2, "__proto__", { value: "abc", enumerable: true }); Object.ksys(obj2); // == > ["__proto__"] delete Object.prototype.__proto__; var obj3 = { __proto__: "abc" ]; Object.ksey(obj3); // ==> ["__proto__"] There is no consistency as a language. At least, I don't hope Object.keys and Object.getOwnPropertyNames tell a lie.
(In reply to teramako from comment #6) > There is no consistency as a language. > At least, I don't hope Object.keys and Object.getOwnPropertyNames tell a lie. True. __proto__ is being currently standardized. Would you be interested in contributing to SpiderMonkey to make __proto__ compliant with the spec? At least, would you be interested in developing a thorough test suite that all JS engines could be tested against in order to reach both consistency and interoperability? Thanks.
(In reply to teramako from comment #6) > var obj1 = Object.create(null); > obj1.__proto__ = "abc"; > Object.keys(obj1); // ==> [] > > var obj2 = {}; > Object.defineProperty(obj2, "__proto__", { value: "abc", enumerable: true }); > Object.ksys(obj2); // == > ["__proto__"] > > delete Object.prototype.__proto__; > var obj3 = { __proto__: "abc" ]; > Object.ksey(obj3); // ==> ["__proto__"] > > > There is no consistency as a language. > At least, I don't hope Object.keys and Object.getOwnPropertyNames tell a lie. This is a problem with SpiderMonkey's implementation, not the language itself.
Assignee: general → nobody
var o = Object.create(null); o["__proto__"] = 42; console.log(Object.keys/getOwnPropertyNames(o)) Chrome/IE/Safari => ["__proto__"] Firefox => [] Per ES6, __proto__ is part of Object.prototype and should not effect objects created by Object.create(null). Are there any plans to work on this bug?
Assignee: nobody → evilpies
Blocks: es6
Attached patch proto-enumerate (obsolete) — Splinter Review
Now that __proto__ is specified in ES6 we should give up and remove this weird special-case. Makes us match IE + Chrome.
Attachment #8578849 - Flags: review?(jwalden+bmo)
Comment on attachment 8578849 [details] [diff] [review] proto-enumerate Review of attachment 8578849 [details] [diff] [review]: ----------------------------------------------------------------- *stabs __proto__ repeatedly*
Attachment #8578849 - Flags: review?(jwalden+bmo) → review+
Of course this breaks some other tests. Why am I still so optimistic?
Blocks: 1144657
We have to adjust some dom/xpconnect test in a trivial way. For devtools we want to keep hiding __proto__, when somebody does e.g. console.log({}). I had to change ..autocomplete_keys.js, because __proto__ now shows up in the autocomplete popup. That seems like an improvement to me.
Attachment #8579410 - Flags: review?(peterv)
Attachment #8579410 - Flags: review?(past)
Attachment #8578849 - Attachment is obsolete: true
Attachment #8579410 - Flags: review?(peterv) → review+
Attachment #8579410 - Flags: review?(past) → review+
Status: NEW → RESOLVED
Closed: 11 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla39
Dupe of that bug: Bug 897021
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: