Browse Source

LibWeb/CSS: Handle calculated integers when expanding unresolved values

In order to know whether `calc(2.5)` is a number or an integer, we have
to see what the property will accept. So, add that knowledge to
`Parser::expand_unresolved_values()`.

This makes `counter-increment: foo calc(2 * var(--n));` work correctly,
in a test I'm working on.
Sam Atkins 9 months ago
parent
commit
69d064697a

+ 41 - 31
Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp

@@ -8802,6 +8802,8 @@ bool Parser::expand_variables(DOM::Element& element, Optional<Selector::PseudoEl
 
 bool Parser::expand_unresolved_values(DOM::Element& element, FlyString const& property_name, TokenStream<ComponentValue>& source, Vector<ComponentValue>& dest)
 {
+    auto property = property_id_from_string(property_name);
+
     while (source.has_next_token()) {
         auto const& value = source.consume_a_token();
         if (value.is_function()) {
@@ -8811,37 +8813,45 @@ bool Parser::expand_unresolved_values(DOM::Element& element, FlyString const& pr
                 continue;
             }
 
-            if (auto maybe_calc_value = parse_calculated_value(value); maybe_calc_value && maybe_calc_value->is_math()) {
-                auto& calc_value = maybe_calc_value->as_math();
-                if (calc_value.resolves_to_angle()) {
-                    auto resolved_value = calc_value.resolve_angle();
-                    dest.empend(Token::create_dimension(resolved_value->to_degrees(), "deg"_fly_string));
-                    continue;
-                }
-                if (calc_value.resolves_to_frequency()) {
-                    auto resolved_value = calc_value.resolve_frequency();
-                    dest.empend(Token::create_dimension(resolved_value->to_hertz(), "hz"_fly_string));
-                    continue;
-                }
-                if (calc_value.resolves_to_length()) {
-                    // FIXME: In order to resolve lengths, we need to know the font metrics in case a font-relative unit
-                    //  is used. So... we can't do that until style is computed?
-                    //  This might be easier once we have calc-simplification implemented.
-                }
-                if (calc_value.resolves_to_percentage()) {
-                    auto resolved_value = calc_value.resolve_percentage();
-                    dest.empend(Token::create_percentage(resolved_value.value().value()));
-                    continue;
-                }
-                if (calc_value.resolves_to_time()) {
-                    auto resolved_value = calc_value.resolve_time();
-                    dest.empend(Token::create_dimension(resolved_value->to_seconds(), "s"_fly_string));
-                    continue;
-                }
-                if (calc_value.resolves_to_number()) {
-                    auto resolved_value = calc_value.resolve_number();
-                    dest.empend(Token::create_number(resolved_value.value()));
-                    continue;
+            if (property.has_value()) {
+                if (auto maybe_calc_value = parse_calculated_value(value); maybe_calc_value && maybe_calc_value->is_math()) {
+                    // FIXME: Run the actual simplification algorithm
+                    auto& calc_value = maybe_calc_value->as_math();
+                    if (property_accepts_type(*property, ValueType::Angle) && calc_value.resolves_to_angle()) {
+                        auto resolved_value = calc_value.resolve_angle();
+                        dest.empend(Token::create_dimension(resolved_value->to_degrees(), "deg"_fly_string));
+                        continue;
+                    }
+                    if (property_accepts_type(*property, ValueType::Frequency) && calc_value.resolves_to_frequency()) {
+                        auto resolved_value = calc_value.resolve_frequency();
+                        dest.empend(Token::create_dimension(resolved_value->to_hertz(), "hz"_fly_string));
+                        continue;
+                    }
+                    if (property_accepts_type(*property, ValueType::Length) && calc_value.resolves_to_length()) {
+                        // FIXME: In order to resolve lengths, we need to know the font metrics in case a font-relative unit
+                        //  is used. So... we can't do that until style is computed?
+                        //  This might be easier once we have calc-simplification implemented.
+                    }
+                    if (property_accepts_type(*property, ValueType::Percentage) && calc_value.resolves_to_percentage()) {
+                        auto resolved_value = calc_value.resolve_percentage();
+                        dest.empend(Token::create_percentage(resolved_value.value().value()));
+                        continue;
+                    }
+                    if (property_accepts_type(*property, ValueType::Time) && calc_value.resolves_to_time()) {
+                        auto resolved_value = calc_value.resolve_time();
+                        dest.empend(Token::create_dimension(resolved_value->to_seconds(), "s"_fly_string));
+                        continue;
+                    }
+                    if (property_accepts_type(*property, ValueType::Number) && calc_value.resolves_to_number()) {
+                        auto resolved_value = calc_value.resolve_number();
+                        dest.empend(Token::create_number(resolved_value.value(), Number::Type::Number));
+                        continue;
+                    }
+                    if (property_accepts_type(*property, ValueType::Integer) && calc_value.resolves_to_number()) {
+                        auto resolved_value = calc_value.resolve_integer();
+                        dest.empend(Token::create_number(resolved_value.value(), Number::Type::Integer));
+                        continue;
+                    }
                 }
             }
 

+ 2 - 2
Userland/Libraries/LibWeb/CSS/Parser/Token.h

@@ -158,11 +158,11 @@ public:
         return token;
     }
 
-    static Token create_number(double value)
+    static Token create_number(double value, Number::Type number_type)
     {
         Token token;
         token.m_type = Type::Number;
-        token.m_number_value = Number(Number::Type::Number, value);
+        token.m_number_value = Number(number_type, value);
         return token;
     }