mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
Introduce a ThreadSafeLayoutNodeHelpers trait for methods to stay in layout.
This commit is contained in:
parent
dac8878467
commit
afc7118a67
4 changed files with 98 additions and 89 deletions
|
@ -60,7 +60,8 @@ use traversal::PostorderNodeMutTraversal;
|
|||
use url::Url;
|
||||
use util::linked_list;
|
||||
use util::opts;
|
||||
use wrapper::{PseudoElementType, TextContent, ThreadSafeLayoutElement, ThreadSafeLayoutNode};
|
||||
use wrapper::{PseudoElementType, TextContent, ThreadSafeLayoutElement};
|
||||
use wrapper::{ThreadSafeLayoutNode, ThreadSafeLayoutNodeHelpers};
|
||||
|
||||
/// The results of flow construction for a DOM node.
|
||||
#[derive(Clone)]
|
||||
|
|
|
@ -34,7 +34,7 @@ use style::properties::style_structs;
|
|||
use style::selector_impl::PseudoElement;
|
||||
use style::values::AuExtensionMethods;
|
||||
use style_traits::cursor::Cursor;
|
||||
use wrapper::{LayoutNode, ThreadSafeLayoutNode};
|
||||
use wrapper::{LayoutNode, ThreadSafeLayoutNode, ThreadSafeLayoutNodeHelpers};
|
||||
|
||||
pub struct LayoutRPCImpl(pub Arc<Mutex<LayoutThreadData>>);
|
||||
|
||||
|
|
|
@ -18,7 +18,8 @@ use style::traversal::{DomTraversalContext, STYLE_BLOOM};
|
|||
use style::traversal::{put_thread_local_bloom_filter, recalc_style_at};
|
||||
use util::opts;
|
||||
use util::tid::tid;
|
||||
use wrapper::{LayoutNode, LayoutNodeLayoutData, ServoLayoutNode, ThreadSafeLayoutNode};
|
||||
use wrapper::{LayoutNode, LayoutNodeLayoutData, ServoLayoutNode};
|
||||
use wrapper::{ThreadSafeLayoutNode, ThreadSafeLayoutNodeHelpers};
|
||||
|
||||
pub struct RecalcStyleAndConstructFlows<'lc> {
|
||||
context: LayoutContext<'lc>,
|
||||
|
|
|
@ -724,8 +724,6 @@ pub trait ThreadSafeLayoutNode: Clone + Copy + Sized + PartialEq {
|
|||
|
||||
fn debug_id(self) -> usize;
|
||||
|
||||
fn flow_debug_id(self) -> usize;
|
||||
|
||||
/// Returns an iterator over this node's children.
|
||||
fn children(&self) -> Self::ChildrenIterator;
|
||||
|
||||
|
@ -796,21 +794,6 @@ pub trait ThreadSafeLayoutNode: Clone + Copy + Sized + PartialEq {
|
|||
|
||||
fn get_style_and_layout_data(&self) -> Option<OpaqueStyleAndLayoutData>;
|
||||
|
||||
#[inline(always)]
|
||||
unsafe fn borrow_layout_data_unchecked(&self) -> Option<*const PrivateLayoutData>;
|
||||
|
||||
/// Borrows the layout data immutably. Fails on a conflicting borrow.
|
||||
///
|
||||
/// TODO(pcwalton): Make this private. It will let us avoid borrow flag checks in some cases.
|
||||
#[inline(always)]
|
||||
fn borrow_layout_data(&self) -> Option<Ref<PrivateLayoutData>>;
|
||||
|
||||
/// Borrows the layout data mutably. Fails on a conflicting borrow.
|
||||
///
|
||||
/// TODO(pcwalton): Make this private. It will let us avoid borrow flag checks in some cases.
|
||||
#[inline(always)]
|
||||
fn mutate_layout_data(&self) -> Option<RefMut<PrivateLayoutData>>;
|
||||
|
||||
/// Returns the style results for the given node. If CSS selector matching
|
||||
/// has not yet been performed, fails.
|
||||
///
|
||||
|
@ -922,19 +905,6 @@ pub trait ThreadSafeLayoutNode: Clone + Copy + Sized + PartialEq {
|
|||
|
||||
fn set_restyle_damage(self, damage: RestyleDamage);
|
||||
|
||||
/// Returns the layout data flags for this node.
|
||||
fn flags(self) -> LayoutDataFlags;
|
||||
|
||||
/// Adds the given flags to this node.
|
||||
fn insert_flags(self, new_flags: LayoutDataFlags) {
|
||||
self.mutate_layout_data().unwrap().flags.insert(new_flags);
|
||||
}
|
||||
|
||||
/// Removes the given flags from this node.
|
||||
fn remove_flags(self, flags: LayoutDataFlags) {
|
||||
self.mutate_layout_data().unwrap().flags.remove(flags);
|
||||
}
|
||||
|
||||
/// Returns true if this node contributes content. This is used in the implementation of
|
||||
/// `empty_cells` per CSS 2.1 § 17.6.1.1.
|
||||
fn is_content(&self) -> bool {
|
||||
|
@ -946,12 +916,6 @@ pub trait ThreadSafeLayoutNode: Clone + Copy + Sized + PartialEq {
|
|||
|
||||
fn can_be_fragmented(&self) -> bool;
|
||||
|
||||
/// If this is a text node, generated content, or a form element, copies out
|
||||
/// its content. Otherwise, panics.
|
||||
///
|
||||
/// FIXME(pcwalton): This might have too much copying and/or allocation. Profile this.
|
||||
fn text_content(&self) -> TextContent;
|
||||
|
||||
fn node_text_content(&self) -> String;
|
||||
|
||||
/// If the insertion point is within this node, returns it. Otherwise, returns `None`.
|
||||
|
@ -988,6 +952,39 @@ pub trait ThreadSafeLayoutNode: Clone + Copy + Sized + PartialEq {
|
|||
fn get_style_data(&self) -> Option<&RefCell<PartialStyleAndLayoutData>>;
|
||||
}
|
||||
|
||||
pub trait ThreadSafeLayoutNodeHelpers {
|
||||
fn flow_debug_id(self) -> usize;
|
||||
|
||||
unsafe fn borrow_layout_data_unchecked(&self) -> Option<*const PrivateLayoutData>;
|
||||
|
||||
/// Borrows the layout data immutably. Fails on a conflicting borrow.
|
||||
///
|
||||
/// TODO(pcwalton): Make this private. It will let us avoid borrow flag checks in some cases.
|
||||
#[inline(always)]
|
||||
fn borrow_layout_data(&self) -> Option<Ref<PrivateLayoutData>>;
|
||||
|
||||
/// Borrows the layout data mutably. Fails on a conflicting borrow.
|
||||
///
|
||||
/// TODO(pcwalton): Make this private. It will let us avoid borrow flag checks in some cases.
|
||||
#[inline(always)]
|
||||
fn mutate_layout_data(&self) -> Option<RefMut<PrivateLayoutData>>;
|
||||
|
||||
/// Returns the layout data flags for this node.
|
||||
fn flags(self) -> LayoutDataFlags;
|
||||
|
||||
/// Adds the given flags to this node.
|
||||
fn insert_flags(self, new_flags: LayoutDataFlags);
|
||||
|
||||
/// Removes the given flags from this node.
|
||||
fn remove_flags(self, flags: LayoutDataFlags);
|
||||
|
||||
/// If this is a text node, generated content, or a form element, copies out
|
||||
/// its content. Otherwise, panics.
|
||||
///
|
||||
/// FIXME(pcwalton): This might have too much copying and/or allocation. Profile this.
|
||||
fn text_content(&self) -> TextContent;
|
||||
}
|
||||
|
||||
// This trait is only public so that it can be implemented by the gecko wrapper.
|
||||
// It can be used to violate thread-safety, so don't use it elsewhere in layout!
|
||||
pub trait DangerousThreadSafeLayoutNode: ThreadSafeLayoutNode {
|
||||
|
@ -1095,10 +1092,6 @@ impl<'ln> ThreadSafeLayoutNode for ServoThreadSafeLayoutNode<'ln> {
|
|||
self.node.debug_id()
|
||||
}
|
||||
|
||||
fn flow_debug_id(self) -> usize {
|
||||
self.node.flow_debug_id()
|
||||
}
|
||||
|
||||
fn children(&self) -> Self::ChildrenIterator {
|
||||
ThreadSafeLayoutNodeChildrenIterator::new(*self)
|
||||
}
|
||||
|
@ -1125,31 +1118,6 @@ impl<'ln> ThreadSafeLayoutNode for ServoThreadSafeLayoutNode<'ln> {
|
|||
self.node.get_style_and_layout_data()
|
||||
}
|
||||
|
||||
unsafe fn borrow_layout_data_unchecked(&self) -> Option<*const PrivateLayoutData> {
|
||||
self.get_style_and_layout_data().map(|opaque| {
|
||||
let container = *opaque.ptr as NonOpaqueStyleAndLayoutData;
|
||||
&(*(*container).as_unsafe_cell().get()) as *const PrivateLayoutData
|
||||
})
|
||||
}
|
||||
|
||||
fn borrow_layout_data(&self) -> Option<Ref<PrivateLayoutData>> {
|
||||
unsafe {
|
||||
self.get_style_and_layout_data().map(|opaque| {
|
||||
let container = *opaque.ptr as NonOpaqueStyleAndLayoutData;
|
||||
(*container).borrow()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn mutate_layout_data(&self) -> Option<RefMut<PrivateLayoutData>> {
|
||||
unsafe {
|
||||
self.get_style_and_layout_data().map(|opaque| {
|
||||
let container = *opaque.ptr as NonOpaqueStyleAndLayoutData;
|
||||
(*container).borrow_mut()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn is_ignorable_whitespace(&self, context: &SharedStyleContext) -> bool {
|
||||
unsafe {
|
||||
let text: LayoutJS<Text> = match self.get_jsmanaged().downcast() {
|
||||
|
@ -1179,31 +1147,10 @@ impl<'ln> ThreadSafeLayoutNode for ServoThreadSafeLayoutNode<'ln> {
|
|||
self.node.set_restyle_damage(damage)
|
||||
}
|
||||
|
||||
fn flags(self) -> LayoutDataFlags {
|
||||
unsafe {
|
||||
(*self.borrow_layout_data_unchecked().unwrap()).flags
|
||||
}
|
||||
}
|
||||
|
||||
fn can_be_fragmented(&self) -> bool {
|
||||
self.node.can_be_fragmented()
|
||||
}
|
||||
|
||||
fn text_content(&self) -> TextContent {
|
||||
if self.pseudo.is_replaced_content() {
|
||||
let style = self.resolved_style();
|
||||
|
||||
return match style.as_ref().get_counters().content {
|
||||
content::T::Content(ref value) if !value.is_empty() => {
|
||||
TextContent::GeneratedContent((*value).clone())
|
||||
}
|
||||
_ => TextContent::GeneratedContent(vec![]),
|
||||
};
|
||||
}
|
||||
|
||||
return TextContent::Text(self.node_text_content());
|
||||
}
|
||||
|
||||
fn node_text_content(&self) -> String {
|
||||
let this = unsafe { self.get_jsmanaged() };
|
||||
return this.text_content();
|
||||
|
@ -1244,6 +1191,66 @@ impl<'ln> ThreadSafeLayoutNode for ServoThreadSafeLayoutNode<'ln> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: ThreadSafeLayoutNode> ThreadSafeLayoutNodeHelpers for T {
|
||||
fn flow_debug_id(self) -> usize {
|
||||
self.borrow_layout_data().map_or(0, |d| d.flow_construction_result.debug_id())
|
||||
}
|
||||
|
||||
unsafe fn borrow_layout_data_unchecked(&self) -> Option<*const PrivateLayoutData> {
|
||||
self.get_style_and_layout_data().map(|opaque| {
|
||||
let container = *opaque.ptr as NonOpaqueStyleAndLayoutData;
|
||||
&(*(*container).as_unsafe_cell().get()) as *const PrivateLayoutData
|
||||
})
|
||||
}
|
||||
|
||||
fn borrow_layout_data(&self) -> Option<Ref<PrivateLayoutData>> {
|
||||
unsafe {
|
||||
self.get_style_and_layout_data().map(|opaque| {
|
||||
let container = *opaque.ptr as NonOpaqueStyleAndLayoutData;
|
||||
(*container).borrow()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn mutate_layout_data(&self) -> Option<RefMut<PrivateLayoutData>> {
|
||||
unsafe {
|
||||
self.get_style_and_layout_data().map(|opaque| {
|
||||
let container = *opaque.ptr as NonOpaqueStyleAndLayoutData;
|
||||
(*container).borrow_mut()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn flags(self) -> LayoutDataFlags {
|
||||
unsafe {
|
||||
(*self.borrow_layout_data_unchecked().unwrap()).flags
|
||||
}
|
||||
}
|
||||
|
||||
fn insert_flags(self, new_flags: LayoutDataFlags) {
|
||||
self.mutate_layout_data().unwrap().flags.insert(new_flags);
|
||||
}
|
||||
|
||||
fn remove_flags(self, flags: LayoutDataFlags) {
|
||||
self.mutate_layout_data().unwrap().flags.remove(flags);
|
||||
}
|
||||
|
||||
fn text_content(&self) -> TextContent {
|
||||
if self.get_pseudo_element_type().is_replaced_content() {
|
||||
let style = self.resolved_style();
|
||||
|
||||
return match style.as_ref().get_counters().content {
|
||||
content::T::Content(ref value) if !value.is_empty() => {
|
||||
TextContent::GeneratedContent((*value).clone())
|
||||
}
|
||||
_ => TextContent::GeneratedContent(vec![]),
|
||||
};
|
||||
}
|
||||
|
||||
return TextContent::Text(self.node_text_content());
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ThreadSafeLayoutNodeChildrenIterator<ConcreteNode: ThreadSafeLayoutNode> {
|
||||
current_node: Option<ConcreteNode>,
|
||||
parent_node: ConcreteNode,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue