diff --git a/dom/base/nsNodeUtils.cpp b/dom/base/nsNodeUtils.cpp index dc11f23015a5..d9fb1704232d 100644 --- a/dom/base/nsNodeUtils.cpp +++ b/dom/base/nsNodeUtils.cpp @@ -42,40 +42,51 @@ using namespace mozilla; using namespace mozilla::dom; using mozilla::AutoJSContext; +enum class IsRemoveNotification +{ + Yes, + No, +}; + // This macro expects the ownerDocument of content_ to be in scope as // |nsIDocument* doc| -#define IMPL_MUTATION_NOTIFICATION(func_, content_, params_) \ - PR_BEGIN_MACRO \ - bool needsEnterLeave = doc->MayHaveDOMMutationObservers(); \ - if (needsEnterLeave) { \ - nsDOMMutationObserver::EnterMutationHandling(); \ - } \ - nsINode* node = content_; \ - NS_ASSERTION(node->OwnerDoc() == doc, "Bogus document"); \ - doc->BindingManager()->func_ params_; \ - nsINode* last; \ - do { \ - nsINode::nsSlots* slots = node->GetExistingSlots(); \ - if (slots && !slots->mMutationObservers.IsEmpty()) { \ - NS_OBSERVER_AUTO_ARRAY_NOTIFY_OBSERVERS( \ - slots->mMutationObservers, nsIMutationObserver, 1, \ - func_, params_); \ - } \ - last = node; \ - if (ShadowRoot* shadow = ShadowRoot::FromNode(node)) { \ - node = shadow->GetHost(); \ - } else { \ - node = node->GetParentNode(); \ - } \ - } while (node); \ - if (last == doc) { \ - if (nsIPresShell* shell = doc->GetObservingShell()) { \ - shell->func_ params_; \ - } \ - } \ - if (needsEnterLeave) { \ - nsDOMMutationObserver::LeaveMutationHandling(); \ - } \ +#define IMPL_MUTATION_NOTIFICATION(func_, content_, params_, remove_) \ + PR_BEGIN_MACRO \ + bool needsEnterLeave = doc->MayHaveDOMMutationObservers(); \ + if (needsEnterLeave) { \ + nsDOMMutationObserver::EnterMutationHandling(); \ + } \ + nsINode* node = content_; \ + NS_ASSERTION(node->OwnerDoc() == doc, "Bogus document"); \ + if (remove_ == IsRemoveNotification::Yes && node->GetComposedDoc()) { \ + if (nsIPresShell* shell = doc->GetObservingShell()) { \ + shell->func_ params_; \ + } \ + } \ + doc->BindingManager()->func_ params_; \ + nsINode* last; \ + do { \ + nsINode::nsSlots* slots = node->GetExistingSlots(); \ + if (slots && !slots->mMutationObservers.IsEmpty()) { \ + NS_OBSERVER_AUTO_ARRAY_NOTIFY_OBSERVERS( \ + slots->mMutationObservers, nsIMutationObserver, 1, \ + func_, params_); \ + } \ + last = node; \ + if (ShadowRoot* shadow = ShadowRoot::FromNode(node)) { \ + node = shadow->GetHost(); \ + } else { \ + node = node->GetParentNode(); \ + } \ + } while (node); \ + if (remove_ == IsRemoveNotification::No && last == doc) { \ + if (nsIPresShell* shell = doc->GetObservingShell()) { \ + shell->func_ params_; \ + } \ + } \ + if (needsEnterLeave) { \ + nsDOMMutationObserver::LeaveMutationHandling(); \ + } \ PR_END_MACRO #define IMPL_ANIMATION_NOTIFICATION(func_, content_, params_) \ @@ -110,7 +121,7 @@ nsNodeUtils::CharacterDataWillChange(nsIContent* aContent, { nsIDocument* doc = aContent->OwnerDoc(); IMPL_MUTATION_NOTIFICATION(CharacterDataWillChange, aContent, - (doc, aContent, aInfo)); + (doc, aContent, aInfo), IsRemoveNotification::No); } void @@ -119,7 +130,7 @@ nsNodeUtils::CharacterDataChanged(nsIContent* aContent, { nsIDocument* doc = aContent->OwnerDoc(); IMPL_MUTATION_NOTIFICATION(CharacterDataChanged, aContent, - (doc, aContent, aInfo)); + (doc, aContent, aInfo), IsRemoveNotification::No); } void @@ -132,7 +143,7 @@ nsNodeUtils::AttributeWillChange(Element* aElement, nsIDocument* doc = aElement->OwnerDoc(); IMPL_MUTATION_NOTIFICATION(AttributeWillChange, aElement, (doc, aElement, aNameSpaceID, aAttribute, - aModType, aNewValue)); + aModType, aNewValue), IsRemoveNotification::No); } void @@ -145,7 +156,7 @@ nsNodeUtils::AttributeChanged(Element* aElement, nsIDocument* doc = aElement->OwnerDoc(); IMPL_MUTATION_NOTIFICATION(AttributeChanged, aElement, (doc, aElement, aNameSpaceID, aAttribute, - aModType, aOldValue)); + aModType, aOldValue), IsRemoveNotification::No); } void @@ -155,7 +166,8 @@ nsNodeUtils::AttributeSetToCurrentValue(Element* aElement, { nsIDocument* doc = aElement->OwnerDoc(); IMPL_MUTATION_NOTIFICATION(AttributeSetToCurrentValue, aElement, - (doc, aElement, aNameSpaceID, aAttribute)); + (doc, aElement, aNameSpaceID, aAttribute), + IsRemoveNotification::No); } void @@ -165,7 +177,8 @@ nsNodeUtils::ContentAppended(nsIContent* aContainer, nsIDocument* doc = aContainer->OwnerDoc(); IMPL_MUTATION_NOTIFICATION(ContentAppended, aContainer, - (doc, aContainer, aFirstNewContent)); + (doc, aContainer, aFirstNewContent), + IsRemoveNotification::No); } void @@ -174,7 +187,8 @@ nsNodeUtils::NativeAnonymousChildListChange(nsIContent* aContent, { nsIDocument* doc = aContent->OwnerDoc(); IMPL_MUTATION_NOTIFICATION(NativeAnonymousChildListChange, aContent, - (doc, aContent, aIsRemove)); + (doc, aContent, aIsRemove), + IsRemoveNotification::No); } void @@ -196,7 +210,8 @@ nsNodeUtils::ContentInserted(nsINode* aContainer, } IMPL_MUTATION_NOTIFICATION(ContentInserted, aContainer, - (document, container, aChild)); + (document, container, aChild), + IsRemoveNotification::No); } void @@ -219,7 +234,8 @@ nsNodeUtils::ContentRemoved(nsINode* aContainer, } IMPL_MUTATION_NOTIFICATION(ContentRemoved, aContainer, - (document, container, aChild, aPreviousSibling)); + (document, container, aChild, aPreviousSibling), + IsRemoveNotification::Yes); } Maybe