Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor flow #416

Merged
merged 12 commits into from May 7, 2013
@@ -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;

@@ -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())
}
}

@@ -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),
@@ -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,
@@ -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();

@@ -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.
}
@@ -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);
}
@@ -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);
@@ -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
}
}
}
@@ -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)
}
}
}

ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.