<!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>[196636] trunk</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/196636">196636</a></dd>
<dt>Author</dt> <dd>antti@apple.com</dd>
<dt>Date</dt> <dd>2016-02-16 09:24:01 -0800 (Tue, 16 Feb 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>Factor id mutation style invalidation code into a class
https://bugs.webkit.org/show_bug.cgi?id=154287

Reviewed by Andreas Kling.

Source/WebCore:

Also add a cheap basic optimization that avoids descendant invalidation if they can not be affected.

It would be easy to implement fine grained invalidation like with classes and attribute selectors.
However dynamic id changes are not common enough (nor recommended) to pay the memory cost of
the required data structures.

Test: fast/css/style-invalidation-id-change-descendants.html

* CMakeLists.txt:
* WebCore.vcxproj/WebCore.vcxproj:
* WebCore.xcodeproj/project.pbxproj:
* css/RuleFeature.cpp:
(WebCore::RuleFeatureSet::recursivelyCollectFeaturesFromSelector):
(WebCore::RuleFeatureSet::add):
(WebCore::RuleFeatureSet::clear):
* css/RuleFeature.h:
* dom/Element.cpp:
(WebCore::makeIdForStyleResolution):
(WebCore::Element::attributeChanged):
(WebCore::checkNeedsStyleInvalidationForIdChange): Deleted.
* style/IdChangeInvalidation.cpp: Added.
(WebCore::Style::IdChangeInvalidation::invalidateStyle):
* style/IdChangeInvalidation.h: Added.
(WebCore::Style::IdChangeInvalidation::IdChangeInvalidation):
(WebCore::Style::IdChangeInvalidation::~IdChangeInvalidation):

LayoutTests:

* fast/css/style-invalidation-id-change-descendants-expected.txt: Added.
* fast/css/style-invalidation-id-change-descendants.html: Added.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsfastcssstyleinvalidationattributechangedescendantsexpectedtxt">trunk/LayoutTests/fast/css/style-invalidation-attribute-change-descendants-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfastcssstyleinvalidationattributechangedescendantshtml">trunk/LayoutTests/fast/css/style-invalidation-attribute-change-descendants.html</a></li>
<li><a href="#trunkSourceWebCoreCMakeListstxt">trunk/Source/WebCore/CMakeLists.txt</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreWebCorevcxprojWebCorevcxproj">trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj</a></li>
<li><a href="#trunkSourceWebCoreWebCorexcodeprojprojectpbxproj">trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceWebCorecssRuleFeaturecpp">trunk/Source/WebCore/css/RuleFeature.cpp</a></li>
<li><a href="#trunkSourceWebCorecssRuleFeatureh">trunk/Source/WebCore/css/RuleFeature.h</a></li>
<li><a href="#trunkSourceWebCoredomElementcpp">trunk/Source/WebCore/dom/Element.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsfastcssstyleinvalidationidchangedescendantsexpectedtxt">trunk/LayoutTests/fast/css/style-invalidation-id-change-descendants-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfastcssstyleinvalidationidchangedescendantshtml">trunk/LayoutTests/fast/css/style-invalidation-id-change-descendants.html</a></li>
<li><a href="#trunkSourceWebCorestyleIdChangeInvalidationcpp">trunk/Source/WebCore/style/IdChangeInvalidation.cpp</a></li>
<li><a href="#trunkSourceWebCorestyleIdChangeInvalidationh">trunk/Source/WebCore/style/IdChangeInvalidation.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (196635 => 196636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2016-02-16 17:12:26 UTC (rev 196635)
+++ trunk/LayoutTests/ChangeLog        2016-02-16 17:24:01 UTC (rev 196636)
</span><span class="lines">@@ -1,3 +1,13 @@
</span><ins>+2016-02-16  Antti Koivisto  &lt;antti@apple.com&gt;
+
+        Factor id mutation style invalidation code into a class
+        https://bugs.webkit.org/show_bug.cgi?id=154287
+
+        Reviewed by Andreas Kling.
+
+        * fast/css/style-invalidation-id-change-descendants-expected.txt: Added.
+        * fast/css/style-invalidation-id-change-descendants.html: Added.
+
</ins><span class="cx"> 2016-02-16  Ryan Haddad  &lt;ryanhaddad@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Rebaseline imported/w3c/web-platform-tests/html/dom/interfaces.html for ios-simulator after r196621
</span></span></pre></div>
<a id="trunkLayoutTestsfastcssstyleinvalidationattributechangedescendantsexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/css/style-invalidation-attribute-change-descendants-expected.txt (196635 => 196636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/css/style-invalidation-attribute-change-descendants-expected.txt        2016-02-16 17:12:26 UTC (rev 196635)
+++ trunk/LayoutTests/fast/css/style-invalidation-attribute-change-descendants-expected.txt        2016-02-16 17:24:01 UTC (rev 196636)
</span><span class="lines">@@ -1,4 +1,4 @@
</span><del>-Test that we invalidate the element subtree minimally on class attribute change
</del><ins>+Test that we invalidate the element subtree minimally on attribute change
</ins><span class="cx"> 
</span><span class="cx"> On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkLayoutTestsfastcssstyleinvalidationattributechangedescendantshtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/css/style-invalidation-attribute-change-descendants.html (196635 => 196636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/css/style-invalidation-attribute-change-descendants.html        2016-02-16 17:12:26 UTC (rev 196635)
+++ trunk/LayoutTests/fast/css/style-invalidation-attribute-change-descendants.html        2016-02-16 17:24:01 UTC (rev 196636)
</span><span class="lines">@@ -76,7 +76,7 @@
</span><span class="cx"> &lt;/body&gt;
</span><span class="cx"> &lt;script&gt;
</span><span class="cx"> 
</span><del>-description('Test that we invalidate the element subtree minimally on class attribute change');
</del><ins>+description('Test that we invalidate the element subtree minimally on attribute change');
</ins><span class="cx"> 
</span><span class="cx"> function testStyleChangeType(tag, type)
</span><span class="cx"> {
</span></span></pre></div>
<a id="trunkLayoutTestsfastcssstyleinvalidationidchangedescendantsexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/css/style-invalidation-id-change-descendants-expected.txt (0 => 196636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/css/style-invalidation-id-change-descendants-expected.txt                                (rev 0)
+++ trunk/LayoutTests/fast/css/style-invalidation-id-change-descendants-expected.txt        2016-02-16 17:24:01 UTC (rev 196636)
</span><span class="lines">@@ -0,0 +1,56 @@
</span><ins>+Test basic style invalidation optimization on id mutation
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+PASS hasExpectedStyle is true
+NoStyleChange
+NoStyleChange
+PASS testStyleChangeType(&quot;root&quot;, &quot;NoStyleChange&quot;) is true
+Setting id NotThere
+NoStyleChange
+NoStyleChange
+PASS testStyleChangeType(&quot;root&quot;, &quot;NoStyleChange&quot;) is true
+Setting id id1
+FullStyleChange
+FullStyleChange
+PASS testStyleChangeType(&quot;root&quot;, &quot;FullStyleChange&quot;) is true
+PASS hasExpectedStyle is true
+Setting id id2
+FullStyleChange
+FullStyleChange
+PASS testStyleChangeType(&quot;root&quot;, &quot;FullStyleChange&quot;) is true
+PASS hasExpectedStyle is true
+Setting id id1
+FullStyleChange
+FullStyleChange
+PASS testStyleChangeType(&quot;root&quot;, &quot;FullStyleChange&quot;) is true
+PASS hasExpectedStyle is true
+Setting id id3
+FullStyleChange
+FullStyleChange
+PASS testStyleChangeType(&quot;root&quot;, &quot;FullStyleChange&quot;) is true
+PASS hasExpectedStyle is true
+Setting id id4
+InlineStyleChange
+InlineStyleChange
+PASS testStyleChangeType(&quot;root&quot;, &quot;InlineStyleChange&quot;) is true
+PASS hasExpectedStyle is true
+Setting id id4
+NoStyleChange
+NoStyleChange
+PASS testStyleChangeType(&quot;root&quot;, &quot;NoStyleChange&quot;) is true
+PASS hasExpectedStyle is true
+Setting id NotThere
+InlineStyleChange
+InlineStyleChange
+PASS testStyleChangeType(&quot;root&quot;, &quot;InlineStyleChange&quot;) is true
+Setting id id1
+FullStyleChange
+FullStyleChange
+PASS testStyleChangeType(&quot;root&quot;, &quot;FullStyleChange&quot;) is true
+PASS hasExpectedStyle is true
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsfastcssstyleinvalidationidchangedescendantshtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/css/style-invalidation-id-change-descendants.html (0 => 196636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/css/style-invalidation-id-change-descendants.html                                (rev 0)
+++ trunk/LayoutTests/fast/css/style-invalidation-id-change-descendants.html        2016-02-16 17:24:01 UTC (rev 196636)
</span><span class="lines">@@ -0,0 +1,137 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;script src=&quot;../../resources/js-test-pre.js&quot;&gt;&lt;/script&gt;
+&lt;style&gt;
+* {
+    color: black;
+}
+#id1 target {
+    color: rgb(1, 1, 1);
+}
+
+#id2 &gt; inert target {
+    color: rgb(2, 2, 2);
+}
+
+#id3 {
+    color: rgb(3, 3, 3);
+}
+
+#id4 {
+    color: rgb(4, 4, 4);
+}
+
+
+&lt;/style&gt;
+&lt;/head&gt;
+&lt;body&gt;
+    &lt;root&gt;
+        &lt;!-- With renderer --&gt;
+        &lt;inert&gt;
+            &lt;inert&gt;
+                &lt;inert&gt;&lt;/inert&gt;
+                &lt;target&gt;
+                    &lt;inert&gt;&lt;/inert&gt;
+                    &lt;target&gt;&lt;/target&gt;
+                &lt;/target&gt;
+            &lt;/inert&gt;
+            &lt;target&gt;&lt;/target&gt;
+            &lt;inert&gt;&lt;/inert&gt;
+        &lt;/inert&gt;
+    &lt;/root&gt;
+    &lt;root style=&quot;display:none;&quot;&gt;
+        &lt;!-- Without renderer --&gt;
+        &lt;inert&gt;
+            &lt;inert&gt;
+                &lt;inert&gt;&lt;/inert&gt;
+                &lt;target&gt;
+                    &lt;inert&gt;&lt;/inert&gt;
+                    &lt;target&gt;&lt;/target&gt;
+                &lt;/target&gt;
+            &lt;/inert&gt;
+            &lt;target&gt;&lt;/target&gt;
+            &lt;inert&gt;&lt;/inert&gt;
+        &lt;/inert&gt;
+    &lt;/root&gt;
+&lt;/body&gt;
+&lt;script&gt;
+
+description('Test basic style invalidation optimization on id mutation');
+
+function testStyleChangeType(tag, type)
+{
+    var elements = document.querySelectorAll(tag);
+    for (var i = 0; i &lt; elements.length; ++i) {
+        debug(window.internals.styleChangeType(elements[i]));
+        if (window.internals.styleChangeType(elements[i]) != type)
+            return false;
+    }
+    return true;
+}
+
+function testStyleInvalidation(expectedDescendantStyleChange) {
+    shouldBeTrue('testStyleChangeType(&quot;root&quot;, &quot;' + expectedDescendantStyleChange +'&quot;)');
+}
+
+function setId(name) {
+    debug(&quot;Setting id &quot; + name);
+    var allRoots = document.querySelectorAll(&quot;root&quot;);
+    allRoots[0].id = name;
+    allRoots[1].id = name
+}
+
+function checkStyle(n) {
+    document.documentElement.offsetTop;
+
+    hasExpectedStyle = true;
+    expectedColor = 'rgb('+n+', '+n+', '+n+')';
+    var targets = document.querySelectorAll(&quot;target&quot;);
+    for (var i = 0; i &lt; targets.length; ++i) {
+        hasExpectedStyle = getComputedStyle(targets[i]).color == expectedColor;
+        if (!hasExpectedStyle)
+            break;
+    }
+    shouldBeTrue(&quot;hasExpectedStyle&quot;);
+}
+
+checkStyle(0);
+testStyleInvalidation(&quot;NoStyleChange&quot;);
+
+setId('NotThere');
+testStyleInvalidation(&quot;NoStyleChange&quot;);
+
+setId('id1');
+testStyleInvalidation(&quot;FullStyleChange&quot;);
+checkStyle(1);
+
+setId('id2');
+testStyleInvalidation(&quot;FullStyleChange&quot;);
+checkStyle(2);
+
+setId('id1');
+testStyleInvalidation(&quot;FullStyleChange&quot;);
+checkStyle(1);
+
+setId('id3');
+testStyleInvalidation(&quot;FullStyleChange&quot;);
+checkStyle(0);
+
+setId('id4');
+testStyleInvalidation(&quot;InlineStyleChange&quot;);
+checkStyle(0);
+
+setId('id4');
+testStyleInvalidation(&quot;NoStyleChange&quot;);
+checkStyle(0);
+
+setId('NotThere');
+testStyleInvalidation(&quot;InlineStyleChange&quot;);
+
+setId('id1');
+testStyleInvalidation(&quot;FullStyleChange&quot;);
+checkStyle(1);
+
+&lt;/script&gt;
+&lt;script src=&quot;../../resources/js-test-post.js&quot;&gt;&lt;/script&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkSourceWebCoreCMakeListstxt"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/CMakeLists.txt (196635 => 196636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/CMakeLists.txt        2016-02-16 17:12:26 UTC (rev 196635)
+++ trunk/Source/WebCore/CMakeLists.txt        2016-02-16 17:24:01 UTC (rev 196636)
</span><span class="lines">@@ -2632,6 +2632,7 @@
</span><span class="cx"> 
</span><span class="cx">     style/AttributeChangeInvalidation.cpp
</span><span class="cx">     style/ClassChangeInvalidation.cpp
</span><ins>+    style/IdChangeInvalidation.cpp
</ins><span class="cx">     style/InlineTextBoxStyle.cpp
</span><span class="cx">     style/RenderTreePosition.cpp
</span><span class="cx">     style/StyleChange.cpp
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (196635 => 196636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-02-16 17:12:26 UTC (rev 196635)
+++ trunk/Source/WebCore/ChangeLog        2016-02-16 17:24:01 UTC (rev 196636)
</span><span class="lines">@@ -1,3 +1,36 @@
</span><ins>+2016-02-16  Antti Koivisto  &lt;antti@apple.com&gt;
+
+        Factor id mutation style invalidation code into a class
+        https://bugs.webkit.org/show_bug.cgi?id=154287
+
+        Reviewed by Andreas Kling.
+
+        Also add a cheap basic optimization that avoids descendant invalidation if they can not be affected.
+
+        It would be easy to implement fine grained invalidation like with classes and attribute selectors.
+        However dynamic id changes are not common enough (nor recommended) to pay the memory cost of
+        the required data structures.
+
+        Test: fast/css/style-invalidation-id-change-descendants.html
+
+        * CMakeLists.txt:
+        * WebCore.vcxproj/WebCore.vcxproj:
+        * WebCore.xcodeproj/project.pbxproj:
+        * css/RuleFeature.cpp:
+        (WebCore::RuleFeatureSet::recursivelyCollectFeaturesFromSelector):
+        (WebCore::RuleFeatureSet::add):
+        (WebCore::RuleFeatureSet::clear):
+        * css/RuleFeature.h:
+        * dom/Element.cpp:
+        (WebCore::makeIdForStyleResolution):
+        (WebCore::Element::attributeChanged):
+        (WebCore::checkNeedsStyleInvalidationForIdChange): Deleted.
+        * style/IdChangeInvalidation.cpp: Added.
+        (WebCore::Style::IdChangeInvalidation::invalidateStyle):
+        * style/IdChangeInvalidation.h: Added.
+        (WebCore::Style::IdChangeInvalidation::IdChangeInvalidation):
+        (WebCore::Style::IdChangeInvalidation::~IdChangeInvalidation):
+
</ins><span class="cx"> 2016-02-16  Andreas Kling  &lt;akling@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Drop StyleResolver and SelectorQueryCache when entering PageCache.
</span></span></pre></div>
<a id="trunkSourceWebCoreWebCorevcxprojWebCorevcxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj (196635 => 196636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj        2016-02-16 17:12:26 UTC (rev 196635)
+++ trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj        2016-02-16 17:24:01 UTC (rev 196636)
</span><span class="lines">@@ -19297,6 +19297,7 @@
</span><span class="cx">     &lt;ClCompile Include=&quot;..\storage\StorageNamespaceProvider.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\style\AttributeChangeInvalidation.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\style\ClassChangeInvalidation.cpp&quot; /&gt;
</span><ins>+    &lt;ClCompile Include=&quot;..\style\IdChangeInvalidation.cpp&quot; /&gt;
</ins><span class="cx">     &lt;ClCompile Include=&quot;..\style\InlineTextBoxStyle.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\style\RenderTreePosition.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\style\StyleChange.cpp&quot; /&gt;
</span><span class="lines">@@ -22868,6 +22869,7 @@
</span><span class="cx">     &lt;ClInclude Include=&quot;..\storage\StorageNamespaceProvider.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\style\AttributeChangeInvalidation.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\style\ClassChangeInvalidation.h&quot; /&gt;
</span><ins>+    &lt;ClInclude Include=&quot;..\style\IdChangeInvalidation.h&quot; /&gt;
</ins><span class="cx">     &lt;ClInclude Include=&quot;..\style\InlineTextBoxStyle.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\style\RenderTreePosition.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\style\StyleChange.h&quot; /&gt;
</span></span></pre></div>
<a id="trunkSourceWebCoreWebCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (196635 => 196636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj        2016-02-16 17:12:26 UTC (rev 196635)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj        2016-02-16 17:24:01 UTC (rev 196636)
</span><span class="lines">@@ -6639,6 +6639,8 @@
</span><span class="cx">                 E4A814D61C6DEE8D00BF85AC /* ClassChangeInvalidation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4A814D51C6DEE8D00BF85AC /* ClassChangeInvalidation.cpp */; };
</span><span class="cx">                 E4A814D81C70E10500BF85AC /* AttributeChangeInvalidation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4A814D71C70E10500BF85AC /* AttributeChangeInvalidation.cpp */; };
</span><span class="cx">                 E4A814DA1C70E10D00BF85AC /* AttributeChangeInvalidation.h in Headers */ = {isa = PBXBuildFile; fileRef = E4A814D91C70E10D00BF85AC /* AttributeChangeInvalidation.h */; };
</span><ins>+                E4A814DE1C7338D100BF85AC /* IdChangeInvalidation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4A814DD1C7338D100BF85AC /* IdChangeInvalidation.cpp */; };
+                E4A814E01C7338EB00BF85AC /* IdChangeInvalidation.h in Headers */ = {isa = PBXBuildFile; fileRef = E4A814DF1C7338EB00BF85AC /* IdChangeInvalidation.h */; };
</ins><span class="cx">                 E4AE7C1617D1BB950009FB31 /* ElementIterator.h in Headers */ = {isa = PBXBuildFile; fileRef = E4AE7C1517D1BB950009FB31 /* ElementIterator.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 E4AE7C1A17D232350009FB31 /* ElementAncestorIterator.h in Headers */ = {isa = PBXBuildFile; fileRef = E4AE7C1917D232350009FB31 /* ElementAncestorIterator.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 E4AFCFA50DAF29A300F5F55C /* UnitBezier.h in Headers */ = {isa = PBXBuildFile; fileRef = E4AFCFA40DAF29A300F5F55C /* UnitBezier.h */; };
</span><span class="lines">@@ -10548,8 +10550,8 @@
</span><span class="cx">                 83D26D3D1AFDCC50001B3873 /* ParentNode.idl */ = {isa = PBXFileReference; lastKnownFileType = text; path = ParentNode.idl; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 83D35AEA1C7187ED00F70D5A /* XMLHttpRequestEventTarget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMLHttpRequestEventTarget.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 83D35AEB1C7187ED00F70D5A /* XMLHttpRequestEventTarget.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = XMLHttpRequestEventTarget.idl; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><del>-                83D35AEF1C718D8400F70D5A /* JSXMLHttpRequestEventTarget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JSXMLHttpRequestEventTarget.cpp; path = JSXMLHttpRequestEventTarget.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
-                83D35AF01C718D8400F70D5A /* JSXMLHttpRequestEventTarget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JSXMLHttpRequestEventTarget.h; path = JSXMLHttpRequestEventTarget.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</del><ins>+                83D35AEF1C718D8400F70D5A /* JSXMLHttpRequestEventTarget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSXMLHttpRequestEventTarget.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                83D35AF01C718D8400F70D5A /* JSXMLHttpRequestEventTarget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSXMLHttpRequestEventTarget.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 83E359A01BB1031D002CEB98 /* JSHTMLTimeElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSHTMLTimeElement.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 83E359A11BB1031D002CEB98 /* JSHTMLTimeElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSHTMLTimeElement.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 83E959E11B8BC22B004D9385 /* NativeNodeFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NativeNodeFilter.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -14647,6 +14649,8 @@
</span><span class="cx">                 E4A814D51C6DEE8D00BF85AC /* ClassChangeInvalidation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ClassChangeInvalidation.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 E4A814D71C70E10500BF85AC /* AttributeChangeInvalidation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AttributeChangeInvalidation.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 E4A814D91C70E10D00BF85AC /* AttributeChangeInvalidation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AttributeChangeInvalidation.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                E4A814DD1C7338D100BF85AC /* IdChangeInvalidation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IdChangeInvalidation.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                E4A814DF1C7338EB00BF85AC /* IdChangeInvalidation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IdChangeInvalidation.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 E4AE7C1517D1BB950009FB31 /* ElementIterator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ElementIterator.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 E4AE7C1917D232350009FB31 /* ElementAncestorIterator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ElementAncestorIterator.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 E4AFCFA40DAF29A300F5F55C /* UnitBezier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UnitBezier.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -23441,6 +23445,8 @@
</span><span class="cx">                                 E4A814D91C70E10D00BF85AC /* AttributeChangeInvalidation.h */,
</span><span class="cx">                                 E4A814D51C6DEE8D00BF85AC /* ClassChangeInvalidation.cpp */,
</span><span class="cx">                                 E4A814D31C6DEC4000BF85AC /* ClassChangeInvalidation.h */,
</span><ins>+                                E4A814DD1C7338D100BF85AC /* IdChangeInvalidation.cpp */,
+                                E4A814DF1C7338EB00BF85AC /* IdChangeInvalidation.h */,
</ins><span class="cx">                                 1C0106FE192594DF008A4201 /* InlineTextBoxStyle.cpp */,
</span><span class="cx">                                 1C0106FF192594DF008A4201 /* InlineTextBoxStyle.h */,
</span><span class="cx">                                 5824ABA81AE849C8009074B7 /* RenderTreePosition.cpp */,
</span><span class="lines">@@ -27866,6 +27872,7 @@
</span><span class="cx">                                 9393E605151A9A1800066F06 /* StyleCachedImageSet.h in Headers */,
</span><span class="cx">                                 E401E0A41C3C0B8300F34D10 /* StyleChange.h in Headers */,
</span><span class="cx">                                 9DAC7C571AF2CB6400437C44 /* StyleContentAlignmentData.h in Headers */,
</span><ins>+                                E4A814E01C7338EB00BF85AC /* IdChangeInvalidation.h in Headers */,
</ins><span class="cx">                                 BC779E171BB227CA00CAA8BF /* StyleCustomPropertyData.h in Headers */,
</span><span class="cx">                                 BC5EB67F0E81D4A700B25965 /* StyleDashboardRegion.h in Headers */,
</span><span class="cx">                                 A8C4A7FD09D563270003AC8D /* StyledElement.h in Headers */,
</span><span class="lines">@@ -30487,6 +30494,7 @@
</span><span class="cx">                                 B2FA3D5A0AB75A6F000E5AC4 /* JSSVGClipPathElement.cpp in Sources */,
</span><span class="cx">                                 B2FA3D5C0AB75A6F000E5AC4 /* JSSVGColor.cpp in Sources */,
</span><span class="cx">                                 B2FA3D5E0AB75A6F000E5AC4 /* JSSVGComponentTransferFunctionElement.cpp in Sources */,
</span><ins>+                                E4A814DE1C7338D100BF85AC /* IdChangeInvalidation.cpp in Sources */,
</ins><span class="cx">                                 B2FA3D600AB75A6F000E5AC4 /* JSSVGCursorElement.cpp in Sources */,
</span><span class="cx">                                 B2FA3D620AB75A6F000E5AC4 /* JSSVGDefsElement.cpp in Sources */,
</span><span class="cx">                                 B2FA3D640AB75A6F000E5AC4 /* JSSVGDescElement.cpp in Sources */,
</span></span></pre></div>
<a id="trunkSourceWebCorecssRuleFeaturecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/css/RuleFeature.cpp (196635 => 196636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/css/RuleFeature.cpp        2016-02-16 17:12:26 UTC (rev 196635)
+++ trunk/Source/WebCore/css/RuleFeature.cpp        2016-02-16 17:24:01 UTC (rev 196636)
</span><span class="lines">@@ -39,9 +39,11 @@
</span><span class="cx"> {
</span><span class="cx">     const CSSSelector* selector = &amp;firstSelector;
</span><span class="cx">     do {
</span><del>-        if (selector-&gt;match() == CSSSelector::Id)
</del><ins>+        if (selector-&gt;match() == CSSSelector::Id) {
</ins><span class="cx">             idsInRules.add(selector-&gt;value().impl());
</span><del>-        else if (selector-&gt;match() == CSSSelector::Class) {
</del><ins>+            if (matchesAncestor)
+                idsMatchingAncestorsInRules.add(selector-&gt;value().impl());
+        } else if (selector-&gt;match() == CSSSelector::Class) {
</ins><span class="cx">             classesInRules.add(selector-&gt;value().impl());
</span><span class="cx">             if (matchesAncestor)
</span><span class="cx">                 selectorFeatures.classesMatchingAncestors.append(selector-&gt;value().impl());
</span><span class="lines">@@ -118,6 +120,7 @@
</span><span class="cx"> void RuleFeatureSet::add(const RuleFeatureSet&amp; other)
</span><span class="cx"> {
</span><span class="cx">     idsInRules.add(other.idsInRules.begin(), other.idsInRules.end());
</span><ins>+    idsMatchingAncestorsInRules.add(other.idsMatchingAncestorsInRules.begin(), other.idsMatchingAncestorsInRules.end());
</ins><span class="cx">     classesInRules.add(other.classesInRules.begin(), other.classesInRules.end());
</span><span class="cx">     attributeCanonicalLocalNamesInRules.add(other.attributeCanonicalLocalNamesInRules.begin(), other.attributeCanonicalLocalNamesInRules.end());
</span><span class="cx">     attributeLocalNamesInRules.add(other.attributeLocalNamesInRules.begin(), other.attributeLocalNamesInRules.end());
</span><span class="lines">@@ -146,6 +149,7 @@
</span><span class="cx"> void RuleFeatureSet::clear()
</span><span class="cx"> {
</span><span class="cx">     idsInRules.clear();
</span><ins>+    idsMatchingAncestorsInRules.clear();
</ins><span class="cx">     classesInRules.clear();
</span><span class="cx">     attributeCanonicalLocalNamesInRules.clear();
</span><span class="cx">     attributeLocalNamesInRules.clear();
</span></span></pre></div>
<a id="trunkSourceWebCorecssRuleFeatureh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/css/RuleFeature.h (196635 => 196636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/css/RuleFeature.h        2016-02-16 17:12:26 UTC (rev 196635)
+++ trunk/Source/WebCore/css/RuleFeature.h        2016-02-16 17:24:01 UTC (rev 196636)
</span><span class="lines">@@ -52,6 +52,7 @@
</span><span class="cx">     void collectFeatures(const RuleData&amp;);
</span><span class="cx"> 
</span><span class="cx">     HashSet&lt;AtomicStringImpl*&gt; idsInRules;
</span><ins>+    HashSet&lt;AtomicStringImpl*&gt; idsMatchingAncestorsInRules;
</ins><span class="cx">     HashSet&lt;AtomicStringImpl*&gt; classesInRules;
</span><span class="cx">     HashSet&lt;AtomicStringImpl*&gt; attributeCanonicalLocalNamesInRules;
</span><span class="cx">     HashSet&lt;AtomicStringImpl*&gt; attributeLocalNamesInRules;
</span></span></pre></div>
<a id="trunkSourceWebCoredomElementcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/Element.cpp (196635 => 196636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/Element.cpp        2016-02-16 17:12:26 UTC (rev 196635)
+++ trunk/Source/WebCore/dom/Element.cpp        2016-02-16 17:24:01 UTC (rev 196636)
</span><span class="lines">@@ -57,6 +57,7 @@
</span><span class="cx"> #include &quot;HTMLParserIdioms.h&quot;
</span><span class="cx"> #include &quot;HTMLSelectElement.h&quot;
</span><span class="cx"> #include &quot;HTMLTemplateElement.h&quot;
</span><ins>+#include &quot;IdChangeInvalidation.h&quot;
</ins><span class="cx"> #include &quot;IdTargetObserverRegistry.h&quot;
</span><span class="cx"> #include &quot;KeyboardEvent.h&quot;
</span><span class="cx"> #include &quot;MainFrame.h&quot;
</span><span class="lines">@@ -1216,25 +1217,10 @@
</span><span class="cx">     return value;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static bool checkNeedsStyleInvalidationForIdChange(const AtomicString&amp; oldId, const AtomicString&amp; newId, StyleResolver* styleResolver)
-{
-    ASSERT(newId != oldId);
-    if (!oldId.isEmpty() &amp;&amp; styleResolver-&gt;hasSelectorForId(oldId))
-        return true;
-    if (!newId.isEmpty() &amp;&amp; styleResolver-&gt;hasSelectorForId(newId))
-        return true;
-    return false;
-}
-
</del><span class="cx"> void Element::attributeChanged(const QualifiedName&amp; name, const AtomicString&amp; oldValue, const AtomicString&amp; newValue, AttributeModificationReason)
</span><span class="cx"> {
</span><span class="cx">     bool valueIsSameAsBefore = oldValue == newValue;
</span><span class="cx"> 
</span><del>-    StyleResolver* styleResolver = document().styleResolverIfExists();
-    bool testShouldInvalidateStyle = inRenderedDocument() &amp;&amp; styleResolver &amp;&amp; styleChangeType() &lt; FullStyleChange;
-
-    bool shouldInvalidateStyle = false;
-
</del><span class="cx">     if (!valueIsSameAsBefore) {
</span><span class="cx">         if (name == HTMLNames::idAttr) {
</span><span class="cx">             if (!oldValue.isEmpty())
</span><span class="lines">@@ -1245,15 +1231,17 @@
</span><span class="cx">             AtomicString oldId = elementData()-&gt;idForStyleResolution();
</span><span class="cx">             AtomicString newId = makeIdForStyleResolution(newValue, document().inQuirksMode());
</span><span class="cx">             if (newId != oldId) {
</span><ins>+                Style::IdChangeInvalidation styleInvalidation(*this, oldId, newId);
</ins><span class="cx">                 elementData()-&gt;setIdForStyleResolution(newId);
</span><del>-                shouldInvalidateStyle = testShouldInvalidateStyle &amp;&amp; checkNeedsStyleInvalidationForIdChange(oldId, newId, styleResolver);
</del><span class="cx">             }
</span><span class="cx">         } else if (name == classAttr)
</span><span class="cx">             classAttributeChanged(newValue);
</span><span class="cx">         else if (name == HTMLNames::nameAttr)
</span><span class="cx">             elementData()-&gt;setHasNameAttribute(!newValue.isNull());
</span><del>-        else if (name == HTMLNames::pseudoAttr)
-            shouldInvalidateStyle |= testShouldInvalidateStyle &amp;&amp; isInShadowTree();
</del><ins>+        else if (name == HTMLNames::pseudoAttr) {
+            if (needsStyleInvalidation() &amp;&amp; isInShadowTree())
+                setNeedsStyleRecalc(FullStyleChange);
+        }
</ins><span class="cx"> #if ENABLE(SHADOW_DOM) || ENABLE(DETAILS_ELEMENT)
</span><span class="cx">         else if (name == HTMLNames::slotAttr) {
</span><span class="cx">             if (auto* parent = parentElement()) {
</span><span class="lines">@@ -1273,9 +1261,6 @@
</span><span class="cx"> 
</span><span class="cx">     invalidateNodeListAndCollectionCachesInAncestors(&amp;name, this);
</span><span class="cx"> 
</span><del>-    if (shouldInvalidateStyle)
-        setNeedsStyleRecalc();
-
</del><span class="cx">     if (AXObjectCache* cache = document().existingAXObjectCache())
</span><span class="cx">         cache-&gt;handleAttributeChanged(name, this);
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCorestyleIdChangeInvalidationcpp"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/style/IdChangeInvalidation.cpp (0 => 196636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/style/IdChangeInvalidation.cpp                                (rev 0)
+++ trunk/Source/WebCore/style/IdChangeInvalidation.cpp        2016-02-16 17:24:01 UTC (rev 196636)
</span><span class="lines">@@ -0,0 +1,64 @@
</span><ins>+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include &quot;config.h&quot;
+#include &quot;IdChangeInvalidation.h&quot;
+
+#include &quot;DocumentRuleSets.h&quot;
+#include &quot;ElementChildIterator.h&quot;
+#include &quot;StyleResolver.h&quot;
+
+namespace WebCore {
+namespace Style {
+
+void IdChangeInvalidation::invalidateStyle(const AtomicString&amp; changedId)
+{
+    if (changedId.isEmpty())
+        return;
+
+    auto&amp; ruleSets = m_element.styleResolver().ruleSets();
+
+    bool mayAffectStyle = ruleSets.features().idsInRules.contains(changedId.impl());
+    if (!mayAffectStyle)
+        return;
+
+    if (m_element.shadowRoot() &amp;&amp; ruleSets.authorStyle()-&gt;hasShadowPseudoElementRules()) {
+        m_element.setNeedsStyleRecalc(FullStyleChange);
+        return;
+    }
+
+    m_element.setNeedsStyleRecalc(InlineStyleChange);
+
+    // This could be easily optimized for fine-grained descendant invalidation similar to ClassChangeInvalidation.
+    // However using ids for dynamic styling is rare and this is probably not worth the memory cost of the required data structures.
+    bool mayAffectDescendantStyle = ruleSets.features().idsMatchingAncestorsInRules.contains(changedId.impl());
+    if (mayAffectDescendantStyle)
+        m_element.setNeedsStyleRecalc(FullStyleChange);
+    else
+        m_element.setNeedsStyleRecalc(InlineStyleChange);
+}
+
+}
+}
</ins></span></pre></div>
<a id="trunkSourceWebCorestyleIdChangeInvalidationh"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/style/IdChangeInvalidation.h (0 => 196636)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/style/IdChangeInvalidation.h                                (rev 0)
+++ trunk/Source/WebCore/style/IdChangeInvalidation.h        2016-02-16 17:24:01 UTC (rev 196636)
</span><span class="lines">@@ -0,0 +1,72 @@
</span><ins>+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef IdChangeInvalidation_h
+#define IdChangeInvalidation_h
+
+#include &quot;Element.h&quot;
+
+namespace WebCore {
+
+namespace Style {
+
+class IdChangeInvalidation {
+public:
+    IdChangeInvalidation(Element&amp;, const AtomicString&amp; oldId, const AtomicString&amp; newId);
+    ~IdChangeInvalidation();
+
+private:
+    void invalidateStyle(const AtomicString&amp;);
+
+    const bool m_isEnabled;
+    Element&amp; m_element;
+
+    AtomicString m_newId;
+};
+
+inline IdChangeInvalidation::IdChangeInvalidation(Element&amp; element, const AtomicString&amp; oldId, const AtomicString&amp; newId)
+    : m_isEnabled(element.needsStyleInvalidation())
+    , m_element(element)
+{
+    if (!m_isEnabled)
+        return;
+    if (oldId == newId)
+        return;
+    m_newId = newId;
+    invalidateStyle(oldId);
+}
+
+inline IdChangeInvalidation::~IdChangeInvalidation()
+{
+    if (!m_isEnabled)
+        return;
+    invalidateStyle(m_newId);
+}
+
+}
+}
+
+#endif
+
</ins></span></pre>
</div>
</div>

</body>
</html>