Changeset 195293 in webkit


Ignore:
Timestamp:
Jan 19, 2016 9:39:20 AM (8 years ago)
Author:
Antti Koivisto
Message:

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):

Location:
trunk/Source/WebCore
Files:
12 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r195291 r195293  
     12016-01-18  Antti Koivisto  <antti@apple.com>
     2
     3        Selector checker should not mutate document and style
     4        https://bugs.webkit.org/show_bug.cgi?id=153205
     5
     6        Reviewed by Darin Adler.
     7
     8        Selector checker currently writes affected-by bits and similar directly to the document and style during selector
     9        matching. This is confusing, complicated and wrong.
     10
     11        This patch changes SelectorChecker and SelectorCompiler to collect style relatationship metadata to a separate
     12        data structure (currently part of SelectorChecker::CheckingContext) instead of changing the document and style
     13        directly. The mutations are performed later outside selector checker.
     14
     15        * css/ElementRuleCollector.cpp:
     16        (WebCore::ElementRuleCollector::ruleMatches):
     17        (WebCore::ElementRuleCollector::commitStyleRelations):
     18
     19            Apply the relationship bit to elements and style.
     20
     21        (WebCore::ElementRuleCollector::collectMatchingRulesForList):
     22        * css/ElementRuleCollector.h:
     23        * css/SelectorChecker.cpp:
     24        (WebCore::SelectorChecker::LocalContext::LocalContext):
     25
     26            LocalContext is now a separate data structure.
     27
     28        (WebCore::addStyleRelation):
     29
     30            Helper for recording new style relations. This is used where code mutated elements or style directly before.
     31
     32        (WebCore::isFirstChildElement):
     33        (WebCore::isLastChildElement):
     34        (WebCore::isFirstOfType):
     35        (WebCore::isLastOfType):
     36        (WebCore::countElementsBefore):
     37        (WebCore::countElementsOfTypeBefore):
     38        (WebCore::SelectorChecker::SelectorChecker):
     39        (WebCore::SelectorChecker::match):
     40        (WebCore::hasScrollbarPseudoElement):
     41        (WebCore::localContextForParent):
     42        (WebCore::SelectorChecker::matchRecursively):
     43        (WebCore::attributeValueMatches):
     44        (WebCore::anyAttributeMatches):
     45        (WebCore::canMatchHoverOrActiveInQuirksMode):
     46        (WebCore::tagMatches):
     47        (WebCore::SelectorChecker::checkOne):
     48        (WebCore::SelectorChecker::matchSelectorList):
     49        (WebCore::SelectorChecker::checkScrollbarPseudoClass):
     50        (WebCore::SelectorChecker::CheckingContextWithStatus::CheckingContextWithStatus): Deleted.
     51        (WebCore::checkingContextForParent): Deleted.
     52        * css/SelectorChecker.h:
     53        (WebCore::SelectorChecker::CheckingContext::CheckingContext):
     54        * css/SelectorCheckerTestFunctions.h:
     55        (WebCore::isEnabled):
     56        (WebCore::isMediaDocument):
     57        (WebCore::isChecked):
     58        (WebCore::isInRange):
     59        (WebCore::isOutOfRange):
     60        * css/StyleResolver.h:
     61        (WebCore::checkRegionSelector):
     62        * cssjit/SelectorCompiler.cpp:
     63        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateAddStyleRelationIfResolvingStyle):
     64        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateAddStyleRelation):
     65
     66            Helpers for generating code for recording new style relations. This is used where code mutated elements or style directly before.
     67
     68        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateSelectorCheckerExcludingPseudoElements):
     69        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateDirectAdjacentTreeWalker):
     70        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateIndirectAdjacentTreeWalker):
     71        (WebCore::SelectorCompiler::addStyleRelationElementFunction):
     72        (WebCore::SelectorCompiler::SelectorCodeGenerator::jumpIfNoPreviousAdjacentElement):
     73        (WebCore::SelectorCompiler::SelectorCodeGenerator::moduloIsZero):
     74        (WebCore::SelectorCompiler::SelectorCodeGenerator::linkFailures):
     75        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementMatching):
     76        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateContextFunctionCallTest):
     77        (WebCore::SelectorCompiler::elementIsActive):
     78        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementIsActive):
     79        (WebCore::SelectorCompiler::jumpIfElementIsNotEmpty):
     80        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementIsEmpty):
     81        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementIsFirstChild):
     82        (WebCore::SelectorCompiler::elementIsHovered):
     83        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementIsHovered):
     84        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementIsInLanguage):
     85        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementIsLastChild):
     86        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementIsOnlyChild):
     87        (WebCore::SelectorCompiler::makeContextStyleUniqueIfNecessaryAndTestIsPlaceholderShown):
     88        (WebCore::SelectorCompiler::isPlaceholderShown):
     89        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementHasPlaceholderShown):
     90        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementIsLink):
     91        (WebCore::SelectorCompiler::nthFilterIsAlwaysSatisified):
     92        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementIsNthChild):
     93        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementIsNthChildOf):
     94        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementIsNthLastChild):
     95        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementIsNthLastChildOf):
     96        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateMarkPseudoStyleForPseudoElement):
     97        (WebCore::SelectorCompiler::SelectorCodeGenerator::addFlagsToElementStyleFromContext): Deleted.
     98        (WebCore::SelectorCompiler::setNodeFlag): Deleted.
     99        (WebCore::SelectorCompiler::SelectorCodeGenerator::markElementIfResolvingStyle): Deleted.
     100        (WebCore::SelectorCompiler::setFirstChildState): Deleted.
     101        (WebCore::SelectorCompiler::elementIsActiveForStyleResolution): Deleted.
     102        (WebCore::SelectorCompiler::setElementStyleIsAffectedByEmpty): Deleted.
     103        (WebCore::SelectorCompiler::setElementStyleFromContextIsAffectedByEmptyAndUpdateRenderStyleIfNecessary): Deleted.
     104        (WebCore::SelectorCompiler::elementIsHoveredForStyleResolution): Deleted.
     105        (WebCore::SelectorCompiler::setLastChildState): Deleted.
     106        (WebCore::SelectorCompiler::setOnlyChildState): Deleted.
     107        (WebCore::SelectorCompiler::makeElementStyleUniqueIfNecessaryAndTestIsPlaceholderShown): Deleted.
     108        (WebCore::SelectorCompiler::setElementChildIndex): Deleted.
     109        (WebCore::SelectorCompiler::setChildrenAffectedByBackwardPositionalRules): Deleted.
     110        (WebCore::SelectorCompiler::setParentAffectedByLastChildOf): Deleted.
     111        * dom/SelectorQuery.cpp:
     112        (WebCore::SelectorDataList::selectorMatches):
     113        (WebCore::SelectorDataList::selectorClosest):
     114        (WebCore::SelectorDataList::matches):
     115        * inspector/InspectorCSSAgent.cpp:
     116        (WebCore::InspectorCSSAgent::buildArrayForMatchedRuleList):
     117        * inspector/InspectorStyleSheet.cpp:
     118        (WebCore::buildObjectForSelectorHelper):
     119
    11202016-01-19  Carlos Garcia Campos  <cgarcia@igalia.com>
    2121
  • trunk/Source/WebCore/css/ElementRuleCollector.cpp

    r194762 r195293  
    3838#include "HTMLElement.h"
    3939#include "InspectorInstrumentation.h"
     40#include "NodeRenderStyle.h"
    4041#include "RenderRegion.h"
    4142#include "SVGElement.h"
     
    329330
    330331    SelectorChecker::CheckingContext context(m_mode);
    331     context.elementStyle = m_style;
    332332    context.pseudoId = m_pseudoStyleRequest.pseudoId;
    333333    context.scrollbar = m_pseudoStyleRequest.scrollbar;
    334334    context.scrollbarPart = m_pseudoStyleRequest.scrollbarPart;
    335335
     336    bool selectorMatches;
    336337#if ENABLE(CSS_SELECTOR_JIT)
    337338    if (compiledSelectorChecker) {
     
    343344        ruleData.compiledSelectorUsed();
    344345#endif
    345         return selectorChecker(&m_element, &context, &specificity);
    346     }
     346        selectorMatches = selectorChecker(&m_element, &context, &specificity);
     347    } else
    347348#endif // ENABLE(CSS_SELECTOR_JIT)
    348 
    349     // Slow path.
    350     SelectorChecker selectorChecker(m_element.document());
    351     return selectorChecker.match(ruleData.selector(), &m_element, context, specificity);
     349    {
     350        // Slow path.
     351        SelectorChecker selectorChecker(m_element.document());
     352        selectorMatches = selectorChecker.match(*ruleData.selector(), m_element, context, specificity);
     353    }
     354
     355    commitStyleRelations(context.styleRelations);
     356
     357    if (context.pseudoIDSet)
     358        m_style->setHasPseudoStyles(context.pseudoIDSet);
     359
     360    return selectorMatches;
     361}
     362
     363// FIXME: Rule collector should not be doing mutations. Move this somewhere else.
     364void ElementRuleCollector::commitStyleRelations(const SelectorChecker::StyleRelations& styleRelations)
     365{
     366    for (auto& relation : styleRelations) {
     367        switch (relation.type) {
     368        case SelectorChecker::StyleRelation::AffectedByActive:
     369            if (&relation.element == &m_element)
     370                m_style->setAffectedByActive();
     371            else
     372                relation.element.setChildrenAffectedByActive();
     373            break;
     374        case SelectorChecker::StyleRelation::AffectedByDrag:
     375            if (&relation.element == &m_element)
     376                m_style->setAffectedByDrag();
     377            else
     378                relation.element.setChildrenAffectedByDrag();
     379            break;
     380        case SelectorChecker::StyleRelation::AffectedByEmpty:
     381            relation.element.setStyleAffectedByEmpty();
     382            if (&relation.element == &m_element)
     383                m_style->setEmptyState(relation.value);
     384            break;
     385        case SelectorChecker::StyleRelation::AffectedByHover:
     386            if (&relation.element == &m_element)
     387                m_style->setAffectedByHover();
     388            else
     389                relation.element.setChildrenAffectedByHover();
     390            break;
     391        case SelectorChecker::StyleRelation::AffectedByPreviousSibling:
     392            relation.element.setStyleIsAffectedByPreviousSibling();
     393            break;
     394        case SelectorChecker::StyleRelation::AffectsNextSibling:
     395            relation.element.setAffectsNextSiblingElementStyle();
     396            break;
     397        case SelectorChecker::StyleRelation::ChildrenAffectedByBackwardPositionalRules:
     398            relation.element.setChildrenAffectedByBackwardPositionalRules();
     399            break;
     400        case SelectorChecker::StyleRelation::ChildrenAffectedByFirstChildRules:
     401            relation.element.setChildrenAffectedByFirstChildRules();
     402            break;
     403        case SelectorChecker::StyleRelation::ChildrenAffectedByPropertyBasedBackwardPositionalRules:
     404            relation.element.setChildrenAffectedByBackwardPositionalRules();
     405            relation.element.setChildrenAffectedByPropertyBasedBackwardPositionalRules();
     406            break;
     407        case SelectorChecker::StyleRelation::ChildrenAffectedByLastChildRules:
     408            relation.element.setChildrenAffectedByLastChildRules();
     409            break;
     410        case SelectorChecker::StyleRelation::FirstChild:
     411            if (&relation.element == &m_element)
     412                m_style->setFirstChildState();
     413            else if (auto* style = relation.element.renderStyle())
     414                style->setFirstChildState();
     415            break;
     416        case SelectorChecker::StyleRelation::LastChild:
     417            if (&relation.element == &m_element)
     418                m_style->setLastChildState();
     419            else if (auto* style = relation.element.renderStyle())
     420                style->setLastChildState();
     421            break;
     422        case SelectorChecker::StyleRelation::NthChildIndex:
     423            relation.element.setChildIndex(relation.value);
     424            break;
     425        case SelectorChecker::StyleRelation::Unique:
     426            if (&relation.element == &m_element)
     427                m_style->setUnique();
     428            else if (auto* style = relation.element.renderStyle())
     429                style->setUnique();
     430            break;
     431        }
     432    }
    352433}
    353434
  • trunk/Source/WebCore/css/ElementRuleCollector.h

    r194762 r195293  
    8585    void addMatchedRule(const MatchedRule&);
    8686
     87    void commitStyleRelations(const SelectorChecker::StyleRelations&);
     88
    8789    Element& m_element;
    8890    RenderStyle* m_style;
  • trunk/Source/WebCore/css/SelectorChecker.cpp

    r191327 r195293  
    33 *           (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com)
    44 * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com)
    5  * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 Apple Inc. All rights reserved.
     5 * Copyright (C) 2005-2016 Apple Inc. All rights reserved.
    66 * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
    77 * Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org>
     
    4747#include "HTMLStyleElement.h"
    4848#include "InspectorInstrumentation.h"
    49 #include "NodeRenderStyle.h"
    5049#include "Page.h"
    5150#include "RenderElement.h"
    52 #include "RenderStyle.h"
    5351#include "SelectorCheckerTestFunctions.h"
    5452#include "ShadowRoot.h"
     
    6462};
    6563
    66 struct SelectorChecker::CheckingContextWithStatus : public SelectorChecker::CheckingContext {
    67     CheckingContextWithStatus(const SelectorChecker::CheckingContext& checkingContext, const CSSSelector* selector, Element* element)
    68         : SelectorChecker::CheckingContext(checkingContext)
    69         , selector(selector)
    70         , element(element)
    71         , visitedMatchType(resolvingMode == SelectorChecker::Mode::QueryingRules ? VisitedMatchType::Disabled : VisitedMatchType::Enabled)
    72         , firstSelectorOfTheFragment(selector)
    73         , inFunctionalPseudoClass(false)
    74         , pseudoElementEffective(true)
    75         , hasScrollbarPseudo(false)
    76         , hasSelectionPseudo(false)
     64struct SelectorChecker::LocalContext {
     65    LocalContext(const CSSSelector& selector, const Element& element, VisitedMatchType visitedMatchType, PseudoId pseudoId)
     66        : selector(&selector)
     67        , element(&element)
     68        , visitedMatchType(visitedMatchType)
     69        , firstSelectorOfTheFragment(&selector)
     70        , pseudoId(pseudoId)
    7771    { }
    7872
    7973    const CSSSelector* selector;
    80     Element* element;
     74    const Element* element;
    8175    VisitedMatchType visitedMatchType;
    8276    const CSSSelector* firstSelectorOfTheFragment;
    83     bool inFunctionalPseudoClass;
    84     bool pseudoElementEffective;
    85     bool hasScrollbarPseudo;
    86     bool hasSelectionPseudo;
     77    PseudoId pseudoId;
     78    bool isMatchElement { true };
     79    bool inFunctionalPseudoClass { false };
     80    bool pseudoElementEffective { true };
     81    bool hasScrollbarPseudo { false };
     82    bool hasSelectionPseudo { false };
     83
    8784};
    8885
     86static inline void addStyleRelation(SelectorChecker::CheckingContext& checkingContext, const Element& element, SelectorChecker::StyleRelation::Type type, unsigned value = 1)
     87{
     88    ASSERT(value == 1 || type == SelectorChecker::StyleRelation::NthChildIndex || type == SelectorChecker::StyleRelation::AffectedByEmpty);
     89    if (checkingContext.resolvingMode != SelectorChecker::Mode::ResolvingStyle)
     90        return;
     91    checkingContext.styleRelations.append({ const_cast<Element&>(element), type, value });
     92}
     93
    8994static inline bool isFirstChildElement(const Element& element)
    9095{
     
    97102}
    98103
    99 static inline bool isFirstOfType(Element& element, const QualifiedName& type, bool isResolvingStyle)
    100 {
    101     for (Element* sibling = ElementTraversal::previousSibling(element); sibling; sibling = ElementTraversal::previousSibling(*sibling)) {
    102         if (isResolvingStyle)
    103             sibling->setAffectsNextSiblingElementStyle();
     104static inline bool isFirstOfType(SelectorChecker::CheckingContext& checkingContext, const Element& element, const QualifiedName& type)
     105{
     106    for (const Element* sibling = ElementTraversal::previousSibling(element); sibling; sibling = ElementTraversal::previousSibling(*sibling)) {
     107        addStyleRelation(checkingContext, *sibling, SelectorChecker::StyleRelation::AffectsNextSibling);
     108
    104109        if (sibling->hasTagName(type))
    105110            return false;
     
    117122}
    118123
    119 static inline int countElementsBefore(Element& element, bool isResolvingStyle)
     124static inline int countElementsBefore(SelectorChecker::CheckingContext& checkingContext, const Element& element)
    120125{
    121126    int count = 0;
    122     for (Element* sibling = ElementTraversal::previousSibling(element); sibling; sibling = ElementTraversal::previousSibling(*sibling)) {
    123         if (isResolvingStyle)
    124             sibling->setAffectsNextSiblingElementStyle();
     127    for (const Element* sibling = ElementTraversal::previousSibling(element); sibling; sibling = ElementTraversal::previousSibling(*sibling)) {
     128
     129        addStyleRelation(checkingContext, *sibling, SelectorChecker::StyleRelation::AffectsNextSibling);
    125130
    126131        unsigned index = sibling->childIndex();
     
    134139}
    135140
    136 static inline int countElementsOfTypeBefore(Element& element, const QualifiedName& type, bool isResolvingStyle)
     141static inline int countElementsOfTypeBefore(SelectorChecker::CheckingContext& checkingContext, const Element& element, const QualifiedName& type)
    137142{
    138143    int count = 0;
    139     for (Element* sibling = ElementTraversal::previousSibling(element); sibling; sibling = ElementTraversal::previousSibling(*sibling)) {
    140         if (isResolvingStyle)
    141             sibling->setAffectsNextSiblingElementStyle();
     144    for (const Element* sibling = ElementTraversal::previousSibling(element); sibling; sibling = ElementTraversal::previousSibling(*sibling)) {
     145        addStyleRelation(checkingContext, *sibling, SelectorChecker::StyleRelation::AffectsNextSibling);
    142146
    143147        if (sibling->hasTagName(type))
     
    171175}
    172176
    173 bool SelectorChecker::match(const CSSSelector* selector, Element* element, const CheckingContext& providedContext, unsigned& specificity) const
     177bool SelectorChecker::match(const CSSSelector& selector, const Element& element, CheckingContext& checkingContext, unsigned& specificity) const
    174178{
    175179    specificity = 0;
    176180
    177     CheckingContextWithStatus context(providedContext, selector, element);
     181    LocalContext context(selector, element, checkingContext.resolvingMode == SelectorChecker::Mode::QueryingRules ? VisitedMatchType::Disabled : VisitedMatchType::Enabled, checkingContext.pseudoId);
    178182    PseudoIdSet pseudoIdSet;
    179     MatchResult result = matchRecursively(context, pseudoIdSet, specificity);
     183    MatchResult result = matchRecursively(checkingContext, context, pseudoIdSet, specificity);
    180184    if (result.match != Match::SelectorMatches)
    181185        return false;
    182     if (context.pseudoId != NOPSEUDO && !pseudoIdSet.has(context.pseudoId))
     186    if (checkingContext.pseudoId != NOPSEUDO && !pseudoIdSet.has(checkingContext.pseudoId))
    183187        return false;
    184188
    185     if (context.pseudoId == NOPSEUDO && pseudoIdSet) {
     189    if (checkingContext.pseudoId == NOPSEUDO && pseudoIdSet) {
    186190        PseudoIdSet publicPseudoIdSet = pseudoIdSet & PseudoIdSet::fromMask(PUBLIC_PSEUDOID_MASK);
    187         if (context.resolvingMode == Mode::ResolvingStyle && publicPseudoIdSet)
    188             context.elementStyle->setHasPseudoStyles(publicPseudoIdSet);
     191        if (checkingContext.resolvingMode == Mode::ResolvingStyle && publicPseudoIdSet)
     192            checkingContext.pseudoIDSet = publicPseudoIdSet;
    189193
    190194        // When ignoring virtual pseudo elements, the context's pseudo should also be NOPSEUDO but that does
    191195        // not cause a failure.
    192         return context.resolvingMode == Mode::CollectingRulesIgnoringVirtualPseudoElements || result.matchType == MatchType::Element;
     196        return checkingContext.resolvingMode == Mode::CollectingRulesIgnoringVirtualPseudoElements || result.matchType == MatchType::Element;
    193197    }
    194198    return true;
     
    206210}
    207211
    208 static SelectorChecker::CheckingContextWithStatus checkingContextForParent(const SelectorChecker::CheckingContextWithStatus& context)
    209 {
    210     SelectorChecker::CheckingContextWithStatus updatedContext(context);
     212static SelectorChecker::LocalContext localContextForParent(const SelectorChecker::LocalContext& context)
     213{
     214    SelectorChecker::LocalContext updatedContext(context);
    211215    // Disable :visited matching when we see the first link.
    212216    if (context.element->isLink())
    213217        updatedContext.visitedMatchType = VisitedMatchType::Disabled;
    214218    updatedContext.element = context.element->parentElement();
     219    updatedContext.isMatchElement = false;
    215220    return updatedContext;
    216221}
     
    222227// * SelectorFailsAllSiblings - the selector fails for e and any sibling of e
    223228// * SelectorFailsCompletely  - the selector fails for e and any sibling or ancestor of e
    224 SelectorChecker::MatchResult SelectorChecker::matchRecursively(const CheckingContextWithStatus& context, PseudoIdSet& dynamicPseudoIdSet, unsigned& specificity) const
     229SelectorChecker::MatchResult SelectorChecker::matchRecursively(CheckingContext& checkingContext, const LocalContext& context, PseudoIdSet& dynamicPseudoIdSet, unsigned& specificity) const
    225230{
    226231    MatchType matchType = MatchType::Element;
    227232
    228233    // The first selector has to match.
    229     if (!checkOne(context, dynamicPseudoIdSet, matchType, specificity))
     234    if (!checkOne(checkingContext, context, dynamicPseudoIdSet, matchType, specificity))
    230235        return MatchResult::fails(Match::SelectorFailsLocally);
    231236
     
    248253                return MatchResult::fails(Match::SelectorFailsCompletely);
    249254
    250             if (context.resolvingMode == Mode::QueryingRules)
     255            if (checkingContext.resolvingMode == Mode::QueryingRules)
    251256                return MatchResult::fails(Match::SelectorFailsCompletely);
    252257
     
    266271        return MatchResult::matches(matchType);
    267272
    268     CheckingContextWithStatus nextContext(context);
     273    LocalContext nextContext(context);
    269274    nextContext.selector = historySelector;
    270275
     
    281286        // Virtual pseudo element is only effective in the rightmost fragment.
    282287        nextContext.pseudoElementEffective = false;
     288        nextContext.isMatchElement = false;
    283289    }
    284290
    285291    switch (relation) {
    286292    case CSSSelector::Descendant:
    287         nextContext = checkingContextForParent(nextContext);
     293        nextContext = localContextForParent(nextContext);
    288294        nextContext.firstSelectorOfTheFragment = nextContext.selector;
    289         nextContext.elementStyle = nullptr;
    290         for (; nextContext.element; nextContext = checkingContextForParent(nextContext)) {
     295        for (; nextContext.element; nextContext = localContextForParent(nextContext)) {
    291296            PseudoIdSet ignoreDynamicPseudo;
    292297            unsigned descendantsSpecificity = 0;
    293             MatchResult result = matchRecursively(nextContext, ignoreDynamicPseudo, descendantsSpecificity);
     298            MatchResult result = matchRecursively(checkingContext, nextContext, ignoreDynamicPseudo, descendantsSpecificity);
    294299            ASSERT(!nextContext.pseudoElementEffective && !ignoreDynamicPseudo);
    295300
     
    304309    case CSSSelector::Child:
    305310        {
    306             nextContext = checkingContextForParent(nextContext);
     311            nextContext = localContextForParent(nextContext);
    307312            if (!nextContext.element)
    308313                return MatchResult::fails(Match::SelectorFailsCompletely);
    309314            nextContext.firstSelectorOfTheFragment = nextContext.selector;
    310             nextContext.elementStyle = nullptr;
    311315            PseudoIdSet ignoreDynamicPseudo;
    312316            unsigned childSpecificity = 0;
    313             MatchResult result = matchRecursively(nextContext, ignoreDynamicPseudo, childSpecificity);
     317            MatchResult result = matchRecursively(checkingContext, nextContext, ignoreDynamicPseudo, childSpecificity);
    314318            ASSERT(!nextContext.pseudoElementEffective && !ignoreDynamicPseudo);
    315319
     
    324328    case CSSSelector::DirectAdjacent:
    325329        {
    326             if (context.resolvingMode == Mode::ResolvingStyle)
    327                 context.element->setStyleIsAffectedByPreviousSibling();
     330            addStyleRelation(checkingContext, *context.element, StyleRelation::AffectedByPreviousSibling);
    328331
    329332            Element* previousElement = context.element->previousElementSibling();
    330333            if (!previousElement)
    331334                return MatchResult::fails(Match::SelectorFailsAllSiblings);
    332             if (context.resolvingMode == Mode::ResolvingStyle)
    333                 previousElement->setAffectsNextSiblingElementStyle();
     335
     336            addStyleRelation(checkingContext, *previousElement, StyleRelation::AffectsNextSibling);
     337
    334338            nextContext.element = previousElement;
    335339            nextContext.firstSelectorOfTheFragment = nextContext.selector;
    336             nextContext.elementStyle = nullptr;
    337340            PseudoIdSet ignoreDynamicPseudo;
    338341            unsigned adjacentSpecificity = 0;
    339             MatchResult result = matchRecursively(nextContext, ignoreDynamicPseudo, adjacentSpecificity);
     342            MatchResult result = matchRecursively(checkingContext, nextContext, ignoreDynamicPseudo, adjacentSpecificity);
    340343            ASSERT(!nextContext.pseudoElementEffective && !ignoreDynamicPseudo);
    341344
     
    346349        }
    347350    case CSSSelector::IndirectAdjacent:
    348         if (context.resolvingMode == Mode::ResolvingStyle)
    349             context.element->setStyleIsAffectedByPreviousSibling();
     351        addStyleRelation(checkingContext, *context.element, StyleRelation::AffectedByPreviousSibling);
     352
    350353        nextContext.element = context.element->previousElementSibling();
    351354        nextContext.firstSelectorOfTheFragment = nextContext.selector;
    352         nextContext.elementStyle = nullptr;
    353355        for (; nextContext.element; nextContext.element = nextContext.element->previousElementSibling()) {
    354             if (context.resolvingMode == Mode::ResolvingStyle)
    355                 nextContext.element->setAffectsNextSiblingElementStyle();
     356            addStyleRelation(checkingContext, *nextContext.element, StyleRelation::AffectsNextSibling);
    356357
    357358            PseudoIdSet ignoreDynamicPseudo;
    358359            unsigned indirectAdjacentSpecificity = 0;
    359             MatchResult result = matchRecursively(nextContext, ignoreDynamicPseudo, indirectAdjacentSpecificity);
     360            MatchResult result = matchRecursively(checkingContext, nextContext, ignoreDynamicPseudo, indirectAdjacentSpecificity);
    360361            ASSERT(!nextContext.pseudoElementEffective && !ignoreDynamicPseudo);
    361362
     
    375376            nextContext.hasScrollbarPseudo = hasScrollbarPseudoElement(dynamicPseudoIdSet);
    376377            nextContext.hasSelectionPseudo = dynamicPseudoIdSet.has(SELECTION);
    377             if ((context.elementStyle || context.resolvingMode == Mode::CollectingRules) && dynamicPseudoIdSet
     378            if ((context.isMatchElement || checkingContext.resolvingMode == Mode::CollectingRules) && dynamicPseudoIdSet
    378379                && !nextContext.hasSelectionPseudo
    379380                && !(nextContext.hasScrollbarPseudo && nextContext.selector->match() == CSSSelector::PseudoClass))
     
    381382
    382383            unsigned subselectorSpecificity = 0;
    383             MatchResult result = matchRecursively(nextContext, dynamicPseudoIdSet, subselectorSpecificity);
     384            MatchResult result = matchRecursively(checkingContext, nextContext, dynamicPseudoIdSet, subselectorSpecificity);
    384385
    385386            if (result.match == Match::SelectorMatches)
     
    395396            nextContext.element = shadowHostNode;
    396397            nextContext.firstSelectorOfTheFragment = nextContext.selector;
    397             nextContext.elementStyle = nullptr;
    398398            PseudoIdSet ignoreDynamicPseudo;
    399399            unsigned shadowDescendantSpecificity = 0;
    400             MatchResult result = matchRecursively(nextContext, ignoreDynamicPseudo, shadowDescendantSpecificity);
     400            MatchResult result = matchRecursively(checkingContext, nextContext, ignoreDynamicPseudo, shadowDescendantSpecificity);
    401401
    402402            if (result.match == Match::SelectorMatches)
     
    505505}
    506506
    507 static bool anyAttributeMatches(Element* element, const CSSSelector* selector, const QualifiedName& selectorAttr, bool caseSensitive)
     507static bool anyAttributeMatches(const Element* element, const CSSSelector* selector, const QualifiedName& selectorAttr, bool caseSensitive)
    508508{
    509509    ASSERT(element->hasAttributesWithoutUpdate());
     
    519519}
    520520
    521 static bool canMatchHoverOrActiveInQuirksMode(const SelectorChecker::CheckingContextWithStatus& context)
     521static bool canMatchHoverOrActiveInQuirksMode(const SelectorChecker::LocalContext& context)
    522522{
    523523    // For quirks mode, follow this: http://quirks.spec.whatwg.org/#the-:active-and-:hover-quirk
     
    589589}
    590590
    591 bool SelectorChecker::checkOne(const CheckingContextWithStatus& context, PseudoIdSet& dynamicPseudoIdSet, MatchType& matchType, unsigned& specificity) const
    592 {
    593     Element* const & element = context.element;
     591bool SelectorChecker::checkOne(CheckingContext& checkingContext, const LocalContext& context, PseudoIdSet& dynamicPseudoIdSet, MatchType& matchType, unsigned& specificity) const
     592{
     593    const Element* element = context.element;
    594594    const CSSSelector* const & selector = context.selector;
    595595    ASSERT(element);
     
    627627
    628628            for (const CSSSelector* subselector = selectorList->first(); subselector; subselector = CSSSelectorList::next(subselector)) {
    629                 CheckingContextWithStatus subcontext(context);
     629                LocalContext subcontext(context);
    630630                subcontext.inFunctionalPseudoClass = true;
    631631                subcontext.pseudoElementEffective = false;
     
    635635
    636636                unsigned ignoredSpecificity;
    637                 if (matchRecursively(subcontext, ignoreDynamicPseudo, ignoredSpecificity).match == Match::SelectorMatches) {
     637                if (matchRecursively(checkingContext, subcontext, ignoreDynamicPseudo, ignoredSpecificity).match == Match::SelectorMatches) {
    638638                    ASSERT(!ignoreDynamicPseudo);
    639639                    return false;
     
    644644            // CSS scrollbars match a specific subset of pseudo classes, and they have specialized rules for each
    645645            // (since there are no elements involved except with window-inactive).
    646             return checkScrollbarPseudoClass(context, selector);
     646            return checkScrollbarPseudoClass(checkingContext, *context.element, selector);
    647647        }
    648648
     
    668668                    }
    669669                }
    670                 if (context.resolvingMode == Mode::ResolvingStyle) {
    671                     element->setStyleAffectedByEmpty();
    672                     if (context.elementStyle)
    673                         context.elementStyle->setEmptyState(result);
    674                 }
     670                addStyleRelation(checkingContext, *context.element, StyleRelation::AffectedByEmpty, result);
     671
    675672                return result;
    676673            }
    677674        case CSSSelector::PseudoClassFirstChild:
    678675            // first-child matches the first child that is an element
    679             if (Element* parentElement = element->parentElement()) {
    680                 bool result = isFirstChildElement(*element);
    681                 if (context.resolvingMode == Mode::ResolvingStyle) {
    682                     RenderStyle* childStyle = context.elementStyle ? context.elementStyle : element->renderStyle();
    683                     parentElement->setChildrenAffectedByFirstChildRules();
    684                     if (result && childStyle)
    685                         childStyle->setFirstChildState();
    686                 }
    687                 return result;
     676            if (const Element* parentElement = element->parentElement()) {
     677                bool isFirstChild = isFirstChildElement(*element);
     678                if (isFirstChild)
     679                    addStyleRelation(checkingContext, *element, StyleRelation::FirstChild);
     680                addStyleRelation(checkingContext, *parentElement, StyleRelation::ChildrenAffectedByFirstChildRules);
     681                return isFirstChild;
    688682            }
    689683            break;
     
    691685            // first-of-type matches the first element of its type
    692686            if (element->parentElement()) {
    693                 if (context.resolvingMode == Mode::ResolvingStyle)
    694                     element->setStyleIsAffectedByPreviousSibling();
    695 
    696                 return isFirstOfType(*element, element->tagQName(), context.resolvingMode == Mode::ResolvingStyle);
     687                addStyleRelation(checkingContext, *element, StyleRelation::AffectedByPreviousSibling);
     688                return isFirstOfType(checkingContext, *element, element->tagQName());
    697689            }
    698690            break;
    699691        case CSSSelector::PseudoClassLastChild:
    700692            // last-child matches the last child that is an element
    701             if (Element* parentElement = element->parentElement()) {
    702                 bool result = parentElement->isFinishedParsingChildren() && isLastChildElement(*element);
    703                 if (context.resolvingMode == Mode::ResolvingStyle) {
    704                     RenderStyle* childStyle = context.elementStyle ? context.elementStyle : element->renderStyle();
    705                     parentElement->setChildrenAffectedByLastChildRules();
    706                     if (result && childStyle)
    707                         childStyle->setLastChildState();
    708                 }
    709                 return result;
     693            if (const Element* parentElement = element->parentElement()) {
     694                bool isLastChild = parentElement->isFinishedParsingChildren() && isLastChildElement(*element);
     695                if (isLastChild)
     696                    addStyleRelation(checkingContext, *element, StyleRelation::LastChild);
     697                addStyleRelation(checkingContext, *parentElement, StyleRelation::ChildrenAffectedByLastChildRules);
     698                return isLastChild;
    710699            }
    711700            break;
     
    713702            // last-of-type matches the last element of its type
    714703            if (Element* parentElement = element->parentElement()) {
    715                 if (context.resolvingMode == Mode::ResolvingStyle)
    716                     parentElement->setChildrenAffectedByBackwardPositionalRules();
     704                addStyleRelation(checkingContext, *parentElement, StyleRelation::ChildrenAffectedByBackwardPositionalRules);
    717705                if (!parentElement->isFinishedParsingChildren())
    718706                    return false;
     
    724712                bool firstChild = isFirstChildElement(*element);
    725713                bool onlyChild = firstChild && parentElement->isFinishedParsingChildren() && isLastChildElement(*element);
    726                 if (context.resolvingMode == Mode::ResolvingStyle) {
    727                     RenderStyle* childStyle = context.elementStyle ? context.elementStyle : element->renderStyle();
    728                     parentElement->setChildrenAffectedByFirstChildRules();
    729                     parentElement->setChildrenAffectedByLastChildRules();
    730                     if (firstChild && childStyle)
    731                         childStyle->setFirstChildState();
    732                     if (onlyChild && childStyle)
    733                         childStyle->setLastChildState();
    734                 }
     714                addStyleRelation(checkingContext, *parentElement, StyleRelation::ChildrenAffectedByFirstChildRules);
     715                addStyleRelation(checkingContext, *parentElement, StyleRelation::ChildrenAffectedByLastChildRules);
     716                if (firstChild)
     717                    addStyleRelation(checkingContext, *element, StyleRelation::FirstChild);
     718                if (onlyChild)
     719                    addStyleRelation(checkingContext, *element, StyleRelation::LastChild);
    735720                return onlyChild;
    736721            }
     
    739724            // FIXME: This selector is very slow.
    740725            if (Element* parentElement = element->parentElement()) {
    741                 if (context.resolvingMode == Mode::ResolvingStyle) {
    742                     element->setStyleIsAffectedByPreviousSibling();
    743                     parentElement->setChildrenAffectedByBackwardPositionalRules();
    744                 }
     726                addStyleRelation(checkingContext, *element, StyleRelation::AffectedByPreviousSibling);
     727                addStyleRelation(checkingContext, *parentElement, StyleRelation::ChildrenAffectedByBackwardPositionalRules);
    745728                if (!parentElement->isFinishedParsingChildren())
    746729                    return false;
    747                 return isFirstOfType(*element, element->tagQName(), context.resolvingMode == Mode::ResolvingStyle) && isLastOfType(*element, element->tagQName());
     730                return isFirstOfType(checkingContext, *element, element->tagQName()) && isLastOfType(*element, element->tagQName());
    748731            }
    749732            break;
     
    755738                MatchType localMatchType = MatchType::VirtualPseudoElementOnly;
    756739                for (const CSSSelector* subselector = selector->selectorList()->first(); subselector; subselector = CSSSelectorList::next(subselector)) {
    757                     CheckingContextWithStatus subcontext(context);
     740                    LocalContext subcontext(context);
    758741                    subcontext.inFunctionalPseudoClass = true;
    759742                    subcontext.pseudoElementEffective = context.pseudoElementEffective;
     
    762745                    PseudoIdSet localDynamicPseudoIdSet;
    763746                    unsigned localSpecificity = 0;
    764                     MatchResult result = matchRecursively(subcontext, localDynamicPseudoIdSet, localSpecificity);
     747                    MatchResult result = matchRecursively(checkingContext, subcontext, localDynamicPseudoIdSet, localSpecificity);
    765748                    if (result.match == Match::SelectorMatches) {
    766749                        maxSpecificity = std::max(maxSpecificity, localSpecificity);
     
    781764        case CSSSelector::PseudoClassPlaceholderShown:
    782765            if (is<HTMLTextFormControlElement>(*element)) {
    783                 if (context.resolvingMode == Mode::ResolvingStyle) {
    784                     if (RenderStyle* style = context.elementStyle ? context.elementStyle : element->renderStyle())
    785                         style->setUnique();
    786                 }
     766                addStyleRelation(checkingContext, *element, StyleRelation::Unique);
    787767                return downcast<HTMLTextFormControlElement>(*element).isPlaceholderVisible();
    788768            }
     
    794774                if (const CSSSelectorList* selectorList = selector->selectorList()) {
    795775                    unsigned selectorListSpecificity;
    796                     if (matchSelectorList(context, *element, *selectorList, selectorListSpecificity))
     776                    if (matchSelectorList(checkingContext, context, *element, *selectorList, selectorListSpecificity))
    797777                        specificity = CSSSelector::addSpecificities(specificity, selectorListSpecificity);
    798778                    else
     
    800780                }
    801781
    802                 if (context.resolvingMode == Mode::ResolvingStyle)
    803                     element->setStyleIsAffectedByPreviousSibling();
     782                addStyleRelation(checkingContext, *element, StyleRelation::AffectedByPreviousSibling);
    804783
    805784                int count = 1;
    806785                if (const CSSSelectorList* selectorList = selector->selectorList()) {
    807786                    for (Element* sibling = ElementTraversal::previousSibling(*element); sibling; sibling = ElementTraversal::previousSibling(*sibling)) {
    808                         if (context.resolvingMode == Mode::ResolvingStyle)
    809                             sibling->setAffectsNextSiblingElementStyle();
     787                        addStyleRelation(checkingContext, *sibling, StyleRelation::AffectsNextSibling);
    810788
    811789                        unsigned ignoredSpecificity;
    812                         if (matchSelectorList(context, *sibling, *selectorList, ignoredSpecificity))
     790                        if (matchSelectorList(checkingContext, context, *sibling, *selectorList, ignoredSpecificity))
    813791                            ++count;
    814792                    }
    815793                } else {
    816                     count += countElementsBefore(*element, context.resolvingMode == Mode::ResolvingStyle);
    817                     if (context.resolvingMode == Mode::ResolvingStyle)
    818                         element->setChildIndex(count);
     794                    count += countElementsBefore(checkingContext, *element);
     795                    addStyleRelation(checkingContext, *element, StyleRelation::NthChildIndex, count);
    819796                }
    820797
     
    828805
    829806            if (element->parentElement()) {
    830                 if (context.resolvingMode == Mode::ResolvingStyle)
    831                     element->setStyleIsAffectedByPreviousSibling();
    832 
    833                 int count = 1 + countElementsOfTypeBefore(*element, element->tagQName(), context.resolvingMode == Mode::ResolvingStyle);
     807                addStyleRelation(checkingContext, *element, StyleRelation::AffectedByPreviousSibling);
     808
     809                int count = 1 + countElementsOfTypeBefore(checkingContext, *element, element->tagQName());
    834810                if (selector->matchNth(count))
    835811                    return true;
     
    842818                if (const CSSSelectorList* selectorList = selector->selectorList()) {
    843819                    unsigned selectorListSpecificity;
    844                     if (matchSelectorList(context, *element, *selectorList, selectorListSpecificity))
     820                    if (matchSelectorList(checkingContext, context, *element, *selectorList, selectorListSpecificity))
    845821                        specificity = CSSSelector::addSpecificities(specificity, selectorListSpecificity);
    846822                    else
    847823                        return false;
    848824
    849                     if (context.resolvingMode == Mode::ResolvingStyle) {
    850                         parentElement->setChildrenAffectedByPropertyBasedBackwardPositionalRules();
    851                         parentElement->setChildrenAffectedByBackwardPositionalRules();
    852                     }
    853                 } else if (context.resolvingMode == Mode::ResolvingStyle)
    854                     parentElement->setChildrenAffectedByBackwardPositionalRules();
     825                    addStyleRelation(checkingContext, *parentElement, StyleRelation::ChildrenAffectedByPropertyBasedBackwardPositionalRules);
     826                } else
     827                    addStyleRelation(checkingContext, *parentElement, StyleRelation::ChildrenAffectedByBackwardPositionalRules);
    855828
    856829                if (!parentElement->isFinishedParsingChildren())
     
    861834                    for (Element* sibling = ElementTraversal::nextSibling(*element); sibling; sibling = ElementTraversal::nextSibling(*sibling)) {
    862835                        unsigned ignoredSpecificity;
    863                         if (matchSelectorList(context, *sibling, *selectorList, ignoredSpecificity))
     836                        if (matchSelectorList(checkingContext, context, *sibling, *selectorList, ignoredSpecificity))
    864837                            ++count;
    865838                    }
     
    875848                break;
    876849            if (Element* parentElement = element->parentElement()) {
    877                 if (context.resolvingMode == Mode::ResolvingStyle)
    878                     parentElement->setChildrenAffectedByBackwardPositionalRules();
     850                addStyleRelation(checkingContext, *parentElement, StyleRelation::ChildrenAffectedByBackwardPositionalRules);
     851
    879852                if (!parentElement->isFinishedParsingChildren())
    880853                    return false;
     
    891864        case CSSSelector::PseudoClassAny:
    892865            {
    893                 CheckingContextWithStatus subContext(context);
    894                 subContext.inFunctionalPseudoClass = true;
    895                 subContext.pseudoElementEffective = false;
    896                 for (subContext.selector = selector->selectorList()->first(); subContext.selector; subContext.selector = CSSSelectorList::next(subContext.selector)) {
    897                     subContext.firstSelectorOfTheFragment = subContext.selector;
     866                LocalContext subcontext(context);
     867                subcontext.inFunctionalPseudoClass = true;
     868                subcontext.pseudoElementEffective = false;
     869                for (subcontext.selector = selector->selectorList()->first(); subcontext.selector; subcontext.selector = CSSSelectorList::next(subcontext.selector)) {
     870                    subcontext.firstSelectorOfTheFragment = subcontext.selector;
    898871                    PseudoIdSet ignoreDynamicPseudo;
    899872                    unsigned ingoredSpecificity = 0;
    900                     if (matchRecursively(subContext, ignoreDynamicPseudo, ingoredSpecificity).match == Match::SelectorMatches)
     873                    if (matchRecursively(checkingContext, subcontext, ignoreDynamicPseudo, ingoredSpecificity).match == Match::SelectorMatches)
    901874                        return true;
    902875                }
     
    917890            return element->isLink() && context.visitedMatchType == VisitedMatchType::Enabled;
    918891        case CSSSelector::PseudoClassDrag:
    919             if (context.resolvingMode == Mode::ResolvingStyle) {
    920                 if (context.elementStyle)
    921                     context.elementStyle->setAffectedByDrag();
    922                 else
    923                     element->setChildrenAffectedByDrag();
    924             }
     892            addStyleRelation(checkingContext, *element, StyleRelation::AffectedByDrag);
     893
    925894            if (element->renderer() && element->renderer()->isDragging())
    926895                return true;
     
    930899        case CSSSelector::PseudoClassHover:
    931900            if (m_strictParsing || element->isLink() || canMatchHoverOrActiveInQuirksMode(context)) {
    932                 if (context.resolvingMode == Mode::ResolvingStyle) {
    933                     if (context.elementStyle)
    934                         context.elementStyle->setAffectedByHover();
    935                     else
    936                         element->setChildrenAffectedByHover();
    937                 }
    938                 if (element->hovered() || InspectorInstrumentation::forcePseudoState(*element, CSSSelector::PseudoClassHover))
     901                addStyleRelation(checkingContext, *element, StyleRelation::AffectedByHover);
     902
     903                if (element->hovered() || InspectorInstrumentation::forcePseudoState(const_cast<Element&>(*element), CSSSelector::PseudoClassHover))
    939904                    return true;
    940905            }
     
    942907        case CSSSelector::PseudoClassActive:
    943908            if (m_strictParsing || element->isLink() || canMatchHoverOrActiveInQuirksMode(context)) {
    944                 if (context.resolvingMode == Mode::ResolvingStyle) {
    945                     if (context.elementStyle)
    946                         context.elementStyle->setAffectedByActive();
    947                     else
    948                         element->setChildrenAffectedByActive();
    949                 }
    950                 if (element->active() || InspectorInstrumentation::forcePseudoState(*element, CSSSelector::PseudoClassActive))
     909                addStyleRelation(checkingContext, *element, StyleRelation::AffectedByActive);
     910
     911                if (element->active() || InspectorInstrumentation::forcePseudoState(const_cast<Element&>(*element), CSSSelector::PseudoClassActive))
    951912                    return true;
    952913            }
     
    1008969        case CSSSelector::PseudoClassScope:
    1009970            {
    1010                 const Node* contextualReferenceNode = !context.scope ? element->document().documentElement() : context.scope;
     971                const Node* contextualReferenceNode = !checkingContext.scope ? element->document().documentElement() : checkingContext.scope;
    1011972                if (element == contextualReferenceNode)
    1012973                    return true;
     
    10511012#if ENABLE(VIDEO_TRACK)
    10521013    if (selector->match() == CSSSelector::PseudoElement && selector->pseudoElementType() == CSSSelector::PseudoElementCue) {
    1053         CheckingContextWithStatus subContext(context);
     1014        LocalContext subcontext(context);
    10541015
    10551016        const CSSSelector* const & selector = context.selector;
    1056         for (subContext.selector = selector->selectorList()->first(); subContext.selector; subContext.selector = CSSSelectorList::next(subContext.selector)) {
    1057             subContext.firstSelectorOfTheFragment = subContext.selector;
    1058             subContext.inFunctionalPseudoClass = true;
    1059             subContext.pseudoElementEffective = false;
     1017        for (subcontext.selector = selector->selectorList()->first(); subcontext.selector; subcontext.selector = CSSSelectorList::next(subcontext.selector)) {
     1018            subcontext.firstSelectorOfTheFragment = subcontext.selector;
     1019            subcontext.inFunctionalPseudoClass = true;
     1020            subcontext.pseudoElementEffective = false;
    10601021            PseudoIdSet ignoredDynamicPseudo;
    10611022            unsigned ignoredSpecificity = 0;
    1062             if (matchRecursively(subContext, ignoredDynamicPseudo, ignoredSpecificity).match == Match::SelectorMatches)
     1023            if (matchRecursively(checkingContext, subcontext, ignoredDynamicPseudo, ignoredSpecificity).match == Match::SelectorMatches)
    10631024                return true;
    10641025        }
     
    10701031}
    10711032
    1072 bool SelectorChecker::matchSelectorList(const CheckingContextWithStatus& baseContext, Element& element, const CSSSelectorList& selectorList, unsigned& specificity) const
     1033bool SelectorChecker::matchSelectorList(CheckingContext& checkingContext, const LocalContext& context, const Element& element, const CSSSelectorList& selectorList, unsigned& specificity) const
    10731034{
    10741035    specificity = 0;
     
    10761037
    10771038    for (const CSSSelector* subselector = selectorList.first(); subselector; subselector = CSSSelectorList::next(subselector)) {
    1078         CheckingContextWithStatus subcontext(baseContext);
     1039        LocalContext subcontext(context);
    10791040        subcontext.element = &element;
    10801041        subcontext.selector = subselector;
     
    10841045        PseudoIdSet ignoreDynamicPseudo;
    10851046        unsigned localSpecificity = 0;
    1086         if (matchRecursively(subcontext, ignoreDynamicPseudo, localSpecificity).match == Match::SelectorMatches) {
     1047        if (matchRecursively(checkingContext, subcontext, ignoreDynamicPseudo, localSpecificity).match == Match::SelectorMatches) {
    10871048            ASSERT(!ignoreDynamicPseudo);
    10881049
     
    10941055}
    10951056
    1096 bool SelectorChecker::checkScrollbarPseudoClass(const CheckingContextWithStatus& context, const CSSSelector* selector) const
     1057bool SelectorChecker::checkScrollbarPseudoClass(const CheckingContext& checkingContext, const Element& element, const CSSSelector* selector) const
    10971058{
    10981059    ASSERT(selector->match() == CSSSelector::PseudoClass);
     
    11001061    switch (selector->pseudoClassType()) {
    11011062    case CSSSelector::PseudoClassWindowInactive:
    1102         return isWindowInactive(context.element);
     1063        return isWindowInactive(&element);
    11031064    case CSSSelector::PseudoClassEnabled:
    1104         return scrollbarMatchesEnabledPseudoClass(context);
     1065        return scrollbarMatchesEnabledPseudoClass(checkingContext);
    11051066    case CSSSelector::PseudoClassDisabled:
    1106         return scrollbarMatchesDisabledPseudoClass(context);
     1067        return scrollbarMatchesDisabledPseudoClass(checkingContext);
    11071068    case CSSSelector::PseudoClassHover:
    1108         return scrollbarMatchesHoverPseudoClass(context);
     1069        return scrollbarMatchesHoverPseudoClass(checkingContext);
    11091070    case CSSSelector::PseudoClassActive:
    1110         return scrollbarMatchesActivePseudoClass(context);
     1071        return scrollbarMatchesActivePseudoClass(checkingContext);
    11111072    case CSSSelector::PseudoClassHorizontal:
    1112         return scrollbarMatchesHorizontalPseudoClass(context);
     1073        return scrollbarMatchesHorizontalPseudoClass(checkingContext);
    11131074    case CSSSelector::PseudoClassVertical:
    1114         return scrollbarMatchesVerticalPseudoClass(context);
     1075        return scrollbarMatchesVerticalPseudoClass(checkingContext);
    11151076    case CSSSelector::PseudoClassDecrement:
    1116         return scrollbarMatchesDecrementPseudoClass(context);
     1077        return scrollbarMatchesDecrementPseudoClass(checkingContext);
    11171078    case CSSSelector::PseudoClassIncrement:
    1118         return scrollbarMatchesIncrementPseudoClass(context);
     1079        return scrollbarMatchesIncrementPseudoClass(checkingContext);
    11191080    case CSSSelector::PseudoClassStart:
    1120         return scrollbarMatchesStartPseudoClass(context);
     1081        return scrollbarMatchesStartPseudoClass(checkingContext);
    11211082    case CSSSelector::PseudoClassEnd:
    1122         return scrollbarMatchesEndPseudoClass(context);
     1083        return scrollbarMatchesEndPseudoClass(checkingContext);
    11231084    case CSSSelector::PseudoClassDoubleButton:
    1124         return scrollbarMatchesDoubleButtonPseudoClass(context);
     1085        return scrollbarMatchesDoubleButtonPseudoClass(checkingContext);
    11251086    case CSSSelector::PseudoClassSingleButton:
    1126         return scrollbarMatchesSingleButtonPseudoClass(context);
     1087        return scrollbarMatchesSingleButtonPseudoClass(checkingContext);
    11271088    case CSSSelector::PseudoClassNoButton:
    1128         return scrollbarMatchesNoButtonPseudoClass(context);
     1089        return scrollbarMatchesNoButtonPseudoClass(checkingContext);
    11291090    case CSSSelector::PseudoClassCornerPresent:
    1130         return scrollbarMatchesCornerPresentPseudoClass(context);
     1091        return scrollbarMatchesCornerPresentPseudoClass(checkingContext);
    11311092    default:
    11321093        return false;
  • trunk/Source/WebCore/css/SelectorChecker.h

    r191252 r195293  
    33 *           (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com)
    44 * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com)
    5  * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 Apple Inc. All rights reserved.
     5 * Copyright (C) 2005-2016 Apple Inc. All rights reserved.
    66 * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
    77 * Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org>
     
    7777    SelectorChecker(Document&);
    7878
     79    struct StyleRelation {
     80        enum Type {
     81            AffectedByActive,
     82            AffectedByDrag,
     83            AffectedByEmpty,
     84            AffectedByHover,
     85            AffectedByPreviousSibling,
     86            AffectsNextSibling,
     87            ChildrenAffectedByBackwardPositionalRules,
     88            ChildrenAffectedByFirstChildRules,
     89            ChildrenAffectedByPropertyBasedBackwardPositionalRules,
     90            ChildrenAffectedByLastChildRules,
     91            FirstChild,
     92            LastChild,
     93            NthChildIndex,
     94            Unique,
     95        };
     96        Element& element;
     97        Type type;
     98        unsigned value;
     99    };
     100    using StyleRelations = Vector<StyleRelation, 8>;
     101
    79102    struct CheckingContext {
    80103        CheckingContext(SelectorChecker::Mode resolvingMode)
    81104            : resolvingMode(resolvingMode)
    82             , elementStyle(nullptr)
    83             , pseudoId(NOPSEUDO)
    84             , scrollbar(nullptr)
    85             , scrollbarPart(NoPart)
    86             , scope(nullptr)
    87105        { }
    88106
    89         SelectorChecker::Mode resolvingMode;
    90         RenderStyle* elementStyle;
    91         PseudoId pseudoId;
    92         RenderScrollbar* scrollbar;
    93         ScrollbarPart scrollbarPart;
    94         const ContainerNode* scope;
     107        const SelectorChecker::Mode resolvingMode;
     108        PseudoId pseudoId { NOPSEUDO };
     109        RenderScrollbar* scrollbar { nullptr };
     110        ScrollbarPart scrollbarPart { NoPart };
     111        const ContainerNode* scope { nullptr };
     112
     113        // FIXME: It would be nicer to have a separate object for return values. This requires some more work in the selector compiler.
     114        StyleRelations styleRelations;
     115        PseudoIdSet pseudoIDSet;
    95116    };
    96117
    97     struct CheckingContextWithStatus;
    98 
    99     bool match(const CSSSelector*, Element*, const CheckingContext&, unsigned& specificity) const;
     118    bool match(const CSSSelector&, const Element&, CheckingContext&, unsigned& specificity) const;
    100119
    101120    static bool isCommonPseudoClassSelector(const CSSSelector*);
     
    106125    static unsigned determineLinkMatchType(const CSSSelector*);
    107126
     127    struct LocalContext;
     128   
    108129private:
    109     MatchResult matchRecursively(const CheckingContextWithStatus&, PseudoIdSet&, unsigned& specificity) const;
    110     bool checkOne(const CheckingContextWithStatus&, PseudoIdSet&, MatchType&, unsigned& specificity) const;
    111     bool matchSelectorList(const CheckingContextWithStatus&, Element&, const CSSSelectorList&, unsigned& specificity) const;
     130    MatchResult matchRecursively(CheckingContext&, const LocalContext&, PseudoIdSet&, unsigned& specificity) const;
     131    bool checkOne(CheckingContext&, const LocalContext&, PseudoIdSet&, MatchType&, unsigned& specificity) const;
     132    bool matchSelectorList(CheckingContext&, const LocalContext&, const Element&, const CSSSelectorList&, unsigned& specificity) const;
    112133
    113     bool checkScrollbarPseudoClass(const CheckingContextWithStatus&, const CSSSelector*) const;
     134    bool checkScrollbarPseudoClass(const CheckingContext&, const Element&, const CSSSelector*) const;
    114135
    115136    bool m_strictParsing;
  • trunk/Source/WebCore/css/SelectorCheckerTestFunctions.h

    r191327 r195293  
    6464}
    6565
    66 ALWAYS_INLINE bool isMediaDocument(Element* element)
     66ALWAYS_INLINE bool isMediaDocument(const Element* element)
    6767{
    6868    return element->document().isMediaDocument();
    6969}
    7070
    71 ALWAYS_INLINE bool isChecked(Element& element)
     71ALWAYS_INLINE bool isChecked(const Element& element)
    7272{
    7373    // Even though WinIE allows checked and indeterminate to co-exist, the CSS selector spec says that
     
    7979    }
    8080    if (is<HTMLOptionElement>(element))
    81         return downcast<HTMLOptionElement>(element).selected();
    82 
    83     return false;
    84 }
    85 
    86 ALWAYS_INLINE bool isInRange(Element* element)
     81        return const_cast<HTMLOptionElement&>(downcast<HTMLOptionElement>(element)).selected();
     82
     83    return false;
     84}
     85
     86ALWAYS_INLINE bool isInRange(const Element* element)
    8787{
    8888    return element->isInRange();
    8989}
    9090
    91 ALWAYS_INLINE bool isOutOfRange(Element* element)
     91ALWAYS_INLINE bool isOutOfRange(const Element* element)
    9292{
    9393    return element->isOutOfRange();
  • trunk/Source/WebCore/css/StyleResolver.h

    r194762 r195293  
    611611        SelectorChecker::CheckingContext selectorCheckingContext(SelectorChecker::Mode::QueryingRules);
    612612        unsigned ignoredSpecificity;
    613         if (selectorChecker.match(s, regionElement, selectorCheckingContext, ignoredSpecificity))
     613        if (selectorChecker.match(*s, *regionElement, selectorCheckingContext, ignoredSpecificity))
    614614            return true;
    615615    }
  • trunk/Source/WebCore/cssjit/SelectorCompiler.cpp

    r194496 r195293  
    11/*
    2  * Copyright (C) 2013-2015 Apple Inc. All rights reserved.
     2 * Copyright (C) 2013-2016 Apple Inc. All rights reserved.
    33 * Copyright (C) 2014 Yusuke Suzuki <utatane.tea@gmail.com>
    44 *
     
    292292    void generateContextFunctionCallTest(Assembler::JumpList& failureCases, JSC::FunctionPtr);
    293293    void generateElementIsActive(Assembler::JumpList& failureCases, const SelectorFragment&);
    294     void generateElementIsEmpty(Assembler::JumpList& failureCases, const SelectorFragment&);
    295     void generateElementIsFirstChild(Assembler::JumpList& failureCases, const SelectorFragment&);
     294    void generateElementIsEmpty(Assembler::JumpList& failureCases);
     295    void generateElementIsFirstChild(Assembler::JumpList& failureCases);
    296296    void generateElementIsHovered(Assembler::JumpList& failureCases, const SelectorFragment&);
    297297    void generateElementIsInLanguage(Assembler::JumpList& failureCases, const SelectorFragment&);
    298298    void generateElementIsInLanguage(Assembler::JumpList& failureCases, const Vector<AtomicString>*);
    299     void generateElementIsLastChild(Assembler::JumpList& failureCases, const SelectorFragment&);
    300     void generateElementIsOnlyChild(Assembler::JumpList& failureCases, const SelectorFragment&);
    301     void generateElementHasPlaceholderShown(Assembler::JumpList& failureCases, const SelectorFragment&);
     299    void generateElementIsLastChild(Assembler::JumpList& failureCases);
     300    void generateElementIsOnlyChild(Assembler::JumpList& failureCases);
     301    void generateElementHasPlaceholderShown(Assembler::JumpList& failureCases);
    302302    void generateSynchronizeStyleAttribute(Assembler::RegisterID elementDataArraySizeAndFlags);
    303303    void generateSynchronizeAllAnimatedSVGAttribute(Assembler::RegisterID elementDataArraySizeAndFlags);
     
    324324
    325325    // Helpers.
    326     void addFlagsToElementStyleFromContext(Assembler::RegisterID checkingContext, int64_t);
     326    void generateAddStyleRelationIfResolvingStyle(Assembler::RegisterID element, SelectorChecker::StyleRelation::Type, Optional<Assembler::RegisterID> value = { });
     327    void generateAddStyleRelation(Assembler::RegisterID checkingContext, Assembler::RegisterID element, SelectorChecker::StyleRelation::Type, Optional<Assembler::RegisterID> value = { });
    327328    Assembler::Jump branchOnResolvingModeWithCheckingContext(Assembler::RelationalCondition, SelectorChecker::Mode, Assembler::RegisterID checkingContext);
    328329    Assembler::Jump branchOnResolvingMode(Assembler::RelationalCondition, SelectorChecker::Mode, Assembler::RegisterID checkingContext);
     
    333334    void generateRequestedPseudoElementEqualsToSelectorPseudoElement(Assembler::JumpList& failureCases, const SelectorFragment&, Assembler::RegisterID checkingContext);
    334335    void generateSpecialFailureInQuirksModeForActiveAndHoverIfNeeded(Assembler::JumpList& failureCases, const SelectorFragment&);
    335     void markElementIfResolvingStyle(Assembler::RegisterID, int32_t);
    336336    Assembler::JumpList jumpIfNoPreviousAdjacentElement();
    337337    Assembler::JumpList jumpIfNoNextAdjacentElement();
     
    18921892        }
    18931893        if (shouldMarkStyleIsAffectedByPreviousSibling(fragment))
    1894             markElementIfResolvingStyle(elementAddressRegister, Node::flagStyleIsAffectedByPreviousSibling());
     1894            generateAddStyleRelationIfResolvingStyle(elementAddressRegister, SelectorChecker::StyleRelation::AffectedByPreviousSibling);
    18951895        generateBacktrackingTailsIfNeeded(failureCases, fragment);
    18961896    }
     
    21362136{
    21372137    generateWalkToPreviousAdjacent(failureCases, fragment);
    2138     markElementIfResolvingStyle(elementAddressRegister, Node::flagAffectsNextSiblingElementStyle());
     2138    generateAddStyleRelationIfResolvingStyle(elementAddressRegister, SelectorChecker::StyleRelation::AffectsNextSibling);
    21392139
    21402140    Assembler::JumpList matchingTagNameFailureCases;
     
    21612161
    21622162    generateWalkToPreviousAdjacent(failureCases, fragment);
    2163     markElementIfResolvingStyle(elementAddressRegister, Node::flagAffectsNextSiblingElementStyle());
     2163    generateAddStyleRelationIfResolvingStyle(elementAddressRegister, SelectorChecker::StyleRelation::AffectsNextSibling);
    21642164
    21652165    if (fragment.backtrackingFlags & BacktrackingFlag::IndirectAdjacentEntryPoint)
     
    21712171}
    21722172
    2173 
    2174 void SelectorCodeGenerator::addFlagsToElementStyleFromContext(Assembler::RegisterID checkingContext, int64_t newFlag)
     2173void SelectorCodeGenerator::generateAddStyleRelationIfResolvingStyle(Assembler::RegisterID element, SelectorChecker::StyleRelation::Type relationType, Optional<Assembler::RegisterID> value)
     2174{
     2175    if (m_selectorContext == SelectorContext::QuerySelector)
     2176        return;
     2177
     2178    LocalRegister checkingContext(m_registerAllocator);
     2179    Assembler::Jump notResolvingStyle = jumpIfNotResolvingStyle(checkingContext);
     2180
     2181    generateAddStyleRelation(checkingContext, element, relationType, value);
     2182
     2183    notResolvingStyle.link(&m_assembler);
     2184}
     2185
     2186static void addStyleRelationFunction(SelectorChecker::CheckingContext* checkingContext, Element* element)
     2187{
     2188    checkingContext->styleRelations.append({ *element, SelectorChecker::StyleRelation::AffectedByActive, 1 });
     2189}
     2190
     2191void SelectorCodeGenerator::generateAddStyleRelation(Assembler::RegisterID checkingContext, Assembler::RegisterID element, SelectorChecker::StyleRelation::Type relationType, Optional<Assembler::RegisterID> value)
    21752192{
    21762193    ASSERT(m_selectorContext != SelectorContext::QuerySelector);
    21772194
    2178     LocalRegister childStyle(m_registerAllocator);
    2179     m_assembler.loadPtr(Assembler::Address(checkingContext, OBJECT_OFFSETOF(SelectorChecker::CheckingContext, elementStyle)), childStyle);
    2180 
    2181     // FIXME: We should look into doing something smart in MacroAssembler instead.
    2182     Assembler::Address flagAddress(childStyle, RenderStyle::noninheritedFlagsMemoryOffset() + RenderStyle::NonInheritedFlags::flagsMemoryOffset());
    2183 #if CPU(ARM_THUMB2)
    2184     int32_t flagLowBits = newFlag & 0xffffffff;
    2185     int32_t flagHighBits = newFlag >> 32;
    2186     if (flagLowBits)
    2187         m_assembler.or32(Assembler::TrustedImm32(flagLowBits), flagAddress);
    2188     if (flagHighBits) {
    2189         Assembler::Address flagHighAddress = flagAddress.withOffset(4);
    2190         m_assembler.or32(Assembler::TrustedImm32(flagHighBits), flagHighAddress);
    2191     }
    2192 #elif CPU(X86_64) || CPU(ARM64)
    2193     LocalRegister flags(m_registerAllocator);
    2194     m_assembler.load64(flagAddress, flags);
    2195     LocalRegister isFirstChildStateFlagImmediate(m_registerAllocator);
    2196     m_assembler.move(Assembler::TrustedImm64(newFlag), isFirstChildStateFlagImmediate);
    2197     m_assembler.or64(isFirstChildStateFlagImmediate, flags);
    2198     m_assembler.store64(flags, flagAddress);
    2199 #else
    2200 #error SelectorCodeGenerator::addFlagsToElementStyleFromContext not implemented for this architecture.
    2201 #endif
     2195    // FIXME: Append to vector without a function call at least when there is sufficient capacity.
     2196    FunctionCall functionCall(m_assembler, m_registerAllocator, m_stackAllocator, m_functionCalls);
     2197    functionCall.setFunctionAddress(addStyleRelationFunction);
     2198    functionCall.setTwoArguments(checkingContext, element);
     2199    functionCall.call();
     2200
     2201    Assembler::Address vectorAddress(checkingContext, OBJECT_OFFSETOF(SelectorChecker::CheckingContext, styleRelations));
     2202    auto dataAddress = vectorAddress.withOffset(SelectorChecker::StyleRelations::dataMemoryOffset());
     2203    auto sizeAddress = vectorAddress.withOffset(SelectorChecker::StyleRelations::sizeMemoryOffset());
     2204
     2205    LocalRegister relationPointer(m_registerAllocator);
     2206    m_assembler.load32(sizeAddress, relationPointer);
     2207    m_assembler.sub32(Assembler::TrustedImm32(1), relationPointer);
     2208    m_assembler.mul32(Assembler::TrustedImm32(sizeof(SelectorChecker::StyleRelation)), relationPointer, relationPointer);
     2209    m_assembler.addPtr(dataAddress, relationPointer);
     2210
     2211    Assembler::Address typeAddress(relationPointer, OBJECT_OFFSETOF(SelectorChecker::StyleRelation, type));
     2212    m_assembler.store32(Assembler::TrustedImm32(relationType), typeAddress);
     2213
     2214    if (value) {
     2215        Assembler::Address valueAddress(relationPointer, OBJECT_OFFSETOF(SelectorChecker::StyleRelation, value));
     2216        m_assembler.store32(*value, valueAddress);
     2217    }
    22022218}
    22032219
     
    24192435
    24202436    failureCases.append(modulo(Assembler::NonZero, inputDividend, divisor));
    2421 }
    2422 
    2423 static void setNodeFlag(Assembler& assembler, Assembler::RegisterID elementAddress, int32_t flag)
    2424 {
    2425     assembler.or32(Assembler::TrustedImm32(flag), Assembler::Address(elementAddress, Node::nodeFlagsMemoryOffset()));
    2426 }
    2427 
    2428 void SelectorCodeGenerator::markElementIfResolvingStyle(Assembler::RegisterID element, int32_t nodeFlag)
    2429 {
    2430     if (m_selectorContext == SelectorContext::QuerySelector)
    2431         return;
    2432 
    2433     Assembler::JumpList skipMarking;
    2434     {
    2435         LocalRegister checkingContext(m_registerAllocator);
    2436         skipMarking.append(jumpIfNotResolvingStyle(checkingContext));
    2437     }
    2438 
    2439     setNodeFlag(m_assembler, element, nodeFlag);
    2440 
    2441     skipMarking.link(&m_assembler);
    24422437}
    24432438
     
    25482543        generateElementIsActive(matchingPostTagNameFailureCases, fragment);
    25492544    if (fragment.pseudoClasses.contains(CSSSelector::PseudoClassEmpty))
    2550         generateElementIsEmpty(matchingPostTagNameFailureCases, fragment);
     2545        generateElementIsEmpty(matchingPostTagNameFailureCases);
    25512546    if (fragment.pseudoClasses.contains(CSSSelector::PseudoClassHover))
    25522547        generateElementIsHovered(matchingPostTagNameFailureCases, fragment);
    25532548    if (fragment.pseudoClasses.contains(CSSSelector::PseudoClassOnlyChild))
    2554         generateElementIsOnlyChild(matchingPostTagNameFailureCases, fragment);
     2549        generateElementIsOnlyChild(matchingPostTagNameFailureCases);
    25552550    if (fragment.pseudoClasses.contains(CSSSelector::PseudoClassPlaceholderShown))
    2556         generateElementHasPlaceholderShown(matchingPostTagNameFailureCases, fragment);
     2551        generateElementHasPlaceholderShown(matchingPostTagNameFailureCases);
    25572552    if (fragment.pseudoClasses.contains(CSSSelector::PseudoClassFirstChild))
    2558         generateElementIsFirstChild(matchingPostTagNameFailureCases, fragment);
     2553        generateElementIsFirstChild(matchingPostTagNameFailureCases);
    25592554    if (fragment.pseudoClasses.contains(CSSSelector::PseudoClassLastChild))
    2560         generateElementIsLastChild(matchingPostTagNameFailureCases, fragment);
     2555        generateElementIsLastChild(matchingPostTagNameFailureCases);
    25612556    if (!fragment.nthChildFilters.isEmpty())
    25622557        generateElementIsNthChild(matchingPostTagNameFailureCases, fragment);
     
    30533048}
    30543049
    3055 static void setFirstChildState(Element* element)
    3056 {
    3057     if (RenderStyle* style = element->renderStyle())
    3058         style->setFirstChildState();
    3059 }
    3060 
    30613050static bool elementIsActive(Element* element)
    30623051{
     
    30643053}
    30653054
    3066 static bool elementIsActiveForStyleResolution(Element* element, const SelectorChecker::CheckingContext* checkingContext)
    3067 {
    3068     if (checkingContext->resolvingMode == SelectorChecker::Mode::ResolvingStyle)
    3069         element->setChildrenAffectedByActive();
    3070     return element->active() || InspectorInstrumentation::forcePseudoState(*element, CSSSelector::PseudoClassActive);
    3071 }
    3072 
    30733055void SelectorCodeGenerator::generateElementIsActive(Assembler::JumpList& failureCases, const SelectorFragment& fragment)
    30743056{
    30753057    generateSpecialFailureInQuirksModeForActiveAndHoverIfNeeded(failureCases, fragment);
    3076     if (m_selectorContext == SelectorContext::QuerySelector) {
    3077         FunctionCall functionCall(m_assembler, m_registerAllocator, m_stackAllocator, m_functionCalls);
    3078         functionCall.setFunctionAddress(elementIsActive);
    3079         functionCall.setOneArgument(elementAddressRegister);
    3080         failureCases.append(functionCall.callAndBranchOnBooleanReturnValue(Assembler::Zero));
    3081         return;
    3082     }
    3083 
    3084     if (fragmentMatchesTheRightmostElement(m_selectorContext, fragment)) {
    3085         LocalRegister checkingContext(m_registerAllocator);
    3086         Assembler::Jump notResolvingStyle = jumpIfNotResolvingStyle(checkingContext);
    3087         addFlagsToElementStyleFromContext(checkingContext, RenderStyle::NonInheritedFlags::flagIsaffectedByActive());
    3088         notResolvingStyle.link(&m_assembler);
    3089 
    3090         FunctionCall functionCall(m_assembler, m_registerAllocator, m_stackAllocator, m_functionCalls);
    3091         functionCall.setFunctionAddress(elementIsActive);
    3092         functionCall.setOneArgument(elementAddressRegister);
    3093         failureCases.append(functionCall.callAndBranchOnBooleanReturnValue(Assembler::Zero));
    3094     } else {
    3095         Assembler::RegisterID checkingContext = m_registerAllocator.allocateRegisterWithPreference(JSC::GPRInfo::argumentGPR1);
    3096         loadCheckingContext(checkingContext);
    3097         m_registerAllocator.deallocateRegister(checkingContext);
    3098 
    3099         FunctionCall functionCall(m_assembler, m_registerAllocator, m_stackAllocator, m_functionCalls);
    3100         functionCall.setFunctionAddress(elementIsActiveForStyleResolution);
    3101         functionCall.setTwoArguments(elementAddressRegister, checkingContext);
    3102         failureCases.append(functionCall.callAndBranchOnBooleanReturnValue(Assembler::Zero));
    3103     }
     3058
     3059    generateAddStyleRelationIfResolvingStyle(elementAddressRegister, SelectorChecker::StyleRelation::AffectedByActive);
     3060
     3061    FunctionCall functionCall(m_assembler, m_registerAllocator, m_stackAllocator, m_functionCalls);
     3062    functionCall.setFunctionAddress(elementIsActive);
     3063    functionCall.setOneArgument(elementAddressRegister);
     3064    failureCases.append(functionCall.callAndBranchOnBooleanReturnValue(Assembler::Zero));
    31043065}
    31053066
     
    31303091}
    31313092
    3132 static void setElementStyleIsAffectedByEmpty(Element* element)
    3133 {
    3134     element->setStyleAffectedByEmpty();
    3135 }
    3136 
    3137 static void setElementStyleFromContextIsAffectedByEmptyAndUpdateRenderStyleIfNecessary(SelectorChecker::CheckingContext* context, bool isEmpty)
    3138 {
    3139     ASSERT(context->elementStyle);
    3140     context->elementStyle->setEmptyState(isEmpty);
    3141 }
    3142 
    3143 void SelectorCodeGenerator::generateElementIsEmpty(Assembler::JumpList& failureCases, const SelectorFragment& fragment)
     3093void SelectorCodeGenerator::generateElementIsEmpty(Assembler::JumpList& failureCases)
    31443094{
    31453095    if (m_selectorContext == SelectorContext::QuerySelector) {
     
    31563106    notEmpty.link(&m_assembler);
    31573107
    3158     Assembler::Jump skipMarking;
    3159     if (fragmentMatchesTheRightmostElement(m_selectorContext, fragment)) {
    3160         {
    3161             LocalRegister checkingContext(m_registerAllocator);
    3162             skipMarking = jumpIfNotResolvingStyle(checkingContext);
    3163 
    3164             FunctionCall functionCall(m_assembler, m_registerAllocator, m_stackAllocator, m_functionCalls);
    3165             functionCall.setFunctionAddress(setElementStyleFromContextIsAffectedByEmptyAndUpdateRenderStyleIfNecessary);
    3166             functionCall.setTwoArguments(checkingContext, isEmptyResults);
    3167             functionCall.call();
    3168         }
    3169 
    3170         FunctionCall functionCall(m_assembler, m_registerAllocator, m_stackAllocator, m_functionCalls);
    3171         functionCall.setFunctionAddress(setElementStyleIsAffectedByEmpty);
    3172         functionCall.setOneArgument(elementAddressRegister);
    3173         functionCall.call();
    3174     } else {
    3175         {
    3176             LocalRegister checkingContext(m_registerAllocator);
    3177             skipMarking = jumpIfNotResolvingStyle(checkingContext);
    3178         }
    3179         FunctionCall functionCall(m_assembler, m_registerAllocator, m_stackAllocator, m_functionCalls);
    3180         functionCall.setFunctionAddress(setElementStyleIsAffectedByEmpty);
    3181         functionCall.setOneArgument(elementAddressRegister);
    3182         functionCall.call();
    3183     }
    3184     skipMarking.link(&m_assembler);
     3108    generateAddStyleRelationIfResolvingStyle(elementAddressRegister, SelectorChecker::StyleRelation::AffectedByEmpty, Assembler::RegisterID(isEmptyResults));
    31853109
    31863110    failureCases.append(m_assembler.branchTest32(Assembler::Zero, isEmptyResults));
    31873111}
    31883112
    3189 void SelectorCodeGenerator::generateElementIsFirstChild(Assembler::JumpList& failureCases, const SelectorFragment& fragment)
     3113void SelectorCodeGenerator::generateElementIsFirstChild(Assembler::JumpList& failureCases)
    31903114{
    31913115    if (m_selectorContext == SelectorContext::QuerySelector) {
     
    32173141    Assembler::Jump notResolvingStyle = jumpIfNotResolvingStyle(checkingContext);
    32183142
    3219     setNodeFlag(m_assembler, parentElement, Node::flagChildrenAffectedByFirstChildRulesFlag());
     3143    generateAddStyleRelation(checkingContext, parentElement, SelectorChecker::StyleRelation::ChildrenAffectedByFirstChildRules);
    32203144    m_registerAllocator.deallocateRegister(parentElement);
    32213145
     
    32243148    failureCases.append(m_assembler.branchTest32(Assembler::NonZero, isFirstChildRegister));
    32253149
    3226     if (fragmentMatchesTheRightmostElement(m_selectorContext, fragment))
    3227         addFlagsToElementStyleFromContext(checkingContext, RenderStyle::NonInheritedFlags::setFirstChildStateFlags());
    3228     else {
    3229         FunctionCall functionCall(m_assembler, m_registerAllocator, m_stackAllocator, m_functionCalls);
    3230         functionCall.setFunctionAddress(setFirstChildState);
    3231         Assembler::RegisterID elementAddress = elementAddressRegister;
    3232         functionCall.setOneArgument(elementAddress);
    3233         functionCall.call();
    3234     }
     3150    generateAddStyleRelation(checkingContext, elementAddressRegister, SelectorChecker::StyleRelation::FirstChild);
    32353151
    32363152    notResolvingStyle.link(&m_assembler);
     
    32433159}
    32443160
    3245 static bool elementIsHoveredForStyleResolution(Element* element, const SelectorChecker::CheckingContext* checkingContext)
    3246 {
    3247     if (checkingContext->resolvingMode == SelectorChecker::Mode::ResolvingStyle)
    3248         element->setChildrenAffectedByHover();
    3249     return element->hovered() || InspectorInstrumentation::forcePseudoState(*element, CSSSelector::PseudoClassHover);
    3250 }
    3251 
    32523161void SelectorCodeGenerator::generateElementIsHovered(Assembler::JumpList& failureCases, const SelectorFragment& fragment)
    32533162{
    32543163    generateSpecialFailureInQuirksModeForActiveAndHoverIfNeeded(failureCases, fragment);
    3255     if (m_selectorContext == SelectorContext::QuerySelector) {
    3256         FunctionCall functionCall(m_assembler, m_registerAllocator, m_stackAllocator, m_functionCalls);
    3257         functionCall.setFunctionAddress(elementIsHovered);
    3258         functionCall.setOneArgument(elementAddressRegister);
    3259         failureCases.append(functionCall.callAndBranchOnBooleanReturnValue(Assembler::Zero));
    3260         return;
    3261     }
    3262 
    3263     if (fragmentMatchesTheRightmostElement(m_selectorContext, fragment)) {
    3264         LocalRegisterWithPreference checkingContext(m_registerAllocator, JSC::GPRInfo::argumentGPR1);
    3265         Assembler::Jump notResolvingStyle = jumpIfNotResolvingStyle(checkingContext);
    3266         addFlagsToElementStyleFromContext(checkingContext, RenderStyle::NonInheritedFlags::flagIsaffectedByHover());
    3267         notResolvingStyle.link(&m_assembler);
    3268 
    3269         FunctionCall functionCall(m_assembler, m_registerAllocator, m_stackAllocator, m_functionCalls);
    3270         functionCall.setFunctionAddress(elementIsHovered);
    3271         functionCall.setOneArgument(elementAddressRegister);
    3272         failureCases.append(functionCall.callAndBranchOnBooleanReturnValue(Assembler::Zero));
    3273     } else {
    3274         Assembler::RegisterID checkingContext = m_registerAllocator.allocateRegisterWithPreference(JSC::GPRInfo::argumentGPR1);
    3275         loadCheckingContext(checkingContext);
    3276         m_registerAllocator.deallocateRegister(checkingContext);
    3277 
    3278         FunctionCall functionCall(m_assembler, m_registerAllocator, m_stackAllocator, m_functionCalls);
    3279         functionCall.setFunctionAddress(elementIsHoveredForStyleResolution);
    3280         functionCall.setTwoArguments(elementAddressRegister, checkingContext);
    3281         failureCases.append(functionCall.callAndBranchOnBooleanReturnValue(Assembler::Zero));
    3282     }
     3164
     3165    generateAddStyleRelationIfResolvingStyle(elementAddressRegister, SelectorChecker::StyleRelation::AffectedByHover);
     3166
     3167    FunctionCall functionCall(m_assembler, m_registerAllocator, m_stackAllocator, m_functionCalls);
     3168    functionCall.setFunctionAddress(elementIsHovered);
     3169    functionCall.setOneArgument(elementAddressRegister);
     3170    failureCases.append(functionCall.callAndBranchOnBooleanReturnValue(Assembler::Zero));
    32833171}
    32843172
     
    33013189}
    33023190
    3303 static void setLastChildState(Element* element)
    3304 {
    3305     if (RenderStyle* style = element->renderStyle())
    3306         style->setLastChildState();
    3307 }
    3308 
    3309 void SelectorCodeGenerator::generateElementIsLastChild(Assembler::JumpList& failureCases, const SelectorFragment& fragment)
     3191void SelectorCodeGenerator::generateElementIsLastChild(Assembler::JumpList& failureCases)
    33103192{
    33113193    if (m_selectorContext == SelectorContext::QuerySelector) {
     
    33433225    Assembler::Jump notResolvingStyle = jumpIfNotResolvingStyle(checkingContext);
    33443226
    3345     setNodeFlag(m_assembler, parentElement, Node::flagChildrenAffectedByLastChildRulesFlag());
     3227    generateAddStyleRelation(checkingContext, parentElement, SelectorChecker::StyleRelation::ChildrenAffectedByLastChildRules);
    33463228    m_registerAllocator.deallocateRegister(parentElement);
    33473229
     
    33503232    failureCases.append(m_assembler.branchTest32(Assembler::NonZero, isLastChildRegister));
    33513233
    3352     if (fragmentMatchesTheRightmostElement(m_selectorContext, fragment))
    3353         addFlagsToElementStyleFromContext(checkingContext, RenderStyle::NonInheritedFlags::setLastChildStateFlags());
    3354     else {
    3355         FunctionCall functionCall(m_assembler, m_registerAllocator, m_stackAllocator, m_functionCalls);
    3356         functionCall.setFunctionAddress(setLastChildState);
    3357         Assembler::RegisterID elementAddress = elementAddressRegister;
    3358         functionCall.setOneArgument(elementAddress);
    3359         functionCall.call();
    3360     }
     3234    generateAddStyleRelation(checkingContext, elementAddressRegister, SelectorChecker::StyleRelation::LastChild);
    33613235
    33623236    notResolvingStyle.link(&m_assembler);
     
    33643238}
    33653239
    3366 static void setOnlyChildState(Element* element)
    3367 {
    3368     if (RenderStyle* style = element->renderStyle()) {
    3369         style->setFirstChildState();
    3370         style->setLastChildState();
    3371     }
    3372 }
    3373 
    3374 void SelectorCodeGenerator::generateElementIsOnlyChild(Assembler::JumpList& failureCases, const SelectorFragment& fragment)
     3240void SelectorCodeGenerator::generateElementIsOnlyChild(Assembler::JumpList& failureCases)
    33753241{
    33763242    // Is Only child is pretty much a combination of isFirstChild + isLastChild. The main difference is that tree marking is combined.
     
    34183284    Assembler::Jump notResolvingStyle = jumpIfNotResolvingStyle(checkingContext);
    34193285
    3420     setNodeFlag(m_assembler, parentElement, Node::flagChildrenAffectedByFirstChildRulesFlag() | Node::flagChildrenAffectedByLastChildRulesFlag());
     3286    generateAddStyleRelation(checkingContext, parentElement, SelectorChecker::StyleRelation::ChildrenAffectedByFirstChildRules);
     3287    generateAddStyleRelation(checkingContext, parentElement, SelectorChecker::StyleRelation::ChildrenAffectedByLastChildRules);
     3288
    34213289    m_registerAllocator.deallocateRegister(parentElement);
    34223290
     
    34253293    failureCases.append(m_assembler.branchTest32(Assembler::NonZero, isOnlyChildRegister));
    34263294
    3427     if (fragmentMatchesTheRightmostElement(m_selectorContext, fragment))
    3428         addFlagsToElementStyleFromContext(checkingContext, RenderStyle::NonInheritedFlags::setFirstChildStateFlags() | RenderStyle::NonInheritedFlags::setLastChildStateFlags());
    3429     else {
    3430         FunctionCall functionCall(m_assembler, m_registerAllocator, m_stackAllocator, m_functionCalls);
    3431         functionCall.setFunctionAddress(setOnlyChildState);
    3432         Assembler::RegisterID elementAddress = elementAddressRegister;
    3433         functionCall.setOneArgument(elementAddress);
    3434         functionCall.call();
    3435     }
     3295    generateAddStyleRelation(checkingContext, elementAddressRegister, SelectorChecker::StyleRelation::FirstChild);
     3296    generateAddStyleRelation(checkingContext, elementAddressRegister, SelectorChecker::StyleRelation::LastChild);
    34363297
    34373298    notResolvingStyle.link(&m_assembler);
     
    34393300}
    34403301
    3441 static bool makeContextStyleUniqueIfNecessaryAndTestIsPlaceholderShown(Element* element, const SelectorChecker::CheckingContext* checkingContext)
     3302static bool makeContextStyleUniqueIfNecessaryAndTestIsPlaceholderShown(Element* element, SelectorChecker::CheckingContext* checkingContext)
    34423303{
    34433304    if (is<HTMLTextFormControlElement>(*element)) {
    34443305        if (checkingContext->resolvingMode == SelectorChecker::Mode::ResolvingStyle)
    3445             checkingContext->elementStyle->setUnique();
     3306            checkingContext->styleRelations.append({ *element, SelectorChecker::StyleRelation::Unique, 1 });
    34463307        return downcast<HTMLTextFormControlElement>(*element).isPlaceholderVisible();
    34473308    }
     
    34493310}
    34503311
    3451 static bool makeElementStyleUniqueIfNecessaryAndTestIsPlaceholderShown(Element* element, const SelectorChecker::CheckingContext* checkingContext)
    3452 {
    3453     if (is<HTMLTextFormControlElement>(*element)) {
    3454         if (checkingContext->resolvingMode == SelectorChecker::Mode::ResolvingStyle) {
    3455             if (RenderStyle* style = element->renderStyle())
    3456                 style->setUnique();
    3457         }
    3458         return downcast<HTMLTextFormControlElement>(*element).isPlaceholderVisible();
    3459     }
    3460     return false;
    3461 }
    3462 
    34633312static bool isPlaceholderShown(Element* element)
    34643313{
     
    34663315}
    34673316
    3468 void SelectorCodeGenerator::generateElementHasPlaceholderShown(Assembler::JumpList& failureCases, const SelectorFragment& fragment)
     3317void SelectorCodeGenerator::generateElementHasPlaceholderShown(Assembler::JumpList& failureCases)
    34693318{
    34703319    if (m_selectorContext == SelectorContext::QuerySelector) {
     
    34813330
    34823331    FunctionCall functionCall(m_assembler, m_registerAllocator, m_stackAllocator, m_functionCalls);
    3483     if (fragmentMatchesTheRightmostElement(m_selectorContext, fragment))
    3484         functionCall.setFunctionAddress(makeContextStyleUniqueIfNecessaryAndTestIsPlaceholderShown);
    3485     else
    3486         functionCall.setFunctionAddress(makeElementStyleUniqueIfNecessaryAndTestIsPlaceholderShown);
     3332    functionCall.setFunctionAddress(makeContextStyleUniqueIfNecessaryAndTestIsPlaceholderShown);
    34873333    functionCall.setTwoArguments(elementAddressRegister, checkingContext);
    34883334    failureCases.append(functionCall.callAndBranchOnBooleanReturnValue(Assembler::Zero));
     
    35863432}
    35873433
    3588 static void setElementChildIndex(Element* element, int index)
    3589 {
    3590     element->setChildIndex(index);
    3591 }
    3592 
    35933434static bool nthFilterIsAlwaysSatisified(int a, int b)
    35943435{
     
    36173458
    36183459    if (!isAdjacentRelation(fragment.relationToRightFragment))
    3619         markElementIfResolvingStyle(elementAddressRegister, Node::flagStyleIsAffectedByPreviousSibling());
     3460        generateAddStyleRelationIfResolvingStyle(elementAddressRegister, SelectorChecker::StyleRelation::AffectedByPreviousSibling);
    36203461
    36213462    // Setup the counter at 1.
     
    36353476        Assembler::JumpList noCachedChildIndexCases;
    36363477        generateWalkToPreviousAdjacentElement(noMoreSiblingsCases, previousSibling);
    3637         markElementIfResolvingStyle(previousSibling, Node::flagAffectsNextSiblingElementStyle());
     3478        generateAddStyleRelationIfResolvingStyle(previousSibling, SelectorChecker::StyleRelation::AffectsNextSibling);
    36383479        noCachedChildIndexCases.append(m_assembler.branchTest32(Assembler::Zero, Assembler::Address(previousSibling, Node::nodeFlagsMemoryOffset()), Assembler::TrustedImm32(Node::flagHasRareData())));
    36393480        {
     
    36513492        Assembler::Label loopStart = m_assembler.label();
    36523493        generateWalkToPreviousAdjacentElement(noMoreSiblingsCases, previousSibling);
    3653         markElementIfResolvingStyle(previousSibling, Node::flagAffectsNextSiblingElementStyle());
     3494        generateAddStyleRelationIfResolvingStyle(previousSibling, SelectorChecker::StyleRelation::AffectsNextSibling);
    36543495        m_assembler.add32(Assembler::TrustedImm32(1), elementCounter);
    36553496        m_assembler.jump().linkTo(loopStart, &m_assembler);
     
    36573498    }
    36583499
    3659     // Tree marking when doing style resolution.
    3660     if (m_selectorContext != SelectorContext::QuerySelector) {
    3661         LocalRegister checkingContext(m_registerAllocator);
    3662         Assembler::Jump notResolvingStyle = jumpIfNotResolvingStyle(checkingContext);
    3663 
    3664         Assembler::RegisterID elementAddress = elementAddressRegister;
    3665         FunctionCall functionCall(m_assembler, m_registerAllocator, m_stackAllocator, m_functionCalls);
    3666         functionCall.setFunctionAddress(setElementChildIndex);
    3667         functionCall.setTwoArguments(elementAddress, elementCounter);
    3668         functionCall.call();
    3669 
    3670         notResolvingStyle.link(&m_assembler);
    3671     }
     3500    generateAddStyleRelationIfResolvingStyle(elementAddressRegister, SelectorChecker::StyleRelation::NthChildIndex, Assembler::RegisterID(elementCounter));
    36723501
    36733502    for (const auto& slot : validSubsetFilters)
     
    36963525
    36973526    if (!isAdjacentRelation(fragment.relationToRightFragment))
    3698         markElementIfResolvingStyle(elementAddressRegister, Node::flagStyleIsAffectedByPreviousSibling());
     3527        generateAddStyleRelationIfResolvingStyle(elementAddressRegister, SelectorChecker::StyleRelation::AffectedByPreviousSibling);
    36993528
    37003529    for (const NthChildOfSelectorInfo* nthChildOfSelectorInfo : validSubsetFilters) {
     
    37133542
    37143543            generateWalkToPreviousAdjacentElement(noMoreSiblingsCases, previousSibling);
    3715             markElementIfResolvingStyle(previousSibling, Node::flagAffectsNextSiblingElementStyle());
     3544            generateAddStyleRelationIfResolvingStyle(previousSibling, SelectorChecker::StyleRelation::AffectsNextSibling);
    37163545
    37173546            Assembler::JumpList localFailureCases;
     
    37283557}
    37293558
    3730 static void setChildrenAffectedByBackwardPositionalRules(Element* element)
    3731 {
    3732     element->setChildrenAffectedByBackwardPositionalRules();
    3733 }
    3734 
    37353559void SelectorCodeGenerator::generateElementIsNthLastChild(Assembler::JumpList& failureCases, const SelectorFragment& fragment)
    37363560{
     
    37413565        generateWalkToParentElement(failureCases, parentElement);
    37423566
    3743         if (m_selectorContext != SelectorContext::QuerySelector) {
    3744             Assembler::Jump skipMarking;
    3745             {
    3746                 LocalRegister checkingContext(m_registerAllocator);
    3747                 skipMarking = jumpIfNotResolvingStyle(checkingContext);
    3748             }
    3749 
    3750             FunctionCall functionCall(m_assembler, m_registerAllocator, m_stackAllocator, m_functionCalls);
    3751             functionCall.setFunctionAddress(setChildrenAffectedByBackwardPositionalRules);
    3752             functionCall.setOneArgument(parentElement);
    3753             functionCall.call();
    3754 
    3755             skipMarking.link(&m_assembler);
    3756         }
     3567        generateAddStyleRelationIfResolvingStyle(parentElement, SelectorChecker::StyleRelation::ChildrenAffectedByBackwardPositionalRules);
    37573568
    37583569        failureCases.append(m_assembler.branchTest32(Assembler::Zero, Assembler::Address(parentElement, Node::nodeFlagsMemoryOffset()), Assembler::TrustedImm32(Node::flagIsParsingChildrenFinished())));
     
    37893600}
    37903601
    3791 static void setParentAffectedByLastChildOf(Element* parentElement)
    3792 {
    3793     ASSERT(parentElement);
    3794     parentElement->setChildrenAffectedByPropertyBasedBackwardPositionalRules();
    3795     parentElement->setChildrenAffectedByBackwardPositionalRules();
    3796 }
    3797 
    37983602void SelectorCodeGenerator::generateElementIsNthLastChildOf(Assembler::JumpList& failureCases, const SelectorFragment& fragment)
    37993603{
     
    38043608        generateWalkToParentElement(failureCases, parentElement);
    38053609
    3806         if (m_selectorContext != SelectorContext::QuerySelector) {
    3807             Assembler::Jump skipMarking;
    3808             {
    3809                 LocalRegister checkingContext(m_registerAllocator);
    3810                 skipMarking = jumpIfNotResolvingStyle(checkingContext);
    3811             }
    3812 
    3813             FunctionCall functionCall(m_assembler, m_registerAllocator, m_stackAllocator, m_functionCalls);
    3814             functionCall.setFunctionAddress(setParentAffectedByLastChildOf);
    3815             functionCall.setOneArgument(parentElement);
    3816             functionCall.call();
    3817 
    3818             skipMarking.link(&m_assembler);
    3819         }
     3610        generateAddStyleRelationIfResolvingStyle(parentElement, SelectorChecker::StyleRelation::ChildrenAffectedByPropertyBasedBackwardPositionalRules);
    38203611
    38213612        failureCases.append(m_assembler.branchTest32(Assembler::Zero, Assembler::Address(parentElement, Node::nodeFlagsMemoryOffset()), Assembler::TrustedImm32(Node::flagIsParsingChildrenFinished())));
     
    40043795    if (dynamicPseudo < FIRST_INTERNAL_PSEUDOID) {
    40053796        failureCases.append(branchOnResolvingModeWithCheckingContext(Assembler::NotEqual, SelectorChecker::Mode::ResolvingStyle, checkingContext));
    4006         addFlagsToElementStyleFromContext(checkingContext, RenderStyle::NonInheritedFlags::flagPseudoStyle(dynamicPseudo));
     3797
     3798        Assembler::Address pseudoIDSetAddress(checkingContext, OBJECT_OFFSETOF(SelectorChecker::CheckingContext, pseudoIDSet));
     3799        auto pseudoIDSetDataAddress = pseudoIDSetAddress.withOffset(PseudoIdSet::dataMemoryOffset());
     3800        PseudoIdSet value { dynamicPseudo };
     3801        m_assembler.store32(Assembler::TrustedImm32(value.data()), pseudoIDSetDataAddress);
    40073802    }
    40083803
  • trunk/Source/WebCore/dom/SelectorQuery.cpp

    r195141 r195293  
    119119    selectorCheckingContext.scope = rootNode.isDocumentNode() ? nullptr : &rootNode;
    120120    unsigned ignoredSpecificity;
    121     return selectorChecker.match(selectorData.selector, &element, selectorCheckingContext, ignoredSpecificity);
     121    return selectorChecker.match(*selectorData.selector, element, selectorCheckingContext, ignoredSpecificity);
    122122}
    123123
     
    127127    SelectorChecker::CheckingContext selectorCheckingContext(SelectorChecker::Mode::QueryingRules);
    128128    selectorCheckingContext.scope = rootNode.isDocumentNode() ? nullptr : &rootNode;
    129     Element* currentNode = &element;
    130129    unsigned ignoredSpecificity;
    131     if (!selectorChecker.match(selectorData.selector, currentNode, selectorCheckingContext, ignoredSpecificity))
     130    if (!selectorChecker.match(*selectorData.selector, element, selectorCheckingContext, ignoredSpecificity))
    132131        return nullptr;
    133     return currentNode;
     132    return &element;
    134133}
    135134
  • trunk/Source/WebCore/inspector/InspectorCSSAgent.cpp

    r194819 r195293  
    10511051        for (const CSSSelector* selector = selectorList.first(); selector; selector = CSSSelectorList::next(selector)) {
    10521052            unsigned ignoredSpecificity;
    1053             bool matched = selectorChecker.match(selector, element, context, ignoredSpecificity);
     1053            bool matched = selectorChecker.match(*selector, *element, context, ignoredSpecificity);
    10541054            if (matched)
    10551055                matchingSelectors->addItem(index);
  • trunk/Source/WebCore/inspector/InspectorStyleSheet.cpp

    r194819 r195293  
    863863
    864864        unsigned specificity;
    865         bool okay = selectorChecker.match(&selector, element, context, specificity);
     865        bool okay = selectorChecker.match(selector, *element, context, specificity);
    866866        if (!okay)
    867867            specificity = selector.staticSpecificity(okay);
  • trunk/Source/WebCore/rendering/style/RenderStyleConstants.h

    r194104 r195293  
    140140
    141141    unsigned data() const { return m_data; }
     142
     143    static ptrdiff_t dataMemoryOffset() { return OBJECT_OFFSETOF(PseudoIdSet, m_data); }
     144
    142145private:
    143146    explicit PseudoIdSet(unsigned rawPseudoIdSet)
Note: See TracChangeset for help on using the changeset viewer.