I will let Tom and Mark field this one in full, but Arrays are *not* host objects, they are native objects in ECMA-262 terms.
However, Allen has taken the action to reconcile and perhaps unify the spec's internal methods (its Meta-Object Protocol) and Proxies' MOP. This would allow the spec to treat arrays as if they were proxies with native handlers. In reality, of course, a proxy is an empty object with a handler object (shared or not) that holdsl mutable state (somehow: closure, weakmap, whatever). Arrays OTOH must be efficient, dense if possible, single allocation if small, etc. No practical implementation would make a proxy and handler holding mutable state. This beautiful slide of Tom's (I believe) shows the parallelism and differences: http://brendaneich.com/brendaneich_content/uploads/selective-interception.png In C and C++ implementations, the handler is a suite of functions or methods, and all the array data is in the green "object" circle, or attached to it for efficient access with dynamic range over length. /be On Jan 27, 2011, at 8:33 AM, David Bruant wrote: > 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> >> 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