summaryrefslogtreecommitdiff
path: root/dom/base
diff options
context:
space:
mode:
authorwolfbeast <mcwerewolf@gmail.com>2018-12-22 02:15:50 +0100
committerwolfbeast <mcwerewolf@gmail.com>2018-12-22 02:15:50 +0100
commitc9d920e9c630fd8b99b863e034742fd3b38e12d3 (patch)
treea2f3f8a11aa10bca612c9648b9219abc89d73e5a /dom/base
parentba81aaf073bbf9b2e832324d1710faa4c61799ba (diff)
downloaduxp-c9d920e9c630fd8b99b863e034742fd3b38e12d3.tar.gz
Revise lifetime management of IntersectionObservers.
Tag #249
Diffstat (limited to 'dom/base')
-rw-r--r--dom/base/DOMIntersectionObserver.cpp18
-rw-r--r--dom/base/DOMIntersectionObserver.h6
-rw-r--r--dom/base/Element.cpp8
-rw-r--r--dom/base/Element.h3
-rw-r--r--dom/base/FragmentOrElement.cpp6
-rw-r--r--dom/base/FragmentOrElement.h3
-rw-r--r--dom/base/nsDocument.cpp23
-rw-r--r--dom/base/nsDocument.h5
8 files changed, 46 insertions, 26 deletions
diff --git a/dom/base/DOMIntersectionObserver.cpp b/dom/base/DOMIntersectionObserver.cpp
index e39abf1a6e..cb624fb17d 100644
--- a/dom/base/DOMIntersectionObserver.cpp
+++ b/dom/base/DOMIntersectionObserver.cpp
@@ -43,16 +43,18 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMIntersectionObserver)
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
+ tmp->Disconnect();
NS_IMPL_CYCLE_COLLECTION_UNLINK(mOwner)
+ NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocument)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mCallback)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mRoot)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mQueuedEntries)
- tmp->Disconnect();
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DOMIntersectionObserver)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOwner)
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocument)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCallback)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRoot)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mQueuedEntries)
@@ -185,10 +187,11 @@ DOMIntersectionObserver::Connect()
if (mConnected) {
return;
}
+
mConnected = true;
-
- nsIDocument* document = mOwner->GetExtantDoc();
- document->AddIntersectionObserver(this);
+ if(mDocument) {
+ mDocument->AddIntersectionObserver(this);
+ }
}
void
@@ -202,11 +205,8 @@ DOMIntersectionObserver::Disconnect()
target->UnregisterIntersectionObserver(this);
}
mObservationTargets.Clear();
- if (mOwner) {
- nsIDocument* document = mOwner->GetExtantDoc();
- if (document) {
- document->RemoveIntersectionObserver(this);
- }
+ if (mDocument) {
+ mDocument->RemoveIntersectionObserver(this);
}
mConnected = false;
}
diff --git a/dom/base/DOMIntersectionObserver.h b/dom/base/DOMIntersectionObserver.h
index 8144fc5c5c..c290002ea5 100644
--- a/dom/base/DOMIntersectionObserver.h
+++ b/dom/base/DOMIntersectionObserver.h
@@ -106,7 +106,10 @@ class DOMIntersectionObserver final : public nsISupports,
public:
DOMIntersectionObserver(already_AddRefed<nsPIDOMWindowInner>&& aOwner,
mozilla::dom::IntersectionCallback& aCb)
- : mOwner(aOwner), mCallback(&aCb), mConnected(false)
+ : mOwner(aOwner)
+ , mDocument(mOwner->GetExtantDoc())
+ , mCallback(&aCb)
+ , mConnected(false)
{
}
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
@@ -164,6 +167,7 @@ protected:
double aIntersectionRatio);
nsCOMPtr<nsPIDOMWindowInner> mOwner;
+ RefPtr<nsIDocument> mDocument;
RefPtr<mozilla::dom::IntersectionCallback> mCallback;
RefPtr<Element> mRoot;
nsCSSRect mRootMargin;
diff --git a/dom/base/Element.cpp b/dom/base/Element.cpp
index 3760dc43f4..67759fdb26 100644
--- a/dom/base/Element.cpp
+++ b/dom/base/Element.cpp
@@ -3947,7 +3947,7 @@ Element::ClearDataset()
slots->mDataset = nullptr;
}
-nsDataHashtable<nsPtrHashKey<DOMIntersectionObserver>, int32_t>*
+nsDataHashtable<nsRefPtrHashKey<DOMIntersectionObserver>, int32_t>*
Element::RegisteredIntersectionObservers()
{
nsDOMSlots* slots = DOMSlots();
@@ -3962,7 +3962,7 @@ enum nsPreviousIntersectionThreshold {
void
Element::RegisterIntersectionObserver(DOMIntersectionObserver* aObserver)
{
- nsDataHashtable<nsPtrHashKey<DOMIntersectionObserver>, int32_t>* observers =
+ nsDataHashtable<nsRefPtrHashKey<DOMIntersectionObserver>, int32_t>* observers =
RegisteredIntersectionObservers();
if (observers->Contains(aObserver)) {
return;
@@ -3979,7 +3979,7 @@ Element::RegisterIntersectionObserver(DOMIntersectionObserver* aObserver)
void
Element::UnregisterIntersectionObserver(DOMIntersectionObserver* aObserver)
{
- nsDataHashtable<nsPtrHashKey<DOMIntersectionObserver>, int32_t>* observers =
+ nsDataHashtable<nsRefPtrHashKey<DOMIntersectionObserver>, int32_t>* observers =
RegisteredIntersectionObservers();
observers->Remove(aObserver);
}
@@ -3987,7 +3987,7 @@ Element::UnregisterIntersectionObserver(DOMIntersectionObserver* aObserver)
bool
Element::UpdateIntersectionObservation(DOMIntersectionObserver* aObserver, int32_t aThreshold)
{
- nsDataHashtable<nsPtrHashKey<DOMIntersectionObserver>, int32_t>* observers =
+ nsDataHashtable<nsRefPtrHashKey<DOMIntersectionObserver>, int32_t>* observers =
RegisteredIntersectionObservers();
if (!observers->Contains(aObserver)) {
return false;
diff --git a/dom/base/Element.h b/dom/base/Element.h
index c269ab14aa..ef57a64668 100644
--- a/dom/base/Element.h
+++ b/dom/base/Element.h
@@ -1382,7 +1382,8 @@ protected:
nsDOMTokenList* GetTokenList(nsIAtom* aAtom,
const DOMTokenListSupportedTokenArray aSupportedTokens = nullptr);
- nsDataHashtable<nsPtrHashKey<DOMIntersectionObserver>, int32_t>* RegisteredIntersectionObservers();
+ nsDataHashtable<nsRefPtrHashKey<DOMIntersectionObserver>, int32_t>*
+ RegisteredIntersectionObservers();
private:
/**
diff --git a/dom/base/FragmentOrElement.cpp b/dom/base/FragmentOrElement.cpp
index fde983e7cb..13ba19c8c6 100644
--- a/dom/base/FragmentOrElement.cpp
+++ b/dom/base/FragmentOrElement.cpp
@@ -585,6 +585,12 @@ FragmentOrElement::nsDOMSlots::Traverse(nsCycleCollectionTraversalCallback &cb,
mCustomElementData->mCallbackQueue[i]->Traverse(cb);
}
}
+
+ for (auto iter = mRegisteredIntersectionObservers.Iter(); !iter.Done(); iter.Next()) {
+ DOMIntersectionObserver* observer = iter.Key();
+ NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mRegisteredIntersectionObservers[i]");
+ cb.NoteXPCOMChild(observer);
+ }
}
void
diff --git a/dom/base/FragmentOrElement.h b/dom/base/FragmentOrElement.h
index 7c74e9cd45..f0cc29f224 100644
--- a/dom/base/FragmentOrElement.h
+++ b/dom/base/FragmentOrElement.h
@@ -354,7 +354,8 @@ public:
/**
* Registered Intersection Observers on the element.
*/
- nsDataHashtable<nsPtrHashKey<DOMIntersectionObserver>, int32_t> mRegisteredIntersectionObservers;
+ nsDataHashtable<nsRefPtrHashKey<DOMIntersectionObserver>, int32_t>
+ mRegisteredIntersectionObservers;
};
protected:
diff --git a/dom/base/nsDocument.cpp b/dom/base/nsDocument.cpp
index ac9601caf1..e779c060c9 100644
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -1736,8 +1736,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsDocument)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOnDemandBuiltInUASheets)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPreloadingImages)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIntersectionObservers)
-
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSubImportLinks)
for (uint32_t i = 0; i < tmp->mFrameRequestCallbacks.Length(); ++i) {
@@ -12375,15 +12373,15 @@ nsDocument::ReportUseCounters()
void
nsDocument::AddIntersectionObserver(DOMIntersectionObserver* aObserver)
{
- NS_ASSERTION(mIntersectionObservers.IndexOf(aObserver) == nsTArray<int>::NoIndex,
- "Intersection observer already in the list");
- mIntersectionObservers.AppendElement(aObserver);
+ MOZ_ASSERT(!mIntersectionObservers.Contains(aObserver),
+ "Intersection observer already in the list");
+ mIntersectionObservers.PutEntry(aObserver);
}
void
nsDocument::RemoveIntersectionObserver(DOMIntersectionObserver* aObserver)
{
- mIntersectionObservers.RemoveElement(aObserver);
+ mIntersectionObservers.RemoveEntry(aObserver);
}
void
@@ -12396,7 +12394,8 @@ nsDocument::UpdateIntersectionObservations()
time = perf->Now();
}
}
- for (const auto& observer : mIntersectionObservers) {
+ for (auto iter = mIntersectionObservers.Iter(); !iter.Done(); iter.Next()) {
+ DOMIntersectionObserver* observer = iter.Get()->GetKey();
observer->Update(this, time);
}
}
@@ -12404,6 +12403,10 @@ nsDocument::UpdateIntersectionObservations()
void
nsDocument::ScheduleIntersectionObserverNotification()
{
+ if (mIntersectionObservers.IsEmpty()) {
+ return;
+ }
+
nsCOMPtr<nsIRunnable> notification = NewRunnableMethod(this,
&nsDocument::NotifyIntersectionObservers);
NS_DispatchToCurrentThread(notification);
@@ -12412,7 +12415,11 @@ nsDocument::ScheduleIntersectionObserverNotification()
void
nsDocument::NotifyIntersectionObservers()
{
- nsTArray<RefPtr<DOMIntersectionObserver>> observers(mIntersectionObservers);
+ nsTArray<RefPtr<DOMIntersectionObserver>> observers(mIntersectionObservers.Count());
+ for (auto iter = mIntersectionObservers.Iter(); !iter.Done(); iter.Next()) {
+ DOMIntersectionObserver* observer = iter.Get()->GetKey();
+ observers.AppendElement(observer);
+ }
for (const auto& observer : observers) {
observer->Notify();
}
diff --git a/dom/base/nsDocument.h b/dom/base/nsDocument.h
index 3725b3c18f..d2f97a33e5 100644
--- a/dom/base/nsDocument.h
+++ b/dom/base/nsDocument.h
@@ -1341,8 +1341,9 @@ protected:
// Array of observers
nsTObserverArray<nsIDocumentObserver*> mObservers;
- // Array of intersection observers
- nsTArray<RefPtr<mozilla::dom::DOMIntersectionObserver>> mIntersectionObservers;
+ // Hashtable of intersection observers
+ nsTHashtable<nsPtrHashKey<mozilla::dom::DOMIntersectionObserver>>
+ mIntersectionObservers;
// Tracker for animations that are waiting to start.
// nullptr until GetOrCreatePendingAnimationTracker is called.