LibWeb/CSS: Make CalculationNodes ref-counted

Calc simplification (which I'm working towards) involves repeatedly
deriving a new calculation tree from an existing one, and in many
cases, either the whole result or a portion of it will be identical to
that of the original. Using RefPtr lets us avoid making unnecessary
copies. As a bonus it will also make it easier to return either `this`
or a new node.

In future we could also cache commonly-used nodes, similar to how we do
so for 1px and 0px LengthStyleValues and various keywords.
This commit is contained in:
Sam Atkins 2025-01-22 16:50:54 +00:00 committed by Andreas Kling
commit c3d61020e7
Notes: github-actions[bot] 2025-01-30 18:33:46 +00:00
7 changed files with 185 additions and 185 deletions

View file

@ -1953,7 +1953,7 @@ RefPtr<CalculatedStyleValue> Parser::parse_calculated_value(ComponentValue const
return CalculatedStyleValue::create(function_node.release_nonnull(), function_type.release_value(), context);
}
OwnPtr<CalculationNode> Parser::parse_a_calc_function_node(Function const& function, CalculationContext const& context)
RefPtr<CalculationNode> Parser::parse_a_calc_function_node(Function const& function, CalculationContext const& context)
{
auto context_guard = push_temporary_value_parsing_context(FunctionContext { function.name });
@ -9257,11 +9257,11 @@ LengthOrCalculated Parser::Parser::parse_as_sizes_attribute(DOM::Element const&
return Length(100, Length::Type::Vw);
}
OwnPtr<CalculationNode> Parser::convert_to_calculation_node(CalcParsing::Node const& node, CalculationContext const& context)
RefPtr<CalculationNode> Parser::convert_to_calculation_node(CalcParsing::Node const& node, CalculationContext const& context)
{
return node.visit(
[this, &context](NonnullOwnPtr<CalcParsing::ProductNode> const& product_node) -> OwnPtr<CalculationNode> {
Vector<NonnullOwnPtr<CalculationNode>> children;
[this, &context](NonnullOwnPtr<CalcParsing::ProductNode> const& product_node) -> RefPtr<CalculationNode> {
Vector<NonnullRefPtr<CalculationNode>> children;
children.ensure_capacity(product_node->children.size());
for (auto const& child : product_node->children) {
@ -9274,8 +9274,8 @@ OwnPtr<CalculationNode> Parser::convert_to_calculation_node(CalcParsing::Node co
return ProductCalculationNode::create(move(children));
},
[this, &context](NonnullOwnPtr<CalcParsing::SumNode> const& sum_node) -> OwnPtr<CalculationNode> {
Vector<NonnullOwnPtr<CalculationNode>> children;
[this, &context](NonnullOwnPtr<CalcParsing::SumNode> const& sum_node) -> RefPtr<CalculationNode> {
Vector<NonnullRefPtr<CalculationNode>> children;
children.ensure_capacity(sum_node->children.size());
for (auto const& child : sum_node->children) {
@ -9288,17 +9288,17 @@ OwnPtr<CalculationNode> Parser::convert_to_calculation_node(CalcParsing::Node co
return SumCalculationNode::create(move(children));
},
[this, &context](NonnullOwnPtr<CalcParsing::InvertNode> const& invert_node) -> OwnPtr<CalculationNode> {
[this, &context](NonnullOwnPtr<CalcParsing::InvertNode> const& invert_node) -> RefPtr<CalculationNode> {
if (auto child_as_node = convert_to_calculation_node(invert_node->child, context))
return InvertCalculationNode::create(child_as_node.release_nonnull());
return nullptr;
},
[this, &context](NonnullOwnPtr<CalcParsing::NegateNode> const& negate_node) -> OwnPtr<CalculationNode> {
[this, &context](NonnullOwnPtr<CalcParsing::NegateNode> const& negate_node) -> RefPtr<CalculationNode> {
if (auto child_as_node = convert_to_calculation_node(negate_node->child, context))
return NegateCalculationNode::create(child_as_node.release_nonnull());
return nullptr;
},
[this, &context](NonnullRawPtr<ComponentValue const> const& component_value) -> OwnPtr<CalculationNode> {
[this, &context](NonnullRawPtr<ComponentValue const> const& component_value) -> RefPtr<CalculationNode> {
// NOTE: This is the "process the leaf nodes" part of step 5 of https://drafts.csswg.org/css-values-4/#parse-a-calculation
// We divert a little from the spec: Rather than modify an existing tree of values, we construct a new one from that source tree.
// This lets us make CalculationNodes immutable.
@ -9375,14 +9375,14 @@ OwnPtr<CalculationNode> Parser::convert_to_calculation_node(CalcParsing::Node co
dbgln_if(CSS_PARSER_DEBUG, "Leftover ComponentValue in calc tree! That probably means the syntax is invalid, but maybe we just didn't implement `{}` yet.", component_value->to_debug_string());
return nullptr;
},
[](CalcParsing::Operator const& op) -> OwnPtr<CalculationNode> {
[](CalcParsing::Operator const& op) -> RefPtr<CalculationNode> {
dbgln_if(CSS_PARSER_DEBUG, "Leftover Operator {} in calc tree!", op.delim);
return nullptr;
});
}
// https://drafts.csswg.org/css-values-4/#parse-a-calculation
OwnPtr<CalculationNode> Parser::parse_a_calculation(Vector<ComponentValue> const& original_values, CalculationContext const& context)
RefPtr<CalculationNode> Parser::parse_a_calculation(Vector<ComponentValue> const& original_values, CalculationContext const& context)
{
// 1. Discard any <whitespace-token>s from values.
// 2. An item in values is an “operator” if its a <delim-token> with the value "+", "-", "*", or "/". Otherwise, its a “value”.