summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorwolfbeast <mcwerewolf@gmail.com>2018-12-24 01:58:16 +0100
committerwolfbeast <mcwerewolf@gmail.com>2018-12-24 01:58:16 +0100
commit3cf7e874fecf940ffeec00bafd3cf96d5c1b2a46 (patch)
treef32ef71a8d6a2831ff3646665a2cecc8a8945d1c
parentbfedd7d40c73ef0423251f6df74bc948a6f44a1e (diff)
downloaduxp-3cf7e874fecf940ffeec00bafd3cf96d5c1b2a46.tar.gz
Fix crashiness of IntersectionObservers.
Mozilla hashtables -still- suck.
-rw-r--r--dom/base/DOMIntersectionObserver.cpp39
-rw-r--r--dom/base/DOMIntersectionObserver.h7
2 files changed, 25 insertions, 21 deletions
diff --git a/dom/base/DOMIntersectionObserver.cpp b/dom/base/DOMIntersectionObserver.cpp
index 2f3a341c5e..e7b3cd0da8 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 c290002ea5..9c8ebf5b12 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;
};