ladybird/Libraries/LibWeb/DOM/AbstractElement.h
Andreas Kling 2bf1f41805 LibWeb: Make computed properties immutable
Move CSS animation values into a mutable overlay on computed properties
and make base computed style data immutable after construction. Base
style mutation now goes through a builder that is consumed on publish,
so installed styles no longer expose mutation APIs.

Build new base style data for inherited style updates instead of cloning
and mutating installed computed properties. Element-specific computed
style adjustments now run before publication, while animation and
transition updates continue to mutate only the animated overlay.
2026-06-20 23:43:17 +02:00

91 lines
3.2 KiB
C++

/*
* Copyright (c) 2025-2026, Sam Atkins <sam@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <LibGC/Cell.h>
#include <LibWeb/CSS/PseudoElement.h>
#include <LibWeb/Forward.h>
namespace Web::DOM {
// Either an Element or a PseudoElement
// FIXME: Figure out const-correctness for the Element.
class WEB_API AbstractElement {
public:
AbstractElement(GC::Ref<Element>, Optional<CSS::PseudoElement> = {});
AbstractElement(Element const&, Optional<CSS::PseudoElement> = {});
Document& document() const;
Element& element() { return m_element; }
Element const& element() const { return m_element; }
Optional<CSS::PseudoElement> pseudo_element() const { return m_pseudo_element; }
Layout::NodeWithStyle* layout_node();
Layout::NodeWithStyle const* layout_node() const { return const_cast<AbstractElement*>(this)->layout_node(); }
Layout::NodeWithStyle* unsafe_layout_node();
Layout::NodeWithStyle const* unsafe_layout_node() const { return const_cast<AbstractElement*>(this)->unsafe_layout_node(); }
struct TreeCountingFunctionResolutionContext {
size_t sibling_count;
size_t sibling_index;
};
TreeCountingFunctionResolutionContext tree_counting_function_resolution_context() const;
GC::Ptr<Element const> parent_element() const;
Optional<AbstractElement> element_to_inherit_style_from() const;
Optional<AbstractElement> previous_in_tree_order() { return walk_layout_tree(WalkMethod::Previous); }
Optional<AbstractElement> previous_sibling_in_tree_order() { return walk_layout_tree(WalkMethod::PreviousSibling); }
bool is_before(AbstractElement const&) const;
void set_inheritance_override(GC::Ref<Element> element) { m_inheritance_override = element; }
CSS::ComputedProperties const* computed_properties() const;
GC::Ptr<CSS::CSSStyleProperties const> inline_style() const;
void set_custom_property_data(RefPtr<CSS::CustomPropertyData const>);
[[nodiscard]] RefPtr<CSS::CustomPropertyData const> custom_property_data() const;
RefPtr<CSS::StyleValue const> get_custom_property(Utf16FlyString const& name) const;
bool has_non_empty_counters_set() const;
Optional<CSS::CountersSet const&> counters_set() const;
CSS::CountersSet& ensure_counters_set();
void set_counters_set(OwnPtr<CSS::CountersSet>&&);
HashMap<FlyString, GC::Ref<CSS::CSSAnimation>>* css_defined_animations() const;
void set_has_css_defined_animations();
void visit(GC::Cell::Visitor& visitor) const;
String debug_description() const;
bool operator==(AbstractElement const&) const = default;
CSS::StyleScope const& style_scope() const;
private:
enum class WalkMethod : u8 {
Previous,
PreviousSibling,
};
Optional<AbstractElement> walk_layout_tree(WalkMethod);
GC::Ref<Element> m_element;
Optional<CSS::PseudoElement> m_pseudo_element;
GC::Ptr<Element> m_inheritance_override;
};
}
template<>
struct AK::Traits<Web::DOM::AbstractElement> : public DefaultTraits<Web::DOM::AbstractElement> {
static unsigned hash(Web::DOM::AbstractElement const& key)
{
return pair_int_hash(ptr_hash(&key.element()), key.pseudo_element().has_value() ? to_underlying(key.pseudo_element().value()) : -1);
}
};