diff --git a/content/base/crashtests/565125-1.html b/content/base/crashtests/565125-1.html new file mode 100644 index 00000000000..ceeb923f4c8 --- /dev/null +++ b/content/base/crashtests/565125-1.html @@ -0,0 +1,27 @@ + + + + + + + diff --git a/content/base/crashtests/crashtests.list b/content/base/crashtests/crashtests.list index cfdd8eca1b0..26f9df43669 100644 --- a/content/base/crashtests/crashtests.list +++ b/content/base/crashtests/crashtests.list @@ -65,3 +65,4 @@ load 552651.html load 558973.html load 564079-1.html load 564114.html +load 565125-1.html diff --git a/content/base/src/nsAttrAndChildArray.cpp b/content/base/src/nsAttrAndChildArray.cpp index 2f956e2a3cc..3d6ffe4ffb4 100644 --- a/content/base/src/nsAttrAndChildArray.cpp +++ b/content/base/src/nsAttrAndChildArray.cpp @@ -666,6 +666,18 @@ nsAttrAndChildArray::Clear() // making this PR_FALSE so tree teardown doesn't end up being // O(N*D) (number of nodes times average depth of tree). child->UnbindFromTree(PR_FALSE); // XXX is it better to let the owner do this? + // Make sure to unlink our kids from each other, since someone + // else could stil be holding references to some of them. + + // XXXbz We probably can't push this assignment down into the |aNullParent| + // case of UnbindFromTree because we still need the assignment in + // RemoveChildAt. In particular, ContentRemoved fires between + // RemoveChildAt and UnbindFromTree, and in ContentRemoved the sibling + // chain needs to be correct. Though maybe we could set the prev and next + // to point to each other but keep the kid being removed pointing to them + // through ContentRemoved so consumers can find where it used to be in the + // list? + child->mPreviousSibling = child->mNextSibling = nsnull; NS_RELEASE(child); }