Hi David, 2013/6/7 David Bruant <bruan...@gmail.com>
> Le 02/06/2013 09:46, Rick Waldron a écrit : > >> 4.4 Proxies >> >> Proxy Invoke Trap and wrong |this|-binding on built-in methods >> >> AWB: with current default behavior of “get”, “Caretaker” will break on >> built-ins such as Date, because the |this| binding is by default set to the >> proxy, so the Date built-in method will not find the correct private state. >> ARB: Same issue with binary methods >> ... >> STH: We should add invoke trap but not change the object model >> MM: Pleasant to have. Separate from private state. >> AWB: used to think this was an issue with proxies, but convinced that >> it’s an API issue: we need to provide default handlers that do the right >> thing, and which users can subclass. In particular, want a handler that, on >> forwarding, rebinds |this| to the target. >> STH: If you want to proxy a Date method the underlying `this` needs to be >> a non wrapped Date object. >> > Doesn't this break encapsulation? > No it doesn't (more below). > var d = new Date(); > var pd = new Proxy(d, { > invoke: function(target, name, thisArg, args){ > return target[name].apply(thisArg, args) > } > }) > > var pt = pd.getTime(); // calls the invoke trap > This will call "invoke", which forwards to the real Date.prototype.getTime but with thisArg still bound to pd (the proxy). Hence this method will fail with a "error: not a Date" exception. The proposed solution is to use a ForwardingHandler [1] in such cases. > > // in a mixed-trusted context with access to pd: > var ppd = new Proxy(pd, { > invoke: function(target, name, thisArg, args){ > // does the actual unwrapped date object leak through thisArg? > } > }); > > var ppt = ppd.getTime(); > For this method call, thisArg inside the invoke trap will be bound to ppd, not the the real wrapped Date object. > In any case, what is the following supposed to do: > > Date.prototype.getTime.call( new Proxy(new Date(), handler) ) > This will still crash with an "error: not a Date" exception. Even when using a ForwardingHandler. > > I imagine we would want this to work too. Is this going through the invoke > trap as well? The question stands for all new "class-specific" (Map, Set, > etc.) methods that would be dot-called with a proxy as first argument. > dot-called methods will not trigger the "invoke" trap. > If the problem being solved is making Date (and Map, Set, etc) built-in > methods works on wrapped objects, I feel the invoke trap is only a partial > solution. > It is indeed. Combined with the ForwardingHandler, the invoke() trap allows us to transparently forward |pd.getTime()| but not |Date.prototype.getTime.call(pd).| > I intuit (but have no proof) that for Date.prototype.getTime.call to work > on proxies, there is a need for class-specific traps. > * Object properties have specific traps to intermediate access > (has/get/set/defineProperty/**keys, etc.), > * [[Prototype]] has specific traps to intermediate access > (get/setPrototypeOf) > * [[Extensible]] has a specific trap to intermediate access > (preventExtensions) > * [[Call]] has a specific trap to intermediate access (apply) > * [[Construct]] has a specific trap to intermediate access (construct) > * Some other things that are somewhat internal (@@iterator, @@class, etc.) > are exposed as symbols and are mediated via object properties-related trap > > The pattern I see is that a good share of object internal properties > (ES5.1 - 8.6.2 - Table 8 and Table 9) have traps dedicated to mediate > access. > > The case of functions is interesting. There are traps that are only > relevant when the target is a function. In that regard, adding traps that > are specific to accessing the Date internal [[Time]] value or specific > traps to mediate access to [[MapData]] isn't any different than the current > specific traps that mediate [[Call]] or [[Construct]] > I think your analysis is mostly right: if we want to make e.g. Date.prototype.getTime.call(proxy) work, then the easiest way to fit that into the current design would be to add Date-specific traps (and Map-specific, Set-specific, Regexp-specific, etc. traps) The question is whether there's a strong need for intercepting these operations. It implies a pretty strong growth of the handler API. And it's not sufficiently general-purpose to also work for exotics that are defined outside of ES6 (e.g. DOM objects). For full transparency across isolated object graphs, I think membranes are still the way to go. Cheers, Tom [1] http://wiki.ecmascript.org/doku.php?id=harmony:virtual_object_api
_______________________________________________ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss