<!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>[209352] 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/209352">209352</a></dd>
<dt>Author</dt> <dd>antti@apple.com</dd>
<dt>Date</dt> <dd>2016-12-05 14:42:28 -0800 (Mon, 05 Dec 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>keyframes do not work when defined inside a style in a shadowRoot
https://bugs.webkit.org/show_bug.cgi?id=164608
&lt;rdar://problem/29210251&gt;

Reviewed by Darin Adler.

Source/WebCore:

With :host and ::slotted rules a keyframe animation affecting an element can be
defined in a style scope different from the element's own scope. Style resolver
loses the scope information when building the RenderStyle so there is no way
to find out the correct scope.

Fix by passing style scope through to style builder and including a scope association
with the animation name. Find the correct scope when resolving keyframes.

Test: fast/shadow-dom/shadow-host-animation.html

* css/CSSToStyleMap.cpp:
(WebCore::CSSToStyleMap::mapAnimationName):

    Include scope with the name.

* css/ElementRuleCollector.cpp:
(WebCore::MatchRequest::MatchRequest):
(WebCore::ElementRuleCollector::addMatchedRule):
(WebCore::ElementRuleCollector::sortAndTransferMatchedRules):
(WebCore::ElementRuleCollector::matchAuthorRules):
(WebCore::ElementRuleCollector::matchAuthorShadowPseudoElementRules):
(WebCore::ElementRuleCollector::matchHostPseudoClassRules):
(WebCore::ElementRuleCollector::matchSlottedPseudoElementRules):
(WebCore::ElementRuleCollector::collectMatchingRulesForList):

    Replace treeContextOrdinal int with Style::ScopeOrdinal enum carrying the same information.
    Simplify the code removing unnecessary use of MatchRequest struct.

(WebCore::compareRules):
* css/ElementRuleCollector.h:
* css/StyleResolver.cpp:
(WebCore::StyleResolver::MatchResult::addMatchedProperties):
(WebCore::StyleResolver::CascadedProperties::setPropertyInternal):
(WebCore::StyleResolver::CascadedProperties::set):
(WebCore::StyleResolver::CascadedProperties::setDeferred):

    Pass styleScopeOrdinal through the cascade mechanism

(WebCore::cascadeLevelForIndex):
(WebCore::StyleResolver::CascadedProperties::addMatch):
(WebCore::StyleResolver::CascadedProperties::addImportantMatches):
(WebCore::StyleResolver::CascadedProperties::Property::apply):

    Set styleScopeOrdinal in State when applying style.

(WebCore::StyleResolver::CascadedProperties::addStyleProperties): Deleted.

    Move the code to the only caller.

* css/StyleResolver.h:
(WebCore::StyleResolver::State::styleScopeOrdinal):
(WebCore::StyleResolver::State::setStyleScopeOrdinal):
* page/animation/CompositeAnimation.cpp:
(WebCore::KeyframeAnimation::KeyframeAnimation):
(WebCore::KeyframeAnimation::resolveKeyframeStyles):

    Find the correct scope for resolving keyframes based on the scope ordinal.

* platform/animation/Animation.cpp:
* platform/animation/Animation.h:

    Add m_nameStyleScopeOrdinal that tells the scope where the name is defined.

* style/StyleScope.cpp:
(WebCore::Style::Scope::forOrdinal):

    Find the scope for ordinal.

* style/StyleScope.h:

    Define ScopeOrdinal types.

(WebCore::Style::operator++):

LayoutTests:

* fast/shadow-dom/shadow-host-animation-expected.html: Added.
* fast/shadow-dom/shadow-host-animation.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="#trunkSourceWebCorecssCSSToStyleMapcpp">trunk/Source/WebCore/css/CSSToStyleMap.cpp</a></li>
<li><a href="#trunkSourceWebCorecssElementRuleCollectorcpp">trunk/Source/WebCore/css/ElementRuleCollector.cpp</a></li>
<li><a href="#trunkSourceWebCorecssElementRuleCollectorh">trunk/Source/WebCore/css/ElementRuleCollector.h</a></li>
<li><a href="#trunkSourceWebCorecssStyleResolvercpp">trunk/Source/WebCore/css/StyleResolver.cpp</a></li>
<li><a href="#trunkSourceWebCorecssStyleResolverh">trunk/Source/WebCore/css/StyleResolver.h</a></li>
<li><a href="#trunkSourceWebCorepageanimationKeyframeAnimationcpp">trunk/Source/WebCore/page/animation/KeyframeAnimation.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformanimationAnimationcpp">trunk/Source/WebCore/platform/animation/Animation.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformanimationAnimationh">trunk/Source/WebCore/platform/animation/Animation.h</a></li>
<li><a href="#trunkSourceWebCorestyleStyleScopecpp">trunk/Source/WebCore/style/StyleScope.cpp</a></li>
<li><a href="#trunkSourceWebCorestyleStyleScopeh">trunk/Source/WebCore/style/StyleScope.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsfastshadowdomshadowhostanimationexpectedhtml">trunk/LayoutTests/fast/shadow-dom/shadow-host-animation-expected.html</a></li>
<li><a href="#trunkLayoutTestsfastshadowdomshadowhostanimationhtml">trunk/LayoutTests/fast/shadow-dom/shadow-host-animation.html</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (209351 => 209352)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2016-12-05 22:38:37 UTC (rev 209351)
+++ trunk/LayoutTests/ChangeLog        2016-12-05 22:42:28 UTC (rev 209352)
</span><span class="lines">@@ -1,3 +1,14 @@
</span><ins>+2016-12-05  Antti Koivisto  &lt;antti@apple.com&gt;
+
+        keyframes do not work when defined inside a style in a shadowRoot
+        https://bugs.webkit.org/show_bug.cgi?id=164608
+        &lt;rdar://problem/29210251&gt;
+
+        Reviewed by Darin Adler.
+
+        * fast/shadow-dom/shadow-host-animation-expected.html: Added.
+        * fast/shadow-dom/shadow-host-animation.html: Added.
+
</ins><span class="cx"> 2016-12-05  Ryan Haddad  &lt;ryanhaddad@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Skip three media/modern-media-controls tests.
</span></span></pre></div>
<a id="trunkLayoutTestsfastshadowdomshadowhostanimationexpectedhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/shadow-dom/shadow-host-animation-expected.html (0 => 209352)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/shadow-dom/shadow-host-animation-expected.html                                (rev 0)
+++ trunk/LayoutTests/fast/shadow-dom/shadow-host-animation-expected.html        2016-12-05 22:42:28 UTC (rev 209352)
</span><span class="lines">@@ -0,0 +1,7 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+&lt;body&gt;
+    &lt;p&gt;Test passes if you see a single 100px by 100px green box below.&lt;/p&gt;
+    &lt;div style=&quot;width: 100px; height: 100px; background: green;&quot;&gt;&lt;/div&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsfastshadowdomshadowhostanimationhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/shadow-dom/shadow-host-animation.html (0 => 209352)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/shadow-dom/shadow-host-animation.html                                (rev 0)
+++ trunk/LayoutTests/fast/shadow-dom/shadow-host-animation.html        2016-12-05 22:42:28 UTC (rev 209352)
</span><span class="lines">@@ -0,0 +1,172 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;style&gt;
+@keyframes top-keyframes {
+    0% { background: red; }
+    100% { background: green; }
+}
+@keyframes shadow-keyframes {
+    0% { background: green; }
+    100% { background: red; }
+}
+@keyframes slotted-keyframes {
+    0% { background: green; }
+    100% { background: red; }
+}
+@keyframes deep-slotted-keyframes {
+    0% { background: green; }
+    100% { background: red; }
+}
+.test {
+    width: 100px;
+    height: 25px;
+    background: red;
+    color: green;
+}
+
+#host1.green {
+    animation-duration: 0.1s;
+    animation-iteration-count: 1;
+    animation-name: top-keyframes;
+    animation-fill-mode: forwards;
+}
+
+&lt;/style&gt;
+&lt;/head&gt;
+&lt;body&gt;
+&lt;p&gt;Test passes if you see a single 100px by 100px green box below.&lt;/p&gt;
+&lt;div id=&quot;host1&quot; class=&quot;test&quot;&gt;&lt;div&gt;text&lt;/div&gt;&lt;/div&gt;
+&lt;div id=&quot;host2&quot; class=&quot;test&quot;&gt;&lt;div&gt;text&lt;/div&gt;&lt;/div&gt;
+&lt;div id=&quot;host3&quot; class=&quot;test&quot;&gt;&lt;div&gt;text&lt;/div&gt;&lt;/div&gt;
+&lt;div id=&quot;host4&quot; class=&quot;test&quot;&gt;&lt;div&gt;text&lt;/div&gt;&lt;/div&gt;
+&lt;script&gt;
+
+if (window.testRunner)
+    testRunner.waitUntilDone();
+
+let expectedEventCount = 0;
+let eventCount = 0;
+
+function animationEndEvent()
+{
+    ++eventCount;
+    if (eventCount == expectedEventCount) {
+        if (window.testRunner)
+            testRunner.notifyDone();
+    }
+}
+
+{
+    const host = document.getElementById('host1');
+    host.attachShadow({mode: 'closed'}).innerHTML = `
+        &lt;slot&gt;&lt;/slot&gt;
+    `;
+
+    getComputedStyle(host.firstChild).backgroundColor;
+    ++expectedEventCount;
+    document.addEventListener('animationend', animationEndEvent);
+    host.classList.toggle('green');
+}
+
+{
+    const host = document.getElementById('host2');
+    host.attachShadow({mode: 'closed'}).innerHTML = `
+    &lt;style&gt;
+    @keyframes shadow-keyframes {
+        0% { background: red; }
+        100% { background: green; }
+    }
+    :host(.green) {
+        animation-duration: 0.1s;
+        animation-iteration-count: 1;
+        animation-name: shadow-keyframes;
+        animation-fill-mode: forwards;
+    }
+    &lt;/style&gt;
+    &lt;slot&gt;&lt;/slot&gt;
+    `;
+
+    getComputedStyle(host.firstChild).backgroundColor;
+    ++expectedEventCount;
+    document.addEventListener('animationend', animationEndEvent);
+    host.classList.toggle('green');
+}
+
+{
+    const host = document.getElementById('host3');
+    const shadow = host.attachShadow({mode: 'closed'});
+    shadow.innerHTML = `
+    &lt;style&gt;
+    @keyframes slotted-keyframes {
+        0% { background: red; }
+        100% { background: green; }
+    }
+    ::slotted(.green) {
+        animation-duration: 0.1s;
+        animation-iteration-count: 1;
+        animation-name: slotted-keyframes;
+        animation-fill-mode: forwards;
+        height: 100%;
+    }
+    div { height: 100%; }
+    &lt;/style&gt;
+    &lt;div&gt;&lt;slot&gt;&lt;/slot&gt;&lt;/div&gt;
+    `;
+
+    shadow.querySelector('div').attachShadow({mode: 'closed'}).innerHTML = `
+    &lt;style&gt;
+    @keyframes slotted-keyframes {
+        0% { background: green; }
+        100% { background: red; }
+    }
+    &lt;/style&gt;
+    &lt;slot&gt;&lt;/slot&gt;
+    `;
+
+    getComputedStyle(host.firstChild).backgroundColor;
+    ++expectedEventCount;
+    document.addEventListener('animationend', animationEndEvent);
+    host.firstChild.classList.toggle('green');
+}
+
+{
+    const host = document.getElementById('host4');
+    const shadow = host.attachShadow({mode: 'closed'});
+    shadow.innerHTML = `
+    &lt;style&gt;
+    @keyframes deep-slotted-keyframes {
+        0% { background: green; }
+        100% { background: red; }
+    }
+    div { height: 100%; }
+    &lt;/style&gt;
+    &lt;div&gt;&lt;slot&gt;&lt;/slot&gt;&lt;/div&gt;
+    `;
+
+    shadow.querySelector('div').attachShadow({mode: 'closed'}).innerHTML = `
+    &lt;style&gt;
+    @keyframes deep-slotted-keyframes {
+        0% { background: red; }
+        100% { background: green; }
+    }
+    ::slotted(.green) {
+        animation-duration: 0.1s;
+        animation-iteration-count: 1;
+        animation-name: deep-slotted-keyframes;
+        animation-fill-mode: forwards;
+        height: 100%;
+    }
+    &lt;/style&gt;
+    &lt;slot&gt;&lt;/slot&gt;
+    `;
+
+    getComputedStyle(host.firstChild).backgroundColor;
+    ++expectedEventCount;
+    document.addEventListener('animationend', animationEndEvent);
+    host.firstChild.classList.toggle('green');
+}
+
+&lt;/script&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (209351 => 209352)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-12-05 22:38:37 UTC (rev 209351)
+++ trunk/Source/WebCore/ChangeLog        2016-12-05 22:42:28 UTC (rev 209352)
</span><span class="lines">@@ -1,3 +1,85 @@
</span><ins>+2016-12-05  Antti Koivisto  &lt;antti@apple.com&gt;
+
+        keyframes do not work when defined inside a style in a shadowRoot
+        https://bugs.webkit.org/show_bug.cgi?id=164608
+        &lt;rdar://problem/29210251&gt;
+
+        Reviewed by Darin Adler.
+
+        With :host and ::slotted rules a keyframe animation affecting an element can be
+        defined in a style scope different from the element's own scope. Style resolver
+        loses the scope information when building the RenderStyle so there is no way
+        to find out the correct scope.
+
+        Fix by passing style scope through to style builder and including a scope association
+        with the animation name. Find the correct scope when resolving keyframes.
+
+        Test: fast/shadow-dom/shadow-host-animation.html
+
+        * css/CSSToStyleMap.cpp:
+        (WebCore::CSSToStyleMap::mapAnimationName):
+
+            Include scope with the name.
+
+        * css/ElementRuleCollector.cpp:
+        (WebCore::MatchRequest::MatchRequest):
+        (WebCore::ElementRuleCollector::addMatchedRule):
+        (WebCore::ElementRuleCollector::sortAndTransferMatchedRules):
+        (WebCore::ElementRuleCollector::matchAuthorRules):
+        (WebCore::ElementRuleCollector::matchAuthorShadowPseudoElementRules):
+        (WebCore::ElementRuleCollector::matchHostPseudoClassRules):
+        (WebCore::ElementRuleCollector::matchSlottedPseudoElementRules):
+        (WebCore::ElementRuleCollector::collectMatchingRulesForList):
+
+            Replace treeContextOrdinal int with Style::ScopeOrdinal enum carrying the same information.
+            Simplify the code removing unnecessary use of MatchRequest struct.
+
+        (WebCore::compareRules):
+        * css/ElementRuleCollector.h:
+        * css/StyleResolver.cpp:
+        (WebCore::StyleResolver::MatchResult::addMatchedProperties):
+        (WebCore::StyleResolver::CascadedProperties::setPropertyInternal):
+        (WebCore::StyleResolver::CascadedProperties::set):
+        (WebCore::StyleResolver::CascadedProperties::setDeferred):
+
+            Pass styleScopeOrdinal through the cascade mechanism
+
+        (WebCore::cascadeLevelForIndex):
+        (WebCore::StyleResolver::CascadedProperties::addMatch):
+        (WebCore::StyleResolver::CascadedProperties::addImportantMatches):
+        (WebCore::StyleResolver::CascadedProperties::Property::apply):
+
+            Set styleScopeOrdinal in State when applying style.
+
+        (WebCore::StyleResolver::CascadedProperties::addStyleProperties): Deleted.
+
+            Move the code to the only caller.
+
+        * css/StyleResolver.h:
+        (WebCore::StyleResolver::State::styleScopeOrdinal):
+        (WebCore::StyleResolver::State::setStyleScopeOrdinal):
+        * page/animation/CompositeAnimation.cpp:
+        (WebCore::KeyframeAnimation::KeyframeAnimation):
+        (WebCore::KeyframeAnimation::resolveKeyframeStyles):
+
+            Find the correct scope for resolving keyframes based on the scope ordinal.
+
+        * platform/animation/Animation.cpp:
+        * platform/animation/Animation.h:
+
+            Add m_nameStyleScopeOrdinal that tells the scope where the name is defined.
+
+        * style/StyleScope.cpp:
+        (WebCore::Style::Scope::forOrdinal):
+
+            Find the scope for ordinal.
+
+        * style/StyleScope.h:
+
+            Define ScopeOrdinal types.
+
+        (WebCore::Style::operator++):
+
</ins><span class="cx"> 2016-12-05  Dave Hyatt  &lt;hyatt@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [CSS Parser] Support glyph-orientation-horizontal and glyph-orientation-vertical
</span></span></pre></div>
<a id="trunkSourceWebCorecssCSSToStyleMapcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/css/CSSToStyleMap.cpp (209351 => 209352)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/css/CSSToStyleMap.cpp        2016-12-05 22:38:37 UTC (rev 209351)
+++ trunk/Source/WebCore/css/CSSToStyleMap.cpp        2016-12-05 22:42:28 UTC (rev 209352)
</span><span class="lines">@@ -412,7 +412,7 @@
</span><span class="cx">     if (primitiveValue.valueID() == CSSValueNone)
</span><span class="cx">         layer.setIsNoneAnimation(true);
</span><span class="cx">     else
</span><del>-        layer.setName(primitiveValue.stringValue());
</del><ins>+        layer.setName(primitiveValue.stringValue(), m_resolver-&gt;state().styleScopeOrdinal());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void CSSToStyleMap::mapAnimationPlayState(Animation&amp; layer, const CSSValue&amp; value)
</span></span></pre></div>
<a id="trunkSourceWebCorecssElementRuleCollectorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/css/ElementRuleCollector.cpp (209351 => 209352)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/css/ElementRuleCollector.cpp        2016-12-05 22:38:37 UTC (rev 209351)
+++ trunk/Source/WebCore/css/ElementRuleCollector.cpp        2016-12-05 22:42:28 UTC (rev 209352)
</span><span class="lines">@@ -68,15 +68,15 @@
</span><span class="cx"> 
</span><span class="cx"> class MatchRequest {
</span><span class="cx"> public:
</span><del>-    MatchRequest(const RuleSet* ruleSet, bool includeEmptyRules = false, int treeContextOrdinal = 0)
</del><ins>+    MatchRequest(const RuleSet* ruleSet, bool includeEmptyRules = false, Style::ScopeOrdinal styleScopeOrdinal = Style::ScopeOrdinal::Element)
</ins><span class="cx">         : ruleSet(ruleSet)
</span><span class="cx">         , includeEmptyRules(includeEmptyRules)
</span><del>-        , treeContextOrdinal(treeContextOrdinal)
</del><ins>+        , styleScopeOrdinal(styleScopeOrdinal)
</ins><span class="cx">     {
</span><span class="cx">     }
</span><span class="cx">     const RuleSet* ruleSet;
</span><span class="cx">     const bool includeEmptyRules;
</span><del>-    int treeContextOrdinal;
</del><ins>+    Style::ScopeOrdinal styleScopeOrdinal;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> ElementRuleCollector::ElementRuleCollector(const Element&amp; element, const DocumentRuleSets&amp; ruleSets, const SelectorFilter* selectorFilter)
</span><span class="lines">@@ -108,7 +108,7 @@
</span><span class="cx">     return m_matchedRuleList;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline void ElementRuleCollector::addMatchedRule(const RuleData&amp; ruleData, unsigned specificity, int treeContextOrdinal, StyleResolver::RuleRange&amp; ruleRange)
</del><ins>+inline void ElementRuleCollector::addMatchedRule(const RuleData&amp; ruleData, unsigned specificity, Style::ScopeOrdinal styleScopeOrdinal, StyleResolver::RuleRange&amp; ruleRange)
</ins><span class="cx"> {
</span><span class="cx">     // Update our first/last rule indices in the matched rules array.
</span><span class="cx">     ++ruleRange.lastRuleIndex;
</span><span class="lines">@@ -115,7 +115,7 @@
</span><span class="cx">     if (ruleRange.firstRuleIndex == -1)
</span><span class="cx">         ruleRange.firstRuleIndex = ruleRange.lastRuleIndex;
</span><span class="cx"> 
</span><del>-    m_matchedRules.append({ &amp;ruleData, specificity, treeContextOrdinal });
</del><ins>+    m_matchedRules.append({ &amp;ruleData, specificity, styleScopeOrdinal });
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void ElementRuleCollector::clearMatchedRules()
</span><span class="lines">@@ -193,7 +193,7 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     for (const MatchedRule&amp; matchedRule : m_matchedRules) {
</span><del>-        m_result.addMatchedProperties(matchedRule.ruleData-&gt;rule()-&gt;properties(), matchedRule.ruleData-&gt;rule(), matchedRule.ruleData-&gt;linkMatchType(), matchedRule.ruleData-&gt;propertyWhitelistType(), matchedRule.treeContextOrdinal);
</del><ins>+        m_result.addMatchedProperties(matchedRule.ruleData-&gt;rule()-&gt;properties(), matchedRule.ruleData-&gt;rule(), matchedRule.ruleData-&gt;linkMatchType(), matchedRule.ruleData-&gt;propertyWhitelistType(), matchedRule.styleScopeOrdinal);
</ins><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -204,25 +204,26 @@
</span><span class="cx">     m_result.ranges.lastAuthorRule = m_result.matchedProperties().size() - 1;
</span><span class="cx">     StyleResolver::RuleRange ruleRange = m_result.ranges.authorRuleRange();
</span><span class="cx"> 
</span><del>-    // Match global author rules.
-    MatchRequest matchRequest(&amp;m_authorStyle, includeEmptyRules);
-    collectMatchingRules(matchRequest, ruleRange);
-    collectMatchingRulesForRegion(matchRequest, ruleRange);
</del><ins>+    {
+        MatchRequest matchRequest(&amp;m_authorStyle, includeEmptyRules);
+        collectMatchingRules(matchRequest, ruleRange);
+        collectMatchingRulesForRegion(matchRequest, ruleRange);
+    }
</ins><span class="cx"> 
</span><span class="cx">     auto* parent = m_element.parentElement();
</span><span class="cx">     if (parent &amp;&amp; parent-&gt;shadowRoot())
</span><del>-        matchSlottedPseudoElementRules(matchRequest, ruleRange);
</del><ins>+        matchSlottedPseudoElementRules(includeEmptyRules, ruleRange);
</ins><span class="cx"> 
</span><span class="cx">     if (m_element.shadowRoot() &amp;&amp; m_pseudoStyleRequest.pseudoId == NOPSEUDO)
</span><del>-        matchHostPseudoClassRules(matchRequest, ruleRange);
</del><ins>+        matchHostPseudoClassRules(includeEmptyRules, ruleRange);
</ins><span class="cx"> 
</span><span class="cx">     if (m_element.isInShadowTree())
</span><del>-        matchAuthorShadowPseudoElementRules(matchRequest, ruleRange);
</del><ins>+        matchAuthorShadowPseudoElementRules(includeEmptyRules, ruleRange);
</ins><span class="cx"> 
</span><span class="cx">     sortAndTransferMatchedRules();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void ElementRuleCollector::matchAuthorShadowPseudoElementRules(const MatchRequest&amp; matchRequest, StyleResolver::RuleRange&amp; ruleRange)
</del><ins>+void ElementRuleCollector::matchAuthorShadowPseudoElementRules(bool includeEmptyRules, StyleResolver::RuleRange&amp; ruleRange)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(m_element.isInShadowTree());
</span><span class="cx">     auto&amp; shadowRoot = *m_element.containingShadowRoot();
</span><span class="lines">@@ -230,16 +231,14 @@
</span><span class="cx">         return;
</span><span class="cx">     // Look up shadow pseudo elements also from the host scope author style as they are web-exposed.
</span><span class="cx">     auto&amp; hostAuthorRules = Style::Scope::forNode(*shadowRoot.host()).resolver().ruleSets().authorStyle();
</span><del>-    MatchRequest hostAuthorRequest { &amp;hostAuthorRules, matchRequest.includeEmptyRules, matchRequest.treeContextOrdinal - 1 };
</del><ins>+    MatchRequest hostAuthorRequest { &amp;hostAuthorRules, includeEmptyRules, Style::ScopeOrdinal::ContainingHost };
</ins><span class="cx">     collectMatchingShadowPseudoElementRules(hostAuthorRequest, ruleRange);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void ElementRuleCollector::matchHostPseudoClassRules(MatchRequest&amp; matchRequest, StyleResolver::RuleRange&amp; ruleRange)
</del><ins>+void ElementRuleCollector::matchHostPseudoClassRules(bool includeEmptyRules, StyleResolver::RuleRange&amp; ruleRange)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(m_element.shadowRoot());
</span><span class="cx"> 
</span><del>-    matchRequest.treeContextOrdinal++;
-
</del><span class="cx">     auto&amp; shadowAuthorStyle = m_element.shadowRoot()-&gt;styleScope().resolver().ruleSets().authorStyle();
</span><span class="cx">     auto&amp; shadowHostRules = shadowAuthorStyle.hostPseudoClassRules();
</span><span class="cx">     if (shadowHostRules.isEmpty())
</span><span class="lines">@@ -249,40 +248,35 @@
</span><span class="cx">     SelectorChecker selectorChecker(m_element.document());
</span><span class="cx"> 
</span><span class="cx">     for (auto&amp; ruleData : shadowHostRules) {
</span><del>-        if (ruleData.rule()-&gt;properties().isEmpty() &amp;&amp; !matchRequest.includeEmptyRules)
</del><ins>+        if (ruleData.rule()-&gt;properties().isEmpty() &amp;&amp; !includeEmptyRules)
</ins><span class="cx">             continue;
</span><span class="cx">         auto&amp; selector = *ruleData.selector();
</span><span class="cx">         unsigned specificity = 0;
</span><span class="cx">         if (!selectorChecker.matchHostPseudoClass(selector, m_element, context, specificity))
</span><span class="cx">             continue;
</span><del>-        addMatchedRule(ruleData, specificity, matchRequest.treeContextOrdinal, ruleRange);
</del><ins>+        addMatchedRule(ruleData, specificity, Style::ScopeOrdinal::Shadow, ruleRange);
</ins><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void ElementRuleCollector::matchSlottedPseudoElementRules(MatchRequest&amp; matchRequest, StyleResolver::RuleRange&amp; ruleRange)
</del><ins>+void ElementRuleCollector::matchSlottedPseudoElementRules(bool includeEmptyRules, StyleResolver::RuleRange&amp; ruleRange)
</ins><span class="cx"> {
</span><del>-    auto* maybeSlotted = &amp;m_element;
-    for (auto* hostShadowRoot = m_element.parentNode()-&gt;shadowRoot(); hostShadowRoot; hostShadowRoot = maybeSlotted-&gt;parentNode()-&gt;shadowRoot()) {
-        auto* slot = hostShadowRoot-&gt;findAssignedSlot(*maybeSlotted);
-        if (!slot)
-            return;
</del><ins>+    auto* slot = m_element.assignedSlot();
+    auto styleScopeOrdinal = Style::ScopeOrdinal::FirstSlot;
</ins><span class="cx"> 
</span><del>-        matchRequest.treeContextOrdinal++;
-
-        // In nested case the slot may itself be assigned to a slot. Collect ::slotted rules from all the nested trees.
-        maybeSlotted = slot;
-        if (!hostShadowRoot-&gt;styleScope().resolver().ruleSets().isAuthorStyleDefined())
</del><ins>+    for (; slot; slot = slot-&gt;assignedSlot(), ++styleScopeOrdinal) {
+        auto&amp; styleScope = Style::Scope::forNode(*slot);
+        if (!styleScope.resolver().ruleSets().isAuthorStyleDefined())
</ins><span class="cx">             continue;
</span><span class="cx">         // Find out if there are any ::slotted rules in the shadow tree matching the current slot.
</span><span class="cx">         // FIXME: This is really part of the slot style and could be cached when resolving it.
</span><del>-        ElementRuleCollector collector(*slot, hostShadowRoot-&gt;styleScope().resolver().ruleSets().authorStyle(), nullptr);
-        auto slottedPseudoElementRules = collector.collectSlottedPseudoElementRulesForSlot(matchRequest.includeEmptyRules);
</del><ins>+        ElementRuleCollector collector(*slot, styleScope.resolver().ruleSets().authorStyle(), nullptr);
+        auto slottedPseudoElementRules = collector.collectSlottedPseudoElementRulesForSlot(includeEmptyRules);
</ins><span class="cx">         if (!slottedPseudoElementRules)
</span><span class="cx">             continue;
</span><span class="cx">         // Match in the current scope.
</span><span class="cx">         SetForScope&lt;bool&gt; change(m_isMatchingSlottedPseudoElements, true);
</span><span class="cx"> 
</span><del>-        MatchRequest scopeMatchRequest(nullptr, matchRequest.includeEmptyRules, matchRequest.treeContextOrdinal);
</del><ins>+        MatchRequest scopeMatchRequest(nullptr, includeEmptyRules, styleScopeOrdinal);
</ins><span class="cx">         collectMatchingRulesForList(slottedPseudoElementRules.get(), scopeMatchRequest, ruleRange);
</span><span class="cx"> 
</span><span class="cx">         m_keepAliveSlottedPseudoElementRules.append(WTFMove(slottedPseudoElementRules));
</span><span class="lines">@@ -507,15 +501,15 @@
</span><span class="cx"> 
</span><span class="cx">         unsigned specificity;
</span><span class="cx">         if (ruleMatches(ruleData, specificity))
</span><del>-            addMatchedRule(ruleData, specificity, matchRequest.treeContextOrdinal, ruleRange);
</del><ins>+            addMatchedRule(ruleData, specificity, matchRequest.styleScopeOrdinal, ruleRange);
</ins><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> static inline bool compareRules(MatchedRule r1, MatchedRule r2)
</span><span class="cx"> {
</span><del>-    // For normal properties the earlier tree wins. This may be reversed by !important which is handled when resolving cascade.
-    if (r1.treeContextOrdinal != r2.treeContextOrdinal)
-        return r1.treeContextOrdinal &gt; r2.treeContextOrdinal;
</del><ins>+    // For normal properties the earlier scope wins. This may be reversed by !important which is handled when resolving cascade.
+    if (r1.styleScopeOrdinal != r2.styleScopeOrdinal)
+        return r1.styleScopeOrdinal &gt; r2.styleScopeOrdinal;
</ins><span class="cx"> 
</span><span class="cx">     if (r1.specificity != r2.specificity)
</span><span class="cx">         return r1.specificity &lt; r2.specificity;
</span></span></pre></div>
<a id="trunkSourceWebCorecssElementRuleCollectorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/css/ElementRuleCollector.h (209351 => 209352)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/css/ElementRuleCollector.h        2016-12-05 22:38:37 UTC (rev 209351)
+++ trunk/Source/WebCore/css/ElementRuleCollector.h        2016-12-05 22:42:28 UTC (rev 209352)
</span><span class="lines">@@ -40,7 +40,7 @@
</span><span class="cx"> struct MatchedRule {
</span><span class="cx">     const RuleData* ruleData;
</span><span class="cx">     unsigned specificity;   
</span><del>-    int treeContextOrdinal;
</del><ins>+    Style::ScopeOrdinal styleScopeOrdinal;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> class ElementRuleCollector {
</span><span class="lines">@@ -75,9 +75,9 @@
</span><span class="cx">     void addElementStyleProperties(const StyleProperties*, bool isCacheable = true);
</span><span class="cx"> 
</span><span class="cx">     void matchUARules(RuleSet*);
</span><del>-    void matchAuthorShadowPseudoElementRules(const MatchRequest&amp;, StyleResolver::RuleRange&amp;);
-    void matchHostPseudoClassRules(MatchRequest&amp;, StyleResolver::RuleRange&amp;);
-    void matchSlottedPseudoElementRules(MatchRequest&amp;, StyleResolver::RuleRange&amp;);
</del><ins>+    void matchAuthorShadowPseudoElementRules(bool includeEmptyRules, StyleResolver::RuleRange&amp;);
+    void matchHostPseudoClassRules(bool includeEmptyRules, StyleResolver::RuleRange&amp;);
+    void matchSlottedPseudoElementRules(bool includeEmptyRules, StyleResolver::RuleRange&amp;);
</ins><span class="cx"> 
</span><span class="cx">     void collectMatchingShadowPseudoElementRules(const MatchRequest&amp;, StyleResolver::RuleRange&amp;);
</span><span class="cx">     std::unique_ptr&lt;RuleSet::RuleDataVector&gt; collectSlottedPseudoElementRulesForSlot(bool includeEmptyRules);
</span><span class="lines">@@ -90,7 +90,7 @@
</span><span class="cx">     void sortMatchedRules();
</span><span class="cx">     void sortAndTransferMatchedRules();
</span><span class="cx"> 
</span><del>-    void addMatchedRule(const RuleData&amp;, unsigned specificity, int treeContextOrdinal, StyleResolver::RuleRange&amp;);
</del><ins>+    void addMatchedRule(const RuleData&amp;, unsigned specificity, Style::ScopeOrdinal, StyleResolver::RuleRange&amp;);
</ins><span class="cx"> 
</span><span class="cx">     const Element&amp; m_element;
</span><span class="cx">     const RuleSet&amp; m_authorStyle;
</span></span></pre></div>
<a id="trunkSourceWebCorecssStyleResolvercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/css/StyleResolver.cpp (209351 => 209352)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/css/StyleResolver.cpp        2016-12-05 22:38:37 UTC (rev 209351)
+++ trunk/Source/WebCore/css/StyleResolver.cpp        2016-12-05 22:42:28 UTC (rev 209352)
</span><span class="lines">@@ -187,7 +187,7 @@
</span><span class="cx">     m_cssToLengthConversionData = CSSToLengthConversionData();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void StyleResolver::MatchResult::addMatchedProperties(const StyleProperties&amp; properties, StyleRule* rule, unsigned linkMatchType, PropertyWhitelistType propertyWhitelistType, int treeContextOrdinal)
</del><ins>+void StyleResolver::MatchResult::addMatchedProperties(const StyleProperties&amp; properties, StyleRule* rule, unsigned linkMatchType, PropertyWhitelistType propertyWhitelistType, Style::ScopeOrdinal styleScopeOrdinal)
</ins><span class="cx"> {
</span><span class="cx">     m_matchedProperties.grow(m_matchedProperties.size() + 1);
</span><span class="cx">     StyleResolver::MatchedProperties&amp; newProperties = m_matchedProperties.last();
</span><span class="lines">@@ -194,11 +194,10 @@
</span><span class="cx">     newProperties.properties = const_cast&lt;StyleProperties*&gt;(&amp;properties);
</span><span class="cx">     newProperties.linkMatchType = linkMatchType;
</span><span class="cx">     newProperties.whitelistType = propertyWhitelistType;
</span><del>-    newProperties.treeContextOrdinal = treeContextOrdinal;
</del><ins>+    newProperties.styleScopeOrdinal = styleScopeOrdinal;
</ins><span class="cx">     matchedRules.append(rule);
</span><span class="cx"> 
</span><del>-    // Ordinal is relative to the currently matched element
-    if (treeContextOrdinal)
</del><ins>+    if (styleScopeOrdinal != Style::ScopeOrdinal::Element)
</ins><span class="cx">         isCacheable = false;
</span><span class="cx"> 
</span><span class="cx">     if (isCacheable) {
</span><span class="lines">@@ -2060,11 +2059,12 @@
</span><span class="cx">     return m_customProperties.get(name);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void StyleResolver::CascadedProperties::setPropertyInternal(Property&amp; property, CSSPropertyID id, CSSValue&amp; cssValue, unsigned linkMatchType, CascadeLevel cascadeLevel)
</del><ins>+void StyleResolver::CascadedProperties::setPropertyInternal(Property&amp; property, CSSPropertyID id, CSSValue&amp; cssValue, unsigned linkMatchType, CascadeLevel cascadeLevel, Style::ScopeOrdinal styleScopeOrdinal)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(linkMatchType &lt;= SelectorChecker::MatchAll);
</span><span class="cx">     property.id = id;
</span><span class="cx">     property.level = cascadeLevel;
</span><ins>+    property.styleScopeOrdinal = styleScopeOrdinal;
</ins><span class="cx">     if (linkMatchType == SelectorChecker::MatchAll) {
</span><span class="cx">         property.cssValue[0] = &amp;cssValue;
</span><span class="cx">         property.cssValue[SelectorChecker::MatchLink] = &amp;cssValue;
</span><span class="lines">@@ -2073,7 +2073,7 @@
</span><span class="cx">         property.cssValue[linkMatchType] = &amp;cssValue;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void StyleResolver::CascadedProperties::set(CSSPropertyID id, CSSValue&amp; cssValue, unsigned linkMatchType, CascadeLevel cascadeLevel)
</del><ins>+void StyleResolver::CascadedProperties::set(CSSPropertyID id, CSSValue&amp; cssValue, unsigned linkMatchType, CascadeLevel cascadeLevel, Style::ScopeOrdinal styleScopeOrdinal)
</ins><span class="cx"> {
</span><span class="cx">     if (CSSProperty::isDirectionAwareProperty(id))
</span><span class="cx">         id = CSSProperty::resolveDirectionAwareProperty(id, m_direction, m_writingMode);
</span><span class="lines">@@ -2090,11 +2090,11 @@
</span><span class="cx">             Property property;
</span><span class="cx">             property.id = id;
</span><span class="cx">             memset(property.cssValue, 0, sizeof(property.cssValue));
</span><del>-            setPropertyInternal(property, id, cssValue, linkMatchType, cascadeLevel);
</del><ins>+            setPropertyInternal(property, id, cssValue, linkMatchType, cascadeLevel, styleScopeOrdinal);
</ins><span class="cx">             customProperties().set(customValue.name(), property);
</span><span class="cx">         } else {
</span><span class="cx">             Property property = customProperties().get(customValue.name());
</span><del>-            setPropertyInternal(property, id, cssValue, linkMatchType, cascadeLevel);
</del><ins>+            setPropertyInternal(property, id, cssValue, linkMatchType, cascadeLevel, styleScopeOrdinal);
</ins><span class="cx">             customProperties().set(customValue.name(), property);
</span><span class="cx">         }
</span><span class="cx">         return;
</span><span class="lines">@@ -2103,10 +2103,10 @@
</span><span class="cx">     if (!m_propertyIsPresent[id])
</span><span class="cx">         memset(property.cssValue, 0, sizeof(property.cssValue));
</span><span class="cx">     m_propertyIsPresent.set(id);
</span><del>-    setPropertyInternal(property, id, cssValue, linkMatchType, cascadeLevel);
</del><ins>+    setPropertyInternal(property, id, cssValue, linkMatchType, cascadeLevel, styleScopeOrdinal);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void StyleResolver::CascadedProperties::setDeferred(CSSPropertyID id, CSSValue&amp; cssValue, unsigned linkMatchType, CascadeLevel cascadeLevel)
</del><ins>+void StyleResolver::CascadedProperties::setDeferred(CSSPropertyID id, CSSValue&amp; cssValue, unsigned linkMatchType, CascadeLevel cascadeLevel, Style::ScopeOrdinal styleScopeOrdinal)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(!CSSProperty::isDirectionAwareProperty(id));
</span><span class="cx">     ASSERT(shouldApplyPropertyInParseOrder(id));
</span><span class="lines">@@ -2113,14 +2113,29 @@
</span><span class="cx"> 
</span><span class="cx">     Property property;
</span><span class="cx">     memset(property.cssValue, 0, sizeof(property.cssValue));
</span><del>-    setPropertyInternal(property, id, cssValue, linkMatchType, cascadeLevel);
</del><ins>+    setPropertyInternal(property, id, cssValue, linkMatchType, cascadeLevel, styleScopeOrdinal);
</ins><span class="cx">     m_deferredProperties.append(property);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void StyleResolver::CascadedProperties::addStyleProperties(const StyleProperties&amp; properties, bool isImportant, bool inheritedOnly, PropertyWhitelistType propertyWhitelistType, unsigned linkMatchType, CascadeLevel cascadeLevel)
</del><ins>+static CascadeLevel cascadeLevelForIndex(const StyleResolver::MatchResult&amp; matchResult, int index)
</ins><span class="cx"> {
</span><del>-    for (unsigned i = 0, count = properties.propertyCount(); i &lt; count; ++i) {
-        auto current = properties.propertyAt(i);
</del><ins>+    if (index &gt;= matchResult.ranges.firstUARule &amp;&amp; index &lt;= matchResult.ranges.lastUARule)
+        return UserAgentLevel;
+    if (index &gt;= matchResult.ranges.firstUserRule &amp;&amp; index &lt;= matchResult.ranges.lastUserRule)
+        return UserLevel;
+    return AuthorLevel;
+}
+
+void StyleResolver::CascadedProperties::addMatch(const MatchResult&amp; matchResult, unsigned index, bool isImportant, bool inheritedOnly)
+{
+    auto&amp; matchedProperties = matchResult.matchedProperties()[index];
+    auto&amp; styleProperties = *matchedProperties.properties;
+
+    auto propertyWhitelistType = static_cast&lt;PropertyWhitelistType&gt;(matchedProperties.whitelistType);
+    auto cascadeLevel = cascadeLevelForIndex(matchResult, index);
+
+    for (unsigned i = 0, count = styleProperties.propertyCount(); i &lt; count; ++i) {
+        auto current = styleProperties.propertyAt(i);
</ins><span class="cx">         if (isImportant != current.isImportant())
</span><span class="cx">             continue;
</span><span class="cx">         if (inheritedOnly &amp;&amp; !current.isInherited()) {
</span><span class="lines">@@ -2139,31 +2154,12 @@
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">         if (shouldApplyPropertyInParseOrder(propertyID))
</span><del>-            setDeferred(propertyID, *current.value(), linkMatchType, cascadeLevel);
</del><ins>+            setDeferred(propertyID, *current.value(), matchedProperties.linkMatchType, cascadeLevel, matchedProperties.styleScopeOrdinal);
</ins><span class="cx">         else
</span><del>-            set(propertyID, *current.value(), linkMatchType, cascadeLevel);
</del><ins>+            set(propertyID, *current.value(), matchedProperties.linkMatchType, cascadeLevel, matchedProperties.styleScopeOrdinal);
</ins><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static CascadeLevel cascadeLevelForIndex(const StyleResolver::MatchResult&amp; matchResult, int index)
-{
-    if (index &gt;= matchResult.ranges.firstUARule &amp;&amp; index &lt;= matchResult.ranges.lastUARule)
-        return UserAgentLevel;
-    if (index &gt;= matchResult.ranges.firstUserRule &amp;&amp; index &lt;= matchResult.ranges.lastUserRule)
-        return UserLevel;
-    return AuthorLevel;
-}
-
-void StyleResolver::CascadedProperties::addMatch(const MatchResult&amp; matchResult, unsigned index, bool isImportant, bool inheritedOnly)
-{
-    const MatchedProperties&amp; matchedProperties = matchResult.matchedProperties()[index];
-
-    auto propertyWhitelistType = static_cast&lt;PropertyWhitelistType&gt;(matchedProperties.whitelistType);
-    auto cascadeLevel = cascadeLevelForIndex(matchResult, index);
-
-    addStyleProperties(*matchedProperties.properties, isImportant, inheritedOnly, propertyWhitelistType, matchedProperties.linkMatchType, cascadeLevel);
-}
-
</del><span class="cx"> void StyleResolver::CascadedProperties::addNormalMatches(const MatchResult&amp; matchResult, int startIndex, int endIndex, bool inheritedOnly)
</span><span class="cx"> {
</span><span class="cx">     if (startIndex == -1)
</span><span class="lines">@@ -2189,7 +2185,7 @@
</span><span class="cx"> 
</span><span class="cx">     struct IndexAndOrdinal {
</span><span class="cx">         int index;
</span><del>-        int ordinal;
</del><ins>+        Style::ScopeOrdinal ordinal;
</ins><span class="cx">     };
</span><span class="cx">     Vector&lt;IndexAndOrdinal&gt; shadowTreeMatches;
</span><span class="cx"> 
</span><span class="lines">@@ -2199,8 +2195,8 @@
</span><span class="cx">         if (!hasImportantProperties(*matchedProperties.properties))
</span><span class="cx">             continue;
</span><span class="cx"> 
</span><del>-        if (matchedProperties.treeContextOrdinal) {
-            shadowTreeMatches.append({ i, matchedProperties.treeContextOrdinal });
</del><ins>+        if (matchedProperties.styleScopeOrdinal != Style::ScopeOrdinal::Element) {
+            shadowTreeMatches.append({ i, matchedProperties.styleScopeOrdinal });
</ins><span class="cx">             continue;
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="lines">@@ -2230,6 +2226,7 @@
</span><span class="cx"> {
</span><span class="cx">     State&amp; state = resolver.state();
</span><span class="cx">     state.setCascadeLevel(level);
</span><ins>+    state.setStyleScopeOrdinal(styleScopeOrdinal);
</ins><span class="cx"> 
</span><span class="cx">     if (cssValue[SelectorChecker::MatchDefault]) {
</span><span class="cx">         state.setApplyPropertyToRegularStyle(true);
</span></span></pre></div>
<a id="trunkSourceWebCorecssStyleResolverh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/css/StyleResolver.h (209351 => 209352)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/css/StyleResolver.h        2016-12-05 22:38:37 UTC (rev 209351)
+++ trunk/Source/WebCore/css/StyleResolver.h        2016-12-05 22:42:28 UTC (rev 209352)
</span><span class="lines">@@ -32,6 +32,7 @@
</span><span class="cx"> #include &quot;RuleSet.h&quot;
</span><span class="cx"> #include &quot;SelectorChecker.h&quot;
</span><span class="cx"> #include &quot;StylePendingResources.h&quot;
</span><ins>+#include &quot;StyleScope.h&quot;
</ins><span class="cx"> #include &lt;bitset&gt;
</span><span class="cx"> #include &lt;memory&gt;
</span><span class="cx"> #include &lt;wtf/HashMap.h&gt;
</span><span class="lines">@@ -250,7 +251,7 @@
</span><span class="cx">         RefPtr&lt;StyleProperties&gt; properties;
</span><span class="cx">         uint16_t linkMatchType;
</span><span class="cx">         uint16_t whitelistType;
</span><del>-        int treeContextOrdinal;
</del><ins>+        Style::ScopeOrdinal styleScopeOrdinal;
</ins><span class="cx">     };
</span><span class="cx"> 
</span><span class="cx">     struct MatchResult {
</span><span class="lines">@@ -261,7 +262,7 @@
</span><span class="cx"> 
</span><span class="cx">         const Vector&lt;MatchedProperties, 64&gt;&amp; matchedProperties() const { return m_matchedProperties; }
</span><span class="cx"> 
</span><del>-        void addMatchedProperties(const StyleProperties&amp;, StyleRule* = nullptr, unsigned linkMatchType = SelectorChecker::MatchAll, PropertyWhitelistType = PropertyWhitelistNone, int treeContextOrdinal = 0);
</del><ins>+        void addMatchedProperties(const StyleProperties&amp;, StyleRule* = nullptr, unsigned linkMatchType = SelectorChecker::MatchAll, PropertyWhitelistType = PropertyWhitelistNone, Style::ScopeOrdinal = Style::ScopeOrdinal::Element);
</ins><span class="cx">     private:
</span><span class="cx">         Vector&lt;MatchedProperties, 64&gt; m_matchedProperties;
</span><span class="cx">     };
</span><span class="lines">@@ -276,6 +277,7 @@
</span><span class="cx"> 
</span><span class="cx">             CSSPropertyID id;
</span><span class="cx">             CascadeLevel level;
</span><ins>+            Style::ScopeOrdinal styleScopeOrdinal;
</ins><span class="cx">             CSSValue* cssValue[3];
</span><span class="cx">         };
</span><span class="cx"> 
</span><span class="lines">@@ -285,9 +287,6 @@
</span><span class="cx">         void addNormalMatches(const MatchResult&amp;, int startIndex, int endIndex, bool inheritedOnly = false);
</span><span class="cx">         void addImportantMatches(const MatchResult&amp;, int startIndex, int endIndex, bool inheritedOnly = false);
</span><span class="cx"> 
</span><del>-        void set(CSSPropertyID, CSSValue&amp;, unsigned linkMatchType, CascadeLevel);
-        void setDeferred(CSSPropertyID, CSSValue&amp;, unsigned linkMatchType, CascadeLevel);
-
</del><span class="cx">         void applyDeferredProperties(StyleResolver&amp;, const MatchResult*);
</span><span class="cx"> 
</span><span class="cx">         HashMap&lt;AtomicString, Property&gt;&amp; customProperties() { return m_customProperties; }
</span><span class="lines">@@ -296,8 +295,9 @@
</span><span class="cx">         
</span><span class="cx">     private:
</span><span class="cx">         void addMatch(const MatchResult&amp;, unsigned index, bool isImportant, bool inheritedOnly);
</span><del>-        void addStyleProperties(const StyleProperties&amp;, bool isImportant, bool inheritedOnly, PropertyWhitelistType, unsigned linkMatchType, CascadeLevel);
-        static void setPropertyInternal(Property&amp;, CSSPropertyID, CSSValue&amp;, unsigned linkMatchType, CascadeLevel);
</del><ins>+        void set(CSSPropertyID, CSSValue&amp;, unsigned linkMatchType, CascadeLevel, Style::ScopeOrdinal);
+        void setDeferred(CSSPropertyID, CSSValue&amp;, unsigned linkMatchType, CascadeLevel, Style::ScopeOrdinal);
+        static void setPropertyInternal(Property&amp;, CSSPropertyID, CSSValue&amp;, unsigned linkMatchType, CascadeLevel, Style::ScopeOrdinal);
</ins><span class="cx"> 
</span><span class="cx">         Property m_properties[numCSSProperties + 2];
</span><span class="cx">         std::bitset&lt;numCSSProperties + 2&gt; m_propertyIsPresent;
</span><span class="lines">@@ -404,7 +404,9 @@
</span><span class="cx"> 
</span><span class="cx">         CascadeLevel cascadeLevel() const { return m_cascadeLevel; }
</span><span class="cx">         void setCascadeLevel(CascadeLevel level) { m_cascadeLevel = level; }
</span><del>-        
</del><ins>+        Style::ScopeOrdinal styleScopeOrdinal() const { return m_styleScopeOrdinal; }
+        void setStyleScopeOrdinal(Style::ScopeOrdinal styleScopeOrdinal) { m_styleScopeOrdinal = styleScopeOrdinal; }
+
</ins><span class="cx">         CascadedProperties* authorRollback() const { return m_authorRollback.get(); }
</span><span class="cx">         CascadedProperties* userRollback() const { return m_userRollback.get(); }
</span><span class="cx">         
</span><span class="lines">@@ -439,6 +441,7 @@
</span><span class="cx">         CSSToLengthConversionData m_cssToLengthConversionData;
</span><span class="cx">         
</span><span class="cx">         CascadeLevel m_cascadeLevel { UserAgentLevel };
</span><ins>+        Style::ScopeOrdinal m_styleScopeOrdinal { Style::ScopeOrdinal::Element };
</ins><span class="cx">         std::unique_ptr&lt;CascadedProperties&gt; m_authorRollback;
</span><span class="cx">         std::unique_ptr&lt;CascadedProperties&gt; m_userRollback;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorepageanimationKeyframeAnimationcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/animation/KeyframeAnimation.cpp (209351 => 209352)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/animation/KeyframeAnimation.cpp        2016-12-05 22:38:37 UTC (rev 209351)
+++ trunk/Source/WebCore/page/animation/KeyframeAnimation.cpp        2016-12-05 22:42:28 UTC (rev 209352)
</span><span class="lines">@@ -39,6 +39,7 @@
</span><span class="cx"> #include &quot;RenderStyle.h&quot;
</span><span class="cx"> #include &quot;StylePendingResources.h&quot;
</span><span class="cx"> #include &quot;StyleResolver.h&quot;
</span><ins>+#include &quot;StyleScope.h&quot;
</ins><span class="cx"> #include &quot;WillChangeData.h&quot;
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="lines">@@ -363,7 +364,8 @@
</span><span class="cx">         return;
</span><span class="cx">     auto&amp; element = *m_object-&gt;element();
</span><span class="cx"> 
</span><del>-    element.styleResolver().keyframeStylesForAnimation(*m_object-&gt;element(), m_unanimatedStyle.get(), m_keyframes);
</del><ins>+    if (auto* styleScope = Style::Scope::forOrdinal(element, m_animation-&gt;nameStyleScopeOrdinal()))
+        styleScope-&gt;resolver().keyframeStylesForAnimation(*m_object-&gt;element(), m_unanimatedStyle.get(), m_keyframes);
</ins><span class="cx"> 
</span><span class="cx">     // Ensure resource loads for all the frames.
</span><span class="cx">     for (auto&amp; keyframe : m_keyframes.keyframes()) {
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformanimationAnimationcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/animation/Animation.cpp (209351 => 209352)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/animation/Animation.cpp        2016-12-05 22:38:37 UTC (rev 209351)
+++ trunk/Source/WebCore/platform/animation/Animation.cpp        2016-12-05 22:42:28 UTC (rev 209352)
</span><span class="lines">@@ -59,6 +59,7 @@
</span><span class="cx"> Animation::Animation(const Animation&amp; o)
</span><span class="cx">     : RefCounted&lt;Animation&gt;()
</span><span class="cx">     , m_name(o.m_name)
</span><ins>+    , m_nameStyleScopeOrdinal(o.m_nameStyleScopeOrdinal)
</ins><span class="cx">     , m_property(o.m_property)
</span><span class="cx">     , m_mode(o.m_mode)
</span><span class="cx">     , m_iterationCount(o.m_iterationCount)
</span><span class="lines">@@ -90,6 +91,7 @@
</span><span class="cx"> Animation&amp; Animation::operator=(const Animation&amp; o)
</span><span class="cx"> {
</span><span class="cx">     m_name = o.m_name;
</span><ins>+    m_nameStyleScopeOrdinal = o.m_nameStyleScopeOrdinal;
</ins><span class="cx">     m_property = o.m_property;
</span><span class="cx">     m_mode = o.m_mode;
</span><span class="cx">     m_iterationCount = o.m_iterationCount;
</span><span class="lines">@@ -130,6 +132,7 @@
</span><span class="cx"> bool Animation::animationsMatch(const Animation&amp; other, bool matchPlayStates) const
</span><span class="cx"> {
</span><span class="cx">     bool result = m_name == other.m_name
</span><ins>+        &amp;&amp; m_nameStyleScopeOrdinal == other.m_nameStyleScopeOrdinal
</ins><span class="cx">         &amp;&amp; m_property == other.m_property
</span><span class="cx">         &amp;&amp; m_mode == other.m_mode
</span><span class="cx">         &amp;&amp; m_iterationCount == other.m_iterationCount
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformanimationAnimationh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/animation/Animation.h (209351 => 209352)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/animation/Animation.h        2016-12-05 22:38:37 UTC (rev 209351)
+++ trunk/Source/WebCore/platform/animation/Animation.h        2016-12-05 22:42:28 UTC (rev 209352)
</span><span class="lines">@@ -32,6 +32,7 @@
</span><span class="cx"> #endif
</span><span class="cx"> #include &quot;CSSPropertyNames.h&quot;
</span><span class="cx"> #include &quot;RenderStyleConstants.h&quot;
</span><ins>+#include &quot;StyleScope.h&quot;
</ins><span class="cx"> #include &quot;TimingFunction.h&quot;
</span><span class="cx"> #include &lt;wtf/PassRefPtr.h&gt;
</span><span class="cx"> #include &lt;wtf/RefCounted.h&gt;
</span><span class="lines">@@ -135,6 +136,7 @@
</span><span class="cx">     enum { IterationCountInfinite = -1 };
</span><span class="cx">     double iterationCount() const { return m_iterationCount; }
</span><span class="cx">     const String&amp; name() const { return m_name; }
</span><ins>+    Style::ScopeOrdinal nameStyleScopeOrdinal() const { return m_nameStyleScopeOrdinal; }
</ins><span class="cx">     EAnimPlayState playState() const { return static_cast&lt;EAnimPlayState&gt;(m_playState); }
</span><span class="cx">     CSSPropertyID property() const { return m_property; }
</span><span class="cx">     PassRefPtr&lt;TimingFunction&gt; timingFunction() const { return m_timingFunction; }
</span><span class="lines">@@ -148,7 +150,12 @@
</span><span class="cx">     void setDuration(double d) { ASSERT(d &gt;= 0); m_duration = d; m_durationSet = true; }
</span><span class="cx">     void setFillMode(unsigned f) { m_fillMode = f; m_fillModeSet = true; }
</span><span class="cx">     void setIterationCount(double c) { m_iterationCount = c; m_iterationCountSet = true; }
</span><del>-    void setName(const String&amp; n) { m_name = n; m_nameSet = true; }
</del><ins>+    void setName(const String&amp; name, Style::ScopeOrdinal scope = Style::ScopeOrdinal::Element)
+    {
+        m_name = name;
+        m_nameStyleScopeOrdinal = scope;
+        m_nameSet = true;
+    }
</ins><span class="cx">     void setPlayState(EAnimPlayState d) { m_playState = d; m_playStateSet = true; }
</span><span class="cx">     void setProperty(CSSPropertyID t) { m_property = t; m_propertySet = true; }
</span><span class="cx">     void setTimingFunction(PassRefPtr&lt;TimingFunction&gt; f) { m_timingFunction = f; m_timingFunctionSet = true; }
</span><span class="lines">@@ -176,6 +183,7 @@
</span><span class="cx">     Animation(const Animation&amp; o);
</span><span class="cx">     
</span><span class="cx">     String m_name;
</span><ins>+    Style::ScopeOrdinal m_nameStyleScopeOrdinal { Style::ScopeOrdinal::Element };
</ins><span class="cx">     CSSPropertyID m_property;
</span><span class="cx">     AnimationMode m_mode;
</span><span class="cx">     double m_iterationCount;
</span></span></pre></div>
<a id="trunkSourceWebCorestyleStyleScopecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/style/StyleScope.cpp (209351 => 209352)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/style/StyleScope.cpp        2016-12-05 22:38:37 UTC (rev 209351)
+++ trunk/Source/WebCore/style/StyleScope.cpp        2016-12-05 22:42:28 UTC (rev 209352)
</span><span class="lines">@@ -34,6 +34,7 @@
</span><span class="cx"> #include &quot;ExtensionStyleSheets.h&quot;
</span><span class="cx"> #include &quot;HTMLIFrameElement.h&quot;
</span><span class="cx"> #include &quot;HTMLLinkElement.h&quot;
</span><ins>+#include &quot;HTMLSlotElement.h&quot;
</ins><span class="cx"> #include &quot;HTMLStyleElement.h&quot;
</span><span class="cx"> #include &quot;InspectorInstrumentation.h&quot;
</span><span class="cx"> #include &quot;Page.h&quot;
</span><span class="lines">@@ -126,6 +127,35 @@
</span><span class="cx">     return node.document().styleScope();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+Scope* Scope::forOrdinal(Element&amp; element, ScopeOrdinal ordinal)
+{
+    switch (ordinal) {
+    case ScopeOrdinal::Element:
+        return &amp;forNode(element);
+    case ScopeOrdinal::ContainingHost: {
+        auto* containingShadowRoot = element.containingShadowRoot();
+        if (!containingShadowRoot)
+            return nullptr;
+        return &amp;forNode(*containingShadowRoot-&gt;host());
+    }
+    case ScopeOrdinal::Shadow: {
+        auto* shadowRoot = element.shadowRoot();
+        if (!shadowRoot)
+            return nullptr;
+        return &amp;shadowRoot-&gt;styleScope();
+    }
+    default: {
+        ASSERT(ordinal &gt;= ScopeOrdinal::FirstSlot);
+        auto slotIndex = ScopeOrdinal::FirstSlot;
+        for (auto* slot = element.assignedSlot(); slot; slot = slot-&gt;assignedSlot(), ++slotIndex) {
+            if (slotIndex == ordinal)
+                return &amp;forNode(*slot);
+        }
+        return nullptr;
+    }
+    }
+}
+
</ins><span class="cx"> void Scope::setPreferredStylesheetSetName(const String&amp; name)
</span><span class="cx"> {
</span><span class="cx">     if (m_preferredStylesheetSetName == name)
</span></span></pre></div>
<a id="trunkSourceWebCorestyleStyleScopeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/style/StyleScope.h (209351 => 209352)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/style/StyleScope.h        2016-12-05 22:38:37 UTC (rev 209351)
+++ trunk/Source/WebCore/style/StyleScope.h        2016-12-05 22:42:28 UTC (rev 209352)
</span><span class="lines">@@ -40,6 +40,7 @@
</span><span class="cx"> 
</span><span class="cx"> class CSSStyleSheet;
</span><span class="cx"> class Document;
</span><ins>+class Element;
</ins><span class="cx"> class Node;
</span><span class="cx"> class StyleResolver;
</span><span class="cx"> class StyleSheet;
</span><span class="lines">@@ -50,6 +51,15 @@
</span><span class="cx"> 
</span><span class="cx"> namespace Style {
</span><span class="cx"> 
</span><ins>+// This is used to identify style scopes that can affect an element.
+// Scopes are in tree-of-trees order. Styles from earlier scopes win over later ones (modulo !important).
+enum class ScopeOrdinal : int {
+    ContainingHost = -1, // Author-exposed UA pseudo classes from the host tree scope.
+    Element = 0, // Normal rules in the same tree where the element is.
+    FirstSlot = 1, // ::slotted rules in the parent's shadow tree. Values greater than FirstSlot indicate subsequent slots in the chain.
+    Shadow = std::numeric_limits&lt;int&gt;::max(), // :host rules in element's own shadow tree.
+};
+
</ins><span class="cx"> class Scope {
</span><span class="cx">     WTF_MAKE_FAST_ALLOCATED;
</span><span class="cx"> public:
</span><span class="lines">@@ -102,6 +112,7 @@
</span><span class="cx">     const Document&amp; document() const { return m_document; }
</span><span class="cx"> 
</span><span class="cx">     static Scope&amp; forNode(Node&amp;);
</span><ins>+    static Scope* forOrdinal(Element&amp;, ScopeOrdinal);
</ins><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     bool shouldUseSharedUserAgentShadowTreeStyleResolver() const;
</span><span class="lines">@@ -164,5 +175,11 @@
</span><span class="cx">         flushPendingSelfUpdate();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+inline ScopeOrdinal&amp; operator++(ScopeOrdinal&amp; ordinal)
+{
+    ASSERT(ordinal &lt; ScopeOrdinal::Shadow);
+    return ordinal = static_cast&lt;ScopeOrdinal&gt;(static_cast&lt;int&gt;(ordinal) + 1);
</ins><span class="cx"> }
</span><ins>+
</ins><span class="cx"> }
</span><ins>+}
</ins></span></pre>
</div>
</div>

</body>
</html>