- Revision
- 250817
- Author
- an...@apple.com
- Date
- 2019-10-08 00:31:36 -0700 (Tue, 08 Oct 2019)
Log Message
[CSS Shadow Parts] Internal shadow pseudo elements should work with ::part
https://bugs.webkit.org/show_bug.cgi?id=202620
Reviewed by Ryosuke Niwa.
Source/WebCore:
Selectors like ::part(foo)::placeholder should work.
This involves hop out of a UA shadow tree and then from an author shadow tree.
* css/ElementRuleCollector.cpp:
(WebCore::ElementRuleCollector::matchAuthorRules):
(WebCore::ElementRuleCollector::matchPartPseudoElementRules):
If we are matching a pseudo element in a UA shadow tree, see if part rules can match is the surrounding scope.
(WebCore::ElementRuleCollector::matchPartPseudoElementRulesForScope):
* css/ElementRuleCollector.h:
* css/RuleSet.cpp:
(WebCore::RuleSet::addRule):
Sort rules with both internal pseudo element and ::part to the part bucket.
* css/SelectorChecker.cpp:
(WebCore::SelectorChecker::matchRecursively const):
* css/parser/CSSSelectorParser.cpp:
(WebCore::CSSSelectorParser::splitCompoundAtImplicitShadowCrossingCombinator):
Allow multiple ShadowDescendant relations for ::part.
LayoutTests:
Note that imported/w3c/web-platform-tests/css/css-shadow-parts/interaction-with-pseudo-elements.html placeholder subtest still
won't pass because we we don't support getComputedStyle for internal pseudo elements. Visually it now work fully.
* TestExpectations:
Unskip imported/w3c/web-platform-tests/css/css-shadow-parts/interaction-with-placeholder.html
Modified Paths
Diff
Modified: trunk/LayoutTests/ChangeLog (250816 => 250817)
--- trunk/LayoutTests/ChangeLog 2019-10-08 06:22:46 UTC (rev 250816)
+++ trunk/LayoutTests/ChangeLog 2019-10-08 07:31:36 UTC (rev 250817)
@@ -1,3 +1,17 @@
+2019-10-08 Antti Koivisto <an...@apple.com>
+
+ [CSS Shadow Parts] Internal shadow pseudo elements should work with ::part
+ https://bugs.webkit.org/show_bug.cgi?id=202620
+
+ Reviewed by Ryosuke Niwa.
+
+ Note that imported/w3c/web-platform-tests/css/css-shadow-parts/interaction-with-pseudo-elements.html placeholder subtest still
+ won't pass because we we don't support getComputedStyle for internal pseudo elements. Visually it now work fully.
+
+ * TestExpectations:
+
+ Unskip imported/w3c/web-platform-tests/css/css-shadow-parts/interaction-with-placeholder.html
+
2019-10-07 Ryosuke Niwa <rn...@webkit.org>
Add IDL for requestIdleCallback
Modified: trunk/LayoutTests/TestExpectations (250816 => 250817)
--- trunk/LayoutTests/TestExpectations 2019-10-08 06:22:46 UTC (rev 250816)
+++ trunk/LayoutTests/TestExpectations 2019-10-08 07:31:36 UTC (rev 250817)
@@ -3856,9 +3856,6 @@
webkit.org/b/196698 imported/w3c/web-platform-tests/loading/lazyload/image-loading-lazy.tentative.html
webkit.org/b/196698 imported/w3c/web-platform-tests/loading/lazyload/iframe-loading-lazy.tentative.html
-# CSS Shadow Parts
-webkit.org/b/149443 imported/w3c/web-platform-tests/css/css-shadow-parts/interaction-with-placeholder.html [ ImageOnlyFailure ]
-
webkit.org/b/202517 imported/w3c/web-platform-tests/2dcontext/text-styles/2d.text.draw.baseline.ideographic.html [ Skip ]
# Console log lines may appear in a different order so we silence them.
Modified: trunk/Source/WebCore/ChangeLog (250816 => 250817)
--- trunk/Source/WebCore/ChangeLog 2019-10-08 06:22:46 UTC (rev 250816)
+++ trunk/Source/WebCore/ChangeLog 2019-10-08 07:31:36 UTC (rev 250817)
@@ -1,3 +1,34 @@
+2019-10-08 Antti Koivisto <an...@apple.com>
+
+ [CSS Shadow Parts] Internal shadow pseudo elements should work with ::part
+ https://bugs.webkit.org/show_bug.cgi?id=202620
+
+ Reviewed by Ryosuke Niwa.
+
+ Selectors like ::part(foo)::placeholder should work.
+
+ This involves hop out of a UA shadow tree and then from an author shadow tree.
+
+ * css/ElementRuleCollector.cpp:
+ (WebCore::ElementRuleCollector::matchAuthorRules):
+ (WebCore::ElementRuleCollector::matchPartPseudoElementRules):
+
+ If we are matching a pseudo element in a UA shadow tree, see if part rules can match is the surrounding scope.
+
+ (WebCore::ElementRuleCollector::matchPartPseudoElementRulesForScope):
+ * css/ElementRuleCollector.h:
+ * css/RuleSet.cpp:
+ (WebCore::RuleSet::addRule):
+
+ Sort rules with both internal pseudo element and ::part to the part bucket.
+
+ * css/SelectorChecker.cpp:
+ (WebCore::SelectorChecker::matchRecursively const):
+ * css/parser/CSSSelectorParser.cpp:
+ (WebCore::CSSSelectorParser::splitCompoundAtImplicitShadowCrossingCombinator):
+
+ Allow multiple ShadowDescendant relations for ::part.
+
2019-10-07 Ryosuke Niwa <rn...@webkit.org>
Add IDL for requestIdleCallback
Modified: trunk/Source/WebCore/css/ElementRuleCollector.cpp (250816 => 250817)
--- trunk/Source/WebCore/css/ElementRuleCollector.cpp 2019-10-08 06:22:46 UTC (rev 250816)
+++ trunk/Source/WebCore/css/ElementRuleCollector.cpp 2019-10-08 07:31:36 UTC (rev 250817)
@@ -203,9 +203,7 @@
if (element().isInShadowTree()) {
matchAuthorShadowPseudoElementRules(includeEmptyRules, ruleRange);
-
- if (!element().partNames().isEmpty())
- matchPartPseudoElementRules(*element().containingShadowRoot(), includeEmptyRules, ruleRange);
+ matchPartPseudoElementRules(includeEmptyRules, ruleRange);
}
sortAndTransferMatchedRules();
@@ -263,12 +261,22 @@
}
}
-void ElementRuleCollector::matchPartPseudoElementRules(const ShadowRoot& containingShadowRoot, bool includeEmptyRules, StyleResolver::RuleRange& ruleRange)
+void ElementRuleCollector::matchPartPseudoElementRules(bool includeEmptyRules, StyleResolver::RuleRange& ruleRange)
{
ASSERT(element().isInShadowTree());
- ASSERT(!element().partNames().isEmpty());
- auto& shadowHost = *containingShadowRoot.host();
+ bool isUAShadowPseudoElement = element().containingShadowRoot()->mode() == ShadowRootMode::UserAgent && !element().shadowPseudoId().isNull();
+
+ auto& partMatchingElement = isUAShadowPseudoElement ? *element().shadowHost() : element();
+ if (partMatchingElement.partNames().isEmpty() || !partMatchingElement.isInShadowTree())
+ return;
+
+ matchPartPseudoElementRulesForScope(*partMatchingElement.containingShadowRoot(), includeEmptyRules, ruleRange);
+}
+
+void ElementRuleCollector::matchPartPseudoElementRulesForScope(const ShadowRoot& scopeShadowRoot, bool includeEmptyRules, StyleResolver::RuleRange& ruleRange)
+{
+ auto& shadowHost = *scopeShadowRoot.host();
{
SetForScope<RefPtr<const Element>> partMatchingScope(m_shadowHostInPartRuleScope, &shadowHost);
@@ -278,11 +286,11 @@
}
// Element may be exposed to styling from enclosing scopes via exportparts attributes.
- if (containingShadowRoot.partMappings().isEmpty())
+ if (scopeShadowRoot.partMappings().isEmpty())
return;
- if (auto* parentShadowRoot = shadowHost.containingShadowRoot())
- matchPartPseudoElementRules(*parentShadowRoot, includeEmptyRules, ruleRange);
+ if (auto* parentScopeShadowRoot = shadowHost.containingShadowRoot())
+ matchPartPseudoElementRulesForScope(*parentScopeShadowRoot, includeEmptyRules, ruleRange);
}
void ElementRuleCollector::collectMatchingShadowPseudoElementRules(const MatchRequest& matchRequest, StyleResolver::RuleRange& ruleRange)
Modified: trunk/Source/WebCore/css/ElementRuleCollector.h (250816 => 250817)
--- trunk/Source/WebCore/css/ElementRuleCollector.h 2019-10-08 06:22:46 UTC (rev 250816)
+++ trunk/Source/WebCore/css/ElementRuleCollector.h 2019-10-08 07:31:36 UTC (rev 250817)
@@ -75,7 +75,8 @@
void matchAuthorShadowPseudoElementRules(bool includeEmptyRules, StyleResolver::RuleRange&);
void matchHostPseudoClassRules(bool includeEmptyRules, StyleResolver::RuleRange&);
void matchSlottedPseudoElementRules(bool includeEmptyRules, StyleResolver::RuleRange&);
- void matchPartPseudoElementRules(const ShadowRoot& containingShadowRoot, bool includeEmptyRules, StyleResolver::RuleRange&);
+ void matchPartPseudoElementRules(bool includeEmptyRules, StyleResolver::RuleRange&);
+ void matchPartPseudoElementRulesForScope(const ShadowRoot& scopeShadowRoot, bool includeEmptyRules, StyleResolver::RuleRange&);
void collectMatchingShadowPseudoElementRules(const MatchRequest&, StyleResolver::RuleRange&);
std::unique_ptr<RuleSet::RuleDataVector> collectSlottedPseudoElementRulesForSlot(bool includeEmptyRules);
Modified: trunk/Source/WebCore/css/RuleSet.cpp (250816 => 250817)
--- trunk/Source/WebCore/css/RuleSet.cpp 2019-10-08 06:22:46 UTC (rev 250816)
+++ trunk/Source/WebCore/css/RuleSet.cpp 2019-10-08 07:31:36 UTC (rev 250817)
@@ -329,6 +329,14 @@
if (customPseudoElementSelector) {
// FIXME: Custom pseudo elements are handled by the shadow tree's selector filter. It doesn't know about the main DOM.
ruleData.disableSelectorFiltering();
+
+ auto* nextSelector = customPseudoElementSelector->tagHistory();
+ if (nextSelector && nextSelector->match() == CSSSelector::PseudoElement && nextSelector->pseudoElementType() == CSSSelector::PseudoElementPart) {
+ // Handle selectors like ::part(foo)::placeholder with the part codepath.
+ m_partPseudoElementRules.append(ruleData);
+ return;
+ }
+
addToRuleSet(customPseudoElementSelector->value(), m_shadowPseudoElementRules, ruleData);
return;
}
Modified: trunk/Source/WebCore/css/SelectorChecker.cpp (250816 => 250817)
--- trunk/Source/WebCore/css/SelectorChecker.cpp 2019-10-08 06:22:46 UTC (rev 250816)
+++ trunk/Source/WebCore/css/SelectorChecker.cpp 2019-10-08 07:31:36 UTC (rev 250817)
@@ -320,8 +320,13 @@
nextContext.visitedMatchType = VisitedMatchType::Disabled;
nextContext.pseudoId = PseudoId::None;
+
+ bool nextIsPart = leftSelector->match() == CSSSelector::PseudoElement && leftSelector->pseudoElementType() == CSSSelector::PseudoElementPart;
+ bool allowMultiplePseudoElements = relation == CSSSelector::ShadowDescendant && nextIsPart;
// Virtual pseudo element is only effective in the rightmost fragment.
- nextContext.pseudoElementEffective = false;
+ if (!allowMultiplePseudoElements)
+ nextContext.pseudoElementEffective = false;
+
nextContext.isMatchElement = false;
}
@@ -430,7 +435,8 @@
case CSSSelector::ShadowDescendant:
{
// When matching foo::part(bar) we skip directly to the tree of element 'foo'.
- auto* shadowHost = checkingContext.shadowHostInPartRuleScope ? checkingContext.shadowHostInPartRuleScope : context.element->shadowHost();
+ bool isPart = context.selector->match() == CSSSelector::PseudoElement && context.selector->pseudoElementType() == CSSSelector::PseudoElementPart;
+ auto* shadowHost = isPart ? checkingContext.shadowHostInPartRuleScope : context.element->shadowHost();
if (!shadowHost)
return MatchResult::fails(Match::SelectorFailsCompletely);
nextContext.element = shadowHost;
Modified: trunk/Source/WebCore/css/parser/CSSSelectorParser.cpp (250816 => 250817)
--- trunk/Source/WebCore/css/parser/CSSSelectorParser.cpp 2019-10-08 06:22:46 UTC (rev 250816)
+++ trunk/Source/WebCore/css/parser/CSSSelectorParser.cpp 2019-10-08 07:31:36 UTC (rev 250817)
@@ -874,10 +874,18 @@
if (!splitAfter || !splitAfter->tagHistory())
return compoundSelector;
- // FIXME: https://bugs.webkit.org/show_bug.cgi?id=161747
- // We have to recur, since we have rules in media controls like video::a::b. This should not be allowed, and
- // we should remove this recursion once those rules are gone.
- std::unique_ptr<CSSParserSelector> secondCompound = context.mode != UASheetMode ? splitAfter->releaseTagHistory() : splitCompoundAtImplicitShadowCrossingCombinator(splitAfter->releaseTagHistory(), context);
+ // ::part() combines with other pseudo elements.
+ bool isPart = splitAfter->tagHistory()->match() == CSSSelector::PseudoElement && splitAfter->tagHistory()->pseudoElementType() == CSSSelector::PseudoElementPart;
+
+ std::unique_ptr<CSSParserSelector> secondCompound;
+ if (context.mode == UASheetMode || isPart) {
+ // FIXME: https://bugs.webkit.org/show_bug.cgi?id=161747
+ // We have to recur, since we have rules in media controls like video::a::b. This should not be allowed, and
+ // we should remove this recursion once those rules are gone.
+ secondCompound = splitCompoundAtImplicitShadowCrossingCombinator(splitAfter->releaseTagHistory(), context);
+ } else
+ secondCompound = splitAfter->releaseTagHistory();
+
secondCompound->appendTagHistory(CSSSelector::ShadowDescendant, WTFMove(compoundSelector));
return secondCompound;
}