فهرست منبع

LibWeb/CSS: Pass Length::ResolutionContext to resolve_integer

The length resolution context might be needed even when resolving an
integer value, since it might contain a sign() function with length
values inside. This fixes a WPT subtest.
Milo van der Tier 8 ماه پیش
والد
کامیت
1882a2e19b

+ 6 - 6
Libraries/LibWeb/CSS/CalculatedOr.cpp

@@ -47,15 +47,15 @@ NonnullRefPtr<CSSStyleValue> FrequencyOrCalculated::create_style_value() const
     return FrequencyStyleValue::create(value());
 }
 
-i64 IntegerOrCalculated::resolve_calculated(NonnullRefPtr<CSSMathValue> const& calculated, Layout::Node const&) const
+i64 IntegerOrCalculated::resolve_calculated(NonnullRefPtr<CSSMathValue> const& calculated, Layout::Node const& layout_node) const
 {
-    return calculated->resolve_integer().value();
+    return calculated->resolve_integer(layout_node).value();
 }
 
-i64 IntegerOrCalculated::resolved() const
+i64 IntegerOrCalculated::resolved(Length::ResolutionContext const& context) const
 {
     if (is_calculated())
-        return calculated()->resolve_integer().value();
+        return calculated()->resolve_integer(context).value();
     return value();
 }
 
@@ -81,9 +81,9 @@ NonnullRefPtr<CSSStyleValue> LengthOrCalculated::create_style_value() const
     return LengthStyleValue::create(value());
 }
 
-double NumberOrCalculated::resolve_calculated(NonnullRefPtr<CSSMathValue> const& calculated, Layout::Node const&) const
+double NumberOrCalculated::resolve_calculated(NonnullRefPtr<CSSMathValue> const& calculated, Layout::Node const& layout_node) const
 {
-    return calculated->resolve_number().value();
+    return calculated->resolve_number(layout_node).value();
 }
 
 NonnullRefPtr<CSSStyleValue> NumberOrCalculated::create_style_value() const

+ 1 - 1
Libraries/LibWeb/CSS/CalculatedOr.h

@@ -119,7 +119,7 @@ class IntegerOrCalculated : public CalculatedOr<i64> {
 public:
     using CalculatedOr<i64>::CalculatedOr;
 
-    [[nodiscard]] i64 resolved() const;
+    [[nodiscard]] i64 resolved(Length::ResolutionContext const&) const;
 
 private:
     virtual i64 resolve_calculated(NonnullRefPtr<CSSMathValue> const&, Layout::Node const&) const override;

+ 8 - 7
Libraries/LibWeb/CSS/MediaQuery.cpp

@@ -90,12 +90,12 @@ bool MediaFeature::evaluate(HTML::Window const& window) const
         return false;
     auto queried_value = maybe_queried_value.release_value();
 
+    auto resolution_context = Length::ResolutionContext::for_window(window);
     switch (m_type) {
     case Type::IsTrue:
         if (queried_value.is_integer())
-            return queried_value.integer().resolved() != 0;
+            return queried_value.integer().resolved(resolution_context) != 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;
         }
@@ -149,17 +149,18 @@ bool MediaFeature::compare(HTML::Window const& window, MediaFeatureValue left, C
     }
 
     if (left.is_integer()) {
+        auto resolution_context = Length::ResolutionContext::for_window(window);
         switch (comparison) {
         case Comparison::Equal:
-            return left.integer().resolved() == right.integer().resolved();
+            return left.integer().resolved(resolution_context) == right.integer().resolved(resolution_context);
         case Comparison::LessThan:
-            return left.integer().resolved() < right.integer().resolved();
+            return left.integer().resolved(resolution_context) < right.integer().resolved(resolution_context);
         case Comparison::LessThanOrEqual:
-            return left.integer().resolved() <= right.integer().resolved();
+            return left.integer().resolved(resolution_context) <= right.integer().resolved(resolution_context);
         case Comparison::GreaterThan:
-            return left.integer().resolved() > right.integer().resolved();
+            return left.integer().resolved(resolution_context) > right.integer().resolved(resolution_context);
         case Comparison::GreaterThanOrEqual:
-            return left.integer().resolved() >= right.integer().resolved();
+            return left.integer().resolved(resolution_context) >= right.integer().resolved(resolution_context);
         }
         VERIFY_NOT_REACHED();
     }

+ 1 - 2
Libraries/LibWeb/CSS/Parser/MediaParsing.cpp

@@ -569,8 +569,7 @@ Optional<MediaFeatureValue> Parser::parse_media_feature_value(MediaFeatureID med
         auto transaction = tokens.begin_transaction();
         tokens.discard_whitespace();
         if (auto integer = parse_integer(tokens); integer.has_value()) {
-            auto integer_value = integer.value().resolved();
-            if (integer_value == 0 || integer_value == 1) {
+            if (integer.value().is_calculated() || integer->value() == 0 || integer->value() == 1) {
                 transaction.commit();
                 return MediaFeatureValue(integer.release_value());
             }

+ 30 - 0
Libraries/LibWeb/CSS/StyleValues/CSSMathValue.cpp

@@ -2797,19 +2797,49 @@ Optional<Time> CSSMathValue::resolve_time_percentage(Time const& percentage_basi
 Optional<double> CSSMathValue::resolve_number() const
 {
     auto result = m_calculation->resolve({}, {});
+
+    if (result.value().has<Number>())
+        return result.value().get<Number>().value();
+    return {};
+}
+
+Optional<double> CSSMathValue::resolve_number(Length::ResolutionContext const& context) const
+{
+    auto result = m_calculation->resolve(context, {});
+
     if (result.value().has<Number>())
         return result.value().get<Number>().value();
     return {};
 }
 
+Optional<double> CSSMathValue::resolve_number(Layout::Node const& layout_node) const
+{
+    return resolve_number(Length::ResolutionContext::for_layout_node(layout_node));
+}
+
 Optional<i64> CSSMathValue::resolve_integer() const
 {
     auto result = m_calculation->resolve({}, {});
+
+    if (result.value().has<Number>())
+        return result.value().get<Number>().integer_value();
+    return {};
+}
+
+Optional<i64> CSSMathValue::resolve_integer(Length::ResolutionContext const& context) const
+{
+    auto result = m_calculation->resolve(context, {});
+
     if (result.value().has<Number>())
         return result.value().get<Number>().integer_value();
     return {};
 }
 
+Optional<i64> CSSMathValue::resolve_integer(Layout::Node const& layout_node) const
+{
+    return resolve_integer(Length::ResolutionContext::for_layout_node(layout_node));
+}
+
 bool CSSMathValue::contains_percentage() const
 {
     return m_calculation->contains_percentage();

+ 5 - 1
Libraries/LibWeb/CSS/StyleValues/CSSMathValue.h

@@ -99,7 +99,7 @@ public:
 
     bool resolves_to_length() const { return m_resolved_type.matches_length(); }
     bool resolves_to_length_percentage() const { return m_resolved_type.matches_length_percentage(); }
-    [[nodiscard]] Optional<Length> resolve_length(Length::ResolutionContext const&) const;
+    Optional<Length> resolve_length(Length::ResolutionContext const&) const;
     Optional<Length> resolve_length(Layout::Node const& layout_node) const;
     Optional<Length> resolve_length_percentage(Layout::Node const&, Length const& percentage_basis) const;
     Optional<Length> resolve_length_percentage(Layout::Node const&, CSSPixels percentage_basis) const;
@@ -119,7 +119,11 @@ public:
     bool resolves_to_number() const { return m_resolved_type.matches_number(); }
     bool resolves_to_number_percentage() const { return m_resolved_type.matches_number_percentage(); }
     Optional<double> resolve_number() const;
+    Optional<double> resolve_number(Length::ResolutionContext const&) const;
+    Optional<double> resolve_number(Layout::Node const& layout_node) const;
     Optional<i64> resolve_integer() const;
+    Optional<i64> resolve_integer(Length::ResolutionContext const&) const;
+    Optional<i64> resolve_integer(Layout::Node const& layout_node) const;
 
     bool resolves_to_dimension() const { return m_resolved_type.matches_dimension(); }
 

+ 24 - 0
Tests/LibWeb/Ref/input/wpt-import/css/mediaqueries/mq-calc-sign-function-006.html

@@ -0,0 +1,24 @@
+<!doctype html>
+<title>Test: support for calc with sign() in Media Queries</title>
+<link rel="author" title="Daniil Sakhapov" href="mailto:sakhapov@chromium.org">
+<link rel="help" href="http://www.w3.org/TR/css3-values/#calc-notation">
+<link rel="help" href="http://www.w3.org/TR/css3-mediaqueries/#units">
+<link rel="match" href="../../../../expected/wpt-import/css/mediaqueries/../reference/ref-filled-green-100px-square.xht">
+<style>
+  :root {
+    font-size: 16px;
+  }
+  div {
+    width: 100px;
+    height: 100px;
+    background-color: green;
+  }
+
+  @media (grid: calc(2 * sign(17px - 1rem))) {
+    div {
+      background-color: red;
+    }
+  }
+</style>
+<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+<div></div>