Hi,

I spent a couple of hours presenting proxies to a couple of folks at the IDRC (Inclusive Design Research Center) in Toronto and Colin Clark (IDRC Tech Lead) made me realize that we have lost something between the previous proxy design and the current one. This is related to the caretaker and membrane patterns and garbage collection.

    // With the previous proxy design:
    var handler = {
        get: function(){
            something(target)
        },
        set: function(){
            somethingElse(target)
        },
        target : {};
    }
    function revoke(){
        handler.target = null;
    }

On calling the revoke method, access to the target will cause error to be thrown when the proxy is touched. Additionally, if this was the only reference to the target, the target can be garbage collected. This scales also for a membrane where revoke can lead to the garbage collection of an arbitrary number of objects.

With the current design, there is no way to cut the access to the target and enable its garbage collection because the target is an internal property of the proxy. It means that malicious or buggy code keeping a reference to the proxy keeps a reference to the target.

As a matter of fact, I've recently had this problem of a library keeping references to a large files and ending up crashing the (node.js) process because of memory overflow. Having the ability to cut the reference would likely allow to garbage collect the content and solve the problem. I should mention also the "Huey fix" [1][2] which is a real-world use of the caretaker pattern used for the sake of memory consumption.

Proposals (first shot at least):
* A Proxy.revokeTarget(proxy) & corresponding revokeTarget trap (returns a boolean to decide whether to procede or not). After the access to the target has been revoked, any attempt to touch the proxy throws an exception without trapping (very much like transferable objects when they've been transfered IIRC). If no revokeTarget trap is provided, the target is not revoked (return false by default).
Called on a non-proxy object, Proxy.revokeTarget does nothing.
Of course, if someone else holds a reference to the target, it is not garbage-collected no matter how many proxies have been revoked access to it. * Alternatively, the proxy constructor returns a pair so that only the proxy creator has access to the revoke method (removes the need for the trap). But it induces boilerplate when you don't care about revokability. * Alternatively, having 2 constructors, Proxy and RevokableProxy. The former is the one for current direct proxies, the latter returns a pair as described in the second proposal.

David

[1] http://blog.kylehuey.com/post/21892343371/fixing-the-memory-leak
[2] https://blog.mozilla.org/nnethercote/2012/05/15/additional-update-on-leaky-add-ons/
_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to