Weak event listener

David Bruant bruant.d at gmail.com
Wed Apr 3 11:20:08 PDT 2013


Le 03/04/2013 11:13, Marius Gundersen a écrit :
> > "A core part of the problem here is that the distinction between an 
> 'important' reference - one that must keep an object alive - and an 
> 'incidental' reference, that only need exist as long as it target does"...
>
> This is a concept which cannot be expressed in JavaScript today, but 
> which most code actually needs to hint at in some way. Most objects 
> are owned by one other object, and known by many other objects. The 
> objects which knows of it shouldn't keep it alive, only the owner 
> should. It is impossible to distinguish between these two cases in 
> JavaScript today.
It is possible to make /a/ distinction with proxies. More specifically, 
with revocable proxies [1]

     let { proxy, revoke } = Proxy.revocable(target, handler);
     proxy.foo // traps
     revoke()
     proxy.foo // throws TypeError: "proxy is revoked"

Let's create a small abstraction on top of that:

     function RevocableRef(target){
         var transparentHandler = {};
         return Proxy.revocable(target, transparentHandler);
     }

You can keep the original target and the revoke function to yourself and 
decide only to share RevocableRefs of the object (which is pretty much 
the equivalent of wrapping with the WeakRef constructor).
When you don't want others to access the object anymore, just call the 
revoke function.

It is one way to make a distinction between different references to the 
same object and keep control of who has access to which object at what time.

> An example of this would be a GUI with event listening widgets, which 
> is usually a tree where each widget is owned by its parent, and a 
> widget without a parent should stop listening to events. There are 
> many ways to implement this without WeakRefs, usually involving an 
> explicit _parent_ field and a dispose method when a widget is removed. 
> But with WeakRefs this could be implemented so only the parent has a 
> strong reference to the children, everyone else has weak references 
> and so the widget (and all its children) are garbage collected and 
> stop listening to events when the parent deletes it.
In that case, it seems that only the parent would keep a strong 
reference to a child widget and hand over a RevocableRef to other 
parties. When detaching the child widget, the parent would just need to 
call the revoke function.
I admit this is more work than just detaching the child, but it is not a 
huge amount (calling one function). More interestingly, all the control 
of references remains at the parent level, that is, the parent decides 
which type of reference is shared (a revocable one or not); no need for 
third-parties to comply to a "dispose protocol", where different parties 
have to dispose, sometimes recursively which can be a mess.

The idea of being able to differentiate references is interesting, but 
doesn't seem to justify the non-determinism that comes with WeakRefs. It 
sounds that what we already have (revokable proxies and the RevocableRef 
abstraction above) would be enough in the use case you described (and 
Kevin's use case too from what I understand).
If I misunderstood any of your (Kevin and Marius) use cases, could you 
explain what would be the added value of WeakRefs over revokable proxies.

Do languages which added WeakRefs have a form of revokable reference 
too? What difference would it make?

David

[1] http://wiki.ecmascript.org/doku.php?id=strawman:revokable_proxies


More information about the es-discuss mailing list