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.
This commit is contained in:
Sam Atkins 2024-10-14 12:20:02 +01:00 committed by Andreas Kling
commit 69d064697a
Notes: github-actions[bot] 2024-10-16 06:35:11 +00:00
2 changed files with 43 additions and 33 deletions

View file

@ -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) 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()) { while (source.has_next_token()) {
auto const& value = source.consume_a_token(); auto const& value = source.consume_a_token();
if (value.is_function()) { if (value.is_function()) {
@ -8811,37 +8813,45 @@ bool Parser::expand_unresolved_values(DOM::Element& element, FlyString const& pr
continue; continue;
} }
if (auto maybe_calc_value = parse_calculated_value(value); maybe_calc_value && maybe_calc_value->is_math()) { if (property.has_value()) {
auto& calc_value = maybe_calc_value->as_math(); if (auto maybe_calc_value = parse_calculated_value(value); maybe_calc_value && maybe_calc_value->is_math()) {
if (calc_value.resolves_to_angle()) { // FIXME: Run the actual simplification algorithm
auto resolved_value = calc_value.resolve_angle(); auto& calc_value = maybe_calc_value->as_math();
dest.empend(Token::create_dimension(resolved_value->to_degrees(), "deg"_fly_string)); if (property_accepts_type(*property, ValueType::Angle) && calc_value.resolves_to_angle()) {
continue; auto resolved_value = calc_value.resolve_angle();
} dest.empend(Token::create_dimension(resolved_value->to_degrees(), "deg"_fly_string));
if (calc_value.resolves_to_frequency()) { continue;
auto resolved_value = calc_value.resolve_frequency(); }
dest.empend(Token::create_dimension(resolved_value->to_hertz(), "hz"_fly_string)); if (property_accepts_type(*property, ValueType::Frequency) && calc_value.resolves_to_frequency()) {
continue; auto resolved_value = calc_value.resolve_frequency();
} dest.empend(Token::create_dimension(resolved_value->to_hertz(), "hz"_fly_string));
if (calc_value.resolves_to_length()) { continue;
// 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? if (property_accepts_type(*property, ValueType::Length) && calc_value.resolves_to_length()) {
// This might be easier once we have calc-simplification implemented. // 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?
if (calc_value.resolves_to_percentage()) { // This might be easier once we have calc-simplification implemented.
auto resolved_value = calc_value.resolve_percentage(); }
dest.empend(Token::create_percentage(resolved_value.value().value())); if (property_accepts_type(*property, ValueType::Percentage) && calc_value.resolves_to_percentage()) {
continue; auto resolved_value = calc_value.resolve_percentage();
} dest.empend(Token::create_percentage(resolved_value.value().value()));
if (calc_value.resolves_to_time()) { continue;
auto resolved_value = calc_value.resolve_time(); }
dest.empend(Token::create_dimension(resolved_value->to_seconds(), "s"_fly_string)); if (property_accepts_type(*property, ValueType::Time) && calc_value.resolves_to_time()) {
continue; auto resolved_value = calc_value.resolve_time();
} dest.empend(Token::create_dimension(resolved_value->to_seconds(), "s"_fly_string));
if (calc_value.resolves_to_number()) { continue;
auto resolved_value = calc_value.resolve_number(); }
dest.empend(Token::create_number(resolved_value.value())); if (property_accepts_type(*property, ValueType::Number) && calc_value.resolves_to_number()) {
continue; 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;
}
} }
} }

View file

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