Do we really need the [[HasOwnProperty]] internal method and hasOwn trap

David Bruant bruant.d at gmail.com
Tue Nov 13 01:44:16 PST 2012


Le 12/11/2012 19:17, Allen Wirfs-Brock a écrit :
> On Nov 12, 2012, at 2:21 AM, Brandon Benvie wrote:
>> Shouldn't it be the reverse, based on the removal of getPropertyDescriptor/Names? The proxy controls what i's [[Prototype]] is which indirectly directs how non-own lookups proceed. The functionality of `has` can (and usually should) be derived from proto-walking hasOwn until true or null.
> yes, that would be a good fix for this particular problem.  [[HasOwnProperty]] could remain as an internal method and HasProperty could be defined as an abstraction operation that uses the [[Prototype]] internal accessor and [[HasOwnProperty]].
Indeed. Otherwise, what happens with 
Object.prototype.hasOwnProperty.call(new Proxy({}, handler), 'a') would 
be unclear.

> Another potential consistency issue is between [[HasOwnProperty]] and [[GetOwnProperty]].  That could be eliminated by combining them into one operation:
>
> [[GetOwnPropety]](name, descriptorNeeded) -> descriptor | boolean | undefined
>
> If descriptorNeeded is true it acts as the current [[GetOwnProperty]]. If descriptorNeeded is false it acts as the current [[HasOwnProperty]].
>
> At the handler-level it makes it impossible to override "hasOwn"without also overriding "getOwnPropertyDescriptor"
The boolean isn't needed. It's possible to get rid of the 
[[hasOwnProperty]] internal method and only keep [[GetOwnPropety]](name).
* "Object.prototype.hasOwnProperty.call(o, name)" would be defined as 
ToBoolean(o.[[GetOwnProperty]](name))
* "name in o" would be the same thing with proto-climbing
Both hasOwnProperty.call and the in operator would call only the 
getOwnPropertyDescriptor trap, the rest would be left to implementors.

It may be weird to get rid of both hasOwn and has traps and that 
hasOwnProperty.call and the in operator call the 
getOwnPropertyDescriptor trap, but it's the cost of wanting consistency 
between [[GetOwnProperty]] and [[HasOwnProperty]]. I'm personally fine 
with this; I have no preference for one side or the other.

 From the spec point of view, it's possible to remove [[HasOwnProperty]] 
as an internal method, but to define a helper function. The idea behind 
doing this (apparently cosmetic) change could be to reach 1-to-1 
correspondence between object internals and proxy traps.


I'd like to point out that long discussions have already occurred about 
invariants and trap results consistency. By essence of allowing to 
provide functions for handler traps, it's possible to allow arbitrary 
inconsistencies. For instance:

     // "temporal inconsistency"
     var a = new WeirdObject();
     console.log('yo' in a); // true
     console.log('yo' in a); // false
     console.log('yo' in a); // false
     console.log('yo' in a); // true

     // "get/set" inconsistency
     var b = new WeirdObject();
     b.yo = 26;
     console.log(b.yo); // logs "what's up es-discuss!!"

These are other inconsistencies with the expectations we currently have 
from objects. I can't help wondering why this inconsistency (or any 
other inconsistency) would be considered more or less important than the 
one discussed in this thread.
IIRC, previous discussions led to the conclusion that it's impossible to 
get rid of all inconsistencies. The minimum consistency required was 
defined for security purposes and led to the invariant enforcement checks.
I'm fine if we're discussing removing some other inconsistencies, but 
I'd be more interested in seeing a principled way to decide which 
inconsistency we're getting rid of and which we still allow. In other 
word, what makes an given inconsistency a bad thing?
The previous answer we had was in essence "if it prevents defensive 
programming" (Tom or Mark will correct me if I'm misinterpreting or 
miswording it) and with the current proxy design, it's possible to offer 
freedom to proxies as long as it's within the boundaries of respecting 
non-configurable properties and non-extensible invariants.

What would be the new answer to my question?

David


More information about the es-discuss mailing list