1use std::cell::RefCell;
6use std::cmp::{Ordering, PartialOrd};
7use std::iter;
8
9use app_units::Au;
10use dom_struct::dom_struct;
11use euclid::Rect;
12use js::context::JSContext;
13use js::jsapi::JSTracer;
14use js::rust::HandleObject;
15use style_traits::CSSPixel;
16
17use crate::dom::abstractrange::{AbstractRange, BoundaryPoint, bp_position};
18use crate::dom::bindings::cell::DomRefCell;
19use crate::dom::bindings::codegen::Bindings::AbstractRangeBinding::AbstractRangeMethods;
20use crate::dom::bindings::codegen::Bindings::CharacterDataBinding::CharacterDataMethods;
21use crate::dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
22use crate::dom::bindings::codegen::Bindings::NodeListBinding::NodeListMethods;
23use crate::dom::bindings::codegen::Bindings::RangeBinding::{RangeConstants, RangeMethods};
24use crate::dom::bindings::codegen::Bindings::TextBinding::TextMethods;
25use crate::dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
26use crate::dom::bindings::codegen::UnionTypes::TrustedHTMLOrString;
27use crate::dom::bindings::error::{Error, ErrorResult, Fallible};
28use crate::dom::bindings::inheritance::{Castable, CharacterDataTypeId, NodeTypeId};
29use crate::dom::bindings::reflector::reflect_dom_object_with_proto;
30use crate::dom::bindings::root::{Dom, DomRoot};
31use crate::dom::bindings::str::DOMString;
32use crate::dom::bindings::trace::JSTraceable;
33use crate::dom::bindings::weakref::{WeakRef, WeakRefVec};
34use crate::dom::characterdata::CharacterData;
35use crate::dom::document::Document;
36use crate::dom::documentfragment::DocumentFragment;
37use crate::dom::domrect::DOMRect;
38use crate::dom::domrectlist::DOMRectList;
39use crate::dom::element::Element;
40use crate::dom::html::htmlscriptelement::HTMLScriptElement;
41use crate::dom::node::{Node, NodeTraits, ShadowIncluding};
42use crate::dom::selection::Selection;
43use crate::dom::text::Text;
44use crate::dom::trustedtypes::trustedhtml::TrustedHTML;
45use crate::dom::window::Window;
46use crate::script_runtime::CanGc;
47
48#[dom_struct]
49pub(crate) struct Range {
50 abstract_range: AbstractRange,
51 associated_selections: DomRefCell<Vec<Dom<Selection>>>,
61}
62
63pub(crate) struct ContainedChildren {
64 first_partially_contained_child: Option<DomRoot<Node>>,
65 last_partially_contained_child: Option<DomRoot<Node>>,
66 pub(crate) contained_children: Vec<DomRoot<Node>>,
67}
68
69impl Range {
70 fn new_inherited(
71 start_container: &Node,
72 start_offset: u32,
73 end_container: &Node,
74 end_offset: u32,
75 ) -> Range {
76 debug_assert!(start_offset <= start_container.len());
77 debug_assert!(end_offset <= end_container.len());
78 Range {
79 abstract_range: AbstractRange::new_inherited(
80 start_container,
81 start_offset,
82 end_container,
83 end_offset,
84 ),
85 associated_selections: DomRefCell::new(vec![]),
86 }
87 }
88
89 pub(crate) fn new_with_doc(
90 document: &Document,
91 proto: Option<HandleObject>,
92 can_gc: CanGc,
93 ) -> DomRoot<Range> {
94 let root = document.upcast();
95 Range::new_with_proto(document, proto, root, 0, root, 0, can_gc)
96 }
97
98 pub(crate) fn new(
99 document: &Document,
100 start_container: &Node,
101 start_offset: u32,
102 end_container: &Node,
103 end_offset: u32,
104 can_gc: CanGc,
105 ) -> DomRoot<Range> {
106 Self::new_with_proto(
107 document,
108 None,
109 start_container,
110 start_offset,
111 end_container,
112 end_offset,
113 can_gc,
114 )
115 }
116
117 fn new_with_proto(
118 document: &Document,
119 proto: Option<HandleObject>,
120 start_container: &Node,
121 start_offset: u32,
122 end_container: &Node,
123 end_offset: u32,
124 can_gc: CanGc,
125 ) -> DomRoot<Range> {
126 let range = reflect_dom_object_with_proto(
127 Box::new(Range::new_inherited(
128 start_container,
129 start_offset,
130 end_container,
131 end_offset,
132 )),
133 document.window(),
134 proto,
135 can_gc,
136 );
137 start_container.ranges().push(WeakRef::new(&range));
138 if start_container != end_container {
139 end_container.ranges().push(WeakRef::new(&range));
140 }
141 range
142 }
143
144 fn contains(&self, node: &Node) -> bool {
146 matches!(
149 (
150 bp_position(node, 0, &self.start_container(), self.start_offset()),
151 bp_position(node, node.len(), &self.end_container(), self.end_offset()),
152 ),
153 (Some(Ordering::Greater), Some(Ordering::Less))
154 )
155 }
156
157 fn partially_contains(&self, node: &Node) -> bool {
159 self.start_container()
162 .inclusive_ancestors(ShadowIncluding::No)
163 .any(|n| &*n == node) !=
164 self.end_container()
165 .inclusive_ancestors(ShadowIncluding::No)
166 .any(|n| &*n == node)
167 }
168
169 pub(crate) fn contained_children(&self) -> Fallible<ContainedChildren> {
171 let start_node = self.start_container();
172 let end_node = self.end_container();
173 let common_ancestor = self.CommonAncestorContainer();
175
176 let first_partially_contained_child = if start_node.is_inclusive_ancestor_of(&end_node) {
177 None
179 } else {
180 common_ancestor
182 .children()
183 .find(|node| Range::partially_contains(self, node))
184 };
185
186 let last_partially_contained_child = if end_node.is_inclusive_ancestor_of(&start_node) {
187 None
189 } else {
190 common_ancestor
192 .rev_children()
193 .find(|node| Range::partially_contains(self, node))
194 };
195
196 let contained_children: Vec<DomRoot<Node>> = common_ancestor
198 .children()
199 .filter(|n| self.contains(n))
200 .collect();
201
202 if contained_children.iter().any(|n| n.is_doctype()) {
204 return Err(Error::HierarchyRequest(None));
205 }
206
207 Ok(ContainedChildren {
208 first_partially_contained_child,
209 last_partially_contained_child,
210 contained_children,
211 })
212 }
213
214 pub(crate) fn set_start(&self, node: &Node, offset: u32) {
216 if self.start().node() != node || self.start_offset() != offset {
217 self.report_change();
218 }
219 if self.start().node() != node {
220 if self.start().node() == self.end().node() {
221 node.ranges().push(WeakRef::new(self));
222 } else if self.end().node() == node {
223 self.start_container().ranges().remove(self);
224 } else {
225 node.ranges()
226 .push(self.start_container().ranges().remove(self));
227 }
228 }
229 self.start().set(node, offset);
230 }
231
232 pub(crate) fn set_end(&self, node: &Node, offset: u32) {
234 if self.end().node() != node || self.end_offset() != offset {
235 self.report_change();
236 }
237 if self.end().node() != node {
238 if self.end().node() == self.start().node() {
239 node.ranges().push(WeakRef::new(self));
240 } else if self.start().node() == node {
241 self.end_container().ranges().remove(self);
242 } else {
243 node.ranges()
244 .push(self.end_container().ranges().remove(self));
245 }
246 }
247 self.end().set(node, offset);
248 }
249
250 fn compare_point(&self, node: &Node, offset: u32) -> Fallible<Ordering> {
252 let start_node = self.start_container();
253 let start_node_root = start_node
254 .inclusive_ancestors(ShadowIncluding::No)
255 .last()
256 .unwrap();
257 let node_root = node
258 .inclusive_ancestors(ShadowIncluding::No)
259 .last()
260 .unwrap();
261 if start_node_root != node_root {
262 return Err(Error::WrongDocument(None));
264 }
265 if node.is_doctype() {
266 return Err(Error::InvalidNodeType(None));
268 }
269 if offset > node.len() {
270 return Err(Error::IndexSize(None));
272 }
273 if let Ordering::Less = bp_position(node, offset, &start_node, self.start_offset()).unwrap()
274 {
275 return Ok(Ordering::Less);
277 }
278 if let Ordering::Greater =
279 bp_position(node, offset, &self.end_container(), self.end_offset()).unwrap()
280 {
281 return Ok(Ordering::Greater);
283 }
284 Ok(Ordering::Equal)
286 }
287
288 pub(crate) fn associate_selection(&self, selection: &Selection) {
289 let mut selections = self.associated_selections.borrow_mut();
290 if !selections.iter().any(|s| &**s == selection) {
291 selections.push(Dom::from_ref(selection));
292 }
293 }
294
295 pub(crate) fn disassociate_selection(&self, selection: &Selection) {
296 self.associated_selections
297 .borrow_mut()
298 .retain(|s| &**s != selection);
299 }
300
301 fn report_change(&self) {
302 self.associated_selections
303 .borrow()
304 .iter()
305 .for_each(|s| s.queue_selectionchange_task());
306 }
307
308 fn abstract_range(&self) -> &AbstractRange {
309 &self.abstract_range
310 }
311
312 fn start(&self) -> &BoundaryPoint {
313 self.abstract_range().start()
314 }
315
316 fn end(&self) -> &BoundaryPoint {
317 self.abstract_range().end()
318 }
319
320 pub(crate) fn start_container(&self) -> DomRoot<Node> {
321 self.abstract_range().StartContainer()
322 }
323
324 pub(crate) fn start_offset(&self) -> u32 {
325 self.abstract_range().StartOffset()
326 }
327
328 pub(crate) fn end_container(&self) -> DomRoot<Node> {
329 self.abstract_range().EndContainer()
330 }
331
332 pub(crate) fn end_offset(&self) -> u32 {
333 self.abstract_range().EndOffset()
334 }
335
336 pub(crate) fn collapsed(&self) -> bool {
337 self.abstract_range().Collapsed()
338 }
339
340 fn client_rects(&self) -> impl Iterator<Item = Rect<Au, CSSPixel>> {
341 let start = self.start_container();
344 let end = self.end_container();
345 let document = start.owner_doc();
346 let end_clone = end.clone();
347 start
348 .following_nodes(document.upcast::<Node>())
349 .take_while(move |node| node != &end)
350 .chain(iter::once(end_clone))
351 .flat_map(move |node| node.border_boxes())
352 }
353
354 #[expect(clippy::neg_cmp_op_on_partial_ord)]
356 fn set_the_start_or_end(
357 &self,
358 node: &Node,
359 offset: u32,
360 start_or_end: StartOrEnd,
361 ) -> ErrorResult {
362 if node.is_doctype() {
364 return Err(Error::InvalidNodeType(None));
365 }
366
367 if offset > node.len() {
369 return Err(Error::IndexSize(None));
370 }
371
372 match start_or_end {
376 StartOrEnd::Start => {
378 self.set_start(node, offset);
382 if !(self.start() <= self.end()) {
383 self.set_end(node, offset);
384 }
385 },
386 StartOrEnd::End => {
388 self.set_end(node, offset);
392 if !(self.end() >= self.start()) {
393 self.set_start(node, offset);
394 }
395 },
396 }
397
398 Ok(())
399 }
400}
401
402enum StartOrEnd {
403 Start,
404 End,
405}
406
407impl RangeMethods<crate::DomTypeHolder> for Range {
408 fn Constructor(
410 window: &Window,
411 proto: Option<HandleObject>,
412 can_gc: CanGc,
413 ) -> Fallible<DomRoot<Range>> {
414 let document = window.Document();
415 Ok(Range::new_with_doc(&document, proto, can_gc))
416 }
417
418 fn CommonAncestorContainer(&self) -> DomRoot<Node> {
420 self.end_container()
421 .common_ancestor(&self.start_container(), ShadowIncluding::No)
422 .expect("Couldn't find common ancestor container")
423 }
424
425 fn SetStart(&self, node: &Node, offset: u32) -> ErrorResult {
427 self.set_the_start_or_end(node, offset, StartOrEnd::Start)
428 }
429
430 fn SetEnd(&self, node: &Node, offset: u32) -> ErrorResult {
432 self.set_the_start_or_end(node, offset, StartOrEnd::End)
433 }
434
435 fn SetStartBefore(&self, node: &Node) -> ErrorResult {
437 let parent = node.GetParentNode().ok_or(Error::InvalidNodeType(None))?;
438 self.SetStart(&parent, node.index())
439 }
440
441 fn SetStartAfter(&self, node: &Node) -> ErrorResult {
443 let parent = node.GetParentNode().ok_or(Error::InvalidNodeType(None))?;
444 self.SetStart(&parent, node.index() + 1)
445 }
446
447 fn SetEndBefore(&self, node: &Node) -> ErrorResult {
449 let parent = node.GetParentNode().ok_or(Error::InvalidNodeType(None))?;
450 self.SetEnd(&parent, node.index())
451 }
452
453 fn SetEndAfter(&self, node: &Node) -> ErrorResult {
455 let parent = node.GetParentNode().ok_or(Error::InvalidNodeType(None))?;
456 self.SetEnd(&parent, node.index() + 1)
457 }
458
459 fn Collapse(&self, to_start: bool) {
461 if to_start {
462 self.set_end(&self.start_container(), self.start_offset());
463 } else {
464 self.set_start(&self.end_container(), self.end_offset());
465 }
466 }
467
468 fn SelectNode(&self, node: &Node) -> ErrorResult {
470 let parent = node.GetParentNode().ok_or(Error::InvalidNodeType(None))?;
472 let index = node.index();
474 self.set_start(&parent, index);
476 self.set_end(&parent, index + 1);
478 Ok(())
479 }
480
481 fn SelectNodeContents(&self, node: &Node) -> ErrorResult {
483 if node.is_doctype() {
484 return Err(Error::InvalidNodeType(None));
486 }
487 let length = node.len();
489 self.set_start(node, 0);
491 self.set_end(node, length);
493 Ok(())
494 }
495
496 fn CompareBoundaryPoints(&self, how: u16, other: &Range) -> Fallible<i16> {
498 if how > RangeConstants::END_TO_START {
499 return Err(Error::NotSupported(None));
501 }
502 let this_root = self
503 .start_container()
504 .inclusive_ancestors(ShadowIncluding::No)
505 .last()
506 .unwrap();
507 let other_root = other
508 .start_container()
509 .inclusive_ancestors(ShadowIncluding::No)
510 .last()
511 .unwrap();
512 if this_root != other_root {
513 return Err(Error::WrongDocument(None));
515 }
516 let (this_point, other_point) = match how {
518 RangeConstants::START_TO_START => (self.start(), other.start()),
519 RangeConstants::START_TO_END => (self.end(), other.start()),
520 RangeConstants::END_TO_END => (self.end(), other.end()),
521 RangeConstants::END_TO_START => (self.start(), other.end()),
522 _ => unreachable!(),
523 };
524 match this_point.partial_cmp(other_point).unwrap() {
526 Ordering::Less => Ok(-1),
527 Ordering::Equal => Ok(0),
528 Ordering::Greater => Ok(1),
529 }
530 }
531
532 fn CloneRange(&self, can_gc: CanGc) -> DomRoot<Range> {
534 let start_node = self.start_container();
535 let owner_doc = start_node.owner_doc();
536 Range::new(
537 &owner_doc,
538 &start_node,
539 self.start_offset(),
540 &self.end_container(),
541 self.end_offset(),
542 can_gc,
543 )
544 }
545
546 fn IsPointInRange(&self, node: &Node, offset: u32) -> Fallible<bool> {
548 match self.compare_point(node, offset) {
549 Ok(Ordering::Less) => Ok(false),
550 Ok(Ordering::Equal) => Ok(true),
551 Ok(Ordering::Greater) => Ok(false),
552 Err(Error::WrongDocument(None)) => {
553 Ok(false)
555 },
556 Err(error) => Err(error),
557 }
558 }
559
560 fn ComparePoint(&self, node: &Node, offset: u32) -> Fallible<i16> {
562 self.compare_point(node, offset).map(|order| match order {
563 Ordering::Less => -1,
564 Ordering::Equal => 0,
565 Ordering::Greater => 1,
566 })
567 }
568
569 fn IntersectsNode(&self, node: &Node) -> bool {
571 let start_node = self.start_container();
572 let start_node_root = self
573 .start_container()
574 .inclusive_ancestors(ShadowIncluding::No)
575 .last()
576 .unwrap();
577 let node_root = node
578 .inclusive_ancestors(ShadowIncluding::No)
579 .last()
580 .unwrap();
581 if start_node_root != node_root {
582 return false;
584 }
585 let parent = match node.GetParentNode() {
586 Some(parent) => parent,
587 None => {
588 return true;
590 },
591 };
592 let offset = node.index();
594 Ordering::Greater ==
596 bp_position(&parent, offset + 1, &start_node, self.start_offset()).unwrap() &&
597 Ordering::Less ==
598 bp_position(&parent, offset, &self.end_container(), self.end_offset())
599 .unwrap()
600 }
601
602 fn CloneContents(&self, cx: &mut JSContext) -> Fallible<DomRoot<DocumentFragment>> {
605 let start_node = self.start_container();
607 let start_offset = self.start_offset();
608 let end_node = self.end_container();
609 let end_offset = self.end_offset();
610
611 let fragment = DocumentFragment::new(&start_node.owner_doc(), CanGc::from_cx(cx));
613
614 if self.start() == self.end() {
616 return Ok(fragment);
617 }
618
619 if end_node == start_node {
620 if let Some(cdata) = start_node.downcast::<CharacterData>() {
621 let data = cdata
623 .SubstringData(start_offset, end_offset - start_offset)
624 .unwrap();
625 let clone =
626 cdata.clone_with_data(data, &start_node.owner_doc(), CanGc::from_cx(cx));
627 fragment
629 .upcast::<Node>()
630 .AppendChild(&clone, CanGc::from_cx(cx))?;
631 return Ok(fragment);
633 }
634 }
635
636 let ContainedChildren {
638 first_partially_contained_child,
639 last_partially_contained_child,
640 contained_children,
641 } = self.contained_children()?;
642
643 if let Some(child) = first_partially_contained_child {
644 if let Some(cdata) = child.downcast::<CharacterData>() {
646 assert!(child == start_node);
647 let data = cdata
649 .SubstringData(start_offset, start_node.len() - start_offset)
650 .unwrap();
651 let clone =
652 cdata.clone_with_data(data, &start_node.owner_doc(), CanGc::from_cx(cx));
653 fragment
655 .upcast::<Node>()
656 .AppendChild(&clone, CanGc::from_cx(cx))?;
657 } else {
658 let clone = child.CloneNode(cx, false)?;
660 fragment
662 .upcast::<Node>()
663 .AppendChild(&clone, CanGc::from_cx(cx))?;
664 let subrange = Range::new(
666 &clone.owner_doc(),
667 &start_node,
668 start_offset,
669 &child,
670 child.len(),
671 CanGc::from_cx(cx),
672 );
673 let subfragment = subrange.CloneContents(cx)?;
675 clone.AppendChild(subfragment.upcast(), CanGc::from_cx(cx))?;
677 }
678 }
679
680 for child in contained_children {
682 let clone = child.CloneNode(cx, true)?;
684 fragment
686 .upcast::<Node>()
687 .AppendChild(&clone, CanGc::from_cx(cx))?;
688 }
689
690 if let Some(child) = last_partially_contained_child {
691 if let Some(cdata) = child.downcast::<CharacterData>() {
693 assert!(child == end_node);
694 let data = cdata.SubstringData(0, end_offset).unwrap();
696 let clone =
697 cdata.clone_with_data(data, &start_node.owner_doc(), CanGc::from_cx(cx));
698 fragment
700 .upcast::<Node>()
701 .AppendChild(&clone, CanGc::from_cx(cx))?;
702 } else {
703 let clone = child.CloneNode(cx, false)?;
705 fragment
707 .upcast::<Node>()
708 .AppendChild(&clone, CanGc::from_cx(cx))?;
709 let subrange = Range::new(
711 &clone.owner_doc(),
712 &child,
713 0,
714 &end_node,
715 end_offset,
716 CanGc::from_cx(cx),
717 );
718 let subfragment = subrange.CloneContents(cx)?;
720 clone.AppendChild(subfragment.upcast(), CanGc::from_cx(cx))?;
722 }
723 }
724
725 Ok(fragment)
727 }
728
729 fn ExtractContents(&self, cx: &mut JSContext) -> Fallible<DomRoot<DocumentFragment>> {
732 let start_node = self.start_container();
734 let start_offset = self.start_offset();
735 let end_node = self.end_container();
736 let end_offset = self.end_offset();
737
738 let fragment = DocumentFragment::new(&start_node.owner_doc(), CanGc::from_cx(cx));
740
741 if self.collapsed() {
743 return Ok(fragment);
744 }
745
746 if end_node == start_node {
747 if let Some(end_data) = end_node.downcast::<CharacterData>() {
748 let clone = end_node.CloneNode(cx, true)?;
750 let text = end_data.SubstringData(start_offset, end_offset - start_offset);
752 clone
753 .downcast::<CharacterData>()
754 .unwrap()
755 .SetData(text.unwrap());
756 fragment
758 .upcast::<Node>()
759 .AppendChild(&clone, CanGc::from_cx(cx))?;
760 end_data.ReplaceData(start_offset, end_offset - start_offset, DOMString::new())?;
762 return Ok(fragment);
764 }
765 }
766
767 let ContainedChildren {
769 first_partially_contained_child,
770 last_partially_contained_child,
771 contained_children,
772 } = self.contained_children()?;
773
774 let (new_node, new_offset) = if start_node.is_inclusive_ancestor_of(&end_node) {
775 (DomRoot::from_ref(&*start_node), start_offset)
777 } else {
778 let reference_node = start_node
780 .ancestors()
781 .take_while(|n| !n.is_inclusive_ancestor_of(&end_node))
782 .last()
783 .unwrap_or(DomRoot::from_ref(&start_node));
784 (
786 reference_node.GetParentNode().unwrap(),
787 reference_node.index() + 1,
788 )
789 };
790
791 if let Some(child) = first_partially_contained_child {
792 if let Some(start_data) = child.downcast::<CharacterData>() {
793 assert!(child == start_node);
794 let clone = start_node.CloneNode(cx, true)?;
796 let text = start_data.SubstringData(start_offset, start_node.len() - start_offset);
798 clone
799 .downcast::<CharacterData>()
800 .unwrap()
801 .SetData(text.unwrap());
802 fragment
804 .upcast::<Node>()
805 .AppendChild(&clone, CanGc::from_cx(cx))?;
806 start_data.ReplaceData(
808 start_offset,
809 start_node.len() - start_offset,
810 DOMString::new(),
811 )?;
812 } else {
813 let clone = child.CloneNode(cx, false)?;
815 fragment
817 .upcast::<Node>()
818 .AppendChild(&clone, CanGc::from_cx(cx))?;
819 let subrange = Range::new(
821 &clone.owner_doc(),
822 &start_node,
823 start_offset,
824 &child,
825 child.len(),
826 CanGc::from_cx(cx),
827 );
828 let subfragment = subrange.ExtractContents(cx)?;
830 clone.AppendChild(subfragment.upcast(), CanGc::from_cx(cx))?;
832 }
833 }
834
835 for child in contained_children {
837 fragment
838 .upcast::<Node>()
839 .AppendChild(&child, CanGc::from_cx(cx))?;
840 }
841
842 if let Some(child) = last_partially_contained_child {
843 if let Some(end_data) = child.downcast::<CharacterData>() {
844 assert!(child == end_node);
845 let clone = end_node.CloneNode(cx, true)?;
847 let text = end_data.SubstringData(0, end_offset);
849 clone
850 .downcast::<CharacterData>()
851 .unwrap()
852 .SetData(text.unwrap());
853 fragment
855 .upcast::<Node>()
856 .AppendChild(&clone, CanGc::from_cx(cx))?;
857 end_data.ReplaceData(0, end_offset, DOMString::new())?;
859 } else {
860 let clone = child.CloneNode(cx, false)?;
862 fragment
864 .upcast::<Node>()
865 .AppendChild(&clone, CanGc::from_cx(cx))?;
866 let subrange = Range::new(
868 &clone.owner_doc(),
869 &child,
870 0,
871 &end_node,
872 end_offset,
873 CanGc::from_cx(cx),
874 );
875 let subfragment = subrange.ExtractContents(cx)?;
877 clone.AppendChild(subfragment.upcast(), CanGc::from_cx(cx))?;
879 }
880 }
881
882 self.SetStart(&new_node, new_offset)?;
884 self.SetEnd(&new_node, new_offset)?;
885
886 Ok(fragment)
888 }
889
890 fn Detach(&self) {
892 }
894
895 fn InsertNode(&self, cx: &mut JSContext, node: &Node) -> ErrorResult {
898 let start_node = self.start_container();
899 let start_offset = self.start_offset();
900
901 if &*start_node == node {
903 return Err(Error::HierarchyRequest(None));
904 }
905 match start_node.type_id() {
906 NodeTypeId::CharacterData(CharacterDataTypeId::Text(_)) => (),
908 NodeTypeId::CharacterData(_) => return Err(Error::HierarchyRequest(None)),
909 _ => (),
910 }
911
912 let (reference_node, parent) = match start_node.type_id() {
914 NodeTypeId::CharacterData(CharacterDataTypeId::Text(_)) => {
915 let parent = match start_node.GetParentNode() {
917 Some(parent) => parent,
918 None => return Err(Error::HierarchyRequest(None)),
920 };
921 (Some(DomRoot::from_ref(&*start_node)), parent)
923 },
924 _ => {
925 let child = start_node.ChildNodes(CanGc::from_cx(cx)).Item(start_offset);
927 (child, DomRoot::from_ref(&*start_node))
928 },
929 };
930
931 Node::ensure_pre_insertion_validity(node, &parent, reference_node.as_deref())?;
933
934 let split_text;
936 let reference_node = match start_node.downcast::<Text>() {
937 Some(text) => {
938 split_text = text.SplitText(start_offset, CanGc::from_cx(cx))?;
939 let new_reference = DomRoot::upcast::<Node>(split_text);
940 assert!(new_reference.GetParentNode().as_deref() == Some(&parent));
941 Some(new_reference)
942 },
943 _ => reference_node,
944 };
945
946 let reference_node = if Some(node) == reference_node.as_deref() {
948 node.GetNextSibling()
949 } else {
950 reference_node
951 };
952
953 node.remove_self(cx);
955
956 let new_offset = reference_node
958 .as_ref()
959 .map_or(parent.len(), |node| node.index());
960
961 let new_offset = new_offset +
963 if let NodeTypeId::DocumentFragment(_) = node.type_id() {
964 node.len()
965 } else {
966 1
967 };
968
969 Node::pre_insert(node, &parent, reference_node.as_deref(), CanGc::from_cx(cx))?;
971
972 if self.collapsed() {
974 self.set_end(&parent, new_offset);
975 }
976
977 Ok(())
978 }
979
980 fn DeleteContents(&self, cx: &mut JSContext) -> ErrorResult {
982 if self.collapsed() {
984 return Ok(());
985 }
986
987 let start_node = self.start_container();
989 let end_node = self.end_container();
990 let start_offset = self.start_offset();
991 let end_offset = self.end_offset();
992
993 if start_node == end_node {
995 if let Some(text) = start_node.downcast::<CharacterData>() {
996 if end_offset > start_offset {
997 self.report_change();
998 }
999 return text.ReplaceData(start_offset, end_offset - start_offset, DOMString::new());
1000 }
1001 }
1002
1003 rooted_vec!(let mut contained_children);
1005 let ancestor = self.CommonAncestorContainer();
1006
1007 let mut iter = start_node.following_nodes(&ancestor);
1008
1009 let mut next = iter.next();
1010 while let Some(child) = next {
1011 if self.contains(&child) {
1012 contained_children.push(Dom::from_ref(&*child));
1013 next = iter.next_skipping_children();
1014 } else {
1015 next = iter.next();
1016 }
1017 }
1018
1019 let (new_node, new_offset) = if start_node.is_inclusive_ancestor_of(&end_node) {
1020 (DomRoot::from_ref(&*start_node), start_offset)
1022 } else {
1023 fn compute_reference(start_node: &Node, end_node: &Node) -> (DomRoot<Node>, u32) {
1025 let mut reference_node = DomRoot::from_ref(start_node);
1026 while let Some(parent) = reference_node.GetParentNode() {
1027 if parent.is_inclusive_ancestor_of(end_node) {
1028 return (parent, reference_node.index() + 1);
1029 }
1030 reference_node = parent;
1031 }
1032 unreachable!()
1033 }
1034
1035 compute_reference(&start_node, &end_node)
1036 };
1037
1038 if let Some(text) = start_node.downcast::<CharacterData>() {
1040 text.ReplaceData(
1041 start_offset,
1042 start_node.len() - start_offset,
1043 DOMString::new(),
1044 )
1045 .unwrap();
1046 }
1047
1048 for child in &*contained_children {
1050 child.remove_self(cx);
1051 }
1052
1053 if let Some(text) = end_node.downcast::<CharacterData>() {
1055 text.ReplaceData(0, end_offset, DOMString::new()).unwrap();
1056 }
1057
1058 self.SetStart(&new_node, new_offset).unwrap();
1060 self.SetEnd(&new_node, new_offset).unwrap();
1061 Ok(())
1062 }
1063
1064 fn SurroundContents(&self, cx: &mut JSContext, new_parent: &Node) -> ErrorResult {
1066 let start = self.start_container();
1068 let end = self.end_container();
1069
1070 if start
1071 .inclusive_ancestors(ShadowIncluding::No)
1072 .any(|n| !n.is_inclusive_ancestor_of(&end) && !n.is::<Text>()) ||
1073 end.inclusive_ancestors(ShadowIncluding::No)
1074 .any(|n| !n.is_inclusive_ancestor_of(&start) && !n.is::<Text>())
1075 {
1076 return Err(Error::InvalidState(None));
1077 }
1078
1079 match new_parent.type_id() {
1081 NodeTypeId::Document(_) |
1082 NodeTypeId::DocumentType |
1083 NodeTypeId::DocumentFragment(_) => {
1084 return Err(Error::InvalidNodeType(None));
1085 },
1086 _ => (),
1087 }
1088
1089 let fragment = self.ExtractContents(cx)?;
1091
1092 Node::replace_all(None, new_parent, CanGc::from_cx(cx));
1094
1095 self.InsertNode(cx, new_parent)?;
1097
1098 new_parent.AppendChild(fragment.upcast(), CanGc::from_cx(cx))?;
1100
1101 self.SelectNode(new_parent)
1103 }
1104
1105 fn Stringifier(&self) -> DOMString {
1107 let start_node = self.start_container();
1108 let end_node = self.end_container();
1109
1110 let mut s = DOMString::new();
1112
1113 if let Some(text_node) = start_node.downcast::<Text>() {
1114 let char_data = text_node.upcast::<CharacterData>();
1115
1116 if start_node == end_node {
1120 return char_data
1121 .SubstringData(self.start_offset(), self.end_offset() - self.start_offset())
1122 .unwrap();
1123 }
1124
1125 s.push_str(
1128 &char_data
1129 .SubstringData(
1130 self.start_offset(),
1131 char_data.Length() - self.start_offset(),
1132 )
1133 .unwrap()
1134 .str(),
1135 );
1136 }
1137
1138 let ancestor = self.CommonAncestorContainer();
1141 let iter = start_node
1142 .following_nodes(&ancestor)
1143 .filter_map(DomRoot::downcast::<Text>);
1144
1145 for child in iter {
1146 if self.contains(child.upcast()) {
1147 s.push_str(&child.upcast::<CharacterData>().Data().str());
1148 }
1149 }
1150
1151 if let Some(text_node) = end_node.downcast::<Text>() {
1154 let char_data = text_node.upcast::<CharacterData>();
1155 s.push_str(&char_data.SubstringData(0, self.end_offset()).unwrap().str());
1156 }
1157
1158 s
1160 }
1161
1162 fn CreateContextualFragment(
1164 &self,
1165 cx: &mut JSContext,
1166 fragment: TrustedHTMLOrString,
1167 ) -> Fallible<DomRoot<DocumentFragment>> {
1168 let node = self.start_container();
1173
1174 let fragment = TrustedHTML::get_trusted_script_compliant_string(
1178 node.owner_window().upcast(),
1179 fragment,
1180 "Range createContextualFragment",
1181 CanGc::from_cx(cx),
1182 )?;
1183
1184 let owner_doc = node.owner_doc();
1185
1186 let element = match node.type_id() {
1190 NodeTypeId::Element(_) => Some(DomRoot::downcast::<Element>(node).unwrap()),
1191 NodeTypeId::CharacterData(CharacterDataTypeId::Comment) |
1192 NodeTypeId::CharacterData(CharacterDataTypeId::Text(_)) => node.GetParentElement(),
1193 _ => None,
1194 };
1195
1196 let element = Element::fragment_parsing_context(cx, &owner_doc, element.as_deref());
1198
1199 let fragment_node = element.parse_fragment(fragment, cx)?;
1201
1202 for node in fragment_node
1204 .upcast::<Node>()
1205 .traverse_preorder(ShadowIncluding::No)
1206 {
1207 if let Some(script) = node.downcast::<HTMLScriptElement>() {
1208 script.set_already_started(false);
1210 script.set_parser_inserted(false);
1212 }
1213 }
1214
1215 Ok(fragment_node)
1217 }
1218
1219 fn GetClientRects(&self, can_gc: CanGc) -> DomRoot<DOMRectList> {
1221 let start = self.start_container();
1222 let window = start.owner_window();
1223
1224 let client_rects = self
1225 .client_rects()
1226 .map(|rect| {
1227 DOMRect::new(
1228 window.upcast(),
1229 rect.origin.x.to_f64_px(),
1230 rect.origin.y.to_f64_px(),
1231 rect.size.width.to_f64_px(),
1232 rect.size.height.to_f64_px(),
1233 can_gc,
1234 )
1235 })
1236 .collect();
1237
1238 DOMRectList::new(&window, client_rects, can_gc)
1239 }
1240
1241 fn GetBoundingClientRect(&self, can_gc: CanGc) -> DomRoot<DOMRect> {
1243 let window = self.start_container().owner_window();
1244
1245 let list = self.client_rects();
1247
1248 let bounding_rect = list.fold(euclid::Rect::zero(), |acc, rect| acc.union(&rect));
1253
1254 DOMRect::new(
1255 window.upcast(),
1256 bounding_rect.origin.x.to_f64_px(),
1257 bounding_rect.origin.y.to_f64_px(),
1258 bounding_rect.size.width.to_f64_px(),
1259 bounding_rect.size.height.to_f64_px(),
1260 can_gc,
1261 )
1262 }
1263}
1264
1265#[derive(MallocSizeOf)]
1266pub(crate) struct WeakRangeVec {
1267 cell: RefCell<WeakRefVec<Range>>,
1268}
1269
1270impl Default for WeakRangeVec {
1271 fn default() -> Self {
1272 WeakRangeVec {
1273 cell: RefCell::new(WeakRefVec::new()),
1274 }
1275 }
1276}
1277
1278impl WeakRangeVec {
1279 pub(crate) fn is_empty(&self) -> bool {
1281 self.cell.borrow().is_empty()
1282 }
1283
1284 pub(crate) fn increase_above(&self, node: &Node, offset: u32, delta: u32) {
1287 self.map_offset_above(node, offset, |offset| offset + delta);
1288 }
1289
1290 pub(crate) fn decrease_above(&self, node: &Node, offset: u32, delta: u32) {
1293 self.map_offset_above(node, offset, |offset| offset - delta);
1294 }
1295
1296 pub(crate) fn drain_to_parent(&self, parent: &Node, offset: u32, child: &Node) {
1300 if self.is_empty() {
1301 return;
1302 }
1303
1304 let ranges = &mut *self.cell.borrow_mut();
1305
1306 ranges.update(|entry| {
1307 let range = entry.root().unwrap();
1308 if range.start().node() == parent || range.end().node() == parent {
1309 entry.remove();
1310 }
1311 if range.start().node() == child {
1312 range.report_change();
1313 range.start().set(parent, offset);
1314 }
1315 if range.end().node() == child {
1316 range.report_change();
1317 range.end().set(parent, offset);
1318 }
1319 });
1320
1321 parent.ranges().cell.borrow_mut().extend(ranges.drain(..));
1322 }
1323
1324 pub(crate) fn drain_to_preceding_text_sibling(&self, node: &Node, sibling: &Node, length: u32) {
1327 if self.is_empty() {
1328 return;
1329 }
1330
1331 let ranges = &mut *self.cell.borrow_mut();
1332
1333 ranges.update(|entry| {
1334 let range = entry.root().unwrap();
1335 if range.start().node() == sibling || range.end().node() == sibling {
1336 entry.remove();
1337 }
1338 if range.start().node() == node {
1339 range.report_change();
1340 range.start().set(sibling, range.start_offset() + length);
1341 }
1342 if range.end().node() == node {
1343 range.report_change();
1344 range.end().set(sibling, range.end_offset() + length);
1345 }
1346 });
1347
1348 sibling.ranges().cell.borrow_mut().extend(ranges.drain(..));
1349 }
1350
1351 pub(crate) fn move_to_text_child_at(
1354 &self,
1355 node: &Node,
1356 offset: u32,
1357 child: &Node,
1358 new_offset: u32,
1359 ) {
1360 let child_ranges = child.ranges();
1361 let mut child_ranges = child_ranges.cell.borrow_mut();
1362
1363 self.cell.borrow_mut().update(|entry| {
1364 let range = entry.root().unwrap();
1365
1366 let node_is_start = range.start().node() == node;
1367 let node_is_end = range.end().node() == node;
1368
1369 let move_start = node_is_start && range.start_offset() == offset;
1370 let move_end = node_is_end && range.end_offset() == offset;
1371
1372 let remove_from_node =
1373 move_start && (move_end || !node_is_end) || move_end && !node_is_start;
1374
1375 let already_in_child = range.start().node() == child || range.end().node() == child;
1376 let push_to_child = !already_in_child && (move_start || move_end);
1377
1378 if remove_from_node {
1379 let ref_ = entry.remove();
1380 if push_to_child {
1381 child_ranges.push(ref_);
1382 }
1383 } else if push_to_child {
1384 child_ranges.push(WeakRef::new(&range));
1385 }
1386
1387 if move_start {
1388 range.report_change();
1389 range.start().set(child, new_offset);
1390 }
1391 if move_end {
1392 range.report_change();
1393 range.end().set(child, new_offset);
1394 }
1395 });
1396 }
1397
1398 pub(crate) fn replace_code_units(
1401 &self,
1402 node: &Node,
1403 offset: u32,
1404 removed_code_units: u32,
1405 added_code_units: u32,
1406 ) {
1407 self.map_offset_above(node, offset, |range_offset| {
1408 if range_offset <= offset + removed_code_units {
1409 offset
1410 } else {
1411 range_offset + added_code_units - removed_code_units
1412 }
1413 });
1414 }
1415
1416 pub(crate) fn move_to_following_text_sibling_above(
1419 &self,
1420 node: &Node,
1421 offset: u32,
1422 sibling: &Node,
1423 ) {
1424 let sibling_ranges = sibling.ranges();
1425 let mut sibling_ranges = sibling_ranges.cell.borrow_mut();
1426
1427 self.cell.borrow_mut().update(|entry| {
1428 let range = entry.root().unwrap();
1429 let start_offset = range.start_offset();
1430 let end_offset = range.end_offset();
1431
1432 let node_is_start = range.start().node() == node;
1433 let node_is_end = range.end().node() == node;
1434
1435 let move_start = node_is_start && start_offset > offset;
1436 let move_end = node_is_end && end_offset > offset;
1437
1438 let remove_from_node =
1439 move_start && (move_end || !node_is_end) || move_end && !node_is_start;
1440
1441 let already_in_sibling =
1442 range.start().node() == sibling || range.end().node() == sibling;
1443 let push_to_sibling = !already_in_sibling && (move_start || move_end);
1444
1445 if remove_from_node {
1446 let ref_ = entry.remove();
1447 if push_to_sibling {
1448 sibling_ranges.push(ref_);
1449 }
1450 } else if push_to_sibling {
1451 sibling_ranges.push(WeakRef::new(&range));
1452 }
1453
1454 if move_start {
1455 range.report_change();
1456 range.start().set(sibling, start_offset - offset);
1457 }
1458 if move_end {
1459 range.report_change();
1460 range.end().set(sibling, end_offset - offset);
1461 }
1462 });
1463 }
1464
1465 pub(crate) fn increment_at(&self, node: &Node, offset: u32) {
1468 self.cell.borrow_mut().update(|entry| {
1469 let range = entry.root().unwrap();
1470 if range.start().node() == node && offset == range.start_offset() {
1471 range.report_change();
1472 range.start().set_offset(offset + 1);
1473 }
1474 if range.end().node() == node && offset == range.end_offset() {
1475 range.report_change();
1476 range.end().set_offset(offset + 1);
1477 }
1478 });
1479 }
1480
1481 fn map_offset_above<F: FnMut(u32) -> u32>(&self, node: &Node, offset: u32, mut f: F) {
1482 self.cell.borrow_mut().update(|entry| {
1483 let range = entry.root().unwrap();
1484 let start_offset = range.start_offset();
1485 if range.start().node() == node && start_offset > offset {
1486 range.report_change();
1487 range.start().set_offset(f(start_offset));
1488 }
1489 let end_offset = range.end_offset();
1490 if range.end().node() == node && end_offset > offset {
1491 range.report_change();
1492 range.end().set_offset(f(end_offset));
1493 }
1494 });
1495 }
1496
1497 pub(crate) fn push(&self, ref_: WeakRef<Range>) {
1498 self.cell.borrow_mut().push(ref_);
1499 }
1500
1501 fn remove(&self, range: &Range) -> WeakRef<Range> {
1502 let mut ranges = self.cell.borrow_mut();
1503 let position = ranges.iter().position(|ref_| ref_ == range).unwrap();
1504 ranges.swap_remove(position)
1505 }
1506}
1507
1508#[expect(unsafe_code)]
1509unsafe impl JSTraceable for WeakRangeVec {
1510 unsafe fn trace(&self, _: *mut JSTracer) {
1511 self.cell.borrow_mut().retain_alive()
1512 }
1513}