Note that passing the proxy means that a shared handler object can do caching 
or other discrimination based upon the  proxy it is being invoked on.  For 
example, the getPropertyDescriptor implementation shown below could have a 
cache to avoid repeated proto chain chasing. 

Adding the proxy parameter seems to add power, but also may add complexity 
because it opens the door for addition hander design alternatives that weren't 
available before.  For example, forwarding could be supported by a single 
shared forwarding handler that used used a weak map to maintain the association 
between the proxy and the target object.  This design saves (relative to the 
currently forwarding proxy design) on handler instances at the cost of a weak 
map lookup for every trap invocation.  Whether this additional design 
flexibility is good or bad is probably debatable.  However, I personally am 
included towards the increased flexibility side of the debate. 

Allen



On Jan 26, 2011, at 8:45 AM, Tom Van Cutsem wrote:

> Ok, so Mark and I briefly discussed the implications of making 
> "getPropertyDescriptor" and "getPropertyNames" derived.
> 
> Here's one issue: if you try and write these traps as methods of some sort of 
> "default" handler as we did for the other derived traps (see 
> <http://wiki.ecmascript.org/doku.php?id=harmony:proxies#trap_defaults>) 
> you'll notice that the handler, by default, has no way of referring to the 
> proxy it's intercepting, hence can't get at its prototype and hence can't do 
> the prototype-chain-walk.
> 
> Now, from an implementation point-of-view, this isn't really a problem since 
> the proxy implementation can make the connection between proxy and handler 
> when the trap is called, and thus can do the prototype-chain-walk. It's just 
> that you can't write it out in Javascript itself. Mark argues that therefore, 
> "getPropertyDescriptor" and "getPropertyNames" are still fundamental.
> 
> Yet we both agree that providing a default implementation for these 2 traps 
> makes perfect sense. Mark suggested we could classify traps in two different 
> ways: ("optional" vs "mandatory") vs ("fundamental" vs "derived"). In that 
> view, getPropertyDescriptor and getPropertyNames would be optional and 
> fundamental. All other traps would be either (fundamental & mandatory) or 
> (derived & optional).
> 
> I think that for developers, really the only distinction that matters is 
> "optional" vs "mandatory". The "fundamental" vs "derived" distinction helps 
> to clarify things for us spec. readers/writers.
> 
> While writing this, I also thought of another potential solution: we could 
> choose to pass the proxy as an additional argument to the traps. Then the 
> default implementation of getPropertyDescriptor could be written in 
> Javascript as follows (adapting David's code):
> 
> // currently, this trap only takes the 'name' param
> getPropertyDescriptor: function(proxy, name) {
>     var objectToInspect;
>     var result;
> 
>     for(objectToInspect = proxy; 
>         objectToInspect !== null; 
>         objectToInspect = Object.getPrototypeOf(objectToInspect))
>     {
>             result = Object.getOwnPropertyDescriptor(objectToInspect, name);
>             if (result !== undefined) { return result; } 
>     }
> 
>     return undefined;
> }
> 
> Cheers,
> Tom
> 
> 2011/1/24 Tom Van Cutsem <tomvc...@gmail.com>
> David,
> 
> Your intuition of what constitutes a fundamental vs. a derived trap is 
> correct. Strictly speaking, the Proxy API could do with just the fundamental 
> traps. The motivation for providing the optional derived traps was that 
> overriding derived traps often allows proxy implementors to implement the 
> operation more efficiently (usually with less object allocations).
> 
> As for your suggestion of turning 'getPropertyNames' and 
> 'getPropertyDescriptor' into derived traps: I think you're correct. We could 
> specify getPropertyNames and getPropertyDescriptor in terms of their "own" 
> siblings + a prototype-chain-walk.
> 
> I recall a discussion with Mark where this issue was briefly discussed 
> before. At that time, I was concerned by the fact that you could equally well 
> define getOwnPropertyDescriptor as the derived trap, in terms of 
> getPropertyDescriptor + getOwnPropertyNames, as follows:
> 
> getOwnPropertyDescriptor: function(name) {
>  var desc = this.getPropertyDescriptor(name);
>  var ownnames = this.getOwnPropertyNames();
>  if (ownnames.indexOf(name) !== -1)
>    return desc;
>  else
>    return undefined;
> }
> 
> But applying the principle of minimizing the amount of allocations in default 
> trap implementations, your definition is strictly the better one.
> 
> I'm in favor of any change that can minimize the amount of fundamental traps, 
> so I'm in favor of adopting your change. Maybe Mark still recalls reasons for 
> why these traps were categorized as fundamental traps in the first place.
> 
> Cheers,
> Tom
> 
> 2011/1/23 Brendan Eich <bren...@mozilla.com>
> 
> I think David has a point. The fundamental vs. derived distinction is, as I 
> understand it, what Mark wrote recently, and David's application of it is 
> sound (we do that prototype-walk with shadowing "duplicate removal" when 
> starting a for-in loop in SpiderMonkey). Tom should weigh in.
> 
> But proxies have a proto chain for instanceof and good old prototype-based 
> delegation purposes, even though their traps could ignore the proto 
> parameter. The instanceof operator will not, and note how there is no 
> getPrototypeOf trap, either.
> 
> This is a feature. I asked early on in the development of proxies whether the 
> alternative, of putting the proto-chain walk "on the outside" of the proxy's 
> handler traps was considered, and Mark pointed out the obvious: that doing so 
> is strictly less flexible for cases where a proxy wants to do something 
> different.
> 
> But this greater-flexibility design decision does not mean the universal, 
> object -invariant (ignoring mutable __proto__) instanceof and getPrototypeOf 
> (and ES3's isPrototypeOf) relations should be outside of a proxy's control. 
> The Proxy.create proto parameter is the way to control those relations, for 
> the life of a given proxy, and modulo property lookup trap freedom to do 
> other things than just delegate up the proto chain.
> 
> /be
> 
> On Jan 23, 2011, at 8:43 AM, François REMY wrote:
> 
>> Moreover, should a Proxy really have a prototype ?
>> I mean, what’s the point about having a prototype, since the “get” method 
>> can return everything you would like for any property ?
>>  
>> I think getProtototypeOf should be defined as a new trap. And its default 
>> behaviour should be to return null (or Object.prototype, but I think null is 
>> the intented behavior of a proxy).
>>  
>> On the other hand, overriding getPropertyNames should not be allowed. 
>> getPropertyNames should *always* return the concatenation of the properties 
>> returned by getOwnPropertyNames() and by 
>> getPrototypeOf(this).getPropertyNames(). It makes no sense otherwhise.
>>  
>> I understand that we may want to redefine the way an ECMAScript Object can 
>> handle the native commands, but I’m strongly against anything that can 
>> conduce to illogical results (if there’s not an use case that justify it, 
>> naturally). The definition of getPropertyNames is clear and being able to 
>> redefine it locally seems me wrong. A proxy can modify is own behavior, not 
>> the behavior of the ES engine. Being able to have getPropertyNames and 
>> getOwnPropertyNames returning incompatible results is somewhat hurting me. 
>> Is there any reason we should allow that ? Any use case ?
>>  
>> I’m issuing the same concerns for the “has” trap. It think it should not be 
>> a trap. It should always return hasOwn(key) || prototype.has(key). Each one 
>> of hasOwn and prototype can be tuned by the proxy, but not the “has” itself. 
>> We’re not removing features, but we prevent bad usage of it. Whatever the 
>> user code do, the ‘has’ behavior will stay logical.
>>  
>> Another thing I don’t quite understand is the difference between “keys” and 
>> “enumerate”. If there’s no strong difference, it should be the same trap 
>> (same logic: enumerate should return the concatenation of this.keys and 
>> this.prototype.keys). Having two different but similar traps will cause 
>> confusion. Maybe there’s a need for this difference however. I just didn’t 
>> understand why such a difference should exist, but at least I see more 
>> possible usages than the first three traps I “contested”.
>>  
>> Anyway, if we should retain only one thing from the discussions we already 
>> have seen on the Proxy hub, is that it’s a great feature, but one that still 
>> needs some work before implementation ;-)
>>  
>> Regards,
>> François
>>  
>> From: David Bruant
>> Sent: Sunday, January 23, 2011 4:24 PM
>> To: es-discuss
>> Cc: Mark S. Miller
>> Subject: [ES Harmony Proxies] Fundamental trap definition
>>  
>> Hi,
>> 
>> I am wondering if getPropertyDescriptor and getPropertyNames fundamental 
>> traps shouldn't rather be derived traps since they could have a pretty 
>> straightforward default implementation.
>> One implementation of getPropertyNames could be :
>> -------------------------- 
>> Object.getPropertyNames = function(o){
>>     var objectToInspect;
>>     var result = [];
>> 
>>     for(objectToInspect = o; 
>>         objectToInspect !== null; 
>>         objectToInspect = Object.getPrototypeOf(objectToInspect))
>>     {
>>             result = 
>> result.concat(Object.getOwnPropertyNames(objectToInspect)); 
>>     }
>> 
>>     return result.removeDuplicates(); // the removeDuplicates method is made 
>> up, but you get the point
>> }
>> --------------------------
>> This seem to fit the proposal 
>> (http://wiki.ecmascript.org/doku.php?id=harmony:extended_object_api&s=getpropertydescriptor)
>>  expectations). This could be also the default getPropertyNames trap 
>> implementation.
>> 
>> I haven't really seen a strong definition of what fundamental traps are in 
>> the proposal. On Mark Miller's e-mail 
>> (https://mail.mozilla.org/pipermail/es-discuss/2011-January/012601.html) is 
>> written:
>> [a trap is fundamental if] there is no coherent default behavior to fall 
>> back to that would be defined in terms of the remaining traps. (please tell 
>> me if I misinterpret what you meant)
>> If we're going with this definition, then getPropertyDescriptor and 
>> getPropertyNames should probably be derived traps since they can clearly be 
>> defined thanks to other traps (respectively getOwnPropertyDescriptor and 
>> getOwnPropertyNames as I showed  above) which seems to be coherent fallback 
>> behavior.
>> Instead of a formal definition, this could be a rational for deciding what 
>> is a fundamental trap and what isn't.
>> 
>> In the 5 remaining traps (getOwnPropertyDescriptor, getOwnPropertyNames, 
>> defineProperty, delete, fix), I don't see any that could be defined thanks 
>> to the others. They seem to be also the fundamental actions that one can 
>> perform on a single object:
>> Property-wise:
>> - create/configure a property (defineProperty)
>> - delete a property (delete)
>> - retrieve a property (getOwnPropertyDescriptor. Can be used to separate the 
>> create and configure cases of defineProperty)
>> Property-set-wise:
>> - retrieve the property set (getOwnPropertyNames. More can be found later on 
>> each property with getOwnPropertyDescriptor)
>> - prevent further extension (and optional reconfigurations for seal and 
>> freeze)(fix)
>> The prototype can be retrieved thanks to Object.getPrototypeOf (which cannot 
>> be trapped for consistency purposes) and all actions can be performed by 
>> climbing the prototype chain.
>> 
>> Any thoughts on the fundamental trap definition?
>> Or on the idea of turning getPropertyDescriptor and getPropertyNames into 
>> derived traps with the suggested definition?
>> 
>> David
>> 
>> _______________________________________________
>> es-discuss mailing list
>> es-discuss@mozilla.org
>> https://mail.mozilla.org/listinfo/es-discuss
>> _______________________________________________
>> es-discuss mailing list
>> es-discuss@mozilla.org
>> https://mail.mozilla.org/listinfo/es-discuss
> 
> 
> _______________________________________________
> es-discuss mailing list
> es-discuss@mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
> 
> 
> 
> _______________________________________________
> es-discuss mailing list
> es-discuss@mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss

_______________________________________________
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to