1use std::cell::RefCell;
6use std::cmp::{Ordering, PartialOrd};
7use std::iter;
8
9use dom_struct::dom_struct;
10use js::jsapi::JSTracer;
11use js::rust::HandleObject;
12
13use crate::dom::abstractrange::{AbstractRange, BoundaryPoint, bp_position};
14use crate::dom::bindings::cell::DomRefCell;
15use crate::dom::bindings::codegen::Bindings::AbstractRangeBinding::AbstractRangeMethods;
16use crate::dom::bindings::codegen::Bindings::CharacterDataBinding::CharacterDataMethods;
17use crate::dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
18use crate::dom::bindings::codegen::Bindings::NodeListBinding::NodeListMethods;
19use crate::dom::bindings::codegen::Bindings::RangeBinding::{RangeConstants, RangeMethods};
20use crate::dom::bindings::codegen::Bindings::TextBinding::TextMethods;
21use crate::dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
22use crate::dom::bindings::codegen::UnionTypes::TrustedHTMLOrString;
23use crate::dom::bindings::error::{Error, ErrorResult, Fallible};
24use crate::dom::bindings::inheritance::{Castable, CharacterDataTypeId, NodeTypeId};
25use crate::dom::bindings::reflector::reflect_dom_object_with_proto;
26use crate::dom::bindings::root::{Dom, DomRoot};
27use crate::dom::bindings::str::DOMString;
28use crate::dom::bindings::trace::JSTraceable;
29use crate::dom::bindings::weakref::{WeakRef, WeakRefVec};
30use crate::dom::characterdata::CharacterData;
31use crate::dom::document::Document;
32use crate::dom::documentfragment::DocumentFragment;
33use crate::dom::domrect::DOMRect;
34use crate::dom::domrectlist::DOMRectList;
35use crate::dom::element::Element;
36use crate::dom::html::htmlscriptelement::HTMLScriptElement;
37use crate::dom::node::{Node, NodeTraits, ShadowIncluding, UnbindContext};
38use crate::dom::selection::Selection;
39use crate::dom::text::Text;
40use crate::dom::trustedhtml::TrustedHTML;
41use crate::dom::window::Window;
42use crate::script_runtime::CanGc;
43
44#[dom_struct]
45pub(crate) struct Range {
46 abstract_range: AbstractRange,
47 associated_selections: DomRefCell<Vec<Dom<Selection>>>,
57}
58
59struct ContainedChildren {
60 first_partially_contained_child: Option<DomRoot<Node>>,
61 last_partially_contained_child: Option<DomRoot<Node>>,
62 contained_children: Vec<DomRoot<Node>>,
63}
64
65impl Range {
66 fn new_inherited(
67 start_container: &Node,
68 start_offset: u32,
69 end_container: &Node,
70 end_offset: u32,
71 ) -> Range {
72 debug_assert!(start_offset <= start_container.len());
73 debug_assert!(end_offset <= end_container.len());
74 Range {
75 abstract_range: AbstractRange::new_inherited(
76 start_container,
77 start_offset,
78 end_container,
79 end_offset,
80 ),
81 associated_selections: DomRefCell::new(vec![]),
82 }
83 }
84
85 pub(crate) fn new_with_doc(
86 document: &Document,
87 proto: Option<HandleObject>,
88 can_gc: CanGc,
89 ) -> DomRoot<Range> {
90 let root = document.upcast();
91 Range::new_with_proto(document, proto, root, 0, root, 0, can_gc)
92 }
93
94 pub(crate) fn new(
95 document: &Document,
96 start_container: &Node,
97 start_offset: u32,
98 end_container: &Node,
99 end_offset: u32,
100 can_gc: CanGc,
101 ) -> DomRoot<Range> {
102 Self::new_with_proto(
103 document,
104 None,
105 start_container,
106 start_offset,
107 end_container,
108 end_offset,
109 can_gc,
110 )
111 }
112
113 fn new_with_proto(
114 document: &Document,
115 proto: Option<HandleObject>,
116 start_container: &Node,
117 start_offset: u32,
118 end_container: &Node,
119 end_offset: u32,
120 can_gc: CanGc,
121 ) -> DomRoot<Range> {
122 let range = reflect_dom_object_with_proto(
123 Box::new(Range::new_inherited(
124 start_container,
125 start_offset,
126 end_container,
127 end_offset,
128 )),
129 document.window(),
130 proto,
131 can_gc,
132 );
133 start_container.ranges().push(WeakRef::new(&range));
134 if start_container != end_container {
135 end_container.ranges().push(WeakRef::new(&range));
136 }
137 range
138 }
139
140 fn contains(&self, node: &Node) -> bool {
142 matches!(
143 (
144 bp_position(node, 0, &self.start_container(), self.start_offset()),
145 bp_position(node, node.len(), &self.end_container(), self.end_offset()),
146 ),
147 (Some(Ordering::Greater), Some(Ordering::Less))
148 )
149 }
150
151 fn partially_contains(&self, node: &Node) -> bool {
153 self.start_container()
154 .inclusive_ancestors(ShadowIncluding::No)
155 .any(|n| &*n == node) !=
156 self.end_container()
157 .inclusive_ancestors(ShadowIncluding::No)
158 .any(|n| &*n == node)
159 }
160
161 fn contained_children(&self) -> Fallible<ContainedChildren> {
163 let start_node = self.start_container();
164 let end_node = self.end_container();
165 let common_ancestor = self.CommonAncestorContainer();
167
168 let first_partially_contained_child = if start_node.is_inclusive_ancestor_of(&end_node) {
169 None
171 } else {
172 common_ancestor
174 .children()
175 .find(|node| Range::partially_contains(self, node))
176 };
177
178 let last_partially_contained_child = if end_node.is_inclusive_ancestor_of(&start_node) {
179 None
181 } else {
182 common_ancestor
184 .rev_children()
185 .find(|node| Range::partially_contains(self, node))
186 };
187
188 let contained_children: Vec<DomRoot<Node>> = common_ancestor
190 .children()
191 .filter(|n| self.contains(n))
192 .collect();
193
194 if contained_children.iter().any(|n| n.is_doctype()) {
196 return Err(Error::HierarchyRequest);
197 }
198
199 Ok(ContainedChildren {
200 first_partially_contained_child,
201 last_partially_contained_child,
202 contained_children,
203 })
204 }
205
206 fn set_start(&self, node: &Node, offset: u32) {
208 if self.start().node() != node || self.start_offset() != offset {
209 self.report_change();
210 }
211 if self.start().node() != node {
212 if self.start().node() == self.end().node() {
213 node.ranges().push(WeakRef::new(self));
214 } else if self.end().node() == node {
215 self.start_container().ranges().remove(self);
216 } else {
217 node.ranges()
218 .push(self.start_container().ranges().remove(self));
219 }
220 }
221 self.start().set(node, offset);
222 }
223
224 fn set_end(&self, node: &Node, offset: u32) {
226 if self.end().node() != node || self.end_offset() != offset {
227 self.report_change();
228 }
229 if self.end().node() != node {
230 if self.end().node() == self.start().node() {
231 node.ranges().push(WeakRef::new(self));
232 } else if self.start().node() == node {
233 self.end_container().ranges().remove(self);
234 } else {
235 node.ranges()
236 .push(self.end_container().ranges().remove(self));
237 }
238 }
239 self.end().set(node, offset);
240 }
241
242 fn compare_point(&self, node: &Node, offset: u32) -> Fallible<Ordering> {
244 let start_node = self.start_container();
245 let start_node_root = start_node
246 .inclusive_ancestors(ShadowIncluding::No)
247 .last()
248 .unwrap();
249 let node_root = node
250 .inclusive_ancestors(ShadowIncluding::No)
251 .last()
252 .unwrap();
253 if start_node_root != node_root {
254 return Err(Error::WrongDocument);
256 }
257 if node.is_doctype() {
258 return Err(Error::InvalidNodeType);
260 }
261 if offset > node.len() {
262 return Err(Error::IndexSize);
264 }
265 if let Ordering::Less = bp_position(node, offset, &start_node, self.start_offset()).unwrap()
266 {
267 return Ok(Ordering::Less);
269 }
270 if let Ordering::Greater =
271 bp_position(node, offset, &self.end_container(), self.end_offset()).unwrap()
272 {
273 return Ok(Ordering::Greater);
275 }
276 Ok(Ordering::Equal)
278 }
279
280 pub(crate) fn associate_selection(&self, selection: &Selection) {
281 let mut selections = self.associated_selections.borrow_mut();
282 if !selections.iter().any(|s| &**s == selection) {
283 selections.push(Dom::from_ref(selection));
284 }
285 }
286
287 pub(crate) fn disassociate_selection(&self, selection: &Selection) {
288 self.associated_selections
289 .borrow_mut()
290 .retain(|s| &**s != selection);
291 }
292
293 fn report_change(&self) {
294 self.associated_selections
295 .borrow()
296 .iter()
297 .for_each(|s| s.queue_selectionchange_task());
298 }
299
300 fn abstract_range(&self) -> &AbstractRange {
301 &self.abstract_range
302 }
303
304 fn start(&self) -> &BoundaryPoint {
305 self.abstract_range().start()
306 }
307
308 fn end(&self) -> &BoundaryPoint {
309 self.abstract_range().end()
310 }
311
312 pub(crate) fn start_container(&self) -> DomRoot<Node> {
313 self.abstract_range().StartContainer()
314 }
315
316 pub(crate) fn start_offset(&self) -> u32 {
317 self.abstract_range().StartOffset()
318 }
319
320 pub(crate) fn end_container(&self) -> DomRoot<Node> {
321 self.abstract_range().EndContainer()
322 }
323
324 pub(crate) fn end_offset(&self) -> u32 {
325 self.abstract_range().EndOffset()
326 }
327
328 pub(crate) fn collapsed(&self) -> bool {
329 self.abstract_range().Collapsed()
330 }
331
332 fn client_rects(
333 &self,
334 ) -> impl Iterator<Item = euclid::Rect<app_units::Au, euclid::UnknownUnit>> {
335 let start = self.start_container();
338 let end = self.end_container();
339 let document = start.owner_doc();
340 let end_clone = end.clone();
341 start
342 .following_nodes(document.upcast::<Node>())
343 .take_while(move |node| node != &end)
344 .chain(iter::once(end_clone))
345 .flat_map(move |node| node.border_boxes())
346 }
347
348 #[allow(clippy::neg_cmp_op_on_partial_ord)]
350 fn set_the_start_or_end(
351 &self,
352 node: &Node,
353 offset: u32,
354 start_or_end: StartOrEnd,
355 ) -> ErrorResult {
356 if node.is_doctype() {
358 return Err(Error::InvalidNodeType);
359 }
360
361 if offset > node.len() {
363 return Err(Error::IndexSize);
364 }
365
366 match start_or_end {
370 StartOrEnd::Start => {
372 self.set_start(node, offset);
376 if !(self.start() <= self.end()) {
377 self.set_end(node, offset);
378 }
379 },
380 StartOrEnd::End => {
382 self.set_end(node, offset);
386 if !(self.end() >= self.start()) {
387 self.set_start(node, offset);
388 }
389 },
390 }
391
392 Ok(())
393 }
394}
395
396enum StartOrEnd {
397 Start,
398 End,
399}
400
401impl RangeMethods<crate::DomTypeHolder> for Range {
402 fn Constructor(
404 window: &Window,
405 proto: Option<HandleObject>,
406 can_gc: CanGc,
407 ) -> Fallible<DomRoot<Range>> {
408 let document = window.Document();
409 Ok(Range::new_with_doc(&document, proto, can_gc))
410 }
411
412 fn CommonAncestorContainer(&self) -> DomRoot<Node> {
414 self.end_container()
415 .common_ancestor(&self.start_container(), ShadowIncluding::No)
416 .expect("Couldn't find common ancestor container")
417 }
418
419 fn SetStart(&self, node: &Node, offset: u32) -> ErrorResult {
421 self.set_the_start_or_end(node, offset, StartOrEnd::Start)
422 }
423
424 fn SetEnd(&self, node: &Node, offset: u32) -> ErrorResult {
426 self.set_the_start_or_end(node, offset, StartOrEnd::End)
427 }
428
429 fn SetStartBefore(&self, node: &Node) -> ErrorResult {
431 let parent = node.GetParentNode().ok_or(Error::InvalidNodeType)?;
432 self.SetStart(&parent, node.index())
433 }
434
435 fn SetStartAfter(&self, node: &Node) -> ErrorResult {
437 let parent = node.GetParentNode().ok_or(Error::InvalidNodeType)?;
438 self.SetStart(&parent, node.index() + 1)
439 }
440
441 fn SetEndBefore(&self, node: &Node) -> ErrorResult {
443 let parent = node.GetParentNode().ok_or(Error::InvalidNodeType)?;
444 self.SetEnd(&parent, node.index())
445 }
446
447 fn SetEndAfter(&self, node: &Node) -> ErrorResult {
449 let parent = node.GetParentNode().ok_or(Error::InvalidNodeType)?;
450 self.SetEnd(&parent, node.index() + 1)
451 }
452
453 fn Collapse(&self, to_start: bool) {
455 if to_start {
456 self.set_end(&self.start_container(), self.start_offset());
457 } else {
458 self.set_start(&self.end_container(), self.end_offset());
459 }
460 }
461
462 fn SelectNode(&self, node: &Node) -> ErrorResult {
464 let parent = node.GetParentNode().ok_or(Error::InvalidNodeType)?;
466 let index = node.index();
468 self.set_start(&parent, index);
470 self.set_end(&parent, index + 1);
472 Ok(())
473 }
474
475 fn SelectNodeContents(&self, node: &Node) -> ErrorResult {
477 if node.is_doctype() {
478 return Err(Error::InvalidNodeType);
480 }
481 let length = node.len();
483 self.set_start(node, 0);
485 self.set_end(node, length);
487 Ok(())
488 }
489
490 fn CompareBoundaryPoints(&self, how: u16, other: &Range) -> Fallible<i16> {
492 if how > RangeConstants::END_TO_START {
493 return Err(Error::NotSupported);
495 }
496 let this_root = self
497 .start_container()
498 .inclusive_ancestors(ShadowIncluding::No)
499 .last()
500 .unwrap();
501 let other_root = other
502 .start_container()
503 .inclusive_ancestors(ShadowIncluding::No)
504 .last()
505 .unwrap();
506 if this_root != other_root {
507 return Err(Error::WrongDocument);
509 }
510 let (this_point, other_point) = match how {
512 RangeConstants::START_TO_START => (self.start(), other.start()),
513 RangeConstants::START_TO_END => (self.end(), other.start()),
514 RangeConstants::END_TO_END => (self.end(), other.end()),
515 RangeConstants::END_TO_START => (self.start(), other.end()),
516 _ => unreachable!(),
517 };
518 match this_point.partial_cmp(other_point).unwrap() {
520 Ordering::Less => Ok(-1),
521 Ordering::Equal => Ok(0),
522 Ordering::Greater => Ok(1),
523 }
524 }
525
526 fn CloneRange(&self, can_gc: CanGc) -> DomRoot<Range> {
528 let start_node = self.start_container();
529 let owner_doc = start_node.owner_doc();
530 Range::new(
531 &owner_doc,
532 &start_node,
533 self.start_offset(),
534 &self.end_container(),
535 self.end_offset(),
536 can_gc,
537 )
538 }
539
540 fn IsPointInRange(&self, node: &Node, offset: u32) -> Fallible<bool> {
542 match self.compare_point(node, offset) {
543 Ok(Ordering::Less) => Ok(false),
544 Ok(Ordering::Equal) => Ok(true),
545 Ok(Ordering::Greater) => Ok(false),
546 Err(Error::WrongDocument) => {
547 Ok(false)
549 },
550 Err(error) => Err(error),
551 }
552 }
553
554 fn ComparePoint(&self, node: &Node, offset: u32) -> Fallible<i16> {
556 self.compare_point(node, offset).map(|order| match order {
557 Ordering::Less => -1,
558 Ordering::Equal => 0,
559 Ordering::Greater => 1,
560 })
561 }
562
563 fn IntersectsNode(&self, node: &Node) -> bool {
565 let start_node = self.start_container();
566 let start_node_root = self
567 .start_container()
568 .inclusive_ancestors(ShadowIncluding::No)
569 .last()
570 .unwrap();
571 let node_root = node
572 .inclusive_ancestors(ShadowIncluding::No)
573 .last()
574 .unwrap();
575 if start_node_root != node_root {
576 return false;
578 }
579 let parent = match node.GetParentNode() {
580 Some(parent) => parent,
581 None => {
582 return true;
584 },
585 };
586 let offset = node.index();
588 Ordering::Greater ==
590 bp_position(&parent, offset + 1, &start_node, self.start_offset()).unwrap() &&
591 Ordering::Less ==
592 bp_position(&parent, offset, &self.end_container(), self.end_offset())
593 .unwrap()
594 }
595
596 fn CloneContents(&self, can_gc: CanGc) -> Fallible<DomRoot<DocumentFragment>> {
599 let start_node = self.start_container();
601 let start_offset = self.start_offset();
602 let end_node = self.end_container();
603 let end_offset = self.end_offset();
604
605 let fragment = DocumentFragment::new(&start_node.owner_doc(), can_gc);
607
608 if self.start() == self.end() {
610 return Ok(fragment);
611 }
612
613 if end_node == start_node {
614 if let Some(cdata) = start_node.downcast::<CharacterData>() {
615 let data = cdata
617 .SubstringData(start_offset, end_offset - start_offset)
618 .unwrap();
619 let clone = cdata.clone_with_data(data, &start_node.owner_doc(), can_gc);
620 fragment.upcast::<Node>().AppendChild(&clone, can_gc)?;
622 return Ok(fragment);
624 }
625 }
626
627 let ContainedChildren {
629 first_partially_contained_child,
630 last_partially_contained_child,
631 contained_children,
632 } = self.contained_children()?;
633
634 if let Some(child) = first_partially_contained_child {
635 if let Some(cdata) = child.downcast::<CharacterData>() {
637 assert!(child == start_node);
638 let data = cdata
640 .SubstringData(start_offset, start_node.len() - start_offset)
641 .unwrap();
642 let clone = cdata.clone_with_data(data, &start_node.owner_doc(), can_gc);
643 fragment.upcast::<Node>().AppendChild(&clone, can_gc)?;
645 } else {
646 let clone = child.CloneNode(false, can_gc)?;
648 fragment.upcast::<Node>().AppendChild(&clone, can_gc)?;
650 let subrange = Range::new(
652 &clone.owner_doc(),
653 &start_node,
654 start_offset,
655 &child,
656 child.len(),
657 can_gc,
658 );
659 let subfragment = subrange.CloneContents(can_gc)?;
661 clone.AppendChild(subfragment.upcast(), can_gc)?;
663 }
664 }
665
666 for child in contained_children {
668 let clone = child.CloneNode(true, can_gc)?;
670 fragment.upcast::<Node>().AppendChild(&clone, can_gc)?;
672 }
673
674 if let Some(child) = last_partially_contained_child {
675 if let Some(cdata) = child.downcast::<CharacterData>() {
677 assert!(child == end_node);
678 let data = cdata.SubstringData(0, end_offset).unwrap();
680 let clone = cdata.clone_with_data(data, &start_node.owner_doc(), can_gc);
681 fragment.upcast::<Node>().AppendChild(&clone, can_gc)?;
683 } else {
684 let clone = child.CloneNode(false, can_gc)?;
686 fragment.upcast::<Node>().AppendChild(&clone, can_gc)?;
688 let subrange =
690 Range::new(&clone.owner_doc(), &child, 0, &end_node, end_offset, can_gc);
691 let subfragment = subrange.CloneContents(can_gc)?;
693 clone.AppendChild(subfragment.upcast(), can_gc)?;
695 }
696 }
697
698 Ok(fragment)
700 }
701
702 fn ExtractContents(&self, can_gc: CanGc) -> Fallible<DomRoot<DocumentFragment>> {
705 let start_node = self.start_container();
707 let start_offset = self.start_offset();
708 let end_node = self.end_container();
709 let end_offset = self.end_offset();
710
711 let fragment = DocumentFragment::new(&start_node.owner_doc(), can_gc);
713
714 if self.collapsed() {
716 return Ok(fragment);
717 }
718
719 if end_node == start_node {
720 if let Some(end_data) = end_node.downcast::<CharacterData>() {
721 let clone = end_node.CloneNode(true, can_gc)?;
723 let text = end_data.SubstringData(start_offset, end_offset - start_offset);
725 clone
726 .downcast::<CharacterData>()
727 .unwrap()
728 .SetData(text.unwrap());
729 fragment.upcast::<Node>().AppendChild(&clone, can_gc)?;
731 end_data.ReplaceData(start_offset, end_offset - start_offset, DOMString::new())?;
733 return Ok(fragment);
735 }
736 }
737
738 let ContainedChildren {
740 first_partially_contained_child,
741 last_partially_contained_child,
742 contained_children,
743 } = self.contained_children()?;
744
745 let (new_node, new_offset) = if start_node.is_inclusive_ancestor_of(&end_node) {
746 (DomRoot::from_ref(&*start_node), start_offset)
748 } else {
749 let reference_node = start_node
751 .ancestors()
752 .take_while(|n| !n.is_inclusive_ancestor_of(&end_node))
753 .last()
754 .unwrap_or(DomRoot::from_ref(&start_node));
755 (
757 reference_node.GetParentNode().unwrap(),
758 reference_node.index() + 1,
759 )
760 };
761
762 if let Some(child) = first_partially_contained_child {
763 if let Some(start_data) = child.downcast::<CharacterData>() {
764 assert!(child == start_node);
765 let clone = start_node.CloneNode(true, can_gc)?;
767 let text = start_data.SubstringData(start_offset, start_node.len() - start_offset);
769 clone
770 .downcast::<CharacterData>()
771 .unwrap()
772 .SetData(text.unwrap());
773 fragment.upcast::<Node>().AppendChild(&clone, can_gc)?;
775 start_data.ReplaceData(
777 start_offset,
778 start_node.len() - start_offset,
779 DOMString::new(),
780 )?;
781 } else {
782 let clone = child.CloneNode(false, can_gc)?;
784 fragment.upcast::<Node>().AppendChild(&clone, can_gc)?;
786 let subrange = Range::new(
788 &clone.owner_doc(),
789 &start_node,
790 start_offset,
791 &child,
792 child.len(),
793 can_gc,
794 );
795 let subfragment = subrange.ExtractContents(can_gc)?;
797 clone.AppendChild(subfragment.upcast(), can_gc)?;
799 }
800 }
801
802 for child in contained_children {
804 fragment.upcast::<Node>().AppendChild(&child, can_gc)?;
805 }
806
807 if let Some(child) = last_partially_contained_child {
808 if let Some(end_data) = child.downcast::<CharacterData>() {
809 assert!(child == end_node);
810 let clone = end_node.CloneNode(true, can_gc)?;
812 let text = end_data.SubstringData(0, end_offset);
814 clone
815 .downcast::<CharacterData>()
816 .unwrap()
817 .SetData(text.unwrap());
818 fragment.upcast::<Node>().AppendChild(&clone, can_gc)?;
820 end_data.ReplaceData(0, end_offset, DOMString::new())?;
822 } else {
823 let clone = child.CloneNode(false, can_gc)?;
825 fragment.upcast::<Node>().AppendChild(&clone, can_gc)?;
827 let subrange =
829 Range::new(&clone.owner_doc(), &child, 0, &end_node, end_offset, can_gc);
830 let subfragment = subrange.ExtractContents(can_gc)?;
832 clone.AppendChild(subfragment.upcast(), can_gc)?;
834 }
835 }
836
837 self.SetStart(&new_node, new_offset)?;
839 self.SetEnd(&new_node, new_offset)?;
840
841 Ok(fragment)
843 }
844
845 fn Detach(&self) {
847 }
849
850 fn InsertNode(&self, node: &Node, can_gc: CanGc) -> ErrorResult {
853 let start_node = self.start_container();
854 let start_offset = self.start_offset();
855
856 if &*start_node == node {
858 return Err(Error::HierarchyRequest);
859 }
860 match start_node.type_id() {
861 NodeTypeId::CharacterData(CharacterDataTypeId::Text(_)) => (),
863 NodeTypeId::CharacterData(_) => return Err(Error::HierarchyRequest),
864 _ => (),
865 }
866
867 let (reference_node, parent) = match start_node.type_id() {
869 NodeTypeId::CharacterData(CharacterDataTypeId::Text(_)) => {
870 let parent = match start_node.GetParentNode() {
872 Some(parent) => parent,
873 None => return Err(Error::HierarchyRequest),
875 };
876 (Some(DomRoot::from_ref(&*start_node)), parent)
878 },
879 _ => {
880 let child = start_node.ChildNodes(can_gc).Item(start_offset);
882 (child, DomRoot::from_ref(&*start_node))
883 },
884 };
885
886 Node::ensure_pre_insertion_validity(node, &parent, reference_node.as_deref())?;
888
889 let split_text;
891 let reference_node = match start_node.downcast::<Text>() {
892 Some(text) => {
893 split_text = text.SplitText(start_offset, can_gc)?;
894 let new_reference = DomRoot::upcast::<Node>(split_text);
895 assert!(new_reference.GetParentNode().as_deref() == Some(&parent));
896 Some(new_reference)
897 },
898 _ => reference_node,
899 };
900
901 let reference_node = if Some(node) == reference_node.as_deref() {
903 node.GetNextSibling()
904 } else {
905 reference_node
906 };
907
908 node.remove_self(can_gc);
910
911 let new_offset = reference_node
913 .as_ref()
914 .map_or(parent.len(), |node| node.index());
915
916 let new_offset = new_offset +
918 if let NodeTypeId::DocumentFragment(_) = node.type_id() {
919 node.len()
920 } else {
921 1
922 };
923
924 Node::pre_insert(node, &parent, reference_node.as_deref(), can_gc)?;
926
927 if self.collapsed() {
929 self.set_end(&parent, new_offset);
930 }
931
932 Ok(())
933 }
934
935 fn DeleteContents(&self) -> ErrorResult {
937 if self.collapsed() {
939 return Ok(());
940 }
941
942 let start_node = self.start_container();
944 let end_node = self.end_container();
945 let start_offset = self.start_offset();
946 let end_offset = self.end_offset();
947
948 if start_node == end_node {
950 if let Some(text) = start_node.downcast::<CharacterData>() {
951 if end_offset > start_offset {
952 self.report_change();
953 }
954 return text.ReplaceData(start_offset, end_offset - start_offset, DOMString::new());
955 }
956 }
957
958 rooted_vec!(let mut contained_children);
960 let ancestor = self.CommonAncestorContainer();
961
962 let mut iter = start_node.following_nodes(&ancestor);
963
964 let mut next = iter.next();
965 while let Some(child) = next {
966 if self.contains(&child) {
967 contained_children.push(Dom::from_ref(&*child));
968 next = iter.next_skipping_children();
969 } else {
970 next = iter.next();
971 }
972 }
973
974 let (new_node, new_offset) = if start_node.is_inclusive_ancestor_of(&end_node) {
975 (DomRoot::from_ref(&*start_node), start_offset)
977 } else {
978 fn compute_reference(start_node: &Node, end_node: &Node) -> (DomRoot<Node>, u32) {
980 let mut reference_node = DomRoot::from_ref(start_node);
981 while let Some(parent) = reference_node.GetParentNode() {
982 if parent.is_inclusive_ancestor_of(end_node) {
983 return (parent, reference_node.index() + 1);
984 }
985 reference_node = parent;
986 }
987 unreachable!()
988 }
989
990 compute_reference(&start_node, &end_node)
991 };
992
993 if let Some(text) = start_node.downcast::<CharacterData>() {
995 text.ReplaceData(
996 start_offset,
997 start_node.len() - start_offset,
998 DOMString::new(),
999 )
1000 .unwrap();
1001 }
1002
1003 for child in &*contained_children {
1005 child.remove_self(CanGc::note());
1006 }
1007
1008 if let Some(text) = end_node.downcast::<CharacterData>() {
1010 text.ReplaceData(0, end_offset, DOMString::new()).unwrap();
1011 }
1012
1013 self.SetStart(&new_node, new_offset).unwrap();
1015 self.SetEnd(&new_node, new_offset).unwrap();
1016 Ok(())
1017 }
1018
1019 fn SurroundContents(&self, new_parent: &Node, can_gc: CanGc) -> ErrorResult {
1021 let start = self.start_container();
1023 let end = self.end_container();
1024
1025 if start
1026 .inclusive_ancestors(ShadowIncluding::No)
1027 .any(|n| !n.is_inclusive_ancestor_of(&end) && !n.is::<Text>()) ||
1028 end.inclusive_ancestors(ShadowIncluding::No)
1029 .any(|n| !n.is_inclusive_ancestor_of(&start) && !n.is::<Text>())
1030 {
1031 return Err(Error::InvalidState);
1032 }
1033
1034 match new_parent.type_id() {
1036 NodeTypeId::Document(_) |
1037 NodeTypeId::DocumentType |
1038 NodeTypeId::DocumentFragment(_) => {
1039 return Err(Error::InvalidNodeType);
1040 },
1041 _ => (),
1042 }
1043
1044 let fragment = self.ExtractContents(can_gc)?;
1046
1047 Node::replace_all(None, new_parent, can_gc);
1049
1050 self.InsertNode(new_parent, can_gc)?;
1052
1053 new_parent.AppendChild(fragment.upcast(), can_gc)?;
1055
1056 self.SelectNode(new_parent)
1058 }
1059
1060 fn Stringifier(&self) -> DOMString {
1062 let start_node = self.start_container();
1063 let end_node = self.end_container();
1064
1065 let mut s = DOMString::new();
1067
1068 if let Some(text_node) = start_node.downcast::<Text>() {
1069 let char_data = text_node.upcast::<CharacterData>();
1070
1071 if start_node == end_node {
1073 return char_data
1074 .SubstringData(self.start_offset(), self.end_offset() - self.start_offset())
1075 .unwrap();
1076 }
1077
1078 s.push_str(
1080 &char_data
1081 .SubstringData(
1082 self.start_offset(),
1083 char_data.Length() - self.start_offset(),
1084 )
1085 .unwrap(),
1086 );
1087 }
1088
1089 let ancestor = self.CommonAncestorContainer();
1091 let iter = start_node
1092 .following_nodes(&ancestor)
1093 .filter_map(DomRoot::downcast::<Text>);
1094
1095 for child in iter {
1096 if self.contains(child.upcast()) {
1097 s.push_str(&child.upcast::<CharacterData>().Data());
1098 }
1099 }
1100
1101 if let Some(text_node) = end_node.downcast::<Text>() {
1103 let char_data = text_node.upcast::<CharacterData>();
1104 s.push_str(&char_data.SubstringData(0, self.end_offset()).unwrap());
1105 }
1106
1107 s
1109 }
1110
1111 fn CreateContextualFragment(
1113 &self,
1114 fragment: TrustedHTMLOrString,
1115 can_gc: CanGc,
1116 ) -> Fallible<DomRoot<DocumentFragment>> {
1117 let node = self.start_container();
1122 let fragment = TrustedHTML::get_trusted_script_compliant_string(
1126 node.owner_window().upcast(),
1127 fragment,
1128 "Range createContextualFragment",
1129 can_gc,
1130 )?;
1131 let owner_doc = node.owner_doc();
1132 let element = match node.type_id() {
1133 NodeTypeId::Document(_) | NodeTypeId::DocumentFragment(_) => None,
1135 NodeTypeId::Element(_) => Some(DomRoot::downcast::<Element>(node).unwrap()),
1137 NodeTypeId::CharacterData(CharacterDataTypeId::Comment) |
1139 NodeTypeId::CharacterData(CharacterDataTypeId::Text(_)) => node.GetParentElement(),
1140 NodeTypeId::CharacterData(CharacterDataTypeId::ProcessingInstruction) |
1141 NodeTypeId::DocumentType => unreachable!(),
1142 NodeTypeId::Attr => unreachable!(),
1143 };
1144
1145 let element = Element::fragment_parsing_context(&owner_doc, element.as_deref(), can_gc);
1147
1148 let fragment_node = element.parse_fragment(fragment, can_gc)?;
1150
1151 for node in fragment_node
1153 .upcast::<Node>()
1154 .traverse_preorder(ShadowIncluding::No)
1155 {
1156 if let Some(script) = node.downcast::<HTMLScriptElement>() {
1157 script.set_already_started(false);
1159 script.set_parser_inserted(false);
1161 }
1162 }
1163
1164 Ok(fragment_node)
1166 }
1167
1168 fn GetClientRects(&self, can_gc: CanGc) -> DomRoot<DOMRectList> {
1170 let start = self.start_container();
1171 let window = start.owner_window();
1172
1173 let client_rects = self
1174 .client_rects()
1175 .map(|rect| {
1176 DOMRect::new(
1177 window.upcast(),
1178 rect.origin.x.to_f64_px(),
1179 rect.origin.y.to_f64_px(),
1180 rect.size.width.to_f64_px(),
1181 rect.size.height.to_f64_px(),
1182 can_gc,
1183 )
1184 })
1185 .collect();
1186
1187 DOMRectList::new(&window, client_rects, can_gc)
1188 }
1189
1190 fn GetBoundingClientRect(&self, can_gc: CanGc) -> DomRoot<DOMRect> {
1192 let window = self.start_container().owner_window();
1193
1194 let list = self.client_rects();
1196
1197 let bounding_rect = list.fold(euclid::Rect::zero(), |acc, rect| acc.union(&rect));
1202
1203 DOMRect::new(
1204 window.upcast(),
1205 bounding_rect.origin.x.to_f64_px(),
1206 bounding_rect.origin.y.to_f64_px(),
1207 bounding_rect.size.width.to_f64_px(),
1208 bounding_rect.size.height.to_f64_px(),
1209 can_gc,
1210 )
1211 }
1212}
1213
1214#[derive(MallocSizeOf)]
1215pub(crate) struct WeakRangeVec {
1216 cell: RefCell<WeakRefVec<Range>>,
1217}
1218
1219impl Default for WeakRangeVec {
1220 fn default() -> Self {
1221 WeakRangeVec {
1222 cell: RefCell::new(WeakRefVec::new()),
1223 }
1224 }
1225}
1226
1227#[allow(unsafe_code)]
1228impl WeakRangeVec {
1229 pub(crate) fn is_empty(&self) -> bool {
1231 self.cell.borrow().is_empty()
1232 }
1233
1234 pub(crate) fn increase_above(&self, node: &Node, offset: u32, delta: u32) {
1237 self.map_offset_above(node, offset, |offset| offset + delta);
1238 }
1239
1240 pub(crate) fn decrease_above(&self, node: &Node, offset: u32, delta: u32) {
1243 self.map_offset_above(node, offset, |offset| offset - delta);
1244 }
1245
1246 pub(crate) fn drain_to_parent(&self, context: &UnbindContext, child: &Node) {
1250 if self.is_empty() {
1251 return;
1252 }
1253
1254 let offset = context.index();
1255 let parent = context.parent;
1256 let ranges = &mut *self.cell.borrow_mut();
1257
1258 ranges.update(|entry| {
1259 let range = entry.root().unwrap();
1260 if range.start().node() == parent || range.end().node() == parent {
1261 entry.remove();
1262 }
1263 if range.start().node() == child {
1264 range.report_change();
1265 range.start().set(context.parent, offset);
1266 }
1267 if range.end().node() == child {
1268 range.report_change();
1269 range.end().set(context.parent, offset);
1270 }
1271 });
1272
1273 context
1274 .parent
1275 .ranges()
1276 .cell
1277 .borrow_mut()
1278 .extend(ranges.drain(..));
1279 }
1280
1281 pub(crate) fn drain_to_preceding_text_sibling(&self, node: &Node, sibling: &Node, length: u32) {
1284 if self.is_empty() {
1285 return;
1286 }
1287
1288 let ranges = &mut *self.cell.borrow_mut();
1289
1290 ranges.update(|entry| {
1291 let range = entry.root().unwrap();
1292 if range.start().node() == sibling || range.end().node() == sibling {
1293 entry.remove();
1294 }
1295 if range.start().node() == node {
1296 range.report_change();
1297 range.start().set(sibling, range.start_offset() + length);
1298 }
1299 if range.end().node() == node {
1300 range.report_change();
1301 range.end().set(sibling, range.end_offset() + length);
1302 }
1303 });
1304
1305 sibling.ranges().cell.borrow_mut().extend(ranges.drain(..));
1306 }
1307
1308 pub(crate) fn move_to_text_child_at(
1311 &self,
1312 node: &Node,
1313 offset: u32,
1314 child: &Node,
1315 new_offset: u32,
1316 ) {
1317 let child_ranges = child.ranges();
1318 let mut child_ranges = child_ranges.cell.borrow_mut();
1319
1320 self.cell.borrow_mut().update(|entry| {
1321 let range = entry.root().unwrap();
1322
1323 let node_is_start = range.start().node() == node;
1324 let node_is_end = range.end().node() == node;
1325
1326 let move_start = node_is_start && range.start_offset() == offset;
1327 let move_end = node_is_end && range.end_offset() == offset;
1328
1329 let remove_from_node =
1330 move_start && (move_end || !node_is_end) || move_end && !node_is_start;
1331
1332 let already_in_child = range.start().node() == child || range.end().node() == child;
1333 let push_to_child = !already_in_child && (move_start || move_end);
1334
1335 if remove_from_node {
1336 let ref_ = entry.remove();
1337 if push_to_child {
1338 child_ranges.push(ref_);
1339 }
1340 } else if push_to_child {
1341 child_ranges.push(WeakRef::new(&range));
1342 }
1343
1344 if move_start {
1345 range.report_change();
1346 range.start().set(child, new_offset);
1347 }
1348 if move_end {
1349 range.report_change();
1350 range.end().set(child, new_offset);
1351 }
1352 });
1353 }
1354
1355 pub(crate) fn replace_code_units(
1358 &self,
1359 node: &Node,
1360 offset: u32,
1361 removed_code_units: u32,
1362 added_code_units: u32,
1363 ) {
1364 self.map_offset_above(node, offset, |range_offset| {
1365 if range_offset <= offset + removed_code_units {
1366 offset
1367 } else {
1368 range_offset + added_code_units - removed_code_units
1369 }
1370 });
1371 }
1372
1373 pub(crate) fn move_to_following_text_sibling_above(
1376 &self,
1377 node: &Node,
1378 offset: u32,
1379 sibling: &Node,
1380 ) {
1381 let sibling_ranges = sibling.ranges();
1382 let mut sibling_ranges = sibling_ranges.cell.borrow_mut();
1383
1384 self.cell.borrow_mut().update(|entry| {
1385 let range = entry.root().unwrap();
1386 let start_offset = range.start_offset();
1387 let end_offset = range.end_offset();
1388
1389 let node_is_start = range.start().node() == node;
1390 let node_is_end = range.end().node() == node;
1391
1392 let move_start = node_is_start && start_offset > offset;
1393 let move_end = node_is_end && end_offset > offset;
1394
1395 let remove_from_node =
1396 move_start && (move_end || !node_is_end) || move_end && !node_is_start;
1397
1398 let already_in_sibling =
1399 range.start().node() == sibling || range.end().node() == sibling;
1400 let push_to_sibling = !already_in_sibling && (move_start || move_end);
1401
1402 if remove_from_node {
1403 let ref_ = entry.remove();
1404 if push_to_sibling {
1405 sibling_ranges.push(ref_);
1406 }
1407 } else if push_to_sibling {
1408 sibling_ranges.push(WeakRef::new(&range));
1409 }
1410
1411 if move_start {
1412 range.report_change();
1413 range.start().set(sibling, start_offset - offset);
1414 }
1415 if move_end {
1416 range.report_change();
1417 range.end().set(sibling, end_offset - offset);
1418 }
1419 });
1420 }
1421
1422 pub(crate) fn increment_at(&self, node: &Node, offset: u32) {
1425 self.cell.borrow_mut().update(|entry| {
1426 let range = entry.root().unwrap();
1427 if range.start().node() == node && offset == range.start_offset() {
1428 range.report_change();
1429 range.start().set_offset(offset + 1);
1430 }
1431 if range.end().node() == node && offset == range.end_offset() {
1432 range.report_change();
1433 range.end().set_offset(offset + 1);
1434 }
1435 });
1436 }
1437
1438 fn map_offset_above<F: FnMut(u32) -> u32>(&self, node: &Node, offset: u32, mut f: F) {
1439 self.cell.borrow_mut().update(|entry| {
1440 let range = entry.root().unwrap();
1441 let start_offset = range.start_offset();
1442 if range.start().node() == node && start_offset > offset {
1443 range.report_change();
1444 range.start().set_offset(f(start_offset));
1445 }
1446 let end_offset = range.end_offset();
1447 if range.end().node() == node && end_offset > offset {
1448 range.report_change();
1449 range.end().set_offset(f(end_offset));
1450 }
1451 });
1452 }
1453
1454 pub(crate) fn push(&self, ref_: WeakRef<Range>) {
1455 self.cell.borrow_mut().push(ref_);
1456 }
1457
1458 fn remove(&self, range: &Range) -> WeakRef<Range> {
1459 let mut ranges = self.cell.borrow_mut();
1460 let position = ranges.iter().position(|ref_| ref_ == range).unwrap();
1461 ranges.swap_remove(position)
1462 }
1463}
1464
1465#[allow(unsafe_code)]
1466unsafe impl JSTraceable for WeakRangeVec {
1467 unsafe fn trace(&self, _: *mut JSTracer) {
1468 self.cell.borrow_mut().retain_alive()
1469 }
1470}