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