/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* * nsBaseContentList is a basic list of content nodes; nsContentList * is a commonly used NodeList implementation (used for * getElementsByTagName, some properties on HTMLDocument/Document, etc).
*/
/** * Insert the element at a given index, shifting the objects at * the given index and later to make space. * @param aContent Element to insert, must not be null * @param aIndex Index to insert the element at.
*/ void InsertElementAt(nsIContent* aContent, int32_t aIndex) {
NS_ASSERTION(aContent, "Element to insert must not be null");
mElements.InsertElementAt(aIndex, aContent);
}
// Memory reporting. For now, subclasses of nsBaseContentList don't really // need to report any members that are not part of the object itself, so we // don't need to make this virtual.
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
protected: virtual ~nsBaseContentList();
/** * To be called from non-destructor locations (e.g. unlink) that want to * remove from caches. Cacheable subclasses should override.
*/ virtualvoid RemoveFromCaches() {}
private: // This has to be a strong reference, the root might go away before the list.
nsCOMPtr<nsINode> mRoot;
};
// Used for returning lists that will always be empty, such as the applets list // in HTML Documents class nsEmptyContentList final : public nsBaseContentList, public nsIHTMLCollection { public: explicit nsEmptyContentList(nsINode* aRoot)
: nsBaseContentList(), mRoot(aRoot) {}
private: // This has to be a strong reference, the root might go away before the list.
nsCOMPtr<nsINode> mRoot;
};
/** * Class that's used as the key to hash nsContentList implementations * for fast retrieval
*/ struct nsContentListKey { // We have to take an aIsHTMLDocument arg for two reasons: // 1) We don't want to include Document.h in this header. // 2) We need to do that to make nsContentList::RemoveFromHashtable // work, because by the time it's called the document of the // list's root node might have changed.
nsContentListKey(nsINode* aRootNode, int32_t aMatchNameSpaceId, const nsAString& aTagname, bool aIsHTMLDocument)
: mRootNode(aRootNode),
mMatchNameSpaceId(aMatchNameSpaceId),
mTagname(aTagname),
mIsHTMLDocument(aIsHTMLDocument),
mHash(mozilla::AddToHash(mozilla::HashString(aTagname), mRootNode,
mMatchNameSpaceId, mIsHTMLDocument)) {}
/** * Class that implements a possibly live NodeList that matches Elements * in the tree based on some criterion.
*/ class nsContentList : public nsBaseContentList, public nsIHTMLCollection, public nsStubMutationObserver { protected: enumclass State : uint8_t { // The list is up to date and need not do any walking to be able to answer // any questions anyone may have.
UpToDate = 0, // The list contains no useful information and if anyone asks it anything it // will have to populate itself before answering.
Dirty, // The list has populated itself to a certain extent and that that part of // the list is still valid. Requests for things outside that part of the // list will require walking the tree some more. When a list is in this // state, the last thing in mElements is the last node in the tree that the // list looked at.
Lazy,
};
public:
NS_DECL_ISUPPORTS_INHERITED
/** * @param aRootNode The node under which to limit our search. * @param aMatchAtom An atom whose meaning depends on aMatchNameSpaceId. * The special value "*" always matches whatever aMatchAtom * is matched against. * @param aMatchNameSpaceId If kNameSpaceID_Unknown, then aMatchAtom is the * tagName to match. * If kNameSpaceID_Wildcard, then aMatchAtom is the * localName to match. * Otherwise we match nodes whose namespace is * aMatchNameSpaceId and localName matches * aMatchAtom. * @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,
nsAtom* aHTMLMatchAtom, nsAtom* aXMLMatchAtom, bool aDeep = true, bool aLiveList = true);
/** * @param aRootNode The node under which to limit our search. * @param aFunc the function to be called to determine whether we match. * This function MUST NOT ever cause mutation of the DOM. * The nsContentList implementation guarantees that everything * passed to the function will be IsElement(). * @param aDestroyFunc the function that will be called to destroy aData * @param aData closure data that will need to be passed back to aFunc * @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 aMatchAtom an atom to be passed back to aFunc * @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,
nsContentListDestroyFunc aDestroyFunc, void* aData, bool aDeep = true, nsAtom* aMatchAtom = nullptr,
int32_t aMatchNameSpaceId = kNameSpaceID_None, bool aFuncMayDependOnAttr = true, bool aLiveList = true);
// nsWrapperCache using nsWrapperCache::GetWrapperPreserveColor; using nsWrapperCache::PreserveWrapper;
JSObject* WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) override;
// If this assertion fires the QI implementation for the object in // question doesn't use the nsINodeList pointer as the nsISupports // pointer. That must be fixed, or we'll crash...
NS_ASSERTION(list_qi == list, "Uh, fix QI!");
} #endif returnstatic_cast<nsContentList*>(list);
}
bool MatchesKey(const nsContentListKey& aKey) const { // The root node is most commonly the same: the document. And the // most common namespace id is kNameSpaceID_Unknown. So check the // string first. Cases in which whether our root's ownerDocument // is HTML changes are extremely rare, so check those last.
MOZ_ASSERT(mXMLMatchAtom, "How did we get here with a null match atom on our list?"); return mXMLMatchAtom->Equals(aKey.mTagname) &&
mRootNode == aKey.mRootNode &&
mMatchNameSpaceId == aKey.mMatchNameSpaceId &&
mIsHTMLDocument == aKey.mIsHTMLDocument;
}
/** * Sets the state to LIST_DIRTY and clears mElements array. * @note This is the only acceptable way to set state to LIST_DIRTY.
*/ void SetDirty() {
mState = State::Dirty;
InvalidateNamedItemsCache();
Reset();
SetEnabledCallbacks(nsIMutationObserver::kNodeWillBeDestroyed);
}
void LastRelease() override;
class HashEntry;
protected: // A cache from name to the first named item in mElements. Only possibly // non-null when mState is State::UpToDate. Elements are kept alive by our // mElements array. using NamedItemsCache = nsTHashMap<nsAtomHashKey, Element*>;
/** * Returns whether the element matches our criterion * * @param aElement the element to attempt to match * @return whether we match
*/ bool Match(Element* aElement); /** * See if anything in the subtree rooted at aContent, including * aContent itself, matches our criterion. * * @param aContent the root of the subtree to match against * @return whether we match something in the tree rooted at aContent
*/ bool MatchSelf(nsIContent* aContent);
/** * Populate our list. Stop once we have at least aNeededLength * elements. At the end of PopulateSelf running, either the last * node we examined is the last node in our array or we have * traversed the whole document (or both). * * @param aNeededLength the length the list should have when we are * done (unless it exhausts the document) * @param aExpectedElementsIfDirty is for debugging only to * assert that mElements has expected number of entries.
*/ virtualvoid PopulateSelf(uint32_t aNeededLength,
uint32_t aExpectedElementsIfDirty = 0);
/** * @param aContainer a content node which must be a descendant of * mRootNode * @return true if children or descendants of aContainer could match our * criterion. * false otherwise.
*/ bool MayContainRelevantNodes(nsINode* aContainer) { return mDeep || aContainer == mRootNode;
}
/** * Remove ourselves from the hashtable that caches commonly accessed * content lists. Generally done on destruction.
*/ void RemoveFromHashtable(); /** * If state is not LIST_UP_TO_DATE, fully populate ourselves with * all the nodes we can find.
*/ inlinevoid BringSelfUpToDate(bool aDoFlush);
/** * To be called from non-destructor locations that want to remove from caches. * Needed because if subclasses want to have cache behavior they can't just * override RemoveFromHashtable(), since we call that in our destructor.
*/ void RemoveFromCaches() override { RemoveFromHashtable(); }
/** * Function to use to determine whether a piece of content matches * our criterion
*/
nsContentListMatchFunc mFunc = nullptr; /** * Cleanup closure data with this.
*/
nsContentListDestroyFunc mDestroyFunc = nullptr; /** * Closure data to pass to mFunc when we call it
*/ void* mData = nullptr;
/** * True if we are looking for elements named "*"
*/ bool mMatchAll : 1; /** * Whether to actually descend the tree. If this is false, we won't * consider grandkids of mRootNode.
*/ bool mDeep : 1; /** * Whether the return value of mFunc could depend on the values of * attributes.
*/ bool mFuncMayDependOnAttr : 1; /** * Whether we actually need to flush to get our state correct.
*/ bool mFlushesNeeded : 1; /** * Whether the ownerDocument of our root node at list creation time was an * HTML document. Only needed when we're doing a namespace/atom match, not * when doing function matching, always false otherwise.
*/ bool mIsHTMLDocument : 1; /** * True mNamedItemsCache is valid. Note mNamedItemsCache might still be null * if there's no named items at all.
*/ bool mNamedItemsCacheValid : 1; /** * Whether the list observes mutations to the DOM tree.
*/ constbool mIsLiveList : 1; /* * True if this content list is cached in a hash table. * For nsContentList (but not its subclasses), the hash table is * gContentListHashTable. * For nsCacheableFuncStringContentList, the hash table is * gFuncStringContentListHashTable. * Other subclasses of nsContentList can't be in hash tables.
*/ bool mInHashtable : 1;
// aDestroyFunc is allowed to be null // aDataAllocator must always return a non-null pointer class nsCacheableFuncStringContentList : public nsContentList { public: virtual ~nsCacheableFuncStringContentList();
/** * Reset root, mutation observer, and clear content list * if the root has been changed. * * @param aRootNode The node under which to limit our search.
*/ void MaybeResetRoot(nsINode* aRootNode);
private: /** * Start searching at the last one if we already have nodes, otherwise * start searching at the root. * * @param aNeededLength The list of length should have when we are * done (unless it exhausts the document). * @param aExpectedElementsIfDirty is for debugging only to * assert that mElements has expected number of entries.
*/ void PopulateSelf(uint32_t aNeededLength,
uint32_t aExpectedElementsIfDirty = 0) override;
}; #endif// nsContentList_h___
¤ Dauer der Verarbeitung: 0.22 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.