<!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>[164707] 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/164707">164707</a></dd>
<dt>Author</dt> <dd>rniwa@webkit.org</dd>
<dt>Date</dt> <dd>2014-02-26 00:26:05 -0800 (Wed, 26 Feb 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>Avoid unnecessary HTML Collection invalidations for id and name attribute changes
https://bugs.webkit.org/show_bug.cgi?id=129361

Reviewed by Benjamin Poulain.

Before this patch, setting id and name attributes resulted in traversing all the ancestors to invalidate
HTML collections on those nodes whenever we had more than one HTMLCollection alive.

Avoid the traversal when HTMLCollections don't have any valid id and name map caches by making each
HTMLCollection explicitly call collectionCachedIdNameMap and collectionWillClearIdNameMap when it caches
or clears the id and name map.

Inspired by https://chromium.googlesource.com/chromium/blink/+/5b06b91b79098f7d42e480f85be32198315d2440

* dom/Document.cpp:
(WebCore::Document::registerCollection): Takes a boolean to indicate whether collection has a valid cache
for the id and name map.
(WebCore::Document::unregisterCollection): Ditto.
(WebCore::Document::collectionCachedIdNameMap): Added.
(WebCore::Document::collectionWillClearIdNameMap): Added.
* dom/Document.h:

* dom/NodeRareData.h:
(WebCore::NodeListsNodeData::adoptDocument): Call invalidateCache on HTML collections after, not before,
calling unregisterCollection and registerCollection since collections' owner nodes have already been
moved to the new document here and invalidateCache uses owner node's document to call
collectionWillClearIdNameMap. So calling invalidateCache before calling unregister/registerCollection
would result in collectionWillClearIdNameMap getting called on a wrong document.

* html/HTMLCollection.cpp:
(WebCore::HTMLCollection::HTMLCollection):
(WebCore::HTMLCollection::~HTMLCollection):
(WebCore::HTMLCollection::invalidateCache):
(WebCore::HTMLCollection::invalidateIdNameCacheMaps): Added the code to uncount itself from the number
of live node lists and HTML collections that need to be invalidated upon id and name attribute changes.
(WebCore::HTMLCollection::updateNameCache):

* html/HTMLCollection.h:
(WebCore::HTMLCollection::invalidateCache):
(WebCore::HTMLCollection::hasIdNameCache): Renamed from hasNameCache.
(WebCore::HTMLCollection::setHasIdNameCache): Renamed from setHasIdNameCache.

* html/HTMLFormControlsCollection.cpp:
(WebCore::HTMLFormControlsCollection::updateNameCache):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoredomDocumentcpp">trunk/Source/WebCore/dom/Document.cpp</a></li>
<li><a href="#trunkSourceWebCoredomDocumenth">trunk/Source/WebCore/dom/Document.h</a></li>
<li><a href="#trunkSourceWebCoredomNodeRareDatah">trunk/Source/WebCore/dom/NodeRareData.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>
<li><a href="#trunkSourceWebCorehtmlHTMLFormControlsCollectioncpp">trunk/Source/WebCore/html/HTMLFormControlsCollection.cpp</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (164706 => 164707)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2014-02-26 08:23:22 UTC (rev 164706)
+++ trunk/Source/WebCore/ChangeLog        2014-02-26 08:26:05 UTC (rev 164707)
</span><span class="lines">@@ -1,3 +1,50 @@
</span><ins>+2014-02-26  Ryosuke Niwa  &lt;rniwa@webkit.org&gt;
+
+        Avoid unnecessary HTML Collection invalidations for id and name attribute changes
+        https://bugs.webkit.org/show_bug.cgi?id=129361
+
+        Reviewed by Benjamin Poulain.
+
+        Before this patch, setting id and name attributes resulted in traversing all the ancestors to invalidate
+        HTML collections on those nodes whenever we had more than one HTMLCollection alive.
+
+        Avoid the traversal when HTMLCollections don't have any valid id and name map caches by making each
+        HTMLCollection explicitly call collectionCachedIdNameMap and collectionWillClearIdNameMap when it caches
+        or clears the id and name map.
+
+        Inspired by https://chromium.googlesource.com/chromium/blink/+/5b06b91b79098f7d42e480f85be32198315d2440
+
+        * dom/Document.cpp:
+        (WebCore::Document::registerCollection): Takes a boolean to indicate whether collection has a valid cache
+        for the id and name map.
+        (WebCore::Document::unregisterCollection): Ditto.
+        (WebCore::Document::collectionCachedIdNameMap): Added.
+        (WebCore::Document::collectionWillClearIdNameMap): Added.
+        * dom/Document.h:
+
+        * dom/NodeRareData.h:
+        (WebCore::NodeListsNodeData::adoptDocument): Call invalidateCache on HTML collections after, not before,
+        calling unregisterCollection and registerCollection since collections' owner nodes have already been
+        moved to the new document here and invalidateCache uses owner node's document to call
+        collectionWillClearIdNameMap. So calling invalidateCache before calling unregister/registerCollection
+        would result in collectionWillClearIdNameMap getting called on a wrong document.
+
+        * html/HTMLCollection.cpp:
+        (WebCore::HTMLCollection::HTMLCollection):
+        (WebCore::HTMLCollection::~HTMLCollection):
+        (WebCore::HTMLCollection::invalidateCache):
+        (WebCore::HTMLCollection::invalidateIdNameCacheMaps): Added the code to uncount itself from the number
+        of live node lists and HTML collections that need to be invalidated upon id and name attribute changes.
+        (WebCore::HTMLCollection::updateNameCache):
+
+        * html/HTMLCollection.h:
+        (WebCore::HTMLCollection::invalidateCache):
+        (WebCore::HTMLCollection::hasIdNameCache): Renamed from hasNameCache.
+        (WebCore::HTMLCollection::setHasIdNameCache): Renamed from setHasIdNameCache.
+
+        * html/HTMLFormControlsCollection.cpp:
+        (WebCore::HTMLFormControlsCollection::updateNameCache):
+
</ins><span class="cx"> 2014-02-25  Frédéric Wang  &lt;fred.wang@free.fr&gt;
</span><span class="cx"> 
</span><span class="cx">         Add support for minsize/maxsize attributes.
</span></span></pre></div>
<a id="trunkSourceWebCoredomDocumentcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/Document.cpp (164706 => 164707)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/Document.cpp        2014-02-26 08:23:22 UTC (rev 164706)
+++ trunk/Source/WebCore/dom/Document.cpp        2014-02-26 08:26:05 UTC (rev 164707)
</span><span class="lines">@@ -3450,17 +3450,20 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void Document::registerCollection(HTMLCollection&amp; collection)
</del><ins>+void Document::registerCollection(HTMLCollection&amp; collection, bool hasIdNameMap)
</ins><span class="cx"> {
</span><del>-    m_nodeListAndCollectionCounts[InvalidateOnIdNameAttrChange]++;
</del><ins>+    if (hasIdNameMap)
+        collectionCachedIdNameMap(collection);
</ins><span class="cx">     m_nodeListAndCollectionCounts[collection.invalidationType()]++;
</span><span class="cx">     if (collection.isRootedAtDocument())
</span><span class="cx">         m_collectionsInvalidatedAtDocument.add(&amp;collection);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void Document::unregisterCollection(HTMLCollection&amp; collection)
</del><ins>+void Document::unregisterCollection(HTMLCollection&amp; collection, bool hasIdNameMap)
</ins><span class="cx"> {
</span><del>-    m_nodeListAndCollectionCounts[InvalidateOnIdNameAttrChange]--;
</del><ins>+    if (hasIdNameMap)
+        collectionWillClearIdNameMap(collection);
+    ASSERT(m_nodeListAndCollectionCounts[collection.invalidationType()]);
</ins><span class="cx">     m_nodeListAndCollectionCounts[collection.invalidationType()]--;
</span><span class="cx">     if (collection.isRootedAtDocument()) {
</span><span class="cx">         ASSERT(m_collectionsInvalidatedAtDocument.contains(&amp;collection));
</span><span class="lines">@@ -3468,6 +3471,19 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void Document::collectionCachedIdNameMap(const HTMLCollection&amp; collection)
+{
+    ASSERT_UNUSED(collection, collection.hasIdNameCache());
+    m_nodeListAndCollectionCounts[InvalidateOnIdNameAttrChange]++;
+}
+
+void Document::collectionWillClearIdNameMap(const HTMLCollection&amp; collection)
+{
+    ASSERT_UNUSED(collection, collection.hasIdNameCache());
+    ASSERT(m_nodeListAndCollectionCounts[InvalidateOnIdNameAttrChange]);
+    m_nodeListAndCollectionCounts[InvalidateOnIdNameAttrChange]--;
+}
+
</ins><span class="cx"> void Document::attachNodeIterator(NodeIterator* ni)
</span><span class="cx"> {
</span><span class="cx">     m_nodeIterators.add(ni);
</span></span></pre></div>
<a id="trunkSourceWebCoredomDocumenth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/Document.h (164706 => 164707)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/Document.h        2014-02-26 08:23:22 UTC (rev 164706)
+++ trunk/Source/WebCore/dom/Document.h        2014-02-26 08:26:05 UTC (rev 164707)
</span><span class="lines">@@ -758,8 +758,10 @@
</span><span class="cx"> 
</span><span class="cx">     void registerNodeList(LiveNodeList&amp;);
</span><span class="cx">     void unregisterNodeList(LiveNodeList&amp;);
</span><del>-    void registerCollection(HTMLCollection&amp;);
-    void unregisterCollection(HTMLCollection&amp;);
</del><ins>+    void registerCollection(HTMLCollection&amp;, bool hasIdNameCache);
+    void unregisterCollection(HTMLCollection&amp;, bool hasIdNameCache);
+    void collectionCachedIdNameMap(const HTMLCollection&amp;);
+    void collectionWillClearIdNameMap(const HTMLCollection&amp;);
</ins><span class="cx">     bool shouldInvalidateNodeListAndCollectionCaches(const QualifiedName* attrName = nullptr) const;
</span><span class="cx">     void invalidateNodeListAndCollectionCaches(const QualifiedName* attrName);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoredomNodeRareDatah"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/NodeRareData.h (164706 => 164707)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/NodeRareData.h        2014-02-26 08:23:22 UTC (rev 164706)
+++ trunk/Source/WebCore/dom/NodeRareData.h        2014-02-26 08:26:05 UTC (rev 164707)
</span><span class="lines">@@ -225,33 +225,38 @@
</span><span class="cx"> 
</span><span class="cx">     void adoptDocument(Document* oldDocument, Document* newDocument)
</span><span class="cx">     {
</span><del>-        invalidateCaches();
</del><ins>+        if (oldDocument == newDocument) {
+            invalidateCaches();
+            return;
+        }
</ins><span class="cx"> 
</span><del>-        if (oldDocument != newDocument) {
-            for (auto it = m_atomicNameCaches.begin(), end = m_atomicNameCaches.end(); it != end; ++it) {
-                LiveNodeList&amp; list = *it-&gt;value;
-                oldDocument-&gt;unregisterNodeList(list);
-                newDocument-&gt;registerNodeList(list);
-            }
</del><ins>+        for (auto it : m_atomicNameCaches) {
+            LiveNodeList&amp; list = *it.value;
+            oldDocument-&gt;unregisterNodeList(list);
+            newDocument-&gt;registerNodeList(list);
+            list.invalidateCache();
+        }
</ins><span class="cx"> 
</span><del>-            for (auto it = m_nameCaches.begin(), end = m_nameCaches.end(); it != end; ++it) {
-                LiveNodeList&amp; list = *it-&gt;value;
-                oldDocument-&gt;unregisterNodeList(list);
-                newDocument-&gt;registerNodeList(list);
-            }
</del><ins>+        for (auto it : m_nameCaches) {
+            LiveNodeList&amp; list = *it.value;
+            oldDocument-&gt;unregisterNodeList(list);
+            newDocument-&gt;registerNodeList(list);
+            list.invalidateCache();
+        }
</ins><span class="cx"> 
</span><del>-            for (auto it = m_tagNodeListCacheNS.begin(), end = m_tagNodeListCacheNS.end(); it != end; ++it) {
-                LiveNodeList&amp; list = *it-&gt;value;
-                ASSERT(!list.isRootedAtDocument());
-                oldDocument-&gt;unregisterNodeList(list);
-                newDocument-&gt;registerNodeList(list);
-            }
</del><ins>+        for (auto it : m_tagNodeListCacheNS) {
+            LiveNodeList&amp; list = *it.value;
+            ASSERT(!list.isRootedAtDocument());
+            oldDocument-&gt;unregisterNodeList(list);
+            newDocument-&gt;registerNodeList(list);
+            list.invalidateCache();
+        }
</ins><span class="cx"> 
</span><del>-            for (auto it = m_cachedCollections.begin(), end = m_cachedCollections.end(); it != end; ++it) {
-                HTMLCollection&amp; collection = *it-&gt;value;
-                oldDocument-&gt;unregisterCollection(collection);
-                newDocument-&gt;registerCollection(collection);
-            }
</del><ins>+        for (auto it : m_cachedCollections) {
+            HTMLCollection&amp; collection = *it.value;
+            oldDocument-&gt;unregisterCollection(collection, collection.hasIdNameCache());
+            newDocument-&gt;registerCollection(collection, collection.hasIdNameCache());
+            collection.invalidateCache();
</ins><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlHTMLCollectioncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/HTMLCollection.cpp (164706 => 164707)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/HTMLCollection.cpp        2014-02-26 08:23:22 UTC (rev 164706)
+++ trunk/Source/WebCore/html/HTMLCollection.cpp        2014-02-26 08:26:05 UTC (rev 164707)
</span><span class="lines">@@ -145,7 +145,7 @@
</span><span class="cx">     ASSERT(m_invalidationType == static_cast&lt;unsigned&gt;(invalidationTypeExcludingIdAndNameAttributes(type)));
</span><span class="cx">     ASSERT(m_collectionType == static_cast&lt;unsigned&gt;(type));
</span><span class="cx"> 
</span><del>-    document().registerCollection(*this);
</del><ins>+    document().registerCollection(*this, hasIdNameCache());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> PassRefPtr&lt;HTMLCollection&gt; HTMLCollection::create(ContainerNode&amp; base, CollectionType type)
</span><span class="lines">@@ -155,7 +155,7 @@
</span><span class="cx"> 
</span><span class="cx"> HTMLCollection::~HTMLCollection()
</span><span class="cx"> {
</span><del>-    document().unregisterCollection(*this);
</del><ins>+    document().unregisterCollection(*this, hasIdNameCache());
</ins><span class="cx">     // HTMLNameCollection removes cache by itself.
</span><span class="cx">     if (type() != WindowNamedItems &amp;&amp; type() != DocumentNamedItems)
</span><span class="cx">         ownerNode().nodeLists()-&gt;removeCachedCollection(this);
</span><span class="lines">@@ -367,14 +367,16 @@
</span><span class="cx"> void HTMLCollection::invalidateCache() const
</span><span class="cx"> {
</span><span class="cx">     m_indexCache.invalidate();
</span><del>-    m_isNameCacheValid = false;
</del><span class="cx">     m_isItemRefElementsCacheValid = false;
</span><del>-    m_idCache.clear();
-    m_nameCache.clear();
</del><ins>+    if (hasIdNameCache())
+        invalidateIdNameCacheMaps();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void HTMLCollection::invalidateIdNameCacheMaps() const
</span><span class="cx"> {
</span><ins>+    ASSERT(hasIdNameCache());
+    document().collectionWillClearIdNameMap(*this);
+    m_isNameCacheValid = false;
</ins><span class="cx">     m_idCache.clear();
</span><span class="cx">     m_nameCache.clear();
</span><span class="cx"> }
</span><span class="lines">@@ -429,7 +431,7 @@
</span><span class="cx"> 
</span><span class="cx"> void HTMLCollection::updateNameCache() const
</span><span class="cx"> {
</span><del>-    if (hasNameCache())
</del><ins>+    if (hasIdNameCache())
</ins><span class="cx">         return;
</span><span class="cx"> 
</span><span class="cx">     ContainerNode&amp; root = rootNode();
</span><span class="lines">@@ -446,7 +448,7 @@
</span><span class="cx">             appendNameCache(nameAttrVal, element);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    setHasNameCache();
</del><ins>+    setHasIdNameCache();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool HTMLCollection::hasNamedItem(const AtomicString&amp; name) const
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlHTMLCollectionh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/HTMLCollection.h (164706 => 164707)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/HTMLCollection.h        2014-02-26 08:23:22 UTC (rev 164706)
+++ trunk/Source/WebCore/html/HTMLCollection.h        2014-02-26 08:26:05 UTC (rev 164707)
</span><span class="lines">@@ -61,11 +61,10 @@
</span><span class="cx">     {
</span><span class="cx">         if (!attrName || shouldInvalidateTypeOnAttributeChange(invalidationType(), *attrName))
</span><span class="cx">             invalidateCache();
</span><del>-        else if (*attrName == HTMLNames::idAttr || *attrName == HTMLNames::nameAttr)
</del><ins>+        else if (hasIdNameCache() &amp;&amp; (*attrName == HTMLNames::idAttr || *attrName == HTMLNames::nameAttr))
</ins><span class="cx">             invalidateIdNameCacheMaps();
</span><span class="cx">     }
</span><span class="cx">     virtual void invalidateCache() const;
</span><del>-    void invalidateIdNameCacheMaps() const;
</del><span class="cx"> 
</span><span class="cx">     // For CollectionIndexCache
</span><span class="cx">     Element* collectionFirst() const;
</span><span class="lines">@@ -74,10 +73,13 @@
</span><span class="cx">     Element* collectionTraverseBackward(Element&amp;, unsigned count) const;
</span><span class="cx">     bool collectionCanTraverseBackward() const { return !m_usesCustomForwardOnlyTraversal; }
</span><span class="cx"> 
</span><ins>+    bool hasIdNameCache() const { return m_isNameCacheValid; }
+
</ins><span class="cx"> protected:
</span><span class="cx">     enum ElementTraversalType { NormalTraversal, CustomForwardOnlyTraversal };
</span><span class="cx">     HTMLCollection(ContainerNode&amp; base, CollectionType, ElementTraversalType = NormalTraversal);
</span><span class="cx"> 
</span><ins>+    void invalidateIdNameCacheMaps() const;
</ins><span class="cx">     virtual void updateNameCache() const;
</span><span class="cx"> 
</span><span class="cx">     typedef HashMap&lt;AtomicStringImpl*, OwnPtr&lt;Vector&lt;Element*&gt;&gt;&gt; NodeCacheMap;
</span><span class="lines">@@ -95,8 +97,11 @@
</span><span class="cx"> 
</span><span class="cx">     NodeListRootType rootType() const { return static_cast&lt;NodeListRootType&gt;(m_rootType); }
</span><span class="cx"> 
</span><del>-    bool hasNameCache() const { return m_isNameCacheValid; }
-    void setHasNameCache() const { m_isNameCacheValid = true; }
</del><ins>+    void setHasIdNameCache() const
+    {
+        m_isNameCacheValid = true;
+        document().collectionCachedIdNameMap(*this);
+    }
</ins><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     static void append(NodeCacheMap&amp;, const AtomicString&amp;, Element*);
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlHTMLFormControlsCollectioncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/HTMLFormControlsCollection.cpp (164706 => 164707)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/HTMLFormControlsCollection.cpp        2014-02-26 08:23:22 UTC (rev 164706)
+++ trunk/Source/WebCore/html/HTMLFormControlsCollection.cpp        2014-02-26 08:26:05 UTC (rev 164707)
</span><span class="lines">@@ -137,7 +137,7 @@
</span><span class="cx"> 
</span><span class="cx"> void HTMLFormControlsCollection::updateNameCache() const
</span><span class="cx"> {
</span><del>-    if (hasNameCache())
</del><ins>+    if (hasIdNameCache())
</ins><span class="cx">         return;
</span><span class="cx"> 
</span><span class="cx">     HashSet&lt;AtomicStringImpl*&gt; foundInputElements;
</span><span class="lines">@@ -174,7 +174,7 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    setHasNameCache();
</del><ins>+    setHasIdNameCache();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void HTMLFormControlsCollection::invalidateCache() const
</span></span></pre>
</div>
</div>

</body>
</html>