[change of Subject: as this reply starts the promised thread]
Hi Lasse, good. That is the direction Dave Herman suggested and which I also find attractive. I have elaborated it at < http://wiki.ecmascript.org/doku.php?id=strawman:magic_proto_property>, which I've also placed on the Agenda for the January EcmaScript meeting. The most surprising punchline is in requirement #4: Object.create(null), creating an object that does not inherit from Object.prototype, also creates an object that does not inherit it’s __proto__, even if that property has not been deleted. With this change, objects-as-stringmaps for objects created by Object.create(null) would avoid the __proto__ hazard, even in contexts where Object.prototype.__proto__ has not been deleted. (FF already acts this way, so my previous message was wrong in claiming that Object.create(null) fails to avoid this platform on all non-IE browsers.) Comments on this proposal appreciated. On Wed, Dec 28, 2011 at 5:26 PM, Lasse Reichstein < [email protected]> wrote: > The biggest problem with __proto__, as I see it, isn't that you can > hit it accidentally, but that even if you know what you are doing, you > can't avoid it (and have to do expensive workarounds). > > It obviously depends on the implementation. In Mozilla > Firefox/*Monkey, __proto__ is an inherited accessor on > Object.prototype (just as __define[SG]etter__). It's not an > own-property and you can shadow it. > > In Chrome/V8, it's an artificial own property on every object, and it > can't be removed, shadowed or ignored. It tries to emulate Safari's > original implementation, but probably fails some details (as your > tests show, they aren't the same). > > I like the Firefox way much better, both as a user and as an > implementor. Since we probably can't get rid of __proto__ totally, I > would cheer if implementations would change to the Mozilla way. > > /L 'entirely my personal opinion'. > > On Tue, Dec 27, 2011 at 3:53 AM, Mark S. Miller <[email protected]> > wrote: > > Or, "Even Crock's Code Doesn't Overcome All The Bad Parts." > > > > > > In this message, I explain why I believe we need to clean up __proto__. > I'll > > start a separate thread on how to clean it up -- which is just my > > documenting a suggestion from Dave Herman. > > > > > > From > > < > http://eleventyone.done.hu/OReilly.JavaScript.The.Good.Parts.May.2008.pdf> > > PDF page 119 > > > > that.on = function (type, ....) { > > .... > > var registry = {}; > > .... > > if (registry.hasOwnProperty(type)) { > > registry[type].push(handler); > > } else { > > registry[type] = [handler]; > > } > > .... > > }; > > > > This "registry" is a classic use of an object as a string-to-value > map. Note > > that the "type" parameter comes in from the client of the abstraction. > The > > only validation performed on it is the "hasOwnProperty" check above. > > Elsewhere Crock points out that this hasOwnProperty check does not work > if > > "hasOwnProperty" itself is ever used as a key, and so we should instead > say: > > > > if (Object.prototype.hasOwnProperty.call(registry, type)) { > > > > This still doesn't yet work on most actual browsers for a reason > explained > > below. > > > > > > > > <aside on why ES5 does not really help> > > > > Going beyond "Good Parts", EcmaScript 5 gives us two new opportunities to > > clean up this code further. > > > > 1) We can protect ourselves from other code monkey patching > > away Object.prototype.hasOwnProperty > > and/or Object.prototype.hasOwnProperty.call by using > > < > http://wiki.ecmascript.org/doku.php?id=conventions:safe_meta_programming> > > at initialization time, assuming that this module gets to initialize > itself > > before such monkey patching may have occurred: > > > > var bind = Function.prototype.bind; > > var uncurryThis = bind.bind(bind.call); > > > > var hopFn = uncurryThis({}.hasOwnProperty); > > > > So that we can say > > > > if (hopFn(registry, type)) { > > > > 2) We can replace the initialization of "registry" with > > > > var registry = Object.create(null); > > > > or, if we wish the same protection from post-initialization monkey > patching > > > > var create = Object.create; > > ... > > var registry = create(null); > > > > It turns out that neither of these additional ES5-based paranoid steps > helps > > with the worst problem remaining with Crock's corrected code. Likewise, > > nothing so far proposed for ES-next would help, except for Dave Herman's > > suggestion which I will write up shortly. > > > > </aside on why ES5 does not really help> > > > > > > > > As you've probably already guessed from the title of this email, the > problem > > occurs on most platforms when the function is called with an argument of > > "__proto__". Since we do a "hasOwnProperty" check first, the way in which > > this goes wrong depends on the platform. Evaluating > > > > [{}.hasOwnProperty('__proto__'), > > {}.__proto__.hasOwnProperty('__proto__')] > > > > on various browsers gives: > > > > false,false // Chrome > > true,true // WebKit Nightly > > false,true // FF Nightly > > false,false // Opera 12 alpha > > throws TypeError // IE10 Preview 2 > > > > Since IE doesn't treat "__proto__" as special magic, no problem there. > > WebKit Nightly will take the branch that happens to fail safe here, but > only > > for the reason that there's no "Object.prototype.push". All we can say is > > that we got lucky this time. When Chrome, FF, and Opera evaluate > > > > registry['__proto__'] = [handler]; > > > > they change registry to inherit from [handler] rather than > Object.prototype. > > WebKit would do the same if it had executed this line. > > > > Think this exercise is academic and doesn't arise in real systems? As > > observed at > > < > http://www.google.com/support/forum/p/Google+Docs/thread?tid=0cd4a00bd4aef9e4 > >, > > until recently, on all non-IE browsers, if you typed "__proto__" at the > > beginning of a new Google Doc, your Google Doc would hang. This was > tracked > > down to such a buggy use of an object as a string map. (To avoid such > > problems, Caja is shifting to using > > < > http://code.google.com/p/es-lab/source/browse/trunk/src/ses/StringMap.js>, > > which does seem safe on all platforms.) > > > > > > -- > > Cheers, > > --MarkM > > > > _______________________________________________ > > es-discuss mailing list > > [email protected] > > https://mail.mozilla.org/listinfo/es-discuss > > > -- Cheers, --MarkM
_______________________________________________ es-discuss mailing list [email protected] https://mail.mozilla.org/listinfo/es-discuss

