Skip to content

Commit 444ff6a

Browse files
committed
LibWeb: Store only typed computed values
Reconstruct transient generic workspaces for animation and inherited style updates, then remove durable ComputedProperties storage from elements and pseudo-elements. Return immutable ComputedValues directly from style computation and keep mutable access confined to consuming builders. Handle CSS animations whose effects are temporarily detached by script.
1 parent 14d843a commit 444ff6a

37 files changed

Lines changed: 1379 additions & 1198 deletions

Libraries/LibWeb/Animations/AnimationEffect.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -931,7 +931,12 @@ AnimationUpdateContext::~AnimationUpdateContext()
931931
}
932932

933933
if (invalidation.needs_repaint()) {
934-
target->set_needs_repaint();
934+
if (element.pseudo_element().has_value()) {
935+
if (auto pseudo_element_node = target->pseudo_element_unsafe_layout_node(*element.pseudo_element()); pseudo_element_node && pseudo_element_node->paintable())
936+
pseudo_element_node->paintable()->set_needs_repaint();
937+
} else {
938+
target->set_needs_repaint();
939+
}
935940
}
936941
if (invalidation.needs_stacking_context_tree_rebuild())
937942
element.document().invalidate_stacking_context_tree();

Libraries/LibWeb/Animations/KeyframeEffect.cpp

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -976,15 +976,20 @@ void KeyframeEffect::update_computed_properties(AnimationUpdateContext& context)
976976
target->update_animated_properties({}, pseudo_element_type(), *this, context);
977977
}
978978

979-
void KeyframeEffect::update_computed_properties_for_style(AnimationUpdateContext& context, DOM::AbstractElement abstract_element, CSS::ComputedProperties& computed_properties)
979+
void KeyframeEffect::update_computed_properties_for_style(AnimationUpdateContext& context, DOM::AbstractElement abstract_element)
980980
{
981-
context.elements.ensure(abstract_element, [&abstract_element, &computed_properties] {
982-
auto old_animated_properties = abstract_element.computed_values()->animated_properties_snapshot();
983-
computed_properties.reset_non_inherited_animated_properties({});
984-
return AnimationUpdateContext::ElementData { move(old_animated_properties), computed_properties };
981+
auto& style_computer = abstract_element.element().document().style_computer();
982+
auto& element_data = context.elements.ensure(abstract_element, [&abstract_element, &style_computer] {
983+
auto computed_values = abstract_element.computed_values();
984+
VERIFY(computed_values);
985+
auto old_animated_properties = computed_values->animated_properties_snapshot();
986+
auto computed_properties = style_computer.reconstruct_computed_properties(*computed_values);
987+
computed_properties->reset_non_inherited_animated_properties({});
988+
return AnimationUpdateContext::ElementData { move(old_animated_properties), move(computed_properties) };
985989
});
986990

987-
abstract_element.element().document().style_computer().collect_animation_into(abstract_element, *this, computed_properties);
991+
VERIFY(element_data.target_style);
992+
style_computer.collect_animation_into(abstract_element, *this, *element_data.target_style);
988993
}
989994

990995
Bindings::CompositeOperation css_animation_composition_to_bindings_composite_operation(CSS::AnimationComposition composition)

Libraries/LibWeb/Animations/KeyframeEffect.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ class KeyframeEffect final : public AnimationEffect {
107107
virtual bool is_keyframe_effect() const override { return true; }
108108

109109
virtual void update_computed_properties(AnimationUpdateContext&) override;
110-
void update_computed_properties_for_style(AnimationUpdateContext&, DOM::AbstractElement, CSS::ComputedProperties&);
110+
void update_computed_properties_for_style(AnimationUpdateContext&, DOM::AbstractElement);
111111

112112
private:
113113
KeyframeEffect(JS::Realm&);

Libraries/LibWeb/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ set(SOURCES
9393
CSS/CascadedProperties.cpp
9494
CSS/Clip.cpp
9595
CSS/ComputedProperties.cpp
96+
CSS/ComputedValues.cpp
9697
CSS/ContainerQuery.cpp
9798
CSS/CountersSet.cpp
9899
CSS/CounterStyle.cpp

Libraries/LibWeb/CSS/CSSStyleProperties.cpp

Lines changed: 14 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -572,10 +572,10 @@ static void ensure_pseudo_element_style_for_cssom(DOM::AbstractElement abstract_
572572

573573
bool did_change_custom_properties = false;
574574
auto style = style_computer.compute_pseudo_element_style_if_needed(abstract_element, did_change_custom_properties);
575-
if (style.has_value())
576-
abstract_element.element().set_computed_style(*pseudo_element, move(style->properties), move(style->values));
575+
if (style)
576+
abstract_element.element().set_computed_style(*pseudo_element, move(style));
577577
else
578-
abstract_element.element().set_computed_style(*pseudo_element, nullptr, nullptr);
578+
abstract_element.element().set_computed_style(*pseudo_element, nullptr);
579579
}
580580

581581
Optional<StyleProperty> CSSStyleProperties::get_direct_property(PropertyNameAndID const& property_name_and_id) const
@@ -680,31 +680,22 @@ Optional<StyleProperty> CSSStyleProperties::get_direct_property(PropertyNameAndI
680680

681681
if (!layout_node) {
682682
auto computed_values = abstract_element.computed_values();
683-
auto computed_properties = abstract_element.computed_properties();
684-
Optional<StyleComputationResult> transient_style;
683+
RefPtr<ComputedValues const> transient_style;
685684
if (!computed_values) {
686685
// A synthetic pseudo-element without matching rules has no durable style. Seed the ancestor chain
687686
// before this one-off computation so ancestor-dependent selectors still match.
688687
transient_style = abstract_element.document().style_computer().compute_style_with_seeded_ancestors(abstract_element);
689-
computed_values = transient_style->values;
690-
computed_properties = transient_style->properties;
688+
computed_values = transient_style;
691689
}
692690

693691
auto computed_value_for_property = [&](PropertyID computed_property_id) -> NonnullRefPtr<StyleValue const> {
694692
if (property_is_logical_alias(computed_property_id))
695693
computed_property_id = map_logical_alias_to_physical_property(computed_property_id, LogicalAliasMappingContext { computed_values->writing_mode(), computed_values->direction() });
696-
auto computed_value = computed_values->computed_style_value(computed_property_id).release_nonnull();
697-
if (computed_property_id == PropertyID::Color)
698-
return computed_value;
699-
if (computed_properties) {
700-
auto const& generic_value = computed_properties->property(computed_property_id);
701-
// NB: Color keywords need the resolved typed color when there is no layout node.
702-
if (property_accepts_type(computed_property_id, ValueType::Color) && generic_value.is_keyword() && first_is_one_of(generic_value.to_keyword(), Keyword::Auto, Keyword::Currentcolor))
703-
return computed_value;
704-
// NB: Keep the generic value until typed reconstruction is structurally lossless for this property.
705-
if (*computed_value != generic_value)
706-
return generic_value;
694+
if (computed_property_id == PropertyID::BackgroundColor) {
695+
if (auto style_value = computed_values->background_color_style_value(); style_value && !style_value->depends_on_current_color())
696+
return style_value.release_nonnull();
707697
}
698+
auto computed_value = computed_values->computed_style_value(computed_property_id).release_nonnull();
708699
return computed_value;
709700
};
710701

@@ -816,12 +807,7 @@ RefPtr<StyleValue const> CSSStyleProperties::style_value_for_computed_property(L
816807
};
817808

818809
auto get_computed_value = [&element, pseudo_element](PropertyID property_id) -> NonnullRefPtr<StyleValue const> {
819-
auto computed_value = element.computed_values(pseudo_element)->computed_style_value(property_id).release_nonnull();
820-
auto const& generic_value = element.computed_properties(pseudo_element)->property(property_id);
821-
// NB: Keep the generic value until typed reconstruction is structurally lossless for this property.
822-
if (*computed_value != generic_value)
823-
return generic_value;
824-
return computed_value;
810+
return element.computed_values(pseudo_element)->computed_style_value(property_id).release_nonnull();
825811
};
826812

827813
if (property_is_logical_alias(property_id)) {
@@ -855,7 +841,10 @@ RefPtr<StyleValue const> CSSStyleProperties::style_value_for_computed_property(L
855841
// -> A resolved value special case property like color defined in another specification
856842
// The resolved value is the used value.
857843
case PropertyID::BackgroundColor:
858-
return resolve_color_style_value(*get_computed_value(property_id), layout_node.computed_values().background_color(), &layout_node);
844+
return resolve_color_style_value(
845+
*layout_node.computed_values().background_color_style_value(),
846+
layout_node.computed_values().background_color(),
847+
&layout_node);
859848
case PropertyID::BorderBottomColor:
860849
return resolve_color_style_value(*get_computed_value(property_id), layout_node.computed_values().border_bottom().color, &layout_node);
861850
case PropertyID::BorderLeftColor:

0 commit comments

Comments
 (0)