mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-08-09 01:29:17 +00:00
LibWeb/CSS: Recalculate calc() numeric type when resolving percentages
Previously, `percentage_of` would be called on the previous value, potentially changing its numeric type, yet this potential change was never reflected as the old numeric type was always used. Now, the numeric type will be re-calculated every time after the percentage is resolved. As well, VERIFY checks have been placed to uphold the requirements for the numeric types to match what the actual values are.
This commit is contained in:
parent
938ffe183e
commit
db58986e5f
Notes:
github-actions[bot]
2025-01-04 18:48:41 +00:00
Author: https://github.com/Jaycadox 🔰
Commit: db58986e5f
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/3007
Reviewed-by: https://github.com/AtkinsSJ ✅
Reviewed-by: https://github.com/LucasChollet
3 changed files with 28 additions and 4 deletions
|
@ -109,12 +109,12 @@ CalculationNode::CalculationNode(Type type, Optional<CSSNumericType> numeric_typ
|
||||||
|
|
||||||
CalculationNode::~CalculationNode() = default;
|
CalculationNode::~CalculationNode() = default;
|
||||||
|
|
||||||
NonnullOwnPtr<NumericCalculationNode> NumericCalculationNode::create(NumericValue value, Optional<ValueType> percentage_resolved_type)
|
static CSSNumericType numeric_type_from_calculated_style_value(CalculatedStyleValue::CalculationResult::Value const& value, Optional<ValueType> percentage_resolved_type)
|
||||||
{
|
{
|
||||||
// https://drafts.csswg.org/css-values-4/#determine-the-type-of-a-calculation
|
// https://drafts.csswg.org/css-values-4/#determine-the-type-of-a-calculation
|
||||||
// Anything else is a terminal value, whose type is determined based on its CSS type.
|
// Anything else is a terminal value, whose type is determined based on its CSS type.
|
||||||
// (Unless otherwise specified, the type’s associated percent hint is null.)
|
// (Unless otherwise specified, the type’s associated percent hint is null.)
|
||||||
auto numeric_type = value.visit(
|
return value.visit(
|
||||||
[](Number const&) {
|
[](Number const&) {
|
||||||
// -> <number>
|
// -> <number>
|
||||||
// -> <integer>
|
// -> <integer>
|
||||||
|
@ -172,7 +172,11 @@ NonnullOwnPtr<NumericCalculationNode> NumericCalculationNode::create(NumericValu
|
||||||
// result.set_percent_hint(CSSNumericType::BaseType::Percent);
|
// result.set_percent_hint(CSSNumericType::BaseType::Percent);
|
||||||
return result;
|
return result;
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
NonnullOwnPtr<NumericCalculationNode> NumericCalculationNode::create(NumericValue value, Optional<ValueType> percentage_resolved_type)
|
||||||
|
{
|
||||||
|
auto numeric_type = numeric_type_from_calculated_style_value(value, percentage_resolved_type);
|
||||||
return adopt_own(*new (nothrow) NumericCalculationNode(move(value), numeric_type));
|
return adopt_own(*new (nothrow) NumericCalculationNode(move(value), numeric_type));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -200,11 +204,13 @@ CalculatedStyleValue::CalculationResult NumericCalculationNode::resolve(Optional
|
||||||
// NOTE: Depending on whether percentage_basis is set, the caller of resolve() is expecting a raw percentage or
|
// NOTE: Depending on whether percentage_basis is set, the caller of resolve() is expecting a raw percentage or
|
||||||
// resolved type.
|
// resolved type.
|
||||||
return percentage_basis.visit(
|
return percentage_basis.visit(
|
||||||
[&](Empty const&) -> CalculatedStyleValue::CalculationResult {
|
[&](Empty const&) {
|
||||||
|
VERIFY(numeric_type_from_calculated_style_value(m_value, {}) == numeric_type());
|
||||||
return CalculatedStyleValue::CalculationResult::from_value(m_value, resolution_context, numeric_type());
|
return CalculatedStyleValue::CalculationResult::from_value(m_value, resolution_context, numeric_type());
|
||||||
},
|
},
|
||||||
[&](auto const& value) {
|
[&](auto const& value) {
|
||||||
return CalculatedStyleValue::CalculationResult::from_value(value.percentage_of(m_value.get<Percentage>()), resolution_context, numeric_type());
|
auto const calculated_value = value.percentage_of(m_value.get<Percentage>());
|
||||||
|
return CalculatedStyleValue::CalculationResult::from_value(calculated_value, resolution_context, numeric_type_from_calculated_style_value(calculated_value, {}));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1730,6 +1736,11 @@ bool RemCalculationNode::equals(CalculationNode const& other) const
|
||||||
|
|
||||||
CalculatedStyleValue::CalculationResult CalculatedStyleValue::CalculationResult::from_value(Value const& value, Optional<Length::ResolutionContext const&> context, Optional<CSSNumericType> numeric_type)
|
CalculatedStyleValue::CalculationResult CalculatedStyleValue::CalculationResult::from_value(Value const& value, Optional<Length::ResolutionContext const&> context, Optional<CSSNumericType> numeric_type)
|
||||||
{
|
{
|
||||||
|
auto const expected_numeric_type = numeric_type_from_calculated_style_value(value, {});
|
||||||
|
if (numeric_type.has_value()) {
|
||||||
|
VERIFY(numeric_type.value() == expected_numeric_type);
|
||||||
|
}
|
||||||
|
|
||||||
auto number = value.visit(
|
auto number = value.visit(
|
||||||
[](Number const& number) { return number.value(); },
|
[](Number const& number) { return number.value(); },
|
||||||
[](Angle const& angle) { return angle.to_degrees(); },
|
[](Angle const& angle) { return angle.to_degrees(); },
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
PASS! (Didn't crash)
|
|
@ -0,0 +1,12 @@
|
||||||
|
<script src="../include.js"></script>
|
||||||
|
<style>
|
||||||
|
div {
|
||||||
|
transform: translateX(calc(10%))
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<div></div>
|
||||||
|
<script>
|
||||||
|
test(() => {
|
||||||
|
println(`PASS! (Didn't crash)`);
|
||||||
|
});
|
||||||
|
</script>
|
Loading…
Add table
Add a link
Reference in a new issue