Title: [250817] trunk
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;
 }
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to