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 - 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 _______________________________________________ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss