Implement Node.isEqualNode

Spec:
http://dom.spec.whatwg.org/#dom-node-isequalnode

Closes #1645.
This commit is contained in:
Bruno de Oliveira Abinader 2014-02-09 04:21:51 -04:00
parent f26cdcf235
commit 4d4495b015
4 changed files with 123 additions and 3 deletions

View file

@ -325,6 +325,7 @@ DOMInterfaces = {
'textContent',
'childNodes',
'contains',
'isEqualNode',
]
},

View file

@ -1540,8 +1540,88 @@ impl Node {
fail!("stub")
}
pub fn IsEqualNode(&self, _node: Option<AbstractNode>) -> bool {
false
// http://dom.spec.whatwg.org/#dom-node-isequalnode
pub fn IsEqualNode(&self, abstract_self: AbstractNode, maybe_node: Option<AbstractNode>) -> bool {
fn is_equal_doctype(node: AbstractNode, other: AbstractNode) -> bool {
node.with_imm_doctype(|doctype| {
other.with_imm_doctype(|other_doctype| {
(doctype.name == other_doctype.name) &&
(doctype.public_id == other_doctype.public_id) &&
(doctype.system_id == other_doctype.system_id)
})
})
}
fn is_equal_element(node: AbstractNode, other: AbstractNode) -> bool {
node.with_imm_element(|element| {
other.with_imm_element(|other_element| {
// FIXME: namespace prefix
(element.namespace == other_element.namespace) &&
(element.tag_name == other_element.tag_name) &&
(element.attrs.len() == other_element.attrs.len())
})
})
}
fn is_equal_processinginstruction(node: AbstractNode, other: AbstractNode) -> bool {
node.with_imm_processing_instruction(|pi| {
other.with_imm_processing_instruction(|other_pi| {
(pi.target == other_pi.target) &&
(pi.element.data == other_pi.element.data)
})
})
}
fn is_equal_characterdata(node: AbstractNode, other: AbstractNode) -> bool {
node.with_imm_characterdata(|characterdata| {
other.with_imm_characterdata(|other_characterdata| {
characterdata.data == other_characterdata.data
})
})
}
fn is_equal_element_attrs(node: AbstractNode, other: AbstractNode) -> bool {
node.with_imm_element(|element| {
other.with_imm_element(|other_element| {
assert!(element.attrs.len() == other_element.attrs.len());
element.attrs.iter().all(|attr| {
other_element.attrs.iter().any(|other_attr| {
(attr.namespace == other_attr.namespace) &&
(attr.local_name == other_attr.local_name) &&
(attr.value == other_attr.value)
})
})
})
})
}
fn is_equal_node(this: AbstractNode, node: AbstractNode) -> bool {
// Step 2.
if this.type_id() != node.type_id() {
return false;
}
match node.type_id() {
// Step 3.
DoctypeNodeTypeId if !is_equal_doctype(this, node) => return false,
ElementNodeTypeId(..) if !is_equal_element(this, node) => return false,
ProcessingInstructionNodeTypeId if !is_equal_processinginstruction(this, node) => return false,
TextNodeTypeId |
CommentNodeTypeId if !is_equal_characterdata(this, node) => return false,
// Step 4.
ElementNodeTypeId(..) if !is_equal_element_attrs(this, node) => return false,
_ => ()
}
// Step 5.
if this.children().len() != node.children().len() {
return false;
}
// Step 6.
this.children().zip(node.children()).all(|(child, other_child)| is_equal_node(child, other_child))
}
match maybe_node {
// Step 1.
None => false,
// Step 2-6.
Some(node) => is_equal_node(abstract_self, node)
}
}
pub fn CompareDocumentPosition(&self, _other: AbstractNode) -> u16 {

View file

@ -69,7 +69,7 @@ interface Node : EventTarget {
[Throws]
Node cloneNode(optional boolean deep = true);
// boolean isEqualNode(Node? node); //XXXjdm we don't deal well with Node? parameters
boolean isEqualNode(Node? node);
const unsigned short DOCUMENT_POSITION_DISCONNECTED = 0x01;
const unsigned short DOCUMENT_POSITION_PRECEDING = 0x02;

View file

@ -0,0 +1,39 @@
<!DOCTYPE html>
<html>
<head>
<script src="harness.js"></script>
<script>
// test1: simple checks
{
var elem = document.createElement("div");
var other = document.createElement("div");
is(elem.isEqualNode(elem), true);
is(elem.isEqualNode(other), true);
is(other.isEqualNode(elem), true);
is(elem.isEqualNode(document), false);
}
// test2: non-element children
{
var parent_elem = document.createElement("div");
var child_elem = document.createElement("div");
parent_elem.appendChild(child_elem);
var other_parent = document.createElement("div");
var other_child = document.createElement("div");
other_parent.appendChild(other_child);
is(parent_elem.isEqualNode(other_parent), true);
is(child_elem.isEqualNode(other_child), true);
var child_text = document.createTextNode("lorem ipsum");
child_elem.appendChild(child_text);
is(parent_elem.isEqualNode(other_parent), false);
is(child_elem.isEqualNode(other_child), false);
}
finish();
</script>
</head>
</html>