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, 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::cssstylesheet::CSSStyleSheet;
90use crate::dom::customelementregistry::{CallbackReaction, try_upgrade_element};
91use crate::dom::document::{Document, DocumentSource, HasBrowsingContext, IsHTMLDocument};
92use crate::dom::documentfragment::DocumentFragment;
93use crate::dom::documenttype::DocumentType;
94use crate::dom::element::{CustomElementCreationMode, Element, ElementCreator, SelectorWrapper};
95use crate::dom::event::{Event, EventBubbles, EventCancelable};
96use crate::dom::eventtarget::EventTarget;
97use crate::dom::globalscope::GlobalScope;
98use crate::dom::html::htmlcanvaselement::{HTMLCanvasElement, LayoutHTMLCanvasElementHelpers};
99use crate::dom::html::htmlcollection::HTMLCollection;
100use crate::dom::html::htmlelement::HTMLElement;
101use crate::dom::html::htmliframeelement::{HTMLIFrameElement, HTMLIFrameElementLayoutMethods};
102use crate::dom::html::htmlimageelement::{HTMLImageElement, LayoutHTMLImageElementHelpers};
103use crate::dom::html::htmlinputelement::{
104 HTMLInputElement, InputType, LayoutHTMLInputElementHelpers,
105};
106use crate::dom::html::htmllinkelement::HTMLLinkElement;
107use crate::dom::html::htmlslotelement::{HTMLSlotElement, Slottable};
108use crate::dom::html::htmlstyleelement::HTMLStyleElement;
109use crate::dom::html::htmltextareaelement::{
110 HTMLTextAreaElement, LayoutHTMLTextAreaElementHelpers,
111};
112use crate::dom::html::htmlvideoelement::{HTMLVideoElement, LayoutHTMLVideoElementHelpers};
113use crate::dom::mutationobserver::{Mutation, MutationObserver, RegisteredObserver};
114use crate::dom::nodelist::NodeList;
115use crate::dom::pointerevent::{PointerEvent, PointerId};
116use crate::dom::processinginstruction::ProcessingInstruction;
117use crate::dom::range::WeakRangeVec;
118use crate::dom::raredata::NodeRareData;
119use crate::dom::servoparser::{ServoParser, serialize_html_fragment};
120use crate::dom::shadowroot::{IsUserAgentWidget, LayoutShadowRootHelpers, ShadowRoot};
121use crate::dom::stylesheetlist::StyleSheetListOwner;
122use crate::dom::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);
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 for node in root.traverse_preorder(ShadowIncluding::Yes) {
390 node.clean_up_style_and_layout_data();
391
392 vtable_for(&node).unbind_from_tree(context, can_gc);
397
398 if is_parent_connected {
400 if let Some(element) = node.as_custom_element() {
401 custom_element_reaction_stack.enqueue_callback_reaction(
402 &element,
403 CallbackReaction::Disconnected,
404 None,
405 );
406 }
407 }
408 }
409 }
410
411 fn remove_child(&self, child: &Node, cached_index: Option<u32>, can_gc: CanGc) {
415 assert!(child.parent_node.get().as_deref() == Some(self));
416 self.note_dirty_descendants();
417
418 let prev_sibling = child.GetPreviousSibling();
419 match prev_sibling {
420 None => {
421 self.first_child.set(child.next_sibling.get().as_deref());
422 },
423 Some(ref prev_sibling) => {
424 prev_sibling
425 .next_sibling
426 .set(child.next_sibling.get().as_deref());
427 },
428 }
429 let next_sibling = child.GetNextSibling();
430 match next_sibling {
431 None => {
432 self.last_child.set(child.prev_sibling.get().as_deref());
433 },
434 Some(ref next_sibling) => {
435 next_sibling
436 .prev_sibling
437 .set(child.prev_sibling.get().as_deref());
438 },
439 }
440
441 let context = UnbindContext::new(
442 self,
443 prev_sibling.as_deref(),
444 next_sibling.as_deref(),
445 cached_index,
446 );
447
448 child.prev_sibling.set(None);
449 child.next_sibling.set(None);
450 child.parent_node.set(None);
451 self.children_count.set(self.children_count.get() - 1);
452
453 Self::complete_remove_subtree(child, &context, can_gc);
454 }
455
456 pub(crate) fn to_untrusted_node_address(&self) -> UntrustedNodeAddress {
457 UntrustedNodeAddress(self.reflector().get_jsobject().get() as *const c_void)
458 }
459
460 pub(crate) fn to_opaque(&self) -> OpaqueNode {
461 OpaqueNode(self.reflector().get_jsobject().get() as usize)
462 }
463
464 pub(crate) fn as_custom_element(&self) -> Option<DomRoot<Element>> {
465 self.downcast::<Element>().and_then(|element| {
466 if element.is_custom() {
467 assert!(element.get_custom_element_definition().is_some());
468 Some(DomRoot::from_ref(element))
469 } else {
470 None
471 }
472 })
473 }
474
475 pub(crate) fn fire_synthetic_pointer_event_not_trusted(&self, name: DOMString, can_gc: CanGc) {
477 let window = self.owner_window();
481
482 let pointer_event = PointerEvent::new(
484 &window, name,
486 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,
513 );
514
515 pointer_event.upcast::<Event>().set_composed(true);
517
518 pointer_event.upcast::<Event>().set_trusted(false);
520
521 pointer_event
524 .upcast::<Event>()
525 .dispatch(self.upcast::<EventTarget>(), false, can_gc);
526 }
527
528 pub(crate) fn parent_directionality(&self) -> String {
529 let mut current = self.GetParentNode();
530
531 loop {
532 match current {
533 Some(node) => {
534 if let Some(directionality) = node
535 .downcast::<HTMLElement>()
536 .and_then(|html_element| html_element.directionality())
537 {
538 return directionality;
539 } else {
540 current = node.GetParentNode();
541 }
542 },
543 None => return "ltr".to_owned(),
544 }
545 }
546 }
547}
548
549pub(crate) struct QuerySelectorIterator {
550 selectors: SelectorList<SelectorImpl>,
551 iterator: TreeIterator,
552}
553
554impl QuerySelectorIterator {
555 fn new(iter: TreeIterator, selectors: SelectorList<SelectorImpl>) -> QuerySelectorIterator {
556 QuerySelectorIterator {
557 selectors,
558 iterator: iter,
559 }
560 }
561}
562
563impl Iterator for QuerySelectorIterator {
564 type Item = DomRoot<Node>;
565
566 fn next(&mut self) -> Option<DomRoot<Node>> {
567 let selectors = &self.selectors;
568
569 self.iterator
570 .by_ref()
571 .filter_map(|node| {
572 let mut nth_index_cache = Default::default();
575 let mut ctx = MatchingContext::new(
576 MatchingMode::Normal,
577 None,
578 &mut nth_index_cache,
579 node.owner_doc().quirks_mode(),
580 NeedsSelectorFlags::No,
581 MatchingForInvalidation::No,
582 );
583 if let Some(element) = DomRoot::downcast(node) {
584 if matches_selector_list(
585 selectors,
586 &SelectorWrapper::Borrowed(&element),
587 &mut ctx,
588 ) {
589 return Some(DomRoot::upcast(element));
590 }
591 }
592 None
593 })
594 .next()
595 }
596}
597
598impl Node {
599 fn rare_data(&self) -> Ref<'_, Option<Box<NodeRareData>>> {
600 self.rare_data.borrow()
601 }
602
603 fn ensure_rare_data(&self) -> RefMut<'_, Box<NodeRareData>> {
604 let mut rare_data = self.rare_data.borrow_mut();
605 if rare_data.is_none() {
606 *rare_data = Some(Default::default());
607 }
608 RefMut::map(rare_data, |rare_data| rare_data.as_mut().unwrap())
609 }
610
611 pub(crate) fn is_before(&self, other: &Node) -> bool {
614 let cmp = other.CompareDocumentPosition(self);
615 if cmp & NodeConstants::DOCUMENT_POSITION_DISCONNECTED != 0 {
616 return false;
617 }
618
619 cmp & NodeConstants::DOCUMENT_POSITION_PRECEDING != 0
620 }
621
622 pub(crate) fn registered_mutation_observers_mut(&self) -> RefMut<'_, Vec<RegisteredObserver>> {
625 RefMut::map(self.ensure_rare_data(), |rare_data| {
626 &mut rare_data.mutation_observers
627 })
628 }
629
630 pub(crate) fn registered_mutation_observers(&self) -> Option<Ref<'_, Vec<RegisteredObserver>>> {
631 let rare_data: Ref<'_, _> = self.rare_data.borrow();
632
633 if rare_data.is_none() {
634 return None;
635 }
636 Some(Ref::map(rare_data, |rare_data| {
637 &rare_data.as_ref().unwrap().mutation_observers
638 }))
639 }
640
641 pub(crate) fn add_mutation_observer(&self, observer: RegisteredObserver) {
643 self.ensure_rare_data().mutation_observers.push(observer);
644 }
645
646 pub(crate) fn remove_mutation_observer(&self, observer: &MutationObserver) {
648 self.ensure_rare_data()
649 .mutation_observers
650 .retain(|reg_obs| &*reg_obs.observer != observer)
651 }
652
653 pub(crate) fn dump(&self) {
655 self.dump_indent(0);
656 }
657
658 pub(crate) fn dump_indent(&self, indent: u32) {
660 let mut s = String::new();
661 for _ in 0..indent {
662 s.push_str(" ");
663 }
664
665 s.push_str(&self.debug_str());
666 debug!("{:?}", s);
667
668 for kid in self.children() {
670 kid.dump_indent(indent + 1)
671 }
672 }
673
674 pub(crate) fn debug_str(&self) -> String {
676 format!("{:?}", self.type_id())
677 }
678
679 pub(crate) fn is_in_a_document_tree(&self) -> bool {
681 self.flags.get().contains(NodeFlags::IS_IN_A_DOCUMENT_TREE)
682 }
683
684 pub(crate) fn is_in_a_shadow_tree(&self) -> bool {
686 self.flags.get().contains(NodeFlags::IS_IN_SHADOW_TREE)
687 }
688
689 pub(crate) fn has_weird_parser_insertion_mode(&self) -> bool {
690 self.flags
691 .get()
692 .contains(NodeFlags::HAS_WEIRD_PARSER_INSERTION_MODE)
693 }
694
695 pub(crate) fn set_weird_parser_insertion_mode(&self) {
696 self.set_flag(NodeFlags::HAS_WEIRD_PARSER_INSERTION_MODE, true)
697 }
698
699 pub(crate) fn is_connected(&self) -> bool {
701 self.flags.get().contains(NodeFlags::IS_CONNECTED)
702 }
703
704 pub(crate) fn set_in_ua_widget(&self, in_ua_widget: bool) {
705 self.set_flag(NodeFlags::IS_IN_UA_WIDGET, in_ua_widget)
706 }
707
708 pub(crate) fn is_in_ua_widget(&self) -> bool {
709 self.flags.get().contains(NodeFlags::IS_IN_UA_WIDGET)
710 }
711
712 pub(crate) fn type_id(&self) -> NodeTypeId {
714 match *self.eventtarget.type_id() {
715 EventTargetTypeId::Node(type_id) => type_id,
716 _ => unreachable!(),
717 }
718 }
719
720 pub(crate) fn len(&self) -> u32 {
722 match self.type_id() {
723 NodeTypeId::DocumentType => 0,
724 NodeTypeId::CharacterData(_) => self.downcast::<CharacterData>().unwrap().Length(),
725 _ => self.children_count(),
726 }
727 }
728
729 pub(crate) fn is_empty(&self) -> bool {
730 self.len() == 0
732 }
733
734 pub(crate) fn index(&self) -> u32 {
736 self.preceding_siblings().count() as u32
737 }
738
739 pub(crate) fn has_parent(&self) -> bool {
741 self.parent_node.get().is_some()
742 }
743
744 pub(crate) fn children_count(&self) -> u32 {
745 self.children_count.get()
746 }
747
748 pub(crate) fn ranges(&self) -> RefMut<'_, WeakRangeVec> {
749 RefMut::map(self.ensure_rare_data(), |rare_data| &mut rare_data.ranges)
750 }
751
752 pub(crate) fn ranges_is_empty(&self) -> bool {
753 self.rare_data()
754 .as_ref()
755 .is_none_or(|data| data.ranges.is_empty())
756 }
757
758 #[inline]
759 pub(crate) fn is_doctype(&self) -> bool {
760 self.type_id() == NodeTypeId::DocumentType
761 }
762
763 pub(crate) fn get_flag(&self, flag: NodeFlags) -> bool {
764 self.flags.get().contains(flag)
765 }
766
767 pub(crate) fn set_flag(&self, flag: NodeFlags, value: bool) {
768 let mut flags = self.flags.get();
769
770 if value {
771 flags.insert(flag);
772 } else {
773 flags.remove(flag);
774 }
775
776 self.flags.set(flags);
777 }
778
779 pub(crate) fn note_dirty_descendants(&self) {
781 self.owner_doc().note_node_with_dirty_descendants(self);
782 }
783
784 pub(crate) fn has_dirty_descendants(&self) -> bool {
785 self.get_flag(NodeFlags::HAS_DIRTY_DESCENDANTS)
786 }
787
788 pub(crate) fn rev_version(&self) {
789 let doc: DomRoot<Node> = DomRoot::upcast(self.owner_doc());
794 let version = cmp::max(
795 self.inclusive_descendants_version(),
796 doc.inclusive_descendants_version(),
797 ) + 1;
798
799 let mut node = &MutNullableDom::new(Some(self));
802 while let Some(p) = node.if_is_some(|p| {
803 p.inclusive_descendants_version.set(version);
804 &p.parent_node
805 }) {
806 node = p
807 }
808 doc.inclusive_descendants_version.set(version);
809 }
810
811 pub(crate) fn dirty(&self, damage: NodeDamage) {
812 self.rev_version();
813 if !self.is_connected() {
814 return;
815 }
816
817 match self.type_id() {
818 NodeTypeId::CharacterData(CharacterDataTypeId::Text(TextTypeId::Text)) => {
819 self.parent_node
823 .get()
824 .unwrap()
825 .dirty(NodeDamage::ContentOrHeritage)
826 },
827 NodeTypeId::Element(_) => self.downcast::<Element>().unwrap().restyle(damage),
828 NodeTypeId::DocumentFragment(DocumentFragmentTypeId::ShadowRoot) => self
829 .downcast::<ShadowRoot>()
830 .unwrap()
831 .Host()
832 .upcast::<Element>()
833 .restyle(damage),
834 _ => {},
835 };
836 }
837
838 pub(crate) fn inclusive_descendants_version(&self) -> u64 {
840 self.inclusive_descendants_version.get()
841 }
842
843 pub(crate) fn traverse_preorder(&self, shadow_including: ShadowIncluding) -> TreeIterator {
845 TreeIterator::new(self, shadow_including)
846 }
847
848 pub(crate) fn inclusively_following_siblings(
849 &self,
850 ) -> impl Iterator<Item = DomRoot<Node>> + use<> {
851 SimpleNodeIterator {
852 current: Some(DomRoot::from_ref(self)),
853 next_node: |n| n.GetNextSibling(),
854 }
855 }
856
857 pub(crate) fn inclusively_preceding_siblings(
858 &self,
859 ) -> impl Iterator<Item = DomRoot<Node>> + use<> {
860 SimpleNodeIterator {
861 current: Some(DomRoot::from_ref(self)),
862 next_node: |n| n.GetPreviousSibling(),
863 }
864 }
865
866 pub(crate) fn common_ancestor(
867 &self,
868 other: &Node,
869 shadow_including: ShadowIncluding,
870 ) -> Option<DomRoot<Node>> {
871 self.inclusive_ancestors(shadow_including).find(|ancestor| {
872 other
873 .inclusive_ancestors(shadow_including)
874 .any(|node| node == *ancestor)
875 })
876 }
877
878 pub(crate) fn common_ancestor_in_flat_tree(&self, other: &Node) -> Option<DomRoot<Node>> {
879 self.inclusive_ancestors_in_flat_tree().find(|ancestor| {
880 other
881 .inclusive_ancestors_in_flat_tree()
882 .any(|node| node == *ancestor)
883 })
884 }
885
886 pub(crate) fn is_inclusive_ancestor_of(&self, child: &Node) -> bool {
887 self == child || self.is_ancestor_of(child)
888 }
889
890 pub(crate) fn is_ancestor_of(&self, child: &Node) -> bool {
891 child.ancestors().any(|ancestor| &*ancestor == self)
892 }
893
894 pub(crate) fn is_shadow_including_inclusive_ancestor_of(&self, node: &Node) -> bool {
895 node.inclusive_ancestors(ShadowIncluding::Yes)
896 .any(|ancestor| &*ancestor == self)
897 }
898
899 pub(crate) fn following_siblings(&self) -> impl Iterator<Item = DomRoot<Node>> + use<> {
900 SimpleNodeIterator {
901 current: self.GetNextSibling(),
902 next_node: |n| n.GetNextSibling(),
903 }
904 }
905
906 pub(crate) fn preceding_siblings(&self) -> impl Iterator<Item = DomRoot<Node>> + use<> {
907 SimpleNodeIterator {
908 current: self.GetPreviousSibling(),
909 next_node: |n| n.GetPreviousSibling(),
910 }
911 }
912
913 pub(crate) fn following_nodes(&self, root: &Node) -> FollowingNodeIterator {
914 FollowingNodeIterator {
915 current: Some(DomRoot::from_ref(self)),
916 root: DomRoot::from_ref(root),
917 }
918 }
919
920 pub(crate) fn preceding_nodes(&self, root: &Node) -> PrecedingNodeIterator {
921 PrecedingNodeIterator {
922 current: Some(DomRoot::from_ref(self)),
923 root: DomRoot::from_ref(root),
924 }
925 }
926
927 pub(crate) fn descending_last_children(&self) -> impl Iterator<Item = DomRoot<Node>> + use<> {
928 SimpleNodeIterator {
929 current: self.GetLastChild(),
930 next_node: |n| n.GetLastChild(),
931 }
932 }
933
934 pub(crate) fn is_parent_of(&self, child: &Node) -> bool {
935 child
936 .parent_node
937 .get()
938 .is_some_and(|parent| &*parent == self)
939 }
940
941 pub(crate) fn to_trusted_node_address(&self) -> TrustedNodeAddress {
942 TrustedNodeAddress(self as *const Node as *const libc::c_void)
943 }
944
945 pub(crate) fn content_box(&self) -> Option<Rect<Au>> {
946 self.owner_window()
947 .box_area_query(self, BoxAreaType::Content)
948 }
949
950 pub(crate) fn border_box(&self) -> Option<Rect<Au>> {
951 self.owner_window()
952 .box_area_query(self, BoxAreaType::Border)
953 }
954
955 pub(crate) fn padding_box(&self) -> Option<Rect<Au>> {
956 self.owner_window()
957 .box_area_query(self, BoxAreaType::Padding)
958 }
959
960 pub(crate) fn border_boxes(&self) -> Vec<Rect<Au>> {
961 self.owner_window()
962 .box_areas_query(self, BoxAreaType::Border)
963 }
964
965 pub(crate) fn client_rect(&self) -> Rect<i32> {
966 self.owner_window().client_rect_query(self)
967 }
968
969 pub(crate) fn scroll_area(&self) -> Rect<i32> {
972 let document = self.owner_doc();
974
975 if !document.is_active() {
977 return Rect::zero();
978 }
979
980 let window = document.window();
983 let viewport = Size2D::new(window.InnerWidth(), window.InnerHeight());
984
985 let in_quirks_mode = document.quirks_mode() == QuirksMode::Quirks;
986 let is_root = self.downcast::<Element>().is_some_and(|e| e.is_root());
987 let is_body_element = self
988 .downcast::<HTMLElement>()
989 .is_some_and(|e| e.is_body_element());
990
991 if (is_root && !in_quirks_mode) || (is_body_element && in_quirks_mode) {
997 let viewport_scrolling_area = window.scrolling_area_query(None);
998 return Rect::new(
999 viewport_scrolling_area.origin,
1000 viewport_scrolling_area.size.max(viewport),
1001 );
1002 }
1003
1004 window.scrolling_area_query(Some(self))
1008 }
1009
1010 pub(crate) fn before(&self, nodes: Vec<NodeOrString>, can_gc: CanGc) -> ErrorResult {
1012 let parent = &self.parent_node;
1014
1015 let parent = match parent.get() {
1017 None => return Ok(()),
1018 Some(parent) => parent,
1019 };
1020
1021 let viable_previous_sibling = first_node_not_in(self.preceding_siblings(), &nodes);
1023
1024 let node = self
1026 .owner_doc()
1027 .node_from_nodes_and_strings(nodes, can_gc)?;
1028
1029 let viable_previous_sibling = match viable_previous_sibling {
1031 Some(ref viable_previous_sibling) => viable_previous_sibling.next_sibling.get(),
1032 None => parent.first_child.get(),
1033 };
1034
1035 Node::pre_insert(&node, &parent, viable_previous_sibling.as_deref(), can_gc)?;
1037
1038 Ok(())
1039 }
1040
1041 pub(crate) fn after(&self, nodes: Vec<NodeOrString>, can_gc: CanGc) -> ErrorResult {
1043 let parent = &self.parent_node;
1045
1046 let parent = match parent.get() {
1048 None => return Ok(()),
1049 Some(parent) => parent,
1050 };
1051
1052 let viable_next_sibling = first_node_not_in(self.following_siblings(), &nodes);
1054
1055 let node = self
1057 .owner_doc()
1058 .node_from_nodes_and_strings(nodes, can_gc)?;
1059
1060 Node::pre_insert(&node, &parent, viable_next_sibling.as_deref(), can_gc)?;
1062
1063 Ok(())
1064 }
1065
1066 pub(crate) fn replace_with(&self, nodes: Vec<NodeOrString>, can_gc: CanGc) -> ErrorResult {
1068 let Some(parent) = self.GetParentNode() else {
1070 return Ok(());
1072 };
1073
1074 let viable_next_sibling = first_node_not_in(self.following_siblings(), &nodes);
1076
1077 let node = self
1079 .owner_doc()
1080 .node_from_nodes_and_strings(nodes, can_gc)?;
1081
1082 if self.parent_node == Some(&*parent) {
1083 parent.ReplaceChild(&node, self, can_gc)?;
1085 } else {
1086 Node::pre_insert(&node, &parent, viable_next_sibling.as_deref(), can_gc)?;
1088 }
1089 Ok(())
1090 }
1091
1092 pub(crate) fn prepend(&self, nodes: Vec<NodeOrString>, can_gc: CanGc) -> ErrorResult {
1094 let doc = self.owner_doc();
1096 let node = doc.node_from_nodes_and_strings(nodes, can_gc)?;
1097 let first_child = self.first_child.get();
1099 Node::pre_insert(&node, self, first_child.as_deref(), can_gc).map(|_| ())
1100 }
1101
1102 pub(crate) fn append(&self, nodes: Vec<NodeOrString>, can_gc: CanGc) -> ErrorResult {
1104 let doc = self.owner_doc();
1106 let node = doc.node_from_nodes_and_strings(nodes, can_gc)?;
1107 self.AppendChild(&node, can_gc).map(|_| ())
1109 }
1110
1111 pub(crate) fn replace_children(&self, nodes: Vec<NodeOrString>, can_gc: CanGc) -> ErrorResult {
1113 let doc = self.owner_doc();
1115 let node = doc.node_from_nodes_and_strings(nodes, can_gc)?;
1116 Node::ensure_pre_insertion_validity(&node, self, None)?;
1118 Node::replace_all(Some(&node), self, can_gc);
1120 Ok(())
1121 }
1122
1123 pub(crate) fn query_selector(
1125 &self,
1126 selectors: DOMString,
1127 ) -> Fallible<Option<DomRoot<Element>>> {
1128 let doc = self.owner_doc();
1130 match SelectorParser::parse_author_origin_no_namespace(
1131 &selectors.str(),
1132 &UrlExtraData(doc.url().get_arc()),
1133 ) {
1134 Err(_) => Err(Error::Syntax(None)),
1136 Ok(selectors) => {
1138 let mut nth_index_cache = Default::default();
1139 let mut ctx = MatchingContext::new(
1140 MatchingMode::Normal,
1141 None,
1142 &mut nth_index_cache,
1143 doc.quirks_mode(),
1144 NeedsSelectorFlags::No,
1145 MatchingForInvalidation::No,
1146 );
1147 let mut descendants = self.traverse_preorder(ShadowIncluding::No);
1148 assert!(&*descendants.next().unwrap() == self);
1150 Ok(descendants.filter_map(DomRoot::downcast).find(|element| {
1151 matches_selector_list(&selectors, &SelectorWrapper::Borrowed(element), &mut ctx)
1152 }))
1153 },
1154 }
1155 }
1156
1157 pub(crate) fn query_selector_iter(
1162 &self,
1163 selectors: DOMString,
1164 ) -> Fallible<QuerySelectorIterator> {
1165 let url = self.owner_doc().url();
1167 match SelectorParser::parse_author_origin_no_namespace(
1168 &selectors.str(),
1169 &UrlExtraData(url.get_arc()),
1170 ) {
1171 Err(_) => Err(Error::Syntax(None)),
1173 Ok(selectors) => {
1175 let mut descendants = self.traverse_preorder(ShadowIncluding::No);
1176 assert!(&*descendants.next().unwrap() == self);
1178 Ok(QuerySelectorIterator::new(descendants, selectors))
1179 },
1180 }
1181 }
1182
1183 #[allow(unsafe_code)]
1185 pub(crate) fn query_selector_all(&self, selectors: DOMString) -> Fallible<DomRoot<NodeList>> {
1186 let window = self.owner_window();
1187 let iter = self.query_selector_iter(selectors)?;
1188 Ok(NodeList::new_simple_list(&window, iter, CanGc::note()))
1189 }
1190
1191 pub(crate) fn ancestors(&self) -> impl Iterator<Item = DomRoot<Node>> + use<> {
1192 SimpleNodeIterator {
1193 current: self.GetParentNode(),
1194 next_node: |n| n.GetParentNode(),
1195 }
1196 }
1197
1198 pub(crate) fn inclusive_ancestors(
1200 &self,
1201 shadow_including: ShadowIncluding,
1202 ) -> impl Iterator<Item = DomRoot<Node>> + use<> {
1203 SimpleNodeIterator {
1204 current: Some(DomRoot::from_ref(self)),
1205 next_node: move |n| {
1206 if shadow_including == ShadowIncluding::Yes {
1207 if let Some(shadow_root) = n.downcast::<ShadowRoot>() {
1208 return Some(DomRoot::from_ref(shadow_root.Host().upcast::<Node>()));
1209 }
1210 }
1211 n.GetParentNode()
1212 },
1213 }
1214 }
1215
1216 pub(crate) fn owner_doc(&self) -> DomRoot<Document> {
1217 self.owner_doc.get().unwrap()
1218 }
1219
1220 pub(crate) fn set_owner_doc(&self, document: &Document) {
1221 self.owner_doc.set(Some(document));
1222 }
1223
1224 pub(crate) fn containing_shadow_root(&self) -> Option<DomRoot<ShadowRoot>> {
1225 self.rare_data()
1226 .as_ref()?
1227 .containing_shadow_root
1228 .as_ref()
1229 .map(|sr| DomRoot::from_ref(&**sr))
1230 }
1231
1232 pub(crate) fn set_containing_shadow_root(&self, shadow_root: Option<&ShadowRoot>) {
1233 self.ensure_rare_data().containing_shadow_root = shadow_root.map(Dom::from_ref);
1234 }
1235
1236 pub(crate) fn is_in_html_doc(&self) -> bool {
1237 self.owner_doc().is_html_document()
1238 }
1239
1240 pub(crate) fn is_connected_with_browsing_context(&self) -> bool {
1241 self.is_connected() && self.owner_doc().browsing_context().is_some()
1242 }
1243
1244 pub(crate) fn children(&self) -> impl Iterator<Item = DomRoot<Node>> + use<> {
1245 SimpleNodeIterator {
1246 current: self.GetFirstChild(),
1247 next_node: |n| n.GetNextSibling(),
1248 }
1249 }
1250
1251 pub(crate) fn rev_children(&self) -> impl Iterator<Item = DomRoot<Node>> + use<> {
1252 SimpleNodeIterator {
1253 current: self.GetLastChild(),
1254 next_node: |n| n.GetPreviousSibling(),
1255 }
1256 }
1257
1258 pub(crate) fn child_elements(&self) -> impl Iterator<Item = DomRoot<Element>> + use<> {
1259 self.children()
1260 .filter_map(DomRoot::downcast as fn(_) -> _)
1261 .peekable()
1262 }
1263
1264 pub(crate) fn remove_self(&self, can_gc: CanGc) {
1265 if let Some(ref parent) = self.GetParentNode() {
1266 Node::remove(self, parent, SuppressObserver::Unsuppressed, can_gc);
1267 }
1268 }
1269
1270 pub(crate) fn unique_id(&self, pipeline: PipelineId) -> String {
1271 let mut rare_data = self.ensure_rare_data();
1272
1273 if rare_data.unique_id.is_none() {
1274 let node_id = UniqueId::new();
1275 ScriptThread::save_node_id(pipeline, node_id.borrow().simple().to_string());
1276 rare_data.unique_id = Some(node_id);
1277 }
1278 rare_data
1279 .unique_id
1280 .as_ref()
1281 .unwrap()
1282 .borrow()
1283 .simple()
1284 .to_string()
1285 }
1286
1287 pub(crate) fn summarize(&self, can_gc: CanGc) -> NodeInfo {
1288 let USVString(base_uri) = self.BaseURI();
1289 let node_type = self.NodeType();
1290 let pipeline = self.owner_window().pipeline_id();
1291
1292 let maybe_shadow_root = self.downcast::<ShadowRoot>();
1293 let shadow_root_mode = maybe_shadow_root
1294 .map(ShadowRoot::Mode)
1295 .map(ShadowRootMode::convert);
1296 let host = maybe_shadow_root
1297 .map(ShadowRoot::Host)
1298 .map(|host| host.upcast::<Node>().unique_id(pipeline));
1299 let is_shadow_host = self.downcast::<Element>().is_some_and(|potential_host| {
1300 let Some(root) = potential_host.shadow_root() else {
1301 return false;
1302 };
1303 !root.is_user_agent_widget() || pref!(inspector_show_servo_internal_shadow_roots)
1304 });
1305
1306 let num_children = if is_shadow_host {
1307 self.ChildNodes(can_gc).Length() as usize + 1
1309 } else {
1310 self.ChildNodes(can_gc).Length() as usize
1311 };
1312
1313 let window = self.owner_window();
1314 let display = self
1315 .downcast::<Element>()
1316 .map(|elem| window.GetComputedStyle(elem, None))
1317 .map(|style| style.Display().into());
1318
1319 NodeInfo {
1320 unique_id: self.unique_id(pipeline),
1321 host,
1322 base_uri,
1323 parent: self
1324 .GetParentNode()
1325 .map_or("".to_owned(), |node| node.unique_id(pipeline)),
1326 node_type,
1327 is_top_level_document: node_type == NodeConstants::DOCUMENT_NODE,
1328 node_name: String::from(self.NodeName()),
1329 node_value: self.GetNodeValue().map(|v| v.into()),
1330 num_children,
1331 attrs: self.downcast().map(Element::summarize).unwrap_or(vec![]),
1332 is_shadow_host,
1333 shadow_root_mode,
1334 display,
1335 is_displayed: !self.is_display_none() || self.is::<DocumentType>(),
1339 doctype_name: self
1340 .downcast::<DocumentType>()
1341 .map(DocumentType::name)
1342 .cloned()
1343 .map(String::from),
1344 doctype_public_identifier: self
1345 .downcast::<DocumentType>()
1346 .map(DocumentType::public_id)
1347 .cloned()
1348 .map(String::from),
1349 doctype_system_identifier: self
1350 .downcast::<DocumentType>()
1351 .map(DocumentType::system_id)
1352 .cloned()
1353 .map(String::from),
1354 }
1355 }
1356
1357 pub(crate) fn insert_cell_or_row<F, G, I>(
1359 &self,
1360 index: i32,
1361 get_items: F,
1362 new_child: G,
1363 can_gc: CanGc,
1364 ) -> Fallible<DomRoot<HTMLElement>>
1365 where
1366 F: Fn() -> DomRoot<HTMLCollection>,
1367 G: Fn() -> DomRoot<I>,
1368 I: DerivedFrom<Node> + DerivedFrom<HTMLElement> + DomObject,
1369 {
1370 if index < -1 {
1371 return Err(Error::IndexSize);
1372 }
1373
1374 let tr = new_child();
1375
1376 {
1377 let tr_node = tr.upcast::<Node>();
1378 if index == -1 {
1379 self.InsertBefore(tr_node, None, can_gc)?;
1380 } else {
1381 let items = get_items();
1382 let node = match items
1383 .elements_iter()
1384 .map(DomRoot::upcast::<Node>)
1385 .map(Some)
1386 .chain(iter::once(None))
1387 .nth(index as usize)
1388 {
1389 None => return Err(Error::IndexSize),
1390 Some(node) => node,
1391 };
1392 self.InsertBefore(tr_node, node.as_deref(), can_gc)?;
1393 }
1394 }
1395
1396 Ok(DomRoot::upcast::<HTMLElement>(tr))
1397 }
1398
1399 pub(crate) fn delete_cell_or_row<F, G>(
1401 &self,
1402 index: i32,
1403 get_items: F,
1404 is_delete_type: G,
1405 can_gc: CanGc,
1406 ) -> ErrorResult
1407 where
1408 F: Fn() -> DomRoot<HTMLCollection>,
1409 G: Fn(&Element) -> bool,
1410 {
1411 let element = match index {
1412 index if index < -1 => return Err(Error::IndexSize),
1413 -1 => {
1414 let last_child = self.upcast::<Node>().GetLastChild();
1415 match last_child.and_then(|node| {
1416 node.inclusively_preceding_siblings()
1417 .filter_map(DomRoot::downcast::<Element>)
1418 .find(|elem| is_delete_type(elem))
1419 }) {
1420 Some(element) => element,
1421 None => return Ok(()),
1422 }
1423 },
1424 index => match get_items().Item(index as u32) {
1425 Some(element) => element,
1426 None => return Err(Error::IndexSize),
1427 },
1428 };
1429
1430 element.upcast::<Node>().remove_self(can_gc);
1431 Ok(())
1432 }
1433
1434 pub(crate) fn get_stylesheet(&self) -> Option<Arc<Stylesheet>> {
1435 if let Some(node) = self.downcast::<HTMLStyleElement>() {
1436 node.get_stylesheet()
1437 } else if let Some(node) = self.downcast::<HTMLLinkElement>() {
1438 node.get_stylesheet()
1439 } else {
1440 None
1441 }
1442 }
1443
1444 pub(crate) fn get_cssom_stylesheet(&self) -> Option<DomRoot<CSSStyleSheet>> {
1445 if let Some(node) = self.downcast::<HTMLStyleElement>() {
1446 node.get_cssom_stylesheet()
1447 } else if let Some(node) = self.downcast::<HTMLLinkElement>() {
1448 node.get_cssom_stylesheet(CanGc::note())
1449 } else {
1450 None
1451 }
1452 }
1453
1454 pub(crate) fn is_styled(&self) -> bool {
1455 self.style_data.borrow().is_some()
1456 }
1457
1458 pub(crate) fn is_display_none(&self) -> bool {
1459 self.style_data.borrow().as_ref().is_none_or(|data| {
1460 data.element_data
1461 .borrow()
1462 .styles
1463 .primary()
1464 .get_box()
1465 .display
1466 .is_none()
1467 })
1468 }
1469
1470 pub(crate) fn style(&self) -> Option<Arc<ComputedValues>> {
1471 self.owner_window().layout_reflow(QueryMsg::StyleQuery);
1472 self.style_data
1473 .borrow()
1474 .as_ref()
1475 .map(|data| data.element_data.borrow().styles.primary().clone())
1476 }
1477
1478 pub(crate) fn get_lang(&self) -> Option<String> {
1480 self.inclusive_ancestors(ShadowIncluding::Yes)
1481 .filter_map(|node| {
1482 node.downcast::<Element>().and_then(|el| {
1483 el.get_attribute(&ns!(xml), &local_name!("lang"))
1484 .or_else(|| el.get_attribute(&ns!(), &local_name!("lang")))
1485 .map(|attr| String::from(attr.Value()))
1486 })
1487 })
1490 .next()
1491 }
1492
1493 pub(crate) fn assign_slottables_for_a_tree(&self) {
1495 let Some(shadow_root) = self.downcast::<ShadowRoot>() else {
1499 return;
1500 };
1501
1502 if !shadow_root.has_slot_descendants() {
1503 return;
1504 }
1505
1506 for node in self.traverse_preorder(ShadowIncluding::No) {
1509 if let Some(slot) = node.downcast::<HTMLSlotElement>() {
1510 slot.assign_slottables();
1511 }
1512 }
1513 }
1514
1515 pub(crate) fn assigned_slot(&self) -> Option<DomRoot<HTMLSlotElement>> {
1516 let assigned_slot = self
1517 .rare_data
1518 .borrow()
1519 .as_ref()?
1520 .slottable_data
1521 .assigned_slot
1522 .as_ref()?
1523 .as_rooted();
1524 Some(assigned_slot)
1525 }
1526
1527 pub(crate) fn set_assigned_slot(&self, assigned_slot: Option<&HTMLSlotElement>) {
1528 self.ensure_rare_data().slottable_data.assigned_slot = assigned_slot.map(Dom::from_ref);
1529 }
1530
1531 pub(crate) fn manual_slot_assignment(&self) -> Option<DomRoot<HTMLSlotElement>> {
1532 let manually_assigned_slot = self
1533 .rare_data
1534 .borrow()
1535 .as_ref()?
1536 .slottable_data
1537 .manual_slot_assignment
1538 .as_ref()?
1539 .as_rooted();
1540 Some(manually_assigned_slot)
1541 }
1542
1543 pub(crate) fn set_manual_slot_assignment(
1544 &self,
1545 manually_assigned_slot: Option<&HTMLSlotElement>,
1546 ) {
1547 self.ensure_rare_data()
1548 .slottable_data
1549 .manual_slot_assignment = manually_assigned_slot.map(Dom::from_ref);
1550 }
1551
1552 pub(crate) fn parent_in_flat_tree(&self) -> Option<DomRoot<Node>> {
1558 if let Some(assigned_slot) = self.assigned_slot() {
1559 return Some(DomRoot::upcast(assigned_slot));
1560 }
1561
1562 let parent_or_none = self.GetParentNode();
1563 if let Some(parent) = parent_or_none.as_deref() {
1564 if let Some(shadow_root) = parent.downcast::<ShadowRoot>() {
1565 return Some(DomRoot::from_ref(shadow_root.Host().upcast::<Node>()));
1566 }
1567 }
1568
1569 parent_or_none
1570 }
1571
1572 pub(crate) fn inclusive_ancestors_in_flat_tree(
1573 &self,
1574 ) -> impl Iterator<Item = DomRoot<Node>> + use<> {
1575 SimpleNodeIterator {
1576 current: Some(DomRoot::from_ref(self)),
1577 next_node: move |n| n.parent_in_flat_tree(),
1578 }
1579 }
1580
1581 pub(crate) fn set_implemented_pseudo_element(&self, pseudo_element: PseudoElement) {
1583 debug_assert!(self.is_in_ua_widget());
1585 self.ensure_rare_data().implemented_pseudo_element = Some(pseudo_element);
1586 }
1587
1588 pub(crate) fn implemented_pseudo_element(&self) -> Option<PseudoElement> {
1589 self.rare_data
1590 .borrow()
1591 .as_ref()
1592 .and_then(|rare_data| rare_data.implemented_pseudo_element)
1593 }
1594}
1595
1596fn first_node_not_in<I>(mut nodes: I, not_in: &[NodeOrString]) -> Option<DomRoot<Node>>
1598where
1599 I: Iterator<Item = DomRoot<Node>>,
1600{
1601 nodes.find(|node| {
1602 not_in.iter().all(|n| match *n {
1603 NodeOrString::Node(ref n) => n != node,
1604 _ => true,
1605 })
1606 })
1607}
1608
1609#[allow(unsafe_code)]
1612pub(crate) unsafe fn from_untrusted_node_address(candidate: UntrustedNodeAddress) -> DomRoot<Node> {
1613 let node = unsafe { Node::from_untrusted_node_address(candidate) };
1614 DomRoot::from_ref(node)
1615}
1616
1617#[allow(unsafe_code)]
1618pub(crate) trait LayoutNodeHelpers<'dom> {
1619 fn type_id_for_layout(self) -> NodeTypeId;
1620
1621 fn parent_node_ref(self) -> Option<LayoutDom<'dom, Node>>;
1622 fn composed_parent_node_ref(self) -> Option<LayoutDom<'dom, Node>>;
1623 fn first_child_ref(self) -> Option<LayoutDom<'dom, Node>>;
1624 fn last_child_ref(self) -> Option<LayoutDom<'dom, Node>>;
1625 fn prev_sibling_ref(self) -> Option<LayoutDom<'dom, Node>>;
1626 fn next_sibling_ref(self) -> Option<LayoutDom<'dom, Node>>;
1627
1628 fn owner_doc_for_layout(self) -> LayoutDom<'dom, Document>;
1629 fn containing_shadow_root_for_layout(self) -> Option<LayoutDom<'dom, ShadowRoot>>;
1630 fn assigned_slot_for_layout(self) -> Option<LayoutDom<'dom, HTMLSlotElement>>;
1631
1632 fn is_element_for_layout(&self) -> bool;
1633 fn is_text_node_for_layout(&self) -> bool;
1634 unsafe fn get_flag(self, flag: NodeFlags) -> bool;
1635 unsafe fn set_flag(self, flag: NodeFlags, value: bool);
1636
1637 fn style_data(self) -> Option<&'dom StyleData>;
1638 fn layout_data(self) -> Option<&'dom GenericLayoutData>;
1639
1640 unsafe fn initialize_style_data(self);
1648
1649 unsafe fn initialize_layout_data(self, data: Box<GenericLayoutData>);
1657
1658 unsafe fn clear_style_and_layout_data(self);
1666
1667 fn is_text_input(&self) -> bool;
1673
1674 fn is_single_line_text_inner_editor(&self) -> bool;
1677
1678 fn is_text_container_of_single_line_input(&self) -> bool;
1681 fn text_content(self) -> Cow<'dom, str>;
1682 fn selection(self) -> Option<Range<usize>>;
1683 fn image_url(self) -> Option<ServoUrl>;
1684 fn image_density(self) -> Option<f64>;
1685 fn image_data(self) -> Option<(Option<Image>, Option<ImageMetadata>)>;
1686 fn canvas_data(self) -> Option<HTMLCanvasData>;
1687 fn media_data(self) -> Option<HTMLMediaData>;
1688 fn svg_data(self) -> Option<SVGElementData>;
1689 fn iframe_browsing_context_id(self) -> Option<BrowsingContextId>;
1690 fn iframe_pipeline_id(self) -> Option<PipelineId>;
1691 fn opaque(self) -> OpaqueNode;
1692 fn implemented_pseudo_element(&self) -> Option<PseudoElement>;
1693 fn is_in_ua_widget(&self) -> bool;
1694}
1695
1696impl<'dom> LayoutDom<'dom, Node> {
1697 #[inline]
1698 #[allow(unsafe_code)]
1699 pub(crate) fn parent_node_ref(self) -> Option<LayoutDom<'dom, Node>> {
1700 unsafe { self.unsafe_get().parent_node.get_inner_as_layout() }
1701 }
1702}
1703
1704impl<'dom> LayoutNodeHelpers<'dom> for LayoutDom<'dom, Node> {
1705 #[inline]
1706 fn type_id_for_layout(self) -> NodeTypeId {
1707 self.unsafe_get().type_id()
1708 }
1709
1710 #[inline]
1711 fn is_element_for_layout(&self) -> bool {
1712 (*self).is::<Element>()
1713 }
1714
1715 fn is_text_node_for_layout(&self) -> bool {
1716 self.type_id_for_layout() ==
1717 NodeTypeId::CharacterData(CharacterDataTypeId::Text(TextTypeId::Text))
1718 }
1719
1720 #[inline]
1721 #[allow(unsafe_code)]
1722 fn parent_node_ref(self) -> Option<LayoutDom<'dom, Node>> {
1723 unsafe { self.unsafe_get().parent_node.get_inner_as_layout() }
1724 }
1725
1726 #[inline]
1727 fn composed_parent_node_ref(self) -> Option<LayoutDom<'dom, Node>> {
1728 let parent = self.parent_node_ref();
1729 if let Some(parent) = parent {
1730 if let Some(shadow_root) = parent.downcast::<ShadowRoot>() {
1731 return Some(shadow_root.get_host_for_layout().upcast());
1732 }
1733 }
1734 parent
1735 }
1736
1737 #[inline]
1738 #[allow(unsafe_code)]
1739 fn first_child_ref(self) -> Option<LayoutDom<'dom, Node>> {
1740 unsafe { self.unsafe_get().first_child.get_inner_as_layout() }
1741 }
1742
1743 #[inline]
1744 #[allow(unsafe_code)]
1745 fn last_child_ref(self) -> Option<LayoutDom<'dom, Node>> {
1746 unsafe { self.unsafe_get().last_child.get_inner_as_layout() }
1747 }
1748
1749 #[inline]
1750 #[allow(unsafe_code)]
1751 fn prev_sibling_ref(self) -> Option<LayoutDom<'dom, Node>> {
1752 unsafe { self.unsafe_get().prev_sibling.get_inner_as_layout() }
1753 }
1754
1755 #[inline]
1756 #[allow(unsafe_code)]
1757 fn next_sibling_ref(self) -> Option<LayoutDom<'dom, Node>> {
1758 unsafe { self.unsafe_get().next_sibling.get_inner_as_layout() }
1759 }
1760
1761 #[inline]
1762 #[allow(unsafe_code)]
1763 fn owner_doc_for_layout(self) -> LayoutDom<'dom, Document> {
1764 unsafe { self.unsafe_get().owner_doc.get_inner_as_layout().unwrap() }
1765 }
1766
1767 #[inline]
1768 #[allow(unsafe_code)]
1769 fn containing_shadow_root_for_layout(self) -> Option<LayoutDom<'dom, ShadowRoot>> {
1770 unsafe {
1771 self.unsafe_get()
1772 .rare_data
1773 .borrow_for_layout()
1774 .as_ref()?
1775 .containing_shadow_root
1776 .as_ref()
1777 .map(|sr| sr.to_layout())
1778 }
1779 }
1780
1781 #[inline]
1782 #[allow(unsafe_code)]
1783 fn assigned_slot_for_layout(self) -> Option<LayoutDom<'dom, HTMLSlotElement>> {
1784 unsafe {
1785 self.unsafe_get()
1786 .rare_data
1787 .borrow_for_layout()
1788 .as_ref()?
1789 .slottable_data
1790 .assigned_slot
1791 .as_ref()
1792 .map(|assigned_slot| assigned_slot.to_layout())
1793 }
1794 }
1795
1796 #[inline]
1801 #[allow(unsafe_code)]
1802 unsafe fn get_flag(self, flag: NodeFlags) -> bool {
1803 (self.unsafe_get()).flags.get().contains(flag)
1804 }
1805
1806 #[inline]
1807 #[allow(unsafe_code)]
1808 unsafe fn set_flag(self, flag: NodeFlags, value: bool) {
1809 let this = self.unsafe_get();
1810 let mut flags = (this).flags.get();
1811
1812 if value {
1813 flags.insert(flag);
1814 } else {
1815 flags.remove(flag);
1816 }
1817
1818 (this).flags.set(flags);
1819 }
1820
1821 #[inline]
1824 #[allow(unsafe_code)]
1825 fn style_data(self) -> Option<&'dom StyleData> {
1826 unsafe { self.unsafe_get().style_data.borrow_for_layout().as_deref() }
1827 }
1828
1829 #[inline]
1830 #[allow(unsafe_code)]
1831 fn layout_data(self) -> Option<&'dom GenericLayoutData> {
1832 unsafe { self.unsafe_get().layout_data.borrow_for_layout().as_deref() }
1833 }
1834
1835 #[inline]
1836 #[allow(unsafe_code)]
1837 unsafe fn initialize_style_data(self) {
1838 let data = unsafe { self.unsafe_get().style_data.borrow_mut_for_layout() };
1839 debug_assert!(data.is_none());
1840 *data = Some(Box::default());
1841 }
1842
1843 #[inline]
1844 #[allow(unsafe_code)]
1845 unsafe fn initialize_layout_data(self, new_data: Box<GenericLayoutData>) {
1846 let data = unsafe { self.unsafe_get().layout_data.borrow_mut_for_layout() };
1847 debug_assert!(data.is_none());
1848 *data = Some(new_data);
1849 }
1850
1851 #[inline]
1852 #[allow(unsafe_code)]
1853 unsafe fn clear_style_and_layout_data(self) {
1854 unsafe {
1855 self.unsafe_get().style_data.borrow_mut_for_layout().take();
1856 self.unsafe_get().layout_data.borrow_mut_for_layout().take();
1857 }
1858 }
1859
1860 fn is_text_input(&self) -> bool {
1864 let type_id = self.type_id_for_layout();
1865 if type_id ==
1866 NodeTypeId::Element(ElementTypeId::HTMLElement(
1867 HTMLElementTypeId::HTMLInputElement,
1868 ))
1869 {
1870 let input = self.unsafe_get().downcast::<HTMLInputElement>().unwrap();
1871
1872 !input.is_textual_widget() && input.input_type() != InputType::Color
1873 } else {
1874 type_id ==
1875 NodeTypeId::Element(ElementTypeId::HTMLElement(
1876 HTMLElementTypeId::HTMLTextAreaElement,
1877 ))
1878 }
1879 }
1880
1881 fn is_single_line_text_inner_editor(&self) -> bool {
1882 matches!(
1883 self.unsafe_get().implemented_pseudo_element(),
1884 Some(PseudoElement::ServoTextControlInnerEditor)
1885 )
1886 }
1887
1888 fn is_text_container_of_single_line_input(&self) -> bool {
1889 let is_single_line_text_inner_placeholder = matches!(
1890 self.unsafe_get().implemented_pseudo_element(),
1891 Some(PseudoElement::Placeholder)
1892 );
1893 debug_assert!(
1895 !is_single_line_text_inner_placeholder ||
1896 self.containing_shadow_root_for_layout()
1897 .map(|root| root.get_host_for_layout())
1898 .map(|host| host.downcast::<HTMLInputElement>())
1899 .is_some()
1900 );
1901
1902 self.is_single_line_text_inner_editor() || is_single_line_text_inner_placeholder
1903 }
1904
1905 fn text_content(self) -> Cow<'dom, str> {
1906 if let Some(text) = self.downcast::<Text>() {
1907 return text.upcast().data_for_layout().into();
1908 }
1909
1910 if let Some(input) = self.downcast::<HTMLInputElement>() {
1911 return input.value_for_layout();
1912 }
1913
1914 if let Some(area) = self.downcast::<HTMLTextAreaElement>() {
1915 return area.value_for_layout().into();
1916 }
1917
1918 panic!("not text!")
1919 }
1920
1921 fn selection(self) -> Option<Range<usize>> {
1922 if self.is_in_ua_widget() &&
1927 self.is_text_node_for_layout() &&
1928 self.parent_node_ref()
1929 .is_some_and(|parent| parent.is_single_line_text_inner_editor())
1930 {
1931 let shadow_root = self.containing_shadow_root_for_layout();
1932 if let Some(containing_shadow_host) = shadow_root.map(|root| root.get_host_for_layout())
1933 {
1934 if let Some(input) = containing_shadow_host.downcast::<HTMLInputElement>() {
1935 return input.selection_for_layout();
1936 }
1937 }
1938 }
1939
1940 if let Some(area) = self.downcast::<HTMLTextAreaElement>() {
1941 return area.selection_for_layout();
1942 }
1943
1944 if let Some(input) = self.downcast::<HTMLInputElement>() {
1945 return input.selection_for_layout();
1946 }
1947
1948 None
1949 }
1950
1951 fn image_url(self) -> Option<ServoUrl> {
1952 self.downcast::<HTMLImageElement>()
1953 .expect("not an image!")
1954 .image_url()
1955 }
1956
1957 fn image_data(self) -> Option<(Option<Image>, Option<ImageMetadata>)> {
1958 self.downcast::<HTMLImageElement>().map(|e| e.image_data())
1959 }
1960
1961 fn image_density(self) -> Option<f64> {
1962 self.downcast::<HTMLImageElement>()
1963 .expect("not an image!")
1964 .image_density()
1965 }
1966
1967 fn canvas_data(self) -> Option<HTMLCanvasData> {
1968 self.downcast::<HTMLCanvasElement>()
1969 .map(|canvas| canvas.data())
1970 }
1971
1972 fn media_data(self) -> Option<HTMLMediaData> {
1973 self.downcast::<HTMLVideoElement>()
1974 .map(|media| media.data())
1975 }
1976
1977 fn svg_data(self) -> Option<SVGElementData> {
1978 self.downcast::<SVGSVGElement>().map(|svg| svg.data())
1979 }
1980
1981 fn iframe_browsing_context_id(self) -> Option<BrowsingContextId> {
1982 self.downcast::<HTMLIFrameElement>()
1983 .and_then(|iframe_element| iframe_element.browsing_context_id())
1984 }
1985
1986 fn iframe_pipeline_id(self) -> Option<PipelineId> {
1987 self.downcast::<HTMLIFrameElement>()
1988 .and_then(|iframe_element| iframe_element.pipeline_id())
1989 }
1990
1991 #[allow(unsafe_code)]
1992 fn opaque(self) -> OpaqueNode {
1993 unsafe { OpaqueNode(self.get_jsobject() as usize) }
1994 }
1995
1996 fn implemented_pseudo_element(&self) -> Option<PseudoElement> {
1997 self.unsafe_get().implemented_pseudo_element()
1998 }
1999
2000 fn is_in_ua_widget(&self) -> bool {
2001 self.unsafe_get().is_in_ua_widget()
2002 }
2003}
2004
2005pub(crate) struct FollowingNodeIterator {
2010 current: Option<DomRoot<Node>>,
2011 root: DomRoot<Node>,
2012}
2013
2014impl FollowingNodeIterator {
2015 pub(crate) fn next_skipping_children(&mut self) -> Option<DomRoot<Node>> {
2017 let current = self.current.take()?;
2018 self.next_skipping_children_impl(current)
2019 }
2020
2021 fn next_skipping_children_impl(&mut self, current: DomRoot<Node>) -> Option<DomRoot<Node>> {
2022 if self.root == current {
2023 self.current = None;
2024 return None;
2025 }
2026
2027 if let Some(next_sibling) = current.GetNextSibling() {
2028 self.current = Some(next_sibling);
2029 return current.GetNextSibling();
2030 }
2031
2032 for ancestor in current.inclusive_ancestors(ShadowIncluding::No) {
2033 if self.root == ancestor {
2034 break;
2035 }
2036 if let Some(next_sibling) = ancestor.GetNextSibling() {
2037 self.current = Some(next_sibling);
2038 return ancestor.GetNextSibling();
2039 }
2040 }
2041 self.current = None;
2042 None
2043 }
2044}
2045
2046impl Iterator for FollowingNodeIterator {
2047 type Item = DomRoot<Node>;
2048
2049 fn next(&mut self) -> Option<DomRoot<Node>> {
2051 let current = self.current.take()?;
2052
2053 if let Some(first_child) = current.GetFirstChild() {
2054 self.current = Some(first_child);
2055 return current.GetFirstChild();
2056 }
2057
2058 self.next_skipping_children_impl(current)
2059 }
2060}
2061
2062pub(crate) struct PrecedingNodeIterator {
2063 current: Option<DomRoot<Node>>,
2064 root: DomRoot<Node>,
2065}
2066
2067impl Iterator for PrecedingNodeIterator {
2068 type Item = DomRoot<Node>;
2069
2070 fn next(&mut self) -> Option<DomRoot<Node>> {
2072 let current = self.current.take()?;
2073
2074 self.current = if self.root == current {
2075 None
2076 } else if let Some(previous_sibling) = current.GetPreviousSibling() {
2077 if self.root == previous_sibling {
2078 None
2079 } else if let Some(last_child) = previous_sibling.descending_last_children().last() {
2080 Some(last_child)
2081 } else {
2082 Some(previous_sibling)
2083 }
2084 } else {
2085 current.GetParentNode()
2086 };
2087 self.current.clone()
2088 }
2089}
2090
2091struct SimpleNodeIterator<I>
2092where
2093 I: Fn(&Node) -> Option<DomRoot<Node>>,
2094{
2095 current: Option<DomRoot<Node>>,
2096 next_node: I,
2097}
2098
2099impl<I> Iterator for SimpleNodeIterator<I>
2100where
2101 I: Fn(&Node) -> Option<DomRoot<Node>>,
2102{
2103 type Item = DomRoot<Node>;
2104
2105 fn next(&mut self) -> Option<Self::Item> {
2106 let current = self.current.take();
2107 self.current = current.as_ref().and_then(|c| (self.next_node)(c));
2108 current
2109 }
2110}
2111
2112#[derive(Clone, Copy, PartialEq)]
2114pub(crate) enum ShadowIncluding {
2115 No,
2116 Yes,
2117}
2118
2119pub(crate) struct TreeIterator {
2120 current: Option<DomRoot<Node>>,
2121 depth: usize,
2122 shadow_including: bool,
2123}
2124
2125impl TreeIterator {
2126 fn new(root: &Node, shadow_including: ShadowIncluding) -> TreeIterator {
2127 TreeIterator {
2128 current: Some(DomRoot::from_ref(root)),
2129 depth: 0,
2130 shadow_including: shadow_including == ShadowIncluding::Yes,
2131 }
2132 }
2133
2134 pub(crate) fn next_skipping_children(&mut self) -> Option<DomRoot<Node>> {
2135 let current = self.current.take()?;
2136
2137 self.next_skipping_children_impl(current)
2138 }
2139
2140 fn next_skipping_children_impl(&mut self, current: DomRoot<Node>) -> Option<DomRoot<Node>> {
2141 let iter = current.inclusive_ancestors(if self.shadow_including {
2142 ShadowIncluding::Yes
2143 } else {
2144 ShadowIncluding::No
2145 });
2146
2147 for ancestor in iter {
2148 if self.depth == 0 {
2149 break;
2150 }
2151 if let Some(next_sibling) = ancestor.GetNextSibling() {
2152 self.current = Some(next_sibling);
2153 return Some(current);
2154 }
2155 if let Some(shadow_root) = ancestor.downcast::<ShadowRoot>() {
2156 if let Some(child) = shadow_root.Host().upcast::<Node>().GetFirstChild() {
2159 self.current = Some(child);
2160 return Some(current);
2161 }
2162 }
2163 self.depth -= 1;
2164 }
2165 debug_assert_eq!(self.depth, 0);
2166 self.current = None;
2167 Some(current)
2168 }
2169
2170 pub(crate) fn peek(&self) -> Option<&DomRoot<Node>> {
2171 self.current.as_ref()
2172 }
2173}
2174
2175impl Iterator for TreeIterator {
2176 type Item = DomRoot<Node>;
2177
2178 fn next(&mut self) -> Option<DomRoot<Node>> {
2181 let current = self.current.take()?;
2182
2183 if let Some(element) = current.downcast::<Element>() {
2185 if let Some(shadow_root) = element.shadow_root() {
2186 if self.shadow_including {
2187 self.current = Some(DomRoot::from_ref(shadow_root.upcast::<Node>()));
2188 self.depth += 1;
2189 return Some(current);
2190 }
2191 }
2192 }
2193
2194 if let Some(first_child) = current.GetFirstChild() {
2195 self.current = Some(first_child);
2196 self.depth += 1;
2197 return Some(current);
2198 };
2199
2200 self.next_skipping_children_impl(current)
2201 }
2202}
2203
2204#[derive(Clone, Copy, MallocSizeOf, PartialEq)]
2206pub(crate) enum CloneChildrenFlag {
2207 CloneChildren,
2208 DoNotCloneChildren,
2209}
2210
2211fn as_uintptr<T>(t: &T) -> uintptr_t {
2212 t as *const T as uintptr_t
2213}
2214
2215impl Node {
2216 pub(crate) fn reflect_node<N>(node: Box<N>, document: &Document, can_gc: CanGc) -> DomRoot<N>
2217 where
2218 N: DerivedFrom<Node> + DomObject + DomObjectWrap<crate::DomTypeHolder>,
2219 {
2220 Self::reflect_node_with_proto(node, document, None, can_gc)
2221 }
2222
2223 pub(crate) fn reflect_node_with_proto<N>(
2224 node: Box<N>,
2225 document: &Document,
2226 proto: Option<HandleObject>,
2227 can_gc: CanGc,
2228 ) -> DomRoot<N>
2229 where
2230 N: DerivedFrom<Node> + DomObject + DomObjectWrap<crate::DomTypeHolder>,
2231 {
2232 let window = document.window();
2233 reflect_dom_object_with_proto(node, window, proto, can_gc)
2234 }
2235
2236 pub(crate) fn new_inherited(doc: &Document) -> Node {
2237 Node::new_(NodeFlags::empty(), Some(doc))
2238 }
2239
2240 #[cfg_attr(crown, allow(crown::unrooted_must_root))]
2241 pub(crate) fn new_document_node() -> Node {
2242 Node::new_(
2243 NodeFlags::IS_IN_A_DOCUMENT_TREE | NodeFlags::IS_CONNECTED,
2244 None,
2245 )
2246 }
2247
2248 #[cfg_attr(crown, allow(crown::unrooted_must_root))]
2249 fn new_(flags: NodeFlags, doc: Option<&Document>) -> Node {
2250 Node {
2251 eventtarget: EventTarget::new_inherited(),
2252
2253 parent_node: Default::default(),
2254 first_child: Default::default(),
2255 last_child: Default::default(),
2256 next_sibling: Default::default(),
2257 prev_sibling: Default::default(),
2258 owner_doc: MutNullableDom::new(doc),
2259 rare_data: Default::default(),
2260 children_count: Cell::new(0u32),
2261 flags: Cell::new(flags),
2262 inclusive_descendants_version: Cell::new(0),
2263 style_data: Default::default(),
2264 layout_data: Default::default(),
2265 }
2266 }
2267
2268 pub(crate) fn adopt(node: &Node, document: &Document, can_gc: CanGc) {
2270 document.add_script_and_layout_blocker();
2271
2272 let old_doc = node.owner_doc();
2274 old_doc.add_script_and_layout_blocker();
2275
2276 node.remove_self(can_gc);
2278
2279 if &*old_doc != document {
2281 for descendant in node.traverse_preorder(ShadowIncluding::Yes) {
2283 descendant.set_owner_doc(document);
2285
2286 if let Some(element) = descendant.downcast::<Element>() {
2289 for attribute in element.attrs().iter() {
2290 attribute.upcast::<Node>().set_owner_doc(document);
2291 }
2292 }
2293 }
2294
2295 let custom_element_reaction_stack = ScriptThread::custom_element_reaction_stack();
2299 for descendant in node
2300 .traverse_preorder(ShadowIncluding::Yes)
2301 .filter_map(|d| d.as_custom_element())
2302 {
2303 custom_element_reaction_stack.enqueue_callback_reaction(
2304 &descendant,
2305 CallbackReaction::Adopted(old_doc.clone(), DomRoot::from_ref(document)),
2306 None,
2307 );
2308 }
2309
2310 for descendant in node.traverse_preorder(ShadowIncluding::Yes) {
2313 vtable_for(&descendant).adopting_steps(&old_doc, can_gc);
2314 }
2315 }
2316
2317 old_doc.remove_script_and_layout_blocker();
2318 document.remove_script_and_layout_blocker();
2319 }
2320
2321 pub(crate) fn ensure_pre_insertion_validity(
2323 node: &Node,
2324 parent: &Node,
2325 child: Option<&Node>,
2326 ) -> ErrorResult {
2327 match parent.type_id() {
2329 NodeTypeId::Document(_) | NodeTypeId::DocumentFragment(_) | NodeTypeId::Element(..) => {
2330 },
2331 _ => return Err(Error::HierarchyRequest),
2332 }
2333
2334 if node.is_inclusive_ancestor_of(parent) {
2336 return Err(Error::HierarchyRequest);
2337 }
2338
2339 if let Some(child) = child {
2341 if !parent.is_parent_of(child) {
2342 return Err(Error::NotFound(None));
2343 }
2344 }
2345
2346 match node.type_id() {
2348 NodeTypeId::CharacterData(CharacterDataTypeId::Text(_)) => {
2349 if parent.is::<Document>() {
2350 return Err(Error::HierarchyRequest);
2351 }
2352 },
2353 NodeTypeId::DocumentType => {
2354 if !parent.is::<Document>() {
2355 return Err(Error::HierarchyRequest);
2356 }
2357 },
2358 NodeTypeId::DocumentFragment(_) |
2359 NodeTypeId::Element(_) |
2360 NodeTypeId::CharacterData(CharacterDataTypeId::ProcessingInstruction) |
2361 NodeTypeId::CharacterData(CharacterDataTypeId::Comment) => (),
2362 NodeTypeId::Document(_) | NodeTypeId::Attr => return Err(Error::HierarchyRequest),
2363 }
2364
2365 if parent.is::<Document>() {
2367 match node.type_id() {
2368 NodeTypeId::DocumentFragment(_) => {
2370 if node.children().any(|c| c.is::<Text>()) {
2372 return Err(Error::HierarchyRequest);
2373 }
2374 match node.child_elements().count() {
2375 0 => (),
2376 1 => {
2378 if parent.child_elements().next().is_some() {
2379 return Err(Error::HierarchyRequest);
2380 }
2381 if let Some(child) = child {
2382 if child
2383 .inclusively_following_siblings()
2384 .any(|child| child.is_doctype())
2385 {
2386 return Err(Error::HierarchyRequest);
2387 }
2388 }
2389 },
2390 _ => return Err(Error::HierarchyRequest),
2392 }
2393 },
2394 NodeTypeId::Element(_) => {
2396 if parent.child_elements().next().is_some() {
2397 return Err(Error::HierarchyRequest);
2398 }
2399 if let Some(child) = child {
2400 if child
2401 .inclusively_following_siblings()
2402 .any(|child| child.is_doctype())
2403 {
2404 return Err(Error::HierarchyRequest);
2405 }
2406 }
2407 },
2408 NodeTypeId::DocumentType => {
2410 if parent.children().any(|c| c.is_doctype()) {
2411 return Err(Error::HierarchyRequest);
2412 }
2413 match child {
2414 Some(child) => {
2415 if parent
2416 .children()
2417 .take_while(|c| &**c != child)
2418 .any(|c| c.is::<Element>())
2419 {
2420 return Err(Error::HierarchyRequest);
2421 }
2422 },
2423 None => {
2424 if parent.child_elements().next().is_some() {
2425 return Err(Error::HierarchyRequest);
2426 }
2427 },
2428 }
2429 },
2430 NodeTypeId::CharacterData(_) => (),
2431 NodeTypeId::Document(_) | NodeTypeId::Attr => unreachable!(),
2434 }
2435 }
2436 Ok(())
2437 }
2438
2439 pub(crate) fn pre_insert(
2441 node: &Node,
2442 parent: &Node,
2443 child: Option<&Node>,
2444 can_gc: CanGc,
2445 ) -> Fallible<DomRoot<Node>> {
2446 Node::ensure_pre_insertion_validity(node, parent, child)?;
2448
2449 let reference_child_root;
2451 let reference_child = match child {
2452 Some(child) if child == node => {
2453 reference_child_root = node.GetNextSibling();
2454 reference_child_root.as_deref()
2455 },
2456 _ => child,
2457 };
2458
2459 Node::insert(
2461 node,
2462 parent,
2463 reference_child,
2464 SuppressObserver::Unsuppressed,
2465 can_gc,
2466 );
2467
2468 Ok(DomRoot::from_ref(node))
2470 }
2471
2472 fn insert(
2474 node: &Node,
2475 parent: &Node,
2476 child: Option<&Node>,
2477 suppress_observers: SuppressObserver,
2478 can_gc: CanGc,
2479 ) {
2480 debug_assert!(child.is_none_or(|child| Some(parent) == child.GetParentNode().as_deref()));
2481
2482 rooted_vec!(let mut new_nodes);
2484 let new_nodes = if let NodeTypeId::DocumentFragment(_) = node.type_id() {
2485 new_nodes.extend(node.children().map(|node| Dom::from_ref(&*node)));
2486 new_nodes.r()
2487 } else {
2488 from_ref(&node)
2489 };
2490
2491 let count = new_nodes.len();
2493
2494 if count == 0 {
2496 return;
2497 }
2498
2499 let parent_document = parent.owner_doc();
2502 let from_document = node.owner_doc();
2503 from_document.add_script_and_layout_blocker();
2504 parent_document.add_script_and_layout_blocker();
2505
2506 if let NodeTypeId::DocumentFragment(_) = node.type_id() {
2508 for kid in new_nodes {
2510 Node::remove(kid, node, SuppressObserver::Suppressed, can_gc);
2511 }
2512 vtable_for(node).children_changed(&ChildrenMutation::replace_all(new_nodes, &[]));
2513
2514 let mutation = LazyCell::new(|| Mutation::ChildList {
2516 added: None,
2517 removed: Some(new_nodes),
2518 prev: None,
2519 next: None,
2520 });
2521 MutationObserver::queue_a_mutation_record(node, mutation);
2522 }
2523
2524 if let Some(child) = child {
2530 if !parent.ranges_is_empty() {
2531 parent
2532 .ranges()
2533 .increase_above(parent, child.index(), count.try_into().unwrap());
2534 }
2535 }
2536
2537 let previous_sibling = match suppress_observers {
2539 SuppressObserver::Unsuppressed => match child {
2540 Some(child) => child.GetPreviousSibling(),
2541 None => parent.GetLastChild(),
2542 },
2543 SuppressObserver::Suppressed => None,
2544 };
2545
2546 let custom_element_reaction_stack = ScriptThread::custom_element_reaction_stack();
2547 for kid in new_nodes {
2549 Node::adopt(kid, &parent.owner_document(), can_gc);
2551
2552 parent.add_child(kid, child, can_gc);
2555
2556 if let Some(shadow_root) = parent.downcast::<Element>().and_then(Element::shadow_root) {
2559 if shadow_root.SlotAssignment() == SlotAssignmentMode::Named {
2560 let cx = GlobalScope::get_cx();
2561 if node.is::<Element>() || node.is::<Text>() {
2562 rooted!(in(*cx) let slottable = Slottable(Dom::from_ref(node)));
2563 slottable.assign_a_slot();
2564 }
2565 }
2566 }
2567
2568 if parent.is_in_a_shadow_tree() {
2571 if let Some(slot_element) = parent.downcast::<HTMLSlotElement>() {
2572 if !slot_element.has_assigned_nodes() {
2573 slot_element.signal_a_slot_change();
2574 }
2575 }
2576 }
2577
2578 kid.GetRootNode(&GetRootNodeOptions::empty())
2580 .assign_slottables_for_a_tree();
2581
2582 for descendant in kid
2585 .traverse_preorder(ShadowIncluding::Yes)
2586 .filter_map(DomRoot::downcast::<Element>)
2587 {
2588 if descendant.is_custom() {
2594 if descendant.is_connected() {
2595 custom_element_reaction_stack.enqueue_callback_reaction(
2596 &descendant,
2597 CallbackReaction::Connected,
2598 None,
2599 );
2600 }
2601 } else {
2602 try_upgrade_element(&descendant);
2603 }
2604 }
2605 }
2606
2607 if let SuppressObserver::Unsuppressed = suppress_observers {
2608 vtable_for(parent).children_changed(&ChildrenMutation::insert(
2611 previous_sibling.as_deref(),
2612 new_nodes,
2613 child,
2614 ));
2615
2616 let mutation = LazyCell::new(|| Mutation::ChildList {
2619 added: Some(new_nodes),
2620 removed: None,
2621 prev: previous_sibling.as_deref(),
2622 next: child,
2623 });
2624 MutationObserver::queue_a_mutation_record(parent, mutation);
2625 }
2626
2627 let mut static_node_list = vec![];
2629
2630 for node in new_nodes {
2632 static_node_list.extend(node.traverse_preorder(ShadowIncluding::Yes));
2635 }
2636
2637 parent_document.add_delayed_task(
2648 task!(PostConnectionSteps: |static_node_list: Vec<DomRoot<Node>>| {
2649 for node in static_node_list.iter().filter(|n| n.is_connected()) {
2652 vtable_for(node).post_connection_steps();
2653 }
2654 }),
2655 );
2656
2657 parent_document.remove_script_and_layout_blocker();
2658 from_document.remove_script_and_layout_blocker();
2659 }
2660
2661 pub(crate) fn replace_all(node: Option<&Node>, parent: &Node, can_gc: CanGc) {
2663 parent.owner_doc().add_script_and_layout_blocker();
2664 if let Some(node) = node {
2666 Node::adopt(node, &parent.owner_doc(), can_gc);
2667 }
2668 rooted_vec!(let removed_nodes <- parent.children().map(|c| DomRoot::as_traced(&c)));
2670 rooted_vec!(let mut added_nodes);
2672 let added_nodes = if let Some(node) = node.as_ref() {
2673 if let NodeTypeId::DocumentFragment(_) = node.type_id() {
2674 added_nodes.extend(node.children().map(|child| Dom::from_ref(&*child)));
2675 added_nodes.r()
2676 } else {
2677 from_ref(node)
2678 }
2679 } else {
2680 &[] as &[&Node]
2681 };
2682 for child in &*removed_nodes {
2684 Node::remove(child, parent, SuppressObserver::Suppressed, can_gc);
2685 }
2686 if let Some(node) = node {
2688 Node::insert(node, parent, None, SuppressObserver::Suppressed, can_gc);
2689 }
2690 vtable_for(parent).children_changed(&ChildrenMutation::replace_all(
2692 removed_nodes.r(),
2693 added_nodes,
2694 ));
2695
2696 if !removed_nodes.is_empty() || !added_nodes.is_empty() {
2697 let mutation = LazyCell::new(|| Mutation::ChildList {
2698 added: Some(added_nodes),
2699 removed: Some(removed_nodes.r()),
2700 prev: None,
2701 next: None,
2702 });
2703 MutationObserver::queue_a_mutation_record(parent, mutation);
2704 }
2705 parent.owner_doc().remove_script_and_layout_blocker();
2706 }
2707
2708 pub(crate) fn string_replace_all(string: DOMString, parent: &Node, can_gc: CanGc) {
2710 if string.is_empty() {
2711 Node::replace_all(None, parent, can_gc);
2712 } else {
2713 let text = Text::new(string, &parent.owner_document(), can_gc);
2714 Node::replace_all(Some(text.upcast::<Node>()), parent, can_gc);
2715 };
2716 }
2717
2718 fn pre_remove(child: &Node, parent: &Node, can_gc: CanGc) -> Fallible<DomRoot<Node>> {
2720 match child.GetParentNode() {
2722 Some(ref node) if &**node != parent => return Err(Error::NotFound(None)),
2723 None => return Err(Error::NotFound(None)),
2724 _ => (),
2725 }
2726
2727 Node::remove(child, parent, SuppressObserver::Unsuppressed, can_gc);
2729
2730 Ok(DomRoot::from_ref(child))
2732 }
2733
2734 fn remove(node: &Node, parent: &Node, suppress_observers: SuppressObserver, can_gc: CanGc) {
2736 parent.owner_doc().add_script_and_layout_blocker();
2737
2738 assert!(
2742 node.GetParentNode()
2743 .is_some_and(|node_parent| &*node_parent == parent)
2744 );
2745
2746 let cached_index = {
2749 if parent.ranges_is_empty() {
2750 None
2751 } else {
2752 let index = node.index();
2758
2759 parent.ranges().decrease_above(parent, index, 1);
2766
2767 Some(index)
2771 }
2772 };
2773
2774 let old_previous_sibling = node.GetPreviousSibling();
2778
2779 let old_next_sibling = node.GetNextSibling();
2781
2782 parent.remove_child(node, cached_index, can_gc);
2785
2786 if let Some(slot) = node.assigned_slot() {
2788 slot.assign_slottables();
2789 }
2790
2791 if parent.is_in_a_shadow_tree() {
2794 if let Some(slot_element) = parent.downcast::<HTMLSlotElement>() {
2795 if !slot_element.has_assigned_nodes() {
2796 slot_element.signal_a_slot_change();
2797 }
2798 }
2799 }
2800
2801 let has_slot_descendant = node
2803 .traverse_preorder(ShadowIncluding::No)
2804 .any(|elem| elem.is::<HTMLSlotElement>());
2805 if has_slot_descendant {
2806 parent
2808 .GetRootNode(&GetRootNodeOptions::empty())
2809 .assign_slottables_for_a_tree();
2810
2811 node.assign_slottables_for_a_tree();
2813 }
2814
2815 if let SuppressObserver::Unsuppressed = suppress_observers {
2819 vtable_for(parent).children_changed(&ChildrenMutation::replace(
2820 old_previous_sibling.as_deref(),
2821 &Some(node),
2822 &[],
2823 old_next_sibling.as_deref(),
2824 ));
2825
2826 let removed = [node];
2827 let mutation = LazyCell::new(|| Mutation::ChildList {
2828 added: None,
2829 removed: Some(&removed),
2830 prev: old_previous_sibling.as_deref(),
2831 next: old_next_sibling.as_deref(),
2832 });
2833 MutationObserver::queue_a_mutation_record(parent, mutation);
2834 }
2835 parent.owner_doc().remove_script_and_layout_blocker();
2836 }
2837
2838 fn compute_attribute_value_with_style_fast_path(attr: &Dom<Attr>, elem: &Element) -> AttrValue {
2844 if *attr.local_name() == local_name!("style") {
2845 if let Some(ref pdb) = *elem.style_attribute().borrow() {
2846 let document = elem.owner_document();
2847 let shared_lock = document.style_shared_lock();
2848 let new_pdb = pdb.read_with(&shared_lock.read()).clone();
2849 return AttrValue::Declaration(
2850 (**attr.value()).to_owned(),
2851 Arc::new(shared_lock.wrap(new_pdb)),
2852 );
2853 }
2854 }
2855
2856 attr.value().clone()
2857 }
2858
2859 pub(crate) fn clone(
2861 node: &Node,
2862 maybe_doc: Option<&Document>,
2863 clone_children: CloneChildrenFlag,
2864 can_gc: CanGc,
2865 ) -> DomRoot<Node> {
2866 let document = match maybe_doc {
2868 Some(doc) => DomRoot::from_ref(doc),
2869 None => node.owner_doc(),
2870 };
2871
2872 let copy: DomRoot<Node> = match node.type_id() {
2875 NodeTypeId::DocumentType => {
2876 let doctype = node.downcast::<DocumentType>().unwrap();
2877 let doctype = DocumentType::new(
2878 doctype.name().clone(),
2879 Some(doctype.public_id().clone()),
2880 Some(doctype.system_id().clone()),
2881 &document,
2882 can_gc,
2883 );
2884 DomRoot::upcast::<Node>(doctype)
2885 },
2886 NodeTypeId::Attr => {
2887 let attr = node.downcast::<Attr>().unwrap();
2888 let attr = Attr::new(
2889 &document,
2890 attr.local_name().clone(),
2891 attr.value().clone(),
2892 attr.name().clone(),
2893 attr.namespace().clone(),
2894 attr.prefix().cloned(),
2895 None,
2896 can_gc,
2897 );
2898 DomRoot::upcast::<Node>(attr)
2899 },
2900 NodeTypeId::DocumentFragment(_) => {
2901 let doc_fragment = DocumentFragment::new(&document, can_gc);
2902 DomRoot::upcast::<Node>(doc_fragment)
2903 },
2904 NodeTypeId::CharacterData(_) => {
2905 let cdata = node.downcast::<CharacterData>().unwrap();
2906 cdata.clone_with_data(cdata.Data(), &document, can_gc)
2907 },
2908 NodeTypeId::Document(_) => {
2909 let document = node.downcast::<Document>().unwrap();
2910 let is_html_doc = if document.is_html_document() {
2911 IsHTMLDocument::HTMLDocument
2912 } else {
2913 IsHTMLDocument::NonHTMLDocument
2914 };
2915 let window = document.window();
2916 let loader = DocumentLoader::new(&document.loader());
2917 let document = Document::new(
2918 window,
2919 HasBrowsingContext::No,
2920 Some(document.url()),
2921 document.origin().clone(),
2923 is_html_doc,
2924 None,
2925 None,
2926 DocumentActivity::Inactive,
2927 DocumentSource::NotFromParser,
2928 loader,
2929 None,
2930 document.status_code(),
2931 Default::default(),
2932 false,
2933 document.allow_declarative_shadow_roots(),
2934 Some(document.insecure_requests_policy()),
2935 document.has_trustworthy_ancestor_or_current_origin(),
2936 document.custom_element_reaction_stack(),
2937 document.creation_sandboxing_flag_set(),
2938 can_gc,
2939 );
2940 DomRoot::upcast::<Node>(document)
2941 },
2942 NodeTypeId::Element(..) => {
2943 let element = node.downcast::<Element>().unwrap();
2944 let name = QualName {
2945 prefix: element.prefix().as_ref().map(|p| Prefix::from(&**p)),
2946 ns: element.namespace().clone(),
2947 local: element.local_name().clone(),
2948 };
2949 let element = Element::create(
2950 name,
2951 element.get_is(),
2952 &document,
2953 ElementCreator::ScriptCreated,
2954 CustomElementCreationMode::Asynchronous,
2955 None,
2956 can_gc,
2957 );
2958 DomRoot::upcast::<Node>(element)
2959 },
2960 };
2961
2962 let document = match copy.downcast::<Document>() {
2965 Some(doc) => DomRoot::from_ref(doc),
2966 None => DomRoot::from_ref(&*document),
2967 };
2968 assert!(copy.owner_doc() == document);
2969
2970 match node.type_id() {
2972 NodeTypeId::Document(_) => {
2973 let node_doc = node.downcast::<Document>().unwrap();
2974 let copy_doc = copy.downcast::<Document>().unwrap();
2975 copy_doc.set_encoding(node_doc.encoding());
2976 copy_doc.set_quirks_mode(node_doc.quirks_mode());
2977 },
2978 NodeTypeId::Element(..) => {
2979 let node_elem = node.downcast::<Element>().unwrap();
2980 let copy_elem = copy.downcast::<Element>().unwrap();
2981
2982 for attr in node_elem.attrs().iter() {
2983 let new_value =
2984 Node::compute_attribute_value_with_style_fast_path(attr, node_elem);
2985 copy_elem.push_new_attribute(
2986 attr.local_name().clone(),
2987 new_value,
2988 attr.name().clone(),
2989 attr.namespace().clone(),
2990 attr.prefix().cloned(),
2991 can_gc,
2992 );
2993 }
2994 },
2995 _ => (),
2996 }
2997
2998 vtable_for(node).cloning_steps(©, maybe_doc, clone_children, can_gc);
3001
3002 if clone_children == CloneChildrenFlag::CloneChildren {
3005 for child in node.children() {
3006 let child_copy = Node::clone(&child, Some(&document), clone_children, can_gc);
3007 let _inserted_node = Node::pre_insert(&child_copy, ©, None, can_gc);
3008 }
3009 }
3010
3011 if matches!(node.type_id(), NodeTypeId::Element(_)) {
3014 let node_elem = node.downcast::<Element>().unwrap();
3015 let copy_elem = copy.downcast::<Element>().unwrap();
3016
3017 if let Some(shadow_root) = node_elem.shadow_root().filter(|r| r.Clonable()) {
3018 assert!(!copy_elem.is_shadow_host());
3020
3021 let copy_shadow_root =
3025 copy_elem.attach_shadow(
3026 IsUserAgentWidget::No,
3027 shadow_root.Mode(),
3028 shadow_root.Clonable(),
3029 shadow_root.Serializable(),
3030 shadow_root.DelegatesFocus(),
3031 shadow_root.SlotAssignment(),
3032 can_gc
3033 )
3034 .expect("placement of attached shadow root must be valid, as this is a copy of an existing one");
3035
3036 copy_shadow_root.set_declarative(shadow_root.is_declarative());
3038
3039 for child in shadow_root.upcast::<Node>().children() {
3042 let child_copy = Node::clone(
3043 &child,
3044 Some(&document),
3045 CloneChildrenFlag::CloneChildren,
3046 can_gc,
3047 );
3048
3049 let _inserted_node = Node::pre_insert(
3051 &child_copy,
3052 copy_shadow_root.upcast::<Node>(),
3053 None,
3054 can_gc,
3055 );
3056 }
3057 }
3058 }
3059
3060 copy
3062 }
3063
3064 pub(crate) fn child_text_content(&self) -> DOMString {
3066 Node::collect_text_contents(self.children())
3067 }
3068
3069 pub(crate) fn descendant_text_content(&self) -> DOMString {
3071 Node::collect_text_contents(self.traverse_preorder(ShadowIncluding::No))
3072 }
3073
3074 pub(crate) fn collect_text_contents<T: Iterator<Item = DomRoot<Node>>>(
3075 iterator: T,
3076 ) -> DOMString {
3077 let mut content = String::new();
3078 for node in iterator {
3079 if let Some(text) = node.downcast::<Text>() {
3080 content.push_str(&text.upcast::<CharacterData>().data());
3081 }
3082 }
3083 DOMString::from(content)
3084 }
3085
3086 pub(crate) fn set_text_content_for_element(&self, value: Option<DOMString>, can_gc: CanGc) {
3088 assert!(matches!(
3091 self.type_id(),
3092 NodeTypeId::DocumentFragment(_) | NodeTypeId::Element(..)
3093 ));
3094 let value = value.unwrap_or_default();
3095 let node = if value.is_empty() {
3096 None
3098 } else {
3099 Some(DomRoot::upcast(
3102 self.owner_doc().CreateTextNode(value, can_gc),
3103 ))
3104 };
3105
3106 Self::replace_all(node.as_deref(), self, can_gc);
3108 }
3109
3110 pub(crate) fn namespace_to_string(namespace: Namespace) -> Option<DOMString> {
3111 match namespace {
3112 ns!() => None,
3113 _ => Some(DOMString::from(&*namespace)),
3115 }
3116 }
3117
3118 pub(crate) fn locate_namespace(node: &Node, prefix: Option<DOMString>) -> Namespace {
3120 match node.type_id() {
3121 NodeTypeId::Element(_) => node.downcast::<Element>().unwrap().locate_namespace(prefix),
3122 NodeTypeId::Attr => node
3123 .downcast::<Attr>()
3124 .unwrap()
3125 .GetOwnerElement()
3126 .as_ref()
3127 .map_or(ns!(), |elem| elem.locate_namespace(prefix)),
3128 NodeTypeId::Document(_) => node
3129 .downcast::<Document>()
3130 .unwrap()
3131 .GetDocumentElement()
3132 .as_ref()
3133 .map_or(ns!(), |elem| elem.locate_namespace(prefix)),
3134 NodeTypeId::DocumentType | NodeTypeId::DocumentFragment(_) => ns!(),
3135 _ => node
3136 .GetParentElement()
3137 .as_ref()
3138 .map_or(ns!(), |elem| elem.locate_namespace(prefix)),
3139 }
3140 }
3141
3142 #[allow(unsafe_code)]
3150 pub(crate) unsafe fn from_untrusted_node_address(
3151 candidate: UntrustedNodeAddress,
3152 ) -> &'static Self {
3153 let candidate = candidate.0 as usize;
3155 let object = candidate as *mut JSObject;
3156 if object.is_null() {
3157 panic!("Attempted to create a `Node` from an invalid pointer!")
3158 }
3159
3160 unsafe { &*(conversions::private_from_object(object) as *const Self) }
3161 }
3162
3163 pub(crate) fn html_serialize(
3164 &self,
3165 traversal_scope: html_serialize::TraversalScope,
3166 serialize_shadow_roots: bool,
3167 shadow_roots: Vec<DomRoot<ShadowRoot>>,
3168 can_gc: CanGc,
3169 ) -> DOMString {
3170 let mut writer = vec![];
3171 let mut serializer = HtmlSerializer::new(
3172 &mut writer,
3173 html_serialize::SerializeOpts {
3174 traversal_scope: traversal_scope.clone(),
3175 ..Default::default()
3176 },
3177 );
3178
3179 serialize_html_fragment(
3180 self,
3181 &mut serializer,
3182 traversal_scope,
3183 serialize_shadow_roots,
3184 shadow_roots,
3185 can_gc,
3186 )
3187 .expect("Serializing node failed");
3188
3189 DOMString::from(String::from_utf8(writer).unwrap())
3191 }
3192
3193 pub(crate) fn xml_serialize(
3195 &self,
3196 traversal_scope: xml_serialize::TraversalScope,
3197 ) -> Fallible<DOMString> {
3198 let mut writer = vec![];
3199 xml_serialize::serialize(
3200 &mut writer,
3201 &self,
3202 xml_serialize::SerializeOpts { traversal_scope },
3203 )
3204 .map_err(|error| {
3205 error!("Cannot serialize node: {error}");
3206 Error::InvalidState(None)
3207 })?;
3208
3209 let string = DOMString::from(String::from_utf8(writer).map_err(|error| {
3211 error!("Cannot serialize node: {error}");
3212 Error::InvalidState(None)
3213 })?);
3214
3215 Ok(string)
3216 }
3217
3218 pub(crate) fn fragment_serialization_algorithm(
3220 &self,
3221 require_well_formed: bool,
3222 can_gc: CanGc,
3223 ) -> Fallible<DOMString> {
3224 let context_document = self.owner_document();
3226
3227 if context_document.is_html_document() {
3230 return Ok(self.html_serialize(
3231 html_serialize::TraversalScope::ChildrenOnly(None),
3232 false,
3233 vec![],
3234 can_gc,
3235 ));
3236 }
3237
3238 let _ = require_well_formed;
3241 self.xml_serialize(xml_serialize::TraversalScope::ChildrenOnly(None))
3242 }
3243
3244 pub(crate) fn establishes_scrolling_box(&self) -> bool {
3246 if self.is::<Document>() {
3251 return true;
3252 }
3253 let Some(element) = self.downcast::<Element>() else {
3254 return false;
3256 };
3257 element.style().is_some_and(|style| {
3260 let overflow_x = style.get_box().clone_overflow_x();
3261 let overflow_y = style.get_box().clone_overflow_y();
3262 overflow_x.is_scrollable() || overflow_y.is_scrollable()
3263 })
3264 }
3265}
3266
3267impl NodeMethods<crate::DomTypeHolder> for Node {
3268 fn NodeType(&self) -> u16 {
3270 match self.type_id() {
3271 NodeTypeId::Attr => NodeConstants::ATTRIBUTE_NODE,
3272 NodeTypeId::CharacterData(CharacterDataTypeId::Text(TextTypeId::Text)) => {
3273 NodeConstants::TEXT_NODE
3274 },
3275 NodeTypeId::CharacterData(CharacterDataTypeId::Text(TextTypeId::CDATASection)) => {
3276 NodeConstants::CDATA_SECTION_NODE
3277 },
3278 NodeTypeId::CharacterData(CharacterDataTypeId::ProcessingInstruction) => {
3279 NodeConstants::PROCESSING_INSTRUCTION_NODE
3280 },
3281 NodeTypeId::CharacterData(CharacterDataTypeId::Comment) => NodeConstants::COMMENT_NODE,
3282 NodeTypeId::Document(_) => NodeConstants::DOCUMENT_NODE,
3283 NodeTypeId::DocumentType => NodeConstants::DOCUMENT_TYPE_NODE,
3284 NodeTypeId::DocumentFragment(_) => NodeConstants::DOCUMENT_FRAGMENT_NODE,
3285 NodeTypeId::Element(_) => NodeConstants::ELEMENT_NODE,
3286 }
3287 }
3288
3289 fn NodeName(&self) -> DOMString {
3291 match self.type_id() {
3292 NodeTypeId::Attr => self.downcast::<Attr>().unwrap().qualified_name(),
3293 NodeTypeId::Element(..) => self.downcast::<Element>().unwrap().TagName(),
3294 NodeTypeId::CharacterData(CharacterDataTypeId::Text(TextTypeId::Text)) => {
3295 DOMString::from("#text")
3296 },
3297 NodeTypeId::CharacterData(CharacterDataTypeId::Text(TextTypeId::CDATASection)) => {
3298 DOMString::from("#cdata-section")
3299 },
3300 NodeTypeId::CharacterData(CharacterDataTypeId::ProcessingInstruction) => {
3301 self.downcast::<ProcessingInstruction>().unwrap().Target()
3302 },
3303 NodeTypeId::CharacterData(CharacterDataTypeId::Comment) => DOMString::from("#comment"),
3304 NodeTypeId::DocumentType => self.downcast::<DocumentType>().unwrap().name().clone(),
3305 NodeTypeId::DocumentFragment(_) => DOMString::from("#document-fragment"),
3306 NodeTypeId::Document(_) => DOMString::from("#document"),
3307 }
3308 }
3309
3310 fn BaseURI(&self) -> USVString {
3312 USVString(String::from(self.owner_doc().base_url().as_str()))
3313 }
3314
3315 fn IsConnected(&self) -> bool {
3317 self.is_connected()
3318 }
3319
3320 fn GetOwnerDocument(&self) -> Option<DomRoot<Document>> {
3322 match self.type_id() {
3323 NodeTypeId::Document(_) => None,
3324 _ => Some(self.owner_doc()),
3325 }
3326 }
3327
3328 fn GetRootNode(&self, options: &GetRootNodeOptions) -> DomRoot<Node> {
3330 if !options.composed {
3331 if let Some(shadow_root) = self.containing_shadow_root() {
3332 return DomRoot::upcast(shadow_root);
3333 }
3334 }
3335
3336 if self.is_connected() {
3337 DomRoot::from_ref(self.owner_doc().upcast::<Node>())
3338 } else {
3339 self.inclusive_ancestors(ShadowIncluding::Yes)
3340 .last()
3341 .unwrap()
3342 }
3343 }
3344
3345 fn GetParentNode(&self) -> Option<DomRoot<Node>> {
3347 self.parent_node.get()
3348 }
3349
3350 fn GetParentElement(&self) -> Option<DomRoot<Element>> {
3352 self.GetParentNode().and_then(DomRoot::downcast)
3353 }
3354
3355 fn HasChildNodes(&self) -> bool {
3357 self.first_child.get().is_some()
3358 }
3359
3360 fn ChildNodes(&self, can_gc: CanGc) -> DomRoot<NodeList> {
3362 if let Some(list) = self.ensure_rare_data().child_list.get() {
3363 return list;
3364 }
3365
3366 let doc = self.owner_doc();
3367 let window = doc.window();
3368 let list = NodeList::new_child_list(window, self, can_gc);
3369 self.ensure_rare_data().child_list.set(Some(&list));
3370 list
3371 }
3372
3373 fn GetFirstChild(&self) -> Option<DomRoot<Node>> {
3375 self.first_child.get()
3376 }
3377
3378 fn GetLastChild(&self) -> Option<DomRoot<Node>> {
3380 self.last_child.get()
3381 }
3382
3383 fn GetPreviousSibling(&self) -> Option<DomRoot<Node>> {
3385 self.prev_sibling.get()
3386 }
3387
3388 fn GetNextSibling(&self) -> Option<DomRoot<Node>> {
3390 self.next_sibling.get()
3391 }
3392
3393 fn GetNodeValue(&self) -> Option<DOMString> {
3395 match self.type_id() {
3396 NodeTypeId::Attr => Some(self.downcast::<Attr>().unwrap().Value()),
3397 NodeTypeId::CharacterData(_) => {
3398 self.downcast::<CharacterData>().map(CharacterData::Data)
3399 },
3400 _ => None,
3401 }
3402 }
3403
3404 fn SetNodeValue(&self, val: Option<DOMString>, can_gc: CanGc) -> Fallible<()> {
3406 match self.type_id() {
3407 NodeTypeId::Attr => {
3408 let attr = self.downcast::<Attr>().unwrap();
3409 attr.SetValue(val.unwrap_or_default(), can_gc)?;
3410 },
3411 NodeTypeId::CharacterData(_) => {
3412 let character_data = self.downcast::<CharacterData>().unwrap();
3413 character_data.SetData(val.unwrap_or_default());
3414 },
3415 _ => {},
3416 };
3417 Ok(())
3418 }
3419
3420 fn GetTextContent(&self) -> Option<DOMString> {
3422 match self.type_id() {
3423 NodeTypeId::DocumentFragment(_) | NodeTypeId::Element(..) => {
3424 let content =
3425 Node::collect_text_contents(self.traverse_preorder(ShadowIncluding::No));
3426 Some(content)
3427 },
3428 NodeTypeId::Attr => Some(self.downcast::<Attr>().unwrap().Value()),
3429 NodeTypeId::CharacterData(..) => {
3430 let characterdata = self.downcast::<CharacterData>().unwrap();
3431 Some(characterdata.Data())
3432 },
3433 NodeTypeId::DocumentType | NodeTypeId::Document(_) => None,
3434 }
3435 }
3436
3437 fn SetTextContent(&self, value: Option<DOMString>, can_gc: CanGc) -> Fallible<()> {
3439 match self.type_id() {
3440 NodeTypeId::DocumentFragment(_) | NodeTypeId::Element(..) => {
3441 self.set_text_content_for_element(value, can_gc);
3442 },
3443 NodeTypeId::Attr => {
3444 let attr = self.downcast::<Attr>().unwrap();
3445 attr.SetValue(value.unwrap_or_default(), can_gc)?;
3446 },
3447 NodeTypeId::CharacterData(..) => {
3448 let characterdata = self.downcast::<CharacterData>().unwrap();
3449 characterdata.SetData(value.unwrap_or_default());
3450 },
3451 NodeTypeId::DocumentType | NodeTypeId::Document(_) => {},
3452 };
3453 Ok(())
3454 }
3455
3456 fn InsertBefore(
3458 &self,
3459 node: &Node,
3460 child: Option<&Node>,
3461 can_gc: CanGc,
3462 ) -> Fallible<DomRoot<Node>> {
3463 Node::pre_insert(node, self, child, can_gc)
3464 }
3465
3466 fn AppendChild(&self, node: &Node, can_gc: CanGc) -> Fallible<DomRoot<Node>> {
3468 Node::pre_insert(node, self, None, can_gc)
3469 }
3470
3471 fn ReplaceChild(&self, node: &Node, child: &Node, can_gc: CanGc) -> Fallible<DomRoot<Node>> {
3473 match self.type_id() {
3476 NodeTypeId::Document(_) | NodeTypeId::DocumentFragment(_) | NodeTypeId::Element(..) => {
3477 },
3478 _ => return Err(Error::HierarchyRequest),
3479 }
3480
3481 if node.is_inclusive_ancestor_of(self) {
3484 return Err(Error::HierarchyRequest);
3485 }
3486
3487 if !self.is_parent_of(child) {
3489 return Err(Error::NotFound(None));
3490 }
3491
3492 match node.type_id() {
3497 NodeTypeId::CharacterData(CharacterDataTypeId::Text(_)) if self.is::<Document>() => {
3498 return Err(Error::HierarchyRequest);
3499 },
3500 NodeTypeId::DocumentType if !self.is::<Document>() => {
3501 return Err(Error::HierarchyRequest);
3502 },
3503 NodeTypeId::Document(_) | NodeTypeId::Attr => return Err(Error::HierarchyRequest),
3504 _ => (),
3505 }
3506
3507 if self.is::<Document>() {
3510 match node.type_id() {
3511 NodeTypeId::DocumentFragment(_) => {
3513 if node.children().any(|c| c.is::<Text>()) {
3515 return Err(Error::HierarchyRequest);
3516 }
3517 match node.child_elements().count() {
3518 0 => (),
3519 1 => {
3521 if self.child_elements().any(|c| c.upcast::<Node>() != child) {
3522 return Err(Error::HierarchyRequest);
3523 }
3524 if child.following_siblings().any(|child| child.is_doctype()) {
3525 return Err(Error::HierarchyRequest);
3526 }
3527 },
3528 _ => return Err(Error::HierarchyRequest),
3530 }
3531 },
3532 NodeTypeId::Element(..) => {
3534 if self.child_elements().any(|c| c.upcast::<Node>() != child) {
3535 return Err(Error::HierarchyRequest);
3536 }
3537 if child.following_siblings().any(|child| child.is_doctype()) {
3538 return Err(Error::HierarchyRequest);
3539 }
3540 },
3541 NodeTypeId::DocumentType => {
3543 if self.children().any(|c| c.is_doctype() && &*c != child) {
3544 return Err(Error::HierarchyRequest);
3545 }
3546 if self
3547 .children()
3548 .take_while(|c| &**c != child)
3549 .any(|c| c.is::<Element>())
3550 {
3551 return Err(Error::HierarchyRequest);
3552 }
3553 },
3554 NodeTypeId::CharacterData(..) => (),
3555 NodeTypeId::Document(_) => unreachable!(),
3558 NodeTypeId::Attr => unreachable!(),
3559 }
3560 }
3561
3562 let child_next_sibling = child.GetNextSibling();
3565 let node_next_sibling = node.GetNextSibling();
3566 let reference_child = if child_next_sibling.as_deref() == Some(node) {
3567 node_next_sibling.as_deref()
3568 } else {
3569 child_next_sibling.as_deref()
3570 };
3571
3572 let previous_sibling = child.GetPreviousSibling();
3574
3575 let document = self.owner_document();
3579 Node::adopt(node, &document, can_gc);
3580
3581 let removed_child = if node != child {
3586 Node::remove(child, self, SuppressObserver::Suppressed, can_gc);
3588 Some(child)
3589 } else {
3590 None
3591 };
3592
3593 rooted_vec!(let mut nodes);
3595 let nodes = if node.type_id() ==
3596 NodeTypeId::DocumentFragment(DocumentFragmentTypeId::DocumentFragment) ||
3597 node.type_id() == NodeTypeId::DocumentFragment(DocumentFragmentTypeId::ShadowRoot)
3598 {
3599 nodes.extend(node.children().map(|node| Dom::from_ref(&*node)));
3600 nodes.r()
3601 } else {
3602 from_ref(&node)
3603 };
3604
3605 Node::insert(
3607 node,
3608 self,
3609 reference_child,
3610 SuppressObserver::Suppressed,
3611 can_gc,
3612 );
3613
3614 vtable_for(self).children_changed(&ChildrenMutation::replace(
3615 previous_sibling.as_deref(),
3616 &removed_child,
3617 nodes,
3618 reference_child,
3619 ));
3620
3621 let removed = removed_child.map(|r| [r]);
3624 let mutation = LazyCell::new(|| Mutation::ChildList {
3625 added: Some(nodes),
3626 removed: removed.as_ref().map(|r| &r[..]),
3627 prev: previous_sibling.as_deref(),
3628 next: reference_child,
3629 });
3630
3631 MutationObserver::queue_a_mutation_record(self, mutation);
3632
3633 Ok(DomRoot::from_ref(child))
3635 }
3636
3637 fn RemoveChild(&self, node: &Node, can_gc: CanGc) -> Fallible<DomRoot<Node>> {
3639 Node::pre_remove(node, self, can_gc)
3640 }
3641
3642 fn Normalize(&self, can_gc: CanGc) {
3644 let mut children = self.children().enumerate().peekable();
3645 while let Some((_, node)) = children.next() {
3646 if let Some(text) = node.downcast::<Text>() {
3647 if text.is::<CDATASection>() {
3648 continue;
3649 }
3650 let cdata = text.upcast::<CharacterData>();
3651 let mut length = cdata.Length();
3652 if length == 0 {
3653 Node::remove(&node, self, SuppressObserver::Unsuppressed, can_gc);
3654 continue;
3655 }
3656 while children.peek().is_some_and(|(_, sibling)| {
3657 sibling.is::<Text>() && !sibling.is::<CDATASection>()
3658 }) {
3659 let (index, sibling) = children.next().unwrap();
3660 sibling
3661 .ranges()
3662 .drain_to_preceding_text_sibling(&sibling, &node, length);
3663 self.ranges()
3664 .move_to_text_child_at(self, index as u32, &node, length);
3665 let sibling_cdata = sibling.downcast::<CharacterData>().unwrap();
3666 length += sibling_cdata.Length();
3667 cdata.append_data(&sibling_cdata.data());
3668 Node::remove(&sibling, self, SuppressObserver::Unsuppressed, can_gc);
3669 }
3670 } else {
3671 node.Normalize(can_gc);
3672 }
3673 }
3674 }
3675
3676 fn CloneNode(&self, subtree: bool, can_gc: CanGc) -> Fallible<DomRoot<Node>> {
3678 if self.is::<ShadowRoot>() {
3680 return Err(Error::NotSupported);
3681 }
3682
3683 let result = Node::clone(
3685 self,
3686 None,
3687 if subtree {
3688 CloneChildrenFlag::CloneChildren
3689 } else {
3690 CloneChildrenFlag::DoNotCloneChildren
3691 },
3692 can_gc,
3693 );
3694 Ok(result)
3695 }
3696
3697 fn IsEqualNode(&self, maybe_node: Option<&Node>) -> bool {
3699 fn is_equal_doctype(node: &Node, other: &Node) -> bool {
3700 let doctype = node.downcast::<DocumentType>().unwrap();
3701 let other_doctype = other.downcast::<DocumentType>().unwrap();
3702 (*doctype.name() == *other_doctype.name()) &&
3703 (*doctype.public_id() == *other_doctype.public_id()) &&
3704 (*doctype.system_id() == *other_doctype.system_id())
3705 }
3706 fn is_equal_element(node: &Node, other: &Node) -> bool {
3707 let element = node.downcast::<Element>().unwrap();
3708 let other_element = other.downcast::<Element>().unwrap();
3709 (*element.namespace() == *other_element.namespace()) &&
3710 (*element.prefix() == *other_element.prefix()) &&
3711 (*element.local_name() == *other_element.local_name()) &&
3712 (element.attrs().len() == other_element.attrs().len())
3713 }
3714 fn is_equal_processinginstruction(node: &Node, other: &Node) -> bool {
3715 let pi = node.downcast::<ProcessingInstruction>().unwrap();
3716 let other_pi = other.downcast::<ProcessingInstruction>().unwrap();
3717 (*pi.target() == *other_pi.target()) &&
3718 (*pi.upcast::<CharacterData>().data() ==
3719 *other_pi.upcast::<CharacterData>().data())
3720 }
3721 fn is_equal_characterdata(node: &Node, other: &Node) -> bool {
3722 let characterdata = node.downcast::<CharacterData>().unwrap();
3723 let other_characterdata = other.downcast::<CharacterData>().unwrap();
3724 *characterdata.data() == *other_characterdata.data()
3725 }
3726 fn is_equal_attr(node: &Node, other: &Node) -> bool {
3727 let attr = node.downcast::<Attr>().unwrap();
3728 let other_attr = other.downcast::<Attr>().unwrap();
3729 (*attr.namespace() == *other_attr.namespace()) &&
3730 (attr.local_name() == other_attr.local_name()) &&
3731 (**attr.value() == **other_attr.value())
3732 }
3733 fn is_equal_element_attrs(node: &Node, other: &Node) -> bool {
3734 let element = node.downcast::<Element>().unwrap();
3735 let other_element = other.downcast::<Element>().unwrap();
3736 assert!(element.attrs().len() == other_element.attrs().len());
3737 element.attrs().iter().all(|attr| {
3738 other_element.attrs().iter().any(|other_attr| {
3739 (*attr.namespace() == *other_attr.namespace()) &&
3740 (attr.local_name() == other_attr.local_name()) &&
3741 (**attr.value() == **other_attr.value())
3742 })
3743 })
3744 }
3745
3746 fn is_equal_node(this: &Node, node: &Node) -> bool {
3747 if this.NodeType() != node.NodeType() {
3749 return false;
3750 }
3751
3752 match node.type_id() {
3753 NodeTypeId::DocumentType if !is_equal_doctype(this, node) => return false,
3755 NodeTypeId::Element(..) if !is_equal_element(this, node) => return false,
3756 NodeTypeId::CharacterData(CharacterDataTypeId::ProcessingInstruction)
3757 if !is_equal_processinginstruction(this, node) =>
3758 {
3759 return false;
3760 },
3761 NodeTypeId::CharacterData(CharacterDataTypeId::Text(_)) |
3762 NodeTypeId::CharacterData(CharacterDataTypeId::Comment)
3763 if !is_equal_characterdata(this, node) =>
3764 {
3765 return false;
3766 },
3767 NodeTypeId::Element(..) if !is_equal_element_attrs(this, node) => return false,
3769 NodeTypeId::Attr if !is_equal_attr(this, node) => return false,
3770
3771 _ => (),
3772 }
3773
3774 if this.children_count() != node.children_count() {
3776 return false;
3777 }
3778
3779 this.children()
3781 .zip(node.children())
3782 .all(|(child, other_child)| is_equal_node(&child, &other_child))
3783 }
3784 match maybe_node {
3785 None => false,
3787 Some(node) => is_equal_node(self, node),
3789 }
3790 }
3791
3792 fn IsSameNode(&self, other_node: Option<&Node>) -> bool {
3794 match other_node {
3795 Some(node) => self == node,
3796 None => false,
3797 }
3798 }
3799
3800 fn CompareDocumentPosition(&self, other: &Node) -> u16 {
3802 if self == other {
3804 return 0;
3805 }
3806
3807 let mut node1 = Some(other);
3809 let mut node2 = Some(self);
3810
3811 let mut attr1: Option<&Attr> = None;
3813 let mut attr2: Option<&Attr> = None;
3814
3815 let attr1owner;
3820 if let Some(a) = other.downcast::<Attr>() {
3821 attr1 = Some(a);
3822 attr1owner = a.GetOwnerElement();
3823 node1 = match attr1owner {
3824 Some(ref e) => Some(e.upcast()),
3825 None => None,
3826 }
3827 }
3828
3829 let attr2owner;
3832 if let Some(a) = self.downcast::<Attr>() {
3833 attr2 = Some(a);
3834 attr2owner = a.GetOwnerElement();
3835 node2 = match attr2owner {
3836 Some(ref e) => Some(e.upcast()),
3837 None => None,
3838 }
3839 }
3840
3841 if let Some(node2) = node2 {
3846 if Some(node2) == node1 {
3847 if let (Some(a1), Some(a2)) = (attr1, attr2) {
3848 let attrs = node2.downcast::<Element>().unwrap().attrs();
3849 for attr in attrs.iter() {
3853 if (*attr.namespace() == *a1.namespace()) &&
3854 (attr.local_name() == a1.local_name()) &&
3855 (**attr.value() == **a1.value())
3856 {
3857 return NodeConstants::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC +
3858 NodeConstants::DOCUMENT_POSITION_PRECEDING;
3859 }
3860 if (*attr.namespace() == *a2.namespace()) &&
3861 (attr.local_name() == a2.local_name()) &&
3862 (**attr.value() == **a2.value())
3863 {
3864 return NodeConstants::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC +
3865 NodeConstants::DOCUMENT_POSITION_FOLLOWING;
3866 }
3867 }
3868 unreachable!();
3871 }
3872 }
3873 }
3874
3875 match (node1, node2) {
3877 (None, _) => {
3878 NodeConstants::DOCUMENT_POSITION_FOLLOWING +
3880 NodeConstants::DOCUMENT_POSITION_DISCONNECTED +
3881 NodeConstants::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC
3882 },
3883 (_, None) => {
3884 NodeConstants::DOCUMENT_POSITION_PRECEDING +
3886 NodeConstants::DOCUMENT_POSITION_DISCONNECTED +
3887 NodeConstants::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC
3888 },
3889 (Some(node1), Some(node2)) => {
3890 let mut self_and_ancestors = node2
3892 .inclusive_ancestors(ShadowIncluding::No)
3893 .collect::<SmallVec<[_; 20]>>();
3894 let mut other_and_ancestors = node1
3895 .inclusive_ancestors(ShadowIncluding::No)
3896 .collect::<SmallVec<[_; 20]>>();
3897
3898 if self_and_ancestors.last() != other_and_ancestors.last() {
3899 let random = as_uintptr(self_and_ancestors.last().unwrap()) <
3900 as_uintptr(other_and_ancestors.last().unwrap());
3901 let random = if random {
3902 NodeConstants::DOCUMENT_POSITION_FOLLOWING
3903 } else {
3904 NodeConstants::DOCUMENT_POSITION_PRECEDING
3905 };
3906
3907 return random +
3909 NodeConstants::DOCUMENT_POSITION_DISCONNECTED +
3910 NodeConstants::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC;
3911 }
3912 let mut parent = self_and_ancestors.pop().unwrap();
3914 other_and_ancestors.pop().unwrap();
3915
3916 let mut current_position =
3917 cmp::min(self_and_ancestors.len(), other_and_ancestors.len());
3918
3919 while current_position > 0 {
3920 current_position -= 1;
3921 let child_1 = self_and_ancestors.pop().unwrap();
3922 let child_2 = other_and_ancestors.pop().unwrap();
3923
3924 if child_1 != child_2 {
3925 let is_before = parent.children().position(|c| c == child_1).unwrap() <
3926 parent.children().position(|c| c == child_2).unwrap();
3927 return if is_before {
3930 NodeConstants::DOCUMENT_POSITION_FOLLOWING
3931 } else {
3932 NodeConstants::DOCUMENT_POSITION_PRECEDING
3933 };
3934 }
3935
3936 parent = child_1;
3937 }
3938
3939 if self_and_ancestors.len() < other_and_ancestors.len() {
3944 NodeConstants::DOCUMENT_POSITION_FOLLOWING +
3945 NodeConstants::DOCUMENT_POSITION_CONTAINED_BY
3946 } else {
3947 NodeConstants::DOCUMENT_POSITION_PRECEDING +
3948 NodeConstants::DOCUMENT_POSITION_CONTAINS
3949 }
3950 },
3951 }
3952 }
3953
3954 fn Contains(&self, maybe_other: Option<&Node>) -> bool {
3956 match maybe_other {
3957 None => false,
3958 Some(other) => self.is_inclusive_ancestor_of(other),
3959 }
3960 }
3961
3962 fn LookupPrefix(&self, namespace: Option<DOMString>) -> Option<DOMString> {
3964 let namespace = namespace_from_domstring(namespace);
3965
3966 if namespace == ns!() {
3968 return None;
3969 }
3970
3971 match self.type_id() {
3973 NodeTypeId::Element(..) => self.downcast::<Element>().unwrap().lookup_prefix(namespace),
3974 NodeTypeId::Document(_) => self
3975 .downcast::<Document>()
3976 .unwrap()
3977 .GetDocumentElement()
3978 .and_then(|element| element.lookup_prefix(namespace)),
3979 NodeTypeId::DocumentType | NodeTypeId::DocumentFragment(_) => None,
3980 NodeTypeId::Attr => self
3981 .downcast::<Attr>()
3982 .unwrap()
3983 .GetOwnerElement()
3984 .and_then(|element| element.lookup_prefix(namespace)),
3985 _ => self
3986 .GetParentElement()
3987 .and_then(|element| element.lookup_prefix(namespace)),
3988 }
3989 }
3990
3991 fn LookupNamespaceURI(&self, prefix: Option<DOMString>) -> Option<DOMString> {
3993 let prefix = prefix.filter(|prefix| !prefix.is_empty());
3995
3996 Node::namespace_to_string(Node::locate_namespace(self, prefix))
3998 }
3999
4000 fn IsDefaultNamespace(&self, namespace: Option<DOMString>) -> bool {
4002 let namespace = namespace_from_domstring(namespace);
4004 Node::locate_namespace(self, None) == namespace
4006 }
4007}
4008
4009pub(crate) trait NodeTraits {
4010 fn owner_document(&self) -> DomRoot<Document>;
4014 fn owner_window(&self) -> DomRoot<Window>;
4018 fn owner_global(&self) -> DomRoot<GlobalScope>;
4022 fn containing_shadow_root(&self) -> Option<DomRoot<ShadowRoot>>;
4024 #[cfg_attr(crown, allow(crown::unrooted_must_root))]
4027 fn stylesheet_list_owner(&self) -> StyleSheetListOwner;
4028}
4029
4030impl<T: DerivedFrom<Node> + DomObject> NodeTraits for T {
4031 fn owner_document(&self) -> DomRoot<Document> {
4032 self.upcast().owner_doc()
4033 }
4034
4035 fn owner_window(&self) -> DomRoot<Window> {
4036 DomRoot::from_ref(self.owner_document().window())
4037 }
4038
4039 fn owner_global(&self) -> DomRoot<GlobalScope> {
4040 DomRoot::from_ref(self.owner_window().upcast())
4041 }
4042
4043 fn containing_shadow_root(&self) -> Option<DomRoot<ShadowRoot>> {
4044 Node::containing_shadow_root(self.upcast())
4045 }
4046
4047 #[cfg_attr(crown, allow(crown::unrooted_must_root))]
4048 fn stylesheet_list_owner(&self) -> StyleSheetListOwner {
4049 self.containing_shadow_root()
4050 .map(|shadow_root| StyleSheetListOwner::ShadowRoot(Dom::from_ref(&*shadow_root)))
4051 .unwrap_or_else(|| {
4052 StyleSheetListOwner::Document(Dom::from_ref(&*self.owner_document()))
4053 })
4054 }
4055}
4056
4057impl VirtualMethods for Node {
4058 fn super_type(&self) -> Option<&dyn VirtualMethods> {
4059 Some(self.upcast::<EventTarget>() as &dyn VirtualMethods)
4060 }
4061
4062 fn children_changed(&self, mutation: &ChildrenMutation) {
4063 if let Some(s) = self.super_type() {
4064 s.children_changed(mutation);
4065 }
4066
4067 if let Some(data) = self.rare_data().as_ref() {
4068 if let Some(list) = data.child_list.get() {
4069 list.as_children_list().children_changed(mutation);
4070 }
4071 }
4072
4073 self.owner_doc().content_and_heritage_changed(self);
4074 }
4075
4076 fn unbind_from_tree(&self, context: &UnbindContext, can_gc: CanGc) {
4079 self.super_type().unwrap().unbind_from_tree(context, can_gc);
4080
4081 if !self.is_in_a_shadow_tree() && !self.ranges_is_empty() {
4086 self.ranges().drain_to_parent(context, self);
4087 }
4088 }
4089
4090 fn handle_event(&self, event: &Event, _: CanGc) {
4091 if let Some(event) = event.downcast::<KeyboardEvent>() {
4092 self.owner_document()
4093 .event_handler()
4094 .run_default_keyboard_event_handler(event);
4095 }
4096 }
4097}
4098
4099#[derive(Clone, Copy, MallocSizeOf, PartialEq)]
4101pub(crate) enum NodeDamage {
4102 Style,
4104 ContentOrHeritage,
4107 Other,
4109}
4110
4111pub(crate) enum ChildrenMutation<'a> {
4112 Append {
4113 prev: &'a Node,
4114 added: &'a [&'a Node],
4115 },
4116 Insert {
4117 prev: &'a Node,
4118 added: &'a [&'a Node],
4119 next: &'a Node,
4120 },
4121 Prepend {
4122 added: &'a [&'a Node],
4123 next: &'a Node,
4124 },
4125 Replace {
4126 prev: Option<&'a Node>,
4127 removed: &'a Node,
4128 added: &'a [&'a Node],
4129 next: Option<&'a Node>,
4130 },
4131 ReplaceAll {
4132 removed: &'a [&'a Node],
4133 added: &'a [&'a Node],
4134 },
4135 ChangeText,
4140}
4141
4142impl<'a> ChildrenMutation<'a> {
4143 fn insert(
4144 prev: Option<&'a Node>,
4145 added: &'a [&'a Node],
4146 next: Option<&'a Node>,
4147 ) -> ChildrenMutation<'a> {
4148 match (prev, next) {
4149 (None, None) => ChildrenMutation::ReplaceAll {
4150 removed: &[],
4151 added,
4152 },
4153 (Some(prev), None) => ChildrenMutation::Append { prev, added },
4154 (None, Some(next)) => ChildrenMutation::Prepend { added, next },
4155 (Some(prev), Some(next)) => ChildrenMutation::Insert { prev, added, next },
4156 }
4157 }
4158
4159 fn replace(
4160 prev: Option<&'a Node>,
4161 removed: &'a Option<&'a Node>,
4162 added: &'a [&'a Node],
4163 next: Option<&'a Node>,
4164 ) -> ChildrenMutation<'a> {
4165 if let Some(ref removed) = *removed {
4166 if let (None, None) = (prev, next) {
4167 ChildrenMutation::ReplaceAll {
4168 removed: from_ref(removed),
4169 added,
4170 }
4171 } else {
4172 ChildrenMutation::Replace {
4173 prev,
4174 removed,
4175 added,
4176 next,
4177 }
4178 }
4179 } else {
4180 ChildrenMutation::insert(prev, added, next)
4181 }
4182 }
4183
4184 fn replace_all(removed: &'a [&'a Node], added: &'a [&'a Node]) -> ChildrenMutation<'a> {
4185 ChildrenMutation::ReplaceAll { removed, added }
4186 }
4187
4188 pub(crate) fn next_child(&self) -> Option<&Node> {
4193 match *self {
4194 ChildrenMutation::Append { .. } => None,
4195 ChildrenMutation::Insert { next, .. } => Some(next),
4196 ChildrenMutation::Prepend { next, .. } => Some(next),
4197 ChildrenMutation::Replace { next, .. } => next,
4198 ChildrenMutation::ReplaceAll { .. } => None,
4199 ChildrenMutation::ChangeText => None,
4200 }
4201 }
4202
4203 pub(crate) fn modified_edge_element(&self) -> Option<DomRoot<Node>> {
4210 match *self {
4211 ChildrenMutation::Prepend { next, .. } |
4213 ChildrenMutation::Replace {
4214 prev: None,
4215 next: Some(next),
4216 ..
4217 } => next
4218 .inclusively_following_siblings()
4219 .find(|node| node.is::<Element>()),
4220 ChildrenMutation::Append { prev, .. } |
4222 ChildrenMutation::Replace {
4223 prev: Some(prev),
4224 next: None,
4225 ..
4226 } => prev
4227 .inclusively_preceding_siblings()
4228 .find(|node| node.is::<Element>()),
4229 ChildrenMutation::Insert { prev, next, .. } |
4231 ChildrenMutation::Replace {
4232 prev: Some(prev),
4233 next: Some(next),
4234 ..
4235 } => {
4236 if prev
4237 .inclusively_preceding_siblings()
4238 .all(|node| !node.is::<Element>())
4239 {
4240 next.inclusively_following_siblings()
4242 .find(|node| node.is::<Element>())
4243 } else if next
4244 .inclusively_following_siblings()
4245 .all(|node| !node.is::<Element>())
4246 {
4247 prev.inclusively_preceding_siblings()
4249 .find(|node| node.is::<Element>())
4250 } else {
4251 None
4252 }
4253 },
4254
4255 ChildrenMutation::Replace {
4256 prev: None,
4257 next: None,
4258 ..
4259 } => unreachable!(),
4260 ChildrenMutation::ReplaceAll { .. } => None,
4261 ChildrenMutation::ChangeText => None,
4262 }
4263 }
4264}
4265
4266pub(crate) struct BindContext<'a> {
4268 pub(crate) parent: &'a Node,
4270
4271 pub(crate) tree_connected: bool,
4275
4276 pub(crate) tree_is_in_a_document_tree: bool,
4280
4281 pub(crate) tree_is_in_a_shadow_tree: bool,
4283}
4284
4285impl<'a> BindContext<'a> {
4286 pub(crate) fn new(parent: &'a Node) -> Self {
4288 BindContext {
4289 parent,
4290 tree_connected: parent.is_connected(),
4291 tree_is_in_a_document_tree: parent.is_in_a_document_tree(),
4292 tree_is_in_a_shadow_tree: parent.is_in_a_shadow_tree(),
4293 }
4294 }
4295
4296 pub(crate) fn is_in_tree(&self) -> bool {
4298 self.tree_is_in_a_document_tree || self.tree_is_in_a_shadow_tree
4299 }
4300}
4301
4302pub(crate) struct UnbindContext<'a> {
4305 index: Cell<Option<u32>>,
4307 pub(crate) parent: &'a Node,
4309 prev_sibling: Option<&'a Node>,
4311 pub(crate) next_sibling: Option<&'a Node>,
4313
4314 pub(crate) tree_connected: bool,
4318
4319 pub(crate) tree_is_in_a_document_tree: bool,
4323
4324 pub(crate) tree_is_in_a_shadow_tree: bool,
4326}
4327
4328impl<'a> UnbindContext<'a> {
4329 pub(crate) fn new(
4331 parent: &'a Node,
4332 prev_sibling: Option<&'a Node>,
4333 next_sibling: Option<&'a Node>,
4334 cached_index: Option<u32>,
4335 ) -> Self {
4336 UnbindContext {
4337 index: Cell::new(cached_index),
4338 parent,
4339 prev_sibling,
4340 next_sibling,
4341 tree_connected: parent.is_connected(),
4342 tree_is_in_a_document_tree: parent.is_in_a_document_tree(),
4343 tree_is_in_a_shadow_tree: parent.is_in_a_shadow_tree(),
4344 }
4345 }
4346
4347 #[allow(unsafe_code)]
4349 pub(crate) fn index(&self) -> u32 {
4350 if let Some(index) = self.index.get() {
4351 return index;
4352 }
4353 let index = self.prev_sibling.map_or(0, |sibling| sibling.index() + 1);
4354 self.index.set(Some(index));
4355 index
4356 }
4357}
4358
4359pub(crate) struct UniqueId {
4361 cell: UnsafeCell<Option<Box<Uuid>>>,
4362}
4363
4364unsafe_no_jsmanaged_fields!(UniqueId);
4365
4366impl MallocSizeOf for UniqueId {
4367 #[allow(unsafe_code)]
4368 fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
4369 if let Some(uuid) = unsafe { &*self.cell.get() } {
4370 unsafe { ops.malloc_size_of(&**uuid) }
4371 } else {
4372 0
4373 }
4374 }
4375}
4376
4377impl UniqueId {
4378 fn new() -> UniqueId {
4380 UniqueId {
4381 cell: UnsafeCell::new(None),
4382 }
4383 }
4384
4385 #[allow(unsafe_code)]
4387 fn borrow(&self) -> &Uuid {
4388 unsafe {
4389 let ptr = self.cell.get();
4390 if (*ptr).is_none() {
4391 *ptr = Some(Box::new(Uuid::new_v4()));
4392 }
4393 (*ptr).as_ref().unwrap()
4394 }
4395 }
4396}
4397
4398pub(crate) struct NodeTypeIdWrapper(pub(crate) NodeTypeId);
4399
4400impl From<NodeTypeIdWrapper> for LayoutNodeType {
4401 #[inline(always)]
4402 fn from(node_type: NodeTypeIdWrapper) -> LayoutNodeType {
4403 match node_type.0 {
4404 NodeTypeId::Element(e) => LayoutNodeType::Element(ElementTypeIdWrapper(e).into()),
4405 NodeTypeId::CharacterData(CharacterDataTypeId::Text(_)) => LayoutNodeType::Text,
4406 x => unreachable!("Layout should not traverse nodes of type {:?}", x),
4407 }
4408 }
4409}
4410
4411struct ElementTypeIdWrapper(ElementTypeId);
4412
4413impl From<ElementTypeIdWrapper> for LayoutElementType {
4414 #[inline(always)]
4415 fn from(element_type: ElementTypeIdWrapper) -> LayoutElementType {
4416 match element_type.0 {
4417 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLBodyElement) => {
4418 LayoutElementType::HTMLBodyElement
4419 },
4420 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLBRElement) => {
4421 LayoutElementType::HTMLBRElement
4422 },
4423 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLCanvasElement) => {
4424 LayoutElementType::HTMLCanvasElement
4425 },
4426 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLHtmlElement) => {
4427 LayoutElementType::HTMLHtmlElement
4428 },
4429 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLIFrameElement) => {
4430 LayoutElementType::HTMLIFrameElement
4431 },
4432 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLImageElement) => {
4433 LayoutElementType::HTMLImageElement
4434 },
4435 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLMediaElement(_)) => {
4436 LayoutElementType::HTMLMediaElement
4437 },
4438 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLInputElement) => {
4439 LayoutElementType::HTMLInputElement
4440 },
4441 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLOptGroupElement) => {
4442 LayoutElementType::HTMLOptGroupElement
4443 },
4444 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLOptionElement) => {
4445 LayoutElementType::HTMLOptionElement
4446 },
4447 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLObjectElement) => {
4448 LayoutElementType::HTMLObjectElement
4449 },
4450 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLParagraphElement) => {
4451 LayoutElementType::HTMLParagraphElement
4452 },
4453 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLPreElement) => {
4454 LayoutElementType::HTMLPreElement
4455 },
4456 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLSelectElement) => {
4457 LayoutElementType::HTMLSelectElement
4458 },
4459 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTableCellElement) => {
4460 LayoutElementType::HTMLTableCellElement
4461 },
4462 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTableColElement) => {
4463 LayoutElementType::HTMLTableColElement
4464 },
4465 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTableElement) => {
4466 LayoutElementType::HTMLTableElement
4467 },
4468 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTableRowElement) => {
4469 LayoutElementType::HTMLTableRowElement
4470 },
4471 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTableSectionElement) => {
4472 LayoutElementType::HTMLTableSectionElement
4473 },
4474 ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTextAreaElement) => {
4475 LayoutElementType::HTMLTextAreaElement
4476 },
4477 ElementTypeId::SVGElement(SVGElementTypeId::SVGGraphicsElement(
4478 SVGGraphicsElementTypeId::SVGImageElement,
4479 )) => LayoutElementType::SVGImageElement,
4480 ElementTypeId::SVGElement(SVGElementTypeId::SVGGraphicsElement(
4481 SVGGraphicsElementTypeId::SVGSVGElement,
4482 )) => LayoutElementType::SVGSVGElement,
4483 _ => LayoutElementType::Element,
4484 }
4485 }
4486}
4487
4488pub(crate) trait VecPreOrderInsertionHelper<T> {
4491 fn insert_pre_order(&mut self, elem: &T, tree_root: &Node);
4492}
4493
4494impl<T> VecPreOrderInsertionHelper<T> for Vec<Dom<T>>
4495where
4496 T: DerivedFrom<Node> + DomObject,
4497{
4498 fn insert_pre_order(&mut self, elem: &T, tree_root: &Node) {
4508 if self.is_empty() {
4509 self.push(Dom::from_ref(elem));
4510 return;
4511 }
4512
4513 let elem_node = elem.upcast::<Node>();
4514 let mut head: usize = 0;
4515 for node in tree_root.traverse_preorder(ShadowIncluding::No) {
4516 let head_node = DomRoot::upcast::<Node>(DomRoot::from_ref(&*self[head]));
4517 if head_node == node {
4518 head += 1;
4519 }
4520 if elem_node == &*node || head == self.len() {
4521 break;
4522 }
4523 }
4524 self.insert(head, Dom::from_ref(elem));
4525 }
4526}