diff --git a/dom/base/DOMIntersectionObserver.cpp b/dom/base/DOMIntersectionObserver.cpp index 29b3aeba888f..169c3fe7add6 100644 --- a/dom/base/DOMIntersectionObserver.cpp +++ b/dom/base/DOMIntersectionObserver.cpp @@ -159,15 +159,23 @@ DOMIntersectionObserver::Observe(Element& aTarget) void DOMIntersectionObserver::Unobserve(Element& aTarget) { - if (!mObservationTargets.Contains(&aTarget)) { - return; + if (UnlinkTarget(aTarget)) { + aTarget.UnregisterIntersectionObserver(this); } - if (mObservationTargets.Count() == 1) { - Disconnect(); - return; - } - aTarget.UnregisterIntersectionObserver(this); - mObservationTargets.RemoveEntry(&aTarget); +} + +bool +DOMIntersectionObserver::UnlinkTarget(Element& aTarget) +{ + if (!mObservationTargets.Contains(&aTarget)) { + return false; + } + if (mObservationTargets.Count() == 1) { + Disconnect(); + return false; + } + mObservationTargets.RemoveEntry(&aTarget); + return true; } void @@ -192,8 +200,10 @@ DOMIntersectionObserver::Disconnect() target->UnregisterIntersectionObserver(this); } mObservationTargets.Clear(); - nsIDocument* document = mOwner->GetExtantDoc(); - document->RemoveIntersectionObserver(this); + if (mOwner) { + nsIDocument* document = mOwner->GetExtantDoc(); + document->RemoveIntersectionObserver(this); + } mConnected = false; } diff --git a/dom/base/DOMIntersectionObserver.h b/dom/base/DOMIntersectionObserver.h index 62cf697c6cf0..8144fc5c5ceb 100644 --- a/dom/base/DOMIntersectionObserver.h +++ b/dom/base/DOMIntersectionObserver.h @@ -142,7 +142,9 @@ public: void Observe(Element& aTarget); void Unobserve(Element& aTarget); + bool UnlinkTarget(Element& aTarget); void Disconnect(); + void TakeRecords(nsTArray>& aRetVal); mozilla::dom::IntersectionCallback* IntersectionCallback() { return mCallback; } diff --git a/dom/base/nsNodeUtils.cpp b/dom/base/nsNodeUtils.cpp index 0cf7db1922c6..c835908000bd 100644 --- a/dom/base/nsNodeUtils.cpp +++ b/dom/base/nsNodeUtils.cpp @@ -297,6 +297,15 @@ nsNodeUtils::LastRelease(nsINode* aNode) NodeWillBeDestroyed, (aNode)); } + if (aNode->IsElement()) { + Element* elem = aNode->AsElement(); + FragmentOrElement::nsDOMSlots* domSlots = + static_cast(slots); + for (auto& reg : domSlots->mRegisteredIntersectionObservers) { + reg.observer->UnlinkTarget(*elem); + } + } + delete slots; aNode->mSlots = nullptr; }