First, I carefully and thoroughly studied this issue. There is already a ticket with jquery UI that I am following. And I know the way around this error, but I am very curious why this is happening. I believe the error is related to closing, but my javascript-fu is not an expert.
I believe the jquery UI team has better options than wasting energy on IE6 error. So I wanted to bring this to the general public of javascript.
The following is a test case:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>jquery ui memory leak test</title> <script type="text/javascript" src="jquery-1.5.js"></script> <script type="text/javascript" src="jquery.ui.widget.js"></script> <script type="text/javascript"> (function($) { $.widget("ui.test", { _create: function() { } }); $(document).ready(function() { for (var i = 0; i < 1; i++) { $("#container").append("<div id='inner'></div>"); $("#inner").test(); $("#inner").test("destroy"); $("#container").empty(); }; }); })(jQuery); </script> </head> <body> <div id="container"> </div> </body> </html>
I tested all combinations of jquery 1.4.4 and 1.5 and jquery-ui-1.8.9 and jquery-ui master (from the moment of writing), but they all give the same result.
My test widget, I think, is the easiest you can get.
If you test with sIEve , you might find a leak. Otherwise, increase the counter to about 1000, and you will see that increasing the memory is quite easy. There is another tool from Microsoft that you can also use to detect leaks.
Thus, the leak is associated with the binding of a custom event in the _createWidget widget _createWidget :
var self = this; this.element.bind( "remove." + this.widgetName, function() { self.destroy(); });
So, if I comment on this, there will be no leak. I use 1.8.9, not master, as the 1.8.8 code seems simpler (the wizard has changed a bit).
Now, if I even bind the same event outside the widget, there is no leak either. For example, after creating the widget, I have to insert the following code, but before destroying it:
$("#inner").bind("remove.test", function() {});
I purposefully added a no-op function, but it doesn't matter what's inside the callback function. You could argue, since after that I destroy manually, no binding is required. But this is not the point.
So my question is: why does the source code, the call of the binding from the widget code, flow? I suspect this is due to the closure, but I cannot explain it.
Can someone explain this?