Serenity Operating System
1/*
2 * Copyright (c) 2018-2022, Andreas Kling <kling@serenityos.org>
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#pragma once
8
9#include <AK/Badge.h>
10#include <AK/DeprecatedString.h>
11#include <AK/JsonObjectSerializer.h>
12#include <AK/RefPtr.h>
13#include <AK/TypeCasts.h>
14#include <AK/Vector.h>
15#include <LibWeb/DOM/AccessibilityTreeNode.h>
16#include <LibWeb/DOM/EventTarget.h>
17#include <LibWeb/DOMParsing/XMLSerializer.h>
18#include <LibWeb/WebIDL/ExceptionOr.h>
19
20namespace Web::DOM {
21
22enum class NodeType : u16 {
23 INVALID = 0,
24 ELEMENT_NODE = 1,
25 ATTRIBUTE_NODE = 2,
26 TEXT_NODE = 3,
27 CDATA_SECTION_NODE = 4,
28 ENTITY_REFERENCE_NODE = 5,
29 ENTITY_NODE = 6,
30 PROCESSING_INSTRUCTION_NODE = 7,
31 COMMENT_NODE = 8,
32 DOCUMENT_NODE = 9,
33 DOCUMENT_TYPE_NODE = 10,
34 DOCUMENT_FRAGMENT_NODE = 11,
35 NOTATION_NODE = 12
36};
37
38enum class NameOrDescription {
39 Name,
40 Description
41};
42
43struct GetRootNodeOptions {
44 bool composed { false };
45};
46
47class Node : public EventTarget {
48 WEB_PLATFORM_OBJECT(Node, EventTarget);
49
50public:
51 ParentNode* parent_or_shadow_host();
52 ParentNode const* parent_or_shadow_host() const { return const_cast<Node*>(this)->parent_or_shadow_host(); }
53
54 Element* parent_or_shadow_host_element();
55 Element const* parent_or_shadow_host_element() const { return const_cast<Node*>(this)->parent_or_shadow_host_element(); }
56
57 virtual ~Node();
58
59 NodeType type() const { return m_type; }
60 bool is_element() const { return type() == NodeType::ELEMENT_NODE; }
61 bool is_text() const { return type() == NodeType::TEXT_NODE; }
62 bool is_document() const { return type() == NodeType::DOCUMENT_NODE; }
63 bool is_document_type() const { return type() == NodeType::DOCUMENT_TYPE_NODE; }
64 bool is_comment() const { return type() == NodeType::COMMENT_NODE; }
65 bool is_character_data() const { return type() == NodeType::TEXT_NODE || type() == NodeType::COMMENT_NODE; }
66 bool is_document_fragment() const { return type() == NodeType::DOCUMENT_FRAGMENT_NODE; }
67 bool is_parent_node() const { return is_element() || is_document() || is_document_fragment(); }
68 bool is_slottable() const { return is_element() || is_text(); }
69 bool is_attribute() const { return type() == NodeType::ATTRIBUTE_NODE; }
70 bool is_cdata_section() const { return type() == NodeType::CDATA_SECTION_NODE; }
71 virtual bool is_shadow_root() const { return false; }
72
73 virtual bool requires_svg_container() const { return false; }
74 virtual bool is_svg_container() const { return false; }
75 virtual bool is_svg_svg_element() const { return false; }
76
77 bool in_a_document_tree() const;
78
79 // NOTE: This is intended for the JS bindings.
80 u16 node_type() const { return (u16)m_type; }
81
82 virtual bool is_editable() const;
83
84 virtual bool is_html_element() const { return false; }
85 virtual bool is_html_html_element() const { return false; }
86 virtual bool is_html_anchor_element() const { return false; }
87 virtual bool is_html_base_element() const { return false; }
88 virtual bool is_html_body_element() const { return false; }
89 virtual bool is_html_input_element() const { return false; }
90 virtual bool is_html_progress_element() const { return false; }
91 virtual bool is_html_template_element() const { return false; }
92 virtual bool is_browsing_context_container() const { return false; }
93
94 WebIDL::ExceptionOr<JS::NonnullGCPtr<Node>> pre_insert(JS::NonnullGCPtr<Node>, JS::GCPtr<Node>);
95 WebIDL::ExceptionOr<JS::NonnullGCPtr<Node>> pre_remove(JS::NonnullGCPtr<Node>);
96
97 WebIDL::ExceptionOr<JS::NonnullGCPtr<Node>> append_child(JS::NonnullGCPtr<Node>);
98 WebIDL::ExceptionOr<JS::NonnullGCPtr<Node>> remove_child(JS::NonnullGCPtr<Node>);
99
100 void insert_before(JS::NonnullGCPtr<Node> node, JS::GCPtr<Node> child, bool suppress_observers = false);
101 void remove(bool suppress_observers = false);
102 void remove_all_children(bool suppress_observers = false);
103 u16 compare_document_position(JS::GCPtr<Node> other);
104
105 WebIDL::ExceptionOr<JS::NonnullGCPtr<Node>> replace_child(JS::NonnullGCPtr<Node> node, JS::NonnullGCPtr<Node> child);
106
107 JS::NonnullGCPtr<Node> clone_node(Document* document = nullptr, bool clone_children = false);
108 WebIDL::ExceptionOr<JS::NonnullGCPtr<Node>> clone_node_binding(bool deep);
109
110 // NOTE: This is intended for the JS bindings.
111 bool has_child_nodes() const { return has_children(); }
112 JS::NonnullGCPtr<NodeList> child_nodes();
113 Vector<JS::Handle<Node>> children_as_vector() const;
114
115 virtual DeprecatedFlyString node_name() const = 0;
116
117 DeprecatedString base_uri() const;
118
119 DeprecatedString descendant_text_content() const;
120 DeprecatedString text_content() const;
121 void set_text_content(DeprecatedString const&);
122
123 DeprecatedString node_value() const;
124 void set_node_value(DeprecatedString const&);
125
126 Document& document() { return *m_document; }
127 Document const& document() const { return *m_document; }
128
129 JS::GCPtr<Document> owner_document() const;
130
131 const HTML::HTMLAnchorElement* enclosing_link_element() const;
132 const HTML::HTMLElement* enclosing_html_element() const;
133 const HTML::HTMLElement* enclosing_html_element_with_attribute(DeprecatedFlyString const&) const;
134
135 DeprecatedString child_text_content() const;
136
137 Node& root();
138 Node const& root() const
139 {
140 return const_cast<Node*>(this)->root();
141 }
142
143 Node& shadow_including_root();
144 Node const& shadow_including_root() const
145 {
146 return const_cast<Node*>(this)->shadow_including_root();
147 }
148
149 bool is_connected() const;
150
151 Node* parent_node() { return parent(); }
152 Node const* parent_node() const { return parent(); }
153
154 Element* parent_element();
155 Element const* parent_element() const;
156
157 virtual void inserted();
158 virtual void removed_from(Node*) { }
159 virtual void children_changed() { }
160 virtual void adopted_from(Document&) { }
161 virtual void cloned(Node&, bool) {};
162
163 Layout::Node const* layout_node() const { return m_layout_node; }
164 Layout::Node* layout_node() { return m_layout_node; }
165
166 Painting::PaintableBox const* paint_box() const;
167 Painting::Paintable const* paintable() const;
168
169 void set_layout_node(Badge<Layout::Node>, JS::NonnullGCPtr<Layout::Node>);
170 void detach_layout_node(Badge<DOM::Document>);
171
172 virtual bool is_child_allowed(Node const&) const { return true; }
173
174 bool needs_style_update() const { return m_needs_style_update; }
175 void set_needs_style_update(bool);
176
177 bool child_needs_style_update() const { return m_child_needs_style_update; }
178 void set_child_needs_style_update(bool b) { m_child_needs_style_update = b; }
179
180 void invalidate_style();
181
182 void set_document(Badge<Document>, Document&);
183
184 virtual EventTarget* get_parent(Event const&) override;
185
186 template<typename T>
187 bool fast_is() const = delete;
188
189 WebIDL::ExceptionOr<void> ensure_pre_insertion_validity(JS::NonnullGCPtr<Node> node, JS::GCPtr<Node> child) const;
190
191 bool is_host_including_inclusive_ancestor_of(Node const&) const;
192
193 bool is_scripting_enabled() const;
194 bool is_scripting_disabled() const;
195
196 bool contains(JS::GCPtr<Node>) const;
197
198 // Used for dumping the DOM Tree
199 void serialize_tree_as_json(JsonObjectSerializer<StringBuilder>&) const;
200
201 bool is_shadow_including_descendant_of(Node const&) const;
202 bool is_shadow_including_inclusive_descendant_of(Node const&) const;
203 bool is_shadow_including_ancestor_of(Node const&) const;
204 bool is_shadow_including_inclusive_ancestor_of(Node const&) const;
205
206 i32 id() const { return m_id; }
207 static Node* from_id(i32 node_id);
208
209 WebIDL::ExceptionOr<DeprecatedString> serialize_fragment(DOMParsing::RequireWellFormed) const;
210
211 void replace_all(JS::GCPtr<Node>);
212 void string_replace_all(DeprecatedString const&);
213
214 bool is_same_node(Node const*) const;
215 bool is_equal_node(Node const*) const;
216
217 JS::NonnullGCPtr<Node> get_root_node(GetRootNodeOptions const& options = {});
218
219 bool is_uninteresting_whitespace_node() const;
220
221 DeprecatedString debug_description() const;
222
223 size_t length() const;
224
225 auto& registered_observers_list() { return m_registered_observer_list; }
226 auto const& registered_observers_list() const { return m_registered_observer_list; }
227
228 void add_registered_observer(RegisteredObserver& registered_observer) { m_registered_observer_list.append(registered_observer); }
229
230 void queue_mutation_record(DeprecatedFlyString const& type, DeprecatedString attribute_name, DeprecatedString attribute_namespace, DeprecatedString old_value, JS::NonnullGCPtr<NodeList> added_nodes, JS::NonnullGCPtr<NodeList> removed_nodes, Node* previous_sibling, Node* next_sibling) const;
231
232 // https://dom.spec.whatwg.org/#concept-shadow-including-descendant
233 template<typename Callback>
234 IterationDecision for_each_shadow_including_descendant(Callback);
235
236 Node* parent() { return m_parent.ptr(); }
237 Node const* parent() const { return m_parent.ptr(); }
238
239 bool has_children() const { return m_first_child; }
240 Node* next_sibling() { return m_next_sibling.ptr(); }
241 Node* previous_sibling() { return m_previous_sibling.ptr(); }
242 Node* first_child() { return m_first_child.ptr(); }
243 Node* last_child() { return m_last_child.ptr(); }
244 Node const* next_sibling() const { return m_next_sibling.ptr(); }
245 Node const* previous_sibling() const { return m_previous_sibling.ptr(); }
246 Node const* first_child() const { return m_first_child.ptr(); }
247 Node const* last_child() const { return m_last_child.ptr(); }
248
249 size_t child_count() const
250 {
251 size_t count = 0;
252 for (auto* child = first_child(); child; child = child->next_sibling())
253 ++count;
254 return count;
255 }
256
257 Node* child_at_index(int index)
258 {
259 int count = 0;
260 for (auto* child = first_child(); child; child = child->next_sibling()) {
261 if (count == index)
262 return child;
263 ++count;
264 }
265 return nullptr;
266 }
267
268 Node const* child_at_index(int index) const
269 {
270 return const_cast<Node*>(this)->child_at_index(index);
271 }
272
273 // https://dom.spec.whatwg.org/#concept-tree-index
274 size_t index() const
275 {
276 // The index of an object is its number of preceding siblings, or 0 if it has none.
277 size_t index = 0;
278 for (auto* node = previous_sibling(); node; node = node->previous_sibling())
279 ++index;
280 return index;
281 }
282
283 Optional<size_t> index_of_child(Node const& search_child)
284 {
285 VERIFY(search_child.parent() == this);
286 size_t index = 0;
287 auto* child = first_child();
288 VERIFY(child);
289
290 do {
291 if (child == &search_child)
292 return index;
293 index++;
294 } while (child && (child = child->next_sibling()));
295 return {};
296 }
297
298 template<typename ChildType>
299 Optional<size_t> index_of_child(Node const& search_child)
300 {
301 VERIFY(search_child.parent() == this);
302 size_t index = 0;
303 auto* child = first_child();
304 VERIFY(child);
305
306 do {
307 if (!is<ChildType>(child))
308 continue;
309 if (child == &search_child)
310 return index;
311 index++;
312 } while (child && (child = child->next_sibling()));
313 return {};
314 }
315
316 bool is_ancestor_of(Node const&) const;
317 bool is_inclusive_ancestor_of(Node const&) const;
318 bool is_descendant_of(Node const&) const;
319 bool is_inclusive_descendant_of(Node const&) const;
320
321 bool is_following(Node const&) const;
322
323 Node* next_in_pre_order()
324 {
325 if (first_child())
326 return first_child();
327 Node* node;
328 if (!(node = next_sibling())) {
329 node = parent();
330 while (node && !node->next_sibling())
331 node = node->parent();
332 if (node)
333 node = node->next_sibling();
334 }
335 return node;
336 }
337
338 Node* next_in_pre_order(Node const* stay_within)
339 {
340 if (first_child())
341 return first_child();
342
343 Node* node = static_cast<Node*>(this);
344 Node* next = nullptr;
345 while (!(next = node->next_sibling())) {
346 node = node->parent();
347 if (!node || node == stay_within)
348 return nullptr;
349 }
350 return next;
351 }
352
353 Node const* next_in_pre_order() const
354 {
355 return const_cast<Node*>(this)->next_in_pre_order();
356 }
357
358 Node const* next_in_pre_order(Node const* stay_within) const
359 {
360 return const_cast<Node*>(this)->next_in_pre_order(stay_within);
361 }
362
363 Node* previous_in_pre_order()
364 {
365 if (auto* node = previous_sibling()) {
366 while (node->last_child())
367 node = node->last_child();
368
369 return node;
370 }
371
372 return parent();
373 }
374
375 Node const* previous_in_pre_order() const
376 {
377 return const_cast<Node*>(this)->previous_in_pre_order();
378 }
379
380 bool is_before(Node const& other) const
381 {
382 if (this == &other)
383 return false;
384 for (auto* node = this; node; node = node->next_in_pre_order()) {
385 if (node == &other)
386 return true;
387 }
388 return false;
389 }
390
391 // https://dom.spec.whatwg.org/#concept-tree-preceding (Object A is 'typename U' and Object B is 'this')
392 template<typename U>
393 bool has_preceding_node_of_type_in_tree_order() const
394 {
395 for (auto* node = previous_in_pre_order(); node; node = node->previous_in_pre_order()) {
396 if (is<U>(node))
397 return true;
398 }
399 return false;
400 }
401
402 // https://dom.spec.whatwg.org/#concept-tree-following (Object A is 'typename U' and Object B is 'this')
403 template<typename U>
404 bool has_following_node_of_type_in_tree_order() const
405 {
406 for (auto* node = next_in_pre_order(); node; node = node->next_in_pre_order()) {
407 if (is<U>(node))
408 return true;
409 }
410 return false;
411 }
412
413 template<typename Callback>
414 IterationDecision for_each_in_inclusive_subtree(Callback callback) const
415 {
416 if (callback(static_cast<Node const&>(*this)) == IterationDecision::Break)
417 return IterationDecision::Break;
418 for (auto* child = first_child(); child; child = child->next_sibling()) {
419 if (child->for_each_in_inclusive_subtree(callback) == IterationDecision::Break)
420 return IterationDecision::Break;
421 }
422 return IterationDecision::Continue;
423 }
424
425 template<typename Callback>
426 IterationDecision for_each_in_inclusive_subtree(Callback callback)
427 {
428 if (callback(static_cast<Node&>(*this)) == IterationDecision::Break)
429 return IterationDecision::Break;
430 for (auto* child = first_child(); child; child = child->next_sibling()) {
431 if (child->for_each_in_inclusive_subtree(callback) == IterationDecision::Break)
432 return IterationDecision::Break;
433 }
434 return IterationDecision::Continue;
435 }
436
437 template<typename U, typename Callback>
438 IterationDecision for_each_in_inclusive_subtree_of_type(Callback callback)
439 {
440 if (is<U>(static_cast<Node&>(*this))) {
441 if (callback(static_cast<U&>(*this)) == IterationDecision::Break)
442 return IterationDecision::Break;
443 }
444 for (auto* child = first_child(); child; child = child->next_sibling()) {
445 if (child->template for_each_in_inclusive_subtree_of_type<U>(callback) == IterationDecision::Break)
446 return IterationDecision::Break;
447 }
448 return IterationDecision::Continue;
449 }
450
451 template<typename U, typename Callback>
452 IterationDecision for_each_in_inclusive_subtree_of_type(Callback callback) const
453 {
454 if (is<U>(static_cast<Node const&>(*this))) {
455 if (callback(static_cast<U const&>(*this)) == IterationDecision::Break)
456 return IterationDecision::Break;
457 }
458 for (auto* child = first_child(); child; child = child->next_sibling()) {
459 if (child->template for_each_in_inclusive_subtree_of_type<U>(callback) == IterationDecision::Break)
460 return IterationDecision::Break;
461 }
462 return IterationDecision::Continue;
463 }
464
465 template<typename Callback>
466 IterationDecision for_each_in_subtree(Callback callback) const
467 {
468 for (auto* child = first_child(); child; child = child->next_sibling()) {
469 if (child->for_each_in_inclusive_subtree(callback) == IterationDecision::Break)
470 return IterationDecision::Break;
471 }
472 return IterationDecision::Continue;
473 }
474
475 template<typename Callback>
476 IterationDecision for_each_in_subtree(Callback callback)
477 {
478 for (auto* child = first_child(); child; child = child->next_sibling()) {
479 if (child->for_each_in_inclusive_subtree(callback) == IterationDecision::Break)
480 return IterationDecision::Break;
481 }
482 return IterationDecision::Continue;
483 }
484
485 template<typename U, typename Callback>
486 IterationDecision for_each_in_subtree_of_type(Callback callback)
487 {
488 for (auto* child = first_child(); child; child = child->next_sibling()) {
489 if (child->template for_each_in_inclusive_subtree_of_type<U>(callback) == IterationDecision::Break)
490 return IterationDecision::Break;
491 }
492 return IterationDecision::Continue;
493 }
494
495 template<typename U, typename Callback>
496 IterationDecision for_each_in_subtree_of_type(Callback callback) const
497 {
498 for (auto* child = first_child(); child; child = child->next_sibling()) {
499 if (child->template for_each_in_inclusive_subtree_of_type<U>(callback) == IterationDecision::Break)
500 return IterationDecision::Break;
501 }
502 return IterationDecision::Continue;
503 }
504
505 template<typename Callback>
506 void for_each_child(Callback callback) const
507 {
508 return const_cast<Node*>(this)->template for_each_child(move(callback));
509 }
510
511 template<typename Callback>
512 void for_each_child(Callback callback)
513 {
514 for (auto* node = first_child(); node; node = node->next_sibling())
515 callback(*node);
516 }
517
518 template<typename U, typename Callback>
519 void for_each_child_of_type(Callback callback)
520 {
521 for (auto* node = first_child(); node; node = node->next_sibling()) {
522 if (is<U>(node))
523 callback(verify_cast<U>(*node));
524 }
525 }
526
527 template<typename U, typename Callback>
528 void for_each_child_of_type(Callback callback) const
529 {
530 return const_cast<Node*>(this)->template for_each_child_of_type<U>(move(callback));
531 }
532
533 template<typename U>
534 U const* next_sibling_of_type() const
535 {
536 return const_cast<Node*>(this)->template next_sibling_of_type<U>();
537 }
538
539 template<typename U>
540 inline U* next_sibling_of_type()
541 {
542 for (auto* sibling = next_sibling(); sibling; sibling = sibling->next_sibling()) {
543 if (is<U>(*sibling))
544 return &verify_cast<U>(*sibling);
545 }
546 return nullptr;
547 }
548
549 template<typename U>
550 U const* previous_sibling_of_type() const
551 {
552 return const_cast<Node*>(this)->template previous_sibling_of_type<U>();
553 }
554
555 template<typename U>
556 U* previous_sibling_of_type()
557 {
558 for (auto* sibling = previous_sibling(); sibling; sibling = sibling->previous_sibling()) {
559 if (is<U>(*sibling))
560 return &verify_cast<U>(*sibling);
561 }
562 return nullptr;
563 }
564
565 template<typename U>
566 U const* first_child_of_type() const
567 {
568 return const_cast<Node*>(this)->template first_child_of_type<U>();
569 }
570
571 template<typename U>
572 U const* last_child_of_type() const
573 {
574 return const_cast<Node*>(this)->template last_child_of_type<U>();
575 }
576
577 template<typename U>
578 U* first_child_of_type()
579 {
580 for (auto* child = first_child(); child; child = child->next_sibling()) {
581 if (is<U>(*child))
582 return &verify_cast<U>(*child);
583 }
584 return nullptr;
585 }
586
587 template<typename U>
588 U* last_child_of_type()
589 {
590 for (auto* child = last_child(); child; child = child->previous_sibling()) {
591 if (is<U>(*child))
592 return &verify_cast<U>(*child);
593 }
594 return nullptr;
595 }
596
597 template<typename U>
598 bool has_child_of_type() const
599 {
600 return first_child_of_type<U>() != nullptr;
601 }
602
603 template<typename U>
604 U const* first_ancestor_of_type() const
605 {
606 return const_cast<Node*>(this)->template first_ancestor_of_type<U>();
607 }
608
609 template<typename U>
610 U* first_ancestor_of_type()
611 {
612 for (auto* ancestor = parent(); ancestor; ancestor = ancestor->parent()) {
613 if (is<U>(*ancestor))
614 return &verify_cast<U>(*ancestor);
615 }
616 return nullptr;
617 }
618
619 bool is_parent_of(Node const& other) const
620 {
621 for (auto* child = first_child(); child; child = child->next_sibling()) {
622 if (&other == child)
623 return true;
624 }
625 return false;
626 }
627
628 ErrorOr<String> accessible_name(Document const&) const;
629 ErrorOr<String> accessible_description(Document const&) const;
630
631protected:
632 Node(JS::Realm&, Document&, NodeType);
633 Node(Document&, NodeType);
634
635 virtual void visit_edges(Cell::Visitor&) override;
636 virtual void finalize() override;
637
638 JS::GCPtr<Document> m_document;
639 JS::GCPtr<Layout::Node> m_layout_node;
640 NodeType m_type { NodeType::INVALID };
641 bool m_needs_style_update { false };
642 bool m_child_needs_style_update { false };
643
644 i32 m_id;
645
646 // https://dom.spec.whatwg.org/#registered-observer-list
647 // "Nodes have a strong reference to registered observers in their registered observer list." https://dom.spec.whatwg.org/#garbage-collection
648 Vector<RegisteredObserver&> m_registered_observer_list;
649
650 void build_accessibility_tree(AccessibilityTreeNode& parent);
651
652 ErrorOr<String> name_or_description(NameOrDescription, Document const&, HashTable<i32>&) const;
653
654private:
655 void queue_tree_mutation_record(JS::NonnullGCPtr<NodeList> added_nodes, JS::NonnullGCPtr<NodeList> removed_nodes, Node* previous_sibling, Node* next_sibling);
656
657 void insert_before_impl(JS::NonnullGCPtr<Node>, JS::GCPtr<Node> child);
658 void append_child_impl(JS::NonnullGCPtr<Node>);
659 void remove_child_impl(JS::NonnullGCPtr<Node>);
660
661 static Optional<StringView> first_valid_id(DeprecatedString const&, Document const&);
662 static ErrorOr<void> append_without_space(StringBuilder, StringView const&);
663 static ErrorOr<void> append_with_space(StringBuilder, StringView const&);
664 static ErrorOr<void> prepend_without_space(StringBuilder, StringView const&);
665 static ErrorOr<void> prepend_with_space(StringBuilder, StringView const&);
666
667 JS::GCPtr<Node> m_parent;
668 JS::GCPtr<Node> m_first_child;
669 JS::GCPtr<Node> m_last_child;
670 JS::GCPtr<Node> m_next_sibling;
671 JS::GCPtr<Node> m_previous_sibling;
672
673 JS::GCPtr<NodeList> m_child_nodes;
674};
675
676}