aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/components/main/layout/box_builder.rs10
-rw-r--r--src/components/script/dom/bindings/codegen/Document.webidl2
-rw-r--r--src/components/script/dom/bindings/node.rs5
-rw-r--r--src/components/script/dom/document.rs69
-rw-r--r--src/components/script/dom/domparser.rs24
-rw-r--r--src/components/script/dom/htmldocument.rs5
-rw-r--r--src/components/script/dom/node.rs67
-rw-r--r--src/components/script/script_task.rs2
-rw-r--r--src/test/html/content/test_parentnodes.html3
-rw-r--r--src/test/html/content/test_prototypes.html3
10 files changed, 94 insertions, 96 deletions
diff --git a/src/components/main/layout/box_builder.rs b/src/components/main/layout/box_builder.rs
index 9686ddcb6cb..cc48c8b3cf5 100644
--- a/src/components/main/layout/box_builder.rs
+++ b/src/components/main/layout/box_builder.rs
@@ -21,7 +21,7 @@ use style::computed_values::display;
use style::computed_values::float;
use layout::float_context::{FloatLeft, FloatRight};
use script::dom::node::{AbstractNode, CommentNodeTypeId, DoctypeNodeTypeId};
-use script::dom::node::{ElementNodeTypeId, LayoutView, TextNodeTypeId};
+use script::dom::node::{ElementNodeTypeId, LayoutView, TextNodeTypeId, DocumentNodeTypeId};
use script::dom::node::DocumentFragmentNodeTypeId;
use servo_util::range::Range;
use servo_util::tree::{TreeNodeRef, TreeNode};
@@ -390,6 +390,7 @@ impl LayoutTreeBuilder {
ElementNodeTypeId(_) => display::inline,
TextNodeTypeId => display::inline,
DoctypeNodeTypeId |
+ DocumentNodeTypeId(_) |
DocumentFragmentNodeTypeId |
CommentNodeTypeId => return NoGenerator,
}
@@ -430,11 +431,12 @@ impl LayoutTreeBuilder {
self.create_child_generator(node, parent_generator, Flow_Float(is_float.unwrap()))
}
- (display::block, & &BlockFlow(ref info), _) => match (info.is_root, node.parent_node().is_some()) {
+ (display::block, & &BlockFlow(ref info), _) => match (info.is_root, node.parent_node()) {
// If this is the root node, then use the root flow's
// context. Otherwise, make a child block context.
- (true, true) => self.create_child_generator(node, parent_generator, Flow_Block),
- (true, false) => { return ParentGenerator }
+ (true, Some(parent)) if !parent.is_document() =>
+ self.create_child_generator(node, parent_generator, Flow_Block),
+ (true, None) | (true, Some(_)) => { return ParentGenerator }
(false, _) => {
self.create_child_generator(node, parent_generator, Flow_Block)
}
diff --git a/src/components/script/dom/bindings/codegen/Document.webidl b/src/components/script/dom/bindings/codegen/Document.webidl
index e834b875184..ef479f01a97 100644
--- a/src/components/script/dom/bindings/codegen/Document.webidl
+++ b/src/components/script/dom/bindings/codegen/Document.webidl
@@ -24,7 +24,7 @@ enum VisibilityState { "hidden", "visible" };
/* http://dom.spec.whatwg.org/#interface-document */
[Constructor]
-interface Document /*: Node*/ { //XXXjdm Requires servo/#623
+interface Document : Node {
/*[Throws]
readonly attribute DOMImplementation implementation;*/
// readonly attribute DOMString URL;
diff --git a/src/components/script/dom/bindings/node.rs b/src/components/script/dom/bindings/node.rs
index 5adf545f14c..e2d10ec6387 100644
--- a/src/components/script/dom/bindings/node.rs
+++ b/src/components/script/dom/bindings/node.rs
@@ -3,10 +3,11 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use dom::bindings::utils::{Reflectable, Reflector, Traceable};
+use dom::document::{PlainDocumentTypeId, HTMLDocumentTypeId};
use dom::element::*;
use dom::types::*;
use dom::node::{AbstractNode, ElementNodeTypeId, TextNodeTypeId, CommentNodeTypeId};
-use dom::node::{DoctypeNodeTypeId, DocumentFragmentNodeTypeId, ScriptView};
+use dom::node::{DoctypeNodeTypeId, DocumentFragmentNodeTypeId, ScriptView, DocumentNodeTypeId};
use std::cast;
use std::libc;
@@ -95,6 +96,8 @@ pub fn create(cx: *JSContext, node: &mut AbstractNode<ScriptView>) -> *JSObject
CommentNodeTypeId => generate_element!(Comment),
DoctypeNodeTypeId => generate_element!(DocumentType),
DocumentFragmentNodeTypeId => generate_element!(DocumentFragment),
+ DocumentNodeTypeId(PlainDocumentTypeId) => generate_element!(Document),
+ DocumentNodeTypeId(HTMLDocumentTypeId) => generate_element!(HTMLDocument),
TextNodeTypeId => generate_element!(Text),
}
}
diff --git a/src/components/script/dom/document.rs b/src/components/script/dom/document.rs
index d0a40235878..ebaffd5fe78 100644
--- a/src/components/script/dom/document.rs
+++ b/src/components/script/dom/document.rs
@@ -13,14 +13,12 @@ use dom::element::{HTMLHtmlElementTypeId, HTMLHeadElementTypeId, HTMLTitleElemen
use dom::htmlcollection::HTMLCollection;
use dom::htmldocument::HTMLDocument;
use dom::htmlelement::HTMLElement;
-use dom::htmlhtmlelement::HTMLHtmlElement;
-use dom::node::{AbstractNode, ScriptView, Node, ElementNodeTypeId};
+use dom::node::{AbstractNode, ScriptView, Node, ElementNodeTypeId, DocumentNodeTypeId};
use dom::text::Text;
use dom::window::Window;
use dom::htmltitleelement::HTMLTitleElement;
use html::hubbub_html_parser::build_element_from_tag;
-use js::jsapi::{JSObject, JSContext, JSVal};
-use js::jsapi::{JSTRACE_OBJECT, JSTracer, JS_CallTracer};
+use js::jsapi::{JSObject, JSContext, JSVal, JSTracer};
use js::glue::RUST_OBJECT_TO_JSVAL;
use servo_util::tree::{TreeNodeRef, ElementLike};
@@ -29,12 +27,18 @@ use std::hashmap::HashMap;
use std::cast;
use std::ptr;
use std::str::eq_slice;
-use std::libc;
use std::ascii::StrAsciiExt;
use std::unstable::raw::Box;
+#[deriving(Eq)]
+pub enum DocumentTypeId {
+ PlainDocumentTypeId,
+ HTMLDocumentTypeId
+}
+
pub trait ReflectableDocument {
fn init_reflector(@mut self, cx: *JSContext);
+ fn init_node(@mut self, doc: AbstractDocument);
}
#[deriving(Eq)]
@@ -45,9 +49,11 @@ pub struct AbstractDocument {
impl AbstractDocument {
pub fn as_abstract<T: ReflectableDocument>(cx: *JSContext, doc: @mut T) -> AbstractDocument {
doc.init_reflector(cx);
- AbstractDocument {
+ let abstract = AbstractDocument {
document: unsafe { cast::transmute(doc) }
- }
+ };
+ doc.init_node(abstract);
+ abstract
}
pub fn document<'a>(&'a self) -> &'a Document {
@@ -91,7 +97,7 @@ impl AbstractDocument {
});
let document = self.mut_document();
- document.root = Some(root);
+ document.node.AppendChild(AbstractNode::from_document(*self), root);
// Register elements having "id" attribute to the owner doc.
document.register_nodes_with_id(&root);
document.content_changed();
@@ -105,7 +111,7 @@ pub enum DocumentType {
}
pub struct Document {
- priv root: Option<AbstractNode<ScriptView>>,
+ node: Node<ScriptView>,
reflector_: Reflector,
window: @mut Window,
doctype: DocumentType,
@@ -116,8 +122,12 @@ pub struct Document {
impl Document {
#[fixed_stack_segment]
pub fn new(window: @mut Window, doctype: DocumentType) -> Document {
+ let node_type = match doctype {
+ HTML => HTMLDocumentTypeId,
+ SVG | XML => PlainDocumentTypeId
+ };
Document {
- root: None,
+ node: Node::new_without_doc(DocumentNodeTypeId(node_type)),
reflector_: Reflector::new(),
window: window,
doctype: doctype,
@@ -128,16 +138,7 @@ impl Document {
pub fn Constructor(owner: @mut Window) -> Fallible<AbstractDocument> {
let cx = owner.get_cx();
-
- let document = AbstractDocument::as_abstract(cx, @mut Document::new(owner, XML));
-
- let root = @HTMLHtmlElement {
- htmlelement: HTMLElement::new(HTMLHtmlElementTypeId, ~"html", document)
- };
- let root = unsafe { Node::as_abstract_node(cx, root) };
- document.set_root(root);
-
- Ok(document)
+ Ok(AbstractDocument::as_abstract(cx, @mut Document::new(owner, XML)))
}
}
@@ -145,6 +146,11 @@ impl ReflectableDocument for Document {
fn init_reflector(@mut self, cx: *JSContext) {
self.wrap_object_shared(cx, ptr::null()); //XXXjdm a proper scope would be nice
}
+
+ fn init_node(@mut self, doc: AbstractDocument) {
+ self.node.set_owner_doc(doc);
+ self.node.add_to_doc(AbstractNode::from_document(doc), doc);
+ }
}
impl Reflectable for AbstractDocument {
@@ -184,11 +190,11 @@ impl DerivedWrapper for AbstractDocument {
impl Reflectable for Document {
fn reflector<'a>(&'a self) -> &'a Reflector {
- &self.reflector_
+ self.node.reflector()
}
fn mut_reflector<'a>(&'a mut self) -> &'a mut Reflector {
- &mut self.reflector_
+ self.node.mut_reflector()
}
fn wrap_object_shared(@mut self, cx: *JSContext, scope: *JSObject) -> *JSObject {
@@ -202,7 +208,7 @@ impl Reflectable for Document {
impl Document {
pub fn GetDocumentElement(&self) -> Option<AbstractNode<ScriptView>> {
- self.root
+ self.node.first_child
}
fn get_cx(&self) -> *JSContext {
@@ -408,21 +414,6 @@ fn foreach_ided_elements(root: &AbstractNode<ScriptView>,
impl Traceable for Document {
#[fixed_stack_segment]
fn trace(&self, tracer: *mut JSTracer) {
- match self.root {
- None => {},
- Some(root) => {
- unsafe {
- (*tracer).debugPrinter = ptr::null();
- (*tracer).debugPrintIndex = -1;
- do "root".to_c_str().with_ref |name| {
- (*tracer).debugPrintArg = name as *libc::c_void;
- debug!("tracing root node");
- JS_CallTracer(tracer as *JSTracer,
- root.reflector().get_jsobject(),
- JSTRACE_OBJECT as u32);
- }
- }
- }
- }
+ self.node.trace(tracer);
}
}
diff --git a/src/components/script/dom/domparser.rs b/src/components/script/dom/domparser.rs
index cc3db3e07a7..a29cdfb32ff 100644
--- a/src/components/script/dom/domparser.rs
+++ b/src/components/script/dom/domparser.rs
@@ -4,13 +4,9 @@
use dom::bindings::codegen::DOMParserBinding;
use dom::bindings::codegen::DOMParserBinding::SupportedTypeValues::{Text_html, Text_xml};
-use dom::bindings::utils::{DOMString, Fallible, Reflector, Reflectable};
+use dom::bindings::utils::{DOMString, Fallible, Reflector, Reflectable, FailureUnknown};
use dom::document::{AbstractDocument, Document, XML};
-use dom::element::HTMLHtmlElementTypeId;
use dom::htmldocument::HTMLDocument;
-use dom::htmlelement::HTMLElement;
-use dom::htmlhtmlelement::HTMLHtmlElement;
-use dom::node::Node;
use dom::window::Window;
pub struct DOMParser {
@@ -41,25 +37,17 @@ impl DOMParser {
ty: DOMParserBinding::SupportedType)
-> Fallible<AbstractDocument> {
let cx = self.owner.get_cx();
- let document = match ty {
+ match ty {
Text_html => {
- HTMLDocument::new(self.owner)
+ Ok(HTMLDocument::new(self.owner))
}
Text_xml => {
- AbstractDocument::as_abstract(cx, @mut Document::new(self.owner, XML))
+ Ok(AbstractDocument::as_abstract(cx, @mut Document::new(self.owner, XML)))
}
_ => {
- fail!("unsupported document type")
+ Err(FailureUnknown)
}
- };
-
- let root = @HTMLHtmlElement {
- htmlelement: HTMLElement::new(HTMLHtmlElementTypeId, ~"html", document)
- };
- let root = unsafe { Node::as_abstract_node(cx, root) };
- document.set_root(root);
-
- Ok(document)
+ }
}
}
diff --git a/src/components/script/dom/htmldocument.rs b/src/components/script/dom/htmldocument.rs
index cadba01ce97..d4ac4fa0e52 100644
--- a/src/components/script/dom/htmldocument.rs
+++ b/src/components/script/dom/htmldocument.rs
@@ -35,6 +35,11 @@ impl ReflectableDocument for HTMLDocument {
fn init_reflector(@mut self, cx: *JSContext) {
self.wrap_object_shared(cx, ptr::null()); //XXXjdm a proper scope would be nice
}
+
+ fn init_node(@mut self, doc: AbstractDocument) {
+ self.parent.node.set_owner_doc(doc);
+ self.parent.node.add_to_doc(AbstractNode::from_document(doc), doc);
+ }
}
impl HTMLDocument {
diff --git a/src/components/script/dom/node.rs b/src/components/script/dom/node.rs
index 9b8f7ea1b07..857fc94fd48 100644
--- a/src/components/script/dom/node.rs
+++ b/src/components/script/dom/node.rs
@@ -9,7 +9,7 @@ use dom::bindings::utils::{Reflectable, Reflector};
use dom::bindings::utils::{DOMString, null_str_as_empty};
use dom::bindings::utils::{ErrorResult, Fallible, NotFound, HierarchyRequest};
use dom::characterdata::CharacterData;
-use dom::document::AbstractDocument;
+use dom::document::{AbstractDocument, DocumentTypeId};
use dom::documenttype::DocumentType;
use dom::element::{Element, ElementTypeId, HTMLImageElementTypeId, HTMLIframeElementTypeId};
use dom::element::{HTMLStyleElementTypeId};
@@ -88,7 +88,7 @@ pub struct Node<View> {
prev_sibling: Option<AbstractNode<View>>,
/// The document that this node belongs to.
- priv owner_doc: AbstractDocument,
+ priv owner_doc: Option<AbstractDocument>,
/// The live list of children return by .childNodes.
child_list: Option<@mut NodeList>,
@@ -103,6 +103,7 @@ pub enum NodeTypeId {
DoctypeNodeTypeId,
DocumentFragmentNodeTypeId,
CommentNodeTypeId,
+ DocumentNodeTypeId(DocumentTypeId),
ElementNodeTypeId(ElementTypeId),
TextNodeTypeId,
}
@@ -200,6 +201,13 @@ impl<'self, View> AbstractNode<View> {
}
}
+ /// Allow consumers to upcast from derived classes.
+ pub fn from_document(doc: AbstractDocument) -> AbstractNode<View> {
+ unsafe {
+ cast::transmute(doc)
+ }
+ }
+
// Convenience accessors
/// Returns the type ID of this node. Fails if this node is borrowed mutably.
@@ -327,6 +335,13 @@ impl<'self, View> AbstractNode<View> {
self.transmute_mut(f)
}
+ pub fn is_document(self) -> bool {
+ match self.type_id() {
+ DocumentNodeTypeId(*) => true,
+ _ => false
+ }
+ }
+
// FIXME: This should be doing dynamic borrow checking for safety.
pub fn with_imm_element<R>(self, f: &fn(&Element) -> R) -> R {
if !self.is_element() {
@@ -463,11 +478,11 @@ impl<View> Iterator<AbstractNode<View>> for AbstractNodeChildrenIterator<View> {
impl<View> Node<View> {
pub fn owner_doc(&self) -> AbstractDocument {
- self.owner_doc
+ self.owner_doc.unwrap()
}
pub fn set_owner_doc(&mut self, document: AbstractDocument) {
- self.owner_doc = document;
+ self.owner_doc = Some(document);
}
}
@@ -508,6 +523,14 @@ impl Node<ScriptView> {
}
pub fn new(type_id: NodeTypeId, doc: AbstractDocument) -> Node<ScriptView> {
+ Node::new_(type_id, Some(doc))
+ }
+
+ pub fn new_without_doc(type_id: NodeTypeId) -> Node<ScriptView> {
+ Node::new_(type_id, None)
+ }
+
+ fn new_(type_id: NodeTypeId, doc: Option<AbstractDocument>) -> Node<ScriptView> {
Node {
reflector_: Reflector::new(),
type_id: type_id,
@@ -526,24 +549,6 @@ impl Node<ScriptView> {
layout_data: LayoutData::new(),
}
}
-
- pub fn getNextSibling(&mut self) -> Option<&mut AbstractNode<ScriptView>> {
- match self.next_sibling {
- // transmute because the compiler can't deduce that the reference
- // is safe outside of with_mut_base blocks.
- Some(ref mut n) => Some(unsafe { cast::transmute(n) }),
- None => None
- }
- }
-
- pub fn getFirstChild(&mut self) -> Option<&mut AbstractNode<ScriptView>> {
- match self.first_child {
- // transmute because the compiler can't deduce that the reference
- // is safe outside of with_mut_base blocks.
- Some(ref mut n) => Some(unsafe { cast::transmute(n) }),
- None => None
- }
- }
}
impl Node<ScriptView> {
@@ -552,6 +557,7 @@ impl Node<ScriptView> {
ElementNodeTypeId(_) => 1,
TextNodeTypeId => 3,
CommentNodeTypeId => 8,
+ DocumentNodeTypeId(_)=> 9,
DoctypeNodeTypeId => 10,
DocumentFragmentNodeTypeId => 11,
}
@@ -572,6 +578,7 @@ impl Node<ScriptView> {
}
},
DocumentFragmentNodeTypeId => ~"#document-fragment",
+ DocumentNodeTypeId(_) => ~"#document"
})
}
@@ -586,7 +593,7 @@ impl Node<ScriptView> {
TextNodeTypeId |
DoctypeNodeTypeId |
DocumentFragmentNodeTypeId => Some(self.owner_doc()),
- // DocumentNodeTypeId => None
+ DocumentNodeTypeId(_) => None
}
}
@@ -655,7 +662,7 @@ impl Node<ScriptView> {
characterdata.Data()
}
}
- DoctypeNodeTypeId => {
+ DoctypeNodeTypeId | DocumentNodeTypeId(_) => {
None
}
}
@@ -717,7 +724,7 @@ impl Node<ScriptView> {
document.document().content_changed();
}
}
- DoctypeNodeTypeId => {}
+ DoctypeNodeTypeId | DocumentNodeTypeId(_) => {}
}
Ok(())
}
@@ -739,10 +746,9 @@ impl Node<ScriptView> {
if new_child.is_doctype() {
return true;
}
- if !this_node.is_element() {
- // FIXME: This should also work for Document and DocumentFragments when they inherit from node.
- // per jgraham
- return true;
+ match this_node.type_id() {
+ DocumentNodeTypeId(*) | ElementNodeTypeId(*) => (),
+ _ => return true
}
if this_node == new_child {
return true;
@@ -793,7 +799,8 @@ impl Node<ScriptView> {
// Unregister elements having "id' from the owner doc.
// This need be called before target nodes are removed from tree.
- self.owner_doc.mut_document().unregister_nodes_with_id(&abstract_self);
+ let owner_doc = self.owner_doc();
+ owner_doc.mut_document().unregister_nodes_with_id(&abstract_self);
abstract_self.remove_child(node);
// Signal the document that it needs to update its display.
diff --git a/src/components/script/script_task.rs b/src/components/script/script_task.rs
index e710dfb6d95..b17449ab0ba 100644
--- a/src/components/script/script_task.rs
+++ b/src/components/script/script_task.rs
@@ -274,7 +274,7 @@ impl Page {
/// This function fails if there is no root frame.
fn reflow(&mut self, goal: ReflowGoal, script_chan: ScriptChan, compositor: @ScriptListener) {
let root = match self.frame {
- None => fail!(~"Tried to relayout with no root frame!"),
+ None => return,
Some(ref frame) => {
frame.document.document().GetDocumentElement()
}
diff --git a/src/test/html/content/test_parentnodes.html b/src/test/html/content/test_parentnodes.html
index b45d5de011d..0b1bb610414 100644
--- a/src/test/html/content/test_parentnodes.html
+++ b/src/test/html/content/test_parentnodes.html
@@ -6,8 +6,7 @@
<body>
<div id="div1"></div>
<script>
- // FIXME: This should be HTMLDocument.
- //isnot(document.documentElement.parentNode, null);
+ is_a(document.documentElement.parentNode, HTMLDocument);
is(document.documentElement.parentElement, null);
var elem = document.createElement("p");
diff --git a/src/test/html/content/test_prototypes.html b/src/test/html/content/test_prototypes.html
index 61835bd750e..11ee11242b5 100644
--- a/src/test/html/content/test_prototypes.html
+++ b/src/test/html/content/test_prototypes.html
@@ -5,6 +5,9 @@
<body>
<foo-á>foo</foo-á>
<script>
+gc(); // ensure that our document rooting works; subsequent accesses should be valid.
+is_a(window.document, Node);
+is(window.document.nodeType, Node.DOCUMENT_NODE);
is_a(window.document.documentElement, Node);
is_a(window.document.documentElement, Element);
is_a(window.document.documentElement, HTMLElement);