mirror of
https://github.com/servo/servo.git
synced 2025-06-20 23:28:59 +01:00
Auto merge of #6568 - dzbarsky:delete_range, r=jdm
Implement Range#insertNode Gecko doesn't really follow the spec but it seems to throw a HierarchyRequest error when parent is null. Any ideas who I should talk to about fixing the spec to account for the null checks? <!-- Reviewable:start --> [<img src="https://reviewable.io/review_button.png" height=40 alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/servo/6568) <!-- Reviewable:end -->
This commit is contained in:
commit
acf47a02cf
5 changed files with 172 additions and 3319 deletions
|
@ -1495,9 +1495,10 @@ impl Node {
|
||||||
// If node is an element, it is _affected by a base URL change_.
|
// If node is an element, it is _affected by a base URL change_.
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://dom.spec.whatwg.org/#concept-node-pre-insert
|
// https://dom.spec.whatwg.org/#concept-node-ensure-pre-insertion-validity
|
||||||
fn pre_insert(node: &Node, parent: &Node, child: Option<&Node>)
|
pub fn ensure_pre_insertion_validity(node: &Node,
|
||||||
-> Fallible<Root<Node>> {
|
parent: &Node,
|
||||||
|
child: Option<&Node>) -> ErrorResult {
|
||||||
// Step 1.
|
// Step 1.
|
||||||
match parent.type_id() {
|
match parent.type_id() {
|
||||||
NodeTypeId::Document |
|
NodeTypeId::Document |
|
||||||
|
@ -1538,8 +1539,7 @@ impl Node {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 6.
|
// Step 6.
|
||||||
match parent.type_id() {
|
if parent.type_id() == NodeTypeId::Document {
|
||||||
NodeTypeId::Document => {
|
|
||||||
match node.type_id() {
|
match node.type_id() {
|
||||||
// Step 6.1
|
// Step 6.1
|
||||||
NodeTypeId::DocumentFragment => {
|
NodeTypeId::DocumentFragment => {
|
||||||
|
@ -1605,11 +1605,17 @@ impl Node {
|
||||||
NodeTypeId::CharacterData(_) => (),
|
NodeTypeId::CharacterData(_) => (),
|
||||||
NodeTypeId::Document => unreachable!(),
|
NodeTypeId::Document => unreachable!(),
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
_ => (),
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 7-8.
|
// https://dom.spec.whatwg.org/#concept-node-pre-insert
|
||||||
|
pub fn pre_insert(node: &Node, parent: &Node, child: Option<&Node>)
|
||||||
|
-> Fallible<Root<Node>> {
|
||||||
|
// Step 1.
|
||||||
|
try!(Node::ensure_pre_insertion_validity(node, parent, child));
|
||||||
|
|
||||||
|
// Steps 2-3.
|
||||||
let reference_child_root;
|
let reference_child_root;
|
||||||
let reference_child = match child {
|
let reference_child = match child {
|
||||||
Some(child) if child == node => {
|
Some(child) if child == node => {
|
||||||
|
@ -1619,14 +1625,14 @@ impl Node {
|
||||||
_ => child
|
_ => child
|
||||||
};
|
};
|
||||||
|
|
||||||
// Step 9.
|
// Step 4.
|
||||||
let document = document_from_node(parent);
|
let document = document_from_node(parent);
|
||||||
Node::adopt(node, document.r());
|
Node::adopt(node, document.r());
|
||||||
|
|
||||||
// Step 10.
|
// Step 5.
|
||||||
Node::insert(node, parent, reference_child, SuppressObserver::Unsuppressed);
|
Node::insert(node, parent, reference_child, SuppressObserver::Unsuppressed);
|
||||||
|
|
||||||
// Step 11.
|
// Step 6.
|
||||||
return Ok(Root::from_ref(node))
|
return Ok(Root::from_ref(node))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,17 +4,20 @@
|
||||||
|
|
||||||
use dom::bindings::codegen::Bindings::NodeBinding::NodeConstants;
|
use dom::bindings::codegen::Bindings::NodeBinding::NodeConstants;
|
||||||
use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
|
use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
|
||||||
|
use dom::bindings::codegen::Bindings::NodeListBinding::NodeListMethods;
|
||||||
use dom::bindings::codegen::Bindings::RangeBinding::{self, RangeConstants};
|
use dom::bindings::codegen::Bindings::RangeBinding::{self, RangeConstants};
|
||||||
use dom::bindings::codegen::Bindings::RangeBinding::RangeMethods;
|
use dom::bindings::codegen::Bindings::RangeBinding::RangeMethods;
|
||||||
|
use dom::bindings::codegen::Bindings::TextBinding::TextMethods;
|
||||||
use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
|
use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
|
||||||
use dom::bindings::codegen::InheritTypes::NodeCast;
|
use dom::bindings::codegen::InheritTypes::{NodeCast, TextCast};
|
||||||
use dom::bindings::error::{Error, ErrorResult, Fallible};
|
use dom::bindings::error::{Error, ErrorResult, Fallible};
|
||||||
|
use dom::bindings::error::Error::HierarchyRequest;
|
||||||
use dom::bindings::global::GlobalRef;
|
use dom::bindings::global::GlobalRef;
|
||||||
use dom::bindings::js::{JS, Root};
|
use dom::bindings::js::{JS, Root, RootedReference};
|
||||||
use dom::bindings::utils::{Reflector, reflect_dom_object};
|
use dom::bindings::utils::{Reflector, reflect_dom_object};
|
||||||
|
use dom::characterdata::CharacterDataTypeId;
|
||||||
use dom::document::{Document, DocumentHelpers};
|
use dom::document::{Document, DocumentHelpers};
|
||||||
use dom::node::{Node, NodeHelpers};
|
use dom::node::{Node, NodeHelpers, NodeTypeId};
|
||||||
|
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::cmp::{Ord, Ordering, PartialEq, PartialOrd};
|
use std::cmp::{Ord, Ordering, PartialEq, PartialOrd};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
@ -288,6 +291,90 @@ impl<'a> RangeMethods for &'a Range {
|
||||||
fn Detach(self) {
|
fn Detach(self) {
|
||||||
// This method intentionally left blank.
|
// This method intentionally left blank.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://dom.spec.whatwg.org/#dom-range-insertnode
|
||||||
|
// https://dom.spec.whatwg.org/#concept-range-insert
|
||||||
|
fn InsertNode(self, node: &Node) -> ErrorResult {
|
||||||
|
let (start_node, start_offset) = {
|
||||||
|
let inner = self.inner().borrow();
|
||||||
|
let start = &inner.start;
|
||||||
|
(start.node(), start.offset())
|
||||||
|
};
|
||||||
|
|
||||||
|
// Step 1.
|
||||||
|
match start_node.type_id() {
|
||||||
|
// Handled under step 2.
|
||||||
|
NodeTypeId::CharacterData(CharacterDataTypeId::Text) => (),
|
||||||
|
NodeTypeId::CharacterData(_) => return Err(HierarchyRequest),
|
||||||
|
_ => ()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 2.
|
||||||
|
let (reference_node, parent) =
|
||||||
|
if start_node.type_id() == NodeTypeId::CharacterData(CharacterDataTypeId::Text) {
|
||||||
|
// Step 3.
|
||||||
|
let parent = match start_node.GetParentNode() {
|
||||||
|
Some(parent) => parent,
|
||||||
|
// Step 1.
|
||||||
|
None => return Err(HierarchyRequest)
|
||||||
|
};
|
||||||
|
// Step 5.
|
||||||
|
(Some(Root::from_ref(start_node.r())), parent)
|
||||||
|
} else {
|
||||||
|
// Steps 4-5.
|
||||||
|
let child = start_node.ChildNodes().Item(start_offset);
|
||||||
|
(child, Root::from_ref(start_node.r()))
|
||||||
|
};
|
||||||
|
|
||||||
|
// Step 6.
|
||||||
|
try!(Node::ensure_pre_insertion_validity(node,
|
||||||
|
parent.r(),
|
||||||
|
reference_node.r()));
|
||||||
|
|
||||||
|
// Step 7.
|
||||||
|
let split_text;
|
||||||
|
let reference_node =
|
||||||
|
match TextCast::to_ref(start_node.r()) {
|
||||||
|
Some(text) => {
|
||||||
|
split_text = try!(text.SplitText(start_offset));
|
||||||
|
let new_reference = NodeCast::from_root(split_text);
|
||||||
|
assert!(new_reference.GetParentNode().r() == Some(parent.r()));
|
||||||
|
Some(new_reference)
|
||||||
|
},
|
||||||
|
_ => reference_node
|
||||||
|
};
|
||||||
|
|
||||||
|
// Step 8.
|
||||||
|
let reference_node = if Some(node) == reference_node.r() {
|
||||||
|
node.GetNextSibling()
|
||||||
|
} else {
|
||||||
|
reference_node
|
||||||
|
};
|
||||||
|
|
||||||
|
// Step 9.
|
||||||
|
node.remove_self();
|
||||||
|
|
||||||
|
// Step 10.
|
||||||
|
let new_offset =
|
||||||
|
reference_node.r().map_or(parent.len(), |node| node.index());
|
||||||
|
|
||||||
|
// Step 11
|
||||||
|
let new_offset = new_offset + if node.type_id() == NodeTypeId::DocumentFragment {
|
||||||
|
node.len()
|
||||||
|
} else {
|
||||||
|
1
|
||||||
|
};
|
||||||
|
|
||||||
|
// Step 12.
|
||||||
|
try!(Node::pre_insert(node, parent.r(), reference_node.r()));
|
||||||
|
|
||||||
|
// Step 13.
|
||||||
|
if self.Collapsed() {
|
||||||
|
self.inner().borrow_mut().set_end(parent.r(), new_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(JSTraceable)]
|
#[derive(JSTraceable)]
|
||||||
|
|
|
@ -48,8 +48,8 @@ interface Range {
|
||||||
// DocumentFragment extractContents();
|
// DocumentFragment extractContents();
|
||||||
// [NewObject, Throws]
|
// [NewObject, Throws]
|
||||||
// DocumentFragment cloneContents();
|
// DocumentFragment cloneContents();
|
||||||
// [Throws]
|
[Throws]
|
||||||
// void insertNode(Node node);
|
void insertNode(Node node);
|
||||||
// [Throws]
|
// [Throws]
|
||||||
// void surroundContents(Node newParent);
|
// void surroundContents(Node newParent);
|
||||||
|
|
||||||
|
|
|
@ -252,9 +252,6 @@
|
||||||
[Range interface: operation cloneContents()]
|
[Range interface: operation cloneContents()]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[Range interface: operation insertNode(Node)]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Range interface: operation surroundContents(Node)]
|
[Range interface: operation surroundContents(Node)]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -270,12 +267,6 @@
|
||||||
[Range interface: document.createRange() must inherit property "cloneContents" with the proper type (22)]
|
[Range interface: document.createRange() must inherit property "cloneContents" with the proper type (22)]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[Range interface: document.createRange() must inherit property "insertNode" with the proper type (23)]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Range interface: calling insertNode(Node) on document.createRange() with too few arguments must throw TypeError]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Range interface: document.createRange() must inherit property "surroundContents" with the proper type (24)]
|
[Range interface: document.createRange() must inherit property "surroundContents" with the proper type (24)]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -291,12 +282,6 @@
|
||||||
[Range interface: detachedRange must inherit property "cloneContents" with the proper type (22)]
|
[Range interface: detachedRange must inherit property "cloneContents" with the proper type (22)]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[Range interface: detachedRange must inherit property "insertNode" with the proper type (23)]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Range interface: calling insertNode(Node) on detachedRange with too few arguments must throw TypeError]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Range interface: detachedRange must inherit property "surroundContents" with the proper type (24)]
|
[Range interface: detachedRange must inherit property "surroundContents" with the proper type (24)]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue