Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(73)

Side by Side Diff: Source/core/dom/LiveNodeListBase.h

Issue 229213002: Make HTMLCollection / NodeList backward traversal consistent with forward one (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 /* 1 /*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org) 3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * (C) 2001 Dirk Mueller (mueller@kde.org) 4 * (C) 2001 Dirk Mueller (mueller@kde.org)
5 * Copyright (C) 2004, 2006, 2007 Apple Inc. All rights reserved. 5 * Copyright (C) 2004, 2006, 2007 Apple Inc. All rights reserved.
6 * Copyright (C) 2014 Samsung Electronics. All rights reserved. 6 * Copyright (C) 2014 Samsung Electronics. All rights reserved.
7 * 7 *
8 * This library is free software; you can redistribute it and/or 8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public 9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either 10 * License as published by the Free Software Foundation; either
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
77 } 77 }
78 virtual void invalidateCache(Document* oldDocument = 0) const = 0; 78 virtual void invalidateCache(Document* oldDocument = 0) const = 0;
79 79
80 static bool shouldInvalidateTypeOnAttributeChange(NodeListInvalidationType, const QualifiedName&); 80 static bool shouldInvalidateTypeOnAttributeChange(NodeListInvalidationType, const QualifiedName&);
81 81
82 protected: 82 protected:
83 Document& document() const { return m_ownerNode->document(); } 83 Document& document() const { return m_ownerNode->document(); }
84 84
85 ALWAYS_INLINE NodeListRootType rootType() const { return static_cast<NodeLis tRootType>(m_rootType); } 85 ALWAYS_INLINE NodeListRootType rootType() const { return static_cast<NodeLis tRootType>(m_rootType); }
86 86
87 template <typename Collection>
88 static Element* itemBefore(const Collection&, const Element* previousItem);
89 template <class NodeListType> 87 template <class NodeListType>
90 static Element* firstMatchingElement(const NodeListType&); 88 static Element* firstMatchingElement(const NodeListType&);
91 template <class NodeListType> 89 template <class NodeListType>
90 static Element* lastMatchingElement(const NodeListType&);
91 template <class NodeListType>
92 static Element* nextMatchingElement(const NodeListType&, Element& current); 92 static Element* nextMatchingElement(const NodeListType&, Element& current);
93 template <class NodeListType> 93 template <class NodeListType>
94 static Element* previousMatchingElement(const NodeListType&, Element& curren t);
95 template <class NodeListType>
94 static Element* traverseMatchingElementsForwardToOffset(const NodeListType&, unsigned offset, Element& currentElement, unsigned& currentOffset); 96 static Element* traverseMatchingElementsForwardToOffset(const NodeListType&, unsigned offset, Element& currentElement, unsigned& currentOffset);
97 template <class NodeListType>
98 static Element* traverseMatchingElementsBackwardToOffset(const NodeListType& , unsigned offset, Element& currentElement, unsigned& currentOffset);
95 99
96 private: 100 private:
97 void invalidateIdNameCacheMaps() const; 101 void invalidateIdNameCacheMaps() const;
98 template <typename Collection>
99 static Element* iterateForPreviousNode(const Collection&, Node* current);
100 static Node* previousNode(const ContainerNode&, const Node& previous, bool o nlyIncludeDirectChildren);
101 static Node* lastDescendant(const ContainerNode&);
102 static Node* lastNode(const ContainerNode&, bool onlyIncludeDirectChildren);
103 102
104 RefPtr<ContainerNode> m_ownerNode; // Cannot be null. 103 RefPtr<ContainerNode> m_ownerNode; // Cannot be null.
105 const unsigned m_rootType : 1; 104 const unsigned m_rootType : 1;
106 const unsigned m_invalidationType : 4; 105 const unsigned m_invalidationType : 4;
107 const unsigned m_collectionType : 5; 106 const unsigned m_collectionType : 5;
108 }; 107 };
109 108
110 ALWAYS_INLINE bool LiveNodeListBase::shouldInvalidateTypeOnAttributeChange(NodeL istInvalidationType type, const QualifiedName& attrName) 109 ALWAYS_INLINE bool LiveNodeListBase::shouldInvalidateTypeOnAttributeChange(NodeL istInvalidationType type, const QualifiedName& attrName)
111 { 110 {
112 switch (type) { 111 switch (type) {
(...skipping 11 matching lines...) Expand all
124 case InvalidateOnHRefAttrChange: 123 case InvalidateOnHRefAttrChange:
125 return attrName == HTMLNames::hrefAttr; 124 return attrName == HTMLNames::hrefAttr;
126 case DoNotInvalidateOnAttributeChanges: 125 case DoNotInvalidateOnAttributeChanges:
127 return false; 126 return false;
128 case InvalidateOnAnyAttrChange: 127 case InvalidateOnAnyAttrChange:
129 return true; 128 return true;
130 } 129 }
131 return false; 130 return false;
132 } 131 }
133 132
134 inline Node* LiveNodeListBase::previousNode(const ContainerNode& base, const Nod e& previous, bool onlyIncludeDirectChildren) 133 template <typename NodeListType>
134 Element* LiveNodeListBase::lastMatchingElement(const NodeListType& nodeList)
135 { 135 {
136 return onlyIncludeDirectChildren ? previous.previousSibling() : NodeTraversa l::previous(previous, &base); 136 ContainerNode& root = nodeList.rootNode();
137 } 137 Element* element = ElementTraversal::lastWithin(root);
138 138 while (element && !isMatchingElement(nodeList, *element))
139 inline Node* LiveNodeListBase::lastDescendant(const ContainerNode& node) 139 element = ElementTraversal::previous(*element, &root);
140 { 140 return element;
141 Node* descendant = node.lastChild();
142 for (Node* current = descendant; current; current = current->lastChild())
143 descendant = current;
144 return descendant;
145 }
146
147 inline Node* LiveNodeListBase::lastNode(const ContainerNode& rootNode, bool only IncludeDirectChildren)
148 {
149 return onlyIncludeDirectChildren ? rootNode.lastChild() : lastDescendant(roo tNode);
150 }
151
152 template <typename Collection>
153 Element* LiveNodeListBase::iterateForPreviousNode(const Collection& collection, Node* current)
154 {
155 bool onlyIncludeDirectChildren = collection.shouldOnlyIncludeDirectChildren( );
156 ContainerNode& rootNode = collection.rootNode();
157 for (; current; current = previousNode(rootNode, *current, onlyIncludeDirect Children)) {
158 if (current->isElementNode() && isMatchingElement(collection, toElement( *current)))
159 return toElement(current);
160 }
161 return 0;
162 }
163
164 template <typename Collection>
165 Element* LiveNodeListBase::itemBefore(const Collection& collection, const Elemen t* previous)
166 {
167 Node* current;
168 if (LIKELY(!!previous)) // Without this LIKELY, length() and item() can be 1 0% slower.
Inactive 2014/04/09 23:08:58 This if check is now avoided as the current caller
169 current = previousNode(collection.rootNode(), *previous, collection.shou ldOnlyIncludeDirectChildren());
170 else
171 current = lastNode(collection.rootNode(), collection.shouldOnlyIncludeDi rectChildren());
172
173 return iterateForPreviousNode(collection, current);
174 } 141 }
175 142
176 template <class NodeListType> 143 template <class NodeListType>
177 Element* LiveNodeListBase::firstMatchingElement(const NodeListType& nodeList) 144 Element* LiveNodeListBase::firstMatchingElement(const NodeListType& nodeList)
178 { 145 {
179 ContainerNode& root = nodeList.rootNode(); 146 ContainerNode& root = nodeList.rootNode();
180 Element* element = ElementTraversal::firstWithin(root); 147 Element* element = ElementTraversal::firstWithin(root);
181 while (element && !isMatchingElement(nodeList, *element)) 148 while (element && !isMatchingElement(nodeList, *element))
182 element = ElementTraversal::next(*element, &root); 149 element = ElementTraversal::next(*element, &root);
183 return element; 150 return element;
184 } 151 }
185 152
186 template <class NodeListType> 153 template <class NodeListType>
187 Element* LiveNodeListBase::nextMatchingElement(const NodeListType& nodeList, Ele ment& current) 154 Element* LiveNodeListBase::nextMatchingElement(const NodeListType& nodeList, Ele ment& current)
188 { 155 {
189 ContainerNode& root = nodeList.rootNode(); 156 ContainerNode& root = nodeList.rootNode();
190 Element* next = &current; 157 Element* next = &current;
191 do { 158 do {
192 next = ElementTraversal::next(*next, &root); 159 next = ElementTraversal::next(*next, &root);
193 } while (next && !isMatchingElement(nodeList, *next)); 160 } while (next && !isMatchingElement(nodeList, *next));
194 return next; 161 return next;
195 } 162 }
196 163
197 template <class NodeListType> 164 template <class NodeListType>
165 Element* LiveNodeListBase::previousMatchingElement(const NodeListType& nodeList, Element& current)
166 {
167 ContainerNode& root = nodeList.rootNode();
168 Element* previous = &current;
169 do {
170 previous = ElementTraversal::previous(*previous, &root);
171 } while (previous && !isMatchingElement(nodeList, *previous));
172 return previous;
173 }
174
175 template <class NodeListType>
198 Element* LiveNodeListBase::traverseMatchingElementsForwardToOffset(const NodeLis tType& nodeList, unsigned offset, Element& currentElement, unsigned& currentOffs et) 176 Element* LiveNodeListBase::traverseMatchingElementsForwardToOffset(const NodeLis tType& nodeList, unsigned offset, Element& currentElement, unsigned& currentOffs et)
199 { 177 {
200 ASSERT(currentOffset < offset); 178 ASSERT(currentOffset < offset);
201 Element* next = &currentElement; 179 Element* next = &currentElement;
202 while ((next = nextMatchingElement(nodeList, *next))) { 180 while ((next = nextMatchingElement(nodeList, *next))) {
203 if (++currentOffset == offset) 181 if (++currentOffset == offset)
204 return next; 182 return next;
205 } 183 }
206 return 0; 184 return 0;
207 } 185 }
208 186
187 template <class NodeListType>
188 Element* LiveNodeListBase::traverseMatchingElementsBackwardToOffset(const NodeLi stType& nodeList, unsigned offset, Element& currentElement, unsigned& currentOff set)
189 {
190 ASSERT(currentOffset > offset);
191 Element* previous = &currentElement;
192 while ((previous = previousMatchingElement(nodeList, *previous))) {
193 if (--currentOffset == offset)
194 return previous;
195 }
196 return 0;
197 }
198
209 } // namespace WebCore 199 } // namespace WebCore
210 200
211 #endif // LiveNodeListBase_h 201 #endif // LiveNodeListBase_h
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698