Le 27/01/2011 11:20, Tom Van Cutsem a écrit :
> - Agreed that if we contemplate adding 'proxy' as an argument to
> getPropertyDescriptor and getPropertyNames, we should add it to all
> other traps as well.
> - Agreed that this is the simplest way of allowing a shared handler to
> get at the proxy it's currently 'serving'
> - W.r.t. a handler not being able to perform typeof/instanceof on the
> proxy it's intercepting: this does have the benefit of detracting
> programmers from writing handlers that act differently for function vs
> object proxies. But agreed that this functionality might be needed to
> fix the quirky behavior of a host object.
This last point is actually a concern. Is the (one?) point of proxies to
being able to fully emulate (and by 'emulate', I also mean 'fix') host
objects. If so, proxies should have access to all internal
methods&properties. As said in ES5 8.6.2 right under Table 8:
"Every object (including host objects) must implement all of the
internal properties listed in Table 8.". If we want to be able to
emulate proxies, we need to be as powerful with proxies.
Question is: do we want to?

I have recently been working on emulating Arrays (they are host objects,
aren't they?) with proxies and native objects. I'll put the code on
github and provide a longer feedback in another e-mail, but the basic
idea was to use a forwarding proxy and implement the only method that
matters: defineProperty. I have almost blindly implemented+adapted
[[defineOwnProperty]] (ES5 15.4.5.1).
Everything works perfectly so far. There are a few differences with
native arrays, though:
- I have no control over the [[class]] internal property, so even though
my "proxyArrays" act like native ones, they can be discriminated quite
easily.
- I haven't tested, but according to the semantics of Array initialisers
(ES5 11.1.4), "[]" calls "new Array() where Array is the standard
built-in constructor with that name.". So even if I try window.Array =
proxyArray, "[]" should not create one of my arrays. This sounds
perfectly fair.
- I obviously initialize my proxyArrays with Array.prototype as
prototype. I haven't tested if it works; it is allowed not to, because
in ES5, under each array prototype method is written:
" The *** function is intentionally generic; it does not require that
its this value be an Array object. Therefore it can be transferred to
other kinds of objects for use as a method. Whether the *** function can
be applied successfully to a host object is implementation-dependent. ".
They could be reimplemented if needed to fully emulate Arrays. (I've
worked on that a billion years ago :
https://github.com/DavidBruant/ecma5array/blob/test_conformance/ecma5array.js)

So here is another question on proxies goal/rational:
Should proxies be powerful enough to fully emulate native Arrays? (If so
and if ES Harmony has proxies in it, then native Array could be
specified as a proxy which is awesome and a half in my opinion, but
that's a different problem).


> Re. adding 'proxy' as an optional last parameter to all traps: what
> worries me is that for some traps, this could be terribly confusing.
> Consider:
>
> Object.getOwnPropertyDescriptor(proxy, name);
> // will trap as:
> getOwnPropertyDescriptor: function(name, proxy) { ... }
>
> The reversed argument order is going to bite people.
> Adding 'proxy' as a last optional argument is confusing in this way
> for get{Own}PropertyDescriptor, defineProperty, delete, hasOwn
> It's OK for get{Own}PropertyNames, keys, fix, has, enumerate
> get and set would then take 4 arguments, and it's unclear to me
> whether tacking 'proxy' to the front or to the back is better.
> (alternatively, maybe 'get' and 'set' don't need access to the proxy
> after all. It seems to me that if 'receiver' has multiple proxies in
> its prototype chain, only the one closest to receiver is going to
> trigger a handler get/set trap. OTOH, without a built-in
> Proxy.isTrapping(obj) method, I don't think the handler can find out
> what object on the prototype chain is a proxy)
>
> We could choose to add 'proxy' at the "right" place in the argument
> list depending on the trap. This trades one kind of cognitive load
> (unexpected argument order for some traps) for another (no uniform
> position of 'proxy' across all traps, and no longer an optional
> argument for all traps). Either way, we need to decide whether this
> added API complexity is worth it.
>
> One more thing: giving the handler access to its proxy by default may
> increase chances of runaway recursion hazards, as every operation that
> the handler performs on its own proxy is going to call some trap on
> the handler itself. Ideally, we should be able to label the 'proxy'
> parameter with a big red warning sign saying "handle with care!". I
> ran into this problem already a couple of times when writing "get"
> traps. The 'receiver' parameter often is the proxy itself, and doing
> even simple things like trying to print the proxy (e.g. for debugging)
> will call proxy.toString, hence will recursively call the "get" trap
> you're trying to debug. But maybe the problem is just more exaggerated
> in the "get" trap since property access is so common, and it won't
> really be an issue for the other traps.
I had already read that point in your proxy tutorial. It will be up to
the resources that people go to to learn how proxies work to tell them
that they should be careful with unwanted recursion.
One important such resource is very likely to be the MDN page. I'll take
care of writing down all these points. Otherwise, it's a wiki, feel free
to jump in anytime to correct things or add examples.

Cheers,

David

>
> Cheers,
> Tom
>
> 2011/1/26 Brendan Eich <bren...@mozilla.com <mailto:bren...@mozilla.com>>
>
>     On Jan 26, 2011, at 11:02 AM, David Bruant wrote:
>
>     >> On the question of proxy parameters for all traps (well,
>     receiver for get and set): fewer args are better, and closure
>     capture of proxy by handler avoids leaking the proxy to handler
>     friends, if that matters. Likewise you can't get the handler from
>     the proxy.
>     > If you handlers are frozen, there should be no leaking,
>     shouldn't there? (I actually think that freezing the handler
>     should be done in the no-op forwarding proxy example or any
>     handler factory, but that's another issue).
>
>     No default freezing is going to be imposed. :-|
>
>
>     > About the closure capturing, it works only if one proxy is using
>     the handler. It doesn't if several proxies share it.
>
>     Good point.
>
>
>     >> These aren't absolute arguments, but I remember working through
>     the alternative of a leading proxy parameter, both as JS hacker
>     using proxies and in terms of SpiderMonkey's C++ implementation,
>     and it was just bigger and less tidy, for both "sides" (JS and
>     C++), without enough payoff.
>     > ... what about a trailing proxy parameter? It won't change
>     anything on the C++ side (by comparison to a leading parameter),
>     but will on the JS side, because you can omit the parameter if you
>     don't need it.
>
>     Not a bad idea, and the C++ gurus can take it. Tom, Mark?
>
>     /be
>
>

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

Reply via email to