1use std::borrow::Cow;
8use std::cell::{Cell, LazyCell, UnsafeCell};
9use std::default::Default;
10use std::f64::consts::PI;
11use std::ops::Range;
12use std::slice::from_ref;
13use std::{cmp, fmt, iter};
14
15use app_units::Au;
16use base::id::{BrowsingContextId, PipelineId};
17use bitflags::bitflags;
18use devtools_traits::NodeInfo;
19use dom_struct::dom_struct;
20use embedder_traits::UntrustedNodeAddress;
21use euclid::Point2D;
22use euclid::default::{Rect, Size2D};
23use html5ever::serialize::HtmlSerializer;
24use html5ever::{Namespace, Prefix, QualName, ns, serialize as html_serialize};
25use js::jsapi::JSObject;
26use js::rust::HandleObject;
27use keyboard_types::Modifiers;
28use layout_api::{
29 BoxAreaType, GenericLayoutData, HTMLCanvasData, HTMLMediaData, LayoutElementType,
30 LayoutNodeType, PhysicalSides, QueryMsg, SVGElementData, StyleData, TrustedNodeAddress,
31};
32use libc::{self, c_void, uintptr_t};
33use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
34use net_traits::image_cache::Image;
35use pixels::ImageMetadata;
36use script_bindings::codegen::InheritTypes::DocumentFragmentTypeId;
37use script_traits::DocumentActivity;
38use selectors::matching::{
39 MatchingContext, MatchingForInvalidation, MatchingMode, NeedsSelectorFlags,
40 matches_selector_list,
41};
42use selectors::parser::SelectorList;
43use servo_arc::Arc;
44use servo_config::pref;
45use servo_url::ServoUrl;
46use smallvec::SmallVec;
47use style::attr::AttrValue;
48use style::context::QuirksMode;
49use style::dom::OpaqueNode;
50use style::properties::ComputedValues;
51use style::selector_parser::{PseudoElement, SelectorImpl, SelectorParser};
52use style::stylesheets::{Stylesheet, UrlExtraData};
53use uuid::Uuid;
54use xml5ever::{local_name, serialize as xml_serialize};
55
56use super::types::CDATASection;
57use crate::conversions::Convert;
58use crate::document_loader::DocumentLoader;
59use crate::dom::attr::Attr;
60use crate::dom::bindings::cell::{DomRefCell, Ref, RefMut};
61use crate::dom::bindings::codegen::Bindings::AttrBinding::AttrMethods;
62use crate::dom::bindings::codegen::Bindings::CSSStyleDeclarationBinding::CSSStyleDeclarationMethods;
63use crate::dom::bindings::codegen::Bindings::CharacterDataBinding::CharacterDataMethods;
64use crate::dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods;
65use crate::dom::bindings::codegen::Bindings::ElementBinding::ElementMethods;
66use crate::dom::bindings::codegen::Bindings::HTMLCollectionBinding::HTMLCollectionMethods;
67use crate::dom::bindings::codegen::Bindings::NodeBinding::{
68 GetRootNodeOptions, NodeConstants, NodeMethods,
69};
70use crate::dom::bindings::codegen::Bindings::NodeListBinding::NodeListMethods;
71use crate::dom::bindings::codegen::Bindings::ProcessingInstructionBinding::ProcessingInstructionMethods;
72use crate::dom::bindings::codegen::Bindings::ShadowRootBinding::ShadowRoot_Binding::ShadowRootMethods;
73use crate::dom::bindings::codegen::Bindings::ShadowRootBinding::{
74 ShadowRootMode, SlotAssignmentMode,
75};
76use crate::dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
77use crate::dom::bindings::codegen::UnionTypes::NodeOrString;
78use crate::dom::bindings::conversions::{self, DerivedFrom};
79use crate::dom::bindings::domname::namespace_from_domstring;
80use crate::dom::bindings::error::{Error, ErrorResult, Fallible};
81use crate::dom::bindings::inheritance::{
82 Castable, CharacterDataTypeId, ElementTypeId, EventTargetTypeId, HTMLElementTypeId, NodeTypeId,
83 SVGElementTypeId, SVGGraphicsElementTypeId, TextTypeId,
84};
85use crate::dom::bindings::reflector::{DomObject, DomObjectWrap, reflect_dom_object_with_proto};
86use crate::dom::bindings::root::{Dom, DomRoot, DomSlice, LayoutDom, MutNullableDom, ToLayout};
87use crate::dom::bindings::str::{DOMString, USVString};
88use crate::dom::characterdata::{CharacterData, LayoutCharacterDataHelpers};
89use crate::dom::css::cssstylesheet::CSSStyleSheet;
90use crate::dom::css::stylesheetlist::StyleSheetListOwner;
91use crate::dom::customelementregistry::{CallbackReaction, try_upgrade_element};
92use crate::dom::document::{Document, DocumentSource, HasBrowsingContext, IsHTMLDocument};
93use crate::dom::documentfragment::DocumentFragment;
94use crate::dom::documenttype::DocumentType;
95use crate::dom::element::{
96 AttributeMutationReason, CustomElementCreationMode, Element, ElementCreator, SelectorWrapper,
97};
98use crate::dom::event::{Event, EventBubbles, EventCancelable};
99use crate::dom::eventtarget::EventTarget;
100use crate::dom::globalscope::GlobalScope;
101use crate::dom::html::htmlcanvaselement::{HTMLCanvasElement, LayoutHTMLCanvasElementHelpers};
102use crate::dom::html::htmlcollection::HTMLCollection;
103use crate::dom::html::htmlelement::HTMLElement;
104use crate::dom::html::htmliframeelement::{HTMLIFrameElement, HTMLIFrameElementLayoutMethods};
105use crate::dom::html::htmlimageelement::{HTMLImageElement, LayoutHTMLImageElementHelpers};
106use crate::dom::html::htmlinputelement::{
107 HTMLInputElement, InputType, LayoutHTMLInputElementHelpers,
108};
109use crate::dom::html::htmllinkelement::HTMLLinkElement;
110use crate::dom::html::htmlslotelement::{HTMLSlotElement, Slottable};
111use crate::dom::html::htmlstyleelement::HTMLStyleElement;
112use crate::dom::html::htmltextareaelement::{
113 HTMLTextAreaElement, LayoutHTMLTextAreaElementHelpers,
114};
115use crate::dom::html::htmlvideoelement::{HTMLVideoElement, LayoutHTMLVideoElementHelpers};
116use crate::dom::mutationobserver::{Mutation, MutationObserver, RegisteredObserver};
117use crate::dom::nodelist::NodeList;
118use crate::dom::pointerevent::{PointerEvent, PointerId};
119use crate::dom::processinginstruction::ProcessingInstruction;
120use crate::dom::range::WeakRangeVec;
121use crate::dom::raredata::NodeRareData;
122use crate::dom::servoparser::html::HtmlSerialize;
123use crate::dom::servoparser::{ServoParser, serialize_html_fragment};
124use crate::dom::shadowroot::{IsUserAgentWidget, LayoutShadowRootHelpers, ShadowRoot};
125use crate::dom::svg::svgsvgelement::{LayoutSVGSVGElementHelpers, SVGSVGElement};
126use crate::dom::text::Text;
127use crate::dom::types::KeyboardEvent;
128use crate::dom::virtualmethods::{VirtualMethods, vtable_for};
129use crate::dom::window::Window;
130use crate::script_runtime::CanGc;
131use crate::script_thread::ScriptThread;
132
133#[dom_struct]
139pub struct Node {
140 eventtarget: EventTarget,
142
143 parent_node: MutNullableDom<Node>,
145
146 first_child: MutNullableDom<Node>,
148
149 last_child: MutNullableDom<Node>,
151
152 next_sibling: MutNullableDom<Node>,
154
155 prev_sibling: MutNullableDom<Node>,
157
158 owner_doc: MutNullableDom<Document>,
160
161 rare_data: DomRefCell<Option<Box<NodeRareData>>>,
163
164 children_count: Cell<u32>,
166
167 flags: Cell<NodeFlags>,
169
170 inclusive_descendants_version: Cell<u64>,
172
173 #[no_trace]
176 style_data: DomRefCell<Option<Box<StyleData>>>,
177
178 #[no_trace]
181 layout_data: DomRefCell<Option<Box<GenericLayoutData>>>,
182}
183
184impl fmt::Debug for Node {
185 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
186 if matches!(self.type_id(), NodeTypeId::Element(_)) {
187 let el = self.downcast::<Element>().unwrap();
188 el.fmt(f)
189 } else {
190 write!(f, "[Node({:?})]", self.type_id())
191 }
192 }
193}
194
195#[derive(Clone, Copy, JSTraceable, MallocSizeOf)]
197pub(crate) struct NodeFlags(u16);
198
199bitflags! {
200 impl NodeFlags: u16 {
201 const IS_IN_A_DOCUMENT_TREE = 1 << 0;
205
206 const HAS_DIRTY_DESCENDANTS = 1 << 1;
208
209 const CLICK_IN_PROGRESS = 1 << 2;
212
213 const SEQUENTIALLY_FOCUSABLE = 1 << 3;
216
217 const PARSER_ASSOCIATED_FORM_OWNER = 1 << 6;
222
223 const HAS_SNAPSHOT = 1 << 7;
228
229 const HANDLED_SNAPSHOT = 1 << 8;
231
232 const IS_IN_SHADOW_TREE = 1 << 9;
234
235 const IS_CONNECTED = 1 << 10;
239
240 const HAS_WEIRD_PARSER_INSERTION_MODE = 1 << 11;
243
244 const IS_IN_UA_WIDGET = 1 << 12;
247 }
248}
249
250#[derive(Clone, Copy, MallocSizeOf)]
254enum SuppressObserver {
255 Suppressed,
256 Unsuppressed,
257}
258
259impl Node {
260 fn add_child(&self, new_child: &Node, before: Option<&Node>, can_gc: CanGc) {
264 assert!(new_child.parent_node.get().is_none());
265 assert!(new_child.prev_sibling.get().is_none());
266 assert!(new_child.next_sibling.get().is_none());
267 match before {
268 Some(before) => {
269 assert!(before.parent_node.get().as_deref() == Some(self));
270 let prev_sibling = before.GetPreviousSibling();
271 match prev_sibling {
272 None => {
273 assert!(self.first_child.get().as_deref() == Some(before));
274 self.first_child.set(Some(new_child));
275 },
276 Some(ref prev_sibling) => {
277 prev_sibling.next_sibling.set(Some(new_child));
278 new_child.prev_sibling.set(Some(prev_sibling));
279 },
280 }
281 before.prev_sibling.set(Some(new_child));
282 new_child.next_sibling.set(Some(before));
283 },
284 None => {
285 let last_child = self.GetLastChild();
286 match last_child {
287 None => self.first_child.set(Some(new_child)),
288 Some(ref last_child) => {
289 assert!(last_child.next_sibling.get().is_none());
290 last_child.next_sibling.set(Some(new_child));
291 new_child.prev_sibling.set(Some(last_child));
292 },
293 }
294
295 self.last_child.set(Some(new_child));
296 },
297 }
298
299 new_child.parent_node.set(Some(self));
300 self.children_count.set(self.children_count.get() + 1);
301
302 let parent_is_in_a_document_tree = self.is_in_a_document_tree();
303 let parent_in_shadow_tree = self.is_in_a_shadow_tree();
304 let parent_is_connected = self.is_connected();
305 let parent_is_in_ua_widget = self.is_in_ua_widget();
306
307 let context = BindContext::new(self, IsShadowTree::No);
308
309 for node in new_child.traverse_preorder(ShadowIncluding::No) {
310 if parent_in_shadow_tree {
311 if let Some(shadow_root) = self.containing_shadow_root() {
312 node.set_containing_shadow_root(Some(&*shadow_root));
313 }
314 debug_assert!(node.containing_shadow_root().is_some());
315 }
316 node.set_flag(
317 NodeFlags::IS_IN_A_DOCUMENT_TREE,
318 parent_is_in_a_document_tree,
319 );
320 node.set_flag(NodeFlags::IS_IN_SHADOW_TREE, parent_in_shadow_tree);
321 node.set_flag(NodeFlags::IS_CONNECTED, parent_is_connected);
322 node.set_flag(NodeFlags::IS_IN_UA_WIDGET, parent_is_in_ua_widget);
323
324 debug_assert!(!node.get_flag(NodeFlags::HAS_DIRTY_DESCENDANTS));
326 vtable_for(&node).bind_to_tree(&context, can_gc);
327 }
328 }
329
330 pub(crate) fn unsafely_set_html(
333 target: &Node,
334 context_element: &Element,
335 html: DOMString,
336 can_gc: CanGc,
337 ) {
338 let new_children = ServoParser::parse_html_fragment(context_element, html, true, can_gc);
340
341 let context_document = context_element.owner_document();
344 let fragment = DocumentFragment::new(&context_document, can_gc);
345
346 for child in new_children {
348 fragment
349 .upcast::<Node>()
350 .AppendChild(&child, can_gc)
351 .unwrap();
352 }
353
354 Node::replace_all(Some(fragment.upcast()), target, can_gc);
356 }
357
358 pub(crate) fn clean_up_style_and_layout_data(&self) {
359 self.owner_doc().cancel_animations_for_node(self);
360 self.style_data.borrow_mut().take();
361 self.layout_data.borrow_mut().take();
362 }
363
364 pub(crate) fn complete_remove_subtree(root: &Node, context: &UnbindContext, can_gc: CanGc) {
367 const RESET_FLAGS: NodeFlags = NodeFlags::IS_IN_A_DOCUMENT_TREE
369 .union(NodeFlags::IS_CONNECTED)
370 .union(NodeFlags::HAS_DIRTY_DESCENDANTS)
371 .union(NodeFlags::HAS_SNAPSHOT)
372 .union(NodeFlags::HANDLED_SNAPSHOT);
373
374 for node in root.traverse_preorder(ShadowIncluding::No) {
375 node.set_flag(RESET_FLAGS | NodeFlags::IS_IN_SHADOW_TREE, false);
376
377 if let Some(shadow_root) = node.downcast::<Element>().and_then(Element::shadow_root) {
380 for node in shadow_root
381 .upcast::<Node>()
382 .traverse_preorder(ShadowIncluding::Yes)
383 {
384 node.set_flag(RESET_FLAGS, false);
385 }
386 }
387 }
388
389 let is_parent_connected = context.parent.is_connected();
391 let custom_element_reaction_stack = ScriptThread::custom_element_reaction_stack();
392
393 let cleanup_node = |node: &Node| {
396 node.clean_up_style_and_layout_data();
397
398 vtable_for(node).unbind_from_tree(context, can_gc);
403
404 if is_parent_connected {
406 if let Some(element) = node.as_custom_element() {
407 custom_element_reaction_stack.enqueue_callback_reaction(
408 &element,
409 CallbackReaction::Disconnected,
410 None,
411 );
412 }
413 }
414 };
415
416 for node in root.traverse_preorder(ShadowIncluding::No) {
417 cleanup_node(&node);
418
419 if node.containing_shadow_root().is_some() {
422 node.set_containing_shadow_root(None);
425 }
426
427 if let Some(shadow_root) = node.downcast::<Element>().and_then(Element::shadow_root) {
430 for node in shadow_root
431 .upcast::<Node>()
432 .traverse_preorder(ShadowIncluding::Yes)
433 {
434 cleanup_node(&node);
435 }
436 }
437 }
438 }
439
440 fn remove_child(&self, child: &Node, cached_index: Option<u32>, can_gc: CanGc) {
444 assert!(child.parent_node.get().as_deref() == Some(self));
445 self.note_dirty_descendants();
446
447 let prev_sibling = child.GetPreviousSibling();
448 match prev_sibling {
449 None => {
450 self.first_child.set(child.next_sibling.get().as_deref());
451 },
452 Some(ref prev_sibling) => {
453 prev_sibling
454 .next_sibling
455 .set(child.next_sibling.get().as_deref());
456 },
457 }
458 let next_sibling = child.GetNextSibling();
459 match next_sibling {
460 None => {
461 self.last_child.set(child.prev_sibling.get().as_deref());
462 },
463 Some(ref next_sibling) => {
464 next_sibling
465 .prev_sibling
466 .set(child.prev_sibling.get().as_deref());
467 },
468 }
469
470 let context = UnbindContext::new(
471 self,
472 prev_sibling.as_deref(),
473 next_sibling.as_deref(),
474 cached_index,
475 );
476
477 child.prev_sibling.set(None);
478 child.next_sibling.set(None);
479 child.parent_node.set(None);
480 self.children_count.set(self.children_count.get() - 1);
481
482 Self::complete_remove_subtree(child, &context, can_gc);
483 }
484
485 pub(crate) fn to_untrusted_node_address(&self) -> UntrustedNodeAddress {
486 UntrustedNodeAddress(self.reflector().get_jsobject().get() as *const c_void)
487 }
488
489 pub(crate) fn to_opaque(&self) -> OpaqueNode {
490 OpaqueNode(self.reflector().get_jsobject().get() as usize)
491 }
492
493 pub(crate) fn as_custom_element(&self) -> Option<DomRoot<Element>> {
494 self.downcast::<Element>().and_then(|element| {
495 if element.is_custom() {
496 assert!(element.get_custom_element_definition().is_some());
497 Some(DomRoot::from_ref(element))
498 } else {
499 None
500 }
501 })
502 }
503
504 pub(crate) fn fire_synthetic_pointer_event_not_trusted(&self, name: DOMString, can_gc: CanGc) {
506 let window = self.owner_window();
510
511 let pointer_event = PointerEvent::new(
513 &window, name,
515 EventBubbles::Bubbles, EventCancelable::Cancelable, Some(&window), 0, Point2D::zero(), Point2D::zero(), Point2D::zero(), Modifiers::empty(), 0, 0, None, None, PointerId::NonPointerDevice as i32, 1, 1, 0.5, 0.0, 0, 0, 0, PI / 2.0, 0.0, DOMString::from(""), false, vec![], vec![], can_gc,
542 );
543
544 pointer_event.upcast::<Event>().set_composed(true);
546
547 pointer_event.upcast::<Event>().set_trusted(false);
549
550 pointer_event
553 .upcast::<Event>()
554 .dispatch(self.upcast::<EventTarget>(), false, can_gc);
555 }
556
557 pub(crate) fn parent_directionality(&self) -> String {
558 let mut current = self.GetParentNode();
559
560 loop {
561 match current {
562 Some(node) => {
563 if let Some(directionality) = node
564 .downcast::<HTMLElement>()
565 .and_then(|html_element| html_element.directionality())
566 {
567 return directionality;
568 } else {
569 current = node.GetParentNode();
570 }
571 },
572 None => return "ltr".to_owned(),
573 }
574 }
575 }
576}
577
578pub(crate) struct QuerySelectorIterator {
579 selectors: SelectorList<SelectorImpl>,
580 iterator: TreeIterator,
581}
582
583impl QuerySelectorIterator {
584 fn new(iter: TreeIterator, selectors: SelectorList<SelectorImpl>) -> QuerySelectorIterator {
585 QuerySelectorIterator {
586 selectors,
587 iterator: iter,
588 }
589 }
590}
591
592impl Iterator for QuerySelectorIterator {
593 type Item = DomRoot<Node>;
594
595 fn next(&mut self) -> Option<DomRoot<Node>> {
596 let selectors = &self.selectors;
597
598 self.iterator.by_ref().find_map(|node| {
599 let mut nth_index_cache = Default::default();
602 let mut ctx = MatchingContext::new(
603 MatchingMode::Normal,
604 None,
605 &mut nth_index_cache,
606 node.owner_doc().quirks_mode(),
607 NeedsSelectorFlags::No,
608 MatchingForInvalidation::No,
609 );
610 if let Some(element) = DomRoot::downcast(node) {
611 if matches_selector_list(selectors, &SelectorWrapper::Borrowed(&element), &mut ctx)
612 {
613 return Some(DomRoot::upcast(element));
614 }
615 }
616 None
617 })
618 }
619}
620
621impl Node {
622 fn rare_data(&self) -> Ref<'_, Option<Box<NodeRareData>>> {
623 self.rare_data.borrow()
624 }
625
626 fn ensure_rare_data(&self) -> RefMut<'_, Box<NodeRareData>> {
627 let mut rare_data = self.rare_data.borrow_mut();
628 if rare_data.is_none() {
629 *rare_data = Some(Default::default());
630 }
631 RefMut::map(rare_data, |rare_data| rare_data.as_mut().unwrap())
632 }
633
634 pub(crate) fn is_before(&self, other: &Node) -> bool {
637 let cmp = other.CompareDocumentPosition(self);
638 if cmp & NodeConstants::DOCUMENT_POSITION_DISCONNECTED != 0 {
639 return false;
640 }
641
642 cmp & NodeConstants::DOCUMENT_POSITION_PRECEDING != 0
643 }
644
645 pub(crate) fn registered_mutation_observers_mut(&self) -> RefMut<'_, Vec<RegisteredObserver>> {
648 RefMut::map(self.ensure_rare_data(), |rare_data| {
649 &mut rare_data.mutation_observers
650 })
651 }
652
653 pub(crate) fn registered_mutation_observers(&self) -> Option<Ref<'_, Vec<RegisteredObserver>>> {
654 let rare_data: Ref<'_, _> = self.rare_data.borrow();
655
656 if rare_data.is_none() {
657 return None;
658 }
659 Some(Ref::map(rare_data, |rare_data| {
660 &rare_data.as_ref().unwrap().mutation_observers
661 }))
662 }
663
664 #[cfg_attr(crown, allow(crown::unrooted_must_root))]
666 pub(crate) fn add_mutation_observer(&self, observer: RegisteredObserver) {
667 self.ensure_rare_data().mutation_observers.push(observer);
668 }
669
670 pub(crate) fn remove_mutation_observer(&self, observer: &MutationObserver) {
672 self.ensure_rare_data()
673 .mutation_observers
674 .retain(|reg_obs| &*reg_obs.observer != observer)
675 }
676
677 pub(crate) fn dump(&self) {
679 self.dump_indent(0);
680 }
681
682 pub(crate) fn dump_indent(&self, indent: u32) {
684 let mut s = String::new();
685 for _ in 0..indent {
686 s.push_str(" ");
687 }
688
689 s.push_str(&self.debug_str());
690 debug!("{:?}", s);
691
692 for kid in self.children() {
694 kid.dump_indent(indent + 1)
695 }
696 }
697
698 pub(crate) fn debug_str(&self) -> String {
700 format!("{:?}", self.type_id())
701 }
702
703 pub(crate) fn is_in_a_document_tree(&self) -> bool {
705 self.flags.get().contains(NodeFlags::IS_IN_A_DOCUMENT_TREE)
706 }
707
708 pub(crate) fn is_in_a_shadow_tree(&self) -> bool {
710 self.flags.get().contains(NodeFlags::IS_IN_SHADOW_TREE)
711 }
712
713 pub(crate) fn has_weird_parser_insertion_mode(&self) -> bool {
714 self.flags
715 .get()
716 .contains(NodeFlags::HAS_WEIRD_PARSER_INSERTION_MODE)
717 }
718
719 pub(crate) fn set_weird_parser_insertion_mode(&self) {
720 self.set_flag(NodeFlags::HAS_WEIRD_PARSER_INSERTION_MODE, true)
721 }
722
723 pub(crate) fn is_connected(&self) -> bool {
725 self.flags.get().contains(NodeFlags::IS_CONNECTED)
726 }
727
728 pub(crate) fn set_in_ua_widget(&self, in_ua_widget: bool) {
729 self.set_flag(NodeFlags::IS_IN_UA_WIDGET, in_ua_widget)
730 }
731
732 pub(crate) fn is_in_ua_widget(&self) -> bool {
733 self.flags.get().contains(NodeFlags::IS_IN_UA_WIDGET)
734 }
735
736 pub(crate) fn type_id(&self) -> NodeTypeId {
738 match *self.eventtarget.type_id() {
739 EventTargetTypeId::Node(type_id) => type_id,
740 _ => unreachable!(),
741 }
742 }
743
744 pub(crate) fn len(&self) -> u32 {
746 match self.type_id() {
747 NodeTypeId::DocumentType => 0,
748 NodeTypeId::CharacterData(_) => self.downcast::<CharacterData>().unwrap().Length(),
749 _ => self.children_count(),
750 }
751 }
752
753 pub(crate) fn is_empty(&self) -> bool {
754 self.len() == 0
756 }
757
758 pub(crate) fn index(&self) -> u32 {
760 self.preceding_siblings().count() as u32
761 }
762
763 pub(crate) fn has_parent(&self) -> bool {
765 self.parent_node.get().is_some()
766 }
767
768 pub(crate) fn children_count(&self) -> u32 {
769 self.children_count.get()
770 }
771
772 pub(crate) fn ranges(&self) -> RefMut<'_, WeakRangeVec> {
773 RefMut::map(self.ensure_rare_data(), |rare_data| &mut rare_data.ranges)
774 }
775
776 pub(crate) fn ranges_is_empty(&self) -> bool {
777 self.rare_data()
778 .as_ref()
779 .is_none_or(|data| data.ranges.is_empty())
780 }
781
782 #[inline]
783 pub(crate) fn is_doctype(&self) -> bool {
784 self.type_id() == NodeTypeId::DocumentType
785 }
786
787 pub(crate) fn get_flag(&self, flag: NodeFlags) -> bool {
788 self.flags.get().contains(flag)
789 }
790
791 pub(crate) fn set_flag(&self, flag: NodeFlags, value: bool) {
792 let mut flags = self.flags.get();
793
794 if value {
795 flags.insert(flag);
796 } else {
797 flags.remove(flag);
798 }
799
800 self.flags.set(flags);
801 }
802
803 pub(crate) fn note_dirty_descendants(&self) {
805 self.owner_doc().note_node_with_dirty_descendants(self);
806 }
807
808 pub(crate) fn has_dirty_descendants(&self) -> bool {
809 self.get_flag(NodeFlags::HAS_DIRTY_DESCENDANTS)
810 }
811
812 pub(crate) fn rev_version(&self) {
813 let doc: DomRoot<Node> = DomRoot::upcast(self.owner_doc());
818 let version = cmp::max(
819 self.inclusive_descendants_version(),
820 doc.inclusive_descendants_version(),
821 ) + 1;
822
823 let mut node = &MutNullableDom::new(Some(self));
826 while let Some(p) = node.if_is_some(|p| {
827 p.inclusive_descendants_version.set(version);
828 &p.parent_node
829 }) {
830 node = p
831 }
832 doc.inclusive_descendants_version.set(version);
833 }
834
835 pub(crate) fn dirty(&self, damage: NodeDamage) {
836 self.rev_version();
837 if !self.is_connected() {
838 return;
839 }
840
841 match self.type_id() {
842 NodeTypeId::CharacterData(CharacterDataTypeId::Text(TextTypeId::Text)) => {
843 self.parent_node
847 .get()
848 .unwrap()
849 .dirty(NodeDamage::ContentOrHeritage)
850 },
851 NodeTypeId::Element(_) => self.downcast::<Element>().unwrap().restyle(damage),
852 NodeTypeId::DocumentFragment(DocumentFragmentTypeId::ShadowRoot) => self
853 .downcast::<ShadowRoot>()
854 .unwrap()
855 .Host()
856 .upcast::<Element>()
857 .restyle(damage),
858 _ => {},
859 };
860 }
861
862 pub(crate) fn inclusive_descendants_version(&self) -> u64 {
864 self.inclusive_descendants_version.get()
865 }
866
867 pub(crate) fn traverse_preorder(&self, shadow_including: ShadowIncluding) -> TreeIterator {
869 TreeIterator::new(self, shadow_including)
870 }
871
872 pub(crate) fn inclusively_following_siblings(
873 &self,
874 ) -> impl Iterator<Item = DomRoot<Node>> + use<> {
875 SimpleNodeIterator {
876 current: Some(DomRoot::from_ref(self)),
877 next_node: |n| n.GetNextSibling(),
878 }
879 }
880
881 pub(crate) fn inclusively_preceding_siblings(
882 &self,
883 ) -> impl Iterator<Item = DomRoot<Node>> + use<> {
884 SimpleNodeIterator {
885 current: Some(DomRoot::from_ref(self)),
886 next_node: |n| n.GetPreviousSibling(),
887 }
888 }
889
890 pub(crate) fn common_ancestor(
891 &self,
892 other: &Node,
893 shadow_including: ShadowIncluding,
894 ) -> Option<DomRoot<Node>> {
895 self.inclusive_ancestors(shadow_including).find(|ancestor| {
896 other
897 .inclusive_ancestors(shadow_including)
898 .any(|node| node == *ancestor)
899 })
900 }
901
902 pub(crate) fn common_ancestor_in_flat_tree(&self, other: &Node) -> Option<DomRoot<Node>> {
903 self.inclusive_ancestors_in_flat_tree().find(|ancestor| {
904 other
905 .inclusive_ancestors_in_flat_tree()
906 .any(|node| node == *ancestor)
907 })
908 }
909
910 pub(crate) fn is_inclusive_ancestor_of(&self, child: &Node) -> bool {
911 self == child || self.is_ancestor_of(child)
912 }
913
914 pub(crate) fn is_ancestor_of(&self, child: &Node) -> bool {
915 child.ancestors().any(|ancestor| &*ancestor == self)
916 }
917
918 pub(crate) fn is_shadow_including_inclusive_ancestor_of(&self, node: &Node) -> bool {
919 node.inclusive_ancestors(ShadowIncluding::Yes)
920 .any(|ancestor| &*ancestor == self)
921 }
922
923 pub(crate) fn following_siblings(&self) -> impl Iterator<Item = DomRoot<Node>> + use<> {
924 SimpleNodeIterator {
925 current: self.GetNextSibling(),
926 next_node: |n| n.GetNextSibling(),
927 }
928 }
929
930 pub(crate) fn preceding_siblings(&self) -> impl Iterator<Item = DomRoot<Node>> + use<> {
931 SimpleNodeIterator {
932 current: self.GetPreviousSibling(),
933 next_node: |n| n.GetPreviousSibling(),
934 }
935 }
936
937 pub(crate) fn following_nodes(&self, root: &Node) -> FollowingNodeIterator {
938 FollowingNodeIterator {
939 current: Some(DomRoot::from_ref(self)),
940 root: DomRoot::from_ref(root),
941 }
942 }
943
944 pub(crate) fn preceding_nodes(&self, root: &Node) -> PrecedingNodeIterator {
945 PrecedingNodeIterator {
946 current: Some(DomRoot::from_ref(self)),
947 root: DomRoot::from_ref(root),
948 }
949 }
950
951 pub(crate) fn descending_last_children(&self) -> impl Iterator<Item = DomRoot<Node>> + use<> {
954 SimpleNodeIterator {
955 current: self.GetLastChild(),
956 next_node: |n| n.GetLastChild(),
957 }
958 }
959
960 pub(crate) fn is_parent_of(&self, child: &Node) -> bool {
961 child
962 .parent_node
963 .get()
964 .is_some_and(|parent| &*parent == self)
965 }
966
967 pub(crate) fn to_trusted_node_address(&self) -> TrustedNodeAddress {
968 TrustedNodeAddress(self as *const Node as *const libc::c_void)
969 }
970
971 pub(crate) fn padding(&self) -> Option<PhysicalSides> {
972 self.owner_window().padding_query_without_reflow(self)
973 }
974
975 pub(crate) fn content_box(&self) -> Option<Rect<Au>> {
976 self.owner_window()
977 .box_area_query(self, BoxAreaType::Content, false)
978 }
979
980 pub(crate) fn border_box(&self) -> Option<Rect<Au>> {
981 self.owner_window()
982 .box_area_query(self, BoxAreaType::Border, false)
983 }
984
985 pub(crate) fn padding_box(&self) -> Option<Rect<Au>> {
986 self.owner_window()
987 .box_area_query(self, BoxAreaType::Padding, false)
988 }
989
990 pub(crate) fn border_boxes(&self) -> Vec<Rect<Au>> {
991 self.owner_window()
992 .box_areas_query(self, BoxAreaType::Border)
993 }
994
995 pub(crate) fn client_rect(&self) -> Rect<i32> {
996 self.owner_window().client_rect_query(self)
997 }
998
999 pub(crate) fn scroll_area(&self) -> Rect<i32> {
1002 let document = self.owner_doc();
1004
1005 if !document.is_active() {
1007 return Rect::zero();
1008 }
1009
1010 let window = document.window();
1013 let viewport = Size2D::new(window.InnerWidth(), window.InnerHeight());
1014
1015 let in_quirks_mode = document.quirks_mode() == QuirksMode::Quirks;
1016 let is_root = self.downcast::<Element>().is_some_and(|e| e.is_root());
1017 let is_body_element = self
1018 .downcast::<HTMLElement>()
1019 .is_some_and(|e| e.is_body_element());
1020
1021 if (is_root && !in_quirks_mode) || (is_body_element && in_quirks_mode) {
1027 let viewport_scrolling_area = window.scrolling_area_query(None);
1028 return Rect::new(
1029 viewport_scrolling_area.origin,
1030 viewport_scrolling_area.size.max(viewport),
1031 );
1032 }
1033
1034 window.scrolling_area_query(Some(self))
1038 }
1039
1040 pub(crate) fn before(&self, nodes: Vec<NodeOrString>, can_gc: CanGc) -> ErrorResult {
1042 let parent = &self.parent_node;
1044
1045 let parent = match parent.get() {
1047 None => return Ok(()),
1048 Some(parent) => parent,
1049 };
1050
1051 let viable_previous_sibling = first_node_not_in(self.preceding_siblings(), &nodes);
1053
1054 let node = self
1056 .owner_doc()
1057 .node_from_nodes_and_strings(nodes, can_gc)?;
1058
1059 let viable_previous_sibling = match viable_previous_sibling {
1061 Some(ref viable_previous_sibling) => viable_previous_sibling.next_sibling.get(),
1062 None => parent.first_child.get(),
1063 };
1064
1065 Node::pre_insert(&node, &parent, viable_previous_sibling.as_deref(), can_gc)?;
1067
1068 Ok(())
1069 }
1070
1071 pub(crate) fn after(&self, nodes: Vec<NodeOrString>, can_gc: CanGc) -> ErrorResult {
1073 let parent = &self.parent_node;
1075
1076 let parent = match parent.get() {
1078 None => return Ok(()),
1079 Some(parent) => parent,
1080 };
1081
1082 let viable_next_sibling = first_node_not_in(self.following_siblings(), &nodes);
1084
1085 let node = self
1087 .owner_doc()
1088 .node_from_nodes_and_strings(nodes, can_gc)?;
1089
1090 Node::pre_insert(&node, &parent, viable_next_sibling.as_deref(), can_gc)?;
1092
1093 Ok(())
1094 }
1095
1096 pub(crate) fn replace_with(&self, nodes: Vec<NodeOrString>, can_gc: CanGc) -> ErrorResult {
1098 let Some(parent) = self.GetParentNode() else {
1100 return Ok(());
1102 };
1103
1104 let viable_next_sibling = first_node_not_in(self.following_siblings(), &nodes);
1106
1107 let node = self
1109 .owner_doc()
1110 .node_from_nodes_and_strings(nodes, can_gc)?;
1111
1112 if self.parent_node == Some(&*parent) {
1113 parent.ReplaceChild(&node, self, can_gc)?;
1115 } else {
1116 Node::pre_insert(&node, &parent, viable_next_sibling.as_deref(), can_gc)?;
1118 }
1119 Ok(())
1120 }
1121
1122 pub(crate) fn prepend(&self, nodes: Vec<NodeOrString>, can_gc: CanGc) -> ErrorResult {
1124 let doc = self.owner_doc();
1126 let node = doc.node_from_nodes_and_strings(nodes, can_gc)?;
1127 let first_child = self.first_child.get();
1129 Node::pre_insert(&node, self, first_child.as_deref(), can_gc).map(|_| ())
1130 }
1131
1132 pub(crate) fn append(&self, nodes: Vec<NodeOrString>, can_gc: CanGc) -> ErrorResult {
1134 let doc = self.owner_doc();
1136 let node = doc.node_from_nodes_and_strings(nodes, can_gc)?;
1137 self.AppendChild(&node, can_gc).map(|_| ())
1139 }
1140
1141 pub(crate) fn replace_children(&self, nodes: Vec<NodeOrString>, can_gc: CanGc) -> ErrorResult {
1143 let doc = self.owner_doc();
1145 let node = doc.node_from_nodes_and_strings(nodes, can_gc)?;
1146 Node::ensure_pre_insertion_validity(&node, self, None)?;
1148 Node::replace_all(Some(&node), self, can_gc);
1150 Ok(())
1151 }
1152
1153 pub(crate) fn query_selector(
1155 &self,
1156 selectors: DOMString,
1157 ) -> Fallible<Option<DomRoot<Element>>> {
1158 let doc = self.owner_doc();
1160 match SelectorParser::parse_author_origin_no_namespace(
1161 &selectors.str(),
1162 &UrlExtraData(doc.url().get_arc()),
1163 ) {
1164 Err(_) => Err(Error::Syntax(None)),
1166 Ok(selectors) => {
1168 let mut nth_index_cache = Default::default();
1169 let mut ctx = MatchingContext::new(
1170 MatchingMode::Normal,
1171 None,
1172 &mut nth_index_cache,
1173 doc.quirks_mode(),
1174 NeedsSelectorFlags::No,
1175 MatchingForInvalidation::No,
1176 );
1177 let mut descendants = self.traverse_preorder(ShadowIncluding::No);
1178 assert!(&*descendants.next().unwrap() == self);
1180 Ok(descendants.filter_map(DomRoot::downcast).find(|element| {
1181 matches_selector_list(&selectors, &SelectorWrapper::Borrowed(element), &mut ctx)
1182 }))
1183 },
1184 }
1185 }
1186
1187 pub(crate) fn query_selector_iter(
1192 &self,
1193 selectors: DOMString,
1194 ) -> Fallible<QuerySelectorIterator> {
1195 let url = self.owner_doc().url();
1197 match SelectorParser::parse_author_origin_no_namespace(
1198 &selectors.str(),
1199 &UrlExtraData(url.get_arc()),
1200 ) {
1201 Err(_) => Err(Error::Syntax(None)),
1203 Ok(selectors) => {
1205 let mut descendants = self.traverse_preorder(ShadowIncluding::No);
1206 assert!(&*descendants.next().unwrap() == self);
1208 Ok(QuerySelectorIterator::new(descendants, selectors))
1209 },
1210 }
1211 }
1212
1213 pub(crate) fn query_selector_all(&self, selectors: DOMString) -> Fallible<DomRoot<NodeList>> {
1215 let window = self.owner_window();
1216 let iter = self.query_selector_iter(selectors)?;
1217 Ok(NodeList::new_simple_list(&window, iter, CanGc::note()))
1218 }
1219
1220 pub(crate) fn ancestors(&self) -> impl Iterator<Item = DomRoot<Node>> + use<> {
1221 SimpleNodeIterator {
1222 current: self.GetParentNode(),
1223 next_node: |n| n.GetParentNode(),
1224 }
1225 }
1226
1227 pub(crate) fn inclusive_ancestors(
1229 &self,
1230 shadow_including: ShadowIncluding,
1231 ) -> impl Iterator<Item = DomRoot<Node>> + use<> {
1232 SimpleNodeIterator {
1233 current: Some(DomRoot::from_ref(self)),
1234 next_node: move |n| {
1235 if shadow_including == ShadowIncluding::Yes {
1236 if let Some(shadow_root) = n.downcast::<ShadowRoot>() {
1237 return Some(DomRoot::from_ref(shadow_root.Host().upcast::<Node>()));
1238 }
1239 }
1240 n.GetParentNode()
1241 },
1242 }
1243 }
1244
1245 pub(crate) fn owner_doc(&self) -> DomRoot<Document> {
1246 self.owner_doc.get().unwrap()
1247 }
1248
1249 pub(crate) fn set_owner_doc(&self, document: &Document) {
1250 self.owner_doc.set(Some(document));
1251 }
1252
1253 pub(crate) fn containing_shadow_root(&self) -> Option<DomRoot<ShadowRoot>> {
1254 self.rare_data()
1255 .as_ref()?
1256 .containing_shadow_root
1257 .as_ref()
1258 .map(|sr| DomRoot::from_ref(&**sr))
1259 }
1260
1261 pub(crate) fn set_containing_shadow_root(&self, shadow_root: Option<&ShadowRoot>) {
1262 self.ensure_rare_data().containing_shadow_root = shadow_root.map(Dom::from_ref);
1263 }
1264
1265 pub(crate) fn is_in_html_doc(&self) -> bool {
1266 self.owner_doc().is_html_document()
1267 }
1268
1269 pub(crate) fn is_connected_with_browsing_context(&self) -> bool {
1270 self.is_connected() && self.owner_doc().browsing_context().is_some()
1271 }
1272
1273 pub(crate) fn children(&self) -> impl Iterator<Item = DomRoot<Node>> + use<> {
1274 SimpleNodeIterator {
1275 current: self.GetFirstChild(),
1276 next_node: |n| n.GetNextSibling(),
1277 }
1278 }
1279
1280 pub(crate) fn rev_children(&self) -> impl Iterator<Item = DomRoot<Node>> + use<> {
1281 SimpleNodeIterator {
1282 current: self.GetLastChild(),
1283 next_node: |n| n.GetPreviousSibling(),
1284 }
1285 }
1286
1287 pub(crate) fn child_elements(&self) -> impl Iterator<Item = DomRoot<Element>> + use<> {
1288 self.children()
1289 .filter_map(DomRoot::downcast as fn(_) -> _)
1290 .peekable()
1291 }
1292
1293 pub(crate) fn remove_self(&self, can_gc: CanGc) {
1294 if let Some(ref parent) = self.GetParentNode() {
1295 Node::remove(self, parent, SuppressObserver::Unsuppressed, can_gc);
1296 }
1297 }
1298
1299 pub(crate) fn unique_id(&self, pipeline: PipelineId) -> String {
1300 let mut rare_data = self.ensure_rare_data();
1301
1302 if rare_data.unique_id.is_none() {
1303 let node_id = UniqueId::new();
1304 ScriptThread::save_node_id(pipeline, node_id.borrow().simple().to_string());
1305 rare_data.unique_id = Some(node_id);
1306 }
1307 rare_data
1308 .unique_id
1309 .as_ref()
1310 .unwrap()
1311 .borrow()
1312 .simple()
1313 .to_string()
1314 }
1315
1316 pub(crate) fn summarize(&self, can_gc: CanGc) -> NodeInfo {
1317 let USVString(base_uri) = self.BaseURI();
1318 let node_type = self.NodeType();
1319 let pipeline = self.owner_window().pipeline_id();
1320
1321 let maybe_shadow_root = self.downcast::<ShadowRoot>();
1322 let shadow_root_mode = maybe_shadow_root
1323 .map(ShadowRoot::Mode)
1324 .map(ShadowRootMode::convert);
1325 let host = maybe_shadow_root
1326 .map(ShadowRoot::Host)
1327 .map(|host| host.upcast::<Node>().unique_id(pipeline));
1328 let is_shadow_host = self.downcast::<Element>().is_some_and(|potential_host| {
1329 let Some(root) = potential_host.shadow_root() else {
1330 return false;
1331 };
1332 !root.is_user_agent_widget() || pref!(inspector_show_servo_internal_shadow_roots)
1333 });
1334
1335 let num_children = if is_shadow_host {
1336 self.ChildNodes(can_gc).Length() as usize + 1
1338 } else {
1339 self.ChildNodes(can_gc).Length() as usize
1340 };
1341
1342 let window = self.owner_window();
1343 let display = self
1344 .downcast::<Element>()
1345 .map(|elem| window.GetComputedStyle(elem, None))
1346 .map(|style| style.Display().into());
1347
1348 NodeInfo {
1349 unique_id: self.unique_id(pipeline),
1350 host,
1351 base_uri,
1352 parent: self
1353 .GetParentNode()
1354 .map_or("".to_owned(), |node| node.unique_id(pipeline)),
1355 node_type,
1356 is_top_level_document: node_type == NodeConstants::DOCUMENT_NODE,
1357 node_name: String::from(self.NodeName()),
1358 node_value: self.GetNodeValue().map(|v| v.into()),
1359 num_children,
1360 attrs: self.downcast().map(Element::summarize).unwrap_or(vec![]),
1361 is_shadow_host,
1362 shadow_root_mode,
1363 display,
1364 is_displayed: !self.is_display_none() || self.is::<DocumentType>(),
1368 doctype_name: self
1369 .downcast::<DocumentType>()
1370 .map(DocumentType::name)
1371 .cloned()
1372 .map(String::from),
1373 doctype_public_identifier: self
1374 .downcast::<DocumentType>()
1375 .map(DocumentType::public_id)
1376 .cloned()
1377 .map(String::from),
1378 doctype_system_identifier: self
1379 .downcast::<DocumentType>()
1380 .map(DocumentType::system_id)
1381 .cloned()
1382 .map(String::from),
1383 }
1384 }
1385
1386 pub(crate) fn insert_cell_or_row<F, G, I>(
1388 &self,
1389 index: i32,
1390 get_items: F,
1391 new_child: G,
1392 can_gc: CanGc,
1393 ) -> Fallible<DomRoot<HTMLElement>>
1394 where
1395 F: Fn() -> DomRoot<HTMLCollection>,
1396 G: Fn() -> DomRoot<I>,
1397 I: DerivedFrom<Node> + DerivedFrom<HTMLElement> + DomObject,
1398 {
1399 if index < -1 {
1400 return Err(Error::IndexSize(None));
1401 }
1402
1403 let tr = new_child();
1404
1405 {
1406 let tr_node = tr.upcast::<Node>();
1407 if index == -1 {
1408 self.InsertBefore(tr_node, None, can_gc)?;
1409 } else {
1410 let items = get_items();
1411 let node = match items
1412 .elements_iter()
1413 .map(DomRoot::upcast::<Node>)
1414 .map(Some)
1415 .chain(iter::once(None))
1416 .nth(index as usize)
1417 {
1418 None => return Err(Error::IndexSize(None)),
1419 Some(node) => node,
1420 };
1421 self.InsertBefore(tr_node, node.as_deref(), can_gc)?;
1422 }
1423 }
1424
1425 Ok(DomRoot::upcast::<HTMLElement>(tr))
1426 }
1427
1428 pub(crate) fn delete_cell_or_row<F, G>(
1430 &self,
1431 index: i32,
1432 get_items: F,
1433 is_delete_type: G,
1434 can_gc: CanGc,
1435 ) -> ErrorResult
1436 where
1437 F: Fn() -> DomRoot<HTMLCollection>,
1438 G: Fn(&Element) -> bool,
1439 {
1440 let element = match index {
1441 index if index < -1 => return Err(Error::IndexSize(None)),
1442 -1 => {
1443 let last_child = self.upcast::<Node>().GetLastChild();
1444 match last_child.and_then(|node| {
1445 node.inclusively_preceding_siblings()
1446 .filter_map(DomRoot::downcast::<Element>)
1447 .find(|elem| is_delete_type(elem))
1448 }) {
1449 Some(element) => element,
1450 None => return Ok(()),
1451 }
1452 },
1453 index => match get_items().Item(index as u32) {
1454 Some(element) => element,
1455 None => return Err(Error::IndexSize(None)),
1456 },
1457 };
1458
1459 element.upcast::<Node>().remove_self(can_gc);
1460 Ok(())
1461 }
1462
1463 pub(crate) fn get_stylesheet(&self) -> Option<Arc<Stylesheet>> {
1464 if let Some(node) = self.downcast::<HTMLStyleElement>() {
1465 node.get_stylesheet()
1466 } else if let Some(node) = self.downcast::<HTMLLinkElement>() {
1467 node.get_stylesheet()
1468 } else {
1469 None
1470 }
1471 }
1472
1473 pub(crate) fn get_cssom_stylesheet(&self) -> Option<DomRoot<CSSStyleSheet>> {
1474 if let Some(node) = self.downcast::<HTMLStyleElement>() {
1475 node.get_cssom_stylesheet()
1476 } else if let Some(node) = self.downcast::<HTMLLinkElement>() {
1477 node.get_cssom_stylesheet(CanGc::note())
1478 } else {
1479 None
1480 }
1481 }
1482
1483 pub(crate) fn is_styled(&self) -> bool {
1484 self.style_data.borrow().is_some()
1485 }
1486
1487 pub(crate) fn is_display_none(&self) -> bool {
1488 self.style_data.borrow().as_ref().is_none_or(|data| {
1489 data.element_data
1490 .borrow()
1491 .styles
1492 .primary()
1493 .get_box()
1494 .display
1495 .is_none()
1496 })
1497 }
1498
1499 pub(crate) fn style(&self) -> Option<Arc<ComputedValues>> {
1500 self.owner_window().layout_reflow(QueryMsg::StyleQuery);
1501 self.style_data
1502 .borrow()
1503 .as_ref()
1504 .map(|data| data.element_data.borrow().styles.primary().clone())
1505 }
1506
1507 pub(crate) fn get_lang(&self) -> Option<String> {
1509 self.inclusive_ancestors(ShadowIncluding::Yes)
1510 .find_map(|node| {
1511 node.downcast::<Element>().and_then(|el| {
1512 el.get_attribute(&ns!(xml), &local_name!("lang"))
1513 .or_else(|| el.get_attribute(&ns!(), &local_name!("lang")))
1514 .map(|attr| String::from(attr.Value()))
1515 })
1516 })
1519 }
1520
1521 pub(crate) fn assign_slottables_for_a_tree(&self) {
1523 let is_shadow_root_with_slots = self
1527 .downcast::<ShadowRoot>()
1528 .is_some_and(|shadow_root| shadow_root.has_slot_descendants());
1529 if !is_shadow_root_with_slots && !self.is::<HTMLSlotElement>() {
1530 return;
1531 }
1532
1533 for node in self.traverse_preorder(ShadowIncluding::No) {
1536 if let Some(slot) = node.downcast::<HTMLSlotElement>() {
1537 slot.assign_slottables();
1538 }
1539 }
1540 }
1541
1542 pub(crate) fn assigned_slot(&self) -> Option<DomRoot<HTMLSlotElement>> {
1543 let assigned_slot = self
1544 .rare_data
1545 .borrow()
1546 .as_ref()?
1547 .slottable_data
1548 .assigned_slot
1549 .as_ref()?
1550 .as_rooted();
1551 Some(assigned_slot)
1552 }
1553
1554 pub(crate) fn set_assigned_slot(&self, assigned_slot: Option<&HTMLSlotElement>) {
1555 self.ensure_rare_data().slottable_data.assigned_slot = assigned_slot.map(Dom::from_ref);
1556 }
1557
1558 pub(crate) fn manual_slot_assignment(&self) -> Option<DomRoot<HTMLSlotElement>> {
1559 let manually_assigned_slot = self
1560 .rare_data
1561 .borrow()
1562 .as_ref()?
1563 .slottable_data
1564 .manual_slot_assignment
1565 .as_ref()?
1566 .as_rooted();
1567 Some(manually_assigned_slot)
1568 }
1569
1570 pub(crate) fn set_manual_slot_assignment(
1571 &self,
1572 manually_assigned_slot: Option<&HTMLSlotElement>,
1573 ) {
1574 self.ensure_rare_data()
1575 .slottable_data
1576 .manual_slot_assignment = manually_assigned_slot.map(Dom::from_ref);
1577 }
1578
1579 pub(crate) fn parent_in_flat_tree(&self) -> Option<DomRoot<Node>> {
1585 if let Some(assigned_slot) = self.assigned_slot() {
1586 return Some(DomRoot::upcast(assigned_slot));
1587 }
1588
1589 let parent_or_none = self.GetParentNode();
1590 if let Some(parent) = parent_or_none.as_deref() {
1591 if let Some(shadow_root) = parent.downcast::<ShadowRoot>() {
1592 return Some(DomRoot::from_ref(shadow_root.Host().upcast::<Node>()));
1593 }
1594 }
1595
1596 parent_or_none
1597 }
1598
1599 pub(crate) fn inclusive_ancestors_in_flat_tree(
1600 &self,
1601 ) -> impl Iterator<Item = DomRoot<Node>> + use<> {
1602 SimpleNodeIterator {
1603 current: Some(DomRoot::from_ref(self)),
1604 next_node: move |n| n.parent_in_flat_tree(),
1605 }
1606 }
1607
1608 pub(crate) fn set_implemented_pseudo_element(&self, pseudo_element: PseudoElement) {
1610 debug_assert!(self.is_in_ua_widget());
1612 self.ensure_rare_data().implemented_pseudo_element = Some(pseudo_element);
1613 }
1614
1615 pub(crate) fn implemented_pseudo_element(&self) -> Option<PseudoElement> {
1616 self.rare_data
1617 .borrow()
1618 .as_ref()
1619 .and_then(|rare_data| rare_data.implemented_pseudo_element)
1620 }
1621}
1622
1623fn first_node_not_in<I>(mut nodes: I, not_in: &[NodeOrString]) -> Option<DomRoot<Node>>
1625where
1626 I: Iterator<Item = DomRoot<Node>>,
1627{
1628 nodes.find(|node| {
1629 not_in.iter().all(|n| match *n {
1630 NodeOrString::Node(ref n) => n != node,
1631 _ => true,
1632 })
1633 })
1634}
1635
1636#[expect(unsafe_code)]
1639pub(crate) unsafe fn from_untrusted_node_address(candidate: UntrustedNodeAddress) -> DomRoot<Node> {
1640 let node = unsafe { Node::from_untrusted_node_address(candidate) };
1641 DomRoot::from_ref(node)
1642}
1643
1644#[expect(unsafe_code)]
1645pub(crate) trait LayoutNodeHelpers<'dom> {
1646 fn type_id_for_layout(self) -> NodeTypeId;
1647
1648 fn parent_node_ref(self) -> Option<LayoutDom<'dom, Node>>;
1649 fn composed_parent_node_ref(self) -> Option<LayoutDom<'dom, Node>>;
1650 fn first_child_ref(self) -> Option<LayoutDom<'dom, Node>>;
1651 fn last_child_ref(self) -> Option<LayoutDom<'dom, Node>>;
1652 fn prev_sibling_ref(self) -> Option<LayoutDom<'dom, Node>>;
1653 fn next_sibling_ref(self) -> Option<LayoutDom<'dom, Node>>;
1654
1655 fn owner_doc_for_layout(self) -> LayoutDom<'dom, Document>;
1656 fn containing_shadow_root_for_layout(self) -> Option<LayoutDom<'dom, ShadowRoot>>;
1657 fn assigned_slot_for_layout(self) -> Option<LayoutDom<'dom, HTMLSlotElement>>;
1658
1659 fn is_element_for_layout(&self) -> bool;
1660 fn is_text_node_for_layout(&self) -> bool;
1661 unsafe fn get_flag(self, flag: NodeFlags) -> bool;
1662 unsafe fn set_flag(self, flag: NodeFlags, value: bool);
1663
1664 fn style_data(self) -> Option<&'dom StyleData>;
1665 fn layout_data(self) -> Option<&'dom GenericLayoutData>;
1666
1667 unsafe fn initialize_style_data(self);
1675
1676 unsafe fn initialize_layout_data(self, data: Box<GenericLayoutData>);
1684
1685 unsafe fn clear_style_and_layout_data(self);
1693
1694 fn is_text_input(&self) -> bool;
1700
1701 fn is_single_line_text_inner_editor(&self) -> bool;
1704
1705 fn is_text_container_of_single_line_input(&self) -> bool;
1708 fn text_content(self) -> Cow<'dom, str>;
1709 fn selection(self) -> Option<Range<usize>>;
1710 fn image_url(self) -> Option<ServoUrl>;
1711 fn image_density(self) -> Option<f64>;
1712 fn image_data(self) -> Option<(Option<Image>, Option<ImageMetadata>)>;
1713 fn showing_broken_image_icon(self) -> bool;
1714 fn canvas_data(self) -> Option<HTMLCanvasData>;
1715 fn media_data(self) -> Option<HTMLMediaData>;
1716 fn svg_data(self) -> Option<SVGElementData>;
1717 fn iframe_browsing_context_id(self) -> Option<BrowsingContextId>;
1718 fn iframe_pipeline_id(self) -> Option<PipelineId>;
1719 fn opaque(self) -> OpaqueNode;
1720 fn implemented_pseudo_element(&self) -> Option<PseudoElement>;
1721 fn is_in_ua_widget(&self) -> bool;
1722}
1723
1724impl<'dom> LayoutDom<'dom, Node> {
1725 #[inline]
1726 #[expect(unsafe_code)]
1727 pub(crate) fn parent_node_ref(self) -> Option<LayoutDom<'dom, Node>> {
1728 unsafe { self.unsafe_get().parent_node.get_inner_as_layout() }
1729 }
1730}
1731
1732impl<'dom> LayoutNodeHelpers<'dom> for LayoutDom<'dom, Node> {
1733 #[inline]
1734 fn type_id_for_layout(self) -> NodeTypeId {
1735 self.unsafe_get().type_id()
1736 }
1737
1738 #[inline]
1739 fn is_element_for_layout(&self) -> bool {
1740 (*self).is::<Element>()
1741 }
1742
1743 fn is_text_node_for_layout(&self) -> bool {
1744 self.type_id_for_layout() ==
1745 NodeTypeId::CharacterData(CharacterDataTypeId::Text(TextTypeId::Text))
1746 }
1747
1748 #[inline]
1749 #[expect(unsafe_code)]
1750 fn parent_node_ref(self) -> Option<LayoutDom<'dom, Node>> {
1751 unsafe { self.unsafe_get().parent_node.get_inner_as_layout() }
1752 }
1753
1754 #[inline]
1755 fn composed_parent_node_ref(self) -> Option<LayoutDom<'dom, Node>> {
1756 let parent = self.parent_node_ref();
1757 if let Some(parent) = parent {
1758 if let Some(shadow_root) = parent.downcast::<ShadowRoot>() {
1759 return Some(shadow_root.get_host_for_layout().upcast());
1760 }
1761 }
1762 parent
1763 }
1764
1765 #[inline]
1766 #[expect(unsafe_code)]
1767 fn first_child_ref(self) -> Option<LayoutDom<'dom, Node>> {
1768 unsafe { self.unsafe_get().first_child.get_inner_as_layout() }
1769 }
1770
1771 #[inline]
1772 #[expect(unsafe_code)]
1773 fn last_child_ref(self) -> Option<LayoutDom<'dom, Node>> {
1774 unsafe { self.unsafe_get().last_child.get_inner_as_layout() }
1775 }
1776
1777 #[inline]
1778 #[expect(unsafe_code)]
1779 fn prev_sibling_ref(self) -> Option<LayoutDom<'dom, Node>> {
1780 unsafe { self.unsafe_get().prev_sibling.get_inner_as_layout() }
1781 }
1782
1783 #[inline]
1784 #[expect(unsafe_code)]
1785 fn next_sibling_ref(self) -> Option<LayoutDom<'dom, Node>> {
1786 unsafe { self.unsafe_get().next_sibling.get_inner_as_layout() }
1787 }
1788
1789 #[inline]
1790 #[expect(unsafe_code)]
1791 fn owner_doc_for_layout(self) -> LayoutDom<'dom, Document> {
1792 unsafe { self.unsafe_get().owner_doc.get_inner_as_layout().unwrap() }
1793 }
1794
1795 #[inline]
1796 #[expect(unsafe_code)]
1797 fn containing_shadow_root_for_layout(self) -> Option<LayoutDom<'dom, ShadowRoot>> {
1798 unsafe {
1799 self.unsafe_get()
1800 .rare_data
1801 .borrow_for_layout()
1802 .as_ref()?
1803 .containing_shadow_root
1804 .as_ref()
1805 .map(|sr| sr.to_layout())
1806 }
1807 }
1808
1809 #[inline]
1810 #[expect(unsafe_code)]
1811 fn assigned_slot_for_layout(self) -> Option<LayoutDom<'dom, HTMLSlotElement>> {
1812 unsafe {
1813 self.unsafe_get()
1814 .rare_data
1815 .borrow_for_layout()
1816 .as_ref()?
1817 .slottable_data
1818 .assigned_slot
1819 .as_ref()
1820 .map(|assigned_slot| assigned_slot.to_layout())
1821 }
1822 }
1823
1824 #[inline]
1829 #[expect(unsafe_code)]
1830 unsafe fn get_flag(self, flag: NodeFlags) -> bool {
1831 (self.unsafe_get()).flags.get().contains(flag)
1832 }
1833
1834 #[inline]
1835 #[expect(unsafe_code)]
1836 unsafe fn set_flag(self, flag: NodeFlags, value: bool) {
1837 let this = self.unsafe_get();
1838 let mut flags = (this).flags.get();
1839
1840 if value {
1841 flags.insert(flag);
1842 } else {
1843 flags.remove(flag);
1844 }
1845
1846 (this).flags.set(flags);
1847 }
1848
1849 #[inline]
1852 #[expect(unsafe_code)]
1853 fn style_data(self) -> Option<&'dom StyleData> {
1854 unsafe { self.unsafe_get().style_data.borrow_for_layout().as_deref() }
1855 }
1856
1857 #[inline]
1858 #[expect(unsafe_code)]
1859 fn layout_data(self) -> Option<&'dom GenericLayoutData> {
1860 unsafe { self.unsafe_get().layout_data.borrow_for_layout().as_deref() }
1861 }
1862
1863 #[inline]
1864 #[expect(unsafe_code)]
1865 unsafe fn initialize_style_data(self) {
1866 let data = unsafe { self.unsafe_get().style_data.borrow_mut_for_layout() };
1867 debug_assert!(data.is_none());
1868 *data = Some(Box::default());
1869 }
1870
1871 #[inline]
1872 #[expect(unsafe_code)]
1873 unsafe fn initialize_layout_data(self, new_data: Box<GenericLayoutData>) {
1874 let data = unsafe { self.unsafe_get().layout_data.borrow_mut_for_layout() };
1875 debug_assert!(data.is_none());
1876 *data = Some(new_data);
1877 }
1878
1879 #[inline]
1880 #[expect(unsafe_code)]
1881 unsafe fn clear_style_and_layout_data(self) {
1882 unsafe {
1883 self.unsafe_get().style_data.borrow_mut_for_layout().take();
1884 self.unsafe_get().layout_data.borrow_mut_for_layout().take();
1885 }
1886 }
1887
1888 fn is_text_input(&self) -> bool {
1892 let type_id = self.type_id_for_layout();
1893 if type_id ==
1894 NodeTypeId::Element(ElementTypeId::HTMLElement(
1895 HTMLElementTypeId::HTMLInputElement,
1896 ))
1897 {
1898 let input = self.unsafe_get().downcast::<HTMLInputElement>().unwrap();
1899
1900 !input.is_textual_widget() && input.input_type() != InputType::Color
1901 } else {
1902 type_id ==
1903 NodeTypeId::Element(ElementTypeId::HTMLElement(
1904 HTMLElementTypeId::HTMLTextAreaElement,
1905 ))
1906 }
1907 }
1908
1909 fn is_single_line_text_inner_editor(&self) -> bool {
1910 matches!(
1911 self.unsafe_get().implemented_pseudo_element(),
1912 Some(PseudoElement::ServoTextControlInnerEditor)
1913 )
1914 }
1915
1916 fn is_text_container_of_single_line_input(&self) -> bool {
1917 let is_single_line_text_inner_placeholder = matches!(
1918 self.unsafe_get().implemented_pseudo_element(),
1919 Some(PseudoElement::Placeholder)
1920 );
1921 debug_assert!(
1923 !is_single_line_text_inner_placeholder ||
1924 self.containing_shadow_root_for_layout()
1925 .map(|root| root.get_host_for_layout())
1926 .map(|host| host.downcast::<HTMLInputElement>())
1927 .is_some()
1928 );
1929
1930 self.is_single_line_text_inner_editor() || is_single_line_text_inner_placeholder
1931 }
1932
1933 fn text_content(self) -> Cow<'dom, str> {
1934 if let Some(text) = self.downcast::<Text>() {
1935 return text.upcast().data_for_layout().into();
1936 }
1937
1938 if let Some(input) = self.downcast::<HTMLInputElement>() {
1939 return input.value_for_layout();
1940 }
1941
1942 if let Some(area) = self.downcast::<HTMLTextAreaElement>() {
1943 return area.value_for_layout().into();
1944 }
1945
1946 panic!("not text!")
1947 }
1948
1949 fn selection(self) -> Option<Range<usize>> {
1950 if self.is_in_ua_widget() &&
1955 self.is_text_node_for_layout() &&
1956 self.parent_node_ref()
1957 .is_some_and(|parent| parent.is_single_line_text_inner_editor())
1958 {
1959 let shadow_root = self.containing_shadow_root_for_layout();
1960 if let Some(containing_shadow_host) = shadow_root.map(|root| root.get_host_for_layout())
1961 {
1962 if let Some(input) = containing_shadow_host.downcast::<HTMLInputElement>() {
1963 return input.selection_for_layout();
1964 }
1965 }
1966 }
1967
1968 if let Some(area) = self.downcast::<HTMLTextAreaElement>() {
1969 return area.selection_for_layout();
1970 }
1971
1972 if let Some(input) = self.downcast::<HTMLInputElement>() {
1973 return input.selection_for_layout();
1974 }
1975
1976 None
1977 }
1978
1979 fn image_url(self) -> Option<ServoUrl> {
1980 self.downcast::<HTMLImageElement>()
1981 .expect("not an image!")
1982 .image_url()
1983 }
1984
1985 fn image_data(self) -> Option<(Option<Image>, Option<ImageMetadata>)> {
1986 self.downcast::<HTMLImageElement>().map(|e| e.image_data())
1987 }
1988
1989 fn image_density(self) -> Option<f64> {
1990 self.downcast::<HTMLImageElement>()
1991 .expect("not an image!")
1992 .image_density()
1993 }
1994
1995 fn showing_broken_image_icon(self) -> bool {
1996 self.downcast::<HTMLImageElement>()
1997 .map(|image_element| image_element.showing_broken_image_icon())
1998 .unwrap_or_default()
1999 }
2000
2001 fn canvas_data(self) -> Option<HTMLCanvasData> {
2002 self.downcast::<HTMLCanvasElement>()
2003 .map(|canvas| canvas.data())
2004 }
2005
2006 fn media_data(self) -> Option<HTMLMediaData> {
2007 self.downcast::<HTMLVideoElement>()
2008 .map(|media| media.data())
2009 }
2010
2011 fn svg_data(self) -> Option<SVGElementData> {
2012 self.downcast::<SVGSVGElement>().map(|svg| svg.data())
2013 }
2014
2015 fn iframe_browsing_context_id(self) -> Option<BrowsingContextId> {
2016 self.downcast::<HTMLIFrameElement>()
2017 .and_then(|iframe_element| iframe_element.browsing_context_id())
2018 }
2019
2020 fn iframe_pipeline_id(self) -> Option<PipelineId> {
2021 self.downcast::<HTMLIFrameElement>()
2022 .and_then(|iframe_element| iframe_element.pipeline_id())
2023 }
2024
2025 #[expect(unsafe_code)]
2026 fn opaque(self) -> OpaqueNode {
2027 unsafe { OpaqueNode(self.get_jsobject() as usize) }
2028 }
2029
2030 fn implemented_pseudo_element(&self) -> Option<PseudoElement> {
2031 self.unsafe_get().implemented_pseudo_element()
2032 }
2033
2034 fn is_in_ua_widget(&self) -> bool {
2035 self.unsafe_get().is_in_ua_widget()
2036 }
2037}
2038
2039pub(crate) struct FollowingNodeIterator {
2044 current: Option<DomRoot<Node>>,
2045 root: DomRoot<Node>,
2046}
2047
2048impl FollowingNodeIterator {
2049 pub(crate) fn next_skipping_children(&mut self) -> Option<DomRoot<Node>> {
2051 let current = self.current.take()?;
2052 self.next_skipping_children_impl(current)
2053 }
2054
2055 fn next_skipping_children_impl(&mut self, current: DomRoot<Node>) -> Option<DomRoot<Node>> {
2056 if self.root == current {
2057 self.current = None;
2058 return None;
2059 }
2060
2061 if let Some(next_sibling) = current.GetNextSibling() {
2062 self.current = Some(next_sibling);
2063 return current.GetNextSibling();
2064 }
2065
2066 for ancestor in current.inclusive_ancestors(ShadowIncluding::No) {
2067 if self.root == ancestor {
2068 break;
2069 }
2070 if let Some(next_sibling) = ancestor.GetNextSibling() {
2071 self.current = Some(next_sibling);
2072 return ancestor.GetNextSibling();
2073 }
2074 }
2075 self.current = None;
2076 None
2077 }
2078}
2079
2080impl Iterator for FollowingNodeIterator {
2081 type Item = DomRoot<Node>;
2082
2083 fn next(&mut self) -> Option<DomRoot<Node>> {
2085 let current = self.current.take()?;
2086
2087 if let Some(first_child) = current.GetFirstChild() {
2088 self.current = Some(first_child);
2089 return current.GetFirstChild();
2090 }
2091
2092 self.next_skipping_children_impl(current)
2093 }
2094}
2095
2096pub(crate) struct PrecedingNodeIterator {
2097 current: Option<DomRoot<Node>>,
2098 root: DomRoot<Node>,
2099}
2100
2101impl Iterator for PrecedingNodeIterator {
2102 type Item = DomRoot<Node>;
2103
2104 fn next(&mut self) -> Option<DomRoot<Node>> {
2106 let current = self.current.take()?;
2107
2108 self.current = if self.root == current {
2109 None
2110 } else if let Some(previous_sibling) = current.GetPreviousSibling() {
2111 if self.root == previous_sibling {
2112 None
2113 } else if let Some(last_child) = previous_sibling.descending_last_children().last() {
2114 Some(last_child)
2115 } else {
2116 Some(previous_sibling)
2117 }
2118 } else {
2119 current.GetParentNode()
2120 };
2121 self.current.clone()
2122 }
2123}
2124
2125struct SimpleNodeIterator<I>
2126where
2127 I: Fn(&Node) -> Option<DomRoot<Node>>,
2128{
2129 current: Option<DomRoot<Node>>,
2130 next_node: I,
2131}
2132
2133impl<I> Iterator for SimpleNodeIterator<I>
2134where
2135 I: Fn(&Node) -> Option<DomRoot<Node>>,
2136{
2137 type Item = DomRoot<Node>;
2138
2139 fn next(&mut self) -> Option<Self::Item> {
2140 let current = self.current.take();
2141 self.current = current.as_ref().and_then(|c| (self.next_node)(c));
2142 current
2143 }
2144}
2145
2146#[derive(Clone, Copy, PartialEq)]
2148pub(crate) enum ShadowIncluding {
2149 No,
2150 Yes,
2151}
2152
2153pub(crate) struct TreeIterator {
2154 current: Option<DomRoot<Node>>,
2155 depth: usize,
2156 shadow_including: bool,
2157}
2158
2159impl TreeIterator {
2160 fn new(root: &Node, shadow_including: ShadowIncluding) -> TreeIterator {
2161 TreeIterator {
2162 current: Some(DomRoot::from_ref(root)),
2163 depth: 0,
2164 shadow_including: shadow_including == ShadowIncluding::Yes,
2165 }
2166 }
2167
2168 pub(crate) fn next_skipping_children(&mut self) -> Option<DomRoot<Node>> {
2169 let current = self.current.take()?;
2170
2171 self.next_skipping_children_impl(current)
2172 }
2173
2174 fn next_skipping_children_impl(&mut self, current: DomRoot<Node>) -> Option<DomRoot<Node>> {
2175 let iter = current.inclusive_ancestors(if self.shadow_including {
2176 ShadowIncluding::Yes
2177 } else {
2178 ShadowIncluding::No
2179 });
2180
2181 for ancestor in iter {
2182 if self.depth == 0 {
2183 break;
2184 }
2185 if let Some(next_sibling) = ancestor.GetNextSibling() {
2186 self.current = Some(next_sibling);
2187 return Some(current);
2188 }
2189 if let Some(shadow_root) = ancestor.downcast::<ShadowRoot>() {
2190 if let Some(child) = shadow_root.Host().upcast::<Node>().GetFirstChild() {
2193 self.current = Some(child);
2194 return Some(current);
2195 }
2196 }
2197 self.depth -= 1;
2198 }
2199 debug_assert_eq!(self.depth, 0);
2200 self.current = None;
2201 Some(current)
2202 }
2203
2204 pub(crate) fn peek(&self) -> Option<&DomRoot<Node>> {
2205 self.current.as_ref()
2206 }
2207}
2208
2209impl Iterator for TreeIterator {
2210 type Item = DomRoot<Node>;
2211
2212 fn next(&mut self) -> Option<DomRoot<Node>> {
2215 let current = self.current.take()?;
2216
2217 if let Some(element) = current.downcast::<Element>() {
2219 if let Some(shadow_root) = element.shadow_root() {
2220 if self.shadow_including {
2221 self.current = Some(DomRoot::from_ref(shadow_root.upcast::<Node>()));
2222 self.depth += 1;
2223 return Some(current);
2224 }
2225 }
2226 }
2227
2228 if let Some(first_child) = current.GetFirstChild() {
2229 self.current = Some(first_child);
2230 self.depth += 1;
2231 return Some(current);
2232 };
2233
2234 self.next_skipping_children_impl(current)
2235 }
2236}
2237
2238#[derive(Clone, Copy, MallocSizeOf, PartialEq)]
2240pub(crate) enum CloneChildrenFlag {
2241 CloneChildren,
2242 DoNotCloneChildren,
2243}
2244
2245fn as_uintptr<T>(t: &T) -> uintptr_t {
2246 t as *const T as uintptr_t
2247}
2248
2249impl Node {
2250 pub(crate) fn reflect_node<N>(node: Box<N>, document: &Document, can_gc: CanGc) -> DomRoot<N>
2251 where
2252 N: DerivedFrom<Node> + DomObject + DomObjectWrap<crate::DomTypeHolder>,
2253 {
2254 Self::reflect_node_with_proto(node, document, None, can_gc)
2255 }
2256
2257 pub(crate) fn reflect_node_with_proto<N>(
2258 node: Box<N>,
2259 document: &Document,
2260 proto: Option<HandleObject>,
2261 can_gc: CanGc,
2262 ) -> DomRoot<N>
2263 where
2264 N: DerivedFrom<Node> + DomObject + DomObjectWrap<crate::DomTypeHolder>,
2265 {
2266 let window = document.window();
2267 reflect_dom_object_with_proto(node, window, proto, can_gc)
2268 }
2269
2270 pub(crate) fn new_inherited(doc: &Document) -> Node {
2271 Node::new_(NodeFlags::empty(), Some(doc))
2272 }
2273
2274 #[cfg_attr(crown, allow(crown::unrooted_must_root))]
2275 pub(crate) fn new_document_node() -> Node {
2276 Node::new_(
2277 NodeFlags::IS_IN_A_DOCUMENT_TREE | NodeFlags::IS_CONNECTED,
2278 None,
2279 )
2280 }
2281
2282 #[cfg_attr(crown, allow(crown::unrooted_must_root))]
2283 fn new_(flags: NodeFlags, doc: Option<&Document>) -> Node {
2284 Node {
2285 eventtarget: EventTarget::new_inherited(),
2286
2287 parent_node: Default::default(),
2288 first_child: Default::default(),
2289 last_child: Default::default(),
2290 next_sibling: Default::default(),
2291 prev_sibling: Default::default(),
2292 owner_doc: MutNullableDom::new(doc),
2293 rare_data: Default::default(),
2294 children_count: Cell::new(0u32),
2295 flags: Cell::new(flags),
2296 inclusive_descendants_version: Cell::new(0),
2297 style_data: Default::default(),
2298 layout_data: Default::default(),
2299 }
2300 }
2301
2302 pub(crate) fn adopt(node: &Node, document: &Document, can_gc: CanGc) {
2304 document.add_script_and_layout_blocker();
2305
2306 let old_doc = node.owner_doc();
2308 old_doc.add_script_and_layout_blocker();
2309
2310 node.remove_self(can_gc);
2312
2313 if &*old_doc != document {
2315 for descendant in node.traverse_preorder(ShadowIncluding::Yes) {
2317 descendant.set_owner_doc(document);
2319
2320 if let Some(element) = descendant.downcast::<Element>() {
2323 for attribute in element.attrs().iter() {
2324 attribute.upcast::<Node>().set_owner_doc(document);
2325 }
2326 }
2327 }
2328
2329 let custom_element_reaction_stack = ScriptThread::custom_element_reaction_stack();
2333 for descendant in node
2334 .traverse_preorder(ShadowIncluding::Yes)
2335 .filter_map(|d| d.as_custom_element())
2336 {
2337 custom_element_reaction_stack.enqueue_callback_reaction(
2338 &descendant,
2339 CallbackReaction::Adopted(old_doc.clone(), DomRoot::from_ref(document)),
2340 None,
2341 );
2342 }
2343
2344 for descendant in node.traverse_preorder(ShadowIncluding::Yes) {
2347 vtable_for(&descendant).adopting_steps(&old_doc, can_gc);
2348 }
2349 }
2350
2351 old_doc.remove_script_and_layout_blocker();
2352 document.remove_script_and_layout_blocker();
2353 }
2354
2355 pub(crate) fn ensure_pre_insertion_validity(
2357 node: &Node,
2358 parent: &Node,
2359 child: Option<&Node>,
2360 ) -> ErrorResult {
2361 match parent.type_id() {
2363 NodeTypeId::Document(_) | NodeTypeId::DocumentFragment(_) | NodeTypeId::Element(..) => {
2364 },
2365 _ => return Err(Error::HierarchyRequest(None)),
2366 }
2367
2368 if node.is_inclusive_ancestor_of(parent) {
2370 return Err(Error::HierarchyRequest(None));
2371 }
2372
2373 if let Some(child) = child {
2375 if !parent.is_parent_of(child) {
2376 return Err(Error::NotFound(None));
2377 }
2378 }
2379
2380 match node.type_id() {
2382 NodeTypeId::CharacterData(CharacterDataTypeId::Text(_)) => {
2383 if parent.is::<Document>() {
2384 return Err(Error::HierarchyRequest(None));
2385 }
2386 },
2387 NodeTypeId::DocumentType => {
2388 if !parent.is::<Document>() {
2389 return Err(Error::HierarchyRequest(None));
2390 }
2391 },
2392 NodeTypeId::DocumentFragment(_) |
2393 NodeTypeId::Element(_) |
2394 NodeTypeId::CharacterData(CharacterDataTypeId::ProcessingInstruction) |
2395 NodeTypeId::CharacterData(CharacterDataTypeId::Comment) => (),
2396 NodeTypeId::Document(_) | NodeTypeId::Attr => {
2397 return Err(Error::HierarchyRequest(None));
2398 },
2399 }
2400
2401 if parent.is::<Document>() {
2403 match node.type_id() {
2404 NodeTypeId::DocumentFragment(_) => {
2406 if node.children().any(|c| c.is::<Text>()) {
2408 return Err(Error::HierarchyRequest(None));
2409 }
2410 match node.child_elements().count() {
2411 0 => (),
2412 1 => {
2414 if parent.child_elements().next().is_some() {
2415 return Err(Error::HierarchyRequest(None));
2416 }
2417 if let Some(child) = child {
2418 if child
2419 .inclusively_following_siblings()
2420 .any(|child| child.is_doctype())
2421 {
2422 return Err(Error::HierarchyRequest(None));
2423 }
2424 }
2425 },
2426 _ => return Err(Error::HierarchyRequest(None)),
2428 }
2429 },
2430 NodeTypeId::Element(_) => {
2432 if parent.child_elements().next().is_some() {
2433 return Err(Error::HierarchyRequest(None));
2434 }
2435 if let Some(child) = child {
2436 if child
2437 .inclusively_following_siblings()
2438 .any(|child| child.is_doctype())
2439 {
2440 return Err(Error::HierarchyRequest(None));
2441 }
2442 }
2443 },
2444 NodeTypeId::DocumentType => {
2446 if parent.children().any(|c| c.is_doctype()) {
2447 return Err(Error::HierarchyRequest(None));
2448 }
2449 match child {
2450 Some(child) => {
2451 if parent
2452 .children()
2453 .take_while(|c| &**c != child)
2454 .any(|c| c.is::<Element>())
2455 {
2456 return Err(Error::HierarchyRequest(None));
2457 }
2458 },
2459 None => {
2460 if parent.child_elements().next().is_some() {
2461 return Err(Error::HierarchyRequest(None));
2462 }
2463 },
2464 }
2465 },
2466 NodeTypeId::CharacterData(_) => (),
2467 NodeTypeId::Document(_) | NodeTypeId::Attr => unreachable!(),
2470 }
2471 }
2472 Ok(())
2473 }
2474
2475 pub(crate) fn pre_insert(
2477 node: &Node,
2478 parent: &Node,
2479 child: Option<&Node>,
2480 can_gc: CanGc,
2481 ) -> Fallible<DomRoot<Node>> {
2482 Node::ensure_pre_insertion_validity(node, parent, child)?;
2484
2485 let reference_child_root;
2487 let reference_child = match child {
2488 Some(child) if child == node => {
2489 reference_child_root = node.GetNextSibling();
2490 reference_child_root.as_deref()
2491 },
2492 _ => child,
2493 };
2494
2495 Node::insert(
2497 node,
2498 parent,
2499 reference_child,
2500 SuppressObserver::Unsuppressed,
2501 can_gc,
2502 );
2503
2504 Ok(DomRoot::from_ref(node))
2506 }
2507
2508 fn insert(
2510 node: &Node,
2511 parent: &Node,
2512 child: Option<&Node>,
2513 suppress_observers: SuppressObserver,
2514 can_gc: CanGc,
2515 ) {
2516 debug_assert!(child.is_none_or(|child| Some(parent) == child.GetParentNode().as_deref()));
2517
2518 rooted_vec!(let mut new_nodes);
2520 let new_nodes = if let NodeTypeId::DocumentFragment(_) = node.type_id() {
2521 new_nodes.extend(node.children().map(|node| Dom::from_ref(&*node)));
2522 new_nodes.r()
2523 } else {
2524 from_ref(&node)
2525 };
2526
2527 let count = new_nodes.len();
2529
2530 if count == 0 {
2532 return;
2533 }
2534
2535 let parent_document = parent.owner_doc();
2538 let from_document = node.owner_doc();
2539 from_document.add_script_and_layout_blocker();
2540 parent_document.add_script_and_layout_blocker();
2541
2542 if let NodeTypeId::DocumentFragment(_) = node.type_id() {
2544 for kid in new_nodes {
2546 Node::remove(kid, node, SuppressObserver::Suppressed, can_gc);
2547 }
2548 vtable_for(node)
2549 .children_changed(&ChildrenMutation::replace_all(new_nodes, &[]), can_gc);
2550
2551 let mutation = LazyCell::new(|| Mutation::ChildList {
2553 added: None,
2554 removed: Some(new_nodes),
2555 prev: None,
2556 next: None,
2557 });
2558 MutationObserver::queue_a_mutation_record(node, mutation);
2559 }
2560
2561 if let Some(child) = child {
2567 if !parent.ranges_is_empty() {
2568 parent
2569 .ranges()
2570 .increase_above(parent, child.index(), count.try_into().unwrap());
2571 }
2572 }
2573
2574 let previous_sibling = match suppress_observers {
2576 SuppressObserver::Unsuppressed => match child {
2577 Some(child) => child.GetPreviousSibling(),
2578 None => parent.GetLastChild(),
2579 },
2580 SuppressObserver::Suppressed => None,
2581 };
2582
2583 let custom_element_reaction_stack = ScriptThread::custom_element_reaction_stack();
2584 for kid in new_nodes {
2586 Node::adopt(kid, &parent.owner_document(), can_gc);
2588
2589 parent.add_child(kid, child, can_gc);
2592
2593 if let Some(shadow_root) = parent.downcast::<Element>().and_then(Element::shadow_root) {
2596 if shadow_root.SlotAssignment() == SlotAssignmentMode::Named {
2597 let cx = GlobalScope::get_cx();
2598 if kid.is::<Element>() || kid.is::<Text>() {
2599 rooted!(in(*cx) let slottable = Slottable(Dom::from_ref(kid)));
2600 slottable.assign_a_slot();
2601 }
2602 }
2603 }
2604
2605 if parent.is_in_a_shadow_tree() {
2608 if let Some(slot_element) = parent.downcast::<HTMLSlotElement>() {
2609 if !slot_element.has_assigned_nodes() {
2610 slot_element.signal_a_slot_change();
2611 }
2612 }
2613 }
2614
2615 kid.GetRootNode(&GetRootNodeOptions::empty())
2617 .assign_slottables_for_a_tree();
2618
2619 for descendant in kid
2622 .traverse_preorder(ShadowIncluding::Yes)
2623 .filter_map(DomRoot::downcast::<Element>)
2624 {
2625 if descendant.is_custom() {
2631 if descendant.is_connected() {
2632 custom_element_reaction_stack.enqueue_callback_reaction(
2633 &descendant,
2634 CallbackReaction::Connected,
2635 None,
2636 );
2637 }
2638 } else {
2639 try_upgrade_element(&descendant);
2640 }
2641 }
2642 }
2643
2644 if let SuppressObserver::Unsuppressed = suppress_observers {
2645 vtable_for(parent).children_changed(
2648 &ChildrenMutation::insert(previous_sibling.as_deref(), new_nodes, child),
2649 can_gc,
2650 );
2651
2652 let mutation = LazyCell::new(|| Mutation::ChildList {
2655 added: Some(new_nodes),
2656 removed: None,
2657 prev: previous_sibling.as_deref(),
2658 next: child,
2659 });
2660 MutationObserver::queue_a_mutation_record(parent, mutation);
2661 }
2662
2663 let mut static_node_list = vec![];
2665
2666 for node in new_nodes {
2668 static_node_list.extend(node.traverse_preorder(ShadowIncluding::Yes));
2671 }
2672
2673 parent_document.add_delayed_task(
2684 task!(PostConnectionSteps: |static_node_list: Vec<DomRoot<Node>>| {
2685 for node in static_node_list.iter().filter(|n| n.is_connected()) {
2688 vtable_for(node).post_connection_steps(CanGc::note());
2689 }
2690 }),
2691 );
2692
2693 parent_document.remove_script_and_layout_blocker();
2694 from_document.remove_script_and_layout_blocker();
2695 }
2696
2697 pub(crate) fn replace_all(node: Option<&Node>, parent: &Node, can_gc: CanGc) {
2699 parent.owner_doc().add_script_and_layout_blocker();
2700 if let Some(node) = node {
2702 Node::adopt(node, &parent.owner_doc(), can_gc);
2703 }
2704 rooted_vec!(let removed_nodes <- parent.children().map(|c| DomRoot::as_traced(&c)));
2706 rooted_vec!(let mut added_nodes);
2708 let added_nodes = if let Some(node) = node.as_ref() {
2709 if let NodeTypeId::DocumentFragment(_) = node.type_id() {
2710 added_nodes.extend(node.children().map(|child| Dom::from_ref(&*child)));
2711 added_nodes.r()
2712 } else {
2713 from_ref(node)
2714 }
2715 } else {
2716 &[] as &[&Node]
2717 };
2718 for child in &*removed_nodes {
2720 Node::remove(child, parent, SuppressObserver::Suppressed, can_gc);
2721 }
2722 if let Some(node) = node {
2724 Node::insert(node, parent, None, SuppressObserver::Suppressed, can_gc);
2725 }
2726 vtable_for(parent).children_changed(
2728 &ChildrenMutation::replace_all(removed_nodes.r(), added_nodes),
2729 can_gc,
2730 );
2731
2732 if !removed_nodes.is_empty() || !added_nodes.is_empty() {
2733 let mutation = LazyCell::new(|| Mutation::ChildList {
2734 added: Some(added_nodes),
2735 removed: Some(removed_nodes.r()),
2736 prev: None,
2737 next: None,
2738 });
2739 MutationObserver::queue_a_mutation_record(parent, mutation);
2740 }
2741 parent.owner_doc().remove_script_and_layout_blocker();
2742 }
2743
2744 pub(crate) fn string_replace_all(string: DOMString, parent: &Node, can_gc: CanGc) {
2746 if string.is_empty() {
2747 Node::replace_all(None, parent, can_gc);
2748 } else {
2749 let text = Text::new(string, &parent.owner_document(), can_gc);
2750 Node::replace_all(Some(text.upcast::<Node>()), parent, can_gc);
2751 };
2752 }
2753
2754 fn pre_remove(child: &Node, parent: &Node, can_gc: CanGc) -> Fallible<DomRoot<Node>> {
2756 match child.GetParentNode() {
2758 Some(ref node) if &**node != parent => return Err(Error::NotFound(None)),
2759 None => return Err(Error::NotFound(None)),
2760 _ => (),
2761 }
2762
2763 Node::remove(child, parent, SuppressObserver::Unsuppressed, can_gc);
2765
2766 Ok(DomRoot::from_ref(child))
2768 }
2769
2770 fn remove(node: &Node, parent: &Node, suppress_observers: SuppressObserver, can_gc: CanGc) {
2772 parent.owner_doc().add_script_and_layout_blocker();
2773
2774 assert!(
2778 node.GetParentNode()
2779 .is_some_and(|node_parent| &*node_parent == parent)
2780 );
2781
2782 let cached_index = {
2785 if parent.ranges_is_empty() {
2786 None
2787 } else {
2788 let index = node.index();
2794
2795 parent.ranges().decrease_above(parent, index, 1);
2802
2803 Some(index)
2807 }
2808 };
2809
2810 let old_previous_sibling = node.GetPreviousSibling();
2814
2815 let old_next_sibling = node.GetNextSibling();
2817
2818 parent.remove_child(node, cached_index, can_gc);
2821
2822 if let Some(slot) = node.assigned_slot() {
2824 slot.assign_slottables();
2825 }
2826
2827 if parent.is_in_a_shadow_tree() {
2830 if let Some(slot_element) = parent.downcast::<HTMLSlotElement>() {
2831 if !slot_element.has_assigned_nodes() {
2832 slot_element.signal_a_slot_change();
2833 }
2834 }
2835 }
2836
2837 let has_slot_descendant = node
2839 .traverse_preorder(ShadowIncluding::No)
2840 .any(|elem| elem.is::<HTMLSlotElement>());
2841 if has_slot_descendant {
2842 parent
2844 .GetRootNode(&GetRootNodeOptions::empty())
2845 .assign_slottables_for_a_tree();
2846
2847 node.assign_slottables_for_a_tree();
2849 }
2850
2851 if let SuppressObserver::Unsuppressed = suppress_observers {
2855 vtable_for(parent).children_changed(
2856 &ChildrenMutation::replace(
2857 old_previous_sibling.as_deref(),
2858 &Some(node),
2859 &[],
2860 old_next_sibling.as_deref(),
2861 ),
2862 can_gc,
2863 );
2864
2865 let removed = [node];
2866 let mutation = LazyCell::new(|| Mutation::ChildList {
2867 added: None,
2868 removed: Some(&removed),
2869 prev: old_previous_sibling.as_deref(),
2870 next: old_next_sibling.as_deref(),
2871 });
2872 MutationObserver::queue_a_mutation_record(parent, mutation);
2873 }
2874 parent.owner_doc().remove_script_and_layout_blocker();
2875 }
2876
2877 fn compute_attribute_value_with_style_fast_path(attr: &Dom<Attr>, elem: &Element) -> AttrValue {
2883 if *attr.local_name() == local_name!("style") {
2884 if let Some(ref pdb) = *elem.style_attribute().borrow() {
2885 let document = elem.owner_document();
2886 let shared_lock = document.style_shared_lock();
2887 let new_pdb = pdb.read_with(&shared_lock.read()).clone();
2888 return AttrValue::Declaration(
2889 (**attr.value()).to_owned(),
2890 Arc::new(shared_lock.wrap(new_pdb)),
2891 );
2892 }
2893 }
2894
2895 attr.value().clone()
2896 }
2897
2898 pub(crate) fn clone(
2900 node: &Node,
2901 maybe_doc: Option<&Document>,
2902 clone_children: CloneChildrenFlag,
2903 can_gc: CanGc,
2904 ) -> DomRoot<Node> {
2905 let document = match maybe_doc {
2907 Some(doc) => DomRoot::from_ref(doc),
2908 None => node.owner_doc(),
2909 };
2910
2911 let copy: DomRoot<Node> = match node.type_id() {
2914 NodeTypeId::DocumentType => {
2915 let doctype = node.downcast::<DocumentType>().unwrap();
2916 let doctype = DocumentType::new(
2917 doctype.name().clone(),
2918 Some(doctype.public_id().clone()),
2919 Some(doctype.system_id().clone()),
2920 &document,
2921 can_gc,
2922 );
2923 DomRoot::upcast::<Node>(doctype)
2924 },
2925 NodeTypeId::Attr => {
2926 let attr = node.downcast::<Attr>().unwrap();
2927 let attr = Attr::new(
2928 &document,
2929 attr.local_name().clone(),
2930 attr.value().clone(),
2931 attr.name().clone(),
2932 attr.namespace().clone(),
2933 attr.prefix().cloned(),
2934 None,
2935 can_gc,
2936 );
2937 DomRoot::upcast::<Node>(attr)
2938 },
2939 NodeTypeId::DocumentFragment(_) => {
2940 let doc_fragment = DocumentFragment::new(&document, can_gc);
2941 DomRoot::upcast::<Node>(doc_fragment)
2942 },
2943 NodeTypeId::CharacterData(_) => {
2944 let cdata = node.downcast::<CharacterData>().unwrap();
2945 cdata.clone_with_data(cdata.Data(), &document, can_gc)
2946 },
2947 NodeTypeId::Document(_) => {
2948 let document = node.downcast::<Document>().unwrap();
2949 let is_html_doc = if document.is_html_document() {
2950 IsHTMLDocument::HTMLDocument
2951 } else {
2952 IsHTMLDocument::NonHTMLDocument
2953 };
2954 let window = document.window();
2955 let loader = DocumentLoader::new(&document.loader());
2956 let document = Document::new(
2957 window,
2958 HasBrowsingContext::No,
2959 Some(document.url()),
2960 document.origin().clone(),
2962 is_html_doc,
2963 None,
2964 None,
2965 DocumentActivity::Inactive,
2966 DocumentSource::NotFromParser,
2967 loader,
2968 None,
2969 document.status_code(),
2970 Default::default(),
2971 false,
2972 document.allow_declarative_shadow_roots(),
2973 Some(document.insecure_requests_policy()),
2974 document.has_trustworthy_ancestor_or_current_origin(),
2975 document.custom_element_reaction_stack(),
2976 document.creation_sandboxing_flag_set(),
2977 can_gc,
2978 );
2979 DomRoot::upcast::<Node>(document)
2980 },
2981 NodeTypeId::Element(..) => {
2982 let element = node.downcast::<Element>().unwrap();
2983 let name = QualName {
2984 prefix: element.prefix().as_ref().map(|p| Prefix::from(&**p)),
2985 ns: element.namespace().clone(),
2986 local: element.local_name().clone(),
2987 };
2988 let element = Element::create(
2989 name,
2990 element.get_is(),
2991 &document,
2992 ElementCreator::ScriptCreated,
2993 CustomElementCreationMode::Asynchronous,
2994 None,
2995 can_gc,
2996 );
2997 DomRoot::upcast::<Node>(element)
2998 },
2999 };
3000
3001 let document = match copy.downcast::<Document>() {
3004 Some(doc) => DomRoot::from_ref(doc),
3005 None => DomRoot::from_ref(&*document),
3006 };
3007 assert!(copy.owner_doc() == document);
3008
3009 match node.type_id() {
3011 NodeTypeId::Document(_) => {
3012 let node_doc = node.downcast::<Document>().unwrap();
3013 let copy_doc = copy.downcast::<Document>().unwrap();
3014 copy_doc.set_encoding(node_doc.encoding());
3015 copy_doc.set_quirks_mode(node_doc.quirks_mode());
3016 },
3017 NodeTypeId::Element(..) => {
3018 let node_elem = node.downcast::<Element>().unwrap();
3019 let copy_elem = copy.downcast::<Element>().unwrap();
3020
3021 for attr in node_elem.attrs().iter() {
3022 let new_value =
3023 Node::compute_attribute_value_with_style_fast_path(attr, node_elem);
3024 copy_elem.push_new_attribute(
3025 attr.local_name().clone(),
3026 new_value,
3027 attr.name().clone(),
3028 attr.namespace().clone(),
3029 attr.prefix().cloned(),
3030 AttributeMutationReason::ByCloning,
3031 can_gc,
3032 );
3033 }
3034 },
3035 _ => (),
3036 }
3037
3038 vtable_for(node).cloning_steps(©, maybe_doc, clone_children, can_gc);
3041
3042 if clone_children == CloneChildrenFlag::CloneChildren {
3045 for child in node.children() {
3046 let child_copy = Node::clone(&child, Some(&document), clone_children, can_gc);
3047 let _inserted_node = Node::pre_insert(&child_copy, ©, None, can_gc);
3048 }
3049 }
3050
3051 if matches!(node.type_id(), NodeTypeId::Element(_)) {
3054 let node_elem = node.downcast::<Element>().unwrap();
3055 let copy_elem = copy.downcast::<Element>().unwrap();
3056
3057 if let Some(shadow_root) = node_elem.shadow_root().filter(|r| r.Clonable()) {
3058 assert!(!copy_elem.is_shadow_host());
3060
3061 let copy_shadow_root =
3065 copy_elem.attach_shadow(
3066 IsUserAgentWidget::No,
3067 shadow_root.Mode(),
3068 shadow_root.Clonable(),
3069 shadow_root.Serializable(),
3070 shadow_root.DelegatesFocus(),
3071 shadow_root.SlotAssignment(),
3072 can_gc
3073 )
3074 .expect("placement of attached shadow root must be valid, as this is a copy of an existing one");
3075
3076 copy_shadow_root.set_declarative(shadow_root.is_declarative());
3078
3079 for child in shadow_root.upcast::<Node>().children() {
3082 let child_copy = Node::clone(
3083 &child,
3084 Some(&document),
3085 CloneChildrenFlag::CloneChildren,
3086 can_gc,
3087 );
3088
3089 let _inserted_node = Node::pre_insert(
3091 &child_copy,
3092 copy_shadow_root.upcast::<Node>(),
3093 None,
3094 can_gc,
3095 );
3096 }
3097 }
3098 }
3099
3100 copy
3102 }
3103
3104 pub(crate) fn child_text_content(&self) -> DOMString {
3106 Node::collect_text_contents(self.children())
3107 }
3108
3109 pub(crate) fn descendant_text_content(&self) -> DOMString {
3111 Node::collect_text_contents(self.traverse_preorder(ShadowIncluding::No))
3112 }
3113
3114 pub(crate) fn collect_text_contents<T: Iterator<Item = DomRoot<Node>>>(
3115 iterator: T,
3116 ) -> DOMString {
3117 let mut content = String::new();
3118 for node in iterator {
3119 if let Some(text) = node.downcast::<Text>() {
3120 content.push_str(&text.upcast::<CharacterData>().data());
3121 }
3122 }
3123 DOMString::from(content)
3124 }
3125
3126 pub(crate) fn set_text_content_for_element(&self, value: Option<DOMString>, can_gc: CanGc) {
3128 assert!(matches!(
3131 self.type_id(),
3132 NodeTypeId::DocumentFragment(_) | NodeTypeId::Element(..)
3133 ));
3134 let value = value.unwrap_or_default();
3135 let node = if value.is_empty() {
3136 None
3138 } else {
3139 Some(DomRoot::upcast(
3142 self.owner_doc().CreateTextNode(value, can_gc),
3143 ))
3144 };
3145
3146 Self::replace_all(node.as_deref(), self, can_gc);
3148 }
3149
3150 pub(crate) fn namespace_to_string(namespace: Namespace) -> Option<DOMString> {
3151 match namespace {
3152 ns!() => None,
3153 _ => Some(DOMString::from(&*namespace)),
3155 }
3156 }
3157
3158 pub(crate) fn locate_namespace(node: &Node, prefix: Option<DOMString>) -> Namespace {
3160 match node.type_id() {
3161 NodeTypeId::Element(_) => node.downcast::<Element>().unwrap().locate_namespace(prefix),
3162 NodeTypeId::Attr => node
3163 .downcast::<Attr>()
3164 .unwrap()
3165 .GetOwnerElement()
3166 .as_ref()
3167 .map_or(ns!(), |elem| elem.locate_namespace(prefix)),
3168 NodeTypeId::Document(_) => node
3169 .downcast::<Document>()
3170 .unwrap()
3171 .GetDocumentElement()
3172 .as_ref()
3173 .map_or(ns!(), |elem| elem.locate_namespace(prefix)),
3174 NodeTypeId::DocumentType | NodeTypeId::DocumentFragment(_) => ns!(),
3175 _ => node
3176 .GetParentElement()
3177 .as_ref()
3178 .map_or(ns!(), |elem| elem.locate_namespace(prefix)),
3179 }
3180 }
3181
3182 #[expect(unsafe_code)]
3190 pub(crate) unsafe fn from_untrusted_node_address(
3191 candidate: UntrustedNodeAddress,
3192 ) -> &'static Self {
3193 let candidate = candidate.0 as usize;
3195 let object = candidate as *mut JSObject;
3196 if object.is_null() {
3197 panic!("Attempted to create a `Node` from an invalid pointer!")
3198 }
3199
3200 unsafe { &*(conversions::private_from_object(object) as *const Self) }
3201 }
3202
3203 pub(crate) fn html_serialize(
3204 &self,
3205 traversal_scope: html_serialize::TraversalScope,
3206 serialize_shadow_roots: bool,
3207 shadow_roots: Vec<DomRoot<ShadowRoot>>,
3208 can_gc: CanGc,
3209 ) -> DOMString {
3210 let mut writer = vec![];
3211 let mut serializer = HtmlSerializer::new(
3212 &mut writer,
3213 html_serialize::SerializeOpts {
3214 traversal_scope: traversal_scope.clone(),
3215 ..Default::default()
3216 },
3217 );
3218
3219 serialize_html_fragment(
3220 self,
3221 &mut serializer,
3222 traversal_scope,
3223 serialize_shadow_roots,
3224 shadow_roots,
3225 can_gc,
3226 )
3227 .expect("Serializing node failed");
3228
3229 DOMString::from(String::from_utf8(writer).unwrap())
3231 }
3232
3233 pub(crate) fn xml_serialize(
3235 &self,
3236 traversal_scope: xml_serialize::TraversalScope,
3237 ) -> Fallible<DOMString> {
3238 let mut writer = vec![];
3239 xml_serialize::serialize(
3240 &mut writer,
3241 &HtmlSerialize::new(self),
3242 xml_serialize::SerializeOpts { traversal_scope },
3243 )
3244 .map_err(|error| {
3245 error!("Cannot serialize node: {error}");
3246 Error::InvalidState(None)
3247 })?;
3248
3249 let string = DOMString::from(String::from_utf8(writer).map_err(|error| {
3251 error!("Cannot serialize node: {error}");
3252 Error::InvalidState(None)
3253 })?);
3254
3255 Ok(string)
3256 }
3257
3258 pub(crate) fn fragment_serialization_algorithm(
3260 &self,
3261 require_well_formed: bool,
3262 can_gc: CanGc,
3263 ) -> Fallible<DOMString> {
3264 let context_document = self.owner_document();
3266
3267 if context_document.is_html_document() {
3270 return Ok(self.html_serialize(
3271 html_serialize::TraversalScope::ChildrenOnly(None),
3272 false,
3273 vec![],
3274 can_gc,
3275 ));
3276 }
3277
3278 let _ = require_well_formed;
3281 self.xml_serialize(xml_serialize::TraversalScope::ChildrenOnly(None))
3282 }
3283
3284 pub(crate) fn establishes_scrolling_box(&self) -> bool {
3286 if self.is::<Document>() {
3291 return true;
3292 }
3293 let Some(element) = self.downcast::<Element>() else {
3294 return false;
3296 };
3297 element.style().is_some_and(|style| {
3300 let overflow_x = style.get_box().clone_overflow_x();
3301 let overflow_y = style.get_box().clone_overflow_y();
3302 overflow_x.is_scrollable() || overflow_y.is_scrollable()
3303 })
3304 }
3305}
3306
3307impl NodeMethods<crate::DomTypeHolder> for Node {
3308 fn NodeType(&self) -> u16 {
3310 match self.type_id() {
3311 NodeTypeId::Attr => NodeConstants::ATTRIBUTE_NODE,
3312 NodeTypeId::CharacterData(CharacterDataTypeId::Text(TextTypeId::Text)) => {
3313 NodeConstants::TEXT_NODE
3314 },
3315 NodeTypeId::CharacterData(CharacterDataTypeId::Text(TextTypeId::CDATASection)) => {
3316 NodeConstants::CDATA_SECTION_NODE
3317 },
3318 NodeTypeId::CharacterData(CharacterDataTypeId::ProcessingInstruction) => {
3319 NodeConstants::PROCESSING_INSTRUCTION_NODE
3320 },
3321 NodeTypeId::CharacterData(CharacterDataTypeId::Comment) => NodeConstants::COMMENT_NODE,
3322 NodeTypeId::Document(_) => NodeConstants::DOCUMENT_NODE,
3323 NodeTypeId::DocumentType => NodeConstants::DOCUMENT_TYPE_NODE,
3324 NodeTypeId::DocumentFragment(_) => NodeConstants::DOCUMENT_FRAGMENT_NODE,
3325 NodeTypeId::Element(_) => NodeConstants::ELEMENT_NODE,
3326 }
3327 }
3328
3329 fn NodeName(&self) -> DOMString {
3331 match self.type_id() {
3332 NodeTypeId::Attr => self.downcast::<Attr>().unwrap().qualified_name(),
3333 NodeTypeId::Element(..) => self.downcast::<Element>().unwrap().TagName(),
3334 NodeTypeId::CharacterData(CharacterDataTypeId::Text(TextTypeId::Text)) => {
3335 DOMString::from("#text")
3336 },
3337 NodeTypeId::CharacterData(CharacterDataTypeId::Text(TextTypeId::CDATASection)) => {
3338 DOMString::from("#cdata-section")
3339 },
3340 NodeTypeId::CharacterData(CharacterDataTypeId::ProcessingInstruction) => {
3341 self.downcast::<ProcessingInstruction>().unwrap().Target()
3342 },
3343 NodeTypeId::CharacterData(CharacterDataTypeId::Comment) => DOMString::from("#comment"),
3344 NodeTypeId::DocumentType => self.downcast::<DocumentType>().unwrap().name().clone(),
3345 NodeTypeId::DocumentFragment(_) => DOMString::from("#document-fragment"),
3346 NodeTypeId::Document(_) => DOMString::from("#document"),
3347 }
3348 }
3349
3350 fn BaseURI(&self) -> USVString {
3352 USVString(String::from(self.owner_doc().base_url().as_str()))
3353 }
3354
3355 fn IsConnected(&self) -> bool {
3357 self.is_connected()
3358 }
3359
3360 fn GetOwnerDocument(&self) -> Option<DomRoot<Document>> {
3362 match self.type_id() {
3363 NodeTypeId::Document(_) => None,
3364 _ => Some(self.owner_doc()),
3365 }
3366 }
3367
3368 fn GetRootNode(&self, options: &GetRootNodeOptions) -> DomRoot<Node> {
3370 if !options.composed {
3371 if let Some(shadow_root) = self.containing_shadow_root() {
3372 return DomRoot::upcast(shadow_root);
3373 }
3374 }
3375
3376 if self.is_connected() {
3377 DomRoot::from_ref(self.owner_doc().upcast::<Node>())
3378 } else {
3379 self.inclusive_ancestors(ShadowIncluding::Yes)
3380 .last()
3381 .unwrap()
3382 }
3383 }
3384
3385 fn GetParentNode(&self) -> Option<DomRoot<Node>> {
3387 self.parent_node.get()
3388 }
3389
3390 fn GetParentElement(&self) -> Option<DomRoot<Element>> {
3392 self.GetParentNode().and_then(DomRoot::downcast)
3393 }
3394
3395 fn HasChildNodes(&self) -> bool {
3397 self.first_child.get().is_some()
3398 }
3399
3400 fn ChildNodes(&self, can_gc: CanGc) -> DomRoot<NodeList> {
3402 if let Some(list) = self.ensure_rare_data().child_list.get() {
3403 return list;
3404 }
3405
3406 let doc = self.owner_doc();
3407 let window = doc.window();
3408 let list = NodeList::new_child_list(window, self, can_gc);
3409 self.ensure_rare_data().child_list.set(Some(&list));
3410 list
3411 }
3412
3413 fn GetFirstChild(&self) -> Option<DomRoot<Node>> {
3415 self.first_child.get()
3416 }
3417
3418 fn GetLastChild(&self) -> Option<DomRoot<Node>> {
3420 self.last_child.get()
3421 }
3422
3423 fn GetPreviousSibling(&self) -> Option<DomRoot<Node>> {
3425 self.prev_sibling.get()
3426 }
3427
3428 fn GetNextSibling(&self) -> Option<DomRoot<Node>> {
3430 self.next_sibling.get()
3431 }
3432
3433 fn GetNodeValue(&self) -> Option<DOMString> {
3435 match self.type_id() {
3436 NodeTypeId::Attr => Some(self.downcast::<Attr>().unwrap().Value()),
3437 NodeTypeId::CharacterData(_) => {
3438 self.downcast::<CharacterData>().map(CharacterData::Data)
3439 },
3440 _ => None,
3441 }
3442 }
3443
3444 fn SetNodeValue(&self, val: Option<DOMString>, can_gc: CanGc) -> Fallible<()> {
3446 match self.type_id() {
3447 NodeTypeId::Attr => {
3448 let attr = self.downcast::<Attr>().unwrap();
3449 attr.SetValue(val.unwrap_or_default(), can_gc)?;
3450 },
3451 NodeTypeId::CharacterData(_) => {
3452 let character_data = self.downcast::<CharacterData>().unwrap();
3453 character_data.SetData(val.unwrap_or_default());
3454 },
3455 _ => {},
3456 };
3457 Ok(())
3458 }
3459
3460 fn GetTextContent(&self) -> Option<DOMString> {
3462 match self.type_id() {
3463 NodeTypeId::DocumentFragment(_) | NodeTypeId::Element(..) => {
3464 let content =
3465 Node::collect_text_contents(self.traverse_preorder(ShadowIncluding::No));
3466 Some(content)
3467 },
3468 NodeTypeId::Attr => Some(self.downcast::<Attr>().unwrap().Value()),
3469 NodeTypeId::CharacterData(..) => {
3470 let characterdata = self.downcast::<CharacterData>().unwrap();
3471 Some(characterdata.Data())
3472 },
3473 NodeTypeId::DocumentType | NodeTypeId::Document(_) => None,
3474 }
3475 }
3476
3477 fn SetTextContent(&self, value: Option<DOMString>, can_gc: CanGc) -> Fallible<()> {
3479 match self.type_id() {
3480 NodeTypeId::DocumentFragment(_) | NodeTypeId::Element(..) => {
3481 self.set_text_content_for_element(value, can_gc);
3482 },
3483 NodeTypeId::Attr => {
3484 let attr = self.downcast::<Attr>().unwrap();
3485 attr.SetValue(value.unwrap_or_default(), can_gc)?;
3486 },
3487 NodeTypeId::CharacterData(..) => {
3488 let characterdata = self.downcast::<CharacterData>().unwrap();
3489 characterdata.SetData(value.unwrap_or_default());
3490 },
3491 NodeTypeId::DocumentType | NodeTypeId::Document(_) => {},
3492 };
3493 Ok(())
3494 }
3495
3496 fn InsertBefore(
3498 &self,
3499 node: &Node,
3500 child: Option<&Node>,
3501 can_gc: CanGc,
3502 ) -> Fallible<DomRoot<Node>> {
3503 Node::pre_insert(node, self, child, can_gc)
3504 }
3505
3506 fn AppendChild(&self, node: &Node, can_gc: CanGc) -> Fallible<DomRoot<Node>> {
3508 Node::pre_insert(node, self, None, can_gc)
3509 }
3510
3511 fn ReplaceChild(&self, node: &Node, child: &Node, can_gc: CanGc) -> Fallible<DomRoot<Node>> {
3513 match self.type_id() {
3516 NodeTypeId::Document(_) | NodeTypeId::DocumentFragment(_) | NodeTypeId::Element(..) => {
3517 },
3518 _ => return Err(Error::HierarchyRequest(None)),
3519 }
3520
3521 if node.is_inclusive_ancestor_of(self) {
3524 return Err(Error::HierarchyRequest(None));
3525 }
3526
3527 if !self.is_parent_of(child) {
3529 return Err(Error::NotFound(None));
3530 }
3531
3532 match node.type_id() {
3537 NodeTypeId::CharacterData(CharacterDataTypeId::Text(_)) if self.is::<Document>() => {
3538 return Err(Error::HierarchyRequest(None));
3539 },
3540 NodeTypeId::DocumentType if !self.is::<Document>() => {
3541 return Err(Error::HierarchyRequest(None));
3542 },
3543 NodeTypeId::Document(_) | NodeTypeId::Attr => {
3544 return Err(Error::HierarchyRequest(None));
3545 },
3546 _ => (),
3547 }
3548
3549 if self.is::<Document>() {
3552 match node.type_id() {
3553 NodeTypeId::DocumentFragment(_) => {
3555 if node.children().any(|c| c.is::<Text>()) {
3557 return Err(Error::HierarchyRequest(None));
3558 }
3559 match node.child_elements().count() {
3560 0 => (),
3561 1 => {
3563 if self.child_elements().any(|c| c.upcast::<Node>() != child) {
3564 return Err(Error::HierarchyRequest(None));
3565 }
3566 if child.following_siblings().any(|child| child.is_doctype()) {
3567 return Err(Error::HierarchyRequest(None));
3568 }
3569 },
3570 _ => return Err(Error::HierarchyRequest(None)),
3572 }
3573 },
3574 NodeTypeId::Element(..) => {
3576 if self.child_elements().any(|c| c.upcast::<Node>() != child) {
3577 return Err(Error::HierarchyRequest(None));
3578 }
3579 if child.following_siblings().any(|child| child.is_doctype()) {
3580 return Err(Error::HierarchyRequest(None));
3581 }
3582 },
3583 NodeTypeId::DocumentType => {
3585 if self.children().any(|c| c.is_doctype() && &*c != child) {
3586 return Err(Error::HierarchyRequest(None));
3587 }
3588 if self
3589 .children()
3590 .take_while(|c| &**c != child)
3591 .any(|c| c.is::<Element>())
3592 {
3593 return Err(Error::HierarchyRequest(None));
3594 }
3595 },
3596 NodeTypeId::CharacterData(..) => (),
3597 NodeTypeId::Document(_) => unreachable!(),
3600 NodeTypeId::Attr => unreachable!(),
3601 }
3602 }
3603
3604 let child_next_sibling = child.GetNextSibling();
3607 let node_next_sibling = node.GetNextSibling();
3608 let reference_child = if child_next_sibling.as_deref() == Some(node) {
3609 node_next_sibling.as_deref()
3610 } else {
3611 child_next_sibling.as_deref()
3612 };
3613
3614 let previous_sibling = child.GetPreviousSibling();
3616
3617 let document = self.owner_document();
3621 Node::adopt(node, &document, can_gc);
3622
3623 let removed_child = if node != child {
3628 Node::remove(child, self, SuppressObserver::Suppressed, can_gc);
3630 Some(child)
3631 } else {
3632 None
3633 };
3634
3635 rooted_vec!(let mut nodes);
3637 let nodes = if node.type_id() ==
3638 NodeTypeId::DocumentFragment(DocumentFragmentTypeId::DocumentFragment) ||
3639 node.type_id() == NodeTypeId::DocumentFragment(DocumentFragmentTypeId::ShadowRoot)
3640 {
3641 nodes.extend(node.children().map(|node| Dom::from_ref(&*node)));
3642 nodes.r()
3643 } else {
3644 from_ref(&node)
3645 };
3646
3647 Node::insert(
3649 node,
3650 self,
3651 reference_child,
3652 SuppressObserver::Suppressed,
3653 can_gc,
3654 );
3655
3656 vtable_for(self).children_changed(
3657 &ChildrenMutation::replace(
3658 previous_sibling.as_deref(),
3659 &removed_child,
3660 nodes,
3661 reference_child,
3662 ),
3663 can_gc,
3664 );
3665
3666 let removed = removed_child.map(|r| [r]);
3669 let mutation = LazyCell::new(|| Mutation::ChildList {
3670 added: Some(nodes),
3671 removed: removed.as_ref().map(|r| &r[..]),
3672 prev: previous_sibling.as_deref(),
3673 next: reference_child,
3674 });
3675
3676 MutationObserver::queue_a_mutation_record(self, mutation);
3677
3678 Ok(DomRoot::from_ref(child))
3680 }
3681
3682 fn RemoveChild(&self, node: &Node, can_gc: CanGc) -> Fallible<DomRoot<Node>> {
3684 Node::pre_remove(node, self, can_gc)
3685 }
3686
3687 fn Normalize(&self, can_gc: CanGc) {
3689 let mut children = self.children().enumerate().peekable();
3690 while let Some((_, node)) = children.next() {
3691 if let Some(text) = node.downcast::<Text>() {
3692 if text.is::<CDATASection>() {
3693 continue;
3694 }
3695 let cdata = text.upcast::<CharacterData>();
3696 let mut length = cdata.Length();
3697 if length == 0 {
3698 Node::remove(&node, self, SuppressObserver::Unsuppressed, can_gc);
3699 continue;
3700 }
3701 while children.peek().is_some_and(|(_, sibling)| {
3702 sibling.is::<Text>() && !sibling.is::<CDATASection>()
3703 }) {
3704 let (index, sibling) = children.next().unwrap();
3705 sibling
3706 .ranges()
3707 .drain_to_preceding_text_sibling(&sibling, &node, length);
3708 self.ranges()
3709 .move_to_text_child_at(self, index as u32, &node, length);
3710 let sibling_cdata = sibling.downcast::<CharacterData>().unwrap();
3711 length += sibling_cdata.Length();
3712 cdata.append_data(&sibling_cdata.data());
3713 Node::remove(&sibling, self, SuppressObserver::Unsuppressed, can_gc);
3714 }
3715 } else {
3716 node.Normalize(can_gc);
3717 }
3718 }
3719 }
3720
3721 fn CloneNode(&self, subtree: bool, can_gc: CanGc) -> Fallible<DomRoot<Node>> {
3723 if self.is::<ShadowRoot>() {
3725 return Err(Error::NotSupported);
3726 }
3727
3728 let result = Node::clone(
3730 self,
3731 None,
3732 if subtree {
3733 CloneChildrenFlag::CloneChildren
3734 } else {
3735 CloneChildrenFlag::DoNotCloneChildren
3736 },
3737 can_gc,
3738 );
3739 Ok(result)
3740 }
3741
3742 fn IsEqualNode(&self, maybe_node: Option<&Node>) -> bool {
3744 fn is_equal_doctype(node: &Node, other: &Node) -> bool {
3745 let doctype = node.downcast::<DocumentType>().unwrap();
3746 let other_doctype = other.downcast::<DocumentType>().unwrap();
3747 (*doctype.name() == *other_doctype.name()) &&
3748 (*doctype.public_id() == *other_doctype.public_id()) &&
3749 (*doctype.system_id() == *other_doctype.system_id())
3750 }
3751 fn is_equal_element(node: &Node, other: &Node) -> bool {
3752 let element = node.downcast::<Element>().unwrap();
3753 let other_element = other.downcast::<Element>().unwrap();
3754 (*element.namespace() == *other_element.namespace()) &&
3755 (*element.prefix() == *other_element.prefix()) &&
3756 (*element.local_name() == *other_element.local_name()) &&
3757 (element.attrs().len() == other_element.attrs().len())
3758 }
3759 fn is_equal_processinginstruction(node: &Node, other: &Node) -> bool {
3760 let pi = node.downcast::<ProcessingInstruction>().unwrap();
3761 let other_pi = other.downcast::<ProcessingInstruction>().unwrap();
3762 (*pi.target() == *other_pi.target()) &&
3763 (*pi.upcast::<CharacterData>().data() ==
3764 *other_pi.upcast::<CharacterData>().data())
3765 }
3766 fn is_equal_characterdata(node: &Node, other: &Node) -> bool {
3767 let characterdata = node.downcast::<CharacterData>().unwrap();
3768 let other_characterdata = other.downcast::<CharacterData>().unwrap();
3769 *characterdata.data() == *other_characterdata.data()
3770 }
3771 fn is_equal_attr(node: &Node, other: &Node) -> bool {
3772 let attr = node.downcast::<Attr>().unwrap();
3773 let other_attr = other.downcast::<Attr>().unwrap();
3774 (*attr.namespace() == *other_attr.namespace()) &&
3775 (attr.local_name() == other_attr.local_name()) &&
3776 (**attr.value() == **other_attr.value())
3777 }
3778 fn is_equal_element_attrs(node: &Node, other: &Node) -> bool {
3779 let element = node.downcast::<Element>().unwrap();
3780 let other_element = other.downcast::<Element>().unwrap();
3781 assert!(element.attrs().len() == other_element.attrs().len());
3782 element.attrs().iter().all(|attr| {
3783 other_element.attrs().iter().any(|other_attr| {
3784 (*attr.namespace() == *other_attr.namespace()) &&
3785 (attr.local_name() == other_attr.local_name()) &&
3786 (**attr.value() == **other_attr.value())
3787 })
3788 })
3789 }
3790
3791 fn is_equal_node(this: &Node, node: &Node) -> bool {
3792 if this.NodeType() != node.NodeType() {
3794 return false;
3795 }
3796
3797 match node.type_id() {
3798 NodeTypeId::DocumentType if !is_equal_doctype(this, node) => return false,
3800 NodeTypeId::Element(..) if !is_equal_element(this, node) => return false,
3801 NodeTypeId::CharacterData(CharacterDataTypeId::ProcessingInstruction)
3802 if !is_equal_processinginstruction(this, node) =>
3803 {
3804 return false;
3805 },
3806 NodeTypeId::CharacterData(CharacterDataTypeId::Text(_)) |
3807 NodeTypeId::CharacterData(CharacterDataTypeId::Comment)
3808 if !is_equal_characterdata(this, node) =>
3809 {
3810 return false;
3811 },
3812 NodeTypeId::Element(..) if !is_equal_element_attrs(this, node) => return false,
3814 NodeTypeId::Attr if !is_equal_attr(this, node) => return false,
3815
3816 _ => (),
3817 }
3818
3819 if this.children_count() != node.children_count() {
3821 return false;
3822 }
3823
3824 this.children()
3826 .zip(node.children())
3827 .all(|(child, other_child)| is_equal_node(&child, &other_child))
3828 }
3829 match maybe_node {
3830 None => false,
3832 Some(node) => is_equal_node(self, node),
3834 }
3835 }
3836
3837 fn IsSameNode(&self, other_node: Option<&Node>) -> bool {
3839 match other_node {
3840 Some(node) => self == node,
3841 None => false,
3842 }
3843 }
3844
3845 fn CompareDocumentPosition(&self, other: &Node) -> u16 {
3847 if self == other {
3849 return 0;
3850 }
3851
3852 let mut node1 = Some(other);
3854 let mut node2 = Some(self);
3855
3856 let mut attr1: Option<&Attr> = None;
3858 let mut attr2: Option<&Attr> = None;
3859
3860 let attr1owner;
3865 if let Some(a) = other.downcast::<Attr>() {
3866 attr1 = Some(a);
3867 attr1owner = a.GetOwnerElement();
3868 node1 = match attr1owner {
3869 Some(ref e) => Some(e.upcast()),
3870 None => None,
3871 }
3872 }
3873
3874 let attr2owner;
3877 if let Some(a) = self.downcast::<Attr>() {
3878 attr2 = Some(a);
3879 attr2owner = a.GetOwnerElement();
3880 node2 = match attr2owner {
3881 Some(ref e) => Some(e.upcast()),
3882 None => None,
3883 }
3884 }
3885
3886 if let Some(node2) = node2 {
3891 if Some(node2) == node1 {
3892 if let (Some(a1), Some(a2)) = (attr1, attr2) {
3893 let attrs = node2.downcast::<Element>().unwrap().attrs();
3894 for attr in attrs.iter() {
3898 if (*attr.namespace() == *a1.namespace()) &&
3899 (attr.local_name() == a1.local_name()) &&
3900 (**attr.value() == **a1.value())
3901 {
3902 return NodeConstants::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC +
3903 NodeConstants::DOCUMENT_POSITION_PRECEDING;
3904 }
3905 if (*attr.namespace() == *a2.namespace()) &&
3906 (attr.local_name() == a2.local_name()) &&
3907 (**attr.value() == **a2.value())
3908 {
3909 return NodeConstants::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC +
3910 NodeConstants::DOCUMENT_POSITION_FOLLOWING;
3911 }
3912 }
3913 unreachable!();
3916 }
3917 }
3918 }
3919
3920 match (node1, node2) {
3922 (None, _) => {
3923 NodeConstants::DOCUMENT_POSITION_FOLLOWING +
3925 NodeConstants::DOCUMENT_POSITION_DISCONNECTED +
3926 NodeConstants::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC
3927 },
3928 (_, None) => {
3929 NodeConstants::DOCUMENT_POSITION_PRECEDING +
3931 NodeConstants::DOCUMENT_POSITION_DISCONNECTED +
3932 NodeConstants::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC
3933 },
3934 (Some(node1), Some(node2)) => {
3935 let mut self_and_ancestors = node2
3937 .inclusive_ancestors(ShadowIncluding::No)
3938 .collect::<SmallVec<[_; 20]>>();
3939 let mut other_and_ancestors = node1
3940 .inclusive_ancestors(ShadowIncluding::No)
3941 .collect::<SmallVec<[_; 20]>>();
3942
3943 if self_and_ancestors.last() != other_and_ancestors.last() {
3944 let random = as_uintptr(self_and_ancestors.last().unwrap()) <
3945 as_uintptr(other_and_ancestors.last().unwrap());
3946 let random = if random {
3947 NodeConstants::DOCUMENT_POSITION_FOLLOWING
3948 } else {
3949 NodeConstants::DOCUMENT_POSITION_PRECEDING
3950 };
3951
3952 return random +
3954 NodeConstants::DOCUMENT_POSITION_DISCONNECTED +
3955 NodeConstants::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC;
3956 }
3957 let mut parent = self_and_ancestors.pop().unwrap();
3959 other_and_ancestors.pop().unwrap();
3960
3961 let mut current_position =
3962 cmp::min(self_and_ancestors.len(), other_and_ancestors.len());
3963
3964 while current_position > 0 {
3965 current_position -= 1;
3966 let child_1 = self_and_ancestors.pop().unwrap();
3967 let child_2 = other_and_ancestors.pop().unwrap();
3968
3969 if child_1 != child_2 {
3970 let is_before = parent.children().position(|c| c == child_1).unwrap() <
3971 parent.children().position(|c| c == child_2).unwrap();
3972 return if is_before {
3975 NodeConstants::DOCUMENT_POSITION_FOLLOWING
3976 } else {
3977 NodeConstants::DOCUMENT_POSITION_PRECEDING
3978 };
3979 }
3980
3981 parent = child_1;
3982 }
3983
3984 if self_and_ancestors.len() < other_and_ancestors.len() {
3989 NodeConstants::DOCUMENT_POSITION_FOLLOWING +
3990 NodeConstants::DOCUMENT_POSITION_CONTAINED_BY
3991 } else {
3992 NodeConstants::DOCUMENT_POSITION_PRECEDING +
3993 NodeConstants::DOCUMENT_POSITION_CONTAINS
3994 }
3995 },
3996 }
3997 }
3998
3999 fn Contains(&self, maybe_other: Option<&Node>) -> bool {
4001 match maybe_other {
4002 None => false,
4003 Some(other) => self.is_inclusive_ancestor_of(other),
4004 }
4005 }
4006
4007 fn LookupPrefix(&self, namespace: Option<DOMString>) -> Option<DOMString> {
4009 let namespace = namespace_from_domstring(namespace);
4010
4011 if namespace == ns!() {
4013 return None;
4014 }
4015
4016 match self.type_id() {
4018 NodeTypeId::Element(..) => self.downcast::<Element>().unwrap().lookup_prefix(namespace),
4019 NodeTypeId::Document(_) => self
4020 .downcast::<Document>()
4021 .unwrap()
4022 .GetDocumentElement()
4023 .and_then(|element| element.lookup_prefix(namespace)),
4024 NodeTypeId::DocumentType | NodeTypeId::DocumentFragment(_) => None,
4025 NodeTypeId::Attr => self
4026 .downcast::<Attr>()
4027 .unwrap()
4028 .GetOwnerElement()
4029 .and_then(|element| element.lookup_prefix(namespace)),
4030 _ => self
4031 .GetParentElement()
4032 .and_then(|element| element.lookup_prefix(namespace)),
4033 }
4034 }
4035
4036 fn LookupNamespaceURI(&self, prefix: Option<DOMString>) -> Option<DOMString> {
4038 let prefix = prefix.filter(|prefix| !prefix.is_empty());
4040
4041 Node::namespace_to_string(Node::locate_namespace(self, prefix))
4043 }
4044
4045 fn IsDefaultNamespace(&self, namespace: Option<DOMString>) -> bool {
4047 let namespace = namespace_from_domstring(namespace);
4049 Node::locate_namespace(self, None) == namespace
4051 }
4052}
4053
4054pub(crate) trait NodeTraits {
4055 fn owner_document(&self) -> DomRoot<Document>;
4059 fn owner_window(&self) -> DomRoot<Window>;
4063 fn owner_global(&self) -> DomRoot<GlobalScope>;
4067 fn containing_shadow_root(&self) -> Option<DomRoot<ShadowRoot>>;
4069 #[cfg_attr(crown, allow(crown::unrooted_must_root))]
4072 fn stylesheet_list_owner(&self) -> StyleSheetListOwner;
4073}
4074
4075impl<T: DerivedFrom<Node> + DomObject> NodeTraits for T {
4076 fn owner_document(&self) -> DomRoot<Document> {
4077 self.upcast().owner_doc()
4078 }
4079
4080 fn owner_window(&self) -> DomRoot<Window> {
4081 DomRoot::from_ref(self.owner_document().window())
4082 }
4083
4084 fn owner_global(&self) -> DomRoot<GlobalScope> {
4085 DomRoot::from_ref(self.owner_window().upcast())
4086 }
4087
4088 fn containing_shadow_root(&self) -> Option<DomRoot<ShadowRoot>> {
4089 Node::containing_shadow_root(self.upcast())
4090 }
4091
4092 #[cfg_attr(crown, allow(crown::unrooted_must_root))]
4093 fn stylesheet_list_owner(&self) -> StyleSheetListOwner {
4094 self.containing_shadow_root()
4095 .map(|shadow_root| StyleSheetListOwner::ShadowRoot(Dom::from_ref(&*shadow_root)))
4096 .unwrap_or_else(|| {
4097 StyleSheetListOwner::Document(Dom::from_ref(&*self.owner_document()))
4098 })
4099 }
4100}
4101
4102impl VirtualMethods for Node {
4103 fn super_type(&self) -> Option<&dyn VirtualMethods> {
4104 Some(self.upcast::<EventTarget>() as &dyn VirtualMethods)
4105 }
4106
4107 fn children_changed(&self, mutation: &ChildrenMutation, can_gc: CanGc) {
4108 if let Some(s) = self.super_type() {
4109 s.children_changed(mutation, can_gc);
4110 }
4111
4112 if let Some(data) = self.rare_data().as_ref() {
4113 if let Some(list) = data.child_list.get() {
4114 list.as_children_list().children_changed(mutation);
4115 }
4116 }
4117
4118 self.owner_doc().content_and_heritage_changed(self);
4119 }
4120
4121 fn unbind_from_tree(&self, context: &UnbindContext, can_gc: CanGc) {
4124 self.super_type().unwrap().unbind_from_tree(context, can_gc);
4125
4126 if !self.is_in_a_shadow_tree() && !self.ranges_is_empty() {
4131 self.ranges().drain_to_parent(context, self);
4132 }
4133 }
4134
4135 fn handle_event(&self, event: &Event, _: CanGc) {
4136 if let Some(event) = event.downcast::<KeyboardEvent>() {
4137 self.owner_document()
4138 .event_handler()
4139 .run_default_keyboard_event_handler(event);
4140 }
4141 }
4142}
4143
4144#[derive(Clone, Copy, MallocSizeOf, PartialEq)]
4146pub(crate) enum NodeDamage {
4147 Style,
4149 ContentOrHeritage,
4152 Other,
4154}
4155
4156pub(crate) enum ChildrenMutation<'a> {
4157 Append {
4158 prev: &'a Node,
4159 added: &'a [&'a Node],
4160 },
4161 Insert {
4162 prev: &'a Node,
4163 added: &'a [&'a Node],
4164 next: &'a Node,
4165 },
4166 Prepend {
4167 added: &'a [&'a Node],
4168 next: &'a Node,
4169 },
4170 Replace {
4171 prev: Option<&'a Node>,
4172 removed: &'a Node,
4173 added: &'a [&'a Node],
4174 next: Option<&'a Node>,
4175 },
4176 ReplaceAll {
4177 removed: &'a [&'a Node],
4178 added: &'a [&'a Node],
4179 },
4180 ChangeText,
4185}
4186
4187impl<'a> ChildrenMutation<'a> {
4188 fn insert(
4189 prev: Option<&'a Node>,
4190 added: &'a [&'a Node],
4191 next: Option<&'a Node>,
4192 ) -> ChildrenMutation<'a> {
4193 match (prev, next) {
4194 (None, None) => ChildrenMutation::ReplaceAll {
4195 removed: &[],
4196 added,
4197 },
4198 (Some(prev), None) => ChildrenMutation::Append { prev, added },
4199 (None, Some(next)) => ChildrenMutation::Prepend { added, next },
4200 (Some(prev), Some(next)) => ChildrenMutation::Insert { prev, added, next },
4201 }
4202 }
4203
4204 fn replace(
4205 prev: Option<&'a Node>,
4206 removed: &'a Option<&'a Node>,
4207 added: &'a [&'a Node],
4208 next: Option<&'a Node>,
4209 ) -> ChildrenMutation<'a> {
4210 if let Some(ref removed) = *removed {
4211 if let (None, None) = (prev, next) {
4212 ChildrenMutation::ReplaceAll {
4213 removed: from_ref(removed),
4214 added,
4215 }
4216 } else {
4217 ChildrenMutation::Replace {
4218 prev,
4219 removed,
4220 added,
4221 next,
4222 }
4223 }
4224 } else {
4225 ChildrenMutation::insert(prev, added, next)
4226 }
4227 }
4228
4229 fn replace_all(removed: &'a [&'a Node], added: &'a [&'a Node]) -> ChildrenMutation<'a> {
4230 ChildrenMutation::ReplaceAll { removed, added }
4231 }
4232
4233 pub(crate) fn next_child(&self) -> Option<&Node> {
4238 match *self {
4239 ChildrenMutation::Append { .. } => None,
4240 ChildrenMutation::Insert { next, .. } => Some(next),
4241 ChildrenMutation::Prepend { next, .. } => Some(next),
4242 ChildrenMutation::Replace { next, .. } => next,
4243 ChildrenMutation::ReplaceAll { .. } => None,
4244 ChildrenMutation::ChangeText => None,
4245 }
4246 }
4247
4248 pub(crate) fn modified_edge_element(&self) -> Option<DomRoot<Node>> {
4255 match *self {
4256 ChildrenMutation::Prepend { next, .. } |
4258 ChildrenMutation::Replace {
4259 prev: None,
4260 next: Some(next),
4261 ..
4262 } => next
4263 .inclusively_following_siblings()
4264 .find(|node| node.is::<Element>()),
4265 ChildrenMutation::Append { prev, .. } |
4267 ChildrenMutation::Replace {
4268 prev: Some(prev),
4269 next: None,
4270 ..
4271 } => prev
4272 .inclusively_preceding_siblings()
4273 .find(|node| node.is::<Element>()),
4274 ChildrenMutation::Insert { prev, next, .. } |
4276 ChildrenMutation::Replace {
4277 prev: Some(prev),
4278 next: Some(next),
4279 ..
4280 } => {
4281 if prev
4282 .inclusively_preceding_siblings()
4283 .all(|node| !node.is::<Element>())
4284 {
4285 next.inclusively_following_siblings()
4287 .find(|node| node.is::<Element>())
4288 } else if next
4289 .inclusively_following_siblings()
4290 .all(|node| !node.is::<Element>())
4291 {
4292 prev.inclusively_preceding_siblings()
4294 .find(|node| node.is::<Element>())
4295 } else {
4296 None
4297 }
4298 },
4299
4300 ChildrenMutation::Replace {
4301 prev: None,
4302 next: None,
4303 ..
4304 } => unreachable!(),
4305 ChildrenMutation::ReplaceAll { .. } => None,
4306 ChildrenMutation::ChangeText => None,
4307 }
4308 }
4309}
4310
4311pub(crate) struct BindContext<'a> {
4313 pub(crate) parent: &'a Node,
4315
4316 pub(crate) tree_connected: bool,
4320
4321 pub(crate) tree_is_in_a_document_tree: bool,
4325
4326 pub(crate) tree_is_in_a_shadow_tree: bool,
4328
4329 pub(crate) is_shadow_tree: IsShadowTree,
4334}
4335
4336#[derive(Debug, Eq, PartialEq)]
4337pub(crate) enum IsShadowTree {
4338 Yes,
4339 No,
4340}
4341
4342impl<'a> BindContext<'a> {
4343 pub(crate) fn new(parent: &'a Node, is_shadow_tree: IsShadowTree) -> Self {
4345 BindContext {
4346 parent,
4347 tree_connected: parent.is_connected(),
4348 tree_is_in_a_document_tree: parent.is_in_a_document_tree(),
4349 tree_is_in_a_shadow_tree: parent.is_in_a_shadow_tree(),
4350 is_shadow_tree,
4351 }
4352 }
4353
4354 pub(crate) fn is_in_tree(&self) -> bool {
4356 self.tree_is_in_a_document_tree || self.tree_is_in_a_shadow_tree
4357 }
4358}
4359
4360pub(crate) struct UnbindContext<'a> {
4363 index: Cell<Option<u32>>,
4365 pub(crate) parent: &'a Node,
4367 prev_sibling: Option<&'a Node>,
4369 pub(crate) next_sibling: Option<&'a Node>,
4371
4372 pub(crate) tree_connected: bool,
4376
4377 pub(crate) tree_is_in_a_document_tree: bool,
4381
4382 pub(crate) tree_is_in_a_shadow_tree: bool,
4384}
4385
4386impl<'a> UnbindContext<'a> {
4387 pub(crate) fn new(
4389 parent: &'a Node,
4390 prev_sibling: Option<&'a Node>,
4391 next_sibling: Option<&'a Node>,
4392 cached_index: Option<u32>,
4393 ) -> Self {
4394 UnbindContext {
4395 index: Cell::new(cached_index),
4396 parent,
4397 prev_sibling,
4398 next_sibling,
4399 tree_connected: parent.is_connected(),
4400 tree_is_in_a_document_tree: parent.is_in_a_document_tree(),
4401 tree_is_in_a_shadow_tree: parent.is_in_a_shadow_tree(),
4402 }
4403 }
4404
4405 pub(crate) fn index(&self) -> u32 {
4407 if let Some(index) = self.index.get() {
4408 return index;
4409 }
4410 let index = self.prev_sibling.map_or(0, |sibling| sibling.index() + 1);
4411 self.index.set(Some(index));
4412 index
4413 }
4414}
4415
4416pub(crate) struct UniqueId {
4418 cell: UnsafeCell<Option<Box<Uuid>>>,
4419}
4420
4421unsafe_no_jsmanaged_fields!(UniqueId);
4422
4423impl MallocSizeOf for UniqueId {
4424 #[expect(unsafe_code)]
4425 fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
4426 if let Some(uuid) = unsafe { &*self.cell.get() } {
4427 unsafe { ops.malloc_size_of(&**uuid) }
4428 } else {
4429 0
4430 }
4431 }
4432}
4433
4434impl UniqueId {
4435 fn new() -> UniqueId {
4437 UniqueId {
4438 cell: UnsafeCell::new(None),
4439 }
4440 }
4441
4442 #[expect(unsafe_code)]
4444 fn borrow(&self) -> &Uuid {
4445 unsafe {
4446 let ptr = self.cell.get();
4447 if (*ptr).is_none() {
4448 *ptr = Some(Box::new(Uuid::new_v4()));
4449 }
4450 (*ptr).as_ref().unwrap()
4451 }
4452 }
4453}
4454
4455pub(crate) struct NodeTypeIdWrapper(pub(crate) NodeTypeId);
4456
4457impl From<NodeTypeIdWrapper> for LayoutNodeType {
4458 #[inline(always)]
4459 fn from(node_type: NodeTypeIdWrapper) -> LayoutNodeType {
4460 match node_type.0 {
4461 NodeTypeId::Element(e) => LayoutNodeType::Element(ElementTypeIdWrapper(e).into()),
4462 NodeTypeId::CharacterData(CharacterDataTypeId::Text(_)) => LayoutNodeType::Text,
4463 x => unreachable!("Layout should not traverse nodes of type {:?}", x),
4464 }
4465 }
4466}
4467
4468struct ElementTypeIdWrapper(ElementTypeId);
4469
4470impl From<ElementTypeIdWrapper> for LayoutElementType {
4471 #[inline(always)]
4472 fn from(element_type: ElementTypeIdWrapper) -> LayoutElementType {
4473 match element_type.0 {
4474 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLBodyElement) => {
4475 LayoutElementType::HTMLBodyElement
4476 },
4477 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLBRElement) => {
4478 LayoutElementType::HTMLBRElement
4479 },
4480 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLCanvasElement) => {
4481 LayoutElementType::HTMLCanvasElement
4482 },
4483 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLHtmlElement) => {
4484 LayoutElementType::HTMLHtmlElement
4485 },
4486 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLIFrameElement) => {
4487 LayoutElementType::HTMLIFrameElement
4488 },
4489 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLImageElement) => {
4490 LayoutElementType::HTMLImageElement
4491 },
4492 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLMediaElement(_)) => {
4493 LayoutElementType::HTMLMediaElement
4494 },
4495 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLInputElement) => {
4496 LayoutElementType::HTMLInputElement
4497 },
4498 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLOptGroupElement) => {
4499 LayoutElementType::HTMLOptGroupElement
4500 },
4501 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLOptionElement) => {
4502 LayoutElementType::HTMLOptionElement
4503 },
4504 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLObjectElement) => {
4505 LayoutElementType::HTMLObjectElement
4506 },
4507 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLParagraphElement) => {
4508 LayoutElementType::HTMLParagraphElement
4509 },
4510 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLPreElement) => {
4511 LayoutElementType::HTMLPreElement
4512 },
4513 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLSelectElement) => {
4514 LayoutElementType::HTMLSelectElement
4515 },
4516 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTableCellElement) => {
4517 LayoutElementType::HTMLTableCellElement
4518 },
4519 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTableColElement) => {
4520 LayoutElementType::HTMLTableColElement
4521 },
4522 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTableElement) => {
4523 LayoutElementType::HTMLTableElement
4524 },
4525 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTableRowElement) => {
4526 LayoutElementType::HTMLTableRowElement
4527 },
4528 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTableSectionElement) => {
4529 LayoutElementType::HTMLTableSectionElement
4530 },
4531 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTextAreaElement) => {
4532 LayoutElementType::HTMLTextAreaElement
4533 },
4534 ElementTypeId::SVGElement(SVGElementTypeId::SVGGraphicsElement(
4535 SVGGraphicsElementTypeId::SVGImageElement,
4536 )) => LayoutElementType::SVGImageElement,
4537 ElementTypeId::SVGElement(SVGElementTypeId::SVGGraphicsElement(
4538 SVGGraphicsElementTypeId::SVGSVGElement,
4539 )) => LayoutElementType::SVGSVGElement,
4540 _ => LayoutElementType::Element,
4541 }
4542 }
4543}
4544
4545pub(crate) trait VecPreOrderInsertionHelper<T> {
4548 fn insert_pre_order(&mut self, elem: &T, tree_root: &Node);
4549}
4550
4551impl<T> VecPreOrderInsertionHelper<T> for Vec<Dom<T>>
4552where
4553 T: DerivedFrom<Node> + DomObject,
4554{
4555 fn insert_pre_order(&mut self, elem: &T, tree_root: &Node) {
4565 if self.is_empty() {
4566 self.push(Dom::from_ref(elem));
4567 return;
4568 }
4569
4570 let elem_node = elem.upcast::<Node>();
4571 let mut head: usize = 0;
4572 for node in tree_root.traverse_preorder(ShadowIncluding::No) {
4573 let head_node = DomRoot::upcast::<Node>(DomRoot::from_ref(&*self[head]));
4574 if head_node == node {
4575 head += 1;
4576 }
4577 if elem_node == &*node || head == self.len() {
4578 break;
4579 }
4580 }
4581 self.insert(head, Dom::from_ref(elem));
4582 }
4583}