2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * (C) 2001 Dirk Mueller (mueller@kde.org)
5 * Copyright (C) 2004, 2006, 2007 Apple Inc. All rights reserved.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public License
18 * along with this library; see the file COPYING.LIB. If not, write to
19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
24 #ifndef DynamicNodeList_h
25 #define DynamicNodeList_h
27 #include "CollectionType.h"
29 #include "HTMLNames.h"
31 #include <wtf/Forward.h>
32 #include <wtf/RefPtr.h>
39 enum NodeListRootType {
40 NodeListIsRootedAtNode,
41 NodeListIsRootedAtDocument,
44 class DynamicNodeListCacheBase {
46 DynamicNodeListCacheBase(NodeListRootType rootType, NodeListInvalidationType invalidationType, CollectionType collectionType = InvalidCollectionType)
48 , m_isLengthCacheValid(false)
49 , m_isItemCacheValid(false)
50 , m_rootedAtDocument(rootType == NodeListIsRootedAtDocument)
51 , m_invalidationType(invalidationType)
52 , m_isNameCacheValid(false)
53 , m_collectionType(collectionType)
55 ASSERT(m_invalidationType == static_cast<unsigned>(invalidationType));
56 ASSERT(m_collectionType == static_cast<unsigned>(collectionType));
60 ALWAYS_INLINE bool isRootedAtDocument() const { return m_rootedAtDocument; }
61 ALWAYS_INLINE NodeListInvalidationType invalidationType() const { return static_cast<NodeListInvalidationType>(m_invalidationType); }
62 ALWAYS_INLINE CollectionType type() const { return static_cast<CollectionType>(m_collectionType); }
64 void invalidateCache() const;
66 static bool shouldInvalidateTypeOnAttributeChange(NodeListInvalidationType, const QualifiedName&);
69 ALWAYS_INLINE bool isItemCacheValid() const { return m_isItemCacheValid; }
70 ALWAYS_INLINE Node* cachedItem() const { return m_cachedItem; }
71 ALWAYS_INLINE unsigned cachedItemOffset() const { return m_cachedItemOffset; }
73 ALWAYS_INLINE bool isLengthCacheValid() const { return m_isLengthCacheValid; }
74 ALWAYS_INLINE unsigned cachedLength() const { return m_cachedLength; }
75 ALWAYS_INLINE void setLengthCache(unsigned length) const
77 m_cachedLength = length;
78 m_isLengthCacheValid = true;
80 ALWAYS_INLINE void setItemCache(Node* item, unsigned offset) const
82 // FIXME: Assert that item is not null once we've updated DynamicNodeList.
84 m_cachedItemOffset = offset;
85 m_isItemCacheValid = true;
88 bool hasNameCache() const { return m_isNameCacheValid; }
89 void setHasNameCache() const { m_isNameCacheValid = true; }
92 mutable Node* m_cachedItem;
93 mutable unsigned m_cachedLength;
94 mutable unsigned m_cachedItemOffset;
95 mutable unsigned m_isLengthCacheValid : 1;
96 mutable unsigned m_isItemCacheValid : 1;
97 const unsigned m_rootedAtDocument : 1;
98 const unsigned m_invalidationType : 4;
100 // From HTMLCollection
101 mutable unsigned m_isNameCacheValid : 1;
102 const unsigned m_collectionType : 5;
105 ALWAYS_INLINE bool DynamicNodeListCacheBase::shouldInvalidateTypeOnAttributeChange(NodeListInvalidationType type, const QualifiedName& attrName)
108 case InvalidateOnClassAttrChange:
109 return attrName == HTMLNames::classAttr;
110 case InvalidateOnNameAttrChange:
111 return attrName == HTMLNames::nameAttr;
112 case InvalidateOnIdNameAttrChange:
113 return attrName == HTMLNames::idAttr || attrName == HTMLNames::nameAttr;
114 case InvalidateOnForAttrChange:
115 return attrName == HTMLNames::forAttr;
116 case InvalidateForFormControls:
117 return attrName == HTMLNames::nameAttr || attrName == HTMLNames::idAttr || attrName == HTMLNames::forAttr || attrName == HTMLNames::typeAttr;
118 case InvalidateOnHRefAttrChange:
119 return attrName == HTMLNames::hrefAttr;
120 case InvalidateOnItemAttrChange:
121 #if ENABLE(MICRODATA)
122 return attrName == HTMLNames::itemscopeAttr || attrName == HTMLNames::itempropAttr || attrName == HTMLNames::itemtypeAttr;
123 #endif // Intentionally fall through
124 case DoNotInvalidateOnAttributeChanges:
125 ASSERT_NOT_REACHED();
127 case InvalidateOnAnyAttrChange:
133 class DynamicNodeList : public NodeList, public DynamicNodeListCacheBase {
142 MicroDataItemListType,
144 DynamicNodeList(PassRefPtr<Node> ownerNode, NodeListRootType rootType, NodeListInvalidationType invalidationType)
145 : DynamicNodeListCacheBase(rootType, invalidationType)
146 , m_ownerNode(ownerNode)
148 virtual ~DynamicNodeList() { }
150 // DOM methods & attributes for NodeList
151 virtual unsigned length() const = 0;
152 virtual Node* item(unsigned index) const = 0;
153 virtual Node* itemWithName(const AtomicString&) const;
155 // Other methods (not part of DOM)
156 Node* ownerNode() const { return m_ownerNode.get(); }
159 Node* rootNode() const
161 if (isRootedAtDocument() && m_ownerNode->inDocument())
162 return m_ownerNode->document();
163 return m_ownerNode.get();
165 Document* document() const { return m_ownerNode->document(); }
166 virtual bool nodeMatches(Element*) const = 0;
169 virtual bool isDynamicNodeList() const OVERRIDE { return true; }
170 RefPtr<Node> m_ownerNode;
173 class DynamicSubtreeNodeList : public DynamicNodeList {
175 virtual ~DynamicSubtreeNodeList()
177 document()->unregisterNodeListCache(this);
179 virtual unsigned length() const OVERRIDE;
180 virtual Node* item(unsigned index) const OVERRIDE;
183 DynamicSubtreeNodeList(PassRefPtr<Node> node, NodeListInvalidationType invalidationType, NodeListRootType rootType = NodeListIsRootedAtNode)
184 : DynamicNodeList(node, rootType, invalidationType)
186 document()->registerNodeListCache(this);
190 Node* itemForwardsFromCurrent(Node* start, unsigned offset, int remainingOffset) const;
191 Node* itemBackwardsFromCurrent(Node* start, unsigned offset, int remainingOffset) const;
194 } // namespace WebCore
196 #endif // DynamicNodeList_h