Why we need to clean up __proto__

John J Barton johnjbarton at johnjbarton.com
Wed Dec 28 08:13:39 PST 2011


Doesn't Object.keys() solve this problem?

jjb

On Wed, Dec 28, 2011 at 1:09 AM, Axel Rauschmayer <axel at rauschma.de> wrote:

> The cleanest solution to the problem you outlined seems to be to never use
> objects as dictionaries(?) That is, one would separate the concerns program
> definition and application data. Allen’s object model reformation (allowing
> one to override the [] operator) would help, too.
> http://wiki.ecmascript.org/doku.php?id=strawman:object_model_reformation
>
>
> On Dec 27, 2011, at 3:53 , Mark S. Miller 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
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
>
> --
> Dr. Axel Rauschmayer
> axel at rauschma.de
>
> home: rauschma.de
> twitter: twitter.com/rauschma
> blog: 2ality.com
>
>
>
>
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20111228/63ead3c1/attachment-0001.html>


More information about the es-discuss mailing list