diff --git a/components/layout/construct.rs b/components/layout/construct.rs index 3066f8f6ae5..8c79618a6ed 100644 --- a/components/layout/construct.rs +++ b/components/layout/construct.rs @@ -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)] diff --git a/components/layout/query.rs b/components/layout/query.rs index 59da80802af..728cf75e7a9 100644 --- a/components/layout/query.rs +++ b/components/layout/query.rs @@ -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>); diff --git a/components/layout/traversal.rs b/components/layout/traversal.rs index 14289683d4d..27734312e1f 100644 --- a/components/layout/traversal.rs +++ b/components/layout/traversal.rs @@ -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>, diff --git a/components/layout/wrapper.rs b/components/layout/wrapper.rs index 72685fbc577..ce4fe30c075 100644 --- a/components/layout/wrapper.rs +++ b/components/layout/wrapper.rs @@ -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; - #[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>; - - /// 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>; - /// 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>; } +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>; + + /// 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>; + + /// 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> { - unsafe { - self.get_style_and_layout_data().map(|opaque| { - let container = *opaque.ptr as NonOpaqueStyleAndLayoutData; - (*container).borrow() - }) - } - } - - fn mutate_layout_data(&self) -> Option> { - 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 = 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 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> { + unsafe { + self.get_style_and_layout_data().map(|opaque| { + let container = *opaque.ptr as NonOpaqueStyleAndLayoutData; + (*container).borrow() + }) + } + } + + fn mutate_layout_data(&self) -> Option> { + 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 { current_node: Option, parent_node: ConcreteNode,