1use std::cell::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 style_traits::CSSPixel;
20
21use crate::dom::abstractrange::{AbstractRange, BoundaryPoint, bp_position};
22use crate::dom::bindings::codegen::Bindings::AbstractRangeBinding::AbstractRangeMethods;
23use crate::dom::bindings::codegen::Bindings::CharacterDataBinding::CharacterDataMethods;
24use crate::dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
25use crate::dom::bindings::codegen::Bindings::NodeListBinding::NodeListMethods;
26use crate::dom::bindings::codegen::Bindings::RangeBinding::{RangeConstants, RangeMethods};
27use crate::dom::bindings::codegen::Bindings::TextBinding::TextMethods;
28use crate::dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
29use crate::dom::bindings::codegen::UnionTypes::TrustedHTMLOrString;
30use crate::dom::bindings::error::{Error, ErrorResult, Fallible};
31use crate::dom::bindings::inheritance::{Castable, CharacterDataTypeId, NodeTypeId};
32use crate::dom::bindings::root::{Dom, DomRoot};
33use crate::dom::bindings::str::DOMString;
34use crate::dom::bindings::trace::JSTraceable;
35use crate::dom::bindings::weakref::{WeakRef, WeakRefVec};
36use crate::dom::characterdata::CharacterData;
37use crate::dom::document::Document;
38use crate::dom::documentfragment::DocumentFragment;
39use crate::dom::domrect::DOMRect;
40use crate::dom::domrectlist::DOMRectList;
41use crate::dom::element::Element;
42use crate::dom::html::htmlscriptelement::HTMLScriptElement;
43use crate::dom::iterators::ShadowIncluding;
44use crate::dom::node::{Node, NodeTraits};
45use crate::dom::selection::Selection;
46use crate::dom::text::Text;
47use crate::dom::trustedtypes::trustedhtml::TrustedHTML;
48use crate::dom::window::Window;
49
50#[dom_struct]
51pub(crate) struct Range {
52 abstract_range: AbstractRange,
53 associated_selections: DomRefCell<Vec<Dom<Selection>>>,
63}
64
65pub(crate) struct ContainedChildren {
66 pub(crate) first_partially_contained_child: Option<DomRoot<Node>>,
67 pub(crate) last_partially_contained_child: Option<DomRoot<Node>>,
68 pub(crate) contained_children: Vec<DomRoot<Node>>,
69}
70
71impl Range {
72 fn new_inherited(
73 start_container: &Node,
74 start_offset: u32,
75 end_container: &Node,
76 end_offset: u32,
77 ) -> Range {
78 debug_assert!(start_offset <= start_container.len());
79 debug_assert!(end_offset <= end_container.len());
80 Range {
81 abstract_range: AbstractRange::new_inherited(
82 start_container,
83 start_offset,
84 end_container,
85 end_offset,
86 ),
87 associated_selections: DomRefCell::new(vec![]),
88 }
89 }
90
91 pub(crate) fn new_with_doc(
92 cx: &mut JSContext,
93 document: &Document,
94 proto: Option<HandleObject>,
95 ) -> DomRoot<Range> {
96 let root = document.upcast();
97 Range::new_with_proto(cx, document, proto, root, 0, root, 0)
98 }
99
100 pub(crate) fn new(
101 cx: &mut JSContext,
102 document: &Document,
103 start_container: &Node,
104 start_offset: u32,
105 end_container: &Node,
106 end_offset: u32,
107 ) -> DomRoot<Range> {
108 Self::new_with_proto(
109 cx,
110 document,
111 None,
112 start_container,
113 start_offset,
114 end_container,
115 end_offset,
116 )
117 }
118
119 fn new_with_proto(
120 cx: &mut JSContext,
121 document: &Document,
122 proto: Option<HandleObject>,
123 start_container: &Node,
124 start_offset: u32,
125 end_container: &Node,
126 end_offset: u32,
127 ) -> DomRoot<Range> {
128 let range = reflect_weak_referenceable_dom_object_with_proto(
129 cx,
130 Rc::new(Range::new_inherited(
131 start_container,
132 start_offset,
133 end_container,
134 end_offset,
135 )),
136 document.window(),
137 proto,
138 );
139 start_container
140 .ensure_weak_ranges()
141 .push(WeakRef::new(&range));
142 if start_container != end_container {
143 end_container
144 .ensure_weak_ranges()
145 .push(WeakRef::new(&range));
146 }
147 range
148 }
149
150 pub(crate) fn root(&self) -> DomRoot<Node> {
154 self.start_container().GetRootNode(&Default::default())
155 }
156
157 pub(crate) fn contains(&self, node: &Node) -> bool {
159 node.GetRootNode(&Default::default()) == self.root() &&
162 matches!(
163 (
164 bp_position(node, 0, &self.start_container(), self.start_offset()),
165 bp_position(node, node.len(), &self.end_container(), self.end_offset()),
166 ),
167 (Ordering::Greater, Ordering::Less)
168 )
169 }
170
171 fn partially_contains(&self, node: &Node) -> bool {
173 self.start_container()
176 .inclusive_ancestors(ShadowIncluding::No)
177 .any(|n| &*n == node) !=
178 self.end_container()
179 .inclusive_ancestors(ShadowIncluding::No)
180 .any(|n| &*n == node)
181 }
182
183 pub(crate) fn contained_children(&self) -> Fallible<ContainedChildren> {
185 let start_node = self.start_container();
186 let end_node = self.end_container();
187 let common_ancestor = self.CommonAncestorContainer();
189
190 let first_partially_contained_child = if start_node.is_inclusive_ancestor_of(&end_node) {
191 None
193 } else {
194 common_ancestor
196 .children()
197 .find(|node| Range::partially_contains(self, node))
198 };
199
200 let last_partially_contained_child = if end_node.is_inclusive_ancestor_of(&start_node) {
201 None
203 } else {
204 common_ancestor
206 .rev_children()
207 .find(|node| Range::partially_contains(self, node))
208 };
209
210 let contained_children: Vec<DomRoot<Node>> = common_ancestor
212 .children()
213 .filter(|n| self.contains(n))
214 .collect();
215
216 if contained_children.iter().any(|n| n.is_doctype()) {
218 return Err(Error::HierarchyRequest(None));
219 }
220
221 Ok(ContainedChildren {
222 first_partially_contained_child,
223 last_partially_contained_child,
224 contained_children,
225 })
226 }
227
228 pub(crate) fn set_start(&self, node: &Node, offset: u32) {
230 if self.start().node() != node || self.start_offset() != offset {
231 self.report_change();
232 }
233 if self.start().node() != node {
234 if self.start().node() == self.end().node() {
235 node.ensure_weak_ranges().push(WeakRef::new(self));
236 } else if self.end().node() == node {
237 self.start_container().ensure_weak_ranges().remove(self);
238 } else {
239 node.ensure_weak_ranges()
240 .push(self.start_container().ensure_weak_ranges().remove(self));
241 }
242 }
243 self.start().set(node, offset);
244 }
245
246 pub(crate) fn set_end(&self, node: &Node, offset: u32) {
248 if self.end().node() != node || self.end_offset() != offset {
249 self.report_change();
250 }
251 if self.end().node() != node {
252 if self.end().node() == self.start().node() {
253 node.ensure_weak_ranges().push(WeakRef::new(self));
254 } else if self.start().node() == node {
255 self.end_container().ensure_weak_ranges().remove(self);
256 } else {
257 node.ensure_weak_ranges()
258 .push(self.end_container().ensure_weak_ranges().remove(self));
259 }
260 }
261 self.end().set(node, offset);
262 }
263
264 fn compare_point(&self, node: &Node, offset: u32) -> Fallible<Ordering> {
266 if node.GetRootNode(&Default::default()) != self.root() {
269 return Err(Error::WrongDocument(None));
270 }
271 if node.is_doctype() {
274 return Err(Error::InvalidNodeType(None));
275 }
276 if offset > node.len() {
279 return Err(Error::IndexSize(None));
280 }
281 let start_node = self.start_container();
283 if let Ordering::Less = bp_position(node, offset, &start_node, self.start_offset()) {
284 return Ok(Ordering::Less);
285 }
286 if let Ordering::Greater =
288 bp_position(node, offset, &self.end_container(), self.end_offset())
289 {
290 return Ok(Ordering::Greater);
291 }
292 Ok(Ordering::Equal)
294 }
295
296 pub(crate) fn associate_selection(&self, selection: &Selection) {
297 let mut selections = self.associated_selections.borrow_mut();
298 if !selections.iter().any(|s| &**s == selection) {
299 selections.push(Dom::from_ref(selection));
300 }
301 }
302
303 pub(crate) fn disassociate_selection(&self, selection: &Selection) {
304 self.associated_selections
305 .borrow_mut()
306 .retain(|s| &**s != selection);
307 }
308
309 fn report_change(&self) {
310 self.associated_selections
311 .borrow()
312 .iter()
313 .for_each(|selection| {
314 selection.queue_selectionchange_task();
315 selection.set_visible_selection_dirty();
316 });
317 }
318
319 fn abstract_range(&self) -> &AbstractRange {
320 &self.abstract_range
321 }
322
323 pub(crate) fn start(&self) -> &BoundaryPoint {
324 self.abstract_range().start()
325 }
326
327 pub(crate) fn end(&self) -> &BoundaryPoint {
328 self.abstract_range().end()
329 }
330
331 pub(crate) fn start_and_end_are_in_document_tree(&self) -> bool {
332 self.start_container().is_in_a_document_tree() &&
333 self.end_container().is_in_a_document_tree()
334 }
335
336 pub(crate) fn start_container(&self) -> DomRoot<Node> {
337 self.abstract_range().StartContainer()
338 }
339
340 pub(crate) fn start_offset(&self) -> u32 {
341 self.abstract_range().StartOffset()
342 }
343
344 pub(crate) fn end_container(&self) -> DomRoot<Node> {
345 self.abstract_range().EndContainer()
346 }
347
348 pub(crate) fn end_offset(&self) -> u32 {
349 self.abstract_range().EndOffset()
350 }
351
352 pub(crate) fn collapsed(&self) -> bool {
353 self.abstract_range().Collapsed()
354 }
355
356 fn client_rects(&self, no_gc: &NoGC) -> Vec<Rect<Au, CSSPixel>> {
358 let start = self.start_container();
361 let end = self.end_container();
362 if !start.is_connected() || !end.is_connected() {
365 return vec![];
366 }
367
368 if self.collapsed() {
371 if start.is::<CharacterData>() {
372 return start.border_boxes();
373 } else {
374 return vec![];
375 }
376 }
377
378 let document = start.owner_doc();
379 let end_clone = UnrootedDom::from_dom(Dom::from_ref(&*end), no_gc);
380 start
381 .following_nodes_unrooted(no_gc, document.upcast::<Node>(), ShadowIncluding::No)
382 .take_while(move |node| *node != *end)
383 .chain(iter::once(end_clone))
384 .flat_map(move |node| node.border_boxes())
385 .collect()
386 }
387
388 fn set_the_start_or_end(
390 &self,
391 node: &Node,
392 offset: u32,
393 start_or_end: StartOrEnd,
394 ) -> ErrorResult {
395 if node.is_doctype() {
398 return Err(Error::InvalidNodeType(None));
399 }
400
401 if offset > node.len() {
404 return Err(Error::IndexSize(None));
405 }
406
407 match start_or_end {
410 StartOrEnd::Start => {
412 if self.root() != node.GetRootNode(&Default::default()) ||
415 bp_position(node, offset, &self.end_container(), self.end_offset()) ==
416 Ordering::Greater
417 {
418 self.set_end(node, offset);
419 }
420
421 self.set_start(node, offset);
423 },
424 StartOrEnd::End => {
426 if self.root() != node.GetRootNode(&Default::default()) ||
429 bp_position(node, offset, &self.start_container(), self.start_offset()) ==
430 Ordering::Less
431 {
432 self.set_start(node, offset);
433 }
434
435 self.set_end(node, offset);
437 },
438 }
439
440 Ok(())
441 }
442}
443
444impl std::fmt::Debug for Range {
445 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
446 write!(
447 f,
448 "[({:?}, {}) -> ({:?}, {})]",
449 self.start_container(),
450 self.start_offset(),
451 self.end_container(),
452 self.end_offset()
453 )
454 }
455}
456
457enum StartOrEnd {
458 Start,
459 End,
460}
461
462impl RangeMethods<crate::DomTypeHolder> for Range {
463 fn Constructor(
465 cx: &mut JSContext,
466 window: &Window,
467 proto: Option<HandleObject>,
468 ) -> Fallible<DomRoot<Range>> {
469 let document = window.Document();
470 Ok(Range::new_with_doc(cx, &document, proto))
471 }
472
473 fn CommonAncestorContainer(&self) -> DomRoot<Node> {
475 self.end_container()
476 .common_ancestor(&self.start_container(), ShadowIncluding::No)
477 .expect("Couldn't find common ancestor container")
478 }
479
480 fn SetStart(&self, node: &Node, offset: u32) -> ErrorResult {
482 self.set_the_start_or_end(node, offset, StartOrEnd::Start)
483 }
484
485 fn SetEnd(&self, node: &Node, offset: u32) -> ErrorResult {
487 self.set_the_start_or_end(node, offset, StartOrEnd::End)
488 }
489
490 fn SetStartBefore(&self, node: &Node) -> ErrorResult {
492 let parent = node.GetParentNode().ok_or(Error::InvalidNodeType(None))?;
493 self.SetStart(&parent, node.index())
494 }
495
496 fn SetStartAfter(&self, node: &Node) -> ErrorResult {
498 let parent = node.GetParentNode().ok_or(Error::InvalidNodeType(None))?;
499 self.SetStart(&parent, node.index() + 1)
500 }
501
502 fn SetEndBefore(&self, node: &Node) -> ErrorResult {
504 let parent = node.GetParentNode().ok_or(Error::InvalidNodeType(None))?;
505 self.SetEnd(&parent, node.index())
506 }
507
508 fn SetEndAfter(&self, node: &Node) -> ErrorResult {
510 let parent = node.GetParentNode().ok_or(Error::InvalidNodeType(None))?;
511 self.SetEnd(&parent, node.index() + 1)
512 }
513
514 fn Collapse(&self, to_start: bool) {
516 if to_start {
517 self.set_end(&self.start_container(), self.start_offset());
518 } else {
519 self.set_start(&self.end_container(), self.end_offset());
520 }
521 }
522
523 fn SelectNode(&self, node: &Node) -> ErrorResult {
525 let parent = node.GetParentNode().ok_or(Error::InvalidNodeType(None))?;
527 let index = node.index();
529 self.set_start(&parent, index);
531 self.set_end(&parent, index + 1);
533 Ok(())
534 }
535
536 fn SelectNodeContents(&self, node: &Node) -> ErrorResult {
538 if node.is_doctype() {
539 return Err(Error::InvalidNodeType(None));
541 }
542 let length = node.len();
544 self.set_start(node, 0);
546 self.set_end(node, length);
548 Ok(())
549 }
550
551 fn CompareBoundaryPoints(&self, how: u16, source_range: &Range) -> Fallible<i16> {
553 if how > RangeConstants::END_TO_START {
560 return Err(Error::NotSupported(None));
561 }
562 if self.root() != source_range.root() {
565 return Err(Error::WrongDocument(None));
566 }
567 let (this_point, source_point) = match how {
578 RangeConstants::START_TO_START => (self.start(), source_range.start()),
579 RangeConstants::START_TO_END => (self.end(), source_range.start()),
580 RangeConstants::END_TO_END => (self.end(), source_range.end()),
581 RangeConstants::END_TO_START => (self.start(), source_range.end()),
582 _ => unreachable!(),
583 };
584 match this_point.partial_cmp(source_point).unwrap() {
592 Ordering::Less => Ok(-1),
593 Ordering::Equal => Ok(0),
594 Ordering::Greater => Ok(1),
595 }
596 }
597
598 fn CloneRange(&self, cx: &mut JSContext) -> DomRoot<Range> {
600 let start_node = self.start_container();
601 let owner_doc = start_node.owner_doc();
602 Range::new(
603 cx,
604 &owner_doc,
605 &start_node,
606 self.start_offset(),
607 &self.end_container(),
608 self.end_offset(),
609 )
610 }
611
612 fn IsPointInRange(&self, node: &Node, offset: u32) -> Fallible<bool> {
614 match self.compare_point(node, offset) {
615 Ok(Ordering::Less) => Ok(false),
616 Ok(Ordering::Equal) => Ok(true),
617 Ok(Ordering::Greater) => Ok(false),
618 Err(Error::WrongDocument(None)) => {
619 Ok(false)
622 },
623 Err(error) => Err(error),
624 }
625 }
626
627 fn ComparePoint(&self, node: &Node, offset: u32) -> Fallible<i16> {
629 self.compare_point(node, offset).map(|order| match order {
630 Ordering::Less => -1,
631 Ordering::Equal => 0,
632 Ordering::Greater => 1,
633 })
634 }
635
636 fn IntersectsNode(&self, node: &Node) -> bool {
638 if self.root() != node.GetRootNode(&Default::default()) {
640 return false;
641 }
642 let Some(parent) = node.GetParentNode() else {
644 return true;
646 };
647 let offset = node.index();
649 let start_node = self.start_container();
653 Ordering::Greater == bp_position(&parent, offset + 1, &start_node, self.start_offset()) &&
654 Ordering::Less ==
655 bp_position(&parent, offset, &self.end_container(), self.end_offset())
656 }
657
658 fn CloneContents(&self, cx: &mut JSContext) -> Fallible<DomRoot<DocumentFragment>> {
661 let start_node = self.start_container();
663 let start_offset = self.start_offset();
664 let end_node = self.end_container();
665 let end_offset = self.end_offset();
666
667 let fragment = DocumentFragment::new(cx, &start_node.owner_doc());
669
670 if self.start() == self.end() {
672 return Ok(fragment);
673 }
674
675 if end_node == start_node &&
676 let Some(cdata) = start_node.downcast::<CharacterData>()
677 {
678 let data = cdata
680 .SubstringData(start_offset, end_offset - start_offset)
681 .unwrap();
682 let clone = cdata.clone_with_data(cx, data, &start_node.owner_doc());
683 fragment.upcast::<Node>().AppendChild(cx, &clone)?;
685 return Ok(fragment);
687 }
688
689 let ContainedChildren {
691 first_partially_contained_child,
692 last_partially_contained_child,
693 contained_children,
694 } = self.contained_children()?;
695
696 if let Some(child) = first_partially_contained_child {
697 if let Some(cdata) = child.downcast::<CharacterData>() {
699 assert!(child == start_node);
700 let data = cdata
702 .SubstringData(start_offset, start_node.len() - start_offset)
703 .unwrap();
704 let clone = cdata.clone_with_data(cx, data, &start_node.owner_doc());
705 fragment.upcast::<Node>().AppendChild(cx, &clone)?;
707 } else {
708 let clone = child.CloneNode(cx, false)?;
710 fragment.upcast::<Node>().AppendChild(cx, &clone)?;
712 let subrange = Range::new(
714 cx,
715 &clone.owner_doc(),
716 &start_node,
717 start_offset,
718 &child,
719 child.len(),
720 );
721 let subfragment = subrange.CloneContents(cx)?;
723 clone.AppendChild(cx, subfragment.upcast())?;
725 }
726 }
727
728 for child in contained_children {
730 let clone = child.CloneNode(cx, true)?;
732 fragment.upcast::<Node>().AppendChild(cx, &clone)?;
734 }
735
736 if let Some(child) = last_partially_contained_child {
737 if let Some(cdata) = child.downcast::<CharacterData>() {
739 assert!(child == end_node);
740 let data = cdata.SubstringData(0, end_offset).unwrap();
742 let clone = cdata.clone_with_data(cx, data, &start_node.owner_doc());
743 fragment.upcast::<Node>().AppendChild(cx, &clone)?;
745 } else {
746 let clone = child.CloneNode(cx, false)?;
748 fragment.upcast::<Node>().AppendChild(cx, &clone)?;
750 let subrange = Range::new(cx, &clone.owner_doc(), &child, 0, &end_node, end_offset);
752 let subfragment = subrange.CloneContents(cx)?;
754 clone.AppendChild(cx, subfragment.upcast())?;
756 }
757 }
758
759 Ok(fragment)
761 }
762
763 fn ExtractContents(&self, cx: &mut JSContext) -> Fallible<DomRoot<DocumentFragment>> {
766 let start_node = self.start_container();
768 let start_offset = self.start_offset();
769 let end_node = self.end_container();
770 let end_offset = self.end_offset();
771
772 let fragment = DocumentFragment::new(cx, &start_node.owner_doc());
774
775 if self.collapsed() {
777 return Ok(fragment);
778 }
779
780 if end_node == start_node &&
781 let Some(end_data) = end_node.downcast::<CharacterData>()
782 {
783 let clone = end_node.CloneNode(cx, true)?;
785 let text = end_data.SubstringData(start_offset, end_offset - start_offset);
787 clone
788 .downcast::<CharacterData>()
789 .unwrap()
790 .SetData(cx, text.unwrap());
791 fragment.upcast::<Node>().AppendChild(cx, &clone)?;
793 end_data.ReplaceData(
795 cx,
796 start_offset,
797 end_offset - start_offset,
798 DOMString::new(),
799 )?;
800 return Ok(fragment);
802 }
803
804 let ContainedChildren {
806 first_partially_contained_child,
807 last_partially_contained_child,
808 contained_children,
809 } = self.contained_children()?;
810
811 let (new_node, new_offset) = if start_node.is_inclusive_ancestor_of(&end_node) {
812 (DomRoot::from_ref(&*start_node), start_offset)
814 } else {
815 let reference_node = start_node
817 .ancestors()
818 .take_while(|n| !n.is_inclusive_ancestor_of(&end_node))
819 .last()
820 .unwrap_or(DomRoot::from_ref(&start_node));
821 (
823 reference_node.GetParentNode().unwrap(),
824 reference_node.index() + 1,
825 )
826 };
827
828 if let Some(child) = first_partially_contained_child {
829 if let Some(start_data) = child.downcast::<CharacterData>() {
830 assert!(child == start_node);
831 let clone = start_node.CloneNode(cx, true)?;
833 let text = start_data.SubstringData(start_offset, start_node.len() - start_offset);
835 clone
836 .downcast::<CharacterData>()
837 .unwrap()
838 .SetData(cx, text.unwrap());
839 fragment.upcast::<Node>().AppendChild(cx, &clone)?;
841 start_data.ReplaceData(
843 cx,
844 start_offset,
845 start_node.len() - start_offset,
846 DOMString::new(),
847 )?;
848 } else {
849 let clone = child.CloneNode(cx, false)?;
851 fragment.upcast::<Node>().AppendChild(cx, &clone)?;
853 let subrange = Range::new(
855 cx,
856 &clone.owner_doc(),
857 &start_node,
858 start_offset,
859 &child,
860 child.len(),
861 );
862 let subfragment = subrange.ExtractContents(cx)?;
864 clone.AppendChild(cx, subfragment.upcast())?;
866 }
867 }
868
869 for child in contained_children {
871 fragment.upcast::<Node>().AppendChild(cx, &child)?;
872 }
873
874 if let Some(child) = last_partially_contained_child {
875 if let Some(end_data) = child.downcast::<CharacterData>() {
876 assert!(child == end_node);
877 let clone = end_node.CloneNode(cx, true)?;
879 let text = end_data.SubstringData(0, end_offset);
881 clone
882 .downcast::<CharacterData>()
883 .unwrap()
884 .SetData(cx, text.unwrap());
885 fragment.upcast::<Node>().AppendChild(cx, &clone)?;
887 end_data.ReplaceData(cx, 0, end_offset, DOMString::new())?;
889 } else {
890 let clone = child.CloneNode(cx, false)?;
892 fragment.upcast::<Node>().AppendChild(cx, &clone)?;
894 let subrange = Range::new(cx, &clone.owner_doc(), &child, 0, &end_node, end_offset);
896 let subfragment = subrange.ExtractContents(cx)?;
898 clone.AppendChild(cx, subfragment.upcast())?;
900 }
901 }
902
903 self.SetStart(&new_node, new_offset)?;
905 self.SetEnd(&new_node, new_offset)?;
906
907 Ok(fragment)
909 }
910
911 fn Detach(&self) {
913 }
915
916 fn InsertNode(&self, cx: &mut JSContext, node: &Node) -> ErrorResult {
919 let start_node = self.start_container();
920 let start_offset = self.start_offset();
921
922 if &*start_node == node {
924 return Err(Error::HierarchyRequest(None));
925 }
926 match start_node.type_id() {
927 NodeTypeId::CharacterData(CharacterDataTypeId::Text(_)) => (),
929 NodeTypeId::CharacterData(_) => return Err(Error::HierarchyRequest(None)),
930 _ => (),
931 }
932
933 let (reference_node, parent) = match start_node.type_id() {
935 NodeTypeId::CharacterData(CharacterDataTypeId::Text(_)) => {
936 let parent = match start_node.GetParentNode() {
938 Some(parent) => parent,
939 None => return Err(Error::HierarchyRequest(None)),
941 };
942 (Some(DomRoot::from_ref(&*start_node)), parent)
944 },
945 _ => {
946 let child = start_node.ChildNodes(cx).Item(cx, start_offset);
948 (child, DomRoot::from_ref(&*start_node))
949 },
950 };
951
952 Node::ensure_pre_insertion_validity(cx.no_gc(), node, &parent, reference_node.as_deref())?;
954
955 let split_text;
957 let reference_node = match start_node.downcast::<Text>() {
958 Some(text) => {
959 split_text = text.SplitText(cx, start_offset)?;
960 let new_reference = DomRoot::upcast::<Node>(split_text);
961 assert!(new_reference.GetParentNode().as_deref() == Some(&parent));
962 Some(new_reference)
963 },
964 _ => reference_node,
965 };
966
967 let reference_node = if Some(node) == reference_node.as_deref() {
969 node.GetNextSibling()
970 } else {
971 reference_node
972 };
973
974 node.remove_self(cx);
976
977 let new_offset = reference_node
979 .as_ref()
980 .map_or(parent.len(), |node| node.index());
981
982 let new_offset = new_offset +
984 if let NodeTypeId::DocumentFragment(_) = node.type_id() {
985 node.len()
986 } else {
987 1
988 };
989
990 Node::pre_insert(cx, node, &parent, reference_node.as_deref())?;
992
993 if self.collapsed() {
995 self.set_end(&parent, new_offset);
996 }
997
998 Ok(())
999 }
1000
1001 fn DeleteContents(&self, cx: &mut JSContext) -> ErrorResult {
1003 if self.collapsed() {
1005 return Ok(());
1006 }
1007
1008 let start_node = self.start_container();
1011 let end_node = self.end_container();
1012 let start_offset = self.start_offset();
1013 let end_offset = self.end_offset();
1014
1015 if start_node == end_node &&
1017 let Some(text) = start_node.downcast::<CharacterData>()
1018 {
1019 if end_offset > start_offset {
1020 self.report_change();
1021 }
1022
1023 return text.ReplaceData(
1027 cx,
1028 start_offset,
1029 end_offset - start_offset,
1030 DOMString::new(),
1031 );
1032 }
1033
1034 rooted_vec!(let mut contained_children);
1037 let ancestor = self.CommonAncestorContainer();
1038
1039 let mut iter = start_node.following_nodes(&ancestor, ShadowIncluding::No);
1040
1041 let mut next = iter.next();
1042 while let Some(child) = next {
1043 if self.contains(&child) {
1044 contained_children.push(Dom::from_ref(&*child));
1045 next = iter.next_skipping_children();
1046 } else {
1047 next = iter.next();
1048 }
1049 }
1050
1051 let (new_node, new_offset) = if start_node.is_inclusive_ancestor_of(&end_node) {
1055 (DomRoot::from_ref(&*start_node), start_offset)
1056 } else {
1057 fn compute_reference(start_node: &Node, end_node: &Node) -> (DomRoot<Node>, u32) {
1059 let mut reference_node = DomRoot::from_ref(start_node);
1061 while let Some(parent) = reference_node.GetParentNode() {
1064 if parent.is_inclusive_ancestor_of(end_node) {
1065 return (parent, reference_node.index() + 1);
1067 }
1068 reference_node = parent;
1069 }
1070 unreachable!()
1071 }
1072
1073 compute_reference(&start_node, &end_node)
1074 };
1075
1076 self.SetStart(&new_node, new_offset).unwrap();
1078 self.SetEnd(&new_node, new_offset).unwrap();
1079
1080 if let Some(text) = start_node.downcast::<CharacterData>() {
1084 text.ReplaceData(
1085 cx,
1086 start_offset,
1087 start_node.len() - start_offset,
1088 DOMString::new(),
1089 )
1090 .unwrap();
1091 }
1092
1093 for child in &*contained_children {
1095 child.remove_self(cx);
1096 }
1097
1098 if let Some(text) = end_node.downcast::<CharacterData>() {
1101 text.ReplaceData(cx, 0, end_offset, DOMString::new())
1102 .unwrap();
1103 }
1104
1105 Ok(())
1106 }
1107
1108 fn SurroundContents(&self, cx: &mut JSContext, new_parent: &Node) -> ErrorResult {
1110 let start = self.start_container();
1112 let end = self.end_container();
1113
1114 if start
1115 .inclusive_ancestors(ShadowIncluding::No)
1116 .any(|n| !n.is_inclusive_ancestor_of(&end) && !n.is::<Text>()) ||
1117 end.inclusive_ancestors(ShadowIncluding::No)
1118 .any(|n| !n.is_inclusive_ancestor_of(&start) && !n.is::<Text>())
1119 {
1120 return Err(Error::InvalidState(None));
1121 }
1122
1123 match new_parent.type_id() {
1125 NodeTypeId::Document(_) |
1126 NodeTypeId::DocumentType |
1127 NodeTypeId::DocumentFragment(_) => {
1128 return Err(Error::InvalidNodeType(None));
1129 },
1130 _ => (),
1131 }
1132
1133 let fragment = self.ExtractContents(cx)?;
1135
1136 Node::replace_all(cx, None, new_parent);
1138
1139 self.InsertNode(cx, new_parent)?;
1141
1142 new_parent.AppendChild(cx, fragment.upcast())?;
1144
1145 self.SelectNode(new_parent)
1147 }
1148
1149 fn Stringifier(&self, no_gc: &NoGC) -> DOMString {
1151 let start_node = self.start_container();
1152 let end_node = self.end_container();
1153
1154 let mut s = DOMString::new();
1156
1157 if let Some(text_node) = start_node.downcast::<Text>() {
1158 let char_data = text_node.upcast::<CharacterData>();
1159
1160 if start_node == end_node {
1164 return char_data
1165 .SubstringData(self.start_offset(), self.end_offset() - self.start_offset())
1166 .unwrap();
1167 }
1168
1169 s.push_str(
1172 &char_data
1173 .SubstringData(
1174 self.start_offset(),
1175 char_data.Length() - self.start_offset(),
1176 )
1177 .unwrap()
1178 .str(),
1179 );
1180 }
1181
1182 let ancestor = self.CommonAncestorContainer();
1185 let iter = start_node
1186 .following_nodes_unrooted(no_gc, &ancestor, ShadowIncluding::No)
1187 .filter_map(UnrootedDom::downcast::<Text>);
1188
1189 for child in iter {
1190 if self.contains(child.upcast()) {
1191 s.push_str(&child.upcast::<CharacterData>().Data().str());
1192 }
1193 }
1194
1195 if let Some(text_node) = end_node.downcast::<Text>() {
1198 let char_data = text_node.upcast::<CharacterData>();
1199 s.push_str(&char_data.SubstringData(0, self.end_offset()).unwrap().str());
1200 }
1201
1202 s
1204 }
1205
1206 fn CreateContextualFragment(
1208 &self,
1209 cx: &mut JSContext,
1210 fragment: TrustedHTMLOrString,
1211 ) -> Fallible<DomRoot<DocumentFragment>> {
1212 let node = self.start_container();
1217
1218 let fragment = TrustedHTML::get_trusted_type_compliant_string(
1222 cx,
1223 node.owner_window().upcast(),
1224 fragment,
1225 "Range createContextualFragment",
1226 )?;
1227
1228 let owner_doc = node.owner_doc();
1229
1230 let element = match node.type_id() {
1234 NodeTypeId::Element(_) => Some(DomRoot::downcast::<Element>(node).unwrap()),
1235 NodeTypeId::CharacterData(CharacterDataTypeId::Comment) |
1236 NodeTypeId::CharacterData(CharacterDataTypeId::Text(_)) => node.GetParentElement(),
1237 _ => None,
1238 };
1239
1240 let element = Element::fragment_parsing_context(cx, &owner_doc, element.as_deref());
1242
1243 let fragment_node = element.parse_fragment(fragment, cx)?;
1245
1246 for node in fragment_node
1248 .upcast::<Node>()
1249 .traverse_preorder(ShadowIncluding::No)
1250 {
1251 if let Some(script) = node.downcast::<HTMLScriptElement>() {
1252 script.set_already_started(false);
1254 script.set_parser_inserted(false);
1256 }
1257 }
1258
1259 Ok(fragment_node)
1261 }
1262
1263 fn GetClientRects(&self, cx: &mut JSContext) -> DomRoot<DOMRectList> {
1265 let start = self.start_container();
1266 let window = start.owner_window();
1267
1268 let client_rects = self.client_rects(cx.no_gc());
1269 let client_rects = client_rects
1270 .iter()
1271 .map(|rect| {
1272 DOMRect::new(
1273 cx,
1274 window.upcast(),
1275 rect.origin.x.to_f64_px(),
1276 rect.origin.y.to_f64_px(),
1277 rect.size.width.to_f64_px(),
1278 rect.size.height.to_f64_px(),
1279 )
1280 })
1281 .collect();
1282
1283 DOMRectList::new(cx, &window, client_rects)
1284 }
1285
1286 fn GetBoundingClientRect(&self, cx: &mut JSContext) -> DomRoot<DOMRect> {
1288 let window = self.start_container().owner_window();
1289
1290 let list = self.client_rects(cx.no_gc());
1292
1293 let bounding_rect = list
1298 .into_iter()
1299 .fold(euclid::Rect::zero(), |acc, rect| acc.union(&rect));
1300
1301 DOMRect::new(
1302 cx,
1303 window.upcast(),
1304 bounding_rect.origin.x.to_f64_px(),
1305 bounding_rect.origin.y.to_f64_px(),
1306 bounding_rect.size.width.to_f64_px(),
1307 bounding_rect.size.height.to_f64_px(),
1308 )
1309 }
1310}
1311
1312#[derive(MallocSizeOf)]
1313pub(crate) struct WeakRangeVec {
1314 cell: RefCell<WeakRefVec<Range>>,
1315}
1316
1317impl Default for WeakRangeVec {
1318 fn default() -> Self {
1319 WeakRangeVec {
1320 cell: RefCell::new(WeakRefVec::new()),
1321 }
1322 }
1323}
1324
1325impl WeakRangeVec {
1326 pub(crate) fn is_empty(&self) -> bool {
1328 self.cell.borrow().is_empty()
1329 }
1330
1331 pub(crate) fn increase_above(&self, node: &Node, offset: u32, delta: u32) {
1334 self.map_offset_above(node, offset, |offset| offset + delta);
1335 }
1336
1337 pub(crate) fn decrease_above(&self, node: &Node, offset: u32, delta: u32) {
1340 self.map_offset_above(node, offset, |offset| offset - delta);
1341 }
1342
1343 pub(crate) fn drain_to_parent(&self, parent: &Node, offset: u32, child: &Node) {
1347 if self.is_empty() {
1348 return;
1349 }
1350
1351 let ranges = &mut *self.cell.borrow_mut();
1352
1353 ranges.update(|entry| {
1354 let range = entry.root().unwrap();
1355 if range.start().node() == parent || range.end().node() == parent {
1356 entry.remove();
1357 }
1358 if range.start().node() == child {
1359 range.report_change();
1360 range.start().set(parent, offset);
1361 }
1362 if range.end().node() == child {
1363 range.report_change();
1364 range.end().set(parent, offset);
1365 }
1366 });
1367
1368 parent
1369 .ensure_weak_ranges()
1370 .cell
1371 .borrow_mut()
1372 .extend(ranges.drain(..));
1373 }
1374
1375 pub(crate) fn drain_to_preceding_text_sibling(&self, node: &Node, sibling: &Node, length: u32) {
1378 if self.is_empty() {
1379 return;
1380 }
1381
1382 let ranges = &mut *self.cell.borrow_mut();
1383
1384 ranges.update(|entry| {
1385 let range = entry.root().unwrap();
1386 if range.start().node() == sibling || range.end().node() == sibling {
1387 entry.remove();
1388 }
1389 if range.start().node() == node {
1390 range.report_change();
1391 range.start().set(sibling, range.start_offset() + length);
1392 }
1393 if range.end().node() == node {
1394 range.report_change();
1395 range.end().set(sibling, range.end_offset() + length);
1396 }
1397 });
1398
1399 sibling
1400 .ensure_weak_ranges()
1401 .cell
1402 .borrow_mut()
1403 .extend(ranges.drain(..));
1404 }
1405
1406 pub(crate) fn move_to_text_child_at(
1409 &self,
1410 node: &Node,
1411 offset: u32,
1412 child: &Node,
1413 new_offset: u32,
1414 ) {
1415 self.cell.borrow_mut().update(|entry| {
1416 let range = entry.root().unwrap();
1417
1418 let node_is_start = range.start().node() == node;
1419 let node_is_end = range.end().node() == node;
1420
1421 let move_start = node_is_start && range.start_offset() == offset;
1422 let move_end = node_is_end && range.end_offset() == offset;
1423
1424 let remove_from_node =
1425 move_start && (move_end || !node_is_end) || move_end && !node_is_start;
1426
1427 let already_in_child = range.start().node() == child || range.end().node() == child;
1428 let push_to_child = !already_in_child && (move_start || move_end);
1429
1430 if remove_from_node {
1431 let weak_range = entry.remove();
1432 if push_to_child {
1433 child
1434 .ensure_weak_ranges()
1435 .cell
1436 .borrow_mut()
1437 .push(weak_range);
1438 }
1439 } else if push_to_child {
1440 child
1441 .ensure_weak_ranges()
1442 .cell
1443 .borrow_mut()
1444 .push(WeakRef::new(&range));
1445 }
1446
1447 if move_start {
1448 range.report_change();
1449 range.start().set(child, new_offset);
1450 }
1451 if move_end {
1452 range.report_change();
1453 range.end().set(child, new_offset);
1454 }
1455 });
1456 }
1457
1458 pub(crate) fn replace_code_units(
1461 &self,
1462 node: &Node,
1463 offset: u32,
1464 removed_code_units: u32,
1465 added_code_units: u32,
1466 ) {
1467 self.map_offset_above(node, offset, |range_offset| {
1468 if range_offset <= offset + removed_code_units {
1469 offset
1470 } else {
1471 range_offset + added_code_units - removed_code_units
1472 }
1473 });
1474 }
1475
1476 pub(crate) fn move_to_following_text_sibling_above(
1479 &self,
1480 node: &Node,
1481 offset: u32,
1482 sibling: &Node,
1483 ) {
1484 self.cell.borrow_mut().update(|entry| {
1485 let range = entry.root().unwrap();
1486 let start_offset = range.start_offset();
1487 let end_offset = range.end_offset();
1488
1489 let node_is_start = range.start().node() == node;
1490 let node_is_end = range.end().node() == node;
1491
1492 let move_start = node_is_start && start_offset > offset;
1493 let move_end = node_is_end && end_offset > offset;
1494
1495 let remove_from_node =
1496 move_start && (move_end || !node_is_end) || move_end && !node_is_start;
1497
1498 let already_in_sibling =
1499 range.start().node() == sibling || range.end().node() == sibling;
1500 let push_to_sibling = !already_in_sibling && (move_start || move_end);
1501
1502 if remove_from_node {
1503 let weak_range = entry.remove();
1504 if push_to_sibling {
1505 sibling
1506 .ensure_weak_ranges()
1507 .cell
1508 .borrow_mut()
1509 .push(weak_range);
1510 }
1511 } else if push_to_sibling {
1512 sibling
1513 .ensure_weak_ranges()
1514 .cell
1515 .borrow_mut()
1516 .push(WeakRef::new(&range));
1517 }
1518
1519 if move_start {
1520 range.report_change();
1521 range.start().set(sibling, start_offset - offset);
1522 }
1523 if move_end {
1524 range.report_change();
1525 range.end().set(sibling, end_offset - offset);
1526 }
1527 });
1528 }
1529
1530 pub(crate) fn increment_at(&self, node: &Node, offset: u32) {
1533 self.cell.borrow_mut().update(|entry| {
1534 let range = entry.root().unwrap();
1535 if range.start().node() == node && offset == range.start_offset() {
1536 range.report_change();
1537 range.start().set_offset(offset + 1);
1538 }
1539 if range.end().node() == node && offset == range.end_offset() {
1540 range.report_change();
1541 range.end().set_offset(offset + 1);
1542 }
1543 });
1544 }
1545
1546 fn map_offset_above<F: FnMut(u32) -> u32>(&self, node: &Node, offset: u32, mut f: F) {
1547 self.cell.borrow_mut().update(|entry| {
1548 let range = entry.root().unwrap();
1549 let start_offset = range.start_offset();
1550 if range.start().node() == node && start_offset > offset {
1551 range.report_change();
1552 range.start().set_offset(f(start_offset));
1553 }
1554 let end_offset = range.end_offset();
1555 if range.end().node() == node && end_offset > offset {
1556 range.report_change();
1557 range.end().set_offset(f(end_offset));
1558 }
1559 });
1560 }
1561
1562 pub(crate) fn push(&self, ref_: WeakRef<Range>) {
1563 self.cell.borrow_mut().push(ref_);
1564 }
1565
1566 fn remove(&self, range: &Range) -> WeakRef<Range> {
1567 let mut ranges = self.cell.borrow_mut();
1568 let position = ranges.iter().position(|ref_| ref_ == range).unwrap();
1569 ranges.swap_remove(position)
1570 }
1571}
1572
1573#[expect(unsafe_code)]
1574unsafe impl JSTraceable for WeakRangeVec {
1575 unsafe fn trace(&self, _: *mut JSTracer) {
1576 self.cell.borrow_mut().retain_alive()
1577 }
1578}