diff options
Diffstat (limited to 'Source/WebCore/dom/LiveNodeList.h')
-rw-r--r-- | Source/WebCore/dom/LiveNodeList.h | 148 |
1 files changed, 83 insertions, 65 deletions
diff --git a/Source/WebCore/dom/LiveNodeList.h b/Source/WebCore/dom/LiveNodeList.h index 6e8ee08e5..415d1909f 100644 --- a/Source/WebCore/dom/LiveNodeList.h +++ b/Source/WebCore/dom/LiveNodeList.h @@ -2,7 +2,7 @@ * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) * (C) 2001 Dirk Mueller (mueller@kde.org) - * Copyright (C) 2004, 2006, 2007, 2013 Apple Inc. All rights reserved. + * Copyright (C) 2004, 2006-2007, 2013-2014 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -21,99 +21,87 @@ * */ -#ifndef LiveNodeList_h -#define LiveNodeList_h +#pragma once #include "CollectionIndexCache.h" +#include "CollectionTraversal.h" #include "CollectionType.h" #include "Document.h" +#include "ElementDescendantIterator.h" #include "HTMLNames.h" #include "NodeList.h" #include <wtf/Forward.h> -#include <wtf/RefPtr.h> namespace WebCore { class Element; -enum NodeListRootType { - NodeListIsRootedAtNode, - NodeListIsRootedAtDocument -}; - static bool shouldInvalidateTypeOnAttributeChange(NodeListInvalidationType, const QualifiedName&); class LiveNodeList : public NodeList { public: - enum Type { - ClassNodeListType, - NameNodeListType, - TagNodeListType, - HTMLTagNodeListType, - RadioNodeListType, - LabelsNodeListType, - }; - - LiveNodeList(ContainerNode& ownerNode, Type type, NodeListInvalidationType invalidationType, NodeListRootType rootType = NodeListIsRootedAtNode) - : m_ownerNode(ownerNode) - , m_rootType(rootType) - , m_invalidationType(invalidationType) - , m_type(type) - { - ASSERT(m_rootType == static_cast<unsigned>(rootType)); - ASSERT(m_invalidationType == static_cast<unsigned>(invalidationType)); - ASSERT(m_type == static_cast<unsigned>(type)); + LiveNodeList(ContainerNode& ownerNode, NodeListInvalidationType); + virtual ~LiveNodeList(); - document().registerNodeList(*this); - } - virtual Node* namedItem(const AtomicString&) const override final; - virtual bool nodeMatches(Element*) const = 0; + virtual bool elementMatches(Element&) const = 0; + virtual bool isRootedAtDocument() const = 0; - virtual ~LiveNodeList() - { - document().unregisterNodeList(*this); - } - - // DOM API - virtual unsigned length() const override final; - virtual Node* item(unsigned offset) const override final; - - ALWAYS_INLINE bool isRootedAtDocument() const { return m_rootType == NodeListIsRootedAtDocument; } ALWAYS_INLINE NodeListInvalidationType invalidationType() const { return static_cast<NodeListInvalidationType>(m_invalidationType); } - ALWAYS_INLINE Type type() const { return static_cast<Type>(m_type); } - ContainerNode& ownerNode() const { return const_cast<ContainerNode&>(m_ownerNode.get()); } - ALWAYS_INLINE void invalidateCache(const QualifiedName* attrName) const + ContainerNode& ownerNode() const { return m_ownerNode; } + ALWAYS_INLINE void invalidateCacheForAttribute(const QualifiedName* attrName) const { if (!attrName || shouldInvalidateTypeOnAttributeChange(invalidationType(), *attrName)) - invalidateCache(); + invalidateCache(document()); } - void invalidateCache() const; + virtual void invalidateCache(Document&) const = 0; - // For CollectionIndexCache - Element* collectionFirst() const; - Element* collectionLast() const; - Element* collectionTraverseForward(Element&, unsigned count, unsigned& traversedCount) const; - Element* collectionTraverseBackward(Element&, unsigned count) const; - bool collectionCanTraverseBackward() const { return true; } + bool isRegisteredForInvalidationAtDocument() const { return m_isRegisteredForInvalidationAtDocument; } + void setRegisteredForInvalidationAtDocument(bool f) { m_isRegisteredForInvalidationAtDocument = f; } protected: Document& document() const { return m_ownerNode->document(); } - ContainerNode& rootNode() const; - - ALWAYS_INLINE NodeListRootType rootType() const { return static_cast<NodeListRootType>(m_rootType); } private: - virtual bool isLiveNodeList() const override { return true; } + bool isLiveNodeList() const final { return true; } - Element* iterateForPreviousElement(Element* current) const; + ContainerNode& rootNode() const; Ref<ContainerNode> m_ownerNode; - mutable CollectionIndexCache<LiveNodeList, Element> m_indexCache; + const unsigned m_invalidationType; + bool m_isRegisteredForInvalidationAtDocument; +}; + +template <class NodeListType> +class CachedLiveNodeList : public LiveNodeList { +public: + virtual ~CachedLiveNodeList(); + + unsigned length() const final { return m_indexCache.nodeCount(nodeList()); } + Element* item(unsigned offset) const override { return m_indexCache.nodeAt(nodeList(), offset); } + + // For CollectionIndexCache + ElementDescendantIterator collectionBegin() const { return CollectionTraversal<CollectionTraversalType::Descendants>::begin(nodeList(), rootNode()); } + ElementDescendantIterator collectionLast() const { return CollectionTraversal<CollectionTraversalType::Descendants>::last(nodeList(), rootNode()); } + ElementDescendantIterator collectionEnd() const { return ElementDescendantIterator(); } + void collectionTraverseForward(ElementDescendantIterator& current, unsigned count, unsigned& traversedCount) const { CollectionTraversal<CollectionTraversalType::Descendants>::traverseForward(nodeList(), current, count, traversedCount); } + void collectionTraverseBackward(ElementDescendantIterator& current, unsigned count) const { CollectionTraversal<CollectionTraversalType::Descendants>::traverseBackward(nodeList(), current, count); } + bool collectionCanTraverseBackward() const { return true; } + void willValidateIndexCache() const { document().registerNodeListForInvalidation(const_cast<CachedLiveNodeList<NodeListType>&>(*this)); } + + void invalidateCache(Document&) const final; + size_t memoryCost() const final { return m_indexCache.memoryCost(); } - const unsigned m_rootType : 2; - const unsigned m_invalidationType : 4; - const unsigned m_type : 5; +protected: + CachedLiveNodeList(ContainerNode& rootNode, NodeListInvalidationType); + +private: + NodeListType& nodeList() { return static_cast<NodeListType&>(*this); } + const NodeListType& nodeList() const { return static_cast<const NodeListType&>(*this); } + + ContainerNode& rootNode() const; + + mutable CollectionIndexCache<NodeListType, ElementDescendantIterator> m_indexCache; }; ALWAYS_INLINE bool shouldInvalidateTypeOnAttributeChange(NodeListInvalidationType type, const QualifiedName& attrName) @@ -125,8 +113,8 @@ ALWAYS_INLINE bool shouldInvalidateTypeOnAttributeChange(NodeListInvalidationTyp return attrName == HTMLNames::nameAttr; case InvalidateOnIdNameAttrChange: return attrName == HTMLNames::idAttr || attrName == HTMLNames::nameAttr; - case InvalidateOnForAttrChange: - return attrName == HTMLNames::forAttr; + case InvalidateOnForTypeAttrChange: + return attrName == HTMLNames::forAttr || attrName == HTMLNames::typeAttr; case InvalidateForFormControls: return attrName == HTMLNames::nameAttr || attrName == HTMLNames::idAttr || attrName == HTMLNames::forAttr || attrName == HTMLNames::formAttr || attrName == HTMLNames::typeAttr; @@ -140,6 +128,36 @@ ALWAYS_INLINE bool shouldInvalidateTypeOnAttributeChange(NodeListInvalidationTyp return false; } -} // namespace WebCore +template <class NodeListType> +CachedLiveNodeList<NodeListType>::CachedLiveNodeList(ContainerNode& ownerNode, NodeListInvalidationType invalidationType) + : LiveNodeList(ownerNode, invalidationType) + , m_indexCache(nodeList()) +{ +} + +template <class NodeListType> +CachedLiveNodeList<NodeListType>::~CachedLiveNodeList() +{ + if (m_indexCache.hasValidCache(nodeList())) + document().unregisterNodeListForInvalidation(*this); +} + +template <class NodeListType> +inline ContainerNode& CachedLiveNodeList<NodeListType>::rootNode() const +{ + if (nodeList().isRootedAtDocument() && ownerNode().isConnected()) + return ownerNode().document(); + + return ownerNode(); +} -#endif // LiveNodeList_h +template <class NodeListType> +void CachedLiveNodeList<NodeListType>::invalidateCache(Document& document) const +{ + if (!m_indexCache.hasValidCache(nodeList())) + return; + document.unregisterNodeListForInvalidation(const_cast<NodeListType&>(nodeList())); + m_indexCache.invalidate(nodeList()); +} + +} // namespace WebCore |