From 3cf7e874fecf940ffeec00bafd3cf96d5c1b2a46 Mon Sep 17 00:00:00 2001 From: wolfbeast Date: Mon, 24 Dec 2018 01:58:16 +0100 Subject: Fix crashiness of IntersectionObservers. Mozilla hashtables -still- suck. --- dom/base/DOMIntersectionObserver.cpp | 39 ++++++++++++++++++------------------ dom/base/DOMIntersectionObserver.h | 7 +++++-- 2 files changed, 25 insertions(+), 21 deletions(-) (limited to 'dom/base') diff --git a/dom/base/DOMIntersectionObserver.cpp b/dom/base/DOMIntersectionObserver.cpp index 2f3a341c5..e7b3cd0da 100644 --- a/dom/base/DOMIntersectionObserver.cpp +++ b/dom/base/DOMIntersectionObserver.cpp @@ -155,30 +155,29 @@ DOMIntersectionObserver::Observe(Element& aTarget) return; } aTarget.RegisterIntersectionObserver(this); - mObservationTargets.PutEntry(&aTarget); + mObservationTargets.AppendElement(&aTarget); Connect(); } void DOMIntersectionObserver::Unobserve(Element& aTarget) { - if (UnlinkTarget(aTarget)) { - aTarget.UnregisterIntersectionObserver(this); + if (mObservationTargets.Length() == 1) { + Disconnect(); + return; } + + mObservationTargets.RemoveElement(&aTarget); + aTarget.UnregisterIntersectionObserver(this); } -bool +void DOMIntersectionObserver::UnlinkTarget(Element& aTarget) { - if (!mObservationTargets.Contains(&aTarget)) { - return false; - } - if (mObservationTargets.Count() == 1) { - Disconnect(); - return false; - } - mObservationTargets.RemoveEntry(&aTarget); - return true; + mObservationTargets.RemoveElement(&aTarget); + if (mObservationTargets.Length() == 0) { + Disconnect(); + } } void @@ -200,15 +199,17 @@ DOMIntersectionObserver::Disconnect() if (!mConnected) { return; } - for (auto iter = mObservationTargets.Iter(); !iter.Done(); iter.Next()) { - Element* target = iter.Get()->GetKey(); + + mConnected = false; + + for (size_t i = 0; i < mObservationTargets.Length(); ++i) { + Element* target = mObservationTargets.ElementAt(i); target->UnregisterIntersectionObserver(this); } mObservationTargets.Clear(); if (mDocument) { mDocument->RemoveIntersectionObserver(this); } - mConnected = false; } void @@ -318,8 +319,8 @@ DOMIntersectionObserver::Update(nsIDocument* aDocument, DOMHighResTimeStamp time rootMargin.Side(side) = nsLayoutUtils::ComputeCBDependentValue(basis, coord); } - for (auto iter = mObservationTargets.Iter(); !iter.Done(); iter.Next()) { - Element* target = iter.Get()->GetKey(); + for (size_t i = 0; i < mObservationTargets.Length(); ++i) { + Element* target = mObservationTargets.ElementAt(i); nsIFrame* targetFrame = target->GetPrimaryFrame(); nsRect targetRect; Maybe intersectionRect; @@ -493,7 +494,7 @@ DOMIntersectionObserver::Notify() } mozilla::dom::Sequence> entries; if (entries.SetCapacity(mQueuedEntries.Length(), mozilla::fallible)) { - for (uint32_t i = 0; i < mQueuedEntries.Length(); ++i) { + for (size_t i = 0; i < mQueuedEntries.Length(); ++i) { RefPtr next = mQueuedEntries[i]; *entries.AppendElement(mozilla::fallible) = next; } diff --git a/dom/base/DOMIntersectionObserver.h b/dom/base/DOMIntersectionObserver.h index c290002ea..9c8ebf5b1 100644 --- a/dom/base/DOMIntersectionObserver.h +++ b/dom/base/DOMIntersectionObserver.h @@ -145,7 +145,7 @@ public: void Observe(Element& aTarget); void Unobserve(Element& aTarget); - bool UnlinkTarget(Element& aTarget); + void UnlinkTarget(Element& aTarget); void Disconnect(); void TakeRecords(nsTArray>& aRetVal); @@ -172,7 +172,10 @@ protected: RefPtr mRoot; nsCSSRect mRootMargin; nsTArray mThresholds; - nsTHashtable> mObservationTargets; + + // Holds raw pointers which are explicitly cleared by UnlinkTarget(). + nsTArray mObservationTargets; + nsTArray> mQueuedEntries; bool mConnected; }; -- cgit v1.2.3