summaryrefslogtreecommitdiff
path: root/Source/WebCore/dom/LiveNodeList.h
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/dom/LiveNodeList.h')
-rw-r--r--Source/WebCore/dom/LiveNodeList.h148
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