Changeset 166460 in webkit
- Timestamp:
- Mar 30, 2014 1:32:13 AM (10 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r166459 r166460 1 2014-03-29 Antti Koivisto <antti@apple.com> 2 3 LiveNodeLists should use ElementDescendantIterator 4 https://bugs.webkit.org/show_bug.cgi?id=130931 5 6 Reviewed by Andreas Kling. 7 8 Make LiveNodeList traversal use the common DOM tree iterator. 9 10 * dom/ChildNodeList.cpp: 11 (WebCore::ChildNodeList::ChildNodeList): 12 (WebCore::ChildNodeList::collectionBegin): 13 (WebCore::ChildNodeList::collectionTraverseForward): 14 (WebCore::ChildNodeList::collectionTraverseBackward): 15 (WebCore::ChildNodeList::invalidateCache): 16 (WebCore::ChildNodeList::collectionFirst): Deleted. 17 18 Iterator for ChildNodeList is still just Node*. 19 20 * dom/ChildNodeList.h: 21 * dom/CollectionIndexCache.h: 22 (WebCore::CollectionIndexCache::hasValidCache): 23 (WebCore::Iterator>::CollectionIndexCache): 24 (WebCore::Iterator>::nodeCount): 25 (WebCore::Iterator>::computeNodeCountUpdatingListCache): 26 (WebCore::Iterator>::traverseBackwardTo): 27 (WebCore::Iterator>::traverseForwardTo): 28 (WebCore::Iterator>::nodeAt): 29 (WebCore::Iterator>::invalidate): 30 31 Make CollectionIndexCache iterator based instead of using NodeType*. The iterator type may 32 still be a Node* though. 33 34 (WebCore::NodeType>::CollectionIndexCache): Deleted. 35 (WebCore::NodeType>::nodeCount): Deleted. 36 (WebCore::NodeType>::computeNodeCountUpdatingListCache): Deleted. 37 (WebCore::NodeType>::nodeBeforeCached): Deleted. 38 (WebCore::NodeType>::nodeAfterCached): Deleted. 39 (WebCore::NodeType>::nodeAt): Deleted. 40 (WebCore::NodeType>::invalidate): Deleted. 41 * dom/ElementDescendantIterator.h: 42 (WebCore::ElementDescendantIterator::operator--): 43 44 Add backward iteration support. 45 46 (WebCore::ElementDescendantIteratorAdapter::last): 47 (WebCore::ElementDescendantConstIteratorAdapter::last): 48 49 Add a way to get the last item. 50 Provide std::iterator_traits so we can extract the type. 51 52 * dom/LiveNodeList.h: 53 (WebCore::CachedLiveNodeList::collectionEnd): 54 (WebCore::CachedLiveNodeList<NodeListType>::CachedLiveNodeList): 55 (WebCore::CachedLiveNodeList<NodeListType>::~CachedLiveNodeList): 56 (WebCore::CachedLiveNodeList<NodeListType>::collectionBegin): 57 (WebCore::CachedLiveNodeList<NodeListType>::collectionLast): 58 (WebCore::CachedLiveNodeList<NodeListType>::collectionTraverseForward): 59 (WebCore::CachedLiveNodeList<NodeListType>::collectionTraverseBackward): 60 (WebCore::CachedLiveNodeList<NodeListType>::invalidateCache): 61 (WebCore::CachedLiveNodeList<NodeListType>::collectionFirst): Deleted. 62 63 Make LiveNodeList traversal use ElementDescendantIterator. 64 65 (WebCore::nextMatchingElement): Deleted. 66 (WebCore::previousMatchingElement): Deleted. 67 * html/HTMLCollection.cpp: 68 (WebCore::HTMLCollection::HTMLCollection): 69 (WebCore::HTMLCollection::~HTMLCollection): 70 (WebCore::HTMLCollection::collectionBegin): 71 (WebCore::HTMLCollection::collectionTraverseForward): 72 (WebCore::HTMLCollection::collectionTraverseBackward): 73 (WebCore::HTMLCollection::invalidateCache): 74 (WebCore::HTMLCollection::collectionFirst): Deleted. 75 * html/HTMLCollection.h: 76 (WebCore::HTMLCollection::collectionEnd): 77 78 HTMLCollection still uses Element* as iterator for now. 79 1 80 2014-03-29 Commit Queue <commit-queue@webkit.org> 2 81 -
trunk/Source/WebCore/dom/ChildNodeList.cpp
r161196 r166460 36 36 ChildNodeList::ChildNodeList(ContainerNode& parent) 37 37 : m_parent(parent) 38 , m_indexCache(*this) 38 39 { 39 40 } … … 54 55 } 55 56 56 Node* ChildNodeList::collection First() const57 Node* ChildNodeList::collectionBegin() const 57 58 { 58 59 return m_parent->firstChild(); … … 64 65 } 65 66 66 Node* ChildNodeList::collectionTraverseForward(Node& current, unsigned count, unsigned& traversedCount) const67 void ChildNodeList::collectionTraverseForward(Node*& current, unsigned count, unsigned& traversedCount) const 67 68 { 68 69 ASSERT(count); 69 Node* child = ¤t;70 70 for (traversedCount = 0; traversedCount < count; ++traversedCount) { 71 c hild = child->nextSibling();72 if (!c hild)73 return nullptr;71 current = current->nextSibling(); 72 if (!current) 73 return; 74 74 } 75 return child;76 75 } 77 76 78 Node* ChildNodeList::collectionTraverseBackward(Node& current, unsigned count) const77 void ChildNodeList::collectionTraverseBackward(Node*& current, unsigned count) const 79 78 { 80 79 ASSERT(count); 81 Node* child = ¤t; 82 for (; count && child ; --count) 83 child = child->previousSibling(); 84 return child; 80 for (; count && current ; --count) 81 current = current->previousSibling(); 85 82 } 86 83 … … 104 101 void ChildNodeList::invalidateCache() 105 102 { 106 m_indexCache.invalidate( );103 m_indexCache.invalidate(*this); 107 104 } 108 105 -
trunk/Source/WebCore/dom/ChildNodeList.h
r165103 r166460 71 71 72 72 // For CollectionIndexCache 73 Node* collection First() const;73 Node* collectionBegin() const; 74 74 Node* collectionLast() const; 75 Node* collectionTraverseForward(Node&, unsigned count, unsigned& traversedCount) const; 76 Node* collectionTraverseBackward(Node&, unsigned count) const; 75 Node* collectionEnd() const { return nullptr; } 76 void collectionTraverseForward(Node*&, unsigned count, unsigned& traversedCount) const; 77 void collectionTraverseBackward(Node*&, unsigned count) const; 77 78 bool collectionCanTraverseBackward() const { return true; } 78 79 void willValidateIndexCache() const { } … … 89 90 90 91 Ref<ContainerNode> m_parent; 91 mutable CollectionIndexCache<ChildNodeList, Node > m_indexCache;92 mutable CollectionIndexCache<ChildNodeList, Node*> m_indexCache; 92 93 }; 93 94 -
trunk/Source/WebCore/dom/CollectionIndexCache.h
r165103 r166460 33 33 void reportExtraMemoryCostForCollectionIndexCache(size_t); 34 34 35 template <class Collection, class NodeType>35 template <class Collection, class Iterator> 36 36 class CollectionIndexCache { 37 37 public: 38 CollectionIndexCache(); 38 explicit CollectionIndexCache(const Collection&); 39 40 typedef typename std::iterator_traits<Iterator>::value_type NodeType; 39 41 40 42 unsigned nodeCount(const Collection&); 41 43 NodeType* nodeAt(const Collection&, unsigned index); 42 44 43 bool hasValidCache( ) const { return m_currentNode|| m_nodeCountValid || m_listValid; }44 void invalidate( );45 bool hasValidCache(const Collection& collection) const { return m_current != collection.collectionEnd() || m_nodeCountValid || m_listValid; } 46 void invalidate(const Collection&); 45 47 size_t memoryCost() { return m_cachedList.capacity() * sizeof(NodeType*); } 46 48 47 49 private: 48 49 50 unsigned computeNodeCountUpdatingListCache(const Collection&); 50 NodeType* nodeBeforeCached(const Collection&, unsigned);51 NodeType* nodeAfterCached(const Collection&, unsigned);52 53 NodeType* m_currentNode;51 NodeType* traverseBackwardTo(const Collection&, unsigned); 52 NodeType* traverseForwardTo(const Collection&, unsigned); 53 54 Iterator m_current; 54 55 unsigned m_currentIndex; 55 56 unsigned m_nodeCount; … … 59 60 }; 60 61 61 template <class Collection, class NodeType>62 inline CollectionIndexCache<Collection, NodeType>::CollectionIndexCache()63 : m_current Node(nullptr)62 template <class Collection, class Iterator> 63 inline CollectionIndexCache<Collection, Iterator>::CollectionIndexCache(const Collection& collection) 64 : m_current(collection.collectionEnd()) 64 65 , m_currentIndex(0) 65 66 , m_nodeCount(0) … … 69 70 } 70 71 71 template <class Collection, class NodeType>72 inline unsigned CollectionIndexCache<Collection, NodeType>::nodeCount(const Collection& collection)72 template <class Collection, class Iterator> 73 inline unsigned CollectionIndexCache<Collection, Iterator>::nodeCount(const Collection& collection) 73 74 { 74 75 if (!m_nodeCountValid) { 75 if (!hasValidCache( ))76 if (!hasValidCache(collection)) 76 77 collection.willValidateIndexCache(); 77 78 m_nodeCount = computeNodeCountUpdatingListCache(collection); … … 82 83 } 83 84 84 template <class Collection, class NodeType> 85 unsigned CollectionIndexCache<Collection, NodeType>::computeNodeCountUpdatingListCache(const Collection& collection) 86 { 87 NodeType* first = collection.collectionFirst(); 88 if (!first) 85 template <class Collection, class Iterator> 86 unsigned CollectionIndexCache<Collection, Iterator>::computeNodeCountUpdatingListCache(const Collection& collection) 87 { 88 auto current = collection.collectionBegin(); 89 auto end = collection.collectionEnd(); 90 if (current == end) 89 91 return 0; 90 92 91 93 unsigned oldCapacity = m_cachedList.capacity(); 92 NodeType* currentNode = first; 93 while (currentNode) { 94 m_cachedList.append(currentNode); 94 while (current != end) { 95 m_cachedList.append(&*current); 95 96 unsigned traversed; 96 c urrentNode = collection.collectionTraverseForward(*currentNode, 1, traversed);97 ASSERT(traversed == (current Node? 1 : 0));97 collection.collectionTraverseForward(current, 1, traversed); 98 ASSERT(traversed == (current != end ? 1 : 0)); 98 99 } 99 100 m_listValid = true; … … 105 106 } 106 107 107 template <class Collection, class NodeType>108 inline NodeType* CollectionIndexCache<Collection, NodeType>::nodeBeforeCached(const Collection& collection, unsigned index)109 { 110 ASSERT(m_current Node);108 template <class Collection, class Iterator> 109 inline typename CollectionIndexCache<Collection, Iterator>::NodeType* CollectionIndexCache<Collection, Iterator>::traverseBackwardTo(const Collection& collection, unsigned index) 110 { 111 ASSERT(m_current != collection.collectionEnd()); 111 112 ASSERT(index < m_currentIndex); 112 113 113 114 bool firstIsCloser = index < m_currentIndex - index; 114 115 if (firstIsCloser || !collection.collectionCanTraverseBackward()) { 115 m_current Node = collection.collectionFirst();116 m_current = collection.collectionBegin(); 116 117 m_currentIndex = 0; 117 118 if (index) 118 m_currentNode = collection.collectionTraverseForward(*m_currentNode, index, m_currentIndex);119 ASSERT(m_current Node);120 return m_currentNode;121 } 122 123 m_currentNode = collection.collectionTraverseBackward(*m_currentNode, m_currentIndex - index);119 collection.collectionTraverseForward(m_current, index, m_currentIndex); 120 ASSERT(m_current != collection.collectionEnd()); 121 return &*m_current; 122 } 123 124 collection.collectionTraverseBackward(m_current, m_currentIndex - index); 124 125 m_currentIndex = index; 125 126 126 ASSERT(m_current Node);127 return m_currentNode;128 } 129 130 template <class Collection, class NodeType>131 inline NodeType* CollectionIndexCache<Collection, NodeType>::nodeAfterCached(const Collection& collection, unsigned index)132 { 133 ASSERT(m_current Node);127 ASSERT(m_current != collection.collectionEnd()); 128 return &*m_current; 129 } 130 131 template <class Collection, class Iterator> 132 inline typename CollectionIndexCache<Collection, Iterator>::NodeType* CollectionIndexCache<Collection, Iterator>::traverseForwardTo(const Collection& collection, unsigned index) 133 { 134 ASSERT(m_current != collection.collectionEnd()); 134 135 ASSERT(index > m_currentIndex); 135 136 ASSERT(!m_nodeCountValid || index < m_nodeCount); … … 137 138 bool lastIsCloser = m_nodeCountValid && m_nodeCount - index < index - m_currentIndex; 138 139 if (lastIsCloser && collection.collectionCanTraverseBackward()) { 139 ASSERT(hasValidCache( ));140 m_current Node= collection.collectionLast();140 ASSERT(hasValidCache(collection)); 141 m_current = collection.collectionLast(); 141 142 if (index < m_nodeCount - 1) 142 m_currentNode = collection.collectionTraverseBackward(*m_currentNode, m_nodeCount - index - 1);143 collection.collectionTraverseBackward(m_current, m_nodeCount - index - 1); 143 144 m_currentIndex = index; 144 ASSERT(m_current Node);145 return m_currentNode;146 } 147 148 if (!hasValidCache( ))145 ASSERT(m_current != collection.collectionEnd()); 146 return &*m_current; 147 } 148 149 if (!hasValidCache(collection)) 149 150 collection.willValidateIndexCache(); 150 151 151 152 unsigned traversedCount; 152 m_currentNode = collection.collectionTraverseForward(*m_currentNode, index - m_currentIndex, traversedCount);153 collection.collectionTraverseForward(m_current, index - m_currentIndex, traversedCount); 153 154 m_currentIndex = m_currentIndex + traversedCount; 154 155 155 ASSERT(m_currentNode || m_currentIndex < index); 156 157 if (!m_currentNode && !m_nodeCountValid) { 156 if (m_current == collection.collectionEnd()) { 157 ASSERT(m_currentIndex < index); 158 158 // Failed to find the index but at least we now know the size. 159 159 m_nodeCount = m_currentIndex + 1; 160 160 m_nodeCountValid = true; 161 } 162 ASSERT(hasValidCache()); 163 return m_currentNode; 164 } 165 166 template <class Collection, class NodeType> 167 inline NodeType* CollectionIndexCache<Collection, NodeType>::nodeAt(const Collection& collection, unsigned index) 161 return nullptr; 162 } 163 ASSERT(hasValidCache(collection)); 164 return &*m_current; 165 } 166 167 template <class Collection, class Iterator> 168 inline typename CollectionIndexCache<Collection, Iterator>::NodeType* CollectionIndexCache<Collection, Iterator>::nodeAt(const Collection& collection, unsigned index) 168 169 { 169 170 if (m_nodeCountValid && index >= m_nodeCount) … … 173 174 return m_cachedList[index]; 174 175 175 if (m_currentNode) { 176 auto end = collection.collectionEnd(); 177 if (m_current != end) { 176 178 if (index > m_currentIndex) 177 return nodeAfterCached(collection, index);179 return traverseForwardTo(collection, index); 178 180 if (index < m_currentIndex) 179 return nodeBeforeCached(collection, index);180 return m_currentNode;181 return traverseBackwardTo(collection, index); 182 return &*m_current; 181 183 } 182 184 183 185 bool lastIsCloser = m_nodeCountValid && m_nodeCount - index < index; 184 186 if (lastIsCloser && collection.collectionCanTraverseBackward()) { 185 ASSERT(hasValidCache( ));186 m_current Node= collection.collectionLast();187 ASSERT(hasValidCache(collection)); 188 m_current = collection.collectionLast(); 187 189 if (index < m_nodeCount - 1) 188 m_currentNode = collection.collectionTraverseBackward(*m_currentNode, m_nodeCount - index - 1);190 collection.collectionTraverseBackward(m_current, m_nodeCount - index - 1); 189 191 m_currentIndex = index; 190 ASSERT(m_current Node);191 return m_currentNode;192 } 193 194 if (!hasValidCache( ))192 ASSERT(m_current != end); 193 return &*m_current; 194 } 195 196 if (!hasValidCache(collection)) 195 197 collection.willValidateIndexCache(); 196 198 197 m_current Node = collection.collectionFirst();199 m_current = collection.collectionBegin(); 198 200 m_currentIndex = 0; 199 if (index && m_current Node) {200 m_currentNode = collection.collectionTraverseForward(*m_currentNode, index, m_currentIndex);201 ASSERT(m_current Node|| m_currentIndex < index);202 } 203 if ( !m_currentNode && !m_nodeCountValid) {201 if (index && m_current != end) { 202 collection.collectionTraverseForward(m_current, index, m_currentIndex); 203 ASSERT(m_current != end || m_currentIndex < index); 204 } 205 if (m_current == end) { 204 206 // Failed to find the index but at least we now know the size. 205 207 m_nodeCount = m_currentIndex + 1; 206 208 m_nodeCountValid = true; 207 } 208 ASSERT(hasValidCache()); 209 return m_currentNode; 210 } 211 212 template <class Collection, class NodeType> 213 void CollectionIndexCache<Collection, NodeType>::invalidate() 214 { 215 m_currentNode = nullptr; 209 return nullptr; 210 } 211 ASSERT(hasValidCache(collection)); 212 return &*m_current; 213 } 214 215 template <class Collection, class Iterator> 216 void CollectionIndexCache<Collection, Iterator>::invalidate(const Collection& collection) 217 { 218 m_current = collection.collectionEnd(); 216 219 m_nodeCountValid = false; 217 220 m_listValid = false; -
trunk/Source/WebCore/dom/ElementDescendantIterator.h
r165822 r166460 40 40 41 41 ElementDescendantIterator& operator++(); 42 ElementDescendantIterator& operator--(); 42 43 43 44 Element& operator*(); … … 83 84 ElementDescendantIterator begin(); 84 85 ElementDescendantIterator end(); 86 ElementDescendantIterator last(); 85 87 86 88 private: … … 93 95 ElementDescendantConstIterator begin() const; 94 96 ElementDescendantConstIterator end() const; 97 ElementDescendantConstIterator last() const; 95 98 96 99 private: … … 145 148 } 146 149 150 ALWAYS_INLINE ElementDescendantIterator& ElementDescendantIterator::operator--() 151 { 152 ASSERT(m_current); 153 ASSERT(!m_assertions.domTreeHasMutated()); 154 155 Element* previousSibling = ElementTraversal::previousSibling(m_current); 156 157 if (!previousSibling) { 158 m_current = m_current->parentElement(); 159 // The stack optimizes for forward traversal only, this just maintains consistency. 160 if (m_current->nextSibling() == m_ancestorSiblingStack.last()) 161 m_ancestorSiblingStack.removeLast(); 162 return *this; 163 } 164 165 Element* deepestSibling = previousSibling; 166 while (Element* lastChild = ElementTraversal::lastChild(deepestSibling)) 167 deepestSibling = lastChild; 168 ASSERT(deepestSibling); 169 170 if (deepestSibling != previousSibling) 171 m_ancestorSiblingStack.append(m_current); 172 173 m_current = deepestSibling; 174 175 #if !ASSERT_DISABLED 176 // Drop the assertion when the iterator reaches the end. 177 if (!m_current) 178 m_assertions.dropEventDispatchAssertion(); 179 #endif 180 181 return *this; 182 } 183 147 184 inline Element& ElementDescendantIterator::operator*() 148 185 { … … 256 293 } 257 294 295 inline ElementDescendantIterator ElementDescendantIteratorAdapter::last() 296 { 297 return ElementDescendantIterator(ElementTraversal::lastWithin(&m_root)); 298 } 299 258 300 // ElementDescendantConstIteratorAdapter 259 301 … … 273 315 } 274 316 317 inline ElementDescendantConstIterator ElementDescendantConstIteratorAdapter::last() const 318 { 319 return ElementDescendantConstIterator(ElementTraversal::lastWithin(&m_root)); 320 } 321 275 322 // Standalone functions 276 323 … … 287 334 } 288 335 289 #endif 336 namespace std { 337 template <> struct iterator_traits<WebCore::ElementDescendantIterator> { 338 typedef WebCore::Element value_type; 339 }; 340 template <> struct iterator_traits<WebCore::ElementDescendantConstIterator> { 341 typedef const WebCore::Element value_type; 342 }; 343 } 344 #endif -
trunk/Source/WebCore/dom/LiveNodeList.h
r166407 r166460 28 28 #include "CollectionType.h" 29 29 #include "Document.h" 30 #include "Element Traversal.h"30 #include "ElementDescendantIterator.h" 31 31 #include "HTMLNames.h" 32 32 #include "NodeList.h" … … 70 70 ContainerNode& rootNode() const; 71 71 72 Element* iterateForPreviousElement(Element* current) const;73 74 72 Ref<ContainerNode> m_ownerNode; 75 73 … … 87 85 88 86 // For CollectionIndexCache 89 Element* collectionFirst() const; 90 Element* collectionLast() const; 91 Element* collectionTraverseForward(Element&, unsigned count, unsigned& traversedCount) const; 92 Element* collectionTraverseBackward(Element&, unsigned count) const; 87 ElementDescendantIterator collectionBegin() const; 88 ElementDescendantIterator collectionLast() const; 89 ElementDescendantIterator collectionEnd() const { return ElementDescendantIterator(); } 90 void collectionTraverseForward(ElementDescendantIterator&, unsigned count, unsigned& traversedCount) const; 91 void collectionTraverseBackward(ElementDescendantIterator&, unsigned count) const; 93 92 bool collectionCanTraverseBackward() const { return true; } 94 93 void willValidateIndexCache() const; … … 103 102 ContainerNode& rootNode() const; 104 103 105 mutable CollectionIndexCache<NodeListType, Element > m_indexCache;104 mutable CollectionIndexCache<NodeListType, ElementDescendantIterator> m_indexCache; 106 105 }; 107 106 … … 133 132 CachedLiveNodeList<NodeListType>::CachedLiveNodeList(ContainerNode& ownerNode, NodeListInvalidationType invalidationType) 134 133 : LiveNodeList(ownerNode, invalidationType) 134 , m_indexCache(static_cast<NodeListType&>(*this)) 135 135 { 136 136 } … … 139 139 CachedLiveNodeList<NodeListType>::~CachedLiveNodeList() 140 140 { 141 if (m_indexCache.hasValidCache()) 141 auto& nodeList = static_cast<const NodeListType&>(*this); 142 if (m_indexCache.hasValidCache(nodeList)) 142 143 document().unregisterNodeListForInvalidation(*this); 143 144 } … … 153 154 154 155 template <class NodeListType> 155 Element* CachedLiveNodeList<NodeListType>::collectionFirst() const 156 { 157 auto& root = rootNode(); 158 Element* element = ElementTraversal::firstWithin(&root); 159 while (element && !static_cast<const NodeListType*>(this)->nodeMatches(element)) 160 element = ElementTraversal::next(element, &root); 161 return element; 162 } 163 164 template <class NodeListType> 165 Element* CachedLiveNodeList<NodeListType>::collectionLast() const 166 { 167 auto& root = rootNode(); 168 Element* element = ElementTraversal::lastWithin(&root); 169 while (element && !static_cast<const NodeListType*>(this)->nodeMatches(element)) 170 element = ElementTraversal::previous(element, &root); 171 return element; 172 } 173 174 template <class NodeListType> 175 inline Element* nextMatchingElement(const NodeListType* nodeList, Element* current, ContainerNode& root) 176 { 177 do { 178 current = ElementTraversal::next(current, &root); 179 } while (current && !static_cast<const NodeListType*>(nodeList)->nodeMatches(current)); 180 return current; 181 } 182 183 template <class NodeListType> 184 Element* CachedLiveNodeList<NodeListType>::collectionTraverseForward(Element& current, unsigned count, unsigned& traversedCount) const 185 { 186 auto& root = rootNode(); 187 Element* element = ¤t; 156 ElementDescendantIterator CachedLiveNodeList<NodeListType>::collectionBegin() const 157 { 158 auto& nodeList = static_cast<const NodeListType&>(*this); 159 auto descendants = elementDescendants(rootNode()); 160 auto end = descendants.end(); 161 for (auto it = descendants.begin(); it != end; ++it) { 162 if (nodeList.nodeMatches(&*it)) 163 return it; 164 } 165 return end; 166 } 167 168 template <class NodeListType> 169 ElementDescendantIterator CachedLiveNodeList<NodeListType>::collectionLast() const 170 { 171 auto& nodeList = static_cast<const NodeListType&>(*this); 172 auto descendants = elementDescendants(rootNode()); 173 auto end = descendants.end(); 174 for (auto it = descendants.last(); it != end; --it) { 175 if (nodeList.nodeMatches(&*it)) 176 return it; 177 } 178 return end; 179 } 180 181 template <class NodeListType> 182 void CachedLiveNodeList<NodeListType>::collectionTraverseForward(ElementDescendantIterator& current, unsigned count, unsigned& traversedCount) const 183 { 184 auto& nodeList = static_cast<const NodeListType&>(*this); 185 ASSERT(nodeList.nodeMatches(&*current)); 186 auto end = collectionEnd(); 188 187 for (traversedCount = 0; traversedCount < count; ++traversedCount) { 189 element = nextMatchingElement(static_cast<const NodeListType*>(this), element, root); 190 if (!element) 191 return nullptr; 192 } 193 return element; 194 } 195 196 template <class NodeListType> 197 inline Element* previousMatchingElement(const NodeListType* nodeList, Element* current, ContainerNode& root) 198 { 199 do { 200 current = ElementTraversal::previous(current, &root); 201 } while (current && !nodeList->nodeMatches(current)); 202 return current; 203 } 204 205 template <class NodeListType> 206 Element* CachedLiveNodeList<NodeListType>::collectionTraverseBackward(Element& current, unsigned count) const 207 { 208 auto& root = rootNode(); 209 Element* element = ¤t; 188 do { 189 ++current; 190 if (current == end) 191 return; 192 } while (!nodeList.nodeMatches(&*current)); 193 } 194 } 195 196 template <class NodeListType> 197 void CachedLiveNodeList<NodeListType>::collectionTraverseBackward(ElementDescendantIterator& current, unsigned count) const 198 { 199 auto& nodeList = static_cast<const NodeListType&>(*this); 200 ASSERT(nodeList.nodeMatches(&*current)); 201 auto end = collectionEnd(); 210 202 for (; count; --count) { 211 element = previousMatchingElement(static_cast<const NodeListType*>(this), element, root); 212 if (!element) 213 return nullptr; 214 } 215 return element; 216 } 203 do { 204 --current; 205 if (current == end) 206 return; 207 } while (!nodeList.nodeMatches(&*current)); 208 } 209 } 210 217 211 template <class NodeListType> 218 212 void CachedLiveNodeList<NodeListType>::willValidateIndexCache() const … … 224 218 void CachedLiveNodeList<NodeListType>::invalidateCache(Document& document) const 225 219 { 226 if (!m_indexCache.hasValidCache()) 220 auto& nodeList = static_cast<const NodeListType&>(*this); 221 if (!m_indexCache.hasValidCache(nodeList)) 227 222 return; 228 document.unregisterNodeListForInvalidation(const_cast<NodeListType&>( static_cast<const NodeListType&>(*this)));229 m_indexCache.invalidate( );223 document.unregisterNodeListForInvalidation(const_cast<NodeListType&>(nodeList)); 224 m_indexCache.invalidate(nodeList); 230 225 } 231 226 -
trunk/Source/WebCore/html/HTMLCollection.cpp
r166407 r166460 134 134 HTMLCollection::HTMLCollection(ContainerNode& ownerNode, CollectionType type, ElementTraversalType traversalType) 135 135 : m_ownerNode(ownerNode) 136 , m_indexCache(*this) 136 137 , m_collectionType(type) 137 138 , m_invalidationType(invalidationTypeExcludingIdAndNameAttributes(type)) … … 152 153 HTMLCollection::~HTMLCollection() 153 154 { 154 if (m_indexCache.hasValidCache( ))155 if (m_indexCache.hasValidCache(*this)) 155 156 document().unregisterCollection(*this); 156 157 if (hasNamedElementCache()) … … 331 332 } 332 333 333 Element* HTMLCollection::collection First() const334 Element* HTMLCollection::collectionBegin() const 334 335 { 335 336 return firstElement(rootNode()); … … 344 345 } 345 346 346 Element* HTMLCollection::collectionTraverseForward(Element& current, unsigned count, unsigned& traversedCount) const347 { 348 return traverseForward(current, count, traversedCount, rootNode());349 } 350 351 Element* HTMLCollection::collectionTraverseBackward(Element& current, unsigned count) const347 void HTMLCollection::collectionTraverseForward(Element*& current, unsigned count, unsigned& traversedCount) const 348 { 349 current = traverseForward(*current, count, traversedCount, rootNode()); 350 } 351 352 void HTMLCollection::collectionTraverseBackward(Element*& current, unsigned count) const 352 353 { 353 354 // FIXME: This should be optimized similarly to the forward case. 354 355 auto& root = rootNode(); 355 Element* element = ¤t;356 356 if (m_shouldOnlyIncludeDirectChildren) { 357 for (; count && element ; --count) 358 element = iterateForPreviousElement(ElementTraversal::previousSibling(element)); 359 return element; 360 } 361 for (; count && element ; --count) 362 element = iterateForPreviousElement(ElementTraversal::previous(element, &root)); 363 return element; 357 for (; count && current ; --count) 358 current = iterateForPreviousElement(ElementTraversal::previousSibling(current)); 359 return; 360 } 361 for (; count && current ; --count) 362 current = iterateForPreviousElement(ElementTraversal::previous(current, &root)); 364 363 } 365 364 366 365 void HTMLCollection::invalidateCache(Document& document) const 367 366 { 368 if (m_indexCache.hasValidCache( )) {367 if (m_indexCache.hasValidCache(*this)) { 369 368 document.unregisterCollection(const_cast<HTMLCollection&>(*this)); 370 m_indexCache.invalidate( );369 m_indexCache.invalidate(*this); 371 370 } 372 371 if (hasNamedElementCache()) -
trunk/Source/WebCore/html/HTMLCollection.h
r166407 r166460 119 119 120 120 // For CollectionIndexCache 121 Element* collection First() const;121 Element* collectionBegin() const; 122 122 Element* collectionLast() const; 123 Element* collectionTraverseForward(Element&, unsigned count, unsigned& traversedCount) const; 124 Element* collectionTraverseBackward(Element&, unsigned count) const; 123 Element* collectionEnd() const { return nullptr; } 124 void collectionTraverseForward(Element*&, unsigned count, unsigned& traversedCount) const; 125 void collectionTraverseBackward(Element*&, unsigned count) const; 125 126 bool collectionCanTraverseBackward() const { return !m_usesCustomForwardOnlyTraversal; } 126 127 void willValidateIndexCache() const { document().registerCollection(const_cast<HTMLCollection&>(*this)); } … … 165 166 Ref<ContainerNode> m_ownerNode; 166 167 167 mutable CollectionIndexCache<HTMLCollection, Element > m_indexCache;168 mutable CollectionIndexCache<HTMLCollection, Element*> m_indexCache; 168 169 mutable std::unique_ptr<CollectionNamedElementCache> m_namedElementCache; 169 170
Note: See TracChangeset
for help on using the changeset viewer.