jQuery memory leak with DOM removal

Viewed 40631

Here's a dead-simple webpage that leaks memory in IE8 using jQuery (I detect memory leaks by watching the memory usage of my iexplore.exe process grow over time in the Windows Task Manager):

<html>
<head>
    <title>Test Page</title>
    <script type="text/javascript" src="jquery.js"></script>
</head>
<body>
<script type="text/javascript">
    function resetContent() {
        $("#content div").remove();
        for(var i=0; i<10000; i++) {
            $("#content").append("<div>Hello World!</div>");
        }
        setTimeout(resetTable, 2000);
    }
    $(resetContent);
</script>
<div id="content"></div>
</body>
</html>

Apparently even when calling the jQuery.remove() function I still experience some memory leakage. I can write my own remove function that experiences no memory leak as follows:

$.fn.removeWithoutLeaking = function() {
    this.each(function(i,e){
        if( e.parentNode )
            e.parentNode.removeChild(e);
    });
};

This works just fine and doesn't leak any memory. So why does jQuery leak memory? I created another remove function based on jQuery.remove() and this does indeed cause a leak:

$.fn.removeWithLeakage = function() {
    this.each(function(i,e) {
        $("*", e).add([e]).each(function(){
            $.event.remove(this);
            $.removeData(this);
        });
        if (e.parentNode)
            e.parentNode.removeChild(e);
    });
};

Interestingly, the memory leak seems to be caused by the each call which jQuery includes to prevent memory leaks from events and data associated with the DOM elements being deleted. When I call the removeWithoutLeaking function then my memory stays constant over time, but when I call removeWithLeakage instead then it just keeps growing.

My question is, what about that each call

$("*", e).add([e]).each(function(){
    $.event.remove(this);
    $.removeData(this);
});

could possibly be causing the memory leak?

EDIT: Fixed typo in code which, upon retesting, proved to have no effect on the results.

FURTHER EDIT: I have filed a bug report with the jQuery project, since this does seem to be a jQuery bug: http://dev.jquery.com/ticket/5285

6 Answers
Related