зеркало из https://github.com/mozilla/gecko-dev.git
servo: Merge #6800 - Implement ChildNode::before & ChildNode::after (from frewsxcv:childnode-before-childnode-after); r=Ms2ger
Continued from #6536 The current implementations of `ChildNode::before` and `ChildNode::after` do not match the WHATWG spec. This commit updates the implementations to match the spec. Our current implementation of `ChildNode::after` passes all the WPT tests. So I made sure to add a regression test that failed with the current implementation. There are a few other unit tests I added to exhaust other corner cases I encountered. Source-Repo: https://github.com/servo/servo Source-Revision: 5873a5cf20b3db0fce59980b2a6b0b7b9da1e737
This commit is contained in:
Родитель
cd7cafe51e
Коммит
30a3893160
|
@ -802,40 +802,54 @@ impl<'a> NodeHelpers for &'a Node {
|
||||||
|
|
||||||
// https://dom.spec.whatwg.org/#dom-childnode-before
|
// https://dom.spec.whatwg.org/#dom-childnode-before
|
||||||
fn before(self, nodes: Vec<NodeOrString>) -> ErrorResult {
|
fn before(self, nodes: Vec<NodeOrString>) -> ErrorResult {
|
||||||
match self.parent_node.get() {
|
|
||||||
None => {
|
|
||||||
// Step 1.
|
// Step 1.
|
||||||
Ok(())
|
let parent = &self.parent_node;
|
||||||
},
|
|
||||||
Some(ref parent_node) => {
|
|
||||||
// Step 2.
|
// Step 2.
|
||||||
let doc = self.owner_doc();
|
let parent = match parent.get() {
|
||||||
let node = try!(doc.r().node_from_nodes_and_strings(nodes));
|
None => return Ok(()),
|
||||||
|
Some(ref parent) => parent.root(),
|
||||||
|
};
|
||||||
|
|
||||||
// Step 3.
|
// Step 3.
|
||||||
Node::pre_insert(node.r(), parent_node.root().r(),
|
let viable_previous_sibling = first_node_not_in(self.preceding_siblings(), &nodes);
|
||||||
Some(self)).map(|_| ())
|
|
||||||
},
|
// Step 4.
|
||||||
}
|
let node = try!(self.owner_doc().node_from_nodes_and_strings(nodes));
|
||||||
|
|
||||||
|
// Step 5.
|
||||||
|
let viable_previous_sibling = match viable_previous_sibling {
|
||||||
|
Some(ref viable_previous_sibling) => viable_previous_sibling.next_sibling.get(),
|
||||||
|
None => parent.first_child.get(),
|
||||||
|
}.map(|s| s.root());
|
||||||
|
|
||||||
|
// Step 6.
|
||||||
|
try!(Node::pre_insert(&node, &parent, viable_previous_sibling.r()));
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://dom.spec.whatwg.org/#dom-childnode-after
|
// https://dom.spec.whatwg.org/#dom-childnode-after
|
||||||
fn after(self, nodes: Vec<NodeOrString>) -> ErrorResult {
|
fn after(self, nodes: Vec<NodeOrString>) -> ErrorResult {
|
||||||
match self.parent_node.get() {
|
|
||||||
None => {
|
|
||||||
// Step 1.
|
// Step 1.
|
||||||
Ok(())
|
let parent = &self.parent_node;
|
||||||
},
|
|
||||||
Some(ref parent_node) => {
|
|
||||||
// Step 2.
|
// Step 2.
|
||||||
let doc = self.owner_doc();
|
let parent = match parent.get() {
|
||||||
let node = try!(doc.r().node_from_nodes_and_strings(nodes));
|
None => return Ok(()),
|
||||||
|
Some(ref parent) => parent.root(),
|
||||||
|
};
|
||||||
|
|
||||||
// Step 3.
|
// Step 3.
|
||||||
// FIXME(https://github.com/servo/servo/issues/5720)
|
let viable_next_sibling = first_node_not_in(self.following_siblings(), &nodes);
|
||||||
let next_sibling = self.next_sibling.get().map(Root::from_rooted);
|
|
||||||
Node::pre_insert(node.r(), parent_node.root().r(),
|
// Step 4.
|
||||||
next_sibling.r()).map(|_| ())
|
let node = try!(self.owner_doc().node_from_nodes_and_strings(nodes));
|
||||||
},
|
|
||||||
}
|
// Step 5.
|
||||||
|
try!(Node::pre_insert(&node, &parent, viable_next_sibling.r()));
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://dom.spec.whatwg.org/#dom-childnode-replacewith
|
// https://dom.spec.whatwg.org/#dom-childnode-replacewith
|
||||||
|
@ -1028,6 +1042,21 @@ impl<'a> NodeHelpers for &'a Node {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Iterate through `nodes` until we find a `Node` that is not in `not_in`
|
||||||
|
fn first_node_not_in<I>(mut nodes: I, not_in: &[NodeOrString]) -> Option<Root<Node>>
|
||||||
|
where I: Iterator<Item=Root<Node>>
|
||||||
|
{
|
||||||
|
nodes.find(|node| {
|
||||||
|
not_in.iter().all(|n| {
|
||||||
|
match n {
|
||||||
|
&NodeOrString::eNode(ref n) => n != node,
|
||||||
|
_ => true,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/// If the given untrusted node address represents a valid DOM node in the given runtime,
|
/// If the given untrusted node address represents a valid DOM node in the given runtime,
|
||||||
/// returns it.
|
/// returns it.
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
|
|
Загрузка…
Ссылка в новой задаче