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 script_bindings::cell::DomRefCell;
16use script_bindings::reflector::reflect_dom_object_with_proto;
17use style_traits::CSSPixel;
18
19use crate::dom::abstractrange::{AbstractRange, BoundaryPoint, bp_position};
20use crate::dom::bindings::codegen::Bindings::AbstractRangeBinding::AbstractRangeMethods;
21use crate::dom::bindings::codegen::Bindings::CharacterDataBinding::CharacterDataMethods;
22use crate::dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
23use crate::dom::bindings::codegen::Bindings::NodeListBinding::NodeListMethods;
24use crate::dom::bindings::codegen::Bindings::RangeBinding::{RangeConstants, RangeMethods};
25use crate::dom::bindings::codegen::Bindings::TextBinding::TextMethods;
26use crate::dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
27use crate::dom::bindings::codegen::UnionTypes::TrustedHTMLOrString;
28use crate::dom::bindings::error::{Error, ErrorResult, Fallible};
29use crate::dom::bindings::inheritance::{Castable, CharacterDataTypeId, NodeTypeId};
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::iterators::ShadowIncluding;
42use crate::dom::node::{Node, NodeTraits};
43use crate::dom::selection::Selection;
44use crate::dom::text::Text;
45use crate::dom::trustedtypes::trustedhtml::TrustedHTML;
46use crate::dom::window::Window;
47use crate::script_runtime::CanGc;
48
49#[dom_struct]
50pub(crate) struct Range {
51 abstract_range: AbstractRange,
52 associated_selections: DomRefCell<Vec<Dom<Selection>>>,
62}
63
64pub(crate) struct ContainedChildren {
65 pub(crate) first_partially_contained_child: Option<DomRoot<Node>>,
66 pub(crate) last_partially_contained_child: Option<DomRoot<Node>>,
67 pub(crate) contained_children: Vec<DomRoot<Node>>,
68}
69
70impl Range {
71 fn new_inherited(
72 start_container: &Node,
73 start_offset: u32,
74 end_container: &Node,
75 end_offset: u32,
76 ) -> Range {
77 debug_assert!(start_offset <= start_container.len());
78 debug_assert!(end_offset <= end_container.len());
79 Range {
80 abstract_range: AbstractRange::new_inherited(
81 start_container,
82 start_offset,
83 end_container,
84 end_offset,
85 ),
86 associated_selections: DomRefCell::new(vec![]),
87 }
88 }
89
90 pub(crate) fn new_with_doc(
91 document: &Document,
92 proto: Option<HandleObject>,
93 can_gc: CanGc,
94 ) -> DomRoot<Range> {
95 let root = document.upcast();
96 Range::new_with_proto(document, proto, root, 0, root, 0, can_gc)
97 }
98
99 pub(crate) fn new(
100 document: &Document,
101 start_container: &Node,
102 start_offset: u32,
103 end_container: &Node,
104 end_offset: u32,
105 can_gc: CanGc,
106 ) -> DomRoot<Range> {
107 Self::new_with_proto(
108 document,
109 None,
110 start_container,
111 start_offset,
112 end_container,
113 end_offset,
114 can_gc,
115 )
116 }
117
118 fn new_with_proto(
119 document: &Document,
120 proto: Option<HandleObject>,
121 start_container: &Node,
122 start_offset: u32,
123 end_container: &Node,
124 end_offset: u32,
125 can_gc: CanGc,
126 ) -> DomRoot<Range> {
127 let range = reflect_dom_object_with_proto(
128 Box::new(Range::new_inherited(
129 start_container,
130 start_offset,
131 end_container,
132 end_offset,
133 )),
134 document.window(),
135 proto,
136 can_gc,
137 );
138 start_container.ranges().push(WeakRef::new(&range));
139 if start_container != end_container {
140 end_container.ranges().push(WeakRef::new(&range));
141 }
142 range
143 }
144
145 pub(crate) fn contains(&self, node: &Node) -> bool {
147 matches!(
150 (
151 bp_position(node, 0, &self.start_container(), self.start_offset()),
152 bp_position(node, node.len(), &self.end_container(), self.end_offset()),
153 ),
154 (Some(Ordering::Greater), Some(Ordering::Less))
155 )
156 }
157
158 fn partially_contains(&self, node: &Node) -> bool {
160 self.start_container()
163 .inclusive_ancestors(ShadowIncluding::No)
164 .any(|n| &*n == node) !=
165 self.end_container()
166 .inclusive_ancestors(ShadowIncluding::No)
167 .any(|n| &*n == node)
168 }
169
170 pub(crate) fn contained_children(&self) -> Fallible<ContainedChildren> {
172 let start_node = self.start_container();
173 let end_node = self.end_container();
174 let common_ancestor = self.CommonAncestorContainer();
176
177 let first_partially_contained_child = if start_node.is_inclusive_ancestor_of(&end_node) {
178 None
180 } else {
181 common_ancestor
183 .children()
184 .find(|node| Range::partially_contains(self, node))
185 };
186
187 let last_partially_contained_child = if end_node.is_inclusive_ancestor_of(&start_node) {
188 None
190 } else {
191 common_ancestor
193 .rev_children()
194 .find(|node| Range::partially_contains(self, node))
195 };
196
197 let contained_children: Vec<DomRoot<Node>> = common_ancestor
199 .children()
200 .filter(|n| self.contains(n))
201 .collect();
202
203 if contained_children.iter().any(|n| n.is_doctype()) {
205 return Err(Error::HierarchyRequest(None));
206 }
207
208 Ok(ContainedChildren {
209 first_partially_contained_child,
210 last_partially_contained_child,
211 contained_children,
212 })
213 }
214
215 pub(crate) fn set_start(&self, node: &Node, offset: u32) {
217 if self.start().node() != node || self.start_offset() != offset {
218 self.report_change();
219 }
220 if self.start().node() != node {
221 if self.start().node() == self.end().node() {
222 node.ranges().push(WeakRef::new(self));
223 } else if self.end().node() == node {
224 self.start_container().ranges().remove(self);
225 } else {
226 node.ranges()
227 .push(self.start_container().ranges().remove(self));
228 }
229 }
230 self.start().set(node, offset);
231 }
232
233 pub(crate) fn set_end(&self, node: &Node, offset: u32) {
235 if self.end().node() != node || self.end_offset() != offset {
236 self.report_change();
237 }
238 if self.end().node() != node {
239 if self.end().node() == self.start().node() {
240 node.ranges().push(WeakRef::new(self));
241 } else if self.start().node() == node {
242 self.end_container().ranges().remove(self);
243 } else {
244 node.ranges()
245 .push(self.end_container().ranges().remove(self));
246 }
247 }
248 self.end().set(node, offset);
249 }
250
251 fn compare_point(&self, node: &Node, offset: u32) -> Fallible<Ordering> {
253 let start_node = self.start_container();
254 let start_node_root = start_node
255 .inclusive_ancestors(ShadowIncluding::No)
256 .last()
257 .unwrap();
258 let node_root = node
259 .inclusive_ancestors(ShadowIncluding::No)
260 .last()
261 .unwrap();
262 if start_node_root != node_root {
263 return Err(Error::WrongDocument(None));
265 }
266 if node.is_doctype() {
267 return Err(Error::InvalidNodeType(None));
269 }
270 if offset > node.len() {
271 return Err(Error::IndexSize(None));
273 }
274 if let Ordering::Less = bp_position(node, offset, &start_node, self.start_offset()).unwrap()
275 {
276 return Ok(Ordering::Less);
278 }
279 if let Ordering::Greater =
280 bp_position(node, offset, &self.end_container(), self.end_offset()).unwrap()
281 {
282 return Ok(Ordering::Greater);
284 }
285 Ok(Ordering::Equal)
287 }
288
289 pub(crate) fn associate_selection(&self, selection: &Selection) {
290 let mut selections = self.associated_selections.borrow_mut();
291 if !selections.iter().any(|s| &**s == selection) {
292 selections.push(Dom::from_ref(selection));
293 }
294 }
295
296 pub(crate) fn disassociate_selection(&self, selection: &Selection) {
297 self.associated_selections
298 .borrow_mut()
299 .retain(|s| &**s != selection);
300 }
301
302 fn report_change(&self) {
303 self.associated_selections
304 .borrow()
305 .iter()
306 .for_each(|s| s.queue_selectionchange_task());
307 }
308
309 fn abstract_range(&self) -> &AbstractRange {
310 &self.abstract_range
311 }
312
313 fn start(&self) -> &BoundaryPoint {
314 self.abstract_range().start()
315 }
316
317 fn end(&self) -> &BoundaryPoint {
318 self.abstract_range().end()
319 }
320
321 pub(crate) fn start_container(&self) -> DomRoot<Node> {
322 self.abstract_range().StartContainer()
323 }
324
325 pub(crate) fn start_offset(&self) -> u32 {
326 self.abstract_range().StartOffset()
327 }
328
329 pub(crate) fn end_container(&self) -> DomRoot<Node> {
330 self.abstract_range().EndContainer()
331 }
332
333 pub(crate) fn end_offset(&self) -> u32 {
334 self.abstract_range().EndOffset()
335 }
336
337 pub(crate) fn collapsed(&self) -> bool {
338 self.abstract_range().Collapsed()
339 }
340
341 fn client_rects(&self) -> impl Iterator<Item = Rect<Au, CSSPixel>> {
342 let start = self.start_container();
345 let end = self.end_container();
346 let document = start.owner_doc();
347 let end_clone = end.clone();
348 start
349 .following_nodes(document.upcast::<Node>(), ShadowIncluding::No)
350 .take_while(move |node| node != &end)
351 .chain(iter::once(end_clone))
352 .flat_map(move |node| node.border_boxes())
353 }
354
355 #[expect(clippy::neg_cmp_op_on_partial_ord)]
357 fn set_the_start_or_end(
358 &self,
359 node: &Node,
360 offset: u32,
361 start_or_end: StartOrEnd,
362 ) -> ErrorResult {
363 if node.is_doctype() {
365 return Err(Error::InvalidNodeType(None));
366 }
367
368 if offset > node.len() {
370 return Err(Error::IndexSize(None));
371 }
372
373 match start_or_end {
377 StartOrEnd::Start => {
379 self.set_start(node, offset);
383 if !(self.start() <= self.end()) {
384 self.set_end(node, offset);
385 }
386 },
387 StartOrEnd::End => {
389 self.set_end(node, offset);
393 if !(self.end() >= self.start()) {
394 self.set_start(node, offset);
395 }
396 },
397 }
398
399 Ok(())
400 }
401}
402
403impl std::fmt::Debug for Range {
404 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
405 write!(
406 f,
407 "[({:?}, {}) -> ({:?}, {})]",
408 self.start_container(),
409 self.start_offset(),
410 self.end_container(),
411 self.end_offset()
412 )
413 }
414}
415
416enum StartOrEnd {
417 Start,
418 End,
419}
420
421impl RangeMethods<crate::DomTypeHolder> for Range {
422 fn Constructor(
424 window: &Window,
425 proto: Option<HandleObject>,
426 can_gc: CanGc,
427 ) -> Fallible<DomRoot<Range>> {
428 let document = window.Document();
429 Ok(Range::new_with_doc(&document, proto, can_gc))
430 }
431
432 fn CommonAncestorContainer(&self) -> DomRoot<Node> {
434 self.end_container()
435 .common_ancestor(&self.start_container(), ShadowIncluding::No)
436 .expect("Couldn't find common ancestor container")
437 }
438
439 fn SetStart(&self, node: &Node, offset: u32) -> ErrorResult {
441 self.set_the_start_or_end(node, offset, StartOrEnd::Start)
442 }
443
444 fn SetEnd(&self, node: &Node, offset: u32) -> ErrorResult {
446 self.set_the_start_or_end(node, offset, StartOrEnd::End)
447 }
448
449 fn SetStartBefore(&self, node: &Node) -> ErrorResult {
451 let parent = node.GetParentNode().ok_or(Error::InvalidNodeType(None))?;
452 self.SetStart(&parent, node.index())
453 }
454
455 fn SetStartAfter(&self, node: &Node) -> ErrorResult {
457 let parent = node.GetParentNode().ok_or(Error::InvalidNodeType(None))?;
458 self.SetStart(&parent, node.index() + 1)
459 }
460
461 fn SetEndBefore(&self, node: &Node) -> ErrorResult {
463 let parent = node.GetParentNode().ok_or(Error::InvalidNodeType(None))?;
464 self.SetEnd(&parent, node.index())
465 }
466
467 fn SetEndAfter(&self, node: &Node) -> ErrorResult {
469 let parent = node.GetParentNode().ok_or(Error::InvalidNodeType(None))?;
470 self.SetEnd(&parent, node.index() + 1)
471 }
472
473 fn Collapse(&self, to_start: bool) {
475 if to_start {
476 self.set_end(&self.start_container(), self.start_offset());
477 } else {
478 self.set_start(&self.end_container(), self.end_offset());
479 }
480 }
481
482 fn SelectNode(&self, node: &Node) -> ErrorResult {
484 let parent = node.GetParentNode().ok_or(Error::InvalidNodeType(None))?;
486 let index = node.index();
488 self.set_start(&parent, index);
490 self.set_end(&parent, index + 1);
492 Ok(())
493 }
494
495 fn SelectNodeContents(&self, node: &Node) -> ErrorResult {
497 if node.is_doctype() {
498 return Err(Error::InvalidNodeType(None));
500 }
501 let length = node.len();
503 self.set_start(node, 0);
505 self.set_end(node, length);
507 Ok(())
508 }
509
510 fn CompareBoundaryPoints(&self, how: u16, other: &Range) -> Fallible<i16> {
512 if how > RangeConstants::END_TO_START {
513 return Err(Error::NotSupported(None));
515 }
516 let this_root = self
517 .start_container()
518 .inclusive_ancestors(ShadowIncluding::No)
519 .last()
520 .unwrap();
521 let other_root = other
522 .start_container()
523 .inclusive_ancestors(ShadowIncluding::No)
524 .last()
525 .unwrap();
526 if this_root != other_root {
527 return Err(Error::WrongDocument(None));
529 }
530 let (this_point, other_point) = match how {
532 RangeConstants::START_TO_START => (self.start(), other.start()),
533 RangeConstants::START_TO_END => (self.end(), other.start()),
534 RangeConstants::END_TO_END => (self.end(), other.end()),
535 RangeConstants::END_TO_START => (self.start(), other.end()),
536 _ => unreachable!(),
537 };
538 match this_point.partial_cmp(other_point).unwrap() {
540 Ordering::Less => Ok(-1),
541 Ordering::Equal => Ok(0),
542 Ordering::Greater => Ok(1),
543 }
544 }
545
546 fn CloneRange(&self, cx: &mut JSContext) -> DomRoot<Range> {
548 let start_node = self.start_container();
549 let owner_doc = start_node.owner_doc();
550 Range::new(
551 &owner_doc,
552 &start_node,
553 self.start_offset(),
554 &self.end_container(),
555 self.end_offset(),
556 CanGc::from_cx(cx),
557 )
558 }
559
560 fn IsPointInRange(&self, node: &Node, offset: u32) -> Fallible<bool> {
562 match self.compare_point(node, offset) {
563 Ok(Ordering::Less) => Ok(false),
564 Ok(Ordering::Equal) => Ok(true),
565 Ok(Ordering::Greater) => Ok(false),
566 Err(Error::WrongDocument(None)) => {
567 Ok(false)
569 },
570 Err(error) => Err(error),
571 }
572 }
573
574 fn ComparePoint(&self, node: &Node, offset: u32) -> Fallible<i16> {
576 self.compare_point(node, offset).map(|order| match order {
577 Ordering::Less => -1,
578 Ordering::Equal => 0,
579 Ordering::Greater => 1,
580 })
581 }
582
583 fn IntersectsNode(&self, node: &Node) -> bool {
585 let start_node = self.start_container();
586 let start_node_root = self
587 .start_container()
588 .inclusive_ancestors(ShadowIncluding::No)
589 .last()
590 .unwrap();
591 let node_root = node
592 .inclusive_ancestors(ShadowIncluding::No)
593 .last()
594 .unwrap();
595 if start_node_root != node_root {
596 return false;
598 }
599 let parent = match node.GetParentNode() {
600 Some(parent) => parent,
601 None => {
602 return true;
604 },
605 };
606 let offset = node.index();
608 Ordering::Greater ==
610 bp_position(&parent, offset + 1, &start_node, self.start_offset()).unwrap() &&
611 Ordering::Less ==
612 bp_position(&parent, offset, &self.end_container(), self.end_offset())
613 .unwrap()
614 }
615
616 fn CloneContents(&self, cx: &mut JSContext) -> Fallible<DomRoot<DocumentFragment>> {
619 let start_node = self.start_container();
621 let start_offset = self.start_offset();
622 let end_node = self.end_container();
623 let end_offset = self.end_offset();
624
625 let fragment = DocumentFragment::new(cx, &start_node.owner_doc());
627
628 if self.start() == self.end() {
630 return Ok(fragment);
631 }
632
633 if end_node == start_node &&
634 let Some(cdata) = start_node.downcast::<CharacterData>()
635 {
636 let data = cdata
638 .SubstringData(start_offset, end_offset - start_offset)
639 .unwrap();
640 let clone = cdata.clone_with_data(cx, data, &start_node.owner_doc());
641 fragment.upcast::<Node>().AppendChild(cx, &clone)?;
643 return Ok(fragment);
645 }
646
647 let ContainedChildren {
649 first_partially_contained_child,
650 last_partially_contained_child,
651 contained_children,
652 } = self.contained_children()?;
653
654 if let Some(child) = first_partially_contained_child {
655 if let Some(cdata) = child.downcast::<CharacterData>() {
657 assert!(child == start_node);
658 let data = cdata
660 .SubstringData(start_offset, start_node.len() - start_offset)
661 .unwrap();
662 let clone = cdata.clone_with_data(cx, data, &start_node.owner_doc());
663 fragment.upcast::<Node>().AppendChild(cx, &clone)?;
665 } else {
666 let clone = child.CloneNode(cx, false)?;
668 fragment.upcast::<Node>().AppendChild(cx, &clone)?;
670 let subrange = Range::new(
672 &clone.owner_doc(),
673 &start_node,
674 start_offset,
675 &child,
676 child.len(),
677 CanGc::from_cx(cx),
678 );
679 let subfragment = subrange.CloneContents(cx)?;
681 clone.AppendChild(cx, subfragment.upcast())?;
683 }
684 }
685
686 for child in contained_children {
688 let clone = child.CloneNode(cx, true)?;
690 fragment.upcast::<Node>().AppendChild(cx, &clone)?;
692 }
693
694 if let Some(child) = last_partially_contained_child {
695 if let Some(cdata) = child.downcast::<CharacterData>() {
697 assert!(child == end_node);
698 let data = cdata.SubstringData(0, end_offset).unwrap();
700 let clone = cdata.clone_with_data(cx, data, &start_node.owner_doc());
701 fragment.upcast::<Node>().AppendChild(cx, &clone)?;
703 } else {
704 let clone = child.CloneNode(cx, false)?;
706 fragment.upcast::<Node>().AppendChild(cx, &clone)?;
708 let subrange = Range::new(
710 &clone.owner_doc(),
711 &child,
712 0,
713 &end_node,
714 end_offset,
715 CanGc::from_cx(cx),
716 );
717 let subfragment = subrange.CloneContents(cx)?;
719 clone.AppendChild(cx, subfragment.upcast())?;
721 }
722 }
723
724 Ok(fragment)
726 }
727
728 fn ExtractContents(&self, cx: &mut JSContext) -> Fallible<DomRoot<DocumentFragment>> {
731 let start_node = self.start_container();
733 let start_offset = self.start_offset();
734 let end_node = self.end_container();
735 let end_offset = self.end_offset();
736
737 let fragment = DocumentFragment::new(cx, &start_node.owner_doc());
739
740 if self.collapsed() {
742 return Ok(fragment);
743 }
744
745 if end_node == start_node &&
746 let Some(end_data) = end_node.downcast::<CharacterData>()
747 {
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(cx, text.unwrap());
756 fragment.upcast::<Node>().AppendChild(cx, &clone)?;
758 end_data.ReplaceData(
760 cx,
761 start_offset,
762 end_offset - start_offset,
763 DOMString::new(),
764 )?;
765 return Ok(fragment);
767 }
768
769 let ContainedChildren {
771 first_partially_contained_child,
772 last_partially_contained_child,
773 contained_children,
774 } = self.contained_children()?;
775
776 let (new_node, new_offset) = if start_node.is_inclusive_ancestor_of(&end_node) {
777 (DomRoot::from_ref(&*start_node), start_offset)
779 } else {
780 let reference_node = start_node
782 .ancestors()
783 .take_while(|n| !n.is_inclusive_ancestor_of(&end_node))
784 .last()
785 .unwrap_or(DomRoot::from_ref(&start_node));
786 (
788 reference_node.GetParentNode().unwrap(),
789 reference_node.index() + 1,
790 )
791 };
792
793 if let Some(child) = first_partially_contained_child {
794 if let Some(start_data) = child.downcast::<CharacterData>() {
795 assert!(child == start_node);
796 let clone = start_node.CloneNode(cx, true)?;
798 let text = start_data.SubstringData(start_offset, start_node.len() - start_offset);
800 clone
801 .downcast::<CharacterData>()
802 .unwrap()
803 .SetData(cx, text.unwrap());
804 fragment.upcast::<Node>().AppendChild(cx, &clone)?;
806 start_data.ReplaceData(
808 cx,
809 start_offset,
810 start_node.len() - start_offset,
811 DOMString::new(),
812 )?;
813 } else {
814 let clone = child.CloneNode(cx, false)?;
816 fragment.upcast::<Node>().AppendChild(cx, &clone)?;
818 let subrange = Range::new(
820 &clone.owner_doc(),
821 &start_node,
822 start_offset,
823 &child,
824 child.len(),
825 CanGc::from_cx(cx),
826 );
827 let subfragment = subrange.ExtractContents(cx)?;
829 clone.AppendChild(cx, subfragment.upcast())?;
831 }
832 }
833
834 for child in contained_children {
836 fragment.upcast::<Node>().AppendChild(cx, &child)?;
837 }
838
839 if let Some(child) = last_partially_contained_child {
840 if let Some(end_data) = child.downcast::<CharacterData>() {
841 assert!(child == end_node);
842 let clone = end_node.CloneNode(cx, true)?;
844 let text = end_data.SubstringData(0, end_offset);
846 clone
847 .downcast::<CharacterData>()
848 .unwrap()
849 .SetData(cx, text.unwrap());
850 fragment.upcast::<Node>().AppendChild(cx, &clone)?;
852 end_data.ReplaceData(cx, 0, end_offset, DOMString::new())?;
854 } else {
855 let clone = child.CloneNode(cx, false)?;
857 fragment.upcast::<Node>().AppendChild(cx, &clone)?;
859 let subrange = Range::new(
861 &clone.owner_doc(),
862 &child,
863 0,
864 &end_node,
865 end_offset,
866 CanGc::from_cx(cx),
867 );
868 let subfragment = subrange.ExtractContents(cx)?;
870 clone.AppendChild(cx, subfragment.upcast())?;
872 }
873 }
874
875 self.SetStart(&new_node, new_offset)?;
877 self.SetEnd(&new_node, new_offset)?;
878
879 Ok(fragment)
881 }
882
883 fn Detach(&self) {
885 }
887
888 fn InsertNode(&self, cx: &mut JSContext, node: &Node) -> ErrorResult {
891 let start_node = self.start_container();
892 let start_offset = self.start_offset();
893
894 if &*start_node == node {
896 return Err(Error::HierarchyRequest(None));
897 }
898 match start_node.type_id() {
899 NodeTypeId::CharacterData(CharacterDataTypeId::Text(_)) => (),
901 NodeTypeId::CharacterData(_) => return Err(Error::HierarchyRequest(None)),
902 _ => (),
903 }
904
905 let (reference_node, parent) = match start_node.type_id() {
907 NodeTypeId::CharacterData(CharacterDataTypeId::Text(_)) => {
908 let parent = match start_node.GetParentNode() {
910 Some(parent) => parent,
911 None => return Err(Error::HierarchyRequest(None)),
913 };
914 (Some(DomRoot::from_ref(&*start_node)), parent)
916 },
917 _ => {
918 let child = start_node.ChildNodes(cx).Item(start_offset);
920 (child, DomRoot::from_ref(&*start_node))
921 },
922 };
923
924 Node::ensure_pre_insertion_validity(cx.no_gc(), node, &parent, reference_node.as_deref())?;
926
927 let split_text;
929 let reference_node = match start_node.downcast::<Text>() {
930 Some(text) => {
931 split_text = text.SplitText(cx, start_offset)?;
932 let new_reference = DomRoot::upcast::<Node>(split_text);
933 assert!(new_reference.GetParentNode().as_deref() == Some(&parent));
934 Some(new_reference)
935 },
936 _ => reference_node,
937 };
938
939 let reference_node = if Some(node) == reference_node.as_deref() {
941 node.GetNextSibling()
942 } else {
943 reference_node
944 };
945
946 node.remove_self(cx);
948
949 let new_offset = reference_node
951 .as_ref()
952 .map_or(parent.len(), |node| node.index());
953
954 let new_offset = new_offset +
956 if let NodeTypeId::DocumentFragment(_) = node.type_id() {
957 node.len()
958 } else {
959 1
960 };
961
962 Node::pre_insert(cx, node, &parent, reference_node.as_deref())?;
964
965 if self.collapsed() {
967 self.set_end(&parent, new_offset);
968 }
969
970 Ok(())
971 }
972
973 fn DeleteContents(&self, cx: &mut JSContext) -> ErrorResult {
975 if self.collapsed() {
977 return Ok(());
978 }
979
980 let start_node = self.start_container();
983 let end_node = self.end_container();
984 let start_offset = self.start_offset();
985 let end_offset = self.end_offset();
986
987 if start_node == end_node &&
989 let Some(text) = start_node.downcast::<CharacterData>()
990 {
991 if end_offset > start_offset {
992 self.report_change();
993 }
994
995 return text.ReplaceData(
999 cx,
1000 start_offset,
1001 end_offset - start_offset,
1002 DOMString::new(),
1003 );
1004 }
1005
1006 rooted_vec!(let mut contained_children);
1009 let ancestor = self.CommonAncestorContainer();
1010
1011 let mut iter = start_node.following_nodes(&ancestor, ShadowIncluding::No);
1012
1013 let mut next = iter.next();
1014 while let Some(child) = next {
1015 if self.contains(&child) {
1016 contained_children.push(Dom::from_ref(&*child));
1017 next = iter.next_skipping_children();
1018 } else {
1019 next = iter.next();
1020 }
1021 }
1022
1023 let (new_node, new_offset) = if start_node.is_inclusive_ancestor_of(&end_node) {
1027 (DomRoot::from_ref(&*start_node), start_offset)
1028 } else {
1029 fn compute_reference(start_node: &Node, end_node: &Node) -> (DomRoot<Node>, u32) {
1031 let mut reference_node = DomRoot::from_ref(start_node);
1033 while let Some(parent) = reference_node.GetParentNode() {
1036 if parent.is_inclusive_ancestor_of(end_node) {
1037 return (parent, reference_node.index() + 1);
1039 }
1040 reference_node = parent;
1041 }
1042 unreachable!()
1043 }
1044
1045 compute_reference(&start_node, &end_node)
1046 };
1047
1048 self.SetStart(&new_node, new_offset).unwrap();
1050 self.SetEnd(&new_node, new_offset).unwrap();
1051
1052 if let Some(text) = start_node.downcast::<CharacterData>() {
1056 text.ReplaceData(
1057 cx,
1058 start_offset,
1059 start_node.len() - start_offset,
1060 DOMString::new(),
1061 )
1062 .unwrap();
1063 }
1064
1065 for child in &*contained_children {
1067 child.remove_self(cx);
1068 }
1069
1070 if let Some(text) = end_node.downcast::<CharacterData>() {
1073 text.ReplaceData(cx, 0, end_offset, DOMString::new())
1074 .unwrap();
1075 }
1076
1077 Ok(())
1078 }
1079
1080 fn SurroundContents(&self, cx: &mut JSContext, new_parent: &Node) -> ErrorResult {
1082 let start = self.start_container();
1084 let end = self.end_container();
1085
1086 if start
1087 .inclusive_ancestors(ShadowIncluding::No)
1088 .any(|n| !n.is_inclusive_ancestor_of(&end) && !n.is::<Text>()) ||
1089 end.inclusive_ancestors(ShadowIncluding::No)
1090 .any(|n| !n.is_inclusive_ancestor_of(&start) && !n.is::<Text>())
1091 {
1092 return Err(Error::InvalidState(None));
1093 }
1094
1095 match new_parent.type_id() {
1097 NodeTypeId::Document(_) |
1098 NodeTypeId::DocumentType |
1099 NodeTypeId::DocumentFragment(_) => {
1100 return Err(Error::InvalidNodeType(None));
1101 },
1102 _ => (),
1103 }
1104
1105 let fragment = self.ExtractContents(cx)?;
1107
1108 Node::replace_all(cx, None, new_parent);
1110
1111 self.InsertNode(cx, new_parent)?;
1113
1114 new_parent.AppendChild(cx, fragment.upcast())?;
1116
1117 self.SelectNode(new_parent)
1119 }
1120
1121 fn Stringifier(&self) -> DOMString {
1123 let start_node = self.start_container();
1124 let end_node = self.end_container();
1125
1126 let mut s = DOMString::new();
1128
1129 if let Some(text_node) = start_node.downcast::<Text>() {
1130 let char_data = text_node.upcast::<CharacterData>();
1131
1132 if start_node == end_node {
1136 return char_data
1137 .SubstringData(self.start_offset(), self.end_offset() - self.start_offset())
1138 .unwrap();
1139 }
1140
1141 s.push_str(
1144 &char_data
1145 .SubstringData(
1146 self.start_offset(),
1147 char_data.Length() - self.start_offset(),
1148 )
1149 .unwrap()
1150 .str(),
1151 );
1152 }
1153
1154 let ancestor = self.CommonAncestorContainer();
1157 let iter = start_node
1158 .following_nodes(&ancestor, ShadowIncluding::No)
1159 .filter_map(DomRoot::downcast::<Text>);
1160
1161 for child in iter {
1162 if self.contains(child.upcast()) {
1163 s.push_str(&child.upcast::<CharacterData>().Data().str());
1164 }
1165 }
1166
1167 if let Some(text_node) = end_node.downcast::<Text>() {
1170 let char_data = text_node.upcast::<CharacterData>();
1171 s.push_str(&char_data.SubstringData(0, self.end_offset()).unwrap().str());
1172 }
1173
1174 s
1176 }
1177
1178 fn CreateContextualFragment(
1180 &self,
1181 cx: &mut JSContext,
1182 fragment: TrustedHTMLOrString,
1183 ) -> Fallible<DomRoot<DocumentFragment>> {
1184 let node = self.start_container();
1189
1190 let fragment = TrustedHTML::get_trusted_type_compliant_string(
1194 cx,
1195 node.owner_window().upcast(),
1196 fragment,
1197 "Range createContextualFragment",
1198 )?;
1199
1200 let owner_doc = node.owner_doc();
1201
1202 let element = match node.type_id() {
1206 NodeTypeId::Element(_) => Some(DomRoot::downcast::<Element>(node).unwrap()),
1207 NodeTypeId::CharacterData(CharacterDataTypeId::Comment) |
1208 NodeTypeId::CharacterData(CharacterDataTypeId::Text(_)) => node.GetParentElement(),
1209 _ => None,
1210 };
1211
1212 let element = Element::fragment_parsing_context(cx, &owner_doc, element.as_deref());
1214
1215 let fragment_node = element.parse_fragment(fragment, cx)?;
1217
1218 for node in fragment_node
1220 .upcast::<Node>()
1221 .traverse_preorder(ShadowIncluding::No)
1222 {
1223 if let Some(script) = node.downcast::<HTMLScriptElement>() {
1224 script.set_already_started(false);
1226 script.set_parser_inserted(false);
1228 }
1229 }
1230
1231 Ok(fragment_node)
1233 }
1234
1235 fn GetClientRects(&self, cx: &mut JSContext) -> DomRoot<DOMRectList> {
1237 let start = self.start_container();
1238 let window = start.owner_window();
1239
1240 let client_rects = self
1241 .client_rects()
1242 .map(|rect| {
1243 DOMRect::new(
1244 window.upcast(),
1245 rect.origin.x.to_f64_px(),
1246 rect.origin.y.to_f64_px(),
1247 rect.size.width.to_f64_px(),
1248 rect.size.height.to_f64_px(),
1249 CanGc::from_cx(cx),
1250 )
1251 })
1252 .collect();
1253
1254 DOMRectList::new(&window, client_rects, CanGc::from_cx(cx))
1255 }
1256
1257 fn GetBoundingClientRect(&self, cx: &mut JSContext) -> DomRoot<DOMRect> {
1259 let window = self.start_container().owner_window();
1260
1261 let list = self.client_rects();
1263
1264 let bounding_rect = list.fold(euclid::Rect::zero(), |acc, rect| acc.union(&rect));
1269
1270 DOMRect::new(
1271 window.upcast(),
1272 bounding_rect.origin.x.to_f64_px(),
1273 bounding_rect.origin.y.to_f64_px(),
1274 bounding_rect.size.width.to_f64_px(),
1275 bounding_rect.size.height.to_f64_px(),
1276 CanGc::from_cx(cx),
1277 )
1278 }
1279}
1280
1281#[derive(MallocSizeOf)]
1282pub(crate) struct WeakRangeVec {
1283 cell: RefCell<WeakRefVec<Range>>,
1284}
1285
1286impl Default for WeakRangeVec {
1287 fn default() -> Self {
1288 WeakRangeVec {
1289 cell: RefCell::new(WeakRefVec::new()),
1290 }
1291 }
1292}
1293
1294impl WeakRangeVec {
1295 pub(crate) fn is_empty(&self) -> bool {
1297 self.cell.borrow().is_empty()
1298 }
1299
1300 pub(crate) fn increase_above(&self, node: &Node, offset: u32, delta: u32) {
1303 self.map_offset_above(node, offset, |offset| offset + delta);
1304 }
1305
1306 pub(crate) fn decrease_above(&self, node: &Node, offset: u32, delta: u32) {
1309 self.map_offset_above(node, offset, |offset| offset - delta);
1310 }
1311
1312 pub(crate) fn drain_to_parent(&self, parent: &Node, offset: u32, child: &Node) {
1316 if self.is_empty() {
1317 return;
1318 }
1319
1320 let ranges = &mut *self.cell.borrow_mut();
1321
1322 ranges.update(|entry| {
1323 let range = entry.root().unwrap();
1324 if range.start().node() == parent || range.end().node() == parent {
1325 entry.remove();
1326 }
1327 if range.start().node() == child {
1328 range.report_change();
1329 range.start().set(parent, offset);
1330 }
1331 if range.end().node() == child {
1332 range.report_change();
1333 range.end().set(parent, offset);
1334 }
1335 });
1336
1337 parent.ranges().cell.borrow_mut().extend(ranges.drain(..));
1338 }
1339
1340 pub(crate) fn drain_to_preceding_text_sibling(&self, node: &Node, sibling: &Node, length: u32) {
1343 if self.is_empty() {
1344 return;
1345 }
1346
1347 let ranges = &mut *self.cell.borrow_mut();
1348
1349 ranges.update(|entry| {
1350 let range = entry.root().unwrap();
1351 if range.start().node() == sibling || range.end().node() == sibling {
1352 entry.remove();
1353 }
1354 if range.start().node() == node {
1355 range.report_change();
1356 range.start().set(sibling, range.start_offset() + length);
1357 }
1358 if range.end().node() == node {
1359 range.report_change();
1360 range.end().set(sibling, range.end_offset() + length);
1361 }
1362 });
1363
1364 sibling.ranges().cell.borrow_mut().extend(ranges.drain(..));
1365 }
1366
1367 pub(crate) fn move_to_text_child_at(
1370 &self,
1371 node: &Node,
1372 offset: u32,
1373 child: &Node,
1374 new_offset: u32,
1375 ) {
1376 let child_ranges = child.ranges();
1377 let mut child_ranges = child_ranges.cell.borrow_mut();
1378
1379 self.cell.borrow_mut().update(|entry| {
1380 let range = entry.root().unwrap();
1381
1382 let node_is_start = range.start().node() == node;
1383 let node_is_end = range.end().node() == node;
1384
1385 let move_start = node_is_start && range.start_offset() == offset;
1386 let move_end = node_is_end && range.end_offset() == offset;
1387
1388 let remove_from_node =
1389 move_start && (move_end || !node_is_end) || move_end && !node_is_start;
1390
1391 let already_in_child = range.start().node() == child || range.end().node() == child;
1392 let push_to_child = !already_in_child && (move_start || move_end);
1393
1394 if remove_from_node {
1395 let ref_ = entry.remove();
1396 if push_to_child {
1397 child_ranges.push(ref_);
1398 }
1399 } else if push_to_child {
1400 child_ranges.push(WeakRef::new(&range));
1401 }
1402
1403 if move_start {
1404 range.report_change();
1405 range.start().set(child, new_offset);
1406 }
1407 if move_end {
1408 range.report_change();
1409 range.end().set(child, new_offset);
1410 }
1411 });
1412 }
1413
1414 pub(crate) fn replace_code_units(
1417 &self,
1418 node: &Node,
1419 offset: u32,
1420 removed_code_units: u32,
1421 added_code_units: u32,
1422 ) {
1423 self.map_offset_above(node, offset, |range_offset| {
1424 if range_offset <= offset + removed_code_units {
1425 offset
1426 } else {
1427 range_offset + added_code_units - removed_code_units
1428 }
1429 });
1430 }
1431
1432 pub(crate) fn move_to_following_text_sibling_above(
1435 &self,
1436 node: &Node,
1437 offset: u32,
1438 sibling: &Node,
1439 ) {
1440 let sibling_ranges = sibling.ranges();
1441 let mut sibling_ranges = sibling_ranges.cell.borrow_mut();
1442
1443 self.cell.borrow_mut().update(|entry| {
1444 let range = entry.root().unwrap();
1445 let start_offset = range.start_offset();
1446 let end_offset = range.end_offset();
1447
1448 let node_is_start = range.start().node() == node;
1449 let node_is_end = range.end().node() == node;
1450
1451 let move_start = node_is_start && start_offset > offset;
1452 let move_end = node_is_end && end_offset > offset;
1453
1454 let remove_from_node =
1455 move_start && (move_end || !node_is_end) || move_end && !node_is_start;
1456
1457 let already_in_sibling =
1458 range.start().node() == sibling || range.end().node() == sibling;
1459 let push_to_sibling = !already_in_sibling && (move_start || move_end);
1460
1461 if remove_from_node {
1462 let ref_ = entry.remove();
1463 if push_to_sibling {
1464 sibling_ranges.push(ref_);
1465 }
1466 } else if push_to_sibling {
1467 sibling_ranges.push(WeakRef::new(&range));
1468 }
1469
1470 if move_start {
1471 range.report_change();
1472 range.start().set(sibling, start_offset - offset);
1473 }
1474 if move_end {
1475 range.report_change();
1476 range.end().set(sibling, end_offset - offset);
1477 }
1478 });
1479 }
1480
1481 pub(crate) fn increment_at(&self, node: &Node, offset: u32) {
1484 self.cell.borrow_mut().update(|entry| {
1485 let range = entry.root().unwrap();
1486 if range.start().node() == node && offset == range.start_offset() {
1487 range.report_change();
1488 range.start().set_offset(offset + 1);
1489 }
1490 if range.end().node() == node && offset == range.end_offset() {
1491 range.report_change();
1492 range.end().set_offset(offset + 1);
1493 }
1494 });
1495 }
1496
1497 fn map_offset_above<F: FnMut(u32) -> u32>(&self, node: &Node, offset: u32, mut f: F) {
1498 self.cell.borrow_mut().update(|entry| {
1499 let range = entry.root().unwrap();
1500 let start_offset = range.start_offset();
1501 if range.start().node() == node && start_offset > offset {
1502 range.report_change();
1503 range.start().set_offset(f(start_offset));
1504 }
1505 let end_offset = range.end_offset();
1506 if range.end().node() == node && end_offset > offset {
1507 range.report_change();
1508 range.end().set_offset(f(end_offset));
1509 }
1510 });
1511 }
1512
1513 pub(crate) fn push(&self, ref_: WeakRef<Range>) {
1514 self.cell.borrow_mut().push(ref_);
1515 }
1516
1517 fn remove(&self, range: &Range) -> WeakRef<Range> {
1518 let mut ranges = self.cell.borrow_mut();
1519 let position = ranges.iter().position(|ref_| ref_ == range).unwrap();
1520 ranges.swap_remove(position)
1521 }
1522}
1523
1524#[expect(unsafe_code)]
1525unsafe impl JSTraceable for WeakRangeVec {
1526 unsafe fn trace(&self, _: *mut JSTracer) {
1527 self.cell.borrow_mut().retain_alive()
1528 }
1529}