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(|s| s.queue_selectionchange_task());
314 }
315
316 fn abstract_range(&self) -> &AbstractRange {
317 &self.abstract_range
318 }
319
320 fn start(&self) -> &BoundaryPoint {
321 self.abstract_range().start()
322 }
323
324 fn end(&self) -> &BoundaryPoint {
325 self.abstract_range().end()
326 }
327
328 pub(crate) fn start_and_end_are_in_document_tree(&self) -> bool {
329 self.start_container().is_in_a_document_tree() &&
330 self.end_container().is_in_a_document_tree()
331 }
332
333 pub(crate) fn start_container(&self) -> DomRoot<Node> {
334 self.abstract_range().StartContainer()
335 }
336
337 pub(crate) fn start_offset(&self) -> u32 {
338 self.abstract_range().StartOffset()
339 }
340
341 pub(crate) fn end_container(&self) -> DomRoot<Node> {
342 self.abstract_range().EndContainer()
343 }
344
345 pub(crate) fn end_offset(&self) -> u32 {
346 self.abstract_range().EndOffset()
347 }
348
349 pub(crate) fn collapsed(&self) -> bool {
350 self.abstract_range().Collapsed()
351 }
352
353 fn client_rects<'a>(&self, no_gc: &'a NoGC) -> impl Iterator<Item = Rect<Au, CSSPixel>> + 'a {
354 let start = self.start_container();
357 let end = self.end_container();
358 let document = start.owner_doc();
359 let end_clone = UnrootedDom::from_dom(Dom::from_ref(&*end), no_gc);
360 start
361 .following_nodes_unrooted(no_gc, document.upcast::<Node>(), ShadowIncluding::No)
362 .take_while(move |node| *node != *end)
363 .chain(iter::once(end_clone))
364 .flat_map(move |node| node.border_boxes())
365 }
366
367 fn set_the_start_or_end(
369 &self,
370 node: &Node,
371 offset: u32,
372 start_or_end: StartOrEnd,
373 ) -> ErrorResult {
374 if node.is_doctype() {
377 return Err(Error::InvalidNodeType(None));
378 }
379
380 if offset > node.len() {
383 return Err(Error::IndexSize(None));
384 }
385
386 match start_or_end {
389 StartOrEnd::Start => {
391 if self.root() != node.GetRootNode(&Default::default()) ||
394 bp_position(node, offset, &self.end_container(), self.end_offset()) ==
395 Ordering::Greater
396 {
397 self.set_end(node, offset);
398 }
399
400 self.set_start(node, offset);
402 },
403 StartOrEnd::End => {
405 if self.root() != node.GetRootNode(&Default::default()) ||
408 bp_position(node, offset, &self.start_container(), self.start_offset()) ==
409 Ordering::Less
410 {
411 self.set_start(node, offset);
412 }
413
414 self.set_end(node, offset);
416 },
417 }
418
419 Ok(())
420 }
421}
422
423impl std::fmt::Debug for Range {
424 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
425 write!(
426 f,
427 "[({:?}, {}) -> ({:?}, {})]",
428 self.start_container(),
429 self.start_offset(),
430 self.end_container(),
431 self.end_offset()
432 )
433 }
434}
435
436enum StartOrEnd {
437 Start,
438 End,
439}
440
441impl RangeMethods<crate::DomTypeHolder> for Range {
442 fn Constructor(
444 cx: &mut JSContext,
445 window: &Window,
446 proto: Option<HandleObject>,
447 ) -> Fallible<DomRoot<Range>> {
448 let document = window.Document();
449 Ok(Range::new_with_doc(cx, &document, proto))
450 }
451
452 fn CommonAncestorContainer(&self) -> DomRoot<Node> {
454 self.end_container()
455 .common_ancestor(&self.start_container(), ShadowIncluding::No)
456 .expect("Couldn't find common ancestor container")
457 }
458
459 fn SetStart(&self, node: &Node, offset: u32) -> ErrorResult {
461 self.set_the_start_or_end(node, offset, StartOrEnd::Start)
462 }
463
464 fn SetEnd(&self, node: &Node, offset: u32) -> ErrorResult {
466 self.set_the_start_or_end(node, offset, StartOrEnd::End)
467 }
468
469 fn SetStartBefore(&self, node: &Node) -> ErrorResult {
471 let parent = node.GetParentNode().ok_or(Error::InvalidNodeType(None))?;
472 self.SetStart(&parent, node.index())
473 }
474
475 fn SetStartAfter(&self, node: &Node) -> ErrorResult {
477 let parent = node.GetParentNode().ok_or(Error::InvalidNodeType(None))?;
478 self.SetStart(&parent, node.index() + 1)
479 }
480
481 fn SetEndBefore(&self, node: &Node) -> ErrorResult {
483 let parent = node.GetParentNode().ok_or(Error::InvalidNodeType(None))?;
484 self.SetEnd(&parent, node.index())
485 }
486
487 fn SetEndAfter(&self, node: &Node) -> ErrorResult {
489 let parent = node.GetParentNode().ok_or(Error::InvalidNodeType(None))?;
490 self.SetEnd(&parent, node.index() + 1)
491 }
492
493 fn Collapse(&self, to_start: bool) {
495 if to_start {
496 self.set_end(&self.start_container(), self.start_offset());
497 } else {
498 self.set_start(&self.end_container(), self.end_offset());
499 }
500 }
501
502 fn SelectNode(&self, node: &Node) -> ErrorResult {
504 let parent = node.GetParentNode().ok_or(Error::InvalidNodeType(None))?;
506 let index = node.index();
508 self.set_start(&parent, index);
510 self.set_end(&parent, index + 1);
512 Ok(())
513 }
514
515 fn SelectNodeContents(&self, node: &Node) -> ErrorResult {
517 if node.is_doctype() {
518 return Err(Error::InvalidNodeType(None));
520 }
521 let length = node.len();
523 self.set_start(node, 0);
525 self.set_end(node, length);
527 Ok(())
528 }
529
530 fn CompareBoundaryPoints(&self, how: u16, source_range: &Range) -> Fallible<i16> {
532 if how > RangeConstants::END_TO_START {
539 return Err(Error::NotSupported(None));
540 }
541 if self.root() != source_range.root() {
544 return Err(Error::WrongDocument(None));
545 }
546 let (this_point, source_point) = match how {
557 RangeConstants::START_TO_START => (self.start(), source_range.start()),
558 RangeConstants::START_TO_END => (self.end(), source_range.start()),
559 RangeConstants::END_TO_END => (self.end(), source_range.end()),
560 RangeConstants::END_TO_START => (self.start(), source_range.end()),
561 _ => unreachable!(),
562 };
563 match this_point.partial_cmp(source_point).unwrap() {
571 Ordering::Less => Ok(-1),
572 Ordering::Equal => Ok(0),
573 Ordering::Greater => Ok(1),
574 }
575 }
576
577 fn CloneRange(&self, cx: &mut JSContext) -> DomRoot<Range> {
579 let start_node = self.start_container();
580 let owner_doc = start_node.owner_doc();
581 Range::new(
582 cx,
583 &owner_doc,
584 &start_node,
585 self.start_offset(),
586 &self.end_container(),
587 self.end_offset(),
588 )
589 }
590
591 fn IsPointInRange(&self, node: &Node, offset: u32) -> Fallible<bool> {
593 match self.compare_point(node, offset) {
594 Ok(Ordering::Less) => Ok(false),
595 Ok(Ordering::Equal) => Ok(true),
596 Ok(Ordering::Greater) => Ok(false),
597 Err(Error::WrongDocument(None)) => {
598 Ok(false)
601 },
602 Err(error) => Err(error),
603 }
604 }
605
606 fn ComparePoint(&self, node: &Node, offset: u32) -> Fallible<i16> {
608 self.compare_point(node, offset).map(|order| match order {
609 Ordering::Less => -1,
610 Ordering::Equal => 0,
611 Ordering::Greater => 1,
612 })
613 }
614
615 fn IntersectsNode(&self, node: &Node) -> bool {
617 if self.root() != node.GetRootNode(&Default::default()) {
619 return false;
620 }
621 let Some(parent) = node.GetParentNode() else {
623 return true;
625 };
626 let offset = node.index();
628 let start_node = self.start_container();
632 Ordering::Greater == bp_position(&parent, offset + 1, &start_node, self.start_offset()) &&
633 Ordering::Less ==
634 bp_position(&parent, offset, &self.end_container(), self.end_offset())
635 }
636
637 fn CloneContents(&self, cx: &mut JSContext) -> Fallible<DomRoot<DocumentFragment>> {
640 let start_node = self.start_container();
642 let start_offset = self.start_offset();
643 let end_node = self.end_container();
644 let end_offset = self.end_offset();
645
646 let fragment = DocumentFragment::new(cx, &start_node.owner_doc());
648
649 if self.start() == self.end() {
651 return Ok(fragment);
652 }
653
654 if end_node == start_node &&
655 let Some(cdata) = start_node.downcast::<CharacterData>()
656 {
657 let data = cdata
659 .SubstringData(start_offset, end_offset - start_offset)
660 .unwrap();
661 let clone = cdata.clone_with_data(cx, data, &start_node.owner_doc());
662 fragment.upcast::<Node>().AppendChild(cx, &clone)?;
664 return Ok(fragment);
666 }
667
668 let ContainedChildren {
670 first_partially_contained_child,
671 last_partially_contained_child,
672 contained_children,
673 } = self.contained_children()?;
674
675 if let Some(child) = first_partially_contained_child {
676 if let Some(cdata) = child.downcast::<CharacterData>() {
678 assert!(child == start_node);
679 let data = cdata
681 .SubstringData(start_offset, start_node.len() - start_offset)
682 .unwrap();
683 let clone = cdata.clone_with_data(cx, data, &start_node.owner_doc());
684 fragment.upcast::<Node>().AppendChild(cx, &clone)?;
686 } else {
687 let clone = child.CloneNode(cx, false)?;
689 fragment.upcast::<Node>().AppendChild(cx, &clone)?;
691 let subrange = Range::new(
693 cx,
694 &clone.owner_doc(),
695 &start_node,
696 start_offset,
697 &child,
698 child.len(),
699 );
700 let subfragment = subrange.CloneContents(cx)?;
702 clone.AppendChild(cx, subfragment.upcast())?;
704 }
705 }
706
707 for child in contained_children {
709 let clone = child.CloneNode(cx, true)?;
711 fragment.upcast::<Node>().AppendChild(cx, &clone)?;
713 }
714
715 if let Some(child) = last_partially_contained_child {
716 if let Some(cdata) = child.downcast::<CharacterData>() {
718 assert!(child == end_node);
719 let data = cdata.SubstringData(0, end_offset).unwrap();
721 let clone = cdata.clone_with_data(cx, data, &start_node.owner_doc());
722 fragment.upcast::<Node>().AppendChild(cx, &clone)?;
724 } else {
725 let clone = child.CloneNode(cx, false)?;
727 fragment.upcast::<Node>().AppendChild(cx, &clone)?;
729 let subrange = Range::new(cx, &clone.owner_doc(), &child, 0, &end_node, end_offset);
731 let subfragment = subrange.CloneContents(cx)?;
733 clone.AppendChild(cx, subfragment.upcast())?;
735 }
736 }
737
738 Ok(fragment)
740 }
741
742 fn ExtractContents(&self, cx: &mut JSContext) -> Fallible<DomRoot<DocumentFragment>> {
745 let start_node = self.start_container();
747 let start_offset = self.start_offset();
748 let end_node = self.end_container();
749 let end_offset = self.end_offset();
750
751 let fragment = DocumentFragment::new(cx, &start_node.owner_doc());
753
754 if self.collapsed() {
756 return Ok(fragment);
757 }
758
759 if end_node == start_node &&
760 let Some(end_data) = end_node.downcast::<CharacterData>()
761 {
762 let clone = end_node.CloneNode(cx, true)?;
764 let text = end_data.SubstringData(start_offset, end_offset - start_offset);
766 clone
767 .downcast::<CharacterData>()
768 .unwrap()
769 .SetData(cx, text.unwrap());
770 fragment.upcast::<Node>().AppendChild(cx, &clone)?;
772 end_data.ReplaceData(
774 cx,
775 start_offset,
776 end_offset - start_offset,
777 DOMString::new(),
778 )?;
779 return Ok(fragment);
781 }
782
783 let ContainedChildren {
785 first_partially_contained_child,
786 last_partially_contained_child,
787 contained_children,
788 } = self.contained_children()?;
789
790 let (new_node, new_offset) = if start_node.is_inclusive_ancestor_of(&end_node) {
791 (DomRoot::from_ref(&*start_node), start_offset)
793 } else {
794 let reference_node = start_node
796 .ancestors()
797 .take_while(|n| !n.is_inclusive_ancestor_of(&end_node))
798 .last()
799 .unwrap_or(DomRoot::from_ref(&start_node));
800 (
802 reference_node.GetParentNode().unwrap(),
803 reference_node.index() + 1,
804 )
805 };
806
807 if let Some(child) = first_partially_contained_child {
808 if let Some(start_data) = child.downcast::<CharacterData>() {
809 assert!(child == start_node);
810 let clone = start_node.CloneNode(cx, true)?;
812 let text = start_data.SubstringData(start_offset, start_node.len() - start_offset);
814 clone
815 .downcast::<CharacterData>()
816 .unwrap()
817 .SetData(cx, text.unwrap());
818 fragment.upcast::<Node>().AppendChild(cx, &clone)?;
820 start_data.ReplaceData(
822 cx,
823 start_offset,
824 start_node.len() - start_offset,
825 DOMString::new(),
826 )?;
827 } else {
828 let clone = child.CloneNode(cx, false)?;
830 fragment.upcast::<Node>().AppendChild(cx, &clone)?;
832 let subrange = Range::new(
834 cx,
835 &clone.owner_doc(),
836 &start_node,
837 start_offset,
838 &child,
839 child.len(),
840 );
841 let subfragment = subrange.ExtractContents(cx)?;
843 clone.AppendChild(cx, subfragment.upcast())?;
845 }
846 }
847
848 for child in contained_children {
850 fragment.upcast::<Node>().AppendChild(cx, &child)?;
851 }
852
853 if let Some(child) = last_partially_contained_child {
854 if let Some(end_data) = child.downcast::<CharacterData>() {
855 assert!(child == end_node);
856 let clone = end_node.CloneNode(cx, true)?;
858 let text = end_data.SubstringData(0, end_offset);
860 clone
861 .downcast::<CharacterData>()
862 .unwrap()
863 .SetData(cx, text.unwrap());
864 fragment.upcast::<Node>().AppendChild(cx, &clone)?;
866 end_data.ReplaceData(cx, 0, end_offset, DOMString::new())?;
868 } else {
869 let clone = child.CloneNode(cx, false)?;
871 fragment.upcast::<Node>().AppendChild(cx, &clone)?;
873 let subrange = Range::new(cx, &clone.owner_doc(), &child, 0, &end_node, end_offset);
875 let subfragment = subrange.ExtractContents(cx)?;
877 clone.AppendChild(cx, subfragment.upcast())?;
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(cx).Item(start_offset);
927 (child, DomRoot::from_ref(&*start_node))
928 },
929 };
930
931 Node::ensure_pre_insertion_validity(cx.no_gc(), 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(cx, start_offset)?;
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(cx, node, &parent, reference_node.as_deref())?;
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();
990 let end_node = self.end_container();
991 let start_offset = self.start_offset();
992 let end_offset = self.end_offset();
993
994 if start_node == end_node &&
996 let Some(text) = start_node.downcast::<CharacterData>()
997 {
998 if end_offset > start_offset {
999 self.report_change();
1000 }
1001
1002 return text.ReplaceData(
1006 cx,
1007 start_offset,
1008 end_offset - start_offset,
1009 DOMString::new(),
1010 );
1011 }
1012
1013 rooted_vec!(let mut contained_children);
1016 let ancestor = self.CommonAncestorContainer();
1017
1018 let mut iter = start_node.following_nodes(&ancestor, ShadowIncluding::No);
1019
1020 let mut next = iter.next();
1021 while let Some(child) = next {
1022 if self.contains(&child) {
1023 contained_children.push(Dom::from_ref(&*child));
1024 next = iter.next_skipping_children();
1025 } else {
1026 next = iter.next();
1027 }
1028 }
1029
1030 let (new_node, new_offset) = if start_node.is_inclusive_ancestor_of(&end_node) {
1034 (DomRoot::from_ref(&*start_node), start_offset)
1035 } else {
1036 fn compute_reference(start_node: &Node, end_node: &Node) -> (DomRoot<Node>, u32) {
1038 let mut reference_node = DomRoot::from_ref(start_node);
1040 while let Some(parent) = reference_node.GetParentNode() {
1043 if parent.is_inclusive_ancestor_of(end_node) {
1044 return (parent, reference_node.index() + 1);
1046 }
1047 reference_node = parent;
1048 }
1049 unreachable!()
1050 }
1051
1052 compute_reference(&start_node, &end_node)
1053 };
1054
1055 self.SetStart(&new_node, new_offset).unwrap();
1057 self.SetEnd(&new_node, new_offset).unwrap();
1058
1059 if let Some(text) = start_node.downcast::<CharacterData>() {
1063 text.ReplaceData(
1064 cx,
1065 start_offset,
1066 start_node.len() - start_offset,
1067 DOMString::new(),
1068 )
1069 .unwrap();
1070 }
1071
1072 for child in &*contained_children {
1074 child.remove_self(cx);
1075 }
1076
1077 if let Some(text) = end_node.downcast::<CharacterData>() {
1080 text.ReplaceData(cx, 0, end_offset, DOMString::new())
1081 .unwrap();
1082 }
1083
1084 Ok(())
1085 }
1086
1087 fn SurroundContents(&self, cx: &mut JSContext, new_parent: &Node) -> ErrorResult {
1089 let start = self.start_container();
1091 let end = self.end_container();
1092
1093 if start
1094 .inclusive_ancestors(ShadowIncluding::No)
1095 .any(|n| !n.is_inclusive_ancestor_of(&end) && !n.is::<Text>()) ||
1096 end.inclusive_ancestors(ShadowIncluding::No)
1097 .any(|n| !n.is_inclusive_ancestor_of(&start) && !n.is::<Text>())
1098 {
1099 return Err(Error::InvalidState(None));
1100 }
1101
1102 match new_parent.type_id() {
1104 NodeTypeId::Document(_) |
1105 NodeTypeId::DocumentType |
1106 NodeTypeId::DocumentFragment(_) => {
1107 return Err(Error::InvalidNodeType(None));
1108 },
1109 _ => (),
1110 }
1111
1112 let fragment = self.ExtractContents(cx)?;
1114
1115 Node::replace_all(cx, None, new_parent);
1117
1118 self.InsertNode(cx, new_parent)?;
1120
1121 new_parent.AppendChild(cx, fragment.upcast())?;
1123
1124 self.SelectNode(new_parent)
1126 }
1127
1128 fn Stringifier(&self, no_gc: &NoGC) -> DOMString {
1130 let start_node = self.start_container();
1131 let end_node = self.end_container();
1132
1133 let mut s = DOMString::new();
1135
1136 if let Some(text_node) = start_node.downcast::<Text>() {
1137 let char_data = text_node.upcast::<CharacterData>();
1138
1139 if start_node == end_node {
1143 return char_data
1144 .SubstringData(self.start_offset(), self.end_offset() - self.start_offset())
1145 .unwrap();
1146 }
1147
1148 s.push_str(
1151 &char_data
1152 .SubstringData(
1153 self.start_offset(),
1154 char_data.Length() - self.start_offset(),
1155 )
1156 .unwrap()
1157 .str(),
1158 );
1159 }
1160
1161 let ancestor = self.CommonAncestorContainer();
1164 let iter = start_node
1165 .following_nodes_unrooted(no_gc, &ancestor, ShadowIncluding::No)
1166 .filter_map(UnrootedDom::downcast::<Text>);
1167
1168 for child in iter {
1169 if self.contains(child.upcast()) {
1170 s.push_str(&child.upcast::<CharacterData>().Data().str());
1171 }
1172 }
1173
1174 if let Some(text_node) = end_node.downcast::<Text>() {
1177 let char_data = text_node.upcast::<CharacterData>();
1178 s.push_str(&char_data.SubstringData(0, self.end_offset()).unwrap().str());
1179 }
1180
1181 s
1183 }
1184
1185 fn CreateContextualFragment(
1187 &self,
1188 cx: &mut JSContext,
1189 fragment: TrustedHTMLOrString,
1190 ) -> Fallible<DomRoot<DocumentFragment>> {
1191 let node = self.start_container();
1196
1197 let fragment = TrustedHTML::get_trusted_type_compliant_string(
1201 cx,
1202 node.owner_window().upcast(),
1203 fragment,
1204 "Range createContextualFragment",
1205 )?;
1206
1207 let owner_doc = node.owner_doc();
1208
1209 let element = match node.type_id() {
1213 NodeTypeId::Element(_) => Some(DomRoot::downcast::<Element>(node).unwrap()),
1214 NodeTypeId::CharacterData(CharacterDataTypeId::Comment) |
1215 NodeTypeId::CharacterData(CharacterDataTypeId::Text(_)) => node.GetParentElement(),
1216 _ => None,
1217 };
1218
1219 let element = Element::fragment_parsing_context(cx, &owner_doc, element.as_deref());
1221
1222 let fragment_node = element.parse_fragment(fragment, cx)?;
1224
1225 for node in fragment_node
1227 .upcast::<Node>()
1228 .traverse_preorder(ShadowIncluding::No)
1229 {
1230 if let Some(script) = node.downcast::<HTMLScriptElement>() {
1231 script.set_already_started(false);
1233 script.set_parser_inserted(false);
1235 }
1236 }
1237
1238 Ok(fragment_node)
1240 }
1241
1242 fn GetClientRects(&self, cx: &mut JSContext) -> DomRoot<DOMRectList> {
1244 let start = self.start_container();
1245 let window = start.owner_window();
1246
1247 let client_rects: Vec<_> = self.client_rects(cx.no_gc()).collect();
1248 let client_rects = client_rects
1249 .iter()
1250 .map(|rect| {
1251 DOMRect::new(
1252 cx,
1253 window.upcast(),
1254 rect.origin.x.to_f64_px(),
1255 rect.origin.y.to_f64_px(),
1256 rect.size.width.to_f64_px(),
1257 rect.size.height.to_f64_px(),
1258 )
1259 })
1260 .collect();
1261
1262 DOMRectList::new(cx, &window, client_rects)
1263 }
1264
1265 fn GetBoundingClientRect(&self, cx: &mut JSContext) -> DomRoot<DOMRect> {
1267 let window = self.start_container().owner_window();
1268
1269 let list = self.client_rects(cx.no_gc());
1271
1272 let bounding_rect = list.fold(euclid::Rect::zero(), |acc, rect| acc.union(&rect));
1277
1278 DOMRect::new(
1279 cx,
1280 window.upcast(),
1281 bounding_rect.origin.x.to_f64_px(),
1282 bounding_rect.origin.y.to_f64_px(),
1283 bounding_rect.size.width.to_f64_px(),
1284 bounding_rect.size.height.to_f64_px(),
1285 )
1286 }
1287}
1288
1289#[derive(MallocSizeOf)]
1290pub(crate) struct WeakRangeVec {
1291 cell: RefCell<WeakRefVec<Range>>,
1292}
1293
1294impl Default for WeakRangeVec {
1295 fn default() -> Self {
1296 WeakRangeVec {
1297 cell: RefCell::new(WeakRefVec::new()),
1298 }
1299 }
1300}
1301
1302impl WeakRangeVec {
1303 pub(crate) fn is_empty(&self) -> bool {
1305 self.cell.borrow().is_empty()
1306 }
1307
1308 pub(crate) fn increase_above(&self, node: &Node, offset: u32, delta: u32) {
1311 self.map_offset_above(node, offset, |offset| offset + delta);
1312 }
1313
1314 pub(crate) fn decrease_above(&self, node: &Node, offset: u32, delta: u32) {
1317 self.map_offset_above(node, offset, |offset| offset - delta);
1318 }
1319
1320 pub(crate) fn drain_to_parent(&self, parent: &Node, offset: u32, child: &Node) {
1324 if self.is_empty() {
1325 return;
1326 }
1327
1328 let ranges = &mut *self.cell.borrow_mut();
1329
1330 ranges.update(|entry| {
1331 let range = entry.root().unwrap();
1332 if range.start().node() == parent || range.end().node() == parent {
1333 entry.remove();
1334 }
1335 if range.start().node() == child {
1336 range.report_change();
1337 range.start().set(parent, offset);
1338 }
1339 if range.end().node() == child {
1340 range.report_change();
1341 range.end().set(parent, offset);
1342 }
1343 });
1344
1345 parent
1346 .ensure_weak_ranges()
1347 .cell
1348 .borrow_mut()
1349 .extend(ranges.drain(..));
1350 }
1351
1352 pub(crate) fn drain_to_preceding_text_sibling(&self, node: &Node, sibling: &Node, length: u32) {
1355 if self.is_empty() {
1356 return;
1357 }
1358
1359 let ranges = &mut *self.cell.borrow_mut();
1360
1361 ranges.update(|entry| {
1362 let range = entry.root().unwrap();
1363 if range.start().node() == sibling || range.end().node() == sibling {
1364 entry.remove();
1365 }
1366 if range.start().node() == node {
1367 range.report_change();
1368 range.start().set(sibling, range.start_offset() + length);
1369 }
1370 if range.end().node() == node {
1371 range.report_change();
1372 range.end().set(sibling, range.end_offset() + length);
1373 }
1374 });
1375
1376 sibling
1377 .ensure_weak_ranges()
1378 .cell
1379 .borrow_mut()
1380 .extend(ranges.drain(..));
1381 }
1382
1383 pub(crate) fn move_to_text_child_at(
1386 &self,
1387 node: &Node,
1388 offset: u32,
1389 child: &Node,
1390 new_offset: u32,
1391 ) {
1392 self.cell.borrow_mut().update(|entry| {
1393 let range = entry.root().unwrap();
1394
1395 let node_is_start = range.start().node() == node;
1396 let node_is_end = range.end().node() == node;
1397
1398 let move_start = node_is_start && range.start_offset() == offset;
1399 let move_end = node_is_end && range.end_offset() == offset;
1400
1401 let remove_from_node =
1402 move_start && (move_end || !node_is_end) || move_end && !node_is_start;
1403
1404 let already_in_child = range.start().node() == child || range.end().node() == child;
1405 let push_to_child = !already_in_child && (move_start || move_end);
1406
1407 if remove_from_node {
1408 let weak_range = entry.remove();
1409 if push_to_child {
1410 child
1411 .ensure_weak_ranges()
1412 .cell
1413 .borrow_mut()
1414 .push(weak_range);
1415 }
1416 } else if push_to_child {
1417 child
1418 .ensure_weak_ranges()
1419 .cell
1420 .borrow_mut()
1421 .push(WeakRef::new(&range));
1422 }
1423
1424 if move_start {
1425 range.report_change();
1426 range.start().set(child, new_offset);
1427 }
1428 if move_end {
1429 range.report_change();
1430 range.end().set(child, new_offset);
1431 }
1432 });
1433 }
1434
1435 pub(crate) fn replace_code_units(
1438 &self,
1439 node: &Node,
1440 offset: u32,
1441 removed_code_units: u32,
1442 added_code_units: u32,
1443 ) {
1444 self.map_offset_above(node, offset, |range_offset| {
1445 if range_offset <= offset + removed_code_units {
1446 offset
1447 } else {
1448 range_offset + added_code_units - removed_code_units
1449 }
1450 });
1451 }
1452
1453 pub(crate) fn move_to_following_text_sibling_above(
1456 &self,
1457 node: &Node,
1458 offset: u32,
1459 sibling: &Node,
1460 ) {
1461 self.cell.borrow_mut().update(|entry| {
1462 let range = entry.root().unwrap();
1463 let start_offset = range.start_offset();
1464 let end_offset = range.end_offset();
1465
1466 let node_is_start = range.start().node() == node;
1467 let node_is_end = range.end().node() == node;
1468
1469 let move_start = node_is_start && start_offset > offset;
1470 let move_end = node_is_end && end_offset > offset;
1471
1472 let remove_from_node =
1473 move_start && (move_end || !node_is_end) || move_end && !node_is_start;
1474
1475 let already_in_sibling =
1476 range.start().node() == sibling || range.end().node() == sibling;
1477 let push_to_sibling = !already_in_sibling && (move_start || move_end);
1478
1479 if remove_from_node {
1480 let weak_range = entry.remove();
1481 if push_to_sibling {
1482 sibling
1483 .ensure_weak_ranges()
1484 .cell
1485 .borrow_mut()
1486 .push(weak_range);
1487 }
1488 } else if push_to_sibling {
1489 sibling
1490 .ensure_weak_ranges()
1491 .cell
1492 .borrow_mut()
1493 .push(WeakRef::new(&range));
1494 }
1495
1496 if move_start {
1497 range.report_change();
1498 range.start().set(sibling, start_offset - offset);
1499 }
1500 if move_end {
1501 range.report_change();
1502 range.end().set(sibling, end_offset - offset);
1503 }
1504 });
1505 }
1506
1507 pub(crate) fn increment_at(&self, node: &Node, offset: u32) {
1510 self.cell.borrow_mut().update(|entry| {
1511 let range = entry.root().unwrap();
1512 if range.start().node() == node && offset == range.start_offset() {
1513 range.report_change();
1514 range.start().set_offset(offset + 1);
1515 }
1516 if range.end().node() == node && offset == range.end_offset() {
1517 range.report_change();
1518 range.end().set_offset(offset + 1);
1519 }
1520 });
1521 }
1522
1523 fn map_offset_above<F: FnMut(u32) -> u32>(&self, node: &Node, offset: u32, mut f: F) {
1524 self.cell.borrow_mut().update(|entry| {
1525 let range = entry.root().unwrap();
1526 let start_offset = range.start_offset();
1527 if range.start().node() == node && start_offset > offset {
1528 range.report_change();
1529 range.start().set_offset(f(start_offset));
1530 }
1531 let end_offset = range.end_offset();
1532 if range.end().node() == node && end_offset > offset {
1533 range.report_change();
1534 range.end().set_offset(f(end_offset));
1535 }
1536 });
1537 }
1538
1539 pub(crate) fn push(&self, ref_: WeakRef<Range>) {
1540 self.cell.borrow_mut().push(ref_);
1541 }
1542
1543 fn remove(&self, range: &Range) -> WeakRef<Range> {
1544 let mut ranges = self.cell.borrow_mut();
1545 let position = ranges.iter().position(|ref_| ref_ == range).unwrap();
1546 ranges.swap_remove(position)
1547 }
1548}
1549
1550#[expect(unsafe_code)]
1551unsafe impl JSTraceable for WeakRangeVec {
1552 unsafe fn trace(&self, _: *mut JSTracer) {
1553 self.cell.borrow_mut().retain_alive()
1554 }
1555}