Skip to content

Commit

Permalink
Merge pull request #416 from pcwalton/refactor-flow
Browse files Browse the repository at this point in the history
Refactor flow
  • Loading branch information
metajack committed May 7, 2013
2 parents c0e79da + e06b31a commit f55b873
Show file tree
Hide file tree
Showing 22 changed files with 1,138 additions and 885 deletions.
1 change: 1 addition & 0 deletions src/servo-util/servo_util.rc
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ extern mod std;
pub mod cache;
pub mod range;
pub mod time;
pub mod tree;
pub mod url;
pub mod vec;

171 changes: 171 additions & 0 deletions src/servo-util/tree.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! Helper functions for garbage collected doubly-linked trees.

/// The basic trait. This function is meant to encapsulate a clonable reference to a tree node.
pub trait TreeNodeRef<N> : Clone {
/// Borrows this node as immutable.
fn with_imm_node<R>(&self, callback: &fn(&N) -> R) -> R;

/// Borrows this node as mutable.
fn with_mut_node<R>(&self, callback: &fn(&mut N) -> R) -> R;
}

/// The contents of a tree node.
pub trait TreeNode<NR> {
/// Returns the parent of this node.
fn parent_node(&self) -> Option<NR>;

/// Returns the first child of this node.
fn first_child(&self) -> Option<NR>;

/// Returns the last child of this node.
fn last_child(&self) -> Option<NR>;

/// Returns the previous sibling of this node.
fn prev_sibling(&self) -> Option<NR>;

/// Returns the next sibling of this node.
fn next_sibling(&self) -> Option<NR>;

/// Sets the parent of this node.
fn set_parent_node(&mut self, new_parent: Option<NR>);

/// Sets the first child of this node.
fn set_first_child(&mut self, new_first_child: Option<NR>);

/// Sets the last child of this node.
fn set_last_child(&mut self, new_last_child: Option<NR>);

/// Sets the previous sibling of this node.
fn set_prev_sibling(&mut self, new_prev_sibling: Option<NR>);

/// Sets the next sibling of this node.
fn set_next_sibling(&mut self, new_next_sibling: Option<NR>);
}

/// A set of helper functions useful for operating on trees.
pub trait TreeUtils {
/// Returns true if this node is disconnected from the tree or has no children.
fn is_leaf(&self) -> bool;

/// 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: Self);

/// 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: Self);

/// Iterates over all children of this node.
fn each_child(&self, callback: &fn(Self) -> bool);

/// Iterates over this node and all its descendants, in preorder.
fn traverse_preorder(&self, callback: &fn(Self) -> bool) -> bool;

/// Iterates over this node and all its descendants, in postorder.
fn traverse_postorder(&self, callback: &fn(Self) -> bool) -> bool;
}

impl<NR:TreeNodeRef<N>,N:TreeNode<NR>> TreeUtils for NR {
fn is_leaf(&self) -> bool {
do self.with_imm_node |this_node| {
this_node.first_child().is_none()
}
}

fn add_child(&self, new_child: NR) {
do self.with_mut_node |this_node| {
do new_child.with_mut_node |new_child_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 this_node.last_child() {
None => this_node.set_first_child(Some(new_child.clone())),
Some(last_child) => {
do last_child.with_mut_node |last_child_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()));
}
}
}

fn remove_child(&self, child: NR) {
do self.with_mut_node |this_node| {
do child.with_mut_node |child_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) => {
do prev_sibling.with_mut_node |prev_sibling_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) => {
do next_sibling.with_mut_node |next_sibling_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);
}
}
}

fn each_child(&self, callback: &fn(NR) -> bool) {
let mut maybe_current = self.with_imm_node(|n| n.first_child());
while !maybe_current.is_none() {
let current = maybe_current.get_ref().clone();
if !callback(current.clone()) {
break;
}

maybe_current = current.with_imm_node(|n| n.next_sibling());
}
}

fn traverse_preorder(&self, callback: &fn(NR) -> bool) -> bool {
if !callback((*self).clone()) {
return false;
}

for self.each_child |kid| {
if !kid.traverse_preorder(callback) {
return false;
}
}

true
}

fn traverse_postorder(&self, callback: &fn(NR) -> bool) -> bool {
for self.each_child |kid| {
if !kid.traverse_postorder(callback) {
return false;
}
}

callback((*self).clone())
}
}

40 changes: 18 additions & 22 deletions src/servo/content/content_task.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,42 +2,41 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

/*!
The content task is the main task that runs JavaScript and spawns layout
tasks.
*/
/// The content task (also called the script task) is the main task that owns the DOM in memory,
/// runs JavaScript, and spawns parsing and layout tasks.

use dom::bindings::utils::GlobalStaticData;
use dom::document::Document;
use dom::node::define_bindings;
use dom::event::{Event, ResizeEvent, ReflowEvent};
use dom::node::define_bindings;
use dom::window::Window;
use layout::layout_task;
use layout::layout_task::{AddStylesheet, BuildData, BuildMsg, Damage, LayoutTask};
use layout::layout_task::{MatchSelectorsDamage, NoDamage, ReflowDamage};
use layout::layout_task;

use core::cell::Cell;
use core::comm::{Port, SharedChan};
use core::pipes::select2i;
use core::either;
use core::task::{SingleThreaded, task};
use core::io::{println, read_whole_file};
use core::pipes::select2i;
use core::ptr::null;
use core::task::{SingleThreaded, task};
use core::util::replace;
use dom;
use geom::size::Size2D;
use gfx::resource::image_cache_task::ImageCacheTask;
use gfx::resource::resource_task::ResourceTask;
use html;
use js::JSVAL_NULL;
use js::global::{global_class, debug_fns};
use js::glue::bindgen::RUST_JSVAL_TO_OBJECT;
use js::jsapi::JSContext;
use js::jsapi::bindgen::{JS_CallFunctionValue, JS_GetContextPrivate};
use js::rust::{Compartment, Cx};
use jsrt = js::rust::rt;
use servo_util::tree::TreeNodeRef;
use std::net::url::Url;
use url_to_str = std::net::url::to_str;
use dom;
use html;

pub enum ControlMsg {
ParseMsg(Url),
Expand Down Expand Up @@ -312,24 +311,20 @@ pub impl Content {
}
}

/**
This method will wait until the layout task has completed its current action,
join the layout task, and then request a new layout run. It won't wait for the
new layout computation to finish.
*/
/// This method will wait until the layout task has completed its current action, join the
/// layout task, and then request a new layout run. It won't wait for the new layout
/// computation to finish.
fn relayout(&mut self, document: &Document, doc_url: &Url) {
debug!("content: performing relayout");

// Now, join the layout so that they will see the latest
// changes we have made.
// Now, join the layout so that they will see the latest changes we have made.
self.join_layout();

// Layout will let us know when it's done
// Layout will let us know when it's done.
let (join_port, join_chan) = comm::stream();
self.layout_join_port = Some(join_port);

// Send new document and relevant styles to layout

// Send new document and relevant styles to layout.
let data = ~BuildData {
node: document.root,
url: copy *doc_url,
Expand All @@ -344,7 +339,8 @@ pub impl Content {
debug!("content: layout forked");
}

fn query_layout(&mut self, query: layout_task::LayoutQuery) -> layout_task::LayoutQueryResponse {
fn query_layout(&mut self, query: layout_task::LayoutQuery)
-> layout_task::LayoutQueryResponse {
//self.relayout(self.document.get(), &(copy self.doc_url).get());
self.join_layout();

Expand Down Expand Up @@ -378,7 +374,7 @@ pub impl Content {
ReflowEvent => {
debug!("content got reflow event");
self.damage.add(MatchSelectorsDamage);
match copy self.document {
match /*bad*/ copy self.document {
None => {
// Nothing to do.
}
Expand Down
2 changes: 2 additions & 0 deletions src/servo/css/matching.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ use dom::node::AbstractNode;
use newcss::complete::CompleteSelectResults;
use newcss::select::{SelectCtx, SelectResults};

use servo_util::tree::TreeUtils;

pub trait MatchMethods {
fn restyle_subtree(&self, select_ctx: &SelectCtx);
}
Expand Down
23 changes: 13 additions & 10 deletions src/servo/dom/bindings/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use js::jsval::{INT_TO_JSVAL};
use js::rust::{Compartment, jsobj};
use js::{JSPROP_ENUMERATE, JSPROP_SHARED, JSVAL_NULL};
use js::{JS_THIS_OBJECT, JSPROP_NATIVE_ACCESSORS};
use servo_util::tree::TreeNodeRef;

pub fn init(compartment: @mut Compartment) {
let obj = utils::define_empty_prototype(~"Node", None, compartment);
Expand Down Expand Up @@ -127,19 +128,19 @@ impl Node {

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_node blocks.
Some(ref mut n) => Some(unsafe { cast::transmute(n) }),
None => None
// transmute because the compiler can't deduce that the reference
// is safe outside of with_mut_node blocks.
Some(ref mut n) => Some(unsafe { cast::transmute(n) }),
None => None
}
}

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_node blocks.
Some(ref mut n) => Some(unsafe { cast::transmute(n) }),
None => None
// transmute because the compiler can't deduce that the reference
// is safe outside of with_mut_node blocks.
Some(ref mut n) => Some(unsafe { cast::transmute(n) }),
None => None
}
}
}
Expand All @@ -162,8 +163,10 @@ extern fn getNodeType(cx: *JSContext, _argc: c_uint, vp: *mut JSVal) -> JSBool {

impl CacheableWrapper for AbstractNode {
fn get_wrappercache(&mut self) -> &mut WrapperCache {
do self.with_mut_node |n| {
unsafe { cast::transmute(&n.wrapper) }
do self.with_mut_node |node| {
unsafe {
cast::transmute(&node.wrapper)
}
}
}

Expand Down

0 comments on commit f55b873

Please sign in to comment.