Changeset 285262 in webkit


Ignore:
Timestamp:
Nov 4, 2021 9:15:14 AM (9 months ago)
Author:
Antti Koivisto
Message:

:host::part(foo) selector does not select elements inside shadow roots
https://bugs.webkit.org/show_bug.cgi?id=232261
<rdar://problem/84894922>

Reviewed by Simon Fraser.

We need to also look for ::part rules from the element's own scope.

  • css/SelectorChecker.cpp:

(WebCore::SelectorChecker::match const):

Rename mayMatchHostPseudoClass -> mustMatchHostPseudoClass for clarity.

(WebCore::localContextForParent):
(WebCore::SelectorChecker::matchRecursively const):

Split ShadowDescendant and ShadowPartDescendant handling as they are sufficiently different.
Set nextContext.mustMatchHostPseudoClass bit for ::part rules coming from the Element's scope as
it is the only way they can match.

(WebCore::SelectorChecker::checkOne const):

No name mapping for rules from the element's own scope.

  • style/ElementRuleCollector.cpp:

(WebCore::Style::ElementRuleCollector::matchPartPseudoElementRules):
(WebCore::Style::ElementRuleCollector::matchPartPseudoElementRulesForScope):

Also check ::part rules from the element scope.

  • style/ElementRuleCollector.h:
Location:
trunk
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-shadow-parts/host-part-001-expected.txt

    r264522 r285262  
    11
    2 FAIL :host::part works assert_equals: :host::part() works expected "rgb(0, 255, 0)" but got "rgb(0, 0, 0)"
     2PASS :host::part works
    33
  • trunk/Source/WebCore/ChangeLog

    r285258 r285262  
     12021-11-04  Antti Koivisto  <antti@apple.com>
     2
     3        :host::part(foo) selector does not select elements inside shadow roots
     4        https://bugs.webkit.org/show_bug.cgi?id=232261
     5        <rdar://problem/84894922>
     6
     7        Reviewed by Simon Fraser.
     8
     9        We need to also look for ::part rules from the element's own scope.
     10
     11        * css/SelectorChecker.cpp:
     12        (WebCore::SelectorChecker::match const):
     13
     14        Rename mayMatchHostPseudoClass -> mustMatchHostPseudoClass for clarity.
     15
     16        (WebCore::localContextForParent):
     17        (WebCore::SelectorChecker::matchRecursively const):
     18
     19        Split ShadowDescendant and ShadowPartDescendant handling as they are sufficiently different.
     20        Set nextContext.mustMatchHostPseudoClass bit for ::part rules coming from the Element's scope as
     21        it is the only way they can match.
     22
     23        (WebCore::SelectorChecker::checkOne const):
     24
     25        No name mapping for rules from the element's own scope.
     26
     27        * style/ElementRuleCollector.cpp:
     28        (WebCore::Style::ElementRuleCollector::matchPartPseudoElementRules):
     29        (WebCore::Style::ElementRuleCollector::matchPartPseudoElementRulesForScope):
     30
     31        Also check ::part rules from the element scope.
     32
     33        * style/ElementRuleCollector.h:
     34
    1352021-11-04  Andres Gonzalez  <andresg_22@apple.com>
    236
  • trunk/Source/WebCore/css/SelectorChecker.cpp

    r285209 r285262  
    7777    bool hasScrollbarPseudo { false };
    7878    bool hasSelectionPseudo { false };
    79     bool mayMatchHostPseudoClass { false };
     79    bool mustMatchHostPseudoClass { false };
    8080};
    8181
     
    178178    if (checkingContext.isMatchingHostPseudoClass) {
    179179        ASSERT(element.shadowRoot());
    180         context.mayMatchHostPseudoClass = true;
     180        context.mustMatchHostPseudoClass = true;
    181181    }
    182182
     
    237237    updatedContext.isSubjectOrAdjacentElement = false;
    238238
    239     if (updatedContext.mayMatchHostPseudoClass) {
     239    if (updatedContext.mustMatchHostPseudoClass) {
    240240        updatedContext.element = nullptr;
    241241        return updatedContext;
     
    245245    if (context.selector->match() == CSSSelector::PseudoClass && context.selector->pseudoClassType() == CSSSelector::PseudoClassHost && is<ShadowRoot>(context.element->parentNode())) {
    246246        updatedContext.element = downcast<ShadowRoot>(*context.element->parentNode()).host();
    247         updatedContext.mayMatchHostPseudoClass = true;
     247        updatedContext.mustMatchHostPseudoClass = true;
    248248        return updatedContext;
    249249    }
     
    407407            return MatchResult::updateWithMatchType(result, matchType);
    408408        }
    409     case CSSSelector::ShadowDescendant:
    410     case CSSSelector::ShadowPartDescendant: {
    411         // Continue matching in the scope where this rule came from.
    412         auto* host = relation == CSSSelector::ShadowPartDescendant
    413             ? Style::hostForScopeOrdinal(*context.element, checkingContext.styleScopeOrdinal)
    414             : context.element->shadowHost();
     409    case CSSSelector::ShadowDescendant:  {
     410        auto* host = context.element->shadowHost();
    415411        if (!host)
    416412            return MatchResult::fails(Match::SelectorFailsCompletely);
     
    419415        nextContext.firstSelectorOfTheFragment = nextContext.selector;
    420416        nextContext.isSubjectOrAdjacentElement = false;
     417        PseudoIdSet ignoreDynamicPseudo;
     418        MatchResult result = matchRecursively(checkingContext, nextContext, ignoreDynamicPseudo);
     419
     420        return MatchResult::updateWithMatchType(result, matchType);
     421    }
     422    case CSSSelector::ShadowPartDescendant: {
     423        // Continue matching in the scope where this rule came from.
     424        auto* host = checkingContext.styleScopeOrdinal == Style::ScopeOrdinal::Element
     425            ? context.element->shadowHost()
     426            : Style::hostForScopeOrdinal(*context.element, checkingContext.styleScopeOrdinal);
     427        if (!host)
     428            return MatchResult::fails(Match::SelectorFailsCompletely);
     429
     430        nextContext.element = host;
     431        nextContext.firstSelectorOfTheFragment = nextContext.selector;
     432        nextContext.isSubjectOrAdjacentElement = false;
     433        // ::part rules from the element's own scope can only match if they apply to :host.
     434        nextContext.mustMatchHostPseudoClass = checkingContext.styleScopeOrdinal == Style::ScopeOrdinal::Element;
    421435        PseudoIdSet ignoreDynamicPseudo;
    422436        MatchResult result = matchRecursively(checkingContext, nextContext, ignoreDynamicPseudo);
     
    642656    const CSSSelector& selector = *context.selector;
    643657
    644     if (context.mayMatchHostPseudoClass) {
     658    if (context.mustMatchHostPseudoClass) {
    645659        // :host doesn't combine with anything except pseudo elements.
    646660        bool isHostPseudoClass = selector.match() == CSSSelector::PseudoClass && selector.pseudoClassType() == CSSSelector::PseudoClassHost;
     
    10901104        }
    10911105        case CSSSelector::PseudoClassHost: {
    1092             if (!context.mayMatchHostPseudoClass)
     1106            if (!context.mustMatchHostPseudoClass)
    10931107                return false;
    10941108            return matchHostPseudoClass(selector, element, checkingContext);
     
    11721186            auto translatePartNameToRuleScope = [&](AtomString partName) {
    11731187                Vector<AtomString, 1> mappedNames { partName };
     1188
     1189                if (checkingContext.styleScopeOrdinal == Style::ScopeOrdinal::Element)
     1190                    return mappedNames;
     1191
    11741192                auto* ruleScopeHost = Style::hostForScopeOrdinal(*context.element, checkingContext.styleScopeOrdinal);
    11751193
  • trunk/Source/WebCore/style/ElementRuleCollector.cpp

    r285202 r285262  
    302302        return;
    303303
    304     matchPartPseudoElementRulesForScope(*partMatchingElement.containingShadowRoot());
    305 }
    306 
    307 void ElementRuleCollector::matchPartPseudoElementRulesForScope(const ShadowRoot& scopeShadowRoot)
    308 {
    309     auto* host = scopeShadowRoot.host();
    310     auto styleScopeOrdinal = ScopeOrdinal::ContainingHost;
    311 
    312     for (; host; host = host->shadowHost(), --styleScopeOrdinal) {
    313         auto& styleScope = Scope::forNode(*host);
     304    matchPartPseudoElementRulesForScope(partMatchingElement);
     305}
     306
     307void ElementRuleCollector::matchPartPseudoElementRulesForScope(const Element& partMatchingElement)
     308{
     309    auto* element = &partMatchingElement;
     310    auto styleScopeOrdinal = ScopeOrdinal::Element;
     311
     312    for (; element; element = element->shadowHost(), --styleScopeOrdinal) {
     313        auto& styleScope = Scope::forNode(const_cast<Element&>(*element));
    314314        if (!styleScope.resolver().ruleSets().isAuthorStyleDefined())
    315315            continue;
     
    321321
    322322        // Element may only be exposed to styling from enclosing scopes via exportparts attributes.
    323         if (host->shadowRoot()->partMappings().isEmpty())
     323        if (element != &partMatchingElement && element->shadowRoot()->partMappings().isEmpty())
    324324            break;
    325325    }
  • trunk/Source/WebCore/style/ElementRuleCollector.h

    r285202 r285262  
    133133    void matchSlottedPseudoElementRules();
    134134    void matchPartPseudoElementRules();
    135     void matchPartPseudoElementRulesForScope(const ShadowRoot& scopeShadowRoot);
     135    void matchPartPseudoElementRulesForScope(const Element& partMatchingElement);
    136136
    137137    void collectMatchingShadowPseudoElementRules(const MatchRequest&);
Note: See TracChangeset for help on using the changeset viewer.