diff options
author | wolfbeast <mcwerewolf@gmail.com> | 2018-12-24 01:58:16 +0100 |
---|---|---|
committer | wolfbeast <mcwerewolf@gmail.com> | 2018-12-24 01:58:16 +0100 |
commit | 3cf7e874fecf940ffeec00bafd3cf96d5c1b2a46 (patch) | |
tree | f32ef71a8d6a2831ff3646665a2cecc8a8945d1c | |
parent | bfedd7d40c73ef0423251f6df74bc948a6f44a1e (diff) | |
download | UXP-3cf7e874fecf940ffeec00bafd3cf96d5c1b2a46.tar UXP-3cf7e874fecf940ffeec00bafd3cf96d5c1b2a46.tar.gz UXP-3cf7e874fecf940ffeec00bafd3cf96d5c1b2a46.tar.lz UXP-3cf7e874fecf940ffeec00bafd3cf96d5c1b2a46.tar.xz UXP-3cf7e874fecf940ffeec00bafd3cf96d5c1b2a46.zip |
Fix crashiness of IntersectionObservers.
Mozilla hashtables -still- suck.
-rw-r--r-- | dom/base/DOMIntersectionObserver.cpp | 39 | ||||
-rw-r--r-- | dom/base/DOMIntersectionObserver.h | 7 |
2 files changed, 25 insertions, 21 deletions
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<nsRect> intersectionRect; @@ -493,7 +494,7 @@ DOMIntersectionObserver::Notify() } mozilla::dom::Sequence<mozilla::OwningNonNull<DOMIntersectionObserverEntry>> 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<DOMIntersectionObserverEntry> 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<RefPtr<DOMIntersectionObserverEntry>>& aRetVal); @@ -172,7 +172,10 @@ protected: RefPtr<Element> mRoot; nsCSSRect mRootMargin; nsTArray<double> mThresholds; - nsTHashtable<nsPtrHashKey<Element>> mObservationTargets; + + // Holds raw pointers which are explicitly cleared by UnlinkTarget(). + nsTArray<Element*> mObservationTargets; + nsTArray<RefPtr<DOMIntersectionObserverEntry>> mQueuedEntries; bool mConnected; }; |