LibWeb/CSS: Parse calc() as intermediate types instead of UnparsedCN

Previously we created a tree of CalculationNodes with dummy
UnparsedCalculationNode children, and then swapped those with the real
children. This matched the spec closely but had the unfortunate
downside that CalculationNodes couldn't be immutable, and couldn't know
their properties at construct-time. UnparsedCalculationNode is also a
footgun, as if it gets left in the tree accidentally we would VERIFY().

So instead, let's parse the calc() tree into an intermediate format, and
then convert each node in that tree, depth-first, into its
corresponding CalculationNode. This means each CalculationNode knows
what its children are when it is constructed, and they never change.

Apart from deleting UnparsedCalculationNode, we can also get rid of the
for_each_child_node() method that was only used by this "replace the
children" code.
This commit is contained in:
Sam Atkins 2024-12-17 14:00:41 +00:00
parent cef1cb6aa7
commit 6969d1eba3
Notes: github-actions[bot] 2024-12-18 12:22:26 +00:00
4 changed files with 166 additions and 336 deletions

View file

@ -366,14 +366,6 @@ CSSMathValue::CalculationResult SumCalculationNode::resolve(Optional<Length::Res
return total.value();
}
void SumCalculationNode::for_each_child_node(Function<void(NonnullOwnPtr<CalculationNode>&)> const& callback)
{
for (auto& item : m_values) {
item->for_each_child_node(callback);
callback(item);
}
}
void SumCalculationNode::dump(StringBuilder& builder, int indent) const
{
builder.appendff("{: >{}}SUM:\n", "", indent);
@ -504,14 +496,6 @@ CSSMathValue::CalculationResult ProductCalculationNode::resolve(Optional<Length:
return total.value();
}
void ProductCalculationNode::for_each_child_node(Function<void(NonnullOwnPtr<CalculationNode>&)> const& callback)
{
for (auto& item : m_values) {
item->for_each_child_node(callback);
callback(item);
}
}
void ProductCalculationNode::dump(StringBuilder& builder, int indent) const
{
builder.appendff("{: >{}}PRODUCT:\n", "", indent);
@ -576,12 +560,6 @@ CSSMathValue::CalculationResult NegateCalculationNode::resolve(Optional<Length::
return child_value;
}
void NegateCalculationNode::for_each_child_node(Function<void(NonnullOwnPtr<CalculationNode>&)> const& callback)
{
m_value->for_each_child_node(callback);
callback(m_value);
}
void NegateCalculationNode::dump(StringBuilder& builder, int indent) const
{
builder.appendff("{: >{}}NEGATE:\n", "", indent);
@ -646,12 +624,6 @@ CSSMathValue::CalculationResult InvertCalculationNode::resolve(Optional<Length::
return child_value;
}
void InvertCalculationNode::for_each_child_node(Function<void(NonnullOwnPtr<CalculationNode>&)> const& callback)
{
m_value->for_each_child_node(callback);
callback(m_value);
}
void InvertCalculationNode::dump(StringBuilder& builder, int indent) const
{
builder.appendff("{: >{}}INVERT:\n", "", indent);
@ -734,14 +706,6 @@ CSSMathValue::CalculationResult MinCalculationNode::resolve(Optional<Length::Res
return smallest_node;
}
void MinCalculationNode::for_each_child_node(Function<void(NonnullOwnPtr<CalculationNode>&)> const& callback)
{
for (auto& value : m_values) {
value->for_each_child_node(callback);
callback(value);
}
}
void MinCalculationNode::dump(StringBuilder& builder, int indent) const
{
builder.appendff("{: >{}}MIN:\n", "", indent);
@ -831,14 +795,6 @@ CSSMathValue::CalculationResult MaxCalculationNode::resolve(Optional<Length::Res
return largest_node;
}
void MaxCalculationNode::for_each_child_node(Function<void(NonnullOwnPtr<CalculationNode>&)> const& callback)
{
for (auto& value : m_values) {
value->for_each_child_node(callback);
callback(value);
}
}
void MaxCalculationNode::dump(StringBuilder& builder, int indent) const
{
builder.appendff("{: >{}}MAX:\n", "", indent);
@ -939,16 +895,6 @@ CSSMathValue::CalculationResult ClampCalculationNode::resolve(Optional<Length::R
VERIFY_NOT_REACHED();
}
void ClampCalculationNode::for_each_child_node(Function<void(NonnullOwnPtr<CalculationNode>&)> const& callback)
{
m_min_value->for_each_child_node(callback);
m_center_value->for_each_child_node(callback);
m_max_value->for_each_child_node(callback);
callback(m_min_value);
callback(m_center_value);
callback(m_max_value);
}
void ClampCalculationNode::dump(StringBuilder& builder, int indent) const
{
builder.appendff("{: >{}}CLAMP:\n", "", indent);
@ -1019,12 +965,6 @@ CSSMathValue::CalculationResult AbsCalculationNode::resolve(Optional<Length::Res
return node_a;
}
void AbsCalculationNode::for_each_child_node(Function<void(NonnullOwnPtr<CalculationNode>&)> const& callback)
{
m_value->for_each_child_node(callback);
callback(m_value);
}
void AbsCalculationNode::dump(StringBuilder& builder, int indent) const
{
builder.appendff("{: >{}}ABS: {}\n", "", indent, to_string());
@ -1092,12 +1032,6 @@ CSSMathValue::CalculationResult SignCalculationNode::resolve(Optional<Length::Re
return { Number(Number::Type::Integer, 0) };
}
void SignCalculationNode::for_each_child_node(Function<void(NonnullOwnPtr<CalculationNode>&)> const& callback)
{
m_value->for_each_child_node(callback);
callback(m_value);
}
void SignCalculationNode::dump(StringBuilder& builder, int indent) const
{
builder.appendff("{: >{}}SIGN: {}\n", "", indent, to_string());
@ -1237,12 +1171,6 @@ CSSMathValue::CalculationResult SinCalculationNode::resolve(Optional<Length::Res
return { Number(Number::Type::Number, result) };
}
void SinCalculationNode::for_each_child_node(Function<void(NonnullOwnPtr<CalculationNode>&)> const& callback)
{
m_value->for_each_child_node(callback);
callback(m_value);
}
void SinCalculationNode::dump(StringBuilder& builder, int indent) const
{
builder.appendff("{: >{}}SIN: {}\n", "", indent, to_string());
@ -1305,12 +1233,6 @@ CSSMathValue::CalculationResult CosCalculationNode::resolve(Optional<Length::Res
return { Number(Number::Type::Number, result) };
}
void CosCalculationNode::for_each_child_node(Function<void(NonnullOwnPtr<CalculationNode>&)> const& callback)
{
m_value->for_each_child_node(callback);
callback(m_value);
}
void CosCalculationNode::dump(StringBuilder& builder, int indent) const
{
builder.appendff("{: >{}}COS: {}\n", "", indent, to_string());
@ -1373,12 +1295,6 @@ CSSMathValue::CalculationResult TanCalculationNode::resolve(Optional<Length::Res
return { Number(Number::Type::Number, result) };
}
void TanCalculationNode::for_each_child_node(Function<void(NonnullOwnPtr<CalculationNode>&)> const& callback)
{
m_value->for_each_child_node(callback);
callback(m_value);
}
void TanCalculationNode::dump(StringBuilder& builder, int indent) const
{
builder.appendff("{: >{}}TAN: {}\n", "", indent, to_string());
@ -1441,12 +1357,6 @@ CSSMathValue::CalculationResult AsinCalculationNode::resolve(Optional<Length::Re
return { Angle(result, Angle::Type::Rad) };
}
void AsinCalculationNode::for_each_child_node(Function<void(NonnullOwnPtr<CalculationNode>&)> const& callback)
{
m_value->for_each_child_node(callback);
callback(m_value);
}
void AsinCalculationNode::dump(StringBuilder& builder, int indent) const
{
builder.appendff("{: >{}}ASIN: {}\n", "", indent, to_string());
@ -1509,12 +1419,6 @@ CSSMathValue::CalculationResult AcosCalculationNode::resolve(Optional<Length::Re
return { Angle(result, Angle::Type::Rad) };
}
void AcosCalculationNode::for_each_child_node(Function<void(NonnullOwnPtr<CalculationNode>&)> const& callback)
{
m_value->for_each_child_node(callback);
callback(m_value);
}
void AcosCalculationNode::dump(StringBuilder& builder, int indent) const
{
builder.appendff("{: >{}}ACOS: {}\n", "", indent, to_string());
@ -1577,12 +1481,6 @@ CSSMathValue::CalculationResult AtanCalculationNode::resolve(Optional<Length::Re
return { Angle(result, Angle::Type::Rad) };
}
void AtanCalculationNode::for_each_child_node(Function<void(NonnullOwnPtr<CalculationNode>&)> const& callback)
{
m_value->for_each_child_node(callback);
callback(m_value);
}
void AtanCalculationNode::dump(StringBuilder& builder, int indent) const
{
builder.appendff("{: >{}}ATAN: {}\n", "", indent, to_string());
@ -1652,14 +1550,6 @@ CSSMathValue::CalculationResult Atan2CalculationNode::resolve(Optional<Length::R
return { Angle(result, Angle::Type::Rad) };
}
void Atan2CalculationNode::for_each_child_node(Function<void(NonnullOwnPtr<CalculationNode>&)> const& callback)
{
m_y->for_each_child_node(callback);
m_x->for_each_child_node(callback);
callback(m_y);
callback(m_x);
}
void Atan2CalculationNode::dump(StringBuilder& builder, int indent) const
{
builder.appendff("{: >{}}ATAN2: {}\n", "", indent, to_string());
@ -1725,14 +1615,6 @@ CSSMathValue::CalculationResult PowCalculationNode::resolve(Optional<Length::Res
return { Number(Number::Type::Number, result) };
}
void PowCalculationNode::for_each_child_node(Function<void(NonnullOwnPtr<CalculationNode>&)> const& callback)
{
m_x->for_each_child_node(callback);
m_y->for_each_child_node(callback);
callback(m_x);
callback(m_y);
}
void PowCalculationNode::dump(StringBuilder& builder, int indent) const
{
builder.appendff("{: >{}}POW: {}\n", "", indent, to_string());
@ -1791,12 +1673,6 @@ CSSMathValue::CalculationResult SqrtCalculationNode::resolve(Optional<Length::Re
return { Number(Number::Type::Number, result) };
}
void SqrtCalculationNode::for_each_child_node(Function<void(NonnullOwnPtr<CalculationNode>&)> const& callback)
{
m_value->for_each_child_node(callback);
callback(m_value);
}
void SqrtCalculationNode::dump(StringBuilder& builder, int indent) const
{
builder.appendff("{: >{}}SQRT: {}\n", "", indent, to_string());
@ -1876,14 +1752,6 @@ CSSMathValue::CalculationResult HypotCalculationNode::resolve(Optional<Length::R
return to_resolved_type(resolved_type().value(), result);
}
void HypotCalculationNode::for_each_child_node(Function<void(NonnullOwnPtr<CalculationNode>&)> const& callback)
{
for (auto& value : m_values) {
value->for_each_child_node(callback);
callback(value);
}
}
void HypotCalculationNode::dump(StringBuilder& builder, int indent) const
{
builder.appendff("{: >{}}HYPOT:\n", "", indent);
@ -1954,14 +1822,6 @@ CSSMathValue::CalculationResult LogCalculationNode::resolve(Optional<Length::Res
return { Number(Number::Type::Number, result) };
}
void LogCalculationNode::for_each_child_node(Function<void(NonnullOwnPtr<CalculationNode>&)> const& callback)
{
m_x->for_each_child_node(callback);
m_y->for_each_child_node(callback);
callback(m_x);
callback(m_y);
}
void LogCalculationNode::dump(StringBuilder& builder, int indent) const
{
builder.appendff("{: >{}}LOG: {}\n", "", indent, to_string());
@ -2020,12 +1880,6 @@ CSSMathValue::CalculationResult ExpCalculationNode::resolve(Optional<Length::Res
return { Number(Number::Type::Number, result) };
}
void ExpCalculationNode::for_each_child_node(Function<void(NonnullOwnPtr<CalculationNode>&)> const& callback)
{
m_value->for_each_child_node(callback);
callback(m_value);
}
void ExpCalculationNode::dump(StringBuilder& builder, int indent) const
{
builder.appendff("{: >{}}EXP: {}\n", "", indent, to_string());
@ -2130,14 +1984,6 @@ CSSMathValue::CalculationResult RoundCalculationNode::resolve(Optional<Length::R
VERIFY_NOT_REACHED();
}
void RoundCalculationNode::for_each_child_node(Function<void(NonnullOwnPtr<CalculationNode>&)> const& callback)
{
m_x->for_each_child_node(callback);
m_y->for_each_child_node(callback);
callback(m_x);
callback(m_y);
}
void RoundCalculationNode::dump(StringBuilder& builder, int indent) const
{
builder.appendff("{: >{}}ROUND: {}\n", "", indent, to_string());
@ -2217,14 +2063,6 @@ CSSMathValue::CalculationResult ModCalculationNode::resolve(Optional<Length::Res
return to_resolved_type(resolved_type, value);
}
void ModCalculationNode::for_each_child_node(Function<void(NonnullOwnPtr<CalculationNode>&)> const& callback)
{
m_x->for_each_child_node(callback);
m_y->for_each_child_node(callback);
callback(m_x);
callback(m_y);
}
void ModCalculationNode::dump(StringBuilder& builder, int indent) const
{
builder.appendff("{: >{}}MOD: {}\n", "", indent, to_string());
@ -2302,14 +2140,6 @@ CSSMathValue::CalculationResult RemCalculationNode::resolve(Optional<Length::Res
return to_resolved_type(resolved_type, value);
}
void RemCalculationNode::for_each_child_node(Function<void(NonnullOwnPtr<CalculationNode>&)> const& callback)
{
m_x->for_each_child_node(callback);
m_y->for_each_child_node(callback);
callback(m_x);
callback(m_y);
}
void RemCalculationNode::dump(StringBuilder& builder, int indent) const
{
builder.appendff("{: >{}}REM: {}\n", "", indent, to_string());