Introduce a phantom type to prevent script from accessing the layout data directly.

Nodes are now parameterized over a "View" type. The particular View type
determines which methods can be called. Layout data accessors and mutators are
only accessible to nodes with a LayoutView. The only way to convert a
`Node<ScriptView>` to a `Node<LayoutView>` is through a transmutation, which is
done at the moment the layout task receives nodes. (This should be factored
better to contain the unsafety.)

We should also lock down DOM node mutation to the ScriptView to forbid data
races, but this patch doesn't do that.

This also reduces coupling between DOM and layout. Soon I would like to move
the DOM into its own crate, and this is a step on the way of doing that.
This commit is contained in:
Patrick Walton 2013-05-21 18:18:05 -07:00
parent c7bce98236
commit 4f3ca373d4
23 changed files with 262 additions and 189 deletions

View file

@ -6,7 +6,7 @@
use css::node_util::NodeUtil;
use css::select_handler::NodeSelectHandler;
use dom::node::AbstractNode;
use dom::node::{AbstractNode, LayoutView};
use newcss::complete::CompleteSelectResults;
use newcss::select::{SelectCtx, SelectResults};
@ -16,7 +16,7 @@ pub trait MatchMethods {
fn restyle_subtree(&self, select_ctx: &SelectCtx);
}
impl MatchMethods for AbstractNode {
impl MatchMethods for AbstractNode<LayoutView> {
/**
* Performs CSS selector matching on a subtree.
*
@ -40,7 +40,8 @@ impl MatchMethods for AbstractNode {
}
}
fn compose_results(node: AbstractNode, results: SelectResults) -> CompleteSelectResults {
fn compose_results(node: AbstractNode<LayoutView>, results: SelectResults)
-> CompleteSelectResults {
match find_parent_element_node(node) {
None => CompleteSelectResults::new_root(results),
Some(parent_node) => {
@ -50,7 +51,7 @@ fn compose_results(node: AbstractNode, results: SelectResults) -> CompleteSelect
}
}
fn find_parent_element_node(node: AbstractNode) -> Option<AbstractNode> {
fn find_parent_element_node(node: AbstractNode<LayoutView>) -> Option<AbstractNode<LayoutView>> {
match node.parent_node() {
Some(parent) if parent.is_element() => Some(parent),
Some(parent) => find_parent_element_node(parent),

View file

@ -5,7 +5,8 @@
// Style retrieval from DOM elements.
use css::node_util::NodeUtil;
use dom::node::AbstractNode;
use dom::node::{AbstractNode, LayoutView};
use newcss::complete::CompleteStyle;
/// Node mixin providing `style` method that returns a `NodeStyle`
@ -13,7 +14,7 @@ pub trait StyledNode {
fn style(&self) -> CompleteStyle;
}
impl StyledNode for AbstractNode {
impl StyledNode for AbstractNode<LayoutView> {
fn style(&self) -> CompleteStyle {
assert!(self.is_element()); // Only elements can have styles
let results = self.get_css_select_results();

View file

@ -2,17 +2,18 @@
* 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/. */
use dom::node::AbstractNode;
use newcss::complete::CompleteSelectResults;
use dom::node::{AbstractNode, LayoutView};
use layout::aux::LayoutAuxMethods;
use core::cast::transmute;
use newcss::complete::CompleteSelectResults;
pub trait NodeUtil<'self> {
fn get_css_select_results(self) -> &'self CompleteSelectResults;
fn set_css_select_results(self, decl: CompleteSelectResults);
}
impl<'self> NodeUtil<'self> for AbstractNode {
impl<'self> NodeUtil<'self> for AbstractNode<LayoutView> {
/**
* Provides the computed style for the given node. If CSS selector
* Returns the style results for the given node. If CSS selector

View file

@ -5,15 +5,15 @@
//! CSS library requires that DOM nodes be convertable to *c_void through this trait
extern mod netsurfcss;
use dom::node::AbstractNode;
use dom::node::{AbstractNode, LayoutView};
use core::cast;
// FIXME: Rust #3908. rust-css can't reexport VoidPtrLike
use css::node_void_ptr::netsurfcss::util::VoidPtrLike;
impl VoidPtrLike for AbstractNode {
fn from_void_ptr(node: *libc::c_void) -> AbstractNode {
impl VoidPtrLike for AbstractNode<LayoutView> {
fn from_void_ptr(node: *libc::c_void) -> AbstractNode<LayoutView> {
assert!(node.is_not_null());
unsafe {
cast::transmute(node)

View file

@ -6,16 +6,16 @@
/// Implementation of the callbacks that the CSS selector engine uses to query the DOM.
///
use dom::node::AbstractNode;
use dom::node::{AbstractNode, LayoutView};
use newcss::select::SelectHandler;
use core::str::eq_slice;
pub struct NodeSelectHandler {
node: AbstractNode
node: AbstractNode<LayoutView>,
}
fn with_node_name<R>(node: AbstractNode, f: &fn(&str) -> R) -> R {
fn with_node_name<R>(node: AbstractNode<LayoutView>, f: &fn(&str) -> R) -> R {
if !node.is_element() {
fail!(~"attempting to style non-element node");
}
@ -24,12 +24,13 @@ fn with_node_name<R>(node: AbstractNode, f: &fn(&str) -> R) -> R {
}
}
impl SelectHandler<AbstractNode> for NodeSelectHandler {
fn with_node_name<R>(&self, node: &AbstractNode, f: &fn(&str) -> R) -> R {
impl SelectHandler<AbstractNode<LayoutView>> for NodeSelectHandler {
fn with_node_name<R>(&self, node: &AbstractNode<LayoutView>, f: &fn(&str) -> R) -> R {
with_node_name(*node, f)
}
fn named_parent_node(&self, node: &AbstractNode, name: &str) -> Option<AbstractNode> {
fn named_parent_node(&self, node: &AbstractNode<LayoutView>, name: &str)
-> Option<AbstractNode<LayoutView>> {
match node.parent_node() {
Some(parent) => {
do with_node_name(parent) |node_name| {
@ -44,12 +45,13 @@ impl SelectHandler<AbstractNode> for NodeSelectHandler {
}
}
fn parent_node(&self, node: &AbstractNode) -> Option<AbstractNode> {
fn parent_node(&self, node: &AbstractNode<LayoutView>) -> Option<AbstractNode<LayoutView>> {
node.parent_node()
}
// TODO: Use a Bloom filter.
fn named_ancestor_node(&self, node: &AbstractNode, name: &str) -> Option<AbstractNode> {
fn named_ancestor_node(&self, node: &AbstractNode<LayoutView>, name: &str)
-> Option<AbstractNode<LayoutView>> {
let mut node = *node;
loop {
let parent = node.parent_node();
@ -71,11 +73,11 @@ impl SelectHandler<AbstractNode> for NodeSelectHandler {
}
}
fn node_is_root(&self, node: &AbstractNode) -> bool {
fn node_is_root(&self, node: &AbstractNode<LayoutView>) -> bool {
self.parent_node(node).is_none()
}
fn with_node_id<R>(&self, node: &AbstractNode, f: &fn(Option<&str>) -> R) -> R {
fn with_node_id<R>(&self, node: &AbstractNode<LayoutView>, f: &fn(Option<&str>) -> R) -> R {
if !node.is_element() {
fail!(~"attempting to style non-element node");
}
@ -84,7 +86,7 @@ impl SelectHandler<AbstractNode> for NodeSelectHandler {
}
}
fn node_has_id(&self, node: &AbstractNode, id: &str) -> bool {
fn node_has_id(&self, node: &AbstractNode<LayoutView>, id: &str) -> bool {
if !node.is_element() {
fail!(~"attempting to style non-element node");
}

View file

@ -513,7 +513,7 @@ addExternalIface('CSSValue')
addExternalIface('Document', nativeType='Document', pointerType='@mut ')
addExternalIface('DOMStringList', nativeType='nsDOMStringList',
headerFile='nsDOMLists.h')
addExternalIface('Element', nativeType='AbstractNode', pointerType='')
addExternalIface('Element', nativeType='AbstractNode<ScriptView>', pointerType='')
addExternalIface('File')
addExternalIface('HitRegionOptions', nativeType='nsISupports')
addExternalIface('HTMLElement')

View file

@ -4149,6 +4149,7 @@ class CGBindingRoot(CGThing):
'dom::eventtarget::*', #XXXjdm
'scripting::script_task::task_from_context',
'dom::bindings::utils::EnumEntry',
'dom::node::ScriptView',
],
[],
curr)

View file

@ -7,7 +7,7 @@ use dom::bindings::utils::jsval_to_str;
use dom::bindings::utils::{domstring_to_jsval, WrapNewBindingObject};
use dom::bindings::utils::{str, CacheableWrapper, DOM_OBJECT_SLOT, DOMString};
use dom::element::*;
use dom::node::{AbstractNode, Element, ElementNodeTypeId};
use dom::node::{AbstractNode, Element, ElementNodeTypeId, ScriptView};
use layout::layout_task;
use scripting::script_task::task_from_context;
use super::utils;
@ -26,7 +26,7 @@ use js::{JS_THIS_OBJECT, JS_SET_RVAL, JSPROP_NATIVE_ACCESSORS};
extern fn finalize(_fop: *JSFreeOp, obj: *JSObject) {
debug!("element finalize: %x!", obj as uint);
unsafe {
let node: AbstractNode = unwrap(obj);
let node: AbstractNode<ScriptView> = unwrap(obj);
//XXXjdm We need separate finalizers for each specialty element type like headings
let _elem: ~Element = cast::transmute(node.raw_object());
}
@ -35,7 +35,7 @@ extern fn finalize(_fop: *JSFreeOp, obj: *JSObject) {
pub extern fn trace(tracer: *mut JSTracer, obj: *JSObject) {
let node = unsafe { unwrap(obj) };
fn trace_node(tracer: *mut JSTracer, node: Option<AbstractNode>, name: &str) {
fn trace_node(tracer: *mut JSTracer, node: Option<AbstractNode<ScriptView>>, name: &str) {
if node.is_none() {
return;
}
@ -278,7 +278,7 @@ extern fn getTagName(cx: *JSContext, _argc: c_uint, vp: *mut JSVal) -> JSBool {
return 1;
}
pub fn create(cx: *JSContext, node: &mut AbstractNode) -> jsobj {
pub fn create(cx: *JSContext, node: &mut AbstractNode<ScriptView>) -> jsobj {
let proto = match node.type_id() {
ElementNodeTypeId(HTMLDivElementTypeId) => ~"HTMLDivElement",
ElementNodeTypeId(HTMLHeadElementTypeId) => ~"HTMLHeadElement",

View file

@ -7,7 +7,7 @@ use dom::bindings::text;
use dom::bindings::utils;
use dom::bindings::utils::{CacheableWrapper, WrapperCache, DerivedWrapper};
use dom::node::{AbstractNode, Node, ElementNodeTypeId, TextNodeTypeId, CommentNodeTypeId};
use dom::node::{DoctypeNodeTypeId};
use dom::node::{DoctypeNodeTypeId, ScriptView};
use core::libc::c_uint;
use core::ptr::null;
@ -58,7 +58,7 @@ pub fn init(compartment: @mut Compartment) {
}
#[allow(non_implicitly_copyable_typarams)]
pub fn create(cx: *JSContext, node: &mut AbstractNode) -> jsobj {
pub fn create(cx: *JSContext, node: &mut AbstractNode<ScriptView>) -> jsobj {
match node.type_id() {
ElementNodeTypeId(_) => element::create(cx, node),
TextNodeTypeId |
@ -67,8 +67,8 @@ pub fn create(cx: *JSContext, node: &mut AbstractNode) -> jsobj {
}
}
pub unsafe fn unwrap(obj: *JSObject) -> AbstractNode {
let raw = utils::unwrap::<*mut Node>(obj);
pub unsafe fn unwrap(obj: *JSObject) -> AbstractNode<ScriptView> {
let raw = utils::unwrap::<*mut Node<ScriptView>>(obj);
AbstractNode::from_raw(raw)
}
@ -116,7 +116,7 @@ extern fn getNextSibling(cx: *JSContext, _argc: c_uint, vp: *mut JSVal) -> JSBoo
return 1;
}
impl Node {
impl Node<ScriptView> {
fn getNodeType(&self) -> i32 {
match self.type_id {
ElementNodeTypeId(_) => 1,
@ -126,7 +126,7 @@ impl Node {
}
}
fn getNextSibling(&mut self) -> Option<&mut AbstractNode> {
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.
@ -135,7 +135,7 @@ impl Node {
}
}
fn getFirstChild(&mut self) -> Option<&mut AbstractNode> {
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.
@ -161,7 +161,7 @@ extern fn getNodeType(cx: *JSContext, _argc: c_uint, vp: *mut JSVal) -> JSBool {
return 1;
}
impl CacheableWrapper for AbstractNode {
impl CacheableWrapper for AbstractNode<ScriptView> {
fn get_wrappercache(&mut self) -> &mut WrapperCache {
do self.with_mut_base |base| {
unsafe {

View file

@ -7,7 +7,7 @@ use dom::bindings::node::unwrap;
use dom::bindings::utils;
use dom::bindings::utils::{DOM_OBJECT_SLOT, CacheableWrapper};
use dom::node::{AbstractNode, Text, Comment, Doctype, TextNodeTypeId, CommentNodeTypeId};
use dom::node::{DoctypeNodeTypeId};
use dom::node::{DoctypeNodeTypeId, ScriptView};
use js::jsapi::{JSFreeOp, JSObject, JSContext};
use js::jsapi::bindgen::{JS_SetReservedSlot};
@ -17,7 +17,7 @@ use js::rust::{Compartment, jsobj};
extern fn finalize_text(_fop: *JSFreeOp, obj: *JSObject) {
debug!("text finalize: %?!", obj as uint);
unsafe {
let node: AbstractNode = unwrap(obj);
let node: AbstractNode<ScriptView> = unwrap(obj);
let _elem: ~Text = cast::transmute(node.raw_object());
}
}
@ -25,7 +25,7 @@ extern fn finalize_text(_fop: *JSFreeOp, obj: *JSObject) {
extern fn finalize_comment(_fop: *JSFreeOp, obj: *JSObject) {
debug!("comment finalize: %?!", obj as uint);
unsafe {
let node: AbstractNode = unwrap(obj);
let node: AbstractNode<ScriptView> = unwrap(obj);
let _elem: ~Comment = cast::transmute(node.raw_object());
}
}
@ -33,8 +33,8 @@ extern fn finalize_comment(_fop: *JSFreeOp, obj: *JSObject) {
extern fn finalize_doctype(_fop: *JSFreeOp, obj: *JSObject) {
debug!("doctype finalize: %?!", obj as uint);
unsafe {
let node: AbstractNode = unwrap(obj);
let _elem: ~Doctype = cast::transmute(node.raw_object());
let node: AbstractNode<ScriptView> = unwrap(obj);
let _elem: ~Doctype<ScriptView> = cast::transmute(node.raw_object());
}
}
@ -64,7 +64,7 @@ pub fn init(compartment: @mut Compartment) {
}
pub fn create(cx: *JSContext, node: &mut AbstractNode) -> jsobj {
pub fn create(cx: *JSContext, node: &mut AbstractNode<ScriptView>) -> jsobj {
let (proto, instance) = match node.type_id() {
TextNodeTypeId => (~"TextPrototype", ~"Text"),
CommentNodeTypeId => (~"CommentPrototype", ~"Comment"),

View file

@ -3,7 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use dom::bindings::node;
use dom::node::AbstractNode;
use dom::node::{AbstractNode, ScriptView};
use js::glue::bindgen::*;
use js::glue::bindgen::{DefineFunctionWithReserved, GetObjectJSClass, RUST_OBJECT_TO_JSVAL};
use js::glue::{PROPERTY_STUB, STRICT_PROPERTY_STUB, ENUMERATE_STUB, CONVERT_STUB, RESOLVE_STUB};
@ -760,7 +760,7 @@ pub trait DerivedWrapper {
fn wrap_shared(@mut self, cx: *JSContext, scope: *JSObject, vp: *mut JSVal) -> i32;
}
impl DerivedWrapper for AbstractNode {
impl DerivedWrapper for AbstractNode<ScriptView> {
fn wrap(&mut self, cx: *JSContext, _scope: *JSObject, vp: *mut JSVal) -> i32 {
let cache = self.get_wrappercache();
let wrapper = cache.get_wrapper();

View file

@ -5,12 +5,12 @@
//! DOM bindings for `CharacterData`.
use dom::bindings::utils::{DOMString, null_string, str};
use dom::node::{Node, NodeTypeId};
use dom::node::{Node, NodeTypeId, ScriptView};
use core::str;
pub struct CharacterData {
parent: Node,
parent: Node<ScriptView>,
data: DOMString
}

View file

@ -5,7 +5,7 @@
use dom::bindings::document;
use dom::bindings::utils::{DOMString, WrapperCache};
use dom::htmlcollection::HTMLCollection;
use dom::node::AbstractNode;
use dom::node::{AbstractNode, ScriptView};
use dom::window::Window;
use scripting::script_task::global_script_context;
@ -13,12 +13,12 @@ use js::jsapi::bindgen::{JS_AddObjectRoot, JS_RemoveObjectRoot};
use servo_util::tree::{TreeNodeRef, TreeUtils};
pub struct Document {
root: AbstractNode,
root: AbstractNode<ScriptView>,
wrapper: WrapperCache,
window: Option<@mut Window>,
}
pub fn Document(root: AbstractNode, window: Option<@mut Window>) -> @mut Document {
pub fn Document(root: AbstractNode<ScriptView>, window: Option<@mut Window>) -> @mut Document {
let doc = @mut Document {
root: root,
wrapper: WrapperCache::new(),

View file

@ -6,7 +6,7 @@
// Element nodes.
//
use dom::node::{ElementNodeTypeId, Node};
use dom::node::{ElementNodeTypeId, Node, ScriptView};
use dom::clientrect::ClientRect;
use dom::clientrectlist::ClientRectList;
use dom::bindings::utils::DOMString;
@ -18,7 +18,7 @@ use core::cell::Cell;
use std::net::url::Url;
pub struct Element {
parent: Node,
parent: Node<ScriptView>,
tag_name: ~str, // TODO: This should be an atom, not a ~str.
attrs: ~[Attr],
}

View file

@ -4,17 +4,17 @@
use dom::bindings::utils::WrapperCache;
use dom::bindings::utils::{DOMString, ErrorResult};
use dom::node::AbstractNode;
use dom::node::{AbstractNode, ScriptView};
use js::jsapi::{JSObject, JSContext};
pub struct HTMLCollection {
elements: ~[AbstractNode],
elements: ~[AbstractNode<ScriptView>],
wrapper: WrapperCache
}
pub impl HTMLCollection {
fn new(elements: ~[AbstractNode]) -> @mut HTMLCollection {
fn new(elements: ~[AbstractNode<ScriptView>]) -> @mut HTMLCollection {
let collection = @mut HTMLCollection {
elements: elements,
wrapper: WrapperCache::new()
@ -27,7 +27,7 @@ pub impl HTMLCollection {
self.elements.len() as u32
}
fn Item(&self, index: u32) -> Option<AbstractNode> {
fn Item(&self, index: u32) -> Option<AbstractNode<ScriptView>> {
if index < self.Length() {
Some(self.elements[index])
} else {
@ -40,7 +40,7 @@ pub impl HTMLCollection {
ptr::null()
}
fn IndexedGetter(&self, index: u32, found: &mut bool) -> Option<AbstractNode> {
fn IndexedGetter(&self, index: u32, found: &mut bool) -> Option<AbstractNode<ScriptView>> {
*found = true;
self.Item(index)
}

View file

@ -13,65 +13,75 @@ use dom::document::Document;
use dom::element::{Element, ElementTypeId, HTMLImageElement, HTMLImageElementTypeId};
use dom::element::{HTMLStyleElementTypeId};
use layout::debug::DebugMethods;
use layout::flow::FlowContext;
use scripting::script_task::global_script_context;
use core::cast::transmute;
use js::rust::Compartment;
use newcss::complete::CompleteSelectResults;
use servo_util::tree::{TreeNode, TreeNodeRef, TreeUtils};
//
// The basic Node structure
//
/// A phantom type representing the script task's view of this node. Script is able to mutate
/// nodes but may not access layout data.
pub struct ScriptView;
/// A phantom type representing the layout task's view of the node. Layout is not allowed to mutate
/// nodes but may access layout data.
pub struct LayoutView;
/// This is what a Node looks like if you do not know what kind of node it is. To unpack it, use
/// downcast().
///
/// FIXME: This should be replaced with a trait once they can inherit from structs.
pub struct AbstractNode {
priv obj: *mut Node,
pub struct AbstractNode<View> {
priv obj: *mut Node<View>,
}
impl Eq for AbstractNode {
fn eq(&self, other: &AbstractNode) -> bool {
impl<View> Eq for AbstractNode<View> {
fn eq(&self, other: &AbstractNode<View>) -> bool {
self.obj == other.obj
}
fn ne(&self, other: &AbstractNode) -> bool {
fn ne(&self, other: &AbstractNode<View>) -> bool {
self.obj != other.obj
}
}
/// An HTML node.
pub struct Node {
///
/// `View` describes extra data associated with this node that this task has access to. For
/// the script task, this is the unit type `()`. For the layout task, this is
/// `layout::aux::LayoutData`.
pub struct Node<View> {
/// The JavaScript wrapper for this node.
wrapper: WrapperCache,
/// The type of node that this is.
type_id: NodeTypeId,
abstract: Option<AbstractNode>,
abstract: Option<AbstractNode<View>>,
/// The parent of this node.
parent_node: Option<AbstractNode>,
parent_node: Option<AbstractNode<View>>,
/// The first child of this node.
first_child: Option<AbstractNode>,
first_child: Option<AbstractNode<View>>,
/// The last child of this node.
last_child: Option<AbstractNode>,
last_child: Option<AbstractNode<View>>,
/// The next sibling of this node.
next_sibling: Option<AbstractNode>,
next_sibling: Option<AbstractNode<View>>,
/// The previous sibling of this node.
prev_sibling: Option<AbstractNode>,
prev_sibling: Option<AbstractNode<View>>,
/// The document that this node belongs to.
owner_doc: Option<@mut Document>,
/// Layout information. You must not touch this if you are not layout.
priv layout_data: Option<@mut LayoutData>
/// Layout information. Only the layout task may touch this data.
priv layout_data: Option<@mut ()>
}
/// The different types of nodes.
@ -83,49 +93,26 @@ pub enum NodeTypeId {
TextNodeTypeId,
}
//
// Auxiliary layout data
//
/// Data that layout associates with a node.
pub struct LayoutData {
/// The results of CSS styling for this node.
style: Option<CompleteSelectResults>,
/// The CSS flow that this node is associated with.
flow: Option<FlowContext>,
}
impl LayoutData {
/// Creates new layout data.
pub fn new() -> LayoutData {
LayoutData {
style: None,
flow: None,
}
}
}
//
// Basic node types
//
/// The `DOCTYPE` tag.
pub struct Doctype {
parent: Node,
pub struct Doctype<View> {
parent: Node<View>,
name: ~str,
public_id: Option<~str>,
system_id: Option<~str>,
force_quirks: bool
}
impl Doctype {
impl Doctype<ScriptView> {
/// Creates a new `DOCTYPE` tag.
pub fn new(name: ~str,
public_id: Option<~str>,
system_id: Option<~str>,
force_quirks: bool)
-> Doctype {
-> Doctype<ScriptView> {
Doctype {
parent: Node::new(DoctypeNodeTypeId),
name: name,
@ -164,58 +151,81 @@ impl Text {
}
}
impl Clone for AbstractNode {
fn clone(&self) -> AbstractNode {
impl<View> Clone for AbstractNode<View> {
fn clone(&self) -> AbstractNode<View> {
*self
}
}
impl TreeNode<AbstractNode> for Node {
fn parent_node(&self) -> Option<AbstractNode> {
impl<View> TreeNode<AbstractNode<View>> for Node<View> {
fn parent_node(&self) -> Option<AbstractNode<View>> {
self.parent_node
}
fn first_child(&self) -> Option<AbstractNode> {
fn first_child(&self) -> Option<AbstractNode<View>> {
self.first_child
}
fn last_child(&self) -> Option<AbstractNode> {
fn last_child(&self) -> Option<AbstractNode<View>> {
self.last_child
}
fn prev_sibling(&self) -> Option<AbstractNode> {
fn prev_sibling(&self) -> Option<AbstractNode<View>> {
self.prev_sibling
}
fn next_sibling(&self) -> Option<AbstractNode> {
fn next_sibling(&self) -> Option<AbstractNode<View>> {
self.next_sibling
}
fn set_parent_node(&mut self, new_parent_node: Option<AbstractNode>) {
fn set_parent_node(&mut self, new_parent_node: Option<AbstractNode<View>>) {
self.parent_node = new_parent_node
}
fn set_first_child(&mut self, new_first_child: Option<AbstractNode>) {
fn set_first_child(&mut self, new_first_child: Option<AbstractNode<View>>) {
self.first_child = new_first_child
}
fn set_last_child(&mut self, new_last_child: Option<AbstractNode>) {
fn set_last_child(&mut self, new_last_child: Option<AbstractNode<View>>) {
self.last_child = new_last_child
}
fn set_prev_sibling(&mut self, new_prev_sibling: Option<AbstractNode>) {
fn set_prev_sibling(&mut self, new_prev_sibling: Option<AbstractNode<View>>) {
self.prev_sibling = new_prev_sibling
}
fn set_next_sibling(&mut self, new_next_sibling: Option<AbstractNode>) {
fn set_next_sibling(&mut self, new_next_sibling: Option<AbstractNode<View>>) {
self.next_sibling = new_next_sibling
}
}
impl TreeNodeRef<Node> for AbstractNode {
impl<View> TreeNodeRef<Node<View>> for AbstractNode<View> {
// FIXME: The duplication between `with_base` and `with_mut_base` is ugly.
fn with_base<R>(&self, callback: &fn(&Node) -> R) -> R {
fn with_base<R>(&self, callback: &fn(&Node<View>) -> R) -> R {
self.transmute(callback)
}
fn with_mut_base<R>(&self, callback: &fn(&mut Node) -> R) -> R {
fn with_mut_base<R>(&self, callback: &fn(&mut Node<View>) -> R) -> R {
self.transmute_mut(callback)
}
}
impl AbstractNode {
impl<View> AbstractNode<View> {
// Unsafe accessors
/// Returns the layout data, unsafely cast to whatever type layout wishes. Only layout is
/// allowed to call this. This is wildly unsafe and is therefore marked as such.
pub unsafe fn unsafe_layout_data<T>(self) -> @mut T {
do self.with_base |base| {
transmute(base.layout_data.get())
}
}
/// Returns true if this node has layout data and false otherwise.
pub unsafe fn unsafe_has_layout_data(self) -> bool {
do self.with_base |base| {
base.layout_data.is_some()
}
}
/// Sets the layout data, unsafely casting the type as layout wishes. Only layout is allowed
/// to call this. This is wildly unsafe and is therefore marked as such.
pub unsafe fn unsafe_set_layout_data<T>(self, data: @mut T) {
do self.with_mut_base |base| {
base.layout_data = Some(transmute(data))
}
}
// Convenience accessors
/// Returns the type ID of this node. Fails if this node is borrowed mutably.
@ -224,49 +234,37 @@ impl AbstractNode {
}
/// Returns the parent node of this node. Fails if this node is borrowed mutably.
pub fn parent_node(self) -> Option<AbstractNode> {
pub fn parent_node(self) -> Option<AbstractNode<View>> {
self.with_base(|b| b.parent_node)
}
/// Returns the first child of this node. Fails if this node is borrowed mutably.
pub fn first_child(self) -> Option<AbstractNode> {
pub fn first_child(self) -> Option<AbstractNode<View>> {
self.with_base(|b| b.first_child)
}
/// Returns the last child of this node. Fails if this node is borrowed mutably.
pub fn last_child(self) -> Option<AbstractNode> {
pub fn last_child(self) -> Option<AbstractNode<View>> {
self.with_base(|b| b.last_child)
}
/// Returns the previous sibling of this node. Fails if this node is borrowed mutably.
pub fn prev_sibling(self) -> Option<AbstractNode> {
pub fn prev_sibling(self) -> Option<AbstractNode<View>> {
self.with_base(|b| b.prev_sibling)
}
/// Returns the next sibling of this node. Fails if this node is borrowed mutably.
pub fn next_sibling(self) -> Option<AbstractNode> {
pub fn next_sibling(self) -> Option<AbstractNode<View>> {
self.with_base(|b| b.next_sibling)
}
// NB: You must not call these if you are not layout. We should do something with scoping to
// ensure this.
pub fn layout_data(self) -> @mut LayoutData {
self.with_base(|b| b.layout_data.get())
}
pub fn has_layout_data(self) -> bool {
self.with_base(|b| b.layout_data.is_some())
}
pub fn set_layout_data(self, data: @mut LayoutData) {
self.with_mut_base(|b| b.layout_data = Some(data))
}
//
// Downcasting borrows
//
pub fn transmute<T, R>(self, f: &fn(&T) -> R) -> R {
unsafe {
let node_box: *mut bindings::utils::rust_box<Node> = transmute(self.obj);
let node_box: *mut bindings::utils::rust_box<Node<View>> = transmute(self.obj);
let node = &mut (*node_box).payload;
let old = node.abstract;
node.abstract = Some(self);
@ -279,7 +277,7 @@ impl AbstractNode {
pub fn transmute_mut<T, R>(self, f: &fn(&mut T) -> R) -> R {
unsafe {
let node_box: *mut bindings::utils::rust_box<Node> = transmute(self.obj);
let node_box: *mut bindings::utils::rust_box<Node<View>> = transmute(self.obj);
let node = &mut (*node_box).payload;
let old = node.abstract;
node.abstract = Some(self);
@ -347,18 +345,18 @@ impl AbstractNode {
self.type_id() == ElementNodeTypeId(HTMLStyleElementTypeId)
}
pub unsafe fn raw_object(self) -> *mut Node {
pub unsafe fn raw_object(self) -> *mut Node<View> {
self.obj
}
pub fn from_raw(raw: *mut Node) -> AbstractNode {
pub fn from_raw(raw: *mut Node<View>) -> AbstractNode<View> {
AbstractNode {
obj: raw
}
}
}
impl DebugMethods for AbstractNode {
impl<View> DebugMethods for AbstractNode<View> {
// Dumps the subtree rooted at this node, for debugging.
fn dump(&self) {
self.dump_indent(0);
@ -385,8 +383,8 @@ impl DebugMethods for AbstractNode {
}
}
impl Node {
pub unsafe fn as_abstract_node<N>(node: ~N) -> AbstractNode {
impl Node<ScriptView> {
pub unsafe fn as_abstract_node<N>(node: ~N) -> AbstractNode<ScriptView> {
// This surrenders memory management of the node!
let mut node = AbstractNode {
obj: transmute(node),
@ -409,7 +407,7 @@ impl Node {
}
}
pub fn new(type_id: NodeTypeId) -> Node {
pub fn new(type_id: NodeTypeId) -> Node<ScriptView> {
Node {
wrapper: WrapperCache::new(),
type_id: type_id,

View file

@ -3,7 +3,8 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use dom::element::*;
use dom::node::{AbstractNode, Comment, Doctype, Element, ElementNodeTypeId, Node, Text};
use dom::node::{AbstractNode, Comment, Doctype, Element, ElementNodeTypeId, Node, ScriptView};
use dom::node::{Text};
use html::cssparse::{InlineProvenance, StylesheetProvenance, UrlProvenance, spawn_css_parser};
use newcss::stylesheet::Stylesheet;
use util::task::spawn_conversation;
@ -49,7 +50,7 @@ enum JSMessage {
}
struct HtmlParserResult {
root: AbstractNode,
root: AbstractNode<ScriptView>,
style_port: Port<Option<Stylesheet>>,
js_port: Port<JSResult>,
}
@ -59,11 +60,11 @@ trait NodeWrapping {
unsafe fn from_hubbub_node(n: hubbub::NodeDataPtr) -> Self;
}
impl NodeWrapping for AbstractNode {
impl NodeWrapping for AbstractNode<ScriptView> {
unsafe fn to_hubbub_node(self) -> hubbub::NodeDataPtr {
cast::transmute(self)
}
unsafe fn from_hubbub_node(n: hubbub::NodeDataPtr) -> AbstractNode {
unsafe fn from_hubbub_node(n: hubbub::NodeDataPtr) -> AbstractNode<ScriptView> {
cast::transmute(n)
}
}
@ -153,7 +154,7 @@ fn js_script_listener(to_parent: Chan<~[~[u8]]>,
// Silly macros to handle constructing DOM nodes. This produces bad code and should be optimized
// via atomization (issue #85).
fn build_element_from_tag(tag: &str) -> AbstractNode {
fn build_element_from_tag(tag: &str) -> AbstractNode<ScriptView> {
// TODO (Issue #85): use atoms
handle_element!(tag, "a", HTMLAnchorElementTypeId, HTMLAnchorElement, []);
handle_element!(tag, "aside", HTMLAsideElementTypeId, HTMLAsideElement, []);
@ -238,7 +239,7 @@ pub fn parse_html(url: Url,
// consists of processing inline stylesheets, but in the future it might perform
// prefetching, etc.
let css_chan2 = css_chan.clone();
let append_hook: ~fn(AbstractNode, AbstractNode) = |parent_node, child_node| {
let append_hook: ~fn(AbstractNode<ScriptView>, AbstractNode<ScriptView>) = |parent_node, child_node| {
if parent_node.is_style_element() && child_node.is_text() {
debug!("found inline CSS stylesheet");
let url = url::from_str("http://example.com/"); // FIXME
@ -335,8 +336,8 @@ pub fn parse_html(url: Url,
append_child: |parent: hubbub::NodeDataPtr, child: hubbub::NodeDataPtr| {
unsafe {
debug!("append child %x %x", cast::transmute(parent), cast::transmute(child));
let parent: AbstractNode = NodeWrapping::from_hubbub_node(parent);
let child: AbstractNode = NodeWrapping::from_hubbub_node(child);
let parent: AbstractNode<ScriptView> = NodeWrapping::from_hubbub_node(parent);
let child: AbstractNode<ScriptView> = NodeWrapping::from_hubbub_node(child);
parent.add_child(child);
append_hook(parent, child);
}
@ -386,7 +387,7 @@ pub fn parse_html(url: Url,
url: Url,
js_chan: SharedChan<JSMessage>) {
unsafe {
let script: AbstractNode = NodeWrapping::from_hubbub_node(script);
let script: AbstractNode<ScriptView> = NodeWrapping::from_hubbub_node(script);
do script.with_imm_element |script| {
match script.get_attr(~"src") {
Some(src) => {

View file

@ -4,16 +4,59 @@
//! Code for managing the layout data in the DOM.
use dom::node::{AbstractNode, LayoutData};
use dom::node::{AbstractNode, LayoutView};
use layout::flow::FlowContext;
use newcss::complete::CompleteSelectResults;
use servo_util::tree::TreeUtils;
/// Data that layout associates with a node.
pub struct LayoutData {
/// The results of CSS styling for this node.
style: Option<CompleteSelectResults>,
/// The CSS flow that this node is associated with.
flow: Option<FlowContext>,
}
impl LayoutData {
/// Creates new layout data.
pub fn new() -> LayoutData {
LayoutData {
style: None,
flow: None,
}
}
}
/// Functionality useful for querying the layout-specific data on DOM nodes.
pub trait LayoutAuxMethods {
fn layout_data(self) -> @mut LayoutData;
pub fn has_layout_data(self) -> bool;
fn set_layout_data(self, data: @mut LayoutData);
fn initialize_layout_data(self) -> Option<@mut LayoutData>;
fn initialize_style_for_subtree(self, refs: &mut ~[@mut LayoutData]);
}
impl LayoutAuxMethods for AbstractNode {
impl LayoutAuxMethods for AbstractNode<LayoutView> {
// FIXME (Rust #3080): These unsafe blocks are *not* unused!
pub fn layout_data(self) -> @mut LayoutData {
unsafe {
self.unsafe_layout_data()
}
}
pub fn has_layout_data(self) -> bool {
unsafe {
self.unsafe_has_layout_data()
}
}
pub fn set_layout_data(self, data: @mut LayoutData) {
unsafe {
self.unsafe_set_layout_data(data)
}
}
/// If none exists, creates empty layout data for the node (the reader-auxiliary
/// box in the COW model) and populates it with an empty style object.
fn initialize_layout_data(self) -> Option<@mut LayoutData> {

View file

@ -5,7 +5,7 @@
//! The `RenderBox` type, which represents the leaves of the layout tree.
use css::node_style::StyledNode;
use dom::node::AbstractNode;
use dom::node::{AbstractNode, LayoutView};
use layout::context::LayoutContext;
use layout::debug::DebugMethods;
use layout::display_list_builder::{DisplayListBuilder, ToGfxColor};
@ -145,7 +145,7 @@ pub enum SplitBoxResult {
/// Data common to all render boxes.
pub struct RenderBoxBase {
/// The DOM node that this `RenderBox` originates from.
node: AbstractNode,
node: AbstractNode<LayoutView>,
/// The reference to the containing flow context which this box participates in.
ctx: FlowContext,
@ -161,7 +161,8 @@ pub struct RenderBoxBase {
impl RenderBoxBase {
/// Constructs a new `RenderBoxBase` instance.
pub fn new(node: AbstractNode, flow_context: FlowContext, id: int) -> RenderBoxBase {
pub fn new(node: AbstractNode<LayoutView>, flow_context: FlowContext, id: int)
-> RenderBoxBase {
RenderBoxBase {
node: node,
ctx: flow_context,
@ -501,7 +502,7 @@ pub impl RenderBox {
}
/// A convenience function to access the DOM node that this render box represents.
fn node(&self) -> AbstractNode {
fn node(&self) -> AbstractNode<LayoutView> {
self.with_imm_base(|base| base.node)
}
@ -509,7 +510,7 @@ pub impl RenderBox {
/// represents.
///
/// If there is no ancestor-or-self `Element` node, fails.
fn nearest_ancestor_element(&self) -> AbstractNode {
fn nearest_ancestor_element(&self) -> AbstractNode<LayoutView> {
do self.with_imm_base |base| {
let mut node = base.node;
while !node.is_element() {

View file

@ -6,7 +6,8 @@
use dom::element::*;
use dom::node::{AbstractNode, CommentNodeTypeId, DoctypeNodeTypeId};
use dom::node::{ElementNodeTypeId, TextNodeTypeId};
use dom::node::{ElementNodeTypeId, LayoutView, TextNodeTypeId};
use layout::aux::LayoutAuxMethods;
use layout::block::BlockFlowData;
use layout::box::{GenericRenderBoxClass, ImageRenderBox, ImageRenderBoxClass, RenderBox};
use layout::box::{RenderBoxBase, RenderBoxType, RenderBox_Generic, RenderBox_Image};
@ -51,7 +52,7 @@ enum InlineSpacerSide {
LogicalAfter,
}
priv fn simulate_UA_display_rules(node: AbstractNode) -> CSSDisplay {
priv fn simulate_UA_display_rules(node: AbstractNode<LayoutView>) -> CSSDisplay {
// FIXME
/*let resolved = do node.aux |nd| {
match nd.style.display_type {
@ -95,14 +96,14 @@ impl BoxGenerator {
}
/* Whether "spacer" boxes are needed to stand in for this DOM node */
fn inline_spacers_needed_for_node(&self, _: AbstractNode) -> bool {
fn inline_spacers_needed_for_node(&self, _: AbstractNode<LayoutView>) -> bool {
return false;
}
// TODO: implement this, generating spacer
fn make_inline_spacer_for_node_side(&self,
_: &LayoutContext,
_: AbstractNode,
_: AbstractNode<LayoutView>,
_: InlineSpacerSide)
-> Option<RenderBox> {
None
@ -111,7 +112,7 @@ impl BoxGenerator {
pub fn push_node(&mut self,
ctx: &LayoutContext,
builder: &mut LayoutTreeBuilder,
node: AbstractNode) {
node: AbstractNode<LayoutView>) {
debug!("BoxGenerator[f%d]: pushing node: %s", self.flow.id(), node.debug_str());
// first, determine the box type, based on node characteristics
@ -159,7 +160,7 @@ impl BoxGenerator {
pub fn pop_node(&mut self,
ctx: &LayoutContext,
_builder: &LayoutTreeBuilder,
node: AbstractNode) {
node: AbstractNode<LayoutView>) {
debug!("BoxGenerator[f%d]: popping node: %s", self.flow.id(), node.debug_str());
match self.flow {
@ -222,14 +223,16 @@ impl BuilderContext {
priv fn create_child_flow_of_type(&self,
flow_type: FlowContextType,
builder: &mut LayoutTreeBuilder,
node: AbstractNode) -> BuilderContext {
node: AbstractNode<LayoutView>) -> BuilderContext {
let new_flow = builder.make_flow(flow_type, node);
self.attach_child_flow(new_flow);
BuilderContext::new(@mut BoxGenerator::new(new_flow))
}
priv fn make_inline_collector(&mut self, builder: &mut LayoutTreeBuilder, node: AbstractNode)
priv fn make_inline_collector(&mut self,
builder: &mut LayoutTreeBuilder,
node: AbstractNode<LayoutView>)
-> BuilderContext {
debug!("BuilderContext: making new inline collector flow");
let new_flow = builder.make_flow(Flow_Inline, node);
@ -241,7 +244,9 @@ impl BuilderContext {
BuilderContext::new(new_generator)
}
priv fn get_inline_collector(&mut self, builder: &mut LayoutTreeBuilder, node: AbstractNode)
priv fn get_inline_collector(&mut self,
builder: &mut LayoutTreeBuilder,
node: AbstractNode<LayoutView>)
-> BuilderContext {
match copy self.inline_collector {
Some(collector) => BuilderContext::new(collector),
@ -256,7 +261,9 @@ impl BuilderContext {
// returns a context for the current node, or None if the document subtree rooted
// by the node should not generate a layout tree. For example, nodes with style 'display:none'
// should just not generate any flows or boxes.
fn containing_context_for_node(&mut self, node: AbstractNode, builder: &mut LayoutTreeBuilder)
fn containing_context_for_node(&mut self,
node: AbstractNode<LayoutView>,
builder: &mut LayoutTreeBuilder)
-> Option<BuilderContext> {
// TODO: remove this once UA styles work
// TODO: handle interactions with 'float', 'position' (CSS 2.1, Section 9.7)
@ -296,7 +303,7 @@ pub impl LayoutTreeBuilder {
/// and recurses on its children.
fn construct_recursively(&mut self,
layout_ctx: &LayoutContext,
cur_node: AbstractNode,
cur_node: AbstractNode<LayoutView>,
parent_ctx: &mut BuilderContext) {
debug!("Considering node: %s", cur_node.debug_str());
@ -418,7 +425,7 @@ pub impl LayoutTreeBuilder {
}
/// Entry point for box creation. Should only be called on the root DOM element.
fn construct_trees(&mut self, layout_ctx: &LayoutContext, root: AbstractNode)
fn construct_trees(&mut self, layout_ctx: &LayoutContext, root: AbstractNode<LayoutView>)
-> Result<FlowContext, ()> {
let new_flow = self.make_flow(Flow_Root, root);
let new_generator = @mut BoxGenerator::new(new_flow);
@ -430,7 +437,7 @@ pub impl LayoutTreeBuilder {
}
/// Creates a flow of the given type for the supplied node.
fn make_flow(&mut self, ty: FlowContextType, node: AbstractNode) -> FlowContext {
fn make_flow(&mut self, ty: FlowContextType, node: AbstractNode<LayoutView>) -> FlowContext {
let info = FlowData::new(self.next_flow_id(), node);
let result = match ty {
Flow_Absolute => AbsoluteFlow(@mut info),
@ -450,7 +457,7 @@ pub impl LayoutTreeBuilder {
fn make_box(&mut self,
layout_ctx: &LayoutContext,
ty: RenderBoxType,
node: AbstractNode,
node: AbstractNode<LayoutView>,
flow_context: FlowContext)
-> RenderBox {
let base = RenderBoxBase::new(node, flow_context, self.next_box_id());
@ -465,7 +472,7 @@ pub impl LayoutTreeBuilder {
fn make_image_box(&mut self,
layout_ctx: &LayoutContext,
node: AbstractNode,
node: AbstractNode<LayoutView>,
base: RenderBoxBase)
-> RenderBox {
assert!(node.is_image_element());
@ -483,7 +490,7 @@ pub impl LayoutTreeBuilder {
}
}
fn decide_box_type(&self, node: AbstractNode, _: CSSDisplay) -> RenderBoxType {
fn decide_box_type(&self, node: AbstractNode<LayoutView>, _: CSSDisplay) -> RenderBoxType {
if node.is_text() {
RenderBox_Text
} else if node.is_image_element() {

View file

@ -25,8 +25,8 @@
/// line breaks and mapping to CSS boxes, for the purpose of handling `getClientRects()` and
/// similar methods.
use dom::node::AbstractNode;
use layout::block::{BlockFlowData};
use dom::node::{AbstractNode, LayoutView};
use layout::block::BlockFlowData;
use layout::box::RenderBox;
use layout::context::LayoutContext;
use layout::debug::DebugMethods;
@ -140,7 +140,7 @@ impl TreeNodeRef<FlowData> for FlowContext {
/// FIXME: We need a naming convention for pseudo-inheritance like this. How about
/// `CommonFlowInfo`?
pub struct FlowData {
node: AbstractNode,
node: AbstractNode<LayoutView>,
parent: Option<FlowContext>,
first_child: Option<FlowContext>,
@ -202,7 +202,7 @@ impl TreeNode<FlowContext> for FlowData {
}
impl FlowData {
pub fn new(id: int, node: AbstractNode) -> FlowData {
pub fn new(id: int, node: AbstractNode<LayoutView>) -> FlowData {
FlowData {
node: node,
@ -321,7 +321,7 @@ impl<'self> FlowContext {
}
pub fn foldl_boxes_for_node<B:Copy>(&self,
node: AbstractNode,
node: AbstractNode<LayoutView>,
seed: B,
callback: &fn(a: B, RenderBox) -> B)
-> B {
@ -358,7 +358,9 @@ impl<'self> FlowContext {
true
}
pub fn iter_boxes_for_node(&self, node: AbstractNode, callback: &fn(RenderBox) -> bool)
pub fn iter_boxes_for_node(&self,
node: AbstractNode<LayoutView>,
callback: &fn(RenderBox) -> bool)
-> bool {
for self.iter_all_boxes |box| {
if box.node() == node {

View file

@ -4,7 +4,7 @@
use core::cell::Cell;
use core;
use dom::node::AbstractNode;
use dom::node::{AbstractNode, LayoutView};
use layout::box::{CannotSplit, GenericRenderBoxClass, ImageRenderBoxClass, RenderBox};
use layout::box::{SplitDidFit, SplitDidNotFit, TextRenderBoxClass, UnscannedTextRenderBoxClass};
use layout::context::LayoutContext;
@ -49,12 +49,12 @@ hard to try out that alternative.
*/
pub struct NodeRange {
node: AbstractNode,
node: AbstractNode<LayoutView>,
range: Range,
}
pub impl NodeRange {
fn new(node: AbstractNode, range: &Range) -> NodeRange {
fn new(node: AbstractNode<LayoutView>, range: &Range) -> NodeRange {
NodeRange { node: node, range: copy *range }
}
}
@ -68,7 +68,7 @@ impl ElementMapping {
ElementMapping { entries: ~[] }
}
pub fn add_mapping(&mut self, node: AbstractNode, range: &Range) {
pub fn add_mapping(&mut self, node: AbstractNode<LayoutView>, range: &Range) {
self.entries.push(NodeRange::new(node, range))
}

View file

@ -8,8 +8,8 @@
use css::matching::MatchMethods;
use css::select::new_css_select_ctx;
use dom::event::ReflowEvent;
use dom::node::{AbstractNode, LayoutData};
use layout::aux::LayoutAuxMethods;
use dom::node::{AbstractNode, LayoutView, ScriptView};
use layout::aux::{LayoutData, LayoutAuxMethods};
use layout::box_builder::LayoutTreeBuilder;
use layout::context::LayoutContext;
use layout::debug::{BoxedMutDebugMethods, DebugMethods};
@ -22,6 +22,7 @@ use servo_util::time::time;
use servo_util::time::profile;
use servo_util::time::ProfilerChan;
use core::cast::transmute;
use core::cell::Cell;
use core::comm::{Chan, Port, SharedChan};
use geom::point::Point2D;
@ -44,8 +45,8 @@ use std::net::url::Url;
pub type LayoutTask = SharedChan<Msg>;
pub enum LayoutQuery {
ContentBox(AbstractNode),
ContentBoxes(AbstractNode)
ContentBox(AbstractNode<ScriptView>),
ContentBoxes(AbstractNode<ScriptView>),
}
pub type LayoutQueryResponse = Result<LayoutQueryResponse_, ()>;
@ -81,7 +82,7 @@ impl Damage {
}
pub struct BuildData {
node: AbstractNode,
node: AbstractNode<ScriptView>,
url: Url,
script_chan: SharedChan<ScriptMsg>,
window_size: Size2D<uint>,
@ -180,7 +181,11 @@ impl Layout {
/// The high-level routine that performs layout tasks.
fn handle_build(&mut self, data: &BuildData) {
let node = &data.node;
// FIXME: Isolate this transmutation into a "bridge" module.
let node: &AbstractNode<LayoutView> = unsafe {
transmute(&data.node)
};
// FIXME: Bad copy!
let doc_url = copy data.url;
let script_chan = data.script_chan.clone();
@ -279,6 +284,11 @@ impl Layout {
fn handle_query(&self, query: LayoutQuery, reply_chan: Chan<LayoutQueryResponse>) {
match query {
ContentBox(node) => {
// FIXME: Isolate this transmutation into a single "bridge" module.
let node: AbstractNode<LayoutView> = unsafe {
transmute(node)
};
let response = match node.layout_data().flow {
None => {
error!("no flow present");
@ -306,6 +316,11 @@ impl Layout {
reply_chan.send(response)
}
ContentBoxes(node) => {
// FIXME: Isolate this transmutation into a single "bridge" module.
let node: AbstractNode<LayoutView> = unsafe {
transmute(node)
};
let response = match node.layout_data().flow {
None => Err(()),
Some(flow) => {