From d4f7cc1e851d03bcf653335c5228c342c41c25d9 Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Sat, 26 Aug 2017 22:26:55 -0400 Subject: [PATCH] Bug 1392891 - Part 1: Make it possible to create nsContentList objects that don't observe DOM mutations; r=smaug --- dom/base/nsContentList.cpp | 25 +++++++++++++++++-------- dom/base/nsContentList.h | 18 ++++++++++++++---- 2 files changed, 31 insertions(+), 12 deletions(-) diff --git a/dom/base/nsContentList.cpp b/dom/base/nsContentList.cpp index 8a6da88bd982..86d72ab9d5bc 100644 --- a/dom/base/nsContentList.cpp +++ b/dom/base/nsContentList.cpp @@ -422,7 +422,8 @@ nsContentList::nsContentList(nsINode* aRootNode, int32_t aMatchNameSpaceId, nsIAtom* aHTMLMatchAtom, nsIAtom* aXMLMatchAtom, - bool aDeep) + bool aDeep, + bool aLiveList) : nsBaseContentList(), mRootNode(aRootNode), mMatchNameSpaceId(aMatchNameSpaceId), @@ -434,7 +435,8 @@ nsContentList::nsContentList(nsINode* aRootNode, mState(LIST_DIRTY), mDeep(aDeep), mFuncMayDependOnAttr(false), - mIsHTMLDocument(aRootNode->OwnerDoc()->IsHTMLDocument()) + mIsHTMLDocument(aRootNode->OwnerDoc()->IsHTMLDocument()), + mIsLiveList(aLiveList) { NS_ASSERTION(mRootNode, "Must have root"); if (nsGkAtoms::_asterisk == mHTMLMatchAtom) { @@ -444,7 +446,9 @@ nsContentList::nsContentList(nsINode* aRootNode, else { mMatchAll = false; } - mRootNode->AddMutationObserver(this); + if (mIsLiveList) { + mRootNode->AddMutationObserver(this); + } // We only need to flush if we're in an non-HTML document, since the // HTML5 parser doesn't need flushing. Further, if we're not in a @@ -462,7 +466,8 @@ nsContentList::nsContentList(nsINode* aRootNode, bool aDeep, nsIAtom* aMatchAtom, int32_t aMatchNameSpaceId, - bool aFuncMayDependOnAttr) + bool aFuncMayDependOnAttr, + bool aLiveList) : nsBaseContentList(), mRootNode(aRootNode), mMatchNameSpaceId(aMatchNameSpaceId), @@ -475,10 +480,13 @@ nsContentList::nsContentList(nsINode* aRootNode, mMatchAll(false), mDeep(aDeep), mFuncMayDependOnAttr(aFuncMayDependOnAttr), - mIsHTMLDocument(false) + mIsHTMLDocument(false), + mIsLiveList(aLiveList) { NS_ASSERTION(mRootNode, "Must have root"); - mRootNode->AddMutationObserver(this); + if (mIsLiveList) { + mRootNode->AddMutationObserver(this); + } // We only need to flush if we're in an non-HTML document, since the // HTML5 parser doesn't need flushing. Further, if we're not in a @@ -492,7 +500,7 @@ nsContentList::nsContentList(nsINode* aRootNode, nsContentList::~nsContentList() { RemoveFromHashtable(); - if (mRootNode) { + if (mIsLiveList && mRootNode) { mRootNode->RemoveMutationObserver(this); } @@ -646,7 +654,7 @@ void nsContentList::LastRelease() { RemoveFromCaches(); - if (mRootNode) { + if (mIsLiveList && mRootNode) { mRootNode->RemoveMutationObserver(this); mRootNode = nullptr; } @@ -1246,6 +1254,7 @@ nsLabelsNodeList::MaybeResetRoot(nsINode* aRootNode) return; } + MOZ_ASSERT(mIsLiveList, "nsLabelsNodeList is always a live list"); if (mRootNode) { mRootNode->RemoveMutationObserver(this); } diff --git a/dom/base/nsContentList.h b/dom/base/nsContentList.h index a9f47cc82195..444bdf452620 100644 --- a/dom/base/nsContentList.h +++ b/dom/base/nsContentList.h @@ -251,8 +251,8 @@ struct nsContentListKey #define LIST_LAZY 2 /** - * Class that implements a live NodeList that matches Elements in the - * tree based on some criterion. + * Class that implements a possibly live NodeList that matches Elements + * in the tree based on some criterion. */ class nsContentList : public nsBaseContentList, public nsIHTMLCollection, @@ -276,12 +276,15 @@ public: * @param aDeep If false, then look only at children of the root, nothing * deeper. If true, then look at the whole subtree rooted at * our root. + * @param aLiveList Whether the created list should be a live list observing + * mutations to the DOM tree. */ nsContentList(nsINode* aRootNode, int32_t aMatchNameSpaceId, nsIAtom* aHTMLMatchAtom, nsIAtom* aXMLMatchAtom, - bool aDeep = true); + bool aDeep = true, + bool aLiveList = true); /** * @param aRootNode The node under which to limit our search. @@ -298,6 +301,8 @@ public: * @param aMatchNameSpaceId a namespace id to be passed back to aFunc * @param aFuncMayDependOnAttr a boolean that indicates whether this list is * sensitive to attribute changes. + * @param aLiveList Whether the created list should be a live list observing + * mutations to the DOM tree. */ nsContentList(nsINode* aRootNode, nsContentListMatchFunc aFunc, @@ -306,7 +311,8 @@ public: bool aDeep = true, nsIAtom* aMatchAtom = nullptr, int32_t aMatchNameSpaceId = kNameSpaceID_None, - bool aFuncMayDependOnAttr = true); + bool aFuncMayDependOnAttr = true, + bool aLiveList = true); // nsWrapperCache using nsWrapperCache::GetWrapperPreserveColor; @@ -517,6 +523,10 @@ protected: * when doing function matching, always false otherwise. */ uint8_t mIsHTMLDocument : 1; + /** + * Whether the list observes mutations to the DOM tree. + */ + const uint8_t mIsLiveList : 1; #ifdef DEBUG_CONTENT_LIST void AssertInSync();