Le 13/11/2012 21:25, Tom Van Cutsem a écrit :
2012/11/13 Allen Wirfs-Brock <[email protected]
<mailto:[email protected]>>
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.
Your proposal of adding a flag to the trap fixes that, but IMHO in a
way that confuses the intent of the operation being intercepted:
var store = new Map()
var p = new Proxy( { } /* target doesn't matter */ , {
getOwnPropertyDescriptor: function(ignoreTarget, name, needDescriptor) {
if (!needDescriptor) { return store.has(name); }
var e = store.get(name);
return e === undefined ? undefined : {value:e, ...};
},
...
};
It's dawning on me that the main reason I dislike adding flags to the
fundamental traps is that it breaks the 1-to-1 symmetry with the
operations that they intercept:
Object.getOwnPropertyDescriptor(proxy, name) // traps as
getOwnPropertyDescriptor(target, name)
This symmetry should make it relatively easy for an ES5 programmer to
pick up the handler API. The signatures look familiar (at least for
all operations that are expressed as function calls). Adding extra
flags breaks the symmetry.
I agree. As I suggested in my other answer, the flag isn't necessary.
Very much like it's not for the internal operation.
David
_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss