Implement Range#insertNode

This commit is contained in:
David Zbarsky 2015-07-06 05:03:20 -04:00
parent 2947d78e4e
commit c2664e52dd
5 changed files with 172 additions and 3319 deletions

View file

@ -1501,9 +1501,10 @@ impl Node {
// If node is an element, it is _affected by a base URL change_.
}
// https://dom.spec.whatwg.org/#concept-node-pre-insert
fn pre_insert(node: &Node, parent: &Node, child: Option<&Node>)
-> Fallible<Root<Node>> {
// https://dom.spec.whatwg.org/#concept-node-ensure-pre-insertion-validity
pub fn ensure_pre_insertion_validity(node: &Node,
parent: &Node,
child: Option<&Node>) -> ErrorResult {
// Step 1.
match parent.type_id() {
NodeTypeId::Document |
@ -1544,78 +1545,83 @@ impl Node {
}
// Step 6.
match parent.type_id() {
NodeTypeId::Document => {
match node.type_id() {
// Step 6.1
NodeTypeId::DocumentFragment => {
// Step 6.1.1(b)
if node.children()
.any(|c| c.r().is_text())
{
return Err(HierarchyRequest);
}
match node.child_elements().count() {
0 => (),
// Step 6.1.2
1 => {
if !parent.child_elements().is_empty() {
return Err(HierarchyRequest);
}
if let Some(child) = child {
if child.inclusively_following_siblings()
.any(|child| child.r().is_doctype()) {
return Err(HierarchyRequest);
}
}
},
// Step 6.1.1(a)
_ => return Err(HierarchyRequest),
}
},
// Step 6.2
NodeTypeId::Element(_) => {
if !parent.child_elements().is_empty() {
return Err(HierarchyRequest);
}
if let Some(ref child) = child {
if child.inclusively_following_siblings()
.any(|child| child.r().is_doctype()) {
return Err(HierarchyRequest);
if parent.type_id() == NodeTypeId::Document {
match node.type_id() {
// Step 6.1
NodeTypeId::DocumentFragment => {
// Step 6.1.1(b)
if node.children()
.any(|c| c.r().is_text())
{
return Err(HierarchyRequest);
}
match node.child_elements().count() {
0 => (),
// Step 6.1.2
1 => {
if !parent.child_elements().is_empty() {
return Err(HierarchyRequest);
}
}
},
// Step 6.3
NodeTypeId::DocumentType => {
if parent.children()
.any(|c| c.r().is_doctype())
{
return Err(HierarchyRequest);
}
match child {
Some(child) => {
if parent.children()
.take_while(|c| c.r() != child)
.any(|c| c.r().is_element())
{
return Err(HierarchyRequest);
if let Some(child) = child {
if child.inclusively_following_siblings()
.any(|child| child.r().is_doctype()) {
return Err(HierarchyRequest);
}
},
None => {
if !parent.child_elements().is_empty() {
return Err(HierarchyRequest);
}
},
}
},
// Step 6.1.1(a)
_ => return Err(HierarchyRequest),
}
},
// Step 6.2
NodeTypeId::Element(_) => {
if !parent.child_elements().is_empty() {
return Err(HierarchyRequest);
}
if let Some(ref child) = child {
if child.inclusively_following_siblings()
.any(|child| child.r().is_doctype()) {
return Err(HierarchyRequest);
}
},
NodeTypeId::CharacterData(_) => (),
NodeTypeId::Document => unreachable!(),
}
},
_ => (),
}
},
// Step 6.3
NodeTypeId::DocumentType => {
if parent.children()
.any(|c| c.r().is_doctype())
{
return Err(HierarchyRequest);
}
match child {
Some(child) => {
if parent.children()
.take_while(|c| c.r() != child)
.any(|c| c.r().is_element())
{
return Err(HierarchyRequest);
}
},
None => {
if !parent.child_elements().is_empty() {
return Err(HierarchyRequest);
}
},
}
},
NodeTypeId::CharacterData(_) => (),
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 = match child {
Some(child) if child == node => {
@ -1625,14 +1631,14 @@ impl Node {
_ => child
};
// Step 9.
// Step 4.
let document = document_from_node(parent);
Node::adopt(node, document.r());
// Step 10.
// Step 5.
Node::insert(node, parent, reference_child, SuppressObserver::Unsuppressed);
// Step 11.
// Step 6.
return Ok(Root::from_ref(node))
}