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&);