2011/11/10 Allen Wirfs-Brock <al...@wirfs-brock.com> > > On Nov 10, 2011, at 9:03 AM, Tom Van Cutsem wrote: > > Regarding property deletion: if an object is implemented as a proxy, and > you would want to delete a property from that object, I'm not sure why you > would want to circumvent triggering the delete trap? > > > In > http://wiki.ecmascript.org/doku.php?id=strawman:object_model_reformation I'm > exploring explicitly distinguishing the semants of obj.propName and > obj[expression] such that an object can explicitly define its > obj[expression] behaviors without using a Proxy (note that currently by > the time a Proxy is called, the distinction is already lost so even if you > wanted to use a Proxy for this purpose they may not be adequate). In many > cases (including the default), the object-specific "handler" for > obj[expression] will delegate back to Object.getProperty/Object.setProperty > (either directly or via a super call). But note that it can do so via > direct [ ] syntax, as that would loop. This can actually all be modeled > with a new Reference variant within the spec. that distinguishes . > references from [ ] references. > > However, I also need to account for the delete operator and distinguish > delete obj.propName from delete obj[expression] . This can be taken care > of by the same reference extension (essentially References needs a delete > "method"). A handler for deleting obj[expression]] may also want to > delegate back to normal property deletion and for the same reason as for > obj[exper] get/set handlers it can't directly use the syntactic form. > Instead it needs to call an Object.deleteProperty function. >
Understood. > BTW, rather than adding these methods to Object, I'm beginning to think it > might be better to import them from a built-in reflection module. > Indeed. Perhaps that built-in reflection module could be the same module that defines the default forwarding handler. Your note that we need an Object.deleteProperty method apart from the built-in syntax reminded me that the default forwarding handler for proxies is really all about providing method-based alternatives to things that can currently only be achieved through built-in syntax. In the direct proxies proposal, I proposed defining a Proxy.forward object that enables forwarding all operations interceptable by proxies to another object. A prototype implementation of it exists here: < http://code.google.com/p/es-lab/source/browse/trunk/src/proxies/DirectProxies.js#1250 > If you observe closely, you'll note that the default forwarding API is really the "dual" of the Proxy API. Proxies uniformly turn all sorts of operations on objects (whether triggered through syntax or built-in methods) into trap invocations, for instance: Object.getOwnPropertyDescriptor(proxy, name) => handler.getOwnPropertyDescriptor(name, target) name in proxy => handler.has(name, target) etc. The default forwarding API turns these trap invocations back into the original operations: Proxy.forward.getOwnPropertyDescriptor(name, target) => Object.getOwnPropertyDescriptor(target, name); Proxy.forward.has(name, target) => name in target etc. That's why the forwarding API is crucial for double lifting to work: if a handler is itself a proxy, then to intercept handler[trapName], we need to be able to generically forward the operation, which is made possible by writing Proxy.forward[trapName]. I proposed the name "Proxy.forward" since that looks very natural when writing handler code that simply wants to "augment" the default behavior: funtion makeChangeLogger(target) { return Proxy.for(target, { set: function(receiver, name, value, target) { log('property '+name+' on '+target+' set to '+value); return Proxy.forward.set(receiver, name, value, target); } });} However, it now seems to me that the methods encapsulated by Proxy.forward can be more generally useful for arbitrary meta-programming, not just for forwarding in the case of proxies. I see an opportunity here to kill two birds with one stone: we can introduce a reflection module (assume it's called "Reflect" for now) that contains the Proxy.forward methods. That would: a) obviate the need for Object.deleteProperty (now named Reflect.delete), Object.getProperty (Reflect.get) and Object.setProperty (Reflect.set). b) obviate the need for Proxy.forward (the above code snippet would call Reflect.set instead, which is even shorter) The design guideline for this Reflect module would be that the methods it exposes have _exactly_ the same name + parameter list as the Proxy API trap names. Not only does this retain consistency, it also enables easy double lifting (or perhaps other design patterns that want to treat operations on objects / Proxy traps generically). Cheers, Tom
_______________________________________________ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss