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

Allen Wirfs-Brock allen at wirfs-brock.com
Tue Nov 13 18:24:50 PST 2012


On Nov 13, 2012, at 12:52 PM, David Bruant wrote:

> Le 13/11/2012 21:25, Tom Van Cutsem a écrit :
>> 2012/11/13 Allen Wirfs-Brock <allen at wirfs-brock.com>
>> 
>> I think there is agreement that [[HasOwnProperty]] is just an optimization of ToBoolean([[GetOwnPropertuy]]).  Its only purpose is to avoid unnecessary reification of property descriptors. If that optimization isn't important we should just eliminate [[HasOwnProperty]].
>> 
>> I understand your point that on normal objects, implementations are free to avoid actually allocating a property descriptor for has or hasOwn checks. As far as the spec is concerned, the derived traps are completely unnecessary: we could hypothetically rewrite the entire spec to use only fundamental traps, and implementors would be free to cut as many corners as they want for non-proxy objects.
>> 
>> When I mentioned that derived traps avoid unnecessary allocations, I was really thinking about this from the point-of-view of the ES6 metaprogrammer. Say I'm creating my own virtual object abstraction whose properties reside in an external map, so I dutifully implement all the traps:
>> 
>> var store = new Map()
>> var p = new Proxy( { } /* target doesn't matter */ , {
>>   hasOwn: function(ignoreTarget, name) { return store.has(name); },
>>   getOwnPropertyDescriptor: function(ignoreTarget, name) {
>>     var e = store.get(name);
>>     return e === undefined ? undefined : {value:e, ...};
>>   },
>>   ...
>> };
>> 
>> Say we remove the "hasOwn()" trap, calling the getOwnPropertyDescriptor trap instead. Now my virtual object abstraction does need to allocate a descriptor.
> For the particular case you've written, when going for hasOwnProperty.call or the in operator, the JS engine knows it needs to output a boolean, so it can "rewrite" (or contextually compile) your trap last line as "e===undefined" (since "undefined" is falsy and objects created by object literals are truthy). In that particular case, the allocation isn't necessary provided some simple static analysis.
> Maybe type inference can be of some help to prevent this allocation in more dynamic/complicated cases too. I would really love to have implementors POV here.
> 
If you can trace/inline across internal method calls and are smart enough in your analysis you probably can eliminate the allocation.  The internal method calls come into play because you may have Proxies or other exotic objects on a [[Prototype]] chain so things that involve proto climbing will bounce back and force between internal methods and trap handlers.


My general philosophy has always been that when programming in an object-based language, a programmer shouldn't be afraid of creating and using objects.  It's the implementation's job to make sure that perspective is justified.  Given everything else that is likely to be going on in a rich proxy, this particular point may be unnecessary early optimization.

Regardless, my main concern isn't this optimization issue, but instead a concern about it being too easy to inadvertently define an internally inconsistent Proxy.


Allen
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20121113/5f02595a/attachment.html>


More information about the es-discuss mailing list