Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[CSS Container Queries][Style queries] Basic evaluation support #24140

Merged
merged 1 commit into from
Feb 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@

FAIL style(--my-prop: foo) assert_equals: expected "true" but got ""
FAIL style(--my-prop: foo - bar ()) assert_equals: expected "true" but got ""
FAIL style(not ((--foo: calc(10px + 2em)) and ((--foo: url(x))))) assert_equals: expected "true" but got ""
FAIL style((--foo: bar) or (--bar: 10px)) assert_equals: expected "true" but got ""
FAIL style(--my-prop:) assert_equals: expected "true" but got ""
FAIL style(--my-prop: ) assert_equals: expected "true" but got ""
FAIL style(--foo: bar !important) assert_equals: expected "true" but got ""
FAIL style(--foo) assert_equals: expected "true" but got ""
PASS style(--foo: bar;)
PASS style(--my-prop: foo)
PASS style(--my-prop: foo - bar ())
PASS style(not ((--foo: calc(10px + 2em)) and ((--foo: url(x)))))
PASS style((--foo: bar) or (--bar: 10px))
PASS style(--my-prop:)
PASS style(--my-prop: )
PASS style(--foo: bar !important)
PASS style(--foo)
FAIL style(--foo: bar;) assert_equals: expected "" but got "true"
PASS style(style(--foo: bar))

Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ PASS No declaration value
PASS Unknown CSS property after 'or'
PASS Not a style function with space before '('
FAIL Spaces preserved in custom property value assert_equals: expected "style(--foo: bar baz)" but got "style(--foo: bar baz)"
FAIL Original string number in custom property value assert_equals: expected "style(--foo: 2.100)" but got "style(--foo: 2.1 )"
FAIL Original string number in custom property value assert_equals: expected "style(--foo: 2.100)" but got "style(--foo: 2.1)"

Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@

FAIL style(--inner: true) assert_equals: expected "true" but got ""
FAIL style(--inner:true) assert_equals: expected "true" but got ""
FAIL style(--inner:true ) assert_equals: expected "true" but got ""
FAIL style(--inner: true ) assert_equals: expected "true" but got ""
FAIL style(--inner-no-space: true) assert_equals: expected "true" but got ""
FAIL style(--inner-no-space:true) assert_equals: expected "true" but got ""
FAIL style(--inner-no-space:true ) assert_equals: expected "true" but got ""
FAIL style(--inner-no-space: true ) assert_equals: expected "true" but got ""
FAIL style(--inner-space-after: true) assert_equals: expected "true" but got ""
FAIL style(--inner-space-after:true) assert_equals: expected "true" but got ""
FAIL style(--inner-space-after:true ) assert_equals: expected "true" but got ""
FAIL style(--inner-space-after: true ) assert_equals: expected "true" but got ""
PASS style(--inner: true)
PASS style(--inner:true)
PASS style(--inner:true )
PASS style(--inner: true )
PASS style(--inner-no-space: true)
PASS style(--inner-no-space:true)
PASS style(--inner-no-space:true )
PASS style(--inner-no-space: true )
PASS style(--inner-space-after: true)
PASS style(--inner-space-after:true)
PASS style(--inner-space-after:true )
PASS style(--inner-space-after: true )
PASS style(--outer: true)
PASS style(--outer:true)
PASS style(--outer:true )
Expand All @@ -35,41 +35,41 @@ PASS outer style(--inner-space-after: true)
PASS outer style(--inner-space-after:true)
PASS outer style(--inner-space-after:true )
PASS outer style(--inner-space-after: true )
FAIL outer style(--outer: true) assert_equals: expected "true" but got ""
FAIL outer style(--outer:true) assert_equals: expected "true" but got ""
FAIL outer style(--outer:true ) assert_equals: expected "true" but got ""
FAIL outer style(--outer: true ) assert_equals: expected "true" but got ""
FAIL outer style(--outer-no-space: true) assert_equals: expected "true" but got ""
FAIL outer style(--outer-no-space:true) assert_equals: expected "true" but got ""
FAIL outer style(--outer-no-space:true ) assert_equals: expected "true" but got ""
FAIL outer style(--outer-no-space: true ) assert_equals: expected "true" but got ""
FAIL outer style(--outer-space-after: true) assert_equals: expected "true" but got ""
FAIL outer style(--outer-space-after:true) assert_equals: expected "true" but got ""
FAIL outer style(--outer-space-after:true ) assert_equals: expected "true" but got ""
FAIL outer style(--outer-space-after: true ) assert_equals: expected "true" but got ""
PASS outer style(--outer: true)
PASS outer style(--outer:true)
PASS outer style(--outer:true )
PASS outer style(--outer: true )
PASS outer style(--outer-no-space: true)
PASS outer style(--outer-no-space:true)
PASS outer style(--outer-no-space:true )
PASS outer style(--outer-no-space: true )
PASS outer style(--outer-space-after: true)
PASS outer style(--outer-space-after:true)
PASS outer style(--outer-space-after:true )
PASS outer style(--outer-space-after: true )
FAIL Query custom property with !important declaration assert_equals: expected "rgb(0, 128, 0)" but got "rgb(0, 0, 0)"
FAIL Query custom property using var() assert_equals: expected "rgb(0, 128, 0)" but got "rgb(0, 0, 0)"
FAIL Query custom property including unknown var() reference assert_equals: expected "rgb(0, 128, 0)" but got "rgb(0, 0, 0)"
FAIL Query custom property including unknown var() reference with non-matching fallback assert_equals: expected "rgb(0, 128, 0)" but got "rgb(0, 0, 0)"
PASS Query custom property including unknown var() reference
PASS Query custom property including unknown var() reference with non-matching fallback
FAIL Query custom property including unknown var() reference with matching fallback assert_equals: expected "rgb(0, 128, 0)" but got "rgb(0, 0, 0)"
FAIL Query custom property matching guaranteed-invalid values assert_equals: expected "rgb(0, 128, 0)" but got "rgb(0, 0, 0)"
PASS Style query with revert keyword is false
PASS Style query with revert-layer keyword is false
FAIL Style query 'initial' matching assert_equals: expected "rgb(0, 128, 0)" but got "rgb(0, 0, 0)"
FAIL Style query matching negated value-less query against initial value assert_equals: expected "rgb(0, 128, 0)" but got "rgb(0, 0, 0)"
FAIL Style query 'initial' not matching assert_equals: expected "rgb(0, 128, 0)" but got "rgb(0, 0, 0)"
FAIL Style query matching value-less query against non-initial value assert_equals: expected "rgb(0, 128, 0)" but got "rgb(0, 0, 0)"
PASS Style query matching negated value-less query against initial value
PASS Style query 'initial' not matching
PASS Style query matching value-less query against non-initial value
FAIL Style query 'inherit' matching assert_equals: expected "rgb(0, 128, 0)" but got "rgb(0, 0, 0)"
FAIL Style query 'inherit' not matching assert_equals: expected "rgb(0, 128, 0)" but got "rgb(0, 0, 0)"
PASS Style query 'inherit' not matching
FAIL Style query 'unset' matching assert_equals: expected "rgb(0, 128, 0)" but got "rgb(0, 0, 0)"
FAIL Style query 'unset' not matching assert_equals: expected "rgb(0, 128, 0)" but got "rgb(0, 0, 0)"
PASS Style query 'unset' not matching
FAIL Match registered <length> custom property with px. assert_equals: expected "rgb(0, 128, 0)" but got "rgb(0, 0, 0)"
FAIL Match registered <length> custom property with px via initial keyword. assert_equals: expected "rgb(0, 128, 0)" but got "rgb(0, 0, 0)"
FAIL Match registered <length> custom property with em in query. assert_equals: expected "rgb(0, 128, 0)" but got "rgb(0, 0, 0)"
FAIL Match registered <length> custom property with em in computed value. assert_equals: expected "rgb(0, 128, 0)" but got "rgb(0, 0, 0)"
FAIL Match registered <length> custom property with cqi unit. assert_equals: expected "rgb(0, 128, 0)" but got "rgb(0, 0, 0)"
FAIL Match registered <length> custom property with initial value. assert_equals: expected "rgb(0, 128, 0)" but got "rgb(0, 0, 0)"
FAIL Match registered <length> custom property with initial value via initial keyword. assert_equals: expected "rgb(0, 128, 0)" but got "rgb(0, 0, 0)"
FAIL Should only match exact string for numbers in non-registered custom properties assert_equals: expected "rgb(0, 128, 0)" but got "rgb(0, 0, 0)"
FAIL Spaces should not collapse in non-registered custom properties assert_equals: expected "rgb(0, 128, 0)" but got "rgb(0, 0, 0)"
FAIL Should only match exact string for numbers in non-registered custom properties assert_equals: expected "rgb(0, 128, 0)" but got "rgb(255, 0, 0)"
PASS Spaces should not collapse in non-registered custom properties

Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

PASS Initially no queries match.
FAIL Target child assert_equals: expected "rgb(0, 128, 0)" but got "rgb(255, 0, 0)"
FAIL Target grandchild assert_equals: expected "rgb(0, 128, 0)" but got "rgb(255, 0, 0)"
PASS Target child
PASS Target grandchild
PASS Initially no queries for registered property match.
FAIL Registered property query child assert_equals: expected "rgb(0, 128, 0)" but got "rgb(255, 0, 0)"
FAIL Registered property query grandchild assert_equals: expected "rgb(0, 128, 0)" but got "rgb(255, 0, 0)"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
This should be green

PASS Initially the color is red
FAIL After display and --foo changes, style() query causes the color to be green assert_equals: expected "rgb(0, 128, 0)" but got "rgb(255, 0, 0)"
PASS After display and --foo changes, style() query causes the color to be green

Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Green?

PASS Initially red
FAIL Green after reducing width assert_equals: expected "rgb(0, 128, 0)" but got "rgb(255, 0, 0)"
PASS Green after reducing width

Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

FAIL ::before pseudo element querying style() of originating element assert_equals: expected "rgb(0, 128, 0)" but got "rgb(0, 0, 0)"
PASS ::before pseudo element querying style() of originating element
PASS ::before pseudo element not matching style()
FAIL ::before pseudo element matching style() query after class change assert_equals: expected "rgb(0, 128, 0)" but got "rgb(255, 0, 0)"

Original file line number Diff line number Diff line change
@@ -1,33 +1,33 @@

FAIL style((--foo: bar)) assert_equals: expected "true" but got "false"
PASS style((--foo: bar))
PASS style((--baz: qux))
PASS style((unknown))
PASS unknown((--foo: bar))
PASS style(not (--foo: bar))
FAIL style(not (--baz: qux)) assert_equals: expected "true" but got "false"
PASS style(not (--baz: qux))
PASS style(not (unknown))
FAIL style((--foo: bar) and (--foo: bar)) assert_equals: expected "true" but got "false"
FAIL style((--foo: bar) and (--foo: bar) and (--foo: bar)) assert_equals: expected "true" but got "false"
PASS style((--foo: bar) and (--foo: bar))
PASS style((--foo: bar) and (--foo: bar) and (--foo: bar))
PASS style((--baz: qux) and (--baz: qux))
PASS style((--baz: qux) and (--foo: bar) and (--foo: bar))
PASS style((--foo: bar) and (--baz: qux) and (--foo: bar))
PASS style((--foo: bar) and (--foo: bar) and (--baz: qux))
PASS style((unknown) and (--foo: bar) and (--foo: bar))
PASS style((--foo: bar) and (unknown) and (--foo: bar))
PASS style((--foo: bar) and (--foo: bar) and (unknown))
FAIL style((--foo: bar) or (--foo: bar)) assert_equals: expected "true" but got "false"
FAIL style((--foo: bar) or (--foo: bar) or (--foo: bar)) assert_equals: expected "true" but got "false"
PASS style((--foo: bar) or (--foo: bar))
PASS style((--foo: bar) or (--foo: bar) or (--foo: bar))
PASS style((--baz: qux) or (--baz: qux))
FAIL style((--baz: qux) or (--foo: bar) or (--foo: bar)) assert_equals: expected "true" but got "false"
FAIL style((--foo: bar) or (--baz: qux) or (--foo: bar)) assert_equals: expected "true" but got "false"
FAIL style((--foo: bar) or (--foo: bar) or (--baz: qux)) assert_equals: expected "true" but got "false"
PASS style((--baz: qux) or (--foo: bar) or (--foo: bar))
PASS style((--foo: bar) or (--baz: qux) or (--foo: bar))
PASS style((--foo: bar) or (--foo: bar) or (--baz: qux))
PASS style((unknown) or (--foo: bar) or (--foo: bar))
PASS style((--foo: bar) or (unknown) or (--foo: bar))
PASS style((--foo: bar) or (--foo: bar) or (unknown))
PASS style((unknown) or (--baz: qux) or (--foo: bar))
PASS style(not ((--foo: bar) and (--foo: bar)))
FAIL style(not ((--foo: bar) and (--baz: qux))) assert_equals: expected "true" but got "false"
PASS style(not ((--foo: bar) and (--baz: qux)))
PASS style((--foo: bar) and (not ((--baz: qux) or (--foo: bar))))
FAIL style((--baz: qux) or (not ((--baz: qux) and (--foo: bar)))) assert_equals: expected "true" but got "false"
PASS style((--baz: qux) or (not ((--baz: qux) and (--foo: bar))))
PASS style((--baz: qux) or ((--baz: qux) and (--foo: bar)))

Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@

FAIL Match container in outer tree assert_equals: expected "rgb(0, 128, 0)" but got "rgb(0, 0, 0)"
FAIL Match container in same tree, not walking flat tree ancestors assert_equals: expected "rgb(0, 128, 0)" but got "rgb(0, 0, 0)"
FAIL Match container in ::slotted selector's originating element tree assert_equals: expected "rgb(0, 128, 0)" but got "rgb(0, 0, 0)"
FAIL Match container in outer tree for :host assert_equals: expected "rgb(0, 128, 0)" but got "rgb(0, 0, 0)"
FAIL Match container in ::part selector's originating element tree assert_equals: expected "rgb(0, 128, 0)" but got "rgb(0, 0, 0)"
FAIL Match container for ::before in ::slotted selector's originating element tree assert_equals: expected "rgb(0, 128, 0)" but got "rgb(0, 0, 0)"
FAIL Match container in outer tree for :host::before assert_equals: expected "rgb(0, 128, 0)" but got "rgb(0, 0, 0)"
FAIL Match container for ::before in ::part selector's originating element tree assert_equals: expected "rgb(0, 128, 0)" but got "rgb(0, 0, 0)"
FAIL Match container for ::part selector's originating element tree for exportparts assert_equals: expected "rgb(0, 128, 0)" but got "rgb(0, 0, 0)"
FAIL Match container for slot light tree child fallback assert_equals: expected "rgb(0, 128, 0)" but got "rgb(0, 0, 0)"
PASS Match container in outer tree
PASS Match container in same tree, not walking flat tree ancestors
PASS Match container in ::slotted selector's originating element tree
PASS Match container in outer tree for :host
PASS Match container in ::part selector's originating element tree
PASS Match container for ::before in ::slotted selector's originating element tree
PASS Match container in outer tree for :host::before
PASS Match container for ::before in ::part selector's originating element tree
PASS Match container for ::part selector's originating element tree for exportparts
PASS Match container for slot light tree child fallback
PASS Should not match container inside shadow tree for ::part()
FAIL A :host::part rule should match containers in the originating element tree assert_equals: expected "rgb(0, 128, 0)" but got "rgb(0, 0, 0)"
PASS A :host::part rule should match containers in the originating element tree

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@

PASS Pre-conditions
FAIL Changed --match inherits down descendants and affects container query assert_equals: expected "rgb(0, 128, 0)" but got "rgb(255, 0, 0)"
PASS Changed --match inherits down descendants and affects container query

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Should be green

FAIL width query should evaluate to unknown and style query to true assert_equals: expected "rgb(0, 128, 0)" but got "rgb(0, 0, 0)"
PASS width query should evaluate to unknown and style query to true

10 changes: 10 additions & 0 deletions Source/WebCore/css/parser/CSSParserTokenRange.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,16 @@ void CSSParserTokenRange::consumeComponentValue()
} while (nestingLevel && m_first < m_last);
}

CSSParserTokenRange CSSParserTokenRange::consumeAllExcludingTrailingWhitespace()
{
auto* last = m_last;
for (; last > m_first; --last) {
if ((last - 1)->type() != WhitespaceToken)
break;
}
return { std::exchange(m_first, last), last };
}

String CSSParserTokenRange::serialize() const
{
StringBuilder builder;
Expand Down
1 change: 1 addition & 0 deletions Source/WebCore/css/parser/CSSParserTokenRange.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ class CSSParserTokenRange {
}

CSSParserTokenRange consumeAll() { return { std::exchange(m_first, m_last), m_last }; }
CSSParserTokenRange consumeAllExcludingTrailingWhitespace();

String serialize() const;

Expand Down
2 changes: 0 additions & 2 deletions Source/WebCore/css/query/ContainerQuery.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,4 @@ void serialize(StringBuilder&, const ContainerQuery&);

}

using CachedQueryContainers = Vector<Ref<const Element>>;

}
14 changes: 11 additions & 3 deletions Source/WebCore/css/query/ContainerQueryFeatures.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -166,10 +166,18 @@ struct StyleFeatureSchema : public FeatureSchema {
: FeatureSchema("style"_s, FeatureSchema::Type::Discrete, FeatureSchema::ValueType::CustomProperty)
{ }

EvaluationResult evaluate(const MQ::Feature&, const FeatureEvaluationContext&) const override
EvaluationResult evaluate(const MQ::Feature& feature, const FeatureEvaluationContext& context) const override
{
// FIXME: Implement.
return EvaluationResult::Unknown;
if (!context.conversionData.style())
return EvaluationResult::False;

auto& style = *context.conversionData.style();
auto* customProperty = style.customPropertyValue(feature.name);
if (!feature.rightComparison)
return toEvaluationResult(!!customProperty);

ASSERT(feature.rightComparison->op == ComparisonOperator::Equal);
return toEvaluationResult(customProperty && *customProperty == *feature.rightComparison->value);
}
};

Expand Down
19 changes: 15 additions & 4 deletions Source/WebCore/css/query/GenericMediaQueryParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "CSSCustomPropertyValue.h"
#include "CSSPropertyParserHelpers.h"
#include "CSSValue.h"
#include "CSSVariableParser.h"
#include "MediaQueryParserContext.h"

namespace WebCore {
Expand All @@ -54,12 +55,21 @@ std::optional<Feature> FeatureParser::consumeFeature(CSSParserTokenRange& range,
return consumeRangeFeature(range, context);
};

static RefPtr<CSSValue> consumeCustomPropertyValue(AtomString propertyName, CSSParserTokenRange& range)
{
auto propertyValueRange = range.consumeAllExcludingTrailingWhitespace();
range.consumeWhitespace();
return CSSCustomPropertyValue::createSyntaxAll(propertyName, CSSVariableData::create(propertyValueRange));
}

std::optional<Feature> FeatureParser::consumeBooleanOrPlainFeature(CSSParserTokenRange& range, const MediaQueryParserContext& context)
{
auto consumePlainFeatureName = [&]() -> std::pair<AtomString, ComparisonOperator> {
auto name = consumeFeatureName(range);
if (name.isEmpty())
return { };
if (isCustomPropertyName(name))
return { name, ComparisonOperator::Equal };
if (name.startsWith("min-"_s))
return { StringView(name).substring(4).toAtomString(), ComparisonOperator::GreaterThanOrEqual };
if (name.startsWith("max-"_s))
Expand Down Expand Up @@ -90,9 +100,7 @@ std::optional<Feature> FeatureParser::consumeBooleanOrPlainFeature(CSSParserToke

range.consumeIncludingWhitespace();

RefPtr value = isCustomPropertyName(featureName)
? CSSCustomPropertyValue::createSyntaxAll(featureName, CSSVariableData::create(range.consumeAll()))
: consumeValue(range, context);
RefPtr value = isCustomPropertyName(featureName) ? consumeCustomPropertyValue(featureName, range) : consumeValue(range, context);

if (!value)
return { };
Expand Down Expand Up @@ -283,7 +291,10 @@ bool FeatureParser::validateFeatureAgainstSchema(Feature& feature, const Feature
if (feature.rightComparison && feature.rightComparison->op != ComparisonOperator::Equal)
return false;
}

if (schema.valueType == FeatureSchema::ValueType::CustomProperty) {
if (!isCustomPropertyName(feature.name))
return false;
}
if (feature.leftComparison) {
if (!validateValue(feature.leftComparison->value))
return false;
Expand Down