Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make ranges observe mutations on document #6639

Closed
wants to merge 7 commits into from
Closed
@@ -68,7 +68,7 @@ use std::ffi::CString;
use std::hash::{Hash, Hasher};
use std::intrinsics::return_address;
use std::ops::{Deref, DerefMut};
use std::rc::Rc;
use std::rc::{Rc, Weak};
use std::sync::Arc;
use std::sync::mpsc::{Receiver, Sender};
use string_cache::{Atom, Namespace};
@@ -136,24 +136,33 @@ pub fn trace_object(tracer: *mut JSTracer, description: &str, obj: &Heap<*mut JS
}
}

impl<T: JSTraceable> JSTraceable for RefCell<T> {
impl<T: JSTraceable + ?Sized> JSTraceable for RefCell<T> {
fn trace(&self, trc: *mut JSTracer) {
self.borrow().trace(trc)
}
}

impl<T: JSTraceable> JSTraceable for Rc<T> {
impl<T: JSTraceable + ?Sized> JSTraceable for Rc<T> {
fn trace(&self, trc: *mut JSTracer) {
(**self).trace(trc)
}
}

impl<T: JSTraceable> JSTraceable for Box<T> {
impl<T: JSTraceable + ?Sized> JSTraceable for Box<T> {
fn trace(&self, trc: *mut JSTracer) {
(**self).trace(trc)
}
}

impl<T: JSTraceable + ?Sized> JSTraceable for Weak<T> {
fn trace(&self, trc: *mut JSTracer) {
match self.upgrade() {
Some(ptr) => ptr.trace(trc),
_ => ()
}
}
}

impl<T: JSTraceable> JSTraceable for *const T {
fn trace(&self, trc: *mut JSTracer) {
if !self.is_null() {
@@ -111,7 +111,9 @@ impl<'a> CharacterDataMethods for &'a CharacterData {
data.push_str(&arg);
data.push_str(&self.data.borrow().slice_chars((offset + count) as usize, length as usize));
*self.data.borrow_mut() = data;
// FIXME: Once we have `Range`, we should implement step7 to step11

let node = NodeCast::from_ref(self);
node.owner_doc().character_data_replaced(node, offset, count, arg);
Ok(())
}

@@ -59,6 +59,7 @@ use dom::nodelist::NodeList;
use dom::nodeiterator::NodeIterator;
use dom::text::Text;
use dom::processinginstruction::ProcessingInstruction;
use dom::range::MutationObserver;
use dom::range::Range;
use dom::servohtmlparser::ServoHTMLParser;
use dom::treewalker::TreeWalker;
@@ -97,7 +98,7 @@ use std::cell::{Cell, Ref, RefMut, RefCell};
use std::default::Default;
use std::ptr;
use std::sync::mpsc::channel;
use std::rc::Rc;
use std::rc::{Rc, Weak};
use time;

#[derive(JSTraceable, PartialEq)]
@@ -149,6 +150,8 @@ pub struct Document {
current_parser: MutNullableHeap<JS<ServoHTMLParser>>,
/// When we should kick off a reflow. This happens during parsing.
reflow_timeout: Cell<Option<u64>>,
/// List of mutation observers
observers: RefCell<Vec<Weak<RefCell<MutationObserver>>>>,
}

impl PartialEq for Document {
@@ -1072,6 +1075,7 @@ impl Document {
loader: DOMRefCell::new(doc_loader),
current_parser: Default::default(),
reflow_timeout: Cell::new(None),
observers: RefCell::new(Vec::new()),
}
}

@@ -1104,6 +1108,51 @@ impl Document {
}
document
}

pub fn add_mutation_observer(&self, observer: Weak<RefCell<MutationObserver>>) {
self.observers.borrow_mut().push(observer);
}

pub fn remove_mutation_observer(&self, observer: &MutationObserver) {
/*self.observers
.borrow_mut()
.retain(|o| &&*o.upgrade().unwrap().borrow() != &observer);*/
}

pub fn character_data_replaced(&self, node: &Node, offset: u32, count: u32, data: DOMString) {
for observer in self.observers.borrow().iter() {
let observer = observer.upgrade().unwrap();
observer.borrow_mut().character_data_replaced(node, offset, count, &data);
}
}

pub fn node_inserted(&self, parent: &Node, child: &Node, index: u32, count: u32) {
for observer in self.observers.borrow().iter() {
let observer = observer.upgrade().unwrap();
observer.borrow_mut().node_inserted(parent, child, index, count);
}
}

pub fn node_removed(&self, parent: &Node, child: &Node, index: u32) {
for observer in self.observers.borrow().iter() {
let observer = observer.upgrade().unwrap();
observer.borrow_mut().node_removed(parent, child, index);
}
}

pub fn text_will_split(&self, node: &Node, parent: &Node, offset: u32, new_node: &Node) {
for observer in self.observers.borrow().iter() {
let observer = observer.upgrade().unwrap();
observer.borrow_mut().text_will_split(node, parent, offset, new_node);
}
}

pub fn text_split(&self, node: &Node, offset: u32) {
for observer in self.observers.borrow().iter() {
let observer = observer.upgrade().unwrap();
observer.borrow_mut().text_split(node, offset);
}
}
}

trait PrivateDocumentHelpers {
@@ -1663,7 +1663,18 @@ impl Node {
}

// XXX assert owner_doc
// Step 1-3: ranges.
// Step 1.
let count = match node.type_id() {
NodeTypeId::DocumentFragment => node.children().count() as u32,
_ => 1
};

// Step 2.
if let Some(child) = child {
parent.owner_doc().node_inserted(parent, child, child.index(), count);
}

// Step 3: mutation records

match node.type_id() {
NodeTypeId::DocumentFragment => {
@@ -1766,8 +1777,12 @@ impl Node {
// https://dom.spec.whatwg.org/#concept-node-remove
fn remove(node: &Node, parent: &Node, _suppress_observers: SuppressObserver) {
assert!(node.GetParentNode().map_or(false, |node_parent| node_parent.r() == parent));
// Step 1.
let index = node.index();

// Steps 2-5
parent.owner_doc().node_removed(parent, node, index);

// Step 1-5: ranges.
// Step 6-7: mutation observers.
// Step 8.
parent.remove_child(node);
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.