From 8b71cda1956ab640ad76bea36e7971476aa78bcf Mon Sep 17 00:00:00 2001 From: wolfbeast Date: Wed, 27 Jun 2018 16:00:53 +0200 Subject: Stabilize and align Intersection Observers - Fixes several crashes - Aligns the feature with the W3C WD spec Tag #249 --- dom/base/Element.cpp | 45 ++++++++++++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 17 deletions(-) (limited to 'dom/base/Element.cpp') diff --git a/dom/base/Element.cpp b/dom/base/Element.cpp index 092755590..52d06b0f8 100644 --- a/dom/base/Element.cpp +++ b/dom/base/Element.cpp @@ -3912,44 +3912,55 @@ Element::ClearDataset() slots->mDataset = nullptr; } -nsTArray* +nsDataHashtable, int32_t>* Element::RegisteredIntersectionObservers() { nsDOMSlots* slots = DOMSlots(); return &slots->mRegisteredIntersectionObservers; } +enum nsPreviousIntersectionThreshold { + eUninitialized = -2, + eNonIntersecting = -1 +}; + void Element::RegisterIntersectionObserver(DOMIntersectionObserver* aObserver) { - RegisteredIntersectionObservers()->AppendElement( - nsDOMSlots::IntersectionObserverRegistration { aObserver, -1 }); + nsDataHashtable, int32_t>* observers = + RegisteredIntersectionObservers(); + if (observers->Contains(aObserver)) { + return; + } + + // Value can be: + // -2: Makes sure next calculated threshold always differs, leading to a + // notification task being scheduled. + // -1: Non-intersecting. + // >= 0: Intersecting, valid index of aObserver->mThresholds. + RegisteredIntersectionObservers()->Put(aObserver, eUninitialized); } void Element::UnregisterIntersectionObserver(DOMIntersectionObserver* aObserver) { - nsTArray* observers = + nsDataHashtable, int32_t>* observers = RegisteredIntersectionObservers(); - for (uint32_t i = 0; i < observers->Length(); ++i) { - nsDOMSlots::IntersectionObserverRegistration reg = observers->ElementAt(i); - if (reg.observer == aObserver) { - observers->RemoveElementAt(i); - break; - } - } + observers->Remove(aObserver); } bool Element::UpdateIntersectionObservation(DOMIntersectionObserver* aObserver, int32_t aThreshold) { - nsTArray* observers = + nsDataHashtable, int32_t>* observers = RegisteredIntersectionObservers(); - for (auto& reg : *observers) { - if (reg.observer == aObserver && reg.previousThreshold != aThreshold) { - reg.previousThreshold = aThreshold; - return true; - } + if (!observers->Contains(aObserver)) { + return false; + } + int32_t previousThreshold = observers->Get(aObserver); + if (previousThreshold != aThreshold) { + observers->Put(aObserver, aThreshold); + return true; } return false; } -- cgit v1.2.3