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