5e69e9a0d8606f9327092643504c3c9f68839cf5
[WebKit-https.git] / Source / WebCore / dom / LiveNodeList.h
1 /*
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, 2013 Apple Inc. All rights reserved.
6  *
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.
11  *
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.
16  *
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.
21  *
22  */
23
24 #ifndef LiveNodeList_h
25 #define LiveNodeList_h
26
27 #include "CollectionIndexCache.h"
28 #include "CollectionType.h"
29 #include "Document.h"
30 #include "HTMLNames.h"
31 #include "NodeList.h"
32 #include <wtf/Forward.h>
33 #include <wtf/RefPtr.h>
34
35 namespace WebCore {
36
37 class Element;
38
39 enum NodeListRootType {
40     NodeListIsRootedAtNode,
41     NodeListIsRootedAtDocument
42 };
43
44 static bool shouldInvalidateTypeOnAttributeChange(NodeListInvalidationType, const QualifiedName&);
45
46 class LiveNodeList : public NodeList {
47 public:
48     enum class Type {
49         ClassNodeListType,
50         NameNodeListType,
51         TagNodeListType,
52         HTMLTagNodeListType,
53         RadioNodeListType,
54         LabelsNodeListType,
55     };
56
57     LiveNodeList(ContainerNode& ownerNode, Type type, NodeListInvalidationType invalidationType, NodeListRootType rootType = NodeListIsRootedAtNode)
58         : m_ownerNode(ownerNode)
59         , m_rootType(rootType)
60         , m_invalidationType(invalidationType)
61         , m_type(static_cast<unsigned>(type))
62     {
63         ASSERT(m_rootType == static_cast<unsigned>(rootType));
64         ASSERT(m_invalidationType == static_cast<unsigned>(invalidationType));
65         ASSERT(m_type == static_cast<unsigned>(type));
66     }
67     virtual Node* namedItem(const AtomicString&) const override final;
68     virtual bool nodeMatches(Element*) const = 0;
69
70     virtual ~LiveNodeList()
71     {
72         if (m_indexCache.hasValidCache())
73             document().unregisterNodeList(*this);
74     }
75
76     // DOM API
77     virtual unsigned length() const override final;
78     virtual Node* item(unsigned offset) const override final;
79     virtual size_t memoryCost() const override;
80
81     ALWAYS_INLINE bool isRootedAtDocument() const { return m_rootType == NodeListIsRootedAtDocument; }
82     ALWAYS_INLINE NodeListInvalidationType invalidationType() const { return static_cast<NodeListInvalidationType>(m_invalidationType); }
83     ALWAYS_INLINE Type type() const { return static_cast<Type>(m_type); }
84     ContainerNode& ownerNode() const { return const_cast<ContainerNode&>(m_ownerNode.get()); }
85     ALWAYS_INLINE void invalidateCache(const QualifiedName* attrName) const
86     {
87         if (!attrName || shouldInvalidateTypeOnAttributeChange(invalidationType(), *attrName))
88             invalidateCache(document());
89     }
90     void invalidateCache(Document&) const;
91
92     // For CollectionIndexCache
93     Element* collectionFirst() const;
94     Element* collectionLast() const;
95     Element* collectionTraverseForward(Element&, unsigned count, unsigned& traversedCount) const;
96     Element* collectionTraverseBackward(Element&, unsigned count) const;
97     bool collectionCanTraverseBackward() const { return true; }
98     void willValidateIndexCache() const { document().registerNodeList(const_cast<LiveNodeList&>(*this)); }
99
100 protected:
101     Document& document() const { return m_ownerNode->document(); }
102     ContainerNode& rootNode() const;
103
104     ALWAYS_INLINE NodeListRootType rootType() const { return static_cast<NodeListRootType>(m_rootType); }
105
106 private:
107     virtual bool isLiveNodeList() const override { return true; }
108
109     Element* iterateForPreviousElement(Element* current) const;
110
111     Ref<ContainerNode> m_ownerNode;
112
113     mutable CollectionIndexCache<LiveNodeList, Element> m_indexCache;
114
115     const unsigned m_rootType : 1;
116     const unsigned m_invalidationType : 4;
117     const unsigned m_type : 3;
118 };
119
120 ALWAYS_INLINE bool shouldInvalidateTypeOnAttributeChange(NodeListInvalidationType type, const QualifiedName& attrName)
121 {
122     switch (type) {
123     case InvalidateOnClassAttrChange:
124         return attrName == HTMLNames::classAttr;
125     case InvalidateOnNameAttrChange:
126         return attrName == HTMLNames::nameAttr;
127     case InvalidateOnIdNameAttrChange:
128         return attrName == HTMLNames::idAttr || attrName == HTMLNames::nameAttr;
129     case InvalidateOnForAttrChange:
130         return attrName == HTMLNames::forAttr;
131     case InvalidateForFormControls:
132         return attrName == HTMLNames::nameAttr || attrName == HTMLNames::idAttr || attrName == HTMLNames::forAttr
133             || attrName == HTMLNames::formAttr || attrName == HTMLNames::typeAttr;
134     case InvalidateOnHRefAttrChange:
135         return attrName == HTMLNames::hrefAttr;
136     case DoNotInvalidateOnAttributeChanges:
137         return false;
138     case InvalidateOnAnyAttrChange:
139         return true;
140     }
141     return false;
142 }
143
144 } // namespace WebCore
145
146 #endif // LiveNodeList_h