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