Skip to content

Commit

Permalink
[CSS Container Queries] Correct container selection for pseudo-elements
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=239279

Reviewed by Simon Fraser.

Source/WebCore:

The element itself may be the container for its pseudo-elements.

* css/CSSPrimitiveValue.cpp:
(WebCore::CSSPrimitiveValue::computeNonCalcLengthDouble):
* style/ContainerQueryEvaluator.cpp:
(WebCore::Style::ContainerQueryEvaluator::ContainerQueryEvaluator):
(WebCore::Style::ContainerQueryEvaluator::selectContainer const):
(WebCore::Style::ContainerQueryEvaluator::selectContainer):
* style/ContainerQueryEvaluator.h:

Instead of passing the pseudo-element being matched, pass a container selection mode flag. The exact pseudo-element type
doesn't matter.

* style/ElementRuleCollector.cpp:
(WebCore::Style::ElementRuleCollector::containerQueriesMatch):

We need to use the pseudo-element mode when matching a rule that matches a pseudo-element, even when we are not actually resolving
the pseudo element. This is because regular element rule matching sets the style bits that indicate what pseudo-elements the
element has.

LayoutTests:

* TestExpectations:

Canonical link: https://commits.webkit.org/249599@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@292819 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
anttijk committed Apr 13, 2022
1 parent 855935c commit 3edd7d7
Show file tree
Hide file tree
Showing 7 changed files with 55 additions and 16 deletions.
9 changes: 9 additions & 0 deletions LayoutTests/ChangeLog
@@ -1,3 +1,12 @@
2022-04-13 Antti Koivisto <antti@apple.com>

[CSS Container Queries] Correct container selection for pseudo-elements
https://bugs.webkit.org/show_bug.cgi?id=239279

Reviewed by Simon Fraser.

* TestExpectations:

2022-04-13 Alan Bujtas <zalan@apple.com>

REGRESSION (r292043): [ Mac ] fast/block/positioning/fixed-container-with-relative-parent.html is a flaky image failure
Expand Down
1 change: 0 additions & 1 deletion LayoutTests/TestExpectations
Expand Up @@ -4701,7 +4701,6 @@ webkit.org/b/238555 imported/w3c/web-platform-tests/css/css-contain/contain-flex

# Container queries
webkit.org/b/229659 imported/w3c/web-platform-tests/css/css-contain/container-queries/custom-layout-container-001.https.html [ ImageOnlyFailure ]
webkit.org/b/229659 imported/w3c/web-platform-tests/css/css-contain/container-queries/pseudo-elements-002.html [ ImageOnlyFailure ]
webkit.org/b/229659 imported/w3c/web-platform-tests/css/css-contain/container-queries/svg-foreignobject-no-size-container.html [ Skip ]
webkit.org/b/229659 imported/w3c/web-platform-tests/css/css-contain/container-queries/inline-size-bfc-floats.html [ ImageOnlyFailure ]

Expand Down
27 changes: 27 additions & 0 deletions Source/WebCore/ChangeLog
@@ -1,3 +1,30 @@
2022-04-13 Antti Koivisto <antti@apple.com>

[CSS Container Queries] Correct container selection for pseudo-elements
https://bugs.webkit.org/show_bug.cgi?id=239279

Reviewed by Simon Fraser.

The element itself may be the container for its pseudo-elements.

* css/CSSPrimitiveValue.cpp:
(WebCore::CSSPrimitiveValue::computeNonCalcLengthDouble):
* style/ContainerQueryEvaluator.cpp:
(WebCore::Style::ContainerQueryEvaluator::ContainerQueryEvaluator):
(WebCore::Style::ContainerQueryEvaluator::selectContainer const):
(WebCore::Style::ContainerQueryEvaluator::selectContainer):
* style/ContainerQueryEvaluator.h:

Instead of passing the pseudo-element being matched, pass a container selection mode flag. The exact pseudo-element type
doesn't matter.

* style/ElementRuleCollector.cpp:
(WebCore::Style::ElementRuleCollector::containerQueriesMatch):

We need to use the pseudo-element mode when matching a rule that matches a pseudo-element, even when we are not actually resolving
the pseudo element. This is because regular element rule matching sets the style bits that indicate what pseudo-elements the
element has.

2022-04-13 Alan Bujtas <zalan@apple.com>

REGRESSION (r292043): [ Mac ] fast/block/positioning/fixed-container-with-relative-parent.html is a flaky image failure
Expand Down
2 changes: 1 addition & 1 deletion Source/WebCore/css/CSSPrimitiveValue.cpp
Expand Up @@ -826,7 +826,7 @@ double CSSPrimitiveValue::computeNonCalcLengthDouble(const CSSToLengthConversion
if (!conversionData.element())
return nullptr;
// FIXME: Use cached query containers when available.
auto* container = Style::ContainerQueryEvaluator::selectContainer(axis, nullString(), *conversionData.element(), nullptr);
auto* container = Style::ContainerQueryEvaluator::selectContainer(axis, nullString(), *conversionData.element());
if (!container)
return nullptr;
return dynamicDowncast<RenderBox>(container->renderer());
Expand Down
18 changes: 9 additions & 9 deletions Source/WebCore/style/ContainerQueryEvaluator.cpp
Expand Up @@ -44,9 +44,9 @@ struct ContainerQueryEvaluator::SelectedContainer {
CSSToLengthConversionData conversionData;
};

ContainerQueryEvaluator::ContainerQueryEvaluator(const Element& element, PseudoId pseudoId, ScopeOrdinal scopeOrdinal, SelectorMatchingState* selectorMatchingState)
ContainerQueryEvaluator::ContainerQueryEvaluator(const Element& element, SelectionMode selectionMode, ScopeOrdinal scopeOrdinal, SelectorMatchingState* selectorMatchingState)
: m_element(element)
, m_pseudoId(pseudoId)
, m_selectionMode(selectionMode)
, m_scopeOrdinal(scopeOrdinal)
, m_selectorMatchingState(selectorMatchingState)
{
Expand Down Expand Up @@ -82,14 +82,14 @@ auto ContainerQueryEvaluator::selectContainer(const FilteredContainerQuery& filt

auto* cachedQueryContainers = m_selectorMatchingState ? &m_selectorMatchingState->queryContainers : nullptr;

auto* container = selectContainer(filteredContainerQuery.axisFilter, filteredContainerQuery.nameFilter, m_element.get(), cachedQueryContainers, m_pseudoId, m_scopeOrdinal);
auto* container = selectContainer(filteredContainerQuery.axisFilter, filteredContainerQuery.nameFilter, m_element.get(), m_selectionMode, m_scopeOrdinal, cachedQueryContainers);
if (!container)
return { };

return makeSelectedContainer(*container);
}

const Element* ContainerQueryEvaluator::selectContainer(OptionSet<CQ::Axis> axes, const String& name, const Element& element, const CachedQueryContainers* cachedQueryContainers, PseudoId pseudoId, ScopeOrdinal scopeOrdinal)
const Element* ContainerQueryEvaluator::selectContainer(OptionSet<CQ::Axis> axes, const String& name, const Element& element, SelectionMode selectionMode, ScopeOrdinal scopeOrdinal, const CachedQueryContainers* cachedQueryContainers)
{
// "For each element, the query container to be queried is selected from among the element’s
// ancestor query containers that have a valid container-type for all the container features
Expand Down Expand Up @@ -144,6 +144,11 @@ const Element* ContainerQueryEvaluator::selectContainer(OptionSet<CQ::Axis> axes
return nullptr;
}

if (selectionMode == SelectionMode::PseudoElement) {
if (isContainerForQuery(element))
return &element;
}

if (cachedQueryContainers) {
for (auto& container : makeReversedRange(*cachedQueryContainers)) {
if (isContainerForQuery(container))
Expand All @@ -152,11 +157,6 @@ const Element* ContainerQueryEvaluator::selectContainer(OptionSet<CQ::Axis> axes
return { };
}

if (pseudoId != PseudoId::None) {
if (isContainerForQuery(element))
return &element;
}

for (auto* ancestor = element.parentOrShadowHostElement(); ancestor; ancestor = ancestor->parentOrShadowHostElement()) {
if (isContainerForQuery(*ancestor))
return ancestor;
Expand Down
9 changes: 5 additions & 4 deletions Source/WebCore/style/ContainerQueryEvaluator.h
Expand Up @@ -39,11 +39,12 @@ enum class EvaluationResult : uint8_t { False, True, Unknown };

class ContainerQueryEvaluator {
public:
ContainerQueryEvaluator(const Element&, PseudoId, ScopeOrdinal, SelectorMatchingState*);
enum class SelectionMode : bool { Element, PseudoElement };
ContainerQueryEvaluator(const Element&, SelectionMode, ScopeOrdinal, SelectorMatchingState*);

bool evaluate(const FilteredContainerQuery&) const;

static const Element* selectContainer(OptionSet<CQ::Axis>, const String& name, const Element&, const CachedQueryContainers*, PseudoId = PseudoId::None, ScopeOrdinal = ScopeOrdinal::Element);
static const Element* selectContainer(OptionSet<CQ::Axis>, const String& name, const Element&, SelectionMode = SelectionMode::Element, ScopeOrdinal = ScopeOrdinal::Element, const CachedQueryContainers* = nullptr);

private:
struct SelectedContainer;
Expand All @@ -54,8 +55,8 @@ class ContainerQueryEvaluator {
EvaluationResult evaluateSizeFeature(const CQ::SizeFeature&, const SelectedContainer&) const;

const Ref<const Element> m_element;
const PseudoId m_pseudoId;
ScopeOrdinal m_scopeOrdinal;
const SelectionMode m_selectionMode;
const ScopeOrdinal m_scopeOrdinal;
SelectorMatchingState* m_selectorMatchingState;
};

Expand Down
5 changes: 4 additions & 1 deletion Source/WebCore/style/ElementRuleCollector.cpp
Expand Up @@ -512,8 +512,11 @@ bool ElementRuleCollector::containerQueriesMatch(const RuleData& ruleData, const
if (queries.isEmpty())
return true;

// Style bits indicating which pseudo-elements match are set during regular element matching. Container queries need to be evaluate in the right mode.
auto selectionMode = ruleData.canMatchPseudoElement() ? ContainerQueryEvaluator::SelectionMode::PseudoElement : ContainerQueryEvaluator::SelectionMode::Element;

// "Style rules defined on an element inside multiple nested container queries apply when all of the wrapping container queries are true for that element."
ContainerQueryEvaluator evaluator(element(), m_pseudoElementRequest.pseudoId, matchRequest.styleScopeOrdinal, m_selectorMatchingState);
ContainerQueryEvaluator evaluator(element(), selectionMode, matchRequest.styleScopeOrdinal, m_selectorMatchingState);
for (auto* query : queries) {
if (!evaluator.evaluate(*query))
return false;
Expand Down

0 comments on commit 3edd7d7

Please sign in to comment.