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

@ -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::{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,
}
@ -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
/// 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)
}
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() {
@ -431,27 +446,7 @@ impl<'self, View> AbstractNode<View> {
// Issue #1030: should not walk the tree
pub fn is_in_doc(&self) -> bool {
let document = self.node().owner_doc();
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
}
}
self.ancestors().any(|node| node.is_document())
}
}
@ -495,11 +490,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);
}
}
@ -528,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,
@ -546,32 +549,16 @@ 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> {
// http://dom.spec.whatwg.org/#dom-node-nodetype
pub fn NodeType(&self) -> u16 {
match self.type_id {
ElementNodeTypeId(_) => 1,
TextNodeTypeId => 3,
CommentNodeTypeId => 8,
DocumentNodeTypeId(_)=> 9,
DoctypeNodeTypeId => 10,
DocumentFragmentNodeTypeId => 11,
}
@ -592,6 +579,7 @@ impl Node<ScriptView> {
}
},
DocumentFragmentNodeTypeId => ~"#document-fragment",
DocumentNodeTypeId(_) => ~"#document"
})
}
@ -606,7 +594,7 @@ impl Node<ScriptView> {
TextNodeTypeId |
DoctypeNodeTypeId |
DocumentFragmentNodeTypeId => Some(self.owner_doc()),
// DocumentNodeTypeId => None
DocumentNodeTypeId(_) => None
}
}
@ -675,7 +663,7 @@ impl Node<ScriptView> {
characterdata.Data()
}
}
DoctypeNodeTypeId => {
DoctypeNodeTypeId | DocumentNodeTypeId(_) => {
None
}
}
@ -723,7 +711,7 @@ impl Node<ScriptView> {
// Step 1.
match parent.type_id() {
// DocumentNodeTypeId |
DocumentNodeTypeId(*) |
DocumentFragmentNodeTypeId |
ElementNodeTypeId(*) => (),
_ => {
@ -754,21 +742,21 @@ impl Node<ScriptView> {
TextNodeTypeId |
// ProcessingInstructionNodeTypeId |
CommentNodeTypeId => (),
/*_ => { XXX #838
return Err(HierarchyRequest);
},*/
DocumentNodeTypeId(*) => return Err(HierarchyRequest),
}
// Step 5.
match node.type_id() {
TextNodeTypeId => {
if false { // XXX #838
return Err(HierarchyRequest);
match node.parent_node() {
Some(parent) if parent.is_document() => return Err(HierarchyRequest),
_ => ()
}
},
DoctypeNodeTypeId => {
if true { // XXX #838
return Err(HierarchyRequest);
match node.parent_node() {
Some(parent) if !parent.is_document() => return Err(HierarchyRequest),
_ => ()
}
},
_ => (),
@ -899,7 +887,7 @@ impl Node<ScriptView> {
document.document().content_changed();
}
}
DoctypeNodeTypeId => {}
DoctypeNodeTypeId | DocumentNodeTypeId(_) => {}
}
Ok(())
}