mirror of
https://github.com/servo/servo.git
synced 2025-08-05 13:40:08 +01:00
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:
parent
c7bce98236
commit
4f3ca373d4
23 changed files with 262 additions and 189 deletions
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
use css::node_util::NodeUtil;
|
use css::node_util::NodeUtil;
|
||||||
use css::select_handler::NodeSelectHandler;
|
use css::select_handler::NodeSelectHandler;
|
||||||
use dom::node::AbstractNode;
|
use dom::node::{AbstractNode, LayoutView};
|
||||||
use newcss::complete::CompleteSelectResults;
|
use newcss::complete::CompleteSelectResults;
|
||||||
use newcss::select::{SelectCtx, SelectResults};
|
use newcss::select::{SelectCtx, SelectResults};
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ pub trait MatchMethods {
|
||||||
fn restyle_subtree(&self, select_ctx: &SelectCtx);
|
fn restyle_subtree(&self, select_ctx: &SelectCtx);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MatchMethods for AbstractNode {
|
impl MatchMethods for AbstractNode<LayoutView> {
|
||||||
/**
|
/**
|
||||||
* Performs CSS selector matching on a subtree.
|
* 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) {
|
match find_parent_element_node(node) {
|
||||||
None => CompleteSelectResults::new_root(results),
|
None => CompleteSelectResults::new_root(results),
|
||||||
Some(parent_node) => {
|
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() {
|
match node.parent_node() {
|
||||||
Some(parent) if parent.is_element() => Some(parent),
|
Some(parent) if parent.is_element() => Some(parent),
|
||||||
Some(parent) => find_parent_element_node(parent),
|
Some(parent) => find_parent_element_node(parent),
|
||||||
|
|
|
@ -5,7 +5,8 @@
|
||||||
// Style retrieval from DOM elements.
|
// Style retrieval from DOM elements.
|
||||||
|
|
||||||
use css::node_util::NodeUtil;
|
use css::node_util::NodeUtil;
|
||||||
use dom::node::AbstractNode;
|
use dom::node::{AbstractNode, LayoutView};
|
||||||
|
|
||||||
use newcss::complete::CompleteStyle;
|
use newcss::complete::CompleteStyle;
|
||||||
|
|
||||||
/// Node mixin providing `style` method that returns a `NodeStyle`
|
/// Node mixin providing `style` method that returns a `NodeStyle`
|
||||||
|
@ -13,7 +14,7 @@ pub trait StyledNode {
|
||||||
fn style(&self) -> CompleteStyle;
|
fn style(&self) -> CompleteStyle;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StyledNode for AbstractNode {
|
impl StyledNode for AbstractNode<LayoutView> {
|
||||||
fn style(&self) -> CompleteStyle {
|
fn style(&self) -> CompleteStyle {
|
||||||
assert!(self.is_element()); // Only elements can have styles
|
assert!(self.is_element()); // Only elements can have styles
|
||||||
let results = self.get_css_select_results();
|
let results = self.get_css_select_results();
|
||||||
|
|
|
@ -2,17 +2,18 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use dom::node::AbstractNode;
|
use dom::node::{AbstractNode, LayoutView};
|
||||||
use newcss::complete::CompleteSelectResults;
|
use layout::aux::LayoutAuxMethods;
|
||||||
|
|
||||||
use core::cast::transmute;
|
use core::cast::transmute;
|
||||||
|
use newcss::complete::CompleteSelectResults;
|
||||||
|
|
||||||
pub trait NodeUtil<'self> {
|
pub trait NodeUtil<'self> {
|
||||||
fn get_css_select_results(self) -> &'self CompleteSelectResults;
|
fn get_css_select_results(self) -> &'self CompleteSelectResults;
|
||||||
fn set_css_select_results(self, decl: 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
|
* Provides the computed style for the given node. If CSS selector
|
||||||
* Returns the style results for the given node. If CSS selector
|
* Returns the style results for the given node. If CSS selector
|
||||||
|
|
|
@ -5,15 +5,15 @@
|
||||||
//! CSS library requires that DOM nodes be convertable to *c_void through this trait
|
//! CSS library requires that DOM nodes be convertable to *c_void through this trait
|
||||||
extern mod netsurfcss;
|
extern mod netsurfcss;
|
||||||
|
|
||||||
use dom::node::AbstractNode;
|
use dom::node::{AbstractNode, LayoutView};
|
||||||
|
|
||||||
use core::cast;
|
use core::cast;
|
||||||
|
|
||||||
// FIXME: Rust #3908. rust-css can't reexport VoidPtrLike
|
// FIXME: Rust #3908. rust-css can't reexport VoidPtrLike
|
||||||
use css::node_void_ptr::netsurfcss::util::VoidPtrLike;
|
use css::node_void_ptr::netsurfcss::util::VoidPtrLike;
|
||||||
|
|
||||||
impl VoidPtrLike for AbstractNode {
|
impl VoidPtrLike for AbstractNode<LayoutView> {
|
||||||
fn from_void_ptr(node: *libc::c_void) -> AbstractNode {
|
fn from_void_ptr(node: *libc::c_void) -> AbstractNode<LayoutView> {
|
||||||
assert!(node.is_not_null());
|
assert!(node.is_not_null());
|
||||||
unsafe {
|
unsafe {
|
||||||
cast::transmute(node)
|
cast::transmute(node)
|
||||||
|
|
|
@ -6,16 +6,16 @@
|
||||||
/// Implementation of the callbacks that the CSS selector engine uses to query the DOM.
|
/// 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 newcss::select::SelectHandler;
|
||||||
|
|
||||||
use core::str::eq_slice;
|
use core::str::eq_slice;
|
||||||
|
|
||||||
pub struct NodeSelectHandler {
|
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() {
|
if !node.is_element() {
|
||||||
fail!(~"attempting to style non-element node");
|
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 {
|
impl SelectHandler<AbstractNode<LayoutView>> for NodeSelectHandler {
|
||||||
fn with_node_name<R>(&self, node: &AbstractNode, f: &fn(&str) -> R) -> R {
|
fn with_node_name<R>(&self, node: &AbstractNode<LayoutView>, f: &fn(&str) -> R) -> R {
|
||||||
with_node_name(*node, f)
|
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() {
|
match node.parent_node() {
|
||||||
Some(parent) => {
|
Some(parent) => {
|
||||||
do with_node_name(parent) |node_name| {
|
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()
|
node.parent_node()
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Use a Bloom filter.
|
// 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;
|
let mut node = *node;
|
||||||
loop {
|
loop {
|
||||||
let parent = node.parent_node();
|
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()
|
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() {
|
if !node.is_element() {
|
||||||
fail!(~"attempting to style non-element node");
|
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() {
|
if !node.is_element() {
|
||||||
fail!(~"attempting to style non-element node");
|
fail!(~"attempting to style non-element node");
|
||||||
}
|
}
|
||||||
|
|
|
@ -513,7 +513,7 @@ addExternalIface('CSSValue')
|
||||||
addExternalIface('Document', nativeType='Document', pointerType='@mut ')
|
addExternalIface('Document', nativeType='Document', pointerType='@mut ')
|
||||||
addExternalIface('DOMStringList', nativeType='nsDOMStringList',
|
addExternalIface('DOMStringList', nativeType='nsDOMStringList',
|
||||||
headerFile='nsDOMLists.h')
|
headerFile='nsDOMLists.h')
|
||||||
addExternalIface('Element', nativeType='AbstractNode', pointerType='')
|
addExternalIface('Element', nativeType='AbstractNode<ScriptView>', pointerType='')
|
||||||
addExternalIface('File')
|
addExternalIface('File')
|
||||||
addExternalIface('HitRegionOptions', nativeType='nsISupports')
|
addExternalIface('HitRegionOptions', nativeType='nsISupports')
|
||||||
addExternalIface('HTMLElement')
|
addExternalIface('HTMLElement')
|
||||||
|
|
|
@ -4149,6 +4149,7 @@ class CGBindingRoot(CGThing):
|
||||||
'dom::eventtarget::*', #XXXjdm
|
'dom::eventtarget::*', #XXXjdm
|
||||||
'scripting::script_task::task_from_context',
|
'scripting::script_task::task_from_context',
|
||||||
'dom::bindings::utils::EnumEntry',
|
'dom::bindings::utils::EnumEntry',
|
||||||
|
'dom::node::ScriptView',
|
||||||
],
|
],
|
||||||
[],
|
[],
|
||||||
curr)
|
curr)
|
||||||
|
|
|
@ -7,7 +7,7 @@ use dom::bindings::utils::jsval_to_str;
|
||||||
use dom::bindings::utils::{domstring_to_jsval, WrapNewBindingObject};
|
use dom::bindings::utils::{domstring_to_jsval, WrapNewBindingObject};
|
||||||
use dom::bindings::utils::{str, CacheableWrapper, DOM_OBJECT_SLOT, DOMString};
|
use dom::bindings::utils::{str, CacheableWrapper, DOM_OBJECT_SLOT, DOMString};
|
||||||
use dom::element::*;
|
use dom::element::*;
|
||||||
use dom::node::{AbstractNode, Element, ElementNodeTypeId};
|
use dom::node::{AbstractNode, Element, ElementNodeTypeId, ScriptView};
|
||||||
use layout::layout_task;
|
use layout::layout_task;
|
||||||
use scripting::script_task::task_from_context;
|
use scripting::script_task::task_from_context;
|
||||||
use super::utils;
|
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) {
|
extern fn finalize(_fop: *JSFreeOp, obj: *JSObject) {
|
||||||
debug!("element finalize: %x!", obj as uint);
|
debug!("element finalize: %x!", obj as uint);
|
||||||
unsafe {
|
unsafe {
|
||||||
let node: AbstractNode = unwrap(obj);
|
let node: AbstractNode<ScriptView> = unwrap(obj);
|
||||||
//XXXjdm We need separate finalizers for each specialty element type like headings
|
//XXXjdm We need separate finalizers for each specialty element type like headings
|
||||||
let _elem: ~Element = cast::transmute(node.raw_object());
|
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) {
|
pub extern fn trace(tracer: *mut JSTracer, obj: *JSObject) {
|
||||||
let node = unsafe { unwrap(obj) };
|
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() {
|
if node.is_none() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -278,7 +278,7 @@ extern fn getTagName(cx: *JSContext, _argc: c_uint, vp: *mut JSVal) -> JSBool {
|
||||||
return 1;
|
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() {
|
let proto = match node.type_id() {
|
||||||
ElementNodeTypeId(HTMLDivElementTypeId) => ~"HTMLDivElement",
|
ElementNodeTypeId(HTMLDivElementTypeId) => ~"HTMLDivElement",
|
||||||
ElementNodeTypeId(HTMLHeadElementTypeId) => ~"HTMLHeadElement",
|
ElementNodeTypeId(HTMLHeadElementTypeId) => ~"HTMLHeadElement",
|
||||||
|
|
|
@ -7,7 +7,7 @@ use dom::bindings::text;
|
||||||
use dom::bindings::utils;
|
use dom::bindings::utils;
|
||||||
use dom::bindings::utils::{CacheableWrapper, WrapperCache, DerivedWrapper};
|
use dom::bindings::utils::{CacheableWrapper, WrapperCache, DerivedWrapper};
|
||||||
use dom::node::{AbstractNode, Node, ElementNodeTypeId, TextNodeTypeId, CommentNodeTypeId};
|
use dom::node::{AbstractNode, Node, ElementNodeTypeId, TextNodeTypeId, CommentNodeTypeId};
|
||||||
use dom::node::{DoctypeNodeTypeId};
|
use dom::node::{DoctypeNodeTypeId, ScriptView};
|
||||||
|
|
||||||
use core::libc::c_uint;
|
use core::libc::c_uint;
|
||||||
use core::ptr::null;
|
use core::ptr::null;
|
||||||
|
@ -58,7 +58,7 @@ pub fn init(compartment: @mut Compartment) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(non_implicitly_copyable_typarams)]
|
#[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() {
|
match node.type_id() {
|
||||||
ElementNodeTypeId(_) => element::create(cx, node),
|
ElementNodeTypeId(_) => element::create(cx, node),
|
||||||
TextNodeTypeId |
|
TextNodeTypeId |
|
||||||
|
@ -67,8 +67,8 @@ pub fn create(cx: *JSContext, node: &mut AbstractNode) -> jsobj {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn unwrap(obj: *JSObject) -> AbstractNode {
|
pub unsafe fn unwrap(obj: *JSObject) -> AbstractNode<ScriptView> {
|
||||||
let raw = utils::unwrap::<*mut Node>(obj);
|
let raw = utils::unwrap::<*mut Node<ScriptView>>(obj);
|
||||||
AbstractNode::from_raw(raw)
|
AbstractNode::from_raw(raw)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,7 +116,7 @@ extern fn getNextSibling(cx: *JSContext, _argc: c_uint, vp: *mut JSVal) -> JSBoo
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Node {
|
impl Node<ScriptView> {
|
||||||
fn getNodeType(&self) -> i32 {
|
fn getNodeType(&self) -> i32 {
|
||||||
match self.type_id {
|
match self.type_id {
|
||||||
ElementNodeTypeId(_) => 1,
|
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 {
|
match self.next_sibling {
|
||||||
// transmute because the compiler can't deduce that the reference
|
// transmute because the compiler can't deduce that the reference
|
||||||
// is safe outside of with_mut_base blocks.
|
// 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 {
|
match self.first_child {
|
||||||
// transmute because the compiler can't deduce that the reference
|
// transmute because the compiler can't deduce that the reference
|
||||||
// is safe outside of with_mut_base blocks.
|
// 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;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CacheableWrapper for AbstractNode {
|
impl CacheableWrapper for AbstractNode<ScriptView> {
|
||||||
fn get_wrappercache(&mut self) -> &mut WrapperCache {
|
fn get_wrappercache(&mut self) -> &mut WrapperCache {
|
||||||
do self.with_mut_base |base| {
|
do self.with_mut_base |base| {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
|
|
@ -7,7 +7,7 @@ use dom::bindings::node::unwrap;
|
||||||
use dom::bindings::utils;
|
use dom::bindings::utils;
|
||||||
use dom::bindings::utils::{DOM_OBJECT_SLOT, CacheableWrapper};
|
use dom::bindings::utils::{DOM_OBJECT_SLOT, CacheableWrapper};
|
||||||
use dom::node::{AbstractNode, Text, Comment, Doctype, TextNodeTypeId, CommentNodeTypeId};
|
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::{JSFreeOp, JSObject, JSContext};
|
||||||
use js::jsapi::bindgen::{JS_SetReservedSlot};
|
use js::jsapi::bindgen::{JS_SetReservedSlot};
|
||||||
|
@ -17,7 +17,7 @@ use js::rust::{Compartment, jsobj};
|
||||||
extern fn finalize_text(_fop: *JSFreeOp, obj: *JSObject) {
|
extern fn finalize_text(_fop: *JSFreeOp, obj: *JSObject) {
|
||||||
debug!("text finalize: %?!", obj as uint);
|
debug!("text finalize: %?!", obj as uint);
|
||||||
unsafe {
|
unsafe {
|
||||||
let node: AbstractNode = unwrap(obj);
|
let node: AbstractNode<ScriptView> = unwrap(obj);
|
||||||
let _elem: ~Text = cast::transmute(node.raw_object());
|
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) {
|
extern fn finalize_comment(_fop: *JSFreeOp, obj: *JSObject) {
|
||||||
debug!("comment finalize: %?!", obj as uint);
|
debug!("comment finalize: %?!", obj as uint);
|
||||||
unsafe {
|
unsafe {
|
||||||
let node: AbstractNode = unwrap(obj);
|
let node: AbstractNode<ScriptView> = unwrap(obj);
|
||||||
let _elem: ~Comment = cast::transmute(node.raw_object());
|
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) {
|
extern fn finalize_doctype(_fop: *JSFreeOp, obj: *JSObject) {
|
||||||
debug!("doctype finalize: %?!", obj as uint);
|
debug!("doctype finalize: %?!", obj as uint);
|
||||||
unsafe {
|
unsafe {
|
||||||
let node: AbstractNode = unwrap(obj);
|
let node: AbstractNode<ScriptView> = unwrap(obj);
|
||||||
let _elem: ~Doctype = cast::transmute(node.raw_object());
|
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() {
|
let (proto, instance) = match node.type_id() {
|
||||||
TextNodeTypeId => (~"TextPrototype", ~"Text"),
|
TextNodeTypeId => (~"TextPrototype", ~"Text"),
|
||||||
CommentNodeTypeId => (~"CommentPrototype", ~"Comment"),
|
CommentNodeTypeId => (~"CommentPrototype", ~"Comment"),
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use dom::bindings::node;
|
use dom::bindings::node;
|
||||||
use dom::node::AbstractNode;
|
use dom::node::{AbstractNode, ScriptView};
|
||||||
use js::glue::bindgen::*;
|
use js::glue::bindgen::*;
|
||||||
use js::glue::bindgen::{DefineFunctionWithReserved, GetObjectJSClass, RUST_OBJECT_TO_JSVAL};
|
use js::glue::bindgen::{DefineFunctionWithReserved, GetObjectJSClass, RUST_OBJECT_TO_JSVAL};
|
||||||
use js::glue::{PROPERTY_STUB, STRICT_PROPERTY_STUB, ENUMERATE_STUB, CONVERT_STUB, RESOLVE_STUB};
|
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;
|
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 {
|
fn wrap(&mut self, cx: *JSContext, _scope: *JSObject, vp: *mut JSVal) -> i32 {
|
||||||
let cache = self.get_wrappercache();
|
let cache = self.get_wrappercache();
|
||||||
let wrapper = cache.get_wrapper();
|
let wrapper = cache.get_wrapper();
|
||||||
|
|
|
@ -5,12 +5,12 @@
|
||||||
//! DOM bindings for `CharacterData`.
|
//! DOM bindings for `CharacterData`.
|
||||||
|
|
||||||
use dom::bindings::utils::{DOMString, null_string, str};
|
use dom::bindings::utils::{DOMString, null_string, str};
|
||||||
use dom::node::{Node, NodeTypeId};
|
use dom::node::{Node, NodeTypeId, ScriptView};
|
||||||
|
|
||||||
use core::str;
|
use core::str;
|
||||||
|
|
||||||
pub struct CharacterData {
|
pub struct CharacterData {
|
||||||
parent: Node,
|
parent: Node<ScriptView>,
|
||||||
data: DOMString
|
data: DOMString
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
use dom::bindings::document;
|
use dom::bindings::document;
|
||||||
use dom::bindings::utils::{DOMString, WrapperCache};
|
use dom::bindings::utils::{DOMString, WrapperCache};
|
||||||
use dom::htmlcollection::HTMLCollection;
|
use dom::htmlcollection::HTMLCollection;
|
||||||
use dom::node::AbstractNode;
|
use dom::node::{AbstractNode, ScriptView};
|
||||||
use dom::window::Window;
|
use dom::window::Window;
|
||||||
use scripting::script_task::global_script_context;
|
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};
|
use servo_util::tree::{TreeNodeRef, TreeUtils};
|
||||||
|
|
||||||
pub struct Document {
|
pub struct Document {
|
||||||
root: AbstractNode,
|
root: AbstractNode<ScriptView>,
|
||||||
wrapper: WrapperCache,
|
wrapper: WrapperCache,
|
||||||
window: Option<@mut Window>,
|
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 {
|
let doc = @mut Document {
|
||||||
root: root,
|
root: root,
|
||||||
wrapper: WrapperCache::new(),
|
wrapper: WrapperCache::new(),
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
// Element nodes.
|
// Element nodes.
|
||||||
//
|
//
|
||||||
|
|
||||||
use dom::node::{ElementNodeTypeId, Node};
|
use dom::node::{ElementNodeTypeId, Node, ScriptView};
|
||||||
use dom::clientrect::ClientRect;
|
use dom::clientrect::ClientRect;
|
||||||
use dom::clientrectlist::ClientRectList;
|
use dom::clientrectlist::ClientRectList;
|
||||||
use dom::bindings::utils::DOMString;
|
use dom::bindings::utils::DOMString;
|
||||||
|
@ -18,7 +18,7 @@ use core::cell::Cell;
|
||||||
use std::net::url::Url;
|
use std::net::url::Url;
|
||||||
|
|
||||||
pub struct Element {
|
pub struct Element {
|
||||||
parent: Node,
|
parent: Node<ScriptView>,
|
||||||
tag_name: ~str, // TODO: This should be an atom, not a ~str.
|
tag_name: ~str, // TODO: This should be an atom, not a ~str.
|
||||||
attrs: ~[Attr],
|
attrs: ~[Attr],
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,17 +4,17 @@
|
||||||
|
|
||||||
use dom::bindings::utils::WrapperCache;
|
use dom::bindings::utils::WrapperCache;
|
||||||
use dom::bindings::utils::{DOMString, ErrorResult};
|
use dom::bindings::utils::{DOMString, ErrorResult};
|
||||||
use dom::node::AbstractNode;
|
use dom::node::{AbstractNode, ScriptView};
|
||||||
|
|
||||||
use js::jsapi::{JSObject, JSContext};
|
use js::jsapi::{JSObject, JSContext};
|
||||||
|
|
||||||
pub struct HTMLCollection {
|
pub struct HTMLCollection {
|
||||||
elements: ~[AbstractNode],
|
elements: ~[AbstractNode<ScriptView>],
|
||||||
wrapper: WrapperCache
|
wrapper: WrapperCache
|
||||||
}
|
}
|
||||||
|
|
||||||
pub impl HTMLCollection {
|
pub impl HTMLCollection {
|
||||||
fn new(elements: ~[AbstractNode]) -> @mut HTMLCollection {
|
fn new(elements: ~[AbstractNode<ScriptView>]) -> @mut HTMLCollection {
|
||||||
let collection = @mut HTMLCollection {
|
let collection = @mut HTMLCollection {
|
||||||
elements: elements,
|
elements: elements,
|
||||||
wrapper: WrapperCache::new()
|
wrapper: WrapperCache::new()
|
||||||
|
@ -27,7 +27,7 @@ pub impl HTMLCollection {
|
||||||
self.elements.len() as u32
|
self.elements.len() as u32
|
||||||
}
|
}
|
||||||
|
|
||||||
fn Item(&self, index: u32) -> Option<AbstractNode> {
|
fn Item(&self, index: u32) -> Option<AbstractNode<ScriptView>> {
|
||||||
if index < self.Length() {
|
if index < self.Length() {
|
||||||
Some(self.elements[index])
|
Some(self.elements[index])
|
||||||
} else {
|
} else {
|
||||||
|
@ -40,7 +40,7 @@ pub impl HTMLCollection {
|
||||||
ptr::null()
|
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;
|
*found = true;
|
||||||
self.Item(index)
|
self.Item(index)
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,65 +13,75 @@ use dom::document::Document;
|
||||||
use dom::element::{Element, ElementTypeId, HTMLImageElement, HTMLImageElementTypeId};
|
use dom::element::{Element, ElementTypeId, HTMLImageElement, HTMLImageElementTypeId};
|
||||||
use dom::element::{HTMLStyleElementTypeId};
|
use dom::element::{HTMLStyleElementTypeId};
|
||||||
use layout::debug::DebugMethods;
|
use layout::debug::DebugMethods;
|
||||||
use layout::flow::FlowContext;
|
|
||||||
use scripting::script_task::global_script_context;
|
use scripting::script_task::global_script_context;
|
||||||
|
|
||||||
use core::cast::transmute;
|
use core::cast::transmute;
|
||||||
use js::rust::Compartment;
|
use js::rust::Compartment;
|
||||||
use newcss::complete::CompleteSelectResults;
|
|
||||||
use servo_util::tree::{TreeNode, TreeNodeRef, TreeUtils};
|
use servo_util::tree::{TreeNode, TreeNodeRef, TreeUtils};
|
||||||
|
|
||||||
//
|
//
|
||||||
// The basic Node structure
|
// 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
|
/// This is what a Node looks like if you do not know what kind of node it is. To unpack it, use
|
||||||
/// downcast().
|
/// downcast().
|
||||||
///
|
///
|
||||||
/// FIXME: This should be replaced with a trait once they can inherit from structs.
|
/// FIXME: This should be replaced with a trait once they can inherit from structs.
|
||||||
pub struct AbstractNode {
|
pub struct AbstractNode<View> {
|
||||||
priv obj: *mut Node,
|
priv obj: *mut Node<View>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Eq for AbstractNode {
|
impl<View> Eq for AbstractNode<View> {
|
||||||
fn eq(&self, other: &AbstractNode) -> bool {
|
fn eq(&self, other: &AbstractNode<View>) -> bool {
|
||||||
self.obj == other.obj
|
self.obj == other.obj
|
||||||
}
|
}
|
||||||
fn ne(&self, other: &AbstractNode) -> bool {
|
fn ne(&self, other: &AbstractNode<View>) -> bool {
|
||||||
self.obj != other.obj
|
self.obj != other.obj
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An HTML node.
|
/// 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.
|
/// The JavaScript wrapper for this node.
|
||||||
wrapper: WrapperCache,
|
wrapper: WrapperCache,
|
||||||
|
|
||||||
/// The type of node that this is.
|
/// The type of node that this is.
|
||||||
type_id: NodeTypeId,
|
type_id: NodeTypeId,
|
||||||
|
|
||||||
abstract: Option<AbstractNode>,
|
abstract: Option<AbstractNode<View>>,
|
||||||
|
|
||||||
/// The parent of this node.
|
/// The parent of this node.
|
||||||
parent_node: Option<AbstractNode>,
|
parent_node: Option<AbstractNode<View>>,
|
||||||
|
|
||||||
/// The first child of this node.
|
/// The first child of this node.
|
||||||
first_child: Option<AbstractNode>,
|
first_child: Option<AbstractNode<View>>,
|
||||||
|
|
||||||
/// The last child of this node.
|
/// The last child of this node.
|
||||||
last_child: Option<AbstractNode>,
|
last_child: Option<AbstractNode<View>>,
|
||||||
|
|
||||||
/// The next sibling of this node.
|
/// The next sibling of this node.
|
||||||
next_sibling: Option<AbstractNode>,
|
next_sibling: Option<AbstractNode<View>>,
|
||||||
|
|
||||||
/// The previous sibling of this node.
|
/// The previous sibling of this node.
|
||||||
prev_sibling: Option<AbstractNode>,
|
prev_sibling: Option<AbstractNode<View>>,
|
||||||
|
|
||||||
/// The document that this node belongs to.
|
/// The document that this node belongs to.
|
||||||
owner_doc: Option<@mut Document>,
|
owner_doc: Option<@mut Document>,
|
||||||
|
|
||||||
/// Layout information. You must not touch this if you are not layout.
|
/// Layout information. Only the layout task may touch this data.
|
||||||
priv layout_data: Option<@mut LayoutData>
|
priv layout_data: Option<@mut ()>
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The different types of nodes.
|
/// The different types of nodes.
|
||||||
|
@ -83,49 +93,26 @@ pub enum NodeTypeId {
|
||||||
TextNodeTypeId,
|
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
|
// Basic node types
|
||||||
//
|
//
|
||||||
|
|
||||||
/// The `DOCTYPE` tag.
|
/// The `DOCTYPE` tag.
|
||||||
pub struct Doctype {
|
pub struct Doctype<View> {
|
||||||
parent: Node,
|
parent: Node<View>,
|
||||||
name: ~str,
|
name: ~str,
|
||||||
public_id: Option<~str>,
|
public_id: Option<~str>,
|
||||||
system_id: Option<~str>,
|
system_id: Option<~str>,
|
||||||
force_quirks: bool
|
force_quirks: bool
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Doctype {
|
impl Doctype<ScriptView> {
|
||||||
/// Creates a new `DOCTYPE` tag.
|
/// Creates a new `DOCTYPE` tag.
|
||||||
pub fn new(name: ~str,
|
pub fn new(name: ~str,
|
||||||
public_id: Option<~str>,
|
public_id: Option<~str>,
|
||||||
system_id: Option<~str>,
|
system_id: Option<~str>,
|
||||||
force_quirks: bool)
|
force_quirks: bool)
|
||||||
-> Doctype {
|
-> Doctype<ScriptView> {
|
||||||
Doctype {
|
Doctype {
|
||||||
parent: Node::new(DoctypeNodeTypeId),
|
parent: Node::new(DoctypeNodeTypeId),
|
||||||
name: name,
|
name: name,
|
||||||
|
@ -164,58 +151,81 @@ impl Text {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Clone for AbstractNode {
|
impl<View> Clone for AbstractNode<View> {
|
||||||
fn clone(&self) -> AbstractNode {
|
fn clone(&self) -> AbstractNode<View> {
|
||||||
*self
|
*self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TreeNode<AbstractNode> for Node {
|
impl<View> TreeNode<AbstractNode<View>> for Node<View> {
|
||||||
fn parent_node(&self) -> Option<AbstractNode> {
|
fn parent_node(&self) -> Option<AbstractNode<View>> {
|
||||||
self.parent_node
|
self.parent_node
|
||||||
}
|
}
|
||||||
fn first_child(&self) -> Option<AbstractNode> {
|
fn first_child(&self) -> Option<AbstractNode<View>> {
|
||||||
self.first_child
|
self.first_child
|
||||||
}
|
}
|
||||||
fn last_child(&self) -> Option<AbstractNode> {
|
fn last_child(&self) -> Option<AbstractNode<View>> {
|
||||||
self.last_child
|
self.last_child
|
||||||
}
|
}
|
||||||
fn prev_sibling(&self) -> Option<AbstractNode> {
|
fn prev_sibling(&self) -> Option<AbstractNode<View>> {
|
||||||
self.prev_sibling
|
self.prev_sibling
|
||||||
}
|
}
|
||||||
fn next_sibling(&self) -> Option<AbstractNode> {
|
fn next_sibling(&self) -> Option<AbstractNode<View>> {
|
||||||
self.next_sibling
|
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
|
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
|
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
|
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
|
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
|
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.
|
// 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)
|
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)
|
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
|
// Convenience accessors
|
||||||
|
|
||||||
/// Returns the type ID of this node. Fails if this node is borrowed mutably.
|
/// 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.
|
/// 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)
|
self.with_base(|b| b.parent_node)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the first child of this node. Fails if this node is borrowed mutably.
|
/// 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)
|
self.with_base(|b| b.first_child)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the last child of this node. Fails if this node is borrowed mutably.
|
/// 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)
|
self.with_base(|b| b.last_child)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the previous sibling of this node. Fails if this node is borrowed mutably.
|
/// 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)
|
self.with_base(|b| b.prev_sibling)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the next sibling of this node. Fails if this node is borrowed mutably.
|
/// 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)
|
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
|
// Downcasting borrows
|
||||||
//
|
//
|
||||||
|
|
||||||
pub fn transmute<T, R>(self, f: &fn(&T) -> R) -> R {
|
pub fn transmute<T, R>(self, f: &fn(&T) -> R) -> R {
|
||||||
unsafe {
|
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 node = &mut (*node_box).payload;
|
||||||
let old = node.abstract;
|
let old = node.abstract;
|
||||||
node.abstract = Some(self);
|
node.abstract = Some(self);
|
||||||
|
@ -279,7 +277,7 @@ impl AbstractNode {
|
||||||
|
|
||||||
pub fn transmute_mut<T, R>(self, f: &fn(&mut T) -> R) -> R {
|
pub fn transmute_mut<T, R>(self, f: &fn(&mut T) -> R) -> R {
|
||||||
unsafe {
|
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 node = &mut (*node_box).payload;
|
||||||
let old = node.abstract;
|
let old = node.abstract;
|
||||||
node.abstract = Some(self);
|
node.abstract = Some(self);
|
||||||
|
@ -347,18 +345,18 @@ impl AbstractNode {
|
||||||
self.type_id() == ElementNodeTypeId(HTMLStyleElementTypeId)
|
self.type_id() == ElementNodeTypeId(HTMLStyleElementTypeId)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn raw_object(self) -> *mut Node {
|
pub unsafe fn raw_object(self) -> *mut Node<View> {
|
||||||
self.obj
|
self.obj
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_raw(raw: *mut Node) -> AbstractNode {
|
pub fn from_raw(raw: *mut Node<View>) -> AbstractNode<View> {
|
||||||
AbstractNode {
|
AbstractNode {
|
||||||
obj: raw
|
obj: raw
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DebugMethods for AbstractNode {
|
impl<View> DebugMethods for AbstractNode<View> {
|
||||||
// Dumps the subtree rooted at this node, for debugging.
|
// Dumps the subtree rooted at this node, for debugging.
|
||||||
fn dump(&self) {
|
fn dump(&self) {
|
||||||
self.dump_indent(0);
|
self.dump_indent(0);
|
||||||
|
@ -385,8 +383,8 @@ impl DebugMethods for AbstractNode {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Node {
|
impl Node<ScriptView> {
|
||||||
pub unsafe fn as_abstract_node<N>(node: ~N) -> AbstractNode {
|
pub unsafe fn as_abstract_node<N>(node: ~N) -> AbstractNode<ScriptView> {
|
||||||
// This surrenders memory management of the node!
|
// This surrenders memory management of the node!
|
||||||
let mut node = AbstractNode {
|
let mut node = AbstractNode {
|
||||||
obj: transmute(node),
|
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 {
|
Node {
|
||||||
wrapper: WrapperCache::new(),
|
wrapper: WrapperCache::new(),
|
||||||
type_id: type_id,
|
type_id: type_id,
|
||||||
|
|
|
@ -3,7 +3,8 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use dom::element::*;
|
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 html::cssparse::{InlineProvenance, StylesheetProvenance, UrlProvenance, spawn_css_parser};
|
||||||
use newcss::stylesheet::Stylesheet;
|
use newcss::stylesheet::Stylesheet;
|
||||||
use util::task::spawn_conversation;
|
use util::task::spawn_conversation;
|
||||||
|
@ -49,7 +50,7 @@ enum JSMessage {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct HtmlParserResult {
|
struct HtmlParserResult {
|
||||||
root: AbstractNode,
|
root: AbstractNode<ScriptView>,
|
||||||
style_port: Port<Option<Stylesheet>>,
|
style_port: Port<Option<Stylesheet>>,
|
||||||
js_port: Port<JSResult>,
|
js_port: Port<JSResult>,
|
||||||
}
|
}
|
||||||
|
@ -59,11 +60,11 @@ trait NodeWrapping {
|
||||||
unsafe fn from_hubbub_node(n: hubbub::NodeDataPtr) -> Self;
|
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 {
|
unsafe fn to_hubbub_node(self) -> hubbub::NodeDataPtr {
|
||||||
cast::transmute(self)
|
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)
|
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
|
// Silly macros to handle constructing DOM nodes. This produces bad code and should be optimized
|
||||||
// via atomization (issue #85).
|
// 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
|
// TODO (Issue #85): use atoms
|
||||||
handle_element!(tag, "a", HTMLAnchorElementTypeId, HTMLAnchorElement, []);
|
handle_element!(tag, "a", HTMLAnchorElementTypeId, HTMLAnchorElement, []);
|
||||||
handle_element!(tag, "aside", HTMLAsideElementTypeId, HTMLAsideElement, []);
|
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
|
// consists of processing inline stylesheets, but in the future it might perform
|
||||||
// prefetching, etc.
|
// prefetching, etc.
|
||||||
let css_chan2 = css_chan.clone();
|
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() {
|
if parent_node.is_style_element() && child_node.is_text() {
|
||||||
debug!("found inline CSS stylesheet");
|
debug!("found inline CSS stylesheet");
|
||||||
let url = url::from_str("http://example.com/"); // FIXME
|
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| {
|
append_child: |parent: hubbub::NodeDataPtr, child: hubbub::NodeDataPtr| {
|
||||||
unsafe {
|
unsafe {
|
||||||
debug!("append child %x %x", cast::transmute(parent), cast::transmute(child));
|
debug!("append child %x %x", cast::transmute(parent), cast::transmute(child));
|
||||||
let parent: AbstractNode = NodeWrapping::from_hubbub_node(parent);
|
let parent: AbstractNode<ScriptView> = NodeWrapping::from_hubbub_node(parent);
|
||||||
let child: AbstractNode = NodeWrapping::from_hubbub_node(child);
|
let child: AbstractNode<ScriptView> = NodeWrapping::from_hubbub_node(child);
|
||||||
parent.add_child(child);
|
parent.add_child(child);
|
||||||
append_hook(parent, child);
|
append_hook(parent, child);
|
||||||
}
|
}
|
||||||
|
@ -386,7 +387,7 @@ pub fn parse_html(url: Url,
|
||||||
url: Url,
|
url: Url,
|
||||||
js_chan: SharedChan<JSMessage>) {
|
js_chan: SharedChan<JSMessage>) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let script: AbstractNode = NodeWrapping::from_hubbub_node(script);
|
let script: AbstractNode<ScriptView> = NodeWrapping::from_hubbub_node(script);
|
||||||
do script.with_imm_element |script| {
|
do script.with_imm_element |script| {
|
||||||
match script.get_attr(~"src") {
|
match script.get_attr(~"src") {
|
||||||
Some(src) => {
|
Some(src) => {
|
||||||
|
|
|
@ -4,16 +4,59 @@
|
||||||
|
|
||||||
//! Code for managing the layout data in the DOM.
|
//! 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;
|
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 {
|
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_layout_data(self) -> Option<@mut LayoutData>;
|
||||||
fn initialize_style_for_subtree(self, refs: &mut ~[@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
|
/// 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.
|
/// box in the COW model) and populates it with an empty style object.
|
||||||
fn initialize_layout_data(self) -> Option<@mut LayoutData> {
|
fn initialize_layout_data(self) -> Option<@mut LayoutData> {
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
//! The `RenderBox` type, which represents the leaves of the layout tree.
|
//! The `RenderBox` type, which represents the leaves of the layout tree.
|
||||||
|
|
||||||
use css::node_style::StyledNode;
|
use css::node_style::StyledNode;
|
||||||
use dom::node::AbstractNode;
|
use dom::node::{AbstractNode, LayoutView};
|
||||||
use layout::context::LayoutContext;
|
use layout::context::LayoutContext;
|
||||||
use layout::debug::DebugMethods;
|
use layout::debug::DebugMethods;
|
||||||
use layout::display_list_builder::{DisplayListBuilder, ToGfxColor};
|
use layout::display_list_builder::{DisplayListBuilder, ToGfxColor};
|
||||||
|
@ -145,7 +145,7 @@ pub enum SplitBoxResult {
|
||||||
/// Data common to all render boxes.
|
/// Data common to all render boxes.
|
||||||
pub struct RenderBoxBase {
|
pub struct RenderBoxBase {
|
||||||
/// The DOM node that this `RenderBox` originates from.
|
/// 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.
|
/// The reference to the containing flow context which this box participates in.
|
||||||
ctx: FlowContext,
|
ctx: FlowContext,
|
||||||
|
@ -161,7 +161,8 @@ pub struct RenderBoxBase {
|
||||||
|
|
||||||
impl RenderBoxBase {
|
impl RenderBoxBase {
|
||||||
/// Constructs a new `RenderBoxBase` instance.
|
/// 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 {
|
RenderBoxBase {
|
||||||
node: node,
|
node: node,
|
||||||
ctx: flow_context,
|
ctx: flow_context,
|
||||||
|
@ -501,7 +502,7 @@ pub impl RenderBox {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A convenience function to access the DOM node that this render box represents.
|
/// 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)
|
self.with_imm_base(|base| base.node)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -509,7 +510,7 @@ pub impl RenderBox {
|
||||||
/// represents.
|
/// represents.
|
||||||
///
|
///
|
||||||
/// If there is no ancestor-or-self `Element` node, fails.
|
/// 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| {
|
do self.with_imm_base |base| {
|
||||||
let mut node = base.node;
|
let mut node = base.node;
|
||||||
while !node.is_element() {
|
while !node.is_element() {
|
||||||
|
|
|
@ -6,7 +6,8 @@
|
||||||
|
|
||||||
use dom::element::*;
|
use dom::element::*;
|
||||||
use dom::node::{AbstractNode, CommentNodeTypeId, DoctypeNodeTypeId};
|
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::block::BlockFlowData;
|
||||||
use layout::box::{GenericRenderBoxClass, ImageRenderBox, ImageRenderBoxClass, RenderBox};
|
use layout::box::{GenericRenderBoxClass, ImageRenderBox, ImageRenderBoxClass, RenderBox};
|
||||||
use layout::box::{RenderBoxBase, RenderBoxType, RenderBox_Generic, RenderBox_Image};
|
use layout::box::{RenderBoxBase, RenderBoxType, RenderBox_Generic, RenderBox_Image};
|
||||||
|
@ -51,7 +52,7 @@ enum InlineSpacerSide {
|
||||||
LogicalAfter,
|
LogicalAfter,
|
||||||
}
|
}
|
||||||
|
|
||||||
priv fn simulate_UA_display_rules(node: AbstractNode) -> CSSDisplay {
|
priv fn simulate_UA_display_rules(node: AbstractNode<LayoutView>) -> CSSDisplay {
|
||||||
// FIXME
|
// FIXME
|
||||||
/*let resolved = do node.aux |nd| {
|
/*let resolved = do node.aux |nd| {
|
||||||
match nd.style.display_type {
|
match nd.style.display_type {
|
||||||
|
@ -95,14 +96,14 @@ impl BoxGenerator {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Whether "spacer" boxes are needed to stand in for this DOM node */
|
/* 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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: implement this, generating spacer
|
// TODO: implement this, generating spacer
|
||||||
fn make_inline_spacer_for_node_side(&self,
|
fn make_inline_spacer_for_node_side(&self,
|
||||||
_: &LayoutContext,
|
_: &LayoutContext,
|
||||||
_: AbstractNode,
|
_: AbstractNode<LayoutView>,
|
||||||
_: InlineSpacerSide)
|
_: InlineSpacerSide)
|
||||||
-> Option<RenderBox> {
|
-> Option<RenderBox> {
|
||||||
None
|
None
|
||||||
|
@ -111,7 +112,7 @@ impl BoxGenerator {
|
||||||
pub fn push_node(&mut self,
|
pub fn push_node(&mut self,
|
||||||
ctx: &LayoutContext,
|
ctx: &LayoutContext,
|
||||||
builder: &mut LayoutTreeBuilder,
|
builder: &mut LayoutTreeBuilder,
|
||||||
node: AbstractNode) {
|
node: AbstractNode<LayoutView>) {
|
||||||
debug!("BoxGenerator[f%d]: pushing node: %s", self.flow.id(), node.debug_str());
|
debug!("BoxGenerator[f%d]: pushing node: %s", self.flow.id(), node.debug_str());
|
||||||
|
|
||||||
// first, determine the box type, based on node characteristics
|
// first, determine the box type, based on node characteristics
|
||||||
|
@ -159,7 +160,7 @@ impl BoxGenerator {
|
||||||
pub fn pop_node(&mut self,
|
pub fn pop_node(&mut self,
|
||||||
ctx: &LayoutContext,
|
ctx: &LayoutContext,
|
||||||
_builder: &LayoutTreeBuilder,
|
_builder: &LayoutTreeBuilder,
|
||||||
node: AbstractNode) {
|
node: AbstractNode<LayoutView>) {
|
||||||
debug!("BoxGenerator[f%d]: popping node: %s", self.flow.id(), node.debug_str());
|
debug!("BoxGenerator[f%d]: popping node: %s", self.flow.id(), node.debug_str());
|
||||||
|
|
||||||
match self.flow {
|
match self.flow {
|
||||||
|
@ -222,14 +223,16 @@ impl BuilderContext {
|
||||||
priv fn create_child_flow_of_type(&self,
|
priv fn create_child_flow_of_type(&self,
|
||||||
flow_type: FlowContextType,
|
flow_type: FlowContextType,
|
||||||
builder: &mut LayoutTreeBuilder,
|
builder: &mut LayoutTreeBuilder,
|
||||||
node: AbstractNode) -> BuilderContext {
|
node: AbstractNode<LayoutView>) -> BuilderContext {
|
||||||
let new_flow = builder.make_flow(flow_type, node);
|
let new_flow = builder.make_flow(flow_type, node);
|
||||||
self.attach_child_flow(new_flow);
|
self.attach_child_flow(new_flow);
|
||||||
|
|
||||||
BuilderContext::new(@mut BoxGenerator::new(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 {
|
-> BuilderContext {
|
||||||
debug!("BuilderContext: making new inline collector flow");
|
debug!("BuilderContext: making new inline collector flow");
|
||||||
let new_flow = builder.make_flow(Flow_Inline, node);
|
let new_flow = builder.make_flow(Flow_Inline, node);
|
||||||
|
@ -241,7 +244,9 @@ impl BuilderContext {
|
||||||
BuilderContext::new(new_generator)
|
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 {
|
-> BuilderContext {
|
||||||
match copy self.inline_collector {
|
match copy self.inline_collector {
|
||||||
Some(collector) => BuilderContext::new(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
|
// 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'
|
// by the node should not generate a layout tree. For example, nodes with style 'display:none'
|
||||||
// should just not generate any flows or boxes.
|
// 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> {
|
-> Option<BuilderContext> {
|
||||||
// TODO: remove this once UA styles work
|
// TODO: remove this once UA styles work
|
||||||
// TODO: handle interactions with 'float', 'position' (CSS 2.1, Section 9.7)
|
// TODO: handle interactions with 'float', 'position' (CSS 2.1, Section 9.7)
|
||||||
|
@ -296,7 +303,7 @@ pub impl LayoutTreeBuilder {
|
||||||
/// and recurses on its children.
|
/// and recurses on its children.
|
||||||
fn construct_recursively(&mut self,
|
fn construct_recursively(&mut self,
|
||||||
layout_ctx: &LayoutContext,
|
layout_ctx: &LayoutContext,
|
||||||
cur_node: AbstractNode,
|
cur_node: AbstractNode<LayoutView>,
|
||||||
parent_ctx: &mut BuilderContext) {
|
parent_ctx: &mut BuilderContext) {
|
||||||
debug!("Considering node: %s", cur_node.debug_str());
|
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.
|
/// 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, ()> {
|
-> Result<FlowContext, ()> {
|
||||||
let new_flow = self.make_flow(Flow_Root, root);
|
let new_flow = self.make_flow(Flow_Root, root);
|
||||||
let new_generator = @mut BoxGenerator::new(new_flow);
|
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.
|
/// 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 info = FlowData::new(self.next_flow_id(), node);
|
||||||
let result = match ty {
|
let result = match ty {
|
||||||
Flow_Absolute => AbsoluteFlow(@mut info),
|
Flow_Absolute => AbsoluteFlow(@mut info),
|
||||||
|
@ -450,7 +457,7 @@ pub impl LayoutTreeBuilder {
|
||||||
fn make_box(&mut self,
|
fn make_box(&mut self,
|
||||||
layout_ctx: &LayoutContext,
|
layout_ctx: &LayoutContext,
|
||||||
ty: RenderBoxType,
|
ty: RenderBoxType,
|
||||||
node: AbstractNode,
|
node: AbstractNode<LayoutView>,
|
||||||
flow_context: FlowContext)
|
flow_context: FlowContext)
|
||||||
-> RenderBox {
|
-> RenderBox {
|
||||||
let base = RenderBoxBase::new(node, flow_context, self.next_box_id());
|
let base = RenderBoxBase::new(node, flow_context, self.next_box_id());
|
||||||
|
@ -465,7 +472,7 @@ pub impl LayoutTreeBuilder {
|
||||||
|
|
||||||
fn make_image_box(&mut self,
|
fn make_image_box(&mut self,
|
||||||
layout_ctx: &LayoutContext,
|
layout_ctx: &LayoutContext,
|
||||||
node: AbstractNode,
|
node: AbstractNode<LayoutView>,
|
||||||
base: RenderBoxBase)
|
base: RenderBoxBase)
|
||||||
-> RenderBox {
|
-> RenderBox {
|
||||||
assert!(node.is_image_element());
|
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() {
|
if node.is_text() {
|
||||||
RenderBox_Text
|
RenderBox_Text
|
||||||
} else if node.is_image_element() {
|
} else if node.is_image_element() {
|
||||||
|
|
|
@ -25,8 +25,8 @@
|
||||||
/// line breaks and mapping to CSS boxes, for the purpose of handling `getClientRects()` and
|
/// line breaks and mapping to CSS boxes, for the purpose of handling `getClientRects()` and
|
||||||
/// similar methods.
|
/// similar methods.
|
||||||
|
|
||||||
use dom::node::AbstractNode;
|
use dom::node::{AbstractNode, LayoutView};
|
||||||
use layout::block::{BlockFlowData};
|
use layout::block::BlockFlowData;
|
||||||
use layout::box::RenderBox;
|
use layout::box::RenderBox;
|
||||||
use layout::context::LayoutContext;
|
use layout::context::LayoutContext;
|
||||||
use layout::debug::DebugMethods;
|
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
|
/// FIXME: We need a naming convention for pseudo-inheritance like this. How about
|
||||||
/// `CommonFlowInfo`?
|
/// `CommonFlowInfo`?
|
||||||
pub struct FlowData {
|
pub struct FlowData {
|
||||||
node: AbstractNode,
|
node: AbstractNode<LayoutView>,
|
||||||
|
|
||||||
parent: Option<FlowContext>,
|
parent: Option<FlowContext>,
|
||||||
first_child: Option<FlowContext>,
|
first_child: Option<FlowContext>,
|
||||||
|
@ -202,7 +202,7 @@ impl TreeNode<FlowContext> for FlowData {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FlowData {
|
impl FlowData {
|
||||||
pub fn new(id: int, node: AbstractNode) -> FlowData {
|
pub fn new(id: int, node: AbstractNode<LayoutView>) -> FlowData {
|
||||||
FlowData {
|
FlowData {
|
||||||
node: node,
|
node: node,
|
||||||
|
|
||||||
|
@ -321,7 +321,7 @@ impl<'self> FlowContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn foldl_boxes_for_node<B:Copy>(&self,
|
pub fn foldl_boxes_for_node<B:Copy>(&self,
|
||||||
node: AbstractNode,
|
node: AbstractNode<LayoutView>,
|
||||||
seed: B,
|
seed: B,
|
||||||
callback: &fn(a: B, RenderBox) -> B)
|
callback: &fn(a: B, RenderBox) -> B)
|
||||||
-> B {
|
-> B {
|
||||||
|
@ -358,7 +358,9 @@ impl<'self> FlowContext {
|
||||||
true
|
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 {
|
-> bool {
|
||||||
for self.iter_all_boxes |box| {
|
for self.iter_all_boxes |box| {
|
||||||
if box.node() == node {
|
if box.node() == node {
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
use core::cell::Cell;
|
use core::cell::Cell;
|
||||||
use core;
|
use core;
|
||||||
use dom::node::AbstractNode;
|
use dom::node::{AbstractNode, LayoutView};
|
||||||
use layout::box::{CannotSplit, GenericRenderBoxClass, ImageRenderBoxClass, RenderBox};
|
use layout::box::{CannotSplit, GenericRenderBoxClass, ImageRenderBoxClass, RenderBox};
|
||||||
use layout::box::{SplitDidFit, SplitDidNotFit, TextRenderBoxClass, UnscannedTextRenderBoxClass};
|
use layout::box::{SplitDidFit, SplitDidNotFit, TextRenderBoxClass, UnscannedTextRenderBoxClass};
|
||||||
use layout::context::LayoutContext;
|
use layout::context::LayoutContext;
|
||||||
|
@ -49,12 +49,12 @@ hard to try out that alternative.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
pub struct NodeRange {
|
pub struct NodeRange {
|
||||||
node: AbstractNode,
|
node: AbstractNode<LayoutView>,
|
||||||
range: Range,
|
range: Range,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub impl NodeRange {
|
pub impl NodeRange {
|
||||||
fn new(node: AbstractNode, range: &Range) -> NodeRange {
|
fn new(node: AbstractNode<LayoutView>, range: &Range) -> NodeRange {
|
||||||
NodeRange { node: node, range: copy *range }
|
NodeRange { node: node, range: copy *range }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -68,7 +68,7 @@ impl ElementMapping {
|
||||||
ElementMapping { entries: ~[] }
|
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))
|
self.entries.push(NodeRange::new(node, range))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,8 +8,8 @@
|
||||||
use css::matching::MatchMethods;
|
use css::matching::MatchMethods;
|
||||||
use css::select::new_css_select_ctx;
|
use css::select::new_css_select_ctx;
|
||||||
use dom::event::ReflowEvent;
|
use dom::event::ReflowEvent;
|
||||||
use dom::node::{AbstractNode, LayoutData};
|
use dom::node::{AbstractNode, LayoutView, ScriptView};
|
||||||
use layout::aux::LayoutAuxMethods;
|
use layout::aux::{LayoutData, LayoutAuxMethods};
|
||||||
use layout::box_builder::LayoutTreeBuilder;
|
use layout::box_builder::LayoutTreeBuilder;
|
||||||
use layout::context::LayoutContext;
|
use layout::context::LayoutContext;
|
||||||
use layout::debug::{BoxedMutDebugMethods, DebugMethods};
|
use layout::debug::{BoxedMutDebugMethods, DebugMethods};
|
||||||
|
@ -22,6 +22,7 @@ use servo_util::time::time;
|
||||||
use servo_util::time::profile;
|
use servo_util::time::profile;
|
||||||
use servo_util::time::ProfilerChan;
|
use servo_util::time::ProfilerChan;
|
||||||
|
|
||||||
|
use core::cast::transmute;
|
||||||
use core::cell::Cell;
|
use core::cell::Cell;
|
||||||
use core::comm::{Chan, Port, SharedChan};
|
use core::comm::{Chan, Port, SharedChan};
|
||||||
use geom::point::Point2D;
|
use geom::point::Point2D;
|
||||||
|
@ -44,8 +45,8 @@ use std::net::url::Url;
|
||||||
pub type LayoutTask = SharedChan<Msg>;
|
pub type LayoutTask = SharedChan<Msg>;
|
||||||
|
|
||||||
pub enum LayoutQuery {
|
pub enum LayoutQuery {
|
||||||
ContentBox(AbstractNode),
|
ContentBox(AbstractNode<ScriptView>),
|
||||||
ContentBoxes(AbstractNode)
|
ContentBoxes(AbstractNode<ScriptView>),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type LayoutQueryResponse = Result<LayoutQueryResponse_, ()>;
|
pub type LayoutQueryResponse = Result<LayoutQueryResponse_, ()>;
|
||||||
|
@ -81,7 +82,7 @@ impl Damage {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct BuildData {
|
pub struct BuildData {
|
||||||
node: AbstractNode,
|
node: AbstractNode<ScriptView>,
|
||||||
url: Url,
|
url: Url,
|
||||||
script_chan: SharedChan<ScriptMsg>,
|
script_chan: SharedChan<ScriptMsg>,
|
||||||
window_size: Size2D<uint>,
|
window_size: Size2D<uint>,
|
||||||
|
@ -180,7 +181,11 @@ impl Layout {
|
||||||
|
|
||||||
/// The high-level routine that performs layout tasks.
|
/// The high-level routine that performs layout tasks.
|
||||||
fn handle_build(&mut self, data: &BuildData) {
|
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!
|
// FIXME: Bad copy!
|
||||||
let doc_url = copy data.url;
|
let doc_url = copy data.url;
|
||||||
let script_chan = data.script_chan.clone();
|
let script_chan = data.script_chan.clone();
|
||||||
|
@ -279,6 +284,11 @@ impl Layout {
|
||||||
fn handle_query(&self, query: LayoutQuery, reply_chan: Chan<LayoutQueryResponse>) {
|
fn handle_query(&self, query: LayoutQuery, reply_chan: Chan<LayoutQueryResponse>) {
|
||||||
match query {
|
match query {
|
||||||
ContentBox(node) => {
|
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 {
|
let response = match node.layout_data().flow {
|
||||||
None => {
|
None => {
|
||||||
error!("no flow present");
|
error!("no flow present");
|
||||||
|
@ -306,6 +316,11 @@ impl Layout {
|
||||||
reply_chan.send(response)
|
reply_chan.send(response)
|
||||||
}
|
}
|
||||||
ContentBoxes(node) => {
|
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 {
|
let response = match node.layout_data().flow {
|
||||||
None => Err(()),
|
None => Err(()),
|
||||||
Some(flow) => {
|
Some(flow) => {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue