I'm having some kind of memory problem in my javascript code. I've been searching online for memory leak patterns in javascript, but none of the patterns seem to apply to my code. It's very simple code, there are no closures, I don't even have internal functions, all my variables merely hold simple values, like DOM objects or booleans, I don't even define properties in my variables. But yet somehow I manage to leak so much memory that Firefox (3.6.11) freezes and IE tells me I'm running out of memory at line 73, I've marked that line. The functions to which there are references in the DOM tree are toggle, replyForm and replyExpand.
<script type="text/javascript">
function toggle(expandable){
if(expandable.parentNode.getElementsByTagName("ul")[0].className=="hide"){
expandable.parentNode.getElementsByTagName("ul")[0].className="show";
expandable.innerHTML="▼";
}
else{
expandable.parentNode.getElementsByTagName("ul")[0].className="hide";
expandable.innerHTML="►";
}
}
var previousSpan;
function replyForm(span,postId,op,commentID){
if(removeForm(span))
return;
previousSpan=span;
if(span.nextSibling!=null){
span.parentNode.insertBefore(form(span,postId,op,commentID),span.nextSibling);
}
else{
span.parentNode.appendChild(form(span,postId,op,commentID));
}
}
function removeForm(span){
if(previousSpan==null)
return false; <-- Out of memory here according to IE
if(previousSpan.parentNode.getElementsByTagName("form").length!=0)
previousSpan.parentNode.removeChild(span.parentNode.getElementsByTagName("form")[0]);
var result=(span==previousSpan);
if(result)
collapse(previousSpan);
previousSpan=null;
return result;
}
function form(span,postId,op,commentID){
var result=
"<form id=\"commentform\" method=\"post\" action=\"http://innategamer.300mb.us/wp-comments-post.php\">\n"+
"<p>Replying to "+op+":</p>\n"+
"<p><label for=\"author\">Name *</label><input id=\"author\" type=\"text\" aria-required=\"true\" size=\"30\" value=\"\" name=\"author\"></p>\n"+
"<p>Email *<input id=\"email\" type=\"text\" aria-required=\"true\" size=\"30\" value=\"\" name=\"email\"></p>\n"+
"<p>Website<input id=\"url\" type=\"text\" size=\"30\" value=\"\" name=\"url\"></p>\n"+
"<textarea id=\"comment\" aria-required=\"true\" rows=\"8\" cols=\"45\" name=\"comment\"></textarea>\n"+
"<input id=\"submit\" type=\"submit\" value=\"Post Comment\" name=\"submit\">\n"+
"<input id=\"comment_post_ID\" type=\"hidden\" value=\""+postId+"\" name=\"comment_post_ID\">\n"+
"<input id=\"comment_parent\" type=\"hidden\" value=\""+commentID+"\" name=\"comment_parent\">\n"+
"</form>";
var div=document.createElement('div');
div.innerHTML=result;
return div.firstChild;
}
function replyExpand(span){
if(span.innerHTML.indexOf("▼")!=-1)
collapse(span);
else
expand(span);
}
function collapse(span){
if(previousSpan==span)
开发者_JAVA百科 removeForm(span);
span.innerHTML=span.innerHTML.replace("▼","►");
while(span.nextSibling!=null){
span=span.nextSibling;
if(span.className=="comment-content show");
span.className="comment-content hide";
}
}
function expand(span){
span.innerHTML=span.innerHTML.replace("►","▼");
while(span.nextSibling!=null){
span=span.nextSibling;
if(span.className=="comment-content hide");
span.className="comment-content show";
}
}
</script>
I'd imagine it has something to do with the fact that these two functions call each other, and as a far as I can tell, the if
statements, once true, will always be true.
function removeForm(span) {
if (previousSpan == null) return false; < --Out of memory here according to IE
if (previousSpan.parentNode.getElementsByTagName("form").length != 0)
previousSpan.parentNode.removeChild(span.parentNode.getElementsByTagName("form")[0]);
var result = (span == previousSpan);
if (result) collapse(previousSpan); // <---------------
previousSpan = null; // |
return result; // |
} // |
// |
function collapse(span) { // |
if (previousSpan == span) removeForm(span); // <--------
span.innerHTML = span.innerHTML.replace("▼", "►");
while (span.nextSibling != null) {
span = span.nextSibling;
if (span.className == "comment-content show");
span.className = "comment-content hide";
}
}
Effectively:
var previousSpan;
function removeForm( span ) {
// ...
if( span == previousSpan ) collapse(previousSpan);
// ...
}
function collapse( span ) { // <---here span is previousSpan,
// <-- always true because you're doing if(previousSpan == previousSpan)
if (previousSpan == span) removeForm(span);
// ...
}
// This makes subsequent comparisons in "removeForm()" always true as well,
// because now it is guaranteed that "span" is the same as "previousSpan"
So once span == previousSpan
in removeForm()
, you're passing previousSpan
to collapse()
. The first thing collapse()
does is checks to see if what it received is equal to previousSpan
, which it always will be since that was the test to send it in the first place.
Looks like you have an infinite loop going on in there.
removeForm
calls collapse
collapse
calls removeForm
I'm not going to take the time to go over this with a fine tooth comb. But I do see removeForm
calls collapse
, which sometimes in turn calls removeForm
. The first thing I'm suspicious of is that these two functions are somehow calling each other in an infinite recursion pattern.
Please try putting break points at the beginning of one of these functions.
In your debugger, check the size of the call stack each time you hit a this break point. If the call stack expands until the program runs out of memory, then congratulations, you have just posted a real Stack Overflow on StackOverflow!
精彩评论