Bug 329982: Give nsXULElement::RemoveChildAt some lovin' to make it deal better with mutationevent handlers mutating the DOM

This commit is contained in:
cvshook@sicking.cc
2006-03-27 22:00:40 +00:00
parent e647b71d44
commit 4a9a362733
2 changed files with 34 additions and 48 deletions

View File

@@ -2371,7 +2371,9 @@ nsGenericElement::AppendChildTo(nsIContent* aKid, PRBool aNotify)
nsresult
nsGenericElement::RemoveChildAt(PRUint32 aIndex, PRBool aNotify)
{
nsCOMPtr<nsIContent> oldKid = GetChildAt(aIndex);
nsCOMPtr<nsIContent> oldKid = mAttrsAndChildren.GetSafeChildAt(aIndex);
NS_ASSERTION(oldKid == GetChildAt(aIndex), "Unexpected child in RemoveChildAt");
if (oldKid) {
return doRemoveChildAt(aIndex, aNotify, oldKid, this, GetCurrentDoc(),
mAttrsAndChildren);
@@ -2399,38 +2401,41 @@ nsGenericElement::doRemoveChildAt(PRUint32 aIndex, PRBool aNotify,
}
NS_PRECONDITION(aKid && aKid->GetParent() == aParent &&
aKid == container->GetChildAt(aIndex), "Bogus aKid");
aKid == container->GetChildAt(aIndex) &&
container->IndexOf(aKid) == aIndex, "Bogus aKid");
mozAutoDocUpdate updateBatch(aDocument, UPDATE_CONTENT_MODEL, aNotify);
PRBool hasListeners =
aParent &&
nsGenericElement::HasMutationListeners(aParent,
NS_EVENT_BITS_MUTATION_NODEREMOVED);
nsMutationGuard guard;
if (hasListeners) {
if (aParent && nsGenericElement::HasMutationListeners(aParent,
NS_EVENT_BITS_MUTATION_NODEREMOVED)) {
nsMutationEvent mutation(PR_TRUE, NS_MUTATION_NODEREMOVED);
mutation.mRelatedNode = do_QueryInterface(aParent);
nsEventDispatcher::Dispatch(aKid, nsnull, &mutation);
}
// Someone may have removed the kid while that event was processing...
if (!hasListeners ||
(aKid->GetParent() == aParent &&
aKid == container->GetChildAt(aIndex))) {
if (aParent) {
nsRange::OwnerChildRemoved(aParent, aIndex, aKid);
// Someone may have removed the kid or any of its siblings while that event
// was processing.
if (guard.Mutated(0)) {
aIndex = container->IndexOf(aKid);
if (aIndex < 0) {
return NS_OK;
}
aChildArray.RemoveChildAt(aIndex);
if (aNotify && aDocument) {
aDocument->ContentRemoved(aParent, aKid, aIndex);
}
aKid->UnbindFromTree();
}
if (aParent) {
nsRange::OwnerChildRemoved(aParent, aIndex, aKid);
}
aChildArray.RemoveChildAt(aIndex);
if (aNotify && aDocument) {
aDocument->ContentRemoved(aParent, aKid, aIndex);
}
aKid->UnbindFromTree();
return NS_OK;
}