aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom/range.rs
diff options
context:
space:
mode:
authorPatrick Shaughnessy <pshaughn@comcast.net>2020-01-31 21:56:36 -0500
committerPatrick Shaughnessy <pshaughn@comcast.net>2020-02-13 20:09:27 -0500
commit5ef335895138bff8288a840c39779dda760dfbec (patch)
tree4bb1a657f7a8bb3d857c030adadd85f2a0633229 /components/script/dom/range.rs
parente697e6cca70bec57b5ed9512b95c2a72359d6ca1 (diff)
downloadservo-5ef335895138bff8288a840c39779dda760dfbec.tar.gz
servo-5ef335895138bff8288a840c39779dda760dfbec.zip
Selection interface working for synthetic operations
Diffstat (limited to 'components/script/dom/range.rs')
-rw-r--r--components/script/dom/range.rs54
1 files changed, 54 insertions, 0 deletions
diff --git a/components/script/dom/range.rs b/components/script/dom/range.rs
index e9e62a9cdc0..1aabc0fc540 100644
--- a/components/script/dom/range.rs
+++ b/components/script/dom/range.rs
@@ -2,6 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
+use crate::dom::bindings::cell::DomRefCell;
use crate::dom::bindings::codegen::Bindings::CharacterDataBinding::CharacterDataMethods;
use crate::dom::bindings::codegen::Bindings::NodeBinding::NodeConstants;
use crate::dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
@@ -24,6 +25,7 @@ use crate::dom::documentfragment::DocumentFragment;
use crate::dom::element::Element;
use crate::dom::htmlscriptelement::HTMLScriptElement;
use crate::dom::node::{Node, ShadowIncluding, UnbindContext};
+use crate::dom::selection::Selection;
use crate::dom::text::Text;
use crate::dom::window::Window;
use dom_struct::dom_struct;
@@ -37,6 +39,16 @@ pub struct Range {
reflector_: Reflector,
start: BoundaryPoint,
end: BoundaryPoint,
+ // A range that belongs to a Selection needs to know about it
+ // so selectionchange can fire when the range changes.
+ // A range shouldn't belong to more than one Selection at a time,
+ // but from the spec as of Feb 1 2020 I can't rule out a corner case like:
+ // * Select a range R in document A, from node X to Y
+ // * Insert everything from X to Y into document B
+ // * Set B's selection's range to R
+ // which leaves R technically, and observably, associated with A even though
+ // it will fail the same-root-node check on many of A's selection's methods.
+ associated_selections: DomRefCell<Vec<Dom<Selection>>>,
}
impl Range {
@@ -50,6 +62,7 @@ impl Range {
reflector_: Reflector::new(),
start: BoundaryPoint::new(start_container, start_offset),
end: BoundaryPoint::new(end_container, end_offset),
+ associated_selections: DomRefCell::new(vec![]),
}
}
@@ -163,6 +176,9 @@ impl Range {
// https://dom.spec.whatwg.org/#concept-range-bp-set
fn set_start(&self, node: &Node, offset: u32) {
+ if &self.start.node != node || self.start.offset.get() != offset {
+ self.report_change();
+ }
if &self.start.node != node {
if self.start.node == self.end.node {
node.ranges().push(WeakRef::new(&self));
@@ -178,6 +194,9 @@ impl Range {
// https://dom.spec.whatwg.org/#concept-range-bp-set
fn set_end(&self, node: &Node, offset: u32) {
+ if &self.end.node != node || self.end.offset.get() != offset {
+ self.report_change();
+ }
if &self.end.node != node {
if self.end.node == self.start.node {
node.ranges().push(WeakRef::new(&self));
@@ -228,6 +247,26 @@ impl Range {
// Step 6.
Ok(Ordering::Equal)
}
+
+ pub fn associate_selection(&self, selection: &Selection) {
+ let mut selections = self.associated_selections.borrow_mut();
+ if !selections.iter().any(|s| &**s == selection) {
+ selections.push(Dom::from_ref(selection));
+ }
+ }
+
+ pub fn disassociate_selection(&self, selection: &Selection) {
+ self.associated_selections
+ .borrow_mut()
+ .retain(|s| &**s != selection);
+ }
+
+ fn report_change(&self) {
+ self.associated_selections
+ .borrow()
+ .iter()
+ .for_each(|s| s.queue_selectionchange_task());
+ }
}
impl RangeMethods for Range {
@@ -821,6 +860,9 @@ impl RangeMethods for Range {
// Step 3.
if start_node == end_node {
if let Some(text) = start_node.downcast::<CharacterData>() {
+ if end_offset > start_offset {
+ self.report_change();
+ }
return text.ReplaceData(start_offset, end_offset - start_offset, DOMString::new());
}
}
@@ -1142,9 +1184,11 @@ impl WeakRangeVec {
entry.remove();
}
if &range.start.node == child {
+ range.report_change();
range.start.set(context.parent, offset);
}
if &range.end.node == child {
+ range.report_change();
range.end.set(context.parent, offset);
}
});
@@ -1169,9 +1213,11 @@ impl WeakRangeVec {
entry.remove();
}
if &range.start.node == node {
+ range.report_change();
range.start.set(sibling, range.StartOffset() + length);
}
if &range.end.node == node {
+ range.report_change();
range.end.set(sibling, range.EndOffset() + length);
}
});
@@ -1212,9 +1258,11 @@ impl WeakRangeVec {
}
if move_start {
+ range.report_change();
range.start.set(child, new_offset);
}
if move_end {
+ range.report_change();
range.end.set(child, new_offset);
}
});
@@ -1273,9 +1321,11 @@ impl WeakRangeVec {
}
if move_start {
+ range.report_change();
range.start.set(sibling, start_offset - offset);
}
if move_end {
+ range.report_change();
range.end.set(sibling, end_offset - offset);
}
});
@@ -1289,9 +1339,11 @@ impl WeakRangeVec {
(*self.cell.get()).update(|entry| {
let range = entry.root().unwrap();
if &range.start.node == node && offset == range.StartOffset() {
+ range.report_change();
range.start.set_offset(offset + 1);
}
if &range.end.node == node && offset == range.EndOffset() {
+ range.report_change();
range.end.set_offset(offset + 1);
}
});
@@ -1304,10 +1356,12 @@ impl WeakRangeVec {
let range = entry.root().unwrap();
let start_offset = range.StartOffset();
if &range.start.node == node && start_offset > offset {
+ range.report_change();
range.start.set_offset(f(start_offset));
}
let end_offset = range.EndOffset();
if &range.end.node == node && end_offset > offset {
+ range.report_change();
range.end.set_offset(f(end_offset));
}
});