Fix for
bug 1142497 - change mDOMMediaQueryLists to use mozilla::LinkedList;r=erahm
MozReview-Commit-ID: G9RtgdYudqA
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -1371,18 +1371,16 @@ nsIDocument::nsIDocument()
mInSyncOperationCount(0),
mBlockDOMContentLoaded(0),
mUseCounters(0),
mChildDocumentUseCounters(0),
mNotifiedPageForUseCounter(0),
mUserHasInteracted(false)
{
SetIsInDocument();
-
- PR_INIT_CLIST(&mDOMMediaQueryLists);
}
nsDocument::nsDocument(const char* aContentType)
: nsIDocument()
, mIsTopLevelContentDocument(false)
, mIsContentDocument(false)
, mSubDocuments(nullptr)
, mFlashClassification(FlashClassification::Unclassified)
@@ -1452,17 +1450,17 @@ nsDocument::ClearAllBoxObjects()
}
delete mBoxObjectTable;
mBoxObjectTable = nullptr;
}
}
nsIDocument::~nsIDocument()
{
- MOZ_ASSERT(PR_CLIST_IS_EMPTY(&mDOMMediaQueryLists),
+ MOZ_ASSERT(mDOMMediaQueryLists.isEmpty(),
"must not have media query lists left");
if (mNodeInfoManager) {
mNodeInfoManager->DropDocumentReference();
}
if (mDocGroup) {
mDocGroup->RemoveDocument(this);
@@ -1853,19 +1851,17 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_
}
}
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCSSLoader)
// We own only the items in mDOMMediaQueryLists that have listeners;
// this reference is managed by their AddListener and RemoveListener
// methods.
- for (PRCList *l = PR_LIST_HEAD(&tmp->mDOMMediaQueryLists);
- l != &tmp->mDOMMediaQueryLists; l = PR_NEXT_LINK(l)) {
- MediaQueryList *mql = static_cast<MediaQueryList*>(l);
+ for (auto mql : tmp->mDOMMediaQueryLists) {
if (mql->HasListeners()) {
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mDOMMediaQueryLists item");
cb.NoteXPCOMChild(mql);
}
}
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_CLASS(nsDocument)
@@ -1957,22 +1953,20 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ns
if (tmp->mCSSLoader) {
tmp->mCSSLoader->DropDocumentReference();
NS_IMPL_CYCLE_COLLECTION_UNLINK(mCSSLoader)
}
// We own only the items in mDOMMediaQueryLists that have listeners;
// this reference is managed by their AddListener and RemoveListener
// methods.
- for (PRCList *l = PR_LIST_HEAD(&tmp->mDOMMediaQueryLists);
- l != &tmp->mDOMMediaQueryLists; ) {
- PRCList *next = PR_NEXT_LINK(l);
- MediaQueryList *mql = static_cast<MediaQueryList*>(l);
+ for (MediaQueryList* mql = tmp->mDOMMediaQueryLists.getFirst(); mql;) {
+ MediaQueryList* next = mql->getNext();
mql->Disconnect();
- l = next;
+ mql = next;
}
tmp->mInUnlinkOrDeletion = false;
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
nsresult
nsDocument::Init()
{
@@ -7164,18 +7158,17 @@ nsDocument::ClearBoxObjectFor(nsIContent
}
}
already_AddRefed<MediaQueryList>
nsIDocument::MatchMedia(const nsAString& aMediaQueryList)
{
RefPtr<MediaQueryList> result = new MediaQueryList(this, aMediaQueryList);
- // Insert the new item at the end of the linked list.
- PR_INSERT_BEFORE(result, &mDOMMediaQueryLists);
+ mDOMMediaQueryLists.insertBack(result);
return result.forget();
}
void
nsDocument::FlushSkinBindings()
{
BindingManager()->FlushSkinBindings();
--- a/dom/base/nsIDocument.h
+++ b/dom/base/nsIDocument.h
@@ -26,17 +26,16 @@
#include "mozilla/net/ReferrerPolicy.h" // for member
#include "nsWeakReference.h"
#include "mozilla/UseCounter.h"
#include "mozilla/WeakPtr.h"
#include "Units.h"
#include "nsContentListDeclarations.h"
#include "nsExpirationTracker.h"
#include "nsClassHashtable.h"
-#include "prclist.h"
#include "mozilla/CORSMode.h"
#include "mozilla/dom/DispatcherTrait.h"
#include "mozilla/LinkedList.h"
#include "mozilla/SegmentedVector.h"
#include "mozilla/StyleBackendType.h"
#include "mozilla/StyleSheet.h"
#include "mozilla/TimeStamp.h"
#include "mozilla/UniquePtr.h"
@@ -1870,18 +1869,18 @@ public:
/**
* Support for window.matchMedia()
*/
already_AddRefed<mozilla::dom::MediaQueryList>
MatchMedia(const nsAString& aMediaQueryList);
- const PRCList* MediaQueryLists() const {
- return &mDOMMediaQueryLists;
+ mozilla::LinkedList<mozilla::dom::MediaQueryList>& MediaQueryLists() {
+ return mDOMMediaQueryLists;
}
/**
* Get the compatibility mode for this document
*/
nsCompatibility GetCompatibilityMode() const {
return mCompatMode;
}
@@ -3370,17 +3369,17 @@ protected:
RefPtr<mozilla::dom::XPathEvaluator> mXPathEvaluator;
nsTArray<RefPtr<mozilla::dom::AnonymousContent>> mAnonymousContents;
uint32_t mBlockDOMContentLoaded;
// Our live MediaQueryLists
- PRCList mDOMMediaQueryLists;
+ mozilla::LinkedList<mozilla::dom::MediaQueryList> mDOMMediaQueryLists;
// Flags for use counters used directly by this document.
std::bitset<mozilla::eUseCounter_Count> mUseCounters;
// Flags for use counters used by any child documents of this document.
std::bitset<mozilla::eUseCounter_Count> mChildDocumentUseCounters;
// Flags for whether we've notified our top-level "page" of a use counter
// for this child document.
std::bitset<mozilla::eUseCounter_Count> mNotifiedPageForUseCounter;
--- a/layout/base/nsPresContext.cpp
+++ b/layout/base/nsPresContext.cpp
@@ -2068,38 +2068,46 @@ nsPresContext::MediaFeatureValuesChanged
if (aRestyleHint || aChangeHint) {
RebuildAllStyleData(aChangeHint, aRestyleHint);
}
mPendingViewportChange = false;
if (mDocument->IsBeingUsedAsImage()) {
- MOZ_ASSERT(PR_CLIST_IS_EMPTY(mDocument->MediaQueryLists()));
+ MOZ_ASSERT(mDocument->MediaQueryLists().isEmpty());
return;
}
mDocument->NotifyMediaFeatureValuesChanged();
MOZ_ASSERT(nsContentUtils::IsSafeToRunScript());
// Media query list listeners should be notified from a queued task
// (in HTML5 terms), although we also want to notify them on certain
// flushes. (We're already running off an event.)
//
// Note that we do this after the new style from media queries in
// style sheets has been computed.
- if (!PR_CLIST_IS_EMPTY(mDocument->MediaQueryLists())) {
+ if (!mDocument->MediaQueryLists().isEmpty()) {
// We build a list of all the notifications we're going to send
- // before we send any of them.
- for (PRCList *l = PR_LIST_HEAD(mDocument->MediaQueryLists());
- l != mDocument->MediaQueryLists(); l = PR_NEXT_LINK(l)) {
- nsAutoMicroTask mt;
- MediaQueryList *mql = static_cast<MediaQueryList*>(l);
+ // before we send any of them. (The spec says the notifications
+ // should be a queued task, so any removals that happen during the
+ // notifications shouldn't affect what gets notified.) Furthermore,
+ // we hold strong pointers to everything we're going to make
+ // notification calls to, since each notification involves calling
+ // arbitrary script that might otherwise destroy these objects, or,
+ // for that matter, |this|.
+ //
+ // Note that we intentionally send the notifications to media query
+ // list in the order they were created and, for each list, to the
+ // listeners in the order added.
+ nsTArray<MediaQueryList::HandleChangeData> notifyList;
+ for (auto mql : mDocument->MediaQueryLists()) {
mql->MaybeNotify();
}
}
}
void
nsPresContext::PostMediaFeatureValuesChangedEvent()
{
--- a/layout/style/MediaQueryList.cpp
+++ b/layout/style/MediaQueryList.cpp
@@ -23,38 +23,32 @@ namespace dom {
MediaQueryList::MediaQueryList(nsIDocument* aDocument,
const nsAString& aMediaQueryList)
: mDocument(aDocument)
, mMatchesValid(false)
, mIsKeptAlive(false)
{
mMediaList =
MediaList::Create(aDocument->GetStyleBackendType(), aMediaQueryList);
-
- PR_INIT_CLIST(this);
}
MediaQueryList::~MediaQueryList()
-{
- if (mDocument) {
- PR_REMOVE_LINK(this);
- }
-}
+{}
NS_IMPL_CYCLE_COLLECTION_CLASS(MediaQueryList)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(MediaQueryList,
DOMEventTargetHelper)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocument)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(MediaQueryList,
DOMEventTargetHelper)
if (tmp->mDocument) {
- PR_REMOVE_LINK(tmp);
+ tmp->remove();
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocument)
}
tmp->Disconnect();
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(MediaQueryList)
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
--- a/layout/style/MediaQueryList.h
+++ b/layout/style/MediaQueryList.h
@@ -8,31 +8,31 @@
#ifndef mozilla_dom_MediaQueryList_h
#define mozilla_dom_MediaQueryList_h
#include "nsISupports.h"
#include "nsCycleCollectionParticipant.h"
#include "nsCOMPtr.h"
#include "nsTArray.h"
-#include "prclist.h"
+#include "mozilla/LinkedList.h"
#include "mozilla/Attributes.h"
#include "nsWrapperCache.h"
#include "mozilla/DOMEventTargetHelper.h"
#include "mozilla/dom/MediaQueryListBinding.h"
class nsIDocument;
namespace mozilla {
namespace dom {
class MediaList;
class MediaQueryList final : public DOMEventTargetHelper,
- public PRCList
+ public mozilla::LinkedListElement<MediaQueryList>
{
public:
// The caller who constructs is responsible for calling Evaluate
// before calling any other methods.
MediaQueryList(nsIDocument *aDocument,
const nsAString &aMediaQueryList);
private:
~MediaQueryList();