On Sun, Jul 3, 2011 at 11:07 AM, David Bruant <david.bru...@labri.fr> wrote:
> Le 03/07/2011 14:59, Tom Van Cutsem a écrit : > > As a follow-up to the fixed properties proposal: > > > > I created a prototype implementation of fixed properties on top of the > > existing Proxy API. The idea is to wrap an existing proxy handler in a > > FixedHandler. This FixedHandler does the bookkeeping and checking to > > ensure that the wrapped handler doesn't misreport non-configurable > > properties. > > > > Full source code available here: > > < > http://code.google.com/p/es-lab/source/browse/trunk/src/proxies/FixedHandler.js > > > Just to make sure I do not misunderstand your work: > - Your code relies on current Proxy implementation behavior (FF4&5) > which doesn't do any check on the "configurable" attribute for > defineProperty and get{Own}PropertyDecsriptor traps > I didn't know that. Is there a bug filed on this yet or a test case that demonstrates this bug? > - The idea is that eventually, by default, any handler would become your > wrapped FixedHandler() handler (functionnally, of course; exact > implementation would be left at the discretion of implementors) > > In your current FixedHandler implementation, all traps of the wrapped > handler are called for configurable properties. For non-configurable > properties, if already present in this.fixedProps, the "delete", > "hasOwn", "has", "get" and "set" traps aren't called while all others > are (first instruction of all other traps). > This might appear to be an inconsistent behavior to the user. An easy > fix could be to change a little bit these traps: > ----- > 'delete': function(name) { > var ret = this.targetHandler['delete'](name); > // allows to throw with personalized message error rather than > default decided by the engine. > > if (name in this.fixedProps) { > throw new TypeError( > "property "+name+" is non-configurable and can't be deleted"); > } > > return ret; > }, > > hasOwn: function(name) { > var ret = this.targetHandler.hasOwn ? > this.targetHandler.hasOwn(name) : // call the trap in all > cases if present > TrapDefaults.hasOwn.call(this.targetHandler, name); > return name in this.fixedProps || ret; // always true if > non-configurable > }, > > has: function(name) { > var ret = this.targetHandler.has ? > this.targetHandler.has(name) : // call the trap in all > cases if present > TrapDefaults.has.call(this.targetHandler, name); > return name in this.fixedProps || ret; // always true if > non-configurable > }, > > get: function(rcvr, name) { > var ret = this.targetHandler.get ? > this.targetHandler.get(rcvr, name) : > TrapDefaults.get.call(this.targetHandler, rcvr, name); > > var desc = Object.getOwnPropertyDescriptor(this.fixedProps, name); > if (desc !== undefined) { > if ('value' in desc) { > return desc.value; > } else { > if (desc.get === undefined) { return undefined; } > return desc.get.call(rcvr); > } > } > > return ret; > }, > > set: function(rcvr, name, val) { > var ret = this.targetHandler.set ? > this.targetHandler.set(rcvr, name, val) : > TrapDefaults.set.call(this.targetHandler, rcvr, name, val); > > var desc = Object.getOwnPropertyDescriptor(this.fixedProps, name); > if (desc !== undefined) { > if ('writable' in desc) { // fixed data property > if (desc.writable) { > desc.value = val; > this.defineProperty(name, desc); > return true; > } else { > return false; > } > } else { // fixed accessor property > if (desc.set) { > desc.set.call(rcvr, val); > return true; > } else { > return false; > } > } > } > // simulate missing derived trap fall-back behavior > return ret; > }, > ----- > This way, all traps are called, regardless of configurability and the > invariant-complying result is returned in all cases. > When it comes to return value, my implementation may surprise the > programmer as what he return from his (target)handler doesn't match what > is returned in the end. An alternative could be to test if "ret" matches > expectations (with harmony:egal, not === of course) and throw if it's > not the case. > > Unless testing expectation matching, there is barely any overhead in > calling the traps (besides the trap themselves, but that's a cost the > programmer is ready to pay for configurable properties already) when > comparing with your implementation. > And it has the advantages of not leaking things the way I've showed it > at the beginning of this thread for the membrane use case. > > Thanks for the follow-up and the implementation. > > David > -- Cheers, --MarkM
_______________________________________________ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss