blueslip: Use reference counting to try and break the circular references we create

We create a circular reference between handler functions and our
wrappers for them so that we can pass the wrapper to jQuery.off when
users pass the original handler to us.  This reference-counting
system can't break all the circular references we create because
users can unbind event handlers without explicitly naming the
handlers they want to remove (they can remove all bindings on an
element, for example).  For now, we hope that this memory leak isn't
too bad.

(imported from commit 9615b5761b4b09ca7ca52c0d847e9b83330373fa)
This commit is contained in:
Zev Benjamin 2013-03-14 14:16:03 -04:00
parent e8470b9481
commit 719e24a25b
1 changed files with 20 additions and 0 deletions

View File

@ -80,6 +80,10 @@ BlueslipError.prototype = Error.prototype;
// through blueslip.
(function() {
function wrap_callback(func) {
if (func.blueslip_wrapper !== undefined) {
func.blueslip_wrapper_refcnt++;
return func.blueslip_wrapper;
}
var new_func = function blueslip_wrapper() {
if (debug_mode) {
return func.apply(this, arguments);
@ -101,9 +105,24 @@ BlueslipError.prototype = Error.prototype;
}
};
func.blueslip_wrapper = new_func;
func.blueslip_wrapper_refcnt = 1;
return new_func;
}
// This reference counting scheme can't break all the circular
// references we create because users can remove jQuery event
// handlers without referencing the particular handler they want
// to remove. We just hope this memory leak won't be too bad.
function dec_wrapper_refcnt(func) {
if (func.blueslip_wrapper_refcnt !== undefined) {
func.blueslip_wrapper_refcnt--;
if (func.blueslip_wrapper_refcnt === 0) {
delete func.blueslip_wrapper;
delete func.blueslip_wrapper_refcnt;
}
}
}
$.ajaxPrefilter(function (options) {
$.each(['success', 'error', 'complete'], function (idx, cb_name) {
if (options[cb_name] !== undefined) {
@ -187,6 +206,7 @@ BlueslipError.prototype = Error.prototype;
if (fn) {
var wrapper = fn.blueslip_wrapper;
if (wrapper !== undefined) {
dec_wrapper_refcnt(fn);
fn = wrapper;
}
}