Notification proxies (Was: possible excessive proxy invariants for Object.keys/etc??)
allen at wirfs-brock.com
Sun Nov 25 13:16:55 PST 2012
On Nov 25, 2012, at 3:44 AM, Tom Van Cutsem wrote:
> I will refer to Dean's proposal as "notification proxies" (where traps essentially become notification callbacks), and will continue to use "direct proxies" for the current design where the trap can return a result (which is then verified).
I agree with Mark that Dean has a quite clever proposal...
> However, some reservations:
me too...although I think notification proxies are optimized for a real use case and might be worth supporting.
> - if traps become mere notifications, perhaps their names should change to reflect this, e.g. "notifyGetOwnPropertyNames" instead of "getOwnPropertyNames". This is to alert handler writers that the return value of these traps will be ignored.
> - I think we do lose some expressiveness in the case of pure virtual object abstractions that don't pretend to uphold any invariants.
> In other words: *all* virtual object abstractions, whether they pretend to be frozen or not, have to make use of the "shadow target" technique, with the burden of synchronizing the shadow upon each operation. That burden currently doesn't exist for non-frozen virtual object abstractions (I'm using "frozen" vs "non-frozen" here as a shorthand for "has non-configurable/non-extensible invariants" vs "has no such invariants").
I have a couple "virtual object" use cases in mind where I don't think I would want to make all properties concrete on the target.
1) A bit vector abstraction where individual bits are accessible as numerically indexed properties.
Assume I have a bit string of fairly large size (as little as 128 bits) and I would like to abstract it as an array of single bit numbers where the indexes correspond to bit positions in the bit string. Using Proxies I want be able to use Get and Put traps to direct such indexed access to a binary data backing store I maintain. I believe that having to reify on the target each bit that is actually accessed would be too expensive in both time and space to justify using this approach.
BTW, this is a scenario where I might not even brother trying to make sure that Object.getOwnPropertyNames listed all of the bit indexes. I could, include them in an array of own property names, but would anybody really care if I didn't?
2) Multiple Inheritance
I'm playing with what it takes to support self-like multiple inheritance using proxies. One approach that looks promising is to use a Proxy-based object as the immediate [[Prototype]] of leaf objects that have multiple logical inheritance parents. That lets put/gets of own property operate at native speed and the Put/Get handlers only get invoked for inherited properties. The MI parent proxy keeps track (using its own private state) of the multiple parents and doesn't really use it own [[Prototype]] ( actually it's target object's [[Prototype]]) as a lookup path for proto climbing. It encapsulates this entire mechanism such that from the perspective of the leaf object, all of its inherited properties look like own properties of the MI parent proxy. I would hate to have to "copy down" every accessed inherited property. There are situations were I might want to copy down some of them, but probably not all.
> I think the storage costs are largely the same. However, with notification proxies, if the properties were "virtual", those properties do linger as "concrete" properties on the target. Yes, the handler can delete them later, but when is later? Should the handler schedule clean-up actions using setTimeout(0)? This somehow does not feel right.
Yes indeed. Storage cost may be comparable for getOwnProperyNames that that is presumably a rare operation. If all traps had that characteristic I think many "virtual object" use cases would be too expensive to make the practical.
> I like the simplicity of notification proxies, but we should think carefully what operations we turn into notifications only.
Yes, I also like the simplicity of notification proxies but don't want to give up the power of virtual objects. Maybe having both would be a reasonable alternative.
> 2012/11/25 Mark S. Miller <erights at google.com>
> +1. I think this is a really effective extension of the direct proxy
> approach, and I don't know why we didn't see it earlier. It's weird
> that this preserves all the flexibility of fully virtual configurable
> properties even though it insists that even these be made into real
> properties on the target. The trick is that placing a configurable
> property on the target doesn't commit the handler to anything, since
> the handler can remove or change this property freely as of the next
> Apologies again for not yet having the time to do more than skim the
> thread at this point. But IIRC someone already suggested a similar
> change to some of the imperative traps -- perhaps freeze, seal, and
> preventExtensions. The handler would not perform these operations on
> the target, only to have the proxy check it. Rather, if the trap
> indicates that the operation should succeed, the proxy then simply
> performs the operation -- or else throws. I wonder if this philosophy
> could be extended to some of the other imperative operations as well?
> What expressiveness does this even-more-direct proxy approach lose?
> AFAICT, not much. At the same time, it should result in a *much*
> simpler implementation and much greater confidence that invariants of
> the non-proxy sublanguage are preserved by the introduction of
> proxies. In fact, I think it's much stronger on invariant preservation
> that the current direct proxies, while being much simpler.
> On Sat, Nov 24, 2012 at 6:49 PM, Dean Tribble <dtribble at gmail.com> wrote:
> > issues below. You could extend the the "direct proxy" approach for this.
> > When the Proxy receives getOwnPropertyNames, it
> > 1) notifies the handler that property names are being requested
> > 2) the handler adds/removes any properties (configurable or otherwise
> > subject to the normal constraints) on the target
> > 3) upon return, the proxy invokes getOwnPropertyNames directly on the target
> > (e..g, invoking the normal system primitive)
> > This approach appears to have consistent behavior for configurability and
> > extensibility. For example, the trap operation above could add configurable
> > properties to an extensible target, and remove them later. It could add
> > non-configurable properties, but they are permanent once added, etc. Thus
> > there's no loss of generality. In addition to optionally setting up
> > properties on the target, the handler trap above would need to indicate to
> > the proxy (via exception or boolean result) that the getOwnPropertyNames
> > operation should proceed ahead or fail.
> > This extension of the "direct proxy" approach applies to all query
> > operations, eliminates the copying and validation overhead discussed below,
> > simplifies the implementation, retains full backwards compatibility, and
> > enables most if not all the expressiveness we might expect for proxies.
> > Dean
> es-discuss mailing list
> es-discuss at mozilla.org
-------------- next part --------------
An HTML attachment was scrubbed...
More information about the es-discuss