Hi, 2011/3/31 David Bruant <[email protected]>
> Hi, > > First, I'd like to say that I'm glad proxy-related issues have been > discussed during the last TC-39 meeting and that all have found an > agreement. > > Then I have a something to say on > http://wiki.ecmascript.org/doku.php?id=strawman:handler_access_to_proxy > Quoting relevant parts: > "Andreas: experimenting with DOM wrappers. All prototype-climbing traps > require access to the receiver object (which is not necessarily the proxy > object), not just the get/set traps. The get and set trap may want access to > both the receiver and the proxy. " > "Current consensus: > * add receiver as a first argument to all prototype-climbing traps (get, > set, has, getPropertyNames, getPropertyDescriptor traps)" > > The intention I understand is that these proto-climbing traps should first > be applied to the own layer (or rather, their "own" equivalent) then be > applied recursively while climbing the prototype chain. > However, I think that with current ES5 internal method definitions and > proxies semantics ( > http://wiki.ecmascript.org/doku.php?id=harmony:proxies_semantics), this > doesn't work as the intention goes. For instance, [[Get]] (ES5 8.12.3) uses > [[GetProperty]] and calls [[GetProperty]] recursively on the prototype > object instead of the [[Get]] internal method. And currently (it was the > case before the meeting. I'm just realizing now), semantics of > [[GetProperty]] is to return undefined. > Similar issues goes with current "has" trap and [[HasProperty]] internal > methods which delegates inheritance responsibility to [[GetProperty]] (back > to previous problem). > > However, getPropertyNames and getPropertyDescriptor traps, recently > "promoted" as derived traps are still underspecified. Interestingly, the > current implementation ( > http://wiki.ecmascript.org/doku.php?id=strawman:proxy_derived_traps) isn't > recursive, but iterative. This is inconsistent with the current model and > should certainly be redefined as a recursive function: > --- > getPropertyDescriptor: function(receiver, name, proxy) { > var pd = Object.getOwnPropertyDescriptor(receiver, name, proxy); > var proto = Object.getPrototypeOf(proxy); > if(proto === null || pd !== undefined) > return pd; > return Object.getPropertyDescriptor(proto); // recursive version. > receiver is passed in some way (?) > } > --- > I think you're right. The spec uses recursion, so a proxy higher up the inheritance chain could terminate the lookup early. I also don't see how the original object to which Object.getPropertyDescriptor was applied could be passed up the chain. I also don't see the need for it, other than perhaps calling |bind(receiver)| on the found property descriptor's value, get or set attribute? > I'd like to remind that if Object.getPropertyDescriptor isn't a native > function with a native underlying internal method, but a monkey patch, it > will not call a proxy trap (maybe this should be addressed?). > There's a Harmony proposal that proposes adding Object.getPropertyDescriptor as a new built-in on Object for precisely this reason: < http://wiki.ecmascript.org/doku.php?id=harmony:extended_object_api> > > The iterative model differs from the recursive one in a way that the engine > is in control of making sure all layers are well-traversed and not > "hijacked" by one particular layer. This is actually the idea I called > "inheritance-safe proxies" ( > https://mail.mozilla.org/pipermail/es-discuss/2011-March/013366.html). > > I am wondering if by providing both proxy and receiver to all > proto-climbing methods, we're not providing too much power to proxies. Let's > imagine the following object with prototype chain: > o --> a --> b --> null. > a is a proxy and o and b are regular objects (or even proxies, it doesn't > really matter with the current model). First, with the current model, since > when a call is trapped, inheritance and actual prototype can be faked, a has > the power of denying b and messing up with be through Object.getPrototypeOf. > Now, if a gets access to 'receiver', it means it can mess up with o. Aren't > we providing too much power to a? > Proxies would always be able to "deny" lookup proceeding to their prototype, since you could implement a proxy that pretends to have all possible properties as own properties. But granted: if the handler never gets access to the proxy, then I don't think it can otherwise influence the proxy's prototype. As for |a| getting access to |o|, it needs this to faithfully emulate accessor properties (see below). > The more I think about it, the more I question the idea of provinding > receiver as an argument to proto-climbing traps. What was the initial > rationale behind it? I understand that it is different from proxy, but is it > necessary? What are the use cases that require it? > For the get and set traps, a proxy needs the original |receiver| as the |this|-binding when calling the get/set functions of accessor properties. Cf. their use in the default implementations of |get| and |set| here: < http://wiki.ecmascript.org/doku.php?id=harmony:proxies#trap_defaults> I'm not sure why it's needed in the other prototype-climbing traps (getPropertyDescriptor, getPropertyNames, has, enumerate). Perhaps Andreas can explain. Cheers, Tom
_______________________________________________ es-discuss mailing list [email protected] https://mail.mozilla.org/listinfo/es-discuss

