diff --git a/src/components/main/layout/box_builder.rs b/src/components/main/layout/box_builder.rs index cc48c8b3cf5..9686ddcb6cb 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, DocumentNodeTypeId}; +use script::dom::node::{ElementNodeTypeId, LayoutView, TextNodeTypeId}; use script::dom::node::DocumentFragmentNodeTypeId; use servo_util::range::Range; use servo_util::tree::{TreeNodeRef, TreeNode}; @@ -390,7 +390,6 @@ impl LayoutTreeBuilder { ElementNodeTypeId(_) => display::inline, TextNodeTypeId => display::inline, DoctypeNodeTypeId | - DocumentNodeTypeId(_) | DocumentFragmentNodeTypeId | CommentNodeTypeId => return NoGenerator, } @@ -431,12 +430,11 @@ 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()) { + (display::block, & &BlockFlow(ref info), _) => match (info.is_root, node.parent_node().is_some()) { // If this is the root node, then use the root flow's // context. Otherwise, make a child block context. - (true, Some(parent)) if !parent.is_document() => - self.create_child_generator(node, parent_generator, Flow_Block), - (true, None) | (true, Some(_)) => { return ParentGenerator } + (true, true) => self.create_child_generator(node, parent_generator, Flow_Block), + (true, false) => { 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 ef479f01a97..e834b875184 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 { +interface Document /*: Node*/ { //XXXjdm Requires servo/#623 /*[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 e2d10ec6387..5adf545f14c 100644 --- a/src/components/script/dom/bindings/node.rs +++ b/src/components/script/dom/bindings/node.rs @@ -3,11 +3,10 @@ * 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, DocumentNodeTypeId}; +use dom::node::{DoctypeNodeTypeId, DocumentFragmentNodeTypeId, ScriptView}; use std::cast; use std::libc; @@ -96,8 +95,6 @@ pub fn create(cx: *JSContext, node: &mut AbstractNode) -> *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 ebaffd5fe78..d0a40235878 100644 --- a/src/components/script/dom/document.rs +++ b/src/components/script/dom/document.rs @@ -13,12 +13,14 @@ use dom::element::{HTMLHtmlElementTypeId, HTMLHeadElementTypeId, HTMLTitleElemen use dom::htmlcollection::HTMLCollection; use dom::htmldocument::HTMLDocument; use dom::htmlelement::HTMLElement; -use dom::node::{AbstractNode, ScriptView, Node, ElementNodeTypeId, DocumentNodeTypeId}; +use dom::htmlhtmlelement::HTMLHtmlElement; +use dom::node::{AbstractNode, ScriptView, Node, ElementNodeTypeId}; 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, JSTracer}; +use js::jsapi::{JSObject, JSContext, JSVal}; +use js::jsapi::{JSTRACE_OBJECT, JSTracer, JS_CallTracer}; use js::glue::RUST_OBJECT_TO_JSVAL; use servo_util::tree::{TreeNodeRef, ElementLike}; @@ -27,18 +29,12 @@ 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)] @@ -49,11 +45,9 @@ pub struct AbstractDocument { impl AbstractDocument { pub fn as_abstract(cx: *JSContext, doc: @mut T) -> AbstractDocument { doc.init_reflector(cx); - let abstract = AbstractDocument { + AbstractDocument { document: unsafe { cast::transmute(doc) } - }; - doc.init_node(abstract); - abstract + } } pub fn document<'a>(&'a self) -> &'a Document { @@ -97,7 +91,7 @@ impl AbstractDocument { }); let document = self.mut_document(); - document.node.AppendChild(AbstractNode::from_document(*self), root); + document.root = Some(root); // Register elements having "id" attribute to the owner doc. document.register_nodes_with_id(&root); document.content_changed(); @@ -111,7 +105,7 @@ pub enum DocumentType { } pub struct Document { - node: Node, + priv root: Option>, reflector_: Reflector, window: @mut Window, doctype: DocumentType, @@ -122,12 +116,8 @@ 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 { - node: Node::new_without_doc(DocumentNodeTypeId(node_type)), + root: None, reflector_: Reflector::new(), window: window, doctype: doctype, @@ -138,7 +128,16 @@ impl Document { pub fn Constructor(owner: @mut Window) -> Fallible { let cx = owner.get_cx(); - Ok(AbstractDocument::as_abstract(cx, @mut Document::new(owner, XML))) + + 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) } } @@ -146,11 +145,6 @@ 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 { @@ -190,11 +184,11 @@ impl DerivedWrapper for AbstractDocument { impl Reflectable for Document { fn reflector<'a>(&'a self) -> &'a Reflector { - self.node.reflector() + &self.reflector_ } fn mut_reflector<'a>(&'a mut self) -> &'a mut Reflector { - self.node.mut_reflector() + &mut self.reflector_ } fn wrap_object_shared(@mut self, cx: *JSContext, scope: *JSObject) -> *JSObject { @@ -208,7 +202,7 @@ impl Reflectable for Document { impl Document { pub fn GetDocumentElement(&self) -> Option> { - self.node.first_child + self.root } fn get_cx(&self) -> *JSContext { @@ -414,6 +408,21 @@ fn foreach_ided_elements(root: &AbstractNode, impl Traceable for Document { #[fixed_stack_segment] fn trace(&self, tracer: *mut JSTracer) { - self.node.trace(tracer); + 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); + } + } + } + } } } diff --git a/src/components/script/dom/domparser.rs b/src/components/script/dom/domparser.rs index ea9666c7c1d..7cc5b8cbb6b 100644 --- a/src/components/script/dom/domparser.rs +++ b/src/components/script/dom/domparser.rs @@ -4,9 +4,13 @@ use dom::bindings::codegen::DOMParserBinding; use dom::bindings::codegen::DOMParserBinding::SupportedTypeValues::{Text_html, Text_xml}; -use dom::bindings::utils::{DOMString, Fallible, Reflector, Reflectable, FailureUnknown, reflect_dom_object}; +use dom::bindings::utils::{DOMString, Fallible, Reflector, Reflectable, reflect_dom_object}; 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; use js::jsapi::{JSContext, JSObject}; @@ -38,17 +42,25 @@ impl DOMParser { ty: DOMParserBinding::SupportedType) -> Fallible { let cx = self.owner.get_cx(); - match ty { + let document = match ty { Text_html => { - Ok(HTMLDocument::new(self.owner)) + HTMLDocument::new(self.owner) } Text_xml => { - Ok(AbstractDocument::as_abstract(cx, @mut Document::new(self.owner, XML))) + AbstractDocument::as_abstract(cx, @mut Document::new(self.owner, XML)) } _ => { - Err(FailureUnknown) + fail!("unsupported document type") } - } + }; + + 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 d4ac4fa0e52..cadba01ce97 100644 --- a/src/components/script/dom/htmldocument.rs +++ b/src/components/script/dom/htmldocument.rs @@ -35,11 +35,6 @@ 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 857fc94fd48..9b8f7ea1b07 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, DocumentTypeId}; +use dom::document::AbstractDocument; use dom::documenttype::DocumentType; use dom::element::{Element, ElementTypeId, HTMLImageElementTypeId, HTMLIframeElementTypeId}; use dom::element::{HTMLStyleElementTypeId}; @@ -88,7 +88,7 @@ pub struct Node { prev_sibling: Option>, /// The document that this node belongs to. - priv owner_doc: Option, + priv owner_doc: AbstractDocument, /// The live list of children return by .childNodes. child_list: Option<@mut NodeList>, @@ -103,7 +103,6 @@ pub enum NodeTypeId { DoctypeNodeTypeId, DocumentFragmentNodeTypeId, CommentNodeTypeId, - DocumentNodeTypeId(DocumentTypeId), ElementNodeTypeId(ElementTypeId), TextNodeTypeId, } @@ -201,13 +200,6 @@ impl<'self, View> AbstractNode { } } - /// Allow consumers to upcast from derived classes. - pub fn from_document(doc: AbstractDocument) -> AbstractNode { - unsafe { - cast::transmute(doc) - } - } - // Convenience accessors /// Returns the type ID of this node. Fails if this node is borrowed mutably. @@ -335,13 +327,6 @@ impl<'self, View> AbstractNode { 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(self, f: &fn(&Element) -> R) -> R { if !self.is_element() { @@ -478,11 +463,11 @@ impl Iterator> for AbstractNodeChildrenIterator { impl Node { pub fn owner_doc(&self) -> AbstractDocument { - self.owner_doc.unwrap() + self.owner_doc } pub fn set_owner_doc(&mut self, document: AbstractDocument) { - self.owner_doc = Some(document); + self.owner_doc = document; } } @@ -523,14 +508,6 @@ impl Node { } pub fn new(type_id: NodeTypeId, doc: AbstractDocument) -> Node { - Node::new_(type_id, Some(doc)) - } - - pub fn new_without_doc(type_id: NodeTypeId) -> Node { - Node::new_(type_id, None) - } - - fn new_(type_id: NodeTypeId, doc: Option) -> Node { Node { reflector_: Reflector::new(), type_id: type_id, @@ -549,6 +526,24 @@ impl Node { layout_data: LayoutData::new(), } } + + pub fn getNextSibling(&mut self) -> Option<&mut AbstractNode> { + 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> { + 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 { @@ -557,7 +552,6 @@ impl Node { ElementNodeTypeId(_) => 1, TextNodeTypeId => 3, CommentNodeTypeId => 8, - DocumentNodeTypeId(_)=> 9, DoctypeNodeTypeId => 10, DocumentFragmentNodeTypeId => 11, } @@ -578,7 +572,6 @@ impl Node { } }, DocumentFragmentNodeTypeId => ~"#document-fragment", - DocumentNodeTypeId(_) => ~"#document" }) } @@ -593,7 +586,7 @@ impl Node { TextNodeTypeId | DoctypeNodeTypeId | DocumentFragmentNodeTypeId => Some(self.owner_doc()), - DocumentNodeTypeId(_) => None + // DocumentNodeTypeId => None } } @@ -662,7 +655,7 @@ impl Node { characterdata.Data() } } - DoctypeNodeTypeId | DocumentNodeTypeId(_) => { + DoctypeNodeTypeId => { None } } @@ -724,7 +717,7 @@ impl Node { document.document().content_changed(); } } - DoctypeNodeTypeId | DocumentNodeTypeId(_) => {} + DoctypeNodeTypeId => {} } Ok(()) } @@ -746,9 +739,10 @@ impl Node { if new_child.is_doctype() { return true; } - match this_node.type_id() { - DocumentNodeTypeId(*) | ElementNodeTypeId(*) => (), - _ => 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; } if this_node == new_child { return true; @@ -799,8 +793,7 @@ impl Node { // Unregister elements having "id' from the owner doc. // This need be called before target nodes are removed from tree. - let owner_doc = self.owner_doc(); - owner_doc.mut_document().unregister_nodes_with_id(&abstract_self); + self.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 b17449ab0ba..e710dfb6d95 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 => return, + None => fail!(~"Tried to relayout with no root frame!"), 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 0b1bb610414..b45d5de011d 100644 --- a/src/test/html/content/test_parentnodes.html +++ b/src/test/html/content/test_parentnodes.html @@ -6,7 +6,8 @@