Skip to content

Commit

Permalink
Selection interface working for synthetic operations
Browse files Browse the repository at this point in the history
  • Loading branch information
pshaughn committed Feb 14, 2020
1 parent e697e6c commit 5ef3358
Show file tree
Hide file tree
Showing 30 changed files with 812 additions and 8,468 deletions.
1 change: 1 addition & 0 deletions components/atoms/static_atoms.txt
Expand Up @@ -109,6 +109,7 @@ seeked
seeking
select
selectend
selectionchange
selectstart
serif
signalingstatechange
Expand Down
18 changes: 18 additions & 0 deletions components/script/dom/document.rs
Expand Up @@ -79,6 +79,7 @@ use crate::dom::pagetransitionevent::PageTransitionEvent;
use crate::dom::processinginstruction::ProcessingInstruction;
use crate::dom::promise::Promise;
use crate::dom::range::Range;
use crate::dom::selection::Selection;
use crate::dom::servoparser::ServoParser;
use crate::dom::shadowroot::ShadowRoot;
use crate::dom::storageevent::StorageEvent;
Expand Down Expand Up @@ -398,6 +399,8 @@ pub struct Document {
/// https://html.spec.whatwg.org/multipage/#concept-document-csp-list
#[ignore_malloc_size_of = "Defined in rust-content-security-policy"]
csp_list: DomRefCell<Option<CspList>>,
/// https://w3c.github.io/slection-api/#dfn-selection
selection: MutNullableDom<Selection>,
}

#[derive(JSTraceable, MallocSizeOf)]
Expand Down Expand Up @@ -2816,6 +2819,7 @@ impl Document {
media_controls: DomRefCell::new(HashMap::new()),
dirty_webgl_contexts: DomRefCell::new(HashMap::new()),
csp_list: DomRefCell::new(None),
selection: MutNullableDom::new(None),
}
}

Expand Down Expand Up @@ -4481,6 +4485,11 @@ impl DocumentMethods for Document {
// TODO: https://github.com/servo/servo/issues/21936
Node::replace_all(None, self.upcast::<Node>());

// Specs and tests are in a state of flux about whether
// we want to clear the selection when we remove the contents;
// WPT selection/Document-open.html wants us to not clear it
// as of Feb 1 2020

// Step 12
if self.is_fully_active() {
let mut new_url = entry_responsible_document.url();
Expand Down Expand Up @@ -4653,6 +4662,15 @@ impl DocumentMethods for Document {
None => Err(Error::InvalidAccess),
}
}

// https://w3c.github.io/selection-api/#dom-document-getselection
fn GetSelection(&self) -> Option<DomRoot<Selection>> {
if self.has_browsing_context {
Some(self.selection.or_init(|| Selection::new(self)))
} else {
None
}
}
}

fn update_with_current_time_ms(marker: &Cell<u64>) {
Expand Down
2 changes: 2 additions & 0 deletions components/script/dom/macros.rs
Expand Up @@ -488,6 +488,8 @@ macro_rules! global_event_handlers(
event_handler!(seeked, GetOnseeked, SetOnseeked);
event_handler!(seeking, GetOnseeking, SetOnseeking);
event_handler!(select, GetOnselect, SetOnselect);
event_handler!(selectionchange, GetOnselectionchange, SetOnselectionchange);
event_handler!(selectstart, GetOnselectstart, SetOnselectstart);
event_handler!(show, GetOnshow, SetOnshow);
event_handler!(stalled, GetOnstalled, SetOnstalled);
event_handler!(submit, GetOnsubmit, SetOnsubmit);
Expand Down
1 change: 1 addition & 0 deletions components/script/dom/mod.rs
Expand Up @@ -477,6 +477,7 @@ pub mod rtcpeerconnectioniceevent;
pub mod rtcsessiondescription;
pub mod rtctrackevent;
pub mod screen;
pub mod selection;
pub mod serviceworker;
pub mod serviceworkercontainer;
pub mod serviceworkerglobalscope;
Expand Down
54 changes: 54 additions & 0 deletions components/script/dom/range.rs
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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 {
Expand All @@ -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![]),
}
}

Expand Down Expand Up @@ -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));
Expand All @@ -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));
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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());
}
}
Expand Down Expand Up @@ -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);
}
});
Expand All @@ -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);
}
});
Expand Down Expand Up @@ -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);
}
});
Expand Down Expand Up @@ -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);
}
});
Expand All @@ -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);
}
});
Expand All @@ -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));
}
});
Expand Down

0 comments on commit 5ef3358

Please sign in to comment.