Title: [288813] trunk
Revision
288813
Author
[email protected]
Date
2022-01-31 06:56:26 -0800 (Mon, 31 Jan 2022)

Log Message

[CSS Container Queries] Check for query containers when matching rules
https://bugs.webkit.org/show_bug.cgi?id=235881

Reviewed by Antoine Quint.

LayoutTests/imported/w3c:

* web-platform-tests/css/css-contain/container-queries/container-type-invalidation-expected.txt:

Source/WebCore:

Skip rules inside container queries when there are no container ancestors.

* style/ElementRuleCollector.cpp:
(WebCore::Style::ElementRuleCollector::collectMatchingRulesForList):
(WebCore::Style::ElementRuleCollector::containerQueryMatches):

Add the matching function.

This patch doesn't yet do any actual container query matching, it just checks
if we are inside a query container.

* style/ElementRuleCollector.h:
* style/RuleSet.h:
(WebCore::Style::RuleSet::containerQueryFor const):
* style/SelectorMatchingState.h:

Add the container stack.

* style/StyleTreeResolver.cpp:
(WebCore::Style::TreeResolver::popParent):
(WebCore::Style::TreeResolver::resolveComposedTree):
(WebCore::Style::TreeResolver::updateQueryContainer):

Maintain the container stack.

* style/StyleTreeResolver.h:

LayoutTests:

* TestExpectations:

Modified Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (288812 => 288813)


--- trunk/LayoutTests/ChangeLog	2022-01-31 14:16:59 UTC (rev 288812)
+++ trunk/LayoutTests/ChangeLog	2022-01-31 14:56:26 UTC (rev 288813)
@@ -1,3 +1,12 @@
+2022-01-31  Antti Koivisto  <[email protected]>
+
+        [CSS Container Queries] Check for query containers when matching rules
+        https://bugs.webkit.org/show_bug.cgi?id=235881
+
+        Reviewed by Antoine Quint.
+
+        * TestExpectations:
+
 2022-01-30  Kimmo Kinnunen  <[email protected]>
 
         Update LayoutTests/resources/testharness.js to 2021-6-24 version

Modified: trunk/LayoutTests/TestExpectations (288812 => 288813)


--- trunk/LayoutTests/TestExpectations	2022-01-31 14:16:59 UTC (rev 288812)
+++ trunk/LayoutTests/TestExpectations	2022-01-31 14:56:26 UTC (rev 288813)
@@ -4747,15 +4747,8 @@
 imported/w3c/web-platform-tests/css/css-contain/contain-html-overflow-004.html [ ImageOnlyFailure ]
 
 # Container queries
-webkit.org/b/229659 imported/w3c/web-platform-tests/css/css-contain/container-queries/change-display-in-container.html [ ImageOnlyFailure ]
-webkit.org/b/229659 imported/w3c/web-platform-tests/css/css-contain/container-queries/counters-in-container-dynamic.html [ ImageOnlyFailure ]
-webkit.org/b/229659 imported/w3c/web-platform-tests/css/css-contain/container-queries/counters-in-container.html [ ImageOnlyFailure ]
 webkit.org/b/229659 imported/w3c/web-platform-tests/css/css-contain/container-queries/display-in-container.html [ ImageOnlyFailure ]
-webkit.org/b/229659 imported/w3c/web-platform-tests/css/css-contain/container-queries/fieldset-legend-change.html [ ImageOnlyFailure ]
-webkit.org/b/229659 imported/w3c/web-platform-tests/css/css-contain/container-queries/multicol-inside-container.html [ ImageOnlyFailure ]
 webkit.org/b/229659 imported/w3c/web-platform-tests/css/css-contain/container-queries/pseudo-elements-002.tentative.html [ ImageOnlyFailure ]
-webkit.org/b/229659 imported/w3c/web-platform-tests/css/css-contain/container-queries/resize-while-content-visibility-hidden.html [ ImageOnlyFailure ]
-webkit.org/b/229659 imported/w3c/web-platform-tests/css/css-contain/container-queries/top-layer-dialog-backdrop.html [ ImageOnlyFailure ]
 webkit.org/b/229659 imported/w3c/web-platform-tests/css/css-contain/container-queries/inline-size-bfc-floats.html [ ImageOnlyFailure ]
 webkit.org/b/229659 imported/w3c/web-platform-tests/css/css-contain/container-queries/whitespace-update-after-removal.html [ ImageOnlyFailure ]
 

Modified: trunk/LayoutTests/imported/w3c/ChangeLog (288812 => 288813)


--- trunk/LayoutTests/imported/w3c/ChangeLog	2022-01-31 14:16:59 UTC (rev 288812)
+++ trunk/LayoutTests/imported/w3c/ChangeLog	2022-01-31 14:56:26 UTC (rev 288813)
@@ -1,3 +1,12 @@
+2022-01-31  Antti Koivisto  <[email protected]>
+
+        [CSS Container Queries] Check for query containers when matching rules
+        https://bugs.webkit.org/show_bug.cgi?id=235881
+
+        Reviewed by Antoine Quint.
+
+        * web-platform-tests/css/css-contain/container-queries/container-type-invalidation-expected.txt:
+
 2022-01-30  Kimmo Kinnunen  <[email protected]>
 
         Update LayoutTests/resources/testharness.js to 2021-6-24 version

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-contain/container-queries/container-type-invalidation-expected.txt (288812 => 288813)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-contain/container-queries/container-type-invalidation-expected.txt	2022-01-31 14:16:59 UTC (rev 288812)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-contain/container-queries/container-type-invalidation-expected.txt	2022-01-31 14:56:26 UTC (rev 288813)
@@ -1,4 +1,4 @@
 Test
 
-FAIL Changing the container type invalidates relevant descendants assert_equals: expected "rgb(0, 0, 0)" but got "rgb(0, 128, 0)"
+FAIL Changing the container type invalidates relevant descendants assert_equals: expected "rgb(0, 128, 0)" but got "rgb(0, 0, 0)"
 

Modified: trunk/Source/WebCore/ChangeLog (288812 => 288813)


--- trunk/Source/WebCore/ChangeLog	2022-01-31 14:16:59 UTC (rev 288812)
+++ trunk/Source/WebCore/ChangeLog	2022-01-31 14:56:26 UTC (rev 288813)
@@ -1,3 +1,37 @@
+2022-01-31  Antti Koivisto  <[email protected]>
+
+        [CSS Container Queries] Check for query containers when matching rules
+        https://bugs.webkit.org/show_bug.cgi?id=235881
+
+        Reviewed by Antoine Quint.
+
+        Skip rules inside container queries when there are no container ancestors.
+
+        * style/ElementRuleCollector.cpp:
+        (WebCore::Style::ElementRuleCollector::collectMatchingRulesForList):
+        (WebCore::Style::ElementRuleCollector::containerQueryMatches):
+
+        Add the matching function.
+
+        This patch doesn't yet do any actual container query matching, it just checks
+        if we are inside a query container.
+
+        * style/ElementRuleCollector.h:
+        * style/RuleSet.h:
+        (WebCore::Style::RuleSet::containerQueryFor const):
+        * style/SelectorMatchingState.h:
+
+        Add the container stack.
+
+        * style/StyleTreeResolver.cpp:
+        (WebCore::Style::TreeResolver::popParent):
+        (WebCore::Style::TreeResolver::resolveComposedTree):
+        (WebCore::Style::TreeResolver::updateQueryContainer):
+
+        Maintain the container stack.
+
+        * style/StyleTreeResolver.h:
+
 2022-01-31  Carlos Garcia Campos  <[email protected]>
 
         [GTK][a11y] WTR: use AXMenuItemSelected for menu item selection change with ATSPI

Modified: trunk/Source/WebCore/style/ElementRuleCollector.cpp (288812 => 288813)


--- trunk/Source/WebCore/style/ElementRuleCollector.cpp	2022-01-31 14:16:59 UTC (rev 288812)
+++ trunk/Source/WebCore/style/ElementRuleCollector.cpp	2022-01-31 14:56:26 UTC (rev 288813)
@@ -73,12 +73,12 @@
 
 class MatchRequest {
 public:
-    MatchRequest(const RuleSet* ruleSet, ScopeOrdinal styleScopeOrdinal = ScopeOrdinal::Element)
+    MatchRequest(const RuleSet& ruleSet, ScopeOrdinal styleScopeOrdinal = ScopeOrdinal::Element)
         : ruleSet(ruleSet)
         , styleScopeOrdinal(styleScopeOrdinal)
     {
     }
-    const RuleSet* ruleSet;
+    const RuleSet& ruleSet;
     ScopeOrdinal styleScopeOrdinal;
 };
 
@@ -114,7 +114,7 @@
 
 inline void ElementRuleCollector::addMatchedRule(const RuleData& ruleData, unsigned specificity, const MatchRequest& matchRequest)
 {
-    auto cascadeLayerPriority = matchRequest.ruleSet ? matchRequest.ruleSet->cascadeLayerPriorityFor(ruleData) : RuleSet::cascadeLayerPriorityForUnlayered;
+    auto cascadeLayerPriority = matchRequest.ruleSet.cascadeLayerPriorityFor(ruleData);
     m_matchedRules.append({ &ruleData, specificity, matchRequest.styleScopeOrdinal, cascadeLayerPriority });
 }
 
@@ -139,7 +139,6 @@
 
 void ElementRuleCollector::collectMatchingRules(const MatchRequest& matchRequest)
 {
-    ASSERT(matchRequest.ruleSet);
     ASSERT_WITH_MESSAGE(!(m_mode == SelectorChecker::Mode::CollectingRulesIgnoringVirtualPseudoElements && m_pseudoElementRequest.pseudoId != PseudoId::None), "When in StyleInvalidation or SharingRules, SelectorChecker does not try to match the pseudo ID. While ElementRuleCollector supports matching a particular pseudoId in this case, this would indicate a error at the call site since matching a particular element should be unnecessary.");
 
     auto* shadowRoot = element().containingShadowRoot();
@@ -150,18 +149,18 @@
     // then sort the buffer.
     auto& id = element().idForStyleResolution();
     if (!id.isNull())
-        collectMatchingRulesForList(matchRequest.ruleSet->idRules(id), matchRequest);
+        collectMatchingRulesForList(matchRequest.ruleSet.idRules(id), matchRequest);
     if (element().hasClass()) {
         for (size_t i = 0; i < element().classNames().size(); ++i)
-            collectMatchingRulesForList(matchRequest.ruleSet->classRules(element().classNames()[i]), matchRequest);
+            collectMatchingRulesForList(matchRequest.ruleSet.classRules(element().classNames()[i]), matchRequest);
     }
 
     if (element().isLink())
-        collectMatchingRulesForList(matchRequest.ruleSet->linkPseudoClassRules(), matchRequest);
+        collectMatchingRulesForList(matchRequest.ruleSet.linkPseudoClassRules(), matchRequest);
     if (matchesFocusPseudoClass(element()))
-        collectMatchingRulesForList(matchRequest.ruleSet->focusPseudoClassRules(), matchRequest);
-    collectMatchingRulesForList(matchRequest.ruleSet->tagRules(element().localName(), element().isHTMLElement() && element().document().isHTMLDocument()), matchRequest);
-    collectMatchingRulesForList(matchRequest.ruleSet->universalRules(), matchRequest);
+        collectMatchingRulesForList(matchRequest.ruleSet.focusPseudoClassRules(), matchRequest);
+    collectMatchingRulesForList(matchRequest.ruleSet.tagRules(element().localName(), element().isHTMLElement() && element().document().isHTMLDocument()), matchRequest);
+    collectMatchingRulesForList(matchRequest.ruleSet.universalRules(), matchRequest);
 }
 
 
@@ -234,7 +233,7 @@
 void ElementRuleCollector::collectMatchingAuthorRules()
 {
     {
-        MatchRequest matchRequest(m_authorStyle.ptr());
+        MatchRequest matchRequest(m_authorStyle);
         collectMatchingRules(matchRequest);
     }
 
@@ -259,7 +258,7 @@
         return;
     // Look up shadow pseudo elements also from the host scope author style as they are web-exposed.
     auto& hostAuthorRules = Scope::forNode(*shadowRoot.host()).resolver().ruleSets().authorStyle();
-    MatchRequest hostAuthorRequest { &hostAuthorRules, ScopeOrdinal::ContainingHost };
+    MatchRequest hostAuthorRequest { hostAuthorRules, ScopeOrdinal::ContainingHost };
     collectMatchingShadowPseudoElementRules(hostAuthorRequest);
 }
 
@@ -272,7 +271,7 @@
     if (shadowHostRules.isEmpty())
         return;
 
-    MatchRequest hostMatchRequest { nullptr, ScopeOrdinal::Shadow };
+    MatchRequest hostMatchRequest { shadowAuthorStyle, ScopeOrdinal::Shadow };
     collectMatchingRulesForList(&shadowHostRules, hostMatchRequest);
 }
 
@@ -288,7 +287,7 @@
 
         auto& scopeAuthorRules = styleScope.resolver().ruleSets().authorStyle();
 
-        MatchRequest scopeMatchRequest(&scopeAuthorRules, styleScopeOrdinal);
+        MatchRequest scopeMatchRequest(scopeAuthorRules, styleScopeOrdinal);
         collectMatchingRulesForList(&scopeAuthorRules.slottedPseudoElementRules(), scopeMatchRequest);
 
         if (styleScopeOrdinal == ScopeOrdinal::SlotLimit)
@@ -321,7 +320,7 @@
 
         auto& hostAuthorRules = styleScope.resolver().ruleSets().authorStyle();
 
-        MatchRequest scopeMatchRequest(&hostAuthorRules, styleScopeOrdinal);
+        MatchRequest scopeMatchRequest(hostAuthorRules, styleScopeOrdinal);
         collectMatchingRulesForList(&hostAuthorRules.partPseudoElementRules(), scopeMatchRequest);
 
         // Element may only be exposed to styling from enclosing scopes via exportparts attributes.
@@ -335,10 +334,9 @@
 
 void ElementRuleCollector::collectMatchingShadowPseudoElementRules(const MatchRequest& matchRequest)
 {
-    ASSERT(matchRequest.ruleSet);
     ASSERT(element().containingShadowRoot()->mode() == ShadowRootMode::UserAgent);
 
-    auto& rules = *matchRequest.ruleSet;
+    auto& rules = matchRequest.ruleSet;
 #if ENABLE(VIDEO)
     // FXIME: WebVTT should not be done by styling UA shadow trees like this.
     if (element().isWebVTTElement())
@@ -356,7 +354,7 @@
     
     clearMatchedRules();
 
-    MatchRequest matchRequest(m_userStyle.get());
+    MatchRequest matchRequest(*m_userStyle);
     collectMatchingRules(matchRequest);
 
     sortAndTransferMatchedRules(DeclarationOrigin::User);
@@ -381,7 +379,7 @@
 {
     clearMatchedRules();
     
-    collectMatchingRules(MatchRequest(&rules));
+    collectMatchingRules(MatchRequest(rules));
 
     sortAndTransferMatchedRules(DeclarationOrigin::UserAgent);
 }
@@ -486,6 +484,11 @@
         if (m_selectorMatchingState && m_selectorMatchingState->selectorFilter.fastRejectSelector(ruleData.descendantSelectorIdentifierHashes()))
             continue;
 
+        if (auto* containerQuery = matchRequest.ruleSet.containerQueryFor(ruleData)) {
+            if (!containerQueryMatches(*containerQuery))
+                continue;
+        }
+
         auto& rule = ruleData.styleRule();
 
         // If the rule has no properties to apply, then ignore it in the non-debug mode.
@@ -501,6 +504,14 @@
     }
 }
 
+bool ElementRuleCollector::containerQueryMatches(const ContainerQuery&)
+{
+    if (!m_selectorMatchingState)
+        return true;
+    // FIXME: The actual matching.
+    return !m_selectorMatchingState->queryContainers.isEmpty();
+}
+
 static inline bool compareRules(MatchedRule r1, MatchedRule r2)
 {
     // For normal properties the earlier scope wins. This may be reversed by !important which is handled when resolving cascade.
@@ -578,7 +589,7 @@
         addElementStyleProperties(downcast<SVGElement>(element()).animatedSMILStyleProperties(), false /* isCacheable */);
 }
 
-bool ElementRuleCollector::hasAnyMatchingRules(const RuleSet* ruleSet)
+bool ElementRuleCollector::hasAnyMatchingRules(const RuleSet& ruleSet)
 {
     clearMatchedRules();
 

Modified: trunk/Source/WebCore/style/ElementRuleCollector.h (288812 => 288813)


--- trunk/Source/WebCore/style/ElementRuleCollector.h	2022-01-31 14:16:59 UTC (rev 288812)
+++ trunk/Source/WebCore/style/ElementRuleCollector.h	2022-01-31 14:56:26 UTC (rev 288813)
@@ -82,7 +82,7 @@
     void setPseudoElementRequest(const PseudoElementRequest& request) { m_pseudoElementRequest = request; }
     void setMedium(const MediaQueryEvaluator* medium) { m_isPrintStyle = medium->mediaTypeMatchSpecific("print"); }
 
-    bool hasAnyMatchingRules(const RuleSet*);
+    bool hasAnyMatchingRules(const RuleSet&);
 
     const MatchResult& matchResult() const;
     const Vector<RefPtr<const StyleRule>>& matchedRuleList() const;
@@ -112,6 +112,7 @@
     void collectMatchingRules(const MatchRequest&);
     void collectMatchingRulesForList(const RuleSet::RuleDataVector*, const MatchRequest&);
     bool ruleMatches(const RuleData&, unsigned& specificity, ScopeOrdinal);
+    bool containerQueryMatches(const ContainerQuery&);
 
     void sortMatchedRules();
 

Modified: trunk/Source/WebCore/style/RuleSet.h (288812 => 288813)


--- trunk/Source/WebCore/style/RuleSet.h	2022-01-31 14:16:59 UTC (rev 288812)
+++ trunk/Source/WebCore/style/RuleSet.h	2022-01-31 14:56:26 UTC (rev 288813)
@@ -108,6 +108,7 @@
     static constexpr auto cascadeLayerPriorityForUnlayered = std::numeric_limits<CascadeLayerPriority>::max();
 
     CascadeLayerPriority cascadeLayerPriorityFor(const RuleData&) const;
+    const ContainerQuery* containerQueryFor(const RuleData&) const;
 
 private:
     friend class RuleSetBuilder;
@@ -220,5 +221,18 @@
     return cascadeLayerPriorityForIdentifier(identifier);
 }
 
+inline const ContainerQuery* RuleSet::containerQueryFor(const RuleData& ruleData) const
+{
+    if (m_containerQueryIdentifierForRulePosition.size() <= ruleData.position())
+        return nullptr;
+
+    auto identifier = m_containerQueryIdentifierForRulePosition[ruleData.position()];
+    if (!identifier)
+        return nullptr;
+
+    return &m_containerQueries[identifier - 1].query;
+}
+
+
 } // namespace Style
 } // namespace WebCore

Modified: trunk/Source/WebCore/style/SelectorMatchingState.h (288812 => 288813)


--- trunk/Source/WebCore/style/SelectorMatchingState.h	2022-01-31 14:16:59 UTC (rev 288812)
+++ trunk/Source/WebCore/style/SelectorMatchingState.h	2022-01-31 14:56:26 UTC (rev 288813)
@@ -38,6 +38,8 @@
 struct SelectorMatchingState {
     SelectorFilter selectorFilter;
 
+    Vector<Ref<const Element>> queryContainers;
+
     HashMap<HasPseudoClassCacheKey, HasPseudoClassMatch> hasPseudoClassMatchCache;
     HashMap<HasPseudoClassFilterKey, std::unique_ptr<HasSelectorFilter>> hasPseudoClassSelectorFilters;
 };

Modified: trunk/Source/WebCore/style/StyleSharingResolver.cpp (288812 => 288813)


--- trunk/Source/WebCore/style/StyleSharingResolver.cpp	2022-01-31 14:16:59 UTC (rev 288812)
+++ trunk/Source/WebCore/style/StyleSharingResolver.cpp	2022-01-31 14:56:26 UTC (rev 288813)
@@ -330,7 +330,7 @@
         return false;
 
     ElementRuleCollector collector(element, m_ruleSets, &m_selectorMatchingState);
-    return collector.hasAnyMatchingRules(ruleSet);
+    return collector.hasAnyMatchingRules(*ruleSet);
 }
 
 bool SharingResolver::sharingCandidateHasIdenticalStyleAffectingAttributes(const Context& context, const StyledElement& sharingCandidate) const

Modified: trunk/Source/WebCore/style/StyleTreeResolver.cpp (288812 => 288813)


--- trunk/Source/WebCore/style/StyleTreeResolver.cpp	2022-01-31 14:16:59 UTC (rev 288812)
+++ trunk/Source/WebCore/style/StyleTreeResolver.cpp	2022-01-31 14:56:26 UTC (rev 288813)
@@ -426,6 +426,10 @@
 
     scope().selectorMatchingState.selectorFilter.popParent();
 
+    auto& queryContainers = scope().selectorMatchingState.queryContainers;
+    if (!queryContainers.isEmpty() && queryContainers.last().ptr() == &parentElement)
+        queryContainers.removeLast();
+
     m_parentStack.removeLast();
 }
 
@@ -594,6 +598,9 @@
 
         bool shouldIterateChildren = style && (element.childNeedsStyleRecalc() || descendantsToResolve != DescendantsToResolve::None);
 
+        if (shouldIterateChildren)
+            updateQueryContainer(element, *style);
+
         if (!m_didSeePendingStylesheet)
             m_didSeePendingStylesheet = hasLoadingStylesheet(m_document.styleScope(), element, !shouldIterateChildren);
 
@@ -612,6 +619,16 @@
     popParentsToDepth(1);
 }
 
+void TreeResolver::updateQueryContainer(const Element& element, const RenderStyle& style)
+{
+    if (style.containerType() == ContainerType::None)
+        return;
+
+    scope().selectorMatchingState.queryContainers.append(element);
+
+    // FIXME: Skip the subtree and ensure the container is resolved by doing a layout if needed.
+}
+
 std::unique_ptr<Update> TreeResolver::resolve()
 {
     auto& renderView = *m_document.renderView();

Modified: trunk/Source/WebCore/style/StyleTreeResolver.h (288812 => 288813)


--- trunk/Source/WebCore/style/StyleTreeResolver.h	2022-01-31 14:16:59 UTC (rev 288812)
+++ trunk/Source/WebCore/style/StyleTreeResolver.h	2022-01-31 14:56:26 UTC (rev 288813)
@@ -59,6 +59,7 @@
     std::unique_ptr<RenderStyle> styleForStyleable(const Styleable&, const ResolutionContext&);
 
     void resolveComposedTree();
+    void updateQueryContainer(const Element&, const RenderStyle&);
 
     ElementUpdates resolveElement(Element&);
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to