aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom/node.rs
diff options
context:
space:
mode:
authorbors-servo <metajack+bors@gmail.com>2015-07-30 04:13:39 -0600
committerbors-servo <metajack+bors@gmail.com>2015-07-30 04:13:39 -0600
commit5873a5cf20b3db0fce59980b2a6b0b7b9da1e737 (patch)
tree33c06b6758d1c71dfc926479514ed7d354340462 /components/script/dom/node.rs
parent9e8d231196693a660a1e70d535d1c3ab290ddf39 (diff)
parent8cfccda542ea8db60e260c29a6a1c7a79340d80b (diff)
downloadservo-5873a5cf20b3db0fce59980b2a6b0b7b9da1e737.tar.gz
servo-5873a5cf20b3db0fce59980b2a6b0b7b9da1e737.zip
Auto merge of #6800 - frewsxcv:childnode-before-childnode-after, r=Ms2ger
Implement ChildNode::before & ChildNode::after 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. <!-- Reviewable:start --> [<img src="https://reviewable.io/review_button.png" height=40 alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/servo/6800) <!-- Reviewable:end -->
Diffstat (limited to 'components/script/dom/node.rs')
-rw-r--r--components/script/dom/node.rs89
1 files changed, 59 insertions, 30 deletions
diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs
index 5df4d633f32..1f6a681e582 100644
--- a/components/script/dom/node.rs
+++ b/components/script/dom/node.rs
@@ -802,40 +802,54 @@ impl<'a> NodeHelpers for &'a Node {
// https://dom.spec.whatwg.org/#dom-childnode-before
fn before(self, nodes: Vec<NodeOrString>) -> ErrorResult {
- match self.parent_node.get() {
- None => {
- // Step 1.
- Ok(())
- },
- Some(ref parent_node) => {
- // Step 2.
- let doc = self.owner_doc();
- let node = try!(doc.r().node_from_nodes_and_strings(nodes));
- // Step 3.
- Node::pre_insert(node.r(), parent_node.root().r(),
- Some(self)).map(|_| ())
- },
- }
+ // Step 1.
+ let parent = &self.parent_node;
+
+ // Step 2.
+ let parent = match parent.get() {
+ None => return Ok(()),
+ Some(ref parent) => parent.root(),
+ };
+
+ // Step 3.
+ let viable_previous_sibling = first_node_not_in(self.preceding_siblings(), &nodes);
+
+ // 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
fn after(self, nodes: Vec<NodeOrString>) -> ErrorResult {
- match self.parent_node.get() {
- None => {
- // Step 1.
- Ok(())
- },
- Some(ref parent_node) => {
- // Step 2.
- let doc = self.owner_doc();
- let node = try!(doc.r().node_from_nodes_and_strings(nodes));
- // Step 3.
- // FIXME(https://github.com/servo/servo/issues/5720)
- let next_sibling = self.next_sibling.get().map(Root::from_rooted);
- Node::pre_insert(node.r(), parent_node.root().r(),
- next_sibling.r()).map(|_| ())
- },
- }
+ // Step 1.
+ let parent = &self.parent_node;
+
+ // Step 2.
+ let parent = match parent.get() {
+ None => return Ok(()),
+ Some(ref parent) => parent.root(),
+ };
+
+ // Step 3.
+ let viable_next_sibling = first_node_not_in(self.following_siblings(), &nodes);
+
+ // Step 4.
+ 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
@@ -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,
/// returns it.
#[allow(unsafe_code)]