<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[166460] trunk/Source/WebCore</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/166460">166460</a></dd>
<dt>Author</dt> <dd>antti@apple.com</dd>
<dt>Date</dt> <dd>2014-03-30 01:32:13 -0700 (Sun, 30 Mar 2014)</dd>
</dl>
<h3>Log Message</h3>
<pre>LiveNodeLists should use ElementDescendantIterator
https://bugs.webkit.org/show_bug.cgi?id=130931
Reviewed by Andreas Kling.
Make LiveNodeList traversal use the common DOM tree iterator.
* dom/ChildNodeList.cpp:
(WebCore::ChildNodeList::ChildNodeList):
(WebCore::ChildNodeList::collectionBegin):
(WebCore::ChildNodeList::collectionTraverseForward):
(WebCore::ChildNodeList::collectionTraverseBackward):
(WebCore::ChildNodeList::invalidateCache):
(WebCore::ChildNodeList::collectionFirst): Deleted.
Iterator for ChildNodeList is still just Node*.
* dom/ChildNodeList.h:
* dom/CollectionIndexCache.h:
(WebCore::CollectionIndexCache::hasValidCache):
(WebCore::Iterator>::CollectionIndexCache):
(WebCore::Iterator>::nodeCount):
(WebCore::Iterator>::computeNodeCountUpdatingListCache):
(WebCore::Iterator>::traverseBackwardTo):
(WebCore::Iterator>::traverseForwardTo):
(WebCore::Iterator>::nodeAt):
(WebCore::Iterator>::invalidate):
Make CollectionIndexCache iterator based instead of using NodeType*. The iterator type may
still be a Node* though.
(WebCore::NodeType>::CollectionIndexCache): Deleted.
(WebCore::NodeType>::nodeCount): Deleted.
(WebCore::NodeType>::computeNodeCountUpdatingListCache): Deleted.
(WebCore::NodeType>::nodeBeforeCached): Deleted.
(WebCore::NodeType>::nodeAfterCached): Deleted.
(WebCore::NodeType>::nodeAt): Deleted.
(WebCore::NodeType>::invalidate): Deleted.
* dom/ElementDescendantIterator.h:
(WebCore::ElementDescendantIterator::operator--):
Add backward iteration support.
(WebCore::ElementDescendantIteratorAdapter::last):
(WebCore::ElementDescendantConstIteratorAdapter::last):
Add a way to get the last item.
Provide std::iterator_traits so we can extract the type.
* dom/LiveNodeList.h:
(WebCore::CachedLiveNodeList::collectionEnd):
(WebCore::CachedLiveNodeList<NodeListType>::CachedLiveNodeList):
(WebCore::CachedLiveNodeList<NodeListType>::~CachedLiveNodeList):
(WebCore::CachedLiveNodeList<NodeListType>::collectionBegin):
(WebCore::CachedLiveNodeList<NodeListType>::collectionLast):
(WebCore::CachedLiveNodeList<NodeListType>::collectionTraverseForward):
(WebCore::CachedLiveNodeList<NodeListType>::collectionTraverseBackward):
(WebCore::CachedLiveNodeList<NodeListType>::invalidateCache):
(WebCore::CachedLiveNodeList<NodeListType>::collectionFirst): Deleted.
Make LiveNodeList traversal use ElementDescendantIterator.
(WebCore::nextMatchingElement): Deleted.
(WebCore::previousMatchingElement): Deleted.
* html/HTMLCollection.cpp:
(WebCore::HTMLCollection::HTMLCollection):
(WebCore::HTMLCollection::~HTMLCollection):
(WebCore::HTMLCollection::collectionBegin):
(WebCore::HTMLCollection::collectionTraverseForward):
(WebCore::HTMLCollection::collectionTraverseBackward):
(WebCore::HTMLCollection::invalidateCache):
(WebCore::HTMLCollection::collectionFirst): Deleted.
* html/HTMLCollection.h:
(WebCore::HTMLCollection::collectionEnd):
HTMLCollection still uses Element* as iterator for now.</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoredomChildNodeListcpp">trunk/Source/WebCore/dom/ChildNodeList.cpp</a></li>
<li><a href="#trunkSourceWebCoredomChildNodeListh">trunk/Source/WebCore/dom/ChildNodeList.h</a></li>
<li><a href="#trunkSourceWebCoredomCollectionIndexCacheh">trunk/Source/WebCore/dom/CollectionIndexCache.h</a></li>
<li><a href="#trunkSourceWebCoredomElementDescendantIteratorh">trunk/Source/WebCore/dom/ElementDescendantIterator.h</a></li>
<li><a href="#trunkSourceWebCoredomLiveNodeListh">trunk/Source/WebCore/dom/LiveNodeList.h</a></li>
<li><a href="#trunkSourceWebCorehtmlHTMLCollectioncpp">trunk/Source/WebCore/html/HTMLCollection.cpp</a></li>
<li><a href="#trunkSourceWebCorehtmlHTMLCollectionh">trunk/Source/WebCore/html/HTMLCollection.h</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (166459 => 166460)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2014-03-30 06:01:08 UTC (rev 166459)
+++ trunk/Source/WebCore/ChangeLog        2014-03-30 08:32:13 UTC (rev 166460)
</span><span class="lines">@@ -1,3 +1,82 @@
</span><ins>+2014-03-29 Antti Koivisto <antti@apple.com>
+
+ LiveNodeLists should use ElementDescendantIterator
+ https://bugs.webkit.org/show_bug.cgi?id=130931
+
+ Reviewed by Andreas Kling.
+
+ Make LiveNodeList traversal use the common DOM tree iterator.
+
+ * dom/ChildNodeList.cpp:
+ (WebCore::ChildNodeList::ChildNodeList):
+ (WebCore::ChildNodeList::collectionBegin):
+ (WebCore::ChildNodeList::collectionTraverseForward):
+ (WebCore::ChildNodeList::collectionTraverseBackward):
+ (WebCore::ChildNodeList::invalidateCache):
+ (WebCore::ChildNodeList::collectionFirst): Deleted.
+
+ Iterator for ChildNodeList is still just Node*.
+
+ * dom/ChildNodeList.h:
+ * dom/CollectionIndexCache.h:
+ (WebCore::CollectionIndexCache::hasValidCache):
+ (WebCore::Iterator>::CollectionIndexCache):
+ (WebCore::Iterator>::nodeCount):
+ (WebCore::Iterator>::computeNodeCountUpdatingListCache):
+ (WebCore::Iterator>::traverseBackwardTo):
+ (WebCore::Iterator>::traverseForwardTo):
+ (WebCore::Iterator>::nodeAt):
+ (WebCore::Iterator>::invalidate):
+
+ Make CollectionIndexCache iterator based instead of using NodeType*. The iterator type may
+ still be a Node* though.
+
+ (WebCore::NodeType>::CollectionIndexCache): Deleted.
+ (WebCore::NodeType>::nodeCount): Deleted.
+ (WebCore::NodeType>::computeNodeCountUpdatingListCache): Deleted.
+ (WebCore::NodeType>::nodeBeforeCached): Deleted.
+ (WebCore::NodeType>::nodeAfterCached): Deleted.
+ (WebCore::NodeType>::nodeAt): Deleted.
+ (WebCore::NodeType>::invalidate): Deleted.
+ * dom/ElementDescendantIterator.h:
+ (WebCore::ElementDescendantIterator::operator--):
+
+ Add backward iteration support.
+
+ (WebCore::ElementDescendantIteratorAdapter::last):
+ (WebCore::ElementDescendantConstIteratorAdapter::last):
+
+ Add a way to get the last item.
+ Provide std::iterator_traits so we can extract the type.
+
+ * dom/LiveNodeList.h:
+ (WebCore::CachedLiveNodeList::collectionEnd):
+ (WebCore::CachedLiveNodeList<NodeListType>::CachedLiveNodeList):
+ (WebCore::CachedLiveNodeList<NodeListType>::~CachedLiveNodeList):
+ (WebCore::CachedLiveNodeList<NodeListType>::collectionBegin):
+ (WebCore::CachedLiveNodeList<NodeListType>::collectionLast):
+ (WebCore::CachedLiveNodeList<NodeListType>::collectionTraverseForward):
+ (WebCore::CachedLiveNodeList<NodeListType>::collectionTraverseBackward):
+ (WebCore::CachedLiveNodeList<NodeListType>::invalidateCache):
+ (WebCore::CachedLiveNodeList<NodeListType>::collectionFirst): Deleted.
+
+ Make LiveNodeList traversal use ElementDescendantIterator.
+
+ (WebCore::nextMatchingElement): Deleted.
+ (WebCore::previousMatchingElement): Deleted.
+ * html/HTMLCollection.cpp:
+ (WebCore::HTMLCollection::HTMLCollection):
+ (WebCore::HTMLCollection::~HTMLCollection):
+ (WebCore::HTMLCollection::collectionBegin):
+ (WebCore::HTMLCollection::collectionTraverseForward):
+ (WebCore::HTMLCollection::collectionTraverseBackward):
+ (WebCore::HTMLCollection::invalidateCache):
+ (WebCore::HTMLCollection::collectionFirst): Deleted.
+ * html/HTMLCollection.h:
+ (WebCore::HTMLCollection::collectionEnd):
+
+ HTMLCollection still uses Element* as iterator for now.
+
</ins><span class="cx"> 2014-03-29 Commit Queue <commit-queue@webkit.org>
</span><span class="cx">
</span><span class="cx"> Unreviewed, rolling out r166434.
</span></span></pre></div>
<a id="trunkSourceWebCoredomChildNodeListcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/ChildNodeList.cpp (166459 => 166460)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/ChildNodeList.cpp        2014-03-30 06:01:08 UTC (rev 166459)
+++ trunk/Source/WebCore/dom/ChildNodeList.cpp        2014-03-30 08:32:13 UTC (rev 166460)
</span><span class="lines">@@ -35,6 +35,7 @@
</span><span class="cx">
</span><span class="cx"> ChildNodeList::ChildNodeList(ContainerNode& parent)
</span><span class="cx"> : m_parent(parent)
</span><ins>+ , m_indexCache(*this)
</ins><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -53,7 +54,7 @@
</span><span class="cx"> return m_indexCache.nodeAt(*this, index);
</span><span class="cx"> }
</span><span class="cx">
</span><del>-Node* ChildNodeList::collectionFirst() const
</del><ins>+Node* ChildNodeList::collectionBegin() const
</ins><span class="cx"> {
</span><span class="cx"> return m_parent->firstChild();
</span><span class="cx"> }
</span><span class="lines">@@ -63,25 +64,21 @@
</span><span class="cx"> return m_parent->lastChild();
</span><span class="cx"> }
</span><span class="cx">
</span><del>-Node* ChildNodeList::collectionTraverseForward(Node& current, unsigned count, unsigned& traversedCount) const
</del><ins>+void ChildNodeList::collectionTraverseForward(Node*& current, unsigned count, unsigned& traversedCount) const
</ins><span class="cx"> {
</span><span class="cx"> ASSERT(count);
</span><del>- Node* child = &current;
</del><span class="cx"> for (traversedCount = 0; traversedCount < count; ++traversedCount) {
</span><del>- child = child->nextSibling();
- if (!child)
- return nullptr;
</del><ins>+ current = current->nextSibling();
+ if (!current)
+ return;
</ins><span class="cx"> }
</span><del>- return child;
</del><span class="cx"> }
</span><span class="cx">
</span><del>-Node* ChildNodeList::collectionTraverseBackward(Node& current, unsigned count) const
</del><ins>+void ChildNodeList::collectionTraverseBackward(Node*& current, unsigned count) const
</ins><span class="cx"> {
</span><span class="cx"> ASSERT(count);
</span><del>- Node* child = &current;
- for (; count && child ; --count)
- child = child->previousSibling();
- return child;
</del><ins>+ for (; count && current ; --count)
+ current = current->previousSibling();
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> Node* ChildNodeList::namedItem(const AtomicString& name) const
</span><span class="lines">@@ -103,7 +100,7 @@
</span><span class="cx">
</span><span class="cx"> void ChildNodeList::invalidateCache()
</span><span class="cx"> {
</span><del>- m_indexCache.invalidate();
</del><ins>+ m_indexCache.invalidate(*this);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCoredomChildNodeListh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/ChildNodeList.h (166459 => 166460)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/ChildNodeList.h        2014-03-30 06:01:08 UTC (rev 166459)
+++ trunk/Source/WebCore/dom/ChildNodeList.h        2014-03-30 08:32:13 UTC (rev 166460)
</span><span class="lines">@@ -70,10 +70,11 @@
</span><span class="cx"> void invalidateCache();
</span><span class="cx">
</span><span class="cx"> // For CollectionIndexCache
</span><del>- Node* collectionFirst() const;
</del><ins>+ Node* collectionBegin() const;
</ins><span class="cx"> Node* collectionLast() const;
</span><del>- Node* collectionTraverseForward(Node&, unsigned count, unsigned& traversedCount) const;
- Node* collectionTraverseBackward(Node&, unsigned count) const;
</del><ins>+ Node* collectionEnd() const { return nullptr; }
+ void collectionTraverseForward(Node*&, unsigned count, unsigned& traversedCount) const;
+ void collectionTraverseBackward(Node*&, unsigned count) const;
</ins><span class="cx"> bool collectionCanTraverseBackward() const { return true; }
</span><span class="cx"> void willValidateIndexCache() const { }
</span><span class="cx">
</span><span class="lines">@@ -88,7 +89,7 @@
</span><span class="cx"> virtual bool isChildNodeList() const override { return true; }
</span><span class="cx">
</span><span class="cx"> Ref<ContainerNode> m_parent;
</span><del>- mutable CollectionIndexCache<ChildNodeList, Node> m_indexCache;
</del><ins>+ mutable CollectionIndexCache<ChildNodeList, Node*> m_indexCache;
</ins><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCoredomCollectionIndexCacheh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/CollectionIndexCache.h (166459 => 166460)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/CollectionIndexCache.h        2014-03-30 06:01:08 UTC (rev 166459)
+++ trunk/Source/WebCore/dom/CollectionIndexCache.h        2014-03-30 08:32:13 UTC (rev 166460)
</span><span class="lines">@@ -32,25 +32,26 @@
</span><span class="cx">
</span><span class="cx"> void reportExtraMemoryCostForCollectionIndexCache(size_t);
</span><span class="cx">
</span><del>-template <class Collection, class NodeType>
</del><ins>+template <class Collection, class Iterator>
</ins><span class="cx"> class CollectionIndexCache {
</span><span class="cx"> public:
</span><del>- CollectionIndexCache();
</del><ins>+ explicit CollectionIndexCache(const Collection&);
</ins><span class="cx">
</span><ins>+ typedef typename std::iterator_traits<Iterator>::value_type NodeType;
+
</ins><span class="cx"> unsigned nodeCount(const Collection&);
</span><span class="cx"> NodeType* nodeAt(const Collection&, unsigned index);
</span><span class="cx">
</span><del>- bool hasValidCache() const { return m_currentNode || m_nodeCountValid || m_listValid; }
- void invalidate();
</del><ins>+ bool hasValidCache(const Collection& collection) const { return m_current != collection.collectionEnd() || m_nodeCountValid || m_listValid; }
+ void invalidate(const Collection&);
</ins><span class="cx"> size_t memoryCost() { return m_cachedList.capacity() * sizeof(NodeType*); }
</span><span class="cx">
</span><span class="cx"> private:
</span><del>-
</del><span class="cx"> unsigned computeNodeCountUpdatingListCache(const Collection&);
</span><del>- NodeType* nodeBeforeCached(const Collection&, unsigned);
- NodeType* nodeAfterCached(const Collection&, unsigned);
</del><ins>+ NodeType* traverseBackwardTo(const Collection&, unsigned);
+ NodeType* traverseForwardTo(const Collection&, unsigned);
</ins><span class="cx">
</span><del>- NodeType* m_currentNode;
</del><ins>+ Iterator m_current;
</ins><span class="cx"> unsigned m_currentIndex;
</span><span class="cx"> unsigned m_nodeCount;
</span><span class="cx"> Vector<NodeType*> m_cachedList;
</span><span class="lines">@@ -58,9 +59,9 @@
</span><span class="cx"> bool m_listValid : 1;
</span><span class="cx"> };
</span><span class="cx">
</span><del>-template <class Collection, class NodeType>
-inline CollectionIndexCache<Collection, NodeType>::CollectionIndexCache()
- : m_currentNode(nullptr)
</del><ins>+template <class Collection, class Iterator>
+inline CollectionIndexCache<Collection, Iterator>::CollectionIndexCache(const Collection& collection)
+ : m_current(collection.collectionEnd())
</ins><span class="cx"> , m_currentIndex(0)
</span><span class="cx"> , m_nodeCount(0)
</span><span class="cx"> , m_nodeCountValid(false)
</span><span class="lines">@@ -68,11 +69,11 @@
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx">
</span><del>-template <class Collection, class NodeType>
-inline unsigned CollectionIndexCache<Collection, NodeType>::nodeCount(const Collection& collection)
</del><ins>+template <class Collection, class Iterator>
+inline unsigned CollectionIndexCache<Collection, Iterator>::nodeCount(const Collection& collection)
</ins><span class="cx"> {
</span><span class="cx"> if (!m_nodeCountValid) {
</span><del>- if (!hasValidCache())
</del><ins>+ if (!hasValidCache(collection))
</ins><span class="cx"> collection.willValidateIndexCache();
</span><span class="cx"> m_nodeCount = computeNodeCountUpdatingListCache(collection);
</span><span class="cx"> m_nodeCountValid = true;
</span><span class="lines">@@ -81,20 +82,20 @@
</span><span class="cx"> return m_nodeCount;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-template <class Collection, class NodeType>
-unsigned CollectionIndexCache<Collection, NodeType>::computeNodeCountUpdatingListCache(const Collection& collection)
</del><ins>+template <class Collection, class Iterator>
+unsigned CollectionIndexCache<Collection, Iterator>::computeNodeCountUpdatingListCache(const Collection& collection)
</ins><span class="cx"> {
</span><del>- NodeType* first = collection.collectionFirst();
- if (!first)
</del><ins>+ auto current = collection.collectionBegin();
+ auto end = collection.collectionEnd();
+ if (current == end)
</ins><span class="cx"> return 0;
</span><span class="cx">
</span><span class="cx"> unsigned oldCapacity = m_cachedList.capacity();
</span><del>- NodeType* currentNode = first;
- while (currentNode) {
- m_cachedList.append(currentNode);
</del><ins>+ while (current != end) {
+ m_cachedList.append(&*current);
</ins><span class="cx"> unsigned traversed;
</span><del>- currentNode = collection.collectionTraverseForward(*currentNode, 1, traversed);
- ASSERT(traversed == (currentNode ? 1 : 0));
</del><ins>+ collection.collectionTraverseForward(current, 1, traversed);
+ ASSERT(traversed == (current != end ? 1 : 0));
</ins><span class="cx"> }
</span><span class="cx"> m_listValid = true;
</span><span class="cx">
</span><span class="lines">@@ -104,67 +105,67 @@
</span><span class="cx"> return m_cachedList.size();
</span><span class="cx"> }
</span><span class="cx">
</span><del>-template <class Collection, class NodeType>
-inline NodeType* CollectionIndexCache<Collection, NodeType>::nodeBeforeCached(const Collection& collection, unsigned index)
</del><ins>+template <class Collection, class Iterator>
+inline typename CollectionIndexCache<Collection, Iterator>::NodeType* CollectionIndexCache<Collection, Iterator>::traverseBackwardTo(const Collection& collection, unsigned index)
</ins><span class="cx"> {
</span><del>- ASSERT(m_currentNode);
</del><ins>+ ASSERT(m_current != collection.collectionEnd());
</ins><span class="cx"> ASSERT(index < m_currentIndex);
</span><span class="cx">
</span><span class="cx"> bool firstIsCloser = index < m_currentIndex - index;
</span><span class="cx"> if (firstIsCloser || !collection.collectionCanTraverseBackward()) {
</span><del>- m_currentNode = collection.collectionFirst();
</del><ins>+ m_current = collection.collectionBegin();
</ins><span class="cx"> m_currentIndex = 0;
</span><span class="cx"> if (index)
</span><del>- m_currentNode = collection.collectionTraverseForward(*m_currentNode, index, m_currentIndex);
- ASSERT(m_currentNode);
- return m_currentNode;
</del><ins>+ collection.collectionTraverseForward(m_current, index, m_currentIndex);
+ ASSERT(m_current != collection.collectionEnd());
+ return &*m_current;
</ins><span class="cx"> }
</span><span class="cx">
</span><del>- m_currentNode = collection.collectionTraverseBackward(*m_currentNode, m_currentIndex - index);
</del><ins>+ collection.collectionTraverseBackward(m_current, m_currentIndex - index);
</ins><span class="cx"> m_currentIndex = index;
</span><span class="cx">
</span><del>- ASSERT(m_currentNode);
- return m_currentNode;
</del><ins>+ ASSERT(m_current != collection.collectionEnd());
+ return &*m_current;
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-template <class Collection, class NodeType>
-inline NodeType* CollectionIndexCache<Collection, NodeType>::nodeAfterCached(const Collection& collection, unsigned index)
</del><ins>+template <class Collection, class Iterator>
+inline typename CollectionIndexCache<Collection, Iterator>::NodeType* CollectionIndexCache<Collection, Iterator>::traverseForwardTo(const Collection& collection, unsigned index)
</ins><span class="cx"> {
</span><del>- ASSERT(m_currentNode);
</del><ins>+ ASSERT(m_current != collection.collectionEnd());
</ins><span class="cx"> ASSERT(index > m_currentIndex);
</span><span class="cx"> ASSERT(!m_nodeCountValid || index < m_nodeCount);
</span><span class="cx">
</span><span class="cx"> bool lastIsCloser = m_nodeCountValid && m_nodeCount - index < index - m_currentIndex;
</span><span class="cx"> if (lastIsCloser && collection.collectionCanTraverseBackward()) {
</span><del>- ASSERT(hasValidCache());
- m_currentNode = collection.collectionLast();
</del><ins>+ ASSERT(hasValidCache(collection));
+ m_current = collection.collectionLast();
</ins><span class="cx"> if (index < m_nodeCount - 1)
</span><del>- m_currentNode = collection.collectionTraverseBackward(*m_currentNode, m_nodeCount - index - 1);
</del><ins>+ collection.collectionTraverseBackward(m_current, m_nodeCount - index - 1);
</ins><span class="cx"> m_currentIndex = index;
</span><del>- ASSERT(m_currentNode);
- return m_currentNode;
</del><ins>+ ASSERT(m_current != collection.collectionEnd());
+ return &*m_current;
</ins><span class="cx"> }
</span><span class="cx">
</span><del>- if (!hasValidCache())
</del><ins>+ if (!hasValidCache(collection))
</ins><span class="cx"> collection.willValidateIndexCache();
</span><span class="cx">
</span><span class="cx"> unsigned traversedCount;
</span><del>- m_currentNode = collection.collectionTraverseForward(*m_currentNode, index - m_currentIndex, traversedCount);
</del><ins>+ collection.collectionTraverseForward(m_current, index - m_currentIndex, traversedCount);
</ins><span class="cx"> m_currentIndex = m_currentIndex + traversedCount;
</span><span class="cx">
</span><del>- ASSERT(m_currentNode || m_currentIndex < index);
-
- if (!m_currentNode && !m_nodeCountValid) {
</del><ins>+ if (m_current == collection.collectionEnd()) {
+ ASSERT(m_currentIndex < index);
</ins><span class="cx"> // Failed to find the index but at least we now know the size.
</span><span class="cx"> m_nodeCount = m_currentIndex + 1;
</span><span class="cx"> m_nodeCountValid = true;
</span><ins>+ return nullptr;
</ins><span class="cx"> }
</span><del>- ASSERT(hasValidCache());
- return m_currentNode;
</del><ins>+ ASSERT(hasValidCache(collection));
+ return &*m_current;
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-template <class Collection, class NodeType>
-inline NodeType* CollectionIndexCache<Collection, NodeType>::nodeAt(const Collection& collection, unsigned index)
</del><ins>+template <class Collection, class Iterator>
+inline typename CollectionIndexCache<Collection, Iterator>::NodeType* CollectionIndexCache<Collection, Iterator>::nodeAt(const Collection& collection, unsigned index)
</ins><span class="cx"> {
</span><span class="cx"> if (m_nodeCountValid && index >= m_nodeCount)
</span><span class="cx"> return nullptr;
</span><span class="lines">@@ -172,47 +173,49 @@
</span><span class="cx"> if (m_listValid)
</span><span class="cx"> return m_cachedList[index];
</span><span class="cx">
</span><del>- if (m_currentNode) {
</del><ins>+ auto end = collection.collectionEnd();
+ if (m_current != end) {
</ins><span class="cx"> if (index > m_currentIndex)
</span><del>- return nodeAfterCached(collection, index);
</del><ins>+ return traverseForwardTo(collection, index);
</ins><span class="cx"> if (index < m_currentIndex)
</span><del>- return nodeBeforeCached(collection, index);
- return m_currentNode;
</del><ins>+ return traverseBackwardTo(collection, index);
+ return &*m_current;
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> bool lastIsCloser = m_nodeCountValid && m_nodeCount - index < index;
</span><span class="cx"> if (lastIsCloser && collection.collectionCanTraverseBackward()) {
</span><del>- ASSERT(hasValidCache());
- m_currentNode = collection.collectionLast();
</del><ins>+ ASSERT(hasValidCache(collection));
+ m_current = collection.collectionLast();
</ins><span class="cx"> if (index < m_nodeCount - 1)
</span><del>- m_currentNode = collection.collectionTraverseBackward(*m_currentNode, m_nodeCount - index - 1);
</del><ins>+ collection.collectionTraverseBackward(m_current, m_nodeCount - index - 1);
</ins><span class="cx"> m_currentIndex = index;
</span><del>- ASSERT(m_currentNode);
- return m_currentNode;
</del><ins>+ ASSERT(m_current != end);
+ return &*m_current;
</ins><span class="cx"> }
</span><span class="cx">
</span><del>- if (!hasValidCache())
</del><ins>+ if (!hasValidCache(collection))
</ins><span class="cx"> collection.willValidateIndexCache();
</span><span class="cx">
</span><del>- m_currentNode = collection.collectionFirst();
</del><ins>+ m_current = collection.collectionBegin();
</ins><span class="cx"> m_currentIndex = 0;
</span><del>- if (index && m_currentNode) {
- m_currentNode = collection.collectionTraverseForward(*m_currentNode, index, m_currentIndex);
- ASSERT(m_currentNode || m_currentIndex < index);
</del><ins>+ if (index && m_current != end) {
+ collection.collectionTraverseForward(m_current, index, m_currentIndex);
+ ASSERT(m_current != end || m_currentIndex < index);
</ins><span class="cx"> }
</span><del>- if (!m_currentNode && !m_nodeCountValid) {
</del><ins>+ if (m_current == end) {
</ins><span class="cx"> // Failed to find the index but at least we now know the size.
</span><span class="cx"> m_nodeCount = m_currentIndex + 1;
</span><span class="cx"> m_nodeCountValid = true;
</span><ins>+ return nullptr;
</ins><span class="cx"> }
</span><del>- ASSERT(hasValidCache());
- return m_currentNode;
</del><ins>+ ASSERT(hasValidCache(collection));
+ return &*m_current;
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-template <class Collection, class NodeType>
-void CollectionIndexCache<Collection, NodeType>::invalidate()
</del><ins>+template <class Collection, class Iterator>
+void CollectionIndexCache<Collection, Iterator>::invalidate(const Collection& collection)
</ins><span class="cx"> {
</span><del>- m_currentNode = nullptr;
</del><ins>+ m_current = collection.collectionEnd();
</ins><span class="cx"> m_nodeCountValid = false;
</span><span class="cx"> m_listValid = false;
</span><span class="cx"> m_cachedList.shrink(0);
</span></span></pre></div>
<a id="trunkSourceWebCoredomElementDescendantIteratorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/ElementDescendantIterator.h (166459 => 166460)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/ElementDescendantIterator.h        2014-03-30 06:01:08 UTC (rev 166459)
+++ trunk/Source/WebCore/dom/ElementDescendantIterator.h        2014-03-30 08:32:13 UTC (rev 166460)
</span><span class="lines">@@ -39,6 +39,7 @@
</span><span class="cx"> explicit ElementDescendantIterator(Element* current);
</span><span class="cx">
</span><span class="cx"> ElementDescendantIterator& operator++();
</span><ins>+ ElementDescendantIterator& operator--();
</ins><span class="cx">
</span><span class="cx"> Element& operator*();
</span><span class="cx"> Element* operator->();
</span><span class="lines">@@ -82,6 +83,7 @@
</span><span class="cx"> ElementDescendantIteratorAdapter(ContainerNode& root);
</span><span class="cx"> ElementDescendantIterator begin();
</span><span class="cx"> ElementDescendantIterator end();
</span><ins>+ ElementDescendantIterator last();
</ins><span class="cx">
</span><span class="cx"> private:
</span><span class="cx"> ContainerNode& m_root;
</span><span class="lines">@@ -92,6 +94,7 @@
</span><span class="cx"> ElementDescendantConstIteratorAdapter(const ContainerNode& root);
</span><span class="cx"> ElementDescendantConstIterator begin() const;
</span><span class="cx"> ElementDescendantConstIterator end() const;
</span><ins>+ ElementDescendantConstIterator last() const;
</ins><span class="cx">
</span><span class="cx"> private:
</span><span class="cx"> const ContainerNode& m_root;
</span><span class="lines">@@ -144,6 +147,40 @@
</span><span class="cx"> return *this;
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+ALWAYS_INLINE ElementDescendantIterator& ElementDescendantIterator::operator--()
+{
+ ASSERT(m_current);
+ ASSERT(!m_assertions.domTreeHasMutated());
+
+ Element* previousSibling = ElementTraversal::previousSibling(m_current);
+
+ if (!previousSibling) {
+ m_current = m_current->parentElement();
+ // The stack optimizes for forward traversal only, this just maintains consistency.
+ if (m_current->nextSibling() == m_ancestorSiblingStack.last())
+ m_ancestorSiblingStack.removeLast();
+ return *this;
+ }
+
+ Element* deepestSibling = previousSibling;
+ while (Element* lastChild = ElementTraversal::lastChild(deepestSibling))
+ deepestSibling = lastChild;
+ ASSERT(deepestSibling);
+
+ if (deepestSibling != previousSibling)
+ m_ancestorSiblingStack.append(m_current);
+
+ m_current = deepestSibling;
+
+#if !ASSERT_DISABLED
+ // Drop the assertion when the iterator reaches the end.
+ if (!m_current)
+ m_assertions.dropEventDispatchAssertion();
+#endif
+
+ return *this;
+}
+
</ins><span class="cx"> inline Element& ElementDescendantIterator::operator*()
</span><span class="cx"> {
</span><span class="cx"> ASSERT(m_current);
</span><span class="lines">@@ -255,6 +292,11 @@
</span><span class="cx"> return ElementDescendantIterator();
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+inline ElementDescendantIterator ElementDescendantIteratorAdapter::last()
+{
+ return ElementDescendantIterator(ElementTraversal::lastWithin(&m_root));
+}
+
</ins><span class="cx"> // ElementDescendantConstIteratorAdapter
</span><span class="cx">
</span><span class="cx"> inline ElementDescendantConstIteratorAdapter::ElementDescendantConstIteratorAdapter(const ContainerNode& root)
</span><span class="lines">@@ -272,6 +314,11 @@
</span><span class="cx"> return ElementDescendantConstIterator();
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+inline ElementDescendantConstIterator ElementDescendantConstIteratorAdapter::last() const
+{
+ return ElementDescendantConstIterator(ElementTraversal::lastWithin(&m_root));
+}
+
</ins><span class="cx"> // Standalone functions
</span><span class="cx">
</span><span class="cx"> inline ElementDescendantIteratorAdapter elementDescendants(ContainerNode& root)
</span><span class="lines">@@ -286,4 +333,12 @@
</span><span class="cx">
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+namespace std {
+template <> struct iterator_traits<WebCore::ElementDescendantIterator> {
+ typedef WebCore::Element value_type;
+};
+template <> struct iterator_traits<WebCore::ElementDescendantConstIterator> {
+ typedef const WebCore::Element value_type;
+};
+}
</ins><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceWebCoredomLiveNodeListh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/LiveNodeList.h (166459 => 166460)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/LiveNodeList.h        2014-03-30 06:01:08 UTC (rev 166459)
+++ trunk/Source/WebCore/dom/LiveNodeList.h        2014-03-30 08:32:13 UTC (rev 166460)
</span><span class="lines">@@ -27,7 +27,7 @@
</span><span class="cx"> #include "CollectionIndexCache.h"
</span><span class="cx"> #include "CollectionType.h"
</span><span class="cx"> #include "Document.h"
</span><del>-#include "ElementTraversal.h"
</del><ins>+#include "ElementDescendantIterator.h"
</ins><span class="cx"> #include "HTMLNames.h"
</span><span class="cx"> #include "NodeList.h"
</span><span class="cx"> #include <wtf/Forward.h>
</span><span class="lines">@@ -69,8 +69,6 @@
</span><span class="cx">
</span><span class="cx"> ContainerNode& rootNode() const;
</span><span class="cx">
</span><del>- Element* iterateForPreviousElement(Element* current) const;
-
</del><span class="cx"> Ref<ContainerNode> m_ownerNode;
</span><span class="cx">
</span><span class="cx"> const unsigned m_invalidationType;
</span><span class="lines">@@ -86,10 +84,11 @@
</span><span class="cx"> virtual Node* item(unsigned offset) const override final;
</span><span class="cx">
</span><span class="cx"> // For CollectionIndexCache
</span><del>- Element* collectionFirst() const;
- Element* collectionLast() const;
- Element* collectionTraverseForward(Element&, unsigned count, unsigned& traversedCount) const;
- Element* collectionTraverseBackward(Element&, unsigned count) const;
</del><ins>+ ElementDescendantIterator collectionBegin() const;
+ ElementDescendantIterator collectionLast() const;
+ ElementDescendantIterator collectionEnd() const { return ElementDescendantIterator(); }
+ void collectionTraverseForward(ElementDescendantIterator&, unsigned count, unsigned& traversedCount) const;
+ void collectionTraverseBackward(ElementDescendantIterator&, unsigned count) const;
</ins><span class="cx"> bool collectionCanTraverseBackward() const { return true; }
</span><span class="cx"> void willValidateIndexCache() const;
</span><span class="cx">
</span><span class="lines">@@ -102,7 +101,7 @@
</span><span class="cx"> private:
</span><span class="cx"> ContainerNode& rootNode() const;
</span><span class="cx">
</span><del>- mutable CollectionIndexCache<NodeListType, Element> m_indexCache;
</del><ins>+ mutable CollectionIndexCache<NodeListType, ElementDescendantIterator> m_indexCache;
</ins><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> ALWAYS_INLINE bool shouldInvalidateTypeOnAttributeChange(NodeListInvalidationType type, const QualifiedName& attrName)
</span><span class="lines">@@ -132,13 +131,15 @@
</span><span class="cx"> template <class NodeListType>
</span><span class="cx"> CachedLiveNodeList<NodeListType>::CachedLiveNodeList(ContainerNode& ownerNode, NodeListInvalidationType invalidationType)
</span><span class="cx"> : LiveNodeList(ownerNode, invalidationType)
</span><ins>+ , m_indexCache(static_cast<NodeListType&>(*this))
</ins><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> template <class NodeListType>
</span><span class="cx"> CachedLiveNodeList<NodeListType>::~CachedLiveNodeList()
</span><span class="cx"> {
</span><del>- if (m_indexCache.hasValidCache())
</del><ins>+ auto& nodeList = static_cast<const NodeListType&>(*this);
+ if (m_indexCache.hasValidCache(nodeList))
</ins><span class="cx"> document().unregisterNodeListForInvalidation(*this);
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -152,68 +153,61 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> template <class NodeListType>
</span><del>-Element* CachedLiveNodeList<NodeListType>::collectionFirst() const
</del><ins>+ElementDescendantIterator CachedLiveNodeList<NodeListType>::collectionBegin() const
</ins><span class="cx"> {
</span><del>- auto& root = rootNode();
- Element* element = ElementTraversal::firstWithin(&root);
- while (element && !static_cast<const NodeListType*>(this)->nodeMatches(element))
- element = ElementTraversal::next(element, &root);
- return element;
</del><ins>+ auto& nodeList = static_cast<const NodeListType&>(*this);
+ auto descendants = elementDescendants(rootNode());
+ auto end = descendants.end();
+ for (auto it = descendants.begin(); it != end; ++it) {
+ if (nodeList.nodeMatches(&*it))
+ return it;
+ }
+ return end;
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> template <class NodeListType>
</span><del>-Element* CachedLiveNodeList<NodeListType>::collectionLast() const
</del><ins>+ElementDescendantIterator CachedLiveNodeList<NodeListType>::collectionLast() const
</ins><span class="cx"> {
</span><del>- auto& root = rootNode();
- Element* element = ElementTraversal::lastWithin(&root);
- while (element && !static_cast<const NodeListType*>(this)->nodeMatches(element))
- element = ElementTraversal::previous(element, &root);
- return element;
</del><ins>+ auto& nodeList = static_cast<const NodeListType&>(*this);
+ auto descendants = elementDescendants(rootNode());
+ auto end = descendants.end();
+ for (auto it = descendants.last(); it != end; --it) {
+ if (nodeList.nodeMatches(&*it))
+ return it;
+ }
+ return end;
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> template <class NodeListType>
</span><del>-inline Element* nextMatchingElement(const NodeListType* nodeList, Element* current, ContainerNode& root)
</del><ins>+void CachedLiveNodeList<NodeListType>::collectionTraverseForward(ElementDescendantIterator& current, unsigned count, unsigned& traversedCount) const
</ins><span class="cx"> {
</span><del>- do {
- current = ElementTraversal::next(current, &root);
- } while (current && !static_cast<const NodeListType*>(nodeList)->nodeMatches(current));
- return current;
-}
-
-template <class NodeListType>
-Element* CachedLiveNodeList<NodeListType>::collectionTraverseForward(Element& current, unsigned count, unsigned& traversedCount) const
-{
- auto& root = rootNode();
- Element* element = &current;
</del><ins>+ auto& nodeList = static_cast<const NodeListType&>(*this);
+ ASSERT(nodeList.nodeMatches(&*current));
+ auto end = collectionEnd();
</ins><span class="cx"> for (traversedCount = 0; traversedCount < count; ++traversedCount) {
</span><del>- element = nextMatchingElement(static_cast<const NodeListType*>(this), element, root);
- if (!element)
- return nullptr;
</del><ins>+ do {
+ ++current;
+ if (current == end)
+ return;
+ } while (!nodeList.nodeMatches(&*current));
</ins><span class="cx"> }
</span><del>- return element;
</del><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> template <class NodeListType>
</span><del>-inline Element* previousMatchingElement(const NodeListType* nodeList, Element* current, ContainerNode& root)
</del><ins>+void CachedLiveNodeList<NodeListType>::collectionTraverseBackward(ElementDescendantIterator& current, unsigned count) const
</ins><span class="cx"> {
</span><del>- do {
- current = ElementTraversal::previous(current, &root);
- } while (current && !nodeList->nodeMatches(current));
- return current;
-}
-
-template <class NodeListType>
-Element* CachedLiveNodeList<NodeListType>::collectionTraverseBackward(Element& current, unsigned count) const
-{
- auto& root = rootNode();
- Element* element = &current;
</del><ins>+ auto& nodeList = static_cast<const NodeListType&>(*this);
+ ASSERT(nodeList.nodeMatches(&*current));
+ auto end = collectionEnd();
</ins><span class="cx"> for (; count; --count) {
</span><del>- element = previousMatchingElement(static_cast<const NodeListType*>(this), element, root);
- if (!element)
- return nullptr;
</del><ins>+ do {
+ --current;
+ if (current == end)
+ return;
+ } while (!nodeList.nodeMatches(&*current));
</ins><span class="cx"> }
</span><del>- return element;
</del><span class="cx"> }
</span><ins>+
</ins><span class="cx"> template <class NodeListType>
</span><span class="cx"> void CachedLiveNodeList<NodeListType>::willValidateIndexCache() const
</span><span class="cx"> {
</span><span class="lines">@@ -223,10 +217,11 @@
</span><span class="cx"> template <class NodeListType>
</span><span class="cx"> void CachedLiveNodeList<NodeListType>::invalidateCache(Document& document) const
</span><span class="cx"> {
</span><del>- if (!m_indexCache.hasValidCache())
</del><ins>+ auto& nodeList = static_cast<const NodeListType&>(*this);
+ if (!m_indexCache.hasValidCache(nodeList))
</ins><span class="cx"> return;
</span><del>- document.unregisterNodeListForInvalidation(const_cast<NodeListType&>(static_cast<const NodeListType&>(*this)));
- m_indexCache.invalidate();
</del><ins>+ document.unregisterNodeListForInvalidation(const_cast<NodeListType&>(nodeList));
+ m_indexCache.invalidate(nodeList);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> template <class NodeListType>
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlHTMLCollectioncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/HTMLCollection.cpp (166459 => 166460)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/HTMLCollection.cpp        2014-03-30 06:01:08 UTC (rev 166459)
+++ trunk/Source/WebCore/html/HTMLCollection.cpp        2014-03-30 08:32:13 UTC (rev 166460)
</span><span class="lines">@@ -133,6 +133,7 @@
</span><span class="cx">
</span><span class="cx"> HTMLCollection::HTMLCollection(ContainerNode& ownerNode, CollectionType type, ElementTraversalType traversalType)
</span><span class="cx"> : m_ownerNode(ownerNode)
</span><ins>+ , m_indexCache(*this)
</ins><span class="cx"> , m_collectionType(type)
</span><span class="cx"> , m_invalidationType(invalidationTypeExcludingIdAndNameAttributes(type))
</span><span class="cx"> , m_rootType(rootTypeFromCollectionType(type))
</span><span class="lines">@@ -151,7 +152,7 @@
</span><span class="cx">
</span><span class="cx"> HTMLCollection::~HTMLCollection()
</span><span class="cx"> {
</span><del>- if (m_indexCache.hasValidCache())
</del><ins>+ if (m_indexCache.hasValidCache(*this))
</ins><span class="cx"> document().unregisterCollection(*this);
</span><span class="cx"> if (hasNamedElementCache())
</span><span class="cx"> document().collectionWillClearIdNameMap(*this);
</span><span class="lines">@@ -330,7 +331,7 @@
</span><span class="cx"> return element;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-Element* HTMLCollection::collectionFirst() const
</del><ins>+Element* HTMLCollection::collectionBegin() const
</ins><span class="cx"> {
</span><span class="cx"> return firstElement(rootNode());
</span><span class="cx"> }
</span><span class="lines">@@ -343,31 +344,29 @@
</span><span class="cx"> return iterateForPreviousElement(last);
</span><span class="cx"> }
</span><span class="cx">
</span><del>-Element* HTMLCollection::collectionTraverseForward(Element& current, unsigned count, unsigned& traversedCount) const
</del><ins>+void HTMLCollection::collectionTraverseForward(Element*& current, unsigned count, unsigned& traversedCount) const
</ins><span class="cx"> {
</span><del>- return traverseForward(current, count, traversedCount, rootNode());
</del><ins>+ current = traverseForward(*current, count, traversedCount, rootNode());
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-Element* HTMLCollection::collectionTraverseBackward(Element& current, unsigned count) const
</del><ins>+void HTMLCollection::collectionTraverseBackward(Element*& current, unsigned count) const
</ins><span class="cx"> {
</span><span class="cx"> // FIXME: This should be optimized similarly to the forward case.
</span><span class="cx"> auto& root = rootNode();
</span><del>- Element* element = &current;
</del><span class="cx"> if (m_shouldOnlyIncludeDirectChildren) {
</span><del>- for (; count && element ; --count)
- element = iterateForPreviousElement(ElementTraversal::previousSibling(element));
- return element;
</del><ins>+ for (; count && current ; --count)
+ current = iterateForPreviousElement(ElementTraversal::previousSibling(current));
+ return;
</ins><span class="cx"> }
</span><del>- for (; count && element ; --count)
- element = iterateForPreviousElement(ElementTraversal::previous(element, &root));
- return element;
</del><ins>+ for (; count && current ; --count)
+ current = iterateForPreviousElement(ElementTraversal::previous(current, &root));
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> void HTMLCollection::invalidateCache(Document& document) const
</span><span class="cx"> {
</span><del>- if (m_indexCache.hasValidCache()) {
</del><ins>+ if (m_indexCache.hasValidCache(*this)) {
</ins><span class="cx"> document.unregisterCollection(const_cast<HTMLCollection&>(*this));
</span><del>- m_indexCache.invalidate();
</del><ins>+ m_indexCache.invalidate(*this);
</ins><span class="cx"> }
</span><span class="cx"> if (hasNamedElementCache())
</span><span class="cx"> invalidateNamedElementCache(document);
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlHTMLCollectionh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/HTMLCollection.h (166459 => 166460)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/HTMLCollection.h        2014-03-30 06:01:08 UTC (rev 166459)
+++ trunk/Source/WebCore/html/HTMLCollection.h        2014-03-30 08:32:13 UTC (rev 166460)
</span><span class="lines">@@ -118,10 +118,11 @@
</span><span class="cx"> virtual void invalidateCache(Document&) const;
</span><span class="cx">
</span><span class="cx"> // For CollectionIndexCache
</span><del>- Element* collectionFirst() const;
</del><ins>+ Element* collectionBegin() const;
</ins><span class="cx"> Element* collectionLast() const;
</span><del>- Element* collectionTraverseForward(Element&, unsigned count, unsigned& traversedCount) const;
- Element* collectionTraverseBackward(Element&, unsigned count) const;
</del><ins>+ Element* collectionEnd() const { return nullptr; }
+ void collectionTraverseForward(Element*&, unsigned count, unsigned& traversedCount) const;
+ void collectionTraverseBackward(Element*&, unsigned count) const;
</ins><span class="cx"> bool collectionCanTraverseBackward() const { return !m_usesCustomForwardOnlyTraversal; }
</span><span class="cx"> void willValidateIndexCache() const { document().registerCollection(const_cast<HTMLCollection&>(*this)); }
</span><span class="cx">
</span><span class="lines">@@ -164,7 +165,7 @@
</span><span class="cx">
</span><span class="cx"> Ref<ContainerNode> m_ownerNode;
</span><span class="cx">
</span><del>- mutable CollectionIndexCache<HTMLCollection, Element> m_indexCache;
</del><ins>+ mutable CollectionIndexCache<HTMLCollection, Element*> m_indexCache;
</ins><span class="cx"> mutable std::unique_ptr<CollectionNamedElementCache> m_namedElementCache;
</span><span class="cx">
</span><span class="cx"> const unsigned m_collectionType : 5;
</span></span></pre>
</div>
</div>
</body>
</html>