diff options
Diffstat (limited to 'src/components/script/dom/node.rs')
-rw-r--r-- | src/components/script/dom/node.rs | 207 |
1 files changed, 110 insertions, 97 deletions
diff --git a/src/components/script/dom/node.rs b/src/components/script/dom/node.rs index a6cf77d0c19..78533b2b48c 100644 --- a/src/components/script/dom/node.rs +++ b/src/components/script/dom/node.rs @@ -21,12 +21,8 @@ use dom::text::Text; use std::cast; use std::cast::transmute; use std::unstable::raw::Box; -use extra::arc::Arc; use js::jsapi::{JSObject, JSContext}; -use style::{ComputedValues, PropertyDeclaration}; use servo_util::tree::{TreeNode, TreeNodeRef, TreeNodeRefAsElement}; -use servo_util::range::Range; -use gfx::display_list::DisplayList; // // The basic Node structure @@ -93,7 +89,7 @@ pub struct Node<View> { child_list: Option<@mut NodeList>, /// Layout information. Only the layout task may touch this data. - priv layout_data: LayoutData, + layout_data: Option<~Any>, } /// The different types of nodes. @@ -445,9 +441,7 @@ impl<'self, View> AbstractNode<View> { } pub fn children(&self) -> AbstractNodeChildrenIterator<View> { - AbstractNodeChildrenIterator { - current_node: self.first_child(), - } + self.node().children() } // Issue #1030: should not walk the tree @@ -502,6 +496,12 @@ impl<View> Node<View> { pub fn set_owner_doc(&mut self, document: AbstractDocument) { self.owner_doc = Some(document); } + + pub fn children(&self) -> AbstractNodeChildrenIterator<View> { + AbstractNodeChildrenIterator { + current_node: self.first_child, + } + } } impl Node<ScriptView> { @@ -543,7 +543,7 @@ impl Node<ScriptView> { owner_doc: doc, child_list: None, - layout_data: LayoutData::new(), + layout_data: None, } } } @@ -562,10 +562,10 @@ impl Node<ScriptView> { } pub fn NodeName(&self, abstract_self: AbstractNode<ScriptView>) -> DOMString { - Some(match self.type_id { + match self.type_id { ElementNodeTypeId(*) => { do abstract_self.with_imm_element |element| { - element.TagName().expect("tagName should never be null") + element.TagName() } } CommentNodeTypeId => ~"#comment", @@ -577,10 +577,10 @@ impl Node<ScriptView> { }, DocumentFragmentNodeTypeId => ~"#document-fragment", DocumentNodeTypeId(_) => ~"#document" - }) + } } - pub fn GetBaseURI(&self) -> DOMString { + pub fn GetBaseURI(&self) -> Option<DOMString> { None } @@ -623,12 +623,12 @@ impl Node<ScriptView> { self.next_sibling } - pub fn GetNodeValue(&self, abstract_self: AbstractNode<ScriptView>) -> DOMString { + pub fn GetNodeValue(&self, abstract_self: AbstractNode<ScriptView>) -> Option<DOMString> { match self.type_id { // ProcessingInstruction CommentNodeTypeId | TextNodeTypeId => { do abstract_self.with_imm_characterdata() |characterdata| { - characterdata.Data() + Some(characterdata.Data()) } } _ => { @@ -637,19 +637,18 @@ impl Node<ScriptView> { } } - pub fn SetNodeValue(&mut self, _abstract_self: AbstractNode<ScriptView>, _val: &DOMString) -> ErrorResult { + pub fn SetNodeValue(&mut self, _abstract_self: AbstractNode<ScriptView>, _val: Option<DOMString>) -> ErrorResult { Ok(()) } - pub fn GetTextContent(&self, abstract_self: AbstractNode<ScriptView>) -> DOMString { + pub fn GetTextContent(&self, abstract_self: AbstractNode<ScriptView>) -> Option<DOMString> { match self.type_id { DocumentFragmentNodeTypeId | ElementNodeTypeId(*) => { let mut content = ~""; for node in abstract_self.traverse_preorder() { if node.is_text() { do node.with_imm_text() |text| { - let s = text.element.Data(); - content = content + null_str_as_empty(&s); + content = content + text.element.Data(); } } } @@ -657,7 +656,7 @@ impl Node<ScriptView> { } CommentNodeTypeId | TextNodeTypeId => { do abstract_self.with_imm_characterdata() |characterdata| { - characterdata.Data() + Some(characterdata.Data()) } } DoctypeNodeTypeId | DocumentNodeTypeId(_) => { @@ -875,6 +874,15 @@ impl Node<ScriptView> { // Step 5: DocumentFragment, mutation records. // Step 6: DocumentFragment. + match node.type_id() { + DocumentFragmentNodeTypeId => { + for c in node.children() { + Node::remove(c, node, true); + } + }, + _ => (), + } + // Step 7: mutation records. // Step 8. for node in nodes.iter() { @@ -890,18 +898,45 @@ impl Node<ScriptView> { } // http://dom.spec.whatwg.org/#concept-node-replace-all - pub fn replace_all(&mut self, - abstract_self: AbstractNode<ScriptView>, - node: Option<AbstractNode<ScriptView>>) { - //FIXME: We should batch document notifications that occur here - for child in abstract_self.children() { - self.RemoveChild(abstract_self, child); + pub fn replace_all(node: Option<AbstractNode<ScriptView>>, + parent: AbstractNode<ScriptView>) { + // Step 1. + match node { + Some(node) => Node::adopt(node, parent.node().owner_doc()), + None => (), } + + // Step 2. + let removedNodes: ~[AbstractNode<ScriptView>] = parent.children().collect(); + + // Step 3. + let addedNodes = match node { + None => ~[], + Some(node) => match node.type_id() { + DocumentFragmentNodeTypeId => node.children().collect(), + _ => ~[node], + }, + }; + + // Step 4. + for child in parent.children() { + Node::remove(child, parent, true); + } + + // Step 5. match node { - None => {}, - Some(node) => { - self.AppendChild(abstract_self, node); - } + Some(node) => Node::insert(node, parent, None, true), + None => (), + } + + // Step 6: mutation records. + + // Step 7. + for removedNode in removedNodes.iter() { + removedNode.node_removed(); + } + for addedNode in addedNodes.iter() { + addedNode.node_inserted(); } } @@ -939,26 +974,25 @@ impl Node<ScriptView> { pub fn SetTextContent(&mut self, abstract_self: AbstractNode<ScriptView>, - value: &DOMString) -> ErrorResult { - let is_empty = match value { - &Some(~"") | &None => true, - _ => false - }; + value: Option<DOMString>) -> ErrorResult { + self.wait_until_safe_to_modify_dom(); + + let value = null_str_as_empty(&value); match self.type_id { DocumentFragmentNodeTypeId | ElementNodeTypeId(*) => { - let node = if is_empty { + // Step 1-2. + let node = if value.len() == 0 { None } else { let document = self.owner_doc(); Some(document.document().CreateTextNode(document, value)) }; - self.replace_all(abstract_self, node); + // Step 3. + Node::replace_all(node, abstract_self); } CommentNodeTypeId | TextNodeTypeId => { - self.wait_until_safe_to_modify_dom(); - do abstract_self.with_mut_characterdata() |characterdata| { - characterdata.data = null_str_as_empty(value); + characterdata.data = value.clone(); // Notify the document that the content of this node is different let document = self.owner_doc(); @@ -1019,27 +1053,27 @@ impl Node<ScriptView> { false } - pub fn LookupPrefix(&self, _prefix: &DOMString) -> DOMString { + pub fn LookupPrefix(&self, _prefix: Option<DOMString>) -> Option<DOMString> { None } - pub fn LookupNamespaceURI(&self, _namespace: &DOMString) -> DOMString { + pub fn LookupNamespaceURI(&self, _namespace: Option<DOMString>) -> Option<DOMString> { None } - pub fn IsDefaultNamespace(&self, _namespace: &DOMString) -> bool { + pub fn IsDefaultNamespace(&self, _namespace: Option<DOMString>) -> bool { false } - pub fn GetNamespaceURI(&self) -> DOMString { + pub fn GetNamespaceURI(&self) -> Option<DOMString> { None } - pub fn GetPrefix(&self) -> DOMString { + pub fn GetPrefix(&self) -> Option<DOMString> { None } - pub fn GetLocalName(&self) -> DOMString { + pub fn GetLocalName(&self) -> Option<DOMString> { None } @@ -1058,62 +1092,41 @@ impl Reflectable for Node<ScriptView> { } } -// This stuff is notionally private to layout, but we put it here because it needs -// to be stored in a Node, and we can't have cross-crate cyclic dependencies. - -pub struct DisplayBoxes { - display_list: Option<Arc<DisplayList<AbstractNode<()>>>>, - range: Option<Range>, -} - -/// Data that layout associates with a node. -pub struct LayoutData { - /// The results of CSS matching for this node. - applicable_declarations: ~[Arc<~[PropertyDeclaration]>], - - /// The results of CSS styling for this node. - style: Option<ComputedValues>, +/// A bottom-up, parallelizable traversal. +pub trait PostorderNodeTraversal { + /// The operation to perform. Return true to continue or false to stop. + fn process(&mut self, node: AbstractNode<LayoutView>) -> bool; - /// Description of how to account for recent style changes. - restyle_damage: Option<int>, - - /// The boxes assosiated with this flow. - /// Used for getBoundingClientRect and friends. - boxes: DisplayBoxes, -} - -impl LayoutData { - /// Creates new layout data. - pub fn new() -> LayoutData { - LayoutData { - applicable_declarations: ~[], - style: None, - restyle_damage: None, - boxes: DisplayBoxes { - display_list: None, - range: None, - }, - } + /// Returns true if this node should be pruned. If this returns true, we skip the operation + /// entirely and do not process any descendant nodes. This is called *before* child nodes are + /// visited. The default implementation never prunes any nodes. + fn should_prune(&mut self, _node: AbstractNode<LayoutView>) -> bool { + false } } -// This serves as a static assertion that layout data remains sendable. If this is not done, then -// we can have memory unsafety, which usually manifests as shutdown crashes. -fn assert_is_sendable<T:Send>(_: T) {} -fn assert_layout_data_is_sendable() { - assert_is_sendable(LayoutData::new()) -} - impl AbstractNode<LayoutView> { - // These accessors take a continuation rather than returning a reference, because - // an AbstractNode doesn't have a lifetime parameter relating to the underlying - // Node. Also this makes it easier to switch to RWArc if we decide that is - // necessary. - pub fn read_layout_data<R>(self, blk: &fn(data: &LayoutData) -> R) -> R { - blk(&self.node().layout_data) - } + /// Traverses the tree in postorder. + /// + /// TODO(pcwalton): Offer a parallel version with a compatible API. + pub fn traverse_postorder<T:PostorderNodeTraversal>(self, traversal: &mut T) -> bool { + if traversal.should_prune(self) { + return true + } + + let mut opt_kid = self.first_child(); + loop { + match opt_kid { + None => break, + Some(kid) => { + if !kid.traverse_postorder(traversal) { + return false + } + opt_kid = kid.next_sibling() + } + } + } - pub fn write_layout_data<R>(self, blk: &fn(data: &mut LayoutData) -> R) -> R { - blk(&mut self.mut_node().layout_data) + traversal.process(self) } } |