1use std::borrow::Cow;
8use std::cell::{Cell, LazyCell, UnsafeCell};
9use std::default::Default;
10use std::f64::consts::PI;
11use std::slice::from_ref;
12use std::{cmp, fmt, iter};
13
14use app_units::Au;
15use base::id::{BrowsingContextId, PipelineId};
16use bitflags::bitflags;
17use devtools_traits::NodeInfo;
18use dom_struct::dom_struct;
19use embedder_traits::UntrustedNodeAddress;
20use euclid::default::Size2D;
21use euclid::{Point2D, Rect};
22use html5ever::serialize::HtmlSerializer;
23use html5ever::{Namespace, Prefix, QualName, ns, serialize as html_serialize};
24use js::jsapi::JSObject;
25use js::rust::HandleObject;
26use keyboard_types::Modifiers;
27use layout_api::wrapper_traits::SharedSelection;
28use layout_api::{
29 BoxAreaType, CSSPixelRectIterator, GenericLayoutData, HTMLCanvasData, HTMLMediaData,
30 LayoutElementType, LayoutNodeType, PhysicalSides, QueryMsg, SVGElementData, StyleData,
31 TrustedNodeAddress,
32};
33use libc::{self, c_void, uintptr_t};
34use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
35use net_traits::image_cache::Image;
36use pixels::ImageMetadata;
37use script_bindings::codegen::InheritTypes::DocumentFragmentTypeId;
38use script_traits::DocumentActivity;
39use selectors::bloom::BloomFilter;
40use selectors::matching::{
41 MatchingContext, MatchingForInvalidation, MatchingMode, NeedsSelectorFlags,
42 matches_selector_list,
43};
44use selectors::parser::SelectorList;
45use servo_arc::Arc as ServoArc;
46use servo_config::pref;
47use servo_url::ServoUrl;
48use smallvec::SmallVec;
49use style::attr::AttrValue;
50use style::context::QuirksMode;
51use style::dom::OpaqueNode;
52use style::properties::ComputedValues;
53use style::selector_parser::{PseudoElement, SelectorImpl, SelectorParser};
54use style::stylesheets::{Stylesheet, UrlExtraData};
55use style_traits::CSSPixel;
56use uuid::Uuid;
57use xml5ever::{local_name, serialize as xml_serialize};
58
59use super::types::CDATASection;
60use crate::conversions::Convert;
61use crate::document_loader::DocumentLoader;
62use crate::dom::attr::Attr;
63use crate::dom::bindings::cell::{DomRefCell, Ref, RefMut};
64use crate::dom::bindings::codegen::Bindings::AttrBinding::AttrMethods;
65use crate::dom::bindings::codegen::Bindings::CSSStyleDeclarationBinding::CSSStyleDeclarationMethods;
66use crate::dom::bindings::codegen::Bindings::CharacterDataBinding::CharacterDataMethods;
67use crate::dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods;
68use crate::dom::bindings::codegen::Bindings::ElementBinding::ElementMethods;
69use crate::dom::bindings::codegen::Bindings::HTMLCollectionBinding::HTMLCollectionMethods;
70use crate::dom::bindings::codegen::Bindings::HTMLElementBinding::HTMLElementMethods;
71use crate::dom::bindings::codegen::Bindings::NodeBinding::{
72 GetRootNodeOptions, NodeConstants, NodeMethods,
73};
74use crate::dom::bindings::codegen::Bindings::NodeListBinding::NodeListMethods;
75use crate::dom::bindings::codegen::Bindings::ProcessingInstructionBinding::ProcessingInstructionMethods;
76use crate::dom::bindings::codegen::Bindings::ShadowRootBinding::ShadowRoot_Binding::ShadowRootMethods;
77use crate::dom::bindings::codegen::Bindings::ShadowRootBinding::{
78 ShadowRootMode, SlotAssignmentMode,
79};
80use crate::dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
81use crate::dom::bindings::codegen::UnionTypes::NodeOrString;
82use crate::dom::bindings::conversions::{self, DerivedFrom};
83use crate::dom::bindings::domname::namespace_from_domstring;
84use crate::dom::bindings::error::{Error, ErrorResult, Fallible};
85use crate::dom::bindings::inheritance::{
86 Castable, CharacterDataTypeId, ElementTypeId, EventTargetTypeId, HTMLElementTypeId, NodeTypeId,
87 SVGElementTypeId, SVGGraphicsElementTypeId, TextTypeId,
88};
89use crate::dom::bindings::reflector::{DomObject, DomObjectWrap, reflect_dom_object_with_proto};
90use crate::dom::bindings::root::{Dom, DomRoot, DomSlice, LayoutDom, MutNullableDom, ToLayout};
91use crate::dom::bindings::str::{DOMString, USVString};
92use crate::dom::characterdata::{CharacterData, LayoutCharacterDataHelpers};
93use crate::dom::css::cssstylesheet::CSSStyleSheet;
94use crate::dom::css::stylesheetlist::StyleSheetListOwner;
95use crate::dom::customelementregistry::{
96 CallbackReaction, CustomElementRegistry, try_upgrade_element,
97};
98use crate::dom::document::{Document, DocumentSource, HasBrowsingContext, IsHTMLDocument};
99use crate::dom::documentfragment::DocumentFragment;
100use crate::dom::documenttype::DocumentType;
101use crate::dom::element::{
102 AttributeMutationReason, CustomElementCreationMode, Element, ElementCreator, SelectorWrapper,
103};
104use crate::dom::event::{Event, EventBubbles, EventCancelable};
105use crate::dom::eventtarget::EventTarget;
106use crate::dom::globalscope::GlobalScope;
107use crate::dom::html::htmlcanvaselement::{HTMLCanvasElement, LayoutHTMLCanvasElementHelpers};
108use crate::dom::html::htmlcollection::HTMLCollection;
109use crate::dom::html::htmlelement::HTMLElement;
110use crate::dom::html::htmliframeelement::{HTMLIFrameElement, HTMLIFrameElementLayoutMethods};
111use crate::dom::html::htmlimageelement::{HTMLImageElement, LayoutHTMLImageElementHelpers};
112use crate::dom::html::htmlinputelement::{HTMLInputElement, LayoutHTMLInputElementHelpers};
113use crate::dom::html::htmllinkelement::HTMLLinkElement;
114use crate::dom::html::htmlslotelement::{HTMLSlotElement, Slottable};
115use crate::dom::html::htmlstyleelement::HTMLStyleElement;
116use crate::dom::html::htmltextareaelement::{
117 HTMLTextAreaElement, LayoutHTMLTextAreaElementHelpers,
118};
119use crate::dom::html::htmlvideoelement::{HTMLVideoElement, LayoutHTMLVideoElementHelpers};
120use crate::dom::mutationobserver::{Mutation, MutationObserver, RegisteredObserver};
121use crate::dom::nodelist::NodeList;
122use crate::dom::pointerevent::{PointerEvent, PointerId};
123use crate::dom::processinginstruction::ProcessingInstruction;
124use crate::dom::range::WeakRangeVec;
125use crate::dom::raredata::NodeRareData;
126use crate::dom::servoparser::html::HtmlSerialize;
127use crate::dom::servoparser::{ServoParser, serialize_html_fragment};
128use crate::dom::shadowroot::{IsUserAgentWidget, LayoutShadowRootHelpers, ShadowRoot};
129use crate::dom::svg::svgsvgelement::{LayoutSVGSVGElementHelpers, SVGSVGElement};
130use crate::dom::text::Text;
131use crate::dom::types::KeyboardEvent;
132use crate::dom::virtualmethods::{VirtualMethods, vtable_for};
133use crate::dom::window::Window;
134use crate::script_runtime::CanGc;
135use crate::script_thread::ScriptThread;
136
137#[dom_struct]
143pub struct Node {
144 eventtarget: EventTarget,
146
147 parent_node: MutNullableDom<Node>,
149
150 first_child: MutNullableDom<Node>,
152
153 last_child: MutNullableDom<Node>,
155
156 next_sibling: MutNullableDom<Node>,
158
159 prev_sibling: MutNullableDom<Node>,
161
162 owner_doc: MutNullableDom<Document>,
164
165 rare_data: DomRefCell<Option<Box<NodeRareData>>>,
167
168 children_count: Cell<u32>,
170
171 flags: Cell<NodeFlags>,
173
174 inclusive_descendants_version: Cell<u64>,
176
177 #[no_trace]
180 style_data: DomRefCell<Option<Box<StyleData>>>,
181
182 #[no_trace]
185 layout_data: DomRefCell<Option<Box<GenericLayoutData>>>,
186}
187
188impl fmt::Debug for Node {
189 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
190 if matches!(self.type_id(), NodeTypeId::Element(_)) {
191 let el = self.downcast::<Element>().unwrap();
192 el.fmt(f)
193 } else {
194 write!(f, "[Node({:?})]", self.type_id())
195 }
196 }
197}
198
199#[derive(Clone, Copy, JSTraceable, MallocSizeOf)]
201pub(crate) struct NodeFlags(u16);
202
203bitflags! {
204 impl NodeFlags: u16 {
205 const IS_IN_A_DOCUMENT_TREE = 1 << 0;
209
210 const HAS_DIRTY_DESCENDANTS = 1 << 1;
212
213 const CLICK_IN_PROGRESS = 1 << 2;
216
217 const SEQUENTIALLY_FOCUSABLE = 1 << 3;
220
221 const PARSER_ASSOCIATED_FORM_OWNER = 1 << 6;
226
227 const HAS_SNAPSHOT = 1 << 7;
232
233 const HANDLED_SNAPSHOT = 1 << 8;
235
236 const IS_IN_SHADOW_TREE = 1 << 9;
238
239 const IS_CONNECTED = 1 << 10;
243
244 const HAS_WEIRD_PARSER_INSERTION_MODE = 1 << 11;
247
248 const IS_IN_UA_WIDGET = 1 << 12;
251
252 const USES_ATTR_IN_CONTENT_ATTRIBUTE = 1 << 13;
254 }
255}
256
257#[derive(Clone, Copy, MallocSizeOf)]
261enum SuppressObserver {
262 Suppressed,
263 Unsuppressed,
264}
265
266pub(crate) enum ForceSlottableNodeReconciliation {
267 Force,
268 Skip,
269}
270
271impl Node {
272 fn add_child(&self, new_child: &Node, before: Option<&Node>, can_gc: CanGc) {
276 assert!(new_child.parent_node.get().is_none());
277 assert!(new_child.prev_sibling.get().is_none());
278 assert!(new_child.next_sibling.get().is_none());
279 match before {
280 Some(before) => {
281 assert!(before.parent_node.get().as_deref() == Some(self));
282 let prev_sibling = before.GetPreviousSibling();
283 match prev_sibling {
284 None => {
285 assert!(self.first_child.get().as_deref() == Some(before));
286 self.first_child.set(Some(new_child));
287 },
288 Some(ref prev_sibling) => {
289 prev_sibling.next_sibling.set(Some(new_child));
290 new_child.prev_sibling.set(Some(prev_sibling));
291 },
292 }
293 before.prev_sibling.set(Some(new_child));
294 new_child.next_sibling.set(Some(before));
295 },
296 None => {
297 let last_child = self.GetLastChild();
298 match last_child {
299 None => self.first_child.set(Some(new_child)),
300 Some(ref last_child) => {
301 assert!(last_child.next_sibling.get().is_none());
302 last_child.next_sibling.set(Some(new_child));
303 new_child.prev_sibling.set(Some(last_child));
304 },
305 }
306
307 self.last_child.set(Some(new_child));
308 },
309 }
310
311 new_child.parent_node.set(Some(self));
312 self.children_count.set(self.children_count.get() + 1);
313
314 let parent_is_in_a_document_tree = self.is_in_a_document_tree();
315 let parent_in_shadow_tree = self.is_in_a_shadow_tree();
316 let parent_is_connected = self.is_connected();
317 let parent_is_in_ua_widget = self.is_in_ua_widget();
318
319 let context = BindContext::new(self, IsShadowTree::No);
320
321 for node in new_child.traverse_preorder(ShadowIncluding::No) {
322 if parent_in_shadow_tree {
323 if let Some(shadow_root) = self.containing_shadow_root() {
324 node.set_containing_shadow_root(Some(&*shadow_root));
325 }
326 debug_assert!(node.containing_shadow_root().is_some());
327 }
328 node.set_flag(
329 NodeFlags::IS_IN_A_DOCUMENT_TREE,
330 parent_is_in_a_document_tree,
331 );
332 node.set_flag(NodeFlags::IS_IN_SHADOW_TREE, parent_in_shadow_tree);
333 node.set_flag(NodeFlags::IS_CONNECTED, parent_is_connected);
334 node.set_flag(NodeFlags::IS_IN_UA_WIDGET, parent_is_in_ua_widget);
335
336 debug_assert!(!node.get_flag(NodeFlags::HAS_DIRTY_DESCENDANTS));
338 vtable_for(&node).bind_to_tree(&context, can_gc);
339 }
340 }
341
342 pub(crate) fn unsafely_set_html(
345 target: &Node,
346 context_element: &Element,
347 html: DOMString,
348 can_gc: CanGc,
349 ) {
350 let new_children = ServoParser::parse_html_fragment(context_element, html, true, can_gc);
352
353 let context_document = context_element.owner_document();
356 let fragment = DocumentFragment::new(&context_document, can_gc);
357
358 for child in new_children {
360 fragment
361 .upcast::<Node>()
362 .AppendChild(&child, can_gc)
363 .unwrap();
364 }
365
366 Node::replace_all(Some(fragment.upcast()), target, can_gc);
368 }
369
370 pub(crate) fn remove_layout_boxes_from_subtree(&self) {
374 for node in self.traverse_preorder(ShadowIncluding::Yes) {
375 node.layout_data.borrow_mut().take();
376 }
377 }
378
379 pub(crate) fn clean_up_style_and_layout_data(&self) {
380 self.owner_doc().cancel_animations_for_node(self);
381 self.style_data.borrow_mut().take();
382 self.layout_data.borrow_mut().take();
383 }
384
385 pub(crate) fn complete_remove_subtree(root: &Node, context: &UnbindContext, can_gc: CanGc) {
388 const RESET_FLAGS: NodeFlags = NodeFlags::IS_IN_A_DOCUMENT_TREE
390 .union(NodeFlags::IS_CONNECTED)
391 .union(NodeFlags::HAS_DIRTY_DESCENDANTS)
392 .union(NodeFlags::HAS_SNAPSHOT)
393 .union(NodeFlags::HANDLED_SNAPSHOT);
394
395 for node in root.traverse_preorder(ShadowIncluding::No) {
396 node.set_flag(RESET_FLAGS | NodeFlags::IS_IN_SHADOW_TREE, false);
397
398 if let Some(shadow_root) = node.downcast::<Element>().and_then(Element::shadow_root) {
401 for node in shadow_root
402 .upcast::<Node>()
403 .traverse_preorder(ShadowIncluding::Yes)
404 {
405 node.set_flag(RESET_FLAGS, false);
406 }
407 }
408 }
409
410 let is_parent_connected = context.parent.is_connected();
412 let custom_element_reaction_stack = ScriptThread::custom_element_reaction_stack();
413
414 let cleanup_node = |node: &Node| {
417 node.clean_up_style_and_layout_data();
418
419 vtable_for(node).unbind_from_tree(context, can_gc);
424
425 if is_parent_connected {
427 if let Some(element) = node.as_custom_element() {
428 custom_element_reaction_stack.enqueue_callback_reaction(
429 &element,
430 CallbackReaction::Disconnected,
431 None,
432 );
433 }
434 }
435 };
436
437 for node in root.traverse_preorder(ShadowIncluding::No) {
438 cleanup_node(&node);
439
440 if node.containing_shadow_root().is_some() {
443 node.set_containing_shadow_root(None);
446 }
447
448 if let Some(shadow_root) = node.downcast::<Element>().and_then(Element::shadow_root) {
451 for node in shadow_root
452 .upcast::<Node>()
453 .traverse_preorder(ShadowIncluding::Yes)
454 {
455 cleanup_node(&node);
456 }
457 }
458 }
459 }
460
461 fn remove_child(&self, child: &Node, cached_index: Option<u32>, can_gc: CanGc) {
465 assert!(child.parent_node.get().as_deref() == Some(self));
466 self.note_dirty_descendants();
467
468 let prev_sibling = child.GetPreviousSibling();
469 match prev_sibling {
470 None => {
471 self.first_child.set(child.next_sibling.get().as_deref());
472 },
473 Some(ref prev_sibling) => {
474 prev_sibling
475 .next_sibling
476 .set(child.next_sibling.get().as_deref());
477 },
478 }
479 let next_sibling = child.GetNextSibling();
480 match next_sibling {
481 None => {
482 self.last_child.set(child.prev_sibling.get().as_deref());
483 },
484 Some(ref next_sibling) => {
485 next_sibling
486 .prev_sibling
487 .set(child.prev_sibling.get().as_deref());
488 },
489 }
490
491 let context = UnbindContext::new(
492 self,
493 prev_sibling.as_deref(),
494 next_sibling.as_deref(),
495 cached_index,
496 );
497
498 child.prev_sibling.set(None);
499 child.next_sibling.set(None);
500 child.parent_node.set(None);
501 self.children_count.set(self.children_count.get() - 1);
502
503 Self::complete_remove_subtree(child, &context, can_gc);
504 }
505
506 pub(crate) fn to_untrusted_node_address(&self) -> UntrustedNodeAddress {
507 UntrustedNodeAddress(self.reflector().get_jsobject().get() as *const c_void)
508 }
509
510 pub(crate) fn to_opaque(&self) -> OpaqueNode {
511 OpaqueNode(self.reflector().get_jsobject().get() as usize)
512 }
513
514 pub(crate) fn as_custom_element(&self) -> Option<DomRoot<Element>> {
515 self.downcast::<Element>().and_then(|element| {
516 if element.is_custom() {
517 assert!(element.get_custom_element_definition().is_some());
518 Some(DomRoot::from_ref(element))
519 } else {
520 None
521 }
522 })
523 }
524
525 pub(crate) fn fire_synthetic_pointer_event_not_trusted(&self, name: DOMString, can_gc: CanGc) {
527 let window = self.owner_window();
531
532 let pointer_event = PointerEvent::new(
534 &window, name,
536 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,
563 );
564
565 pointer_event.upcast::<Event>().set_composed(true);
567
568 pointer_event.upcast::<Event>().set_trusted(false);
570
571 pointer_event
574 .upcast::<Event>()
575 .dispatch(self.upcast::<EventTarget>(), false, can_gc);
576 }
577
578 pub(crate) fn parent_directionality(&self) -> String {
579 let mut current = self.GetParentNode();
580
581 loop {
582 match current {
583 Some(node) => {
584 if let Some(directionality) = node
585 .downcast::<HTMLElement>()
586 .and_then(|html_element| html_element.directionality())
587 {
588 return directionality;
589 } else {
590 current = node.GetParentNode();
591 }
592 },
593 None => return "ltr".to_owned(),
594 }
595 }
596 }
597}
598
599pub(crate) struct QuerySelectorIterator {
600 selectors: SelectorList<SelectorImpl>,
601 iterator: TreeIterator,
602}
603
604impl QuerySelectorIterator {
605 fn new(iter: TreeIterator, selectors: SelectorList<SelectorImpl>) -> QuerySelectorIterator {
606 QuerySelectorIterator {
607 selectors,
608 iterator: iter,
609 }
610 }
611}
612
613impl Iterator for QuerySelectorIterator {
614 type Item = DomRoot<Node>;
615
616 fn next(&mut self) -> Option<DomRoot<Node>> {
617 let selectors = &self.selectors;
618
619 let (quirks_mode, filter) = match self.iterator.by_ref().peek() {
620 Some(node) => (node.owner_doc().quirks_mode(), BloomFilter::default()),
621 None => return None,
622 };
623
624 self.iterator.by_ref().find_map(|node| {
625 if let Some(element) = DomRoot::downcast(node) {
626 let mut nth_index_cache = Default::default();
627 let mut ctx = MatchingContext::new(
628 MatchingMode::Normal,
629 Some(&filter),
630 &mut nth_index_cache,
631 quirks_mode,
632 NeedsSelectorFlags::No,
633 MatchingForInvalidation::No,
634 );
635 if matches_selector_list(selectors, &SelectorWrapper::Borrowed(&element), &mut ctx)
636 {
637 return Some(DomRoot::upcast(element));
638 }
639 }
640 None
641 })
642 }
643}
644
645impl Node {
646 fn rare_data(&self) -> Ref<'_, Option<Box<NodeRareData>>> {
647 self.rare_data.borrow()
648 }
649
650 fn ensure_rare_data(&self) -> RefMut<'_, Box<NodeRareData>> {
651 let mut rare_data = self.rare_data.borrow_mut();
652 if rare_data.is_none() {
653 *rare_data = Some(Default::default());
654 }
655 RefMut::map(rare_data, |rare_data| rare_data.as_mut().unwrap())
656 }
657
658 pub(crate) fn is_before(&self, other: &Node) -> bool {
661 let cmp = other.CompareDocumentPosition(self);
662 if cmp & NodeConstants::DOCUMENT_POSITION_DISCONNECTED != 0 {
663 return false;
664 }
665
666 cmp & NodeConstants::DOCUMENT_POSITION_PRECEDING != 0
667 }
668
669 pub(crate) fn registered_mutation_observers_mut(&self) -> RefMut<'_, Vec<RegisteredObserver>> {
672 RefMut::map(self.ensure_rare_data(), |rare_data| {
673 &mut rare_data.mutation_observers
674 })
675 }
676
677 pub(crate) fn registered_mutation_observers(&self) -> Option<Ref<'_, Vec<RegisteredObserver>>> {
678 let rare_data: Ref<'_, _> = self.rare_data.borrow();
679
680 if rare_data.is_none() {
681 return None;
682 }
683 Some(Ref::map(rare_data, |rare_data| {
684 &rare_data.as_ref().unwrap().mutation_observers
685 }))
686 }
687
688 #[cfg_attr(crown, expect(crown::unrooted_must_root))]
690 pub(crate) fn add_mutation_observer(&self, observer: RegisteredObserver) {
691 self.ensure_rare_data().mutation_observers.push(observer);
692 }
693
694 pub(crate) fn remove_mutation_observer(&self, observer: &MutationObserver) {
696 self.ensure_rare_data()
697 .mutation_observers
698 .retain(|reg_obs| &*reg_obs.observer != observer)
699 }
700
701 pub(crate) fn dump(&self) {
703 self.dump_indent(0);
704 }
705
706 pub(crate) fn dump_indent(&self, indent: u32) {
708 let mut s = String::new();
709 for _ in 0..indent {
710 s.push_str(" ");
711 }
712
713 s.push_str(&self.debug_str());
714 debug!("{:?}", s);
715
716 for kid in self.children() {
718 kid.dump_indent(indent + 1)
719 }
720 }
721
722 pub(crate) fn debug_str(&self) -> String {
724 format!("{:?}", self.type_id())
725 }
726
727 pub(crate) fn is_in_a_document_tree(&self) -> bool {
729 self.flags.get().contains(NodeFlags::IS_IN_A_DOCUMENT_TREE)
730 }
731
732 pub(crate) fn is_in_a_shadow_tree(&self) -> bool {
734 self.flags.get().contains(NodeFlags::IS_IN_SHADOW_TREE)
735 }
736
737 pub(crate) fn has_weird_parser_insertion_mode(&self) -> bool {
738 self.flags
739 .get()
740 .contains(NodeFlags::HAS_WEIRD_PARSER_INSERTION_MODE)
741 }
742
743 pub(crate) fn set_weird_parser_insertion_mode(&self) {
744 self.set_flag(NodeFlags::HAS_WEIRD_PARSER_INSERTION_MODE, true)
745 }
746
747 pub(crate) fn is_connected(&self) -> bool {
749 self.flags.get().contains(NodeFlags::IS_CONNECTED)
750 }
751
752 pub(crate) fn set_in_ua_widget(&self, in_ua_widget: bool) {
753 self.set_flag(NodeFlags::IS_IN_UA_WIDGET, in_ua_widget)
754 }
755
756 pub(crate) fn is_in_ua_widget(&self) -> bool {
757 self.flags.get().contains(NodeFlags::IS_IN_UA_WIDGET)
758 }
759
760 pub(crate) fn type_id(&self) -> NodeTypeId {
762 match *self.eventtarget.type_id() {
763 EventTargetTypeId::Node(type_id) => type_id,
764 _ => unreachable!(),
765 }
766 }
767
768 pub(crate) fn len(&self) -> u32 {
770 match self.type_id() {
771 NodeTypeId::DocumentType => 0,
772 NodeTypeId::CharacterData(_) => self.downcast::<CharacterData>().unwrap().Length(),
773 _ => self.children_count(),
774 }
775 }
776
777 pub(crate) fn is_empty(&self) -> bool {
778 self.len() == 0
780 }
781
782 pub(crate) fn index(&self) -> u32 {
784 self.preceding_siblings().count() as u32
785 }
786
787 pub(crate) fn has_parent(&self) -> bool {
789 self.parent_node.get().is_some()
790 }
791
792 pub(crate) fn children_count(&self) -> u32 {
793 self.children_count.get()
794 }
795
796 pub(crate) fn ranges(&self) -> RefMut<'_, WeakRangeVec> {
797 RefMut::map(self.ensure_rare_data(), |rare_data| &mut rare_data.ranges)
798 }
799
800 pub(crate) fn ranges_is_empty(&self) -> bool {
801 self.rare_data()
802 .as_ref()
803 .is_none_or(|data| data.ranges.is_empty())
804 }
805
806 #[inline]
807 pub(crate) fn is_doctype(&self) -> bool {
808 self.type_id() == NodeTypeId::DocumentType
809 }
810
811 pub(crate) fn get_flag(&self, flag: NodeFlags) -> bool {
812 self.flags.get().contains(flag)
813 }
814
815 pub(crate) fn set_flag(&self, flag: NodeFlags, value: bool) {
816 let mut flags = self.flags.get();
817
818 if value {
819 flags.insert(flag);
820 } else {
821 flags.remove(flag);
822 }
823
824 self.flags.set(flags);
825 }
826
827 pub(crate) fn note_dirty_descendants(&self) {
829 self.owner_doc().note_node_with_dirty_descendants(self);
830 }
831
832 pub(crate) fn has_dirty_descendants(&self) -> bool {
833 self.get_flag(NodeFlags::HAS_DIRTY_DESCENDANTS)
834 }
835
836 pub(crate) fn rev_version(&self) {
837 let doc: DomRoot<Node> = DomRoot::upcast(self.owner_doc());
842 let version = cmp::max(
843 self.inclusive_descendants_version(),
844 doc.inclusive_descendants_version(),
845 ) + 1;
846
847 let mut node = &MutNullableDom::new(Some(self));
850 while let Some(p) = node.if_is_some(|p| {
851 p.inclusive_descendants_version.set(version);
852 &p.parent_node
853 }) {
854 node = p
855 }
856 doc.inclusive_descendants_version.set(version);
857 }
858
859 pub(crate) fn dirty(&self, damage: NodeDamage) {
860 self.rev_version();
861 if !self.is_connected() {
862 return;
863 }
864
865 match self.type_id() {
866 NodeTypeId::CharacterData(CharacterDataTypeId::Text(TextTypeId::Text)) => {
867 self.parent_node
871 .get()
872 .unwrap()
873 .dirty(NodeDamage::ContentOrHeritage)
874 },
875 NodeTypeId::Element(_) => self.downcast::<Element>().unwrap().restyle(damage),
876 NodeTypeId::DocumentFragment(DocumentFragmentTypeId::ShadowRoot) => self
877 .downcast::<ShadowRoot>()
878 .unwrap()
879 .Host()
880 .upcast::<Element>()
881 .restyle(damage),
882 _ => {},
883 };
884 }
885
886 pub(crate) fn inclusive_descendants_version(&self) -> u64 {
888 self.inclusive_descendants_version.get()
889 }
890
891 pub(crate) fn traverse_preorder(&self, shadow_including: ShadowIncluding) -> TreeIterator {
893 TreeIterator::new(self, shadow_including)
894 }
895
896 pub(crate) fn inclusively_following_siblings(
897 &self,
898 ) -> impl Iterator<Item = DomRoot<Node>> + use<> {
899 SimpleNodeIterator {
900 current: Some(DomRoot::from_ref(self)),
901 next_node: |n| n.GetNextSibling(),
902 }
903 }
904
905 pub(crate) fn inclusively_preceding_siblings(
906 &self,
907 ) -> impl Iterator<Item = DomRoot<Node>> + use<> {
908 SimpleNodeIterator {
909 current: Some(DomRoot::from_ref(self)),
910 next_node: |n| n.GetPreviousSibling(),
911 }
912 }
913
914 pub(crate) fn common_ancestor(
915 &self,
916 other: &Node,
917 shadow_including: ShadowIncluding,
918 ) -> Option<DomRoot<Node>> {
919 self.inclusive_ancestors(shadow_including).find(|ancestor| {
920 other
921 .inclusive_ancestors(shadow_including)
922 .any(|node| node == *ancestor)
923 })
924 }
925
926 pub(crate) fn common_ancestor_in_flat_tree(&self, other: &Node) -> Option<DomRoot<Node>> {
927 self.inclusive_ancestors_in_flat_tree().find(|ancestor| {
928 other
929 .inclusive_ancestors_in_flat_tree()
930 .any(|node| node == *ancestor)
931 })
932 }
933
934 pub(crate) fn is_inclusive_ancestor_of(&self, child: &Node) -> bool {
936 self == child || self.is_ancestor_of(child)
938 }
939
940 pub(crate) fn is_ancestor_of(&self, possible_descendant: &Node) -> bool {
942 let mut current = &possible_descendant.parent_node;
944 let mut done = false;
945
946 while let Some(node) = current.if_is_some(|node| {
947 done = node == self;
948 &node.parent_node
949 }) {
950 if done {
951 break;
952 }
953 current = node
954 }
955 done
956 }
957
958 fn is_host_including_inclusive_ancestor(&self, child: &Node) -> bool {
960 self.is_inclusive_ancestor_of(child) ||
963 child
964 .GetRootNode(&GetRootNodeOptions::empty())
965 .downcast::<DocumentFragment>()
966 .and_then(|fragment| fragment.host())
967 .is_some_and(|host| self.is_host_including_inclusive_ancestor(host.upcast()))
968 }
969
970 pub(crate) fn is_shadow_including_inclusive_ancestor_of(&self, node: &Node) -> bool {
972 node.inclusive_ancestors(ShadowIncluding::Yes)
973 .any(|ancestor| &*ancestor == self)
974 }
975
976 pub(crate) fn following_siblings(&self) -> impl Iterator<Item = DomRoot<Node>> + use<> {
977 SimpleNodeIterator {
978 current: self.GetNextSibling(),
979 next_node: |n| n.GetNextSibling(),
980 }
981 }
982
983 pub(crate) fn preceding_siblings(&self) -> impl Iterator<Item = DomRoot<Node>> + use<> {
984 SimpleNodeIterator {
985 current: self.GetPreviousSibling(),
986 next_node: |n| n.GetPreviousSibling(),
987 }
988 }
989
990 pub(crate) fn following_nodes(&self, root: &Node) -> FollowingNodeIterator {
991 FollowingNodeIterator {
992 current: Some(DomRoot::from_ref(self)),
993 root: DomRoot::from_ref(root),
994 }
995 }
996
997 pub(crate) fn preceding_nodes(&self, root: &Node) -> PrecedingNodeIterator {
998 PrecedingNodeIterator {
999 current: Some(DomRoot::from_ref(self)),
1000 root: DomRoot::from_ref(root),
1001 }
1002 }
1003
1004 pub(crate) fn descending_last_children(&self) -> impl Iterator<Item = DomRoot<Node>> + use<> {
1007 SimpleNodeIterator {
1008 current: self.GetLastChild(),
1009 next_node: |n| n.GetLastChild(),
1010 }
1011 }
1012
1013 pub(crate) fn is_parent_of(&self, child: &Node) -> bool {
1014 child
1015 .parent_node
1016 .get()
1017 .is_some_and(|parent| &*parent == self)
1018 }
1019
1020 pub(crate) fn to_trusted_node_address(&self) -> TrustedNodeAddress {
1021 TrustedNodeAddress(self as *const Node as *const libc::c_void)
1022 }
1023
1024 pub(crate) fn padding(&self) -> Option<PhysicalSides> {
1025 self.owner_window().padding_query_without_reflow(self)
1026 }
1027
1028 pub(crate) fn content_box(&self) -> Option<Rect<Au, CSSPixel>> {
1029 self.owner_window()
1030 .box_area_query(self, BoxAreaType::Content, false)
1031 }
1032
1033 pub(crate) fn border_box(&self) -> Option<Rect<Au, CSSPixel>> {
1034 self.owner_window()
1035 .box_area_query(self, BoxAreaType::Border, false)
1036 }
1037
1038 pub(crate) fn padding_box(&self) -> Option<Rect<Au, CSSPixel>> {
1039 self.owner_window()
1040 .box_area_query(self, BoxAreaType::Padding, false)
1041 }
1042
1043 pub(crate) fn border_boxes(&self) -> CSSPixelRectIterator {
1044 self.owner_window()
1045 .box_areas_query(self, BoxAreaType::Border)
1046 }
1047
1048 pub(crate) fn client_rect(&self) -> Rect<i32, CSSPixel> {
1049 self.owner_window().client_rect_query(self)
1050 }
1051
1052 pub(crate) fn scroll_area(&self) -> Rect<i32, CSSPixel> {
1055 let document = self.owner_doc();
1057
1058 if !document.is_active() {
1060 return Rect::zero();
1061 }
1062
1063 let window = document.window();
1066 let viewport = Size2D::new(window.InnerWidth(), window.InnerHeight()).cast_unit();
1067
1068 let in_quirks_mode = document.quirks_mode() == QuirksMode::Quirks;
1069 let is_root = self.downcast::<Element>().is_some_and(|e| e.is_root());
1070 let is_body_element = self
1071 .downcast::<HTMLElement>()
1072 .is_some_and(|e| e.is_body_element());
1073
1074 if (is_root && !in_quirks_mode) || (is_body_element && in_quirks_mode) {
1080 let viewport_scrolling_area = window.scrolling_area_query(None);
1081 return Rect::new(
1082 viewport_scrolling_area.origin,
1083 viewport_scrolling_area.size.max(viewport),
1084 );
1085 }
1086
1087 window.scrolling_area_query(Some(self))
1091 }
1092
1093 pub(crate) fn before(&self, nodes: Vec<NodeOrString>, can_gc: CanGc) -> ErrorResult {
1095 let parent = &self.parent_node;
1097
1098 let parent = match parent.get() {
1100 None => return Ok(()),
1101 Some(parent) => parent,
1102 };
1103
1104 let viable_previous_sibling = first_node_not_in(self.preceding_siblings(), &nodes);
1106
1107 let node = self
1109 .owner_doc()
1110 .node_from_nodes_and_strings(nodes, can_gc)?;
1111
1112 let viable_previous_sibling = match viable_previous_sibling {
1114 Some(ref viable_previous_sibling) => viable_previous_sibling.next_sibling.get(),
1115 None => parent.first_child.get(),
1116 };
1117
1118 Node::pre_insert(&node, &parent, viable_previous_sibling.as_deref(), can_gc)?;
1120
1121 Ok(())
1122 }
1123
1124 pub(crate) fn after(&self, nodes: Vec<NodeOrString>, can_gc: CanGc) -> ErrorResult {
1126 let parent = &self.parent_node;
1128
1129 let parent = match parent.get() {
1131 None => return Ok(()),
1132 Some(parent) => parent,
1133 };
1134
1135 let viable_next_sibling = first_node_not_in(self.following_siblings(), &nodes);
1137
1138 let node = self
1140 .owner_doc()
1141 .node_from_nodes_and_strings(nodes, can_gc)?;
1142
1143 Node::pre_insert(&node, &parent, viable_next_sibling.as_deref(), can_gc)?;
1145
1146 Ok(())
1147 }
1148
1149 pub(crate) fn replace_with(&self, nodes: Vec<NodeOrString>, can_gc: CanGc) -> ErrorResult {
1151 let Some(parent) = self.GetParentNode() else {
1153 return Ok(());
1155 };
1156
1157 let viable_next_sibling = first_node_not_in(self.following_siblings(), &nodes);
1159
1160 let node = self
1162 .owner_doc()
1163 .node_from_nodes_and_strings(nodes, can_gc)?;
1164
1165 if self.parent_node == Some(&*parent) {
1166 parent.ReplaceChild(&node, self, can_gc)?;
1168 } else {
1169 Node::pre_insert(&node, &parent, viable_next_sibling.as_deref(), can_gc)?;
1171 }
1172 Ok(())
1173 }
1174
1175 pub(crate) fn prepend(&self, nodes: Vec<NodeOrString>, can_gc: CanGc) -> ErrorResult {
1177 let doc = self.owner_doc();
1179 let node = doc.node_from_nodes_and_strings(nodes, can_gc)?;
1180 let first_child = self.first_child.get();
1182 Node::pre_insert(&node, self, first_child.as_deref(), can_gc).map(|_| ())
1183 }
1184
1185 pub(crate) fn append(&self, nodes: Vec<NodeOrString>, can_gc: CanGc) -> ErrorResult {
1187 let doc = self.owner_doc();
1189 let node = doc.node_from_nodes_and_strings(nodes, can_gc)?;
1190 self.AppendChild(&node, can_gc).map(|_| ())
1192 }
1193
1194 pub(crate) fn replace_children(&self, nodes: Vec<NodeOrString>, can_gc: CanGc) -> ErrorResult {
1196 let doc = self.owner_doc();
1199 let node = doc.node_from_nodes_and_strings(nodes, can_gc)?;
1200
1201 Node::ensure_pre_insertion_validity(&node, self, None)?;
1203
1204 Node::replace_all(Some(&node), self, can_gc);
1206 Ok(())
1207 }
1208
1209 pub(crate) fn query_selector(
1211 &self,
1212 selectors: DOMString,
1213 ) -> Fallible<Option<DomRoot<Element>>> {
1214 let doc = self.owner_doc();
1216 match SelectorParser::parse_author_origin_no_namespace(
1217 &selectors.str(),
1218 &UrlExtraData(doc.url().get_arc()),
1219 ) {
1220 Err(_) => Err(Error::Syntax(None)),
1222 Ok(selectors) => {
1224 let mut nth_index_cache = Default::default();
1225 let filter = BloomFilter::default();
1226 let mut ctx = MatchingContext::new(
1227 MatchingMode::Normal,
1228 Some(&filter),
1229 &mut nth_index_cache,
1230 doc.quirks_mode(),
1231 NeedsSelectorFlags::No,
1232 MatchingForInvalidation::No,
1233 );
1234 let mut descendants = self.traverse_preorder(ShadowIncluding::No);
1235 assert!(&*descendants.next().unwrap() == self);
1237 Ok(descendants.filter_map(DomRoot::downcast).find(|element| {
1238 matches_selector_list(&selectors, &SelectorWrapper::Borrowed(element), &mut ctx)
1239 }))
1240 },
1241 }
1242 }
1243
1244 pub(crate) fn query_selector_iter(
1249 &self,
1250 selectors: DOMString,
1251 ) -> Fallible<QuerySelectorIterator> {
1252 let url = self.owner_doc().url();
1254 match SelectorParser::parse_author_origin_no_namespace(
1255 &selectors.str(),
1256 &UrlExtraData(url.get_arc()),
1257 ) {
1258 Err(_) => Err(Error::Syntax(None)),
1260 Ok(selectors) => {
1262 let mut descendants = self.traverse_preorder(ShadowIncluding::No);
1263 assert!(&*descendants.next().unwrap() == self);
1265 Ok(QuerySelectorIterator::new(descendants, selectors))
1266 },
1267 }
1268 }
1269
1270 pub(crate) fn query_selector_all(&self, selectors: DOMString) -> Fallible<DomRoot<NodeList>> {
1272 let window = self.owner_window();
1273 let iter = self.query_selector_iter(selectors)?;
1274 Ok(NodeList::new_simple_list(&window, iter, CanGc::note()))
1275 }
1276
1277 pub(crate) fn ancestors(&self) -> impl Iterator<Item = DomRoot<Node>> + use<> {
1278 SimpleNodeIterator {
1279 current: self.GetParentNode(),
1280 next_node: |n| n.GetParentNode(),
1281 }
1282 }
1283
1284 pub(crate) fn inclusive_ancestors(
1286 &self,
1287 shadow_including: ShadowIncluding,
1288 ) -> impl Iterator<Item = DomRoot<Node>> + use<> {
1289 SimpleNodeIterator {
1290 current: Some(DomRoot::from_ref(self)),
1291 next_node: move |n| {
1292 if shadow_including == ShadowIncluding::Yes {
1293 if let Some(shadow_root) = n.downcast::<ShadowRoot>() {
1294 return Some(DomRoot::from_ref(shadow_root.Host().upcast::<Node>()));
1295 }
1296 }
1297 n.GetParentNode()
1298 },
1299 }
1300 }
1301
1302 pub(crate) fn owner_doc(&self) -> DomRoot<Document> {
1303 self.owner_doc.get().unwrap()
1304 }
1305
1306 pub(crate) fn set_owner_doc(&self, document: &Document) {
1307 self.owner_doc.set(Some(document));
1308 }
1309
1310 pub(crate) fn containing_shadow_root(&self) -> Option<DomRoot<ShadowRoot>> {
1311 self.rare_data()
1312 .as_ref()?
1313 .containing_shadow_root
1314 .as_ref()
1315 .map(|sr| DomRoot::from_ref(&**sr))
1316 }
1317
1318 pub(crate) fn set_containing_shadow_root(&self, shadow_root: Option<&ShadowRoot>) {
1319 self.ensure_rare_data().containing_shadow_root = shadow_root.map(Dom::from_ref);
1320 }
1321
1322 pub(crate) fn is_in_html_doc(&self) -> bool {
1323 self.owner_doc().is_html_document()
1324 }
1325
1326 pub(crate) fn is_connected_with_browsing_context(&self) -> bool {
1327 self.is_connected() && self.owner_doc().browsing_context().is_some()
1328 }
1329
1330 pub(crate) fn children(&self) -> impl Iterator<Item = DomRoot<Node>> + use<> {
1331 SimpleNodeIterator {
1332 current: self.GetFirstChild(),
1333 next_node: |n| n.GetNextSibling(),
1334 }
1335 }
1336
1337 pub(crate) fn rev_children(&self) -> impl Iterator<Item = DomRoot<Node>> + use<> {
1338 SimpleNodeIterator {
1339 current: self.GetLastChild(),
1340 next_node: |n| n.GetPreviousSibling(),
1341 }
1342 }
1343
1344 pub(crate) fn child_elements(&self) -> impl Iterator<Item = DomRoot<Element>> + use<> {
1345 self.children()
1346 .filter_map(DomRoot::downcast as fn(_) -> _)
1347 .peekable()
1348 }
1349
1350 pub(crate) fn remove_self(&self, can_gc: CanGc) {
1351 if let Some(ref parent) = self.GetParentNode() {
1352 Node::remove(self, parent, SuppressObserver::Unsuppressed, can_gc);
1353 }
1354 }
1355
1356 pub(crate) fn unique_id(&self, pipeline: PipelineId) -> String {
1357 let mut rare_data = self.ensure_rare_data();
1358
1359 if rare_data.unique_id.is_none() {
1360 let node_id = UniqueId::new();
1361 ScriptThread::save_node_id(pipeline, node_id.borrow().simple().to_string());
1362 rare_data.unique_id = Some(node_id);
1363 }
1364 rare_data
1365 .unique_id
1366 .as_ref()
1367 .unwrap()
1368 .borrow()
1369 .simple()
1370 .to_string()
1371 }
1372
1373 pub(crate) fn summarize(&self, can_gc: CanGc) -> NodeInfo {
1374 let USVString(base_uri) = self.BaseURI();
1375 let node_type = self.NodeType();
1376 let pipeline = self.owner_window().pipeline_id();
1377
1378 let maybe_shadow_root = self.downcast::<ShadowRoot>();
1379 let shadow_root_mode = maybe_shadow_root
1380 .map(ShadowRoot::Mode)
1381 .map(ShadowRootMode::convert);
1382 let host = maybe_shadow_root
1383 .map(ShadowRoot::Host)
1384 .map(|host| host.upcast::<Node>().unique_id(pipeline));
1385 let is_shadow_host = self.downcast::<Element>().is_some_and(|potential_host| {
1386 let Some(root) = potential_host.shadow_root() else {
1387 return false;
1388 };
1389 !root.is_user_agent_widget() || pref!(inspector_show_servo_internal_shadow_roots)
1390 });
1391
1392 let num_children = if is_shadow_host {
1393 self.ChildNodes(can_gc).Length() as usize + 1
1395 } else {
1396 self.ChildNodes(can_gc).Length() as usize
1397 };
1398
1399 let window = self.owner_window();
1400 let display = self
1401 .downcast::<Element>()
1402 .map(|elem| window.GetComputedStyle(elem, None))
1403 .map(|style| style.Display().into());
1404
1405 NodeInfo {
1406 unique_id: self.unique_id(pipeline),
1407 host,
1408 base_uri,
1409 parent: self
1410 .GetParentNode()
1411 .map_or("".to_owned(), |node| node.unique_id(pipeline)),
1412 node_type,
1413 is_top_level_document: node_type == NodeConstants::DOCUMENT_NODE,
1414 node_name: String::from(self.NodeName()),
1415 node_value: self.GetNodeValue().map(|v| v.into()),
1416 num_children,
1417 attrs: self.downcast().map(Element::summarize).unwrap_or(vec![]),
1418 is_shadow_host,
1419 shadow_root_mode,
1420 display,
1421 is_displayed: !self.is_display_none() || self.is::<DocumentType>(),
1425 doctype_name: self
1426 .downcast::<DocumentType>()
1427 .map(DocumentType::name)
1428 .cloned()
1429 .map(String::from),
1430 doctype_public_identifier: self
1431 .downcast::<DocumentType>()
1432 .map(DocumentType::public_id)
1433 .cloned()
1434 .map(String::from),
1435 doctype_system_identifier: self
1436 .downcast::<DocumentType>()
1437 .map(DocumentType::system_id)
1438 .cloned()
1439 .map(String::from),
1440 has_event_listeners: self.upcast::<EventTarget>().has_handlers(),
1441 }
1442 }
1443
1444 pub(crate) fn insert_cell_or_row<F, G, I>(
1446 &self,
1447 index: i32,
1448 get_items: F,
1449 new_child: G,
1450 can_gc: CanGc,
1451 ) -> Fallible<DomRoot<HTMLElement>>
1452 where
1453 F: Fn() -> DomRoot<HTMLCollection>,
1454 G: Fn() -> DomRoot<I>,
1455 I: DerivedFrom<Node> + DerivedFrom<HTMLElement> + DomObject,
1456 {
1457 if index < -1 {
1458 return Err(Error::IndexSize(None));
1459 }
1460
1461 let tr = new_child();
1462
1463 {
1464 let tr_node = tr.upcast::<Node>();
1465 if index == -1 {
1466 self.InsertBefore(tr_node, None, can_gc)?;
1467 } else {
1468 let items = get_items();
1469 let node = match items
1470 .elements_iter()
1471 .map(DomRoot::upcast::<Node>)
1472 .map(Some)
1473 .chain(iter::once(None))
1474 .nth(index as usize)
1475 {
1476 None => return Err(Error::IndexSize(None)),
1477 Some(node) => node,
1478 };
1479 self.InsertBefore(tr_node, node.as_deref(), can_gc)?;
1480 }
1481 }
1482
1483 Ok(DomRoot::upcast::<HTMLElement>(tr))
1484 }
1485
1486 pub(crate) fn delete_cell_or_row<F, G>(
1488 &self,
1489 index: i32,
1490 get_items: F,
1491 is_delete_type: G,
1492 can_gc: CanGc,
1493 ) -> ErrorResult
1494 where
1495 F: Fn() -> DomRoot<HTMLCollection>,
1496 G: Fn(&Element) -> bool,
1497 {
1498 let element = match index {
1499 index if index < -1 => return Err(Error::IndexSize(None)),
1500 -1 => {
1501 let last_child = self.upcast::<Node>().GetLastChild();
1502 match last_child.and_then(|node| {
1503 node.inclusively_preceding_siblings()
1504 .filter_map(DomRoot::downcast::<Element>)
1505 .find(|elem| is_delete_type(elem))
1506 }) {
1507 Some(element) => element,
1508 None => return Ok(()),
1509 }
1510 },
1511 index => match get_items().Item(index as u32) {
1512 Some(element) => element,
1513 None => return Err(Error::IndexSize(None)),
1514 },
1515 };
1516
1517 element.upcast::<Node>().remove_self(can_gc);
1518 Ok(())
1519 }
1520
1521 pub(crate) fn get_stylesheet(&self) -> Option<ServoArc<Stylesheet>> {
1522 if let Some(node) = self.downcast::<HTMLStyleElement>() {
1523 node.get_stylesheet()
1524 } else if let Some(node) = self.downcast::<HTMLLinkElement>() {
1525 node.get_stylesheet()
1526 } else {
1527 None
1528 }
1529 }
1530
1531 pub(crate) fn get_cssom_stylesheet(&self) -> Option<DomRoot<CSSStyleSheet>> {
1532 if let Some(node) = self.downcast::<HTMLStyleElement>() {
1533 node.get_cssom_stylesheet()
1534 } else if let Some(node) = self.downcast::<HTMLLinkElement>() {
1535 node.get_cssom_stylesheet(CanGc::note())
1536 } else {
1537 None
1538 }
1539 }
1540
1541 pub(crate) fn is_styled(&self) -> bool {
1542 self.style_data.borrow().is_some()
1543 }
1544
1545 pub(crate) fn is_display_none(&self) -> bool {
1546 self.style_data.borrow().as_ref().is_none_or(|data| {
1547 data.element_data
1548 .borrow()
1549 .styles
1550 .primary()
1551 .get_box()
1552 .display
1553 .is_none()
1554 })
1555 }
1556
1557 pub(crate) fn style(&self) -> Option<ServoArc<ComputedValues>> {
1558 self.owner_window().layout_reflow(QueryMsg::StyleQuery);
1559 self.style_data
1560 .borrow()
1561 .as_ref()
1562 .map(|data| data.element_data.borrow().styles.primary().clone())
1563 }
1564
1565 pub(crate) fn get_lang(&self) -> Option<String> {
1567 self.inclusive_ancestors(ShadowIncluding::Yes)
1568 .find_map(|node| {
1569 node.downcast::<Element>().and_then(|el| {
1570 el.get_attribute(&ns!(xml), &local_name!("lang"))
1571 .or_else(|| el.get_attribute(&ns!(), &local_name!("lang")))
1572 .map(|attr| String::from(attr.Value()))
1573 })
1574 })
1577 }
1578
1579 pub(crate) fn assign_slottables_for_a_tree(&self, force: ForceSlottableNodeReconciliation) {
1581 let is_shadow_root_with_slots = self
1588 .downcast::<ShadowRoot>()
1589 .is_some_and(|shadow_root| shadow_root.has_slot_descendants());
1590 if !is_shadow_root_with_slots &&
1591 !self.is::<HTMLSlotElement>() &&
1592 matches!(force, ForceSlottableNodeReconciliation::Skip)
1593 {
1594 return;
1595 }
1596
1597 for node in self.traverse_preorder(ShadowIncluding::No) {
1600 if let Some(slot) = node.downcast::<HTMLSlotElement>() {
1601 slot.assign_slottables();
1602 }
1603 }
1604 }
1605
1606 pub(crate) fn assigned_slot(&self) -> Option<DomRoot<HTMLSlotElement>> {
1607 let assigned_slot = self
1608 .rare_data
1609 .borrow()
1610 .as_ref()?
1611 .slottable_data
1612 .assigned_slot
1613 .as_ref()?
1614 .as_rooted();
1615 Some(assigned_slot)
1616 }
1617
1618 pub(crate) fn set_assigned_slot(&self, assigned_slot: Option<&HTMLSlotElement>) {
1619 self.ensure_rare_data().slottable_data.assigned_slot = assigned_slot.map(Dom::from_ref);
1620 }
1621
1622 pub(crate) fn manual_slot_assignment(&self) -> Option<DomRoot<HTMLSlotElement>> {
1623 let manually_assigned_slot = self
1624 .rare_data
1625 .borrow()
1626 .as_ref()?
1627 .slottable_data
1628 .manual_slot_assignment
1629 .as_ref()?
1630 .as_rooted();
1631 Some(manually_assigned_slot)
1632 }
1633
1634 pub(crate) fn set_manual_slot_assignment(
1635 &self,
1636 manually_assigned_slot: Option<&HTMLSlotElement>,
1637 ) {
1638 self.ensure_rare_data()
1639 .slottable_data
1640 .manual_slot_assignment = manually_assigned_slot.map(Dom::from_ref);
1641 }
1642
1643 pub(crate) fn parent_in_flat_tree(&self) -> Option<DomRoot<Node>> {
1649 if let Some(assigned_slot) = self.assigned_slot() {
1650 return Some(DomRoot::upcast(assigned_slot));
1651 }
1652
1653 let parent_or_none = self.GetParentNode();
1654 if let Some(parent) = parent_or_none.as_deref() {
1655 if let Some(shadow_root) = parent.downcast::<ShadowRoot>() {
1656 return Some(DomRoot::from_ref(shadow_root.Host().upcast::<Node>()));
1657 }
1658 }
1659
1660 parent_or_none
1661 }
1662
1663 pub(crate) fn inclusive_ancestors_in_flat_tree(
1664 &self,
1665 ) -> impl Iterator<Item = DomRoot<Node>> + use<> {
1666 SimpleNodeIterator {
1667 current: Some(DomRoot::from_ref(self)),
1668 next_node: move |n| n.parent_in_flat_tree(),
1669 }
1670 }
1671
1672 pub(crate) fn set_implemented_pseudo_element(&self, pseudo_element: PseudoElement) {
1674 debug_assert!(self.is_in_ua_widget());
1676 self.ensure_rare_data().implemented_pseudo_element = Some(pseudo_element);
1677 }
1678
1679 pub(crate) fn implemented_pseudo_element(&self) -> Option<PseudoElement> {
1680 self.rare_data
1681 .borrow()
1682 .as_ref()
1683 .and_then(|rare_data| rare_data.implemented_pseudo_element)
1684 }
1685
1686 pub(crate) fn editing_host_of(&self) -> Option<DomRoot<Node>> {
1688 for ancestor in self.inclusive_ancestors(ShadowIncluding::No) {
1692 if ancestor.is_editing_host() {
1693 return Some(ancestor);
1694 }
1695 if ancestor
1696 .downcast::<HTMLElement>()
1697 .is_some_and(|el| el.ContentEditable().str() == "false")
1698 {
1699 return None;
1700 }
1701 }
1702 None
1703 }
1704
1705 pub(crate) fn is_editable_or_editing_host(&self) -> bool {
1706 self.editing_host_of().is_some()
1707 }
1708
1709 pub(crate) fn is_editing_host(&self) -> bool {
1711 self.downcast::<HTMLElement>()
1712 .is_some_and(HTMLElement::is_editing_host)
1713 }
1714
1715 pub(crate) fn is_editable(&self) -> bool {
1717 if self.is_editing_host() {
1719 return false;
1720 }
1721 let html_element = self.downcast::<HTMLElement>();
1723 if html_element.is_some_and(|el| el.ContentEditable().str() == "false") {
1724 return false;
1725 }
1726 let Some(parent) = self.GetParentNode() else {
1728 return false;
1729 };
1730 if !parent.is_editable_or_editing_host() {
1731 return false;
1732 }
1733 html_element.is_some() || parent.downcast::<HTMLElement>().is_some()
1735 }
1736}
1737
1738fn first_node_not_in<I>(mut nodes: I, not_in: &[NodeOrString]) -> Option<DomRoot<Node>>
1740where
1741 I: Iterator<Item = DomRoot<Node>>,
1742{
1743 nodes.find(|node| {
1744 not_in.iter().all(|n| match *n {
1745 NodeOrString::Node(ref n) => n != node,
1746 _ => true,
1747 })
1748 })
1749}
1750
1751#[expect(unsafe_code)]
1754pub(crate) unsafe fn from_untrusted_node_address(candidate: UntrustedNodeAddress) -> DomRoot<Node> {
1755 let node = unsafe { Node::from_untrusted_node_address(candidate) };
1756 DomRoot::from_ref(node)
1757}
1758
1759#[expect(unsafe_code)]
1760pub(crate) trait LayoutNodeHelpers<'dom> {
1761 fn type_id_for_layout(self) -> NodeTypeId;
1762
1763 fn parent_node_ref(self) -> Option<LayoutDom<'dom, Node>>;
1764 fn composed_parent_node_ref(self) -> Option<LayoutDom<'dom, Node>>;
1765 fn first_child_ref(self) -> Option<LayoutDom<'dom, Node>>;
1766 fn last_child_ref(self) -> Option<LayoutDom<'dom, Node>>;
1767 fn prev_sibling_ref(self) -> Option<LayoutDom<'dom, Node>>;
1768 fn next_sibling_ref(self) -> Option<LayoutDom<'dom, Node>>;
1769
1770 fn owner_doc_for_layout(self) -> LayoutDom<'dom, Document>;
1771 fn containing_shadow_root_for_layout(self) -> Option<LayoutDom<'dom, ShadowRoot>>;
1772 fn assigned_slot_for_layout(self) -> Option<LayoutDom<'dom, HTMLSlotElement>>;
1773
1774 fn is_element_for_layout(&self) -> bool;
1775 fn is_text_node_for_layout(&self) -> bool;
1776 unsafe fn get_flag(self, flag: NodeFlags) -> bool;
1777 unsafe fn set_flag(self, flag: NodeFlags, value: bool);
1778
1779 fn style_data(self) -> Option<&'dom StyleData>;
1780 fn layout_data(self) -> Option<&'dom GenericLayoutData>;
1781
1782 unsafe fn initialize_style_data(self);
1790
1791 unsafe fn initialize_layout_data(self, data: Box<GenericLayoutData>);
1799
1800 unsafe fn clear_style_and_layout_data(self);
1808
1809 fn is_single_line_text_inner_editor(&self) -> bool;
1812
1813 fn is_text_container_of_single_line_input(&self) -> bool;
1816 fn text_content(self) -> Cow<'dom, str>;
1817 fn selection(self) -> Option<SharedSelection>;
1818 fn image_url(self) -> Option<ServoUrl>;
1819 fn image_density(self) -> Option<f64>;
1820 fn image_data(self) -> Option<(Option<Image>, Option<ImageMetadata>)>;
1821 fn showing_broken_image_icon(self) -> bool;
1822 fn canvas_data(self) -> Option<HTMLCanvasData>;
1823 fn media_data(self) -> Option<HTMLMediaData>;
1824 fn svg_data(self) -> Option<SVGElementData<'dom>>;
1825 fn iframe_browsing_context_id(self) -> Option<BrowsingContextId>;
1826 fn iframe_pipeline_id(self) -> Option<PipelineId>;
1827 fn opaque(self) -> OpaqueNode;
1828 fn implemented_pseudo_element(&self) -> Option<PseudoElement>;
1829 fn is_in_ua_widget(&self) -> bool;
1830}
1831
1832impl<'dom> LayoutDom<'dom, Node> {
1833 #[inline]
1834 #[expect(unsafe_code)]
1835 pub(crate) fn parent_node_ref(self) -> Option<LayoutDom<'dom, Node>> {
1836 unsafe { self.unsafe_get().parent_node.get_inner_as_layout() }
1837 }
1838}
1839
1840impl<'dom> LayoutNodeHelpers<'dom> for LayoutDom<'dom, Node> {
1841 #[inline]
1842 fn type_id_for_layout(self) -> NodeTypeId {
1843 self.unsafe_get().type_id()
1844 }
1845
1846 #[inline]
1847 fn is_element_for_layout(&self) -> bool {
1848 (*self).is::<Element>()
1849 }
1850
1851 fn is_text_node_for_layout(&self) -> bool {
1852 self.type_id_for_layout() ==
1853 NodeTypeId::CharacterData(CharacterDataTypeId::Text(TextTypeId::Text))
1854 }
1855
1856 #[inline]
1857 #[expect(unsafe_code)]
1858 fn parent_node_ref(self) -> Option<LayoutDom<'dom, Node>> {
1859 unsafe { self.unsafe_get().parent_node.get_inner_as_layout() }
1860 }
1861
1862 #[inline]
1863 fn composed_parent_node_ref(self) -> Option<LayoutDom<'dom, Node>> {
1864 let parent = self.parent_node_ref();
1865 if let Some(parent) = parent {
1866 if let Some(shadow_root) = parent.downcast::<ShadowRoot>() {
1867 return Some(shadow_root.get_host_for_layout().upcast());
1868 }
1869 }
1870 parent
1871 }
1872
1873 #[inline]
1874 #[expect(unsafe_code)]
1875 fn first_child_ref(self) -> Option<LayoutDom<'dom, Node>> {
1876 unsafe { self.unsafe_get().first_child.get_inner_as_layout() }
1877 }
1878
1879 #[inline]
1880 #[expect(unsafe_code)]
1881 fn last_child_ref(self) -> Option<LayoutDom<'dom, Node>> {
1882 unsafe { self.unsafe_get().last_child.get_inner_as_layout() }
1883 }
1884
1885 #[inline]
1886 #[expect(unsafe_code)]
1887 fn prev_sibling_ref(self) -> Option<LayoutDom<'dom, Node>> {
1888 unsafe { self.unsafe_get().prev_sibling.get_inner_as_layout() }
1889 }
1890
1891 #[inline]
1892 #[expect(unsafe_code)]
1893 fn next_sibling_ref(self) -> Option<LayoutDom<'dom, Node>> {
1894 unsafe { self.unsafe_get().next_sibling.get_inner_as_layout() }
1895 }
1896
1897 #[inline]
1898 #[expect(unsafe_code)]
1899 fn owner_doc_for_layout(self) -> LayoutDom<'dom, Document> {
1900 unsafe { self.unsafe_get().owner_doc.get_inner_as_layout().unwrap() }
1901 }
1902
1903 #[inline]
1904 #[expect(unsafe_code)]
1905 fn containing_shadow_root_for_layout(self) -> Option<LayoutDom<'dom, ShadowRoot>> {
1906 unsafe {
1907 self.unsafe_get()
1908 .rare_data
1909 .borrow_for_layout()
1910 .as_ref()?
1911 .containing_shadow_root
1912 .as_ref()
1913 .map(|sr| sr.to_layout())
1914 }
1915 }
1916
1917 #[inline]
1918 #[expect(unsafe_code)]
1919 fn assigned_slot_for_layout(self) -> Option<LayoutDom<'dom, HTMLSlotElement>> {
1920 unsafe {
1921 self.unsafe_get()
1922 .rare_data
1923 .borrow_for_layout()
1924 .as_ref()?
1925 .slottable_data
1926 .assigned_slot
1927 .as_ref()
1928 .map(|assigned_slot| assigned_slot.to_layout())
1929 }
1930 }
1931
1932 #[inline]
1937 #[expect(unsafe_code)]
1938 unsafe fn get_flag(self, flag: NodeFlags) -> bool {
1939 (self.unsafe_get()).flags.get().contains(flag)
1940 }
1941
1942 #[inline]
1943 #[expect(unsafe_code)]
1944 unsafe fn set_flag(self, flag: NodeFlags, value: bool) {
1945 let this = self.unsafe_get();
1946 let mut flags = (this).flags.get();
1947
1948 if value {
1949 flags.insert(flag);
1950 } else {
1951 flags.remove(flag);
1952 }
1953
1954 (this).flags.set(flags);
1955 }
1956
1957 #[inline]
1960 #[expect(unsafe_code)]
1961 fn style_data(self) -> Option<&'dom StyleData> {
1962 unsafe { self.unsafe_get().style_data.borrow_for_layout().as_deref() }
1963 }
1964
1965 #[inline]
1966 #[expect(unsafe_code)]
1967 fn layout_data(self) -> Option<&'dom GenericLayoutData> {
1968 unsafe { self.unsafe_get().layout_data.borrow_for_layout().as_deref() }
1969 }
1970
1971 #[inline]
1972 #[expect(unsafe_code)]
1973 unsafe fn initialize_style_data(self) {
1974 let data = unsafe { self.unsafe_get().style_data.borrow_mut_for_layout() };
1975 debug_assert!(data.is_none());
1976 *data = Some(Box::default());
1977 }
1978
1979 #[inline]
1980 #[expect(unsafe_code)]
1981 unsafe fn initialize_layout_data(self, new_data: Box<GenericLayoutData>) {
1982 let data = unsafe { self.unsafe_get().layout_data.borrow_mut_for_layout() };
1983 debug_assert!(data.is_none());
1984 *data = Some(new_data);
1985 }
1986
1987 #[inline]
1988 #[expect(unsafe_code)]
1989 unsafe fn clear_style_and_layout_data(self) {
1990 unsafe {
1991 self.unsafe_get().style_data.borrow_mut_for_layout().take();
1992 self.unsafe_get().layout_data.borrow_mut_for_layout().take();
1993 }
1994 }
1995
1996 fn is_single_line_text_inner_editor(&self) -> bool {
1997 matches!(
1998 self.unsafe_get().implemented_pseudo_element(),
1999 Some(PseudoElement::ServoTextControlInnerEditor)
2000 )
2001 }
2002
2003 fn is_text_container_of_single_line_input(&self) -> bool {
2004 let is_single_line_text_inner_placeholder = matches!(
2005 self.unsafe_get().implemented_pseudo_element(),
2006 Some(PseudoElement::Placeholder)
2007 );
2008 debug_assert!(
2010 !is_single_line_text_inner_placeholder ||
2011 self.containing_shadow_root_for_layout()
2012 .map(|root| root.get_host_for_layout())
2013 .map(|host| host.downcast::<HTMLInputElement>())
2014 .is_some()
2015 );
2016
2017 self.is_single_line_text_inner_editor() || is_single_line_text_inner_placeholder
2018 }
2019
2020 fn text_content(self) -> Cow<'dom, str> {
2021 self.downcast::<Text>()
2022 .expect("Called LayoutDom::text_content on non-Text node!")
2023 .upcast()
2024 .data_for_layout()
2025 .into()
2026 }
2027
2028 fn selection(self) -> Option<SharedSelection> {
2035 if let Some(input) = self.downcast::<HTMLInputElement>() {
2036 return input.selection_for_layout();
2037 }
2038 if let Some(textarea) = self.downcast::<HTMLTextAreaElement>() {
2039 return Some(textarea.selection_for_layout());
2040 }
2041
2042 let shadow_root = self
2043 .containing_shadow_root_for_layout()?
2044 .get_host_for_layout();
2045 if let Some(input) = shadow_root.downcast::<HTMLInputElement>() {
2046 return input.selection_for_layout();
2047 }
2048 shadow_root
2049 .downcast::<HTMLTextAreaElement>()
2050 .map(|textarea| textarea.selection_for_layout())
2051 }
2052
2053 fn image_url(self) -> Option<ServoUrl> {
2054 self.downcast::<HTMLImageElement>()
2055 .expect("not an image!")
2056 .image_url()
2057 }
2058
2059 fn image_data(self) -> Option<(Option<Image>, Option<ImageMetadata>)> {
2060 self.downcast::<HTMLImageElement>().map(|e| e.image_data())
2061 }
2062
2063 fn image_density(self) -> Option<f64> {
2064 self.downcast::<HTMLImageElement>()
2065 .expect("not an image!")
2066 .image_density()
2067 }
2068
2069 fn showing_broken_image_icon(self) -> bool {
2070 self.downcast::<HTMLImageElement>()
2071 .map(|image_element| image_element.showing_broken_image_icon())
2072 .unwrap_or_default()
2073 }
2074
2075 fn canvas_data(self) -> Option<HTMLCanvasData> {
2076 self.downcast::<HTMLCanvasElement>()
2077 .map(|canvas| canvas.data())
2078 }
2079
2080 fn media_data(self) -> Option<HTMLMediaData> {
2081 self.downcast::<HTMLVideoElement>()
2082 .map(|media| media.data())
2083 }
2084
2085 fn svg_data(self) -> Option<SVGElementData<'dom>> {
2086 self.downcast::<SVGSVGElement>().map(|svg| svg.data())
2087 }
2088
2089 fn iframe_browsing_context_id(self) -> Option<BrowsingContextId> {
2090 self.downcast::<HTMLIFrameElement>()
2091 .and_then(|iframe_element| iframe_element.browsing_context_id())
2092 }
2093
2094 fn iframe_pipeline_id(self) -> Option<PipelineId> {
2095 self.downcast::<HTMLIFrameElement>()
2096 .and_then(|iframe_element| iframe_element.pipeline_id())
2097 }
2098
2099 #[expect(unsafe_code)]
2100 fn opaque(self) -> OpaqueNode {
2101 unsafe { OpaqueNode(self.get_jsobject() as usize) }
2102 }
2103
2104 fn implemented_pseudo_element(&self) -> Option<PseudoElement> {
2105 self.unsafe_get().implemented_pseudo_element()
2106 }
2107
2108 fn is_in_ua_widget(&self) -> bool {
2109 self.unsafe_get().is_in_ua_widget()
2110 }
2111}
2112
2113pub(crate) struct FollowingNodeIterator {
2118 current: Option<DomRoot<Node>>,
2119 root: DomRoot<Node>,
2120}
2121
2122impl FollowingNodeIterator {
2123 pub(crate) fn next_skipping_children(&mut self) -> Option<DomRoot<Node>> {
2125 let current = self.current.take()?;
2126 self.next_skipping_children_impl(current)
2127 }
2128
2129 fn next_skipping_children_impl(&mut self, current: DomRoot<Node>) -> Option<DomRoot<Node>> {
2130 if self.root == current {
2131 self.current = None;
2132 return None;
2133 }
2134
2135 if let Some(next_sibling) = current.GetNextSibling() {
2136 self.current = Some(next_sibling);
2137 return current.GetNextSibling();
2138 }
2139
2140 for ancestor in current.inclusive_ancestors(ShadowIncluding::No) {
2141 if self.root == ancestor {
2142 break;
2143 }
2144 if let Some(next_sibling) = ancestor.GetNextSibling() {
2145 self.current = Some(next_sibling);
2146 return ancestor.GetNextSibling();
2147 }
2148 }
2149 self.current = None;
2150 None
2151 }
2152}
2153
2154impl Iterator for FollowingNodeIterator {
2155 type Item = DomRoot<Node>;
2156
2157 fn next(&mut self) -> Option<DomRoot<Node>> {
2159 let current = self.current.take()?;
2160
2161 if let Some(first_child) = current.GetFirstChild() {
2162 self.current = Some(first_child);
2163 return current.GetFirstChild();
2164 }
2165
2166 self.next_skipping_children_impl(current)
2167 }
2168}
2169
2170pub(crate) struct PrecedingNodeIterator {
2171 current: Option<DomRoot<Node>>,
2172 root: DomRoot<Node>,
2173}
2174
2175impl Iterator for PrecedingNodeIterator {
2176 type Item = DomRoot<Node>;
2177
2178 fn next(&mut self) -> Option<DomRoot<Node>> {
2180 let current = self.current.take()?;
2181
2182 self.current = if self.root == current {
2183 None
2184 } else if let Some(previous_sibling) = current.GetPreviousSibling() {
2185 if self.root == previous_sibling {
2186 None
2187 } else if let Some(last_child) = previous_sibling.descending_last_children().last() {
2188 Some(last_child)
2189 } else {
2190 Some(previous_sibling)
2191 }
2192 } else {
2193 current.GetParentNode()
2194 };
2195 self.current.clone()
2196 }
2197}
2198
2199struct SimpleNodeIterator<I>
2200where
2201 I: Fn(&Node) -> Option<DomRoot<Node>>,
2202{
2203 current: Option<DomRoot<Node>>,
2204 next_node: I,
2205}
2206
2207impl<I> Iterator for SimpleNodeIterator<I>
2208where
2209 I: Fn(&Node) -> Option<DomRoot<Node>>,
2210{
2211 type Item = DomRoot<Node>;
2212
2213 fn next(&mut self) -> Option<Self::Item> {
2214 let current = self.current.take();
2215 self.current = current.as_ref().and_then(|c| (self.next_node)(c));
2216 current
2217 }
2218}
2219
2220#[derive(Clone, Copy, PartialEq)]
2222pub(crate) enum ShadowIncluding {
2223 No,
2224 Yes,
2225}
2226
2227pub(crate) struct TreeIterator {
2228 current: Option<DomRoot<Node>>,
2229 depth: usize,
2230 shadow_including: bool,
2231}
2232
2233impl TreeIterator {
2234 fn new(root: &Node, shadow_including: ShadowIncluding) -> TreeIterator {
2235 TreeIterator {
2236 current: Some(DomRoot::from_ref(root)),
2237 depth: 0,
2238 shadow_including: shadow_including == ShadowIncluding::Yes,
2239 }
2240 }
2241
2242 pub(crate) fn next_skipping_children(&mut self) -> Option<DomRoot<Node>> {
2243 let current = self.current.take()?;
2244
2245 self.next_skipping_children_impl(current)
2246 }
2247
2248 fn next_skipping_children_impl(&mut self, current: DomRoot<Node>) -> Option<DomRoot<Node>> {
2249 let iter = current.inclusive_ancestors(if self.shadow_including {
2250 ShadowIncluding::Yes
2251 } else {
2252 ShadowIncluding::No
2253 });
2254
2255 for ancestor in iter {
2256 if self.depth == 0 {
2257 break;
2258 }
2259 if let Some(next_sibling) = ancestor.GetNextSibling() {
2260 self.current = Some(next_sibling);
2261 return Some(current);
2262 }
2263 if let Some(shadow_root) = ancestor.downcast::<ShadowRoot>() {
2264 if let Some(child) = shadow_root.Host().upcast::<Node>().GetFirstChild() {
2267 self.current = Some(child);
2268 return Some(current);
2269 }
2270 }
2271 self.depth -= 1;
2272 }
2273 debug_assert_eq!(self.depth, 0);
2274 self.current = None;
2275 Some(current)
2276 }
2277
2278 pub(crate) fn peek(&self) -> Option<&DomRoot<Node>> {
2279 self.current.as_ref()
2280 }
2281}
2282
2283impl Iterator for TreeIterator {
2284 type Item = DomRoot<Node>;
2285
2286 fn next(&mut self) -> Option<DomRoot<Node>> {
2289 let current = self.current.take()?;
2290
2291 if let Some(element) = current.downcast::<Element>() {
2293 if let Some(shadow_root) = element.shadow_root() {
2294 if self.shadow_including {
2295 self.current = Some(DomRoot::from_ref(shadow_root.upcast::<Node>()));
2296 self.depth += 1;
2297 return Some(current);
2298 }
2299 }
2300 }
2301
2302 if let Some(first_child) = current.GetFirstChild() {
2303 self.current = Some(first_child);
2304 self.depth += 1;
2305 return Some(current);
2306 };
2307
2308 self.next_skipping_children_impl(current)
2309 }
2310}
2311
2312#[derive(Clone, Copy, MallocSizeOf, PartialEq)]
2314pub(crate) enum CloneChildrenFlag {
2315 CloneChildren,
2316 DoNotCloneChildren,
2317}
2318
2319impl From<bool> for CloneChildrenFlag {
2320 fn from(boolean: bool) -> Self {
2321 if boolean {
2322 CloneChildrenFlag::CloneChildren
2323 } else {
2324 CloneChildrenFlag::DoNotCloneChildren
2325 }
2326 }
2327}
2328
2329fn as_uintptr<T>(t: &T) -> uintptr_t {
2330 t as *const T as uintptr_t
2331}
2332
2333impl Node {
2334 pub(crate) fn reflect_node<N>(node: Box<N>, document: &Document, can_gc: CanGc) -> DomRoot<N>
2335 where
2336 N: DerivedFrom<Node> + DomObject + DomObjectWrap<crate::DomTypeHolder>,
2337 {
2338 Self::reflect_node_with_proto(node, document, None, can_gc)
2339 }
2340
2341 pub(crate) fn reflect_node_with_proto<N>(
2342 node: Box<N>,
2343 document: &Document,
2344 proto: Option<HandleObject>,
2345 can_gc: CanGc,
2346 ) -> DomRoot<N>
2347 where
2348 N: DerivedFrom<Node> + DomObject + DomObjectWrap<crate::DomTypeHolder>,
2349 {
2350 let window = document.window();
2351 reflect_dom_object_with_proto(node, window, proto, can_gc)
2352 }
2353
2354 pub(crate) fn new_inherited(doc: &Document) -> Node {
2355 Node::new_(NodeFlags::empty(), Some(doc))
2356 }
2357
2358 pub(crate) fn new_document_node() -> Node {
2359 Node::new_(
2360 NodeFlags::IS_IN_A_DOCUMENT_TREE | NodeFlags::IS_CONNECTED,
2361 None,
2362 )
2363 }
2364
2365 fn new_(flags: NodeFlags, doc: Option<&Document>) -> Node {
2366 Node {
2367 eventtarget: EventTarget::new_inherited(),
2368
2369 parent_node: Default::default(),
2370 first_child: Default::default(),
2371 last_child: Default::default(),
2372 next_sibling: Default::default(),
2373 prev_sibling: Default::default(),
2374 owner_doc: MutNullableDom::new(doc),
2375 rare_data: Default::default(),
2376 children_count: Cell::new(0u32),
2377 flags: Cell::new(flags),
2378 inclusive_descendants_version: Cell::new(0),
2379 style_data: Default::default(),
2380 layout_data: Default::default(),
2381 }
2382 }
2383
2384 pub(crate) fn adopt(node: &Node, document: &Document, can_gc: CanGc) {
2386 document.add_script_and_layout_blocker();
2387
2388 let old_doc = node.owner_doc();
2390 old_doc.add_script_and_layout_blocker();
2391
2392 node.remove_self(can_gc);
2394
2395 if &*old_doc != document {
2397 for descendant in node.traverse_preorder(ShadowIncluding::Yes) {
2399 descendant.set_owner_doc(document);
2401
2402 if let Some(element) = descendant.downcast::<Element>() {
2405 for attribute in element.attrs().iter() {
2406 attribute.upcast::<Node>().set_owner_doc(document);
2407 }
2408 }
2409 }
2410
2411 let custom_element_reaction_stack = ScriptThread::custom_element_reaction_stack();
2415 for descendant in node
2416 .traverse_preorder(ShadowIncluding::Yes)
2417 .filter_map(|d| d.as_custom_element())
2418 {
2419 custom_element_reaction_stack.enqueue_callback_reaction(
2420 &descendant,
2421 CallbackReaction::Adopted(old_doc.clone(), DomRoot::from_ref(document)),
2422 None,
2423 );
2424 }
2425
2426 for descendant in node.traverse_preorder(ShadowIncluding::Yes) {
2429 vtable_for(&descendant).adopting_steps(&old_doc, can_gc);
2430 }
2431 }
2432
2433 old_doc.remove_script_and_layout_blocker();
2434 document.remove_script_and_layout_blocker();
2435 }
2436
2437 pub(crate) fn ensure_pre_insertion_validity(
2439 node: &Node,
2440 parent: &Node,
2441 child: Option<&Node>,
2442 ) -> ErrorResult {
2443 match parent.type_id() {
2445 NodeTypeId::Document(_) | NodeTypeId::DocumentFragment(_) | NodeTypeId::Element(..) => {
2446 },
2447 _ => return Err(Error::HierarchyRequest(None)),
2448 }
2449
2450 if node.is_host_including_inclusive_ancestor(parent) {
2452 return Err(Error::HierarchyRequest(None));
2453 }
2454
2455 if let Some(child) = child {
2457 if !parent.is_parent_of(child) {
2458 return Err(Error::NotFound(None));
2459 }
2460 }
2461
2462 match node.type_id() {
2464 NodeTypeId::CharacterData(CharacterDataTypeId::Text(_)) => {
2467 if parent.is::<Document>() {
2468 return Err(Error::HierarchyRequest(None));
2469 }
2470 },
2471 NodeTypeId::DocumentType => {
2472 if !parent.is::<Document>() {
2473 return Err(Error::HierarchyRequest(None));
2474 }
2475 },
2476 NodeTypeId::DocumentFragment(_) |
2477 NodeTypeId::Element(_) |
2478 NodeTypeId::CharacterData(CharacterDataTypeId::ProcessingInstruction) |
2479 NodeTypeId::CharacterData(CharacterDataTypeId::Comment) => (),
2480 NodeTypeId::Document(_) | NodeTypeId::Attr => {
2481 return Err(Error::HierarchyRequest(None));
2482 },
2483 }
2484
2485 if parent.is::<Document>() {
2488 match node.type_id() {
2489 NodeTypeId::DocumentFragment(_) => {
2490 if node.children().any(|c| c.is::<Text>()) {
2492 return Err(Error::HierarchyRequest(None));
2493 }
2494 match node.child_elements().count() {
2495 0 => (),
2496 1 => {
2499 if parent.child_elements().next().is_some() {
2500 return Err(Error::HierarchyRequest(None));
2501 }
2502 if let Some(child) = child {
2503 if child
2504 .inclusively_following_siblings()
2505 .any(|child| child.is_doctype())
2506 {
2507 return Err(Error::HierarchyRequest(None));
2508 }
2509 }
2510 },
2511 _ => return Err(Error::HierarchyRequest(None)),
2512 }
2513 },
2514 NodeTypeId::Element(_) => {
2515 if parent.child_elements().next().is_some() {
2517 return Err(Error::HierarchyRequest(None));
2518 }
2519 if let Some(child) = child {
2520 if child
2521 .inclusively_following_siblings()
2522 .any(|child| child.is_doctype())
2523 {
2524 return Err(Error::HierarchyRequest(None));
2525 }
2526 }
2527 },
2528 NodeTypeId::DocumentType => {
2529 if parent.children().any(|c| c.is_doctype()) {
2532 return Err(Error::HierarchyRequest(None));
2533 }
2534 match child {
2535 Some(child) => {
2536 if parent
2537 .children()
2538 .take_while(|c| &**c != child)
2539 .any(|c| c.is::<Element>())
2540 {
2541 return Err(Error::HierarchyRequest(None));
2542 }
2543 },
2544 None => {
2545 if parent.child_elements().next().is_some() {
2546 return Err(Error::HierarchyRequest(None));
2547 }
2548 },
2549 }
2550 },
2551 NodeTypeId::CharacterData(_) => (),
2552 NodeTypeId::Document(_) | NodeTypeId::Attr => unreachable!(),
2555 }
2556 }
2557 Ok(())
2558 }
2559
2560 pub(crate) fn pre_insert(
2562 node: &Node,
2563 parent: &Node,
2564 child: Option<&Node>,
2565 can_gc: CanGc,
2566 ) -> Fallible<DomRoot<Node>> {
2567 Node::ensure_pre_insertion_validity(node, parent, child)?;
2569
2570 let reference_child_root;
2572 let reference_child = match child {
2573 Some(child) if child == node => {
2575 reference_child_root = node.GetNextSibling();
2576 reference_child_root.as_deref()
2577 },
2578 _ => child,
2579 };
2580
2581 Node::insert(
2583 node,
2584 parent,
2585 reference_child,
2586 SuppressObserver::Unsuppressed,
2587 can_gc,
2588 );
2589
2590 Ok(DomRoot::from_ref(node))
2592 }
2593
2594 fn insert(
2596 node: &Node,
2597 parent: &Node,
2598 child: Option<&Node>,
2599 suppress_observers: SuppressObserver,
2600 can_gc: CanGc,
2601 ) {
2602 debug_assert!(child.is_none_or(|child| Some(parent) == child.GetParentNode().as_deref()));
2603
2604 rooted_vec!(let mut new_nodes);
2606 let new_nodes = if let NodeTypeId::DocumentFragment(_) = node.type_id() {
2607 new_nodes.extend(node.children().map(|node| Dom::from_ref(&*node)));
2608 new_nodes.r()
2609 } else {
2610 from_ref(&node)
2611 };
2612
2613 let count = new_nodes.len();
2615
2616 if count == 0 {
2618 return;
2619 }
2620
2621 let parent_document = parent.owner_doc();
2624 let from_document = node.owner_doc();
2625 from_document.add_script_and_layout_blocker();
2626 parent_document.add_script_and_layout_blocker();
2627
2628 if let NodeTypeId::DocumentFragment(_) = node.type_id() {
2630 for kid in new_nodes {
2632 Node::remove(kid, node, SuppressObserver::Suppressed, can_gc);
2633 }
2634 vtable_for(node)
2635 .children_changed(&ChildrenMutation::replace_all(new_nodes, &[]), can_gc);
2636
2637 let mutation = LazyCell::new(|| Mutation::ChildList {
2639 added: None,
2640 removed: Some(new_nodes),
2641 prev: None,
2642 next: None,
2643 });
2644 MutationObserver::queue_a_mutation_record(node, mutation);
2645 }
2646
2647 if let Some(child) = child {
2653 if !parent.ranges_is_empty() {
2654 parent
2655 .ranges()
2656 .increase_above(parent, child.index(), count.try_into().unwrap());
2657 }
2658 }
2659
2660 let previous_sibling = match suppress_observers {
2662 SuppressObserver::Unsuppressed => match child {
2663 Some(child) => child.GetPreviousSibling(),
2664 None => parent.GetLastChild(),
2665 },
2666 SuppressObserver::Suppressed => None,
2667 };
2668
2669 let custom_element_reaction_stack = ScriptThread::custom_element_reaction_stack();
2670
2671 let mut static_node_list: SmallVec<[_; 4]> = Default::default();
2673
2674 let parent_shadow_root = parent.downcast::<Element>().and_then(Element::shadow_root);
2675 let parent_in_shadow_tree = parent.is_in_a_shadow_tree();
2676 let parent_as_slot = parent.downcast::<HTMLSlotElement>();
2677
2678 for kid in new_nodes {
2680 Node::adopt(kid, &parent.owner_document(), can_gc);
2682
2683 parent.add_child(kid, child, can_gc);
2686
2687 if let Some(ref shadow_root) = parent_shadow_root {
2690 if shadow_root.SlotAssignment() == SlotAssignmentMode::Named {
2691 let cx = GlobalScope::get_cx();
2692 if kid.is::<Element>() || kid.is::<Text>() {
2693 rooted!(in(*cx) let slottable = Slottable(Dom::from_ref(kid)));
2694 slottable.assign_a_slot();
2695 }
2696 }
2697 }
2698
2699 if parent_in_shadow_tree {
2702 if let Some(slot_element) = parent_as_slot {
2703 if !slot_element.has_assigned_nodes() {
2704 slot_element.signal_a_slot_change();
2705 }
2706 }
2707 }
2708
2709 kid.GetRootNode(&GetRootNodeOptions::empty())
2711 .assign_slottables_for_a_tree(ForceSlottableNodeReconciliation::Skip);
2712
2713 for descendant in kid.traverse_preorder(ShadowIncluding::Yes) {
2716 if descendant.is_connected() {
2719 static_node_list.push(descendant.clone());
2720 }
2721
2722 if let Some(descendant) = DomRoot::downcast::<Element>(descendant) {
2728 if descendant.is_custom() {
2729 if descendant.is_connected() {
2730 custom_element_reaction_stack.enqueue_callback_reaction(
2731 &descendant,
2732 CallbackReaction::Connected,
2733 None,
2734 );
2735 }
2736 } else {
2737 try_upgrade_element(&descendant);
2738 }
2739 }
2740 }
2741 }
2742
2743 if let SuppressObserver::Unsuppressed = suppress_observers {
2744 vtable_for(parent).children_changed(
2747 &ChildrenMutation::insert(previous_sibling.as_deref(), new_nodes, child),
2748 can_gc,
2749 );
2750
2751 let mutation = LazyCell::new(|| Mutation::ChildList {
2754 added: Some(new_nodes),
2755 removed: None,
2756 prev: previous_sibling.as_deref(),
2757 next: child,
2758 });
2759 MutationObserver::queue_a_mutation_record(parent, mutation);
2760 }
2761
2762 parent_document.add_delayed_task(
2773 task!(PostConnectionSteps: |cx, static_node_list: SmallVec<[DomRoot<Node>; 4]>| {
2774 for node in static_node_list {
2777 vtable_for(&node).post_connection_steps(cx);
2778 }
2779 }),
2780 );
2781
2782 parent_document.remove_script_and_layout_blocker();
2783 from_document.remove_script_and_layout_blocker();
2784 }
2785
2786 pub(crate) fn replace_all(node: Option<&Node>, parent: &Node, can_gc: CanGc) {
2788 parent.owner_doc().add_script_and_layout_blocker();
2789
2790 rooted_vec!(let removed_nodes <- parent.children().map(|child| DomRoot::as_traced(&child)));
2792
2793 rooted_vec!(let mut added_nodes);
2797 let added_nodes = if let Some(node) = node.as_ref() {
2798 if let NodeTypeId::DocumentFragment(_) = node.type_id() {
2799 added_nodes.extend(node.children().map(|child| Dom::from_ref(&*child)));
2800 added_nodes.r()
2801 } else {
2802 from_ref(node)
2803 }
2804 } else {
2805 &[] as &[&Node]
2806 };
2807
2808 for child in &*removed_nodes {
2810 Node::remove(child, parent, SuppressObserver::Suppressed, can_gc);
2811 }
2812
2813 if let Some(node) = node {
2815 Node::insert(node, parent, None, SuppressObserver::Suppressed, can_gc);
2816 }
2817
2818 vtable_for(parent).children_changed(
2819 &ChildrenMutation::replace_all(removed_nodes.r(), added_nodes),
2820 can_gc,
2821 );
2822
2823 if !removed_nodes.is_empty() || !added_nodes.is_empty() {
2826 let mutation = LazyCell::new(|| Mutation::ChildList {
2827 added: Some(added_nodes),
2828 removed: Some(removed_nodes.r()),
2829 prev: None,
2830 next: None,
2831 });
2832 MutationObserver::queue_a_mutation_record(parent, mutation);
2833 }
2834 parent.owner_doc().remove_script_and_layout_blocker();
2835 }
2836
2837 pub(crate) fn string_replace_all(string: DOMString, parent: &Node, can_gc: CanGc) {
2839 if string.is_empty() {
2840 Node::replace_all(None, parent, can_gc);
2841 } else {
2842 let text = Text::new(string, &parent.owner_document(), can_gc);
2843 Node::replace_all(Some(text.upcast::<Node>()), parent, can_gc);
2844 };
2845 }
2846
2847 fn pre_remove(child: &Node, parent: &Node, can_gc: CanGc) -> Fallible<DomRoot<Node>> {
2849 match child.GetParentNode() {
2851 Some(ref node) if &**node != parent => return Err(Error::NotFound(None)),
2852 None => return Err(Error::NotFound(None)),
2853 _ => (),
2854 }
2855
2856 Node::remove(child, parent, SuppressObserver::Unsuppressed, can_gc);
2858
2859 Ok(DomRoot::from_ref(child))
2861 }
2862
2863 fn remove(node: &Node, parent: &Node, suppress_observers: SuppressObserver, can_gc: CanGc) {
2865 parent.owner_doc().add_script_and_layout_blocker();
2866
2867 assert!(
2871 node.GetParentNode()
2872 .is_some_and(|node_parent| &*node_parent == parent)
2873 );
2874
2875 let cached_index = {
2878 if parent.ranges_is_empty() {
2879 None
2880 } else {
2881 let index = node.index();
2887
2888 parent.ranges().decrease_above(parent, index, 1);
2895
2896 Some(index)
2900 }
2901 };
2902
2903 let old_previous_sibling = node.GetPreviousSibling();
2907
2908 let old_next_sibling = node.GetNextSibling();
2910
2911 parent.remove_child(node, cached_index, can_gc);
2914
2915 if let Some(slot) = node.assigned_slot() {
2917 slot.assign_slottables();
2918 }
2919
2920 if parent.is_in_a_shadow_tree() {
2923 if let Some(slot_element) = parent.downcast::<HTMLSlotElement>() {
2924 if !slot_element.has_assigned_nodes() {
2925 slot_element.signal_a_slot_change();
2926 }
2927 }
2928 }
2929
2930 let has_slot_descendant = node
2932 .traverse_preorder(ShadowIncluding::No)
2933 .any(|elem| elem.is::<HTMLSlotElement>());
2934 if has_slot_descendant {
2935 parent
2937 .GetRootNode(&GetRootNodeOptions::empty())
2938 .assign_slottables_for_a_tree(ForceSlottableNodeReconciliation::Skip);
2939
2940 node.assign_slottables_for_a_tree(ForceSlottableNodeReconciliation::Force);
2942 }
2943
2944 if let SuppressObserver::Unsuppressed = suppress_observers {
2948 vtable_for(parent).children_changed(
2949 &ChildrenMutation::replace(
2950 old_previous_sibling.as_deref(),
2951 &Some(node),
2952 &[],
2953 old_next_sibling.as_deref(),
2954 ),
2955 can_gc,
2956 );
2957
2958 let removed = [node];
2959 let mutation = LazyCell::new(|| Mutation::ChildList {
2960 added: None,
2961 removed: Some(&removed),
2962 prev: old_previous_sibling.as_deref(),
2963 next: old_next_sibling.as_deref(),
2964 });
2965 MutationObserver::queue_a_mutation_record(parent, mutation);
2966 }
2967 parent.owner_doc().remove_script_and_layout_blocker();
2968 }
2969
2970 fn compute_attribute_value_with_style_fast_path(attr: &Dom<Attr>, elem: &Element) -> AttrValue {
2976 if *attr.local_name() == local_name!("style") {
2977 if let Some(ref pdb) = *elem.style_attribute().borrow() {
2978 let document = elem.owner_document();
2979 let shared_lock = document.style_shared_lock();
2980 let new_pdb = pdb.read_with(&shared_lock.read()).clone();
2981 return AttrValue::Declaration(
2982 (**attr.value()).to_owned(),
2983 ServoArc::new(shared_lock.wrap(new_pdb)),
2984 );
2985 }
2986 }
2987
2988 attr.value().clone()
2989 }
2990
2991 pub(crate) fn clone(
2993 node: &Node,
2994 maybe_doc: Option<&Document>,
2995 clone_children: CloneChildrenFlag,
2996 registry: Option<DomRoot<CustomElementRegistry>>,
2997 can_gc: CanGc,
2998 ) -> DomRoot<Node> {
2999 let document = match maybe_doc {
3001 Some(doc) => DomRoot::from_ref(doc),
3002 None => node.owner_doc(),
3003 };
3004
3005 let copy: DomRoot<Node> = match node.type_id() {
3008 NodeTypeId::DocumentType => {
3009 let doctype = node.downcast::<DocumentType>().unwrap();
3010 let doctype = DocumentType::new(
3011 doctype.name().clone(),
3012 Some(doctype.public_id().clone()),
3013 Some(doctype.system_id().clone()),
3014 &document,
3015 can_gc,
3016 );
3017 DomRoot::upcast::<Node>(doctype)
3018 },
3019 NodeTypeId::Attr => {
3020 let attr = node.downcast::<Attr>().unwrap();
3021 let attr = Attr::new(
3022 &document,
3023 attr.local_name().clone(),
3024 attr.value().clone(),
3025 attr.name().clone(),
3026 attr.namespace().clone(),
3027 attr.prefix().cloned(),
3028 None,
3029 can_gc,
3030 );
3031 DomRoot::upcast::<Node>(attr)
3032 },
3033 NodeTypeId::DocumentFragment(_) => {
3034 let doc_fragment = DocumentFragment::new(&document, can_gc);
3035 DomRoot::upcast::<Node>(doc_fragment)
3036 },
3037 NodeTypeId::CharacterData(_) => {
3038 let cdata = node.downcast::<CharacterData>().unwrap();
3039 cdata.clone_with_data(cdata.Data(), &document, can_gc)
3040 },
3041 NodeTypeId::Document(_) => {
3042 let document = node.downcast::<Document>().unwrap();
3045 let is_html_doc = if document.is_html_document() {
3046 IsHTMLDocument::HTMLDocument
3047 } else {
3048 IsHTMLDocument::NonHTMLDocument
3049 };
3050 let window = document.window();
3051 let loader = DocumentLoader::new(&document.loader());
3052 let document = Document::new(
3053 window,
3054 HasBrowsingContext::No,
3055 Some(document.url()),
3056 None,
3057 document.origin().clone(),
3059 is_html_doc,
3060 None,
3061 None,
3062 DocumentActivity::Inactive,
3063 DocumentSource::NotFromParser,
3064 loader,
3065 None,
3066 document.status_code(),
3067 Default::default(),
3068 false,
3069 document.allow_declarative_shadow_roots(),
3070 Some(document.insecure_requests_policy()),
3071 document.has_trustworthy_ancestor_or_current_origin(),
3072 document.custom_element_reaction_stack(),
3073 document.creation_sandboxing_flag_set(),
3074 can_gc,
3075 );
3076 DomRoot::upcast::<Node>(document)
3080 },
3081 NodeTypeId::Element(..) => {
3083 let element = node.downcast::<Element>().unwrap();
3084 let registry = element.custom_element_registry().or(registry);
3087 let registry =
3090 if CustomElementRegistry::is_a_global_element_registry(registry.as_deref()) {
3091 Some(document.custom_element_registry())
3092 } else {
3093 registry
3094 };
3095 let name = QualName {
3099 prefix: element.prefix().as_ref().map(|p| Prefix::from(&**p)),
3100 ns: element.namespace().clone(),
3101 local: element.local_name().clone(),
3102 };
3103 let element = Element::create(
3104 name,
3105 element.get_is(),
3106 &document,
3107 ElementCreator::ScriptCreated,
3108 CustomElementCreationMode::Asynchronous,
3109 None,
3110 can_gc,
3111 );
3112 element.set_custom_element_registry(registry);
3114 DomRoot::upcast::<Node>(element)
3115 },
3116 };
3117
3118 let document = match copy.downcast::<Document>() {
3121 Some(doc) => DomRoot::from_ref(doc),
3122 None => DomRoot::from_ref(&*document),
3123 };
3124 assert!(copy.owner_doc() == document);
3125
3126 match node.type_id() {
3128 NodeTypeId::Document(_) => {
3129 let node_doc = node.downcast::<Document>().unwrap();
3130 let copy_doc = copy.downcast::<Document>().unwrap();
3131 copy_doc.set_encoding(node_doc.encoding());
3132 copy_doc.set_quirks_mode(node_doc.quirks_mode());
3133 },
3134 NodeTypeId::Element(..) => {
3135 let node_elem = node.downcast::<Element>().unwrap();
3136 let copy_elem = copy.downcast::<Element>().unwrap();
3137
3138 for attr in node_elem.attrs().iter() {
3140 let new_value =
3142 Node::compute_attribute_value_with_style_fast_path(attr, node_elem);
3143 copy_elem.push_new_attribute(
3145 attr.local_name().clone(),
3146 new_value,
3147 attr.name().clone(),
3148 attr.namespace().clone(),
3149 attr.prefix().cloned(),
3150 AttributeMutationReason::ByCloning,
3151 can_gc,
3152 );
3153 }
3154 },
3155 _ => (),
3156 }
3157
3158 vtable_for(node).cloning_steps(©, maybe_doc, clone_children, can_gc);
3161
3162 if clone_children == CloneChildrenFlag::CloneChildren {
3165 for child in node.children() {
3166 let child_copy = Node::clone(&child, Some(&document), clone_children, None, can_gc);
3167 let _inserted_node = Node::pre_insert(&child_copy, ©, None, can_gc);
3168 }
3169 }
3170
3171 if matches!(node.type_id(), NodeTypeId::Element(_)) {
3174 let node_elem = node.downcast::<Element>().unwrap();
3175 let copy_elem = copy.downcast::<Element>().unwrap();
3176
3177 if let Some(shadow_root) = node_elem.shadow_root().filter(|r| r.Clonable()) {
3178 assert!(!copy_elem.is_shadow_host());
3180
3181 let copy_shadow_root =
3185 copy_elem.attach_shadow(
3186 IsUserAgentWidget::No,
3187 shadow_root.Mode(),
3188 shadow_root.Clonable(),
3189 shadow_root.Serializable(),
3190 shadow_root.DelegatesFocus(),
3191 shadow_root.SlotAssignment(),
3192 can_gc
3193 )
3194 .expect("placement of attached shadow root must be valid, as this is a copy of an existing one");
3195
3196 copy_shadow_root.set_declarative(shadow_root.is_declarative());
3198
3199 for child in shadow_root.upcast::<Node>().children() {
3202 let child_copy = Node::clone(
3203 &child,
3204 Some(&document),
3205 CloneChildrenFlag::CloneChildren,
3206 None,
3207 can_gc,
3208 );
3209
3210 let _inserted_node = Node::pre_insert(
3212 &child_copy,
3213 copy_shadow_root.upcast::<Node>(),
3214 None,
3215 can_gc,
3216 );
3217 }
3218 }
3219 }
3220
3221 copy
3223 }
3224
3225 pub(crate) fn child_text_content(&self) -> DOMString {
3227 Node::collect_text_contents(self.children())
3228 }
3229
3230 pub(crate) fn descendant_text_content(&self) -> DOMString {
3232 Node::collect_text_contents(self.traverse_preorder(ShadowIncluding::No))
3233 }
3234
3235 pub(crate) fn collect_text_contents<T: Iterator<Item = DomRoot<Node>>>(
3236 iterator: T,
3237 ) -> DOMString {
3238 let mut content = String::new();
3239 for node in iterator {
3240 if let Some(text) = node.downcast::<Text>() {
3241 content.push_str(&text.upcast::<CharacterData>().data());
3242 }
3243 }
3244 DOMString::from(content)
3245 }
3246
3247 pub(crate) fn set_text_content_for_element(&self, value: Option<DOMString>, can_gc: CanGc) {
3249 assert!(matches!(
3252 self.type_id(),
3253 NodeTypeId::DocumentFragment(_) | NodeTypeId::Element(..)
3254 ));
3255 let value = value.unwrap_or_default();
3256 let node = if value.is_empty() {
3257 None
3259 } else {
3260 Some(DomRoot::upcast(
3263 self.owner_doc().CreateTextNode(value, can_gc),
3264 ))
3265 };
3266
3267 Self::replace_all(node.as_deref(), self, can_gc);
3269 }
3270
3271 pub(crate) fn namespace_to_string(namespace: Namespace) -> Option<DOMString> {
3272 match namespace {
3273 ns!() => None,
3274 _ => Some(DOMString::from(&*namespace)),
3276 }
3277 }
3278
3279 pub(crate) fn locate_namespace(node: &Node, prefix: Option<DOMString>) -> Namespace {
3281 match node.type_id() {
3282 NodeTypeId::Element(_) => node.downcast::<Element>().unwrap().locate_namespace(prefix),
3283 NodeTypeId::Attr => node
3284 .downcast::<Attr>()
3285 .unwrap()
3286 .GetOwnerElement()
3287 .as_ref()
3288 .map_or(ns!(), |elem| elem.locate_namespace(prefix)),
3289 NodeTypeId::Document(_) => node
3290 .downcast::<Document>()
3291 .unwrap()
3292 .GetDocumentElement()
3293 .as_ref()
3294 .map_or(ns!(), |elem| elem.locate_namespace(prefix)),
3295 NodeTypeId::DocumentType | NodeTypeId::DocumentFragment(_) => ns!(),
3296 _ => node
3297 .GetParentElement()
3298 .as_ref()
3299 .map_or(ns!(), |elem| elem.locate_namespace(prefix)),
3300 }
3301 }
3302
3303 #[expect(unsafe_code)]
3311 pub(crate) unsafe fn from_untrusted_node_address(
3312 candidate: UntrustedNodeAddress,
3313 ) -> &'static Self {
3314 let candidate = candidate.0 as usize;
3316 let object = candidate as *mut JSObject;
3317 if object.is_null() {
3318 panic!("Attempted to create a `Node` from an invalid pointer!")
3319 }
3320
3321 unsafe { &*(conversions::private_from_object(object) as *const Self) }
3322 }
3323
3324 pub(crate) fn html_serialize(
3325 &self,
3326 traversal_scope: html_serialize::TraversalScope,
3327 serialize_shadow_roots: bool,
3328 shadow_roots: Vec<DomRoot<ShadowRoot>>,
3329 can_gc: CanGc,
3330 ) -> DOMString {
3331 let mut writer = vec![];
3332 let mut serializer = HtmlSerializer::new(
3333 &mut writer,
3334 html_serialize::SerializeOpts {
3335 traversal_scope: traversal_scope.clone(),
3336 ..Default::default()
3337 },
3338 );
3339
3340 serialize_html_fragment(
3341 self,
3342 &mut serializer,
3343 traversal_scope,
3344 serialize_shadow_roots,
3345 shadow_roots,
3346 can_gc,
3347 )
3348 .expect("Serializing node failed");
3349
3350 DOMString::from(String::from_utf8(writer).unwrap())
3352 }
3353
3354 pub(crate) fn xml_serialize(
3356 &self,
3357 traversal_scope: xml_serialize::TraversalScope,
3358 ) -> Fallible<DOMString> {
3359 let mut writer = vec![];
3360 xml_serialize::serialize(
3361 &mut writer,
3362 &HtmlSerialize::new(self),
3363 xml_serialize::SerializeOpts { traversal_scope },
3364 )
3365 .map_err(|error| {
3366 error!("Cannot serialize node: {error}");
3367 Error::InvalidState(None)
3368 })?;
3369
3370 let string = DOMString::from(String::from_utf8(writer).map_err(|error| {
3372 error!("Cannot serialize node: {error}");
3373 Error::InvalidState(None)
3374 })?);
3375
3376 Ok(string)
3377 }
3378
3379 pub(crate) fn fragment_serialization_algorithm(
3381 &self,
3382 require_well_formed: bool,
3383 can_gc: CanGc,
3384 ) -> Fallible<DOMString> {
3385 let context_document = self.owner_document();
3387
3388 if context_document.is_html_document() {
3391 return Ok(self.html_serialize(
3392 html_serialize::TraversalScope::ChildrenOnly(None),
3393 false,
3394 vec![],
3395 can_gc,
3396 ));
3397 }
3398
3399 let _ = require_well_formed;
3402 self.xml_serialize(xml_serialize::TraversalScope::ChildrenOnly(None))
3403 }
3404
3405 pub(crate) fn establishes_scrolling_box(&self) -> bool {
3407 if self.is::<Document>() {
3412 return true;
3413 }
3414 let Some(element) = self.downcast::<Element>() else {
3415 return false;
3417 };
3418 element.style().is_some_and(|style| {
3421 let overflow_x = style.get_box().clone_overflow_x();
3422 let overflow_y = style.get_box().clone_overflow_y();
3423 overflow_x.is_scrollable() || overflow_y.is_scrollable()
3424 })
3425 }
3426}
3427
3428impl NodeMethods<crate::DomTypeHolder> for Node {
3429 fn NodeType(&self) -> u16 {
3431 match self.type_id() {
3432 NodeTypeId::Attr => NodeConstants::ATTRIBUTE_NODE,
3433 NodeTypeId::CharacterData(CharacterDataTypeId::Text(TextTypeId::Text)) => {
3434 NodeConstants::TEXT_NODE
3435 },
3436 NodeTypeId::CharacterData(CharacterDataTypeId::Text(TextTypeId::CDATASection)) => {
3437 NodeConstants::CDATA_SECTION_NODE
3438 },
3439 NodeTypeId::CharacterData(CharacterDataTypeId::ProcessingInstruction) => {
3440 NodeConstants::PROCESSING_INSTRUCTION_NODE
3441 },
3442 NodeTypeId::CharacterData(CharacterDataTypeId::Comment) => NodeConstants::COMMENT_NODE,
3443 NodeTypeId::Document(_) => NodeConstants::DOCUMENT_NODE,
3444 NodeTypeId::DocumentType => NodeConstants::DOCUMENT_TYPE_NODE,
3445 NodeTypeId::DocumentFragment(_) => NodeConstants::DOCUMENT_FRAGMENT_NODE,
3446 NodeTypeId::Element(_) => NodeConstants::ELEMENT_NODE,
3447 }
3448 }
3449
3450 fn NodeName(&self) -> DOMString {
3452 match self.type_id() {
3453 NodeTypeId::Attr => self.downcast::<Attr>().unwrap().qualified_name(),
3454 NodeTypeId::Element(..) => self.downcast::<Element>().unwrap().TagName(),
3455 NodeTypeId::CharacterData(CharacterDataTypeId::Text(TextTypeId::Text)) => {
3456 DOMString::from("#text")
3457 },
3458 NodeTypeId::CharacterData(CharacterDataTypeId::Text(TextTypeId::CDATASection)) => {
3459 DOMString::from("#cdata-section")
3460 },
3461 NodeTypeId::CharacterData(CharacterDataTypeId::ProcessingInstruction) => {
3462 self.downcast::<ProcessingInstruction>().unwrap().Target()
3463 },
3464 NodeTypeId::CharacterData(CharacterDataTypeId::Comment) => DOMString::from("#comment"),
3465 NodeTypeId::DocumentType => self.downcast::<DocumentType>().unwrap().name().clone(),
3466 NodeTypeId::DocumentFragment(_) => DOMString::from("#document-fragment"),
3467 NodeTypeId::Document(_) => DOMString::from("#document"),
3468 }
3469 }
3470
3471 fn BaseURI(&self) -> USVString {
3473 USVString(String::from(self.owner_doc().base_url().as_str()))
3474 }
3475
3476 fn IsConnected(&self) -> bool {
3478 self.is_connected()
3479 }
3480
3481 fn GetOwnerDocument(&self) -> Option<DomRoot<Document>> {
3483 match self.type_id() {
3484 NodeTypeId::Document(_) => None,
3485 _ => Some(self.owner_doc()),
3486 }
3487 }
3488
3489 fn GetRootNode(&self, options: &GetRootNodeOptions) -> DomRoot<Node> {
3491 if !options.composed {
3492 if let Some(shadow_root) = self.containing_shadow_root() {
3493 return DomRoot::upcast(shadow_root);
3494 }
3495 }
3496
3497 if self.is_connected() {
3498 DomRoot::from_ref(self.owner_doc().upcast::<Node>())
3499 } else {
3500 self.inclusive_ancestors(ShadowIncluding::Yes)
3501 .last()
3502 .unwrap()
3503 }
3504 }
3505
3506 fn GetParentNode(&self) -> Option<DomRoot<Node>> {
3508 self.parent_node.get()
3509 }
3510
3511 fn GetParentElement(&self) -> Option<DomRoot<Element>> {
3513 self.GetParentNode().and_then(DomRoot::downcast)
3514 }
3515
3516 fn HasChildNodes(&self) -> bool {
3518 self.first_child.get().is_some()
3519 }
3520
3521 fn ChildNodes(&self, can_gc: CanGc) -> DomRoot<NodeList> {
3523 if let Some(list) = self.ensure_rare_data().child_list.get() {
3524 return list;
3525 }
3526
3527 let doc = self.owner_doc();
3528 let window = doc.window();
3529 let list = NodeList::new_child_list(window, self, can_gc);
3530 self.ensure_rare_data().child_list.set(Some(&list));
3531 list
3532 }
3533
3534 fn GetFirstChild(&self) -> Option<DomRoot<Node>> {
3536 self.first_child.get()
3537 }
3538
3539 fn GetLastChild(&self) -> Option<DomRoot<Node>> {
3541 self.last_child.get()
3542 }
3543
3544 fn GetPreviousSibling(&self) -> Option<DomRoot<Node>> {
3546 self.prev_sibling.get()
3547 }
3548
3549 fn GetNextSibling(&self) -> Option<DomRoot<Node>> {
3551 self.next_sibling.get()
3552 }
3553
3554 fn GetNodeValue(&self) -> Option<DOMString> {
3556 match self.type_id() {
3557 NodeTypeId::Attr => Some(self.downcast::<Attr>().unwrap().Value()),
3558 NodeTypeId::CharacterData(_) => {
3559 self.downcast::<CharacterData>().map(CharacterData::Data)
3560 },
3561 _ => None,
3562 }
3563 }
3564
3565 fn SetNodeValue(&self, val: Option<DOMString>, can_gc: CanGc) -> Fallible<()> {
3567 match self.type_id() {
3568 NodeTypeId::Attr => {
3569 let attr = self.downcast::<Attr>().unwrap();
3570 attr.SetValue(val.unwrap_or_default(), can_gc)?;
3571 },
3572 NodeTypeId::CharacterData(_) => {
3573 let character_data = self.downcast::<CharacterData>().unwrap();
3574 character_data.SetData(val.unwrap_or_default());
3575 },
3576 _ => {},
3577 };
3578 Ok(())
3579 }
3580
3581 fn GetTextContent(&self) -> Option<DOMString> {
3583 match self.type_id() {
3584 NodeTypeId::DocumentFragment(_) | NodeTypeId::Element(..) => {
3585 let content =
3586 Node::collect_text_contents(self.traverse_preorder(ShadowIncluding::No));
3587 Some(content)
3588 },
3589 NodeTypeId::Attr => Some(self.downcast::<Attr>().unwrap().Value()),
3590 NodeTypeId::CharacterData(..) => {
3591 let characterdata = self.downcast::<CharacterData>().unwrap();
3592 Some(characterdata.Data())
3593 },
3594 NodeTypeId::DocumentType | NodeTypeId::Document(_) => None,
3595 }
3596 }
3597
3598 fn SetTextContent(&self, value: Option<DOMString>, can_gc: CanGc) -> Fallible<()> {
3600 match self.type_id() {
3601 NodeTypeId::DocumentFragment(_) | NodeTypeId::Element(..) => {
3602 self.set_text_content_for_element(value, can_gc);
3603 },
3604 NodeTypeId::Attr => {
3605 let attr = self.downcast::<Attr>().unwrap();
3606 attr.SetValue(value.unwrap_or_default(), can_gc)?;
3607 },
3608 NodeTypeId::CharacterData(..) => {
3609 let characterdata = self.downcast::<CharacterData>().unwrap();
3610 characterdata.SetData(value.unwrap_or_default());
3611 },
3612 NodeTypeId::DocumentType | NodeTypeId::Document(_) => {},
3613 };
3614 Ok(())
3615 }
3616
3617 fn InsertBefore(
3619 &self,
3620 node: &Node,
3621 child: Option<&Node>,
3622 can_gc: CanGc,
3623 ) -> Fallible<DomRoot<Node>> {
3624 Node::pre_insert(node, self, child, can_gc)
3625 }
3626
3627 fn AppendChild(&self, node: &Node, can_gc: CanGc) -> Fallible<DomRoot<Node>> {
3629 Node::pre_insert(node, self, None, can_gc)
3630 }
3631
3632 fn ReplaceChild(&self, node: &Node, child: &Node, can_gc: CanGc) -> Fallible<DomRoot<Node>> {
3634 match self.type_id() {
3637 NodeTypeId::Document(_) | NodeTypeId::DocumentFragment(_) | NodeTypeId::Element(..) => {
3638 },
3639 _ => return Err(Error::HierarchyRequest(None)),
3640 }
3641
3642 if node.is_inclusive_ancestor_of(self) {
3645 return Err(Error::HierarchyRequest(None));
3646 }
3647
3648 if !self.is_parent_of(child) {
3650 return Err(Error::NotFound(None));
3651 }
3652
3653 match node.type_id() {
3658 NodeTypeId::CharacterData(CharacterDataTypeId::Text(_)) if self.is::<Document>() => {
3659 return Err(Error::HierarchyRequest(None));
3660 },
3661 NodeTypeId::DocumentType if !self.is::<Document>() => {
3662 return Err(Error::HierarchyRequest(None));
3663 },
3664 NodeTypeId::Document(_) | NodeTypeId::Attr => {
3665 return Err(Error::HierarchyRequest(None));
3666 },
3667 _ => (),
3668 }
3669
3670 if self.is::<Document>() {
3673 match node.type_id() {
3674 NodeTypeId::DocumentFragment(_) => {
3676 if node.children().any(|c| c.is::<Text>()) {
3678 return Err(Error::HierarchyRequest(None));
3679 }
3680 match node.child_elements().count() {
3681 0 => (),
3682 1 => {
3684 if self.child_elements().any(|c| c.upcast::<Node>() != child) {
3685 return Err(Error::HierarchyRequest(None));
3686 }
3687 if child.following_siblings().any(|child| child.is_doctype()) {
3688 return Err(Error::HierarchyRequest(None));
3689 }
3690 },
3691 _ => return Err(Error::HierarchyRequest(None)),
3693 }
3694 },
3695 NodeTypeId::Element(..) => {
3697 if self.child_elements().any(|c| c.upcast::<Node>() != child) {
3698 return Err(Error::HierarchyRequest(None));
3699 }
3700 if child.following_siblings().any(|child| child.is_doctype()) {
3701 return Err(Error::HierarchyRequest(None));
3702 }
3703 },
3704 NodeTypeId::DocumentType => {
3706 if self.children().any(|c| c.is_doctype() && &*c != child) {
3707 return Err(Error::HierarchyRequest(None));
3708 }
3709 if self
3710 .children()
3711 .take_while(|c| &**c != child)
3712 .any(|c| c.is::<Element>())
3713 {
3714 return Err(Error::HierarchyRequest(None));
3715 }
3716 },
3717 NodeTypeId::CharacterData(..) => (),
3718 NodeTypeId::Document(_) => unreachable!(),
3721 NodeTypeId::Attr => unreachable!(),
3722 }
3723 }
3724
3725 let child_next_sibling = child.GetNextSibling();
3728 let node_next_sibling = node.GetNextSibling();
3729 let reference_child = if child_next_sibling.as_deref() == Some(node) {
3730 node_next_sibling.as_deref()
3731 } else {
3732 child_next_sibling.as_deref()
3733 };
3734
3735 let previous_sibling = child.GetPreviousSibling();
3737
3738 let document = self.owner_document();
3742 Node::adopt(node, &document, can_gc);
3743
3744 let removed_child = if node != child {
3749 Node::remove(child, self, SuppressObserver::Suppressed, can_gc);
3751 Some(child)
3752 } else {
3753 None
3754 };
3755
3756 rooted_vec!(let mut nodes);
3758 let nodes = if node.type_id() ==
3759 NodeTypeId::DocumentFragment(DocumentFragmentTypeId::DocumentFragment) ||
3760 node.type_id() == NodeTypeId::DocumentFragment(DocumentFragmentTypeId::ShadowRoot)
3761 {
3762 nodes.extend(node.children().map(|node| Dom::from_ref(&*node)));
3763 nodes.r()
3764 } else {
3765 from_ref(&node)
3766 };
3767
3768 Node::insert(
3770 node,
3771 self,
3772 reference_child,
3773 SuppressObserver::Suppressed,
3774 can_gc,
3775 );
3776
3777 vtable_for(self).children_changed(
3778 &ChildrenMutation::replace(
3779 previous_sibling.as_deref(),
3780 &removed_child,
3781 nodes,
3782 reference_child,
3783 ),
3784 can_gc,
3785 );
3786
3787 let removed = removed_child.map(|r| [r]);
3790 let mutation = LazyCell::new(|| Mutation::ChildList {
3791 added: Some(nodes),
3792 removed: removed.as_ref().map(|r| &r[..]),
3793 prev: previous_sibling.as_deref(),
3794 next: reference_child,
3795 });
3796
3797 MutationObserver::queue_a_mutation_record(self, mutation);
3798
3799 Ok(DomRoot::from_ref(child))
3801 }
3802
3803 fn RemoveChild(&self, node: &Node, can_gc: CanGc) -> Fallible<DomRoot<Node>> {
3805 Node::pre_remove(node, self, can_gc)
3806 }
3807
3808 fn Normalize(&self, can_gc: CanGc) {
3810 let mut children = self.children().enumerate().peekable();
3811 while let Some((_, node)) = children.next() {
3812 if let Some(text) = node.downcast::<Text>() {
3813 if text.is::<CDATASection>() {
3814 continue;
3815 }
3816 let cdata = text.upcast::<CharacterData>();
3817 let mut length = cdata.Length();
3818 if length == 0 {
3819 Node::remove(&node, self, SuppressObserver::Unsuppressed, can_gc);
3820 continue;
3821 }
3822 while children.peek().is_some_and(|(_, sibling)| {
3823 sibling.is::<Text>() && !sibling.is::<CDATASection>()
3824 }) {
3825 let (index, sibling) = children.next().unwrap();
3826 sibling
3827 .ranges()
3828 .drain_to_preceding_text_sibling(&sibling, &node, length);
3829 self.ranges()
3830 .move_to_text_child_at(self, index as u32, &node, length);
3831 let sibling_cdata = sibling.downcast::<CharacterData>().unwrap();
3832 length += sibling_cdata.Length();
3833 cdata.append_data(&sibling_cdata.data());
3834 Node::remove(&sibling, self, SuppressObserver::Unsuppressed, can_gc);
3835 }
3836 } else {
3837 node.Normalize(can_gc);
3838 }
3839 }
3840 }
3841
3842 fn CloneNode(&self, subtree: bool, can_gc: CanGc) -> Fallible<DomRoot<Node>> {
3844 if self.is::<ShadowRoot>() {
3846 return Err(Error::NotSupported(None));
3847 }
3848
3849 let result = Node::clone(
3851 self,
3852 None,
3853 if subtree {
3854 CloneChildrenFlag::CloneChildren
3855 } else {
3856 CloneChildrenFlag::DoNotCloneChildren
3857 },
3858 None,
3859 can_gc,
3860 );
3861 Ok(result)
3862 }
3863
3864 fn IsEqualNode(&self, maybe_node: Option<&Node>) -> bool {
3866 fn is_equal_doctype(node: &Node, other: &Node) -> bool {
3867 let doctype = node.downcast::<DocumentType>().unwrap();
3868 let other_doctype = other.downcast::<DocumentType>().unwrap();
3869 (*doctype.name() == *other_doctype.name()) &&
3870 (*doctype.public_id() == *other_doctype.public_id()) &&
3871 (*doctype.system_id() == *other_doctype.system_id())
3872 }
3873 fn is_equal_element(node: &Node, other: &Node) -> bool {
3874 let element = node.downcast::<Element>().unwrap();
3875 let other_element = other.downcast::<Element>().unwrap();
3876 (*element.namespace() == *other_element.namespace()) &&
3877 (*element.prefix() == *other_element.prefix()) &&
3878 (*element.local_name() == *other_element.local_name()) &&
3879 (element.attrs().len() == other_element.attrs().len())
3880 }
3881 fn is_equal_processinginstruction(node: &Node, other: &Node) -> bool {
3882 let pi = node.downcast::<ProcessingInstruction>().unwrap();
3883 let other_pi = other.downcast::<ProcessingInstruction>().unwrap();
3884 (*pi.target() == *other_pi.target()) &&
3885 (*pi.upcast::<CharacterData>().data() ==
3886 *other_pi.upcast::<CharacterData>().data())
3887 }
3888 fn is_equal_characterdata(node: &Node, other: &Node) -> bool {
3889 let characterdata = node.downcast::<CharacterData>().unwrap();
3890 let other_characterdata = other.downcast::<CharacterData>().unwrap();
3891 *characterdata.data() == *other_characterdata.data()
3892 }
3893 fn is_equal_attr(node: &Node, other: &Node) -> bool {
3894 let attr = node.downcast::<Attr>().unwrap();
3895 let other_attr = other.downcast::<Attr>().unwrap();
3896 (*attr.namespace() == *other_attr.namespace()) &&
3897 (attr.local_name() == other_attr.local_name()) &&
3898 (**attr.value() == **other_attr.value())
3899 }
3900 fn is_equal_element_attrs(node: &Node, other: &Node) -> bool {
3901 let element = node.downcast::<Element>().unwrap();
3902 let other_element = other.downcast::<Element>().unwrap();
3903 assert!(element.attrs().len() == other_element.attrs().len());
3904 element.attrs().iter().all(|attr| {
3905 other_element.attrs().iter().any(|other_attr| {
3906 (*attr.namespace() == *other_attr.namespace()) &&
3907 (attr.local_name() == other_attr.local_name()) &&
3908 (**attr.value() == **other_attr.value())
3909 })
3910 })
3911 }
3912
3913 fn is_equal_node(this: &Node, node: &Node) -> bool {
3914 if this.NodeType() != node.NodeType() {
3916 return false;
3917 }
3918
3919 match node.type_id() {
3920 NodeTypeId::DocumentType if !is_equal_doctype(this, node) => return false,
3922 NodeTypeId::Element(..) if !is_equal_element(this, node) => return false,
3923 NodeTypeId::CharacterData(CharacterDataTypeId::ProcessingInstruction)
3924 if !is_equal_processinginstruction(this, node) =>
3925 {
3926 return false;
3927 },
3928 NodeTypeId::CharacterData(CharacterDataTypeId::Text(_)) |
3929 NodeTypeId::CharacterData(CharacterDataTypeId::Comment)
3930 if !is_equal_characterdata(this, node) =>
3931 {
3932 return false;
3933 },
3934 NodeTypeId::Element(..) if !is_equal_element_attrs(this, node) => return false,
3936 NodeTypeId::Attr if !is_equal_attr(this, node) => return false,
3937
3938 _ => (),
3939 }
3940
3941 if this.children_count() != node.children_count() {
3943 return false;
3944 }
3945
3946 this.children()
3948 .zip(node.children())
3949 .all(|(child, other_child)| is_equal_node(&child, &other_child))
3950 }
3951 match maybe_node {
3952 None => false,
3954 Some(node) => is_equal_node(self, node),
3956 }
3957 }
3958
3959 fn IsSameNode(&self, other_node: Option<&Node>) -> bool {
3961 match other_node {
3962 Some(node) => self == node,
3963 None => false,
3964 }
3965 }
3966
3967 fn CompareDocumentPosition(&self, other: &Node) -> u16 {
3969 if self == other {
3971 return 0;
3972 }
3973
3974 let mut node1 = Some(other);
3976 let mut node2 = Some(self);
3977
3978 let mut attr1: Option<&Attr> = None;
3980 let mut attr2: Option<&Attr> = None;
3981
3982 let attr1owner;
3987 if let Some(a) = other.downcast::<Attr>() {
3988 attr1 = Some(a);
3989 attr1owner = a.GetOwnerElement();
3990 node1 = match attr1owner {
3991 Some(ref e) => Some(e.upcast()),
3992 None => None,
3993 }
3994 }
3995
3996 let attr2owner;
3999 if let Some(a) = self.downcast::<Attr>() {
4000 attr2 = Some(a);
4001 attr2owner = a.GetOwnerElement();
4002 node2 = match attr2owner {
4003 Some(ref e) => Some(e.upcast()),
4004 None => None,
4005 }
4006 }
4007
4008 if let Some(node2) = node2 {
4013 if Some(node2) == node1 {
4014 if let (Some(a1), Some(a2)) = (attr1, attr2) {
4015 let attrs = node2.downcast::<Element>().unwrap().attrs();
4016 for attr in attrs.iter() {
4020 if (*attr.namespace() == *a1.namespace()) &&
4021 (attr.local_name() == a1.local_name()) &&
4022 (**attr.value() == **a1.value())
4023 {
4024 return NodeConstants::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC +
4025 NodeConstants::DOCUMENT_POSITION_PRECEDING;
4026 }
4027 if (*attr.namespace() == *a2.namespace()) &&
4028 (attr.local_name() == a2.local_name()) &&
4029 (**attr.value() == **a2.value())
4030 {
4031 return NodeConstants::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC +
4032 NodeConstants::DOCUMENT_POSITION_FOLLOWING;
4033 }
4034 }
4035 unreachable!();
4038 }
4039 }
4040 }
4041
4042 match (node1, node2) {
4044 (None, _) => {
4045 NodeConstants::DOCUMENT_POSITION_FOLLOWING +
4047 NodeConstants::DOCUMENT_POSITION_DISCONNECTED +
4048 NodeConstants::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC
4049 },
4050 (_, None) => {
4051 NodeConstants::DOCUMENT_POSITION_PRECEDING +
4053 NodeConstants::DOCUMENT_POSITION_DISCONNECTED +
4054 NodeConstants::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC
4055 },
4056 (Some(node1), Some(node2)) => {
4057 let mut self_and_ancestors = node2
4059 .inclusive_ancestors(ShadowIncluding::No)
4060 .collect::<SmallVec<[_; 20]>>();
4061 let mut other_and_ancestors = node1
4062 .inclusive_ancestors(ShadowIncluding::No)
4063 .collect::<SmallVec<[_; 20]>>();
4064
4065 if self_and_ancestors.last() != other_and_ancestors.last() {
4066 let random = as_uintptr(self_and_ancestors.last().unwrap()) <
4067 as_uintptr(other_and_ancestors.last().unwrap());
4068 let random = if random {
4069 NodeConstants::DOCUMENT_POSITION_FOLLOWING
4070 } else {
4071 NodeConstants::DOCUMENT_POSITION_PRECEDING
4072 };
4073
4074 return random +
4076 NodeConstants::DOCUMENT_POSITION_DISCONNECTED +
4077 NodeConstants::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC;
4078 }
4079 let mut parent = self_and_ancestors.pop().unwrap();
4081 other_and_ancestors.pop().unwrap();
4082
4083 let mut current_position =
4084 cmp::min(self_and_ancestors.len(), other_and_ancestors.len());
4085
4086 while current_position > 0 {
4087 current_position -= 1;
4088 let child_1 = self_and_ancestors.pop().unwrap();
4089 let child_2 = other_and_ancestors.pop().unwrap();
4090
4091 if child_1 != child_2 {
4092 for child in parent.children() {
4093 if child == child_1 {
4094 return NodeConstants::DOCUMENT_POSITION_FOLLOWING;
4096 }
4097 if child == child_2 {
4098 return NodeConstants::DOCUMENT_POSITION_PRECEDING;
4100 }
4101 }
4102 }
4103
4104 parent = child_1;
4105 }
4106
4107 if self_and_ancestors.len() < other_and_ancestors.len() {
4112 NodeConstants::DOCUMENT_POSITION_FOLLOWING +
4113 NodeConstants::DOCUMENT_POSITION_CONTAINED_BY
4114 } else {
4115 NodeConstants::DOCUMENT_POSITION_PRECEDING +
4116 NodeConstants::DOCUMENT_POSITION_CONTAINS
4117 }
4118 },
4119 }
4120 }
4121
4122 fn Contains(&self, maybe_other: Option<&Node>) -> bool {
4124 match maybe_other {
4125 None => false,
4126 Some(other) => self.is_inclusive_ancestor_of(other),
4127 }
4128 }
4129
4130 fn LookupPrefix(&self, namespace: Option<DOMString>) -> Option<DOMString> {
4132 let namespace = namespace_from_domstring(namespace);
4133
4134 if namespace == ns!() {
4136 return None;
4137 }
4138
4139 match self.type_id() {
4141 NodeTypeId::Element(..) => self.downcast::<Element>().unwrap().lookup_prefix(namespace),
4142 NodeTypeId::Document(_) => self
4143 .downcast::<Document>()
4144 .unwrap()
4145 .GetDocumentElement()
4146 .and_then(|element| element.lookup_prefix(namespace)),
4147 NodeTypeId::DocumentType | NodeTypeId::DocumentFragment(_) => None,
4148 NodeTypeId::Attr => self
4149 .downcast::<Attr>()
4150 .unwrap()
4151 .GetOwnerElement()
4152 .and_then(|element| element.lookup_prefix(namespace)),
4153 _ => self
4154 .GetParentElement()
4155 .and_then(|element| element.lookup_prefix(namespace)),
4156 }
4157 }
4158
4159 fn LookupNamespaceURI(&self, prefix: Option<DOMString>) -> Option<DOMString> {
4161 let prefix = prefix.filter(|prefix| !prefix.is_empty());
4163
4164 Node::namespace_to_string(Node::locate_namespace(self, prefix))
4166 }
4167
4168 fn IsDefaultNamespace(&self, namespace: Option<DOMString>) -> bool {
4170 let namespace = namespace_from_domstring(namespace);
4172 Node::locate_namespace(self, None) == namespace
4174 }
4175}
4176
4177pub(crate) trait NodeTraits {
4178 fn owner_document(&self) -> DomRoot<Document>;
4182 fn owner_window(&self) -> DomRoot<Window>;
4186 fn owner_global(&self) -> DomRoot<GlobalScope>;
4190 fn containing_shadow_root(&self) -> Option<DomRoot<ShadowRoot>>;
4192 fn stylesheet_list_owner(&self) -> StyleSheetListOwner;
4195}
4196
4197impl<T: DerivedFrom<Node> + DomObject> NodeTraits for T {
4198 fn owner_document(&self) -> DomRoot<Document> {
4199 self.upcast().owner_doc()
4200 }
4201
4202 fn owner_window(&self) -> DomRoot<Window> {
4203 DomRoot::from_ref(self.owner_document().window())
4204 }
4205
4206 fn owner_global(&self) -> DomRoot<GlobalScope> {
4207 DomRoot::from_ref(self.owner_window().upcast())
4208 }
4209
4210 fn containing_shadow_root(&self) -> Option<DomRoot<ShadowRoot>> {
4211 Node::containing_shadow_root(self.upcast())
4212 }
4213
4214 #[cfg_attr(crown, expect(crown::unrooted_must_root))]
4215 fn stylesheet_list_owner(&self) -> StyleSheetListOwner {
4216 self.containing_shadow_root()
4217 .map(|shadow_root| StyleSheetListOwner::ShadowRoot(Dom::from_ref(&*shadow_root)))
4218 .unwrap_or_else(|| {
4219 StyleSheetListOwner::Document(Dom::from_ref(&*self.owner_document()))
4220 })
4221 }
4222}
4223
4224impl VirtualMethods for Node {
4225 fn super_type(&self) -> Option<&dyn VirtualMethods> {
4226 Some(self.upcast::<EventTarget>() as &dyn VirtualMethods)
4227 }
4228
4229 fn children_changed(&self, mutation: &ChildrenMutation, can_gc: CanGc) {
4230 if let Some(s) = self.super_type() {
4231 s.children_changed(mutation, can_gc);
4232 }
4233
4234 if let Some(data) = self.rare_data().as_ref() {
4235 if let Some(list) = data.child_list.get() {
4236 list.as_children_list().children_changed(mutation);
4237 }
4238 }
4239
4240 self.owner_doc().content_and_heritage_changed(self);
4241 }
4242
4243 fn unbind_from_tree(&self, context: &UnbindContext, can_gc: CanGc) {
4246 self.super_type().unwrap().unbind_from_tree(context, can_gc);
4247
4248 if !self.is_in_a_shadow_tree() && !self.ranges_is_empty() {
4253 self.ranges().drain_to_parent(context, self);
4254 }
4255 }
4256
4257 fn handle_event(&self, event: &Event, _: CanGc) {
4258 if let Some(event) = event.downcast::<KeyboardEvent>() {
4259 self.owner_document()
4260 .event_handler()
4261 .run_default_keyboard_event_handler(event);
4262 }
4263 }
4264}
4265
4266#[derive(Clone, Copy, MallocSizeOf, PartialEq)]
4268pub(crate) enum NodeDamage {
4269 Style,
4271 ContentOrHeritage,
4274 Other,
4276}
4277
4278pub(crate) enum ChildrenMutation<'a> {
4279 Append {
4280 prev: &'a Node,
4281 added: &'a [&'a Node],
4282 },
4283 Insert {
4284 prev: &'a Node,
4285 added: &'a [&'a Node],
4286 next: &'a Node,
4287 },
4288 Prepend {
4289 added: &'a [&'a Node],
4290 next: &'a Node,
4291 },
4292 Replace {
4293 prev: Option<&'a Node>,
4294 removed: &'a Node,
4295 added: &'a [&'a Node],
4296 next: Option<&'a Node>,
4297 },
4298 ReplaceAll {
4299 removed: &'a [&'a Node],
4300 added: &'a [&'a Node],
4301 },
4302 ChangeText,
4307}
4308
4309impl<'a> ChildrenMutation<'a> {
4310 fn insert(
4311 prev: Option<&'a Node>,
4312 added: &'a [&'a Node],
4313 next: Option<&'a Node>,
4314 ) -> ChildrenMutation<'a> {
4315 match (prev, next) {
4316 (None, None) => ChildrenMutation::ReplaceAll {
4317 removed: &[],
4318 added,
4319 },
4320 (Some(prev), None) => ChildrenMutation::Append { prev, added },
4321 (None, Some(next)) => ChildrenMutation::Prepend { added, next },
4322 (Some(prev), Some(next)) => ChildrenMutation::Insert { prev, added, next },
4323 }
4324 }
4325
4326 fn replace(
4327 prev: Option<&'a Node>,
4328 removed: &'a Option<&'a Node>,
4329 added: &'a [&'a Node],
4330 next: Option<&'a Node>,
4331 ) -> ChildrenMutation<'a> {
4332 if let Some(ref removed) = *removed {
4333 if let (None, None) = (prev, next) {
4334 ChildrenMutation::ReplaceAll {
4335 removed: from_ref(removed),
4336 added,
4337 }
4338 } else {
4339 ChildrenMutation::Replace {
4340 prev,
4341 removed,
4342 added,
4343 next,
4344 }
4345 }
4346 } else {
4347 ChildrenMutation::insert(prev, added, next)
4348 }
4349 }
4350
4351 fn replace_all(removed: &'a [&'a Node], added: &'a [&'a Node]) -> ChildrenMutation<'a> {
4352 ChildrenMutation::ReplaceAll { removed, added }
4353 }
4354
4355 pub(crate) fn next_child(&self) -> Option<&Node> {
4360 match *self {
4361 ChildrenMutation::Append { .. } => None,
4362 ChildrenMutation::Insert { next, .. } => Some(next),
4363 ChildrenMutation::Prepend { next, .. } => Some(next),
4364 ChildrenMutation::Replace { next, .. } => next,
4365 ChildrenMutation::ReplaceAll { .. } => None,
4366 ChildrenMutation::ChangeText => None,
4367 }
4368 }
4369
4370 pub(crate) fn modified_edge_element(&self) -> Option<DomRoot<Node>> {
4377 match *self {
4378 ChildrenMutation::Prepend { next, .. } |
4380 ChildrenMutation::Replace {
4381 prev: None,
4382 next: Some(next),
4383 ..
4384 } => next
4385 .inclusively_following_siblings()
4386 .find(|node| node.is::<Element>()),
4387 ChildrenMutation::Append { prev, .. } |
4389 ChildrenMutation::Replace {
4390 prev: Some(prev),
4391 next: None,
4392 ..
4393 } => prev
4394 .inclusively_preceding_siblings()
4395 .find(|node| node.is::<Element>()),
4396 ChildrenMutation::Insert { prev, next, .. } |
4398 ChildrenMutation::Replace {
4399 prev: Some(prev),
4400 next: Some(next),
4401 ..
4402 } => {
4403 if prev
4404 .inclusively_preceding_siblings()
4405 .all(|node| !node.is::<Element>())
4406 {
4407 next.inclusively_following_siblings()
4409 .find(|node| node.is::<Element>())
4410 } else if next
4411 .inclusively_following_siblings()
4412 .all(|node| !node.is::<Element>())
4413 {
4414 prev.inclusively_preceding_siblings()
4416 .find(|node| node.is::<Element>())
4417 } else {
4418 None
4419 }
4420 },
4421
4422 ChildrenMutation::Replace {
4423 prev: None,
4424 next: None,
4425 ..
4426 } => unreachable!(),
4427 ChildrenMutation::ReplaceAll { .. } => None,
4428 ChildrenMutation::ChangeText => None,
4429 }
4430 }
4431}
4432
4433pub(crate) struct BindContext<'a> {
4435 pub(crate) parent: &'a Node,
4437
4438 pub(crate) tree_connected: bool,
4442
4443 pub(crate) tree_is_in_a_document_tree: bool,
4447
4448 pub(crate) tree_is_in_a_shadow_tree: bool,
4450
4451 pub(crate) is_shadow_tree: IsShadowTree,
4456}
4457
4458#[derive(Debug, Eq, PartialEq)]
4459pub(crate) enum IsShadowTree {
4460 Yes,
4461 No,
4462}
4463
4464impl<'a> BindContext<'a> {
4465 pub(crate) fn new(parent: &'a Node, is_shadow_tree: IsShadowTree) -> Self {
4467 BindContext {
4468 parent,
4469 tree_connected: parent.is_connected(),
4470 tree_is_in_a_document_tree: parent.is_in_a_document_tree(),
4471 tree_is_in_a_shadow_tree: parent.is_in_a_shadow_tree(),
4472 is_shadow_tree,
4473 }
4474 }
4475
4476 pub(crate) fn is_in_tree(&self) -> bool {
4478 self.tree_is_in_a_document_tree || self.tree_is_in_a_shadow_tree
4479 }
4480}
4481
4482pub(crate) struct UnbindContext<'a> {
4485 index: Cell<Option<u32>>,
4487 pub(crate) parent: &'a Node,
4489 prev_sibling: Option<&'a Node>,
4491 pub(crate) next_sibling: Option<&'a Node>,
4493
4494 pub(crate) tree_connected: bool,
4498
4499 pub(crate) tree_is_in_a_document_tree: bool,
4503
4504 pub(crate) tree_is_in_a_shadow_tree: bool,
4506}
4507
4508impl<'a> UnbindContext<'a> {
4509 pub(crate) fn new(
4511 parent: &'a Node,
4512 prev_sibling: Option<&'a Node>,
4513 next_sibling: Option<&'a Node>,
4514 cached_index: Option<u32>,
4515 ) -> Self {
4516 UnbindContext {
4517 index: Cell::new(cached_index),
4518 parent,
4519 prev_sibling,
4520 next_sibling,
4521 tree_connected: parent.is_connected(),
4522 tree_is_in_a_document_tree: parent.is_in_a_document_tree(),
4523 tree_is_in_a_shadow_tree: parent.is_in_a_shadow_tree(),
4524 }
4525 }
4526
4527 pub(crate) fn index(&self) -> u32 {
4529 if let Some(index) = self.index.get() {
4530 return index;
4531 }
4532 let index = self.prev_sibling.map_or(0, |sibling| sibling.index() + 1);
4533 self.index.set(Some(index));
4534 index
4535 }
4536}
4537
4538pub(crate) struct UniqueId {
4540 cell: UnsafeCell<Option<Box<Uuid>>>,
4541}
4542
4543unsafe_no_jsmanaged_fields!(UniqueId);
4544
4545impl MallocSizeOf for UniqueId {
4546 #[expect(unsafe_code)]
4547 fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
4548 if let Some(uuid) = unsafe { &*self.cell.get() } {
4549 unsafe { ops.malloc_size_of(&**uuid) }
4550 } else {
4551 0
4552 }
4553 }
4554}
4555
4556impl UniqueId {
4557 fn new() -> UniqueId {
4559 UniqueId {
4560 cell: UnsafeCell::new(None),
4561 }
4562 }
4563
4564 #[expect(unsafe_code)]
4566 fn borrow(&self) -> &Uuid {
4567 unsafe {
4568 let ptr = self.cell.get();
4569 if (*ptr).is_none() {
4570 *ptr = Some(Box::new(Uuid::new_v4()));
4571 }
4572 (*ptr).as_ref().unwrap()
4573 }
4574 }
4575}
4576
4577pub(crate) struct NodeTypeIdWrapper(pub(crate) NodeTypeId);
4578
4579impl From<NodeTypeIdWrapper> for LayoutNodeType {
4580 #[inline(always)]
4581 fn from(node_type: NodeTypeIdWrapper) -> LayoutNodeType {
4582 match node_type.0 {
4583 NodeTypeId::Element(e) => LayoutNodeType::Element(ElementTypeIdWrapper(e).into()),
4584 NodeTypeId::CharacterData(CharacterDataTypeId::Text(_)) => LayoutNodeType::Text,
4585 x => unreachable!("Layout should not traverse nodes of type {:?}", x),
4586 }
4587 }
4588}
4589
4590struct ElementTypeIdWrapper(ElementTypeId);
4591
4592impl From<ElementTypeIdWrapper> for LayoutElementType {
4593 #[inline(always)]
4594 fn from(element_type: ElementTypeIdWrapper) -> LayoutElementType {
4595 match element_type.0 {
4596 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLBodyElement) => {
4597 LayoutElementType::HTMLBodyElement
4598 },
4599 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLBRElement) => {
4600 LayoutElementType::HTMLBRElement
4601 },
4602 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLCanvasElement) => {
4603 LayoutElementType::HTMLCanvasElement
4604 },
4605 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLHtmlElement) => {
4606 LayoutElementType::HTMLHtmlElement
4607 },
4608 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLIFrameElement) => {
4609 LayoutElementType::HTMLIFrameElement
4610 },
4611 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLImageElement) => {
4612 LayoutElementType::HTMLImageElement
4613 },
4614 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLMediaElement(_)) => {
4615 LayoutElementType::HTMLMediaElement
4616 },
4617 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLInputElement) => {
4618 LayoutElementType::HTMLInputElement
4619 },
4620 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLOptGroupElement) => {
4621 LayoutElementType::HTMLOptGroupElement
4622 },
4623 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLOptionElement) => {
4624 LayoutElementType::HTMLOptionElement
4625 },
4626 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLObjectElement) => {
4627 LayoutElementType::HTMLObjectElement
4628 },
4629 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLParagraphElement) => {
4630 LayoutElementType::HTMLParagraphElement
4631 },
4632 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLPreElement) => {
4633 LayoutElementType::HTMLPreElement
4634 },
4635 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLSelectElement) => {
4636 LayoutElementType::HTMLSelectElement
4637 },
4638 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTableCellElement) => {
4639 LayoutElementType::HTMLTableCellElement
4640 },
4641 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTableColElement) => {
4642 LayoutElementType::HTMLTableColElement
4643 },
4644 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTableElement) => {
4645 LayoutElementType::HTMLTableElement
4646 },
4647 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTableRowElement) => {
4648 LayoutElementType::HTMLTableRowElement
4649 },
4650 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTableSectionElement) => {
4651 LayoutElementType::HTMLTableSectionElement
4652 },
4653 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTextAreaElement) => {
4654 LayoutElementType::HTMLTextAreaElement
4655 },
4656 ElementTypeId::SVGElement(SVGElementTypeId::SVGGraphicsElement(
4657 SVGGraphicsElementTypeId::SVGImageElement,
4658 )) => LayoutElementType::SVGImageElement,
4659 ElementTypeId::SVGElement(SVGElementTypeId::SVGGraphicsElement(
4660 SVGGraphicsElementTypeId::SVGSVGElement,
4661 )) => LayoutElementType::SVGSVGElement,
4662 _ => LayoutElementType::Element,
4663 }
4664 }
4665}
4666
4667pub(crate) trait VecPreOrderInsertionHelper<T> {
4670 fn insert_pre_order(&mut self, elem: &T, tree_root: &Node);
4671}
4672
4673impl<T> VecPreOrderInsertionHelper<T> for Vec<Dom<T>>
4674where
4675 T: DerivedFrom<Node> + DomObject,
4676{
4677 fn insert_pre_order(&mut self, elem: &T, tree_root: &Node) {
4687 if self.is_empty() {
4688 self.push(Dom::from_ref(elem));
4689 return;
4690 }
4691
4692 let elem_node = elem.upcast::<Node>();
4693 let mut head: usize = 0;
4694 for node in tree_root.traverse_preorder(ShadowIncluding::No) {
4695 let head_node = DomRoot::upcast::<Node>(DomRoot::from_ref(&*self[head]));
4696 if head_node == node {
4697 head += 1;
4698 }
4699 if elem_node == &*node || head == self.len() {
4700 break;
4701 }
4702 }
4703 self.insert(head, Dom::from_ref(elem));
4704 }
4705}