<!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>[206990] 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/206990">206990</a></dd>
<dt>Author</dt> <dd>antti@apple.com</dd>
<dt>Date</dt> <dd>2016-10-10 01:19:03 -0700 (Mon, 10 Oct 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>Enable optimized stylesheet updates in shadow trees
https://bugs.webkit.org/show_bug.cgi?id=163180

Reviewed by Darin Adler.

Source/WebCore:

When we get a new stylesheet (for example when load completes) we invalidate only
those elements in DOM that are affected by the new sheet. This patch makes the
optimization also work in shadow trees.

Test: fast/shadow-dom/scoped-style-invalidation.html

* css/StyleInvalidationAnalysis.cpp:
(WebCore::StyleInvalidationAnalysis::invalidateStyle):
* css/StyleInvalidationAnalysis.h:
* dom/Document.cpp:
(WebCore::Document::didRemoveAllPendingStylesheet):
* style/StyleScope.cpp:
(WebCore::Style::Scope::removePendingSheet):
(WebCore::Style::Scope::analyzeStyleSheetChange):
(WebCore::Style::Scope::updateActiveStyleSheets):

LayoutTests:

* fast/shadow-dom/scoped-style-invalidation-expected.txt: Added.
* fast/shadow-dom/scoped-style-invalidation.html: Added.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCorecssStyleInvalidationAnalysiscpp">trunk/Source/WebCore/css/StyleInvalidationAnalysis.cpp</a></li>
<li><a href="#trunkSourceWebCorecssStyleInvalidationAnalysish">trunk/Source/WebCore/css/StyleInvalidationAnalysis.h</a></li>
<li><a href="#trunkSourceWebCoredomDocumentcpp">trunk/Source/WebCore/dom/Document.cpp</a></li>
<li><a href="#trunkSourceWebCorestyleStyleScopecpp">trunk/Source/WebCore/style/StyleScope.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsfastshadowdomscopedstyleinvalidationexpectedtxt">trunk/LayoutTests/fast/shadow-dom/scoped-style-invalidation-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfastshadowdomscopedstyleinvalidationhtml">trunk/LayoutTests/fast/shadow-dom/scoped-style-invalidation.html</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (206989 => 206990)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2016-10-10 08:13:56 UTC (rev 206989)
+++ trunk/LayoutTests/ChangeLog        2016-10-10 08:19:03 UTC (rev 206990)
</span><span class="lines">@@ -1,3 +1,13 @@
</span><ins>+2016-10-09  Antti Koivisto  &lt;antti@apple.com&gt;
+
+        Enable optimized stylesheet updates in shadow trees
+        https://bugs.webkit.org/show_bug.cgi?id=163180
+
+        Reviewed by Darin Adler.
+
+        * fast/shadow-dom/scoped-style-invalidation-expected.txt: Added.
+        * fast/shadow-dom/scoped-style-invalidation.html: Added.
+
</ins><span class="cx"> 2016-10-09  Gyuyoung Kim  &lt;gyuyoung.kim@navercorp.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Unreviewed, EFL Gardening on Oct. 10th - 2
</span></span></pre></div>
<a id="trunkLayoutTestsfastshadowdomscopedstyleinvalidationexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/shadow-dom/scoped-style-invalidation-expected.txt (0 => 206990)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/shadow-dom/scoped-style-invalidation-expected.txt                                (rev 0)
+++ trunk/LayoutTests/fast/shadow-dom/scoped-style-invalidation-expected.txt        2016-10-10 08:19:03 UTC (rev 206990)
</span><span class="lines">@@ -0,0 +1,6 @@
</span><ins>+
+PASS Test that adding stylesheet with matching selector invalidates in document scope 
+PASS Test that adding stylesheet without matching selector does not invalidate in document scope 
+PASS Test that adding stylesheet with matching selector invalidates in shadow scope 
+PASS Test that adding stylesheet without matching selector does not invalidate in shadow scope 
+
</ins></span></pre></div>
<a id="trunkLayoutTestsfastshadowdomscopedstyleinvalidationhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/shadow-dom/scoped-style-invalidation.html (0 => 206990)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/shadow-dom/scoped-style-invalidation.html                                (rev 0)
+++ trunk/LayoutTests/fast/shadow-dom/scoped-style-invalidation.html        2016-10-10 08:19:03 UTC (rev 206990)
</span><span class="lines">@@ -0,0 +1,43 @@
</span><ins>+&lt;script src=&quot;../../resources/testharness.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;../../resources/testharnessreport.js&quot;&gt;&lt;/script&gt;
+
+&lt;div&gt;&lt;/div&gt;
+&lt;div class=styled&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;
+&lt;div&gt;&lt;div class=styled&gt;&lt;/div&gt;&lt;/div&gt;
+
+&lt;div id=host&gt;&lt;/div&gt;
+
+&lt;script&gt;
+var host = document.getElementById('host');
+var shadow = host.attachShadow({mode: 'closed'});
+shadow.innerHTML = `
+    &lt;div&gt;&lt;/div&gt;
+    &lt;div class=styled&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;
+    &lt;div&gt;&lt;div class=styled&gt;&lt;/div&gt;&lt;/div&gt;
+`;
+
+function testInvalidation(scope, cssText, shouldInvalidate, name)
+{
+    test(() =&gt; {
+        internals.updateLayoutIgnorePendingStylesheetsAndRunPostLayoutTasks();
+
+        var style = document.createElement(&quot;style&quot;);
+        style.textContent = cssText;
+        scope.appendChild(style);
+
+        var styledDiv = scope.querySelectorAll(&quot;div.styled&quot;);
+        for (var div of styledDiv)
+            assert_equals(internals.styleChangeType(div), shouldInvalidate ? &quot;InlineStyleChange&quot; : &quot;NoStyleChange&quot;);
+
+        var notStyledDiv = scope.querySelectorAll(&quot;div:not(.styled)&quot;);
+        for (var div of notStyledDiv)
+            assert_equals(internals.styleChangeType(div), &quot;NoStyleChange&quot;);
+    }, name);
+}
+
+testInvalidation(document.body, &quot;.styled { color: red }&quot;, true, &quot;Test that adding stylesheet with matching selector invalidates in document scope&quot;);
+testInvalidation(document.body, &quot;.nothere { color: red }&quot;, false, &quot;Test that adding stylesheet without matching selector does not invalidate in document scope&quot;);
+testInvalidation(shadow, &quot;.styled { color: red }&quot;, true, &quot;Test that adding stylesheet with matching selector invalidates in shadow scope&quot;);
+testInvalidation(shadow, &quot;.nothere { color: red }&quot;, false, &quot;Test that adding stylesheet without matching selector does not invalidate in shadow scope&quot;);
+
+&lt;/script&gt;
</ins></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (206989 => 206990)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-10-10 08:13:56 UTC (rev 206989)
+++ trunk/Source/WebCore/ChangeLog        2016-10-10 08:19:03 UTC (rev 206990)
</span><span class="lines">@@ -1,3 +1,26 @@
</span><ins>+2016-10-09  Antti Koivisto  &lt;antti@apple.com&gt;
+
+        Enable optimized stylesheet updates in shadow trees
+        https://bugs.webkit.org/show_bug.cgi?id=163180
+
+        Reviewed by Darin Adler.
+
+        When we get a new stylesheet (for example when load completes) we invalidate only
+        those elements in DOM that are affected by the new sheet. This patch makes the
+        optimization also work in shadow trees.
+
+        Test: fast/shadow-dom/scoped-style-invalidation.html
+
+        * css/StyleInvalidationAnalysis.cpp:
+        (WebCore::StyleInvalidationAnalysis::invalidateStyle):
+        * css/StyleInvalidationAnalysis.h:
+        * dom/Document.cpp:
+        (WebCore::Document::didRemoveAllPendingStylesheet):
+        * style/StyleScope.cpp:
+        (WebCore::Style::Scope::removePendingSheet):
+        (WebCore::Style::Scope::analyzeStyleSheetChange):
+        (WebCore::Style::Scope::updateActiveStyleSheets):
+
</ins><span class="cx"> 2016-10-10  Youenn Fablet  &lt;youenn@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Refactor binding generated casted-this checks for attribute setters
</span></span></pre></div>
<a id="trunkSourceWebCorecssStyleInvalidationAnalysiscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/css/StyleInvalidationAnalysis.cpp (206989 => 206990)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/css/StyleInvalidationAnalysis.cpp        2016-10-10 08:13:56 UTC (rev 206989)
+++ trunk/Source/WebCore/css/StyleInvalidationAnalysis.cpp        2016-10-10 08:19:03 UTC (rev 206990)
</span><span class="lines">@@ -169,6 +169,16 @@
</span><span class="cx">     invalidateStyleForTree(*documentElement, &amp;filter);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void StyleInvalidationAnalysis::invalidateStyle(ShadowRoot&amp; shadowRoot)
+{
+    ASSERT(!m_dirtiesAllStyle);
+
+    for (auto&amp; child : childrenOfType&lt;Element&gt;(shadowRoot)) {
+        SelectorFilter filter;
+        invalidateStyleForTree(child, &amp;filter);
+    }
+}
+
</ins><span class="cx"> void StyleInvalidationAnalysis::invalidateStyle(Element&amp; element)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(!m_dirtiesAllStyle);
</span></span></pre></div>
<a id="trunkSourceWebCorecssStyleInvalidationAnalysish"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/css/StyleInvalidationAnalysis.h (206989 => 206990)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/css/StyleInvalidationAnalysis.h        2016-10-10 08:13:56 UTC (rev 206989)
+++ trunk/Source/WebCore/css/StyleInvalidationAnalysis.h        2016-10-10 08:19:03 UTC (rev 206990)
</span><span class="lines">@@ -35,6 +35,7 @@
</span><span class="cx"> class MediaQueryEvaluator;
</span><span class="cx"> class RuleSet;
</span><span class="cx"> class SelectorFilter;
</span><ins>+class ShadowRoot;
</ins><span class="cx"> class StyleSheetContents;
</span><span class="cx"> 
</span><span class="cx"> class StyleInvalidationAnalysis {
</span><span class="lines">@@ -45,6 +46,7 @@
</span><span class="cx">     bool dirtiesAllStyle() const { return m_dirtiesAllStyle; }
</span><span class="cx">     bool hasShadowPseudoElementRulesInAuthorSheet() const { return m_hasShadowPseudoElementRulesInAuthorSheet; }
</span><span class="cx">     void invalidateStyle(Document&amp;);
</span><ins>+    void invalidateStyle(ShadowRoot&amp;);
</ins><span class="cx">     void invalidateStyle(Element&amp;);
</span><span class="cx"> 
</span><span class="cx"> private:
</span></span></pre></div>
<a id="trunkSourceWebCoredomDocumentcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/Document.cpp (206989 => 206990)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/Document.cpp        2016-10-10 08:13:56 UTC (rev 206989)
+++ trunk/Source/WebCore/dom/Document.cpp        2016-10-10 08:19:03 UTC (rev 206990)
</span><span class="lines">@@ -3083,8 +3083,6 @@
</span><span class="cx"> {
</span><span class="cx">     m_needsNotifyRemoveAllPendingStylesheet = false;
</span><span class="cx"> 
</span><del>-    styleScope().didChangeCandidatesForActiveSet();
-
</del><span class="cx">     if (m_pendingSheetLayout == DidLayoutWithPendingSheets) {
</span><span class="cx">         m_pendingSheetLayout = IgnoreLayoutWithPendingSheets;
</span><span class="cx">         if (renderView())
</span></span></pre></div>
<a id="trunkSourceWebCorestyleStyleScopecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/style/StyleScope.cpp (206989 => 206990)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/style/StyleScope.cpp        2016-10-10 08:13:56 UTC (rev 206989)
+++ trunk/Source/WebCore/style/StyleScope.cpp        2016-10-10 08:19:03 UTC (rev 206990)
</span><span class="lines">@@ -129,13 +129,10 @@
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    if (m_shadowRoot) {
-        // FIXME: Make optimized updates work.
-        didChangeContentsOrInterpretation();
-        return;
-    }
</del><ins>+    didChangeCandidatesForActiveSet();
</ins><span class="cx"> 
</span><del>-    m_document.didRemoveAllPendingStylesheet();
</del><ins>+    if (!m_shadowRoot)
+        m_document.didRemoveAllPendingStylesheet();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void Scope::addStyleSheetCandidateNode(Node&amp; node, bool createdByParser)
</span><span class="lines">@@ -300,7 +297,12 @@
</span><span class="cx">     StyleInvalidationAnalysis invalidationAnalysis(addedSheets, styleResolver.mediaQueryEvaluator());
</span><span class="cx">     if (invalidationAnalysis.dirtiesAllStyle())
</span><span class="cx">         return styleResolverUpdateType;
</span><del>-    invalidationAnalysis.invalidateStyle(m_document);
</del><ins>+
+    if (m_shadowRoot)
+        invalidationAnalysis.invalidateStyle(*m_shadowRoot);
+    else
+        invalidationAnalysis.invalidateStyle(m_document);
+
</ins><span class="cx">     requiresFullStyleRecalc = false;
</span><span class="cx"> 
</span><span class="cx">     return styleResolverUpdateType;
</span><span class="lines">@@ -347,10 +349,6 @@
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    // FIXME: Support optimized invalidation in shadow trees.
-    if (m_shadowRoot)
-        updateType = UpdateType::ContentsOrInterpretation;
-
</del><span class="cx">     m_didUpdateActiveStyleSheets = true;
</span><span class="cx"> 
</span><span class="cx">     Vector&lt;RefPtr&lt;StyleSheet&gt;&gt; activeStyleSheets;
</span></span></pre>
</div>
</div>

</body>
</html>