<!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&gt;::CollectionIndexCache):
(WebCore::Iterator&gt;::nodeCount):
(WebCore::Iterator&gt;::computeNodeCountUpdatingListCache):
(WebCore::Iterator&gt;::traverseBackwardTo):
(WebCore::Iterator&gt;::traverseForwardTo):
(WebCore::Iterator&gt;::nodeAt):
(WebCore::Iterator&gt;::invalidate):
        
    Make CollectionIndexCache iterator based instead of using NodeType*. The iterator type may
    still be a Node* though.

(WebCore::NodeType&gt;::CollectionIndexCache): Deleted.
(WebCore::NodeType&gt;::nodeCount): Deleted.
(WebCore::NodeType&gt;::computeNodeCountUpdatingListCache): Deleted.
(WebCore::NodeType&gt;::nodeBeforeCached): Deleted.
(WebCore::NodeType&gt;::nodeAfterCached): Deleted.
(WebCore::NodeType&gt;::nodeAt): Deleted.
(WebCore::NodeType&gt;::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&lt;NodeListType&gt;::CachedLiveNodeList):
(WebCore::CachedLiveNodeList&lt;NodeListType&gt;::~CachedLiveNodeList):
(WebCore::CachedLiveNodeList&lt;NodeListType&gt;::collectionBegin):
(WebCore::CachedLiveNodeList&lt;NodeListType&gt;::collectionLast):
(WebCore::CachedLiveNodeList&lt;NodeListType&gt;::collectionTraverseForward):
(WebCore::CachedLiveNodeList&lt;NodeListType&gt;::collectionTraverseBackward):
(WebCore::CachedLiveNodeList&lt;NodeListType&gt;::invalidateCache):
(WebCore::CachedLiveNodeList&lt;NodeListType&gt;::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  &lt;antti@apple.com&gt;
+
+        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&gt;::CollectionIndexCache):
+        (WebCore::Iterator&gt;::nodeCount):
+        (WebCore::Iterator&gt;::computeNodeCountUpdatingListCache):
+        (WebCore::Iterator&gt;::traverseBackwardTo):
+        (WebCore::Iterator&gt;::traverseForwardTo):
+        (WebCore::Iterator&gt;::nodeAt):
+        (WebCore::Iterator&gt;::invalidate):
+        
+            Make CollectionIndexCache iterator based instead of using NodeType*. The iterator type may
+            still be a Node* though.
+
+        (WebCore::NodeType&gt;::CollectionIndexCache): Deleted.
+        (WebCore::NodeType&gt;::nodeCount): Deleted.
+        (WebCore::NodeType&gt;::computeNodeCountUpdatingListCache): Deleted.
+        (WebCore::NodeType&gt;::nodeBeforeCached): Deleted.
+        (WebCore::NodeType&gt;::nodeAfterCached): Deleted.
+        (WebCore::NodeType&gt;::nodeAt): Deleted.
+        (WebCore::NodeType&gt;::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&lt;NodeListType&gt;::CachedLiveNodeList):
+        (WebCore::CachedLiveNodeList&lt;NodeListType&gt;::~CachedLiveNodeList):
+        (WebCore::CachedLiveNodeList&lt;NodeListType&gt;::collectionBegin):
+        (WebCore::CachedLiveNodeList&lt;NodeListType&gt;::collectionLast):
+        (WebCore::CachedLiveNodeList&lt;NodeListType&gt;::collectionTraverseForward):
+        (WebCore::CachedLiveNodeList&lt;NodeListType&gt;::collectionTraverseBackward):
+        (WebCore::CachedLiveNodeList&lt;NodeListType&gt;::invalidateCache):
+        (WebCore::CachedLiveNodeList&lt;NodeListType&gt;::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  &lt;commit-queue@webkit.org&gt;
</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&amp; 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-&gt;firstChild();
</span><span class="cx"> }
</span><span class="lines">@@ -63,25 +64,21 @@
</span><span class="cx">     return m_parent-&gt;lastChild();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-Node* ChildNodeList::collectionTraverseForward(Node&amp; current, unsigned count, unsigned&amp; traversedCount) const
</del><ins>+void ChildNodeList::collectionTraverseForward(Node*&amp; current, unsigned count, unsigned&amp; traversedCount) const
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(count);
</span><del>-    Node* child = &amp;current;
</del><span class="cx">     for (traversedCount = 0; traversedCount &lt; count; ++traversedCount) {
</span><del>-        child = child-&gt;nextSibling();
-        if (!child)
-            return nullptr;
</del><ins>+        current = current-&gt;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&amp; current, unsigned count) const
</del><ins>+void ChildNodeList::collectionTraverseBackward(Node*&amp; current, unsigned count) const
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(count);
</span><del>-    Node* child = &amp;current;
-    for (; count &amp;&amp; child ; --count)
-        child = child-&gt;previousSibling();
-    return child;
</del><ins>+    for (; count &amp;&amp; current ; --count)
+        current = current-&gt;previousSibling();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> Node* ChildNodeList::namedItem(const AtomicString&amp; 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&amp;, unsigned count, unsigned&amp; traversedCount) const;
-    Node* collectionTraverseBackward(Node&amp;, unsigned count) const;
</del><ins>+    Node* collectionEnd() const { return nullptr; }
+    void collectionTraverseForward(Node*&amp;, unsigned count, unsigned&amp; traversedCount) const;
+    void collectionTraverseBackward(Node*&amp;, 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&lt;ContainerNode&gt; m_parent;
</span><del>-    mutable CollectionIndexCache&lt;ChildNodeList, Node&gt; m_indexCache;
</del><ins>+    mutable CollectionIndexCache&lt;ChildNodeList, Node*&gt; 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 &lt;class Collection, class NodeType&gt;
</del><ins>+template &lt;class Collection, class Iterator&gt;
</ins><span class="cx"> class CollectionIndexCache {
</span><span class="cx"> public:
</span><del>-    CollectionIndexCache();
</del><ins>+    explicit CollectionIndexCache(const Collection&amp;);
</ins><span class="cx"> 
</span><ins>+    typedef typename std::iterator_traits&lt;Iterator&gt;::value_type NodeType;
+
</ins><span class="cx">     unsigned nodeCount(const Collection&amp;);
</span><span class="cx">     NodeType* nodeAt(const Collection&amp;, 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&amp; collection) const { return m_current != collection.collectionEnd() || m_nodeCountValid || m_listValid; }
+    void invalidate(const Collection&amp;);
</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&amp;);
</span><del>-    NodeType* nodeBeforeCached(const Collection&amp;, unsigned);
-    NodeType* nodeAfterCached(const Collection&amp;, unsigned);
</del><ins>+    NodeType* traverseBackwardTo(const Collection&amp;, unsigned);
+    NodeType* traverseForwardTo(const Collection&amp;, 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&lt;NodeType*&gt; 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 &lt;class Collection, class NodeType&gt;
-inline CollectionIndexCache&lt;Collection, NodeType&gt;::CollectionIndexCache()
-    : m_currentNode(nullptr)
</del><ins>+template &lt;class Collection, class Iterator&gt;
+inline CollectionIndexCache&lt;Collection, Iterator&gt;::CollectionIndexCache(const Collection&amp; 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 &lt;class Collection, class NodeType&gt;
-inline unsigned CollectionIndexCache&lt;Collection, NodeType&gt;::nodeCount(const Collection&amp; collection)
</del><ins>+template &lt;class Collection, class Iterator&gt;
+inline unsigned CollectionIndexCache&lt;Collection, Iterator&gt;::nodeCount(const Collection&amp; 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 &lt;class Collection, class NodeType&gt;
-unsigned CollectionIndexCache&lt;Collection, NodeType&gt;::computeNodeCountUpdatingListCache(const Collection&amp; collection)
</del><ins>+template &lt;class Collection, class Iterator&gt;
+unsigned CollectionIndexCache&lt;Collection, Iterator&gt;::computeNodeCountUpdatingListCache(const Collection&amp; 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(&amp;*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 &lt;class Collection, class NodeType&gt;
-inline NodeType* CollectionIndexCache&lt;Collection, NodeType&gt;::nodeBeforeCached(const Collection&amp; collection, unsigned index)
</del><ins>+template &lt;class Collection, class Iterator&gt;
+inline typename CollectionIndexCache&lt;Collection, Iterator&gt;::NodeType* CollectionIndexCache&lt;Collection, Iterator&gt;::traverseBackwardTo(const Collection&amp; 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 &lt; m_currentIndex);
</span><span class="cx"> 
</span><span class="cx">     bool firstIsCloser = index &lt; 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 &amp;*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 &amp;*m_current;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-template &lt;class Collection, class NodeType&gt;
-inline NodeType* CollectionIndexCache&lt;Collection, NodeType&gt;::nodeAfterCached(const Collection&amp; collection, unsigned index)
</del><ins>+template &lt;class Collection, class Iterator&gt;
+inline typename CollectionIndexCache&lt;Collection, Iterator&gt;::NodeType* CollectionIndexCache&lt;Collection, Iterator&gt;::traverseForwardTo(const Collection&amp; 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 &gt; m_currentIndex);
</span><span class="cx">     ASSERT(!m_nodeCountValid || index &lt; m_nodeCount);
</span><span class="cx"> 
</span><span class="cx">     bool lastIsCloser = m_nodeCountValid &amp;&amp; m_nodeCount - index &lt; index - m_currentIndex;
</span><span class="cx">     if (lastIsCloser &amp;&amp; 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 &lt; 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 &amp;*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 &lt; index);
-
-    if (!m_currentNode &amp;&amp; !m_nodeCountValid) {
</del><ins>+    if (m_current == collection.collectionEnd()) {
+        ASSERT(m_currentIndex &lt; 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 &amp;*m_current;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-template &lt;class Collection, class NodeType&gt;
-inline NodeType* CollectionIndexCache&lt;Collection, NodeType&gt;::nodeAt(const Collection&amp; collection, unsigned index)
</del><ins>+template &lt;class Collection, class Iterator&gt;
+inline typename CollectionIndexCache&lt;Collection, Iterator&gt;::NodeType* CollectionIndexCache&lt;Collection, Iterator&gt;::nodeAt(const Collection&amp; collection, unsigned index)
</ins><span class="cx"> {
</span><span class="cx">     if (m_nodeCountValid &amp;&amp; index &gt;= 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 &gt; m_currentIndex)
</span><del>-            return nodeAfterCached(collection, index);
</del><ins>+            return traverseForwardTo(collection, index);
</ins><span class="cx">         if (index &lt; m_currentIndex)
</span><del>-            return nodeBeforeCached(collection, index);
-        return m_currentNode;
</del><ins>+            return traverseBackwardTo(collection, index);
+        return &amp;*m_current;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     bool lastIsCloser = m_nodeCountValid &amp;&amp; m_nodeCount - index &lt; index;
</span><span class="cx">     if (lastIsCloser &amp;&amp; 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 &lt; 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 &amp;*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 &amp;&amp; m_currentNode) {
-        m_currentNode = collection.collectionTraverseForward(*m_currentNode, index, m_currentIndex);
-        ASSERT(m_currentNode || m_currentIndex &lt; index);
</del><ins>+    if (index &amp;&amp; m_current != end) {
+        collection.collectionTraverseForward(m_current, index, m_currentIndex);
+        ASSERT(m_current != end || m_currentIndex &lt; index);
</ins><span class="cx">     }
</span><del>-    if (!m_currentNode &amp;&amp; !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 &amp;*m_current;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-template &lt;class Collection, class NodeType&gt;
-void CollectionIndexCache&lt;Collection, NodeType&gt;::invalidate()
</del><ins>+template &lt;class Collection, class Iterator&gt;
+void CollectionIndexCache&lt;Collection, Iterator&gt;::invalidate(const Collection&amp; 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&amp; operator++();
</span><ins>+    ElementDescendantIterator&amp; operator--();
</ins><span class="cx"> 
</span><span class="cx">     Element&amp; operator*();
</span><span class="cx">     Element* operator-&gt;();
</span><span class="lines">@@ -82,6 +83,7 @@
</span><span class="cx">     ElementDescendantIteratorAdapter(ContainerNode&amp; 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&amp; m_root;
</span><span class="lines">@@ -92,6 +94,7 @@
</span><span class="cx">     ElementDescendantConstIteratorAdapter(const ContainerNode&amp; 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&amp; 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&amp; ElementDescendantIterator::operator--()
+{
+    ASSERT(m_current);
+    ASSERT(!m_assertions.domTreeHasMutated());
+
+    Element* previousSibling = ElementTraversal::previousSibling(m_current);
+
+    if (!previousSibling) {
+        m_current = m_current-&gt;parentElement();
+        // The stack optimizes for forward traversal only, this just maintains consistency.
+        if (m_current-&gt;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&amp; 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(&amp;m_root));
+}
+
</ins><span class="cx"> // ElementDescendantConstIteratorAdapter
</span><span class="cx"> 
</span><span class="cx"> inline ElementDescendantConstIteratorAdapter::ElementDescendantConstIteratorAdapter(const ContainerNode&amp; 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(&amp;m_root));
+}
+
</ins><span class="cx"> // Standalone functions
</span><span class="cx"> 
</span><span class="cx"> inline ElementDescendantIteratorAdapter elementDescendants(ContainerNode&amp; 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 &lt;&gt; struct iterator_traits&lt;WebCore::ElementDescendantIterator&gt; {
+    typedef WebCore::Element value_type;
+};
+template &lt;&gt; struct iterator_traits&lt;WebCore::ElementDescendantConstIterator&gt; {
+    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 &quot;CollectionIndexCache.h&quot;
</span><span class="cx"> #include &quot;CollectionType.h&quot;
</span><span class="cx"> #include &quot;Document.h&quot;
</span><del>-#include &quot;ElementTraversal.h&quot;
</del><ins>+#include &quot;ElementDescendantIterator.h&quot;
</ins><span class="cx"> #include &quot;HTMLNames.h&quot;
</span><span class="cx"> #include &quot;NodeList.h&quot;
</span><span class="cx"> #include &lt;wtf/Forward.h&gt;
</span><span class="lines">@@ -69,8 +69,6 @@
</span><span class="cx"> 
</span><span class="cx">     ContainerNode&amp; rootNode() const;
</span><span class="cx"> 
</span><del>-    Element* iterateForPreviousElement(Element* current) const;
-
</del><span class="cx">     Ref&lt;ContainerNode&gt; 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&amp;, unsigned count, unsigned&amp; traversedCount) const;
-    Element* collectionTraverseBackward(Element&amp;, unsigned count) const;
</del><ins>+    ElementDescendantIterator collectionBegin() const;
+    ElementDescendantIterator collectionLast() const;
+    ElementDescendantIterator collectionEnd() const { return ElementDescendantIterator(); }
+    void collectionTraverseForward(ElementDescendantIterator&amp;, unsigned count, unsigned&amp; traversedCount) const;
+    void collectionTraverseBackward(ElementDescendantIterator&amp;, 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&amp; rootNode() const;
</span><span class="cx"> 
</span><del>-    mutable CollectionIndexCache&lt;NodeListType, Element&gt; m_indexCache;
</del><ins>+    mutable CollectionIndexCache&lt;NodeListType, ElementDescendantIterator&gt; m_indexCache;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> ALWAYS_INLINE bool shouldInvalidateTypeOnAttributeChange(NodeListInvalidationType type, const QualifiedName&amp; attrName)
</span><span class="lines">@@ -132,13 +131,15 @@
</span><span class="cx"> template &lt;class NodeListType&gt;
</span><span class="cx"> CachedLiveNodeList&lt;NodeListType&gt;::CachedLiveNodeList(ContainerNode&amp; ownerNode, NodeListInvalidationType invalidationType)
</span><span class="cx">     : LiveNodeList(ownerNode, invalidationType)
</span><ins>+    , m_indexCache(static_cast&lt;NodeListType&amp;&gt;(*this))
</ins><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template &lt;class NodeListType&gt;
</span><span class="cx"> CachedLiveNodeList&lt;NodeListType&gt;::~CachedLiveNodeList()
</span><span class="cx"> {
</span><del>-    if (m_indexCache.hasValidCache())
</del><ins>+    auto&amp; nodeList = static_cast&lt;const NodeListType&amp;&gt;(*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 &lt;class NodeListType&gt;
</span><del>-Element* CachedLiveNodeList&lt;NodeListType&gt;::collectionFirst() const
</del><ins>+ElementDescendantIterator CachedLiveNodeList&lt;NodeListType&gt;::collectionBegin() const
</ins><span class="cx"> {
</span><del>-    auto&amp; root = rootNode();
-    Element* element = ElementTraversal::firstWithin(&amp;root);
-    while (element &amp;&amp; !static_cast&lt;const NodeListType*&gt;(this)-&gt;nodeMatches(element))
-        element = ElementTraversal::next(element, &amp;root);
-    return element;
</del><ins>+    auto&amp; nodeList = static_cast&lt;const NodeListType&amp;&gt;(*this);
+    auto descendants = elementDescendants(rootNode());
+    auto end = descendants.end();
+    for (auto it = descendants.begin(); it != end; ++it) {
+        if (nodeList.nodeMatches(&amp;*it))
+            return it;
+    }
+    return end;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template &lt;class NodeListType&gt;
</span><del>-Element* CachedLiveNodeList&lt;NodeListType&gt;::collectionLast() const
</del><ins>+ElementDescendantIterator CachedLiveNodeList&lt;NodeListType&gt;::collectionLast() const
</ins><span class="cx"> {
</span><del>-    auto&amp; root = rootNode();
-    Element* element = ElementTraversal::lastWithin(&amp;root);
-    while (element &amp;&amp; !static_cast&lt;const NodeListType*&gt;(this)-&gt;nodeMatches(element))
-        element = ElementTraversal::previous(element, &amp;root);
-    return element;
</del><ins>+    auto&amp; nodeList = static_cast&lt;const NodeListType&amp;&gt;(*this);
+    auto descendants = elementDescendants(rootNode());
+    auto end = descendants.end();
+    for (auto it = descendants.last(); it != end; --it) {
+        if (nodeList.nodeMatches(&amp;*it))
+            return it;
+    }
+    return end;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template &lt;class NodeListType&gt;
</span><del>-inline Element* nextMatchingElement(const NodeListType* nodeList, Element* current, ContainerNode&amp; root)
</del><ins>+void CachedLiveNodeList&lt;NodeListType&gt;::collectionTraverseForward(ElementDescendantIterator&amp; current, unsigned count, unsigned&amp; traversedCount) const
</ins><span class="cx"> {
</span><del>-    do {
-        current = ElementTraversal::next(current, &amp;root);
-    } while (current &amp;&amp; !static_cast&lt;const NodeListType*&gt;(nodeList)-&gt;nodeMatches(current));
-    return current;
-}
-
-template &lt;class NodeListType&gt;
-Element* CachedLiveNodeList&lt;NodeListType&gt;::collectionTraverseForward(Element&amp; current, unsigned count, unsigned&amp; traversedCount) const
-{
-    auto&amp; root = rootNode();
-    Element* element = &amp;current;
</del><ins>+    auto&amp; nodeList = static_cast&lt;const NodeListType&amp;&gt;(*this);
+    ASSERT(nodeList.nodeMatches(&amp;*current));
+    auto end = collectionEnd();
</ins><span class="cx">     for (traversedCount = 0; traversedCount &lt; count; ++traversedCount) {
</span><del>-        element = nextMatchingElement(static_cast&lt;const NodeListType*&gt;(this), element, root);
-        if (!element)
-            return nullptr;
</del><ins>+        do {
+            ++current;
+            if (current == end)
+                return;
+        } while (!nodeList.nodeMatches(&amp;*current));
</ins><span class="cx">     }
</span><del>-    return element;
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template &lt;class NodeListType&gt;
</span><del>-inline Element* previousMatchingElement(const NodeListType* nodeList, Element* current, ContainerNode&amp; root)
</del><ins>+void CachedLiveNodeList&lt;NodeListType&gt;::collectionTraverseBackward(ElementDescendantIterator&amp; current, unsigned count) const
</ins><span class="cx"> {
</span><del>-    do {
-        current = ElementTraversal::previous(current, &amp;root);
-    } while (current &amp;&amp; !nodeList-&gt;nodeMatches(current));
-    return current;
-}
-
-template &lt;class NodeListType&gt;
-Element* CachedLiveNodeList&lt;NodeListType&gt;::collectionTraverseBackward(Element&amp; current, unsigned count) const
-{
-    auto&amp; root = rootNode();
-    Element* element = &amp;current;
</del><ins>+    auto&amp; nodeList = static_cast&lt;const NodeListType&amp;&gt;(*this);
+    ASSERT(nodeList.nodeMatches(&amp;*current));
+    auto end = collectionEnd();
</ins><span class="cx">     for (; count; --count) {
</span><del>-        element = previousMatchingElement(static_cast&lt;const NodeListType*&gt;(this), element, root);
-        if (!element)
-            return nullptr;
</del><ins>+        do {
+            --current;
+            if (current == end)
+                return;
+        } while (!nodeList.nodeMatches(&amp;*current));
</ins><span class="cx">     }
</span><del>-    return element;
</del><span class="cx"> }
</span><ins>+
</ins><span class="cx"> template &lt;class NodeListType&gt;
</span><span class="cx"> void CachedLiveNodeList&lt;NodeListType&gt;::willValidateIndexCache() const
</span><span class="cx"> {
</span><span class="lines">@@ -223,10 +217,11 @@
</span><span class="cx"> template &lt;class NodeListType&gt;
</span><span class="cx"> void CachedLiveNodeList&lt;NodeListType&gt;::invalidateCache(Document&amp; document) const
</span><span class="cx"> {
</span><del>-    if (!m_indexCache.hasValidCache())
</del><ins>+    auto&amp; nodeList = static_cast&lt;const NodeListType&amp;&gt;(*this);
+    if (!m_indexCache.hasValidCache(nodeList))
</ins><span class="cx">         return;
</span><del>-    document.unregisterNodeListForInvalidation(const_cast&lt;NodeListType&amp;&gt;(static_cast&lt;const NodeListType&amp;&gt;(*this)));
-    m_indexCache.invalidate();
</del><ins>+    document.unregisterNodeListForInvalidation(const_cast&lt;NodeListType&amp;&gt;(nodeList));
+    m_indexCache.invalidate(nodeList);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template &lt;class NodeListType&gt;
</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&amp; 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&amp; current, unsigned count, unsigned&amp; traversedCount) const
</del><ins>+void HTMLCollection::collectionTraverseForward(Element*&amp; current, unsigned count, unsigned&amp; 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&amp; current, unsigned count) const
</del><ins>+void HTMLCollection::collectionTraverseBackward(Element*&amp; 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&amp; root = rootNode();
</span><del>-    Element* element = &amp;current;
</del><span class="cx">     if (m_shouldOnlyIncludeDirectChildren) {
</span><del>-        for (; count &amp;&amp; element ; --count)
-            element = iterateForPreviousElement(ElementTraversal::previousSibling(element));
-        return element;
</del><ins>+        for (; count &amp;&amp; current ; --count)
+            current = iterateForPreviousElement(ElementTraversal::previousSibling(current));
+        return;
</ins><span class="cx">     }
</span><del>-    for (; count &amp;&amp; element ; --count)
-        element = iterateForPreviousElement(ElementTraversal::previous(element, &amp;root));
-    return element;
</del><ins>+    for (; count &amp;&amp; current ; --count)
+        current = iterateForPreviousElement(ElementTraversal::previous(current, &amp;root));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void HTMLCollection::invalidateCache(Document&amp; 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&lt;HTMLCollection&amp;&gt;(*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&amp;) 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&amp;, unsigned count, unsigned&amp; traversedCount) const;
-    Element* collectionTraverseBackward(Element&amp;, unsigned count) const;
</del><ins>+    Element* collectionEnd() const { return nullptr; }
+    void collectionTraverseForward(Element*&amp;, unsigned count, unsigned&amp; traversedCount) const;
+    void collectionTraverseBackward(Element*&amp;, unsigned count) const;
</ins><span class="cx">     bool collectionCanTraverseBackward() const { return !m_usesCustomForwardOnlyTraversal; }
</span><span class="cx">     void willValidateIndexCache() const { document().registerCollection(const_cast&lt;HTMLCollection&amp;&gt;(*this)); }
</span><span class="cx"> 
</span><span class="lines">@@ -164,7 +165,7 @@
</span><span class="cx"> 
</span><span class="cx">     Ref&lt;ContainerNode&gt; m_ownerNode;
</span><span class="cx"> 
</span><del>-    mutable CollectionIndexCache&lt;HTMLCollection, Element&gt; m_indexCache;
</del><ins>+    mutable CollectionIndexCache&lt;HTMLCollection, Element*&gt; m_indexCache;
</ins><span class="cx">     mutable std::unique_ptr&lt;CollectionNamedElementCache&gt; m_namedElementCache;
</span><span class="cx"> 
</span><span class="cx">     const unsigned m_collectionType : 5;
</span></span></pre>
</div>
</div>

</body>
</html>