mirror of
https://github.com/servo/servo.git
synced 2025-08-05 05:30:08 +01:00
Implement Document's 'body' attribute
Implement Document's 'body' attribute (getter and setter). Proper implementation of setter requires Node::ReplaceChild(), which is currently a stub and will be done on a later step. This patch is for: https://github.com/mozilla/servo/issues/1428
This commit is contained in:
parent
824c7ac613
commit
ce434dfb3e
5 changed files with 140 additions and 3 deletions
|
@ -156,6 +156,7 @@ DOMInterfaces = {
|
||||||
'createElement',
|
'createElement',
|
||||||
'createTextNode',
|
'createTextNode',
|
||||||
'title',
|
'title',
|
||||||
|
'body',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -100,7 +100,7 @@ partial interface Document {
|
||||||
[SetterThrows]
|
[SetterThrows]
|
||||||
attribute DOMString title;
|
attribute DOMString title;
|
||||||
// attribute DOMString dir;
|
// attribute DOMString dir;
|
||||||
//(HTML only) attribute HTMLElement? body;
|
attribute HTMLElement? body;
|
||||||
//(HTML only)readonly attribute HTMLHeadElement? head;
|
//(HTML only)readonly attribute HTMLHeadElement? head;
|
||||||
//(HTML only)readonly attribute HTMLCollection images;
|
//(HTML only)readonly attribute HTMLCollection images;
|
||||||
//(HTML only)readonly attribute HTMLCollection embeds;
|
//(HTML only)readonly attribute HTMLCollection embeds;
|
||||||
|
|
|
@ -5,12 +5,12 @@
|
||||||
use dom::comment::Comment;
|
use dom::comment::Comment;
|
||||||
use dom::bindings::codegen::DocumentBinding;
|
use dom::bindings::codegen::DocumentBinding;
|
||||||
use dom::bindings::utils::{Reflectable, Reflector, Traceable, reflect_dom_object};
|
use dom::bindings::utils::{Reflectable, Reflector, Traceable, reflect_dom_object};
|
||||||
use dom::bindings::utils::{ErrorResult, Fallible, NotSupported, InvalidCharacter};
|
use dom::bindings::utils::{ErrorResult, Fallible, NotSupported, InvalidCharacter, HierarchyRequest};
|
||||||
use dom::bindings::utils::DOMString;
|
use dom::bindings::utils::DOMString;
|
||||||
use dom::bindings::utils::{xml_name_type, InvalidXMLName};
|
use dom::bindings::utils::{xml_name_type, InvalidXMLName};
|
||||||
use dom::documentfragment::DocumentFragment;
|
use dom::documentfragment::DocumentFragment;
|
||||||
use dom::element::{Element};
|
use dom::element::{Element};
|
||||||
use dom::element::{HTMLHeadElementTypeId, HTMLTitleElementTypeId};
|
use dom::element::{HTMLHtmlElementTypeId, HTMLHeadElementTypeId, HTMLTitleElementTypeId, HTMLBodyElementTypeId, HTMLFrameSetElementTypeId};
|
||||||
use dom::event::{AbstractEvent, Event};
|
use dom::event::{AbstractEvent, Event};
|
||||||
use dom::htmlcollection::HTMLCollection;
|
use dom::htmlcollection::HTMLCollection;
|
||||||
use dom::htmldocument::HTMLDocument;
|
use dom::htmldocument::HTMLDocument;
|
||||||
|
@ -295,6 +295,63 @@ impl Document {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_html_element(&self) -> Option<AbstractNode> {
|
||||||
|
do self.GetDocumentElement().filtered |root| {
|
||||||
|
match root.type_id() {
|
||||||
|
ElementNodeTypeId(HTMLHtmlElementTypeId) => true,
|
||||||
|
_ => false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn GetBody(&self, _: AbstractDocument) -> Option<AbstractNode> {
|
||||||
|
match self.get_html_element() {
|
||||||
|
None => None,
|
||||||
|
Some(root) => {
|
||||||
|
do root.children().find |child| {
|
||||||
|
match child.type_id() {
|
||||||
|
ElementNodeTypeId(HTMLBodyElementTypeId) |
|
||||||
|
ElementNodeTypeId(HTMLFrameSetElementTypeId) => true,
|
||||||
|
_ => false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://www.whatwg.org/specs/web-apps/current-work/#dom-document-body
|
||||||
|
pub fn SetBody(&self, abstract_self: AbstractDocument, new_body: Option<AbstractNode>) -> ErrorResult {
|
||||||
|
// Step 1.
|
||||||
|
match new_body {
|
||||||
|
Some(node) => {
|
||||||
|
match node.type_id() {
|
||||||
|
ElementNodeTypeId(HTMLBodyElementTypeId) | ElementNodeTypeId(HTMLFrameSetElementTypeId) => {}
|
||||||
|
_ => return Err(HierarchyRequest)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => return Err(HierarchyRequest)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 2.
|
||||||
|
let old_body: Option<AbstractNode> = self.GetBody(abstract_self);
|
||||||
|
if old_body == new_body {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 3.
|
||||||
|
match self.get_html_element() {
|
||||||
|
// Step 4.
|
||||||
|
None => return Err(HierarchyRequest),
|
||||||
|
Some(root) => {
|
||||||
|
match old_body {
|
||||||
|
Some(child) => { root.ReplaceChild(new_body.unwrap(), child); }
|
||||||
|
None => { root.AppendChild(new_body.unwrap()); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn GetElementsByName(&self, name: DOMString) -> @mut HTMLCollection {
|
pub fn GetElementsByName(&self, name: DOMString) -> @mut HTMLCollection {
|
||||||
self.createHTMLCollection(|elem|
|
self.createHTMLCollection(|elem|
|
||||||
elem.get_attr(None, "name").is_some() && eq_slice(elem.get_attr(None, "name").unwrap(), name))
|
elem.get_attr(None, "name").is_some() && eq_slice(elem.get_attr(None, "name").unwrap(), name))
|
||||||
|
|
|
@ -496,6 +496,10 @@ impl AbstractNode {
|
||||||
self.node().AppendChild(self, node)
|
self.node().AppendChild(self, node)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn ReplaceChild(self, node: AbstractNode, child: AbstractNode) -> Fallible<AbstractNode> {
|
||||||
|
self.mut_node().ReplaceChild(node, child)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn RemoveChild(self, node: AbstractNode) -> Fallible<AbstractNode> {
|
pub fn RemoveChild(self, node: AbstractNode) -> Fallible<AbstractNode> {
|
||||||
self.node().RemoveChild(self, node)
|
self.node().RemoveChild(self, node)
|
||||||
}
|
}
|
||||||
|
|
75
src/test/html/content/test_document_body.html
Normal file
75
src/test/html/content/test_document_body.html
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<script src="harness.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<script>
|
||||||
|
// test1: existing document's body
|
||||||
|
{
|
||||||
|
isnot(document.body, null, "test1-0, existing document's body");
|
||||||
|
is_a(document.body, HTMLBodyElement, "test1-1, exising document's body");
|
||||||
|
is(document.body && document.body.tagName, "BODY", "test1-2, existing document's body");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: Depends on https://github.com/mozilla/servo/issues/1430
|
||||||
|
// test2: replace document's body with new body
|
||||||
|
{
|
||||||
|
let new_body = document.createElement("body");
|
||||||
|
isnot(new_body, null, "test2-0, replace document's body with new body");
|
||||||
|
document.body = new_body;
|
||||||
|
is(new_body, document.body, "test2-1, replace document's body with new body");
|
||||||
|
}
|
||||||
|
|
||||||
|
// test3: replace document's body with new frameset
|
||||||
|
{
|
||||||
|
let new_frameset = document.createElement("frameset");
|
||||||
|
isnot(new_frameset, null, "test2-0, replace document's body with new frameset");
|
||||||
|
document.body = new_frameset;
|
||||||
|
is(new_frameset, document.body, "test2-1, replace document's body with new frameset");
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// test4: append an invalid element to a new document
|
||||||
|
{
|
||||||
|
let new_document = new Document();
|
||||||
|
new_document.appendChild(new_document.createElement("html"));
|
||||||
|
let new_div = new_document.createElement("div");
|
||||||
|
|
||||||
|
isnot(new_div, null, "test4-0, append an invalid element to a new document");
|
||||||
|
|
||||||
|
new_document.body = new_div;
|
||||||
|
is(new_document.body, null, "test4-1, append an invalid element to a new document");
|
||||||
|
}
|
||||||
|
|
||||||
|
// test5: append body to a new document
|
||||||
|
{
|
||||||
|
let new_document = new Document();
|
||||||
|
new_document.appendChild(new_document.createElement("html"));
|
||||||
|
let new_body = new_document.createElement("body");
|
||||||
|
|
||||||
|
isnot(new_body, null, "test5-0, append body to a new document");
|
||||||
|
is_a(new_body, HTMLBodyElement, "test5-1, append body to a new document");
|
||||||
|
is(new_body && new_body.tagName, "BODY", "test5-2, append body to a new document");
|
||||||
|
|
||||||
|
new_document.body = new_body;
|
||||||
|
is(new_document.body, new_body, "test5-3, append body to a new document");
|
||||||
|
}
|
||||||
|
|
||||||
|
// test6: append frameset to a new document
|
||||||
|
{
|
||||||
|
let new_document = new Document();
|
||||||
|
new_document.appendChild(new_document.createElement("html"));
|
||||||
|
let new_frameset = new_document.createElement("frameset");
|
||||||
|
|
||||||
|
isnot(new_frameset, null, "test6-0, append frameset to a new document");
|
||||||
|
is_a(new_frameset, HTMLFrameSetElement, "test6-1, append frameset to a new document");
|
||||||
|
is(new_frameset && new_frameset.tagName, "FRAMESET", "test6-2, append frameset to a new document");
|
||||||
|
|
||||||
|
new_document.body = new_frameset;
|
||||||
|
is(new_document.body, new_frameset, "test6-3, append frameset to a new document");
|
||||||
|
}
|
||||||
|
|
||||||
|
finish();
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Add table
Add a link
Reference in a new issue