diff --git a/Libraries/LibWeb/CMakeLists.txt b/Libraries/LibWeb/CMakeLists.txt index 28cfa5721ac..e363ffe592e 100644 --- a/Libraries/LibWeb/CMakeLists.txt +++ b/Libraries/LibWeb/CMakeLists.txt @@ -211,6 +211,7 @@ set(SOURCES CSS/VisualViewport.cpp DOM/AbortController.cpp DOM/AbortSignal.cpp + DOM/AbstractElement.cpp DOM/AbstractRange.cpp DOM/AccessibilityTreeNode.cpp DOM/AdoptedStyleSheets.cpp diff --git a/Libraries/LibWeb/CSS/CSSStyleDeclaration.h b/Libraries/LibWeb/CSS/CSSStyleDeclaration.h index 7b4f63eddab..b3e69b3578f 100644 --- a/Libraries/LibWeb/CSS/CSSStyleDeclaration.h +++ b/Libraries/LibWeb/CSS/CSSStyleDeclaration.h @@ -11,7 +11,7 @@ #include #include #include -#include +#include namespace Web::CSS { @@ -50,8 +50,8 @@ public: void set_parent_rule(GC::Ptr parent) { m_parent_rule = parent; } // https://drafts.csswg.org/cssom/#cssstyledeclaration-owner-node - Optional owner_node() const { return m_owner_node; } - void set_owner_node(Optional owner_node) { m_owner_node = move(owner_node); } + Optional owner_node() const { return m_owner_node; } + void set_owner_node(Optional owner_node) { m_owner_node = move(owner_node); } // https://drafts.csswg.org/cssom/#cssstyledeclaration-updating-flag [[nodiscard]] bool is_updating() const { return m_updating; } @@ -80,7 +80,7 @@ private: GC::Ptr m_parent_rule { nullptr }; // https://drafts.csswg.org/cssom/#cssstyledeclaration-owner-node - Optional m_owner_node {}; + Optional m_owner_node {}; // https://drafts.csswg.org/cssom/#cssstyledeclaration-computed-flag bool m_computed { false }; diff --git a/Libraries/LibWeb/CSS/CSSStyleProperties.cpp b/Libraries/LibWeb/CSS/CSSStyleProperties.cpp index 98a7eda5d91..6f680e442bf 100644 --- a/Libraries/LibWeb/CSS/CSSStyleProperties.cpp +++ b/Libraries/LibWeb/CSS/CSSStyleProperties.cpp @@ -44,7 +44,7 @@ GC::Ref CSSStyleProperties::create(JS::Realm& realm, Vector< return realm.create(realm, Computed::No, Readonly::No, convert_declarations_to_specified_order(properties), move(custom_properties), OptionalNone {}); } -GC::Ref CSSStyleProperties::create_resolved_style(JS::Realm& realm, Optional element_reference) +GC::Ref CSSStyleProperties::create_resolved_style(JS::Realm& realm, Optional element_reference) { // https://drafts.csswg.org/cssom/#dom-window-getcomputedstyle // 6. Return a live CSSStyleProperties object with the following properties: @@ -57,7 +57,7 @@ GC::Ref CSSStyleProperties::create_resolved_style(JS::Realm& return realm.create(realm, Computed::Yes, Readonly::Yes, Vector {}, HashMap {}, move(element_reference)); } -GC::Ref CSSStyleProperties::create_element_inline_style(DOM::ElementReference element_reference, Vector properties, HashMap custom_properties) +GC::Ref CSSStyleProperties::create_element_inline_style(DOM::AbstractElement element_reference, Vector properties, HashMap custom_properties) { // https://drafts.csswg.org/cssom/#dom-elementcssinlinestyle-style // The style attribute must return a CSS declaration block object whose readonly flag is unset, whose parent CSS @@ -66,7 +66,7 @@ GC::Ref CSSStyleProperties::create_element_inline_style(DOM: return realm.create(realm, Computed::No, Readonly::No, convert_declarations_to_specified_order(properties), move(custom_properties), move(element_reference)); } -CSSStyleProperties::CSSStyleProperties(JS::Realm& realm, Computed computed, Readonly readonly, Vector properties, HashMap custom_properties, Optional owner_node) +CSSStyleProperties::CSSStyleProperties(JS::Realm& realm, Computed computed, Readonly readonly, Vector properties, HashMap custom_properties, Optional owner_node) : CSSStyleDeclaration(realm, computed, readonly) , m_properties(move(properties)) , m_custom_properties(move(custom_properties)) diff --git a/Libraries/LibWeb/CSS/CSSStyleProperties.h b/Libraries/LibWeb/CSS/CSSStyleProperties.h index f2f7da8feca..d29f850ba08 100644 --- a/Libraries/LibWeb/CSS/CSSStyleProperties.h +++ b/Libraries/LibWeb/CSS/CSSStyleProperties.h @@ -22,8 +22,8 @@ class CSSStyleProperties public: [[nodiscard]] static GC::Ref create(JS::Realm&, Vector, HashMap custom_properties); - [[nodiscard]] static GC::Ref create_resolved_style(JS::Realm&, Optional); - [[nodiscard]] static GC::Ref create_element_inline_style(DOM::ElementReference, Vector, HashMap custom_properties); + [[nodiscard]] static GC::Ref create_resolved_style(JS::Realm&, Optional); + [[nodiscard]] static GC::Ref create_element_inline_style(DOM::AbstractElement, Vector, HashMap custom_properties); virtual ~CSSStyleProperties() override = default; virtual void initialize(JS::Realm&) override; @@ -62,7 +62,7 @@ public: virtual CSSStyleProperties& generated_style_properties_to_css_style_properties() override { return *this; } private: - CSSStyleProperties(JS::Realm&, Computed, Readonly, Vector properties, HashMap custom_properties, Optional); + CSSStyleProperties(JS::Realm&, Computed, Readonly, Vector properties, HashMap custom_properties, Optional); static Vector convert_declarations_to_specified_order(Vector&); virtual void visit_edges(Cell::Visitor&) override; diff --git a/Libraries/LibWeb/DOM/AbstractElement.cpp b/Libraries/LibWeb/DOM/AbstractElement.cpp new file mode 100644 index 00000000000..04e211b539f --- /dev/null +++ b/Libraries/LibWeb/DOM/AbstractElement.cpp @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2024-2025, Sam Atkins + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include + +namespace Web::DOM { + +AbstractElement::AbstractElement(GC::Ref element, Optional pseudo_element) + : m_element(element) + , m_pseudo_element(move(pseudo_element)) +{ +} + +void AbstractElement::visit(GC::Cell::Visitor& visitor) const +{ + visitor.visit(m_element); +} + +GC::Ptr AbstractElement::parent_element() const +{ + if (m_pseudo_element.has_value()) + return m_element; + return m_element->parent_element(); +} + +GC::Ptr AbstractElement::computed_properties() const +{ + if (m_pseudo_element.has_value()) + return m_element->pseudo_element_computed_properties(*m_pseudo_element); + return m_element->computed_properties(); +} + +CSS::CountersSet& AbstractElement::ensure_counters_set() +{ + // FIXME: Handle pseudo-elements + return m_element->ensure_counters_set(); +} + +void AbstractElement::set_counters_set(OwnPtr&& counters_set) +{ + // FIXME: Handle pseudo-elements + m_element->set_counters_set(move(counters_set)); +} + +} diff --git a/Libraries/LibWeb/DOM/ElementReference.h b/Libraries/LibWeb/DOM/AbstractElement.h similarity index 56% rename from Libraries/LibWeb/DOM/ElementReference.h rename to Libraries/LibWeb/DOM/AbstractElement.h index 80f656f5da4..ed4d2a22a18 100644 --- a/Libraries/LibWeb/DOM/ElementReference.h +++ b/Libraries/LibWeb/DOM/AbstractElement.h @@ -12,22 +12,22 @@ namespace Web::DOM { -class ElementReference { +// Either an Element or a PseudoElement +class AbstractElement { public: - ElementReference(GC::Ref element, Optional pseudo_element = {}) - : m_element(element) - , m_pseudo_element(move(pseudo_element)) - { - } + AbstractElement(GC::Ref, Optional = {}); Element& element() { return m_element; } Element const& element() const { return m_element; } Optional pseudo_element() const { return m_pseudo_element; } - void visit(GC::Cell::Visitor& visitor) const - { - visitor.visit(m_element); - } + GC::Ptr parent_element() const; + GC::Ptr computed_properties() const; + + CSS::CountersSet& ensure_counters_set(); + void set_counters_set(OwnPtr&&); + + void visit(GC::Cell::Visitor& visitor) const; private: GC::Ref m_element; diff --git a/Libraries/LibWeb/DOM/Element.cpp b/Libraries/LibWeb/DOM/Element.cpp index d725ca80e1a..ba8459875b7 100644 --- a/Libraries/LibWeb/DOM/Element.cpp +++ b/Libraries/LibWeb/DOM/Element.cpp @@ -832,7 +832,7 @@ CSS::RequiredInvalidationAfterStyleChange Element::recompute_inherited_style() GC::Ref Element::resolved_css_values(Optional type) { - auto element_computed_style = CSS::CSSStyleProperties::create_resolved_style(realm(), ElementReference { *this, type }); + auto element_computed_style = CSS::CSSStyleProperties::create_resolved_style(realm(), AbstractElement { *this, type }); auto properties = heap().allocate(); for (auto i = to_underlying(CSS::first_property_id); i <= to_underlying(CSS::last_property_id); ++i) { diff --git a/Libraries/LibWeb/Editing/Internal/Algorithms.cpp b/Libraries/LibWeb/Editing/Internal/Algorithms.cpp index dd8f76ffcb3..68b4b466786 100644 --- a/Libraries/LibWeb/Editing/Internal/Algorithms.cpp +++ b/Libraries/LibWeb/Editing/Internal/Algorithms.cpp @@ -4741,7 +4741,7 @@ Optional> resolved_value(GC::Refrealm(), DOM::ElementReference { static_cast(*element) }); + auto resolved_css_style_declaration = CSS::CSSStyleProperties::create_resolved_style(element->realm(), DOM::AbstractElement { static_cast(*element) }); auto optional_style_property = resolved_css_style_declaration->property(property_id); if (!optional_style_property.has_value()) return {}; diff --git a/Libraries/LibWeb/Forward.h b/Libraries/LibWeb/Forward.h index e41f2b7a9de..45dc4e0dffb 100644 --- a/Libraries/LibWeb/Forward.h +++ b/Libraries/LibWeb/Forward.h @@ -339,6 +339,7 @@ namespace Web::DOM { class AbortController; class AbortSignal; +class AbstractElement; class AbstractRange; class AccessibilityTreeNode; class Attr; diff --git a/Libraries/LibWeb/HTML/Window.cpp b/Libraries/LibWeb/HTML/Window.cpp index 32c220c7a1d..6607cfe2cfb 100644 --- a/Libraries/LibWeb/HTML/Window.cpp +++ b/Libraries/LibWeb/HTML/Window.cpp @@ -1278,7 +1278,7 @@ GC::Ref Window::get_computed_style(DOM::Element& eleme // 1. Let doc be elt’s node document. // 2. Let obj be elt. - Optional object { element }; + Optional object { element }; // 3. If pseudoElt is provided, is not the empty string, and starts with a colon, then: if (pseudo_element.has_value() && pseudo_element.value().starts_with(':')) {