LibWeb: Skip inverted non-canonical values when simplifying product node

This matches the logic with the non-inverted children.

Gains us 2 WPT tests.
This commit is contained in:
Callum Law 2025-07-31 00:14:04 +12:00 committed by Sam Atkins
parent cd1cf75f7b
commit c3b1013018
Notes: github-actions[bot] 2025-08-06 13:56:43 +00:00
17 changed files with 387 additions and 44 deletions

View file

@ -3304,32 +3304,39 @@ NonnullRefPtr<CalculationNode const> simplify_a_calculation_tree(CalculationNode
// its childs value), expressed in the results canonical unit.
Optional<CalculatedStyleValue::CalculationResult> accumulated_result;
bool is_valid = true;
auto accumulate = [&accumulated_result, &resolution_context, &context](NumericCalculationNode const& numeric_child, bool invert) {
auto child_type = numeric_child.numeric_type();
if (!child_type.has_value())
return false;
// FIXME: The spec doesn't handle unresolved percentages here, but if we don't exit when we see one,
// we'll get a wrongly-typed value after multiplying the types.
// Same goes for other numerics with non-canonical units.
// Spec bug: https://github.com/w3c/csswg-drafts/issues/11588
if ((numeric_child.value().has<Percentage>() && context.percentages_resolve_as.has_value()) || !numeric_child.is_in_canonical_unit())
return false;
auto child_value = CalculatedStyleValue::CalculationResult::from_value(numeric_child.value(), resolution_context, child_type);
if (invert)
child_value.invert();
if (accumulated_result.has_value())
accumulated_result->multiply_by(child_value);
else
accumulated_result = child_value;
if (!accumulated_result->type().has_value())
return false;
return true;
};
for (auto const& child : children) {
if (child->type() == CalculationNode::Type::Numeric) {
auto const& numeric_child = as<NumericCalculationNode>(*child);
auto child_type = numeric_child.numeric_type();
if (!child_type.has_value()) {
is_valid = false;
break;
}
// FIXME: The spec doesn't handle unresolved percentages here, but if we don't exit when we see one,
// we'll get a wrongly-typed value after multiplying the types.
// Same goes for other numerics with non-canonical units.
// Spec bug: https://github.com/w3c/csswg-drafts/issues/11588
if ((numeric_child.value().has<Percentage>() && context.percentages_resolve_as.has_value())
|| !numeric_child.is_in_canonical_unit()) {
is_valid = false;
break;
}
auto child_value = CalculatedStyleValue::CalculationResult::from_value(numeric_child.value(), resolution_context, child_type);
if (accumulated_result.has_value()) {
accumulated_result->multiply_by(child_value);
} else {
accumulated_result = move(child_value);
}
if (!accumulated_result->type().has_value()) {
if (!accumulate(as<NumericCalculationNode>(*child), false)) {
is_valid = false;
break;
}
@ -3337,26 +3344,7 @@ NonnullRefPtr<CalculationNode const> simplify_a_calculation_tree(CalculationNode
}
if (child->type() == CalculationNode::Type::Invert) {
auto const& invert_child = as<InvertCalculationNode>(*child);
if (invert_child.child().type() != CalculationNode::Type::Numeric) {
is_valid = false;
break;
}
auto const& grandchild = as<NumericCalculationNode>(invert_child.child());
auto child_type = child->numeric_type();
if (!child_type.has_value()) {
is_valid = false;
break;
}
auto child_value = CalculatedStyleValue::CalculationResult::from_value(grandchild.value(), resolution_context, grandchild.numeric_type());
child_value.invert();
if (accumulated_result.has_value()) {
accumulated_result->multiply_by(child_value);
} else {
accumulated_result = move(child_value);
}
if (!accumulated_result->type().has_value()) {
if (invert_child.child().type() != CalculationNode::Type::Numeric || !accumulate(as<NumericCalculationNode>(invert_child.child()), true)) {
is_valid = false;
break;
}