Title: [285262] trunk
Revision
285262
Author
[email protected]
Date
2021-11-04 09:15:14 -0700 (Thu, 04 Nov 2021)

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

Modified Paths

Diff

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-shadow-parts/host-part-001-expected.txt (285261 => 285262)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-shadow-parts/host-part-001-expected.txt	2021-11-04 12:51:27 UTC (rev 285261)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-shadow-parts/host-part-001-expected.txt	2021-11-04 16:15:14 UTC (rev 285262)
@@ -1,3 +1,3 @@
 
-FAIL :host::part works assert_equals: :host::part() works expected "rgb(0, 255, 0)" but got "rgb(0, 0, 0)"
+PASS :host::part works
 

Modified: trunk/Source/WebCore/ChangeLog (285261 => 285262)


--- trunk/Source/WebCore/ChangeLog	2021-11-04 12:51:27 UTC (rev 285261)
+++ trunk/Source/WebCore/ChangeLog	2021-11-04 16:15:14 UTC (rev 285262)
@@ -1,3 +1,37 @@
+2021-11-04  Antti Koivisto  <[email protected]>
+
+        :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:
+
 2021-11-04  Andres Gonzalez  <[email protected]>
 
         Fix for AXObjectCache::postPlatformNotification in isolated tree mode, debug builds.

Modified: trunk/Source/WebCore/css/SelectorChecker.cpp (285261 => 285262)


--- trunk/Source/WebCore/css/SelectorChecker.cpp	2021-11-04 12:51:27 UTC (rev 285261)
+++ trunk/Source/WebCore/css/SelectorChecker.cpp	2021-11-04 16:15:14 UTC (rev 285262)
@@ -76,7 +76,7 @@
     bool pseudoElementEffective { true };
     bool hasScrollbarPseudo { false };
     bool hasSelectionPseudo { false };
-    bool mayMatchHostPseudoClass { false };
+    bool mustMatchHostPseudoClass { false };
 };
 
 static inline void addStyleRelation(SelectorChecker::CheckingContext& checkingContext, const Element& element, Style::Relation::Type type, unsigned value = 1)
@@ -177,7 +177,7 @@
 
     if (checkingContext.isMatchingHostPseudoClass) {
         ASSERT(element.shadowRoot());
-        context.mayMatchHostPseudoClass = true;
+        context.mustMatchHostPseudoClass = true;
     }
 
     PseudoIdSet pseudoIdSet;
@@ -236,7 +236,7 @@
     updatedContext.isMatchElement = false;
     updatedContext.isSubjectOrAdjacentElement = false;
 
-    if (updatedContext.mayMatchHostPseudoClass) {
+    if (updatedContext.mustMatchHostPseudoClass) {
         updatedContext.element = nullptr;
         return updatedContext;
     }
@@ -244,7 +244,7 @@
     // Move to the shadow host if matching :host and the parent is the shadow root.
     if (context.selector->match() == CSSSelector::PseudoClass && context.selector->pseudoClassType() == CSSSelector::PseudoClassHost && is<ShadowRoot>(context.element->parentNode())) {
         updatedContext.element = downcast<ShadowRoot>(*context.element->parentNode()).host();
-        updatedContext.mayMatchHostPseudoClass = true;
+        updatedContext.mustMatchHostPseudoClass = true;
         return updatedContext;
     }
 
@@ -406,12 +406,24 @@
 
             return MatchResult::updateWithMatchType(result, matchType);
         }
-    case CSSSelector::ShadowDescendant:
+    case CSSSelector::ShadowDescendant:  {
+        auto* host = context.element->shadowHost();
+        if (!host)
+            return MatchResult::fails(Match::SelectorFailsCompletely);
+
+        nextContext.element = host;
+        nextContext.firstSelectorOfTheFragment = nextContext.selector;
+        nextContext.isSubjectOrAdjacentElement = false;
+        PseudoIdSet ignoreDynamicPseudo;
+        MatchResult result = matchRecursively(checkingContext, nextContext, ignoreDynamicPseudo);
+
+        return MatchResult::updateWithMatchType(result, matchType);
+    }
     case CSSSelector::ShadowPartDescendant: {
         // Continue matching in the scope where this rule came from.
-        auto* host = relation == CSSSelector::ShadowPartDescendant
-            ? Style::hostForScopeOrdinal(*context.element, checkingContext.styleScopeOrdinal)
-            : context.element->shadowHost();
+        auto* host = checkingContext.styleScopeOrdinal == Style::ScopeOrdinal::Element
+            ? context.element->shadowHost()
+            : Style::hostForScopeOrdinal(*context.element, checkingContext.styleScopeOrdinal);
         if (!host)
             return MatchResult::fails(Match::SelectorFailsCompletely);
 
@@ -418,6 +430,8 @@
         nextContext.element = host;
         nextContext.firstSelectorOfTheFragment = nextContext.selector;
         nextContext.isSubjectOrAdjacentElement = false;
+        // ::part rules from the element's own scope can only match if they apply to :host.
+        nextContext.mustMatchHostPseudoClass = checkingContext.styleScopeOrdinal == Style::ScopeOrdinal::Element;
         PseudoIdSet ignoreDynamicPseudo;
         MatchResult result = matchRecursively(checkingContext, nextContext, ignoreDynamicPseudo);
 
@@ -641,7 +655,7 @@
     const Element& element = *context.element;
     const CSSSelector& selector = *context.selector;
 
-    if (context.mayMatchHostPseudoClass) {
+    if (context.mustMatchHostPseudoClass) {
         // :host doesn't combine with anything except pseudo elements.
         bool isHostPseudoClass = selector.match() == CSSSelector::PseudoClass && selector.pseudoClassType() == CSSSelector::PseudoClassHost;
         bool isPseudoElement = selector.match() == CSSSelector::PseudoElement;
@@ -1089,7 +1103,7 @@
             break;
         }
         case CSSSelector::PseudoClassHost: {
-            if (!context.mayMatchHostPseudoClass)
+            if (!context.mustMatchHostPseudoClass)
                 return false;
             return matchHostPseudoClass(selector, element, checkingContext);
         }
@@ -1171,6 +1185,10 @@
         case CSSSelector::PseudoElementPart: {
             auto translatePartNameToRuleScope = [&](AtomString partName) {
                 Vector<AtomString, 1> mappedNames { partName };
+
+                if (checkingContext.styleScopeOrdinal == Style::ScopeOrdinal::Element)
+                    return mappedNames;
+
                 auto* ruleScopeHost = Style::hostForScopeOrdinal(*context.element, checkingContext.styleScopeOrdinal);
 
                 for (auto* shadowRoot = element.containingShadowRoot(); shadowRoot; shadowRoot = shadowRoot->host()->containingShadowRoot()) {

Modified: trunk/Source/WebCore/style/ElementRuleCollector.cpp (285261 => 285262)


--- trunk/Source/WebCore/style/ElementRuleCollector.cpp	2021-11-04 12:51:27 UTC (rev 285261)
+++ trunk/Source/WebCore/style/ElementRuleCollector.cpp	2021-11-04 16:15:14 UTC (rev 285262)
@@ -301,16 +301,16 @@
     if (partMatchingElement.partNames().isEmpty() || !partMatchingElement.isInShadowTree())
         return;
 
-    matchPartPseudoElementRulesForScope(*partMatchingElement.containingShadowRoot());
+    matchPartPseudoElementRulesForScope(partMatchingElement);
 }
 
-void ElementRuleCollector::matchPartPseudoElementRulesForScope(const ShadowRoot& scopeShadowRoot)
+void ElementRuleCollector::matchPartPseudoElementRulesForScope(const Element& partMatchingElement)
 {
-    auto* host = scopeShadowRoot.host();
-    auto styleScopeOrdinal = ScopeOrdinal::ContainingHost;
+    auto* element = &partMatchingElement;
+    auto styleScopeOrdinal = ScopeOrdinal::Element;
 
-    for (; host; host = host->shadowHost(), --styleScopeOrdinal) {
-        auto& styleScope = Scope::forNode(*host);
+    for (; element; element = element->shadowHost(), --styleScopeOrdinal) {
+        auto& styleScope = Scope::forNode(const_cast<Element&>(*element));
         if (!styleScope.resolver().ruleSets().isAuthorStyleDefined())
             continue;
 
@@ -320,7 +320,7 @@
         collectMatchingRulesForList(&hostAuthorRules.partPseudoElementRules(), scopeMatchRequest);
 
         // Element may only be exposed to styling from enclosing scopes via exportparts attributes.
-        if (host->shadowRoot()->partMappings().isEmpty())
+        if (element != &partMatchingElement && element->shadowRoot()->partMappings().isEmpty())
             break;
     }
 }

Modified: trunk/Source/WebCore/style/ElementRuleCollector.h (285261 => 285262)


--- trunk/Source/WebCore/style/ElementRuleCollector.h	2021-11-04 12:51:27 UTC (rev 285261)
+++ trunk/Source/WebCore/style/ElementRuleCollector.h	2021-11-04 16:15:14 UTC (rev 285262)
@@ -132,7 +132,7 @@
     void matchHostPseudoClassRules();
     void matchSlottedPseudoElementRules();
     void matchPartPseudoElementRules();
-    void matchPartPseudoElementRulesForScope(const ShadowRoot& scopeShadowRoot);
+    void matchPartPseudoElementRulesForScope(const Element& partMatchingElement);
 
     void collectMatchingShadowPseudoElementRules(const MatchRequest&);
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to