[Harmony proxies] Proxies, prototype chain and inheritance

Mark S. Miller erights at google.com
Mon Mar 21 18:22:36 PDT 2011


Hi David, are you aware of <
http://wiki.ecmascript.org/doku.php?id=strawman:proxy_instanceof>?

I just heard from Brendan today that Andreas Gal has encountered some DOM
emulation issues that might make us want us to consider this sooner rather
than later. How well would it also address the cases you have in mind?



On Mon, Mar 21, 2011 at 4:08 PM, David Bruant <david.bruant at labri.fr> wrote:

>  Hi,
>
> Proxies can be helpful to emulate multiple inheritance (
> http://journal.stuffwithstuff.com/2011/02/21/multiple-inheritance-in-javascript/).
> Long story short, with the get and set traps, you can emulate this multiple
> inheritance without having the required prototype chain. However, since
> "Object.getPrototypeOf" and "instanceof" cannot be trapped, these cannot be
> used to observe inheritance. There are perfectly valid reasons for which
> they cannot be trapped, I won't question this. My present suggestion is a
> mechanism to unable inheritance observation while keeping a couple of
> language properties safe.
>
> One ECMAScript invariant when dealing with objects is that the prototype
> chain of an object is set once for all at object creation. Consequently, for
> all function F, the ordered list of objects traversed while calling
> F.[[HasInstance]] (ES5 15.3.5.3 step 4 a) will always be the same throughout
> the entire object lifetime. My idea consists of being allowed to provide
> this such a list at proxy creation time. With this list, multiple
> inheritance can be observed if 'instanceof' calls looks at this list. This
> is the idea, then comes "how to achieve it?". Everything said from now on is
> just thoughts of how the idea could be achieved, neither definitive thoughts
> nor exhaustive.
>
> The idea can be achieved at different degrees of consistency with how
> objects currently work. Here are the questions that I have asked myself
> while thinking about the topic:
> At initialization, should this list replace the second prototype argument
> of Proxy.create or should it be provided as a complement just for the
> purpose of instanceof?
> What level of consistency with Object.getPrototypeOf?
> Let's imagine for a minute that the list replaces the prototype object as
> second argument:
> ---------------
> // a, b, c are already existing object
> function A(){} A.prototype = a;
> function B(){} B.prototype = b;
> function C(){} C.prototype = c;
>
> var p = Proxy.create(handler, [a,b,c]);
> // p instanceof A && p instanceof B && p instanceof C === true
> --------------
> Instead of returning "a", "Object.getPrototypeOf(p)" could return something
> like: "Proxy.create(forwardingHandler(a), [b,c]);". Please notice the
> recursivity. If the list is empty, Object.getPrototypeOf returns null,
> obviously.
> One little issue is that "Object.getPrototypeOf(p) !==
> Object.getPrototypeOf(p)" since Proxy.create creates a new object (new
> identity) each time, but a cache will solve the issue easily and the same
> object can be returned each time. This cache trick will preserve the
> invariant that an object has a unique prototype chain.
> Two invariants (at least) are broken, though:
> - p instanceof A iff there exists an n such that A.prototype ===
> (Object.getPrototypeOf)^n(p)
> - if two objects (o1, o2) inherit from the same two object (a, b) in the
> prototype chain, then there is a unique partial prototype chain going from a
> to b or b to a.
> However, thanks to the forwarding proxy we keep a way for all "A" instances
> (created through "new A()" or with my proxy mechanism) to communicate and
> all still inherit (actually or virtually) from the "same" "A.prototype"
> object.
>
> The idea is a bit new, so there are certainly plenty of other questions I
> haven't thought of. And once again, this was just one possible beginning of
> how to achieve my idea above.
>
> Anyway, through the "getPropertyDescriptor", "getPropertyNames", "has",
> "get", "set" and "enumerate" traps (let's call them "prototype-climbing
> traps" since there behavior on regular object is to climb the prototype
> chain), there are already plenty of ways to break ECMAScript inheritance
> invariants. My personal opinion is that "Object.getPrototypeOf" and
> "instanceof" are currently overprotected with regard to the already broken
> invariants. I agree that trapping them is too dangerous, because it would
> provide too much freedom (and there is the security issue with instanceof).
> However, I think there is room in between to provide some power to the proxy
> writer while keeping things under control. I have tried to show one such
> idea and one way to partially achieve this idea, there are different
> achievement tracks for the same idea and certainly other ideas.
>
>
> Another way of solving the inconsistency I see in providing the 6
> "prototype-climbing" traps ("getPropertyDescriptor", "getPropertyNames",
> "has", "get", "set" and "enumerate") and protecting Object.getPrototypeOf
> and instanceof could be to provide a softer version of proxies where these
> traps wouldn't be provided. Prototype-climbing internal methods would be
> delegated to the ECMAScript engine with the default behavior they have on
> objects (but still calling own traps when their algorithm requires them to).
> By design of this softer version, proxy writers would be ensured that
> inheritance will be done properly for them and they don't have to worry
> about it. They would just have to take care of the own properties "layer".
> (This paragraph is a slightly different topic. If you feel it requires its
> own thread, feel free to fork)
>
> David
>
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
>


-- 
    Cheers,
    --MarkM
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20110321/286861dd/attachment.html>


More information about the es-discuss mailing list