2011/1/27 David Bruant <bru...@enseirb-matmeca.fr>

>  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.
>

Right, this issue has come up before. From the "open issues" on the proxies
wiki page:

*TC39 Meeting 1/28/10 *The number of operators that proxies can virtualize
is still open for discussion. The current proposal does not allow proxies to
virtualize typeof and [[Class]]. Perhaps these could be virtualized but kept
constant by passing appropriate values for typeof and [[Class]] to the
Proxy constructor.
The alternative
API<http://wiki.ecmascript.org/doku.php?id=strawman:uniform_proxies>
does
virtualize typeof in this manner.
*TC39 Meeting 3/24/10 *The experimental third className parameter to
Proxy.create in spidermonkey should not be standardized. Objects should not
be able to virtualize the [[Class]] built-in property. However,
Object.prototype.toString.call(proxy) will reveal proxies if the object they
are proxying has a non-Object or non-Function [[Class]].

There is concern within the committee that overriding [[Class]] may violate
spec. invariants. I believe it is Allen's intention to take issues like this
into account in his MOP refactoring (Allen, correct me if I'm wrong).

IMHO, I think being able to override the [[Class]] at least for toString()
purposes will be required for proxies to fully fix/emulate existing host
objects.

- 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).
>

As Brendan pointed out, Arrays are not host objects, they are much more
privileged and part of the core language.

To elaborate on Brendan's response, I think the point of Allen's
MOP-refactoring is to structure the spec. such that ES-harmony has a very
well-defined internal object hierarchy, and proxies are the mechanism by
which JS developers can hook into that hierarchy. All existing built-ins
(Object, String, Array, ...) are part of the predefined internal object
hierarchy. They could or could not be defined in terms of proxies &
handlers, but even if they would be, their traps would still be defined in
terms of spec. language, not in terms of pure JS, to
avoid over-specification and to allow for efficient internal
representations.

That said, it would be very nice if the behavior of all built-ins can in
fact be emulated via proxies. I can imagine that a tutorial on ES-harmony
could then explain the behavior of built-ins by showing example code similar
to your Array emulation code.

Cheers,
Tom


>
>
>
>  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>
>
>> 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