atom feed22 messages in com.googlegroups.jquery-en[jQuery] Memory leaks forever
FromSent OnAttachments
Franck MarciaMar 25, 2006 7:13 am 
Dave MethvinMar 25, 2006 8:55 am 
Franck MarciaMar 25, 2006 9:08 am 
John ResigMar 25, 2006 9:15 am 
Dave MethvinMar 25, 2006 10:07 am 
Michael GearyMar 25, 2006 10:07 am 
Franck MarciaMar 25, 2006 10:39 am 
Michael GearyMar 25, 2006 10:56 am 
Dave MethvinMar 25, 2006 11:05 am 
Franck MarciaMar 25, 2006 1:45 pm 
Michael GearyMar 25, 2006 2:19 pm 
Franck MarciaMar 25, 2006 5:16 pm 
Dave MethvinMar 26, 2006 9:02 am 
Michael GearyMar 26, 2006 1:24 pm 
Franck MarciaMar 28, 2006 2:25 am 
Dave MethvinMar 28, 2006 5:45 am 
John ResigMar 28, 2006 7:30 am 
Franck MarciaMar 28, 2006 8:26 am 
jqu...@vikas.mailshell.comMar 28, 2006 8:57 am 
John ResigMar 28, 2006 9:03 am 
Michael GearyMar 28, 2006 9:14 am 
jqu...@vikas.mailshell.comMar 28, 2006 9:24 am 
Subject:[jQuery] Memory leaks forever
From:Michael Geary (M.@Geary.com)
Date:Mar 25, 2006 2:19:45 pm
List:com.googlegroups.jquery-en

From: Dave Methvin

Mike, so the goal of $.closure is to put all event handlers in the window object so that they will be properly cleaned up when the page is unloaded?

Not exactly. It removes the circular reference by breaking the closure chain and substituting a different closure that doesn't chain through the DOM. You can see this in action by commenting out this line:

// Clear references to keep them out of the closure scope obj = fun = null;

For the closure leak pattern that this code addresses, the leak will return when you comment out that line.

It seems like that wouldn't help the leaks with elements removed while the page is running, unless empty() and the others also remove events.

I think it should handle those; once the closure chain is broken the circular reference is gone, so when you delete the element it should get cleaned up OK. $.closure does keep a table of closures that it doesn't clean up, but when you leave the page that should also get cleaned up.

I have to admit, this stuff about leaks is seriously confusing me. There seems to be a lot of bad or ambiguous information about the IE memory leak problem. Doug Crockford says that Microsoft's document generally blaming closures is wrong--although closures *can* cause leaks--and the Microsoft article you mentioned earlier seems to make non-standard (non-sensical?) use of document.createElement.

It's not so much that they are blaming closures, but that closures are an easy way to get a circular JS-DOM reference without realizing it.

The "interesting" document.createElement calls in the document don't really have anything to do with the leak. The same thing would happen if you create the element with a standard createElement call, then attach an event to it, then attach the element to the DOM.

I'm not clear on if and when these memory leaks resolve themselves, for example whether they go away when you navigate off a page.

They don't. That's why they are so nasty.

From some of the info I thought they persisted across pages and/or reloads, but I tried writing the simplest possible sample code (not JQuery but raw DOM calls with attached events) and I don't see any repeatable leakage pattern that way.

If you'd like to show me your code, I can probably get it to leak. I seem to be better at that than I wish I were! :-) Or I can probably tell you why it doesn't leak. Or maybe not... I'm learning this as I go along, just like you.

For example, doesn't jquery-dom.js have the potential to leak as well? The Insertion Order Leak that Microsoft describes says that nodes should be inserted from the top down rather than the bottom up. If you were to attach an event handler in a $.DIV call and nest that in another $.DIV call then that seems like it would leak.

The DOM Insertion Order leak occurs when you attach an event handler to a node that is not yet part of the DOM tree. If you are just creating DOM nodes, and you wait to attach any event handlers until *after* you've inserted the nodes into the DOM, then you are OK.

This doesn't leak:

$().append( $.DIV({}, $.SPAN({}, 'test' ) ) );

Nor does this:

var div = $.DIV({}); $().append(div); $(div).click( function() { alert('howdy'); } );

But this does:

var div = $.DIV({}); $(div).click( function() { alert('howdy'); } ); $().append(div);

-Mike