Make Document a Node.

This commit is contained in:
Josh Matthews 2013-10-17 16:42:51 +01:00
parent cc76a2188e
commit 99a36cbeb6
10 changed files with 96 additions and 120 deletions

View file

@ -23,7 +23,7 @@ use style::computed_values::display;
use style::computed_values::float; use style::computed_values::float;
use layout::float_context::{FloatLeft, FloatRight}; use layout::float_context::{FloatLeft, FloatRight};
use script::dom::node::{AbstractNode, CommentNodeTypeId, DoctypeNodeTypeId}; 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 script::dom::node::DocumentFragmentNodeTypeId;
use servo_util::range::Range; use servo_util::range::Range;
use servo_util::tree::{TreeNodeRef, TreeNode}; use servo_util::tree::{TreeNodeRef, TreeNode};
@ -391,6 +391,7 @@ impl LayoutTreeBuilder {
display => display, display => display,
}, },
TextNodeTypeId => display::inline, TextNodeTypeId => display::inline,
DocumentNodeTypeId(_) |
DoctypeNodeTypeId | DoctypeNodeTypeId |
DocumentFragmentNodeTypeId | DocumentFragmentNodeTypeId |
CommentNodeTypeId => return NoGenerator, CommentNodeTypeId => return NoGenerator,
@ -449,10 +450,10 @@ impl LayoutTreeBuilder {
match (parent_generator.flow.as_block().is_root, node.parent_node()) { match (parent_generator.flow.as_block().is_root, node.parent_node()) {
// If this is the root node, then use the root flow's // If this is the root node, then use the root flow's
// context. Otherwise, make a child block context. // context. Otherwise, make a child block context.
(true, Some(_)) => { (true, Some(parent)) if !parent.is_document() => {
self.create_child_generator(node, parent_generator, BlockFlowType) self.create_child_generator(node, parent_generator, BlockFlowType)
} }
(true, None) => return ParentGenerator, (true, None) | (true, Some(_)) => return ParentGenerator,
(false, _) => { (false, _) => {
self.create_child_generator(node, parent_generator, BlockFlowType) self.create_child_generator(node, parent_generator, BlockFlowType)
} }

View file

@ -24,7 +24,7 @@ enum VisibilityState { "hidden", "visible" };
/* http://dom.spec.whatwg.org/#interface-document */ /* http://dom.spec.whatwg.org/#interface-document */
[Constructor] [Constructor]
interface Document /*: Node*/ { //XXXjdm Requires servo/#623 interface Document : Node {
/*[Throws] /*[Throws]
readonly attribute DOMImplementation implementation;*/ readonly attribute DOMImplementation implementation;*/
// readonly attribute DOMString URL; // readonly attribute DOMString URL;

View file

@ -3,10 +3,11 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use dom::bindings::utils::{Reflectable, Reflector, Traceable}; use dom::bindings::utils::{Reflectable, Reflector, Traceable};
use dom::document::{PlainDocumentTypeId, HTMLDocumentTypeId};
use dom::element::*; use dom::element::*;
use dom::types::*; use dom::types::*;
use dom::node::{AbstractNode, ElementNodeTypeId, TextNodeTypeId, CommentNodeTypeId}; 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::cast;
use std::libc; use std::libc;
@ -95,6 +96,8 @@ pub fn create(cx: *JSContext, node: &mut AbstractNode<ScriptView>) -> *JSObject
CommentNodeTypeId => generate_element!(Comment), CommentNodeTypeId => generate_element!(Comment),
DoctypeNodeTypeId => generate_element!(DocumentType), DoctypeNodeTypeId => generate_element!(DocumentType),
DocumentFragmentNodeTypeId => generate_element!(DocumentFragment), DocumentFragmentNodeTypeId => generate_element!(DocumentFragment),
DocumentNodeTypeId(PlainDocumentTypeId) => generate_element!(Document),
DocumentNodeTypeId(HTMLDocumentTypeId) => generate_element!(HTMLDocument),
TextNodeTypeId => generate_element!(Text), TextNodeTypeId => generate_element!(Text),
} }
} }

View file

@ -9,18 +9,16 @@ use dom::bindings::utils::{Reflectable, Reflector, DerivedWrapper};
use dom::bindings::utils::{is_valid_element_name, InvalidCharacter, Traceable, null_str_as_empty, null_str_as_word_null}; use dom::bindings::utils::{is_valid_element_name, InvalidCharacter, Traceable, null_str_as_empty, null_str_as_word_null};
use dom::documentfragment::DocumentFragment; use dom::documentfragment::DocumentFragment;
use dom::element::{Element}; use dom::element::{Element};
use dom::element::{HTMLHtmlElementTypeId, HTMLHeadElementTypeId, HTMLTitleElementTypeId}; use dom::element::{HTMLHeadElementTypeId, HTMLTitleElementTypeId};
use dom::htmlcollection::HTMLCollection; use dom::htmlcollection::HTMLCollection;
use dom::htmldocument::HTMLDocument; use dom::htmldocument::HTMLDocument;
use dom::htmlelement::HTMLElement; use dom::htmlelement::HTMLElement;
use dom::htmlhtmlelement::HTMLHtmlElement; use dom::node::{AbstractNode, ScriptView, Node, ElementNodeTypeId, DocumentNodeTypeId};
use dom::node::{AbstractNode, ScriptView, Node, ElementNodeTypeId};
use dom::text::Text; use dom::text::Text;
use dom::window::Window; use dom::window::Window;
use dom::htmltitleelement::HTMLTitleElement; use dom::htmltitleelement::HTMLTitleElement;
use html::hubbub_html_parser::build_element_from_tag; use html::hubbub_html_parser::build_element_from_tag;
use js::jsapi::{JSObject, JSContext, JSVal}; use js::jsapi::{JSObject, JSContext, JSVal, JSTracer};
use js::jsapi::{JSTRACE_OBJECT, JSTracer, JS_CallTracer};
use js::glue::RUST_OBJECT_TO_JSVAL; use js::glue::RUST_OBJECT_TO_JSVAL;
use servo_util::tree::{TreeNodeRef, ElementLike}; use servo_util::tree::{TreeNodeRef, ElementLike};
@ -29,12 +27,18 @@ use std::hashmap::HashMap;
use std::cast; use std::cast;
use std::ptr; use std::ptr;
use std::str::eq_slice; use std::str::eq_slice;
use std::libc;
use std::ascii::StrAsciiExt; use std::ascii::StrAsciiExt;
use std::unstable::raw::Box; use std::unstable::raw::Box;
#[deriving(Eq)]
pub enum DocumentTypeId {
PlainDocumentTypeId,
HTMLDocumentTypeId
}
pub trait ReflectableDocument { pub trait ReflectableDocument {
fn init_reflector(@mut self, cx: *JSContext); fn init_reflector(@mut self, cx: *JSContext);
fn init_node(@mut self, doc: AbstractDocument);
} }
#[deriving(Eq)] #[deriving(Eq)]
@ -45,9 +49,11 @@ pub struct AbstractDocument {
impl AbstractDocument { impl AbstractDocument {
pub fn as_abstract<T: ReflectableDocument>(cx: *JSContext, doc: @mut T) -> AbstractDocument { pub fn as_abstract<T: ReflectableDocument>(cx: *JSContext, doc: @mut T) -> AbstractDocument {
doc.init_reflector(cx); doc.init_reflector(cx);
AbstractDocument { let abstract = AbstractDocument {
document: unsafe { cast::transmute(doc) } document: unsafe { cast::transmute(doc) }
} };
doc.init_node(abstract);
abstract
} }
pub fn document<'a>(&'a self) -> &'a Document { pub fn document<'a>(&'a self) -> &'a Document {
@ -91,10 +97,9 @@ impl AbstractDocument {
}); });
let document = self.mut_document(); 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. // Register elements having "id" attribute to the owner doc.
document.register_nodes_with_id(&root); document.register_nodes_with_id(&root);
document.content_changed();
} }
} }
@ -105,7 +110,7 @@ pub enum DocumentType {
} }
pub struct Document { pub struct Document {
priv root: Option<AbstractNode<ScriptView>>, node: Node<ScriptView>,
reflector_: Reflector, reflector_: Reflector,
window: @mut Window, window: @mut Window,
doctype: DocumentType, doctype: DocumentType,
@ -116,8 +121,12 @@ pub struct Document {
impl Document { impl Document {
#[fixed_stack_segment] #[fixed_stack_segment]
pub fn new(window: @mut Window, doctype: DocumentType) -> Document { pub fn new(window: @mut Window, doctype: DocumentType) -> Document {
let node_type = match doctype {
HTML => HTMLDocumentTypeId,
SVG | XML => PlainDocumentTypeId
};
Document { Document {
root: None, node: Node::new_without_doc(DocumentNodeTypeId(node_type)),
reflector_: Reflector::new(), reflector_: Reflector::new(),
window: window, window: window,
doctype: doctype, doctype: doctype,
@ -128,16 +137,7 @@ impl Document {
pub fn Constructor(owner: @mut Window) -> Fallible<AbstractDocument> { pub fn Constructor(owner: @mut Window) -> Fallible<AbstractDocument> {
let cx = owner.get_cx(); 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)
} }
} }
@ -145,6 +145,10 @@ impl ReflectableDocument for Document {
fn init_reflector(@mut self, cx: *JSContext) { fn init_reflector(@mut self, cx: *JSContext) {
self.wrap_object_shared(cx, ptr::null()); //XXXjdm a proper scope would be nice 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);
}
} }
impl Reflectable for AbstractDocument { impl Reflectable for AbstractDocument {
@ -184,11 +188,11 @@ impl DerivedWrapper for AbstractDocument {
impl Reflectable for Document { impl Reflectable for Document {
fn reflector<'a>(&'a self) -> &'a Reflector { fn reflector<'a>(&'a self) -> &'a Reflector {
&self.reflector_ self.node.reflector()
} }
fn mut_reflector<'a>(&'a mut self) -> &'a mut 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 { fn wrap_object_shared(@mut self, cx: *JSContext, scope: *JSObject) -> *JSObject {
@ -202,7 +206,7 @@ impl Reflectable for Document {
impl Document { impl Document {
pub fn GetDocumentElement(&self) -> Option<AbstractNode<ScriptView>> { pub fn GetDocumentElement(&self) -> Option<AbstractNode<ScriptView>> {
self.root self.node.first_child
} }
fn get_cx(&self) -> *JSContext { fn get_cx(&self) -> *JSContext {
@ -408,21 +412,6 @@ fn foreach_ided_elements(root: &AbstractNode<ScriptView>,
impl Traceable for Document { impl Traceable for Document {
#[fixed_stack_segment] #[fixed_stack_segment]
fn trace(&self, tracer: *mut JSTracer) { fn trace(&self, tracer: *mut JSTracer) {
match self.root { self.node.trace(tracer);
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);
}
}
}
}
} }
} }

View file

@ -5,12 +5,9 @@
use dom::bindings::codegen::DOMParserBinding; use dom::bindings::codegen::DOMParserBinding;
use dom::bindings::codegen::DOMParserBinding::SupportedTypeValues::{Text_html, Text_xml}; use dom::bindings::codegen::DOMParserBinding::SupportedTypeValues::{Text_html, Text_xml};
use dom::bindings::utils::{DOMString, Fallible, Reflector, Reflectable, reflect_dom_object}; use dom::bindings::utils::{DOMString, Fallible, Reflector, Reflectable, reflect_dom_object};
use dom::bindings::utils::FailureUnknown;
use dom::document::{AbstractDocument, Document, XML}; use dom::document::{AbstractDocument, Document, XML};
use dom::element::HTMLHtmlElementTypeId;
use dom::htmldocument::HTMLDocument; use dom::htmldocument::HTMLDocument;
use dom::htmlelement::HTMLElement;
use dom::htmlhtmlelement::HTMLHtmlElement;
use dom::node::Node;
use dom::window::Window; use dom::window::Window;
use js::jsapi::{JSContext, JSObject}; use js::jsapi::{JSContext, JSObject};
@ -42,25 +39,17 @@ impl DOMParser {
ty: DOMParserBinding::SupportedType) ty: DOMParserBinding::SupportedType)
-> Fallible<AbstractDocument> { -> Fallible<AbstractDocument> {
let cx = self.owner.get_cx(); let cx = self.owner.get_cx();
let document = match ty { match ty {
Text_html => { Text_html => {
HTMLDocument::new(self.owner) Ok(HTMLDocument::new(self.owner))
} }
Text_xml => { 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)
} }
} }

View file

@ -35,6 +35,10 @@ impl ReflectableDocument for HTMLDocument {
fn init_reflector(@mut self, cx: *JSContext) { fn init_reflector(@mut self, cx: *JSContext) {
self.wrap_object_shared(cx, ptr::null()); //XXXjdm a proper scope would be nice 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);
}
} }
impl HTMLDocument { impl HTMLDocument {

View file

@ -9,7 +9,7 @@ use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
use dom::bindings::utils::{DOMString, null_str_as_empty}; use dom::bindings::utils::{DOMString, null_str_as_empty};
use dom::bindings::utils::{ErrorResult, Fallible, NotFound, HierarchyRequest}; use dom::bindings::utils::{ErrorResult, Fallible, NotFound, HierarchyRequest};
use dom::characterdata::CharacterData; use dom::characterdata::CharacterData;
use dom::document::AbstractDocument; use dom::document::{AbstractDocument, DocumentTypeId};
use dom::documenttype::DocumentType; use dom::documenttype::DocumentType;
use dom::element::{Element, ElementTypeId, HTMLImageElementTypeId, HTMLIframeElementTypeId}; use dom::element::{Element, ElementTypeId, HTMLImageElementTypeId, HTMLIframeElementTypeId};
use dom::element::{HTMLStyleElementTypeId}; use dom::element::{HTMLStyleElementTypeId};
@ -88,7 +88,7 @@ pub struct Node<View> {
prev_sibling: Option<AbstractNode<View>>, prev_sibling: Option<AbstractNode<View>>,
/// The document that this node belongs to. /// The document that this node belongs to.
priv owner_doc: AbstractDocument, priv owner_doc: Option<AbstractDocument>,
/// The live list of children return by .childNodes. /// The live list of children return by .childNodes.
child_list: Option<@mut NodeList>, child_list: Option<@mut NodeList>,
@ -103,6 +103,7 @@ pub enum NodeTypeId {
DoctypeNodeTypeId, DoctypeNodeTypeId,
DocumentFragmentNodeTypeId, DocumentFragmentNodeTypeId,
CommentNodeTypeId, CommentNodeTypeId,
DocumentNodeTypeId(DocumentTypeId),
ElementNodeTypeId(ElementTypeId), ElementNodeTypeId(ElementTypeId),
TextNodeTypeId, TextNodeTypeId,
} }
@ -204,6 +205,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 // Convenience accessors
/// Returns the type ID of this node. Fails if this node is borrowed mutably. /// Returns the type ID of this node. Fails if this node is borrowed mutably.
@ -331,6 +339,13 @@ impl<'self, View> AbstractNode<View> {
self.transmute_mut(f) 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. // FIXME: This should be doing dynamic borrow checking for safety.
pub fn with_imm_element<R>(self, f: &fn(&Element) -> R) -> R { pub fn with_imm_element<R>(self, f: &fn(&Element) -> R) -> R {
if !self.is_element() { if !self.is_element() {
@ -431,27 +446,7 @@ impl<'self, View> AbstractNode<View> {
// Issue #1030: should not walk the tree // Issue #1030: should not walk the tree
pub fn is_in_doc(&self) -> bool { pub fn is_in_doc(&self) -> bool {
let document = self.node().owner_doc(); self.ancestors().any(|node| node.is_document())
match document.document().GetDocumentElement() {
None => false,
Some(root) => {
let mut node = *self;
let mut in_doc;
loop {
match node.parent_node() {
Some(parent) => {
node = parent;
},
None => {
// Issue #1029: this is horrible.
in_doc = unsafe { node.raw_object() as uint == root.raw_object() as uint };
break;
}
}
}
in_doc
}
}
} }
} }
@ -495,11 +490,11 @@ impl<View> Iterator<AbstractNode<View>> for AbstractNodeChildrenIterator<View> {
impl<View> Node<View> { impl<View> Node<View> {
pub fn owner_doc(&self) -> AbstractDocument { pub fn owner_doc(&self) -> AbstractDocument {
self.owner_doc self.owner_doc.unwrap()
} }
pub fn set_owner_doc(&mut self, document: AbstractDocument) { pub fn set_owner_doc(&mut self, document: AbstractDocument) {
self.owner_doc = document; self.owner_doc = Some(document);
} }
} }
@ -528,6 +523,14 @@ impl Node<ScriptView> {
} }
pub fn new(type_id: NodeTypeId, doc: AbstractDocument) -> 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 { Node {
reflector_: Reflector::new(), reflector_: Reflector::new(),
type_id: type_id, type_id: type_id,
@ -546,32 +549,16 @@ impl Node<ScriptView> {
layout_data: LayoutData::new(), 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> { impl Node<ScriptView> {
// http://dom.spec.whatwg.org/#dom-node-nodetype
pub fn NodeType(&self) -> u16 { pub fn NodeType(&self) -> u16 {
match self.type_id { match self.type_id {
ElementNodeTypeId(_) => 1, ElementNodeTypeId(_) => 1,
TextNodeTypeId => 3, TextNodeTypeId => 3,
CommentNodeTypeId => 8, CommentNodeTypeId => 8,
DocumentNodeTypeId(_)=> 9,
DoctypeNodeTypeId => 10, DoctypeNodeTypeId => 10,
DocumentFragmentNodeTypeId => 11, DocumentFragmentNodeTypeId => 11,
} }
@ -592,6 +579,7 @@ impl Node<ScriptView> {
} }
}, },
DocumentFragmentNodeTypeId => ~"#document-fragment", DocumentFragmentNodeTypeId => ~"#document-fragment",
DocumentNodeTypeId(_) => ~"#document"
}) })
} }
@ -606,7 +594,7 @@ impl Node<ScriptView> {
TextNodeTypeId | TextNodeTypeId |
DoctypeNodeTypeId | DoctypeNodeTypeId |
DocumentFragmentNodeTypeId => Some(self.owner_doc()), DocumentFragmentNodeTypeId => Some(self.owner_doc()),
// DocumentNodeTypeId => None DocumentNodeTypeId(_) => None
} }
} }
@ -675,7 +663,7 @@ impl Node<ScriptView> {
characterdata.Data() characterdata.Data()
} }
} }
DoctypeNodeTypeId => { DoctypeNodeTypeId | DocumentNodeTypeId(_) => {
None None
} }
} }
@ -723,7 +711,7 @@ impl Node<ScriptView> {
// Step 1. // Step 1.
match parent.type_id() { match parent.type_id() {
// DocumentNodeTypeId | DocumentNodeTypeId(*) |
DocumentFragmentNodeTypeId | DocumentFragmentNodeTypeId |
ElementNodeTypeId(*) => (), ElementNodeTypeId(*) => (),
_ => { _ => {
@ -754,21 +742,21 @@ impl Node<ScriptView> {
TextNodeTypeId | TextNodeTypeId |
// ProcessingInstructionNodeTypeId | // ProcessingInstructionNodeTypeId |
CommentNodeTypeId => (), CommentNodeTypeId => (),
/*_ => { XXX #838 DocumentNodeTypeId(*) => return Err(HierarchyRequest),
return Err(HierarchyRequest);
},*/
} }
// Step 5. // Step 5.
match node.type_id() { match node.type_id() {
TextNodeTypeId => { TextNodeTypeId => {
if false { // XXX #838 match node.parent_node() {
return Err(HierarchyRequest); Some(parent) if parent.is_document() => return Err(HierarchyRequest),
_ => ()
} }
}, },
DoctypeNodeTypeId => { DoctypeNodeTypeId => {
if true { // XXX #838 match node.parent_node() {
return Err(HierarchyRequest); Some(parent) if !parent.is_document() => return Err(HierarchyRequest),
_ => ()
} }
}, },
_ => (), _ => (),
@ -899,7 +887,7 @@ impl Node<ScriptView> {
document.document().content_changed(); document.document().content_changed();
} }
} }
DoctypeNodeTypeId => {} DoctypeNodeTypeId | DocumentNodeTypeId(_) => {}
} }
Ok(()) Ok(())
} }

View file

@ -274,7 +274,7 @@ impl Page {
/// This function fails if there is no root frame. /// This function fails if there is no root frame.
fn reflow(&mut self, goal: ReflowGoal, script_chan: ScriptChan, compositor: @ScriptListener) { fn reflow(&mut self, goal: ReflowGoal, script_chan: ScriptChan, compositor: @ScriptListener) {
let root = match self.frame { let root = match self.frame {
None => fail!(~"Tried to relayout with no root frame!"), None => return,
Some(ref frame) => { Some(ref frame) => {
frame.document.document().GetDocumentElement() frame.document.document().GetDocumentElement()
} }

View file

@ -6,8 +6,7 @@
<body> <body>
<div id="div1"></div> <div id="div1"></div>
<script> <script>
// FIXME: This should be HTMLDocument. is_a(document.documentElement.parentNode, HTMLDocument);
//isnot(document.documentElement.parentNode, null);
is(document.documentElement.parentElement, null); is(document.documentElement.parentElement, null);
var elem = document.createElement("p"); var elem = document.createElement("p");

View file

@ -5,6 +5,9 @@
<body> <body>
<foo-á>foo</foo-á> <foo-á>foo</foo-á>
<script> <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, Node);
is_a(window.document.documentElement, Element); is_a(window.document.documentElement, Element);
is_a(window.document.documentElement, HTMLElement); is_a(window.document.documentElement, HTMLElement);