script: Make trees less generic

This commit is contained in:
Patrick Walton 2013-12-16 17:35:58 -08:00
parent 44a8b0987c
commit 199ca33b72
23 changed files with 382 additions and 523 deletions

View file

@ -10,7 +10,6 @@ use std::cast;
use std::libc;
use std::ptr;
use js::jsapi::{JSTracer, JSTRACE_OBJECT, JS_CallTracer};
use servo_util::tree::TreeNodeRef;
impl Reflectable for AbstractNode<ScriptView> {
fn reflector<'a>(&'a self) -> &'a Reflector {

View file

@ -21,16 +21,15 @@ use dom::uievent::UIEvent;
use dom::window::Window;
use dom::htmltitleelement::HTMLTitleElement;
use html::hubbub_html_parser::build_element_from_tag;
use js::jsapi::{JSObject, JSContext, JSTracer};
use servo_util::tree::{TreeNodeRef, ElementLike};
use layout_interface::{DocumentDamageLevel, ContentChangedDocumentDamage};
use std::hashmap::HashMap;
use std::cast;
use std::str::eq_slice;
use js::jsapi::{JSObject, JSContext, JSTracer};
use std::ascii::StrAsciiExt;
use std::cast;
use std::hashmap::HashMap;
use std::str::eq_slice;
use std::unstable::raw::Box;
use style::{TElement, TNode};
#[deriving(Eq)]
pub enum DocumentTypeId {

View file

@ -20,8 +20,8 @@ use dom::namespace::Namespace;
use layout_interface::{ContentBoxQuery, ContentBoxResponse, ContentBoxesQuery};
use layout_interface::{ContentBoxesResponse, ContentChangedDocumentDamage};
use layout_interface::{MatchSelectorsDocumentDamage};
use style::{TElement, TNode};
use style;
use servo_util::tree::{TreeNodeRef, ElementLike};
use std::comm;
use std::hashmap::HashMap;
@ -125,7 +125,7 @@ pub enum ElementTypeId {
// Element methods
//
impl ElementLike for Element {
impl TElement for Element {
fn get_local_name<'a>(&'a self) -> &'a str {
self.tag_name.as_slice()
}

View file

@ -6,7 +6,6 @@ use dom::bindings::callback::eReportExceptions;
use dom::eventtarget::{AbstractEventTarget, Capturing, Bubbling};
use dom::event::{AbstractEvent, Phase_At_Target, Phase_None, Phase_Bubbling, Phase_Capturing};
use dom::node::AbstractNode;
use servo_util::tree::{TreeNodeRef};
// See http://dom.spec.whatwg.org/#concept-event-dispatch for the full dispatch algorithm
pub fn dispatch_event(target: AbstractEventTarget,

View file

@ -11,10 +11,8 @@ use dom::node::{AbstractNode, ScriptView, ElementNodeTypeId};
use dom::window::Window;
use js::jsapi::JSTracer;
use servo_util::tree::{TreeNodeRef, ElementLike};
use std::str::eq_slice;
use style::TElement;
pub struct HTMLDocument {
parent: Document

View file

@ -14,7 +14,7 @@ use layout_interface::{ContentBoxQuery, ContentBoxResponse};
use servo_net::image_cache_task;
use servo_net::image_cache_task::ImageCacheTask;
use servo_util::url::make_url;
use servo_util::tree::ElementLike;
use style::TElement;
pub struct HTMLImageElement {
htmlelement: HTMLElement,

View file

@ -8,7 +8,7 @@ use dom::document::AbstractDocument;
use dom::element::HTMLScriptElementTypeId;
use dom::htmlelement::HTMLElement;
use dom::node::{AbstractNode, Node, ScriptView};
use servo_util::tree::ElementLike;
use style::TElement;
pub struct HTMLScriptElement {
htmlelement: HTMLElement,

View file

@ -21,11 +21,11 @@ use dom::text::Text;
use js::jsapi::{JSObject, JSContext};
use servo_util::slot::{MutSlotRef, Slot, SlotRef};
use servo_util::tree::{TreeNode, TreeNodeRef, TreeNodeRefAsElement};
use std::cast::transmute;
use std::cast;
use std::unstable::raw::Box;
use std::util;
use style::TNode;
//
// The basic Node structure
@ -210,59 +210,17 @@ impl<View> Clone for AbstractNode<View> {
}
}
impl<View> TreeNodeRef<Node<View>> for AbstractNode<View> {
fn node<'a>(&'a self) -> &'a Node<View> {
unsafe {
&(*self.obj).data
}
impl<View> TNode<Element> for AbstractNode<View> {
fn parent_node(&self) -> Option<AbstractNode<View>> {
self.node().parent_node
}
fn mut_node<'a>(&'a self) -> &'a mut Node<View> {
unsafe {
&mut (*self.obj).data
}
fn prev_sibling(&self) -> Option<AbstractNode<View>> {
self.node().prev_sibling
}
fn parent_node(node: &Node<View>) -> Option<AbstractNode<View>> {
node.parent_node
}
fn first_child(node: &Node<View>) -> Option<AbstractNode<View>> {
node.first_child
}
fn last_child(node: &Node<View>) -> Option<AbstractNode<View>> {
node.last_child
}
fn prev_sibling(node: &Node<View>) -> Option<AbstractNode<View>> {
node.prev_sibling
}
fn next_sibling(node: &Node<View>) -> Option<AbstractNode<View>> {
node.next_sibling
}
fn set_parent_node(node: &mut Node<View>, new_parent_node: Option<AbstractNode<View>>) {
let doc = node.owner_doc();
doc.document().wait_until_safe_to_modify_dom();
node.parent_node = new_parent_node
}
fn set_first_child(node: &mut Node<View>, new_first_child: Option<AbstractNode<View>>) {
let doc = node.owner_doc();
doc.document().wait_until_safe_to_modify_dom();
node.first_child = new_first_child
}
fn set_last_child(node: &mut Node<View>, new_last_child: Option<AbstractNode<View>>) {
let doc = node.owner_doc();
doc.document().wait_until_safe_to_modify_dom();
node.last_child = new_last_child
}
fn set_prev_sibling(node: &mut Node<View>, new_prev_sibling: Option<AbstractNode<View>>) {
let doc = node.owner_doc();
doc.document().wait_until_safe_to_modify_dom();
node.prev_sibling = new_prev_sibling
}
fn set_next_sibling(node: &mut Node<View>, new_next_sibling: Option<AbstractNode<View>>) {
let doc = node.owner_doc();
doc.document().wait_until_safe_to_modify_dom();
node.next_sibling = new_next_sibling
fn next_sibling(&self) -> Option<AbstractNode<View>> {
self.node().next_sibling
}
fn is_element(&self) -> bool {
@ -278,17 +236,34 @@ impl<View> TreeNodeRef<Node<View>> for AbstractNode<View> {
_ => false
}
}
}
impl<View> TreeNodeRefAsElement<Node<View>, Element> for AbstractNode<View> {
#[inline]
fn with_imm_element_like<R>(&self, f: &fn(&Element) -> R) -> R {
fn with_element<R>(&self, f: &fn(&Element) -> R) -> R {
self.with_imm_element(f)
}
}
impl<View> AbstractNode<View> {
pub fn node<'a>(&'a self) -> &'a Node<View> {
unsafe {
&(*self.obj).data
}
}
impl<View> TreeNode<AbstractNode<View>> for Node<View> { }
pub fn mut_node<'a>(&'a self) -> &'a mut Node<View> {
unsafe {
&mut (*self.obj).data
}
}
pub fn first_child(&self) -> Option<AbstractNode<View>> {
self.node().first_child
}
pub fn last_child(&self) -> Option<AbstractNode<View>> {
self.node().last_child
}
}
impl<'self, View> AbstractNode<View> {
// Unsafe accessors
@ -335,21 +310,6 @@ impl<'self, View> AbstractNode<View> {
self.node().type_id
}
/// Returns the parent node of this node. Fails if this node is borrowed mutably.
pub fn parent_node(self) -> Option<AbstractNode<View>> {
self.node().parent_node
}
/// Returns the first child of this node. Fails if this node is borrowed mutably.
pub fn first_child(self) -> Option<AbstractNode<View>> {
self.node().first_child
}
/// Returns the last child of this node. Fails if this node is borrowed mutably.
pub fn last_child(self) -> Option<AbstractNode<View>> {
self.node().last_child
}
/// Returns the previous sibling of this node. Fails if this node is borrowed mutably.
pub fn prev_sibling(self) -> Option<AbstractNode<View>> {
self.node().prev_sibling
@ -562,6 +522,14 @@ impl<'self, View> AbstractNode<View> {
format!("{:?}", self.type_id())
}
//
// Convenience accessors
//
fn is_leaf(&self) -> bool {
self.first_child().is_none()
}
pub fn children(&self) -> AbstractNodeChildrenIterator<View> {
self.node().children()
}
@ -601,8 +569,123 @@ impl AbstractNode<ScriptView> {
document.document().content_changed();
}
//
// Pointer stitching
//
/// Adds a new child to the end of this node's list of children.
///
/// Fails unless `new_child` is disconnected from the tree.
fn add_child(&self,
new_child: AbstractNode<ScriptView>,
before: Option<AbstractNode<ScriptView>>) {
let this_node = self.mut_node();
let new_child_node = new_child.mut_node();
assert!(new_child_node.parent_node.is_none());
assert!(new_child_node.prev_sibling.is_none());
assert!(new_child_node.next_sibling.is_none());
match before {
Some(before) => {
let before_node = before.mut_node();
// XXX Should assert that parent is self.
assert!(before_node.parent_node.is_some());
before_node.set_prev_sibling(Some(new_child.clone()));
new_child_node.set_next_sibling(Some(before.clone()));
match before_node.prev_sibling {
None => {
// XXX Should assert that before is the first child of
// self.
this_node.set_first_child(Some(new_child.clone()));
},
Some(prev_sibling) => {
let prev_sibling_node = prev_sibling.mut_node();
prev_sibling_node.set_next_sibling(Some(new_child.clone()));
new_child_node.set_prev_sibling(Some(prev_sibling.clone()));
},
}
},
None => {
match this_node.last_child {
None => this_node.set_first_child(Some(new_child.clone())),
Some(last_child) => {
let last_child_node = last_child.mut_node();
assert!(last_child_node.next_sibling.is_none());
last_child_node.set_next_sibling(Some(new_child.clone()));
new_child_node.set_prev_sibling(Some(last_child.clone()));
}
}
this_node.set_last_child(Some(new_child.clone()));
},
}
new_child_node.set_parent_node(Some((*self).clone()));
}
/// Removes the given child from this node's list of children.
///
/// Fails unless `child` is a child of this node. (FIXME: This is not yet checked.)
fn remove_child(&self, child: AbstractNode<ScriptView>) {
let this_node = self.mut_node();
let child_node = child.mut_node();
assert!(child_node.parent_node.is_some());
match child_node.prev_sibling {
None => this_node.set_first_child(child_node.next_sibling),
Some(prev_sibling) => {
let prev_sibling_node = prev_sibling.mut_node();
prev_sibling_node.set_next_sibling(child_node.next_sibling);
}
}
match child_node.next_sibling {
None => this_node.set_last_child(child_node.prev_sibling),
Some(next_sibling) => {
let next_sibling_node = next_sibling.mut_node();
next_sibling_node.set_prev_sibling(child_node.prev_sibling);
}
}
child_node.set_prev_sibling(None);
child_node.set_next_sibling(None);
child_node.set_parent_node(None);
}
//
// Low-level pointer stitching wrappers
//
fn set_parent_node(&self, new_parent_node: Option<AbstractNode<ScriptView>>) {
let node = self.mut_node();
node.set_parent_node(new_parent_node)
}
fn set_first_child(&self, new_first_child: Option<AbstractNode<ScriptView>>) {
let node = self.mut_node();
node.set_first_child(new_first_child)
}
fn set_last_child(&self, new_last_child: Option<AbstractNode<ScriptView>>) {
let node = self.mut_node();
node.set_last_child(new_last_child)
}
fn set_prev_sibling(&self, new_prev_sibling: Option<AbstractNode<ScriptView>>) {
let node = self.mut_node();
node.set_prev_sibling(new_prev_sibling)
}
fn set_next_sibling(&self, new_next_sibling: Option<AbstractNode<ScriptView>>) {
let node = self.mut_node();
node.set_next_sibling(new_next_sibling)
}
}
//
// Iteration and traversal
//
impl<View> Iterator<AbstractNode<View>> for AbstractNodeChildrenIterator<View> {
fn next(&mut self) -> Option<AbstractNode<View>> {
let node = self.current_node;
@ -613,6 +696,86 @@ impl<View> Iterator<AbstractNode<View>> for AbstractNodeChildrenIterator<View> {
}
}
pub struct AncestorIterator<View> {
priv current: Option<AbstractNode<View>>,
}
impl<View> Iterator<AbstractNode<View>> for AncestorIterator<View> {
fn next(&mut self) -> Option<AbstractNode<View>> {
if self.current.is_none() {
return None;
}
// FIXME: Do we need two clones here?
let x = self.current.get_ref().clone();
self.current = x.parent_node();
Some(x.clone())
}
}
// FIXME: Do this without precomputing a vector of refs.
// Easy for preorder; harder for postorder.
pub struct TreeIterator<View> {
priv nodes: ~[AbstractNode<View>],
priv index: uint,
}
impl<View> TreeIterator<View> {
fn new(nodes: ~[AbstractNode<View>]) -> TreeIterator<View> {
TreeIterator {
nodes: nodes,
index: 0,
}
}
}
impl<View> Iterator<AbstractNode<View>> for TreeIterator<View> {
fn next(&mut self) -> Option<AbstractNode<View>> {
if self.index >= self.nodes.len() {
None
} else {
let v = self.nodes[self.index].clone();
self.index += 1;
Some(v)
}
}
}
fn gather<View>(cur: &AbstractNode<View>, refs: &mut ~[AbstractNode<View>], postorder: bool) {
if !postorder {
refs.push(cur.clone());
}
for kid in cur.children() {
gather(&kid, refs, postorder)
}
if postorder {
refs.push(cur.clone());
}
}
impl<View> AbstractNode<View> {
/// Iterates over all ancestors of this node.
pub fn ancestors(&self) -> AncestorIterator<View> {
AncestorIterator {
current: self.parent_node(),
}
}
/// Iterates over this node and all its descendants, in preorder.
pub fn traverse_preorder(&self) -> TreeIterator<View> {
let mut nodes = ~[];
gather(self, &mut nodes, false);
TreeIterator::new(nodes)
}
/// Iterates over this node and all its descendants, in postorder.
pub fn sequential_traverse_postorder(&self) -> TreeIterator<View> {
let mut nodes = ~[];
gather(self, &mut nodes, true);
TreeIterator::new(nodes)
}
}
impl<View> Node<View> {
pub fn owner_doc(&self) -> AbstractDocument {
self.owner_doc.unwrap()
@ -1215,6 +1378,41 @@ impl Node<ScriptView> {
pub fn HasAttributes(&self) -> bool {
false
}
//
// Low-level pointer stitching
//
pub fn set_parent_node(&mut self, new_parent_node: Option<AbstractNode<ScriptView>>) {
let doc = self.owner_doc();
doc.document().wait_until_safe_to_modify_dom();
self.parent_node = new_parent_node
}
pub fn set_first_child(&mut self, new_first_child: Option<AbstractNode<ScriptView>>) {
let doc = self.owner_doc();
doc.document().wait_until_safe_to_modify_dom();
self.first_child = new_first_child
}
pub fn set_last_child(&mut self, new_last_child: Option<AbstractNode<ScriptView>>) {
let doc = self.owner_doc();
doc.document().wait_until_safe_to_modify_dom();
self.last_child = new_last_child
}
pub fn set_prev_sibling(&mut self, new_prev_sibling: Option<AbstractNode<ScriptView>>) {
let doc = self.owner_doc();
doc.document().wait_until_safe_to_modify_dom();
self.prev_sibling = new_prev_sibling
}
pub fn set_next_sibling(&mut self, new_next_sibling: Option<AbstractNode<ScriptView>>) {
let doc = self.owner_doc();
doc.document().wait_until_safe_to_modify_dom();
self.next_sibling = new_next_sibling
}
}
impl Reflectable for Node<ScriptView> {