1use std::cell::{LazyCell, RefCell};
6use std::cmp::{Ordering, PartialOrd};
7use std::iter;
8use std::rc::Rc;
9
10use app_units::Au;
11use dom_struct::dom_struct;
12use euclid::Rect;
13use js::context::{JSContext, NoGC};
14use js::jsapi::JSTracer;
15use js::rust::HandleObject;
16use script_bindings::cell::DomRefCell;
17use script_bindings::dom::UnrootedDom;
18use script_bindings::reflector::reflect_weak_referenceable_dom_object_with_proto;
19use smallvec::SmallVec;
20use style_traits::CSSPixel;
21
22use crate::dom::abstractrange::{AbstractRange, BoundaryPoint, bp_position};
23use crate::dom::bindings::codegen::Bindings::AbstractRangeBinding::AbstractRangeMethods;
24use crate::dom::bindings::codegen::Bindings::CharacterDataBinding::CharacterDataMethods;
25use crate::dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
26use crate::dom::bindings::codegen::Bindings::NodeListBinding::NodeListMethods;
27use crate::dom::bindings::codegen::Bindings::RangeBinding::{RangeConstants, RangeMethods};
28use crate::dom::bindings::codegen::Bindings::TextBinding::TextMethods;
29use crate::dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
30use crate::dom::bindings::codegen::UnionTypes::TrustedHTMLOrString;
31use crate::dom::bindings::error::{Error, ErrorResult, Fallible};
32use crate::dom::bindings::inheritance::{Castable, CharacterDataTypeId, NodeTypeId};
33use crate::dom::bindings::root::{Dom, DomRoot};
34use crate::dom::bindings::str::DOMString;
35use crate::dom::bindings::trace::JSTraceable;
36use crate::dom::bindings::weakref::{WeakRef, WeakRefVec};
37use crate::dom::characterdata::CharacterData;
38use crate::dom::document::Document;
39use crate::dom::documentfragment::DocumentFragment;
40use crate::dom::domrect::DOMRect;
41use crate::dom::domrectlist::DOMRectList;
42use crate::dom::element::Element;
43use crate::dom::html::htmlscriptelement::HTMLScriptElement;
44use crate::dom::iterators::ShadowIncluding;
45use crate::dom::node::{Node, NodeTraits};
46use crate::dom::selection::{Selection, SelectionLiveRangeNotification};
47use crate::dom::text::Text;
48use crate::dom::trustedtypes::trustedhtml::TrustedHTML;
49use crate::dom::window::Window;
50
51#[dom_struct]
52pub(crate) struct Range {
53 abstract_range: AbstractRange,
54 associated_selections: DomRefCell<Vec<Dom<Selection>>>,
64}
65
66pub(crate) struct ContainedChildren {
67 pub(crate) first_partially_contained_child: Option<DomRoot<Node>>,
68 pub(crate) last_partially_contained_child: Option<DomRoot<Node>>,
69 pub(crate) contained_children: Vec<DomRoot<Node>>,
70}
71
72impl Range {
73 fn new_inherited(
74 start_container: &Node,
75 start_offset: u32,
76 end_container: &Node,
77 end_offset: u32,
78 ) -> Range {
79 debug_assert!(start_offset <= start_container.len());
80 debug_assert!(end_offset <= end_container.len());
81 Range {
82 abstract_range: AbstractRange::new_inherited(
83 start_container,
84 start_offset,
85 end_container,
86 end_offset,
87 ),
88 associated_selections: DomRefCell::new(vec![]),
89 }
90 }
91
92 pub(crate) fn new_with_doc(
93 cx: &mut JSContext,
94 document: &Document,
95 proto: Option<HandleObject>,
96 ) -> DomRoot<Range> {
97 let root = document.upcast();
98 Range::new_with_proto(cx, document, proto, root, 0, root, 0)
99 }
100
101 pub(crate) fn new(
102 cx: &mut JSContext,
103 document: &Document,
104 start_container: &Node,
105 start_offset: u32,
106 end_container: &Node,
107 end_offset: u32,
108 ) -> DomRoot<Range> {
109 Self::new_with_proto(
110 cx,
111 document,
112 None,
113 start_container,
114 start_offset,
115 end_container,
116 end_offset,
117 )
118 }
119
120 fn new_with_proto(
121 cx: &mut JSContext,
122 document: &Document,
123 proto: Option<HandleObject>,
124 start_container: &Node,
125 start_offset: u32,
126 end_container: &Node,
127 end_offset: u32,
128 ) -> DomRoot<Range> {
129 let range = reflect_weak_referenceable_dom_object_with_proto(
130 cx,
131 Rc::new(Range::new_inherited(
132 start_container,
133 start_offset,
134 end_container,
135 end_offset,
136 )),
137 document.window(),
138 proto,
139 );
140 start_container
141 .ensure_weak_ranges()
142 .push(WeakRef::new(&range));
143 if start_container != end_container {
144 end_container
145 .ensure_weak_ranges()
146 .push(WeakRef::new(&range));
147 }
148 range
149 }
150
151 pub(crate) fn root(&self) -> DomRoot<Node> {
155 self.start_container().GetRootNode(&Default::default())
156 }
157
158 pub(crate) fn contains(&self, node: &Node) -> bool {
160 node.GetRootNode(&Default::default()) == self.root() &&
163 matches!(
164 (
165 bp_position(node, 0, &self.start_container(), self.start_offset()),
166 bp_position(node, node.len(), &self.end_container(), self.end_offset()),
167 ),
168 (Ordering::Greater, Ordering::Less)
169 )
170 }
171
172 fn partially_contains(&self, node: &Node) -> bool {
174 self.start_container()
177 .inclusive_ancestors(ShadowIncluding::No)
178 .any(|n| &*n == node) !=
179 self.end_container()
180 .inclusive_ancestors(ShadowIncluding::No)
181 .any(|n| &*n == node)
182 }
183
184 pub(crate) fn contained_children(&self) -> Fallible<ContainedChildren> {
186 let start_node = self.start_container();
187 let end_node = self.end_container();
188 let common_ancestor = self.CommonAncestorContainer();
190
191 let first_partially_contained_child = if start_node.is_inclusive_ancestor_of(&end_node) {
192 None
194 } else {
195 common_ancestor
197 .children()
198 .find(|node| Range::partially_contains(self, node))
199 };
200
201 let last_partially_contained_child = if end_node.is_inclusive_ancestor_of(&start_node) {
202 None
204 } else {
205 common_ancestor
207 .rev_children()
208 .find(|node| Range::partially_contains(self, node))
209 };
210
211 let contained_children: Vec<DomRoot<Node>> = common_ancestor
213 .children()
214 .filter(|n| self.contains(n))
215 .collect();
216
217 if contained_children.iter().any(|n| n.is_doctype()) {
219 return Err(Error::HierarchyRequest(None));
220 }
221
222 Ok(ContainedChildren {
223 first_partially_contained_child,
224 last_partially_contained_child,
225 contained_children,
226 })
227 }
228
229 pub(crate) fn set_start(&self, node: &Node, offset: u32) {
231 if self.set_start_without_reporting(node, offset) {
232 self.report_change(SelectionLiveRangeNotification::Start);
233 }
234 }
235
236 pub(crate) fn set_start_without_reporting(&self, node: &Node, offset: u32) -> bool {
237 if self.start().node() == node && self.start_offset() == offset {
238 return false;
239 }
240
241 if self.start().node() != node {
242 if self.start().node() == self.end().node() {
243 node.ensure_weak_ranges().push(WeakRef::new(self));
244 } else if self.end().node() == node {
245 self.start_container().ensure_weak_ranges().remove(self);
246 } else {
247 node.ensure_weak_ranges()
248 .push(self.start_container().ensure_weak_ranges().remove(self));
249 }
250 }
251
252 self.start().set(node, offset);
253 true
254 }
255
256 pub(crate) fn set_end(&self, node: &Node, offset: u32) {
258 if self.set_end_without_reporting(node, offset) {
259 self.report_change(SelectionLiveRangeNotification::End);
260 }
261 }
262
263 pub(crate) fn set_end_without_reporting(&self, node: &Node, offset: u32) -> bool {
264 if self.end().node() == node && self.end_offset() == offset {
265 return false;
266 }
267 if self.end().node() != node {
268 if self.end().node() == self.start().node() {
269 node.ensure_weak_ranges().push(WeakRef::new(self));
270 } else if self.start().node() == node {
271 self.end_container().ensure_weak_ranges().remove(self);
272 } else {
273 node.ensure_weak_ranges()
274 .push(self.end_container().ensure_weak_ranges().remove(self));
275 }
276 }
277
278 self.end().set(node, offset);
279 true
280 }
281
282 fn compare_point(&self, node: &Node, offset: u32) -> Fallible<Ordering> {
284 if node.GetRootNode(&Default::default()) != self.root() {
287 return Err(Error::WrongDocument(None));
288 }
289 if node.is_doctype() {
292 return Err(Error::InvalidNodeType(None));
293 }
294 if offset > node.len() {
297 return Err(Error::IndexSize(None));
298 }
299 let start_node = self.start_container();
301 if let Ordering::Less = bp_position(node, offset, &start_node, self.start_offset()) {
302 return Ok(Ordering::Less);
303 }
304 if let Ordering::Greater =
306 bp_position(node, offset, &self.end_container(), self.end_offset())
307 {
308 return Ok(Ordering::Greater);
309 }
310 Ok(Ordering::Equal)
312 }
313
314 pub(crate) fn associate_selection(&self, selection: &Selection) {
315 let mut selections = self.associated_selections.borrow_mut();
316 if !selections.iter().any(|s| &**s == selection) {
317 selections.push(Dom::from_ref(selection));
318 }
319 }
320
321 pub(crate) fn disassociate_selection(&self, selection: &Selection) {
322 self.associated_selections
323 .borrow_mut()
324 .retain(|s| &**s != selection);
325 }
326
327 pub(crate) fn report_change(&self, notification: SelectionLiveRangeNotification) {
328 if notification.is_empty() {
329 return;
330 }
331
332 self.associated_selections
333 .borrow()
334 .iter()
335 .for_each(|selection| {
336 selection.update_from_live_range(self, notification);
337 });
338 }
339
340 fn abstract_range(&self) -> &AbstractRange {
341 &self.abstract_range
342 }
343
344 pub(crate) fn start(&self) -> &BoundaryPoint {
345 self.abstract_range().start()
346 }
347
348 pub(crate) fn end(&self) -> &BoundaryPoint {
349 self.abstract_range().end()
350 }
351
352 pub(crate) fn start_container(&self) -> DomRoot<Node> {
353 self.abstract_range().StartContainer()
354 }
355
356 pub(crate) fn start_offset(&self) -> u32 {
357 self.abstract_range().StartOffset()
358 }
359
360 pub(crate) fn end_container(&self) -> DomRoot<Node> {
361 self.abstract_range().EndContainer()
362 }
363
364 pub(crate) fn end_offset(&self) -> u32 {
365 self.abstract_range().EndOffset()
366 }
367
368 pub(crate) fn collapsed(&self) -> bool {
369 self.abstract_range().Collapsed()
370 }
371
372 fn client_rects(&self, no_gc: &NoGC) -> Vec<Rect<Au, CSSPixel>> {
374 let start = self.start_container();
377 let end = self.end_container();
378 if !start.is_connected() || !end.is_connected() {
381 return vec![];
382 }
383
384 if self.collapsed() {
387 if start.is::<CharacterData>() {
388 return start.border_boxes();
389 } else {
390 return vec![];
391 }
392 }
393
394 let document = start.owner_doc();
395 let end_clone = UnrootedDom::from_dom(Dom::from_ref(&*end), no_gc);
396 start
397 .following_nodes_unrooted(no_gc, document.upcast::<Node>(), ShadowIncluding::No)
398 .take_while(move |node| *node != *end)
399 .chain(iter::once(end_clone))
400 .flat_map(move |node| node.border_boxes())
401 .collect()
402 }
403
404 fn set_the_start_or_end(
406 &self,
407 node: &Node,
408 offset: u32,
409 start_or_end: StartOrEnd,
410 ) -> ErrorResult {
411 if node.is_doctype() {
414 return Err(Error::InvalidNodeType(None));
415 }
416
417 if offset > node.len() {
420 return Err(Error::IndexSize(None));
421 }
422
423 let mut notification = SelectionLiveRangeNotification::empty();
426 match start_or_end {
427 StartOrEnd::Start => {
429 if self.root() != node.GetRootNode(&Default::default()) ||
432 bp_position(node, offset, &self.end_container(), self.end_offset()) ==
433 Ordering::Greater
434 {
435 notification.set(
436 SelectionLiveRangeNotification::End,
437 self.set_end_without_reporting(node, offset),
438 );
439 }
440
441 notification.set(
443 SelectionLiveRangeNotification::Start,
444 self.set_start_without_reporting(node, offset),
445 );
446 },
447 StartOrEnd::End => {
449 if self.root() != node.GetRootNode(&Default::default()) ||
452 bp_position(node, offset, &self.start_container(), self.start_offset()) ==
453 Ordering::Less
454 {
455 notification.set(
456 SelectionLiveRangeNotification::Start,
457 self.set_start_without_reporting(node, offset),
458 );
459 }
460
461 notification.set(
463 SelectionLiveRangeNotification::End,
464 self.set_end_without_reporting(node, offset),
465 );
466 },
467 }
468
469 self.report_change(notification);
470 Ok(())
471 }
472}
473
474impl std::fmt::Debug for Range {
475 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
476 write!(
477 f,
478 "[({:?}, {}) -> ({:?}, {})]",
479 self.start_container(),
480 self.start_offset(),
481 self.end_container(),
482 self.end_offset()
483 )
484 }
485}
486
487#[derive(Copy, Clone)]
488pub(crate) enum StartOrEnd {
489 Start,
490 End,
491}
492
493impl RangeMethods<crate::DomTypeHolder> for Range {
494 fn Constructor(
496 cx: &mut JSContext,
497 window: &Window,
498 proto: Option<HandleObject>,
499 ) -> Fallible<DomRoot<Range>> {
500 let document = window.Document();
501 Ok(Range::new_with_doc(cx, &document, proto))
502 }
503
504 fn CommonAncestorContainer(&self) -> DomRoot<Node> {
506 self.end_container()
507 .common_ancestor(&self.start_container(), ShadowIncluding::No)
508 .expect("Couldn't find common ancestor container")
509 }
510
511 fn SetStart(&self, node: &Node, offset: u32) -> ErrorResult {
513 self.set_the_start_or_end(node, offset, StartOrEnd::Start)
514 }
515
516 fn SetEnd(&self, node: &Node, offset: u32) -> ErrorResult {
518 self.set_the_start_or_end(node, offset, StartOrEnd::End)
519 }
520
521 fn SetStartBefore(&self, node: &Node) -> ErrorResult {
523 let parent = node.GetParentNode().ok_or(Error::InvalidNodeType(None))?;
524 self.SetStart(&parent, node.index())
525 }
526
527 fn SetStartAfter(&self, node: &Node) -> ErrorResult {
529 let parent = node.GetParentNode().ok_or(Error::InvalidNodeType(None))?;
530 self.SetStart(&parent, node.index() + 1)
531 }
532
533 fn SetEndBefore(&self, node: &Node) -> ErrorResult {
535 let parent = node.GetParentNode().ok_or(Error::InvalidNodeType(None))?;
536 self.SetEnd(&parent, node.index())
537 }
538
539 fn SetEndAfter(&self, node: &Node) -> ErrorResult {
541 let parent = node.GetParentNode().ok_or(Error::InvalidNodeType(None))?;
542 self.SetEnd(&parent, node.index() + 1)
543 }
544
545 fn Collapse(&self, to_start: bool) {
547 if to_start {
548 self.set_end(&self.start_container(), self.start_offset());
549 } else {
550 self.set_start(&self.end_container(), self.end_offset());
551 }
552 }
553
554 fn SelectNode(&self, node: &Node) -> ErrorResult {
556 let parent = node.GetParentNode().ok_or(Error::InvalidNodeType(None))?;
558 let index = node.index();
560 self.set_start(&parent, index);
562 self.set_end(&parent, index + 1);
564 Ok(())
565 }
566
567 fn SelectNodeContents(&self, node: &Node) -> ErrorResult {
569 if node.is_doctype() {
570 return Err(Error::InvalidNodeType(None));
572 }
573 let length = node.len();
575 self.set_start(node, 0);
577 self.set_end(node, length);
579 Ok(())
580 }
581
582 fn CompareBoundaryPoints(&self, how: u16, source_range: &Range) -> Fallible<i16> {
584 if how > RangeConstants::END_TO_START {
591 return Err(Error::NotSupported(None));
592 }
593 if self.root() != source_range.root() {
596 return Err(Error::WrongDocument(None));
597 }
598 let (this_point, source_point) = match how {
609 RangeConstants::START_TO_START => (self.start(), source_range.start()),
610 RangeConstants::START_TO_END => (self.end(), source_range.start()),
611 RangeConstants::END_TO_END => (self.end(), source_range.end()),
612 RangeConstants::END_TO_START => (self.start(), source_range.end()),
613 _ => unreachable!(),
614 };
615 match this_point.partial_cmp(source_point).unwrap() {
623 Ordering::Less => Ok(-1),
624 Ordering::Equal => Ok(0),
625 Ordering::Greater => Ok(1),
626 }
627 }
628
629 fn CloneRange(&self, cx: &mut JSContext) -> DomRoot<Range> {
631 let start_node = self.start_container();
632 let owner_doc = start_node.owner_doc();
633 Range::new(
634 cx,
635 &owner_doc,
636 &start_node,
637 self.start_offset(),
638 &self.end_container(),
639 self.end_offset(),
640 )
641 }
642
643 fn IsPointInRange(&self, node: &Node, offset: u32) -> Fallible<bool> {
645 match self.compare_point(node, offset) {
646 Ok(Ordering::Less) => Ok(false),
647 Ok(Ordering::Equal) => Ok(true),
648 Ok(Ordering::Greater) => Ok(false),
649 Err(Error::WrongDocument(None)) => {
650 Ok(false)
653 },
654 Err(error) => Err(error),
655 }
656 }
657
658 fn ComparePoint(&self, node: &Node, offset: u32) -> Fallible<i16> {
660 self.compare_point(node, offset).map(|order| match order {
661 Ordering::Less => -1,
662 Ordering::Equal => 0,
663 Ordering::Greater => 1,
664 })
665 }
666
667 fn IntersectsNode(&self, node: &Node) -> bool {
669 if self.root() != node.GetRootNode(&Default::default()) {
671 return false;
672 }
673 let Some(parent) = node.GetParentNode() else {
675 return true;
677 };
678 let offset = node.index();
680 let start_node = self.start_container();
684 Ordering::Greater == bp_position(&parent, offset + 1, &start_node, self.start_offset()) &&
685 Ordering::Less ==
686 bp_position(&parent, offset, &self.end_container(), self.end_offset())
687 }
688
689 fn CloneContents(&self, cx: &mut JSContext) -> Fallible<DomRoot<DocumentFragment>> {
692 let start_node = self.start_container();
694 let start_offset = self.start_offset();
695 let end_node = self.end_container();
696 let end_offset = self.end_offset();
697
698 let fragment = DocumentFragment::new(cx, &start_node.owner_doc());
700
701 if self.start() == self.end() {
703 return Ok(fragment);
704 }
705
706 if end_node == start_node &&
707 let Some(cdata) = start_node.downcast::<CharacterData>()
708 {
709 let data = cdata
711 .SubstringData(start_offset, end_offset - start_offset)
712 .unwrap();
713 let clone = cdata.clone_with_data(cx, data, &start_node.owner_doc());
714 fragment.upcast::<Node>().AppendChild(cx, &clone)?;
716 return Ok(fragment);
718 }
719
720 let ContainedChildren {
722 first_partially_contained_child,
723 last_partially_contained_child,
724 contained_children,
725 } = self.contained_children()?;
726
727 if let Some(child) = first_partially_contained_child {
728 if let Some(cdata) = child.downcast::<CharacterData>() {
730 assert!(child == start_node);
731 let data = cdata
733 .SubstringData(start_offset, start_node.len() - start_offset)
734 .unwrap();
735 let clone = cdata.clone_with_data(cx, data, &start_node.owner_doc());
736 fragment.upcast::<Node>().AppendChild(cx, &clone)?;
738 } else {
739 let clone = child.CloneNode(cx, false)?;
741 fragment.upcast::<Node>().AppendChild(cx, &clone)?;
743 let subrange = Range::new(
745 cx,
746 &clone.owner_doc(),
747 &start_node,
748 start_offset,
749 &child,
750 child.len(),
751 );
752 let subfragment = subrange.CloneContents(cx)?;
754 clone.AppendChild(cx, subfragment.upcast())?;
756 }
757 }
758
759 for child in contained_children {
761 let clone = child.CloneNode(cx, true)?;
763 fragment.upcast::<Node>().AppendChild(cx, &clone)?;
765 }
766
767 if let Some(child) = last_partially_contained_child {
768 if let Some(cdata) = child.downcast::<CharacterData>() {
770 assert!(child == end_node);
771 let data = cdata.SubstringData(0, end_offset).unwrap();
773 let clone = cdata.clone_with_data(cx, data, &start_node.owner_doc());
774 fragment.upcast::<Node>().AppendChild(cx, &clone)?;
776 } else {
777 let clone = child.CloneNode(cx, false)?;
779 fragment.upcast::<Node>().AppendChild(cx, &clone)?;
781 let subrange = Range::new(cx, &clone.owner_doc(), &child, 0, &end_node, end_offset);
783 let subfragment = subrange.CloneContents(cx)?;
785 clone.AppendChild(cx, subfragment.upcast())?;
787 }
788 }
789
790 Ok(fragment)
792 }
793
794 fn ExtractContents(&self, cx: &mut JSContext) -> Fallible<DomRoot<DocumentFragment>> {
797 let start_node = self.start_container();
799 let start_offset = self.start_offset();
800 let end_node = self.end_container();
801 let end_offset = self.end_offset();
802
803 let fragment = DocumentFragment::new(cx, &start_node.owner_doc());
805
806 if self.collapsed() {
808 return Ok(fragment);
809 }
810
811 if end_node == start_node &&
812 let Some(end_data) = end_node.downcast::<CharacterData>()
813 {
814 let clone = end_node.CloneNode(cx, true)?;
816 let text = end_data.SubstringData(start_offset, end_offset - start_offset);
818 clone
819 .downcast::<CharacterData>()
820 .unwrap()
821 .SetData(cx, text.unwrap());
822 fragment.upcast::<Node>().AppendChild(cx, &clone)?;
824 end_data.ReplaceData(
826 cx,
827 start_offset,
828 end_offset - start_offset,
829 DOMString::new(),
830 )?;
831 return Ok(fragment);
833 }
834
835 let ContainedChildren {
837 first_partially_contained_child,
838 last_partially_contained_child,
839 contained_children,
840 } = self.contained_children()?;
841
842 let (new_node, new_offset) = if start_node.is_inclusive_ancestor_of(&end_node) {
843 (DomRoot::from_ref(&*start_node), start_offset)
845 } else {
846 let reference_node = start_node
848 .ancestors()
849 .take_while(|n| !n.is_inclusive_ancestor_of(&end_node))
850 .last()
851 .unwrap_or(DomRoot::from_ref(&start_node));
852 (
854 reference_node.GetParentNode().unwrap(),
855 reference_node.index() + 1,
856 )
857 };
858
859 if let Some(child) = first_partially_contained_child {
860 if let Some(start_data) = child.downcast::<CharacterData>() {
861 assert!(child == start_node);
862 let clone = start_node.CloneNode(cx, true)?;
864 let text = start_data.SubstringData(start_offset, start_node.len() - start_offset);
866 clone
867 .downcast::<CharacterData>()
868 .unwrap()
869 .SetData(cx, text.unwrap());
870 fragment.upcast::<Node>().AppendChild(cx, &clone)?;
872 start_data.ReplaceData(
874 cx,
875 start_offset,
876 start_node.len() - start_offset,
877 DOMString::new(),
878 )?;
879 } else {
880 let clone = child.CloneNode(cx, false)?;
882 fragment.upcast::<Node>().AppendChild(cx, &clone)?;
884 let subrange = Range::new(
886 cx,
887 &clone.owner_doc(),
888 &start_node,
889 start_offset,
890 &child,
891 child.len(),
892 );
893 let subfragment = subrange.ExtractContents(cx)?;
895 clone.AppendChild(cx, subfragment.upcast())?;
897 }
898 }
899
900 for child in contained_children {
902 fragment.upcast::<Node>().AppendChild(cx, &child)?;
903 }
904
905 if let Some(child) = last_partially_contained_child {
906 if let Some(end_data) = child.downcast::<CharacterData>() {
907 assert!(child == end_node);
908 let clone = end_node.CloneNode(cx, true)?;
910 let text = end_data.SubstringData(0, end_offset);
912 clone
913 .downcast::<CharacterData>()
914 .unwrap()
915 .SetData(cx, text.unwrap());
916 fragment.upcast::<Node>().AppendChild(cx, &clone)?;
918 end_data.ReplaceData(cx, 0, end_offset, DOMString::new())?;
920 } else {
921 let clone = child.CloneNode(cx, false)?;
923 fragment.upcast::<Node>().AppendChild(cx, &clone)?;
925 let subrange = Range::new(cx, &clone.owner_doc(), &child, 0, &end_node, end_offset);
927 let subfragment = subrange.ExtractContents(cx)?;
929 clone.AppendChild(cx, subfragment.upcast())?;
931 }
932 }
933
934 self.SetStart(&new_node, new_offset)?;
936 self.SetEnd(&new_node, new_offset)?;
937
938 Ok(fragment)
940 }
941
942 fn Detach(&self) {
944 }
946
947 fn InsertNode(&self, cx: &mut JSContext, node: &Node) -> ErrorResult {
950 let start_node = self.start_container();
951 let start_offset = self.start_offset();
952
953 if &*start_node == node {
955 return Err(Error::HierarchyRequest(None));
956 }
957 match start_node.type_id() {
958 NodeTypeId::CharacterData(CharacterDataTypeId::Text(_)) => (),
960 NodeTypeId::CharacterData(_) => return Err(Error::HierarchyRequest(None)),
961 _ => (),
962 }
963
964 let (reference_node, parent) = match start_node.type_id() {
966 NodeTypeId::CharacterData(CharacterDataTypeId::Text(_)) => {
967 let parent = match start_node.GetParentNode() {
969 Some(parent) => parent,
970 None => return Err(Error::HierarchyRequest(None)),
972 };
973 (Some(DomRoot::from_ref(&*start_node)), parent)
975 },
976 _ => {
977 let child = start_node.ChildNodes(cx).Item(cx, start_offset);
979 (child, DomRoot::from_ref(&*start_node))
980 },
981 };
982
983 Node::ensure_pre_insertion_validity(cx.no_gc(), node, &parent, reference_node.as_deref())?;
985
986 let split_text;
988 let reference_node = match start_node.downcast::<Text>() {
989 Some(text) => {
990 split_text = text.SplitText(cx, start_offset)?;
991 let new_reference = DomRoot::upcast::<Node>(split_text);
992 assert!(new_reference.GetParentNode().as_deref() == Some(&parent));
993 Some(new_reference)
994 },
995 _ => reference_node,
996 };
997
998 let reference_node = if Some(node) == reference_node.as_deref() {
1000 node.GetNextSibling()
1001 } else {
1002 reference_node
1003 };
1004
1005 node.remove_self(cx);
1007
1008 let new_offset = reference_node
1010 .as_ref()
1011 .map_or(parent.len(), |node| node.index());
1012
1013 let new_offset = new_offset +
1015 if let NodeTypeId::DocumentFragment(_) = node.type_id() {
1016 node.len()
1017 } else {
1018 1
1019 };
1020
1021 Node::pre_insert(cx, node, &parent, reference_node.as_deref())?;
1023
1024 if self.collapsed() {
1026 self.set_end(&parent, new_offset);
1027 }
1028
1029 Ok(())
1030 }
1031
1032 fn DeleteContents(&self, cx: &mut JSContext) -> ErrorResult {
1034 if self.collapsed() {
1036 return Ok(());
1037 }
1038
1039 let start_node = self.start_container();
1042 let end_node = self.end_container();
1043 let start_offset = self.start_offset();
1044 let end_offset = self.end_offset();
1045
1046 if start_node == end_node &&
1048 let Some(text) = start_node.downcast::<CharacterData>()
1049 {
1050 return text.ReplaceData(
1054 cx,
1055 start_offset,
1056 end_offset - start_offset,
1057 DOMString::new(),
1058 );
1059 }
1060
1061 rooted_vec!(let mut contained_children);
1064 let ancestor = self.CommonAncestorContainer();
1065
1066 let mut iter = start_node.following_nodes(&ancestor, ShadowIncluding::No);
1067
1068 let mut next = iter.next();
1069 while let Some(child) = next {
1070 if self.contains(&child) {
1071 contained_children.push(Dom::from_ref(&*child));
1072 next = iter.next_skipping_children();
1073 } else {
1074 next = iter.next();
1075 }
1076 }
1077
1078 let (new_node, new_offset) = if start_node.is_inclusive_ancestor_of(&end_node) {
1082 (DomRoot::from_ref(&*start_node), start_offset)
1083 } else {
1084 fn compute_reference(start_node: &Node, end_node: &Node) -> (DomRoot<Node>, u32) {
1086 let mut reference_node = DomRoot::from_ref(start_node);
1088 while let Some(parent) = reference_node.GetParentNode() {
1091 if parent.is_inclusive_ancestor_of(end_node) {
1092 return (parent, reference_node.index() + 1);
1094 }
1095 reference_node = parent;
1096 }
1097 unreachable!()
1098 }
1099
1100 compute_reference(&start_node, &end_node)
1101 };
1102
1103 self.SetStart(&new_node, new_offset).unwrap();
1105 self.SetEnd(&new_node, new_offset).unwrap();
1106
1107 if let Some(text) = start_node.downcast::<CharacterData>() {
1111 text.ReplaceData(
1112 cx,
1113 start_offset,
1114 start_node.len() - start_offset,
1115 DOMString::new(),
1116 )
1117 .unwrap();
1118 }
1119
1120 for child in &*contained_children {
1122 child.remove_self(cx);
1123 }
1124
1125 if let Some(text) = end_node.downcast::<CharacterData>() {
1128 text.ReplaceData(cx, 0, end_offset, DOMString::new())
1129 .unwrap();
1130 }
1131
1132 Ok(())
1133 }
1134
1135 fn SurroundContents(&self, cx: &mut JSContext, new_parent: &Node) -> ErrorResult {
1137 let start = self.start_container();
1139 let end = self.end_container();
1140
1141 if start
1142 .inclusive_ancestors(ShadowIncluding::No)
1143 .any(|n| !n.is_inclusive_ancestor_of(&end) && !n.is::<Text>()) ||
1144 end.inclusive_ancestors(ShadowIncluding::No)
1145 .any(|n| !n.is_inclusive_ancestor_of(&start) && !n.is::<Text>())
1146 {
1147 return Err(Error::InvalidState(None));
1148 }
1149
1150 match new_parent.type_id() {
1152 NodeTypeId::Document(_) |
1153 NodeTypeId::DocumentType |
1154 NodeTypeId::DocumentFragment(_) => {
1155 return Err(Error::InvalidNodeType(None));
1156 },
1157 _ => (),
1158 }
1159
1160 let fragment = self.ExtractContents(cx)?;
1162
1163 Node::replace_all(cx, None, new_parent);
1165
1166 self.InsertNode(cx, new_parent)?;
1168
1169 new_parent.AppendChild(cx, fragment.upcast())?;
1171
1172 self.SelectNode(new_parent)
1174 }
1175
1176 fn Stringifier(&self, no_gc: &NoGC) -> DOMString {
1178 let start_node = self.start_container();
1179 let end_node = self.end_container();
1180
1181 let mut s = DOMString::new();
1183
1184 if let Some(text_node) = start_node.downcast::<Text>() {
1185 let char_data = text_node.upcast::<CharacterData>();
1186
1187 if start_node == end_node {
1191 return char_data
1192 .SubstringData(self.start_offset(), self.end_offset() - self.start_offset())
1193 .unwrap();
1194 }
1195
1196 s.push_str(
1199 &char_data
1200 .SubstringData(
1201 self.start_offset(),
1202 char_data.Length() - self.start_offset(),
1203 )
1204 .unwrap()
1205 .str(),
1206 );
1207 }
1208
1209 let ancestor = self.CommonAncestorContainer();
1212 let iter = start_node
1213 .following_nodes_unrooted(no_gc, &ancestor, ShadowIncluding::No)
1214 .filter_map(UnrootedDom::downcast::<Text>);
1215
1216 for child in iter {
1217 if self.contains(child.upcast()) {
1218 s.push_str(&child.upcast::<CharacterData>().Data().str());
1219 }
1220 }
1221
1222 if let Some(text_node) = end_node.downcast::<Text>() {
1225 let char_data = text_node.upcast::<CharacterData>();
1226 s.push_str(&char_data.SubstringData(0, self.end_offset()).unwrap().str());
1227 }
1228
1229 s
1231 }
1232
1233 fn CreateContextualFragment(
1235 &self,
1236 cx: &mut JSContext,
1237 fragment: TrustedHTMLOrString,
1238 ) -> Fallible<DomRoot<DocumentFragment>> {
1239 let node = self.start_container();
1244
1245 let fragment = TrustedHTML::get_trusted_type_compliant_string(
1249 cx,
1250 node.owner_window().upcast(),
1251 fragment,
1252 "Range createContextualFragment",
1253 )?;
1254
1255 let owner_doc = node.owner_doc();
1256
1257 let element = match node.type_id() {
1261 NodeTypeId::Element(_) => Some(DomRoot::downcast::<Element>(node).unwrap()),
1262 NodeTypeId::CharacterData(CharacterDataTypeId::Comment) |
1263 NodeTypeId::CharacterData(CharacterDataTypeId::Text(_)) => node.GetParentElement(),
1264 _ => None,
1265 };
1266
1267 let element = Element::fragment_parsing_context(cx, &owner_doc, element.as_deref());
1269
1270 let fragment_node = element.parse_fragment(fragment, cx)?;
1272
1273 for node in fragment_node
1275 .upcast::<Node>()
1276 .traverse_preorder(ShadowIncluding::No)
1277 {
1278 if let Some(script) = node.downcast::<HTMLScriptElement>() {
1279 script.set_already_started(false);
1281 script.set_parser_inserted(false);
1283 }
1284 }
1285
1286 Ok(fragment_node)
1288 }
1289
1290 fn GetClientRects(&self, cx: &mut JSContext) -> DomRoot<DOMRectList> {
1292 let start = self.start_container();
1293 let window = start.owner_window();
1294
1295 let client_rects = self.client_rects(cx.no_gc());
1296 let client_rects = client_rects
1297 .iter()
1298 .map(|rect| {
1299 DOMRect::new(
1300 cx,
1301 window.upcast(),
1302 rect.origin.x.to_f64_px(),
1303 rect.origin.y.to_f64_px(),
1304 rect.size.width.to_f64_px(),
1305 rect.size.height.to_f64_px(),
1306 )
1307 })
1308 .collect();
1309
1310 DOMRectList::new(cx, &window, client_rects)
1311 }
1312
1313 fn GetBoundingClientRect(&self, cx: &mut JSContext) -> DomRoot<DOMRect> {
1315 let window = self.start_container().owner_window();
1316
1317 let list = self.client_rects(cx.no_gc());
1319
1320 let bounding_rect = list
1325 .into_iter()
1326 .fold(euclid::Rect::zero(), |acc, rect| acc.union(&rect));
1327
1328 DOMRect::new(
1329 cx,
1330 window.upcast(),
1331 bounding_rect.origin.x.to_f64_px(),
1332 bounding_rect.origin.y.to_f64_px(),
1333 bounding_rect.size.width.to_f64_px(),
1334 bounding_rect.size.height.to_f64_px(),
1335 )
1336 }
1337}
1338
1339#[derive(MallocSizeOf)]
1340pub(crate) struct WeakRangeVec {
1341 cell: RefCell<WeakRefVec<Range>>,
1342}
1343
1344impl Default for WeakRangeVec {
1345 fn default() -> Self {
1346 WeakRangeVec {
1347 cell: RefCell::new(WeakRefVec::new()),
1348 }
1349 }
1350}
1351
1352impl WeakRangeVec {
1353 pub(crate) fn is_empty(&self) -> bool {
1355 self.cell.borrow().is_empty()
1356 }
1357
1358 pub(crate) fn live_ranges(&self) -> SmallVec<[DomRoot<Range>; 4]> {
1360 let cell = self.cell.borrow();
1361 if cell.is_empty() {
1362 return Default::default();
1363 }
1364 cell.iter().filter_map(|range| range.root()).collect()
1365 }
1366
1367 pub(crate) fn push(&self, ref_: WeakRef<Range>) {
1368 self.cell.borrow_mut().push(ref_);
1369 }
1370
1371 fn remove(&self, range: &Range) -> WeakRef<Range> {
1372 let mut ranges = self.cell.borrow_mut();
1373 let position = ranges.iter().position(|ref_| ref_ == range).unwrap();
1374 ranges.swap_remove(position)
1375 }
1376}
1377
1378#[expect(unsafe_code)]
1379unsafe impl JSTraceable for WeakRangeVec {
1380 unsafe fn trace(&self, _: *mut JSTracer) {
1381 self.cell.borrow_mut().retain_alive()
1382 }
1383}
1384
1385pub(crate) fn live_range_insert_steps(parent: &Node, child: &Node, count: u32) {
1389 if parent.has_live_ranges() {
1390 let child_index = LazyCell::new(|| child.index());
1391 for range in parent.live_ranges() {
1392 if &*range.start_container() == parent && range.start_offset() > *child_index {
1395 range.set_start_without_reporting(parent, range.start_offset() + count);
1396 }
1397 if &*range.end_container() == parent && range.end_offset() > *child_index {
1400 range.set_end_without_reporting(parent, range.end_offset() + count);
1401 }
1402 }
1403 }
1404}
1405
1406pub(crate) fn live_range_pre_remove_steps_for_removed_subtree(
1412 inclusive_descendant_of_removed_node: &Node, parent_of_removed_node: &Node, index_of_removed_node: &mut dyn FnMut() -> u32, ) {
1416 if inclusive_descendant_of_removed_node.is_in_a_shadow_tree() {
1419 return;
1420 }
1421 for range in inclusive_descendant_of_removed_node.live_ranges() {
1422 if &*range.start_container() == inclusive_descendant_of_removed_node {
1425 range.set_start_without_reporting(parent_of_removed_node, index_of_removed_node());
1426 }
1427 if &*range.end_container() == inclusive_descendant_of_removed_node {
1430 range.set_end_without_reporting(parent_of_removed_node, index_of_removed_node());
1431 }
1432 }
1433}
1434
1435pub(crate) fn live_range_pre_remove_steps_for_parent(
1437 parent: &Node,
1438 node_index: &mut dyn FnMut() -> u32,
1439) {
1440 for range in parent.live_ranges() {
1441 if &*range.start_container() == parent && range.start_offset() > node_index() {
1444 range.set_start_without_reporting(parent, range.start_offset() - 1);
1445 }
1446 if &*range.end_container() == parent && range.end_offset() > node_index() {
1449 range.set_end_without_reporting(parent, range.end_offset() - 1);
1450 }
1451 }
1452}
1453
1454pub(crate) fn live_range_normalization_steps(
1465 parent: &Node,
1466 node: &Node,
1467 current_node: &Node,
1468 current_node_index: &dyn Fn() -> u32,
1469 length: u32,
1470) {
1471 for range in current_node.live_ranges() {
1472 if &*range.start_container() == current_node {
1475 range.set_start_without_reporting(node, range.start_offset() + length);
1476 }
1477 if &*range.end_container() == current_node {
1480 range.set_end_without_reporting(node, range.end_offset() + length);
1481 }
1482 }
1483
1484 for range in parent.live_ranges() {
1485 if &*range.start_container() == parent && range.start_offset() == current_node_index() {
1489 range.set_start_without_reporting(node, length);
1490 }
1491 if &*range.end_container() == parent && range.end_offset() == current_node_index() {
1495 range.set_end_without_reporting(node, length);
1496 }
1497 }
1498}
1499
1500pub(crate) fn live_range_replace_data_steps(
1502 node: &Node,
1503 offset: u32,
1504 removed_code_units: u32,
1505 added_code_units: &mut dyn FnMut() -> u32,
1506) {
1507 for range in node.live_ranges() {
1508 let start_container = range.start_container();
1512 let start_offset = range.start_offset();
1513 if &*start_container == node &&
1514 start_offset > offset &&
1515 start_offset <= offset + removed_code_units
1516 {
1517 range.set_start_without_reporting(node, offset);
1518 }
1519 let end_container = range.end_container();
1523 let end_offset = range.end_offset();
1524 if &*end_container == node &&
1525 end_offset > offset &&
1526 end_offset <= offset + removed_code_units
1527 {
1528 range.set_end_without_reporting(node, offset);
1529 }
1530 if &*start_container == node && start_offset > offset + removed_code_units {
1534 range.set_start_without_reporting(
1535 node,
1536 start_offset + added_code_units() - removed_code_units,
1537 );
1538 }
1539 if &*end_container == node && end_offset > offset + removed_code_units {
1543 range.set_end_without_reporting(
1544 node,
1545 end_offset + added_code_units() - removed_code_units,
1546 );
1547 }
1548 }
1549}
1550
1551pub(crate) fn live_range_text_split_steps(
1553 parent: &Node,
1554 node: &Node,
1555 offset: u32,
1556 new_node: &Node,
1557) {
1558 for range in node.live_ranges() {
1559 if &*range.start_container() == node && range.start_offset() > offset {
1563 range.set_start_without_reporting(new_node, range.start_offset() - offset);
1564 }
1565 if &*range.end_container() == node && range.end_offset() > offset {
1569 range.set_end_without_reporting(new_node, range.end_offset() - offset);
1570 }
1571 }
1572
1573 let node_index = LazyCell::new(|| node.index());
1574 for range in parent.live_ranges() {
1575 if &*range.start_container() == parent && range.start_offset() == *node_index + 1 {
1578 range.set_start_without_reporting(parent, range.start_offset() + 1);
1579 }
1580
1581 if &*range.end_container() == parent && range.end_offset() == *node_index + 1 {
1584 range.set_end_without_reporting(parent, range.end_offset() + 1);
1585 }
1586 }
1587}
1588
1589pub(crate) fn live_range_pre_remove_steps(node: &Node, old_parent: &Node) {
1591 let mut cached_index = None;
1598 let mut lazy_index = || *cached_index.get_or_insert_with(|| node.index());
1599
1600 let selection = node.owner_document().selection();
1607 for descendant in node.traverse_preorder(ShadowIncluding::No) {
1608 if let Some(selection) = &selection {
1609 selection.remove_steps_for_removed_subtree(&descendant, old_parent, &mut lazy_index);
1610 }
1611 live_range_pre_remove_steps_for_removed_subtree(&descendant, old_parent, &mut lazy_index);
1612 }
1613
1614 if let Some(selection) = &selection {
1619 selection.remove_steps_for_parent(old_parent, &mut lazy_index);
1620 }
1621 live_range_pre_remove_steps_for_parent(old_parent, &mut lazy_index);
1622}