auto merge of #1932 : brunoabinader/servo/document-import-adopt-node, r=Ms2ger

Specs:
http://dom.spec.whatwg.org/#dom-document-importnode
http://dom.spec.whatwg.org/#dom-document-adoptnode
This commit is contained in:
bors-servo 2014-03-26 10:55:40 -04:00
commit 3d4e157faa
6 changed files with 110 additions and 17 deletions

View file

@ -26,6 +26,7 @@ DOMInterfaces = {
'Console': {}, 'Console': {},
'Document': { 'Document': {
'needsAbstract': [ 'needsAbstract': [
'adoptNode',
'anchors', 'anchors',
'applets', 'applets',
'body', 'body',
@ -40,6 +41,7 @@ DOMInterfaces = {
'getElementsByTagName', 'getElementsByTagName',
'getElementsByTagNameNS', 'getElementsByTagNameNS',
'images', 'images',
'importNode',
'links', 'links',
'plugins', 'plugins',
'scripts', 'scripts',

View file

@ -28,6 +28,7 @@ use dom::htmlhtmlelement::HTMLHtmlElement;
use dom::htmltitleelement::HTMLTitleElement; use dom::htmltitleelement::HTMLTitleElement;
use dom::mouseevent::MouseEvent; use dom::mouseevent::MouseEvent;
use dom::node::{Node, ElementNodeTypeId, DocumentNodeTypeId, NodeHelpers, INode}; use dom::node::{Node, ElementNodeTypeId, DocumentNodeTypeId, NodeHelpers, INode};
use dom::node::{CloneChildren, DoNotCloneChildren};
use dom::text::Text; use dom::text::Text;
use dom::processinginstruction::ProcessingInstruction; use dom::processinginstruction::ProcessingInstruction;
use dom::uievent::UIEvent; use dom::uievent::UIEvent;
@ -294,6 +295,37 @@ impl Document {
Ok(ProcessingInstruction::new(target, data, abstract_self)) Ok(ProcessingInstruction::new(target, data, abstract_self))
} }
// http://dom.spec.whatwg.org/#dom-document-importnode
pub fn ImportNode(&self, abstract_self: &JS<Document>, node: &JS<Node>, deep: bool) -> Fallible<JS<Node>> {
// Step 1.
if node.is_document() {
return Err(NotSupported);
}
// Step 2.
let clone_children = match deep {
true => CloneChildren,
false => DoNotCloneChildren
};
Ok(Node::clone(node, Some(abstract_self), clone_children))
}
// http://dom.spec.whatwg.org/#dom-document-adoptnode
pub fn AdoptNode(&self, abstract_self: &JS<Document>, node: &JS<Node>) -> Fallible<JS<Node>> {
// Step 1.
if node.is_document() {
return Err(NotSupported);
}
// Step 2.
let mut adoptee = node.clone();
Node::adopt(&mut adoptee, abstract_self);
// Step 3.
Ok(adoptee)
}
// http://dom.spec.whatwg.org/#dom-document-createevent // http://dom.spec.whatwg.org/#dom-document-createevent
pub fn CreateEvent(&self, interface: DOMString) -> Fallible<JS<Event>> { pub fn CreateEvent(&self, interface: DOMString) -> Fallible<JS<Event>> {
match interface.as_slice() { match interface.as_slice() {

View file

@ -728,7 +728,8 @@ fn gather_abstract_nodes(cur: &JS<Node>, refs: &mut ~[JS<Node>], postorder: bool
} }
/// Specifies whether children must be recursively cloned or not. /// Specifies whether children must be recursively cloned or not.
enum CloneChildrenFlag { #[deriving(Eq)]
pub enum CloneChildrenFlag {
CloneChildren, CloneChildren,
DoNotCloneChildren DoNotCloneChildren
} }
@ -1016,7 +1017,7 @@ impl Node {
} }
// http://dom.spec.whatwg.org/#concept-node-adopt // http://dom.spec.whatwg.org/#concept-node-adopt
fn adopt(node: &mut JS<Node>, document: &JS<Document>) { pub fn adopt(node: &mut JS<Node>, document: &JS<Document>) {
// Step 1. // Step 1.
match node.parent_node() { match node.parent_node() {
Some(ref mut parent) => Node::remove(node, parent, Unsuppressed), Some(ref mut parent) => Node::remove(node, parent, Unsuppressed),
@ -1287,18 +1288,8 @@ impl Node {
} }
// http://dom.spec.whatwg.org/#concept-node-clone // http://dom.spec.whatwg.org/#concept-node-clone
fn clone(node: &JS<Node>, maybe_doc: Option<&JS<Document>>, clone_children: CloneChildrenFlag) pub fn clone(node: &JS<Node>, maybe_doc: Option<&JS<Document>>,
-> JS<Node> { clone_children: CloneChildrenFlag) -> JS<Node> {
fn clone_recursively(node: &JS<Node>, copy: &mut JS<Node>, doc: &JS<Document>) {
for ref child in node.get().children() {
let mut cloned = Node::clone(child, Some(doc), DoNotCloneChildren);
match Node::pre_insert(&mut cloned, copy, None) {
Ok(ref mut appended) => clone_recursively(child, appended, doc),
Err(..) => fail!("an error occurred while appending children")
}
}
}
// Step 1. // Step 1.
let mut document = match maybe_doc { let mut document = match maybe_doc {
Some(doc) => doc.clone(), Some(doc) => doc.clone(),
@ -1395,9 +1386,11 @@ impl Node {
// Step 5: cloning steps. // Step 5: cloning steps.
// Step 6. // Step 6.
match clone_children { if clone_children == CloneChildren {
CloneChildren => clone_recursively(node, &mut copy, &document), for ref child in node.get().children() {
DoNotCloneChildren => () let mut child_copy = Node::clone(child, Some(&document), clone_children);
let _inserted_node = Node::pre_insert(&mut child_copy, &mut copy, None);
}
} }
// Step 7. // Step 7.

View file

@ -36,6 +36,11 @@ interface Document : Node {
[Creator, Throws] [Creator, Throws]
ProcessingInstruction createProcessingInstruction(DOMString target, DOMString data); ProcessingInstruction createProcessingInstruction(DOMString target, DOMString data);
[Throws]
Node importNode(Node node, optional boolean deep = false);
[Throws]
Node adoptNode(Node node);
[Creator, Throws] [Creator, Throws]
Event createEvent(DOMString interface_); Event createEvent(DOMString interface_);
}; };

View file

@ -0,0 +1,25 @@
<!DOCTYPE html>
<html>
<head>
<script src="harness.js"></script>
<script>
let foo = document.getElementById("foo");
let doc = document.implementation.createHTMLDocument("title");
is(foo.ownerDocument, document);
let adopted_foo = doc.adoptNode(foo);
is(document.getElementById("foo"), null);
is(foo, adopted_foo);
is(foo.ownerDocument, doc);
is(foo.parentNode, null);
is(foo.childNodes.length, 1);
finish();
</script>
</head>
<body>
<div id="foo"><div id="bar"></div></div>
</body>
</html>

View file

@ -0,0 +1,36 @@
<!DOCTYPE html>
<html>
<head>
<script src="harness.js"></script>
<script>
let doc = document.implementation.createHTMLDocument("title");
is_not(doc, null);
let foo = document.getElementById("foo");
is(foo.ownerDocument, document);
let imported_foo = doc.importNode(foo); // deep = false
is(imported_foo.parentNode, null);
is(imported_foo.ownerDocument, doc);
is(imported_foo.childNodes.length, 0);
imported_foo = doc.importNode(foo, true);
is(imported_foo.parentNode, null);
is(imported_foo.ownerDocument, doc);
is(imported_foo.childNodes.length, 1);
let bar = document.createElement("div");
bar.appendChild(document.createElement("div"));
imported_bar = doc.importNode(bar, true);
is(imported_bar.parentNode, null);
is(imported_bar.ownerDocument, doc);
is(imported_bar.childNodes.length, 1);
finish();
</script>
</head>
<body>
<div id="foo"><div id="bar"></div></div>
</body>
</html>