From 5b9a36b172577bf24eacc378a129b7962218d171 Mon Sep 17 00:00:00 2001 From: Callum Law Date: Wed, 22 Oct 2025 00:06:38 +1300 Subject: [PATCH] LibWeb: Pass `AbstractElement` in `ComputationContext` Passing the `AbstractElement` rather than the `TreeCountingFunctionResolutionContext` allows us to only compute the resolution context when necessary (i.e. when we actually need to resolve a tree counting function) --- .../LibWeb/CSS/CalculationResolutionContext.h | 4 ++-- Libraries/LibWeb/CSS/StyleComputer.cpp | 15 ++++++--------- .../LibWeb/CSS/StyleValues/ComputationContext.h | 8 ++------ .../TreeCountingFunctionStyleValue.cpp | 12 +++++++----- .../StyleValues/TreeCountingFunctionStyleValue.h | 2 +- Libraries/LibWeb/DOM/AbstractElement.cpp | 2 +- Libraries/LibWeb/DOM/AbstractElement.h | 6 +++++- Libraries/LibWeb/Forward.h | 1 - .../LibWeb/HTML/Canvas/CanvasTextDrawingStyles.h | 9 ++++----- 9 files changed, 28 insertions(+), 31 deletions(-) diff --git a/Libraries/LibWeb/CSS/CalculationResolutionContext.h b/Libraries/LibWeb/CSS/CalculationResolutionContext.h index 97f9cc8e018..1da5768d4ed 100644 --- a/Libraries/LibWeb/CSS/CalculationResolutionContext.h +++ b/Libraries/LibWeb/CSS/CalculationResolutionContext.h @@ -19,14 +19,14 @@ struct CalculationResolutionContext { PercentageBasis percentage_basis {}; Optional length_resolution_context {}; - Optional tree_counting_function_resolution_context {}; + Optional abstract_element {}; static CalculationResolutionContext from_computation_context(ComputationContext const& computation_context, PercentageBasis percentage_basis = {}) { return { .percentage_basis = percentage_basis, .length_resolution_context = computation_context.length_resolution_context, - .tree_counting_function_resolution_context = computation_context.tree_counting_function_resolution_context + .abstract_element = computation_context.abstract_element }; } }; diff --git a/Libraries/LibWeb/CSS/StyleComputer.cpp b/Libraries/LibWeb/CSS/StyleComputer.cpp index 2f2c9de87cf..0647e785d91 100644 --- a/Libraries/LibWeb/CSS/StyleComputer.cpp +++ b/Libraries/LibWeb/CSS/StyleComputer.cpp @@ -1078,12 +1078,11 @@ void StyleComputer::collect_animation_into(DOM::AbstractElement abstract_element }); } - auto tree_counting_function_resolution_context = abstract_element.tree_counting_function_resolution_context(); auto const& inheritance_parent = abstract_element.element_to_inherit_style_from(); auto inheritance_parent_has_computed_properties = inheritance_parent.has_value() && inheritance_parent->computed_properties(); ComputationContext font_computation_context { .length_resolution_context = inheritance_parent_has_computed_properties ? Length::ResolutionContext::for_element(inheritance_parent.value()) : Length::ResolutionContext::for_window(*m_document->window()), - .tree_counting_function_resolution_context = tree_counting_function_resolution_context + .abstract_element = abstract_element }; if (auto const& font_size_specified_value = specified_values.get(PropertyID::FontSize); font_size_specified_value.has_value()) { @@ -1140,7 +1139,7 @@ void StyleComputer::collect_animation_into(DOM::AbstractElement abstract_element computed_properties.first_available_computed_font().pixel_metrics(), inheritance_parent_has_computed_properties ? inheritance_parent->computed_properties()->line_height() : InitialValues::line_height() }, .root_font_metrics = m_root_element_font_metrics }, - .tree_counting_function_resolution_context = tree_counting_function_resolution_context + .abstract_element = abstract_element }; PropertyComputationDependencies property_computation_dependencies; @@ -1153,7 +1152,7 @@ void StyleComputer::collect_animation_into(DOM::AbstractElement abstract_element .viewport_rect = viewport_rect(), .font_metrics = font_metrics, .root_font_metrics = m_root_element_font_metrics }, - .tree_counting_function_resolution_context = tree_counting_function_resolution_context + .abstract_element = abstract_element }; // NOTE: This doesn't necessarily return the specified value if we reach into computed_properties but that @@ -2062,11 +2061,9 @@ void StyleComputer::compute_font(ComputedProperties& style, Optionalcomputed_properties()->font_size() : InitialValues::font_size(); auto inherited_math_depth = inheritance_parent_has_computed_properties ? inheritance_parent->computed_properties()->math_depth() : InitialValues::math_depth(); - auto tree_counting_function_resolution_context = abstract_element.map([](auto abstract_element) { return abstract_element.tree_counting_function_resolution_context(); }).value_or({ .sibling_count = 1, .sibling_index = 1 }); - ComputationContext font_computation_context { .length_resolution_context = inheritance_parent_has_computed_properties ? Length::ResolutionContext::for_element(inheritance_parent.value()) : Length::ResolutionContext::for_window(*m_document->window()), - .tree_counting_function_resolution_context = tree_counting_function_resolution_context + .abstract_element = abstract_element }; auto const& font_size_specified_value = style.property(PropertyID::FontSize, ComputedProperties::WithAnimationsApplied::No); @@ -2129,7 +2126,7 @@ void StyleComputer::compute_font(ComputedProperties& style, Optional(abstract_element->element()) ? line_height_font_metrics : m_root_element_font_metrics, }, - .tree_counting_function_resolution_context = tree_counting_function_resolution_context + .abstract_element = abstract_element }; auto const& line_height_specified_value = style.property(CSS::PropertyID::LineHeight, ComputedProperties::WithAnimationsApplied::No); @@ -2206,7 +2203,7 @@ void StyleComputer::compute_property_values(ComputedProperties& style, Optional< .font_metrics = font_metrics, .root_font_metrics = m_root_element_font_metrics, }, - .tree_counting_function_resolution_context = abstract_element.map([](auto abstract_element) { return abstract_element.tree_counting_function_resolution_context(); }).value_or({ .sibling_count = 1, .sibling_index = 1 }) + .abstract_element = abstract_element }; // NOTE: This doesn't necessarily return the specified value if we have already computed this property but that diff --git a/Libraries/LibWeb/CSS/StyleValues/ComputationContext.h b/Libraries/LibWeb/CSS/StyleValues/ComputationContext.h index 5410f6e4ac5..935504a5b3d 100644 --- a/Libraries/LibWeb/CSS/StyleValues/ComputationContext.h +++ b/Libraries/LibWeb/CSS/StyleValues/ComputationContext.h @@ -7,17 +7,13 @@ #pragma once #include +#include namespace Web::CSS { -struct TreeCountingFunctionResolutionContext { - size_t sibling_count; - size_t sibling_index; -}; - struct ComputationContext { Length::ResolutionContext length_resolution_context; - Optional tree_counting_function_resolution_context {}; + Optional abstract_element {}; }; } diff --git a/Libraries/LibWeb/CSS/StyleValues/TreeCountingFunctionStyleValue.cpp b/Libraries/LibWeb/CSS/StyleValues/TreeCountingFunctionStyleValue.cpp index edba0944ff1..408aa3093b1 100644 --- a/Libraries/LibWeb/CSS/StyleValues/TreeCountingFunctionStyleValue.cpp +++ b/Libraries/LibWeb/CSS/StyleValues/TreeCountingFunctionStyleValue.cpp @@ -23,10 +23,12 @@ String TreeCountingFunctionStyleValue::to_string(SerializationMode) const VERIFY_NOT_REACHED(); } -size_t TreeCountingFunctionStyleValue::resolve(TreeCountingFunctionResolutionContext const& tree_counting_function_resolution_context, PropertyComputationDependencies& property_computation_dependencies) const +size_t TreeCountingFunctionStyleValue::resolve(DOM::AbstractElement const& abstract_element, PropertyComputationDependencies& property_computation_dependencies) const { property_computation_dependencies.tree_counting_function = true; + auto tree_counting_function_resolution_context = abstract_element.tree_counting_function_resolution_context(); + switch (m_function) { case TreeCountingFunction::SiblingCount: return tree_counting_function_resolution_context.sibling_count; @@ -39,20 +41,20 @@ size_t TreeCountingFunctionStyleValue::resolve(TreeCountingFunctionResolutionCon RefPtr TreeCountingFunctionStyleValue::resolve_to_calculation_node(CalculationContext const& calculation_context, CalculationResolutionContext const& calculation_resolution_context, PropertyComputationDependencies* property_computation_dependencies) const { - if (!calculation_resolution_context.tree_counting_function_resolution_context.has_value()) + if (!calculation_resolution_context.abstract_element.has_value()) return nullptr; VERIFY(property_computation_dependencies); - return NumericCalculationNode::create(Number { Number::Type::Number, static_cast(resolve(calculation_resolution_context.tree_counting_function_resolution_context.value(), *property_computation_dependencies)) }, calculation_context); + return NumericCalculationNode::create(Number { Number::Type::Number, static_cast(resolve(calculation_resolution_context.abstract_element.value(), *property_computation_dependencies)) }, calculation_context); } ValueComparingNonnullRefPtr TreeCountingFunctionStyleValue::absolutized(ComputationContext const& computation_context, PropertyComputationDependencies& property_computation_dependencies) const { // FIXME: We should clamp this value in case it falls outside the valid range for the context it is in - VERIFY(computation_context.tree_counting_function_resolution_context.has_value()); + VERIFY(computation_context.abstract_element.has_value()); - size_t value = resolve(computation_context.tree_counting_function_resolution_context.value(), property_computation_dependencies); + size_t value = resolve(computation_context.abstract_element.value(), property_computation_dependencies); switch (m_computed_type) { case ComputedType::Integer: diff --git a/Libraries/LibWeb/CSS/StyleValues/TreeCountingFunctionStyleValue.h b/Libraries/LibWeb/CSS/StyleValues/TreeCountingFunctionStyleValue.h index 3cc3b0dc2c1..75d31014748 100644 --- a/Libraries/LibWeb/CSS/StyleValues/TreeCountingFunctionStyleValue.h +++ b/Libraries/LibWeb/CSS/StyleValues/TreeCountingFunctionStyleValue.h @@ -30,7 +30,7 @@ public: virtual String to_string(SerializationMode) const override; - size_t resolve(TreeCountingFunctionResolutionContext const&, PropertyComputationDependencies&) const; + size_t resolve(DOM::AbstractElement const&, PropertyComputationDependencies&) const; virtual RefPtr resolve_to_calculation_node(CalculationContext const&, CalculationResolutionContext const&, PropertyComputationDependencies*) const override; virtual ValueComparingNonnullRefPtr absolutized(ComputationContext const&, PropertyComputationDependencies&) const override; diff --git a/Libraries/LibWeb/DOM/AbstractElement.cpp b/Libraries/LibWeb/DOM/AbstractElement.cpp index 25365eed142..c18ca8e1d33 100644 --- a/Libraries/LibWeb/DOM/AbstractElement.cpp +++ b/Libraries/LibWeb/DOM/AbstractElement.cpp @@ -27,7 +27,7 @@ Document& AbstractElement::document() const return m_element->document(); } -CSS::TreeCountingFunctionResolutionContext AbstractElement::tree_counting_function_resolution_context() const +AbstractElement::TreeCountingFunctionResolutionContext AbstractElement::tree_counting_function_resolution_context() const { // FIXME: When used on an element-backed pseudo-element which is also a real element, the tree counting functions // resolve for that real element. For other pseudo elements, they resolve as if they were resolved against diff --git a/Libraries/LibWeb/DOM/AbstractElement.h b/Libraries/LibWeb/DOM/AbstractElement.h index 691b4639ed3..2d5cfd7b8b1 100644 --- a/Libraries/LibWeb/DOM/AbstractElement.h +++ b/Libraries/LibWeb/DOM/AbstractElement.h @@ -27,7 +27,11 @@ public: GC::Ptr layout_node(); GC::Ptr layout_node() const { return const_cast(this)->layout_node(); } - CSS::TreeCountingFunctionResolutionContext tree_counting_function_resolution_context() const; + struct TreeCountingFunctionResolutionContext { + size_t sibling_count; + size_t sibling_index; + }; + TreeCountingFunctionResolutionContext tree_counting_function_resolution_context() const; GC::Ptr parent_element() const; Optional element_to_inherit_style_from() const; diff --git a/Libraries/LibWeb/Forward.h b/Libraries/LibWeb/Forward.h index 50fa30038ec..69bbc9acf88 100644 --- a/Libraries/LibWeb/Forward.h +++ b/Libraries/LibWeb/Forward.h @@ -402,7 +402,6 @@ struct CalculationResolutionContext; struct CSSStyleSheetInit; struct GridRepeatParams; struct StyleSheetIdentifier; -struct TreeCountingFunctionResolutionContext; } diff --git a/Libraries/LibWeb/HTML/Canvas/CanvasTextDrawingStyles.h b/Libraries/LibWeb/HTML/Canvas/CanvasTextDrawingStyles.h index 310f0592919..5e6fd77b7d3 100644 --- a/Libraries/LibWeb/HTML/Canvas/CanvasTextDrawingStyles.h +++ b/Libraries/LibWeb/HTML/Canvas/CanvasTextDrawingStyles.h @@ -116,7 +116,7 @@ public: // FIXME: Investigate whether this is the correct resolution context (i.e. whether we should instead use // a font-size of 10px) for OffscreenCanvas auto length_resolution_context = CSS::Length::ResolutionContext::for_window(*document->window()); - Optional tree_counting_function_resolution_context; + Optional abstract_element; if constexpr (SameAs) { // NOTE: The canvas itself is considered the inheritance parent @@ -127,16 +127,15 @@ public: inherited_font_size = canvas_element.computed_properties()->font_size(); inherited_font_weight = canvas_element.computed_properties()->font_weight(); - DOM::AbstractElement abstract_element { canvas_element }; + abstract_element = DOM::AbstractElement { canvas_element }; - length_resolution_context = CSS::Length::ResolutionContext::for_element(abstract_element); - tree_counting_function_resolution_context = abstract_element.tree_counting_function_resolution_context(); + length_resolution_context = CSS::Length::ResolutionContext::for_element(abstract_element.value()); } } CSS::ComputationContext computation_context { .length_resolution_context = length_resolution_context, - .tree_counting_function_resolution_context = tree_counting_function_resolution_context + .abstract_element = abstract_element }; // FIXME: Should font be recomputed on canvas element style change?