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