<!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>[195293] trunk/Source/WebCore</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/195293">195293</a></dd>
<dt>Author</dt> <dd>antti@apple.com</dd>
<dt>Date</dt> <dd>2016-01-19 09:39:20 -0800 (Tue, 19 Jan 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>Selector checker should not mutate document and style
https://bugs.webkit.org/show_bug.cgi?id=153205

Reviewed by Darin Adler.

Selector checker currently writes affected-by bits and similar directly to the document and style during selector
matching. This is confusing, complicated and wrong.

This patch changes SelectorChecker and SelectorCompiler to collect style relatationship metadata to a separate
data structure (currently part of SelectorChecker::CheckingContext) instead of changing the document and style
directly. The mutations are performed later outside selector checker.

* css/ElementRuleCollector.cpp:
(WebCore::ElementRuleCollector::ruleMatches):
(WebCore::ElementRuleCollector::commitStyleRelations):

    Apply the relationship bit to elements and style.

(WebCore::ElementRuleCollector::collectMatchingRulesForList):
* css/ElementRuleCollector.h:
* css/SelectorChecker.cpp:
(WebCore::SelectorChecker::LocalContext::LocalContext):

    LocalContext is now a separate data structure.

(WebCore::addStyleRelation):

    Helper for recording new style relations. This is used where code mutated elements or style directly before.

(WebCore::isFirstChildElement):
(WebCore::isLastChildElement):
(WebCore::isFirstOfType):
(WebCore::isLastOfType):
(WebCore::countElementsBefore):
(WebCore::countElementsOfTypeBefore):
(WebCore::SelectorChecker::SelectorChecker):
(WebCore::SelectorChecker::match):
(WebCore::hasScrollbarPseudoElement):
(WebCore::localContextForParent):
(WebCore::SelectorChecker::matchRecursively):
(WebCore::attributeValueMatches):
(WebCore::anyAttributeMatches):
(WebCore::canMatchHoverOrActiveInQuirksMode):
(WebCore::tagMatches):
(WebCore::SelectorChecker::checkOne):
(WebCore::SelectorChecker::matchSelectorList):
(WebCore::SelectorChecker::checkScrollbarPseudoClass):
(WebCore::SelectorChecker::CheckingContextWithStatus::CheckingContextWithStatus): Deleted.
(WebCore::checkingContextForParent): Deleted.
* css/SelectorChecker.h:
(WebCore::SelectorChecker::CheckingContext::CheckingContext):
* css/SelectorCheckerTestFunctions.h:
(WebCore::isEnabled):
(WebCore::isMediaDocument):
(WebCore::isChecked):
(WebCore::isInRange):
(WebCore::isOutOfRange):
* css/StyleResolver.h:
(WebCore::checkRegionSelector):
* cssjit/SelectorCompiler.cpp:
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateAddStyleRelationIfResolvingStyle):
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateAddStyleRelation):

    Helpers for generating code for recording new style relations. This is used where code mutated elements or style directly before.

(WebCore::SelectorCompiler::SelectorCodeGenerator::generateSelectorCheckerExcludingPseudoElements):
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateDirectAdjacentTreeWalker):
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateIndirectAdjacentTreeWalker):
(WebCore::SelectorCompiler::addStyleRelationElementFunction):
(WebCore::SelectorCompiler::SelectorCodeGenerator::jumpIfNoPreviousAdjacentElement):
(WebCore::SelectorCompiler::SelectorCodeGenerator::moduloIsZero):
(WebCore::SelectorCompiler::SelectorCodeGenerator::linkFailures):
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementMatching):
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateContextFunctionCallTest):
(WebCore::SelectorCompiler::elementIsActive):
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementIsActive):
(WebCore::SelectorCompiler::jumpIfElementIsNotEmpty):
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementIsEmpty):
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementIsFirstChild):
(WebCore::SelectorCompiler::elementIsHovered):
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementIsHovered):
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementIsInLanguage):
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementIsLastChild):
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementIsOnlyChild):
(WebCore::SelectorCompiler::makeContextStyleUniqueIfNecessaryAndTestIsPlaceholderShown):
(WebCore::SelectorCompiler::isPlaceholderShown):
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementHasPlaceholderShown):
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementIsLink):
(WebCore::SelectorCompiler::nthFilterIsAlwaysSatisified):
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementIsNthChild):
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementIsNthChildOf):
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementIsNthLastChild):
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementIsNthLastChildOf):
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateMarkPseudoStyleForPseudoElement):
(WebCore::SelectorCompiler::SelectorCodeGenerator::addFlagsToElementStyleFromContext): Deleted.
(WebCore::SelectorCompiler::setNodeFlag): Deleted.
(WebCore::SelectorCompiler::SelectorCodeGenerator::markElementIfResolvingStyle): Deleted.
(WebCore::SelectorCompiler::setFirstChildState): Deleted.
(WebCore::SelectorCompiler::elementIsActiveForStyleResolution): Deleted.
(WebCore::SelectorCompiler::setElementStyleIsAffectedByEmpty): Deleted.
(WebCore::SelectorCompiler::setElementStyleFromContextIsAffectedByEmptyAndUpdateRenderStyleIfNecessary): Deleted.
(WebCore::SelectorCompiler::elementIsHoveredForStyleResolution): Deleted.
(WebCore::SelectorCompiler::setLastChildState): Deleted.
(WebCore::SelectorCompiler::setOnlyChildState): Deleted.
(WebCore::SelectorCompiler::makeElementStyleUniqueIfNecessaryAndTestIsPlaceholderShown): Deleted.
(WebCore::SelectorCompiler::setElementChildIndex): Deleted.
(WebCore::SelectorCompiler::setChildrenAffectedByBackwardPositionalRules): Deleted.
(WebCore::SelectorCompiler::setParentAffectedByLastChildOf): Deleted.
* dom/SelectorQuery.cpp:
(WebCore::SelectorDataList::selectorMatches):
(WebCore::SelectorDataList::selectorClosest):
(WebCore::SelectorDataList::matches):
* inspector/InspectorCSSAgent.cpp:
(WebCore::InspectorCSSAgent::buildArrayForMatchedRuleList):
* inspector/InspectorStyleSheet.cpp:
(WebCore::buildObjectForSelectorHelper):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</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="#trunkSourceWebCorecssSelectorCheckercpp">trunk/Source/WebCore/css/SelectorChecker.cpp</a></li>
<li><a href="#trunkSourceWebCorecssSelectorCheckerh">trunk/Source/WebCore/css/SelectorChecker.h</a></li>
<li><a href="#trunkSourceWebCorecssSelectorCheckerTestFunctionsh">trunk/Source/WebCore/css/SelectorCheckerTestFunctions.h</a></li>
<li><a href="#trunkSourceWebCorecssStyleResolverh">trunk/Source/WebCore/css/StyleResolver.h</a></li>
<li><a href="#trunkSourceWebCorecssjitSelectorCompilercpp">trunk/Source/WebCore/cssjit/SelectorCompiler.cpp</a></li>
<li><a href="#trunkSourceWebCoredomSelectorQuerycpp">trunk/Source/WebCore/dom/SelectorQuery.cpp</a></li>
<li><a href="#trunkSourceWebCoreinspectorInspectorCSSAgentcpp">trunk/Source/WebCore/inspector/InspectorCSSAgent.cpp</a></li>
<li><a href="#trunkSourceWebCoreinspectorInspectorStyleSheetcpp">trunk/Source/WebCore/inspector/InspectorStyleSheet.cpp</a></li>
<li><a href="#trunkSourceWebCorerenderingstyleRenderStyleConstantsh">trunk/Source/WebCore/rendering/style/RenderStyleConstants.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (195292 => 195293)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-01-19 17:20:59 UTC (rev 195292)
+++ trunk/Source/WebCore/ChangeLog        2016-01-19 17:39:20 UTC (rev 195293)
</span><span class="lines">@@ -1,3 +1,122 @@
</span><ins>+2016-01-18  Antti Koivisto  &lt;antti@apple.com&gt;
+
+        Selector checker should not mutate document and style
+        https://bugs.webkit.org/show_bug.cgi?id=153205
+
+        Reviewed by Darin Adler.
+
+        Selector checker currently writes affected-by bits and similar directly to the document and style during selector
+        matching. This is confusing, complicated and wrong.
+
+        This patch changes SelectorChecker and SelectorCompiler to collect style relatationship metadata to a separate
+        data structure (currently part of SelectorChecker::CheckingContext) instead of changing the document and style
+        directly. The mutations are performed later outside selector checker.
+
+        * css/ElementRuleCollector.cpp:
+        (WebCore::ElementRuleCollector::ruleMatches):
+        (WebCore::ElementRuleCollector::commitStyleRelations):
+
+            Apply the relationship bit to elements and style.
+
+        (WebCore::ElementRuleCollector::collectMatchingRulesForList):
+        * css/ElementRuleCollector.h:
+        * css/SelectorChecker.cpp:
+        (WebCore::SelectorChecker::LocalContext::LocalContext):
+
+            LocalContext is now a separate data structure.
+
+        (WebCore::addStyleRelation):
+
+            Helper for recording new style relations. This is used where code mutated elements or style directly before.
+
+        (WebCore::isFirstChildElement):
+        (WebCore::isLastChildElement):
+        (WebCore::isFirstOfType):
+        (WebCore::isLastOfType):
+        (WebCore::countElementsBefore):
+        (WebCore::countElementsOfTypeBefore):
+        (WebCore::SelectorChecker::SelectorChecker):
+        (WebCore::SelectorChecker::match):
+        (WebCore::hasScrollbarPseudoElement):
+        (WebCore::localContextForParent):
+        (WebCore::SelectorChecker::matchRecursively):
+        (WebCore::attributeValueMatches):
+        (WebCore::anyAttributeMatches):
+        (WebCore::canMatchHoverOrActiveInQuirksMode):
+        (WebCore::tagMatches):
+        (WebCore::SelectorChecker::checkOne):
+        (WebCore::SelectorChecker::matchSelectorList):
+        (WebCore::SelectorChecker::checkScrollbarPseudoClass):
+        (WebCore::SelectorChecker::CheckingContextWithStatus::CheckingContextWithStatus): Deleted.
+        (WebCore::checkingContextForParent): Deleted.
+        * css/SelectorChecker.h:
+        (WebCore::SelectorChecker::CheckingContext::CheckingContext):
+        * css/SelectorCheckerTestFunctions.h:
+        (WebCore::isEnabled):
+        (WebCore::isMediaDocument):
+        (WebCore::isChecked):
+        (WebCore::isInRange):
+        (WebCore::isOutOfRange):
+        * css/StyleResolver.h:
+        (WebCore::checkRegionSelector):
+        * cssjit/SelectorCompiler.cpp:
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateAddStyleRelationIfResolvingStyle):
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateAddStyleRelation):
+
+            Helpers for generating code for recording new style relations. This is used where code mutated elements or style directly before.
+
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateSelectorCheckerExcludingPseudoElements):
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateDirectAdjacentTreeWalker):
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateIndirectAdjacentTreeWalker):
+        (WebCore::SelectorCompiler::addStyleRelationElementFunction):
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::jumpIfNoPreviousAdjacentElement):
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::moduloIsZero):
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::linkFailures):
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementMatching):
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateContextFunctionCallTest):
+        (WebCore::SelectorCompiler::elementIsActive):
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementIsActive):
+        (WebCore::SelectorCompiler::jumpIfElementIsNotEmpty):
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementIsEmpty):
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementIsFirstChild):
+        (WebCore::SelectorCompiler::elementIsHovered):
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementIsHovered):
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementIsInLanguage):
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementIsLastChild):
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementIsOnlyChild):
+        (WebCore::SelectorCompiler::makeContextStyleUniqueIfNecessaryAndTestIsPlaceholderShown):
+        (WebCore::SelectorCompiler::isPlaceholderShown):
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementHasPlaceholderShown):
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementIsLink):
+        (WebCore::SelectorCompiler::nthFilterIsAlwaysSatisified):
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementIsNthChild):
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementIsNthChildOf):
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementIsNthLastChild):
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementIsNthLastChildOf):
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateMarkPseudoStyleForPseudoElement):
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::addFlagsToElementStyleFromContext): Deleted.
+        (WebCore::SelectorCompiler::setNodeFlag): Deleted.
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::markElementIfResolvingStyle): Deleted.
+        (WebCore::SelectorCompiler::setFirstChildState): Deleted.
+        (WebCore::SelectorCompiler::elementIsActiveForStyleResolution): Deleted.
+        (WebCore::SelectorCompiler::setElementStyleIsAffectedByEmpty): Deleted.
+        (WebCore::SelectorCompiler::setElementStyleFromContextIsAffectedByEmptyAndUpdateRenderStyleIfNecessary): Deleted.
+        (WebCore::SelectorCompiler::elementIsHoveredForStyleResolution): Deleted.
+        (WebCore::SelectorCompiler::setLastChildState): Deleted.
+        (WebCore::SelectorCompiler::setOnlyChildState): Deleted.
+        (WebCore::SelectorCompiler::makeElementStyleUniqueIfNecessaryAndTestIsPlaceholderShown): Deleted.
+        (WebCore::SelectorCompiler::setElementChildIndex): Deleted.
+        (WebCore::SelectorCompiler::setChildrenAffectedByBackwardPositionalRules): Deleted.
+        (WebCore::SelectorCompiler::setParentAffectedByLastChildOf): Deleted.
+        * dom/SelectorQuery.cpp:
+        (WebCore::SelectorDataList::selectorMatches):
+        (WebCore::SelectorDataList::selectorClosest):
+        (WebCore::SelectorDataList::matches):
+        * inspector/InspectorCSSAgent.cpp:
+        (WebCore::InspectorCSSAgent::buildArrayForMatchedRuleList):
+        * inspector/InspectorStyleSheet.cpp:
+        (WebCore::buildObjectForSelectorHelper):
+
</ins><span class="cx"> 2016-01-19  Carlos Garcia Campos  &lt;cgarcia@igalia.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Unreviewed. Fix GTK+ build with GTK+ &lt; 3.14.
</span></span></pre></div>
<a id="trunkSourceWebCorecssElementRuleCollectorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/css/ElementRuleCollector.cpp (195292 => 195293)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/css/ElementRuleCollector.cpp        2016-01-19 17:20:59 UTC (rev 195292)
+++ trunk/Source/WebCore/css/ElementRuleCollector.cpp        2016-01-19 17:39:20 UTC (rev 195293)
</span><span class="lines">@@ -37,6 +37,7 @@
</span><span class="cx"> #include &quot;CSSValueKeywords.h&quot;
</span><span class="cx"> #include &quot;HTMLElement.h&quot;
</span><span class="cx"> #include &quot;InspectorInstrumentation.h&quot;
</span><ins>+#include &quot;NodeRenderStyle.h&quot;
</ins><span class="cx"> #include &quot;RenderRegion.h&quot;
</span><span class="cx"> #include &quot;SVGElement.h&quot;
</span><span class="cx"> #include &quot;SelectorCompiler.h&quot;
</span><span class="lines">@@ -328,11 +329,11 @@
</span><span class="cx"> #endif // ENABLE(CSS_SELECTOR_JIT)
</span><span class="cx"> 
</span><span class="cx">     SelectorChecker::CheckingContext context(m_mode);
</span><del>-    context.elementStyle = m_style;
</del><span class="cx">     context.pseudoId = m_pseudoStyleRequest.pseudoId;
</span><span class="cx">     context.scrollbar = m_pseudoStyleRequest.scrollbar;
</span><span class="cx">     context.scrollbarPart = m_pseudoStyleRequest.scrollbarPart;
</span><span class="cx"> 
</span><ins>+    bool selectorMatches;
</ins><span class="cx"> #if ENABLE(CSS_SELECTOR_JIT)
</span><span class="cx">     if (compiledSelectorChecker) {
</span><span class="cx">         ASSERT(ruleData.compilationStatus() == SelectorCompilationStatus::SelectorCheckerWithCheckingContext);
</span><span class="lines">@@ -342,15 +343,95 @@
</span><span class="cx"> #if CSS_SELECTOR_JIT_PROFILING
</span><span class="cx">         ruleData.compiledSelectorUsed();
</span><span class="cx"> #endif
</span><del>-        return selectorChecker(&amp;m_element, &amp;context, &amp;specificity);
</del><ins>+        selectorMatches = selectorChecker(&amp;m_element, &amp;context, &amp;specificity);
+    } else
+#endif // ENABLE(CSS_SELECTOR_JIT)
+    {
+        // Slow path.
+        SelectorChecker selectorChecker(m_element.document());
+        selectorMatches = selectorChecker.match(*ruleData.selector(), m_element, context, specificity);
</ins><span class="cx">     }
</span><del>-#endif // ENABLE(CSS_SELECTOR_JIT)
</del><span class="cx"> 
</span><del>-    // Slow path.
-    SelectorChecker selectorChecker(m_element.document());
-    return selectorChecker.match(ruleData.selector(), &amp;m_element, context, specificity);
</del><ins>+    commitStyleRelations(context.styleRelations);
+
+    if (context.pseudoIDSet)
+        m_style-&gt;setHasPseudoStyles(context.pseudoIDSet);
+
+    return selectorMatches;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+// FIXME: Rule collector should not be doing mutations. Move this somewhere else.
+void ElementRuleCollector::commitStyleRelations(const SelectorChecker::StyleRelations&amp; styleRelations)
+{
+    for (auto&amp; relation : styleRelations) {
+        switch (relation.type) {
+        case SelectorChecker::StyleRelation::AffectedByActive:
+            if (&amp;relation.element == &amp;m_element)
+                m_style-&gt;setAffectedByActive();
+            else
+                relation.element.setChildrenAffectedByActive();
+            break;
+        case SelectorChecker::StyleRelation::AffectedByDrag:
+            if (&amp;relation.element == &amp;m_element)
+                m_style-&gt;setAffectedByDrag();
+            else
+                relation.element.setChildrenAffectedByDrag();
+            break;
+        case SelectorChecker::StyleRelation::AffectedByEmpty:
+            relation.element.setStyleAffectedByEmpty();
+            if (&amp;relation.element == &amp;m_element)
+                m_style-&gt;setEmptyState(relation.value);
+            break;
+        case SelectorChecker::StyleRelation::AffectedByHover:
+            if (&amp;relation.element == &amp;m_element)
+                m_style-&gt;setAffectedByHover();
+            else
+                relation.element.setChildrenAffectedByHover();
+            break;
+        case SelectorChecker::StyleRelation::AffectedByPreviousSibling:
+            relation.element.setStyleIsAffectedByPreviousSibling();
+            break;
+        case SelectorChecker::StyleRelation::AffectsNextSibling:
+            relation.element.setAffectsNextSiblingElementStyle();
+            break;
+        case SelectorChecker::StyleRelation::ChildrenAffectedByBackwardPositionalRules:
+            relation.element.setChildrenAffectedByBackwardPositionalRules();
+            break;
+        case SelectorChecker::StyleRelation::ChildrenAffectedByFirstChildRules:
+            relation.element.setChildrenAffectedByFirstChildRules();
+            break;
+        case SelectorChecker::StyleRelation::ChildrenAffectedByPropertyBasedBackwardPositionalRules:
+            relation.element.setChildrenAffectedByBackwardPositionalRules();
+            relation.element.setChildrenAffectedByPropertyBasedBackwardPositionalRules();
+            break;
+        case SelectorChecker::StyleRelation::ChildrenAffectedByLastChildRules:
+            relation.element.setChildrenAffectedByLastChildRules();
+            break;
+        case SelectorChecker::StyleRelation::FirstChild:
+            if (&amp;relation.element == &amp;m_element)
+                m_style-&gt;setFirstChildState();
+            else if (auto* style = relation.element.renderStyle())
+                style-&gt;setFirstChildState();
+            break;
+        case SelectorChecker::StyleRelation::LastChild:
+            if (&amp;relation.element == &amp;m_element)
+                m_style-&gt;setLastChildState();
+            else if (auto* style = relation.element.renderStyle())
+                style-&gt;setLastChildState();
+            break;
+        case SelectorChecker::StyleRelation::NthChildIndex:
+            relation.element.setChildIndex(relation.value);
+            break;
+        case SelectorChecker::StyleRelation::Unique:
+            if (&amp;relation.element == &amp;m_element)
+                m_style-&gt;setUnique();
+            else if (auto* style = relation.element.renderStyle())
+                style-&gt;setUnique();
+            break;
+        }
+    }
+}
+
</ins><span class="cx"> void ElementRuleCollector::collectMatchingRulesForList(const RuleSet::RuleDataVector* rules, const MatchRequest&amp; matchRequest, StyleResolver::RuleRange&amp; ruleRange)
</span><span class="cx"> {
</span><span class="cx">     if (!rules)
</span></span></pre></div>
<a id="trunkSourceWebCorecssElementRuleCollectorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/css/ElementRuleCollector.h (195292 => 195293)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/css/ElementRuleCollector.h        2016-01-19 17:20:59 UTC (rev 195292)
+++ trunk/Source/WebCore/css/ElementRuleCollector.h        2016-01-19 17:39:20 UTC (rev 195293)
</span><span class="lines">@@ -84,6 +84,8 @@
</span><span class="cx"> 
</span><span class="cx">     void addMatchedRule(const MatchedRule&amp;);
</span><span class="cx"> 
</span><ins>+    void commitStyleRelations(const SelectorChecker::StyleRelations&amp;);
+
</ins><span class="cx">     Element&amp; m_element;
</span><span class="cx">     RenderStyle* m_style;
</span><span class="cx">     const DocumentRuleSets&amp; m_ruleSets;
</span></span></pre></div>
<a id="trunkSourceWebCorecssSelectorCheckercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/css/SelectorChecker.cpp (195292 => 195293)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/css/SelectorChecker.cpp        2016-01-19 17:20:59 UTC (rev 195292)
+++ trunk/Source/WebCore/css/SelectorChecker.cpp        2016-01-19 17:39:20 UTC (rev 195293)
</span><span class="lines">@@ -2,7 +2,7 @@
</span><span class="cx">  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
</span><span class="cx">  *           (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com)
</span><span class="cx">  * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com)
</span><del>- * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2005-2016 Apple Inc. All rights reserved.
</ins><span class="cx">  * Copyright (C) 2007 Alexey Proskuryakov &lt;ap@webkit.org&gt;
</span><span class="cx">  * Copyright (C) 2007, 2008 Eric Seidel &lt;eric@webkit.org&gt;
</span><span class="cx">  * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
</span><span class="lines">@@ -46,10 +46,8 @@
</span><span class="cx"> #include &quot;HTMLProgressElement.h&quot;
</span><span class="cx"> #include &quot;HTMLStyleElement.h&quot;
</span><span class="cx"> #include &quot;InspectorInstrumentation.h&quot;
</span><del>-#include &quot;NodeRenderStyle.h&quot;
</del><span class="cx"> #include &quot;Page.h&quot;
</span><span class="cx"> #include &quot;RenderElement.h&quot;
</span><del>-#include &quot;RenderStyle.h&quot;
</del><span class="cx"> #include &quot;SelectorCheckerTestFunctions.h&quot;
</span><span class="cx"> #include &quot;ShadowRoot.h&quot;
</span><span class="cx"> #include &quot;StyledElement.h&quot;
</span><span class="lines">@@ -63,29 +61,36 @@
</span><span class="cx">     Disabled, Enabled
</span><span class="cx"> };
</span><span class="cx"> 
</span><del>-struct SelectorChecker::CheckingContextWithStatus : public SelectorChecker::CheckingContext {
-    CheckingContextWithStatus(const SelectorChecker::CheckingContext&amp; checkingContext, const CSSSelector* selector, Element* element)
-        : SelectorChecker::CheckingContext(checkingContext)
-        , selector(selector)
-        , element(element)
-        , visitedMatchType(resolvingMode == SelectorChecker::Mode::QueryingRules ? VisitedMatchType::Disabled : VisitedMatchType::Enabled)
-        , firstSelectorOfTheFragment(selector)
-        , inFunctionalPseudoClass(false)
-        , pseudoElementEffective(true)
-        , hasScrollbarPseudo(false)
-        , hasSelectionPseudo(false)
</del><ins>+struct SelectorChecker::LocalContext {
+    LocalContext(const CSSSelector&amp; selector, const Element&amp; element, VisitedMatchType visitedMatchType, PseudoId pseudoId)
+        : selector(&amp;selector)
+        , element(&amp;element)
+        , visitedMatchType(visitedMatchType)
+        , firstSelectorOfTheFragment(&amp;selector)
+        , pseudoId(pseudoId)
</ins><span class="cx">     { }
</span><span class="cx"> 
</span><span class="cx">     const CSSSelector* selector;
</span><del>-    Element* element;
</del><ins>+    const Element* element;
</ins><span class="cx">     VisitedMatchType visitedMatchType;
</span><span class="cx">     const CSSSelector* firstSelectorOfTheFragment;
</span><del>-    bool inFunctionalPseudoClass;
-    bool pseudoElementEffective;
-    bool hasScrollbarPseudo;
-    bool hasSelectionPseudo;
</del><ins>+    PseudoId pseudoId;
+    bool isMatchElement { true };
+    bool inFunctionalPseudoClass { false };
+    bool pseudoElementEffective { true };
+    bool hasScrollbarPseudo { false };
+    bool hasSelectionPseudo { false };
+
</ins><span class="cx"> };
</span><span class="cx"> 
</span><ins>+static inline void addStyleRelation(SelectorChecker::CheckingContext&amp; checkingContext, const Element&amp; element, SelectorChecker::StyleRelation::Type type, unsigned value = 1)
+{
+    ASSERT(value == 1 || type == SelectorChecker::StyleRelation::NthChildIndex || type == SelectorChecker::StyleRelation::AffectedByEmpty);
+    if (checkingContext.resolvingMode != SelectorChecker::Mode::ResolvingStyle)
+        return;
+    checkingContext.styleRelations.append({ const_cast&lt;Element&amp;&gt;(element), type, value });
+}
+
</ins><span class="cx"> static inline bool isFirstChildElement(const Element&amp; element)
</span><span class="cx"> {
</span><span class="cx">     return !ElementTraversal::previousSibling(element);
</span><span class="lines">@@ -96,11 +101,11 @@
</span><span class="cx">     return !ElementTraversal::nextSibling(element);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static inline bool isFirstOfType(Element&amp; element, const QualifiedName&amp; type, bool isResolvingStyle)
</del><ins>+static inline bool isFirstOfType(SelectorChecker::CheckingContext&amp; checkingContext, const Element&amp; element, const QualifiedName&amp; type)
</ins><span class="cx"> {
</span><del>-    for (Element* sibling = ElementTraversal::previousSibling(element); sibling; sibling = ElementTraversal::previousSibling(*sibling)) {
-        if (isResolvingStyle)
-            sibling-&gt;setAffectsNextSiblingElementStyle();
</del><ins>+    for (const Element* sibling = ElementTraversal::previousSibling(element); sibling; sibling = ElementTraversal::previousSibling(*sibling)) {
+        addStyleRelation(checkingContext, *sibling, SelectorChecker::StyleRelation::AffectsNextSibling);
+
</ins><span class="cx">         if (sibling-&gt;hasTagName(type))
</span><span class="cx">             return false;
</span><span class="cx">     }
</span><span class="lines">@@ -116,13 +121,13 @@
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static inline int countElementsBefore(Element&amp; element, bool isResolvingStyle)
</del><ins>+static inline int countElementsBefore(SelectorChecker::CheckingContext&amp; checkingContext, const Element&amp; element)
</ins><span class="cx"> {
</span><span class="cx">     int count = 0;
</span><del>-    for (Element* sibling = ElementTraversal::previousSibling(element); sibling; sibling = ElementTraversal::previousSibling(*sibling)) {
-        if (isResolvingStyle)
-            sibling-&gt;setAffectsNextSiblingElementStyle();
</del><ins>+    for (const Element* sibling = ElementTraversal::previousSibling(element); sibling; sibling = ElementTraversal::previousSibling(*sibling)) {
</ins><span class="cx"> 
</span><ins>+        addStyleRelation(checkingContext, *sibling, SelectorChecker::StyleRelation::AffectsNextSibling);
+
</ins><span class="cx">         unsigned index = sibling-&gt;childIndex();
</span><span class="cx">         if (index) {
</span><span class="cx">             count += index;
</span><span class="lines">@@ -133,12 +138,11 @@
</span><span class="cx">     return count;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static inline int countElementsOfTypeBefore(Element&amp; element, const QualifiedName&amp; type, bool isResolvingStyle)
</del><ins>+static inline int countElementsOfTypeBefore(SelectorChecker::CheckingContext&amp; checkingContext, const Element&amp; element, const QualifiedName&amp; type)
</ins><span class="cx"> {
</span><span class="cx">     int count = 0;
</span><del>-    for (Element* sibling = ElementTraversal::previousSibling(element); sibling; sibling = ElementTraversal::previousSibling(*sibling)) {
-        if (isResolvingStyle)
-            sibling-&gt;setAffectsNextSiblingElementStyle();
</del><ins>+    for (const Element* sibling = ElementTraversal::previousSibling(element); sibling; sibling = ElementTraversal::previousSibling(*sibling)) {
+        addStyleRelation(checkingContext, *sibling, SelectorChecker::StyleRelation::AffectsNextSibling);
</ins><span class="cx"> 
</span><span class="cx">         if (sibling-&gt;hasTagName(type))
</span><span class="cx">             ++count;
</span><span class="lines">@@ -170,26 +174,26 @@
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool SelectorChecker::match(const CSSSelector* selector, Element* element, const CheckingContext&amp; providedContext, unsigned&amp; specificity) const
</del><ins>+bool SelectorChecker::match(const CSSSelector&amp; selector, const Element&amp; element, CheckingContext&amp; checkingContext, unsigned&amp; specificity) const
</ins><span class="cx"> {
</span><span class="cx">     specificity = 0;
</span><span class="cx"> 
</span><del>-    CheckingContextWithStatus context(providedContext, selector, element);
</del><ins>+    LocalContext context(selector, element, checkingContext.resolvingMode == SelectorChecker::Mode::QueryingRules ? VisitedMatchType::Disabled : VisitedMatchType::Enabled, checkingContext.pseudoId);
</ins><span class="cx">     PseudoIdSet pseudoIdSet;
</span><del>-    MatchResult result = matchRecursively(context, pseudoIdSet, specificity);
</del><ins>+    MatchResult result = matchRecursively(checkingContext, context, pseudoIdSet, specificity);
</ins><span class="cx">     if (result.match != Match::SelectorMatches)
</span><span class="cx">         return false;
</span><del>-    if (context.pseudoId != NOPSEUDO &amp;&amp; !pseudoIdSet.has(context.pseudoId))
</del><ins>+    if (checkingContext.pseudoId != NOPSEUDO &amp;&amp; !pseudoIdSet.has(checkingContext.pseudoId))
</ins><span class="cx">         return false;
</span><span class="cx"> 
</span><del>-    if (context.pseudoId == NOPSEUDO &amp;&amp; pseudoIdSet) {
</del><ins>+    if (checkingContext.pseudoId == NOPSEUDO &amp;&amp; pseudoIdSet) {
</ins><span class="cx">         PseudoIdSet publicPseudoIdSet = pseudoIdSet &amp; PseudoIdSet::fromMask(PUBLIC_PSEUDOID_MASK);
</span><del>-        if (context.resolvingMode == Mode::ResolvingStyle &amp;&amp; publicPseudoIdSet)
-            context.elementStyle-&gt;setHasPseudoStyles(publicPseudoIdSet);
</del><ins>+        if (checkingContext.resolvingMode == Mode::ResolvingStyle &amp;&amp; publicPseudoIdSet)
+            checkingContext.pseudoIDSet = publicPseudoIdSet;
</ins><span class="cx"> 
</span><span class="cx">         // When ignoring virtual pseudo elements, the context's pseudo should also be NOPSEUDO but that does
</span><span class="cx">         // not cause a failure.
</span><del>-        return context.resolvingMode == Mode::CollectingRulesIgnoringVirtualPseudoElements || result.matchType == MatchType::Element;
</del><ins>+        return checkingContext.resolvingMode == Mode::CollectingRulesIgnoringVirtualPseudoElements || result.matchType == MatchType::Element;
</ins><span class="cx">     }
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="lines">@@ -205,13 +209,14 @@
</span><span class="cx">     return dynamicPseudoIdSet.has(RESIZER);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static SelectorChecker::CheckingContextWithStatus checkingContextForParent(const SelectorChecker::CheckingContextWithStatus&amp; context)
</del><ins>+static SelectorChecker::LocalContext localContextForParent(const SelectorChecker::LocalContext&amp; context)
</ins><span class="cx"> {
</span><del>-    SelectorChecker::CheckingContextWithStatus updatedContext(context);
</del><ins>+    SelectorChecker::LocalContext updatedContext(context);
</ins><span class="cx">     // Disable :visited matching when we see the first link.
</span><span class="cx">     if (context.element-&gt;isLink())
</span><span class="cx">         updatedContext.visitedMatchType = VisitedMatchType::Disabled;
</span><span class="cx">     updatedContext.element = context.element-&gt;parentElement();
</span><ins>+    updatedContext.isMatchElement = false;
</ins><span class="cx">     return updatedContext;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -221,12 +226,12 @@
</span><span class="cx"> // * SelectorFailsLocally     - the selector fails for the element e
</span><span class="cx"> // * SelectorFailsAllSiblings - the selector fails for e and any sibling of e
</span><span class="cx"> // * SelectorFailsCompletely  - the selector fails for e and any sibling or ancestor of e
</span><del>-SelectorChecker::MatchResult SelectorChecker::matchRecursively(const CheckingContextWithStatus&amp; context, PseudoIdSet&amp; dynamicPseudoIdSet, unsigned&amp; specificity) const
</del><ins>+SelectorChecker::MatchResult SelectorChecker::matchRecursively(CheckingContext&amp; checkingContext, const LocalContext&amp; context, PseudoIdSet&amp; dynamicPseudoIdSet, unsigned&amp; specificity) const
</ins><span class="cx"> {
</span><span class="cx">     MatchType matchType = MatchType::Element;
</span><span class="cx"> 
</span><span class="cx">     // The first selector has to match.
</span><del>-    if (!checkOne(context, dynamicPseudoIdSet, matchType, specificity))
</del><ins>+    if (!checkOne(checkingContext, context, dynamicPseudoIdSet, matchType, specificity))
</ins><span class="cx">         return MatchResult::fails(Match::SelectorFailsLocally);
</span><span class="cx"> 
</span><span class="cx">     if (context.selector-&gt;match() == CSSSelector::PseudoElement) {
</span><span class="lines">@@ -247,7 +252,7 @@
</span><span class="cx">             if (!context.pseudoElementEffective)
</span><span class="cx">                 return MatchResult::fails(Match::SelectorFailsCompletely);
</span><span class="cx"> 
</span><del>-            if (context.resolvingMode == Mode::QueryingRules)
</del><ins>+            if (checkingContext.resolvingMode == Mode::QueryingRules)
</ins><span class="cx">                 return MatchResult::fails(Match::SelectorFailsCompletely);
</span><span class="cx"> 
</span><span class="cx">             PseudoId pseudoId = CSSSelector::pseudoId(context.selector-&gt;pseudoElementType());
</span><span class="lines">@@ -265,7 +270,7 @@
</span><span class="cx">     if (!historySelector)
</span><span class="cx">         return MatchResult::matches(matchType);
</span><span class="cx"> 
</span><del>-    CheckingContextWithStatus nextContext(context);
</del><ins>+    LocalContext nextContext(context);
</ins><span class="cx">     nextContext.selector = historySelector;
</span><span class="cx"> 
</span><span class="cx">     if (relation != CSSSelector::SubSelector) {
</span><span class="lines">@@ -280,17 +285,17 @@
</span><span class="cx">         nextContext.pseudoId = NOPSEUDO;
</span><span class="cx">         // Virtual pseudo element is only effective in the rightmost fragment.
</span><span class="cx">         nextContext.pseudoElementEffective = false;
</span><ins>+        nextContext.isMatchElement = false;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     switch (relation) {
</span><span class="cx">     case CSSSelector::Descendant:
</span><del>-        nextContext = checkingContextForParent(nextContext);
</del><ins>+        nextContext = localContextForParent(nextContext);
</ins><span class="cx">         nextContext.firstSelectorOfTheFragment = nextContext.selector;
</span><del>-        nextContext.elementStyle = nullptr;
-        for (; nextContext.element; nextContext = checkingContextForParent(nextContext)) {
</del><ins>+        for (; nextContext.element; nextContext = localContextForParent(nextContext)) {
</ins><span class="cx">             PseudoIdSet ignoreDynamicPseudo;
</span><span class="cx">             unsigned descendantsSpecificity = 0;
</span><del>-            MatchResult result = matchRecursively(nextContext, ignoreDynamicPseudo, descendantsSpecificity);
</del><ins>+            MatchResult result = matchRecursively(checkingContext, nextContext, ignoreDynamicPseudo, descendantsSpecificity);
</ins><span class="cx">             ASSERT(!nextContext.pseudoElementEffective &amp;&amp; !ignoreDynamicPseudo);
</span><span class="cx"> 
</span><span class="cx">             if (result.match == Match::SelectorMatches)
</span><span class="lines">@@ -303,14 +308,13 @@
</span><span class="cx"> 
</span><span class="cx">     case CSSSelector::Child:
</span><span class="cx">         {
</span><del>-            nextContext = checkingContextForParent(nextContext);
</del><ins>+            nextContext = localContextForParent(nextContext);
</ins><span class="cx">             if (!nextContext.element)
</span><span class="cx">                 return MatchResult::fails(Match::SelectorFailsCompletely);
</span><span class="cx">             nextContext.firstSelectorOfTheFragment = nextContext.selector;
</span><del>-            nextContext.elementStyle = nullptr;
</del><span class="cx">             PseudoIdSet ignoreDynamicPseudo;
</span><span class="cx">             unsigned childSpecificity = 0;
</span><del>-            MatchResult result = matchRecursively(nextContext, ignoreDynamicPseudo, childSpecificity);
</del><ins>+            MatchResult result = matchRecursively(checkingContext, nextContext, ignoreDynamicPseudo, childSpecificity);
</ins><span class="cx">             ASSERT(!nextContext.pseudoElementEffective &amp;&amp; !ignoreDynamicPseudo);
</span><span class="cx"> 
</span><span class="cx">             if (result.match == Match::SelectorMatches)
</span><span class="lines">@@ -323,20 +327,19 @@
</span><span class="cx"> 
</span><span class="cx">     case CSSSelector::DirectAdjacent:
</span><span class="cx">         {
</span><del>-            if (context.resolvingMode == Mode::ResolvingStyle)
-                context.element-&gt;setStyleIsAffectedByPreviousSibling();
</del><ins>+            addStyleRelation(checkingContext, *context.element, StyleRelation::AffectedByPreviousSibling);
</ins><span class="cx"> 
</span><span class="cx">             Element* previousElement = context.element-&gt;previousElementSibling();
</span><span class="cx">             if (!previousElement)
</span><span class="cx">                 return MatchResult::fails(Match::SelectorFailsAllSiblings);
</span><del>-            if (context.resolvingMode == Mode::ResolvingStyle)
-                previousElement-&gt;setAffectsNextSiblingElementStyle();
</del><ins>+
+            addStyleRelation(checkingContext, *previousElement, StyleRelation::AffectsNextSibling);
+
</ins><span class="cx">             nextContext.element = previousElement;
</span><span class="cx">             nextContext.firstSelectorOfTheFragment = nextContext.selector;
</span><del>-            nextContext.elementStyle = nullptr;
</del><span class="cx">             PseudoIdSet ignoreDynamicPseudo;
</span><span class="cx">             unsigned adjacentSpecificity = 0;
</span><del>-            MatchResult result = matchRecursively(nextContext, ignoreDynamicPseudo, adjacentSpecificity);
</del><ins>+            MatchResult result = matchRecursively(checkingContext, nextContext, ignoreDynamicPseudo, adjacentSpecificity);
</ins><span class="cx">             ASSERT(!nextContext.pseudoElementEffective &amp;&amp; !ignoreDynamicPseudo);
</span><span class="cx"> 
</span><span class="cx">             if (result.match == Match::SelectorMatches)
</span><span class="lines">@@ -345,18 +348,16 @@
</span><span class="cx">             return MatchResult::updateWithMatchType(result, matchType);
</span><span class="cx">         }
</span><span class="cx">     case CSSSelector::IndirectAdjacent:
</span><del>-        if (context.resolvingMode == Mode::ResolvingStyle)
-            context.element-&gt;setStyleIsAffectedByPreviousSibling();
</del><ins>+        addStyleRelation(checkingContext, *context.element, StyleRelation::AffectedByPreviousSibling);
+
</ins><span class="cx">         nextContext.element = context.element-&gt;previousElementSibling();
</span><span class="cx">         nextContext.firstSelectorOfTheFragment = nextContext.selector;
</span><del>-        nextContext.elementStyle = nullptr;
</del><span class="cx">         for (; nextContext.element; nextContext.element = nextContext.element-&gt;previousElementSibling()) {
</span><del>-            if (context.resolvingMode == Mode::ResolvingStyle)
-                nextContext.element-&gt;setAffectsNextSiblingElementStyle();
</del><ins>+            addStyleRelation(checkingContext, *nextContext.element, StyleRelation::AffectsNextSibling);
</ins><span class="cx"> 
</span><span class="cx">             PseudoIdSet ignoreDynamicPseudo;
</span><span class="cx">             unsigned indirectAdjacentSpecificity = 0;
</span><del>-            MatchResult result = matchRecursively(nextContext, ignoreDynamicPseudo, indirectAdjacentSpecificity);
</del><ins>+            MatchResult result = matchRecursively(checkingContext, nextContext, ignoreDynamicPseudo, indirectAdjacentSpecificity);
</ins><span class="cx">             ASSERT(!nextContext.pseudoElementEffective &amp;&amp; !ignoreDynamicPseudo);
</span><span class="cx"> 
</span><span class="cx">             if (result.match == Match::SelectorMatches)
</span><span class="lines">@@ -374,13 +375,13 @@
</span><span class="cx">             // to follow the pseudo elements.
</span><span class="cx">             nextContext.hasScrollbarPseudo = hasScrollbarPseudoElement(dynamicPseudoIdSet);
</span><span class="cx">             nextContext.hasSelectionPseudo = dynamicPseudoIdSet.has(SELECTION);
</span><del>-            if ((context.elementStyle || context.resolvingMode == Mode::CollectingRules) &amp;&amp; dynamicPseudoIdSet
</del><ins>+            if ((context.isMatchElement || checkingContext.resolvingMode == Mode::CollectingRules) &amp;&amp; dynamicPseudoIdSet
</ins><span class="cx">                 &amp;&amp; !nextContext.hasSelectionPseudo
</span><span class="cx">                 &amp;&amp; !(nextContext.hasScrollbarPseudo &amp;&amp; nextContext.selector-&gt;match() == CSSSelector::PseudoClass))
</span><span class="cx">                 return MatchResult::fails(Match::SelectorFailsCompletely);
</span><span class="cx"> 
</span><span class="cx">             unsigned subselectorSpecificity = 0;
</span><del>-            MatchResult result = matchRecursively(nextContext, dynamicPseudoIdSet, subselectorSpecificity);
</del><ins>+            MatchResult result = matchRecursively(checkingContext, nextContext, dynamicPseudoIdSet, subselectorSpecificity);
</ins><span class="cx"> 
</span><span class="cx">             if (result.match == Match::SelectorMatches)
</span><span class="cx">                 specificity = CSSSelector::addSpecificities(specificity, subselectorSpecificity);
</span><span class="lines">@@ -394,10 +395,9 @@
</span><span class="cx">                 return MatchResult::fails(Match::SelectorFailsCompletely);
</span><span class="cx">             nextContext.element = shadowHostNode;
</span><span class="cx">             nextContext.firstSelectorOfTheFragment = nextContext.selector;
</span><del>-            nextContext.elementStyle = nullptr;
</del><span class="cx">             PseudoIdSet ignoreDynamicPseudo;
</span><span class="cx">             unsigned shadowDescendantSpecificity = 0;
</span><del>-            MatchResult result = matchRecursively(nextContext, ignoreDynamicPseudo, shadowDescendantSpecificity);
</del><ins>+            MatchResult result = matchRecursively(checkingContext, nextContext, ignoreDynamicPseudo, shadowDescendantSpecificity);
</ins><span class="cx"> 
</span><span class="cx">             if (result.match == Match::SelectorMatches)
</span><span class="cx">                 specificity = CSSSelector::addSpecificities(specificity, shadowDescendantSpecificity);
</span><span class="lines">@@ -504,7 +504,7 @@
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static bool anyAttributeMatches(Element* element, const CSSSelector* selector, const QualifiedName&amp; selectorAttr, bool caseSensitive)
</del><ins>+static bool anyAttributeMatches(const Element* element, const CSSSelector* selector, const QualifiedName&amp; selectorAttr, bool caseSensitive)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(element-&gt;hasAttributesWithoutUpdate());
</span><span class="cx">     for (const Attribute&amp; attribute : element-&gt;attributesIterator()) {
</span><span class="lines">@@ -518,7 +518,7 @@
</span><span class="cx">     return false;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static bool canMatchHoverOrActiveInQuirksMode(const SelectorChecker::CheckingContextWithStatus&amp; context)
</del><ins>+static bool canMatchHoverOrActiveInQuirksMode(const SelectorChecker::LocalContext&amp; context)
</ins><span class="cx"> {
</span><span class="cx">     // For quirks mode, follow this: http://quirks.spec.whatwg.org/#the-:active-and-:hover-quirk
</span><span class="cx">     // In quirks mode, a compound selector 'selector' that matches the following conditions must not match elements that would not also match the ':any-link' selector.
</span><span class="lines">@@ -588,9 +588,9 @@
</span><span class="cx">     return namespaceURI == starAtom || namespaceURI == element.namespaceURI();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool SelectorChecker::checkOne(const CheckingContextWithStatus&amp; context, PseudoIdSet&amp; dynamicPseudoIdSet, MatchType&amp; matchType, unsigned&amp; specificity) const
</del><ins>+bool SelectorChecker::checkOne(CheckingContext&amp; checkingContext, const LocalContext&amp; context, PseudoIdSet&amp; dynamicPseudoIdSet, MatchType&amp; matchType, unsigned&amp; specificity) const
</ins><span class="cx"> {
</span><del>-    Element* const &amp; element = context.element;
</del><ins>+    const Element* element = context.element;
</ins><span class="cx">     const CSSSelector* const &amp; selector = context.selector;
</span><span class="cx">     ASSERT(element);
</span><span class="cx">     ASSERT(selector);
</span><span class="lines">@@ -626,7 +626,7 @@
</span><span class="cx">             const CSSSelectorList* selectorList = selector-&gt;selectorList();
</span><span class="cx"> 
</span><span class="cx">             for (const CSSSelector* subselector = selectorList-&gt;first(); subselector; subselector = CSSSelectorList::next(subselector)) {
</span><del>-                CheckingContextWithStatus subcontext(context);
</del><ins>+                LocalContext subcontext(context);
</ins><span class="cx">                 subcontext.inFunctionalPseudoClass = true;
</span><span class="cx">                 subcontext.pseudoElementEffective = false;
</span><span class="cx">                 subcontext.selector = subselector;
</span><span class="lines">@@ -634,7 +634,7 @@
</span><span class="cx">                 PseudoIdSet ignoreDynamicPseudo;
</span><span class="cx"> 
</span><span class="cx">                 unsigned ignoredSpecificity;
</span><del>-                if (matchRecursively(subcontext, ignoreDynamicPseudo, ignoredSpecificity).match == Match::SelectorMatches) {
</del><ins>+                if (matchRecursively(checkingContext, subcontext, ignoreDynamicPseudo, ignoredSpecificity).match == Match::SelectorMatches) {
</ins><span class="cx">                     ASSERT(!ignoreDynamicPseudo);
</span><span class="cx">                     return false;
</span><span class="cx">                 }
</span><span class="lines">@@ -643,7 +643,7 @@
</span><span class="cx">         } else if (context.hasScrollbarPseudo) {
</span><span class="cx">             // CSS scrollbars match a specific subset of pseudo classes, and they have specialized rules for each
</span><span class="cx">             // (since there are no elements involved except with window-inactive).
</span><del>-            return checkScrollbarPseudoClass(context, selector);
</del><ins>+            return checkScrollbarPseudoClass(checkingContext, *context.element, selector);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         // Normal element pseudo class checking.
</span><span class="lines">@@ -667,53 +667,41 @@
</span><span class="cx">                         }
</span><span class="cx">                     }
</span><span class="cx">                 }
</span><del>-                if (context.resolvingMode == Mode::ResolvingStyle) {
-                    element-&gt;setStyleAffectedByEmpty();
-                    if (context.elementStyle)
-                        context.elementStyle-&gt;setEmptyState(result);
-                }
</del><ins>+                addStyleRelation(checkingContext, *context.element, StyleRelation::AffectedByEmpty, result);
+
</ins><span class="cx">                 return result;
</span><span class="cx">             }
</span><span class="cx">         case CSSSelector::PseudoClassFirstChild:
</span><span class="cx">             // first-child matches the first child that is an element
</span><del>-            if (Element* parentElement = element-&gt;parentElement()) {
-                bool result = isFirstChildElement(*element);
-                if (context.resolvingMode == Mode::ResolvingStyle) {
-                    RenderStyle* childStyle = context.elementStyle ? context.elementStyle : element-&gt;renderStyle();
-                    parentElement-&gt;setChildrenAffectedByFirstChildRules();
-                    if (result &amp;&amp; childStyle)
-                        childStyle-&gt;setFirstChildState();
-                }
-                return result;
</del><ins>+            if (const Element* parentElement = element-&gt;parentElement()) {
+                bool isFirstChild = isFirstChildElement(*element);
+                if (isFirstChild)
+                    addStyleRelation(checkingContext, *element, StyleRelation::FirstChild);
+                addStyleRelation(checkingContext, *parentElement, StyleRelation::ChildrenAffectedByFirstChildRules);
+                return isFirstChild;
</ins><span class="cx">             }
</span><span class="cx">             break;
</span><span class="cx">         case CSSSelector::PseudoClassFirstOfType:
</span><span class="cx">             // first-of-type matches the first element of its type
</span><span class="cx">             if (element-&gt;parentElement()) {
</span><del>-                if (context.resolvingMode == Mode::ResolvingStyle)
-                    element-&gt;setStyleIsAffectedByPreviousSibling();
-
-                return isFirstOfType(*element, element-&gt;tagQName(), context.resolvingMode == Mode::ResolvingStyle);
</del><ins>+                addStyleRelation(checkingContext, *element, StyleRelation::AffectedByPreviousSibling);
+                return isFirstOfType(checkingContext, *element, element-&gt;tagQName());
</ins><span class="cx">             }
</span><span class="cx">             break;
</span><span class="cx">         case CSSSelector::PseudoClassLastChild:
</span><span class="cx">             // last-child matches the last child that is an element
</span><del>-            if (Element* parentElement = element-&gt;parentElement()) {
-                bool result = parentElement-&gt;isFinishedParsingChildren() &amp;&amp; isLastChildElement(*element);
-                if (context.resolvingMode == Mode::ResolvingStyle) {
-                    RenderStyle* childStyle = context.elementStyle ? context.elementStyle : element-&gt;renderStyle();
-                    parentElement-&gt;setChildrenAffectedByLastChildRules();
-                    if (result &amp;&amp; childStyle)
-                        childStyle-&gt;setLastChildState();
-                }
-                return result;
</del><ins>+            if (const Element* parentElement = element-&gt;parentElement()) {
+                bool isLastChild = parentElement-&gt;isFinishedParsingChildren() &amp;&amp; isLastChildElement(*element);
+                if (isLastChild)
+                    addStyleRelation(checkingContext, *element, StyleRelation::LastChild);
+                addStyleRelation(checkingContext, *parentElement, StyleRelation::ChildrenAffectedByLastChildRules);
+                return isLastChild;
</ins><span class="cx">             }
</span><span class="cx">             break;
</span><span class="cx">         case CSSSelector::PseudoClassLastOfType:
</span><span class="cx">             // last-of-type matches the last element of its type
</span><span class="cx">             if (Element* parentElement = element-&gt;parentElement()) {
</span><del>-                if (context.resolvingMode == Mode::ResolvingStyle)
-                    parentElement-&gt;setChildrenAffectedByBackwardPositionalRules();
</del><ins>+                addStyleRelation(checkingContext, *parentElement, StyleRelation::ChildrenAffectedByBackwardPositionalRules);
</ins><span class="cx">                 if (!parentElement-&gt;isFinishedParsingChildren())
</span><span class="cx">                     return false;
</span><span class="cx">                 return isLastOfType(*element, element-&gt;tagQName());
</span><span class="lines">@@ -723,28 +711,23 @@
</span><span class="cx">             if (Element* parentElement = element-&gt;parentElement()) {
</span><span class="cx">                 bool firstChild = isFirstChildElement(*element);
</span><span class="cx">                 bool onlyChild = firstChild &amp;&amp; parentElement-&gt;isFinishedParsingChildren() &amp;&amp; isLastChildElement(*element);
</span><del>-                if (context.resolvingMode == Mode::ResolvingStyle) {
-                    RenderStyle* childStyle = context.elementStyle ? context.elementStyle : element-&gt;renderStyle();
-                    parentElement-&gt;setChildrenAffectedByFirstChildRules();
-                    parentElement-&gt;setChildrenAffectedByLastChildRules();
-                    if (firstChild &amp;&amp; childStyle)
-                        childStyle-&gt;setFirstChildState();
-                    if (onlyChild &amp;&amp; childStyle)
-                        childStyle-&gt;setLastChildState();
-                }
</del><ins>+                addStyleRelation(checkingContext, *parentElement, StyleRelation::ChildrenAffectedByFirstChildRules);
+                addStyleRelation(checkingContext, *parentElement, StyleRelation::ChildrenAffectedByLastChildRules);
+                if (firstChild)
+                    addStyleRelation(checkingContext, *element, StyleRelation::FirstChild);
+                if (onlyChild)
+                    addStyleRelation(checkingContext, *element, StyleRelation::LastChild);
</ins><span class="cx">                 return onlyChild;
</span><span class="cx">             }
</span><span class="cx">             break;
</span><span class="cx">         case CSSSelector::PseudoClassOnlyOfType:
</span><span class="cx">             // FIXME: This selector is very slow.
</span><span class="cx">             if (Element* parentElement = element-&gt;parentElement()) {
</span><del>-                if (context.resolvingMode == Mode::ResolvingStyle) {
-                    element-&gt;setStyleIsAffectedByPreviousSibling();
-                    parentElement-&gt;setChildrenAffectedByBackwardPositionalRules();
-                }
</del><ins>+                addStyleRelation(checkingContext, *element, StyleRelation::AffectedByPreviousSibling);
+                addStyleRelation(checkingContext, *parentElement, StyleRelation::ChildrenAffectedByBackwardPositionalRules);
</ins><span class="cx">                 if (!parentElement-&gt;isFinishedParsingChildren())
</span><span class="cx">                     return false;
</span><del>-                return isFirstOfType(*element, element-&gt;tagQName(), context.resolvingMode == Mode::ResolvingStyle) &amp;&amp; isLastOfType(*element, element-&gt;tagQName());
</del><ins>+                return isFirstOfType(checkingContext, *element, element-&gt;tagQName()) &amp;&amp; isLastOfType(*element, element-&gt;tagQName());
</ins><span class="cx">             }
</span><span class="cx">             break;
</span><span class="cx">         case CSSSelector::PseudoClassMatches:
</span><span class="lines">@@ -754,14 +737,14 @@
</span><span class="cx"> 
</span><span class="cx">                 MatchType localMatchType = MatchType::VirtualPseudoElementOnly;
</span><span class="cx">                 for (const CSSSelector* subselector = selector-&gt;selectorList()-&gt;first(); subselector; subselector = CSSSelectorList::next(subselector)) {
</span><del>-                    CheckingContextWithStatus subcontext(context);
</del><ins>+                    LocalContext subcontext(context);
</ins><span class="cx">                     subcontext.inFunctionalPseudoClass = true;
</span><span class="cx">                     subcontext.pseudoElementEffective = context.pseudoElementEffective;
</span><span class="cx">                     subcontext.selector = subselector;
</span><span class="cx">                     subcontext.firstSelectorOfTheFragment = subselector;
</span><span class="cx">                     PseudoIdSet localDynamicPseudoIdSet;
</span><span class="cx">                     unsigned localSpecificity = 0;
</span><del>-                    MatchResult result = matchRecursively(subcontext, localDynamicPseudoIdSet, localSpecificity);
</del><ins>+                    MatchResult result = matchRecursively(checkingContext, subcontext, localDynamicPseudoIdSet, localSpecificity);
</ins><span class="cx">                     if (result.match == Match::SelectorMatches) {
</span><span class="cx">                         maxSpecificity = std::max(maxSpecificity, localSpecificity);
</span><span class="cx"> 
</span><span class="lines">@@ -780,10 +763,7 @@
</span><span class="cx">             }
</span><span class="cx">         case CSSSelector::PseudoClassPlaceholderShown:
</span><span class="cx">             if (is&lt;HTMLTextFormControlElement&gt;(*element)) {
</span><del>-                if (context.resolvingMode == Mode::ResolvingStyle) {
-                    if (RenderStyle* style = context.elementStyle ? context.elementStyle : element-&gt;renderStyle())
-                        style-&gt;setUnique();
-                }
</del><ins>+                addStyleRelation(checkingContext, *element, StyleRelation::Unique);
</ins><span class="cx">                 return downcast&lt;HTMLTextFormControlElement&gt;(*element).isPlaceholderVisible();
</span><span class="cx">             }
</span><span class="cx">             return false;
</span><span class="lines">@@ -793,29 +773,26 @@
</span><span class="cx">             if (element-&gt;parentElement()) {
</span><span class="cx">                 if (const CSSSelectorList* selectorList = selector-&gt;selectorList()) {
</span><span class="cx">                     unsigned selectorListSpecificity;
</span><del>-                    if (matchSelectorList(context, *element, *selectorList, selectorListSpecificity))
</del><ins>+                    if (matchSelectorList(checkingContext, context, *element, *selectorList, selectorListSpecificity))
</ins><span class="cx">                         specificity = CSSSelector::addSpecificities(specificity, selectorListSpecificity);
</span><span class="cx">                     else
</span><span class="cx">                         return false;
</span><span class="cx">                 }
</span><span class="cx"> 
</span><del>-                if (context.resolvingMode == Mode::ResolvingStyle)
-                    element-&gt;setStyleIsAffectedByPreviousSibling();
</del><ins>+                addStyleRelation(checkingContext, *element, StyleRelation::AffectedByPreviousSibling);
</ins><span class="cx"> 
</span><span class="cx">                 int count = 1;
</span><span class="cx">                 if (const CSSSelectorList* selectorList = selector-&gt;selectorList()) {
</span><span class="cx">                     for (Element* sibling = ElementTraversal::previousSibling(*element); sibling; sibling = ElementTraversal::previousSibling(*sibling)) {
</span><del>-                        if (context.resolvingMode == Mode::ResolvingStyle)
-                            sibling-&gt;setAffectsNextSiblingElementStyle();
</del><ins>+                        addStyleRelation(checkingContext, *sibling, StyleRelation::AffectsNextSibling);
</ins><span class="cx"> 
</span><span class="cx">                         unsigned ignoredSpecificity;
</span><del>-                        if (matchSelectorList(context, *sibling, *selectorList, ignoredSpecificity))
</del><ins>+                        if (matchSelectorList(checkingContext, context, *sibling, *selectorList, ignoredSpecificity))
</ins><span class="cx">                             ++count;
</span><span class="cx">                     }
</span><span class="cx">                 } else {
</span><del>-                    count += countElementsBefore(*element, context.resolvingMode == Mode::ResolvingStyle);
-                    if (context.resolvingMode == Mode::ResolvingStyle)
-                        element-&gt;setChildIndex(count);
</del><ins>+                    count += countElementsBefore(checkingContext, *element);
+                    addStyleRelation(checkingContext, *element, StyleRelation::NthChildIndex, count);
</ins><span class="cx">                 }
</span><span class="cx"> 
</span><span class="cx">                 if (selector-&gt;matchNth(count))
</span><span class="lines">@@ -827,10 +804,9 @@
</span><span class="cx">                 break;
</span><span class="cx"> 
</span><span class="cx">             if (element-&gt;parentElement()) {
</span><del>-                if (context.resolvingMode == Mode::ResolvingStyle)
-                    element-&gt;setStyleIsAffectedByPreviousSibling();
</del><ins>+                addStyleRelation(checkingContext, *element, StyleRelation::AffectedByPreviousSibling);
</ins><span class="cx"> 
</span><del>-                int count = 1 + countElementsOfTypeBefore(*element, element-&gt;tagQName(), context.resolvingMode == Mode::ResolvingStyle);
</del><ins>+                int count = 1 + countElementsOfTypeBefore(checkingContext, *element, element-&gt;tagQName());
</ins><span class="cx">                 if (selector-&gt;matchNth(count))
</span><span class="cx">                     return true;
</span><span class="cx">             }
</span><span class="lines">@@ -841,17 +817,14 @@
</span><span class="cx">             if (Element* parentElement = element-&gt;parentElement()) {
</span><span class="cx">                 if (const CSSSelectorList* selectorList = selector-&gt;selectorList()) {
</span><span class="cx">                     unsigned selectorListSpecificity;
</span><del>-                    if (matchSelectorList(context, *element, *selectorList, selectorListSpecificity))
</del><ins>+                    if (matchSelectorList(checkingContext, context, *element, *selectorList, selectorListSpecificity))
</ins><span class="cx">                         specificity = CSSSelector::addSpecificities(specificity, selectorListSpecificity);
</span><span class="cx">                     else
</span><span class="cx">                         return false;
</span><span class="cx"> 
</span><del>-                    if (context.resolvingMode == Mode::ResolvingStyle) {
-                        parentElement-&gt;setChildrenAffectedByPropertyBasedBackwardPositionalRules();
-                        parentElement-&gt;setChildrenAffectedByBackwardPositionalRules();
-                    }
-                } else if (context.resolvingMode == Mode::ResolvingStyle)
-                    parentElement-&gt;setChildrenAffectedByBackwardPositionalRules();
</del><ins>+                    addStyleRelation(checkingContext, *parentElement, StyleRelation::ChildrenAffectedByPropertyBasedBackwardPositionalRules);
+                } else
+                    addStyleRelation(checkingContext, *parentElement, StyleRelation::ChildrenAffectedByBackwardPositionalRules);
</ins><span class="cx"> 
</span><span class="cx">                 if (!parentElement-&gt;isFinishedParsingChildren())
</span><span class="cx">                     return false;
</span><span class="lines">@@ -860,7 +833,7 @@
</span><span class="cx">                 if (const CSSSelectorList* selectorList = selector-&gt;selectorList()) {
</span><span class="cx">                     for (Element* sibling = ElementTraversal::nextSibling(*element); sibling; sibling = ElementTraversal::nextSibling(*sibling)) {
</span><span class="cx">                         unsigned ignoredSpecificity;
</span><del>-                        if (matchSelectorList(context, *sibling, *selectorList, ignoredSpecificity))
</del><ins>+                        if (matchSelectorList(checkingContext, context, *sibling, *selectorList, ignoredSpecificity))
</ins><span class="cx">                             ++count;
</span><span class="cx">                     }
</span><span class="cx">                 } else
</span><span class="lines">@@ -874,8 +847,8 @@
</span><span class="cx">             if (!selector-&gt;parseNth())
</span><span class="cx">                 break;
</span><span class="cx">             if (Element* parentElement = element-&gt;parentElement()) {
</span><del>-                if (context.resolvingMode == Mode::ResolvingStyle)
-                    parentElement-&gt;setChildrenAffectedByBackwardPositionalRules();
</del><ins>+                addStyleRelation(checkingContext, *parentElement, StyleRelation::ChildrenAffectedByBackwardPositionalRules);
+
</ins><span class="cx">                 if (!parentElement-&gt;isFinishedParsingChildren())
</span><span class="cx">                     return false;
</span><span class="cx"> 
</span><span class="lines">@@ -890,14 +863,14 @@
</span><span class="cx">             break;
</span><span class="cx">         case CSSSelector::PseudoClassAny:
</span><span class="cx">             {
</span><del>-                CheckingContextWithStatus subContext(context);
-                subContext.inFunctionalPseudoClass = true;
-                subContext.pseudoElementEffective = false;
-                for (subContext.selector = selector-&gt;selectorList()-&gt;first(); subContext.selector; subContext.selector = CSSSelectorList::next(subContext.selector)) {
-                    subContext.firstSelectorOfTheFragment = subContext.selector;
</del><ins>+                LocalContext subcontext(context);
+                subcontext.inFunctionalPseudoClass = true;
+                subcontext.pseudoElementEffective = false;
+                for (subcontext.selector = selector-&gt;selectorList()-&gt;first(); subcontext.selector; subcontext.selector = CSSSelectorList::next(subcontext.selector)) {
+                    subcontext.firstSelectorOfTheFragment = subcontext.selector;
</ins><span class="cx">                     PseudoIdSet ignoreDynamicPseudo;
</span><span class="cx">                     unsigned ingoredSpecificity = 0;
</span><del>-                    if (matchRecursively(subContext, ignoreDynamicPseudo, ingoredSpecificity).match == Match::SelectorMatches)
</del><ins>+                    if (matchRecursively(checkingContext, subcontext, ignoreDynamicPseudo, ingoredSpecificity).match == Match::SelectorMatches)
</ins><span class="cx">                         return true;
</span><span class="cx">                 }
</span><span class="cx">             }
</span><span class="lines">@@ -916,12 +889,8 @@
</span><span class="cx">                 return false;
</span><span class="cx">             return element-&gt;isLink() &amp;&amp; context.visitedMatchType == VisitedMatchType::Enabled;
</span><span class="cx">         case CSSSelector::PseudoClassDrag:
</span><del>-            if (context.resolvingMode == Mode::ResolvingStyle) {
-                if (context.elementStyle)
-                    context.elementStyle-&gt;setAffectedByDrag();
-                else
-                    element-&gt;setChildrenAffectedByDrag();
-            }
</del><ins>+            addStyleRelation(checkingContext, *element, StyleRelation::AffectedByDrag);
+
</ins><span class="cx">             if (element-&gt;renderer() &amp;&amp; element-&gt;renderer()-&gt;isDragging())
</span><span class="cx">                 return true;
</span><span class="cx">             break;
</span><span class="lines">@@ -929,25 +898,17 @@
</span><span class="cx">             return matchesFocusPseudoClass(element);
</span><span class="cx">         case CSSSelector::PseudoClassHover:
</span><span class="cx">             if (m_strictParsing || element-&gt;isLink() || canMatchHoverOrActiveInQuirksMode(context)) {
</span><del>-                if (context.resolvingMode == Mode::ResolvingStyle) {
-                    if (context.elementStyle)
-                        context.elementStyle-&gt;setAffectedByHover();
-                    else
-                        element-&gt;setChildrenAffectedByHover();
-                }
-                if (element-&gt;hovered() || InspectorInstrumentation::forcePseudoState(*element, CSSSelector::PseudoClassHover))
</del><ins>+                addStyleRelation(checkingContext, *element, StyleRelation::AffectedByHover);
+
+                if (element-&gt;hovered() || InspectorInstrumentation::forcePseudoState(const_cast&lt;Element&amp;&gt;(*element), CSSSelector::PseudoClassHover))
</ins><span class="cx">                     return true;
</span><span class="cx">             }
</span><span class="cx">             break;
</span><span class="cx">         case CSSSelector::PseudoClassActive:
</span><span class="cx">             if (m_strictParsing || element-&gt;isLink() || canMatchHoverOrActiveInQuirksMode(context)) {
</span><del>-                if (context.resolvingMode == Mode::ResolvingStyle) {
-                    if (context.elementStyle)
-                        context.elementStyle-&gt;setAffectedByActive();
-                    else
-                        element-&gt;setChildrenAffectedByActive();
-                }
-                if (element-&gt;active() || InspectorInstrumentation::forcePseudoState(*element, CSSSelector::PseudoClassActive))
</del><ins>+                addStyleRelation(checkingContext, *element, StyleRelation::AffectedByActive);
+
+                if (element-&gt;active() || InspectorInstrumentation::forcePseudoState(const_cast&lt;Element&amp;&gt;(*element), CSSSelector::PseudoClassActive))
</ins><span class="cx">                     return true;
</span><span class="cx">             }
</span><span class="cx">             break;
</span><span class="lines">@@ -1007,7 +968,7 @@
</span><span class="cx"> 
</span><span class="cx">         case CSSSelector::PseudoClassScope:
</span><span class="cx">             {
</span><del>-                const Node* contextualReferenceNode = !context.scope ? element-&gt;document().documentElement() : context.scope;
</del><ins>+                const Node* contextualReferenceNode = !checkingContext.scope ? element-&gt;document().documentElement() : checkingContext.scope;
</ins><span class="cx">                 if (element == contextualReferenceNode)
</span><span class="cx">                     return true;
</span><span class="cx">                 break;
</span><span class="lines">@@ -1050,16 +1011,16 @@
</span><span class="cx">     }
</span><span class="cx"> #if ENABLE(VIDEO_TRACK)
</span><span class="cx">     if (selector-&gt;match() == CSSSelector::PseudoElement &amp;&amp; selector-&gt;pseudoElementType() == CSSSelector::PseudoElementCue) {
</span><del>-        CheckingContextWithStatus subContext(context);
</del><ins>+        LocalContext subcontext(context);
</ins><span class="cx"> 
</span><span class="cx">         const CSSSelector* const &amp; selector = context.selector;
</span><del>-        for (subContext.selector = selector-&gt;selectorList()-&gt;first(); subContext.selector; subContext.selector = CSSSelectorList::next(subContext.selector)) {
-            subContext.firstSelectorOfTheFragment = subContext.selector;
-            subContext.inFunctionalPseudoClass = true;
-            subContext.pseudoElementEffective = false;
</del><ins>+        for (subcontext.selector = selector-&gt;selectorList()-&gt;first(); subcontext.selector; subcontext.selector = CSSSelectorList::next(subcontext.selector)) {
+            subcontext.firstSelectorOfTheFragment = subcontext.selector;
+            subcontext.inFunctionalPseudoClass = true;
+            subcontext.pseudoElementEffective = false;
</ins><span class="cx">             PseudoIdSet ignoredDynamicPseudo;
</span><span class="cx">             unsigned ignoredSpecificity = 0;
</span><del>-            if (matchRecursively(subContext, ignoredDynamicPseudo, ignoredSpecificity).match == Match::SelectorMatches)
</del><ins>+            if (matchRecursively(checkingContext, subcontext, ignoredDynamicPseudo, ignoredSpecificity).match == Match::SelectorMatches)
</ins><span class="cx">                 return true;
</span><span class="cx">         }
</span><span class="cx">         return false;
</span><span class="lines">@@ -1069,13 +1030,13 @@
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool SelectorChecker::matchSelectorList(const CheckingContextWithStatus&amp; baseContext, Element&amp; element, const CSSSelectorList&amp; selectorList, unsigned&amp; specificity) const
</del><ins>+bool SelectorChecker::matchSelectorList(CheckingContext&amp; checkingContext, const LocalContext&amp; context, const Element&amp; element, const CSSSelectorList&amp; selectorList, unsigned&amp; specificity) const
</ins><span class="cx"> {
</span><span class="cx">     specificity = 0;
</span><span class="cx">     bool hasMatchedAnything = false;
</span><span class="cx"> 
</span><span class="cx">     for (const CSSSelector* subselector = selectorList.first(); subselector; subselector = CSSSelectorList::next(subselector)) {
</span><del>-        CheckingContextWithStatus subcontext(baseContext);
</del><ins>+        LocalContext subcontext(context);
</ins><span class="cx">         subcontext.element = &amp;element;
</span><span class="cx">         subcontext.selector = subselector;
</span><span class="cx">         subcontext.inFunctionalPseudoClass = true;
</span><span class="lines">@@ -1083,7 +1044,7 @@
</span><span class="cx">         subcontext.firstSelectorOfTheFragment = subselector;
</span><span class="cx">         PseudoIdSet ignoreDynamicPseudo;
</span><span class="cx">         unsigned localSpecificity = 0;
</span><del>-        if (matchRecursively(subcontext, ignoreDynamicPseudo, localSpecificity).match == Match::SelectorMatches) {
</del><ins>+        if (matchRecursively(checkingContext, subcontext, ignoreDynamicPseudo, localSpecificity).match == Match::SelectorMatches) {
</ins><span class="cx">             ASSERT(!ignoreDynamicPseudo);
</span><span class="cx"> 
</span><span class="cx">             hasMatchedAnything = true;
</span><span class="lines">@@ -1093,41 +1054,41 @@
</span><span class="cx">     return hasMatchedAnything;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool SelectorChecker::checkScrollbarPseudoClass(const CheckingContextWithStatus&amp; context, const CSSSelector* selector) const
</del><ins>+bool SelectorChecker::checkScrollbarPseudoClass(const CheckingContext&amp; checkingContext, const Element&amp; element, const CSSSelector* selector) const
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(selector-&gt;match() == CSSSelector::PseudoClass);
</span><span class="cx"> 
</span><span class="cx">     switch (selector-&gt;pseudoClassType()) {
</span><span class="cx">     case CSSSelector::PseudoClassWindowInactive:
</span><del>-        return isWindowInactive(context.element);
</del><ins>+        return isWindowInactive(&amp;element);
</ins><span class="cx">     case CSSSelector::PseudoClassEnabled:
</span><del>-        return scrollbarMatchesEnabledPseudoClass(context);
</del><ins>+        return scrollbarMatchesEnabledPseudoClass(checkingContext);
</ins><span class="cx">     case CSSSelector::PseudoClassDisabled:
</span><del>-        return scrollbarMatchesDisabledPseudoClass(context);
</del><ins>+        return scrollbarMatchesDisabledPseudoClass(checkingContext);
</ins><span class="cx">     case CSSSelector::PseudoClassHover:
</span><del>-        return scrollbarMatchesHoverPseudoClass(context);
</del><ins>+        return scrollbarMatchesHoverPseudoClass(checkingContext);
</ins><span class="cx">     case CSSSelector::PseudoClassActive:
</span><del>-        return scrollbarMatchesActivePseudoClass(context);
</del><ins>+        return scrollbarMatchesActivePseudoClass(checkingContext);
</ins><span class="cx">     case CSSSelector::PseudoClassHorizontal:
</span><del>-        return scrollbarMatchesHorizontalPseudoClass(context);
</del><ins>+        return scrollbarMatchesHorizontalPseudoClass(checkingContext);
</ins><span class="cx">     case CSSSelector::PseudoClassVertical:
</span><del>-        return scrollbarMatchesVerticalPseudoClass(context);
</del><ins>+        return scrollbarMatchesVerticalPseudoClass(checkingContext);
</ins><span class="cx">     case CSSSelector::PseudoClassDecrement:
</span><del>-        return scrollbarMatchesDecrementPseudoClass(context);
</del><ins>+        return scrollbarMatchesDecrementPseudoClass(checkingContext);
</ins><span class="cx">     case CSSSelector::PseudoClassIncrement:
</span><del>-        return scrollbarMatchesIncrementPseudoClass(context);
</del><ins>+        return scrollbarMatchesIncrementPseudoClass(checkingContext);
</ins><span class="cx">     case CSSSelector::PseudoClassStart:
</span><del>-        return scrollbarMatchesStartPseudoClass(context);
</del><ins>+        return scrollbarMatchesStartPseudoClass(checkingContext);
</ins><span class="cx">     case CSSSelector::PseudoClassEnd:
</span><del>-        return scrollbarMatchesEndPseudoClass(context);
</del><ins>+        return scrollbarMatchesEndPseudoClass(checkingContext);
</ins><span class="cx">     case CSSSelector::PseudoClassDoubleButton:
</span><del>-        return scrollbarMatchesDoubleButtonPseudoClass(context);
</del><ins>+        return scrollbarMatchesDoubleButtonPseudoClass(checkingContext);
</ins><span class="cx">     case CSSSelector::PseudoClassSingleButton:
</span><del>-        return scrollbarMatchesSingleButtonPseudoClass(context);
</del><ins>+        return scrollbarMatchesSingleButtonPseudoClass(checkingContext);
</ins><span class="cx">     case CSSSelector::PseudoClassNoButton:
</span><del>-        return scrollbarMatchesNoButtonPseudoClass(context);
</del><ins>+        return scrollbarMatchesNoButtonPseudoClass(checkingContext);
</ins><span class="cx">     case CSSSelector::PseudoClassCornerPresent:
</span><del>-        return scrollbarMatchesCornerPresentPseudoClass(context);
</del><ins>+        return scrollbarMatchesCornerPresentPseudoClass(checkingContext);
</ins><span class="cx">     default:
</span><span class="cx">         return false;
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceWebCorecssSelectorCheckerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/css/SelectorChecker.h (195292 => 195293)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/css/SelectorChecker.h        2016-01-19 17:20:59 UTC (rev 195292)
+++ trunk/Source/WebCore/css/SelectorChecker.h        2016-01-19 17:39:20 UTC (rev 195293)
</span><span class="lines">@@ -2,7 +2,7 @@
</span><span class="cx">  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
</span><span class="cx">  *           (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com)
</span><span class="cx">  * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com)
</span><del>- * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2005-2016 Apple Inc. All rights reserved.
</ins><span class="cx">  * Copyright (C) 2007 Alexey Proskuryakov &lt;ap@webkit.org&gt;
</span><span class="cx">  * Copyright (C) 2007, 2008 Eric Seidel &lt;eric@webkit.org&gt;
</span><span class="cx">  * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
</span><span class="lines">@@ -76,28 +76,47 @@
</span><span class="cx"> 
</span><span class="cx">     SelectorChecker(Document&amp;);
</span><span class="cx"> 
</span><ins>+    struct StyleRelation {
+        enum Type {
+            AffectedByActive,
+            AffectedByDrag,
+            AffectedByEmpty,
+            AffectedByHover,
+            AffectedByPreviousSibling,
+            AffectsNextSibling,
+            ChildrenAffectedByBackwardPositionalRules,
+            ChildrenAffectedByFirstChildRules,
+            ChildrenAffectedByPropertyBasedBackwardPositionalRules,
+            ChildrenAffectedByLastChildRules,
+            FirstChild,
+            LastChild,
+            NthChildIndex,
+            Unique,
+        };
+        Element&amp; element;
+        Type type;
+        unsigned value;
+    };
+    using StyleRelations = Vector&lt;StyleRelation, 8&gt;;
+
</ins><span class="cx">     struct CheckingContext {
</span><span class="cx">         CheckingContext(SelectorChecker::Mode resolvingMode)
</span><span class="cx">             : resolvingMode(resolvingMode)
</span><del>-            , elementStyle(nullptr)
-            , pseudoId(NOPSEUDO)
-            , scrollbar(nullptr)
-            , scrollbarPart(NoPart)
-            , scope(nullptr)
</del><span class="cx">         { }
</span><span class="cx"> 
</span><del>-        SelectorChecker::Mode resolvingMode;
-        RenderStyle* elementStyle;
-        PseudoId pseudoId;
-        RenderScrollbar* scrollbar;
-        ScrollbarPart scrollbarPart;
-        const ContainerNode* scope;
</del><ins>+        const SelectorChecker::Mode resolvingMode;
+        PseudoId pseudoId { NOPSEUDO };
+        RenderScrollbar* scrollbar { nullptr };
+        ScrollbarPart scrollbarPart { NoPart };
+        const ContainerNode* scope { nullptr };
+
+        // FIXME: It would be nicer to have a separate object for return values. This requires some more work in the selector compiler.
+        StyleRelations styleRelations;
+        PseudoIdSet pseudoIDSet;
</ins><span class="cx">     };
</span><span class="cx"> 
</span><del>-    struct CheckingContextWithStatus;
</del><ins>+    bool match(const CSSSelector&amp;, const Element&amp;, CheckingContext&amp;, unsigned&amp; specificity) const;
</ins><span class="cx"> 
</span><del>-    bool match(const CSSSelector*, Element*, const CheckingContext&amp;, unsigned&amp; specificity) const;
-
</del><span class="cx">     static bool isCommonPseudoClassSelector(const CSSSelector*);
</span><span class="cx">     static bool matchesFocusPseudoClass(const Element*);
</span><span class="cx">     static bool checkExactAttribute(const Element*, const CSSSelector*, const QualifiedName&amp; selectorAttributeName, const AtomicStringImpl* value);
</span><span class="lines">@@ -105,12 +124,14 @@
</span><span class="cx">     enum LinkMatchMask { MatchDefault = 0, MatchLink = 1, MatchVisited = 2, MatchAll = MatchLink | MatchVisited };
</span><span class="cx">     static unsigned determineLinkMatchType(const CSSSelector*);
</span><span class="cx"> 
</span><ins>+    struct LocalContext;
+    
</ins><span class="cx"> private:
</span><del>-    MatchResult matchRecursively(const CheckingContextWithStatus&amp;, PseudoIdSet&amp;, unsigned&amp; specificity) const;
-    bool checkOne(const CheckingContextWithStatus&amp;, PseudoIdSet&amp;, MatchType&amp;, unsigned&amp; specificity) const;
-    bool matchSelectorList(const CheckingContextWithStatus&amp;, Element&amp;, const CSSSelectorList&amp;, unsigned&amp; specificity) const;
</del><ins>+    MatchResult matchRecursively(CheckingContext&amp;, const LocalContext&amp;, PseudoIdSet&amp;, unsigned&amp; specificity) const;
+    bool checkOne(CheckingContext&amp;, const LocalContext&amp;, PseudoIdSet&amp;, MatchType&amp;, unsigned&amp; specificity) const;
+    bool matchSelectorList(CheckingContext&amp;, const LocalContext&amp;, const Element&amp;, const CSSSelectorList&amp;, unsigned&amp; specificity) const;
</ins><span class="cx"> 
</span><del>-    bool checkScrollbarPseudoClass(const CheckingContextWithStatus&amp;, const CSSSelector*) const;
</del><ins>+    bool checkScrollbarPseudoClass(const CheckingContext&amp;, const Element&amp;, const CSSSelector*) const;
</ins><span class="cx"> 
</span><span class="cx">     bool m_strictParsing;
</span><span class="cx">     bool m_documentIsHTML;
</span></span></pre></div>
<a id="trunkSourceWebCorecssSelectorCheckerTestFunctionsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/css/SelectorCheckerTestFunctions.h (195292 => 195293)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/css/SelectorCheckerTestFunctions.h        2016-01-19 17:20:59 UTC (rev 195292)
+++ trunk/Source/WebCore/css/SelectorCheckerTestFunctions.h        2016-01-19 17:39:20 UTC (rev 195293)
</span><span class="lines">@@ -63,12 +63,12 @@
</span><span class="cx">         &amp;&amp; !element-&gt;isDisabledFormControl();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-ALWAYS_INLINE bool isMediaDocument(Element* element)
</del><ins>+ALWAYS_INLINE bool isMediaDocument(const Element* element)
</ins><span class="cx"> {
</span><span class="cx">     return element-&gt;document().isMediaDocument();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-ALWAYS_INLINE bool isChecked(Element&amp; element)
</del><ins>+ALWAYS_INLINE bool isChecked(const Element&amp; element)
</ins><span class="cx"> {
</span><span class="cx">     // Even though WinIE allows checked and indeterminate to co-exist, the CSS selector spec says that
</span><span class="cx">     // you can't be both checked and indeterminate. We will behave like WinIE behind the scenes and just
</span><span class="lines">@@ -78,17 +78,17 @@
</span><span class="cx">         return inputElement.shouldAppearChecked() &amp;&amp; !inputElement.shouldAppearIndeterminate();
</span><span class="cx">     }
</span><span class="cx">     if (is&lt;HTMLOptionElement&gt;(element))
</span><del>-        return downcast&lt;HTMLOptionElement&gt;(element).selected();
</del><ins>+        return const_cast&lt;HTMLOptionElement&amp;&gt;(downcast&lt;HTMLOptionElement&gt;(element)).selected();
</ins><span class="cx"> 
</span><span class="cx">     return false;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-ALWAYS_INLINE bool isInRange(Element* element)
</del><ins>+ALWAYS_INLINE bool isInRange(const Element* element)
</ins><span class="cx"> {
</span><span class="cx">     return element-&gt;isInRange();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-ALWAYS_INLINE bool isOutOfRange(Element* element)
</del><ins>+ALWAYS_INLINE bool isOutOfRange(const Element* element)
</ins><span class="cx"> {
</span><span class="cx">     return element-&gt;isOutOfRange();
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCorecssStyleResolverh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/css/StyleResolver.h (195292 => 195293)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/css/StyleResolver.h        2016-01-19 17:20:59 UTC (rev 195292)
+++ trunk/Source/WebCore/css/StyleResolver.h        2016-01-19 17:39:20 UTC (rev 195293)
</span><span class="lines">@@ -610,7 +610,7 @@
</span><span class="cx">     for (const CSSSelector* s = regionSelector; s; s = CSSSelectorList::next(s)) {
</span><span class="cx">         SelectorChecker::CheckingContext selectorCheckingContext(SelectorChecker::Mode::QueryingRules);
</span><span class="cx">         unsigned ignoredSpecificity;
</span><del>-        if (selectorChecker.match(s, regionElement, selectorCheckingContext, ignoredSpecificity))
</del><ins>+        if (selectorChecker.match(*s, *regionElement, selectorCheckingContext, ignoredSpecificity))
</ins><span class="cx">             return true;
</span><span class="cx">     }
</span><span class="cx">     return false;
</span></span></pre></div>
<a id="trunkSourceWebCorecssjitSelectorCompilercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/cssjit/SelectorCompiler.cpp (195292 => 195293)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/cssjit/SelectorCompiler.cpp        2016-01-19 17:20:59 UTC (rev 195292)
+++ trunk/Source/WebCore/cssjit/SelectorCompiler.cpp        2016-01-19 17:39:20 UTC (rev 195293)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2013-2015 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2013-2016 Apple Inc. All rights reserved.
</ins><span class="cx">  * Copyright (C) 2014 Yusuke Suzuki &lt;utatane.tea@gmail.com&gt;
</span><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="lines">@@ -291,14 +291,14 @@
</span><span class="cx">     void generateElementFunctionCallTest(Assembler::JumpList&amp; failureCases, JSC::FunctionPtr);
</span><span class="cx">     void generateContextFunctionCallTest(Assembler::JumpList&amp; failureCases, JSC::FunctionPtr);
</span><span class="cx">     void generateElementIsActive(Assembler::JumpList&amp; failureCases, const SelectorFragment&amp;);
</span><del>-    void generateElementIsEmpty(Assembler::JumpList&amp; failureCases, const SelectorFragment&amp;);
-    void generateElementIsFirstChild(Assembler::JumpList&amp; failureCases, const SelectorFragment&amp;);
</del><ins>+    void generateElementIsEmpty(Assembler::JumpList&amp; failureCases);
+    void generateElementIsFirstChild(Assembler::JumpList&amp; failureCases);
</ins><span class="cx">     void generateElementIsHovered(Assembler::JumpList&amp; failureCases, const SelectorFragment&amp;);
</span><span class="cx">     void generateElementIsInLanguage(Assembler::JumpList&amp; failureCases, const SelectorFragment&amp;);
</span><span class="cx">     void generateElementIsInLanguage(Assembler::JumpList&amp; failureCases, const Vector&lt;AtomicString&gt;*);
</span><del>-    void generateElementIsLastChild(Assembler::JumpList&amp; failureCases, const SelectorFragment&amp;);
-    void generateElementIsOnlyChild(Assembler::JumpList&amp; failureCases, const SelectorFragment&amp;);
-    void generateElementHasPlaceholderShown(Assembler::JumpList&amp; failureCases, const SelectorFragment&amp;);
</del><ins>+    void generateElementIsLastChild(Assembler::JumpList&amp; failureCases);
+    void generateElementIsOnlyChild(Assembler::JumpList&amp; failureCases);
+    void generateElementHasPlaceholderShown(Assembler::JumpList&amp; failureCases);
</ins><span class="cx">     void generateSynchronizeStyleAttribute(Assembler::RegisterID elementDataArraySizeAndFlags);
</span><span class="cx">     void generateSynchronizeAllAnimatedSVGAttribute(Assembler::RegisterID elementDataArraySizeAndFlags);
</span><span class="cx">     void generateElementAttributesMatching(Assembler::JumpList&amp; failureCases, const LocalRegister&amp; elementDataAddress, const SelectorFragment&amp;);
</span><span class="lines">@@ -323,7 +323,8 @@
</span><span class="cx">     void generateElementIsTarget(Assembler::JumpList&amp; failureCases);
</span><span class="cx"> 
</span><span class="cx">     // Helpers.
</span><del>-    void addFlagsToElementStyleFromContext(Assembler::RegisterID checkingContext, int64_t);
</del><ins>+    void generateAddStyleRelationIfResolvingStyle(Assembler::RegisterID element, SelectorChecker::StyleRelation::Type, Optional&lt;Assembler::RegisterID&gt; value = { });
+    void generateAddStyleRelation(Assembler::RegisterID checkingContext, Assembler::RegisterID element, SelectorChecker::StyleRelation::Type, Optional&lt;Assembler::RegisterID&gt; value = { });
</ins><span class="cx">     Assembler::Jump branchOnResolvingModeWithCheckingContext(Assembler::RelationalCondition, SelectorChecker::Mode, Assembler::RegisterID checkingContext);
</span><span class="cx">     Assembler::Jump branchOnResolvingMode(Assembler::RelationalCondition, SelectorChecker::Mode, Assembler::RegisterID checkingContext);
</span><span class="cx">     void generateElementIsFirstLink(Assembler::JumpList&amp; failureCases, Assembler::RegisterID element);
</span><span class="lines">@@ -332,7 +333,6 @@
</span><span class="cx">     void generateNthFilterTest(Assembler::JumpList&amp; failureCases, Assembler::RegisterID counter, int a, int b);
</span><span class="cx">     void generateRequestedPseudoElementEqualsToSelectorPseudoElement(Assembler::JumpList&amp; failureCases, const SelectorFragment&amp;, Assembler::RegisterID checkingContext);
</span><span class="cx">     void generateSpecialFailureInQuirksModeForActiveAndHoverIfNeeded(Assembler::JumpList&amp; failureCases, const SelectorFragment&amp;);
</span><del>-    void markElementIfResolvingStyle(Assembler::RegisterID, int32_t);
</del><span class="cx">     Assembler::JumpList jumpIfNoPreviousAdjacentElement();
</span><span class="cx">     Assembler::JumpList jumpIfNoNextAdjacentElement();
</span><span class="cx">     Assembler::Jump jumpIfNotResolvingStyle(Assembler::RegisterID checkingContextRegister);
</span><span class="lines">@@ -1891,7 +1891,7 @@
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">         if (shouldMarkStyleIsAffectedByPreviousSibling(fragment))
</span><del>-            markElementIfResolvingStyle(elementAddressRegister, Node::flagStyleIsAffectedByPreviousSibling());
</del><ins>+            generateAddStyleRelationIfResolvingStyle(elementAddressRegister, SelectorChecker::StyleRelation::AffectedByPreviousSibling);
</ins><span class="cx">         generateBacktrackingTailsIfNeeded(failureCases, fragment);
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -2135,7 +2135,7 @@
</span><span class="cx"> void SelectorCodeGenerator::generateDirectAdjacentTreeWalker(Assembler::JumpList&amp; failureCases, const SelectorFragment&amp; fragment)
</span><span class="cx"> {
</span><span class="cx">     generateWalkToPreviousAdjacent(failureCases, fragment);
</span><del>-    markElementIfResolvingStyle(elementAddressRegister, Node::flagAffectsNextSiblingElementStyle());
</del><ins>+    generateAddStyleRelationIfResolvingStyle(elementAddressRegister, SelectorChecker::StyleRelation::AffectsNextSibling);
</ins><span class="cx"> 
</span><span class="cx">     Assembler::JumpList matchingTagNameFailureCases;
</span><span class="cx">     Assembler::JumpList matchingPostTagNameFailureCases;
</span><span class="lines">@@ -2160,7 +2160,7 @@
</span><span class="cx">         m_backtrackingLevels.last().indirectAdjacentTreeWalkerBacktrackingPoint = m_assembler.label();
</span><span class="cx"> 
</span><span class="cx">     generateWalkToPreviousAdjacent(failureCases, fragment);
</span><del>-    markElementIfResolvingStyle(elementAddressRegister, Node::flagAffectsNextSiblingElementStyle());
</del><ins>+    generateAddStyleRelationIfResolvingStyle(elementAddressRegister, SelectorChecker::StyleRelation::AffectsNextSibling);
</ins><span class="cx"> 
</span><span class="cx">     if (fragment.backtrackingFlags &amp; BacktrackingFlag::IndirectAdjacentEntryPoint)
</span><span class="cx">         m_backtrackingLevels.last().indirectAdjacentEntryPoint = m_assembler.label();
</span><span class="lines">@@ -2170,35 +2170,51 @@
</span><span class="cx">     localFailureCases.linkTo(loopStart, &amp;m_assembler);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void SelectorCodeGenerator::generateAddStyleRelationIfResolvingStyle(Assembler::RegisterID element, SelectorChecker::StyleRelation::Type relationType, Optional&lt;Assembler::RegisterID&gt; value)
+{
+    if (m_selectorContext == SelectorContext::QuerySelector)
+        return;
</ins><span class="cx"> 
</span><del>-void SelectorCodeGenerator::addFlagsToElementStyleFromContext(Assembler::RegisterID checkingContext, int64_t newFlag)
</del><ins>+    LocalRegister checkingContext(m_registerAllocator);
+    Assembler::Jump notResolvingStyle = jumpIfNotResolvingStyle(checkingContext);
+
+    generateAddStyleRelation(checkingContext, element, relationType, value);
+
+    notResolvingStyle.link(&amp;m_assembler);
+}
+
+static void addStyleRelationFunction(SelectorChecker::CheckingContext* checkingContext, Element* element)
</ins><span class="cx"> {
</span><ins>+    checkingContext-&gt;styleRelations.append({ *element, SelectorChecker::StyleRelation::AffectedByActive, 1 });
+}
+
+void SelectorCodeGenerator::generateAddStyleRelation(Assembler::RegisterID checkingContext, Assembler::RegisterID element, SelectorChecker::StyleRelation::Type relationType, Optional&lt;Assembler::RegisterID&gt; value)
+{
</ins><span class="cx">     ASSERT(m_selectorContext != SelectorContext::QuerySelector);
</span><span class="cx"> 
</span><del>-    LocalRegister childStyle(m_registerAllocator);
-    m_assembler.loadPtr(Assembler::Address(checkingContext, OBJECT_OFFSETOF(SelectorChecker::CheckingContext, elementStyle)), childStyle);
</del><ins>+    // FIXME: Append to vector without a function call at least when there is sufficient capacity.
+    FunctionCall functionCall(m_assembler, m_registerAllocator, m_stackAllocator, m_functionCalls);
+    functionCall.setFunctionAddress(addStyleRelationFunction);
+    functionCall.setTwoArguments(checkingContext, element);
+    functionCall.call();
</ins><span class="cx"> 
</span><del>-    // FIXME: We should look into doing something smart in MacroAssembler instead.
-    Assembler::Address flagAddress(childStyle, RenderStyle::noninheritedFlagsMemoryOffset() + RenderStyle::NonInheritedFlags::flagsMemoryOffset());
-#if CPU(ARM_THUMB2)
-    int32_t flagLowBits = newFlag &amp; 0xffffffff;
-    int32_t flagHighBits = newFlag &gt;&gt; 32;
-    if (flagLowBits)
-        m_assembler.or32(Assembler::TrustedImm32(flagLowBits), flagAddress);
-    if (flagHighBits) {
-        Assembler::Address flagHighAddress = flagAddress.withOffset(4);
-        m_assembler.or32(Assembler::TrustedImm32(flagHighBits), flagHighAddress);
</del><ins>+    Assembler::Address vectorAddress(checkingContext, OBJECT_OFFSETOF(SelectorChecker::CheckingContext, styleRelations));
+    auto dataAddress = vectorAddress.withOffset(SelectorChecker::StyleRelations::dataMemoryOffset());
+    auto sizeAddress = vectorAddress.withOffset(SelectorChecker::StyleRelations::sizeMemoryOffset());
+
+    LocalRegister relationPointer(m_registerAllocator);
+    m_assembler.load32(sizeAddress, relationPointer);
+    m_assembler.sub32(Assembler::TrustedImm32(1), relationPointer);
+    m_assembler.mul32(Assembler::TrustedImm32(sizeof(SelectorChecker::StyleRelation)), relationPointer, relationPointer);
+    m_assembler.addPtr(dataAddress, relationPointer);
+
+    Assembler::Address typeAddress(relationPointer, OBJECT_OFFSETOF(SelectorChecker::StyleRelation, type));
+    m_assembler.store32(Assembler::TrustedImm32(relationType), typeAddress);
+
+    if (value) {
+        Assembler::Address valueAddress(relationPointer, OBJECT_OFFSETOF(SelectorChecker::StyleRelation, value));
+        m_assembler.store32(*value, valueAddress);
</ins><span class="cx">     }
</span><del>-#elif CPU(X86_64) || CPU(ARM64)
-    LocalRegister flags(m_registerAllocator);
-    m_assembler.load64(flagAddress, flags);
-    LocalRegister isFirstChildStateFlagImmediate(m_registerAllocator);
-    m_assembler.move(Assembler::TrustedImm64(newFlag), isFirstChildStateFlagImmediate);
-    m_assembler.or64(isFirstChildStateFlagImmediate, flags);
-    m_assembler.store64(flags, flagAddress);
-#else
-#error SelectorCodeGenerator::addFlagsToElementStyleFromContext not implemented for this architecture.
-#endif
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> Assembler::JumpList SelectorCodeGenerator::jumpIfNoPreviousAdjacentElement()
</span><span class="lines">@@ -2420,27 +2436,6 @@
</span><span class="cx">     failureCases.append(modulo(Assembler::NonZero, inputDividend, divisor));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static void setNodeFlag(Assembler&amp; assembler, Assembler::RegisterID elementAddress, int32_t flag)
-{
-    assembler.or32(Assembler::TrustedImm32(flag), Assembler::Address(elementAddress, Node::nodeFlagsMemoryOffset()));
-}
-
-void SelectorCodeGenerator::markElementIfResolvingStyle(Assembler::RegisterID element, int32_t nodeFlag)
-{
-    if (m_selectorContext == SelectorContext::QuerySelector)
-        return;
-
-    Assembler::JumpList skipMarking;
-    {
-        LocalRegister checkingContext(m_registerAllocator);
-        skipMarking.append(jumpIfNotResolvingStyle(checkingContext));
-    }
-
-    setNodeFlag(m_assembler, element, nodeFlag);
-
-    skipMarking.link(&amp;m_assembler);
-}
-
</del><span class="cx"> void SelectorCodeGenerator::linkFailures(Assembler::JumpList&amp; globalFailureCases, BacktrackingAction backtrackingAction, Assembler::JumpList&amp; localFailureCases)
</span><span class="cx"> {
</span><span class="cx">     switch (backtrackingAction) {
</span><span class="lines">@@ -2547,17 +2542,17 @@
</span><span class="cx">     if (fragment.pseudoClasses.contains(CSSSelector::PseudoClassActive))
</span><span class="cx">         generateElementIsActive(matchingPostTagNameFailureCases, fragment);
</span><span class="cx">     if (fragment.pseudoClasses.contains(CSSSelector::PseudoClassEmpty))
</span><del>-        generateElementIsEmpty(matchingPostTagNameFailureCases, fragment);
</del><ins>+        generateElementIsEmpty(matchingPostTagNameFailureCases);
</ins><span class="cx">     if (fragment.pseudoClasses.contains(CSSSelector::PseudoClassHover))
</span><span class="cx">         generateElementIsHovered(matchingPostTagNameFailureCases, fragment);
</span><span class="cx">     if (fragment.pseudoClasses.contains(CSSSelector::PseudoClassOnlyChild))
</span><del>-        generateElementIsOnlyChild(matchingPostTagNameFailureCases, fragment);
</del><ins>+        generateElementIsOnlyChild(matchingPostTagNameFailureCases);
</ins><span class="cx">     if (fragment.pseudoClasses.contains(CSSSelector::PseudoClassPlaceholderShown))
</span><del>-        generateElementHasPlaceholderShown(matchingPostTagNameFailureCases, fragment);
</del><ins>+        generateElementHasPlaceholderShown(matchingPostTagNameFailureCases);
</ins><span class="cx">     if (fragment.pseudoClasses.contains(CSSSelector::PseudoClassFirstChild))
</span><del>-        generateElementIsFirstChild(matchingPostTagNameFailureCases, fragment);
</del><ins>+        generateElementIsFirstChild(matchingPostTagNameFailureCases);
</ins><span class="cx">     if (fragment.pseudoClasses.contains(CSSSelector::PseudoClassLastChild))
</span><del>-        generateElementIsLastChild(matchingPostTagNameFailureCases, fragment);
</del><ins>+        generateElementIsLastChild(matchingPostTagNameFailureCases);
</ins><span class="cx">     if (!fragment.nthChildFilters.isEmpty())
</span><span class="cx">         generateElementIsNthChild(matchingPostTagNameFailureCases, fragment);
</span><span class="cx">     if (!fragment.nthLastChildFilters.isEmpty())
</span><span class="lines">@@ -3052,55 +3047,21 @@
</span><span class="cx">     failureCases.append(functionCall.callAndBranchOnBooleanReturnValue(Assembler::Zero));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static void setFirstChildState(Element* element)
-{
-    if (RenderStyle* style = element-&gt;renderStyle())
-        style-&gt;setFirstChildState();
-}
-
</del><span class="cx"> static bool elementIsActive(Element* element)
</span><span class="cx"> {
</span><span class="cx">     return element-&gt;active() || InspectorInstrumentation::forcePseudoState(*element, CSSSelector::PseudoClassActive);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static bool elementIsActiveForStyleResolution(Element* element, const SelectorChecker::CheckingContext* checkingContext)
-{
-    if (checkingContext-&gt;resolvingMode == SelectorChecker::Mode::ResolvingStyle)
-        element-&gt;setChildrenAffectedByActive();
-    return element-&gt;active() || InspectorInstrumentation::forcePseudoState(*element, CSSSelector::PseudoClassActive);
-}
-
</del><span class="cx"> void SelectorCodeGenerator::generateElementIsActive(Assembler::JumpList&amp; failureCases, const SelectorFragment&amp; fragment)
</span><span class="cx"> {
</span><span class="cx">     generateSpecialFailureInQuirksModeForActiveAndHoverIfNeeded(failureCases, fragment);
</span><del>-    if (m_selectorContext == SelectorContext::QuerySelector) {
-        FunctionCall functionCall(m_assembler, m_registerAllocator, m_stackAllocator, m_functionCalls);
-        functionCall.setFunctionAddress(elementIsActive);
-        functionCall.setOneArgument(elementAddressRegister);
-        failureCases.append(functionCall.callAndBranchOnBooleanReturnValue(Assembler::Zero));
-        return;
-    }
</del><span class="cx"> 
</span><del>-    if (fragmentMatchesTheRightmostElement(m_selectorContext, fragment)) {
-        LocalRegister checkingContext(m_registerAllocator);
-        Assembler::Jump notResolvingStyle = jumpIfNotResolvingStyle(checkingContext);
-        addFlagsToElementStyleFromContext(checkingContext, RenderStyle::NonInheritedFlags::flagIsaffectedByActive());
-        notResolvingStyle.link(&amp;m_assembler);
</del><ins>+    generateAddStyleRelationIfResolvingStyle(elementAddressRegister, SelectorChecker::StyleRelation::AffectedByActive);
</ins><span class="cx"> 
</span><del>-        FunctionCall functionCall(m_assembler, m_registerAllocator, m_stackAllocator, m_functionCalls);
-        functionCall.setFunctionAddress(elementIsActive);
-        functionCall.setOneArgument(elementAddressRegister);
-        failureCases.append(functionCall.callAndBranchOnBooleanReturnValue(Assembler::Zero));
-    } else {
-        Assembler::RegisterID checkingContext = m_registerAllocator.allocateRegisterWithPreference(JSC::GPRInfo::argumentGPR1);
-        loadCheckingContext(checkingContext);
-        m_registerAllocator.deallocateRegister(checkingContext);
-
-        FunctionCall functionCall(m_assembler, m_registerAllocator, m_stackAllocator, m_functionCalls);
-        functionCall.setFunctionAddress(elementIsActiveForStyleResolution);
-        functionCall.setTwoArguments(elementAddressRegister, checkingContext);
-        failureCases.append(functionCall.callAndBranchOnBooleanReturnValue(Assembler::Zero));
-    }
</del><ins>+    FunctionCall functionCall(m_assembler, m_registerAllocator, m_stackAllocator, m_functionCalls);
+    functionCall.setFunctionAddress(elementIsActive);
+    functionCall.setOneArgument(elementAddressRegister);
+    failureCases.append(functionCall.callAndBranchOnBooleanReturnValue(Assembler::Zero));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> static void jumpIfElementIsNotEmpty(Assembler&amp; assembler, RegisterAllocator&amp; registerAllocator, Assembler::JumpList&amp; notEmptyCases, Assembler::RegisterID element)
</span><span class="lines">@@ -3129,19 +3090,8 @@
</span><span class="cx">     noMoreChildren.link(&amp;assembler);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static void setElementStyleIsAffectedByEmpty(Element* element)
</del><ins>+void SelectorCodeGenerator::generateElementIsEmpty(Assembler::JumpList&amp; failureCases)
</ins><span class="cx"> {
</span><del>-    element-&gt;setStyleAffectedByEmpty();
-}
-
-static void setElementStyleFromContextIsAffectedByEmptyAndUpdateRenderStyleIfNecessary(SelectorChecker::CheckingContext* context, bool isEmpty)
-{
-    ASSERT(context-&gt;elementStyle);
-    context-&gt;elementStyle-&gt;setEmptyState(isEmpty);
-}
-
-void SelectorCodeGenerator::generateElementIsEmpty(Assembler::JumpList&amp; failureCases, const SelectorFragment&amp; fragment)
-{
</del><span class="cx">     if (m_selectorContext == SelectorContext::QuerySelector) {
</span><span class="cx">         jumpIfElementIsNotEmpty(m_assembler, m_registerAllocator, failureCases, elementAddressRegister);
</span><span class="cx">         return;
</span><span class="lines">@@ -3155,38 +3105,12 @@
</span><span class="cx">     m_assembler.move(Assembler::TrustedImm32(1), isEmptyResults);
</span><span class="cx">     notEmpty.link(&amp;m_assembler);
</span><span class="cx"> 
</span><del>-    Assembler::Jump skipMarking;
-    if (fragmentMatchesTheRightmostElement(m_selectorContext, fragment)) {
-        {
-            LocalRegister checkingContext(m_registerAllocator);
-            skipMarking = jumpIfNotResolvingStyle(checkingContext);
</del><ins>+    generateAddStyleRelationIfResolvingStyle(elementAddressRegister, SelectorChecker::StyleRelation::AffectedByEmpty, Assembler::RegisterID(isEmptyResults));
</ins><span class="cx"> 
</span><del>-            FunctionCall functionCall(m_assembler, m_registerAllocator, m_stackAllocator, m_functionCalls);
-            functionCall.setFunctionAddress(setElementStyleFromContextIsAffectedByEmptyAndUpdateRenderStyleIfNecessary);
-            functionCall.setTwoArguments(checkingContext, isEmptyResults);
-            functionCall.call();
-        }
-
-        FunctionCall functionCall(m_assembler, m_registerAllocator, m_stackAllocator, m_functionCalls);
-        functionCall.setFunctionAddress(setElementStyleIsAffectedByEmpty);
-        functionCall.setOneArgument(elementAddressRegister);
-        functionCall.call();
-    } else {
-        {
-            LocalRegister checkingContext(m_registerAllocator);
-            skipMarking = jumpIfNotResolvingStyle(checkingContext);
-        }
-        FunctionCall functionCall(m_assembler, m_registerAllocator, m_stackAllocator, m_functionCalls);
-        functionCall.setFunctionAddress(setElementStyleIsAffectedByEmpty);
-        functionCall.setOneArgument(elementAddressRegister);
-        functionCall.call();
-    }
-    skipMarking.link(&amp;m_assembler);
-
</del><span class="cx">     failureCases.append(m_assembler.branchTest32(Assembler::Zero, isEmptyResults));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void SelectorCodeGenerator::generateElementIsFirstChild(Assembler::JumpList&amp; failureCases, const SelectorFragment&amp; fragment)
</del><ins>+void SelectorCodeGenerator::generateElementIsFirstChild(Assembler::JumpList&amp; failureCases)
</ins><span class="cx"> {
</span><span class="cx">     if (m_selectorContext == SelectorContext::QuerySelector) {
</span><span class="cx">         Assembler::JumpList successCase = jumpIfNoPreviousAdjacentElement();
</span><span class="lines">@@ -3216,22 +3140,14 @@
</span><span class="cx">     LocalRegister checkingContext(m_registerAllocator);
</span><span class="cx">     Assembler::Jump notResolvingStyle = jumpIfNotResolvingStyle(checkingContext);
</span><span class="cx"> 
</span><del>-    setNodeFlag(m_assembler, parentElement, Node::flagChildrenAffectedByFirstChildRulesFlag());
</del><ins>+    generateAddStyleRelation(checkingContext, parentElement, SelectorChecker::StyleRelation::ChildrenAffectedByFirstChildRules);
</ins><span class="cx">     m_registerAllocator.deallocateRegister(parentElement);
</span><span class="cx"> 
</span><span class="cx">     // The parent marking is unconditional. If the matching is not a success, we can now fail.
</span><span class="cx">     // Otherwise we need to apply setFirstChildState() on the RenderStyle.
</span><span class="cx">     failureCases.append(m_assembler.branchTest32(Assembler::NonZero, isFirstChildRegister));
</span><span class="cx"> 
</span><del>-    if (fragmentMatchesTheRightmostElement(m_selectorContext, fragment))
-        addFlagsToElementStyleFromContext(checkingContext, RenderStyle::NonInheritedFlags::setFirstChildStateFlags());
-    else {
-        FunctionCall functionCall(m_assembler, m_registerAllocator, m_stackAllocator, m_functionCalls);
-        functionCall.setFunctionAddress(setFirstChildState);
-        Assembler::RegisterID elementAddress = elementAddressRegister;
-        functionCall.setOneArgument(elementAddress);
-        functionCall.call();
-    }
</del><ins>+    generateAddStyleRelation(checkingContext, elementAddressRegister, SelectorChecker::StyleRelation::FirstChild);
</ins><span class="cx"> 
</span><span class="cx">     notResolvingStyle.link(&amp;m_assembler);
</span><span class="cx">     failureCases.append(m_assembler.branchTest32(Assembler::NonZero, isFirstChildRegister));
</span><span class="lines">@@ -3242,44 +3158,16 @@
</span><span class="cx">     return element-&gt;hovered() || InspectorInstrumentation::forcePseudoState(*element, CSSSelector::PseudoClassHover);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static bool elementIsHoveredForStyleResolution(Element* element, const SelectorChecker::CheckingContext* checkingContext)
-{
-    if (checkingContext-&gt;resolvingMode == SelectorChecker::Mode::ResolvingStyle)
-        element-&gt;setChildrenAffectedByHover();
-    return element-&gt;hovered() || InspectorInstrumentation::forcePseudoState(*element, CSSSelector::PseudoClassHover);
-}
-
</del><span class="cx"> void SelectorCodeGenerator::generateElementIsHovered(Assembler::JumpList&amp; failureCases, const SelectorFragment&amp; fragment)
</span><span class="cx"> {
</span><span class="cx">     generateSpecialFailureInQuirksModeForActiveAndHoverIfNeeded(failureCases, fragment);
</span><del>-    if (m_selectorContext == SelectorContext::QuerySelector) {
-        FunctionCall functionCall(m_assembler, m_registerAllocator, m_stackAllocator, m_functionCalls);
-        functionCall.setFunctionAddress(elementIsHovered);
-        functionCall.setOneArgument(elementAddressRegister);
-        failureCases.append(functionCall.callAndBranchOnBooleanReturnValue(Assembler::Zero));
-        return;
-    }
</del><span class="cx"> 
</span><del>-    if (fragmentMatchesTheRightmostElement(m_selectorContext, fragment)) {
-        LocalRegisterWithPreference checkingContext(m_registerAllocator, JSC::GPRInfo::argumentGPR1);
-        Assembler::Jump notResolvingStyle = jumpIfNotResolvingStyle(checkingContext);
-        addFlagsToElementStyleFromContext(checkingContext, RenderStyle::NonInheritedFlags::flagIsaffectedByHover());
-        notResolvingStyle.link(&amp;m_assembler);
</del><ins>+    generateAddStyleRelationIfResolvingStyle(elementAddressRegister, SelectorChecker::StyleRelation::AffectedByHover);
</ins><span class="cx"> 
</span><del>-        FunctionCall functionCall(m_assembler, m_registerAllocator, m_stackAllocator, m_functionCalls);
-        functionCall.setFunctionAddress(elementIsHovered);
-        functionCall.setOneArgument(elementAddressRegister);
-        failureCases.append(functionCall.callAndBranchOnBooleanReturnValue(Assembler::Zero));
-    } else {
-        Assembler::RegisterID checkingContext = m_registerAllocator.allocateRegisterWithPreference(JSC::GPRInfo::argumentGPR1);
-        loadCheckingContext(checkingContext);
-        m_registerAllocator.deallocateRegister(checkingContext);
-
-        FunctionCall functionCall(m_assembler, m_registerAllocator, m_stackAllocator, m_functionCalls);
-        functionCall.setFunctionAddress(elementIsHoveredForStyleResolution);
-        functionCall.setTwoArguments(elementAddressRegister, checkingContext);
-        failureCases.append(functionCall.callAndBranchOnBooleanReturnValue(Assembler::Zero));
-    }
</del><ins>+    FunctionCall functionCall(m_assembler, m_registerAllocator, m_stackAllocator, m_functionCalls);
+    functionCall.setFunctionAddress(elementIsHovered);
+    functionCall.setOneArgument(elementAddressRegister);
+    failureCases.append(functionCall.callAndBranchOnBooleanReturnValue(Assembler::Zero));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void SelectorCodeGenerator::generateElementIsInLanguage(Assembler::JumpList&amp; failureCases, const SelectorFragment&amp; fragment)
</span><span class="lines">@@ -3300,14 +3188,8 @@
</span><span class="cx">     failureCases.append(functionCall.callAndBranchOnBooleanReturnValue(Assembler::Zero));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static void setLastChildState(Element* element)
</del><ins>+void SelectorCodeGenerator::generateElementIsLastChild(Assembler::JumpList&amp; failureCases)
</ins><span class="cx"> {
</span><del>-    if (RenderStyle* style = element-&gt;renderStyle())
-        style-&gt;setLastChildState();
-}
-
-void SelectorCodeGenerator::generateElementIsLastChild(Assembler::JumpList&amp; failureCases, const SelectorFragment&amp; fragment)
-{
</del><span class="cx">     if (m_selectorContext == SelectorContext::QuerySelector) {
</span><span class="cx">         Assembler::JumpList successCase = jumpIfNoNextAdjacentElement();
</span><span class="cx">         failureCases.append(m_assembler.jump());
</span><span class="lines">@@ -3342,37 +3224,21 @@
</span><span class="cx">     LocalRegister checkingContext(m_registerAllocator);
</span><span class="cx">     Assembler::Jump notResolvingStyle = jumpIfNotResolvingStyle(checkingContext);
</span><span class="cx"> 
</span><del>-    setNodeFlag(m_assembler, parentElement, Node::flagChildrenAffectedByLastChildRulesFlag());
</del><ins>+    generateAddStyleRelation(checkingContext, parentElement, SelectorChecker::StyleRelation::ChildrenAffectedByLastChildRules);
</ins><span class="cx">     m_registerAllocator.deallocateRegister(parentElement);
</span><span class="cx"> 
</span><span class="cx">     // The parent marking is unconditional. If the matching is not a success, we can now fail.
</span><span class="cx">     // Otherwise we need to apply setLastChildState() on the RenderStyle.
</span><span class="cx">     failureCases.append(m_assembler.branchTest32(Assembler::NonZero, isLastChildRegister));
</span><span class="cx"> 
</span><del>-    if (fragmentMatchesTheRightmostElement(m_selectorContext, fragment))
-        addFlagsToElementStyleFromContext(checkingContext, RenderStyle::NonInheritedFlags::setLastChildStateFlags());
-    else {
-        FunctionCall functionCall(m_assembler, m_registerAllocator, m_stackAllocator, m_functionCalls);
-        functionCall.setFunctionAddress(setLastChildState);
-        Assembler::RegisterID elementAddress = elementAddressRegister;
-        functionCall.setOneArgument(elementAddress);
-        functionCall.call();
-    }
</del><ins>+    generateAddStyleRelation(checkingContext, elementAddressRegister, SelectorChecker::StyleRelation::LastChild);
</ins><span class="cx"> 
</span><span class="cx">     notResolvingStyle.link(&amp;m_assembler);
</span><span class="cx">     failureCases.append(m_assembler.branchTest32(Assembler::NonZero, isLastChildRegister));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static void setOnlyChildState(Element* element)
</del><ins>+void SelectorCodeGenerator::generateElementIsOnlyChild(Assembler::JumpList&amp; failureCases)
</ins><span class="cx"> {
</span><del>-    if (RenderStyle* style = element-&gt;renderStyle()) {
-        style-&gt;setFirstChildState();
-        style-&gt;setLastChildState();
-    }
-}
-
-void SelectorCodeGenerator::generateElementIsOnlyChild(Assembler::JumpList&amp; failureCases, const SelectorFragment&amp; fragment)
-{
</del><span class="cx">     // Is Only child is pretty much a combination of isFirstChild + isLastChild. The main difference is that tree marking is combined.
</span><span class="cx">     if (m_selectorContext == SelectorContext::QuerySelector) {
</span><span class="cx">         Assembler::JumpList previousSuccessCase = jumpIfNoPreviousAdjacentElement();
</span><span class="lines">@@ -3417,55 +3283,38 @@
</span><span class="cx">     LocalRegister checkingContext(m_registerAllocator);
</span><span class="cx">     Assembler::Jump notResolvingStyle = jumpIfNotResolvingStyle(checkingContext);
</span><span class="cx"> 
</span><del>-    setNodeFlag(m_assembler, parentElement, Node::flagChildrenAffectedByFirstChildRulesFlag() | Node::flagChildrenAffectedByLastChildRulesFlag());
</del><ins>+    generateAddStyleRelation(checkingContext, parentElement, SelectorChecker::StyleRelation::ChildrenAffectedByFirstChildRules);
+    generateAddStyleRelation(checkingContext, parentElement, SelectorChecker::StyleRelation::ChildrenAffectedByLastChildRules);
+
</ins><span class="cx">     m_registerAllocator.deallocateRegister(parentElement);
</span><span class="cx"> 
</span><span class="cx">     // The parent marking is unconditional. If the matching is not a success, we can now fail.
</span><span class="cx">     // Otherwise we need to apply setLastChildState() on the RenderStyle.
</span><span class="cx">     failureCases.append(m_assembler.branchTest32(Assembler::NonZero, isOnlyChildRegister));
</span><span class="cx"> 
</span><del>-    if (fragmentMatchesTheRightmostElement(m_selectorContext, fragment))
-        addFlagsToElementStyleFromContext(checkingContext, RenderStyle::NonInheritedFlags::setFirstChildStateFlags() | RenderStyle::NonInheritedFlags::setLastChildStateFlags());
-    else {
-        FunctionCall functionCall(m_assembler, m_registerAllocator, m_stackAllocator, m_functionCalls);
-        functionCall.setFunctionAddress(setOnlyChildState);
-        Assembler::RegisterID elementAddress = elementAddressRegister;
-        functionCall.setOneArgument(elementAddress);
-        functionCall.call();
-    }
</del><ins>+    generateAddStyleRelation(checkingContext, elementAddressRegister, SelectorChecker::StyleRelation::FirstChild);
+    generateAddStyleRelation(checkingContext, elementAddressRegister, SelectorChecker::StyleRelation::LastChild);
</ins><span class="cx"> 
</span><span class="cx">     notResolvingStyle.link(&amp;m_assembler);
</span><span class="cx">     failureCases.append(m_assembler.branchTest32(Assembler::NonZero, isOnlyChildRegister));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static bool makeContextStyleUniqueIfNecessaryAndTestIsPlaceholderShown(Element* element, const SelectorChecker::CheckingContext* checkingContext)
</del><ins>+static bool makeContextStyleUniqueIfNecessaryAndTestIsPlaceholderShown(Element* element, SelectorChecker::CheckingContext* checkingContext)
</ins><span class="cx"> {
</span><span class="cx">     if (is&lt;HTMLTextFormControlElement&gt;(*element)) {
</span><span class="cx">         if (checkingContext-&gt;resolvingMode == SelectorChecker::Mode::ResolvingStyle)
</span><del>-            checkingContext-&gt;elementStyle-&gt;setUnique();
</del><ins>+            checkingContext-&gt;styleRelations.append({ *element, SelectorChecker::StyleRelation::Unique, 1 });
</ins><span class="cx">         return downcast&lt;HTMLTextFormControlElement&gt;(*element).isPlaceholderVisible();
</span><span class="cx">     }
</span><span class="cx">     return false;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static bool makeElementStyleUniqueIfNecessaryAndTestIsPlaceholderShown(Element* element, const SelectorChecker::CheckingContext* checkingContext)
-{
-    if (is&lt;HTMLTextFormControlElement&gt;(*element)) {
-        if (checkingContext-&gt;resolvingMode == SelectorChecker::Mode::ResolvingStyle) {
-            if (RenderStyle* style = element-&gt;renderStyle())
-                style-&gt;setUnique();
-        }
-        return downcast&lt;HTMLTextFormControlElement&gt;(*element).isPlaceholderVisible();
-    }
-    return false;
-}
-
</del><span class="cx"> static bool isPlaceholderShown(Element* element)
</span><span class="cx"> {
</span><span class="cx">     return is&lt;HTMLTextFormControlElement&gt;(*element) &amp;&amp; downcast&lt;HTMLTextFormControlElement&gt;(*element).isPlaceholderVisible();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void SelectorCodeGenerator::generateElementHasPlaceholderShown(Assembler::JumpList&amp; failureCases, const SelectorFragment&amp; fragment)
</del><ins>+void SelectorCodeGenerator::generateElementHasPlaceholderShown(Assembler::JumpList&amp; failureCases)
</ins><span class="cx"> {
</span><span class="cx">     if (m_selectorContext == SelectorContext::QuerySelector) {
</span><span class="cx">         FunctionCall functionCall(m_assembler, m_registerAllocator, m_stackAllocator, m_functionCalls);
</span><span class="lines">@@ -3480,10 +3329,7 @@
</span><span class="cx">     m_registerAllocator.deallocateRegister(checkingContext);
</span><span class="cx"> 
</span><span class="cx">     FunctionCall functionCall(m_assembler, m_registerAllocator, m_stackAllocator, m_functionCalls);
</span><del>-    if (fragmentMatchesTheRightmostElement(m_selectorContext, fragment))
-        functionCall.setFunctionAddress(makeContextStyleUniqueIfNecessaryAndTestIsPlaceholderShown);
-    else
-        functionCall.setFunctionAddress(makeElementStyleUniqueIfNecessaryAndTestIsPlaceholderShown);
</del><ins>+    functionCall.setFunctionAddress(makeContextStyleUniqueIfNecessaryAndTestIsPlaceholderShown);
</ins><span class="cx">     functionCall.setTwoArguments(elementAddressRegister, checkingContext);
</span><span class="cx">     failureCases.append(functionCall.callAndBranchOnBooleanReturnValue(Assembler::Zero));
</span><span class="cx"> }
</span><span class="lines">@@ -3585,11 +3431,6 @@
</span><span class="cx">     failureCases.append(m_assembler.branchTest32(Assembler::Zero, Assembler::Address(elementAddressRegister, Node::nodeFlagsMemoryOffset()), Assembler::TrustedImm32(Node::flagIsLink())));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static void setElementChildIndex(Element* element, int index)
-{
-    element-&gt;setChildIndex(index);
-}
-
</del><span class="cx"> static bool nthFilterIsAlwaysSatisified(int a, int b)
</span><span class="cx"> {
</span><span class="cx">     // Anything modulo 1 is zero. Unless b restricts the range, this does not filter anything out.
</span><span class="lines">@@ -3616,7 +3457,7 @@
</span><span class="cx">         return;
</span><span class="cx"> 
</span><span class="cx">     if (!isAdjacentRelation(fragment.relationToRightFragment))
</span><del>-        markElementIfResolvingStyle(elementAddressRegister, Node::flagStyleIsAffectedByPreviousSibling());
</del><ins>+        generateAddStyleRelationIfResolvingStyle(elementAddressRegister, SelectorChecker::StyleRelation::AffectedByPreviousSibling);
</ins><span class="cx"> 
</span><span class="cx">     // Setup the counter at 1.
</span><span class="cx">     LocalRegisterWithPreference elementCounter(m_registerAllocator, JSC::GPRInfo::argumentGPR1);
</span><span class="lines">@@ -3634,7 +3475,7 @@
</span><span class="cx"> 
</span><span class="cx">         Assembler::JumpList noCachedChildIndexCases;
</span><span class="cx">         generateWalkToPreviousAdjacentElement(noMoreSiblingsCases, previousSibling);
</span><del>-        markElementIfResolvingStyle(previousSibling, Node::flagAffectsNextSiblingElementStyle());
</del><ins>+        generateAddStyleRelationIfResolvingStyle(previousSibling, SelectorChecker::StyleRelation::AffectsNextSibling);
</ins><span class="cx">         noCachedChildIndexCases.append(m_assembler.branchTest32(Assembler::Zero, Assembler::Address(previousSibling, Node::nodeFlagsMemoryOffset()), Assembler::TrustedImm32(Node::flagHasRareData())));
</span><span class="cx">         {
</span><span class="cx">             LocalRegister elementRareData(m_registerAllocator);
</span><span class="lines">@@ -3650,26 +3491,14 @@
</span><span class="cx"> 
</span><span class="cx">         Assembler::Label loopStart = m_assembler.label();
</span><span class="cx">         generateWalkToPreviousAdjacentElement(noMoreSiblingsCases, previousSibling);
</span><del>-        markElementIfResolvingStyle(previousSibling, Node::flagAffectsNextSiblingElementStyle());
</del><ins>+        generateAddStyleRelationIfResolvingStyle(previousSibling, SelectorChecker::StyleRelation::AffectsNextSibling);
</ins><span class="cx">         m_assembler.add32(Assembler::TrustedImm32(1), elementCounter);
</span><span class="cx">         m_assembler.jump().linkTo(loopStart, &amp;m_assembler);
</span><span class="cx">         noMoreSiblingsCases.link(&amp;m_assembler);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    // Tree marking when doing style resolution.
-    if (m_selectorContext != SelectorContext::QuerySelector) {
-        LocalRegister checkingContext(m_registerAllocator);
-        Assembler::Jump notResolvingStyle = jumpIfNotResolvingStyle(checkingContext);
</del><ins>+    generateAddStyleRelationIfResolvingStyle(elementAddressRegister, SelectorChecker::StyleRelation::NthChildIndex, Assembler::RegisterID(elementCounter));
</ins><span class="cx"> 
</span><del>-        Assembler::RegisterID elementAddress = elementAddressRegister;
-        FunctionCall functionCall(m_assembler, m_registerAllocator, m_stackAllocator, m_functionCalls);
-        functionCall.setFunctionAddress(setElementChildIndex);
-        functionCall.setTwoArguments(elementAddress, elementCounter);
-        functionCall.call();
-
-        notResolvingStyle.link(&amp;m_assembler);
-    }
-
</del><span class="cx">     for (const auto&amp; slot : validSubsetFilters)
</span><span class="cx">         generateNthFilterTest(failureCases, elementCounter, slot.first, slot.second);
</span><span class="cx"> }
</span><span class="lines">@@ -3695,7 +3524,7 @@
</span><span class="cx">         return;
</span><span class="cx"> 
</span><span class="cx">     if (!isAdjacentRelation(fragment.relationToRightFragment))
</span><del>-        markElementIfResolvingStyle(elementAddressRegister, Node::flagStyleIsAffectedByPreviousSibling());
</del><ins>+        generateAddStyleRelationIfResolvingStyle(elementAddressRegister, SelectorChecker::StyleRelation::AffectedByPreviousSibling);
</ins><span class="cx"> 
</span><span class="cx">     for (const NthChildOfSelectorInfo* nthChildOfSelectorInfo : validSubsetFilters) {
</span><span class="cx">         // Setup the counter at 1.
</span><span class="lines">@@ -3712,7 +3541,7 @@
</span><span class="cx">             Assembler::Label loopStart = m_assembler.label();
</span><span class="cx"> 
</span><span class="cx">             generateWalkToPreviousAdjacentElement(noMoreSiblingsCases, previousSibling);
</span><del>-            markElementIfResolvingStyle(previousSibling, Node::flagAffectsNextSiblingElementStyle());
</del><ins>+            generateAddStyleRelationIfResolvingStyle(previousSibling, SelectorChecker::StyleRelation::AffectsNextSibling);
</ins><span class="cx"> 
</span><span class="cx">             Assembler::JumpList localFailureCases;
</span><span class="cx">             generateElementMatchesSelectorList(localFailureCases, previousSibling, nthChildOfSelectorInfo-&gt;selectorList);
</span><span class="lines">@@ -3727,11 +3556,6 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static void setChildrenAffectedByBackwardPositionalRules(Element* element)
-{
-    element-&gt;setChildrenAffectedByBackwardPositionalRules();
-}
-
</del><span class="cx"> void SelectorCodeGenerator::generateElementIsNthLastChild(Assembler::JumpList&amp; failureCases, const SelectorFragment&amp; fragment)
</span><span class="cx"> {
</span><span class="cx">     Vector&lt;std::pair&lt;int, int&gt;, 32&gt; validSubsetFilters;
</span><span class="lines">@@ -3740,21 +3564,8 @@
</span><span class="cx">         LocalRegister parentElement(m_registerAllocator);
</span><span class="cx">         generateWalkToParentElement(failureCases, parentElement);
</span><span class="cx"> 
</span><del>-        if (m_selectorContext != SelectorContext::QuerySelector) {
-            Assembler::Jump skipMarking;
-            {
-                LocalRegister checkingContext(m_registerAllocator);
-                skipMarking = jumpIfNotResolvingStyle(checkingContext);
-            }
</del><ins>+        generateAddStyleRelationIfResolvingStyle(parentElement, SelectorChecker::StyleRelation::ChildrenAffectedByBackwardPositionalRules);
</ins><span class="cx"> 
</span><del>-            FunctionCall functionCall(m_assembler, m_registerAllocator, m_stackAllocator, m_functionCalls);
-            functionCall.setFunctionAddress(setChildrenAffectedByBackwardPositionalRules);
-            functionCall.setOneArgument(parentElement);
-            functionCall.call();
-
-            skipMarking.link(&amp;m_assembler);
-        }
-
</del><span class="cx">         failureCases.append(m_assembler.branchTest32(Assembler::Zero, Assembler::Address(parentElement, Node::nodeFlagsMemoryOffset()), Assembler::TrustedImm32(Node::flagIsParsingChildrenFinished())));
</span><span class="cx"> 
</span><span class="cx">         for (const auto&amp; slot : fragment.nthLastChildFilters) {
</span><span class="lines">@@ -3788,13 +3599,6 @@
</span><span class="cx">         generateNthFilterTest(failureCases, elementCounter, slot.first, slot.second);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static void setParentAffectedByLastChildOf(Element* parentElement)
-{
-    ASSERT(parentElement);
-    parentElement-&gt;setChildrenAffectedByPropertyBasedBackwardPositionalRules();
-    parentElement-&gt;setChildrenAffectedByBackwardPositionalRules();
-}
-
</del><span class="cx"> void SelectorCodeGenerator::generateElementIsNthLastChildOf(Assembler::JumpList&amp; failureCases, const SelectorFragment&amp; fragment)
</span><span class="cx"> {
</span><span class="cx">     Vector&lt;const NthChildOfSelectorInfo*&gt; validSubsetFilters;
</span><span class="lines">@@ -3803,21 +3607,8 @@
</span><span class="cx">         LocalRegister parentElement(m_registerAllocator);
</span><span class="cx">         generateWalkToParentElement(failureCases, parentElement);
</span><span class="cx"> 
</span><del>-        if (m_selectorContext != SelectorContext::QuerySelector) {
-            Assembler::Jump skipMarking;
-            {
-                LocalRegister checkingContext(m_registerAllocator);
-                skipMarking = jumpIfNotResolvingStyle(checkingContext);
-            }
</del><ins>+        generateAddStyleRelationIfResolvingStyle(parentElement, SelectorChecker::StyleRelation::ChildrenAffectedByPropertyBasedBackwardPositionalRules);
</ins><span class="cx"> 
</span><del>-            FunctionCall functionCall(m_assembler, m_registerAllocator, m_stackAllocator, m_functionCalls);
-            functionCall.setFunctionAddress(setParentAffectedByLastChildOf);
-            functionCall.setOneArgument(parentElement);
-            functionCall.call();
-
-            skipMarking.link(&amp;m_assembler);
-        }
-
</del><span class="cx">         failureCases.append(m_assembler.branchTest32(Assembler::Zero, Assembler::Address(parentElement, Node::nodeFlagsMemoryOffset()), Assembler::TrustedImm32(Node::flagIsParsingChildrenFinished())));
</span><span class="cx"> 
</span><span class="cx">         // The initial element must match the selector list.
</span><span class="lines">@@ -4003,7 +3794,11 @@
</span><span class="cx">     PseudoId dynamicPseudo = CSSSelector::pseudoId(fragment.pseudoElementSelector-&gt;pseudoElementType());
</span><span class="cx">     if (dynamicPseudo &lt; FIRST_INTERNAL_PSEUDOID) {
</span><span class="cx">         failureCases.append(branchOnResolvingModeWithCheckingContext(Assembler::NotEqual, SelectorChecker::Mode::ResolvingStyle, checkingContext));
</span><del>-        addFlagsToElementStyleFromContext(checkingContext, RenderStyle::NonInheritedFlags::flagPseudoStyle(dynamicPseudo));
</del><ins>+
+        Assembler::Address pseudoIDSetAddress(checkingContext, OBJECT_OFFSETOF(SelectorChecker::CheckingContext, pseudoIDSet));
+        auto pseudoIDSetDataAddress = pseudoIDSetAddress.withOffset(PseudoIdSet::dataMemoryOffset());
+        PseudoIdSet value { dynamicPseudo };
+        m_assembler.store32(Assembler::TrustedImm32(value.data()), pseudoIDSetDataAddress);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // We have a pseudoElementSelector, we are not in CollectingRulesIgnoringVirtualPseudoElements so
</span></span></pre></div>
<a id="trunkSourceWebCoredomSelectorQuerycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/SelectorQuery.cpp (195292 => 195293)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/SelectorQuery.cpp        2016-01-19 17:20:59 UTC (rev 195292)
+++ trunk/Source/WebCore/dom/SelectorQuery.cpp        2016-01-19 17:39:20 UTC (rev 195293)
</span><span class="lines">@@ -118,7 +118,7 @@
</span><span class="cx">     SelectorChecker::CheckingContext selectorCheckingContext(SelectorChecker::Mode::QueryingRules);
</span><span class="cx">     selectorCheckingContext.scope = rootNode.isDocumentNode() ? nullptr : &amp;rootNode;
</span><span class="cx">     unsigned ignoredSpecificity;
</span><del>-    return selectorChecker.match(selectorData.selector, &amp;element, selectorCheckingContext, ignoredSpecificity);
</del><ins>+    return selectorChecker.match(*selectorData.selector, element, selectorCheckingContext, ignoredSpecificity);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> inline Element* SelectorDataList::selectorClosest(const SelectorData&amp; selectorData, Element&amp; element, const ContainerNode&amp; rootNode) const
</span><span class="lines">@@ -126,11 +126,10 @@
</span><span class="cx">     SelectorChecker selectorChecker(element.document());
</span><span class="cx">     SelectorChecker::CheckingContext selectorCheckingContext(SelectorChecker::Mode::QueryingRules);
</span><span class="cx">     selectorCheckingContext.scope = rootNode.isDocumentNode() ? nullptr : &amp;rootNode;
</span><del>-    Element* currentNode = &amp;element;
</del><span class="cx">     unsigned ignoredSpecificity;
</span><del>-    if (!selectorChecker.match(selectorData.selector, currentNode, selectorCheckingContext, ignoredSpecificity))
</del><ins>+    if (!selectorChecker.match(*selectorData.selector, element, selectorCheckingContext, ignoredSpecificity))
</ins><span class="cx">         return nullptr;
</span><del>-    return currentNode;
</del><ins>+    return &amp;element;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool SelectorDataList::matches(Element&amp; targetElement) const
</span></span></pre></div>
<a id="trunkSourceWebCoreinspectorInspectorCSSAgentcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/inspector/InspectorCSSAgent.cpp (195292 => 195293)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/inspector/InspectorCSSAgent.cpp        2016-01-19 17:20:59 UTC (rev 195292)
+++ trunk/Source/WebCore/inspector/InspectorCSSAgent.cpp        2016-01-19 17:39:20 UTC (rev 195293)
</span><span class="lines">@@ -1050,7 +1050,7 @@
</span><span class="cx">         int index = 0;
</span><span class="cx">         for (const CSSSelector* selector = selectorList.first(); selector; selector = CSSSelectorList::next(selector)) {
</span><span class="cx">             unsigned ignoredSpecificity;
</span><del>-            bool matched = selectorChecker.match(selector, element, context, ignoredSpecificity);
</del><ins>+            bool matched = selectorChecker.match(*selector, *element, context, ignoredSpecificity);
</ins><span class="cx">             if (matched)
</span><span class="cx">                 matchingSelectors-&gt;addItem(index);
</span><span class="cx">             ++index;
</span></span></pre></div>
<a id="trunkSourceWebCoreinspectorInspectorStyleSheetcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/inspector/InspectorStyleSheet.cpp (195292 => 195293)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/inspector/InspectorStyleSheet.cpp        2016-01-19 17:20:59 UTC (rev 195292)
+++ trunk/Source/WebCore/inspector/InspectorStyleSheet.cpp        2016-01-19 17:39:20 UTC (rev 195293)
</span><span class="lines">@@ -862,7 +862,7 @@
</span><span class="cx">         SelectorChecker selectorChecker(element-&gt;document());
</span><span class="cx"> 
</span><span class="cx">         unsigned specificity;
</span><del>-        bool okay = selectorChecker.match(&amp;selector, element, context, specificity);
</del><ins>+        bool okay = selectorChecker.match(selector, *element, context, specificity);
</ins><span class="cx">         if (!okay)
</span><span class="cx">             specificity = selector.staticSpecificity(okay);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingstyleRenderStyleConstantsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/style/RenderStyleConstants.h (195292 => 195293)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/style/RenderStyleConstants.h        2016-01-19 17:20:59 UTC (rev 195292)
+++ trunk/Source/WebCore/rendering/style/RenderStyleConstants.h        2016-01-19 17:39:20 UTC (rev 195293)
</span><span class="lines">@@ -139,6 +139,9 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     unsigned data() const { return m_data; }
</span><ins>+
+    static ptrdiff_t dataMemoryOffset() { return OBJECT_OFFSETOF(PseudoIdSet, m_data); }
+
</ins><span class="cx"> private:
</span><span class="cx">     explicit PseudoIdSet(unsigned rawPseudoIdSet)
</span><span class="cx">         : m_data(rawPseudoIdSet)
</span></span></pre>
</div>
</div>

</body>
</html>