aboutsummaryrefslogtreecommitdiffstats
path: root/components/script_layout_interface/wrapper_traits.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/script_layout_interface/wrapper_traits.rs')
-rw-r--r--components/script_layout_interface/wrapper_traits.rs246
1 files changed, 134 insertions, 112 deletions
diff --git a/components/script_layout_interface/wrapper_traits.rs b/components/script_layout_interface/wrapper_traits.rs
index 200aeaa03af..669a3e331be 100644
--- a/components/script_layout_interface/wrapper_traits.rs
+++ b/components/script_layout_interface/wrapper_traits.rs
@@ -25,7 +25,7 @@ use style::properties::ServoComputedValues;
use style::selector_impl::{PseudoElement, PseudoElementCascadeType, ServoSelectorImpl};
use url::Url;
-#[derive(Copy, PartialEq, Clone)]
+#[derive(Copy, PartialEq, Clone, Debug)]
pub enum PseudoElementType<T> {
Normal,
Before(T),
@@ -70,9 +70,14 @@ impl<T> PseudoElementType<T> {
}
}
+/// Trait to abstract access to layout data across various data structures.
+pub trait GetLayoutData {
+ fn get_style_and_layout_data(&self) -> Option<OpaqueStyleAndLayoutData>;
+}
+
/// A wrapper so that layout can access only the methods that it should have access to. Layout must
/// only ever see these and must never see instances of `LayoutJS`.
-pub trait LayoutNode: TNode {
+pub trait LayoutNode: GetLayoutData + TNode {
type ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode;
fn to_threadsafe(&self) -> Self::ConcreteThreadSafeLayoutNode;
@@ -86,7 +91,6 @@ pub trait LayoutNode: TNode {
fn get_style_data(&self) -> Option<&AtomicRefCell<NodeData>>;
fn init_style_and_layout_data(&self, data: OpaqueStyleAndLayoutData);
- fn get_style_and_layout_data(&self) -> Option<OpaqueStyleAndLayoutData>;
fn rev_children(self) -> LayoutIterator<ReverseChildrenIterator<Self>> {
LayoutIterator(ReverseChildrenIterator {
@@ -144,16 +148,12 @@ impl<ConcreteNode> Iterator for TreeIterator<ConcreteNode>
/// A thread-safe version of `LayoutNode`, used during flow construction. This type of layout
/// node does not allow any parents or siblings of nodes to be accessed, to avoid races.
-pub trait ThreadSafeLayoutNode: Clone + Copy + NodeInfo + PartialEq + Sized {
+pub trait ThreadSafeLayoutNode: Clone + Copy + GetLayoutData + NodeInfo + PartialEq + Sized {
type ConcreteThreadSafeLayoutElement:
ThreadSafeLayoutElement<ConcreteThreadSafeLayoutNode = Self>
+ ::selectors::Element<Impl=ServoSelectorImpl>;
type ChildrenIterator: Iterator<Item = Self> + Sized;
- /// Creates a new `ThreadSafeLayoutNode` for the same `LayoutNode`
- /// with a different pseudo-element type.
- fn with_pseudo(&self, pseudo: PseudoElementType<Option<display::T>>) -> Self;
-
/// Converts self into an `OpaqueNode`.
fn opaque(&self) -> OpaqueNode;
@@ -183,22 +183,126 @@ pub trait ThreadSafeLayoutNode: Clone + Copy + NodeInfo + PartialEq + Sized {
}
}
+ fn get_before_pseudo(&self) -> Option<Self> {
+ self.as_element().and_then(|el| el.get_before_pseudo()).map(|el| el.as_node())
+ }
+
+ fn get_after_pseudo(&self) -> Option<Self> {
+ self.as_element().and_then(|el| el.get_after_pseudo()).map(|el| el.as_node())
+ }
+
+ fn get_details_summary_pseudo(&self) -> Option<Self> {
+ self.as_element().and_then(|el| el.get_details_summary_pseudo()).map(|el| el.as_node())
+ }
+
+ fn get_details_content_pseudo(&self) -> Option<Self> {
+ self.as_element().and_then(|el| el.get_details_content_pseudo()).map(|el| el.as_node())
+ }
+
fn debug_id(self) -> usize;
/// Returns an iterator over this node's children.
fn children(&self) -> LayoutIterator<Self::ChildrenIterator>;
- /// If this is an element, accesses the element data. Fails if this is not an element node.
+ /// Returns a ThreadSafeLayoutElement if this is an element, None otherwise.
+ #[inline]
+ fn as_element(&self) -> Option<Self::ConcreteThreadSafeLayoutElement>;
+
+ #[inline]
+ fn get_pseudo_element_type(&self) -> PseudoElementType<Option<display::T>> {
+ self.as_element().map_or(PseudoElementType::Normal, |el| el.get_pseudo_element_type())
+ }
+
+ fn get_style_and_layout_data(&self) -> Option<OpaqueStyleAndLayoutData>;
+
+ fn style(&self, context: &SharedStyleContext) -> Arc<ServoComputedValues> {
+ if let Some(el) = self.as_element() {
+ el.style(context)
+ } else {
+ debug_assert!(self.is_text_node());
+ self.style_for_text_node()
+ }
+ }
+
+ fn selected_style(&self) -> Arc<ServoComputedValues> {
+ if let Some(el) = self.as_element() {
+ el.selected_style()
+ } else {
+ debug_assert!(self.is_text_node());
+ self.style_for_text_node()
+ }
+ }
+
+ fn is_ignorable_whitespace(&self, context: &SharedStyleContext) -> bool;
+
+ fn restyle_damage(self) -> RestyleDamage;
+
+ fn clear_restyle_damage(self);
+
+ /// 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 {
+ self.type_id().is_some()
+ }
+
+ fn can_be_fragmented(&self) -> bool;
+
+ fn node_text_content(&self) -> String;
+
+ /// If the insertion point is within this node, returns it. Otherwise, returns `None`.
+ fn selection(&self) -> Option<Range<ByteIndex>>;
+
+ /// If this is an image element, returns its URL. If this is not an image element, fails.
+ ///
+ /// FIXME(pcwalton): Don't copy URLs.
+ fn image_url(&self) -> Option<Url>;
+
+ fn canvas_data(&self) -> Option<HTMLCanvasData>;
+
+ fn svg_data(&self) -> Option<SVGSVGData>;
+
+ /// If this node is an iframe element, returns its pipeline ID. If this node is
+ /// not an iframe element, fails.
+ fn iframe_pipeline_id(&self) -> PipelineId;
+
+ fn get_colspan(&self) -> u32;
+}
+
+// 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!
+#[allow(unsafe_code)]
+pub trait DangerousThreadSafeLayoutNode: ThreadSafeLayoutNode {
+ unsafe fn dangerous_first_child(&self) -> Option<Self>;
+ unsafe fn dangerous_next_sibling(&self) -> Option<Self>;
+}
+
+pub trait ThreadSafeLayoutElement: Clone + Copy + Sized + Debug +
+ ::selectors::Element<Impl=ServoSelectorImpl> +
+ GetLayoutData +
+ PresentationalHintsSynthetizer {
+ type ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode<ConcreteThreadSafeLayoutElement = Self>;
+
+ fn as_node(&self) -> Self::ConcreteThreadSafeLayoutNode;
+
+ /// Creates a new `ThreadSafeLayoutElement` for the same `LayoutElement`
+ /// with a different pseudo-element type.
+ fn with_pseudo(&self, pseudo: PseudoElementType<Option<display::T>>) -> Self;
+
+ /// Returns the type ID of this node.
+ /// Returns `None` if this is a pseudo-element; otherwise, returns `Some`.
+ fn type_id(&self) -> Option<LayoutNodeType>;
+
#[inline]
- fn as_element(&self) -> Self::ConcreteThreadSafeLayoutElement;
+ fn get_attr(&self, namespace: &Namespace, name: &Atom) -> Option<&str>;
+
+ fn get_style_data(&self) -> Option<&AtomicRefCell<NodeData>>;
#[inline]
fn get_pseudo_element_type(&self) -> PseudoElementType<Option<display::T>>;
#[inline]
fn get_before_pseudo(&self) -> Option<Self> {
- if self.is_element() &&
- self.get_style_data()
+ if self.get_style_data()
.unwrap()
.borrow()
.current_styles().pseudos
@@ -211,8 +315,7 @@ pub trait ThreadSafeLayoutNode: Clone + Copy + NodeInfo + PartialEq + Sized {
#[inline]
fn get_after_pseudo(&self) -> Option<Self> {
- if self.is_element() &&
- self.get_style_data()
+ if self.get_style_data()
.unwrap()
.borrow()
.current_styles().pseudos
@@ -225,9 +328,8 @@ pub trait ThreadSafeLayoutNode: Clone + Copy + NodeInfo + PartialEq + Sized {
#[inline]
fn get_details_summary_pseudo(&self) -> Option<Self> {
- if self.is_element() &&
- self.as_element().get_local_name() == &atom!("details") &&
- self.as_element().get_namespace() == &ns!(html) {
+ if self.get_local_name() == &atom!("details") &&
+ self.get_namespace() == &ns!(html) {
Some(self.with_pseudo(PseudoElementType::DetailsSummary(None)))
} else {
None
@@ -236,10 +338,9 @@ pub trait ThreadSafeLayoutNode: Clone + Copy + NodeInfo + PartialEq + Sized {
#[inline]
fn get_details_content_pseudo(&self) -> Option<Self> {
- if self.is_element() &&
- self.as_element().get_local_name() == &atom!("details") &&
- self.as_element().get_namespace() == &ns!(html) {
- let display = if self.as_element().get_attr(&ns!(), &atom!("open")).is_some() {
+ if self.get_local_name() == &atom!("details") &&
+ self.get_namespace() == &ns!(html) {
+ let display = if self.get_attr(&ns!(), &atom!("open")).is_some() {
None // Specified by the stylesheet
} else {
Some(display::T::none)
@@ -250,8 +351,6 @@ pub trait ThreadSafeLayoutNode: Clone + Copy + NodeInfo + PartialEq + Sized {
}
}
- fn get_style_and_layout_data(&self) -> Option<OpaqueStyleAndLayoutData>;
-
/// Returns the style results for the given node. If CSS selector matching
/// has not yet been performed, fails.
///
@@ -259,13 +358,8 @@ pub trait ThreadSafeLayoutNode: Clone + Copy + NodeInfo + PartialEq + Sized {
#[inline]
fn style(&self, context: &SharedStyleContext) -> Arc<ServoComputedValues> {
match self.get_pseudo_element_type() {
- PseudoElementType::Normal => {
- match self.type_id().unwrap() {
- LayoutNodeType::Text => self.style_for_text_node(),
- LayoutNodeType::Element(_) => self.get_style_data().unwrap().borrow()
- .current_styles().primary.clone(),
- }
- },
+ PseudoElementType::Normal => self.get_style_data().unwrap().borrow()
+ .current_styles().primary.clone(),
other => {
// Precompute non-eagerly-cascaded pseudo-element styles if not
// cached before.
@@ -289,7 +383,6 @@ pub trait ThreadSafeLayoutNode: Clone + Copy + NodeInfo + PartialEq + Sized {
}
}
PseudoElementCascadeType::Lazy => {
- debug_assert!(self.is_element_or_elements_pseudo());
if !self.get_style_data()
.unwrap()
.borrow()
@@ -298,7 +391,7 @@ pub trait ThreadSafeLayoutNode: Clone + Copy + NodeInfo + PartialEq + Sized {
let new_style =
context.stylist
.lazily_compute_pseudo_element_style(
- &self.as_element(),
+ self,
&style_pseudo,
&data.current_styles().primary);
data.current_pseudos_mut()
@@ -314,6 +407,15 @@ pub trait ThreadSafeLayoutNode: Clone + Copy + NodeInfo + PartialEq + Sized {
}
}
+ #[inline]
+ fn selected_style(&self) -> Arc<ServoComputedValues> {
+ let data = self.get_style_data().unwrap().borrow();
+ data.current_styles().pseudos
+ .get(&PseudoElement::Selection)
+ .unwrap_or(&data.current_styles().primary)
+ .clone()
+ }
+
/// Returns the already resolved style of the node.
///
/// This differs from `style(ctx)` in that if the pseudo-element has not yet
@@ -323,11 +425,6 @@ pub trait ThreadSafeLayoutNode: Clone + Copy + NodeInfo + PartialEq + Sized {
/// element style is precomputed, not from general layout itself.
#[inline]
fn resolved_style(&self) -> Arc<ServoComputedValues> {
- // FIXME(bholley): This should move to Element and lose the text node check.
- if self.is_text_node() {
- return self.style_for_text_node();
- }
-
let data = self.get_style_data().unwrap().borrow();
match self.get_pseudo_element_type() {
PseudoElementType::Normal
@@ -337,79 +434,4 @@ pub trait ThreadSafeLayoutNode: Clone + Copy + NodeInfo + PartialEq + Sized {
}
}
- #[inline]
- fn selected_style(&self, _context: &SharedStyleContext) -> Arc<ServoComputedValues> {
- // FIXME(bholley): This should move to Element and lose the text node check.
- if self.is_text_node() {
- return self.style_for_text_node();
- }
-
- let data = self.get_style_data().unwrap().borrow();
- data.current_styles().pseudos
- .get(&PseudoElement::Selection)
- .unwrap_or(&data.current_styles().primary)
- .clone()
- }
-
- fn is_ignorable_whitespace(&self, context: &SharedStyleContext) -> bool;
-
- fn restyle_damage(self) -> RestyleDamage;
-
- fn clear_restyle_damage(self);
-
- /// 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 {
- match self.type_id() {
- Some(LayoutNodeType::Element(..)) | Some(LayoutNodeType::Text) => true,
- _ => false
- }
- }
-
- fn can_be_fragmented(&self) -> bool;
-
- fn node_text_content(&self) -> String;
-
- /// If the insertion point is within this node, returns it. Otherwise, returns `None`.
- fn selection(&self) -> Option<Range<ByteIndex>>;
-
- /// If this is an image element, returns its URL. If this is not an image element, fails.
- ///
- /// FIXME(pcwalton): Don't copy URLs.
- fn image_url(&self) -> Option<Url>;
-
- fn canvas_data(&self) -> Option<HTMLCanvasData>;
-
- fn svg_data(&self) -> Option<SVGSVGData>;
-
- /// If this node is an iframe element, returns its pipeline ID. If this node is
- /// not an iframe element, fails.
- fn iframe_pipeline_id(&self) -> PipelineId;
-
- fn get_colspan(&self) -> u32;
-
- fn get_style_data(&self) -> Option<&AtomicRefCell<NodeData>>;
-}
-
-// 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!
-#[allow(unsafe_code)]
-pub trait DangerousThreadSafeLayoutNode: ThreadSafeLayoutNode {
- unsafe fn dangerous_first_child(&self) -> Option<Self>;
- unsafe fn dangerous_next_sibling(&self) -> Option<Self>;
-}
-
-pub trait ThreadSafeLayoutElement: Clone + Copy + Sized + Debug +
- ::selectors::Element<Impl=ServoSelectorImpl> +
- PresentationalHintsSynthetizer {
- type ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode<ConcreteThreadSafeLayoutElement = Self>;
-
- #[inline]
- fn get_attr(&self, namespace: &Namespace, name: &Atom) -> Option<&str>;
-
- #[inline]
- fn get_local_name(&self) -> &Atom;
-
- #[inline]
- fn get_namespace(&self) -> &Namespace;
}