2020-01-18 09:38:21 +01:00
|
|
|
/*
|
2024-10-20 10:37:44 +02:00
|
|
|
* Copyright (c) 2018-2024, Andreas Kling <andreas@ladybird.org>
|
2020-01-18 09:38:21 +01:00
|
|
|
*
|
2021-04-22 01:24:48 -07:00
|
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
2020-01-18 09:38:21 +01:00
|
|
|
*/
|
|
|
|
|
2019-06-15 18:55:47 +02:00
|
|
|
#pragma once
|
|
|
|
|
2019-06-15 22:49:44 +02:00
|
|
|
#include <AK/Badge.h>
|
2024-10-20 10:37:44 +02:00
|
|
|
#include <AK/DistinctNumeric.h>
|
2023-03-18 10:59:48 -04:00
|
|
|
#include <AK/FlyString.h>
|
2024-07-23 21:55:48 +01:00
|
|
|
#include <AK/GenericShorthands.h>
|
2021-06-07 16:32:24 +01:00
|
|
|
#include <AK/JsonObjectSerializer.h>
|
2019-06-21 18:45:35 +02:00
|
|
|
#include <AK/RefPtr.h>
|
2020-07-26 17:16:18 +02:00
|
|
|
#include <AK/TypeCasts.h>
|
2019-06-15 18:55:47 +02:00
|
|
|
#include <AK/Vector.h>
|
2022-12-11 10:56:37 -06:00
|
|
|
#include <LibWeb/DOM/AccessibilityTreeNode.h>
|
2020-03-18 15:22:31 +01:00
|
|
|
#include <LibWeb/DOM/EventTarget.h>
|
2023-09-05 13:07:35 -04:00
|
|
|
#include <LibWeb/DOM/Slottable.h>
|
2022-11-02 19:14:27 -04:00
|
|
|
#include <LibWeb/DOMParsing/XMLSerializer.h>
|
2024-05-04 14:47:04 +01:00
|
|
|
#include <LibWeb/TraversalDecision.h>
|
2022-09-25 17:03:42 +01:00
|
|
|
#include <LibWeb/WebIDL/ExceptionOr.h>
|
2019-06-15 18:55:47 +02:00
|
|
|
|
2020-07-26 19:37:56 +02:00
|
|
|
namespace Web::DOM {
|
2020-03-07 10:27:02 +01:00
|
|
|
|
2021-03-06 17:06:25 +00:00
|
|
|
enum class NodeType : u16 {
|
2019-06-15 18:55:47 +02:00
|
|
|
INVALID = 0,
|
|
|
|
ELEMENT_NODE = 1,
|
2021-03-06 17:06:25 +00:00
|
|
|
ATTRIBUTE_NODE = 2,
|
2019-06-15 18:55:47 +02:00
|
|
|
TEXT_NODE = 3,
|
2021-03-06 17:06:25 +00:00
|
|
|
CDATA_SECTION_NODE = 4,
|
|
|
|
ENTITY_REFERENCE_NODE = 5,
|
|
|
|
ENTITY_NODE = 6,
|
|
|
|
PROCESSING_INSTRUCTION_NODE = 7,
|
2019-10-12 23:26:47 +02:00
|
|
|
COMMENT_NODE = 8,
|
2019-06-15 18:55:47 +02:00
|
|
|
DOCUMENT_NODE = 9,
|
2019-10-09 20:17:01 +02:00
|
|
|
DOCUMENT_TYPE_NODE = 10,
|
2019-11-06 20:27:53 +01:00
|
|
|
DOCUMENT_FRAGMENT_NODE = 11,
|
2021-03-06 17:06:25 +00:00
|
|
|
NOTATION_NODE = 12
|
2019-06-15 18:55:47 +02:00
|
|
|
};
|
|
|
|
|
2023-02-05 11:21:59 -06:00
|
|
|
enum class NameOrDescription {
|
|
|
|
Name,
|
|
|
|
Description
|
|
|
|
};
|
|
|
|
|
2021-10-16 03:04:55 +01:00
|
|
|
struct GetRootNodeOptions {
|
|
|
|
bool composed { false };
|
|
|
|
};
|
|
|
|
|
2024-04-09 14:44:58 +02:00
|
|
|
enum class FragmentSerializationMode {
|
|
|
|
Inner,
|
|
|
|
Outer,
|
|
|
|
};
|
|
|
|
|
2024-11-01 21:11:32 +09:00
|
|
|
enum class IsDescendant {
|
|
|
|
No,
|
|
|
|
Yes,
|
|
|
|
};
|
|
|
|
|
2024-12-19 23:21:48 +09:00
|
|
|
enum class ShouldComputeRole {
|
|
|
|
No,
|
|
|
|
Yes,
|
|
|
|
};
|
|
|
|
|
2024-09-04 10:01:08 +02:00
|
|
|
#define ENUMERATE_STYLE_INVALIDATION_REASONS(X) \
|
2024-11-06 18:00:18 +01:00
|
|
|
X(ActiveElementChange) \
|
2024-09-04 10:01:08 +02:00
|
|
|
X(AdoptedStyleSheetsList) \
|
|
|
|
X(CSSFontLoaded) \
|
|
|
|
X(CSSImportRule) \
|
2024-11-06 15:49:22 +01:00
|
|
|
X(CustomElementStateChange) \
|
2024-09-04 10:01:08 +02:00
|
|
|
X(DidLoseFocus) \
|
|
|
|
X(DidReceiveFocus) \
|
|
|
|
X(EditingInsertion) \
|
|
|
|
X(ElementAttributeChange) \
|
|
|
|
X(ElementSetShadowRoot) \
|
2024-11-06 18:00:18 +01:00
|
|
|
X(FocusedElementChange) \
|
|
|
|
X(HTMLHyperlinkElementHrefChange) \
|
2024-12-23 17:51:10 +01:00
|
|
|
X(HTMLIFrameElementGeometryChange) \
|
2024-09-04 10:01:08 +02:00
|
|
|
X(HTMLInputElementSetChecked) \
|
|
|
|
X(HTMLObjectElementUpdateLayoutAndChildObjects) \
|
2025-01-03 14:46:24 +01:00
|
|
|
X(HTMLOptionElementSelectedChange) \
|
2024-09-04 10:01:08 +02:00
|
|
|
X(HTMLSelectElementSetIsOpen) \
|
|
|
|
X(Hover) \
|
|
|
|
X(MediaQueryChangedMatchState) \
|
|
|
|
X(NavigableSetViewportSize) \
|
|
|
|
X(NodeInsertBefore) \
|
|
|
|
X(NodeRemove) \
|
|
|
|
X(NodeSetTextContent) \
|
|
|
|
X(Other) \
|
2024-09-22 13:27:02 +02:00
|
|
|
X(ParentOfInsertedNode) \
|
2024-09-04 10:01:08 +02:00
|
|
|
X(SetSelectorText) \
|
|
|
|
X(SettingsChange) \
|
|
|
|
X(StyleSheetDeleteRule) \
|
|
|
|
X(StyleSheetInsertRule) \
|
|
|
|
X(StyleSheetListAddSheet) \
|
2024-11-06 18:00:18 +01:00
|
|
|
X(StyleSheetListRemoveSheet) \
|
|
|
|
X(TargetElementChange)
|
2024-09-04 10:01:08 +02:00
|
|
|
|
|
|
|
enum class StyleInvalidationReason {
|
|
|
|
#define __ENUMERATE_STYLE_INVALIDATION_REASON(reason) reason,
|
|
|
|
ENUMERATE_STYLE_INVALIDATION_REASONS(__ENUMERATE_STYLE_INVALIDATION_REASON)
|
|
|
|
#undef __ENUMERATE_STYLE_INVALIDATION_REASON
|
|
|
|
};
|
|
|
|
|
2022-08-28 13:42:07 +02:00
|
|
|
class Node : public EventTarget {
|
|
|
|
WEB_PLATFORM_OBJECT(Node, EventTarget);
|
2020-03-18 15:22:31 +01:00
|
|
|
|
2022-08-28 13:42:07 +02:00
|
|
|
public:
|
2021-02-10 18:22:20 +01:00
|
|
|
ParentNode* parent_or_shadow_host();
|
2022-04-01 20:58:27 +03:00
|
|
|
ParentNode const* parent_or_shadow_host() const { return const_cast<Node*>(this)->parent_or_shadow_host(); }
|
2021-02-10 18:22:20 +01:00
|
|
|
|
2022-11-05 17:06:19 +01:00
|
|
|
Element* parent_or_shadow_host_element();
|
|
|
|
Element const* parent_or_shadow_host_element() const { return const_cast<Node*>(this)->parent_or_shadow_host_element(); }
|
|
|
|
|
2019-06-15 18:55:47 +02:00
|
|
|
virtual ~Node();
|
|
|
|
|
|
|
|
NodeType type() const { return m_type; }
|
|
|
|
bool is_element() const { return type() == NodeType::ELEMENT_NODE; }
|
2024-11-19 15:35:31 +01:00
|
|
|
bool is_text() const { return type() == NodeType::TEXT_NODE || type() == NodeType::CDATA_SECTION_NODE; }
|
2024-11-20 11:31:59 +01:00
|
|
|
bool is_exclusive_text() const { return type() == NodeType::TEXT_NODE; }
|
2019-06-15 18:55:47 +02:00
|
|
|
bool is_document() const { return type() == NodeType::DOCUMENT_NODE; }
|
2019-10-09 20:17:01 +02:00
|
|
|
bool is_document_type() const { return type() == NodeType::DOCUMENT_TYPE_NODE; }
|
2019-10-12 23:26:47 +02:00
|
|
|
bool is_comment() const { return type() == NodeType::COMMENT_NODE; }
|
2024-07-23 21:55:48 +01:00
|
|
|
bool is_character_data() const { return first_is_one_of(type(), NodeType::TEXT_NODE, NodeType::COMMENT_NODE, NodeType::CDATA_SECTION_NODE, NodeType::PROCESSING_INSTRUCTION_NODE); }
|
2019-11-06 20:27:53 +01:00
|
|
|
bool is_document_fragment() const { return type() == NodeType::DOCUMENT_FRAGMENT_NODE; }
|
2020-03-25 18:48:10 +01:00
|
|
|
bool is_parent_node() const { return is_element() || is_document() || is_document_fragment(); }
|
2024-03-23 15:46:08 +00:00
|
|
|
bool is_slottable() const { return is_element() || is_text() || is_cdata_section(); }
|
2022-01-31 18:05:54 +00:00
|
|
|
bool is_attribute() const { return type() == NodeType::ATTRIBUTE_NODE; }
|
2022-06-27 21:20:59 +01:00
|
|
|
bool is_cdata_section() const { return type() == NodeType::CDATA_SECTION_NODE; }
|
2022-03-13 17:21:27 +01:00
|
|
|
virtual bool is_shadow_root() const { return false; }
|
2019-06-15 18:55:47 +02:00
|
|
|
|
2021-08-05 10:26:09 +02:00
|
|
|
virtual bool requires_svg_container() const { return false; }
|
|
|
|
virtual bool is_svg_container() const { return false; }
|
2023-05-24 05:41:55 +02:00
|
|
|
virtual bool is_svg_element() const { return false; }
|
2023-08-03 13:26:29 +02:00
|
|
|
virtual bool is_svg_graphics_element() const { return false; }
|
2023-09-23 08:56:49 +12:00
|
|
|
virtual bool is_svg_script_element() const { return false; }
|
2024-08-23 10:42:35 +01:00
|
|
|
virtual bool is_svg_style_element() const { return false; }
|
2022-03-12 16:08:40 +01:00
|
|
|
virtual bool is_svg_svg_element() const { return false; }
|
2023-06-23 02:15:03 +03:00
|
|
|
virtual bool is_svg_use_element() const { return false; }
|
2021-08-05 10:26:09 +02:00
|
|
|
|
2021-09-29 22:23:28 +02:00
|
|
|
bool in_a_document_tree() const;
|
|
|
|
|
2021-03-06 17:06:25 +00:00
|
|
|
// NOTE: This is intended for the JS bindings.
|
|
|
|
u16 node_type() const { return (u16)m_type; }
|
|
|
|
|
2024-12-06 11:41:20 +01:00
|
|
|
bool is_editable() const;
|
|
|
|
bool is_editing_host() const;
|
|
|
|
bool is_editable_or_editing_host() const { return is_editable() || is_editing_host(); }
|
2020-08-02 16:05:59 +02:00
|
|
|
|
2023-07-13 19:54:03 +02:00
|
|
|
virtual bool is_dom_node() const final { return true; }
|
2022-07-27 16:04:31 +02:00
|
|
|
virtual bool is_html_element() const { return false; }
|
2021-10-27 17:58:57 +02:00
|
|
|
virtual bool is_html_html_element() const { return false; }
|
2022-03-02 15:14:38 +01:00
|
|
|
virtual bool is_html_anchor_element() const { return false; }
|
2022-07-27 16:03:43 +02:00
|
|
|
virtual bool is_html_base_element() const { return false; }
|
2023-03-10 21:16:18 +01:00
|
|
|
virtual bool is_html_body_element() const { return false; }
|
|
|
|
virtual bool is_html_input_element() const { return false; }
|
2024-08-23 10:42:35 +01:00
|
|
|
virtual bool is_html_link_element() const { return false; }
|
2023-03-10 21:16:18 +01:00
|
|
|
virtual bool is_html_progress_element() const { return false; }
|
2023-05-07 07:43:21 +02:00
|
|
|
virtual bool is_html_script_element() const { return false; }
|
2024-08-23 10:42:35 +01:00
|
|
|
virtual bool is_html_style_element() const { return false; }
|
2021-09-16 00:52:10 +02:00
|
|
|
virtual bool is_html_template_element() const { return false; }
|
2023-08-22 14:55:10 +02:00
|
|
|
virtual bool is_html_table_element() const { return false; }
|
|
|
|
virtual bool is_html_table_section_element() const { return false; }
|
|
|
|
virtual bool is_html_table_row_element() const { return false; }
|
|
|
|
virtual bool is_html_table_cell_element() const { return false; }
|
2023-09-01 09:55:56 +02:00
|
|
|
virtual bool is_html_br_element() const { return false; }
|
2023-09-09 17:13:41 +02:00
|
|
|
virtual bool is_html_button_element() const { return false; }
|
2023-09-23 13:03:59 +02:00
|
|
|
virtual bool is_html_slot_element() const { return false; }
|
2023-12-24 14:41:33 +01:00
|
|
|
virtual bool is_html_embed_element() const { return false; }
|
|
|
|
virtual bool is_html_object_element() const { return false; }
|
|
|
|
virtual bool is_html_form_element() const { return false; }
|
|
|
|
virtual bool is_html_image_element() const { return false; }
|
2022-12-12 12:20:02 +01:00
|
|
|
virtual bool is_navigable_container() const { return false; }
|
2023-11-21 18:50:09 +00:00
|
|
|
virtual bool is_lazy_loading() const { return false; }
|
2021-09-16 00:52:10 +02:00
|
|
|
|
2024-11-15 04:01:23 +13:00
|
|
|
WebIDL::ExceptionOr<GC::Ref<Node>> pre_insert(GC::Ref<Node>, GC::Ptr<Node>);
|
|
|
|
WebIDL::ExceptionOr<GC::Ref<Node>> pre_remove(GC::Ref<Node>);
|
2021-04-06 19:34:49 +01:00
|
|
|
|
2024-11-15 04:01:23 +13:00
|
|
|
WebIDL::ExceptionOr<GC::Ref<Node>> append_child(GC::Ref<Node>);
|
|
|
|
WebIDL::ExceptionOr<GC::Ref<Node>> remove_child(GC::Ref<Node>);
|
2022-02-21 22:21:59 +01:00
|
|
|
|
2024-11-15 04:01:23 +13:00
|
|
|
void insert_before(GC::Ref<Node> node, GC::Ptr<Node> child, bool suppress_observers = false);
|
2021-04-06 19:34:49 +01:00
|
|
|
void remove(bool suppress_observers = false);
|
|
|
|
void remove_all_children(bool suppress_observers = false);
|
2023-03-30 11:14:26 +02:00
|
|
|
|
|
|
|
enum DocumentPosition : u16 {
|
|
|
|
DOCUMENT_POSITION_EQUAL = 0,
|
|
|
|
DOCUMENT_POSITION_DISCONNECTED = 1,
|
|
|
|
DOCUMENT_POSITION_PRECEDING = 2,
|
|
|
|
DOCUMENT_POSITION_FOLLOWING = 4,
|
|
|
|
DOCUMENT_POSITION_CONTAINS = 8,
|
|
|
|
DOCUMENT_POSITION_CONTAINED_BY = 16,
|
|
|
|
DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = 32,
|
|
|
|
};
|
|
|
|
|
2024-11-15 04:01:23 +13:00
|
|
|
u16 compare_document_position(GC::Ptr<Node> other);
|
2020-06-21 01:00:58 +02:00
|
|
|
|
2024-11-15 04:01:23 +13:00
|
|
|
WebIDL::ExceptionOr<GC::Ref<Node>> replace_child(GC::Ref<Node> node, GC::Ref<Node> child);
|
2021-05-07 00:52:23 +01:00
|
|
|
|
2025-01-03 15:24:30 +00:00
|
|
|
WebIDL::ExceptionOr<GC::Ref<Node>> clone_node(Document* document = nullptr, bool subtree = false, Node* parent = nullptr);
|
|
|
|
WebIDL::ExceptionOr<GC::Ref<Node>> clone_single_node(Document&);
|
|
|
|
WebIDL::ExceptionOr<GC::Ref<Node>> clone_node_binding(bool subtree);
|
2021-04-14 01:25:10 +02:00
|
|
|
|
2021-03-06 17:06:25 +00:00
|
|
|
// NOTE: This is intended for the JS bindings.
|
|
|
|
bool has_child_nodes() const { return has_children(); }
|
2024-11-15 04:01:23 +13:00
|
|
|
GC::Ref<NodeList> child_nodes();
|
|
|
|
Vector<GC::Root<Node>> children_as_vector() const;
|
2021-03-06 17:06:25 +00:00
|
|
|
|
2023-09-17 10:51:43 +12:00
|
|
|
virtual FlyString node_name() const = 0;
|
2019-09-28 22:59:16 +02:00
|
|
|
|
2023-09-17 10:51:43 +12:00
|
|
|
String base_uri() const;
|
2022-04-12 13:20:13 -03:00
|
|
|
|
2024-11-09 23:45:09 +09:00
|
|
|
virtual Optional<String> alternative_text() const;
|
|
|
|
|
2023-09-17 10:51:43 +12:00
|
|
|
String descendant_text_content() const;
|
|
|
|
Optional<String> text_content() const;
|
|
|
|
void set_text_content(Optional<String> const&);
|
2019-09-29 16:22:15 +02:00
|
|
|
|
2024-07-11 21:52:03 +01:00
|
|
|
WebIDL::ExceptionOr<void> normalize();
|
|
|
|
|
2023-09-17 10:51:43 +12:00
|
|
|
Optional<String> node_value() const;
|
|
|
|
void set_node_value(Optional<String> const&);
|
2022-02-18 22:11:43 +00:00
|
|
|
|
2024-11-15 04:01:23 +13:00
|
|
|
GC::Ptr<HTML::Navigable> navigable() const;
|
2023-04-23 00:21:59 +03:00
|
|
|
|
2020-06-25 23:42:08 +02:00
|
|
|
Document& document() { return *m_document; }
|
2022-04-01 20:58:27 +03:00
|
|
|
Document const& document() const { return *m_document; }
|
2019-09-29 11:43:07 +02:00
|
|
|
|
2024-11-15 04:01:23 +13:00
|
|
|
GC::Ptr<Document> owner_document() const;
|
2021-05-02 21:03:50 +01:00
|
|
|
|
2020-07-28 18:20:36 +02:00
|
|
|
const HTML::HTMLAnchorElement* enclosing_link_element() const;
|
|
|
|
const HTML::HTMLElement* enclosing_html_element() const;
|
2023-10-08 11:42:00 +13:00
|
|
|
const HTML::HTMLElement* enclosing_html_element_with_attribute(FlyString const&) const;
|
2019-09-29 12:24:36 +02:00
|
|
|
|
2023-12-03 08:24:04 +13:00
|
|
|
String child_text_content() const;
|
2020-05-24 21:59:24 +02:00
|
|
|
|
2021-09-02 19:27:42 +01:00
|
|
|
Node& root();
|
2022-04-01 20:58:27 +03:00
|
|
|
Node const& root() const
|
2020-11-21 18:32:39 +00:00
|
|
|
{
|
|
|
|
return const_cast<Node*>(this)->root();
|
|
|
|
}
|
|
|
|
|
2021-09-02 19:27:42 +01:00
|
|
|
Node& shadow_including_root();
|
2022-04-01 20:58:27 +03:00
|
|
|
Node const& shadow_including_root() const
|
2020-11-21 18:32:39 +00:00
|
|
|
{
|
|
|
|
return const_cast<Node*>(this)->shadow_including_root();
|
|
|
|
}
|
|
|
|
|
2020-05-24 21:59:24 +02:00
|
|
|
bool is_connected() const;
|
|
|
|
|
2024-04-26 09:29:27 +02:00
|
|
|
[[nodiscard]] bool is_browsing_context_connected() const;
|
|
|
|
|
2020-06-20 22:26:54 +02:00
|
|
|
Node* parent_node() { return parent(); }
|
2022-04-01 20:58:27 +03:00
|
|
|
Node const* parent_node() const { return parent(); }
|
2020-06-20 22:26:54 +02:00
|
|
|
|
|
|
|
Element* parent_element();
|
2022-04-01 20:58:27 +03:00
|
|
|
Element const* parent_element() const;
|
2020-06-20 22:26:54 +02:00
|
|
|
|
2021-04-06 17:58:20 +01:00
|
|
|
virtual void inserted();
|
2024-12-10 19:34:50 +13:00
|
|
|
virtual void post_connection();
|
2024-02-19 02:22:15 +01:00
|
|
|
virtual void removed_from(Node*);
|
2020-07-26 17:16:18 +02:00
|
|
|
virtual void children_changed() { }
|
2021-07-05 05:33:35 +01:00
|
|
|
virtual void adopted_from(Document&) { }
|
2024-06-25 11:06:41 +02:00
|
|
|
virtual WebIDL::ExceptionOr<void> cloned(Node&, bool) { return {}; }
|
2019-09-29 17:40:39 +02:00
|
|
|
|
2022-04-01 20:58:27 +03:00
|
|
|
Layout::Node const* layout_node() const { return m_layout_node; }
|
2020-11-22 15:53:01 +01:00
|
|
|
Layout::Node* layout_node() { return m_layout_node; }
|
2019-10-04 21:05:52 +02:00
|
|
|
|
2023-04-20 16:01:16 +01:00
|
|
|
Painting::PaintableBox const* paintable_box() const;
|
2023-08-07 00:59:23 +02:00
|
|
|
Painting::PaintableBox* paintable_box();
|
2022-03-10 22:46:35 +01:00
|
|
|
Painting::Paintable const* paintable() const;
|
2023-08-19 09:29:04 +02:00
|
|
|
Painting::Paintable* paintable();
|
2022-03-09 23:53:41 +01:00
|
|
|
|
2024-11-15 04:01:23 +13:00
|
|
|
void set_paintable(GC::Ptr<Painting::Paintable>);
|
2024-10-14 16:07:56 +02:00
|
|
|
void clear_paintable();
|
2023-08-19 12:00:42 +02:00
|
|
|
|
2024-11-15 04:01:23 +13:00
|
|
|
void set_layout_node(Badge<Layout::Node>, GC::Ref<Layout::Node>);
|
2023-08-01 08:23:13 +02:00
|
|
|
void detach_layout_node(Badge<Layout::TreeBuilder>);
|
2019-10-04 21:05:52 +02:00
|
|
|
|
2022-04-01 20:58:27 +03:00
|
|
|
virtual bool is_child_allowed(Node const&) const { return true; }
|
2019-10-12 23:26:47 +02:00
|
|
|
|
2019-10-19 18:57:02 +02:00
|
|
|
bool needs_style_update() const { return m_needs_style_update; }
|
2020-12-13 15:19:42 +01:00
|
|
|
void set_needs_style_update(bool);
|
2019-10-19 18:57:02 +02:00
|
|
|
|
2024-12-22 11:59:58 +01:00
|
|
|
bool needs_inherited_style_update() const { return m_needs_inherited_style_update; }
|
|
|
|
void set_needs_inherited_style_update(bool);
|
|
|
|
|
2020-12-14 12:04:30 +01:00
|
|
|
bool child_needs_style_update() const { return m_child_needs_style_update; }
|
|
|
|
void set_child_needs_style_update(bool b) { m_child_needs_style_update = b; }
|
|
|
|
|
2024-09-04 10:01:08 +02:00
|
|
|
void invalidate_style(StyleInvalidationReason);
|
2019-10-14 18:32:02 +02:00
|
|
|
|
2020-06-25 23:42:08 +02:00
|
|
|
void set_document(Badge<Document>, Document&);
|
|
|
|
|
2022-04-01 20:58:27 +03:00
|
|
|
virtual EventTarget* get_parent(Event const&) override;
|
2020-11-21 18:32:39 +00:00
|
|
|
|
2021-01-17 09:34:01 +01:00
|
|
|
template<typename T>
|
|
|
|
bool fast_is() const = delete;
|
|
|
|
|
2024-11-15 04:01:23 +13:00
|
|
|
WebIDL::ExceptionOr<void> ensure_pre_insertion_validity(GC::Ref<Node> node, GC::Ptr<Node> child) const;
|
2021-04-06 19:34:49 +01:00
|
|
|
|
2022-04-01 20:58:27 +03:00
|
|
|
bool is_host_including_inclusive_ancestor_of(Node const&) const;
|
2021-04-06 19:34:49 +01:00
|
|
|
|
2022-03-30 22:28:28 +01:00
|
|
|
bool is_scripting_enabled() const;
|
2021-07-05 03:59:47 +01:00
|
|
|
bool is_scripting_disabled() const;
|
|
|
|
|
2024-11-15 04:01:23 +13:00
|
|
|
bool contains(GC::Ptr<Node>) const;
|
2021-07-05 05:55:02 +01:00
|
|
|
|
2021-06-07 16:32:24 +01:00
|
|
|
// Used for dumping the DOM Tree
|
|
|
|
void serialize_tree_as_json(JsonObjectSerializer<StringBuilder>&) const;
|
|
|
|
|
2021-09-02 02:17:13 +01:00
|
|
|
bool is_shadow_including_descendant_of(Node const&) const;
|
|
|
|
bool is_shadow_including_inclusive_descendant_of(Node const&) const;
|
|
|
|
bool is_shadow_including_ancestor_of(Node const&) const;
|
|
|
|
bool is_shadow_including_inclusive_ancestor_of(Node const&) const;
|
|
|
|
|
2024-10-20 10:37:44 +02:00
|
|
|
[[nodiscard]] UniqueNodeID unique_id() const { return m_unique_id; }
|
|
|
|
static Node* from_unique_id(UniqueNodeID);
|
2021-08-30 15:52:08 +01:00
|
|
|
|
2024-04-09 14:44:58 +02:00
|
|
|
WebIDL::ExceptionOr<String> serialize_fragment(DOMParsing::RequireWellFormed, FragmentSerializationMode = FragmentSerializationMode::Inner) const;
|
2021-09-13 22:42:15 +01:00
|
|
|
|
2024-06-25 20:55:58 +01:00
|
|
|
WebIDL::ExceptionOr<void> unsafely_set_html(Element&, StringView);
|
|
|
|
|
2024-11-15 04:01:23 +13:00
|
|
|
void replace_all(GC::Ptr<Node>);
|
2023-12-03 08:24:04 +13:00
|
|
|
void string_replace_all(String const&);
|
2021-09-06 01:25:58 +01:00
|
|
|
|
2021-09-13 12:49:23 +02:00
|
|
|
bool is_same_node(Node const*) const;
|
2021-09-13 12:54:24 +02:00
|
|
|
bool is_equal_node(Node const*) const;
|
2021-09-13 12:49:23 +02:00
|
|
|
|
2024-11-15 04:01:23 +13:00
|
|
|
GC::Ref<Node> get_root_node(GetRootNodeOptions const& options = {});
|
2021-10-16 03:04:55 +01:00
|
|
|
|
2021-11-02 19:20:57 +01:00
|
|
|
bool is_uninteresting_whitespace_node() const;
|
|
|
|
|
2023-12-03 08:24:04 +13:00
|
|
|
String debug_description() const;
|
2022-02-26 08:18:14 +01:00
|
|
|
|
2022-01-31 18:05:54 +00:00
|
|
|
size_t length() const;
|
|
|
|
|
2023-11-18 11:22:51 +01:00
|
|
|
auto& registered_observer_list() { return m_registered_observer_list; }
|
|
|
|
auto const& registered_observer_list() const { return m_registered_observer_list; }
|
2022-07-11 16:37:51 +01:00
|
|
|
|
2023-11-18 11:22:51 +01:00
|
|
|
void add_registered_observer(RegisteredObserver&);
|
2022-07-11 16:37:51 +01:00
|
|
|
|
2024-11-15 04:01:23 +13:00
|
|
|
void queue_mutation_record(FlyString const& type, Optional<FlyString> const& attribute_name, Optional<FlyString> const& attribute_namespace, Optional<String> const& old_value, Vector<GC::Root<Node>> added_nodes, Vector<GC::Root<Node>> removed_nodes, Node* previous_sibling, Node* next_sibling) const;
|
2022-07-11 16:39:14 +01:00
|
|
|
|
2023-03-29 23:46:18 +01:00
|
|
|
// https://dom.spec.whatwg.org/#concept-shadow-including-inclusive-descendant
|
|
|
|
template<typename Callback>
|
2024-05-04 14:47:04 +01:00
|
|
|
TraversalDecision for_each_shadow_including_inclusive_descendant(Callback);
|
2023-03-29 23:46:18 +01:00
|
|
|
|
2022-07-12 23:13:57 +02:00
|
|
|
// https://dom.spec.whatwg.org/#concept-shadow-including-descendant
|
|
|
|
template<typename Callback>
|
2024-05-04 14:47:04 +01:00
|
|
|
TraversalDecision for_each_shadow_including_descendant(Callback);
|
2022-07-12 23:13:57 +02:00
|
|
|
|
2023-09-05 13:07:35 -04:00
|
|
|
Slottable as_slottable();
|
|
|
|
|
2022-08-28 13:42:07 +02:00
|
|
|
Node* parent() { return m_parent.ptr(); }
|
|
|
|
Node const* parent() const { return m_parent.ptr(); }
|
|
|
|
|
|
|
|
bool has_children() const { return m_first_child; }
|
|
|
|
Node* next_sibling() { return m_next_sibling.ptr(); }
|
|
|
|
Node* previous_sibling() { return m_previous_sibling.ptr(); }
|
|
|
|
Node* first_child() { return m_first_child.ptr(); }
|
|
|
|
Node* last_child() { return m_last_child.ptr(); }
|
|
|
|
Node const* next_sibling() const { return m_next_sibling.ptr(); }
|
|
|
|
Node const* previous_sibling() const { return m_previous_sibling.ptr(); }
|
|
|
|
Node const* first_child() const { return m_first_child.ptr(); }
|
|
|
|
Node const* last_child() const { return m_last_child.ptr(); }
|
|
|
|
|
|
|
|
size_t child_count() const
|
|
|
|
{
|
|
|
|
size_t count = 0;
|
|
|
|
for (auto* child = first_child(); child; child = child->next_sibling())
|
|
|
|
++count;
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
|
|
|
Node* child_at_index(int index)
|
|
|
|
{
|
|
|
|
int count = 0;
|
|
|
|
for (auto* child = first_child(); child; child = child->next_sibling()) {
|
|
|
|
if (count == index)
|
|
|
|
return child;
|
|
|
|
++count;
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
Node const* child_at_index(int index) const
|
|
|
|
{
|
|
|
|
return const_cast<Node*>(this)->child_at_index(index);
|
|
|
|
}
|
|
|
|
|
|
|
|
// https://dom.spec.whatwg.org/#concept-tree-index
|
|
|
|
size_t index() const
|
|
|
|
{
|
|
|
|
// The index of an object is its number of preceding siblings, or 0 if it has none.
|
|
|
|
size_t index = 0;
|
|
|
|
for (auto* node = previous_sibling(); node; node = node->previous_sibling())
|
|
|
|
++index;
|
|
|
|
return index;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool is_ancestor_of(Node const&) const;
|
|
|
|
bool is_inclusive_ancestor_of(Node const&) const;
|
|
|
|
bool is_descendant_of(Node const&) const;
|
|
|
|
bool is_inclusive_descendant_of(Node const&) const;
|
|
|
|
|
|
|
|
bool is_following(Node const&) const;
|
|
|
|
|
|
|
|
Node* next_in_pre_order()
|
|
|
|
{
|
|
|
|
if (first_child())
|
|
|
|
return first_child();
|
|
|
|
Node* node;
|
|
|
|
if (!(node = next_sibling())) {
|
|
|
|
node = parent();
|
|
|
|
while (node && !node->next_sibling())
|
|
|
|
node = node->parent();
|
|
|
|
if (node)
|
|
|
|
node = node->next_sibling();
|
|
|
|
}
|
|
|
|
return node;
|
|
|
|
}
|
|
|
|
|
|
|
|
Node* next_in_pre_order(Node const* stay_within)
|
|
|
|
{
|
|
|
|
if (first_child())
|
|
|
|
return first_child();
|
|
|
|
|
|
|
|
Node* node = static_cast<Node*>(this);
|
|
|
|
Node* next = nullptr;
|
|
|
|
while (!(next = node->next_sibling())) {
|
|
|
|
node = node->parent();
|
|
|
|
if (!node || node == stay_within)
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
return next;
|
|
|
|
}
|
|
|
|
|
|
|
|
Node const* next_in_pre_order() const
|
|
|
|
{
|
|
|
|
return const_cast<Node*>(this)->next_in_pre_order();
|
|
|
|
}
|
|
|
|
|
|
|
|
Node const* next_in_pre_order(Node const* stay_within) const
|
|
|
|
{
|
|
|
|
return const_cast<Node*>(this)->next_in_pre_order(stay_within);
|
|
|
|
}
|
|
|
|
|
|
|
|
Node* previous_in_pre_order()
|
|
|
|
{
|
|
|
|
if (auto* node = previous_sibling()) {
|
|
|
|
while (node->last_child())
|
|
|
|
node = node->last_child();
|
|
|
|
|
|
|
|
return node;
|
|
|
|
}
|
|
|
|
|
|
|
|
return parent();
|
|
|
|
}
|
|
|
|
|
|
|
|
Node const* previous_in_pre_order() const
|
|
|
|
{
|
|
|
|
return const_cast<Node*>(this)->previous_in_pre_order();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool is_before(Node const& other) const
|
|
|
|
{
|
|
|
|
if (this == &other)
|
|
|
|
return false;
|
|
|
|
for (auto* node = this; node; node = node->next_in_pre_order()) {
|
|
|
|
if (node == &other)
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// https://dom.spec.whatwg.org/#concept-tree-preceding (Object A is 'typename U' and Object B is 'this')
|
|
|
|
template<typename U>
|
|
|
|
bool has_preceding_node_of_type_in_tree_order() const
|
|
|
|
{
|
|
|
|
for (auto* node = previous_in_pre_order(); node; node = node->previous_in_pre_order()) {
|
|
|
|
if (is<U>(node))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// https://dom.spec.whatwg.org/#concept-tree-following (Object A is 'typename U' and Object B is 'this')
|
|
|
|
template<typename U>
|
|
|
|
bool has_following_node_of_type_in_tree_order() const
|
|
|
|
{
|
|
|
|
for (auto* node = next_in_pre_order(); node; node = node->next_in_pre_order()) {
|
|
|
|
if (is<U>(node))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename Callback>
|
2024-05-04 14:47:04 +01:00
|
|
|
TraversalDecision for_each_in_inclusive_subtree(Callback callback) const
|
2022-08-28 13:42:07 +02:00
|
|
|
{
|
2024-05-04 14:47:04 +01:00
|
|
|
if (auto decision = callback(static_cast<Node const&>(*this)); decision != TraversalDecision::Continue)
|
|
|
|
return decision;
|
2022-08-28 13:42:07 +02:00
|
|
|
for (auto* child = first_child(); child; child = child->next_sibling()) {
|
2024-05-04 14:47:04 +01:00
|
|
|
if (child->for_each_in_inclusive_subtree(callback) == TraversalDecision::Break)
|
|
|
|
return TraversalDecision::Break;
|
2022-08-28 13:42:07 +02:00
|
|
|
}
|
2024-05-04 14:47:04 +01:00
|
|
|
return TraversalDecision::Continue;
|
2022-08-28 13:42:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
template<typename Callback>
|
2024-05-04 14:47:04 +01:00
|
|
|
TraversalDecision for_each_in_inclusive_subtree(Callback callback)
|
2022-08-28 13:42:07 +02:00
|
|
|
{
|
2024-05-04 14:47:04 +01:00
|
|
|
if (auto decision = callback(static_cast<Node&>(*this)); decision != TraversalDecision::Continue)
|
|
|
|
return decision;
|
2022-08-28 13:42:07 +02:00
|
|
|
for (auto* child = first_child(); child; child = child->next_sibling()) {
|
2024-05-04 14:47:04 +01:00
|
|
|
if (child->for_each_in_inclusive_subtree(callback) == TraversalDecision::Break)
|
|
|
|
return TraversalDecision::Break;
|
2022-08-28 13:42:07 +02:00
|
|
|
}
|
2024-05-04 14:47:04 +01:00
|
|
|
return TraversalDecision::Continue;
|
2022-08-28 13:42:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
template<typename U, typename Callback>
|
2024-05-04 14:47:04 +01:00
|
|
|
TraversalDecision for_each_in_inclusive_subtree_of_type(Callback callback)
|
2022-08-28 13:42:07 +02:00
|
|
|
{
|
2023-02-25 10:44:51 -07:00
|
|
|
if (is<U>(static_cast<Node&>(*this))) {
|
2024-05-04 14:47:04 +01:00
|
|
|
if (auto decision = callback(static_cast<U&>(*this)); decision != TraversalDecision::Continue)
|
|
|
|
return decision;
|
2022-08-28 13:42:07 +02:00
|
|
|
}
|
|
|
|
for (auto* child = first_child(); child; child = child->next_sibling()) {
|
2024-05-04 14:47:04 +01:00
|
|
|
if (child->template for_each_in_inclusive_subtree_of_type<U>(callback) == TraversalDecision::Break)
|
|
|
|
return TraversalDecision::Break;
|
2022-08-28 13:42:07 +02:00
|
|
|
}
|
2024-05-04 14:47:04 +01:00
|
|
|
return TraversalDecision::Continue;
|
2022-08-28 13:42:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
template<typename U, typename Callback>
|
2024-05-04 14:47:04 +01:00
|
|
|
TraversalDecision for_each_in_inclusive_subtree_of_type(Callback callback) const
|
2022-08-28 13:42:07 +02:00
|
|
|
{
|
|
|
|
if (is<U>(static_cast<Node const&>(*this))) {
|
2024-05-04 14:47:04 +01:00
|
|
|
if (auto decision = callback(static_cast<U const&>(*this)); decision != TraversalDecision::Continue)
|
|
|
|
return decision;
|
2022-08-28 13:42:07 +02:00
|
|
|
}
|
|
|
|
for (auto* child = first_child(); child; child = child->next_sibling()) {
|
2024-05-04 14:47:04 +01:00
|
|
|
if (child->template for_each_in_inclusive_subtree_of_type<U>(callback) == TraversalDecision::Break)
|
|
|
|
return TraversalDecision::Break;
|
2022-08-28 13:42:07 +02:00
|
|
|
}
|
2024-05-04 14:47:04 +01:00
|
|
|
return TraversalDecision::Continue;
|
2022-08-28 13:42:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
template<typename Callback>
|
2024-05-04 14:47:04 +01:00
|
|
|
TraversalDecision for_each_in_subtree(Callback callback) const
|
2022-08-28 13:42:07 +02:00
|
|
|
{
|
|
|
|
for (auto* child = first_child(); child; child = child->next_sibling()) {
|
2024-05-04 14:47:04 +01:00
|
|
|
if (child->for_each_in_inclusive_subtree(callback) == TraversalDecision::Break)
|
|
|
|
return TraversalDecision::Break;
|
2022-08-28 13:42:07 +02:00
|
|
|
}
|
2024-05-04 14:47:04 +01:00
|
|
|
return TraversalDecision::Continue;
|
2022-08-28 13:42:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
template<typename Callback>
|
2024-05-04 14:47:04 +01:00
|
|
|
TraversalDecision for_each_in_subtree(Callback callback)
|
2022-08-28 13:42:07 +02:00
|
|
|
{
|
|
|
|
for (auto* child = first_child(); child; child = child->next_sibling()) {
|
2024-05-04 14:47:04 +01:00
|
|
|
if (child->for_each_in_inclusive_subtree(callback) == TraversalDecision::Break)
|
|
|
|
return TraversalDecision::Break;
|
2022-08-28 13:42:07 +02:00
|
|
|
}
|
2024-05-04 14:47:04 +01:00
|
|
|
return TraversalDecision::Continue;
|
2022-08-28 13:42:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
template<typename U, typename Callback>
|
2024-05-04 14:47:04 +01:00
|
|
|
TraversalDecision for_each_in_subtree_of_type(Callback callback)
|
2022-08-28 13:42:07 +02:00
|
|
|
{
|
|
|
|
for (auto* child = first_child(); child; child = child->next_sibling()) {
|
2024-05-04 14:47:04 +01:00
|
|
|
if (child->template for_each_in_inclusive_subtree_of_type<U>(callback) == TraversalDecision::Break)
|
|
|
|
return TraversalDecision::Break;
|
2022-08-28 13:42:07 +02:00
|
|
|
}
|
2024-05-04 14:47:04 +01:00
|
|
|
return TraversalDecision::Continue;
|
2022-08-28 13:42:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
template<typename U, typename Callback>
|
2024-05-04 14:47:04 +01:00
|
|
|
TraversalDecision for_each_in_subtree_of_type(Callback callback) const
|
2022-08-28 13:42:07 +02:00
|
|
|
{
|
|
|
|
for (auto* child = first_child(); child; child = child->next_sibling()) {
|
2024-05-04 14:47:04 +01:00
|
|
|
if (child->template for_each_in_inclusive_subtree_of_type<U>(callback) == TraversalDecision::Break)
|
|
|
|
return TraversalDecision::Break;
|
2022-08-28 13:42:07 +02:00
|
|
|
}
|
2024-05-04 14:47:04 +01:00
|
|
|
return TraversalDecision::Continue;
|
2022-08-28 13:42:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
template<typename Callback>
|
|
|
|
void for_each_child(Callback callback) const
|
|
|
|
{
|
2024-06-04 22:19:15 +02:00
|
|
|
return const_cast<Node*>(this)->for_each_child(move(callback));
|
2022-08-28 13:42:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
template<typename Callback>
|
|
|
|
void for_each_child(Callback callback)
|
|
|
|
{
|
2024-05-04 14:59:52 +01:00
|
|
|
for (auto* node = first_child(); node; node = node->next_sibling()) {
|
|
|
|
if (callback(*node) == IterationDecision::Break)
|
|
|
|
return;
|
|
|
|
}
|
2022-08-28 13:42:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
template<typename U, typename Callback>
|
|
|
|
void for_each_child_of_type(Callback callback)
|
|
|
|
{
|
|
|
|
for (auto* node = first_child(); node; node = node->next_sibling()) {
|
2024-05-04 14:59:52 +01:00
|
|
|
if (is<U>(node)) {
|
|
|
|
if (callback(verify_cast<U>(*node)) == IterationDecision::Break)
|
|
|
|
return;
|
|
|
|
}
|
2022-08-28 13:42:07 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename U, typename Callback>
|
|
|
|
void for_each_child_of_type(Callback callback) const
|
|
|
|
{
|
|
|
|
return const_cast<Node*>(this)->template for_each_child_of_type<U>(move(callback));
|
|
|
|
}
|
|
|
|
|
2024-11-08 15:41:49 +00:00
|
|
|
template<typename U, typename Callback>
|
|
|
|
WebIDL::ExceptionOr<void> for_each_child_of_type_fallible(Callback callback)
|
|
|
|
{
|
|
|
|
for (auto* node = first_child(); node; node = node->next_sibling()) {
|
|
|
|
if (is<U>(node)) {
|
|
|
|
if (TRY(callback(verify_cast<U>(*node))) == IterationDecision::Break)
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
2022-08-28 13:42:07 +02:00
|
|
|
template<typename U>
|
|
|
|
U const* next_sibling_of_type() const
|
|
|
|
{
|
|
|
|
return const_cast<Node*>(this)->template next_sibling_of_type<U>();
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename U>
|
|
|
|
inline U* next_sibling_of_type()
|
|
|
|
{
|
|
|
|
for (auto* sibling = next_sibling(); sibling; sibling = sibling->next_sibling()) {
|
|
|
|
if (is<U>(*sibling))
|
|
|
|
return &verify_cast<U>(*sibling);
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename U>
|
|
|
|
U const* previous_sibling_of_type() const
|
|
|
|
{
|
|
|
|
return const_cast<Node*>(this)->template previous_sibling_of_type<U>();
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename U>
|
|
|
|
U* previous_sibling_of_type()
|
|
|
|
{
|
|
|
|
for (auto* sibling = previous_sibling(); sibling; sibling = sibling->previous_sibling()) {
|
|
|
|
if (is<U>(*sibling))
|
|
|
|
return &verify_cast<U>(*sibling);
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename U>
|
|
|
|
U const* first_child_of_type() const
|
|
|
|
{
|
|
|
|
return const_cast<Node*>(this)->template first_child_of_type<U>();
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename U>
|
|
|
|
U const* last_child_of_type() const
|
|
|
|
{
|
|
|
|
return const_cast<Node*>(this)->template last_child_of_type<U>();
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename U>
|
|
|
|
U* first_child_of_type()
|
|
|
|
{
|
|
|
|
for (auto* child = first_child(); child; child = child->next_sibling()) {
|
|
|
|
if (is<U>(*child))
|
|
|
|
return &verify_cast<U>(*child);
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename U>
|
|
|
|
U* last_child_of_type()
|
|
|
|
{
|
|
|
|
for (auto* child = last_child(); child; child = child->previous_sibling()) {
|
|
|
|
if (is<U>(*child))
|
|
|
|
return &verify_cast<U>(*child);
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename U>
|
|
|
|
bool has_child_of_type() const
|
|
|
|
{
|
|
|
|
return first_child_of_type<U>() != nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename U>
|
|
|
|
U const* first_ancestor_of_type() const
|
|
|
|
{
|
|
|
|
return const_cast<Node*>(this)->template first_ancestor_of_type<U>();
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename U>
|
|
|
|
U* first_ancestor_of_type()
|
|
|
|
{
|
|
|
|
for (auto* ancestor = parent(); ancestor; ancestor = ancestor->parent()) {
|
|
|
|
if (is<U>(*ancestor))
|
|
|
|
return &verify_cast<U>(*ancestor);
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2023-05-28 18:27:35 +01:00
|
|
|
template<typename U>
|
|
|
|
U const* shadow_including_first_ancestor_of_type() const
|
|
|
|
{
|
|
|
|
return const_cast<Node*>(this)->template shadow_including_first_ancestor_of_type<U>();
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename U>
|
|
|
|
U* shadow_including_first_ancestor_of_type();
|
|
|
|
|
2022-08-28 13:42:07 +02:00
|
|
|
bool is_parent_of(Node const& other) const
|
|
|
|
{
|
|
|
|
for (auto* child = first_child(); child; child = child->next_sibling()) {
|
|
|
|
if (&other == child)
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2024-12-19 23:21:48 +09:00
|
|
|
ErrorOr<String> accessible_name(Document const&, ShouldComputeRole = ShouldComputeRole::Yes) const;
|
2023-02-05 11:21:59 -06:00
|
|
|
ErrorOr<String> accessible_description(Document const&) const;
|
|
|
|
|
2024-07-14 22:50:38 +01:00
|
|
|
Optional<String> locate_a_namespace(Optional<String> const& prefix) const;
|
|
|
|
Optional<String> lookup_namespace_uri(Optional<String> prefix) const;
|
2024-07-27 12:51:36 -06:00
|
|
|
Optional<String> lookup_prefix(Optional<String> namespace_) const;
|
2024-07-17 14:42:45 +01:00
|
|
|
bool is_default_namespace(Optional<String> namespace_) const;
|
2024-07-14 22:50:38 +01:00
|
|
|
|
2019-06-15 18:55:47 +02:00
|
|
|
protected:
|
2022-08-28 13:42:07 +02:00
|
|
|
Node(JS::Realm&, Document&, NodeType);
|
2019-09-29 11:43:07 +02:00
|
|
|
Node(Document&, NodeType);
|
2019-06-15 18:55:47 +02:00
|
|
|
|
2025-01-03 15:24:30 +00:00
|
|
|
void set_document(Document&);
|
|
|
|
|
2022-08-28 13:42:07 +02:00
|
|
|
virtual void visit_edges(Cell::Visitor&) override;
|
2022-10-20 19:30:29 +02:00
|
|
|
virtual void finalize() override;
|
2022-08-28 13:42:07 +02:00
|
|
|
|
2024-11-15 04:01:23 +13:00
|
|
|
GC::Ptr<Document> m_document;
|
|
|
|
GC::Ptr<Layout::Node> m_layout_node;
|
|
|
|
GC::Ptr<Painting::Paintable> m_paintable;
|
2019-06-15 18:55:47 +02:00
|
|
|
NodeType m_type { NodeType::INVALID };
|
2020-12-14 12:04:30 +01:00
|
|
|
bool m_needs_style_update { false };
|
2024-12-22 11:59:58 +01:00
|
|
|
bool m_needs_inherited_style_update { false };
|
2020-12-14 12:04:30 +01:00
|
|
|
bool m_child_needs_style_update { false };
|
2021-08-30 15:52:08 +01:00
|
|
|
|
2024-10-20 10:37:44 +02:00
|
|
|
UniqueNodeID m_unique_id;
|
2022-07-11 16:37:51 +01:00
|
|
|
|
|
|
|
// https://dom.spec.whatwg.org/#registered-observer-list
|
|
|
|
// "Nodes have a strong reference to registered observers in their registered observer list." https://dom.spec.whatwg.org/#garbage-collection
|
2024-11-15 04:01:23 +13:00
|
|
|
OwnPtr<Vector<GC::Ref<RegisteredObserver>>> m_registered_observer_list;
|
2022-07-11 16:39:14 +01:00
|
|
|
|
2023-02-25 10:44:51 -07:00
|
|
|
void build_accessibility_tree(AccessibilityTreeNode& parent);
|
2022-12-11 10:56:37 -06:00
|
|
|
|
2024-12-19 23:21:48 +09:00
|
|
|
ErrorOr<String> name_or_description(NameOrDescription, Document const&, HashTable<UniqueNodeID>&, IsDescendant = IsDescendant::No, ShouldComputeRole = ShouldComputeRole::Yes) const;
|
2023-02-05 11:21:59 -06:00
|
|
|
|
2022-07-11 16:39:14 +01:00
|
|
|
private:
|
2024-11-15 04:01:23 +13:00
|
|
|
void queue_tree_mutation_record(Vector<GC::Root<Node>> added_nodes, Vector<GC::Root<Node>> removed_nodes, Node* previous_sibling, Node* next_sibling);
|
2022-08-28 13:42:07 +02:00
|
|
|
|
2024-11-15 04:01:23 +13:00
|
|
|
void insert_before_impl(GC::Ref<Node>, GC::Ptr<Node> child);
|
|
|
|
void append_child_impl(GC::Ref<Node>);
|
|
|
|
void remove_child_impl(GC::Ref<Node>);
|
2022-08-28 13:42:07 +02:00
|
|
|
|
2023-12-03 08:24:04 +13:00
|
|
|
static Optional<StringView> first_valid_id(StringView, Document const&);
|
2023-02-05 11:21:59 -06:00
|
|
|
|
2024-11-15 04:01:23 +13:00
|
|
|
GC::Ptr<Node> m_parent;
|
|
|
|
GC::Ptr<Node> m_first_child;
|
|
|
|
GC::Ptr<Node> m_last_child;
|
|
|
|
GC::Ptr<Node> m_next_sibling;
|
|
|
|
GC::Ptr<Node> m_previous_sibling;
|
2022-09-21 13:49:31 +02:00
|
|
|
|
2024-11-15 04:01:23 +13:00
|
|
|
GC::Ptr<NodeList> m_child_nodes;
|
2019-06-15 18:55:47 +02:00
|
|
|
};
|
2019-10-06 20:37:39 +02:00
|
|
|
|
2020-03-07 10:27:02 +01:00
|
|
|
}
|
2023-07-13 19:54:03 +02:00
|
|
|
|
|
|
|
template<>
|
|
|
|
inline bool JS::Object::fast_is<Web::DOM::Node>() const { return is_dom_node(); }
|