1use std::cell::{Cell, LazyCell};
6use std::cmp::Ordering;
7
8use atomic_refcell::{AtomicRef, AtomicRefCell};
9use bitflags::bitflags;
10use dom_struct::dom_struct;
11use js::context::{JSContext, NoGC};
12use layout_api::QueryMsg;
13use rustc_hash::{FxHashMap, FxHashSet};
14use script_bindings::cell::DomRefCell;
15use script_bindings::codegen::GenericBindings::ShadowRootBinding::ShadowRootMethods;
16use script_bindings::dom::UnrootedDom;
17use script_bindings::reflector::{Reflector, reflect_dom_object};
18use servo_base::text::{
19 AssumeUnder4GB, RangeAny, Utf16CodeUnits, Utf32CodeUnits, Utf32CodeUnitsOrNodeOffset,
20};
21
22use crate::dom::abstractrange::bp_position;
23use crate::dom::bindings::cell::AtomicSafeBorrowMut;
24use crate::dom::bindings::codegen::Bindings::NodeBinding::{GetRootNodeOptions, NodeMethods};
25use crate::dom::bindings::codegen::Bindings::RangeBinding::RangeMethods;
26use crate::dom::bindings::codegen::Bindings::SelectionBinding::{
27 GetComposedRangesOptions, SelectionMethods,
28};
29use crate::dom::bindings::error::{Error, ErrorResult, Fallible};
30use crate::dom::bindings::inheritance::Castable;
31use crate::dom::bindings::refcounted::Trusted;
32use crate::dom::bindings::reflector::DomGlobal;
33use crate::dom::bindings::root::{Dom, DomRoot, LayoutDom, MutNullableDom};
34use crate::dom::bindings::str::DOMString;
35use crate::dom::comparator::compare_dom_positions;
36use crate::dom::document::Document;
37use crate::dom::eventtarget::EventTarget;
38use crate::dom::iterators::{PrePostIteration, UnrootedFollowingFlatTreeNodesTraversal};
39use crate::dom::node::{Node, NodeTraits};
40use crate::dom::range::Range;
41use crate::dom::selection_range::{RootedSelectionBoundary, SelectionBoundary, SelectionRange};
42use crate::dom::staticrange::StaticRange;
43use crate::dom::traversal::FlatTreeForSelectionNoGcTraversal;
44use crate::dom::types::ShadowRoot;
45use crate::dom::{CharacterData, FlatTreeParent, NodeDamage, NodeFlags, StartOrEnd};
46
47#[derive(Copy, Clone, PartialEq)]
50pub(crate) enum UsedUserSelect {
51 Text,
52 None,
53 Contain,
54 All,
55}
56
57#[derive(Clone, Copy, JSTraceable, MallocSizeOf)]
58pub(crate) enum Direction {
59 Forwards,
60 Backwards,
61 Directionless,
62}
63
64#[dom_struct]
66pub(crate) struct Selection {
67 reflector_: Reflector,
68 document: Dom<Document>,
69 range: DomRefCell<Option<SelectionRange>>,
72 live_range: MutNullableDom<Range>,
74 #[custom_trace]
79 visible_range: AtomicRefCell<Option<SelectionRange>>,
80 direction: Cell<Direction>,
83 has_scheduled_selectionchange_event: Cell<bool>,
85 visible_selection_dirty: Cell<bool>,
88}
89
90impl Selection {
91 fn new_inherited(document: &Document) -> Selection {
92 Selection {
93 reflector_: Reflector::new(),
94 document: Dom::from_ref(document),
95 range: Default::default(),
96 live_range: MutNullableDom::new(None),
97 visible_range: Default::default(),
98 direction: Cell::new(Direction::Directionless),
99 has_scheduled_selectionchange_event: Cell::new(false),
100 visible_selection_dirty: Cell::new(false),
101 }
102 }
103
104 pub(crate) fn new(cx: &mut JSContext, document: &Document) -> DomRoot<Selection> {
105 reflect_dom_object(
106 cx,
107 Box::new(Selection::new_inherited(document)),
108 &*document.global(),
109 )
110 }
111
112 pub(crate) fn visible_selection_dirty(&self) -> bool {
113 self.visible_selection_dirty.get()
114 }
115
116 pub(crate) fn collapsed(&self) -> bool {
117 self.range
118 .borrow()
119 .as_ref()
120 .is_none_or(|range| range.collapsed())
121 }
122
123 fn clear_cached_live_range(&self) {
124 if let Some(old_range) = self.live_range.take() {
125 old_range.disassociate_selection(self);
126 }
127 }
128
129 pub(crate) fn clear_selection_if_live_range_document_changed(
133 &self,
134 no_gc: &NoGC,
135 range: &Range,
136 ) -> bool {
137 let range_start_container = range.start_container();
140 let range_end_container = range.end_container();
141 if self.is_in_composed_tree_of_document_and_is_not_ua_widget(&range_start_container) &&
142 self.is_in_composed_tree_of_document_and_is_not_ua_widget(&range_end_container)
143 {
144 return false;
145 }
146
147 self.set_range(no_gc, None);
148 true
149 }
150
151 pub(crate) fn set_start_or_end_from_live_range(
156 &self,
157 no_gc: &NoGC,
158 start_or_end: StartOrEnd,
159 live_range: &Range,
160 ) -> bool {
161 let mut range = self.range.borrow_mut();
162 let range = range
163 .as_mut()
164 .expect("A live range implies a selection range");
165
166 let (container, offset) = match start_or_end {
167 StartOrEnd::Start if range.start != *live_range.start() => {
168 (live_range.start_container(), live_range.start_offset())
169 },
170 StartOrEnd::End if range.end != *live_range.end() => {
171 (live_range.end_container(), live_range.end_offset())
172 },
173 _ => return false,
174 };
175
176 let would_invert = match start_or_end {
177 StartOrEnd::Start => {
178 compare_shadow_including_dom_positions(
179 no_gc,
180 &container,
181 offset,
182 &range.end.container,
183 range.end.offset,
184 ) == Ordering::Greater
185 },
186 StartOrEnd::End => {
187 compare_shadow_including_dom_positions(
188 no_gc,
189 &range.start.container,
190 range.start.offset,
191 &container,
192 offset,
193 ) == Ordering::Greater
194 },
195 };
196
197 if would_invert {
198 *range = SelectionRange::collapsed_at(SelectionBoundary::new(&container, offset));
199 } else {
200 match start_or_end {
201 StartOrEnd::Start => range.start = SelectionBoundary::new(&container, offset),
202 StartOrEnd::End => range.end = SelectionBoundary::new(&container, offset),
203 }
204 }
205 true
206 }
207
208 pub(crate) fn update_from_live_range(
209 &self,
210 no_gc: &NoGC,
211 live_range: &Range,
212 notification: SelectionLiveRangeNotification,
213 ) {
214 debug_assert!(Some(live_range) == self.live_range.get().as_deref());
215 let start_changed = notification.contains(SelectionLiveRangeNotification::Start) &&
216 self.set_start_or_end_from_live_range(no_gc, StartOrEnd::Start, live_range);
217 let end_changed = notification.contains(SelectionLiveRangeNotification::End) &&
218 self.set_start_or_end_from_live_range(no_gc, StartOrEnd::End, live_range);
219 if start_changed || end_changed {
220 self.selection_boundaries_changed();
221 }
222 }
223
224 #[cfg_attr(crown, expect(crown::unrooted_must_root))]
225 fn set_range(&self, _no_gc: &NoGC, new_range: Option<SelectionRange>) -> bool {
226 let changed;
227 {
228 let mut range = self.range.borrow_mut();
229 changed = *range != new_range;
230 *range = new_range;
231
232 if range.is_none() {
233 self.direction.set(Direction::Directionless);
234 }
235 }
236
237 self.clear_cached_live_range();
239
240 if changed {
241 self.selection_boundaries_changed();
242 #[cfg(debug_assertions)]
243 self.assert_valid_selection(_no_gc);
244 }
245
246 changed
247 }
248
249 pub(crate) fn set_live_range(&self, no_gc: &NoGC, new_range: Option<&Range>) {
250 if new_range == self.live_range.get().as_deref() {
251 return;
252 }
253
254 let boundaries_changed = self.set_range(no_gc, new_range.map(|new_range| new_range.into()));
255
256 if let Some(old_range) = self.live_range.take() {
259 old_range.disassociate_selection(self);
260 }
261 if let Some(new_range) = new_range {
262 self.live_range.set(Some(new_range));
263 new_range.associate_selection(self);
264 }
265
266 if !boundaries_changed {
277 self.queue_selectionchange_task();
278 }
279 }
280
281 fn selection_boundaries_changed(&self) {
282 self.set_visible_selection_dirty();
283 self.queue_selectionchange_task();
284
285 self.document.clear_command_overrides();
294 }
295
296 fn iter_nodes_with_overlaps_document_selection_flag<'no_gc>(
297 &self,
298 no_gc: &'no_gc NoGC,
299 ) -> impl Iterator<Item = UnrootedDom<'no_gc, Node>> {
300 let mut traversal = self
301 .document
302 .upcast::<Node>()
303 .following_flat_tree_nodes_unrooted(no_gc);
304 let mut next = traversal.next();
305 std::iter::from_fn(move || {
306 while let Some(node) = next.take() {
307 match node {
308 PrePostIteration::Enter(node) => {
309 if node.get_flag(NodeFlags::OVERLAPS_DOCUMENT_SELECTION) {
310 next = traversal.next();
311 return Some(node);
312 } else {
313 next = traversal.next_skipping_subtree();
318 }
319 },
320 PrePostIteration::Leave(_) => next = traversal.next(),
321 }
322 }
323 None
324 })
325 }
326
327 fn set_visible_range(&self, no_gc: &NoGC, flat_tree_selection: Option<FlatTreeSelection>) {
328 *self.visible_range.safe_borrow_mut(no_gc) = flat_tree_selection.map(|selection| {
329 SelectionRange::new(
330 SelectionBoundary::new(&selection.start.container, selection.start.offset),
331 SelectionBoundary::new(&selection.end.container, selection.end.offset),
332 )
333 });
334 }
335
336 pub(crate) fn update_overlaps_document_selection_flags(&self, no_gc: &NoGC) {
337 if !self.visible_selection_dirty.take() {
338 return;
339 }
340
341 let previously_flagged_nodes = self
342 .iter_nodes_with_overlaps_document_selection_flag(no_gc)
343 .collect();
344 let flat_tree_selection = FlatTreeSelection::from_selection_if_renderable(no_gc, self);
345 VisibleSelectionFlagUpdate::run(
346 no_gc,
347 previously_flagged_nodes,
348 flat_tree_selection.as_ref(),
349 &self.document,
350 );
351 self.set_visible_range(no_gc, flat_tree_selection);
352 }
353
354 pub(crate) fn queue_selectionchange_task(&self) {
356 if self.has_scheduled_selectionchange_event.get() {
358 return;
359 }
360 self.has_scheduled_selectionchange_event.set(true);
362 let this = Trusted::new(self);
365 self.document
366 .owner_global()
367 .task_manager()
368 .user_interaction_task_source() .queue(
370 task!(selectionchange_task_steps: move |cx| {
372 let this = this.root();
373 this.has_scheduled_selectionchange_event.set(false);
375 this.document.upcast::<EventTarget>().fire_event(cx, atom!("selectionchange"));
384 }),
385 );
386 }
387
388 fn is_in_composed_tree_of_document_and_is_not_ua_widget(&self, node: &Node) -> bool {
389 &*node.GetRootNode(&GetRootNodeOptions { composed: true }) == self.document.upcast::<Node>() &&
390 !node.is_in_ua_widget()
391 }
392
393 pub(crate) fn start_boundary(&self, cx: &mut JSContext) -> (DomRoot<Node>, u32) {
394 let range = self.expect_active_range(cx);
395 (range.start_container(), range.start_offset())
396 }
397
398 pub(crate) fn end_boundary(&self, cx: &mut JSContext) -> (DomRoot<Node>, u32) {
399 let range = self.expect_active_range(cx);
400 (range.end_container(), range.end_offset())
401 }
402
403 #[cfg(debug_assertions)]
404 fn assert_valid_selection(&self, no_gc: &NoGC) {
405 let range_borrow = self.range.borrow();
406 let Some(range) = range_borrow.as_ref() else {
407 return;
408 };
409 debug_assert_eq!(
410 range
411 .start
412 .container
413 .GetRootNode(&GetRootNodeOptions { composed: true }),
414 range
415 .end
416 .container
417 .GetRootNode(&GetRootNodeOptions { composed: true })
418 );
419 debug_assert!(
420 compare_shadow_including_dom_positions(
421 no_gc,
422 &range.start.container,
423 range.start.offset,
424 &range.end.container,
425 range.end.offset
426 ) != Ordering::Greater
427 );
428 }
429
430 #[cfg(debug_assertions)]
431 fn assert_valid_selection_and_live_range(&self, no_gc: &NoGC) {
432 self.assert_valid_selection(no_gc);
433
434 let Some(active_range) = self.live_range.get() else {
435 return;
436 };
437 debug_assert!(
438 bp_position(
439 no_gc,
440 &active_range.start_container(),
441 active_range.start_offset(),
442 &active_range.end_container(),
443 active_range.end_offset()
444 ) != Ordering::Greater
445 );
446 }
447
448 pub(crate) fn active_range(&self, cx: &mut JSContext) -> Option<DomRoot<Range>> {
453 #[cfg(debug_assertions)]
454 self.assert_valid_selection_and_live_range(cx.no_gc());
455
456 if let Some(active_range) = self.live_range.get() {
457 return Some(active_range);
458 }
459
460 let live_range = {
461 let range = self.range.borrow();
462 let range = range.as_ref()?;
463 let live_range = Range::new(
464 cx,
465 &self.document,
466 &range.start.container,
467 range.start.offset,
468 &range.start.container,
469 range.start.offset,
470 );
471 live_range
472 .SetEnd(cx.no_gc(), &range.end.container, range.end.offset)
473 .expect("New end boundary should always be valid");
474 live_range
475 };
476
477 self.live_range.set(Some(&live_range));
478 live_range.associate_selection(self);
479 Some(live_range)
480 }
481
482 pub(crate) fn expect_active_range(&self, cx: &mut JSContext) -> DomRoot<Range> {
483 self.active_range(cx)
484 .expect("Should always have an active range")
485 }
486
487 pub(crate) fn set_visible_selection_dirty(&self) {
488 self.visible_selection_dirty.set(true);
489 }
490
491 pub(crate) fn composed_anchor_position(&self) -> Option<RootedSelectionBoundary> {
492 let range = self.range.borrow();
493 let range = range.as_ref()?;
494 let (container, offset) = match self.direction.get() {
495 Direction::Forwards => (range.start.container.as_rooted(), range.start.offset),
496 _ => (range.end.container.as_rooted(), range.end.offset),
497 };
498 Some(RootedSelectionBoundary::new_with_utf16_offset(
499 container, offset,
500 ))
501 }
502
503 fn live_anchor_node(&self, cx: &mut JSContext) -> Option<DomRoot<Node>> {
505 self.active_range(cx)
506 .map(|range| match self.direction.get() {
507 Direction::Forwards => range.start_container(),
508 _ => range.end_container(),
509 })
510 }
511
512 fn live_anchor_offset(&self, cx: &mut JSContext) -> u32 {
514 self.active_range(cx)
515 .map_or(0, |range| match self.direction.get() {
516 Direction::Forwards => range.start_offset(),
517 _ => range.end_offset(),
518 })
519 }
520
521 fn live_focus_node(&self, cx: &mut JSContext) -> Option<DomRoot<Node>> {
523 self.active_range(cx)
524 .map(|range| match self.direction.get() {
525 Direction::Forwards => range.end_container(),
526 _ => range.start_container(),
527 })
528 }
529
530 fn live_focus_offset(&self, cx: &mut JSContext) -> u32 {
532 self.active_range(cx)
533 .map_or(0, |range| match self.direction.get() {
534 Direction::Forwards => range.end_offset(),
535 _ => range.start_offset(),
536 })
537 }
538
539 pub(crate) fn insert_steps(&self, parent: &Node, child: &Node, count: u32) {
544 let mut range_borrow = self.range.borrow_mut();
545 let Some(range) = &mut *range_borrow else {
546 return;
547 };
548 let child_index = LazyCell::new(|| child.index());
549 if range.start.container == parent && range.start.offset > *child_index {
552 range.start.offset += count;
553 self.selection_boundaries_changed();
554 }
555 if range.end.container == parent && range.end.offset > *child_index {
558 range.end.offset += count;
559 self.selection_boundaries_changed();
560 }
561 }
562
563 pub(crate) fn pre_remove_steps(
566 &self,
567 removed_node: &Node, parent_of_removed_node: &Node, index_of_removed_node: &mut dyn FnMut() -> u32, ) {
571 let mut range_borrow = self.range.borrow_mut();
572 let Some(range) = &mut *range_borrow else {
573 return;
574 };
575
576 if removed_node.is_shadow_including_inclusive_ancestor_of(&range.start.container) {
579 range.start = SelectionBoundary::new(parent_of_removed_node, index_of_removed_node());
580 self.selection_boundaries_changed();
581 }
582 if removed_node.is_shadow_including_inclusive_ancestor_of(&range.end.container) {
585 range.end = SelectionBoundary::new(parent_of_removed_node, index_of_removed_node());
586 self.selection_boundaries_changed();
587 }
588 if range.start.container == parent_of_removed_node &&
591 range.start.offset > index_of_removed_node()
592 {
593 range.start.offset -= 1;
594 self.selection_boundaries_changed();
595 }
596 if range.end.container == parent_of_removed_node &&
599 range.end.offset > index_of_removed_node()
600 {
601 range.end.offset -= 1;
602 self.selection_boundaries_changed();
603 }
604 }
605
606 pub(crate) fn normalization_steps(
615 &self,
616 parent: &Node,
617 node: &Node,
618 current_node: &Node,
619 current_node_index: &dyn Fn() -> u32,
620 length: u32,
621 ) {
622 let mut range_borrow = self.range.borrow_mut();
623 let Some(range) = &mut *range_borrow else {
624 return;
625 };
626 if range.start.container == current_node {
629 range.start.offset += length;
630 range.start.container = Dom::from_ref(node);
631 self.selection_boundaries_changed();
632 }
633 if range.end.container == current_node {
636 range.end.offset += length;
637 range.end.container = Dom::from_ref(node);
638 self.selection_boundaries_changed();
639 }
640 if range.start.container == parent && range.start.offset == current_node_index() {
644 range.start.container = Dom::from_ref(node);
645 range.start.offset = length;
646 self.selection_boundaries_changed();
647 }
648 if range.end.container == parent && range.end.offset == current_node_index() {
651 range.end.container = Dom::from_ref(node);
652 range.end.offset = length;
653 self.selection_boundaries_changed();
654 }
655 }
656
657 pub(crate) fn replace_data_steps(
660 &self,
661 node: &Node,
662 offset: u32,
663 removed_code_units: u32,
664 added_code_units: &mut dyn FnMut() -> u32,
665 ) {
666 let mut range_borrow = self.range.borrow_mut();
667 let Some(range) = &mut *range_borrow else {
668 return;
669 };
670 let start_container = &range.start.container;
674 let start_offset = range.start.offset;
675 if &**start_container == node &&
676 start_offset > offset &&
677 start_offset <= offset + removed_code_units
678 {
679 range.start.offset = offset;
680 self.selection_boundaries_changed();
681 }
682 let end_container = &range.end.container;
686 let end_offset = range.end.offset;
687 if &**end_container == node &&
688 end_offset > offset &&
689 end_offset <= offset + removed_code_units
690 {
691 range.end.offset = offset;
692 self.selection_boundaries_changed();
693 }
694 if &**start_container == node && start_offset > offset + removed_code_units {
698 range.start.offset = start_offset + added_code_units() - removed_code_units;
699 self.selection_boundaries_changed();
700 }
701 if &**end_container == node && end_offset > offset + removed_code_units {
705 range.end.offset = end_offset + added_code_units() - removed_code_units;
706 self.selection_boundaries_changed();
707 }
708 }
709
710 pub(crate) fn text_split_steps(
713 &self,
714 node: &Node,
715 offset: u32,
716 parent_node: &Node,
717 new_node: &Node,
718 ) {
719 let mut range_borrow = self.range.borrow_mut();
720 let Some(range) = &mut *range_borrow else {
721 return;
722 };
723 if range.start.container == node && range.start.offset > offset {
727 range.start.container = Dom::from_ref(new_node);
728 range.start.offset -= offset;
729 self.selection_boundaries_changed();
730 }
731 if range.end.container == node && range.end.offset > offset {
734 range.end.container = Dom::from_ref(new_node);
735 range.end.offset -= offset;
736 self.selection_boundaries_changed();
737 }
738 let node_index = LazyCell::new(|| node.index());
741 if range.start.container == parent_node && range.start.offset == *node_index + 1 {
742 range.start.offset += 1;
743 self.selection_boundaries_changed();
744 }
745 if range.end.container == parent_node && range.end.offset == *node_index + 1 {
748 range.end.offset += 1;
749 self.selection_boundaries_changed();
750 }
751 }
752
753 pub(crate) fn collapse_to_dom_position(
754 &self,
755 cx: &mut JSContext,
756 boundary: &RootedSelectionBoundary,
757 ) {
758 let _ = self.Collapse(cx, Some(&boundary.container), boundary.offset);
759 }
760
761 pub(crate) fn collapse_or_extend_to_dom_position(
762 &self,
763 cx: &mut JSContext,
764 boundary: &RootedSelectionBoundary,
765 ) {
766 let is_anchor = self
767 .composed_anchor_position()
768 .is_some_and(|anchor| anchor == *boundary);
769
770 if self.range.borrow().is_none() || is_anchor {
771 let _ = self.Collapse(cx, Some(&boundary.container), boundary.offset);
772 } else {
773 let _ = self.Extend(cx, &boundary.container, boundary.offset);
774 }
775 }
776
777 pub(crate) fn set_anchor_and_focus(
781 &self,
782 cx: &mut JSContext,
783 anchor: &RootedSelectionBoundary,
784 focus: &RootedSelectionBoundary,
785 ) {
786 let _ = self.SetBaseAndExtent(
787 cx,
788 &anchor.container,
789 anchor.offset,
790 &focus.container,
791 focus.offset,
792 );
793 }
794}
795
796impl SelectionMethods<crate::DomTypeHolder> for Selection {
797 fn GetAnchorNode(&self, cx: &mut JSContext) -> Option<DomRoot<Node>> {
799 self.live_anchor_node(cx)
805 }
806
807 fn AnchorOffset(&self, cx: &mut JSContext) -> u32 {
809 self.live_anchor_offset(cx)
815 }
816
817 fn GetFocusNode(&self, cx: &mut JSContext) -> Option<DomRoot<Node>> {
819 self.live_focus_node(cx)
825 }
826
827 fn FocusOffset(&self, cx: &mut JSContext) -> u32 {
829 self.live_focus_offset(cx)
835 }
836
837 fn IsCollapsed(&self, cx: &mut JSContext) -> bool {
839 self.active_range(cx).is_none_or(|range| range.collapsed())
842 }
843
844 fn RangeCount(&self) -> u32 {
846 if self.range.borrow().is_none() {
852 return 0;
853 }
854 1
855 }
856
857 fn Type(&self) -> DOMString {
859 let range = self.range.borrow();
866 let Some(range) = range.as_ref() else {
867 return DOMString::from_static("None");
868 };
869 if range.collapsed() {
870 DOMString::from_static("Caret")
871 } else {
872 DOMString::from_static("Range")
873 }
874 }
875
876 fn Direction(&self) -> DOMString {
878 match self.direction.get() {
882 Direction::Directionless => DOMString::from_static("none"),
883 Direction::Forwards => DOMString::from_static("forward"),
884 Direction::Backwards => DOMString::from_static("backward"),
885 }
886 }
887
888 fn GetRangeAt(&self, cx: &mut JSContext, index: u32) -> Fallible<DomRoot<Range>> {
890 if index != 0 {
897 return Err(Error::IndexSize(Some("Index must be zero".into())));
898 }
899
900 let Some(range) = self.active_range(cx) else {
901 return Err(Error::IndexSize(Some("Selection is empty".into())));
902 };
903
904 Ok(range)
905 }
906
907 fn AddRange(&self, no_gc: &NoGC, range: &Range) {
909 if !self.is_in_composed_tree_of_document_and_is_not_ua_widget(&range.start_container()) {
912 return;
913 }
914
915 if self.RangeCount() != 0 {
917 return;
918 }
919
920 self.set_live_range(no_gc, Some(range));
922
923 self.direction.set(Direction::Forwards);
925 }
926
927 fn RemoveRange(&self, no_gc: &NoGC, range: &Range) -> ErrorResult {
929 if let Some(own_range) = self.live_range.get() &&
932 &*own_range == range
933 {
934 self.set_range(no_gc, None);
935 return Ok(());
936 }
937 Err(Error::NotFound(Some(
938 "Range is not the selection's range".into(),
939 )))
940 }
941
942 fn RemoveAllRanges(&self, no_gc: &NoGC) {
944 self.set_range(no_gc, None);
947 }
948
949 fn Empty(&self, no_gc: &NoGC) {
951 self.RemoveAllRanges(no_gc);
953 }
954
955 fn GetComposedRanges(
957 &self,
958 cx: &mut JSContext,
959 options: &GetComposedRangesOptions,
960 ) -> Vec<DomRoot<StaticRange>> {
961 let borrowed_range = self.range.borrow();
963 let Some(range) = borrowed_range.as_ref() else {
964 return Vec::new();
965 };
966
967 let mut start_node = range.start.container.as_rooted();
970 let mut start_offset = range.start.offset;
971
972 let is_ancestor_of_provided_shadow_roots = |shadow_root: &ShadowRoot| {
973 let shadow_root_node = shadow_root.upcast::<Node>();
974 options.shadowRoots.iter().any(|option_shadow_root| {
975 shadow_root_node
976 .is_shadow_including_inclusive_ancestor_of(option_shadow_root.upcast())
977 })
978 };
979
980 while let Some(containing_shadow_root) = start_node.containing_shadow_root() &&
984 !is_ancestor_of_provided_shadow_roots(&containing_shadow_root)
985 {
986 let host = DomRoot::upcast::<Node>(containing_shadow_root.Host());
988 start_offset = host.index();
989
990 let Some(new_start_node) = host.GetParentNode() else {
994 return Vec::new();
995 };
996 start_node = new_start_node;
997 }
998
999 let mut end_node = range.end.container.as_rooted();
1002 let mut end_offset = range.end.offset;
1003
1004 while let Some(containing_shadow_root) = end_node.containing_shadow_root() &&
1008 !is_ancestor_of_provided_shadow_roots(&containing_shadow_root)
1009 {
1010 let host = DomRoot::upcast::<Node>(containing_shadow_root.Host());
1012 end_offset = host.index() + 1;
1013
1014 let Some(new_end_node) = host.GetParentNode() else {
1018 return Vec::new();
1019 };
1020 end_node = new_end_node;
1021 }
1022
1023 drop(borrowed_range);
1024
1025 vec![DomRoot::from_ref(&StaticRange::new(
1029 cx,
1030 &self.document,
1031 &start_node,
1032 start_offset,
1033 &end_node,
1034 end_offset,
1035 ))]
1036 }
1037
1038 fn Collapse(&self, cx: &mut JSContext, node: Option<&Node>, offset: u32) -> ErrorResult {
1040 let Some(node) = node else {
1043 self.set_range(cx.no_gc(), None);
1044 return Ok(());
1045 };
1046
1047 if node.is_doctype() {
1050 return Err(Error::InvalidNodeType(Some("Node is a doctype".into())));
1051 }
1052
1053 if offset > node.len() {
1056 return Err(Error::IndexSize(Some(
1057 "Offset is greater than the node's length".into(),
1058 )));
1059 }
1060
1061 if !self.is_in_composed_tree_of_document_and_is_not_ua_widget(node) {
1064 return Ok(());
1065 }
1066
1067 self.set_range(
1071 cx.no_gc(),
1072 Some(SelectionRange::collapsed_at(SelectionBoundary::new(
1073 node, offset,
1074 ))),
1075 );
1076
1077 self.direction.set(Direction::Forwards);
1079
1080 Ok(())
1081 }
1082
1083 fn SetPosition(&self, cx: &mut JSContext, node: Option<&Node>, offset: u32) -> ErrorResult {
1085 self.Collapse(cx, node, offset)
1087 }
1088
1089 fn CollapseToStart(&self, cx: &mut JSContext) -> ErrorResult {
1091 let Some((start_container, start_offset)) = self
1096 .range
1097 .borrow()
1098 .as_ref()
1099 .map(|range| (range.start.container.as_rooted(), range.start.offset))
1100 else {
1101 return Err(Error::InvalidState(Some("Selection is empty".into())));
1102 };
1103 self.Collapse(cx, Some(&*start_container), start_offset)
1104 }
1105
1106 fn CollapseToEnd(&self, cx: &mut JSContext) -> ErrorResult {
1108 let Some((end_container, end_offset)) = self
1112 .range
1113 .borrow()
1114 .as_ref()
1115 .map(|range| (range.end.container.as_rooted(), range.end.offset))
1116 else {
1117 return Err(Error::InvalidState(Some("Selection is empty".into())));
1118 };
1119 self.Collapse(cx, Some(&*end_container), end_offset)
1120 }
1121
1122 fn Extend(&self, cx: &mut JSContext, node: &Node, offset: u32) -> ErrorResult {
1124 if !self.is_in_composed_tree_of_document_and_is_not_ua_widget(node) {
1127 return Ok(());
1128 }
1129
1130 let range_borrow = self.range.borrow();
1132 let Some(range) = range_borrow.as_ref() else {
1133 return Err(Error::InvalidState(Some("Selection is empty".into())));
1134 };
1135
1136 if node.is_doctype() {
1139 return Err(Error::InvalidNodeType(Some("Node is a doctype".into())));
1140 }
1141
1142 if offset > node.len() {
1145 return Err(Error::IndexSize(Some(
1146 "Offset is greater than the node's length".into(),
1147 )));
1148 }
1149
1150 let old_anchor = self
1155 .composed_anchor_position()
1156 .expect("has range, therefore has anchor node");
1157
1158 let direction;
1161
1162 let in_different_roots = !nodes_have_same_shadow_root(&range.start.container, node);
1165 drop(range_borrow);
1166
1167 if in_different_roots {
1168 self.set_range(
1169 cx.no_gc(),
1170 Some(SelectionRange::collapsed_at(SelectionBoundary::new(
1171 node, offset,
1172 ))),
1173 );
1174 direction = Direction::Forwards;
1175 } else {
1176 let is_old_anchor_before_or_equal = matches!(
1177 compare_shadow_including_dom_positions(
1178 cx.no_gc(),
1179 &old_anchor.container,
1180 old_anchor.offset,
1181 node,
1182 offset
1183 ),
1184 Ordering::Less | Ordering::Equal
1185 );
1186 if is_old_anchor_before_or_equal {
1187 self.set_range(
1190 cx.no_gc(),
1191 Some(SelectionRange::new(
1192 SelectionBoundary::new(&old_anchor.container, old_anchor.offset),
1193 SelectionBoundary::new(node, offset),
1194 )),
1195 );
1196 direction = Direction::Forwards;
1197 } else {
1198 self.set_range(
1201 cx.no_gc(),
1202 Some(SelectionRange::new(
1203 SelectionBoundary::new(node, offset),
1204 SelectionBoundary::new(&old_anchor.container, old_anchor.offset),
1205 )),
1206 );
1207 direction = Direction::Backwards;
1208 }
1209 }
1210
1211 self.direction.set(direction);
1217
1218 Ok(())
1219 }
1220
1221 fn SetBaseAndExtent(
1223 &self,
1224 cx: &mut JSContext,
1225 anchor_node: &Node,
1226 anchor_offset: u32,
1227 focus_node: &Node,
1228 focus_offset: u32,
1229 ) -> ErrorResult {
1230 if anchor_node.is_doctype() || focus_node.is_doctype() {
1233 return Err(Error::InvalidNodeType(Some("Node is a doctype".into())));
1234 }
1235
1236 if anchor_offset > anchor_node.len() || focus_offset > focus_node.len() {
1240 return Err(Error::IndexSize(Some(
1241 "Offset is greater than the node's length".into(),
1242 )));
1243 }
1244
1245 if !self.is_in_composed_tree_of_document_and_is_not_ua_widget(anchor_node) ||
1248 !self.is_in_composed_tree_of_document_and_is_not_ua_widget(focus_node)
1249 {
1250 return Ok(());
1251 }
1252
1253 let ordering = compare_shadow_including_dom_positions(
1265 cx.no_gc(),
1266 anchor_node,
1267 anchor_offset,
1268 focus_node,
1269 focus_offset,
1270 );
1271 if ordering == Ordering::Less {
1272 self.set_range(
1273 cx.no_gc(),
1274 Some(SelectionRange::new(
1275 SelectionBoundary::new(anchor_node, anchor_offset),
1276 SelectionBoundary::new(focus_node, focus_offset),
1277 )),
1278 );
1279 } else {
1280 self.set_range(
1281 cx.no_gc(),
1282 Some(SelectionRange::new(
1283 SelectionBoundary::new(focus_node, focus_offset),
1284 SelectionBoundary::new(anchor_node, anchor_offset),
1285 )),
1286 );
1287 };
1288
1289 if ordering == Ordering::Greater {
1295 self.direction.set(Direction::Backwards);
1296 } else {
1297 self.direction.set(Direction::Forwards);
1298 }
1299
1300 Ok(())
1301 }
1302
1303 fn SelectAllChildren(&self, cx: &mut JSContext, node: &Node) -> ErrorResult {
1305 if node.is_doctype() {
1308 return Err(Error::InvalidNodeType(Some("Node is a doctype".into())));
1309 }
1310
1311 if !self.is_in_composed_tree_of_document_and_is_not_ua_widget(node) {
1314 return Ok(());
1315 }
1316
1317 let child_count = node.children_count();
1319
1320 self.set_range(
1324 cx.no_gc(),
1325 Some(SelectionRange::new(
1326 SelectionBoundary::new(node, 0),
1327 SelectionBoundary::new(node, child_count),
1328 )),
1329 );
1330
1331 self.direction.set(Direction::Forwards);
1333
1334 Ok(())
1335 }
1336
1337 fn DeleteFromDocument(&self, cx: &mut JSContext) -> ErrorResult {
1339 let Some(active_range) = self
1343 .active_range(cx)
1344 .filter(|range| range.start_and_end_are_in_document_tree())
1345 else {
1346 return Ok(());
1347 };
1348
1349 active_range.DeleteContents(cx)
1350 }
1351
1352 fn ContainsNode(&self, no_gc: &NoGC, node: &Node, allow_partial_containment: bool) -> bool {
1354 if !self.is_in_composed_tree_of_document_and_is_not_ua_widget(node) {
1367 return false;
1368 }
1369 let range = self.range.borrow();
1370 let Some(range) = range.as_ref() else {
1371 return false;
1372 };
1373 let start_node = &*range.start.container;
1374 if !self.is_in_composed_tree_of_document_and_is_not_ua_widget(start_node) {
1375 return false;
1376 }
1377 let end_node = &*range.end.container;
1378
1379 let first_offset = 0;
1380 let last_offset = node.len();
1381 let (compare_start_to, compare_end_to) = if allow_partial_containment {
1382 (last_offset, first_offset)
1383 } else {
1384 (first_offset, last_offset)
1385 };
1386
1387 if !node.is_in_flat_tree(no_gc) {
1392 return false;
1393 }
1394
1395 matches!(
1396 compare_shadow_including_dom_positions(
1397 no_gc,
1398 start_node,
1399 range.start.offset,
1400 node,
1401 compare_start_to
1402 ),
1403 Ordering::Less | Ordering::Equal
1404 ) && matches!(
1405 compare_shadow_including_dom_positions(
1406 no_gc,
1407 end_node,
1408 range.end.offset,
1409 node,
1410 compare_end_to
1411 ),
1412 Ordering::Greater | Ordering::Equal
1413 )
1414 }
1415
1416 fn Stringifier(&self, cx: &mut JSContext) -> DOMString {
1418 self.document
1420 .window()
1421 .layout_reflow(cx, QueryMsg::StyleQuery);
1422
1423 let Some(visible_selection) =
1429 FlatTreeSelection::from_selection_if_renderable(cx.no_gc(), self)
1430 else {
1431 return DOMString::new();
1432 };
1433
1434 let mut user_select_cache = Default::default();
1435 let mut string = DOMString::new();
1436 for node in visible_selection.traversal() {
1437 let Some(character_data) = node.downcast::<CharacterData>() else {
1438 continue;
1439 };
1440
1441 if node.used_user_select(cx.no_gc(), &mut user_select_cache) == UsedUserSelect::None {
1442 continue;
1443 }
1444
1445 let range = visible_selection.range_for_character_data(character_data);
1446 let Some(text) = character_data.rendered_text(range) else {
1447 continue;
1448 };
1449 string.push_str(&text);
1450 }
1451
1452 string
1453 }
1454}
1455
1456impl<'dom> LayoutDom<'dom, Selection> {
1457 pub(crate) fn range_for_layout(&self) -> Option<AtomicRef<'dom, SelectionRange>> {
1458 AtomicRef::filter_map(self.unsafe_get().visible_range.borrow(), Option::as_ref)
1459 }
1460}
1461
1462enum FlatTreeNodePosition {
1463 Before(DomRoot<Node>),
1464 Inside(DomRoot<Node>),
1465 After(DomRoot<Node>),
1466}
1467
1468impl FlatTreeNodePosition {
1469 fn node(&self) -> &Node {
1470 match self {
1471 FlatTreeNodePosition::Before(node) => node,
1472 FlatTreeNodePosition::Inside(node) => node,
1473 FlatTreeNodePosition::After(node) => node,
1474 }
1475 }
1476}
1477
1478fn position_in_flat_tree_for_selection(
1482 no_gc: &NoGC,
1483 boundary: &FlatTreeBoundary,
1484) -> FlatTreeNodePosition {
1485 if boundary.container.is::<CharacterData>() {
1486 return FlatTreeNodePosition::Inside(boundary.container.as_rooted());
1487 }
1488
1489 let shadow_host_or_node = |node: &Node| {
1490 boundary
1491 .container
1492 .downcast::<ShadowRoot>()
1493 .map(|shadow_root| DomRoot::upcast(shadow_root.Host()))
1494 .unwrap_or(DomRoot::from_ref(node))
1495 };
1496
1497 if let Some(child) = boundary.container.children().nth(boundary.offset as usize) {
1498 if let FlatTreeParent::Parent(_) = child.parent_in_flat_tree(no_gc) {
1499 return FlatTreeNodePosition::Before(child);
1500 }
1501 } else if let Some(last_child) = boundary.container.GetLastChild() &&
1502 let FlatTreeParent::Parent(_) = last_child.parent_in_flat_tree(no_gc)
1503 {
1504 return FlatTreeNodePosition::After(shadow_host_or_node(&boundary.container.as_rooted()));
1505 }
1506
1507 FlatTreeNodePosition::Inside(shadow_host_or_node(&boundary.container.as_rooted()))
1510}
1511
1512impl Node {
1513 pub(crate) fn to_sibling_or_utf16_offset(&self, offset: Utf32CodeUnitsOrNodeOffset) -> u32 {
1516 if let Some(character_data) = self.downcast::<CharacterData>() {
1517 offset
1519 .to_utf16_code_units_in(AssumeUnder4GB, &character_data.data())
1520 .0
1521 } else {
1522 offset.0
1523 }
1524 }
1525
1526 pub(crate) fn to_sibling_or_utf32_offset(&self, offset: u32) -> Utf32CodeUnitsOrNodeOffset {
1529 Utf32CodeUnitsOrNodeOffset(
1530 if let Some(character_data) = self.downcast::<CharacterData>() {
1531 Utf16CodeUnits(offset)
1533 .to_utf32_code_units_in(&character_data.data())
1534 .0
1535 } else {
1536 offset
1537 },
1538 )
1539 }
1540}
1541
1542bitflags! {
1543 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
1544 pub(crate) struct SelectionLiveRangeNotification: u8 {
1545 const Start = 1 << 0;
1546 const End = 1 << 1;
1547 }
1548}
1549
1550fn nodes_have_same_shadow_root(a: &Node, b: &Node) -> bool {
1551 a.is_connected() && b.is_connected() && a.containing_shadow_root() == b.containing_shadow_root()
1552}
1553
1554fn project_into_shared_tree<'a>(
1561 no_gc: &'a NoGC,
1562 container_a: &Node,
1563 mut offset_a: u32,
1564 target: Option<&Node>,
1565) -> (UnrootedDom<'a, Node>, u32) {
1566 let mut start_node = UnrootedDom::from_ref(container_a, no_gc);
1567 while let Some(containing_shadow_root) = start_node.containing_shadow_root_unrooted(no_gc) &&
1568 target.is_none_or(|target| {
1569 !containing_shadow_root
1570 .upcast::<Node>()
1571 .is_shadow_including_inclusive_ancestor_of(target)
1572 })
1573 {
1574 let host = DomRoot::upcast::<Node>(containing_shadow_root.Host());
1575 offset_a = host.index();
1576 start_node = host
1577 .get_parent_node_unrooted(no_gc)
1578 .expect("Should only be called on nodes in the same tree");
1579 }
1580
1581 (start_node, offset_a)
1582}
1583
1584pub(crate) fn compare_shadow_including_dom_positions(
1588 no_gc: &NoGC,
1589 container_a: &Node,
1590 offset_a: u32,
1591 container_b: &Node,
1592 offset_b: u32,
1593) -> Ordering {
1594 let (projected_container_a, projected_offset_a) =
1595 project_into_shared_tree(no_gc, container_a, offset_a, Some(container_b));
1596 let (projected_container_b, projected_offset_b) =
1597 project_into_shared_tree(no_gc, container_b, offset_b, Some(container_a));
1598
1599 let a_was_projected = &**projected_container_a != container_a;
1600 let b_was_projected = &**projected_container_b != container_b;
1601
1602 match bp_position(
1603 no_gc,
1604 &projected_container_a,
1605 projected_offset_a,
1606 &projected_container_b,
1607 projected_offset_b,
1608 ) {
1609 Ordering::Equal if a_was_projected && !b_was_projected => Ordering::Greater,
1610 Ordering::Equal if !a_was_projected && b_was_projected => Ordering::Less,
1611 ordering => ordering,
1612 }
1613}
1614
1615struct FlatTreeBoundary<'no_gc> {
1616 container: UnrootedDom<'no_gc, Node>,
1617 offset: u32,
1618}
1619
1620struct FlatTreeSelection<'no_gc> {
1621 no_gc: &'no_gc NoGC,
1622 start: FlatTreeBoundary<'no_gc>,
1623 end: FlatTreeBoundary<'no_gc>,
1624}
1625
1626impl<'no_gc> FlatTreeSelection<'no_gc> {
1627 fn from_selection_if_renderable(no_gc: &'no_gc NoGC, selection: &Selection) -> Option<Self> {
1631 let range = selection.range.borrow();
1632 let range = range.as_ref()?;
1633
1634 let mut start_container = range.start.container.as_unrooted(no_gc);
1635 let mut start_offset = range.start.offset;
1636 let mut end_container = range.end.container.as_unrooted(no_gc);
1637 let mut end_offset = range.end.offset;
1638
1639 if !start_container.is_in_flat_tree(no_gc) {
1640 return None;
1641 }
1642 if !end_container.is_in_flat_tree(no_gc) {
1643 return None;
1644 }
1645
1646 let ordering = compare_dom_positions::<FlatTreeForSelectionNoGcTraversal>(
1650 no_gc,
1651 &range.start.container,
1652 range.start.offset,
1653 &range.end.container,
1654 range.end.offset,
1655 )
1656 .0?;
1657
1658 if ordering == Ordering::Greater {
1661 std::mem::swap(&mut start_container, &mut end_container);
1662 std::mem::swap(&mut start_offset, &mut end_offset);
1663 }
1664
1665 Some(FlatTreeSelection {
1666 no_gc,
1667 start: FlatTreeBoundary {
1668 container: start_container,
1669 offset: start_offset,
1670 },
1671 end: FlatTreeBoundary {
1672 container: end_container,
1673 offset: end_offset,
1674 },
1675 })
1676 }
1677
1678 fn range_for_character_data(&self, character_data: &CharacterData) -> RangeAny<Utf32CodeUnits> {
1679 let text = character_data.data();
1680 let node: &Node = character_data.upcast();
1681 RangeAny::new(
1682 (node == &**self.start.container)
1683 .then(|| Utf16CodeUnits(self.start.offset).to_utf32_code_units_in(&text)),
1684 (node == &**self.end.container)
1685 .then(|| Utf16CodeUnits(self.end.offset).to_utf32_code_units_in(&text)),
1686 )
1687 }
1688
1689 fn traversal(&self) -> VisibleSelectionTraversal<'no_gc> {
1690 let start_position = position_in_flat_tree_for_selection(self.no_gc, &self.start);
1691 let end_position = position_in_flat_tree_for_selection(self.no_gc, &self.end);
1692 VisibleSelectionTraversal {
1693 following: start_position
1694 .node()
1695 .following_flat_tree_nodes_unrooted(self.no_gc),
1696 start: start_position,
1697 end: end_position,
1698 finished: false,
1699 skip_subtree: false,
1700 }
1701 }
1702}
1703
1704struct VisibleSelectionTraversal<'no_gc> {
1705 following: UnrootedFollowingFlatTreeNodesTraversal<'no_gc>,
1706 start: FlatTreeNodePosition,
1707 end: FlatTreeNodePosition,
1708 finished: bool,
1709 skip_subtree: bool,
1710}
1711
1712impl<'no_gc> Iterator for VisibleSelectionTraversal<'no_gc> {
1713 type Item = UnrootedDom<'no_gc, Node>;
1714
1715 fn next(&mut self) -> Option<Self::Item> {
1716 while !self.finished {
1717 let following = if std::mem::take(&mut self.skip_subtree) {
1718 self.following.next_skipping_subtree()?
1719 } else {
1720 self.following.next()?
1721 };
1722
1723 match following {
1724 PrePostIteration::Enter(node) => {
1725 if &**node == self.end.node() &&
1728 matches!(self.end, FlatTreeNodePosition::Before(_))
1729 {
1730 self.finished = true;
1731 break;
1732 }
1733 if &**node == self.start.node() &&
1736 matches!(self.start, FlatTreeNodePosition::After(_))
1737 {
1738 self.skip_subtree = true;
1739 }
1740 return Some(node);
1741 },
1742 PrePostIteration::Leave(node) => {
1743 self.finished = &**node == self.end.node();
1744 },
1745 }
1746 }
1747
1748 None
1749 }
1750}
1751
1752struct VisibleSelectionFlagUpdate<'no_gc> {
1753 no_gc: &'no_gc NoGC,
1754 previously_flagged_nodes: FxHashSet<UnrootedDom<'no_gc, Node>>,
1760 used_user_select_cache: FxHashMap<UnrootedDom<'no_gc, Node>, UsedUserSelect>,
1762 needs_new_display_list: bool,
1764}
1765
1766impl<'no_gc> VisibleSelectionFlagUpdate<'no_gc> {
1767 fn run(
1768 no_gc: &'no_gc NoGC,
1769 previously_flagged_nodes: FxHashSet<UnrootedDom<'no_gc, Node>>,
1770 flat_tree_selection: Option<&FlatTreeSelection<'_>>,
1771 document: &Document,
1772 ) {
1773 let mut update = Self {
1774 no_gc,
1775 previously_flagged_nodes,
1776 used_user_select_cache: Default::default(),
1777 needs_new_display_list: false,
1778 };
1779
1780 if let Some(flat_tree_selection) = flat_tree_selection {
1781 let traversal = flat_tree_selection.traversal();
1782 for ancestor in traversal
1783 .start
1784 .node()
1785 .ancestors_in_flat_tree_unrooted(no_gc)
1786 {
1787 update.set(&ancestor, flat_tree_selection);
1788 }
1789 for node in traversal {
1790 update.set(&node, flat_tree_selection);
1791 }
1792 }
1793
1794 update.finish(document);
1795 }
1796
1797 fn set(&mut self, node: &UnrootedDom<'no_gc, Node>, flat_tree_selection: &FlatTreeSelection) {
1798 if !node.get_flag(NodeFlags::OVERLAPS_DOCUMENT_SELECTION) {
1799 node.set_flag(NodeFlags::OVERLAPS_DOCUMENT_SELECTION, true);
1800 debug_assert!(!self.previously_flagged_nodes.contains(node));
1801 } else {
1802 self.previously_flagged_nodes.remove(node);
1803 }
1804
1805 let user_select = node.used_user_select(self.no_gc, &mut self.used_user_select_cache);
1810 let inhibited = user_select == UsedUserSelect::None;
1811 node.set_flag(NodeFlags::SELECTION_INHIBITED, inhibited);
1812
1813 self.set_node_selection(node, (!inhibited).then_some(flat_tree_selection));
1814 }
1815
1816 fn clear(&mut self, node: &Node) {
1817 node.set_flag(NodeFlags::OVERLAPS_DOCUMENT_SELECTION, false);
1818 node.set_flag(NodeFlags::SELECTION_INHIBITED, false);
1819 self.set_node_selection(node, None);
1820 }
1821
1822 fn set_character_data_selection(
1823 &mut self,
1824 character_data: &CharacterData,
1825 range: Option<RangeAny<Utf32CodeUnits>>,
1826 ) {
1827 if character_data.set_text_run_selection(range) {
1828 self.needs_new_display_list = true;
1829 } else {
1830 character_data
1835 .upcast::<Node>()
1836 .dirty(self.no_gc, NodeDamage::ContentOrHeritage);
1837 }
1838 }
1839
1840 fn set_node_selection(&mut self, node: &Node, flat_tree_selection: Option<&FlatTreeSelection>) {
1841 if let Some(character_data) = node.downcast::<CharacterData>() {
1842 let range = flat_tree_selection.map(|flat_tree_selection| {
1843 flat_tree_selection.range_for_character_data(character_data)
1844 });
1845 self.set_character_data_selection(character_data, range);
1846 } else if node.set_element_selection(flat_tree_selection.is_some()) {
1847 self.needs_new_display_list = true;
1848 }
1849 }
1850
1851 fn finish(mut self, document: &Document) {
1852 for node in std::mem::take(&mut self.previously_flagged_nodes) {
1853 self.clear(&node);
1854 }
1855 if self.needs_new_display_list {
1856 document.window().layout().set_needs_new_display_list();
1857 }
1858 }
1859}