Do we really need the [[HasOwnProperty]] internal method and hasOwn trap
Tom Van Cutsem
tomvc.be at gmail.com
Wed Nov 14 01:22:54 PST 2012
2012/11/14 Allen Wirfs-Brock <allen at wirfs-brock.com>
> On Nov 13, 2012, at 12:25 PM, Tom Van Cutsem wrote:
> 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.
> Interesting, the 1-to-1 symmetry I've been look for is between the
> internal methods and the proxy traps. To me, that is the MOP and things
> like Object.getOwnPropertyDescriptor are a connivence layer a level above
> the MOP. From that perspective, it feels fine to me to have a MOP
> operation (a trap or internal method), called say, CheckOwnProperty that
> has a flag argument that controls whether you want to get a property
> descriptor or a boolean result. That MOP operation can be used at the
> language level to implement the in operator and other language
> level-semantics and at the library level to implement convenience functions
> such as O.p.hasOwnProperty and Object.getOwnPropertyDescriptor. The MOP
> programmer (whether implementing ordinary objects in the implementation,
> host objects using low level extension points or using Proxy to implement
> exotic objects)r sits in the middle between those two layers. All they
> really need to know about is the MOP.
I think I understand your point of view. I'll try to restate it differently:
You are arguing for 2 levels of abstraction ("layers"):
- Most JS developers are "base-level" programmers: they use ES5 APIs like
Object.getOwnPropertyDescriptor to reflect on their objects.
- A small fraction of JS developers will be "meta-level" programmers: these
include at least proxy authors and host object authors. These programmers
would use a *different* API, i.e. the MOP, which consists of methods such
as a "checkOwnProperty" trap and presumably a corresponding
Reflect.checkOwnProperty method. There would be a correspondence between
the base-level API and the internal MOP methods, but this correspondence is
not a straightforward 1-to-1 correspondence.
Now, there are two routes to optimize for, with opposite pay-offs:
1) Make the MOP API correspond as much as possible to the base-level ES5
API. This benefits ES5 programmers, who can easily pick up the meta-level
API as it's recognizable, at the expense of ES6 meta-level programmers, who
must deal with a larger API surface (incl. the burden to keep fundamental
and derived traps in sync).
2) Make the MOP API as minimal as possible. This benefits ES6
meta-programmers, but at the expense of increasing the learning curve for
ES5 programmers to become ES6 meta-level programmers (because the
difference between base-level and meta-level API will necessarily be bigger)
Approach 1) corresponds roughly to the current setup with fundamental +
Approach 2) corresponds roughly to "provide only fundamental traps".
Now consider an ES6 meta-programmer interested in intercepting the
Given approach 1) she can look at the full list of traps (e.g. the list at
the top of <http://wiki.ecmascript.org/doku.php?id=harmony:direct_proxies>)
and quickly figure out that she must implement the "has" trap.
Given approach 2), our meta-programmer must figure out that the
"in"-operator in fact calls the "getOwnPropertyDescriptor" trap instead,
and tests for its result to be undefined or not.
In effect, approach 2) requires that meta-programmers understand the
default implementation of the derived traps (i.e. this code: <
before being able to intercept a derived operation.
To be fair, if our meta-programmer in approach 1) implements the "has"
trap, and that trap is not a simple before/after/around method that
forwards to the target, then she must also override
"getOwnPropertyDescriptor" to return consistent results. If she subclassed
Handler (and we make the fundamental traps abstract methods again), she'll
get an exception prompting her to investigate further. If she did not
subclass Handler, she just shot herself in the foot. So eventually, she
will have to learn about distinction between fundamental and derived
The difference between approach 1) and 2) is at what point you must learn
about the differences.
Approach 1) favors ES5 programmers. Approach 2) favors ES6
meta-programmers. I think we should optimize for ES5 programmers.
-------------- next part --------------
An HTML attachment was scrubbed...
More information about the es-discuss