Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-contain/container-queries/aspect-ratio-feature-evaluation-expected.txt (289889 => 289890)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-contain/container-queries/aspect-ratio-feature-evaluation-expected.txt 2022-02-16 14:45:33 UTC (rev 289889)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-contain/container-queries/aspect-ratio-feature-evaluation-expected.txt 2022-02-16 16:52:54 UTC (rev 289890)
@@ -1,4 +1,4 @@
-FAIL @container queries with aspect-ratio and size containment assert_equals: Should not match for inline-size containment expected "rgb(255, 0, 0)" but got "rgb(0, 128, 0)"
+PASS @container queries with aspect-ratio and size containment
FAIL @container query with aspect-ratio change after resize assert_equals: Should match 2/1 min-ratio expected "rgb(0, 255, 0)" but got "rgba(0, 0, 0, 0)"
Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-contain/container-queries/unsupported-axis-expected.txt (289889 => 289890)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-contain/container-queries/unsupported-axis-expected.txt 2022-02-16 14:45:33 UTC (rev 289889)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-contain/container-queries/unsupported-axis-expected.txt 2022-02-16 16:52:54 UTC (rev 289890)
@@ -1,14 +1,14 @@
Test
PASS size(width > 0px)
-FAIL size(height > 0px) assert_equals: expected "" but got "true"
+PASS size(height > 0px)
PASS size((height > 0px) or (width > 0px))
PASS size((width > 0px) or (height > 0px))
PASS size((orientation: landscape) or (width > 0px))
PASS size((width > 0px) or (orientation: landscape))
-FAIL size((height > 0px) or (orientation: landscape)) assert_equals: expected "" but got "true"
-FAIL size((height > 0px) or (orientation: landscape)), with contain:size assert_equals: expected "" but got "true"
+PASS size((height > 0px) or (orientation: landscape))
+PASS size((height > 0px) or (orientation: landscape)), with contain:size
PASS size(inline-size > 0px)
-FAIL size(block-size > 0px) assert_equals: expected "" but got "true"
-FAIL size(block-size > 0px), with writing-mode:vertical-rl assert_equals: expected "" but got "true"
+PASS size(block-size > 0px)
+PASS size(block-size > 0px), with writing-mode:vertical-rl
Modified: trunk/Source/WebCore/style/ContainerQueryEvaluator.cpp (289889 => 289890)
--- trunk/Source/WebCore/style/ContainerQueryEvaluator.cpp 2022-02-16 14:45:33 UTC (rev 289889)
+++ trunk/Source/WebCore/style/ContainerQueryEvaluator.cpp 2022-02-16 16:52:54 UTC (rev 289890)
@@ -37,8 +37,8 @@
namespace WebCore::Style {
-struct ContainerQueryEvaluator::EvaluationContext {
- RenderBox& renderer;
+struct ContainerQueryEvaluator::ResolvedContainer {
+ const RenderBox& renderer;
CSSToLengthConversionData conversionData;
};
@@ -52,57 +52,57 @@
if (m_containers.isEmpty())
return false;
- auto containerRendererForFilter = [&]() -> RenderBox* {
+ auto makeResolvedContainer = [&](const RenderBox& renderer) -> ResolvedContainer {
+ auto& view = renderer.view();
+ return {
+ renderer,
+ CSSToLengthConversionData { &renderer.style(), &view.style(), nullptr, &view, 1 }
+ };
+ };
+
+ auto resolveContainer = [&]() -> std::optional<ResolvedContainer> {
for (auto& container : makeReversedRange(m_containers)) {
auto* renderer = dynamicDowncast<RenderBox>(container->renderer());
if (!renderer)
- return nullptr;
+ return { };
if (filteredContainerQuery.nameFilter.isEmpty())
- return renderer;
+ return makeResolvedContainer(*renderer);
// FIXME: Support type filter.
if (renderer->style().containerNames().contains(filteredContainerQuery.nameFilter))
- return renderer;
+ return makeResolvedContainer(*renderer);
}
- return nullptr;
+ return { };
};
- auto* renderer = containerRendererForFilter();
- if (!renderer)
- return false;
+ auto container = resolveContainer();
+ if (!container)
+ return { };
- auto& view = renderer->view();
- CSSToLengthConversionData { &renderer->style(), &view.style(), nullptr, &view, 1 };
-
- EvaluationContext evaluationContext {
- *renderer,
- CSSToLengthConversionData { &renderer->style(), &view.style(), nullptr, &view, 1 }
- };
-
- return evaluateQuery(filteredContainerQuery.query, evaluationContext) == EvaluationResult::True;
+ return evaluateQuery(filteredContainerQuery.query, *container) == EvaluationResult::True;
}
-auto ContainerQueryEvaluator::evaluateQuery(const CQ::ContainerQuery& containerQuery, const EvaluationContext& context) const -> EvaluationResult
+auto ContainerQueryEvaluator::evaluateQuery(const CQ::ContainerQuery& containerQuery, const ResolvedContainer& container) const -> EvaluationResult
{
return WTF::switchOn(containerQuery, [&](const CQ::ContainerCondition& containerCondition) {
- return evaluateCondition(containerCondition, context);
+ return evaluateCondition(containerCondition, container);
}, [&](const CQ::SizeQuery& sizeQuery) {
- return evaluateQuery(sizeQuery, context);
+ return evaluateQuery(sizeQuery, container);
}, [&](const CQ::UnknownQuery&) {
return EvaluationResult::Unknown;
});
}
-auto ContainerQueryEvaluator::evaluateQuery(const CQ::SizeQuery& sizeQuery, const EvaluationContext& context) const -> EvaluationResult
+auto ContainerQueryEvaluator::evaluateQuery(const CQ::SizeQuery& sizeQuery, const ResolvedContainer& container) const -> EvaluationResult
{
return WTF::switchOn(sizeQuery, [&](const CQ::SizeCondition& sizeCondition) {
- return evaluateCondition(sizeCondition, context);
+ return evaluateCondition(sizeCondition, container);
}, [&](const CQ::SizeFeature& sizeFeature) {
- return evaluateSizeFeature(sizeFeature, context);
+ return evaluateSizeFeature(sizeFeature, container);
});
}
template<typename ConditionType>
-auto ContainerQueryEvaluator::evaluateCondition(const ConditionType& condition, const EvaluationContext& context) const -> EvaluationResult
+auto ContainerQueryEvaluator::evaluateCondition(const ConditionType& condition, const ResolvedContainer& container) const -> EvaluationResult
{
if (condition.queries.isEmpty())
return EvaluationResult::Unknown;
@@ -109,7 +109,7 @@
switch (condition.logicalOperator) {
case CQ::LogicalOperator::Not: {
- switch (evaluateQuery(condition.queries.first(), context)) {
+ switch (evaluateQuery(condition.queries.first(), container)) {
case EvaluationResult::True:
return EvaluationResult::False;
case EvaluationResult::False:
@@ -121,7 +121,7 @@
case CQ::LogicalOperator::And: {
auto result = EvaluationResult::True;
for (auto query : condition.queries) {
- auto queryResult = evaluateQuery(query, context);
+ auto queryResult = evaluateQuery(query, container);
if (queryResult == EvaluationResult::False)
return EvaluationResult::False;
if (queryResult == EvaluationResult::Unknown)
@@ -132,7 +132,7 @@
case CQ::LogicalOperator::Or: {
auto result = EvaluationResult::False;
for (auto query : condition.queries) {
- auto queryResult = evaluateQuery(query, context);
+ auto queryResult = evaluateQuery(query, container);
if (queryResult == EvaluationResult::True)
return EvaluationResult::True;
if (queryResult == EvaluationResult::Unknown)
@@ -160,7 +160,7 @@
return primitiveValue.computeLength<LayoutUnit>(conversionData);
}
-auto ContainerQueryEvaluator::evaluateSizeFeature(const CQ::SizeFeature& sizeFeature, const EvaluationContext& context) const -> EvaluationResult
+auto ContainerQueryEvaluator::evaluateSizeFeature(const CQ::SizeFeature& sizeFeature, const ResolvedContainer& container) const -> EvaluationResult
{
auto toEvaluationResult = [](bool boolean) {
return boolean ? EvaluationResult::True : EvaluationResult::False;
@@ -188,7 +188,7 @@
if (sizeFeature.comparisonOperator == CQ::ComparisonOperator::True)
return toEvaluationResult(!!size);
- auto expressionSize = computeSize(sizeFeature.value.get(), context.conversionData);
+ auto expressionSize = computeSize(sizeFeature.value.get(), container.conversionData);
if (!expressionSize)
return EvaluationResult::Unknown;
@@ -195,20 +195,56 @@
return toEvaluationResult(compare(size, *expressionSize));
};
- if (sizeFeature.name == CQ::FeatureNames::width())
- return evaluateSize(context.renderer.contentWidth());
+ enum class Axis : uint8_t { Both, Block, Inline, Width, Height };
+ auto containerSupportsRequiredAxis = [&](Axis axis) {
+ switch (container.renderer.style().containerType()) {
+ case ContainerType::Size:
+ return true;
+ case ContainerType::InlineSize:
+ if (axis == Axis::Width)
+ return container.renderer.isHorizontalWritingMode();
+ if (axis == Axis::Height)
+ return !container.renderer.isHorizontalWritingMode();
+ return axis == Axis::Inline;
+ case ContainerType::None:
+ ASSERT_NOT_REACHED();
+ return false;
+ }
+ };
- if (sizeFeature.name == CQ::FeatureNames::height())
- return evaluateSize(context.renderer.contentHeight());
+ if (sizeFeature.name == CQ::FeatureNames::width()) {
+ if (!containerSupportsRequiredAxis(Axis::Width))
+ return EvaluationResult::Unknown;
- if (sizeFeature.name == CQ::FeatureNames::inlineSize())
- return evaluateSize(context.renderer.contentLogicalWidth());
+ return evaluateSize(container.renderer.contentWidth());
+ }
- if (sizeFeature.name == CQ::FeatureNames::blockSize())
- return evaluateSize(context.renderer.contentLogicalHeight());
+ if (sizeFeature.name == CQ::FeatureNames::height()) {
+ if (!containerSupportsRequiredAxis(Axis::Height))
+ return EvaluationResult::Unknown;
+ return evaluateSize(container.renderer.contentHeight());
+ }
+
+ if (sizeFeature.name == CQ::FeatureNames::inlineSize()) {
+ if (!containerSupportsRequiredAxis(Axis::Inline))
+ return EvaluationResult::Unknown;
+
+ return evaluateSize(container.renderer.contentLogicalWidth());
+ }
+
+ if (sizeFeature.name == CQ::FeatureNames::blockSize()) {
+ if (!containerSupportsRequiredAxis(Axis::Block))
+ return EvaluationResult::Unknown;
+
+ return evaluateSize(container.renderer.contentLogicalHeight());
+ }
+
if (sizeFeature.name == CQ::FeatureNames::aspectRatio()) {
- auto boxRatio = context.renderer.contentWidth().toDouble() / context.renderer.contentHeight().toDouble();
+ if (!containerSupportsRequiredAxis(Axis::Both))
+ return EvaluationResult::Unknown;
+
+ auto boxRatio = container.renderer.contentWidth().toDouble() / container.renderer.contentHeight().toDouble();
if (sizeFeature.comparisonOperator == CQ::ComparisonOperator::True)
return toEvaluationResult(!!boxRatio);
@@ -231,12 +267,15 @@
}
if (sizeFeature.name == CQ::FeatureNames::orientation()) {
+ if (!containerSupportsRequiredAxis(Axis::Both))
+ return EvaluationResult::Unknown;
+
if (!is<CSSPrimitiveValue>(sizeFeature.value) || sizeFeature.comparisonOperator != CQ::ComparisonOperator::Equal)
return EvaluationResult::Unknown;
auto& value = downcast<CSSPrimitiveValue>(*sizeFeature.value);
- bool isPortrait = context.renderer.contentHeight() >= context.renderer.contentWidth();
+ bool isPortrait = container.renderer.contentHeight() >= container.renderer.contentWidth();
if (value.valueID() == CSSValuePortrait)
return toEvaluationResult(isPortrait);
if (value.valueID() == CSSValueLandscape)
Modified: trunk/Source/WebCore/style/ContainerQueryEvaluator.h (289889 => 289890)
--- trunk/Source/WebCore/style/ContainerQueryEvaluator.h 2022-02-16 14:45:33 UTC (rev 289889)
+++ trunk/Source/WebCore/style/ContainerQueryEvaluator.h 2022-02-16 16:52:54 UTC (rev 289890)
@@ -40,13 +40,13 @@
bool evaluate(const FilteredContainerQuery&) const;
private:
- struct EvaluationContext;
+ struct ResolvedContainer;
enum class EvaluationResult : uint8_t { False, True, Unknown };
- EvaluationResult evaluateQuery(const CQ::ContainerQuery&, const EvaluationContext&) const;
- EvaluationResult evaluateQuery(const CQ::SizeQuery&, const EvaluationContext&) const;
- template<typename ConditionType> EvaluationResult evaluateCondition(const ConditionType&, const EvaluationContext&) const;
- EvaluationResult evaluateSizeFeature(const CQ::SizeFeature&, const EvaluationContext&) const;
+ EvaluationResult evaluateQuery(const CQ::ContainerQuery&, const ResolvedContainer&) const;
+ EvaluationResult evaluateQuery(const CQ::SizeQuery&, const ResolvedContainer&) const;
+ template<typename ConditionType> EvaluationResult evaluateCondition(const ConditionType&, const ResolvedContainer&) const;
+ EvaluationResult evaluateSizeFeature(const CQ::SizeFeature&, const ResolvedContainer&) const;
const Vector<Ref<const Element>>& m_containers;
};