<!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 <antti@apple.com>
+
+ 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 <cgarcia@igalia.com>
</span><span class="cx">
</span><span class="cx"> Unreviewed. Fix GTK+ build with GTK+ < 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 "CSSValueKeywords.h"
</span><span class="cx"> #include "HTMLElement.h"
</span><span class="cx"> #include "InspectorInstrumentation.h"
</span><ins>+#include "NodeRenderStyle.h"
</ins><span class="cx"> #include "RenderRegion.h"
</span><span class="cx"> #include "SVGElement.h"
</span><span class="cx"> #include "SelectorCompiler.h"
</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(&m_element, &context, &specificity);
</del><ins>+ selectorMatches = selectorChecker(&m_element, &context, &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(), &m_element, context, specificity);
</del><ins>+ commitStyleRelations(context.styleRelations);
+
+ if (context.pseudoIDSet)
+ m_style->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& styleRelations)
+{
+ for (auto& relation : styleRelations) {
+ switch (relation.type) {
+ case SelectorChecker::StyleRelation::AffectedByActive:
+ if (&relation.element == &m_element)
+ m_style->setAffectedByActive();
+ else
+ relation.element.setChildrenAffectedByActive();
+ break;
+ case SelectorChecker::StyleRelation::AffectedByDrag:
+ if (&relation.element == &m_element)
+ m_style->setAffectedByDrag();
+ else
+ relation.element.setChildrenAffectedByDrag();
+ break;
+ case SelectorChecker::StyleRelation::AffectedByEmpty:
+ relation.element.setStyleAffectedByEmpty();
+ if (&relation.element == &m_element)
+ m_style->setEmptyState(relation.value);
+ break;
+ case SelectorChecker::StyleRelation::AffectedByHover:
+ if (&relation.element == &m_element)
+ m_style->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 (&relation.element == &m_element)
+ m_style->setFirstChildState();
+ else if (auto* style = relation.element.renderStyle())
+ style->setFirstChildState();
+ break;
+ case SelectorChecker::StyleRelation::LastChild:
+ if (&relation.element == &m_element)
+ m_style->setLastChildState();
+ else if (auto* style = relation.element.renderStyle())
+ style->setLastChildState();
+ break;
+ case SelectorChecker::StyleRelation::NthChildIndex:
+ relation.element.setChildIndex(relation.value);
+ break;
+ case SelectorChecker::StyleRelation::Unique:
+ if (&relation.element == &m_element)
+ m_style->setUnique();
+ else if (auto* style = relation.element.renderStyle())
+ style->setUnique();
+ break;
+ }
+ }
+}
+
</ins><span class="cx"> void ElementRuleCollector::collectMatchingRulesForList(const RuleSet::RuleDataVector* rules, const MatchRequest& matchRequest, StyleResolver::RuleRange& 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&);
</span><span class="cx">
</span><ins>+ void commitStyleRelations(const SelectorChecker::StyleRelations&);
+
</ins><span class="cx"> Element& m_element;
</span><span class="cx"> RenderStyle* m_style;
</span><span class="cx"> const DocumentRuleSets& 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 <ap@webkit.org>
</span><span class="cx"> * Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org>
</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 "HTMLProgressElement.h"
</span><span class="cx"> #include "HTMLStyleElement.h"
</span><span class="cx"> #include "InspectorInstrumentation.h"
</span><del>-#include "NodeRenderStyle.h"
</del><span class="cx"> #include "Page.h"
</span><span class="cx"> #include "RenderElement.h"
</span><del>-#include "RenderStyle.h"
</del><span class="cx"> #include "SelectorCheckerTestFunctions.h"
</span><span class="cx"> #include "ShadowRoot.h"
</span><span class="cx"> #include "StyledElement.h"
</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& 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& selector, const Element& element, VisitedMatchType visitedMatchType, PseudoId pseudoId)
+ : selector(&selector)
+ , element(&element)
+ , visitedMatchType(visitedMatchType)
+ , firstSelectorOfTheFragment(&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& checkingContext, const Element& 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<Element&>(element), type, value });
+}
+
</ins><span class="cx"> static inline bool isFirstChildElement(const Element& 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& element, const QualifiedName& type, bool isResolvingStyle)
</del><ins>+static inline bool isFirstOfType(SelectorChecker::CheckingContext& checkingContext, const Element& element, const QualifiedName& type)
</ins><span class="cx"> {
</span><del>- for (Element* sibling = ElementTraversal::previousSibling(element); sibling; sibling = ElementTraversal::previousSibling(*sibling)) {
- if (isResolvingStyle)
- sibling->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->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& element, bool isResolvingStyle)
</del><ins>+static inline int countElementsBefore(SelectorChecker::CheckingContext& checkingContext, const Element& 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->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->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& element, const QualifiedName& type, bool isResolvingStyle)
</del><ins>+static inline int countElementsOfTypeBefore(SelectorChecker::CheckingContext& checkingContext, const Element& element, const QualifiedName& 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->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->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& providedContext, unsigned& specificity) const
</del><ins>+bool SelectorChecker::match(const CSSSelector& selector, const Element& element, CheckingContext& checkingContext, unsigned& 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 && !pseudoIdSet.has(context.pseudoId))
</del><ins>+ if (checkingContext.pseudoId != NOPSEUDO && !pseudoIdSet.has(checkingContext.pseudoId))
</ins><span class="cx"> return false;
</span><span class="cx">
</span><del>- if (context.pseudoId == NOPSEUDO && pseudoIdSet) {
</del><ins>+ if (checkingContext.pseudoId == NOPSEUDO && pseudoIdSet) {
</ins><span class="cx"> PseudoIdSet publicPseudoIdSet = pseudoIdSet & PseudoIdSet::fromMask(PUBLIC_PSEUDOID_MASK);
</span><del>- if (context.resolvingMode == Mode::ResolvingStyle && publicPseudoIdSet)
- context.elementStyle->setHasPseudoStyles(publicPseudoIdSet);
</del><ins>+ if (checkingContext.resolvingMode == Mode::ResolvingStyle && 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& context)
</del><ins>+static SelectorChecker::LocalContext localContextForParent(const SelectorChecker::LocalContext& 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->isLink())
</span><span class="cx"> updatedContext.visitedMatchType = VisitedMatchType::Disabled;
</span><span class="cx"> updatedContext.element = context.element->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& context, PseudoIdSet& dynamicPseudoIdSet, unsigned& specificity) const
</del><ins>+SelectorChecker::MatchResult SelectorChecker::matchRecursively(CheckingContext& checkingContext, const LocalContext& context, PseudoIdSet& dynamicPseudoIdSet, unsigned& 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->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->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 && !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 && !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->setStyleIsAffectedByPreviousSibling();
</del><ins>+ addStyleRelation(checkingContext, *context.element, StyleRelation::AffectedByPreviousSibling);
</ins><span class="cx">
</span><span class="cx"> Element* previousElement = context.element->previousElementSibling();
</span><span class="cx"> if (!previousElement)
</span><span class="cx"> return MatchResult::fails(Match::SelectorFailsAllSiblings);
</span><del>- if (context.resolvingMode == Mode::ResolvingStyle)
- previousElement->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 && !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->setStyleIsAffectedByPreviousSibling();
</del><ins>+ addStyleRelation(checkingContext, *context.element, StyleRelation::AffectedByPreviousSibling);
+
</ins><span class="cx"> nextContext.element = context.element->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->previousElementSibling()) {
</span><del>- if (context.resolvingMode == Mode::ResolvingStyle)
- nextContext.element->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 && !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) && dynamicPseudoIdSet
</del><ins>+ if ((context.isMatchElement || checkingContext.resolvingMode == Mode::CollectingRules) && dynamicPseudoIdSet
</ins><span class="cx"> && !nextContext.hasSelectionPseudo
</span><span class="cx"> && !(nextContext.hasScrollbarPseudo && nextContext.selector->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& selectorAttr, bool caseSensitive)
</del><ins>+static bool anyAttributeMatches(const Element* element, const CSSSelector* selector, const QualifiedName& selectorAttr, bool caseSensitive)
</ins><span class="cx"> {
</span><span class="cx"> ASSERT(element->hasAttributesWithoutUpdate());
</span><span class="cx"> for (const Attribute& attribute : element->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& context)
</del><ins>+static bool canMatchHoverOrActiveInQuirksMode(const SelectorChecker::LocalContext& 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& context, PseudoIdSet& dynamicPseudoIdSet, MatchType& matchType, unsigned& specificity) const
</del><ins>+bool SelectorChecker::checkOne(CheckingContext& checkingContext, const LocalContext& context, PseudoIdSet& dynamicPseudoIdSet, MatchType& matchType, unsigned& specificity) const
</ins><span class="cx"> {
</span><del>- Element* const & element = context.element;
</del><ins>+ const Element* element = context.element;
</ins><span class="cx"> const CSSSelector* const & 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->selectorList();
</span><span class="cx">
</span><span class="cx"> for (const CSSSelector* subselector = selectorList->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->setStyleAffectedByEmpty();
- if (context.elementStyle)
- context.elementStyle->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->parentElement()) {
- bool result = isFirstChildElement(*element);
- if (context.resolvingMode == Mode::ResolvingStyle) {
- RenderStyle* childStyle = context.elementStyle ? context.elementStyle : element->renderStyle();
- parentElement->setChildrenAffectedByFirstChildRules();
- if (result && childStyle)
- childStyle->setFirstChildState();
- }
- return result;
</del><ins>+ if (const Element* parentElement = element->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->parentElement()) {
</span><del>- if (context.resolvingMode == Mode::ResolvingStyle)
- element->setStyleIsAffectedByPreviousSibling();
-
- return isFirstOfType(*element, element->tagQName(), context.resolvingMode == Mode::ResolvingStyle);
</del><ins>+ addStyleRelation(checkingContext, *element, StyleRelation::AffectedByPreviousSibling);
+ return isFirstOfType(checkingContext, *element, element->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->parentElement()) {
- bool result = parentElement->isFinishedParsingChildren() && isLastChildElement(*element);
- if (context.resolvingMode == Mode::ResolvingStyle) {
- RenderStyle* childStyle = context.elementStyle ? context.elementStyle : element->renderStyle();
- parentElement->setChildrenAffectedByLastChildRules();
- if (result && childStyle)
- childStyle->setLastChildState();
- }
- return result;
</del><ins>+ if (const Element* parentElement = element->parentElement()) {
+ bool isLastChild = parentElement->isFinishedParsingChildren() && 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->parentElement()) {
</span><del>- if (context.resolvingMode == Mode::ResolvingStyle)
- parentElement->setChildrenAffectedByBackwardPositionalRules();
</del><ins>+ addStyleRelation(checkingContext, *parentElement, StyleRelation::ChildrenAffectedByBackwardPositionalRules);
</ins><span class="cx"> if (!parentElement->isFinishedParsingChildren())
</span><span class="cx"> return false;
</span><span class="cx"> return isLastOfType(*element, element->tagQName());
</span><span class="lines">@@ -723,28 +711,23 @@
</span><span class="cx"> if (Element* parentElement = element->parentElement()) {
</span><span class="cx"> bool firstChild = isFirstChildElement(*element);
</span><span class="cx"> bool onlyChild = firstChild && parentElement->isFinishedParsingChildren() && isLastChildElement(*element);
</span><del>- if (context.resolvingMode == Mode::ResolvingStyle) {
- RenderStyle* childStyle = context.elementStyle ? context.elementStyle : element->renderStyle();
- parentElement->setChildrenAffectedByFirstChildRules();
- parentElement->setChildrenAffectedByLastChildRules();
- if (firstChild && childStyle)
- childStyle->setFirstChildState();
- if (onlyChild && childStyle)
- childStyle->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->parentElement()) {
</span><del>- if (context.resolvingMode == Mode::ResolvingStyle) {
- element->setStyleIsAffectedByPreviousSibling();
- parentElement->setChildrenAffectedByBackwardPositionalRules();
- }
</del><ins>+ addStyleRelation(checkingContext, *element, StyleRelation::AffectedByPreviousSibling);
+ addStyleRelation(checkingContext, *parentElement, StyleRelation::ChildrenAffectedByBackwardPositionalRules);
</ins><span class="cx"> if (!parentElement->isFinishedParsingChildren())
</span><span class="cx"> return false;
</span><del>- return isFirstOfType(*element, element->tagQName(), context.resolvingMode == Mode::ResolvingStyle) && isLastOfType(*element, element->tagQName());
</del><ins>+ return isFirstOfType(checkingContext, *element, element->tagQName()) && isLastOfType(*element, element->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->selectorList()->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<HTMLTextFormControlElement>(*element)) {
</span><del>- if (context.resolvingMode == Mode::ResolvingStyle) {
- if (RenderStyle* style = context.elementStyle ? context.elementStyle : element->renderStyle())
- style->setUnique();
- }
</del><ins>+ addStyleRelation(checkingContext, *element, StyleRelation::Unique);
</ins><span class="cx"> return downcast<HTMLTextFormControlElement>(*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->parentElement()) {
</span><span class="cx"> if (const CSSSelectorList* selectorList = selector->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->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->selectorList()) {
</span><span class="cx"> for (Element* sibling = ElementTraversal::previousSibling(*element); sibling; sibling = ElementTraversal::previousSibling(*sibling)) {
</span><del>- if (context.resolvingMode == Mode::ResolvingStyle)
- sibling->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->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->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->parentElement()) {
</span><del>- if (context.resolvingMode == Mode::ResolvingStyle)
- element->setStyleIsAffectedByPreviousSibling();
</del><ins>+ addStyleRelation(checkingContext, *element, StyleRelation::AffectedByPreviousSibling);
</ins><span class="cx">
</span><del>- int count = 1 + countElementsOfTypeBefore(*element, element->tagQName(), context.resolvingMode == Mode::ResolvingStyle);
</del><ins>+ int count = 1 + countElementsOfTypeBefore(checkingContext, *element, element->tagQName());
</ins><span class="cx"> if (selector->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->parentElement()) {
</span><span class="cx"> if (const CSSSelectorList* selectorList = selector->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->setChildrenAffectedByPropertyBasedBackwardPositionalRules();
- parentElement->setChildrenAffectedByBackwardPositionalRules();
- }
- } else if (context.resolvingMode == Mode::ResolvingStyle)
- parentElement->setChildrenAffectedByBackwardPositionalRules();
</del><ins>+ addStyleRelation(checkingContext, *parentElement, StyleRelation::ChildrenAffectedByPropertyBasedBackwardPositionalRules);
+ } else
+ addStyleRelation(checkingContext, *parentElement, StyleRelation::ChildrenAffectedByBackwardPositionalRules);
</ins><span class="cx">
</span><span class="cx"> if (!parentElement->isFinishedParsingChildren())
</span><span class="cx"> return false;
</span><span class="lines">@@ -860,7 +833,7 @@
</span><span class="cx"> if (const CSSSelectorList* selectorList = selector->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->parseNth())
</span><span class="cx"> break;
</span><span class="cx"> if (Element* parentElement = element->parentElement()) {
</span><del>- if (context.resolvingMode == Mode::ResolvingStyle)
- parentElement->setChildrenAffectedByBackwardPositionalRules();
</del><ins>+ addStyleRelation(checkingContext, *parentElement, StyleRelation::ChildrenAffectedByBackwardPositionalRules);
+
</ins><span class="cx"> if (!parentElement->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->selectorList()->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->selectorList()->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->isLink() && context.visitedMatchType == VisitedMatchType::Enabled;
</span><span class="cx"> case CSSSelector::PseudoClassDrag:
</span><del>- if (context.resolvingMode == Mode::ResolvingStyle) {
- if (context.elementStyle)
- context.elementStyle->setAffectedByDrag();
- else
- element->setChildrenAffectedByDrag();
- }
</del><ins>+ addStyleRelation(checkingContext, *element, StyleRelation::AffectedByDrag);
+
</ins><span class="cx"> if (element->renderer() && element->renderer()->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->isLink() || canMatchHoverOrActiveInQuirksMode(context)) {
</span><del>- if (context.resolvingMode == Mode::ResolvingStyle) {
- if (context.elementStyle)
- context.elementStyle->setAffectedByHover();
- else
- element->setChildrenAffectedByHover();
- }
- if (element->hovered() || InspectorInstrumentation::forcePseudoState(*element, CSSSelector::PseudoClassHover))
</del><ins>+ addStyleRelation(checkingContext, *element, StyleRelation::AffectedByHover);
+
+ if (element->hovered() || InspectorInstrumentation::forcePseudoState(const_cast<Element&>(*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->isLink() || canMatchHoverOrActiveInQuirksMode(context)) {
</span><del>- if (context.resolvingMode == Mode::ResolvingStyle) {
- if (context.elementStyle)
- context.elementStyle->setAffectedByActive();
- else
- element->setChildrenAffectedByActive();
- }
- if (element->active() || InspectorInstrumentation::forcePseudoState(*element, CSSSelector::PseudoClassActive))
</del><ins>+ addStyleRelation(checkingContext, *element, StyleRelation::AffectedByActive);
+
+ if (element->active() || InspectorInstrumentation::forcePseudoState(const_cast<Element&>(*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->document().documentElement() : context.scope;
</del><ins>+ const Node* contextualReferenceNode = !checkingContext.scope ? element->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->match() == CSSSelector::PseudoElement && selector->pseudoElementType() == CSSSelector::PseudoElementCue) {
</span><del>- CheckingContextWithStatus subContext(context);
</del><ins>+ LocalContext subcontext(context);
</ins><span class="cx">
</span><span class="cx"> const CSSSelector* const & selector = context.selector;
</span><del>- for (subContext.selector = selector->selectorList()->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->selectorList()->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& baseContext, Element& element, const CSSSelectorList& selectorList, unsigned& specificity) const
</del><ins>+bool SelectorChecker::matchSelectorList(CheckingContext& checkingContext, const LocalContext& context, const Element& element, const CSSSelectorList& selectorList, unsigned& 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 = &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& context, const CSSSelector* selector) const
</del><ins>+bool SelectorChecker::checkScrollbarPseudoClass(const CheckingContext& checkingContext, const Element& element, const CSSSelector* selector) const
</ins><span class="cx"> {
</span><span class="cx"> ASSERT(selector->match() == CSSSelector::PseudoClass);
</span><span class="cx">
</span><span class="cx"> switch (selector->pseudoClassType()) {
</span><span class="cx"> case CSSSelector::PseudoClassWindowInactive:
</span><del>- return isWindowInactive(context.element);
</del><ins>+ return isWindowInactive(&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 <ap@webkit.org>
</span><span class="cx"> * Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org>
</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&);
</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& element;
+ Type type;
+ unsigned value;
+ };
+ using StyleRelations = Vector<StyleRelation, 8>;
+
</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&, const Element&, CheckingContext&, unsigned& specificity) const;
</ins><span class="cx">
</span><del>- bool match(const CSSSelector*, Element*, const CheckingContext&, unsigned& 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& 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&, PseudoIdSet&, unsigned& specificity) const;
- bool checkOne(const CheckingContextWithStatus&, PseudoIdSet&, MatchType&, unsigned& specificity) const;
- bool matchSelectorList(const CheckingContextWithStatus&, Element&, const CSSSelectorList&, unsigned& specificity) const;
</del><ins>+ MatchResult matchRecursively(CheckingContext&, const LocalContext&, PseudoIdSet&, unsigned& specificity) const;
+ bool checkOne(CheckingContext&, const LocalContext&, PseudoIdSet&, MatchType&, unsigned& specificity) const;
+ bool matchSelectorList(CheckingContext&, const LocalContext&, const Element&, const CSSSelectorList&, unsigned& specificity) const;
</ins><span class="cx">
</span><del>- bool checkScrollbarPseudoClass(const CheckingContextWithStatus&, const CSSSelector*) const;
</del><ins>+ bool checkScrollbarPseudoClass(const CheckingContext&, const Element&, 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"> && !element->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->document().isMediaDocument();
</span><span class="cx"> }
</span><span class="cx">
</span><del>-ALWAYS_INLINE bool isChecked(Element& element)
</del><ins>+ALWAYS_INLINE bool isChecked(const Element& 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() && !inputElement.shouldAppearIndeterminate();
</span><span class="cx"> }
</span><span class="cx"> if (is<HTMLOptionElement>(element))
</span><del>- return downcast<HTMLOptionElement>(element).selected();
</del><ins>+ return const_cast<HTMLOptionElement&>(downcast<HTMLOptionElement>(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->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->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 <utatane.tea@gmail.com>
</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& failureCases, JSC::FunctionPtr);
</span><span class="cx"> void generateContextFunctionCallTest(Assembler::JumpList& failureCases, JSC::FunctionPtr);
</span><span class="cx"> void generateElementIsActive(Assembler::JumpList& failureCases, const SelectorFragment&);
</span><del>- void generateElementIsEmpty(Assembler::JumpList& failureCases, const SelectorFragment&);
- void generateElementIsFirstChild(Assembler::JumpList& failureCases, const SelectorFragment&);
</del><ins>+ void generateElementIsEmpty(Assembler::JumpList& failureCases);
+ void generateElementIsFirstChild(Assembler::JumpList& failureCases);
</ins><span class="cx"> void generateElementIsHovered(Assembler::JumpList& failureCases, const SelectorFragment&);
</span><span class="cx"> void generateElementIsInLanguage(Assembler::JumpList& failureCases, const SelectorFragment&);
</span><span class="cx"> void generateElementIsInLanguage(Assembler::JumpList& failureCases, const Vector<AtomicString>*);
</span><del>- void generateElementIsLastChild(Assembler::JumpList& failureCases, const SelectorFragment&);
- void generateElementIsOnlyChild(Assembler::JumpList& failureCases, const SelectorFragment&);
- void generateElementHasPlaceholderShown(Assembler::JumpList& failureCases, const SelectorFragment&);
</del><ins>+ void generateElementIsLastChild(Assembler::JumpList& failureCases);
+ void generateElementIsOnlyChild(Assembler::JumpList& failureCases);
+ void generateElementHasPlaceholderShown(Assembler::JumpList& 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& failureCases, const LocalRegister& elementDataAddress, const SelectorFragment&);
</span><span class="lines">@@ -323,7 +323,8 @@
</span><span class="cx"> void generateElementIsTarget(Assembler::JumpList& 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<Assembler::RegisterID> value = { });
+ void generateAddStyleRelation(Assembler::RegisterID checkingContext, Assembler::RegisterID element, SelectorChecker::StyleRelation::Type, Optional<Assembler::RegisterID> 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& failureCases, Assembler::RegisterID element);
</span><span class="lines">@@ -332,7 +333,6 @@
</span><span class="cx"> void generateNthFilterTest(Assembler::JumpList& failureCases, Assembler::RegisterID counter, int a, int b);
</span><span class="cx"> void generateRequestedPseudoElementEqualsToSelectorPseudoElement(Assembler::JumpList& failureCases, const SelectorFragment&, Assembler::RegisterID checkingContext);
</span><span class="cx"> void generateSpecialFailureInQuirksModeForActiveAndHoverIfNeeded(Assembler::JumpList& failureCases, const SelectorFragment&);
</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& failureCases, const SelectorFragment& 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 & 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, &m_assembler);
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+void SelectorCodeGenerator::generateAddStyleRelationIfResolvingStyle(Assembler::RegisterID element, SelectorChecker::StyleRelation::Type relationType, Optional<Assembler::RegisterID> 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(&m_assembler);
+}
+
+static void addStyleRelationFunction(SelectorChecker::CheckingContext* checkingContext, Element* element)
</ins><span class="cx"> {
</span><ins>+ checkingContext->styleRelations.append({ *element, SelectorChecker::StyleRelation::AffectedByActive, 1 });
+}
+
+void SelectorCodeGenerator::generateAddStyleRelation(Assembler::RegisterID checkingContext, Assembler::RegisterID element, SelectorChecker::StyleRelation::Type relationType, Optional<Assembler::RegisterID> 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 & 0xffffffff;
- int32_t flagHighBits = newFlag >> 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& 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(&m_assembler);
-}
-
</del><span class="cx"> void SelectorCodeGenerator::linkFailures(Assembler::JumpList& globalFailureCases, BacktrackingAction backtrackingAction, Assembler::JumpList& 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->renderStyle())
- style->setFirstChildState();
-}
-
</del><span class="cx"> static bool elementIsActive(Element* element)
</span><span class="cx"> {
</span><span class="cx"> return element->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->resolvingMode == SelectorChecker::Mode::ResolvingStyle)
- element->setChildrenAffectedByActive();
- return element->active() || InspectorInstrumentation::forcePseudoState(*element, CSSSelector::PseudoClassActive);
-}
-
</del><span class="cx"> void SelectorCodeGenerator::generateElementIsActive(Assembler::JumpList& failureCases, const SelectorFragment& 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(&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& assembler, RegisterAllocator& registerAllocator, Assembler::JumpList& notEmptyCases, Assembler::RegisterID element)
</span><span class="lines">@@ -3129,19 +3090,8 @@
</span><span class="cx"> noMoreChildren.link(&assembler);
</span><span class="cx"> }
</span><span class="cx">
</span><del>-static void setElementStyleIsAffectedByEmpty(Element* element)
</del><ins>+void SelectorCodeGenerator::generateElementIsEmpty(Assembler::JumpList& failureCases)
</ins><span class="cx"> {
</span><del>- element->setStyleAffectedByEmpty();
-}
-
-static void setElementStyleFromContextIsAffectedByEmptyAndUpdateRenderStyleIfNecessary(SelectorChecker::CheckingContext* context, bool isEmpty)
-{
- ASSERT(context->elementStyle);
- context->elementStyle->setEmptyState(isEmpty);
-}
-
-void SelectorCodeGenerator::generateElementIsEmpty(Assembler::JumpList& failureCases, const SelectorFragment& 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(&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(&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& failureCases, const SelectorFragment& fragment)
</del><ins>+void SelectorCodeGenerator::generateElementIsFirstChild(Assembler::JumpList& 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(&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->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->resolvingMode == SelectorChecker::Mode::ResolvingStyle)
- element->setChildrenAffectedByHover();
- return element->hovered() || InspectorInstrumentation::forcePseudoState(*element, CSSSelector::PseudoClassHover);
-}
-
</del><span class="cx"> void SelectorCodeGenerator::generateElementIsHovered(Assembler::JumpList& failureCases, const SelectorFragment& 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(&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& failureCases, const SelectorFragment& 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& failureCases)
</ins><span class="cx"> {
</span><del>- if (RenderStyle* style = element->renderStyle())
- style->setLastChildState();
-}
-
-void SelectorCodeGenerator::generateElementIsLastChild(Assembler::JumpList& failureCases, const SelectorFragment& 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(&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& failureCases)
</ins><span class="cx"> {
</span><del>- if (RenderStyle* style = element->renderStyle()) {
- style->setFirstChildState();
- style->setLastChildState();
- }
-}
-
-void SelectorCodeGenerator::generateElementIsOnlyChild(Assembler::JumpList& failureCases, const SelectorFragment& 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(&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<HTMLTextFormControlElement>(*element)) {
</span><span class="cx"> if (checkingContext->resolvingMode == SelectorChecker::Mode::ResolvingStyle)
</span><del>- checkingContext->elementStyle->setUnique();
</del><ins>+ checkingContext->styleRelations.append({ *element, SelectorChecker::StyleRelation::Unique, 1 });
</ins><span class="cx"> return downcast<HTMLTextFormControlElement>(*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<HTMLTextFormControlElement>(*element)) {
- if (checkingContext->resolvingMode == SelectorChecker::Mode::ResolvingStyle) {
- if (RenderStyle* style = element->renderStyle())
- style->setUnique();
- }
- return downcast<HTMLTextFormControlElement>(*element).isPlaceholderVisible();
- }
- return false;
-}
-
</del><span class="cx"> static bool isPlaceholderShown(Element* element)
</span><span class="cx"> {
</span><span class="cx"> return is<HTMLTextFormControlElement>(*element) && downcast<HTMLTextFormControlElement>(*element).isPlaceholderVisible();
</span><span class="cx"> }
</span><span class="cx">
</span><del>-void SelectorCodeGenerator::generateElementHasPlaceholderShown(Assembler::JumpList& failureCases, const SelectorFragment& fragment)
</del><ins>+void SelectorCodeGenerator::generateElementHasPlaceholderShown(Assembler::JumpList& 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->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, &m_assembler);
</span><span class="cx"> noMoreSiblingsCases.link(&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(&m_assembler);
- }
-
</del><span class="cx"> for (const auto& 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->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->setChildrenAffectedByBackwardPositionalRules();
-}
-
</del><span class="cx"> void SelectorCodeGenerator::generateElementIsNthLastChild(Assembler::JumpList& failureCases, const SelectorFragment& fragment)
</span><span class="cx"> {
</span><span class="cx"> Vector<std::pair<int, int>, 32> 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(&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& 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->setChildrenAffectedByPropertyBasedBackwardPositionalRules();
- parentElement->setChildrenAffectedByBackwardPositionalRules();
-}
-
</del><span class="cx"> void SelectorCodeGenerator::generateElementIsNthLastChildOf(Assembler::JumpList& failureCases, const SelectorFragment& fragment)
</span><span class="cx"> {
</span><span class="cx"> Vector<const NthChildOfSelectorInfo*> 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(&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->pseudoElementType());
</span><span class="cx"> if (dynamicPseudo < 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 : &rootNode;
</span><span class="cx"> unsigned ignoredSpecificity;
</span><del>- return selectorChecker.match(selectorData.selector, &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& selectorData, Element& element, const ContainerNode& 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 : &rootNode;
</span><del>- Element* currentNode = &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 &element;
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> bool SelectorDataList::matches(Element& 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->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->document());
</span><span class="cx">
</span><span class="cx"> unsigned specificity;
</span><del>- bool okay = selectorChecker.match(&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>