mirror of
https://github.com/servo/servo.git
synced 2025-07-24 15:50:21 +01:00
Separate style+layout and layout-specific wrapper functionality.
This patch does a number of things, unfortunately all at once: * Hoists a large subset of the layout wrapper functionality into the style system. * Merges TElementAttributes into the newly-created TElement. * Reorganizes LayoutData by style vs layout, and removes LayoutDataShared. * Simplifies the API for borrowing style/layout data. There's still more to do to make the style system usable standalone, but this is a good start.
This commit is contained in:
parent
89ab368258
commit
47059d2d26
20 changed files with 657 additions and 706 deletions
|
@ -57,14 +57,12 @@ use selectors::matching::matches;
|
|||
use selectors::parser::Selector;
|
||||
use selectors::parser::parse_author_origin_selector_list_from_str;
|
||||
use std::borrow::ToOwned;
|
||||
use std::cell::{Cell, Ref, RefCell, RefMut};
|
||||
use std::cell::Cell;
|
||||
use std::cmp::max;
|
||||
use std::default::Default;
|
||||
use std::iter::{self, FilterMap, Peekable};
|
||||
use std::mem;
|
||||
use std::sync::Arc;
|
||||
use string_cache::{Atom, Namespace, QualName};
|
||||
use style::properties::ComputedValues;
|
||||
use util::str::DOMString;
|
||||
use util::task_state;
|
||||
use uuid::Uuid;
|
||||
|
@ -115,11 +113,11 @@ pub struct Node {
|
|||
/// are this node.
|
||||
ranges: WeakRangeVec,
|
||||
|
||||
/// Layout information. Only the layout task may touch this data.
|
||||
/// Style+Layout information. Only the layout task may touch this data.
|
||||
///
|
||||
/// Must be sent back to the layout task to be destroyed when this
|
||||
/// node is finalized.
|
||||
layout_data: LayoutDataRef,
|
||||
style_and_layout_data: Cell<Option<OpaqueStyleAndLayoutData>>,
|
||||
|
||||
unique_id: DOMRefCell<Option<Box<Uuid>>>,
|
||||
}
|
||||
|
@ -164,7 +162,7 @@ impl NodeFlags {
|
|||
impl Drop for Node {
|
||||
#[allow(unsafe_code)]
|
||||
fn drop(&mut self) {
|
||||
self.layout_data.dispose(self);
|
||||
self.style_and_layout_data.get().map(|d| d.dispose(self));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -177,74 +175,27 @@ enum SuppressObserver {
|
|||
Unsuppressed
|
||||
}
|
||||
|
||||
/// Layout data that is shared between the script and layout tasks.
|
||||
#[derive(HeapSizeOf)]
|
||||
pub struct SharedLayoutData {
|
||||
/// The results of CSS styling for this node.
|
||||
pub style: Option<Arc<ComputedValues>>,
|
||||
}
|
||||
|
||||
/// Encapsulates the abstract layout data.
|
||||
#[derive(HeapSizeOf)]
|
||||
pub struct LayoutData {
|
||||
_shared_data: SharedLayoutData,
|
||||
#[ignore_heap_size_of = "TODO(#6910) Box value that should be counted but the type lives in layout"]
|
||||
_data: NonZero<*const ()>,
|
||||
#[derive(Copy, Clone, HeapSizeOf)]
|
||||
pub struct OpaqueStyleAndLayoutData {
|
||||
#[ignore_heap_size_of = "TODO(#6910) Box value that should be counted but \
|
||||
the type lives in layout"]
|
||||
pub ptr: NonZero<*mut ()>
|
||||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
unsafe impl Send for LayoutData {}
|
||||
unsafe impl Send for OpaqueStyleAndLayoutData {}
|
||||
|
||||
#[derive(HeapSizeOf)]
|
||||
pub struct LayoutDataRef {
|
||||
data_cell: RefCell<Option<LayoutData>>,
|
||||
}
|
||||
no_jsmanaged_fields!(OpaqueStyleAndLayoutData);
|
||||
|
||||
no_jsmanaged_fields!(LayoutDataRef);
|
||||
|
||||
impl LayoutDataRef {
|
||||
pub fn new() -> LayoutDataRef {
|
||||
LayoutDataRef {
|
||||
data_cell: RefCell::new(None),
|
||||
}
|
||||
}
|
||||
|
||||
/// Sends layout data, if any, back to the layout task to be destroyed.
|
||||
pub fn dispose(&self, node: &Node) {
|
||||
impl OpaqueStyleAndLayoutData {
|
||||
/// Sends the style and layout data, if any, back to the layout task to be destroyed.
|
||||
pub fn dispose(self, node: &Node) {
|
||||
debug_assert!(task_state::get().is_script());
|
||||
if let Some(layout_data) = mem::replace(&mut *self.data_cell.borrow_mut(), None) {
|
||||
let win = window_from_node(node);
|
||||
let LayoutChan(chan) = win.layout_chan();
|
||||
chan.send(Msg::ReapLayoutData(layout_data)).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
/// Borrows the layout data immutably, *assuming that there are no mutators*. Bad things will
|
||||
/// happen if you try to mutate the layout data while this is held. This is the only thread-
|
||||
/// safe layout data accessor.
|
||||
#[inline]
|
||||
#[allow(unsafe_code)]
|
||||
pub unsafe fn borrow_unchecked(&self) -> *const Option<LayoutData> {
|
||||
debug_assert!(task_state::get().is_layout());
|
||||
self.data_cell.as_unsafe_cell().get() as *const _
|
||||
}
|
||||
|
||||
/// Borrows the layout data immutably. This function is *not* thread-safe.
|
||||
#[inline]
|
||||
pub fn borrow(&self) -> Ref<Option<LayoutData>> {
|
||||
debug_assert!(task_state::get().is_layout());
|
||||
self.data_cell.borrow()
|
||||
}
|
||||
|
||||
/// Borrows the layout data mutably. This function is *not* thread-safe.
|
||||
///
|
||||
/// FIXME(pcwalton): We should really put this behind a `MutLayoutView` phantom type, to
|
||||
/// prevent CSS selector matching from mutably accessing nodes it's not supposed to and racing
|
||||
/// on it. This has already resulted in one bug!
|
||||
#[inline]
|
||||
pub fn borrow_mut(&self) -> RefMut<Option<LayoutData>> {
|
||||
debug_assert!(task_state::get().is_layout());
|
||||
self.data_cell.borrow_mut()
|
||||
let win = window_from_node(node);
|
||||
let LayoutChan(chan) = win.layout_chan();
|
||||
node.style_and_layout_data.set(None);
|
||||
chan.send(Msg::ReapStyleAndLayoutData(self)).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -334,7 +285,7 @@ impl Node {
|
|||
for node in child.traverse_preorder() {
|
||||
node.set_flag(IS_IN_DOC, false);
|
||||
vtable_for(&&*node).unbind_from_tree(&context);
|
||||
node.layout_data.dispose(&node);
|
||||
node.style_and_layout_data.get().map(|d| d.dispose(&node));
|
||||
}
|
||||
|
||||
self.owner_doc().content_and_heritage_changed(self, NodeDamage::OtherNodeDamage);
|
||||
|
@ -378,7 +329,7 @@ impl<'a> Iterator for QuerySelectorIterator {
|
|||
|
||||
impl Node {
|
||||
pub fn teardown(&self) {
|
||||
self.layout_data.dispose(self);
|
||||
self.style_and_layout_data.get().map(|d| d.dispose(self));
|
||||
for kid in self.children() {
|
||||
kid.teardown();
|
||||
}
|
||||
|
@ -966,9 +917,8 @@ pub trait LayoutNodeHelpers {
|
|||
|
||||
unsafe fn children_count(&self) -> u32;
|
||||
|
||||
unsafe fn layout_data(&self) -> Ref<Option<LayoutData>>;
|
||||
unsafe fn layout_data_mut(&self) -> RefMut<Option<LayoutData>>;
|
||||
unsafe fn layout_data_unchecked(&self) -> *const Option<LayoutData>;
|
||||
unsafe fn get_style_and_layout_data(&self) -> Option<OpaqueStyleAndLayoutData>;
|
||||
unsafe fn init_style_and_layout_data(&self, OpaqueStyleAndLayoutData);
|
||||
}
|
||||
|
||||
impl LayoutNodeHelpers for LayoutJS<Node> {
|
||||
|
@ -1049,20 +999,15 @@ impl LayoutNodeHelpers for LayoutJS<Node> {
|
|||
|
||||
#[inline]
|
||||
#[allow(unsafe_code)]
|
||||
unsafe fn layout_data(&self) -> Ref<Option<LayoutData>> {
|
||||
(*self.unsafe_get()).layout_data.borrow()
|
||||
unsafe fn get_style_and_layout_data(&self) -> Option<OpaqueStyleAndLayoutData> {
|
||||
(*self.unsafe_get()).style_and_layout_data.get()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[allow(unsafe_code)]
|
||||
unsafe fn layout_data_mut(&self) -> RefMut<Option<LayoutData>> {
|
||||
(*self.unsafe_get()).layout_data.borrow_mut()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[allow(unsafe_code)]
|
||||
unsafe fn layout_data_unchecked(&self) -> *const Option<LayoutData> {
|
||||
(*self.unsafe_get()).layout_data.borrow_unchecked()
|
||||
unsafe fn init_style_and_layout_data(&self, val: OpaqueStyleAndLayoutData) {
|
||||
debug_assert!((*self.unsafe_get()).style_and_layout_data.get().is_none());
|
||||
(*self.unsafe_get()).style_and_layout_data.set(Some(val));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1322,7 +1267,7 @@ impl Node {
|
|||
inclusive_descendants_version: Cell::new(0),
|
||||
ranges: WeakRangeVec::new(),
|
||||
|
||||
layout_data: LayoutDataRef::new(),
|
||||
style_and_layout_data: Cell::new(None),
|
||||
|
||||
unique_id: DOMRefCell::new(None),
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
//! the DOM to be placed in a separate crate from layout.
|
||||
|
||||
use app_units::Au;
|
||||
use dom::node::LayoutData;
|
||||
use dom::node::OpaqueStyleAndLayoutData;
|
||||
use euclid::point::Point2D;
|
||||
use euclid::rect::Rect;
|
||||
use gfx_traits::LayerId;
|
||||
|
@ -59,7 +59,7 @@ pub enum Msg {
|
|||
/// Destroys layout data associated with a DOM node.
|
||||
///
|
||||
/// TODO(pcwalton): Maybe think about batching to avoid message traffic.
|
||||
ReapLayoutData(LayoutData),
|
||||
ReapStyleAndLayoutData(OpaqueStyleAndLayoutData),
|
||||
|
||||
/// Requests that the layout task measure its memory usage. The resulting reports are sent back
|
||||
/// via the supplied channel.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue