From 8bec80ac477f0a02bf23176bb825d686495a5de0 Mon Sep 17 00:00:00 2001 From: Milo van der Tier Date: Fri, 29 Nov 2024 13:16:15 +0100 Subject: [PATCH] LibWeb/CSS: Allow calc() values in media queries It was initially thought that the spec disallows them, but this turned out to be incorrect. This fixes several WPT tests. --- Libraries/LibWeb/CSS/CalculatedOr.cpp | 14 +++++ Libraries/LibWeb/CSS/CalculatedOr.h | 4 ++ Libraries/LibWeb/CSS/Length.cpp | 13 +++++ Libraries/LibWeb/CSS/Length.h | 1 + Libraries/LibWeb/CSS/MediaQuery.cpp | 58 +++++++++++-------- Libraries/LibWeb/CSS/MediaQuery.h | 38 ++++++------ Libraries/LibWeb/CSS/Parser/MediaParsing.cpp | 20 +++---- .../css/mediaqueries/mq-calc-001.html | 24 ++++++++ .../css/mediaqueries/mq-calc-002.html | 35 +++++++++++ .../css/mediaqueries/mq-calc-003.html | 35 +++++++++++ .../css/mediaqueries/mq-calc-004.html | 32 ++++++++++ .../css/mediaqueries/mq-calc-005.html | 32 ++++++++++ .../css/mediaqueries/mq-calc-006.html | 20 +++++++ .../css/mediaqueries/mq-calc-007.html | 20 +++++++ .../css/mediaqueries/mq-calc-008.html | 28 +++++++++ .../css/mediaqueries/mq-calc-resolution.html | 20 +++++++ .../mq-calc-sign-function-001.html | 25 ++++++++ .../mq-calc-sign-function-002.html | 24 ++++++++ .../mq-calc-sign-function-004.html | 24 ++++++++ .../mq-calc-sign-function-005.html | 24 ++++++++ 20 files changed, 439 insertions(+), 52 deletions(-) create mode 100644 Tests/LibWeb/Ref/input/wpt-import/css/mediaqueries/mq-calc-001.html create mode 100644 Tests/LibWeb/Ref/input/wpt-import/css/mediaqueries/mq-calc-002.html create mode 100644 Tests/LibWeb/Ref/input/wpt-import/css/mediaqueries/mq-calc-003.html create mode 100644 Tests/LibWeb/Ref/input/wpt-import/css/mediaqueries/mq-calc-004.html create mode 100644 Tests/LibWeb/Ref/input/wpt-import/css/mediaqueries/mq-calc-005.html create mode 100644 Tests/LibWeb/Ref/input/wpt-import/css/mediaqueries/mq-calc-006.html create mode 100644 Tests/LibWeb/Ref/input/wpt-import/css/mediaqueries/mq-calc-007.html create mode 100644 Tests/LibWeb/Ref/input/wpt-import/css/mediaqueries/mq-calc-008.html create mode 100644 Tests/LibWeb/Ref/input/wpt-import/css/mediaqueries/mq-calc-resolution.html create mode 100644 Tests/LibWeb/Ref/input/wpt-import/css/mediaqueries/mq-calc-sign-function-001.html create mode 100644 Tests/LibWeb/Ref/input/wpt-import/css/mediaqueries/mq-calc-sign-function-002.html create mode 100644 Tests/LibWeb/Ref/input/wpt-import/css/mediaqueries/mq-calc-sign-function-004.html create mode 100644 Tests/LibWeb/Ref/input/wpt-import/css/mediaqueries/mq-calc-sign-function-005.html diff --git a/Libraries/LibWeb/CSS/CalculatedOr.cpp b/Libraries/LibWeb/CSS/CalculatedOr.cpp index c289485ffc7..b191c41f7ad 100644 --- a/Libraries/LibWeb/CSS/CalculatedOr.cpp +++ b/Libraries/LibWeb/CSS/CalculatedOr.cpp @@ -52,6 +52,13 @@ i64 IntegerOrCalculated::resolve_calculated(NonnullRefPtr const& c return calculated->resolve_integer().value(); } +i64 IntegerOrCalculated::resolved() const +{ + if (is_calculated()) + return calculated()->resolve_integer().value(); + return value(); +} + NonnullRefPtr IntegerOrCalculated::create_style_value() const { return IntegerStyleValue::create(value()); @@ -99,6 +106,13 @@ Resolution ResolutionOrCalculated::resolve_calculated(NonnullRefPtrresolve_resolution().value(); } +Resolution ResolutionOrCalculated::resolved() const +{ + if (is_calculated()) + return calculated()->resolve_resolution().value(); + return value(); +} + NonnullRefPtr ResolutionOrCalculated::create_style_value() const { return ResolutionStyleValue::create(value()); diff --git a/Libraries/LibWeb/CSS/CalculatedOr.h b/Libraries/LibWeb/CSS/CalculatedOr.h index e046979f117..4efbc949e9e 100644 --- a/Libraries/LibWeb/CSS/CalculatedOr.h +++ b/Libraries/LibWeb/CSS/CalculatedOr.h @@ -119,6 +119,8 @@ class IntegerOrCalculated : public CalculatedOr { public: using CalculatedOr::CalculatedOr; + [[nodiscard]] i64 resolved() const; + private: virtual i64 resolve_calculated(NonnullRefPtr const&, Layout::Node const&) const override; virtual NonnullRefPtr create_style_value() const override; @@ -157,6 +159,8 @@ class ResolutionOrCalculated : public CalculatedOr { public: using CalculatedOr::CalculatedOr; + [[nodiscard]] Resolution resolved() const; + private: virtual Resolution resolve_calculated(NonnullRefPtr const&, Layout::Node const&) const override; virtual NonnullRefPtr create_style_value() const override; diff --git a/Libraries/LibWeb/CSS/Length.cpp b/Libraries/LibWeb/CSS/Length.cpp index 3bf5badd369..f3542466f6b 100644 --- a/Libraries/LibWeb/CSS/Length.cpp +++ b/Libraries/LibWeb/CSS/Length.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include namespace Web::CSS { @@ -131,6 +132,18 @@ CSSPixels Length::viewport_relative_length_to_px(CSSPixelRect const& viewport_re } } +Length::ResolutionContext Length::ResolutionContext::for_window(HTML::Window const& window) +{ + auto const& initial_font = window.associated_document().style_computer().initial_font(); + Gfx::FontPixelMetrics const& initial_font_metrics = initial_font.pixel_metrics(); + Length::FontMetrics font_metrics { CSSPixels { initial_font.pixel_size() }, initial_font_metrics }; + return Length::ResolutionContext { + .viewport_rect = window.page().web_exposed_screen_area(), + .font_metrics = font_metrics, + .root_font_metrics = font_metrics, + }; +} + Length::ResolutionContext Length::ResolutionContext::for_layout_node(Layout::Node const& node) { auto const* root_element = node.document().document_element(); diff --git a/Libraries/LibWeb/CSS/Length.h b/Libraries/LibWeb/CSS/Length.h index 1a8e0d968b1..a0e252e696b 100644 --- a/Libraries/LibWeb/CSS/Length.h +++ b/Libraries/LibWeb/CSS/Length.h @@ -158,6 +158,7 @@ public: StringView unit_name() const; struct ResolutionContext { + [[nodiscard]] static Length::ResolutionContext for_window(HTML::Window const&); [[nodiscard]] static Length::ResolutionContext for_layout_node(Layout::Node const&); CSSPixelRect viewport_rect; diff --git a/Libraries/LibWeb/CSS/MediaQuery.cpp b/Libraries/LibWeb/CSS/MediaQuery.cpp index 841d8d35621..5dffd5934eb 100644 --- a/Libraries/LibWeb/CSS/MediaQuery.cpp +++ b/Libraries/LibWeb/CSS/MediaQuery.cpp @@ -26,20 +26,24 @@ String MediaFeatureValue::to_string() const { return m_value.visit( [](Keyword const& ident) { return MUST(String::from_utf8(string_from_keyword(ident))); }, - [](Length const& length) { return length.to_string(); }, + [](LengthOrCalculated const& length) { return length.to_string(); }, [](Ratio const& ratio) { return ratio.to_string(); }, - [](Resolution const& resolution) { return resolution.to_string(); }, - [](float number) { return String::number(number); }); + [](ResolutionOrCalculated const& resolution) { return resolution.to_string(); }, + [](IntegerOrCalculated const& integer) { + if (integer.is_calculated()) + return integer.calculated()->to_string(); + return String::number(integer.value()); + }); } bool MediaFeatureValue::is_same_type(MediaFeatureValue const& other) const { return m_value.visit( [&](Keyword const&) { return other.is_ident(); }, - [&](Length const&) { return other.is_length(); }, + [&](LengthOrCalculated const&) { return other.is_length(); }, [&](Ratio const&) { return other.is_ratio(); }, - [&](Resolution const&) { return other.is_resolution(); }, - [&](float) { return other.is_number(); }); + [&](ResolutionOrCalculated const&) { return other.is_resolution(); }, + [&](IntegerOrCalculated const&) { return other.is_integer(); }); } String MediaFeature::to_string() const @@ -88,15 +92,18 @@ bool MediaFeature::evaluate(HTML::Window const& window) const switch (m_type) { case Type::IsTrue: - if (queried_value.is_number()) - return queried_value.number() != 0; - if (queried_value.is_length()) - return queried_value.length().raw_value() != 0; + if (queried_value.is_integer()) + return queried_value.integer().resolved() != 0; + if (queried_value.is_length()) { + auto resolution_context = Length::ResolutionContext::for_window(window); + auto length = queried_value.length().resolved(resolution_context); + return length.raw_value() != 0; + } // FIXME: I couldn't figure out from the spec how ratios should be evaluated in a boolean context. if (queried_value.is_ratio()) return !queried_value.ratio().is_degenerate(); if (queried_value.is_resolution()) - return queried_value.resolution().to_dots_per_pixel() != 0; + return queried_value.resolution().resolved().to_dots_per_pixel() != 0; if (queried_value.is_ident()) { // NOTE: It is not technically correct to always treat `no-preference` as false, but every // media-feature that accepts it as a value treats it as false, so good enough. :^) @@ -141,18 +148,18 @@ bool MediaFeature::compare(HTML::Window const& window, MediaFeatureValue left, C return false; } - if (left.is_number()) { + if (left.is_integer()) { switch (comparison) { case Comparison::Equal: - return left.number() == right.number(); + return left.integer().resolved() == right.integer().resolved(); case Comparison::LessThan: - return left.number() < right.number(); + return left.integer().resolved() < right.integer().resolved(); case Comparison::LessThanOrEqual: - return left.number() <= right.number(); + return left.integer().resolved() <= right.integer().resolved(); case Comparison::GreaterThan: - return left.number() > right.number(); + return left.integer().resolved() > right.integer().resolved(); case Comparison::GreaterThanOrEqual: - return left.number() >= right.number(); + return left.integer().resolved() >= right.integer().resolved(); } VERIFY_NOT_REACHED(); } @@ -160,10 +167,13 @@ bool MediaFeature::compare(HTML::Window const& window, MediaFeatureValue left, C if (left.is_length()) { CSSPixels left_px; CSSPixels right_px; + auto resolution_context = Length::ResolutionContext::for_window(window); + auto left_length = left.length().resolved(resolution_context); + auto right_length = right.length().resolved(resolution_context); // Save ourselves some work if neither side is a relative length. - if (left.length().is_absolute() && right.length().is_absolute()) { - left_px = left.length().absolute_length_to_px(); - right_px = right.length().absolute_length_to_px(); + if (left_length.is_absolute() && right_length.is_absolute()) { + left_px = left_length.absolute_length_to_px(); + right_px = right_length.absolute_length_to_px(); } else { auto viewport_rect = window.page().web_exposed_screen_area(); @@ -171,8 +181,8 @@ bool MediaFeature::compare(HTML::Window const& window, MediaFeatureValue left, C Gfx::FontPixelMetrics const& initial_font_metrics = initial_font.pixel_metrics(); Length::FontMetrics font_metrics { CSSPixels { initial_font.point_size() }, initial_font_metrics }; - left_px = left.length().to_px(viewport_rect, font_metrics, font_metrics); - right_px = right.length().to_px(viewport_rect, font_metrics, font_metrics); + left_px = left_length.to_px(viewport_rect, font_metrics, font_metrics); + right_px = right_length.to_px(viewport_rect, font_metrics, font_metrics); } switch (comparison) { @@ -211,8 +221,8 @@ bool MediaFeature::compare(HTML::Window const& window, MediaFeatureValue left, C } if (left.is_resolution()) { - auto left_dppx = left.resolution().to_dots_per_pixel(); - auto right_dppx = right.resolution().to_dots_per_pixel(); + auto left_dppx = left.resolution().resolved().to_dots_per_pixel(); + auto right_dppx = right.resolution().resolved().to_dots_per_pixel(); switch (comparison) { case Comparison::Equal: diff --git a/Libraries/LibWeb/CSS/MediaQuery.h b/Libraries/LibWeb/CSS/MediaQuery.h index d3f3870d2d0..72b5f0a8949 100644 --- a/Libraries/LibWeb/CSS/MediaQuery.h +++ b/Libraries/LibWeb/CSS/MediaQuery.h @@ -10,11 +10,10 @@ #include #include #include +#include #include -#include #include #include -#include namespace Web::CSS { @@ -26,7 +25,7 @@ public: { } - explicit MediaFeatureValue(Length length) + explicit MediaFeatureValue(LengthOrCalculated length) : m_value(move(length)) { } @@ -36,23 +35,28 @@ public: { } - explicit MediaFeatureValue(Resolution resolution) + explicit MediaFeatureValue(ResolutionOrCalculated resolution) : m_value(move(resolution)) { } - explicit MediaFeatureValue(float number) - : m_value(number) + explicit MediaFeatureValue(IntegerOrCalculated integer) + : m_value(move(integer)) + { + } + + explicit MediaFeatureValue(i64 integer) + : m_value(IntegerOrCalculated(integer)) { } String to_string() const; bool is_ident() const { return m_value.has(); } - bool is_length() const { return m_value.has(); } - bool is_number() const { return m_value.has(); } + bool is_length() const { return m_value.has(); } + bool is_integer() const { return m_value.has(); } bool is_ratio() const { return m_value.has(); } - bool is_resolution() const { return m_value.has(); } + bool is_resolution() const { return m_value.has(); } bool is_same_type(MediaFeatureValue const& other) const; Keyword const& ident() const @@ -61,10 +65,10 @@ public: return m_value.get(); } - Length const& length() const + LengthOrCalculated const& length() const { VERIFY(is_length()); - return m_value.get(); + return m_value.get(); } Ratio const& ratio() const @@ -73,20 +77,20 @@ public: return m_value.get(); } - Resolution const& resolution() const + ResolutionOrCalculated const& resolution() const { VERIFY(is_resolution()); - return m_value.get(); + return m_value.get(); } - float number() const + IntegerOrCalculated integer() const { - VERIFY(is_number()); - return m_value.get(); + VERIFY(is_integer()); + return m_value.get(); } private: - Variant m_value; + Variant m_value; }; // https://www.w3.org/TR/mediaqueries-4/#mq-features diff --git a/Libraries/LibWeb/CSS/Parser/MediaParsing.cpp b/Libraries/LibWeb/CSS/Parser/MediaParsing.cpp index 9fe3a1f436d..cf15cf20095 100644 --- a/Libraries/LibWeb/CSS/Parser/MediaParsing.cpp +++ b/Libraries/LibWeb/CSS/Parser/MediaParsing.cpp @@ -551,8 +551,6 @@ OwnPtr Parser::parse_media_in_parens(TokenStream // ``, https://www.w3.org/TR/mediaqueries-4/#typedef-mf-value Optional Parser::parse_media_feature_value(MediaFeatureID media_feature, TokenStream& tokens) { - // NOTE: Calculations are not allowed for media feature values, at least in the current spec, so we reject them. - // Identifiers if (tokens.next_token().is(Token::Type::Ident)) { auto transaction = tokens.begin_transaction(); @@ -570,11 +568,11 @@ Optional Parser::parse_media_feature_value(MediaFeatureID med if (media_feature_accepts_type(media_feature, MediaFeatureValueType::Boolean)) { auto transaction = tokens.begin_transaction(); tokens.discard_whitespace(); - if (auto integer = parse_integer(tokens); integer.has_value() && !integer->is_calculated()) { - auto integer_value = integer->value(); + if (auto integer = parse_integer(tokens); integer.has_value()) { + auto integer_value = integer.value().resolved(); if (integer_value == 0 || integer_value == 1) { transaction.commit(); - return MediaFeatureValue(integer_value); + return MediaFeatureValue(integer.release_value()); } } } @@ -582,9 +580,9 @@ Optional Parser::parse_media_feature_value(MediaFeatureID med // Integer if (media_feature_accepts_type(media_feature, MediaFeatureValueType::Integer)) { auto transaction = tokens.begin_transaction(); - if (auto integer = parse_integer(tokens); integer.has_value() && !integer->is_calculated()) { + if (auto integer = parse_integer(tokens); integer.has_value()) { transaction.commit(); - return MediaFeatureValue(integer->value()); + return MediaFeatureValue(integer.release_value()); } } @@ -592,9 +590,9 @@ Optional Parser::parse_media_feature_value(MediaFeatureID med if (media_feature_accepts_type(media_feature, MediaFeatureValueType::Length)) { auto transaction = tokens.begin_transaction(); tokens.discard_whitespace(); - if (auto length = parse_length(tokens); length.has_value() && !length->is_calculated()) { + if (auto length = parse_length(tokens); length.has_value()) { transaction.commit(); - return MediaFeatureValue(length->value()); + return MediaFeatureValue(length.release_value()); } } @@ -612,9 +610,9 @@ Optional Parser::parse_media_feature_value(MediaFeatureID med if (media_feature_accepts_type(media_feature, MediaFeatureValueType::Resolution)) { auto transaction = tokens.begin_transaction(); tokens.discard_whitespace(); - if (auto resolution = parse_resolution(tokens); resolution.has_value() && !resolution->is_calculated()) { + if (auto resolution = parse_resolution(tokens); resolution.has_value()) { transaction.commit(); - return MediaFeatureValue(resolution->value()); + return MediaFeatureValue(resolution.release_value()); } } diff --git a/Tests/LibWeb/Ref/input/wpt-import/css/mediaqueries/mq-calc-001.html b/Tests/LibWeb/Ref/input/wpt-import/css/mediaqueries/mq-calc-001.html new file mode 100644 index 00000000000..cb232362526 --- /dev/null +++ b/Tests/LibWeb/Ref/input/wpt-import/css/mediaqueries/mq-calc-001.html @@ -0,0 +1,24 @@ + + + + Test: support for calc in Media Queries + + + + + + + +

Test passes if there is a filled green square and no red.

+
+ + diff --git a/Tests/LibWeb/Ref/input/wpt-import/css/mediaqueries/mq-calc-002.html b/Tests/LibWeb/Ref/input/wpt-import/css/mediaqueries/mq-calc-002.html new file mode 100644 index 00000000000..f21a561a54c --- /dev/null +++ b/Tests/LibWeb/Ref/input/wpt-import/css/mediaqueries/mq-calc-002.html @@ -0,0 +1,35 @@ + + + + Test: evaluation of em in calc in Media Queries + + + + + + + + +

Test passes if there is a filled green square and no red.

+
+ + + + diff --git a/Tests/LibWeb/Ref/input/wpt-import/css/mediaqueries/mq-calc-003.html b/Tests/LibWeb/Ref/input/wpt-import/css/mediaqueries/mq-calc-003.html new file mode 100644 index 00000000000..f0b7c0211f0 --- /dev/null +++ b/Tests/LibWeb/Ref/input/wpt-import/css/mediaqueries/mq-calc-003.html @@ -0,0 +1,35 @@ + + + + Test: evaluation of ex in calc in Media Queries + + + + + + + + +

Test passes if there is a filled green square and no red.

+
+ + + + diff --git a/Tests/LibWeb/Ref/input/wpt-import/css/mediaqueries/mq-calc-004.html b/Tests/LibWeb/Ref/input/wpt-import/css/mediaqueries/mq-calc-004.html new file mode 100644 index 00000000000..0d5b5edd67f --- /dev/null +++ b/Tests/LibWeb/Ref/input/wpt-import/css/mediaqueries/mq-calc-004.html @@ -0,0 +1,32 @@ + + + + Test: evaluation of ch in calc in Media Queries + + + + + + + + +

Test passes if there is a filled green square and no red.

+
+ + + + diff --git a/Tests/LibWeb/Ref/input/wpt-import/css/mediaqueries/mq-calc-005.html b/Tests/LibWeb/Ref/input/wpt-import/css/mediaqueries/mq-calc-005.html new file mode 100644 index 00000000000..7896c7a2b95 --- /dev/null +++ b/Tests/LibWeb/Ref/input/wpt-import/css/mediaqueries/mq-calc-005.html @@ -0,0 +1,32 @@ + + + + Test: evaluation of rem in calc in Media Queries + + + + + + + + +

Test passes if there is a filled green square and no red.

+
+ + + + diff --git a/Tests/LibWeb/Ref/input/wpt-import/css/mediaqueries/mq-calc-006.html b/Tests/LibWeb/Ref/input/wpt-import/css/mediaqueries/mq-calc-006.html new file mode 100644 index 00000000000..2b31ba7eb19 --- /dev/null +++ b/Tests/LibWeb/Ref/input/wpt-import/css/mediaqueries/mq-calc-006.html @@ -0,0 +1,20 @@ + + + + + + + +

Test passes if there is a filled green square and no red.

+
diff --git a/Tests/LibWeb/Ref/input/wpt-import/css/mediaqueries/mq-calc-007.html b/Tests/LibWeb/Ref/input/wpt-import/css/mediaqueries/mq-calc-007.html new file mode 100644 index 00000000000..1cddd7f45eb --- /dev/null +++ b/Tests/LibWeb/Ref/input/wpt-import/css/mediaqueries/mq-calc-007.html @@ -0,0 +1,20 @@ + +Test: evaluation of mixed-unit calc in Media Queries + + + + +

Test passes if there is a filled green square and no red.

+
+
diff --git a/Tests/LibWeb/Ref/input/wpt-import/css/mediaqueries/mq-calc-008.html b/Tests/LibWeb/Ref/input/wpt-import/css/mediaqueries/mq-calc-008.html new file mode 100644 index 00000000000..2662dd58ac4 --- /dev/null +++ b/Tests/LibWeb/Ref/input/wpt-import/css/mediaqueries/mq-calc-008.html @@ -0,0 +1,28 @@ + + + + Test: support for calc in Media Queries + + + + + + + + + +

Test passes if there is a filled green square and no red.

+
+ + diff --git a/Tests/LibWeb/Ref/input/wpt-import/css/mediaqueries/mq-calc-resolution.html b/Tests/LibWeb/Ref/input/wpt-import/css/mediaqueries/mq-calc-resolution.html new file mode 100644 index 00000000000..00aac13b4ce --- /dev/null +++ b/Tests/LibWeb/Ref/input/wpt-import/css/mediaqueries/mq-calc-resolution.html @@ -0,0 +1,20 @@ + +Test: support for calc resolution in Media Queries + + + + +

Test passes if there is a filled green square and no red.

+
diff --git a/Tests/LibWeb/Ref/input/wpt-import/css/mediaqueries/mq-calc-sign-function-001.html b/Tests/LibWeb/Ref/input/wpt-import/css/mediaqueries/mq-calc-sign-function-001.html new file mode 100644 index 00000000000..661258a60bb --- /dev/null +++ b/Tests/LibWeb/Ref/input/wpt-import/css/mediaqueries/mq-calc-sign-function-001.html @@ -0,0 +1,25 @@ + +Test: support for calc with sign() in Media Queries + + + + + + +

Test passes if there is a filled green square and no red.

+
diff --git a/Tests/LibWeb/Ref/input/wpt-import/css/mediaqueries/mq-calc-sign-function-002.html b/Tests/LibWeb/Ref/input/wpt-import/css/mediaqueries/mq-calc-sign-function-002.html new file mode 100644 index 00000000000..54f8bea6480 --- /dev/null +++ b/Tests/LibWeb/Ref/input/wpt-import/css/mediaqueries/mq-calc-sign-function-002.html @@ -0,0 +1,24 @@ + +Test: support for calc with sign() in Media Queries + + + + + +

Test passes if there is a filled green square and no red.

+
diff --git a/Tests/LibWeb/Ref/input/wpt-import/css/mediaqueries/mq-calc-sign-function-004.html b/Tests/LibWeb/Ref/input/wpt-import/css/mediaqueries/mq-calc-sign-function-004.html new file mode 100644 index 00000000000..1a44f458e18 --- /dev/null +++ b/Tests/LibWeb/Ref/input/wpt-import/css/mediaqueries/mq-calc-sign-function-004.html @@ -0,0 +1,24 @@ + +Test: support for calc with sign() in Media Queries + + + + + +

Test passes if there is a filled green square and no red.

+
diff --git a/Tests/LibWeb/Ref/input/wpt-import/css/mediaqueries/mq-calc-sign-function-005.html b/Tests/LibWeb/Ref/input/wpt-import/css/mediaqueries/mq-calc-sign-function-005.html new file mode 100644 index 00000000000..a38f6567906 --- /dev/null +++ b/Tests/LibWeb/Ref/input/wpt-import/css/mediaqueries/mq-calc-sign-function-005.html @@ -0,0 +1,24 @@ + +Test: support for calc with sign() in Media Queries + + + + + +

Test passes if there is a filled green square and no red.

+