> (reposting source code from previous message as plain text)
>
> fix: function() {
> // As long as target is not frozen, the proxy won't allow itself
> to be fixed
> if (!Object.isFrozen(this.target))
> return undefined;
> var props = {};
> var handler = this;
> Object.getOwnPropertyNames(this.target).forEach(function (name) {
> var desc = Object.getOwnPropertyDescriptor(this.target, name);
> // turn descriptor into a trapping accessor property
> props[name] = {
> get: function( ) { return handler.get(this, name); },
> set: function(v) { return handler.set(this, name, v); },
> enumerable: desc.enumerable,
> configurable: desc.configurable
> };
> });
> return props;
> },
I really love this.
The Object.isFrozen call is unfortunate but necessary since we only have
one trap for the three extension-preventing methods. Throwing a
TypeError on Object.preventExtension(proxy) because the target isn't
frozen sounds a bit wrong to me though. Maybe that something could be
passed as an argument to fix in order to discriminate which call happened.
>From what I understand, all interaction that set [[Extensible]] to false
will end up calling the fix trap (+ TypeError||become) for proxies. As
we can't know now what will later be added to the language to do that,
it may be a good thing to be able to discriminate the origin of the fix
trap call.
Also, an idea for so-called "forwarding" proxies could be that the proxy
forwards preventExtension/seal/freeze calls to the target too. It could
be a nice thing if target is itself a proxy.
Combining the ideas, we could have something like:
fix: function(type){
if (type === Proxy.PREVENT_EXTENSION) // syntax example
Object.preventExtension(this.target);
// a switch case could be a good idea too
// same code than you starting at "var props"
}
Even if not forwarding the call, it could allow better granularity than
Object.isFrozen.
Now that I think about it, if forwarding Object.seal/freeze calls, the
target and previously-proxy would act the same with very few exception.
The non-configurability of all properties ensure that both keep the
exact same property set will remain (non-deletable) with same
[[enumerable]] for each (non-configurable). Your get/set method ensure
that property access react the same in both objects. Besides
Object.getOwnPropertyDescriptor and their identity, I can't think of any
way to distinguish them.
David
>
> 2011/4/5 Tom Van Cutsem <tomvc.be <http://tomvc.be>@gmail.com
> <http://gmail.com>>
>
>
>
> 2011/3/24 Tom Van Cutsem <tomvc.be <http://tomvc.be>@gmail.com
> <http://gmail.com>>
>
> I just wanted to discuss forwarding patterns when it comes
> to inheritance because the current forwarding proxy
> doesn't discuss the point and when it comes to fixing the
> proxy, surprising results could arise (since inheritance
> changes because target and proxy prototypes aren't the
> same object). Actually, if forwarding handlers were part
> of the spec, would it make sense to fix them? shouldn't
> "return undefined;" be the default fix trap?
>
> (http://wiki.ecmascript.org/doku.php?id=harmony:proxy_defaulthandler)
> (just the default, of course, the user can change it anytime)
>
>
> "return undefined;" is definitely a sensible default. The
> current default goes a bit further: if the target object is
> frozen, it will fix the forwarding proxy in such a way that
> the proxy and the target have the exact same own properties. I
> don't recall us giving much thought to this default
> implementation though. In fact, I think it's broken since it
> doesn't take into account any custom proxying behavior. As an
> example: say I implement a "logging" proxy that just logs all
> operations performed on "target". It's sensible to extend the
> default forwarding handler to do this. Now, if both the target
> and the proxy are frozen, the logging behavior will be lost!
> The solution is for my logging proxy to override the fix()
> trap and perhaps return a property descriptor map that
> replaces each own property in target with a wrapped version
> that still performs the logging. If fix() returns "undefined"
> by default, the above scenario would lead to an exception
> instead of silently doing the wrong thing.
>
>
> I've been thinking about the default implementation of the |fix()|
> trap. Another sensible default, other than just returning
> undefined unconditionally, is to freeze the proxy's structure, but
> to replace all original properties with accessor properties that
> still trigger the proxy's handler. A fixed forwarding proxy can
> then still intercept property access, but other than its get and
> set traps, none of its other traps would be called anymore:
>
> fix:function(){
> // As long as target is not frozen, the proxy won't allow
> itself to be fixed
> if(!Object.isFrozen(this.target))
> returnundefined;
> varprops ={};
> varhandler =this;
> Object.getOwnPropertyNames(this.target).forEach(function(name){
> vardesc =Object.getOwnPropertyDescriptor(this.target,name);
> // turn descriptor into a trapping accessor property
> props[name]={
> get:function(){returnhandler.get(this,name);},
> set:function(v){returnhandler.set(this,name,v);},
> enumerable:desc.enumerable,
> configurable:desc.configurable
> };
> });
> returnprops;
> },
>
>
> (full forwarding handler available at
>
> <http://code.google.com/p/es-lab/source/browse/trunk/src/proxies/forwardingHandler.js>)
>
> (untested because fix() isn't yet supported in fx4, see
> <https://bugzilla.mozilla.org/show_bug.cgi?id=600677>)
>
> Cheers,
> Tom
>
>
_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss