1use std::borrow::Cow;
8use std::cell::{Cell, LazyCell, UnsafeCell};
9use std::default::Default;
10use std::f64::consts::PI;
11use std::slice::from_ref;
12use std::{cmp, fmt, iter};
13
14use app_units::Au;
15use base::id::{BrowsingContextId, PipelineId};
16use bitflags::bitflags;
17use devtools_traits::NodeInfo;
18use dom_struct::dom_struct;
19use embedder_traits::UntrustedNodeAddress;
20use euclid::default::Size2D;
21use euclid::{Point2D, Rect};
22use html5ever::serialize::HtmlSerializer;
23use html5ever::{Namespace, Prefix, QualName, ns, serialize as html_serialize};
24use js::jsapi::JSObject;
25use js::rust::HandleObject;
26use keyboard_types::Modifiers;
27use layout_api::wrapper_traits::SharedSelection;
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::bloom::BloomFilter;
39use selectors::matching::{
40 MatchingContext, MatchingForInvalidation, MatchingMode, NeedsSelectorFlags,
41 matches_selector_list,
42};
43use selectors::parser::SelectorList;
44use servo_arc::Arc as ServoArc;
45use servo_config::pref;
46use servo_url::ServoUrl;
47use smallvec::SmallVec;
48use style::attr::AttrValue;
49use style::context::QuirksMode;
50use style::dom::OpaqueNode;
51use style::properties::ComputedValues;
52use style::selector_parser::{PseudoElement, SelectorImpl, SelectorParser};
53use style::stylesheets::{Stylesheet, UrlExtraData};
54use style_traits::CSSPixel;
55use uuid::Uuid;
56use xml5ever::{local_name, serialize as xml_serialize};
57
58use super::types::CDATASection;
59use crate::conversions::Convert;
60use crate::document_loader::DocumentLoader;
61use crate::dom::attr::Attr;
62use crate::dom::bindings::cell::{DomRefCell, Ref, RefMut};
63use crate::dom::bindings::codegen::Bindings::AttrBinding::AttrMethods;
64use crate::dom::bindings::codegen::Bindings::CSSStyleDeclarationBinding::CSSStyleDeclarationMethods;
65use crate::dom::bindings::codegen::Bindings::CharacterDataBinding::CharacterDataMethods;
66use crate::dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods;
67use crate::dom::bindings::codegen::Bindings::ElementBinding::ElementMethods;
68use crate::dom::bindings::codegen::Bindings::HTMLCollectionBinding::HTMLCollectionMethods;
69use crate::dom::bindings::codegen::Bindings::NodeBinding::{
70 GetRootNodeOptions, NodeConstants, NodeMethods,
71};
72use crate::dom::bindings::codegen::Bindings::NodeListBinding::NodeListMethods;
73use crate::dom::bindings::codegen::Bindings::ProcessingInstructionBinding::ProcessingInstructionMethods;
74use crate::dom::bindings::codegen::Bindings::ShadowRootBinding::ShadowRoot_Binding::ShadowRootMethods;
75use crate::dom::bindings::codegen::Bindings::ShadowRootBinding::{
76 ShadowRootMode, SlotAssignmentMode,
77};
78use crate::dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
79use crate::dom::bindings::codegen::UnionTypes::NodeOrString;
80use crate::dom::bindings::conversions::{self, DerivedFrom};
81use crate::dom::bindings::domname::namespace_from_domstring;
82use crate::dom::bindings::error::{Error, ErrorResult, Fallible};
83use crate::dom::bindings::inheritance::{
84 Castable, CharacterDataTypeId, ElementTypeId, EventTargetTypeId, HTMLElementTypeId, NodeTypeId,
85 SVGElementTypeId, SVGGraphicsElementTypeId, TextTypeId,
86};
87use crate::dom::bindings::reflector::{DomObject, DomObjectWrap, reflect_dom_object_with_proto};
88use crate::dom::bindings::root::{Dom, DomRoot, DomSlice, LayoutDom, MutNullableDom, ToLayout};
89use crate::dom::bindings::str::{DOMString, USVString};
90use crate::dom::characterdata::{CharacterData, LayoutCharacterDataHelpers};
91use crate::dom::css::cssstylesheet::CSSStyleSheet;
92use crate::dom::css::stylesheetlist::StyleSheetListOwner;
93use crate::dom::customelementregistry::{
94 CallbackReaction, CustomElementRegistry, try_upgrade_element,
95};
96use crate::dom::document::{Document, DocumentSource, HasBrowsingContext, IsHTMLDocument};
97use crate::dom::documentfragment::DocumentFragment;
98use crate::dom::documenttype::DocumentType;
99use crate::dom::element::{
100 AttributeMutationReason, CustomElementCreationMode, Element, ElementCreator, SelectorWrapper,
101};
102use crate::dom::event::{Event, EventBubbles, EventCancelable};
103use crate::dom::eventtarget::EventTarget;
104use crate::dom::globalscope::GlobalScope;
105use crate::dom::html::htmlcanvaselement::{HTMLCanvasElement, LayoutHTMLCanvasElementHelpers};
106use crate::dom::html::htmlcollection::HTMLCollection;
107use crate::dom::html::htmlelement::HTMLElement;
108use crate::dom::html::htmliframeelement::{HTMLIFrameElement, HTMLIFrameElementLayoutMethods};
109use crate::dom::html::htmlimageelement::{HTMLImageElement, LayoutHTMLImageElementHelpers};
110use crate::dom::html::htmlinputelement::{HTMLInputElement, LayoutHTMLInputElementHelpers};
111use crate::dom::html::htmllinkelement::HTMLLinkElement;
112use crate::dom::html::htmlslotelement::{HTMLSlotElement, Slottable};
113use crate::dom::html::htmlstyleelement::HTMLStyleElement;
114use crate::dom::html::htmltextareaelement::{
115 HTMLTextAreaElement, LayoutHTMLTextAreaElementHelpers,
116};
117use crate::dom::html::htmlvideoelement::{HTMLVideoElement, LayoutHTMLVideoElementHelpers};
118use crate::dom::mutationobserver::{Mutation, MutationObserver, RegisteredObserver};
119use crate::dom::nodelist::NodeList;
120use crate::dom::pointerevent::{PointerEvent, PointerId};
121use crate::dom::processinginstruction::ProcessingInstruction;
122use crate::dom::range::WeakRangeVec;
123use crate::dom::raredata::NodeRareData;
124use crate::dom::servoparser::html::HtmlSerialize;
125use crate::dom::servoparser::{ServoParser, serialize_html_fragment};
126use crate::dom::shadowroot::{IsUserAgentWidget, LayoutShadowRootHelpers, ShadowRoot};
127use crate::dom::svg::svgsvgelement::{LayoutSVGSVGElementHelpers, SVGSVGElement};
128use crate::dom::text::Text;
129use crate::dom::types::KeyboardEvent;
130use crate::dom::virtualmethods::{VirtualMethods, vtable_for};
131use crate::dom::window::Window;
132use crate::script_runtime::CanGc;
133use crate::script_thread::ScriptThread;
134
135#[dom_struct]
141pub struct Node {
142 eventtarget: EventTarget,
144
145 parent_node: MutNullableDom<Node>,
147
148 first_child: MutNullableDom<Node>,
150
151 last_child: MutNullableDom<Node>,
153
154 next_sibling: MutNullableDom<Node>,
156
157 prev_sibling: MutNullableDom<Node>,
159
160 owner_doc: MutNullableDom<Document>,
162
163 rare_data: DomRefCell<Option<Box<NodeRareData>>>,
165
166 children_count: Cell<u32>,
168
169 flags: Cell<NodeFlags>,
171
172 inclusive_descendants_version: Cell<u64>,
174
175 #[no_trace]
178 style_data: DomRefCell<Option<Box<StyleData>>>,
179
180 #[no_trace]
183 layout_data: DomRefCell<Option<Box<GenericLayoutData>>>,
184}
185
186impl fmt::Debug for Node {
187 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
188 if matches!(self.type_id(), NodeTypeId::Element(_)) {
189 let el = self.downcast::<Element>().unwrap();
190 el.fmt(f)
191 } else {
192 write!(f, "[Node({:?})]", self.type_id())
193 }
194 }
195}
196
197#[derive(Clone, Copy, JSTraceable, MallocSizeOf)]
199pub(crate) struct NodeFlags(u16);
200
201bitflags! {
202 impl NodeFlags: u16 {
203 const IS_IN_A_DOCUMENT_TREE = 1 << 0;
207
208 const HAS_DIRTY_DESCENDANTS = 1 << 1;
210
211 const CLICK_IN_PROGRESS = 1 << 2;
214
215 const SEQUENTIALLY_FOCUSABLE = 1 << 3;
218
219 const PARSER_ASSOCIATED_FORM_OWNER = 1 << 6;
224
225 const HAS_SNAPSHOT = 1 << 7;
230
231 const HANDLED_SNAPSHOT = 1 << 8;
233
234 const IS_IN_SHADOW_TREE = 1 << 9;
236
237 const IS_CONNECTED = 1 << 10;
241
242 const HAS_WEIRD_PARSER_INSERTION_MODE = 1 << 11;
245
246 const IS_IN_UA_WIDGET = 1 << 12;
249
250 const USES_ATTR_IN_CONTENT_ATTRIBUTE = 1 << 13;
252 }
253}
254
255#[derive(Clone, Copy, MallocSizeOf)]
259enum SuppressObserver {
260 Suppressed,
261 Unsuppressed,
262}
263
264impl Node {
265 fn add_child(&self, new_child: &Node, before: Option<&Node>, can_gc: CanGc) {
269 assert!(new_child.parent_node.get().is_none());
270 assert!(new_child.prev_sibling.get().is_none());
271 assert!(new_child.next_sibling.get().is_none());
272 match before {
273 Some(before) => {
274 assert!(before.parent_node.get().as_deref() == Some(self));
275 let prev_sibling = before.GetPreviousSibling();
276 match prev_sibling {
277 None => {
278 assert!(self.first_child.get().as_deref() == Some(before));
279 self.first_child.set(Some(new_child));
280 },
281 Some(ref prev_sibling) => {
282 prev_sibling.next_sibling.set(Some(new_child));
283 new_child.prev_sibling.set(Some(prev_sibling));
284 },
285 }
286 before.prev_sibling.set(Some(new_child));
287 new_child.next_sibling.set(Some(before));
288 },
289 None => {
290 let last_child = self.GetLastChild();
291 match last_child {
292 None => self.first_child.set(Some(new_child)),
293 Some(ref last_child) => {
294 assert!(last_child.next_sibling.get().is_none());
295 last_child.next_sibling.set(Some(new_child));
296 new_child.prev_sibling.set(Some(last_child));
297 },
298 }
299
300 self.last_child.set(Some(new_child));
301 },
302 }
303
304 new_child.parent_node.set(Some(self));
305 self.children_count.set(self.children_count.get() + 1);
306
307 let parent_is_in_a_document_tree = self.is_in_a_document_tree();
308 let parent_in_shadow_tree = self.is_in_a_shadow_tree();
309 let parent_is_connected = self.is_connected();
310 let parent_is_in_ua_widget = self.is_in_ua_widget();
311
312 let context = BindContext::new(self, IsShadowTree::No);
313
314 for node in new_child.traverse_preorder(ShadowIncluding::No) {
315 if parent_in_shadow_tree {
316 if let Some(shadow_root) = self.containing_shadow_root() {
317 node.set_containing_shadow_root(Some(&*shadow_root));
318 }
319 debug_assert!(node.containing_shadow_root().is_some());
320 }
321 node.set_flag(
322 NodeFlags::IS_IN_A_DOCUMENT_TREE,
323 parent_is_in_a_document_tree,
324 );
325 node.set_flag(NodeFlags::IS_IN_SHADOW_TREE, parent_in_shadow_tree);
326 node.set_flag(NodeFlags::IS_CONNECTED, parent_is_connected);
327 node.set_flag(NodeFlags::IS_IN_UA_WIDGET, parent_is_in_ua_widget);
328
329 debug_assert!(!node.get_flag(NodeFlags::HAS_DIRTY_DESCENDANTS));
331 vtable_for(&node).bind_to_tree(&context, can_gc);
332 }
333 }
334
335 pub(crate) fn unsafely_set_html(
338 target: &Node,
339 context_element: &Element,
340 html: DOMString,
341 can_gc: CanGc,
342 ) {
343 let new_children = ServoParser::parse_html_fragment(context_element, html, true, can_gc);
345
346 let context_document = context_element.owner_document();
349 let fragment = DocumentFragment::new(&context_document, can_gc);
350
351 for child in new_children {
353 fragment
354 .upcast::<Node>()
355 .AppendChild(&child, can_gc)
356 .unwrap();
357 }
358
359 Node::replace_all(Some(fragment.upcast()), target, can_gc);
361 }
362
363 pub(crate) fn remove_layout_boxes_from_subtree(&self) {
367 for node in self.traverse_preorder(ShadowIncluding::Yes) {
368 node.layout_data.borrow_mut().take();
369 }
370 }
371
372 pub(crate) fn clean_up_style_and_layout_data(&self) {
373 self.owner_doc().cancel_animations_for_node(self);
374 self.style_data.borrow_mut().take();
375 self.layout_data.borrow_mut().take();
376 }
377
378 pub(crate) fn complete_remove_subtree(root: &Node, context: &UnbindContext, can_gc: CanGc) {
381 const RESET_FLAGS: NodeFlags = NodeFlags::IS_IN_A_DOCUMENT_TREE
383 .union(NodeFlags::IS_CONNECTED)
384 .union(NodeFlags::HAS_DIRTY_DESCENDANTS)
385 .union(NodeFlags::HAS_SNAPSHOT)
386 .union(NodeFlags::HANDLED_SNAPSHOT);
387
388 for node in root.traverse_preorder(ShadowIncluding::No) {
389 node.set_flag(RESET_FLAGS | NodeFlags::IS_IN_SHADOW_TREE, false);
390
391 if let Some(shadow_root) = node.downcast::<Element>().and_then(Element::shadow_root) {
394 for node in shadow_root
395 .upcast::<Node>()
396 .traverse_preorder(ShadowIncluding::Yes)
397 {
398 node.set_flag(RESET_FLAGS, false);
399 }
400 }
401 }
402
403 let is_parent_connected = context.parent.is_connected();
405 let custom_element_reaction_stack = ScriptThread::custom_element_reaction_stack();
406
407 let cleanup_node = |node: &Node| {
410 node.clean_up_style_and_layout_data();
411
412 vtable_for(node).unbind_from_tree(context, can_gc);
417
418 if is_parent_connected {
420 if let Some(element) = node.as_custom_element() {
421 custom_element_reaction_stack.enqueue_callback_reaction(
422 &element,
423 CallbackReaction::Disconnected,
424 None,
425 );
426 }
427 }
428 };
429
430 for node in root.traverse_preorder(ShadowIncluding::No) {
431 cleanup_node(&node);
432
433 if node.containing_shadow_root().is_some() {
436 node.set_containing_shadow_root(None);
439 }
440
441 if let Some(shadow_root) = node.downcast::<Element>().and_then(Element::shadow_root) {
444 for node in shadow_root
445 .upcast::<Node>()
446 .traverse_preorder(ShadowIncluding::Yes)
447 {
448 cleanup_node(&node);
449 }
450 }
451 }
452 }
453
454 fn remove_child(&self, child: &Node, cached_index: Option<u32>, can_gc: CanGc) {
458 assert!(child.parent_node.get().as_deref() == Some(self));
459 self.note_dirty_descendants();
460
461 let prev_sibling = child.GetPreviousSibling();
462 match prev_sibling {
463 None => {
464 self.first_child.set(child.next_sibling.get().as_deref());
465 },
466 Some(ref prev_sibling) => {
467 prev_sibling
468 .next_sibling
469 .set(child.next_sibling.get().as_deref());
470 },
471 }
472 let next_sibling = child.GetNextSibling();
473 match next_sibling {
474 None => {
475 self.last_child.set(child.prev_sibling.get().as_deref());
476 },
477 Some(ref next_sibling) => {
478 next_sibling
479 .prev_sibling
480 .set(child.prev_sibling.get().as_deref());
481 },
482 }
483
484 let context = UnbindContext::new(
485 self,
486 prev_sibling.as_deref(),
487 next_sibling.as_deref(),
488 cached_index,
489 );
490
491 child.prev_sibling.set(None);
492 child.next_sibling.set(None);
493 child.parent_node.set(None);
494 self.children_count.set(self.children_count.get() - 1);
495
496 Self::complete_remove_subtree(child, &context, can_gc);
497 }
498
499 pub(crate) fn to_untrusted_node_address(&self) -> UntrustedNodeAddress {
500 UntrustedNodeAddress(self.reflector().get_jsobject().get() as *const c_void)
501 }
502
503 pub(crate) fn to_opaque(&self) -> OpaqueNode {
504 OpaqueNode(self.reflector().get_jsobject().get() as usize)
505 }
506
507 pub(crate) fn as_custom_element(&self) -> Option<DomRoot<Element>> {
508 self.downcast::<Element>().and_then(|element| {
509 if element.is_custom() {
510 assert!(element.get_custom_element_definition().is_some());
511 Some(DomRoot::from_ref(element))
512 } else {
513 None
514 }
515 })
516 }
517
518 pub(crate) fn fire_synthetic_pointer_event_not_trusted(&self, name: DOMString, can_gc: CanGc) {
520 let window = self.owner_window();
524
525 let pointer_event = PointerEvent::new(
527 &window, name,
529 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,
556 );
557
558 pointer_event.upcast::<Event>().set_composed(true);
560
561 pointer_event.upcast::<Event>().set_trusted(false);
563
564 pointer_event
567 .upcast::<Event>()
568 .dispatch(self.upcast::<EventTarget>(), false, can_gc);
569 }
570
571 pub(crate) fn parent_directionality(&self) -> String {
572 let mut current = self.GetParentNode();
573
574 loop {
575 match current {
576 Some(node) => {
577 if let Some(directionality) = node
578 .downcast::<HTMLElement>()
579 .and_then(|html_element| html_element.directionality())
580 {
581 return directionality;
582 } else {
583 current = node.GetParentNode();
584 }
585 },
586 None => return "ltr".to_owned(),
587 }
588 }
589 }
590}
591
592pub(crate) struct QuerySelectorIterator {
593 selectors: SelectorList<SelectorImpl>,
594 iterator: TreeIterator,
595}
596
597impl QuerySelectorIterator {
598 fn new(iter: TreeIterator, selectors: SelectorList<SelectorImpl>) -> QuerySelectorIterator {
599 QuerySelectorIterator {
600 selectors,
601 iterator: iter,
602 }
603 }
604}
605
606impl Iterator for QuerySelectorIterator {
607 type Item = DomRoot<Node>;
608
609 fn next(&mut self) -> Option<DomRoot<Node>> {
610 let selectors = &self.selectors;
611
612 let (quirks_mode, filter) = match self.iterator.by_ref().peek() {
613 Some(node) => (node.owner_doc().quirks_mode(), BloomFilter::default()),
614 None => return None,
615 };
616
617 self.iterator.by_ref().find_map(|node| {
618 if let Some(element) = DomRoot::downcast(node) {
619 let mut nth_index_cache = Default::default();
620 let mut ctx = MatchingContext::new(
621 MatchingMode::Normal,
622 Some(&filter),
623 &mut nth_index_cache,
624 quirks_mode,
625 NeedsSelectorFlags::No,
626 MatchingForInvalidation::No,
627 );
628 if matches_selector_list(selectors, &SelectorWrapper::Borrowed(&element), &mut ctx)
629 {
630 return Some(DomRoot::upcast(element));
631 }
632 }
633 None
634 })
635 }
636}
637
638impl Node {
639 fn rare_data(&self) -> Ref<'_, Option<Box<NodeRareData>>> {
640 self.rare_data.borrow()
641 }
642
643 fn ensure_rare_data(&self) -> RefMut<'_, Box<NodeRareData>> {
644 let mut rare_data = self.rare_data.borrow_mut();
645 if rare_data.is_none() {
646 *rare_data = Some(Default::default());
647 }
648 RefMut::map(rare_data, |rare_data| rare_data.as_mut().unwrap())
649 }
650
651 pub(crate) fn is_before(&self, other: &Node) -> bool {
654 let cmp = other.CompareDocumentPosition(self);
655 if cmp & NodeConstants::DOCUMENT_POSITION_DISCONNECTED != 0 {
656 return false;
657 }
658
659 cmp & NodeConstants::DOCUMENT_POSITION_PRECEDING != 0
660 }
661
662 pub(crate) fn registered_mutation_observers_mut(&self) -> RefMut<'_, Vec<RegisteredObserver>> {
665 RefMut::map(self.ensure_rare_data(), |rare_data| {
666 &mut rare_data.mutation_observers
667 })
668 }
669
670 pub(crate) fn registered_mutation_observers(&self) -> Option<Ref<'_, Vec<RegisteredObserver>>> {
671 let rare_data: Ref<'_, _> = self.rare_data.borrow();
672
673 if rare_data.is_none() {
674 return None;
675 }
676 Some(Ref::map(rare_data, |rare_data| {
677 &rare_data.as_ref().unwrap().mutation_observers
678 }))
679 }
680
681 #[cfg_attr(crown, expect(crown::unrooted_must_root))]
683 pub(crate) fn add_mutation_observer(&self, observer: RegisteredObserver) {
684 self.ensure_rare_data().mutation_observers.push(observer);
685 }
686
687 pub(crate) fn remove_mutation_observer(&self, observer: &MutationObserver) {
689 self.ensure_rare_data()
690 .mutation_observers
691 .retain(|reg_obs| &*reg_obs.observer != observer)
692 }
693
694 pub(crate) fn dump(&self) {
696 self.dump_indent(0);
697 }
698
699 pub(crate) fn dump_indent(&self, indent: u32) {
701 let mut s = String::new();
702 for _ in 0..indent {
703 s.push_str(" ");
704 }
705
706 s.push_str(&self.debug_str());
707 debug!("{:?}", s);
708
709 for kid in self.children() {
711 kid.dump_indent(indent + 1)
712 }
713 }
714
715 pub(crate) fn debug_str(&self) -> String {
717 format!("{:?}", self.type_id())
718 }
719
720 pub(crate) fn is_in_a_document_tree(&self) -> bool {
722 self.flags.get().contains(NodeFlags::IS_IN_A_DOCUMENT_TREE)
723 }
724
725 pub(crate) fn is_in_a_shadow_tree(&self) -> bool {
727 self.flags.get().contains(NodeFlags::IS_IN_SHADOW_TREE)
728 }
729
730 pub(crate) fn has_weird_parser_insertion_mode(&self) -> bool {
731 self.flags
732 .get()
733 .contains(NodeFlags::HAS_WEIRD_PARSER_INSERTION_MODE)
734 }
735
736 pub(crate) fn set_weird_parser_insertion_mode(&self) {
737 self.set_flag(NodeFlags::HAS_WEIRD_PARSER_INSERTION_MODE, true)
738 }
739
740 pub(crate) fn is_connected(&self) -> bool {
742 self.flags.get().contains(NodeFlags::IS_CONNECTED)
743 }
744
745 pub(crate) fn set_in_ua_widget(&self, in_ua_widget: bool) {
746 self.set_flag(NodeFlags::IS_IN_UA_WIDGET, in_ua_widget)
747 }
748
749 pub(crate) fn is_in_ua_widget(&self) -> bool {
750 self.flags.get().contains(NodeFlags::IS_IN_UA_WIDGET)
751 }
752
753 pub(crate) fn type_id(&self) -> NodeTypeId {
755 match *self.eventtarget.type_id() {
756 EventTargetTypeId::Node(type_id) => type_id,
757 _ => unreachable!(),
758 }
759 }
760
761 pub(crate) fn len(&self) -> u32 {
763 match self.type_id() {
764 NodeTypeId::DocumentType => 0,
765 NodeTypeId::CharacterData(_) => self.downcast::<CharacterData>().unwrap().Length(),
766 _ => self.children_count(),
767 }
768 }
769
770 pub(crate) fn is_empty(&self) -> bool {
771 self.len() == 0
773 }
774
775 pub(crate) fn index(&self) -> u32 {
777 self.preceding_siblings().count() as u32
778 }
779
780 pub(crate) fn has_parent(&self) -> bool {
782 self.parent_node.get().is_some()
783 }
784
785 pub(crate) fn children_count(&self) -> u32 {
786 self.children_count.get()
787 }
788
789 pub(crate) fn ranges(&self) -> RefMut<'_, WeakRangeVec> {
790 RefMut::map(self.ensure_rare_data(), |rare_data| &mut rare_data.ranges)
791 }
792
793 pub(crate) fn ranges_is_empty(&self) -> bool {
794 self.rare_data()
795 .as_ref()
796 .is_none_or(|data| data.ranges.is_empty())
797 }
798
799 #[inline]
800 pub(crate) fn is_doctype(&self) -> bool {
801 self.type_id() == NodeTypeId::DocumentType
802 }
803
804 pub(crate) fn get_flag(&self, flag: NodeFlags) -> bool {
805 self.flags.get().contains(flag)
806 }
807
808 pub(crate) fn set_flag(&self, flag: NodeFlags, value: bool) {
809 let mut flags = self.flags.get();
810
811 if value {
812 flags.insert(flag);
813 } else {
814 flags.remove(flag);
815 }
816
817 self.flags.set(flags);
818 }
819
820 pub(crate) fn note_dirty_descendants(&self) {
822 self.owner_doc().note_node_with_dirty_descendants(self);
823 }
824
825 pub(crate) fn has_dirty_descendants(&self) -> bool {
826 self.get_flag(NodeFlags::HAS_DIRTY_DESCENDANTS)
827 }
828
829 pub(crate) fn rev_version(&self) {
830 let doc: DomRoot<Node> = DomRoot::upcast(self.owner_doc());
835 let version = cmp::max(
836 self.inclusive_descendants_version(),
837 doc.inclusive_descendants_version(),
838 ) + 1;
839
840 let mut node = &MutNullableDom::new(Some(self));
843 while let Some(p) = node.if_is_some(|p| {
844 p.inclusive_descendants_version.set(version);
845 &p.parent_node
846 }) {
847 node = p
848 }
849 doc.inclusive_descendants_version.set(version);
850 }
851
852 pub(crate) fn dirty(&self, damage: NodeDamage) {
853 self.rev_version();
854 if !self.is_connected() {
855 return;
856 }
857
858 match self.type_id() {
859 NodeTypeId::CharacterData(CharacterDataTypeId::Text(TextTypeId::Text)) => {
860 self.parent_node
864 .get()
865 .unwrap()
866 .dirty(NodeDamage::ContentOrHeritage)
867 },
868 NodeTypeId::Element(_) => self.downcast::<Element>().unwrap().restyle(damage),
869 NodeTypeId::DocumentFragment(DocumentFragmentTypeId::ShadowRoot) => self
870 .downcast::<ShadowRoot>()
871 .unwrap()
872 .Host()
873 .upcast::<Element>()
874 .restyle(damage),
875 _ => {},
876 };
877 }
878
879 pub(crate) fn inclusive_descendants_version(&self) -> u64 {
881 self.inclusive_descendants_version.get()
882 }
883
884 pub(crate) fn traverse_preorder(&self, shadow_including: ShadowIncluding) -> TreeIterator {
886 TreeIterator::new(self, shadow_including)
887 }
888
889 pub(crate) fn inclusively_following_siblings(
890 &self,
891 ) -> impl Iterator<Item = DomRoot<Node>> + use<> {
892 SimpleNodeIterator {
893 current: Some(DomRoot::from_ref(self)),
894 next_node: |n| n.GetNextSibling(),
895 }
896 }
897
898 pub(crate) fn inclusively_preceding_siblings(
899 &self,
900 ) -> impl Iterator<Item = DomRoot<Node>> + use<> {
901 SimpleNodeIterator {
902 current: Some(DomRoot::from_ref(self)),
903 next_node: |n| n.GetPreviousSibling(),
904 }
905 }
906
907 pub(crate) fn common_ancestor(
908 &self,
909 other: &Node,
910 shadow_including: ShadowIncluding,
911 ) -> Option<DomRoot<Node>> {
912 self.inclusive_ancestors(shadow_including).find(|ancestor| {
913 other
914 .inclusive_ancestors(shadow_including)
915 .any(|node| node == *ancestor)
916 })
917 }
918
919 pub(crate) fn common_ancestor_in_flat_tree(&self, other: &Node) -> Option<DomRoot<Node>> {
920 self.inclusive_ancestors_in_flat_tree().find(|ancestor| {
921 other
922 .inclusive_ancestors_in_flat_tree()
923 .any(|node| node == *ancestor)
924 })
925 }
926
927 pub(crate) fn is_inclusive_ancestor_of(&self, child: &Node) -> bool {
928 self == child || self.is_ancestor_of(child)
929 }
930
931 pub(crate) fn is_ancestor_of(&self, child: &Node) -> bool {
932 let mut current = &MutNullableDom::new(Some(child));
933 let mut done = false;
934
935 while let Some(node) = current.if_is_some(|node| {
936 done = node == self;
937 &node.parent_node
938 }) {
939 if done {
940 break;
941 }
942 current = node
943 }
944 done
945 }
946
947 pub(crate) fn is_shadow_including_inclusive_ancestor_of(&self, node: &Node) -> bool {
948 node.inclusive_ancestors(ShadowIncluding::Yes)
949 .any(|ancestor| &*ancestor == self)
950 }
951
952 pub(crate) fn following_siblings(&self) -> impl Iterator<Item = DomRoot<Node>> + use<> {
953 SimpleNodeIterator {
954 current: self.GetNextSibling(),
955 next_node: |n| n.GetNextSibling(),
956 }
957 }
958
959 pub(crate) fn preceding_siblings(&self) -> impl Iterator<Item = DomRoot<Node>> + use<> {
960 SimpleNodeIterator {
961 current: self.GetPreviousSibling(),
962 next_node: |n| n.GetPreviousSibling(),
963 }
964 }
965
966 pub(crate) fn following_nodes(&self, root: &Node) -> FollowingNodeIterator {
967 FollowingNodeIterator {
968 current: Some(DomRoot::from_ref(self)),
969 root: DomRoot::from_ref(root),
970 }
971 }
972
973 pub(crate) fn preceding_nodes(&self, root: &Node) -> PrecedingNodeIterator {
974 PrecedingNodeIterator {
975 current: Some(DomRoot::from_ref(self)),
976 root: DomRoot::from_ref(root),
977 }
978 }
979
980 pub(crate) fn descending_last_children(&self) -> impl Iterator<Item = DomRoot<Node>> + use<> {
983 SimpleNodeIterator {
984 current: self.GetLastChild(),
985 next_node: |n| n.GetLastChild(),
986 }
987 }
988
989 pub(crate) fn is_parent_of(&self, child: &Node) -> bool {
990 child
991 .parent_node
992 .get()
993 .is_some_and(|parent| &*parent == self)
994 }
995
996 pub(crate) fn to_trusted_node_address(&self) -> TrustedNodeAddress {
997 TrustedNodeAddress(self as *const Node as *const libc::c_void)
998 }
999
1000 pub(crate) fn padding(&self) -> Option<PhysicalSides> {
1001 self.owner_window().padding_query_without_reflow(self)
1002 }
1003
1004 pub(crate) fn content_box(&self) -> Option<Rect<Au, CSSPixel>> {
1005 self.owner_window()
1006 .box_area_query(self, BoxAreaType::Content, false)
1007 }
1008
1009 pub(crate) fn border_box(&self) -> Option<Rect<Au, CSSPixel>> {
1010 self.owner_window()
1011 .box_area_query(self, BoxAreaType::Border, false)
1012 }
1013
1014 pub(crate) fn padding_box(&self) -> Option<Rect<Au, CSSPixel>> {
1015 self.owner_window()
1016 .box_area_query(self, BoxAreaType::Padding, false)
1017 }
1018
1019 pub(crate) fn border_boxes(&self) -> Vec<Rect<Au, CSSPixel>> {
1020 self.owner_window()
1021 .box_areas_query(self, BoxAreaType::Border)
1022 }
1023
1024 pub(crate) fn client_rect(&self) -> Rect<i32, CSSPixel> {
1025 self.owner_window().client_rect_query(self)
1026 }
1027
1028 pub(crate) fn scroll_area(&self) -> Rect<i32, CSSPixel> {
1031 let document = self.owner_doc();
1033
1034 if !document.is_active() {
1036 return Rect::zero();
1037 }
1038
1039 let window = document.window();
1042 let viewport = Size2D::new(window.InnerWidth(), window.InnerHeight()).cast_unit();
1043
1044 let in_quirks_mode = document.quirks_mode() == QuirksMode::Quirks;
1045 let is_root = self.downcast::<Element>().is_some_and(|e| e.is_root());
1046 let is_body_element = self
1047 .downcast::<HTMLElement>()
1048 .is_some_and(|e| e.is_body_element());
1049
1050 if (is_root && !in_quirks_mode) || (is_body_element && in_quirks_mode) {
1056 let viewport_scrolling_area = window.scrolling_area_query(None);
1057 return Rect::new(
1058 viewport_scrolling_area.origin,
1059 viewport_scrolling_area.size.max(viewport),
1060 );
1061 }
1062
1063 window.scrolling_area_query(Some(self))
1067 }
1068
1069 pub(crate) fn before(&self, nodes: Vec<NodeOrString>, can_gc: CanGc) -> ErrorResult {
1071 let parent = &self.parent_node;
1073
1074 let parent = match parent.get() {
1076 None => return Ok(()),
1077 Some(parent) => parent,
1078 };
1079
1080 let viable_previous_sibling = first_node_not_in(self.preceding_siblings(), &nodes);
1082
1083 let node = self
1085 .owner_doc()
1086 .node_from_nodes_and_strings(nodes, can_gc)?;
1087
1088 let viable_previous_sibling = match viable_previous_sibling {
1090 Some(ref viable_previous_sibling) => viable_previous_sibling.next_sibling.get(),
1091 None => parent.first_child.get(),
1092 };
1093
1094 Node::pre_insert(&node, &parent, viable_previous_sibling.as_deref(), can_gc)?;
1096
1097 Ok(())
1098 }
1099
1100 pub(crate) fn after(&self, nodes: Vec<NodeOrString>, can_gc: CanGc) -> ErrorResult {
1102 let parent = &self.parent_node;
1104
1105 let parent = match parent.get() {
1107 None => return Ok(()),
1108 Some(parent) => parent,
1109 };
1110
1111 let viable_next_sibling = first_node_not_in(self.following_siblings(), &nodes);
1113
1114 let node = self
1116 .owner_doc()
1117 .node_from_nodes_and_strings(nodes, can_gc)?;
1118
1119 Node::pre_insert(&node, &parent, viable_next_sibling.as_deref(), can_gc)?;
1121
1122 Ok(())
1123 }
1124
1125 pub(crate) fn replace_with(&self, nodes: Vec<NodeOrString>, can_gc: CanGc) -> ErrorResult {
1127 let Some(parent) = self.GetParentNode() else {
1129 return Ok(());
1131 };
1132
1133 let viable_next_sibling = first_node_not_in(self.following_siblings(), &nodes);
1135
1136 let node = self
1138 .owner_doc()
1139 .node_from_nodes_and_strings(nodes, can_gc)?;
1140
1141 if self.parent_node == Some(&*parent) {
1142 parent.ReplaceChild(&node, self, can_gc)?;
1144 } else {
1145 Node::pre_insert(&node, &parent, viable_next_sibling.as_deref(), can_gc)?;
1147 }
1148 Ok(())
1149 }
1150
1151 pub(crate) fn prepend(&self, nodes: Vec<NodeOrString>, can_gc: CanGc) -> ErrorResult {
1153 let doc = self.owner_doc();
1155 let node = doc.node_from_nodes_and_strings(nodes, can_gc)?;
1156 let first_child = self.first_child.get();
1158 Node::pre_insert(&node, self, first_child.as_deref(), can_gc).map(|_| ())
1159 }
1160
1161 pub(crate) fn append(&self, nodes: Vec<NodeOrString>, can_gc: CanGc) -> ErrorResult {
1163 let doc = self.owner_doc();
1165 let node = doc.node_from_nodes_and_strings(nodes, can_gc)?;
1166 self.AppendChild(&node, can_gc).map(|_| ())
1168 }
1169
1170 pub(crate) fn replace_children(&self, nodes: Vec<NodeOrString>, can_gc: CanGc) -> ErrorResult {
1172 let doc = self.owner_doc();
1175 let node = doc.node_from_nodes_and_strings(nodes, can_gc)?;
1176
1177 Node::ensure_pre_insertion_validity(&node, self, None)?;
1179
1180 Node::replace_all(Some(&node), self, can_gc);
1182 Ok(())
1183 }
1184
1185 pub(crate) fn query_selector(
1187 &self,
1188 selectors: DOMString,
1189 ) -> Fallible<Option<DomRoot<Element>>> {
1190 let doc = self.owner_doc();
1192 match SelectorParser::parse_author_origin_no_namespace(
1193 &selectors.str(),
1194 &UrlExtraData(doc.url().get_arc()),
1195 ) {
1196 Err(_) => Err(Error::Syntax(None)),
1198 Ok(selectors) => {
1200 let mut nth_index_cache = Default::default();
1201 let filter = BloomFilter::default();
1202 let mut ctx = MatchingContext::new(
1203 MatchingMode::Normal,
1204 Some(&filter),
1205 &mut nth_index_cache,
1206 doc.quirks_mode(),
1207 NeedsSelectorFlags::No,
1208 MatchingForInvalidation::No,
1209 );
1210 let mut descendants = self.traverse_preorder(ShadowIncluding::No);
1211 assert!(&*descendants.next().unwrap() == self);
1213 Ok(descendants.filter_map(DomRoot::downcast).find(|element| {
1214 matches_selector_list(&selectors, &SelectorWrapper::Borrowed(element), &mut ctx)
1215 }))
1216 },
1217 }
1218 }
1219
1220 pub(crate) fn query_selector_iter(
1225 &self,
1226 selectors: DOMString,
1227 ) -> Fallible<QuerySelectorIterator> {
1228 let url = self.owner_doc().url();
1230 match SelectorParser::parse_author_origin_no_namespace(
1231 &selectors.str(),
1232 &UrlExtraData(url.get_arc()),
1233 ) {
1234 Err(_) => Err(Error::Syntax(None)),
1236 Ok(selectors) => {
1238 let mut descendants = self.traverse_preorder(ShadowIncluding::No);
1239 assert!(&*descendants.next().unwrap() == self);
1241 Ok(QuerySelectorIterator::new(descendants, selectors))
1242 },
1243 }
1244 }
1245
1246 pub(crate) fn query_selector_all(&self, selectors: DOMString) -> Fallible<DomRoot<NodeList>> {
1248 let window = self.owner_window();
1249 let iter = self.query_selector_iter(selectors)?;
1250 Ok(NodeList::new_simple_list(&window, iter, CanGc::note()))
1251 }
1252
1253 pub(crate) fn ancestors(&self) -> impl Iterator<Item = DomRoot<Node>> + use<> {
1254 SimpleNodeIterator {
1255 current: self.GetParentNode(),
1256 next_node: |n| n.GetParentNode(),
1257 }
1258 }
1259
1260 pub(crate) fn inclusive_ancestors(
1262 &self,
1263 shadow_including: ShadowIncluding,
1264 ) -> impl Iterator<Item = DomRoot<Node>> + use<> {
1265 SimpleNodeIterator {
1266 current: Some(DomRoot::from_ref(self)),
1267 next_node: move |n| {
1268 if shadow_including == ShadowIncluding::Yes {
1269 if let Some(shadow_root) = n.downcast::<ShadowRoot>() {
1270 return Some(DomRoot::from_ref(shadow_root.Host().upcast::<Node>()));
1271 }
1272 }
1273 n.GetParentNode()
1274 },
1275 }
1276 }
1277
1278 pub(crate) fn owner_doc(&self) -> DomRoot<Document> {
1279 self.owner_doc.get().unwrap()
1280 }
1281
1282 pub(crate) fn set_owner_doc(&self, document: &Document) {
1283 self.owner_doc.set(Some(document));
1284 }
1285
1286 pub(crate) fn containing_shadow_root(&self) -> Option<DomRoot<ShadowRoot>> {
1287 self.rare_data()
1288 .as_ref()?
1289 .containing_shadow_root
1290 .as_ref()
1291 .map(|sr| DomRoot::from_ref(&**sr))
1292 }
1293
1294 pub(crate) fn set_containing_shadow_root(&self, shadow_root: Option<&ShadowRoot>) {
1295 self.ensure_rare_data().containing_shadow_root = shadow_root.map(Dom::from_ref);
1296 }
1297
1298 pub(crate) fn is_in_html_doc(&self) -> bool {
1299 self.owner_doc().is_html_document()
1300 }
1301
1302 pub(crate) fn is_connected_with_browsing_context(&self) -> bool {
1303 self.is_connected() && self.owner_doc().browsing_context().is_some()
1304 }
1305
1306 pub(crate) fn children(&self) -> impl Iterator<Item = DomRoot<Node>> + use<> {
1307 SimpleNodeIterator {
1308 current: self.GetFirstChild(),
1309 next_node: |n| n.GetNextSibling(),
1310 }
1311 }
1312
1313 pub(crate) fn rev_children(&self) -> impl Iterator<Item = DomRoot<Node>> + use<> {
1314 SimpleNodeIterator {
1315 current: self.GetLastChild(),
1316 next_node: |n| n.GetPreviousSibling(),
1317 }
1318 }
1319
1320 pub(crate) fn child_elements(&self) -> impl Iterator<Item = DomRoot<Element>> + use<> {
1321 self.children()
1322 .filter_map(DomRoot::downcast as fn(_) -> _)
1323 .peekable()
1324 }
1325
1326 pub(crate) fn remove_self(&self, can_gc: CanGc) {
1327 if let Some(ref parent) = self.GetParentNode() {
1328 Node::remove(self, parent, SuppressObserver::Unsuppressed, can_gc);
1329 }
1330 }
1331
1332 pub(crate) fn unique_id(&self, pipeline: PipelineId) -> String {
1333 let mut rare_data = self.ensure_rare_data();
1334
1335 if rare_data.unique_id.is_none() {
1336 let node_id = UniqueId::new();
1337 ScriptThread::save_node_id(pipeline, node_id.borrow().simple().to_string());
1338 rare_data.unique_id = Some(node_id);
1339 }
1340 rare_data
1341 .unique_id
1342 .as_ref()
1343 .unwrap()
1344 .borrow()
1345 .simple()
1346 .to_string()
1347 }
1348
1349 pub(crate) fn summarize(&self, can_gc: CanGc) -> NodeInfo {
1350 let USVString(base_uri) = self.BaseURI();
1351 let node_type = self.NodeType();
1352 let pipeline = self.owner_window().pipeline_id();
1353
1354 let maybe_shadow_root = self.downcast::<ShadowRoot>();
1355 let shadow_root_mode = maybe_shadow_root
1356 .map(ShadowRoot::Mode)
1357 .map(ShadowRootMode::convert);
1358 let host = maybe_shadow_root
1359 .map(ShadowRoot::Host)
1360 .map(|host| host.upcast::<Node>().unique_id(pipeline));
1361 let is_shadow_host = self.downcast::<Element>().is_some_and(|potential_host| {
1362 let Some(root) = potential_host.shadow_root() else {
1363 return false;
1364 };
1365 !root.is_user_agent_widget() || pref!(inspector_show_servo_internal_shadow_roots)
1366 });
1367
1368 let num_children = if is_shadow_host {
1369 self.ChildNodes(can_gc).Length() as usize + 1
1371 } else {
1372 self.ChildNodes(can_gc).Length() as usize
1373 };
1374
1375 let window = self.owner_window();
1376 let display = self
1377 .downcast::<Element>()
1378 .map(|elem| window.GetComputedStyle(elem, None))
1379 .map(|style| style.Display().into());
1380
1381 NodeInfo {
1382 unique_id: self.unique_id(pipeline),
1383 host,
1384 base_uri,
1385 parent: self
1386 .GetParentNode()
1387 .map_or("".to_owned(), |node| node.unique_id(pipeline)),
1388 node_type,
1389 is_top_level_document: node_type == NodeConstants::DOCUMENT_NODE,
1390 node_name: String::from(self.NodeName()),
1391 node_value: self.GetNodeValue().map(|v| v.into()),
1392 num_children,
1393 attrs: self.downcast().map(Element::summarize).unwrap_or(vec![]),
1394 is_shadow_host,
1395 shadow_root_mode,
1396 display,
1397 is_displayed: !self.is_display_none() || self.is::<DocumentType>(),
1401 doctype_name: self
1402 .downcast::<DocumentType>()
1403 .map(DocumentType::name)
1404 .cloned()
1405 .map(String::from),
1406 doctype_public_identifier: self
1407 .downcast::<DocumentType>()
1408 .map(DocumentType::public_id)
1409 .cloned()
1410 .map(String::from),
1411 doctype_system_identifier: self
1412 .downcast::<DocumentType>()
1413 .map(DocumentType::system_id)
1414 .cloned()
1415 .map(String::from),
1416 }
1417 }
1418
1419 pub(crate) fn insert_cell_or_row<F, G, I>(
1421 &self,
1422 index: i32,
1423 get_items: F,
1424 new_child: G,
1425 can_gc: CanGc,
1426 ) -> Fallible<DomRoot<HTMLElement>>
1427 where
1428 F: Fn() -> DomRoot<HTMLCollection>,
1429 G: Fn() -> DomRoot<I>,
1430 I: DerivedFrom<Node> + DerivedFrom<HTMLElement> + DomObject,
1431 {
1432 if index < -1 {
1433 return Err(Error::IndexSize(None));
1434 }
1435
1436 let tr = new_child();
1437
1438 {
1439 let tr_node = tr.upcast::<Node>();
1440 if index == -1 {
1441 self.InsertBefore(tr_node, None, can_gc)?;
1442 } else {
1443 let items = get_items();
1444 let node = match items
1445 .elements_iter()
1446 .map(DomRoot::upcast::<Node>)
1447 .map(Some)
1448 .chain(iter::once(None))
1449 .nth(index as usize)
1450 {
1451 None => return Err(Error::IndexSize(None)),
1452 Some(node) => node,
1453 };
1454 self.InsertBefore(tr_node, node.as_deref(), can_gc)?;
1455 }
1456 }
1457
1458 Ok(DomRoot::upcast::<HTMLElement>(tr))
1459 }
1460
1461 pub(crate) fn delete_cell_or_row<F, G>(
1463 &self,
1464 index: i32,
1465 get_items: F,
1466 is_delete_type: G,
1467 can_gc: CanGc,
1468 ) -> ErrorResult
1469 where
1470 F: Fn() -> DomRoot<HTMLCollection>,
1471 G: Fn(&Element) -> bool,
1472 {
1473 let element = match index {
1474 index if index < -1 => return Err(Error::IndexSize(None)),
1475 -1 => {
1476 let last_child = self.upcast::<Node>().GetLastChild();
1477 match last_child.and_then(|node| {
1478 node.inclusively_preceding_siblings()
1479 .filter_map(DomRoot::downcast::<Element>)
1480 .find(|elem| is_delete_type(elem))
1481 }) {
1482 Some(element) => element,
1483 None => return Ok(()),
1484 }
1485 },
1486 index => match get_items().Item(index as u32) {
1487 Some(element) => element,
1488 None => return Err(Error::IndexSize(None)),
1489 },
1490 };
1491
1492 element.upcast::<Node>().remove_self(can_gc);
1493 Ok(())
1494 }
1495
1496 pub(crate) fn get_stylesheet(&self) -> Option<ServoArc<Stylesheet>> {
1497 if let Some(node) = self.downcast::<HTMLStyleElement>() {
1498 node.get_stylesheet()
1499 } else if let Some(node) = self.downcast::<HTMLLinkElement>() {
1500 node.get_stylesheet()
1501 } else {
1502 None
1503 }
1504 }
1505
1506 pub(crate) fn get_cssom_stylesheet(&self) -> Option<DomRoot<CSSStyleSheet>> {
1507 if let Some(node) = self.downcast::<HTMLStyleElement>() {
1508 node.get_cssom_stylesheet()
1509 } else if let Some(node) = self.downcast::<HTMLLinkElement>() {
1510 node.get_cssom_stylesheet(CanGc::note())
1511 } else {
1512 None
1513 }
1514 }
1515
1516 pub(crate) fn is_styled(&self) -> bool {
1517 self.style_data.borrow().is_some()
1518 }
1519
1520 pub(crate) fn is_display_none(&self) -> bool {
1521 self.style_data.borrow().as_ref().is_none_or(|data| {
1522 data.element_data
1523 .borrow()
1524 .styles
1525 .primary()
1526 .get_box()
1527 .display
1528 .is_none()
1529 })
1530 }
1531
1532 pub(crate) fn style(&self) -> Option<ServoArc<ComputedValues>> {
1533 self.owner_window().layout_reflow(QueryMsg::StyleQuery);
1534 self.style_data
1535 .borrow()
1536 .as_ref()
1537 .map(|data| data.element_data.borrow().styles.primary().clone())
1538 }
1539
1540 pub(crate) fn get_lang(&self) -> Option<String> {
1542 self.inclusive_ancestors(ShadowIncluding::Yes)
1543 .find_map(|node| {
1544 node.downcast::<Element>().and_then(|el| {
1545 el.get_attribute(&ns!(xml), &local_name!("lang"))
1546 .or_else(|| el.get_attribute(&ns!(), &local_name!("lang")))
1547 .map(|attr| String::from(attr.Value()))
1548 })
1549 })
1552 }
1553
1554 pub(crate) fn assign_slottables_for_a_tree(&self) {
1556 let is_shadow_root_with_slots = self
1560 .downcast::<ShadowRoot>()
1561 .is_some_and(|shadow_root| shadow_root.has_slot_descendants());
1562 if !is_shadow_root_with_slots && !self.is::<HTMLSlotElement>() {
1563 return;
1564 }
1565
1566 for node in self.traverse_preorder(ShadowIncluding::No) {
1569 if let Some(slot) = node.downcast::<HTMLSlotElement>() {
1570 slot.assign_slottables();
1571 }
1572 }
1573 }
1574
1575 pub(crate) fn assigned_slot(&self) -> Option<DomRoot<HTMLSlotElement>> {
1576 let assigned_slot = self
1577 .rare_data
1578 .borrow()
1579 .as_ref()?
1580 .slottable_data
1581 .assigned_slot
1582 .as_ref()?
1583 .as_rooted();
1584 Some(assigned_slot)
1585 }
1586
1587 pub(crate) fn set_assigned_slot(&self, assigned_slot: Option<&HTMLSlotElement>) {
1588 self.ensure_rare_data().slottable_data.assigned_slot = assigned_slot.map(Dom::from_ref);
1589 }
1590
1591 pub(crate) fn manual_slot_assignment(&self) -> Option<DomRoot<HTMLSlotElement>> {
1592 let manually_assigned_slot = self
1593 .rare_data
1594 .borrow()
1595 .as_ref()?
1596 .slottable_data
1597 .manual_slot_assignment
1598 .as_ref()?
1599 .as_rooted();
1600 Some(manually_assigned_slot)
1601 }
1602
1603 pub(crate) fn set_manual_slot_assignment(
1604 &self,
1605 manually_assigned_slot: Option<&HTMLSlotElement>,
1606 ) {
1607 self.ensure_rare_data()
1608 .slottable_data
1609 .manual_slot_assignment = manually_assigned_slot.map(Dom::from_ref);
1610 }
1611
1612 pub(crate) fn parent_in_flat_tree(&self) -> Option<DomRoot<Node>> {
1618 if let Some(assigned_slot) = self.assigned_slot() {
1619 return Some(DomRoot::upcast(assigned_slot));
1620 }
1621
1622 let parent_or_none = self.GetParentNode();
1623 if let Some(parent) = parent_or_none.as_deref() {
1624 if let Some(shadow_root) = parent.downcast::<ShadowRoot>() {
1625 return Some(DomRoot::from_ref(shadow_root.Host().upcast::<Node>()));
1626 }
1627 }
1628
1629 parent_or_none
1630 }
1631
1632 pub(crate) fn inclusive_ancestors_in_flat_tree(
1633 &self,
1634 ) -> impl Iterator<Item = DomRoot<Node>> + use<> {
1635 SimpleNodeIterator {
1636 current: Some(DomRoot::from_ref(self)),
1637 next_node: move |n| n.parent_in_flat_tree(),
1638 }
1639 }
1640
1641 pub(crate) fn set_implemented_pseudo_element(&self, pseudo_element: PseudoElement) {
1643 debug_assert!(self.is_in_ua_widget());
1645 self.ensure_rare_data().implemented_pseudo_element = Some(pseudo_element);
1646 }
1647
1648 pub(crate) fn implemented_pseudo_element(&self) -> Option<PseudoElement> {
1649 self.rare_data
1650 .borrow()
1651 .as_ref()
1652 .and_then(|rare_data| rare_data.implemented_pseudo_element)
1653 }
1654}
1655
1656fn first_node_not_in<I>(mut nodes: I, not_in: &[NodeOrString]) -> Option<DomRoot<Node>>
1658where
1659 I: Iterator<Item = DomRoot<Node>>,
1660{
1661 nodes.find(|node| {
1662 not_in.iter().all(|n| match *n {
1663 NodeOrString::Node(ref n) => n != node,
1664 _ => true,
1665 })
1666 })
1667}
1668
1669#[expect(unsafe_code)]
1672pub(crate) unsafe fn from_untrusted_node_address(candidate: UntrustedNodeAddress) -> DomRoot<Node> {
1673 let node = unsafe { Node::from_untrusted_node_address(candidate) };
1674 DomRoot::from_ref(node)
1675}
1676
1677#[expect(unsafe_code)]
1678pub(crate) trait LayoutNodeHelpers<'dom> {
1679 fn type_id_for_layout(self) -> NodeTypeId;
1680
1681 fn parent_node_ref(self) -> Option<LayoutDom<'dom, Node>>;
1682 fn composed_parent_node_ref(self) -> Option<LayoutDom<'dom, Node>>;
1683 fn first_child_ref(self) -> Option<LayoutDom<'dom, Node>>;
1684 fn last_child_ref(self) -> Option<LayoutDom<'dom, Node>>;
1685 fn prev_sibling_ref(self) -> Option<LayoutDom<'dom, Node>>;
1686 fn next_sibling_ref(self) -> Option<LayoutDom<'dom, Node>>;
1687
1688 fn owner_doc_for_layout(self) -> LayoutDom<'dom, Document>;
1689 fn containing_shadow_root_for_layout(self) -> Option<LayoutDom<'dom, ShadowRoot>>;
1690 fn assigned_slot_for_layout(self) -> Option<LayoutDom<'dom, HTMLSlotElement>>;
1691
1692 fn is_element_for_layout(&self) -> bool;
1693 fn is_text_node_for_layout(&self) -> bool;
1694 unsafe fn get_flag(self, flag: NodeFlags) -> bool;
1695 unsafe fn set_flag(self, flag: NodeFlags, value: bool);
1696
1697 fn style_data(self) -> Option<&'dom StyleData>;
1698 fn layout_data(self) -> Option<&'dom GenericLayoutData>;
1699
1700 unsafe fn initialize_style_data(self);
1708
1709 unsafe fn initialize_layout_data(self, data: Box<GenericLayoutData>);
1717
1718 unsafe fn clear_style_and_layout_data(self);
1726
1727 fn is_single_line_text_inner_editor(&self) -> bool;
1730
1731 fn is_text_container_of_single_line_input(&self) -> bool;
1734 fn text_content(self) -> Cow<'dom, str>;
1735 fn selection(self) -> Option<SharedSelection>;
1736 fn image_url(self) -> Option<ServoUrl>;
1737 fn image_density(self) -> Option<f64>;
1738 fn image_data(self) -> Option<(Option<Image>, Option<ImageMetadata>)>;
1739 fn showing_broken_image_icon(self) -> bool;
1740 fn canvas_data(self) -> Option<HTMLCanvasData>;
1741 fn media_data(self) -> Option<HTMLMediaData>;
1742 fn svg_data(self) -> Option<SVGElementData<'dom>>;
1743 fn iframe_browsing_context_id(self) -> Option<BrowsingContextId>;
1744 fn iframe_pipeline_id(self) -> Option<PipelineId>;
1745 fn opaque(self) -> OpaqueNode;
1746 fn implemented_pseudo_element(&self) -> Option<PseudoElement>;
1747 fn is_in_ua_widget(&self) -> bool;
1748}
1749
1750impl<'dom> LayoutDom<'dom, Node> {
1751 #[inline]
1752 #[expect(unsafe_code)]
1753 pub(crate) fn parent_node_ref(self) -> Option<LayoutDom<'dom, Node>> {
1754 unsafe { self.unsafe_get().parent_node.get_inner_as_layout() }
1755 }
1756}
1757
1758impl<'dom> LayoutNodeHelpers<'dom> for LayoutDom<'dom, Node> {
1759 #[inline]
1760 fn type_id_for_layout(self) -> NodeTypeId {
1761 self.unsafe_get().type_id()
1762 }
1763
1764 #[inline]
1765 fn is_element_for_layout(&self) -> bool {
1766 (*self).is::<Element>()
1767 }
1768
1769 fn is_text_node_for_layout(&self) -> bool {
1770 self.type_id_for_layout() ==
1771 NodeTypeId::CharacterData(CharacterDataTypeId::Text(TextTypeId::Text))
1772 }
1773
1774 #[inline]
1775 #[expect(unsafe_code)]
1776 fn parent_node_ref(self) -> Option<LayoutDom<'dom, Node>> {
1777 unsafe { self.unsafe_get().parent_node.get_inner_as_layout() }
1778 }
1779
1780 #[inline]
1781 fn composed_parent_node_ref(self) -> Option<LayoutDom<'dom, Node>> {
1782 let parent = self.parent_node_ref();
1783 if let Some(parent) = parent {
1784 if let Some(shadow_root) = parent.downcast::<ShadowRoot>() {
1785 return Some(shadow_root.get_host_for_layout().upcast());
1786 }
1787 }
1788 parent
1789 }
1790
1791 #[inline]
1792 #[expect(unsafe_code)]
1793 fn first_child_ref(self) -> Option<LayoutDom<'dom, Node>> {
1794 unsafe { self.unsafe_get().first_child.get_inner_as_layout() }
1795 }
1796
1797 #[inline]
1798 #[expect(unsafe_code)]
1799 fn last_child_ref(self) -> Option<LayoutDom<'dom, Node>> {
1800 unsafe { self.unsafe_get().last_child.get_inner_as_layout() }
1801 }
1802
1803 #[inline]
1804 #[expect(unsafe_code)]
1805 fn prev_sibling_ref(self) -> Option<LayoutDom<'dom, Node>> {
1806 unsafe { self.unsafe_get().prev_sibling.get_inner_as_layout() }
1807 }
1808
1809 #[inline]
1810 #[expect(unsafe_code)]
1811 fn next_sibling_ref(self) -> Option<LayoutDom<'dom, Node>> {
1812 unsafe { self.unsafe_get().next_sibling.get_inner_as_layout() }
1813 }
1814
1815 #[inline]
1816 #[expect(unsafe_code)]
1817 fn owner_doc_for_layout(self) -> LayoutDom<'dom, Document> {
1818 unsafe { self.unsafe_get().owner_doc.get_inner_as_layout().unwrap() }
1819 }
1820
1821 #[inline]
1822 #[expect(unsafe_code)]
1823 fn containing_shadow_root_for_layout(self) -> Option<LayoutDom<'dom, ShadowRoot>> {
1824 unsafe {
1825 self.unsafe_get()
1826 .rare_data
1827 .borrow_for_layout()
1828 .as_ref()?
1829 .containing_shadow_root
1830 .as_ref()
1831 .map(|sr| sr.to_layout())
1832 }
1833 }
1834
1835 #[inline]
1836 #[expect(unsafe_code)]
1837 fn assigned_slot_for_layout(self) -> Option<LayoutDom<'dom, HTMLSlotElement>> {
1838 unsafe {
1839 self.unsafe_get()
1840 .rare_data
1841 .borrow_for_layout()
1842 .as_ref()?
1843 .slottable_data
1844 .assigned_slot
1845 .as_ref()
1846 .map(|assigned_slot| assigned_slot.to_layout())
1847 }
1848 }
1849
1850 #[inline]
1855 #[expect(unsafe_code)]
1856 unsafe fn get_flag(self, flag: NodeFlags) -> bool {
1857 (self.unsafe_get()).flags.get().contains(flag)
1858 }
1859
1860 #[inline]
1861 #[expect(unsafe_code)]
1862 unsafe fn set_flag(self, flag: NodeFlags, value: bool) {
1863 let this = self.unsafe_get();
1864 let mut flags = (this).flags.get();
1865
1866 if value {
1867 flags.insert(flag);
1868 } else {
1869 flags.remove(flag);
1870 }
1871
1872 (this).flags.set(flags);
1873 }
1874
1875 #[inline]
1878 #[expect(unsafe_code)]
1879 fn style_data(self) -> Option<&'dom StyleData> {
1880 unsafe { self.unsafe_get().style_data.borrow_for_layout().as_deref() }
1881 }
1882
1883 #[inline]
1884 #[expect(unsafe_code)]
1885 fn layout_data(self) -> Option<&'dom GenericLayoutData> {
1886 unsafe { self.unsafe_get().layout_data.borrow_for_layout().as_deref() }
1887 }
1888
1889 #[inline]
1890 #[expect(unsafe_code)]
1891 unsafe fn initialize_style_data(self) {
1892 let data = unsafe { self.unsafe_get().style_data.borrow_mut_for_layout() };
1893 debug_assert!(data.is_none());
1894 *data = Some(Box::default());
1895 }
1896
1897 #[inline]
1898 #[expect(unsafe_code)]
1899 unsafe fn initialize_layout_data(self, new_data: Box<GenericLayoutData>) {
1900 let data = unsafe { self.unsafe_get().layout_data.borrow_mut_for_layout() };
1901 debug_assert!(data.is_none());
1902 *data = Some(new_data);
1903 }
1904
1905 #[inline]
1906 #[expect(unsafe_code)]
1907 unsafe fn clear_style_and_layout_data(self) {
1908 unsafe {
1909 self.unsafe_get().style_data.borrow_mut_for_layout().take();
1910 self.unsafe_get().layout_data.borrow_mut_for_layout().take();
1911 }
1912 }
1913
1914 fn is_single_line_text_inner_editor(&self) -> bool {
1915 matches!(
1916 self.unsafe_get().implemented_pseudo_element(),
1917 Some(PseudoElement::ServoTextControlInnerEditor)
1918 )
1919 }
1920
1921 fn is_text_container_of_single_line_input(&self) -> bool {
1922 let is_single_line_text_inner_placeholder = matches!(
1923 self.unsafe_get().implemented_pseudo_element(),
1924 Some(PseudoElement::Placeholder)
1925 );
1926 debug_assert!(
1928 !is_single_line_text_inner_placeholder ||
1929 self.containing_shadow_root_for_layout()
1930 .map(|root| root.get_host_for_layout())
1931 .map(|host| host.downcast::<HTMLInputElement>())
1932 .is_some()
1933 );
1934
1935 self.is_single_line_text_inner_editor() || is_single_line_text_inner_placeholder
1936 }
1937
1938 fn text_content(self) -> Cow<'dom, str> {
1939 self.downcast::<Text>()
1940 .expect("Called LayoutDom::text_content on non-Text node!")
1941 .upcast()
1942 .data_for_layout()
1943 .into()
1944 }
1945
1946 fn selection(self) -> Option<SharedSelection> {
1953 if let Some(input) = self.downcast::<HTMLInputElement>() {
1954 return input.selection_for_layout();
1955 }
1956 if let Some(textarea) = self.downcast::<HTMLTextAreaElement>() {
1957 return Some(textarea.selection_for_layout());
1958 }
1959
1960 let shadow_root = self
1961 .containing_shadow_root_for_layout()?
1962 .get_host_for_layout();
1963 if let Some(input) = shadow_root.downcast::<HTMLInputElement>() {
1964 return input.selection_for_layout();
1965 }
1966 shadow_root
1967 .downcast::<HTMLTextAreaElement>()
1968 .map(|textarea| textarea.selection_for_layout())
1969 }
1970
1971 fn image_url(self) -> Option<ServoUrl> {
1972 self.downcast::<HTMLImageElement>()
1973 .expect("not an image!")
1974 .image_url()
1975 }
1976
1977 fn image_data(self) -> Option<(Option<Image>, Option<ImageMetadata>)> {
1978 self.downcast::<HTMLImageElement>().map(|e| e.image_data())
1979 }
1980
1981 fn image_density(self) -> Option<f64> {
1982 self.downcast::<HTMLImageElement>()
1983 .expect("not an image!")
1984 .image_density()
1985 }
1986
1987 fn showing_broken_image_icon(self) -> bool {
1988 self.downcast::<HTMLImageElement>()
1989 .map(|image_element| image_element.showing_broken_image_icon())
1990 .unwrap_or_default()
1991 }
1992
1993 fn canvas_data(self) -> Option<HTMLCanvasData> {
1994 self.downcast::<HTMLCanvasElement>()
1995 .map(|canvas| canvas.data())
1996 }
1997
1998 fn media_data(self) -> Option<HTMLMediaData> {
1999 self.downcast::<HTMLVideoElement>()
2000 .map(|media| media.data())
2001 }
2002
2003 fn svg_data(self) -> Option<SVGElementData<'dom>> {
2004 self.downcast::<SVGSVGElement>().map(|svg| svg.data())
2005 }
2006
2007 fn iframe_browsing_context_id(self) -> Option<BrowsingContextId> {
2008 self.downcast::<HTMLIFrameElement>()
2009 .and_then(|iframe_element| iframe_element.browsing_context_id())
2010 }
2011
2012 fn iframe_pipeline_id(self) -> Option<PipelineId> {
2013 self.downcast::<HTMLIFrameElement>()
2014 .and_then(|iframe_element| iframe_element.pipeline_id())
2015 }
2016
2017 #[expect(unsafe_code)]
2018 fn opaque(self) -> OpaqueNode {
2019 unsafe { OpaqueNode(self.get_jsobject() as usize) }
2020 }
2021
2022 fn implemented_pseudo_element(&self) -> Option<PseudoElement> {
2023 self.unsafe_get().implemented_pseudo_element()
2024 }
2025
2026 fn is_in_ua_widget(&self) -> bool {
2027 self.unsafe_get().is_in_ua_widget()
2028 }
2029}
2030
2031pub(crate) struct FollowingNodeIterator {
2036 current: Option<DomRoot<Node>>,
2037 root: DomRoot<Node>,
2038}
2039
2040impl FollowingNodeIterator {
2041 pub(crate) fn next_skipping_children(&mut self) -> Option<DomRoot<Node>> {
2043 let current = self.current.take()?;
2044 self.next_skipping_children_impl(current)
2045 }
2046
2047 fn next_skipping_children_impl(&mut self, current: DomRoot<Node>) -> Option<DomRoot<Node>> {
2048 if self.root == current {
2049 self.current = None;
2050 return None;
2051 }
2052
2053 if let Some(next_sibling) = current.GetNextSibling() {
2054 self.current = Some(next_sibling);
2055 return current.GetNextSibling();
2056 }
2057
2058 for ancestor in current.inclusive_ancestors(ShadowIncluding::No) {
2059 if self.root == ancestor {
2060 break;
2061 }
2062 if let Some(next_sibling) = ancestor.GetNextSibling() {
2063 self.current = Some(next_sibling);
2064 return ancestor.GetNextSibling();
2065 }
2066 }
2067 self.current = None;
2068 None
2069 }
2070}
2071
2072impl Iterator for FollowingNodeIterator {
2073 type Item = DomRoot<Node>;
2074
2075 fn next(&mut self) -> Option<DomRoot<Node>> {
2077 let current = self.current.take()?;
2078
2079 if let Some(first_child) = current.GetFirstChild() {
2080 self.current = Some(first_child);
2081 return current.GetFirstChild();
2082 }
2083
2084 self.next_skipping_children_impl(current)
2085 }
2086}
2087
2088pub(crate) struct PrecedingNodeIterator {
2089 current: Option<DomRoot<Node>>,
2090 root: DomRoot<Node>,
2091}
2092
2093impl Iterator for PrecedingNodeIterator {
2094 type Item = DomRoot<Node>;
2095
2096 fn next(&mut self) -> Option<DomRoot<Node>> {
2098 let current = self.current.take()?;
2099
2100 self.current = if self.root == current {
2101 None
2102 } else if let Some(previous_sibling) = current.GetPreviousSibling() {
2103 if self.root == previous_sibling {
2104 None
2105 } else if let Some(last_child) = previous_sibling.descending_last_children().last() {
2106 Some(last_child)
2107 } else {
2108 Some(previous_sibling)
2109 }
2110 } else {
2111 current.GetParentNode()
2112 };
2113 self.current.clone()
2114 }
2115}
2116
2117struct SimpleNodeIterator<I>
2118where
2119 I: Fn(&Node) -> Option<DomRoot<Node>>,
2120{
2121 current: Option<DomRoot<Node>>,
2122 next_node: I,
2123}
2124
2125impl<I> Iterator for SimpleNodeIterator<I>
2126where
2127 I: Fn(&Node) -> Option<DomRoot<Node>>,
2128{
2129 type Item = DomRoot<Node>;
2130
2131 fn next(&mut self) -> Option<Self::Item> {
2132 let current = self.current.take();
2133 self.current = current.as_ref().and_then(|c| (self.next_node)(c));
2134 current
2135 }
2136}
2137
2138#[derive(Clone, Copy, PartialEq)]
2140pub(crate) enum ShadowIncluding {
2141 No,
2142 Yes,
2143}
2144
2145pub(crate) struct TreeIterator {
2146 current: Option<DomRoot<Node>>,
2147 depth: usize,
2148 shadow_including: bool,
2149}
2150
2151impl TreeIterator {
2152 fn new(root: &Node, shadow_including: ShadowIncluding) -> TreeIterator {
2153 TreeIterator {
2154 current: Some(DomRoot::from_ref(root)),
2155 depth: 0,
2156 shadow_including: shadow_including == ShadowIncluding::Yes,
2157 }
2158 }
2159
2160 pub(crate) fn next_skipping_children(&mut self) -> Option<DomRoot<Node>> {
2161 let current = self.current.take()?;
2162
2163 self.next_skipping_children_impl(current)
2164 }
2165
2166 fn next_skipping_children_impl(&mut self, current: DomRoot<Node>) -> Option<DomRoot<Node>> {
2167 let iter = current.inclusive_ancestors(if self.shadow_including {
2168 ShadowIncluding::Yes
2169 } else {
2170 ShadowIncluding::No
2171 });
2172
2173 for ancestor in iter {
2174 if self.depth == 0 {
2175 break;
2176 }
2177 if let Some(next_sibling) = ancestor.GetNextSibling() {
2178 self.current = Some(next_sibling);
2179 return Some(current);
2180 }
2181 if let Some(shadow_root) = ancestor.downcast::<ShadowRoot>() {
2182 if let Some(child) = shadow_root.Host().upcast::<Node>().GetFirstChild() {
2185 self.current = Some(child);
2186 return Some(current);
2187 }
2188 }
2189 self.depth -= 1;
2190 }
2191 debug_assert_eq!(self.depth, 0);
2192 self.current = None;
2193 Some(current)
2194 }
2195
2196 pub(crate) fn peek(&self) -> Option<&DomRoot<Node>> {
2197 self.current.as_ref()
2198 }
2199}
2200
2201impl Iterator for TreeIterator {
2202 type Item = DomRoot<Node>;
2203
2204 fn next(&mut self) -> Option<DomRoot<Node>> {
2207 let current = self.current.take()?;
2208
2209 if let Some(element) = current.downcast::<Element>() {
2211 if let Some(shadow_root) = element.shadow_root() {
2212 if self.shadow_including {
2213 self.current = Some(DomRoot::from_ref(shadow_root.upcast::<Node>()));
2214 self.depth += 1;
2215 return Some(current);
2216 }
2217 }
2218 }
2219
2220 if let Some(first_child) = current.GetFirstChild() {
2221 self.current = Some(first_child);
2222 self.depth += 1;
2223 return Some(current);
2224 };
2225
2226 self.next_skipping_children_impl(current)
2227 }
2228}
2229
2230#[derive(Clone, Copy, MallocSizeOf, PartialEq)]
2232pub(crate) enum CloneChildrenFlag {
2233 CloneChildren,
2234 DoNotCloneChildren,
2235}
2236
2237impl From<bool> for CloneChildrenFlag {
2238 fn from(boolean: bool) -> Self {
2239 if boolean {
2240 CloneChildrenFlag::CloneChildren
2241 } else {
2242 CloneChildrenFlag::DoNotCloneChildren
2243 }
2244 }
2245}
2246
2247fn as_uintptr<T>(t: &T) -> uintptr_t {
2248 t as *const T as uintptr_t
2249}
2250
2251impl Node {
2252 pub(crate) fn reflect_node<N>(node: Box<N>, document: &Document, can_gc: CanGc) -> DomRoot<N>
2253 where
2254 N: DerivedFrom<Node> + DomObject + DomObjectWrap<crate::DomTypeHolder>,
2255 {
2256 Self::reflect_node_with_proto(node, document, None, can_gc)
2257 }
2258
2259 pub(crate) fn reflect_node_with_proto<N>(
2260 node: Box<N>,
2261 document: &Document,
2262 proto: Option<HandleObject>,
2263 can_gc: CanGc,
2264 ) -> DomRoot<N>
2265 where
2266 N: DerivedFrom<Node> + DomObject + DomObjectWrap<crate::DomTypeHolder>,
2267 {
2268 let window = document.window();
2269 reflect_dom_object_with_proto(node, window, proto, can_gc)
2270 }
2271
2272 pub(crate) fn new_inherited(doc: &Document) -> Node {
2273 Node::new_(NodeFlags::empty(), Some(doc))
2274 }
2275
2276 pub(crate) fn new_document_node() -> Node {
2277 Node::new_(
2278 NodeFlags::IS_IN_A_DOCUMENT_TREE | NodeFlags::IS_CONNECTED,
2279 None,
2280 )
2281 }
2282
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
2585 let mut static_node_list: SmallVec<[_; 4]> = Default::default();
2587
2588 let parent_shadow_root = parent.downcast::<Element>().and_then(Element::shadow_root);
2589 let parent_in_shadow_tree = parent.is_in_a_shadow_tree();
2590 let parent_as_slot = parent.downcast::<HTMLSlotElement>();
2591
2592 for kid in new_nodes {
2594 Node::adopt(kid, &parent.owner_document(), can_gc);
2596
2597 parent.add_child(kid, child, can_gc);
2600
2601 if let Some(ref shadow_root) = parent_shadow_root {
2604 if shadow_root.SlotAssignment() == SlotAssignmentMode::Named {
2605 let cx = GlobalScope::get_cx();
2606 if kid.is::<Element>() || kid.is::<Text>() {
2607 rooted!(in(*cx) let slottable = Slottable(Dom::from_ref(kid)));
2608 slottable.assign_a_slot();
2609 }
2610 }
2611 }
2612
2613 if parent_in_shadow_tree {
2616 if let Some(slot_element) = parent_as_slot {
2617 if !slot_element.has_assigned_nodes() {
2618 slot_element.signal_a_slot_change();
2619 }
2620 }
2621 }
2622
2623 kid.GetRootNode(&GetRootNodeOptions::empty())
2625 .assign_slottables_for_a_tree();
2626
2627 for descendant in kid.traverse_preorder(ShadowIncluding::Yes) {
2630 if descendant.is_connected() {
2633 static_node_list.push(descendant.clone());
2634 }
2635
2636 if let Some(descendant) = DomRoot::downcast::<Element>(descendant) {
2642 if descendant.is_custom() {
2643 if descendant.is_connected() {
2644 custom_element_reaction_stack.enqueue_callback_reaction(
2645 &descendant,
2646 CallbackReaction::Connected,
2647 None,
2648 );
2649 }
2650 } else {
2651 try_upgrade_element(&descendant);
2652 }
2653 }
2654 }
2655 }
2656
2657 if let SuppressObserver::Unsuppressed = suppress_observers {
2658 vtable_for(parent).children_changed(
2661 &ChildrenMutation::insert(previous_sibling.as_deref(), new_nodes, child),
2662 can_gc,
2663 );
2664
2665 let mutation = LazyCell::new(|| Mutation::ChildList {
2668 added: Some(new_nodes),
2669 removed: None,
2670 prev: previous_sibling.as_deref(),
2671 next: child,
2672 });
2673 MutationObserver::queue_a_mutation_record(parent, mutation);
2674 }
2675
2676 parent_document.add_delayed_task(
2687 task!(PostConnectionSteps: |cx, static_node_list: SmallVec<[DomRoot<Node>; 4]>| {
2688 for node in static_node_list {
2691 vtable_for(&node).post_connection_steps(CanGc::from_cx(cx));
2692 }
2693 }),
2694 );
2695
2696 parent_document.remove_script_and_layout_blocker();
2697 from_document.remove_script_and_layout_blocker();
2698 }
2699
2700 pub(crate) fn replace_all(node: Option<&Node>, parent: &Node, can_gc: CanGc) {
2702 parent.owner_doc().add_script_and_layout_blocker();
2703
2704 rooted_vec!(let removed_nodes <- parent.children().map(|child| DomRoot::as_traced(&child)));
2706
2707 rooted_vec!(let mut added_nodes);
2711 let added_nodes = if let Some(node) = node.as_ref() {
2712 if let NodeTypeId::DocumentFragment(_) = node.type_id() {
2713 added_nodes.extend(node.children().map(|child| Dom::from_ref(&*child)));
2714 added_nodes.r()
2715 } else {
2716 from_ref(node)
2717 }
2718 } else {
2719 &[] as &[&Node]
2720 };
2721
2722 for child in &*removed_nodes {
2724 Node::remove(child, parent, SuppressObserver::Suppressed, can_gc);
2725 }
2726
2727 if let Some(node) = node {
2729 Node::insert(node, parent, None, SuppressObserver::Suppressed, can_gc);
2730 }
2731
2732 vtable_for(parent).children_changed(
2733 &ChildrenMutation::replace_all(removed_nodes.r(), added_nodes),
2734 can_gc,
2735 );
2736
2737 if !removed_nodes.is_empty() || !added_nodes.is_empty() {
2740 let mutation = LazyCell::new(|| Mutation::ChildList {
2741 added: Some(added_nodes),
2742 removed: Some(removed_nodes.r()),
2743 prev: None,
2744 next: None,
2745 });
2746 MutationObserver::queue_a_mutation_record(parent, mutation);
2747 }
2748 parent.owner_doc().remove_script_and_layout_blocker();
2749 }
2750
2751 pub(crate) fn string_replace_all(string: DOMString, parent: &Node, can_gc: CanGc) {
2753 if string.is_empty() {
2754 Node::replace_all(None, parent, can_gc);
2755 } else {
2756 let text = Text::new(string, &parent.owner_document(), can_gc);
2757 Node::replace_all(Some(text.upcast::<Node>()), parent, can_gc);
2758 };
2759 }
2760
2761 fn pre_remove(child: &Node, parent: &Node, can_gc: CanGc) -> Fallible<DomRoot<Node>> {
2763 match child.GetParentNode() {
2765 Some(ref node) if &**node != parent => return Err(Error::NotFound(None)),
2766 None => return Err(Error::NotFound(None)),
2767 _ => (),
2768 }
2769
2770 Node::remove(child, parent, SuppressObserver::Unsuppressed, can_gc);
2772
2773 Ok(DomRoot::from_ref(child))
2775 }
2776
2777 fn remove(node: &Node, parent: &Node, suppress_observers: SuppressObserver, can_gc: CanGc) {
2779 parent.owner_doc().add_script_and_layout_blocker();
2780
2781 assert!(
2785 node.GetParentNode()
2786 .is_some_and(|node_parent| &*node_parent == parent)
2787 );
2788
2789 let cached_index = {
2792 if parent.ranges_is_empty() {
2793 None
2794 } else {
2795 let index = node.index();
2801
2802 parent.ranges().decrease_above(parent, index, 1);
2809
2810 Some(index)
2814 }
2815 };
2816
2817 let old_previous_sibling = node.GetPreviousSibling();
2821
2822 let old_next_sibling = node.GetNextSibling();
2824
2825 parent.remove_child(node, cached_index, can_gc);
2828
2829 if let Some(slot) = node.assigned_slot() {
2831 slot.assign_slottables();
2832 }
2833
2834 if parent.is_in_a_shadow_tree() {
2837 if let Some(slot_element) = parent.downcast::<HTMLSlotElement>() {
2838 if !slot_element.has_assigned_nodes() {
2839 slot_element.signal_a_slot_change();
2840 }
2841 }
2842 }
2843
2844 let has_slot_descendant = node
2846 .traverse_preorder(ShadowIncluding::No)
2847 .any(|elem| elem.is::<HTMLSlotElement>());
2848 if has_slot_descendant {
2849 parent
2851 .GetRootNode(&GetRootNodeOptions::empty())
2852 .assign_slottables_for_a_tree();
2853
2854 node.assign_slottables_for_a_tree();
2856 }
2857
2858 if let SuppressObserver::Unsuppressed = suppress_observers {
2862 vtable_for(parent).children_changed(
2863 &ChildrenMutation::replace(
2864 old_previous_sibling.as_deref(),
2865 &Some(node),
2866 &[],
2867 old_next_sibling.as_deref(),
2868 ),
2869 can_gc,
2870 );
2871
2872 let removed = [node];
2873 let mutation = LazyCell::new(|| Mutation::ChildList {
2874 added: None,
2875 removed: Some(&removed),
2876 prev: old_previous_sibling.as_deref(),
2877 next: old_next_sibling.as_deref(),
2878 });
2879 MutationObserver::queue_a_mutation_record(parent, mutation);
2880 }
2881 parent.owner_doc().remove_script_and_layout_blocker();
2882 }
2883
2884 fn compute_attribute_value_with_style_fast_path(attr: &Dom<Attr>, elem: &Element) -> AttrValue {
2890 if *attr.local_name() == local_name!("style") {
2891 if let Some(ref pdb) = *elem.style_attribute().borrow() {
2892 let document = elem.owner_document();
2893 let shared_lock = document.style_shared_lock();
2894 let new_pdb = pdb.read_with(&shared_lock.read()).clone();
2895 return AttrValue::Declaration(
2896 (**attr.value()).to_owned(),
2897 ServoArc::new(shared_lock.wrap(new_pdb)),
2898 );
2899 }
2900 }
2901
2902 attr.value().clone()
2903 }
2904
2905 pub(crate) fn clone(
2907 node: &Node,
2908 maybe_doc: Option<&Document>,
2909 clone_children: CloneChildrenFlag,
2910 registry: Option<DomRoot<CustomElementRegistry>>,
2911 can_gc: CanGc,
2912 ) -> DomRoot<Node> {
2913 let document = match maybe_doc {
2915 Some(doc) => DomRoot::from_ref(doc),
2916 None => node.owner_doc(),
2917 };
2918
2919 let copy: DomRoot<Node> = match node.type_id() {
2922 NodeTypeId::DocumentType => {
2923 let doctype = node.downcast::<DocumentType>().unwrap();
2924 let doctype = DocumentType::new(
2925 doctype.name().clone(),
2926 Some(doctype.public_id().clone()),
2927 Some(doctype.system_id().clone()),
2928 &document,
2929 can_gc,
2930 );
2931 DomRoot::upcast::<Node>(doctype)
2932 },
2933 NodeTypeId::Attr => {
2934 let attr = node.downcast::<Attr>().unwrap();
2935 let attr = Attr::new(
2936 &document,
2937 attr.local_name().clone(),
2938 attr.value().clone(),
2939 attr.name().clone(),
2940 attr.namespace().clone(),
2941 attr.prefix().cloned(),
2942 None,
2943 can_gc,
2944 );
2945 DomRoot::upcast::<Node>(attr)
2946 },
2947 NodeTypeId::DocumentFragment(_) => {
2948 let doc_fragment = DocumentFragment::new(&document, can_gc);
2949 DomRoot::upcast::<Node>(doc_fragment)
2950 },
2951 NodeTypeId::CharacterData(_) => {
2952 let cdata = node.downcast::<CharacterData>().unwrap();
2953 cdata.clone_with_data(cdata.Data(), &document, can_gc)
2954 },
2955 NodeTypeId::Document(_) => {
2956 let document = node.downcast::<Document>().unwrap();
2959 let is_html_doc = if document.is_html_document() {
2960 IsHTMLDocument::HTMLDocument
2961 } else {
2962 IsHTMLDocument::NonHTMLDocument
2963 };
2964 let window = document.window();
2965 let loader = DocumentLoader::new(&document.loader());
2966 let document = Document::new(
2967 window,
2968 HasBrowsingContext::No,
2969 Some(document.url()),
2970 None,
2971 document.origin().clone(),
2973 is_html_doc,
2974 None,
2975 None,
2976 DocumentActivity::Inactive,
2977 DocumentSource::NotFromParser,
2978 loader,
2979 None,
2980 document.status_code(),
2981 Default::default(),
2982 false,
2983 document.allow_declarative_shadow_roots(),
2984 Some(document.insecure_requests_policy()),
2985 document.has_trustworthy_ancestor_or_current_origin(),
2986 document.custom_element_reaction_stack(),
2987 document.creation_sandboxing_flag_set(),
2988 can_gc,
2989 );
2990 DomRoot::upcast::<Node>(document)
2994 },
2995 NodeTypeId::Element(..) => {
2997 let element = node.downcast::<Element>().unwrap();
2998 let registry = element.custom_element_registry().or(registry);
3001 let registry =
3004 if CustomElementRegistry::is_a_global_element_registry(registry.as_deref()) {
3005 Some(document.custom_element_registry())
3006 } else {
3007 registry
3008 };
3009 let name = QualName {
3013 prefix: element.prefix().as_ref().map(|p| Prefix::from(&**p)),
3014 ns: element.namespace().clone(),
3015 local: element.local_name().clone(),
3016 };
3017 let element = Element::create(
3018 name,
3019 element.get_is(),
3020 &document,
3021 ElementCreator::ScriptCreated,
3022 CustomElementCreationMode::Asynchronous,
3023 None,
3024 can_gc,
3025 );
3026 element.set_custom_element_registry(registry);
3028 DomRoot::upcast::<Node>(element)
3029 },
3030 };
3031
3032 let document = match copy.downcast::<Document>() {
3035 Some(doc) => DomRoot::from_ref(doc),
3036 None => DomRoot::from_ref(&*document),
3037 };
3038 assert!(copy.owner_doc() == document);
3039
3040 match node.type_id() {
3042 NodeTypeId::Document(_) => {
3043 let node_doc = node.downcast::<Document>().unwrap();
3044 let copy_doc = copy.downcast::<Document>().unwrap();
3045 copy_doc.set_encoding(node_doc.encoding());
3046 copy_doc.set_quirks_mode(node_doc.quirks_mode());
3047 },
3048 NodeTypeId::Element(..) => {
3049 let node_elem = node.downcast::<Element>().unwrap();
3050 let copy_elem = copy.downcast::<Element>().unwrap();
3051
3052 for attr in node_elem.attrs().iter() {
3054 let new_value =
3056 Node::compute_attribute_value_with_style_fast_path(attr, node_elem);
3057 copy_elem.push_new_attribute(
3059 attr.local_name().clone(),
3060 new_value,
3061 attr.name().clone(),
3062 attr.namespace().clone(),
3063 attr.prefix().cloned(),
3064 AttributeMutationReason::ByCloning,
3065 can_gc,
3066 );
3067 }
3068 },
3069 _ => (),
3070 }
3071
3072 vtable_for(node).cloning_steps(©, maybe_doc, clone_children, can_gc);
3075
3076 if clone_children == CloneChildrenFlag::CloneChildren {
3079 for child in node.children() {
3080 let child_copy = Node::clone(&child, Some(&document), clone_children, None, can_gc);
3081 let _inserted_node = Node::pre_insert(&child_copy, ©, None, can_gc);
3082 }
3083 }
3084
3085 if matches!(node.type_id(), NodeTypeId::Element(_)) {
3088 let node_elem = node.downcast::<Element>().unwrap();
3089 let copy_elem = copy.downcast::<Element>().unwrap();
3090
3091 if let Some(shadow_root) = node_elem.shadow_root().filter(|r| r.Clonable()) {
3092 assert!(!copy_elem.is_shadow_host());
3094
3095 let copy_shadow_root =
3099 copy_elem.attach_shadow(
3100 IsUserAgentWidget::No,
3101 shadow_root.Mode(),
3102 shadow_root.Clonable(),
3103 shadow_root.Serializable(),
3104 shadow_root.DelegatesFocus(),
3105 shadow_root.SlotAssignment(),
3106 can_gc
3107 )
3108 .expect("placement of attached shadow root must be valid, as this is a copy of an existing one");
3109
3110 copy_shadow_root.set_declarative(shadow_root.is_declarative());
3112
3113 for child in shadow_root.upcast::<Node>().children() {
3116 let child_copy = Node::clone(
3117 &child,
3118 Some(&document),
3119 CloneChildrenFlag::CloneChildren,
3120 None,
3121 can_gc,
3122 );
3123
3124 let _inserted_node = Node::pre_insert(
3126 &child_copy,
3127 copy_shadow_root.upcast::<Node>(),
3128 None,
3129 can_gc,
3130 );
3131 }
3132 }
3133 }
3134
3135 copy
3137 }
3138
3139 pub(crate) fn child_text_content(&self) -> DOMString {
3141 Node::collect_text_contents(self.children())
3142 }
3143
3144 pub(crate) fn descendant_text_content(&self) -> DOMString {
3146 Node::collect_text_contents(self.traverse_preorder(ShadowIncluding::No))
3147 }
3148
3149 pub(crate) fn collect_text_contents<T: Iterator<Item = DomRoot<Node>>>(
3150 iterator: T,
3151 ) -> DOMString {
3152 let mut content = String::new();
3153 for node in iterator {
3154 if let Some(text) = node.downcast::<Text>() {
3155 content.push_str(&text.upcast::<CharacterData>().data());
3156 }
3157 }
3158 DOMString::from(content)
3159 }
3160
3161 pub(crate) fn set_text_content_for_element(&self, value: Option<DOMString>, can_gc: CanGc) {
3163 assert!(matches!(
3166 self.type_id(),
3167 NodeTypeId::DocumentFragment(_) | NodeTypeId::Element(..)
3168 ));
3169 let value = value.unwrap_or_default();
3170 let node = if value.is_empty() {
3171 None
3173 } else {
3174 Some(DomRoot::upcast(
3177 self.owner_doc().CreateTextNode(value, can_gc),
3178 ))
3179 };
3180
3181 Self::replace_all(node.as_deref(), self, can_gc);
3183 }
3184
3185 pub(crate) fn namespace_to_string(namespace: Namespace) -> Option<DOMString> {
3186 match namespace {
3187 ns!() => None,
3188 _ => Some(DOMString::from(&*namespace)),
3190 }
3191 }
3192
3193 pub(crate) fn locate_namespace(node: &Node, prefix: Option<DOMString>) -> Namespace {
3195 match node.type_id() {
3196 NodeTypeId::Element(_) => node.downcast::<Element>().unwrap().locate_namespace(prefix),
3197 NodeTypeId::Attr => node
3198 .downcast::<Attr>()
3199 .unwrap()
3200 .GetOwnerElement()
3201 .as_ref()
3202 .map_or(ns!(), |elem| elem.locate_namespace(prefix)),
3203 NodeTypeId::Document(_) => node
3204 .downcast::<Document>()
3205 .unwrap()
3206 .GetDocumentElement()
3207 .as_ref()
3208 .map_or(ns!(), |elem| elem.locate_namespace(prefix)),
3209 NodeTypeId::DocumentType | NodeTypeId::DocumentFragment(_) => ns!(),
3210 _ => node
3211 .GetParentElement()
3212 .as_ref()
3213 .map_or(ns!(), |elem| elem.locate_namespace(prefix)),
3214 }
3215 }
3216
3217 #[expect(unsafe_code)]
3225 pub(crate) unsafe fn from_untrusted_node_address(
3226 candidate: UntrustedNodeAddress,
3227 ) -> &'static Self {
3228 let candidate = candidate.0 as usize;
3230 let object = candidate as *mut JSObject;
3231 if object.is_null() {
3232 panic!("Attempted to create a `Node` from an invalid pointer!")
3233 }
3234
3235 unsafe { &*(conversions::private_from_object(object) as *const Self) }
3236 }
3237
3238 pub(crate) fn html_serialize(
3239 &self,
3240 traversal_scope: html_serialize::TraversalScope,
3241 serialize_shadow_roots: bool,
3242 shadow_roots: Vec<DomRoot<ShadowRoot>>,
3243 can_gc: CanGc,
3244 ) -> DOMString {
3245 let mut writer = vec![];
3246 let mut serializer = HtmlSerializer::new(
3247 &mut writer,
3248 html_serialize::SerializeOpts {
3249 traversal_scope: traversal_scope.clone(),
3250 ..Default::default()
3251 },
3252 );
3253
3254 serialize_html_fragment(
3255 self,
3256 &mut serializer,
3257 traversal_scope,
3258 serialize_shadow_roots,
3259 shadow_roots,
3260 can_gc,
3261 )
3262 .expect("Serializing node failed");
3263
3264 DOMString::from(String::from_utf8(writer).unwrap())
3266 }
3267
3268 pub(crate) fn xml_serialize(
3270 &self,
3271 traversal_scope: xml_serialize::TraversalScope,
3272 ) -> Fallible<DOMString> {
3273 let mut writer = vec![];
3274 xml_serialize::serialize(
3275 &mut writer,
3276 &HtmlSerialize::new(self),
3277 xml_serialize::SerializeOpts { traversal_scope },
3278 )
3279 .map_err(|error| {
3280 error!("Cannot serialize node: {error}");
3281 Error::InvalidState(None)
3282 })?;
3283
3284 let string = DOMString::from(String::from_utf8(writer).map_err(|error| {
3286 error!("Cannot serialize node: {error}");
3287 Error::InvalidState(None)
3288 })?);
3289
3290 Ok(string)
3291 }
3292
3293 pub(crate) fn fragment_serialization_algorithm(
3295 &self,
3296 require_well_formed: bool,
3297 can_gc: CanGc,
3298 ) -> Fallible<DOMString> {
3299 let context_document = self.owner_document();
3301
3302 if context_document.is_html_document() {
3305 return Ok(self.html_serialize(
3306 html_serialize::TraversalScope::ChildrenOnly(None),
3307 false,
3308 vec![],
3309 can_gc,
3310 ));
3311 }
3312
3313 let _ = require_well_formed;
3316 self.xml_serialize(xml_serialize::TraversalScope::ChildrenOnly(None))
3317 }
3318
3319 pub(crate) fn establishes_scrolling_box(&self) -> bool {
3321 if self.is::<Document>() {
3326 return true;
3327 }
3328 let Some(element) = self.downcast::<Element>() else {
3329 return false;
3331 };
3332 element.style().is_some_and(|style| {
3335 let overflow_x = style.get_box().clone_overflow_x();
3336 let overflow_y = style.get_box().clone_overflow_y();
3337 overflow_x.is_scrollable() || overflow_y.is_scrollable()
3338 })
3339 }
3340}
3341
3342impl NodeMethods<crate::DomTypeHolder> for Node {
3343 fn NodeType(&self) -> u16 {
3345 match self.type_id() {
3346 NodeTypeId::Attr => NodeConstants::ATTRIBUTE_NODE,
3347 NodeTypeId::CharacterData(CharacterDataTypeId::Text(TextTypeId::Text)) => {
3348 NodeConstants::TEXT_NODE
3349 },
3350 NodeTypeId::CharacterData(CharacterDataTypeId::Text(TextTypeId::CDATASection)) => {
3351 NodeConstants::CDATA_SECTION_NODE
3352 },
3353 NodeTypeId::CharacterData(CharacterDataTypeId::ProcessingInstruction) => {
3354 NodeConstants::PROCESSING_INSTRUCTION_NODE
3355 },
3356 NodeTypeId::CharacterData(CharacterDataTypeId::Comment) => NodeConstants::COMMENT_NODE,
3357 NodeTypeId::Document(_) => NodeConstants::DOCUMENT_NODE,
3358 NodeTypeId::DocumentType => NodeConstants::DOCUMENT_TYPE_NODE,
3359 NodeTypeId::DocumentFragment(_) => NodeConstants::DOCUMENT_FRAGMENT_NODE,
3360 NodeTypeId::Element(_) => NodeConstants::ELEMENT_NODE,
3361 }
3362 }
3363
3364 fn NodeName(&self) -> DOMString {
3366 match self.type_id() {
3367 NodeTypeId::Attr => self.downcast::<Attr>().unwrap().qualified_name(),
3368 NodeTypeId::Element(..) => self.downcast::<Element>().unwrap().TagName(),
3369 NodeTypeId::CharacterData(CharacterDataTypeId::Text(TextTypeId::Text)) => {
3370 DOMString::from("#text")
3371 },
3372 NodeTypeId::CharacterData(CharacterDataTypeId::Text(TextTypeId::CDATASection)) => {
3373 DOMString::from("#cdata-section")
3374 },
3375 NodeTypeId::CharacterData(CharacterDataTypeId::ProcessingInstruction) => {
3376 self.downcast::<ProcessingInstruction>().unwrap().Target()
3377 },
3378 NodeTypeId::CharacterData(CharacterDataTypeId::Comment) => DOMString::from("#comment"),
3379 NodeTypeId::DocumentType => self.downcast::<DocumentType>().unwrap().name().clone(),
3380 NodeTypeId::DocumentFragment(_) => DOMString::from("#document-fragment"),
3381 NodeTypeId::Document(_) => DOMString::from("#document"),
3382 }
3383 }
3384
3385 fn BaseURI(&self) -> USVString {
3387 USVString(String::from(self.owner_doc().base_url().as_str()))
3388 }
3389
3390 fn IsConnected(&self) -> bool {
3392 self.is_connected()
3393 }
3394
3395 fn GetOwnerDocument(&self) -> Option<DomRoot<Document>> {
3397 match self.type_id() {
3398 NodeTypeId::Document(_) => None,
3399 _ => Some(self.owner_doc()),
3400 }
3401 }
3402
3403 fn GetRootNode(&self, options: &GetRootNodeOptions) -> DomRoot<Node> {
3405 if !options.composed {
3406 if let Some(shadow_root) = self.containing_shadow_root() {
3407 return DomRoot::upcast(shadow_root);
3408 }
3409 }
3410
3411 if self.is_connected() {
3412 DomRoot::from_ref(self.owner_doc().upcast::<Node>())
3413 } else {
3414 self.inclusive_ancestors(ShadowIncluding::Yes)
3415 .last()
3416 .unwrap()
3417 }
3418 }
3419
3420 fn GetParentNode(&self) -> Option<DomRoot<Node>> {
3422 self.parent_node.get()
3423 }
3424
3425 fn GetParentElement(&self) -> Option<DomRoot<Element>> {
3427 self.GetParentNode().and_then(DomRoot::downcast)
3428 }
3429
3430 fn HasChildNodes(&self) -> bool {
3432 self.first_child.get().is_some()
3433 }
3434
3435 fn ChildNodes(&self, can_gc: CanGc) -> DomRoot<NodeList> {
3437 if let Some(list) = self.ensure_rare_data().child_list.get() {
3438 return list;
3439 }
3440
3441 let doc = self.owner_doc();
3442 let window = doc.window();
3443 let list = NodeList::new_child_list(window, self, can_gc);
3444 self.ensure_rare_data().child_list.set(Some(&list));
3445 list
3446 }
3447
3448 fn GetFirstChild(&self) -> Option<DomRoot<Node>> {
3450 self.first_child.get()
3451 }
3452
3453 fn GetLastChild(&self) -> Option<DomRoot<Node>> {
3455 self.last_child.get()
3456 }
3457
3458 fn GetPreviousSibling(&self) -> Option<DomRoot<Node>> {
3460 self.prev_sibling.get()
3461 }
3462
3463 fn GetNextSibling(&self) -> Option<DomRoot<Node>> {
3465 self.next_sibling.get()
3466 }
3467
3468 fn GetNodeValue(&self) -> Option<DOMString> {
3470 match self.type_id() {
3471 NodeTypeId::Attr => Some(self.downcast::<Attr>().unwrap().Value()),
3472 NodeTypeId::CharacterData(_) => {
3473 self.downcast::<CharacterData>().map(CharacterData::Data)
3474 },
3475 _ => None,
3476 }
3477 }
3478
3479 fn SetNodeValue(&self, val: Option<DOMString>, can_gc: CanGc) -> Fallible<()> {
3481 match self.type_id() {
3482 NodeTypeId::Attr => {
3483 let attr = self.downcast::<Attr>().unwrap();
3484 attr.SetValue(val.unwrap_or_default(), can_gc)?;
3485 },
3486 NodeTypeId::CharacterData(_) => {
3487 let character_data = self.downcast::<CharacterData>().unwrap();
3488 character_data.SetData(val.unwrap_or_default());
3489 },
3490 _ => {},
3491 };
3492 Ok(())
3493 }
3494
3495 fn GetTextContent(&self) -> Option<DOMString> {
3497 match self.type_id() {
3498 NodeTypeId::DocumentFragment(_) | NodeTypeId::Element(..) => {
3499 let content =
3500 Node::collect_text_contents(self.traverse_preorder(ShadowIncluding::No));
3501 Some(content)
3502 },
3503 NodeTypeId::Attr => Some(self.downcast::<Attr>().unwrap().Value()),
3504 NodeTypeId::CharacterData(..) => {
3505 let characterdata = self.downcast::<CharacterData>().unwrap();
3506 Some(characterdata.Data())
3507 },
3508 NodeTypeId::DocumentType | NodeTypeId::Document(_) => None,
3509 }
3510 }
3511
3512 fn SetTextContent(&self, value: Option<DOMString>, can_gc: CanGc) -> Fallible<()> {
3514 match self.type_id() {
3515 NodeTypeId::DocumentFragment(_) | NodeTypeId::Element(..) => {
3516 self.set_text_content_for_element(value, can_gc);
3517 },
3518 NodeTypeId::Attr => {
3519 let attr = self.downcast::<Attr>().unwrap();
3520 attr.SetValue(value.unwrap_or_default(), can_gc)?;
3521 },
3522 NodeTypeId::CharacterData(..) => {
3523 let characterdata = self.downcast::<CharacterData>().unwrap();
3524 characterdata.SetData(value.unwrap_or_default());
3525 },
3526 NodeTypeId::DocumentType | NodeTypeId::Document(_) => {},
3527 };
3528 Ok(())
3529 }
3530
3531 fn InsertBefore(
3533 &self,
3534 node: &Node,
3535 child: Option<&Node>,
3536 can_gc: CanGc,
3537 ) -> Fallible<DomRoot<Node>> {
3538 Node::pre_insert(node, self, child, can_gc)
3539 }
3540
3541 fn AppendChild(&self, node: &Node, can_gc: CanGc) -> Fallible<DomRoot<Node>> {
3543 Node::pre_insert(node, self, None, can_gc)
3544 }
3545
3546 fn ReplaceChild(&self, node: &Node, child: &Node, can_gc: CanGc) -> Fallible<DomRoot<Node>> {
3548 match self.type_id() {
3551 NodeTypeId::Document(_) | NodeTypeId::DocumentFragment(_) | NodeTypeId::Element(..) => {
3552 },
3553 _ => return Err(Error::HierarchyRequest(None)),
3554 }
3555
3556 if node.is_inclusive_ancestor_of(self) {
3559 return Err(Error::HierarchyRequest(None));
3560 }
3561
3562 if !self.is_parent_of(child) {
3564 return Err(Error::NotFound(None));
3565 }
3566
3567 match node.type_id() {
3572 NodeTypeId::CharacterData(CharacterDataTypeId::Text(_)) if self.is::<Document>() => {
3573 return Err(Error::HierarchyRequest(None));
3574 },
3575 NodeTypeId::DocumentType if !self.is::<Document>() => {
3576 return Err(Error::HierarchyRequest(None));
3577 },
3578 NodeTypeId::Document(_) | NodeTypeId::Attr => {
3579 return Err(Error::HierarchyRequest(None));
3580 },
3581 _ => (),
3582 }
3583
3584 if self.is::<Document>() {
3587 match node.type_id() {
3588 NodeTypeId::DocumentFragment(_) => {
3590 if node.children().any(|c| c.is::<Text>()) {
3592 return Err(Error::HierarchyRequest(None));
3593 }
3594 match node.child_elements().count() {
3595 0 => (),
3596 1 => {
3598 if self.child_elements().any(|c| c.upcast::<Node>() != child) {
3599 return Err(Error::HierarchyRequest(None));
3600 }
3601 if child.following_siblings().any(|child| child.is_doctype()) {
3602 return Err(Error::HierarchyRequest(None));
3603 }
3604 },
3605 _ => return Err(Error::HierarchyRequest(None)),
3607 }
3608 },
3609 NodeTypeId::Element(..) => {
3611 if self.child_elements().any(|c| c.upcast::<Node>() != child) {
3612 return Err(Error::HierarchyRequest(None));
3613 }
3614 if child.following_siblings().any(|child| child.is_doctype()) {
3615 return Err(Error::HierarchyRequest(None));
3616 }
3617 },
3618 NodeTypeId::DocumentType => {
3620 if self.children().any(|c| c.is_doctype() && &*c != child) {
3621 return Err(Error::HierarchyRequest(None));
3622 }
3623 if self
3624 .children()
3625 .take_while(|c| &**c != child)
3626 .any(|c| c.is::<Element>())
3627 {
3628 return Err(Error::HierarchyRequest(None));
3629 }
3630 },
3631 NodeTypeId::CharacterData(..) => (),
3632 NodeTypeId::Document(_) => unreachable!(),
3635 NodeTypeId::Attr => unreachable!(),
3636 }
3637 }
3638
3639 let child_next_sibling = child.GetNextSibling();
3642 let node_next_sibling = node.GetNextSibling();
3643 let reference_child = if child_next_sibling.as_deref() == Some(node) {
3644 node_next_sibling.as_deref()
3645 } else {
3646 child_next_sibling.as_deref()
3647 };
3648
3649 let previous_sibling = child.GetPreviousSibling();
3651
3652 let document = self.owner_document();
3656 Node::adopt(node, &document, can_gc);
3657
3658 let removed_child = if node != child {
3663 Node::remove(child, self, SuppressObserver::Suppressed, can_gc);
3665 Some(child)
3666 } else {
3667 None
3668 };
3669
3670 rooted_vec!(let mut nodes);
3672 let nodes = if node.type_id() ==
3673 NodeTypeId::DocumentFragment(DocumentFragmentTypeId::DocumentFragment) ||
3674 node.type_id() == NodeTypeId::DocumentFragment(DocumentFragmentTypeId::ShadowRoot)
3675 {
3676 nodes.extend(node.children().map(|node| Dom::from_ref(&*node)));
3677 nodes.r()
3678 } else {
3679 from_ref(&node)
3680 };
3681
3682 Node::insert(
3684 node,
3685 self,
3686 reference_child,
3687 SuppressObserver::Suppressed,
3688 can_gc,
3689 );
3690
3691 vtable_for(self).children_changed(
3692 &ChildrenMutation::replace(
3693 previous_sibling.as_deref(),
3694 &removed_child,
3695 nodes,
3696 reference_child,
3697 ),
3698 can_gc,
3699 );
3700
3701 let removed = removed_child.map(|r| [r]);
3704 let mutation = LazyCell::new(|| Mutation::ChildList {
3705 added: Some(nodes),
3706 removed: removed.as_ref().map(|r| &r[..]),
3707 prev: previous_sibling.as_deref(),
3708 next: reference_child,
3709 });
3710
3711 MutationObserver::queue_a_mutation_record(self, mutation);
3712
3713 Ok(DomRoot::from_ref(child))
3715 }
3716
3717 fn RemoveChild(&self, node: &Node, can_gc: CanGc) -> Fallible<DomRoot<Node>> {
3719 Node::pre_remove(node, self, can_gc)
3720 }
3721
3722 fn Normalize(&self, can_gc: CanGc) {
3724 let mut children = self.children().enumerate().peekable();
3725 while let Some((_, node)) = children.next() {
3726 if let Some(text) = node.downcast::<Text>() {
3727 if text.is::<CDATASection>() {
3728 continue;
3729 }
3730 let cdata = text.upcast::<CharacterData>();
3731 let mut length = cdata.Length();
3732 if length == 0 {
3733 Node::remove(&node, self, SuppressObserver::Unsuppressed, can_gc);
3734 continue;
3735 }
3736 while children.peek().is_some_and(|(_, sibling)| {
3737 sibling.is::<Text>() && !sibling.is::<CDATASection>()
3738 }) {
3739 let (index, sibling) = children.next().unwrap();
3740 sibling
3741 .ranges()
3742 .drain_to_preceding_text_sibling(&sibling, &node, length);
3743 self.ranges()
3744 .move_to_text_child_at(self, index as u32, &node, length);
3745 let sibling_cdata = sibling.downcast::<CharacterData>().unwrap();
3746 length += sibling_cdata.Length();
3747 cdata.append_data(&sibling_cdata.data());
3748 Node::remove(&sibling, self, SuppressObserver::Unsuppressed, can_gc);
3749 }
3750 } else {
3751 node.Normalize(can_gc);
3752 }
3753 }
3754 }
3755
3756 fn CloneNode(&self, subtree: bool, can_gc: CanGc) -> Fallible<DomRoot<Node>> {
3758 if self.is::<ShadowRoot>() {
3760 return Err(Error::NotSupported(None));
3761 }
3762
3763 let result = Node::clone(
3765 self,
3766 None,
3767 if subtree {
3768 CloneChildrenFlag::CloneChildren
3769 } else {
3770 CloneChildrenFlag::DoNotCloneChildren
3771 },
3772 None,
3773 can_gc,
3774 );
3775 Ok(result)
3776 }
3777
3778 fn IsEqualNode(&self, maybe_node: Option<&Node>) -> bool {
3780 fn is_equal_doctype(node: &Node, other: &Node) -> bool {
3781 let doctype = node.downcast::<DocumentType>().unwrap();
3782 let other_doctype = other.downcast::<DocumentType>().unwrap();
3783 (*doctype.name() == *other_doctype.name()) &&
3784 (*doctype.public_id() == *other_doctype.public_id()) &&
3785 (*doctype.system_id() == *other_doctype.system_id())
3786 }
3787 fn is_equal_element(node: &Node, other: &Node) -> bool {
3788 let element = node.downcast::<Element>().unwrap();
3789 let other_element = other.downcast::<Element>().unwrap();
3790 (*element.namespace() == *other_element.namespace()) &&
3791 (*element.prefix() == *other_element.prefix()) &&
3792 (*element.local_name() == *other_element.local_name()) &&
3793 (element.attrs().len() == other_element.attrs().len())
3794 }
3795 fn is_equal_processinginstruction(node: &Node, other: &Node) -> bool {
3796 let pi = node.downcast::<ProcessingInstruction>().unwrap();
3797 let other_pi = other.downcast::<ProcessingInstruction>().unwrap();
3798 (*pi.target() == *other_pi.target()) &&
3799 (*pi.upcast::<CharacterData>().data() ==
3800 *other_pi.upcast::<CharacterData>().data())
3801 }
3802 fn is_equal_characterdata(node: &Node, other: &Node) -> bool {
3803 let characterdata = node.downcast::<CharacterData>().unwrap();
3804 let other_characterdata = other.downcast::<CharacterData>().unwrap();
3805 *characterdata.data() == *other_characterdata.data()
3806 }
3807 fn is_equal_attr(node: &Node, other: &Node) -> bool {
3808 let attr = node.downcast::<Attr>().unwrap();
3809 let other_attr = other.downcast::<Attr>().unwrap();
3810 (*attr.namespace() == *other_attr.namespace()) &&
3811 (attr.local_name() == other_attr.local_name()) &&
3812 (**attr.value() == **other_attr.value())
3813 }
3814 fn is_equal_element_attrs(node: &Node, other: &Node) -> bool {
3815 let element = node.downcast::<Element>().unwrap();
3816 let other_element = other.downcast::<Element>().unwrap();
3817 assert!(element.attrs().len() == other_element.attrs().len());
3818 element.attrs().iter().all(|attr| {
3819 other_element.attrs().iter().any(|other_attr| {
3820 (*attr.namespace() == *other_attr.namespace()) &&
3821 (attr.local_name() == other_attr.local_name()) &&
3822 (**attr.value() == **other_attr.value())
3823 })
3824 })
3825 }
3826
3827 fn is_equal_node(this: &Node, node: &Node) -> bool {
3828 if this.NodeType() != node.NodeType() {
3830 return false;
3831 }
3832
3833 match node.type_id() {
3834 NodeTypeId::DocumentType if !is_equal_doctype(this, node) => return false,
3836 NodeTypeId::Element(..) if !is_equal_element(this, node) => return false,
3837 NodeTypeId::CharacterData(CharacterDataTypeId::ProcessingInstruction)
3838 if !is_equal_processinginstruction(this, node) =>
3839 {
3840 return false;
3841 },
3842 NodeTypeId::CharacterData(CharacterDataTypeId::Text(_)) |
3843 NodeTypeId::CharacterData(CharacterDataTypeId::Comment)
3844 if !is_equal_characterdata(this, node) =>
3845 {
3846 return false;
3847 },
3848 NodeTypeId::Element(..) if !is_equal_element_attrs(this, node) => return false,
3850 NodeTypeId::Attr if !is_equal_attr(this, node) => return false,
3851
3852 _ => (),
3853 }
3854
3855 if this.children_count() != node.children_count() {
3857 return false;
3858 }
3859
3860 this.children()
3862 .zip(node.children())
3863 .all(|(child, other_child)| is_equal_node(&child, &other_child))
3864 }
3865 match maybe_node {
3866 None => false,
3868 Some(node) => is_equal_node(self, node),
3870 }
3871 }
3872
3873 fn IsSameNode(&self, other_node: Option<&Node>) -> bool {
3875 match other_node {
3876 Some(node) => self == node,
3877 None => false,
3878 }
3879 }
3880
3881 fn CompareDocumentPosition(&self, other: &Node) -> u16 {
3883 if self == other {
3885 return 0;
3886 }
3887
3888 let mut node1 = Some(other);
3890 let mut node2 = Some(self);
3891
3892 let mut attr1: Option<&Attr> = None;
3894 let mut attr2: Option<&Attr> = None;
3895
3896 let attr1owner;
3901 if let Some(a) = other.downcast::<Attr>() {
3902 attr1 = Some(a);
3903 attr1owner = a.GetOwnerElement();
3904 node1 = match attr1owner {
3905 Some(ref e) => Some(e.upcast()),
3906 None => None,
3907 }
3908 }
3909
3910 let attr2owner;
3913 if let Some(a) = self.downcast::<Attr>() {
3914 attr2 = Some(a);
3915 attr2owner = a.GetOwnerElement();
3916 node2 = match attr2owner {
3917 Some(ref e) => Some(e.upcast()),
3918 None => None,
3919 }
3920 }
3921
3922 if let Some(node2) = node2 {
3927 if Some(node2) == node1 {
3928 if let (Some(a1), Some(a2)) = (attr1, attr2) {
3929 let attrs = node2.downcast::<Element>().unwrap().attrs();
3930 for attr in attrs.iter() {
3934 if (*attr.namespace() == *a1.namespace()) &&
3935 (attr.local_name() == a1.local_name()) &&
3936 (**attr.value() == **a1.value())
3937 {
3938 return NodeConstants::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC +
3939 NodeConstants::DOCUMENT_POSITION_PRECEDING;
3940 }
3941 if (*attr.namespace() == *a2.namespace()) &&
3942 (attr.local_name() == a2.local_name()) &&
3943 (**attr.value() == **a2.value())
3944 {
3945 return NodeConstants::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC +
3946 NodeConstants::DOCUMENT_POSITION_FOLLOWING;
3947 }
3948 }
3949 unreachable!();
3952 }
3953 }
3954 }
3955
3956 match (node1, node2) {
3958 (None, _) => {
3959 NodeConstants::DOCUMENT_POSITION_FOLLOWING +
3961 NodeConstants::DOCUMENT_POSITION_DISCONNECTED +
3962 NodeConstants::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC
3963 },
3964 (_, None) => {
3965 NodeConstants::DOCUMENT_POSITION_PRECEDING +
3967 NodeConstants::DOCUMENT_POSITION_DISCONNECTED +
3968 NodeConstants::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC
3969 },
3970 (Some(node1), Some(node2)) => {
3971 let mut self_and_ancestors = node2
3973 .inclusive_ancestors(ShadowIncluding::No)
3974 .collect::<SmallVec<[_; 20]>>();
3975 let mut other_and_ancestors = node1
3976 .inclusive_ancestors(ShadowIncluding::No)
3977 .collect::<SmallVec<[_; 20]>>();
3978
3979 if self_and_ancestors.last() != other_and_ancestors.last() {
3980 let random = as_uintptr(self_and_ancestors.last().unwrap()) <
3981 as_uintptr(other_and_ancestors.last().unwrap());
3982 let random = if random {
3983 NodeConstants::DOCUMENT_POSITION_FOLLOWING
3984 } else {
3985 NodeConstants::DOCUMENT_POSITION_PRECEDING
3986 };
3987
3988 return random +
3990 NodeConstants::DOCUMENT_POSITION_DISCONNECTED +
3991 NodeConstants::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC;
3992 }
3993 let mut parent = self_and_ancestors.pop().unwrap();
3995 other_and_ancestors.pop().unwrap();
3996
3997 let mut current_position =
3998 cmp::min(self_and_ancestors.len(), other_and_ancestors.len());
3999
4000 while current_position > 0 {
4001 current_position -= 1;
4002 let child_1 = self_and_ancestors.pop().unwrap();
4003 let child_2 = other_and_ancestors.pop().unwrap();
4004
4005 if child_1 != child_2 {
4006 let is_before = parent.children().position(|c| c == child_1).unwrap() <
4007 parent.children().position(|c| c == child_2).unwrap();
4008 return if is_before {
4011 NodeConstants::DOCUMENT_POSITION_FOLLOWING
4012 } else {
4013 NodeConstants::DOCUMENT_POSITION_PRECEDING
4014 };
4015 }
4016
4017 parent = child_1;
4018 }
4019
4020 if self_and_ancestors.len() < other_and_ancestors.len() {
4025 NodeConstants::DOCUMENT_POSITION_FOLLOWING +
4026 NodeConstants::DOCUMENT_POSITION_CONTAINED_BY
4027 } else {
4028 NodeConstants::DOCUMENT_POSITION_PRECEDING +
4029 NodeConstants::DOCUMENT_POSITION_CONTAINS
4030 }
4031 },
4032 }
4033 }
4034
4035 fn Contains(&self, maybe_other: Option<&Node>) -> bool {
4037 match maybe_other {
4038 None => false,
4039 Some(other) => self.is_inclusive_ancestor_of(other),
4040 }
4041 }
4042
4043 fn LookupPrefix(&self, namespace: Option<DOMString>) -> Option<DOMString> {
4045 let namespace = namespace_from_domstring(namespace);
4046
4047 if namespace == ns!() {
4049 return None;
4050 }
4051
4052 match self.type_id() {
4054 NodeTypeId::Element(..) => self.downcast::<Element>().unwrap().lookup_prefix(namespace),
4055 NodeTypeId::Document(_) => self
4056 .downcast::<Document>()
4057 .unwrap()
4058 .GetDocumentElement()
4059 .and_then(|element| element.lookup_prefix(namespace)),
4060 NodeTypeId::DocumentType | NodeTypeId::DocumentFragment(_) => None,
4061 NodeTypeId::Attr => self
4062 .downcast::<Attr>()
4063 .unwrap()
4064 .GetOwnerElement()
4065 .and_then(|element| element.lookup_prefix(namespace)),
4066 _ => self
4067 .GetParentElement()
4068 .and_then(|element| element.lookup_prefix(namespace)),
4069 }
4070 }
4071
4072 fn LookupNamespaceURI(&self, prefix: Option<DOMString>) -> Option<DOMString> {
4074 let prefix = prefix.filter(|prefix| !prefix.is_empty());
4076
4077 Node::namespace_to_string(Node::locate_namespace(self, prefix))
4079 }
4080
4081 fn IsDefaultNamespace(&self, namespace: Option<DOMString>) -> bool {
4083 let namespace = namespace_from_domstring(namespace);
4085 Node::locate_namespace(self, None) == namespace
4087 }
4088}
4089
4090pub(crate) trait NodeTraits {
4091 fn owner_document(&self) -> DomRoot<Document>;
4095 fn owner_window(&self) -> DomRoot<Window>;
4099 fn owner_global(&self) -> DomRoot<GlobalScope>;
4103 fn containing_shadow_root(&self) -> Option<DomRoot<ShadowRoot>>;
4105 fn stylesheet_list_owner(&self) -> StyleSheetListOwner;
4108}
4109
4110impl<T: DerivedFrom<Node> + DomObject> NodeTraits for T {
4111 fn owner_document(&self) -> DomRoot<Document> {
4112 self.upcast().owner_doc()
4113 }
4114
4115 fn owner_window(&self) -> DomRoot<Window> {
4116 DomRoot::from_ref(self.owner_document().window())
4117 }
4118
4119 fn owner_global(&self) -> DomRoot<GlobalScope> {
4120 DomRoot::from_ref(self.owner_window().upcast())
4121 }
4122
4123 fn containing_shadow_root(&self) -> Option<DomRoot<ShadowRoot>> {
4124 Node::containing_shadow_root(self.upcast())
4125 }
4126
4127 #[cfg_attr(crown, expect(crown::unrooted_must_root))]
4128 fn stylesheet_list_owner(&self) -> StyleSheetListOwner {
4129 self.containing_shadow_root()
4130 .map(|shadow_root| StyleSheetListOwner::ShadowRoot(Dom::from_ref(&*shadow_root)))
4131 .unwrap_or_else(|| {
4132 StyleSheetListOwner::Document(Dom::from_ref(&*self.owner_document()))
4133 })
4134 }
4135}
4136
4137impl VirtualMethods for Node {
4138 fn super_type(&self) -> Option<&dyn VirtualMethods> {
4139 Some(self.upcast::<EventTarget>() as &dyn VirtualMethods)
4140 }
4141
4142 fn children_changed(&self, mutation: &ChildrenMutation, can_gc: CanGc) {
4143 if let Some(s) = self.super_type() {
4144 s.children_changed(mutation, can_gc);
4145 }
4146
4147 if let Some(data) = self.rare_data().as_ref() {
4148 if let Some(list) = data.child_list.get() {
4149 list.as_children_list().children_changed(mutation);
4150 }
4151 }
4152
4153 self.owner_doc().content_and_heritage_changed(self);
4154 }
4155
4156 fn unbind_from_tree(&self, context: &UnbindContext, can_gc: CanGc) {
4159 self.super_type().unwrap().unbind_from_tree(context, can_gc);
4160
4161 if !self.is_in_a_shadow_tree() && !self.ranges_is_empty() {
4166 self.ranges().drain_to_parent(context, self);
4167 }
4168 }
4169
4170 fn handle_event(&self, event: &Event, _: CanGc) {
4171 if let Some(event) = event.downcast::<KeyboardEvent>() {
4172 self.owner_document()
4173 .event_handler()
4174 .run_default_keyboard_event_handler(event);
4175 }
4176 }
4177}
4178
4179#[derive(Clone, Copy, MallocSizeOf, PartialEq)]
4181pub(crate) enum NodeDamage {
4182 Style,
4184 ContentOrHeritage,
4187 Other,
4189}
4190
4191pub(crate) enum ChildrenMutation<'a> {
4192 Append {
4193 prev: &'a Node,
4194 added: &'a [&'a Node],
4195 },
4196 Insert {
4197 prev: &'a Node,
4198 added: &'a [&'a Node],
4199 next: &'a Node,
4200 },
4201 Prepend {
4202 added: &'a [&'a Node],
4203 next: &'a Node,
4204 },
4205 Replace {
4206 prev: Option<&'a Node>,
4207 removed: &'a Node,
4208 added: &'a [&'a Node],
4209 next: Option<&'a Node>,
4210 },
4211 ReplaceAll {
4212 removed: &'a [&'a Node],
4213 added: &'a [&'a Node],
4214 },
4215 ChangeText,
4220}
4221
4222impl<'a> ChildrenMutation<'a> {
4223 fn insert(
4224 prev: Option<&'a Node>,
4225 added: &'a [&'a Node],
4226 next: Option<&'a Node>,
4227 ) -> ChildrenMutation<'a> {
4228 match (prev, next) {
4229 (None, None) => ChildrenMutation::ReplaceAll {
4230 removed: &[],
4231 added,
4232 },
4233 (Some(prev), None) => ChildrenMutation::Append { prev, added },
4234 (None, Some(next)) => ChildrenMutation::Prepend { added, next },
4235 (Some(prev), Some(next)) => ChildrenMutation::Insert { prev, added, next },
4236 }
4237 }
4238
4239 fn replace(
4240 prev: Option<&'a Node>,
4241 removed: &'a Option<&'a Node>,
4242 added: &'a [&'a Node],
4243 next: Option<&'a Node>,
4244 ) -> ChildrenMutation<'a> {
4245 if let Some(ref removed) = *removed {
4246 if let (None, None) = (prev, next) {
4247 ChildrenMutation::ReplaceAll {
4248 removed: from_ref(removed),
4249 added,
4250 }
4251 } else {
4252 ChildrenMutation::Replace {
4253 prev,
4254 removed,
4255 added,
4256 next,
4257 }
4258 }
4259 } else {
4260 ChildrenMutation::insert(prev, added, next)
4261 }
4262 }
4263
4264 fn replace_all(removed: &'a [&'a Node], added: &'a [&'a Node]) -> ChildrenMutation<'a> {
4265 ChildrenMutation::ReplaceAll { removed, added }
4266 }
4267
4268 pub(crate) fn next_child(&self) -> Option<&Node> {
4273 match *self {
4274 ChildrenMutation::Append { .. } => None,
4275 ChildrenMutation::Insert { next, .. } => Some(next),
4276 ChildrenMutation::Prepend { next, .. } => Some(next),
4277 ChildrenMutation::Replace { next, .. } => next,
4278 ChildrenMutation::ReplaceAll { .. } => None,
4279 ChildrenMutation::ChangeText => None,
4280 }
4281 }
4282
4283 pub(crate) fn modified_edge_element(&self) -> Option<DomRoot<Node>> {
4290 match *self {
4291 ChildrenMutation::Prepend { next, .. } |
4293 ChildrenMutation::Replace {
4294 prev: None,
4295 next: Some(next),
4296 ..
4297 } => next
4298 .inclusively_following_siblings()
4299 .find(|node| node.is::<Element>()),
4300 ChildrenMutation::Append { prev, .. } |
4302 ChildrenMutation::Replace {
4303 prev: Some(prev),
4304 next: None,
4305 ..
4306 } => prev
4307 .inclusively_preceding_siblings()
4308 .find(|node| node.is::<Element>()),
4309 ChildrenMutation::Insert { prev, next, .. } |
4311 ChildrenMutation::Replace {
4312 prev: Some(prev),
4313 next: Some(next),
4314 ..
4315 } => {
4316 if prev
4317 .inclusively_preceding_siblings()
4318 .all(|node| !node.is::<Element>())
4319 {
4320 next.inclusively_following_siblings()
4322 .find(|node| node.is::<Element>())
4323 } else if next
4324 .inclusively_following_siblings()
4325 .all(|node| !node.is::<Element>())
4326 {
4327 prev.inclusively_preceding_siblings()
4329 .find(|node| node.is::<Element>())
4330 } else {
4331 None
4332 }
4333 },
4334
4335 ChildrenMutation::Replace {
4336 prev: None,
4337 next: None,
4338 ..
4339 } => unreachable!(),
4340 ChildrenMutation::ReplaceAll { .. } => None,
4341 ChildrenMutation::ChangeText => None,
4342 }
4343 }
4344}
4345
4346pub(crate) struct BindContext<'a> {
4348 pub(crate) parent: &'a Node,
4350
4351 pub(crate) tree_connected: bool,
4355
4356 pub(crate) tree_is_in_a_document_tree: bool,
4360
4361 pub(crate) tree_is_in_a_shadow_tree: bool,
4363
4364 pub(crate) is_shadow_tree: IsShadowTree,
4369}
4370
4371#[derive(Debug, Eq, PartialEq)]
4372pub(crate) enum IsShadowTree {
4373 Yes,
4374 No,
4375}
4376
4377impl<'a> BindContext<'a> {
4378 pub(crate) fn new(parent: &'a Node, is_shadow_tree: IsShadowTree) -> Self {
4380 BindContext {
4381 parent,
4382 tree_connected: parent.is_connected(),
4383 tree_is_in_a_document_tree: parent.is_in_a_document_tree(),
4384 tree_is_in_a_shadow_tree: parent.is_in_a_shadow_tree(),
4385 is_shadow_tree,
4386 }
4387 }
4388
4389 pub(crate) fn is_in_tree(&self) -> bool {
4391 self.tree_is_in_a_document_tree || self.tree_is_in_a_shadow_tree
4392 }
4393}
4394
4395pub(crate) struct UnbindContext<'a> {
4398 index: Cell<Option<u32>>,
4400 pub(crate) parent: &'a Node,
4402 prev_sibling: Option<&'a Node>,
4404 pub(crate) next_sibling: Option<&'a Node>,
4406
4407 pub(crate) tree_connected: bool,
4411
4412 pub(crate) tree_is_in_a_document_tree: bool,
4416
4417 pub(crate) tree_is_in_a_shadow_tree: bool,
4419}
4420
4421impl<'a> UnbindContext<'a> {
4422 pub(crate) fn new(
4424 parent: &'a Node,
4425 prev_sibling: Option<&'a Node>,
4426 next_sibling: Option<&'a Node>,
4427 cached_index: Option<u32>,
4428 ) -> Self {
4429 UnbindContext {
4430 index: Cell::new(cached_index),
4431 parent,
4432 prev_sibling,
4433 next_sibling,
4434 tree_connected: parent.is_connected(),
4435 tree_is_in_a_document_tree: parent.is_in_a_document_tree(),
4436 tree_is_in_a_shadow_tree: parent.is_in_a_shadow_tree(),
4437 }
4438 }
4439
4440 pub(crate) fn index(&self) -> u32 {
4442 if let Some(index) = self.index.get() {
4443 return index;
4444 }
4445 let index = self.prev_sibling.map_or(0, |sibling| sibling.index() + 1);
4446 self.index.set(Some(index));
4447 index
4448 }
4449}
4450
4451pub(crate) struct UniqueId {
4453 cell: UnsafeCell<Option<Box<Uuid>>>,
4454}
4455
4456unsafe_no_jsmanaged_fields!(UniqueId);
4457
4458impl MallocSizeOf for UniqueId {
4459 #[expect(unsafe_code)]
4460 fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
4461 if let Some(uuid) = unsafe { &*self.cell.get() } {
4462 unsafe { ops.malloc_size_of(&**uuid) }
4463 } else {
4464 0
4465 }
4466 }
4467}
4468
4469impl UniqueId {
4470 fn new() -> UniqueId {
4472 UniqueId {
4473 cell: UnsafeCell::new(None),
4474 }
4475 }
4476
4477 #[expect(unsafe_code)]
4479 fn borrow(&self) -> &Uuid {
4480 unsafe {
4481 let ptr = self.cell.get();
4482 if (*ptr).is_none() {
4483 *ptr = Some(Box::new(Uuid::new_v4()));
4484 }
4485 (*ptr).as_ref().unwrap()
4486 }
4487 }
4488}
4489
4490pub(crate) struct NodeTypeIdWrapper(pub(crate) NodeTypeId);
4491
4492impl From<NodeTypeIdWrapper> for LayoutNodeType {
4493 #[inline(always)]
4494 fn from(node_type: NodeTypeIdWrapper) -> LayoutNodeType {
4495 match node_type.0 {
4496 NodeTypeId::Element(e) => LayoutNodeType::Element(ElementTypeIdWrapper(e).into()),
4497 NodeTypeId::CharacterData(CharacterDataTypeId::Text(_)) => LayoutNodeType::Text,
4498 x => unreachable!("Layout should not traverse nodes of type {:?}", x),
4499 }
4500 }
4501}
4502
4503struct ElementTypeIdWrapper(ElementTypeId);
4504
4505impl From<ElementTypeIdWrapper> for LayoutElementType {
4506 #[inline(always)]
4507 fn from(element_type: ElementTypeIdWrapper) -> LayoutElementType {
4508 match element_type.0 {
4509 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLBodyElement) => {
4510 LayoutElementType::HTMLBodyElement
4511 },
4512 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLBRElement) => {
4513 LayoutElementType::HTMLBRElement
4514 },
4515 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLCanvasElement) => {
4516 LayoutElementType::HTMLCanvasElement
4517 },
4518 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLHtmlElement) => {
4519 LayoutElementType::HTMLHtmlElement
4520 },
4521 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLIFrameElement) => {
4522 LayoutElementType::HTMLIFrameElement
4523 },
4524 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLImageElement) => {
4525 LayoutElementType::HTMLImageElement
4526 },
4527 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLMediaElement(_)) => {
4528 LayoutElementType::HTMLMediaElement
4529 },
4530 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLInputElement) => {
4531 LayoutElementType::HTMLInputElement
4532 },
4533 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLOptGroupElement) => {
4534 LayoutElementType::HTMLOptGroupElement
4535 },
4536 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLOptionElement) => {
4537 LayoutElementType::HTMLOptionElement
4538 },
4539 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLObjectElement) => {
4540 LayoutElementType::HTMLObjectElement
4541 },
4542 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLParagraphElement) => {
4543 LayoutElementType::HTMLParagraphElement
4544 },
4545 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLPreElement) => {
4546 LayoutElementType::HTMLPreElement
4547 },
4548 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLSelectElement) => {
4549 LayoutElementType::HTMLSelectElement
4550 },
4551 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTableCellElement) => {
4552 LayoutElementType::HTMLTableCellElement
4553 },
4554 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTableColElement) => {
4555 LayoutElementType::HTMLTableColElement
4556 },
4557 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTableElement) => {
4558 LayoutElementType::HTMLTableElement
4559 },
4560 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTableRowElement) => {
4561 LayoutElementType::HTMLTableRowElement
4562 },
4563 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTableSectionElement) => {
4564 LayoutElementType::HTMLTableSectionElement
4565 },
4566 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTextAreaElement) => {
4567 LayoutElementType::HTMLTextAreaElement
4568 },
4569 ElementTypeId::SVGElement(SVGElementTypeId::SVGGraphicsElement(
4570 SVGGraphicsElementTypeId::SVGImageElement,
4571 )) => LayoutElementType::SVGImageElement,
4572 ElementTypeId::SVGElement(SVGElementTypeId::SVGGraphicsElement(
4573 SVGGraphicsElementTypeId::SVGSVGElement,
4574 )) => LayoutElementType::SVGSVGElement,
4575 _ => LayoutElementType::Element,
4576 }
4577 }
4578}
4579
4580pub(crate) trait VecPreOrderInsertionHelper<T> {
4583 fn insert_pre_order(&mut self, elem: &T, tree_root: &Node);
4584}
4585
4586impl<T> VecPreOrderInsertionHelper<T> for Vec<Dom<T>>
4587where
4588 T: DerivedFrom<Node> + DomObject,
4589{
4590 fn insert_pre_order(&mut self, elem: &T, tree_root: &Node) {
4600 if self.is_empty() {
4601 self.push(Dom::from_ref(elem));
4602 return;
4603 }
4604
4605 let elem_node = elem.upcast::<Node>();
4606 let mut head: usize = 0;
4607 for node in tree_root.traverse_preorder(ShadowIncluding::No) {
4608 let head_node = DomRoot::upcast::<Node>(DomRoot::from_ref(&*self[head]));
4609 if head_node == node {
4610 head += 1;
4611 }
4612 if elem_node == &*node || head == self.len() {
4613 break;
4614 }
4615 }
4616 self.insert(head, Dom::from_ref(elem));
4617 }
4618}