aboutsummaryrefslogtreecommitdiffstats
path: root/components
diff options
context:
space:
mode:
Diffstat (limited to 'components')
-rw-r--r--components/layout/construct.rs24
-rw-r--r--components/layout/fragment.rs4
-rw-r--r--components/layout/query.rs32
-rw-r--r--components/layout/traversal.rs2
-rw-r--r--components/layout/wrapper.rs58
-rw-r--r--components/script/layout_wrapper.rs141
-rw-r--r--components/script_layout_interface/wrapper_traits.rs246
7 files changed, 260 insertions, 247 deletions
diff --git a/components/layout/construct.rs b/components/layout/construct.rs
index 7c7eff8bc0c..03d7e767f69 100644
--- a/components/layout/construct.rs
+++ b/components/layout/construct.rs
@@ -62,7 +62,7 @@ use text::TextRunScanner;
use traversal::PostorderNodeMutTraversal;
use url::Url;
use util::opts;
-use wrapper::{TextContent, ThreadSafeLayoutNodeHelpers};
+use wrapper::{LayoutNodeLayoutData, TextContent, ThreadSafeLayoutNodeHelpers};
/// The results of flow construction for a DOM node.
#[derive(Clone)]
@@ -221,7 +221,7 @@ impl InlineFragmentsAccumulator {
address: node.opaque(),
pseudo: node.get_pseudo_element_type().strip(),
style: node.style(style_context),
- selected_style: node.selected_style(style_context),
+ selected_style: node.selected_style(),
flags: InlineFragmentNodeFlags::empty(),
}),
bidi_control_chars: None,
@@ -514,11 +514,10 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
box UnscannedTextFragmentInfo::new(" ".to_owned(), None));
properties::modify_style_for_replaced_content(&mut whitespace_style);
properties::modify_style_for_text(&mut whitespace_style);
- let style_context = self.style_context();
let fragment = Fragment::from_opaque_node_and_style(whitespace_node,
whitespace_pseudo,
whitespace_style,
- node.selected_style(style_context),
+ node.selected_style(),
whitespace_damage,
fragment_info);
inline_fragment_accumulator.fragments.fragments.push_back(fragment);
@@ -650,7 +649,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
_ => properties::modify_style_for_text(&mut style)
}
- let selected_style = node.selected_style(self.style_context());
+ let selected_style = node.selected_style();
match text_content {
TextContent::Text(string) => {
@@ -811,7 +810,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
Fragment::from_opaque_node_and_style(whitespace_node,
whitespace_pseudo,
whitespace_style,
- node.selected_style(self.style_context()),
+ node.selected_style(),
whitespace_damage,
fragment_info);
fragment_accumulator.fragments.fragments.push_back(fragment)
@@ -834,7 +833,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
let fragment = Fragment::from_opaque_node_and_style(node.opaque(),
node.get_pseudo_element_type().strip(),
modified_style,
- node.selected_style(self.style_context()),
+ node.selected_style(),
node.restyle_damage(),
info);
fragment_accumulator.fragments.fragments.push_back(fragment)
@@ -921,7 +920,6 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
_ => unreachable!()
};
- let style_context = self.style_context();
let mut modified_style = node.style(self.style_context());
properties::modify_style_for_outer_inline_block_fragment(&mut modified_style);
let fragment_info = SpecificFragmentInfo::InlineBlock(InlineBlockFragmentInfo::new(
@@ -929,7 +927,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
let fragment = Fragment::from_opaque_node_and_style(node.opaque(),
node.get_pseudo_element_type().strip(),
modified_style,
- node.selected_style(style_context),
+ node.selected_style(),
node.restyle_damage(),
fragment_info);
@@ -964,7 +962,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
let fragment = Fragment::from_opaque_node_and_style(node.opaque(),
PseudoElementType::Normal,
style,
- node.selected_style(style_context),
+ node.selected_style(),
node.restyle_damage(),
fragment_info);
@@ -1076,7 +1074,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
Fragment::from_opaque_node_and_style(node.opaque(),
PseudoElementType::Normal,
wrapper_style,
- node.selected_style(self.style_context()),
+ node.selected_style(),
node.restyle_damage(),
SpecificFragmentInfo::TableWrapper);
let wrapper_float_kind = FloatKind::from_property(float_value);
@@ -1661,7 +1659,7 @@ trait ObjectElement {
impl<N> ObjectElement for N where N: ThreadSafeLayoutNode {
fn has_object_data(&self) -> bool {
- let elem = self.as_element();
+ let elem = self.as_element().unwrap();
let type_and_data = (elem.get_attr(&ns!(), &atom!("type")), elem.get_attr(&ns!(), &atom!("data")));
match type_and_data {
(None, Some(uri)) => is_image_data(uri),
@@ -1670,7 +1668,7 @@ impl<N> ObjectElement for N where N: ThreadSafeLayoutNode {
}
fn object_data(&self) -> Option<Url> {
- let elem = self.as_element();
+ let elem = self.as_element().unwrap();
let type_and_data = (elem.get_attr(&ns!(), &atom!("type")), elem.get_attr(&ns!(), &atom!("data")));
match type_and_data {
(None, Some(uri)) if is_image_data(uri) => Url::parse(uri).ok(),
diff --git a/components/layout/fragment.rs b/components/layout/fragment.rs
index e79360d08f4..ab9563c90bc 100644
--- a/components/layout/fragment.rs
+++ b/components/layout/fragment.rs
@@ -885,7 +885,7 @@ pub struct TableColumnFragmentInfo {
impl TableColumnFragmentInfo {
/// Create the information specific to an table column fragment.
pub fn new<N: ThreadSafeLayoutNode>(node: &N) -> TableColumnFragmentInfo {
- let element = node.as_element();
+ let element = node.as_element().unwrap();
let span = element.get_attr(&ns!(), &atom!("span"))
.and_then(|string| string.parse().ok())
.unwrap_or(0);
@@ -908,7 +908,7 @@ impl Fragment {
Fragment {
node: node.opaque(),
style: style,
- selected_style: node.selected_style(style_context),
+ selected_style: node.selected_style(),
restyle_damage: restyle_damage,
border_box: LogicalRect::zero(writing_mode),
border_padding: LogicalMargin::zero(writing_mode),
diff --git a/components/layout/query.rs b/components/layout/query.rs
index b491f08632d..8b394ac8fec 100644
--- a/components/layout/query.rs
+++ b/components/layout/query.rs
@@ -19,7 +19,7 @@ use script_layout_interface::rpc::{HitTestResponse, LayoutRPC};
use script_layout_interface::rpc::{MarginStyleResponse, NodeGeometryResponse};
use script_layout_interface::rpc::{NodeOverflowResponse, OffsetParentResponse};
use script_layout_interface::rpc::ResolvedStyleResponse;
-use script_layout_interface::wrapper_traits::{LayoutNode, ThreadSafeLayoutNode};
+use script_layout_interface::wrapper_traits::{LayoutNode, ThreadSafeLayoutElement, ThreadSafeLayoutNode};
use script_traits::LayoutMsg as ConstellationMsg;
use script_traits::UntrustedNodeAddress;
use sequential;
@@ -36,7 +36,7 @@ use style::selector_impl::PseudoElement;
use style::selector_matching::Stylist;
use style::values::LocalToCss;
use style_traits::cursor::Cursor;
-use wrapper::{LayoutNodeLayoutData, ThreadSafeLayoutNodeHelpers};
+use wrapper::{LayoutNodeHelpers, LayoutNodeLayoutData};
/// Mutable data belonging to the LayoutThread.
///
@@ -640,27 +640,27 @@ pub fn process_resolved_style_request<'a, N, C>(requested_node: N,
ensure_node_data_initialized(&requested_node);
ensure_element_styled(requested_node.as_element().unwrap(), style_context);
- let layout_node = requested_node.to_threadsafe();
- let layout_node = match *pseudo {
- Some(PseudoElement::Before) => layout_node.get_before_pseudo(),
- Some(PseudoElement::After) => layout_node.get_after_pseudo(),
+ let layout_el = requested_node.to_threadsafe().as_element().unwrap();
+ let layout_el = match *pseudo {
+ Some(PseudoElement::Before) => layout_el.get_before_pseudo(),
+ Some(PseudoElement::After) => layout_el.get_after_pseudo(),
Some(PseudoElement::DetailsSummary) |
Some(PseudoElement::DetailsContent) |
Some(PseudoElement::Selection) => None,
- _ => Some(layout_node)
+ _ => Some(layout_el)
};
- let layout_node = match layout_node {
+ let layout_el = match layout_el {
None => {
// The pseudo doesn't exist, return nothing. Chrome seems to query
// the element itself in this case, Firefox uses the resolved value.
// https://www.w3.org/Bugs/Public/show_bug.cgi?id=29006
return None;
}
- Some(layout_node) => layout_node
+ Some(layout_el) => layout_el
};
- let style = &*layout_node.resolved_style();
+ let style = &*layout_el.resolved_style();
let positioned = match style.get_box().position {
position::computed_value::T::relative |
@@ -678,11 +678,11 @@ pub fn process_resolved_style_request<'a, N, C>(requested_node: N,
let applies = true;
fn used_value_for_position_property<N: LayoutNode>(
- layout_node: N::ConcreteThreadSafeLayoutNode,
+ layout_el: <N::ConcreteThreadSafeLayoutNode as ThreadSafeLayoutNode>::ConcreteThreadSafeLayoutElement,
layout_root: &mut Flow,
requested_node: N,
property: &Atom) -> Option<String> {
- let maybe_data = layout_node.borrow_layout_data();
+ let maybe_data = layout_el.borrow_layout_data();
let position = maybe_data.map_or(Point2D::zero(), |data| {
match (*data).flow_construction_result {
ConstructionResult::Flow(ref flow_ref, _) =>
@@ -744,12 +744,12 @@ pub fn process_resolved_style_request<'a, N, C>(requested_node: N,
atom!("left")
if applies && positioned && style.get_box().display !=
display::computed_value::T::none => {
- used_value_for_position_property(layout_node, layout_root, requested_node, property)
+ used_value_for_position_property(layout_el, layout_root, requested_node, property)
}
atom!("width") | atom!("height")
if applies && style.get_box().display !=
display::computed_value::T::none => {
- used_value_for_position_property(layout_node, layout_root, requested_node, property)
+ used_value_for_position_property(layout_el, layout_root, requested_node, property)
}
// FIXME: implement used value computation for line-height
ref property => {
@@ -781,7 +781,7 @@ pub fn process_offset_parent_query<N: LayoutNode>(requested_node: N, layout_root
pub fn process_node_overflow_request<N: LayoutNode>(requested_node: N) -> NodeOverflowResponse {
let layout_node = requested_node.to_threadsafe();
- let style = &*layout_node.resolved_style();
+ let style = &*layout_node.as_element().unwrap().resolved_style();
let style_box = style.get_box();
NodeOverflowResponse(Some((Point2D::new(style_box.overflow_x, style_box.overflow_y.0))))
@@ -790,7 +790,7 @@ pub fn process_node_overflow_request<N: LayoutNode>(requested_node: N) -> NodeOv
pub fn process_margin_style_query<N: LayoutNode>(requested_node: N)
-> MarginStyleResponse {
let layout_node = requested_node.to_threadsafe();
- let style = &*layout_node.resolved_style();
+ let style = &*layout_node.as_element().unwrap().resolved_style();
let margin = style.get_margin();
MarginStyleResponse {
diff --git a/components/layout/traversal.rs b/components/layout/traversal.rs
index 2ab1e21cebe..2f6c49b8ea8 100644
--- a/components/layout/traversal.rs
+++ b/components/layout/traversal.rs
@@ -23,7 +23,7 @@ use style::traversal::{recalc_style_at, remove_from_bloom_filter};
use style::traversal::RestyleResult;
use style::traversal::take_thread_local_bloom_filter;
use util::opts;
-use wrapper::{LayoutNodeLayoutData, ThreadSafeLayoutNodeHelpers};
+use wrapper::{LayoutNodeHelpers, LayoutNodeLayoutData};
pub struct RecalcStyleAndConstructFlows<'lc> {
context: LayoutContext<'lc>,
diff --git a/components/layout/wrapper.rs b/components/layout/wrapper.rs
index 99f9a4cc54d..c37499a12af 100644
--- a/components/layout/wrapper.rs
+++ b/components/layout/wrapper.rs
@@ -33,7 +33,8 @@
use core::nonzero::NonZero;
use data::{LayoutDataFlags, PersistentLayoutData};
use script_layout_interface::{OpaqueStyleAndLayoutData, PartialPersistentLayoutData};
-use script_layout_interface::wrapper_traits::{LayoutNode, ThreadSafeLayoutNode};
+use script_layout_interface::wrapper_traits::{GetLayoutData, LayoutNode};
+use script_layout_interface::wrapper_traits::{ThreadSafeLayoutElement, ThreadSafeLayoutNode};
use style::atomic_refcell::{AtomicRef, AtomicRefCell, AtomicRefMut};
use style::computed_values::content::{self, ContentItem};
@@ -44,11 +45,10 @@ pub trait LayoutNodeLayoutData {
/// than only the style::data::NodeData.
fn borrow_layout_data(&self) -> Option<AtomicRef<PersistentLayoutData>>;
fn mutate_layout_data(&self) -> Option<AtomicRefMut<PersistentLayoutData>>;
- fn initialize_data(self);
fn flow_debug_id(self) -> usize;
}
-impl<T: LayoutNode> LayoutNodeLayoutData for T {
+impl<T: GetLayoutData> LayoutNodeLayoutData for T {
fn borrow_layout_data(&self) -> Option<AtomicRef<PersistentLayoutData>> {
unsafe {
self.get_style_and_layout_data().map(|opaque| {
@@ -67,6 +67,16 @@ impl<T: LayoutNode> LayoutNodeLayoutData for T {
}
}
+ fn flow_debug_id(self) -> usize {
+ self.borrow_layout_data().map_or(0, |d| d.flow_construction_result.debug_id())
+ }
+}
+
+pub trait LayoutNodeHelpers {
+ fn initialize_data(self);
+}
+
+impl<T: LayoutNode> LayoutNodeHelpers for T {
fn initialize_data(self) {
if self.borrow_layout_data().is_none() {
let ptr: NonOpaqueStyleAndLayoutData =
@@ -77,27 +87,9 @@ impl<T: LayoutNode> LayoutNodeLayoutData for T {
self.init_style_and_layout_data(opaque);
}
}
-
- fn flow_debug_id(self) -> usize {
- self.borrow_layout_data().map_or(0, |d| d.flow_construction_result.debug_id())
- }
}
pub trait ThreadSafeLayoutNodeHelpers {
- fn flow_debug_id(self) -> usize;
-
- /// 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<AtomicRef<PersistentLayoutData>>;
-
- /// 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<AtomicRefMut<PersistentLayoutData>>;
-
/// Returns the layout data flags for this node.
fn flags(self) -> LayoutDataFlags;
@@ -115,28 +107,6 @@ pub trait ThreadSafeLayoutNodeHelpers {
}
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())
- }
-
- fn borrow_layout_data(&self) -> Option<AtomicRef<PersistentLayoutData>> {
- unsafe {
- self.get_style_and_layout_data().map(|opaque| {
- let container = *opaque.ptr as NonOpaqueStyleAndLayoutData;
- (*container).borrow()
- })
- }
- }
-
- fn mutate_layout_data(&self) -> Option<AtomicRefMut<PersistentLayoutData>> {
- unsafe {
- self.get_style_and_layout_data().map(|opaque| {
- let container = *opaque.ptr as NonOpaqueStyleAndLayoutData;
- (*container).borrow_mut()
- })
- }
- }
-
fn flags(self) -> LayoutDataFlags {
self.borrow_layout_data().as_ref().unwrap().flags
}
@@ -151,7 +121,7 @@ impl<T: ThreadSafeLayoutNode> ThreadSafeLayoutNodeHelpers for T {
fn text_content(&self) -> TextContent {
if self.get_pseudo_element_type().is_replaced_content() {
- let style = self.resolved_style();
+ let style = self.as_element().unwrap().resolved_style();
return match style.as_ref().get_counters().content {
content::T::Content(ref value) if !value.is_empty() => {
diff --git a/components/script/layout_wrapper.rs b/components/script/layout_wrapper.rs
index 75bdd55aedc..73d06eec76a 100644
--- a/components/script/layout_wrapper.rs
+++ b/components/script/layout_wrapper.rs
@@ -46,8 +46,8 @@ use range::Range;
use script_layout_interface::{HTMLCanvasData, LayoutNodeType, SVGSVGData, TrustedNodeAddress};
use script_layout_interface::{OpaqueStyleAndLayoutData, PartialPersistentLayoutData};
use script_layout_interface::restyle_damage::RestyleDamage;
-use script_layout_interface::wrapper_traits::{DangerousThreadSafeLayoutNode, LayoutNode, PseudoElementType};
-use script_layout_interface::wrapper_traits::{ThreadSafeLayoutElement, ThreadSafeLayoutNode};
+use script_layout_interface::wrapper_traits::{DangerousThreadSafeLayoutNode, GetLayoutData, LayoutNode};
+use script_layout_interface::wrapper_traits::{PseudoElementType, ThreadSafeLayoutElement, ThreadSafeLayoutNode};
use selectors::matching::ElementFlags;
use selectors::parser::{AttrSelector, NamespaceConstraint};
use std::fmt;
@@ -306,6 +306,8 @@ impl<'ln> LayoutNode for ServoLayoutNode<'ln> {
self.node.set_flag(HAS_DIRTY_DESCENDANTS, false);
}
+ // NB: This duplicates the get_style_data on ThreadSafeLayoutElement, but
+ // will go away soon.
fn get_style_data(&self) -> Option<&AtomicRefCell<NodeData>> {
unsafe {
self.get_jsmanaged().get_style_and_layout_data().map(|d| {
@@ -321,7 +323,9 @@ impl<'ln> LayoutNode for ServoLayoutNode<'ln> {
self.get_jsmanaged().init_style_and_layout_data(data);
}
}
+}
+impl<'ln> GetLayoutData for ServoLayoutNode<'ln> {
fn get_style_and_layout_data(&self) -> Option<OpaqueStyleAndLayoutData> {
unsafe {
self.get_jsmanaged().get_style_and_layout_data()
@@ -329,6 +333,24 @@ impl<'ln> LayoutNode for ServoLayoutNode<'ln> {
}
}
+impl<'le> GetLayoutData for ServoLayoutElement<'le> {
+ fn get_style_and_layout_data(&self) -> Option<OpaqueStyleAndLayoutData> {
+ self.as_node().get_style_and_layout_data()
+ }
+}
+
+impl<'ln> GetLayoutData for ServoThreadSafeLayoutNode<'ln> {
+ fn get_style_and_layout_data(&self) -> Option<OpaqueStyleAndLayoutData> {
+ self.node.get_style_and_layout_data()
+ }
+}
+
+impl<'le> GetLayoutData for ServoThreadSafeLayoutElement<'le> {
+ fn get_style_and_layout_data(&self) -> Option<OpaqueStyleAndLayoutData> {
+ self.element.as_node().get_style_and_layout_data()
+ }
+}
+
impl<'ln> ServoLayoutNode<'ln> {
pub fn is_dirty(&self) -> bool {
unsafe { self.node.get_flag(IS_DIRTY) }
@@ -710,8 +732,8 @@ pub struct ServoThreadSafeLayoutNode<'ln> {
/// The wrapped node.
node: ServoLayoutNode<'ln>,
- /// The pseudo-element type, with (optionally),
- /// an specified display value to override the stylesheet.
+ /// The pseudo-element type, with (optionally)
+ /// a specified display value to override the stylesheet.
pseudo: PseudoElementType<Option<display::T>>,
}
@@ -757,21 +779,19 @@ impl<'ln> ServoThreadSafeLayoutNode<'ln> {
}
}
+// NB: The implementation here is a bit tricky because elements implementing
+// pseudos are supposed to return false for is_element().
impl<'ln> NodeInfo for ServoThreadSafeLayoutNode<'ln> {
fn is_element(&self) -> bool {
self.pseudo == PseudoElementType::Normal && self.node.is_element()
}
fn is_text_node(&self) -> bool {
- // It's unlikely that text nodes will ever be used to implement a
- // pseudo-element, but the type system doesn't really enforce that,
- // so we check to be safe.
- self.pseudo == PseudoElementType::Normal && self.node.is_text_node()
+ self.node.is_text_node()
}
fn needs_layout(&self) -> bool {
- self.pseudo != PseudoElementType::Normal ||
- self.node.is_element() || self.node.is_text_node()
+ self.node.is_text_node() || self.node.is_element()
}
}
@@ -779,24 +799,16 @@ impl<'ln> ThreadSafeLayoutNode for ServoThreadSafeLayoutNode<'ln> {
type ConcreteThreadSafeLayoutElement = ServoThreadSafeLayoutElement<'ln>;
type ChildrenIterator = ThreadSafeLayoutNodeChildrenIterator<Self>;
- fn with_pseudo(&self,
- pseudo: PseudoElementType<Option<display::T>>) -> ServoThreadSafeLayoutNode<'ln> {
- ServoThreadSafeLayoutNode {
- node: self.node.clone(),
- pseudo: pseudo,
- }
- }
-
fn opaque(&self) -> OpaqueNode {
unsafe { self.get_jsmanaged().opaque() }
}
fn type_id(&self) -> Option<LayoutNodeType> {
- if self.pseudo != PseudoElementType::Normal {
- return None
+ if self.pseudo == PseudoElementType::Normal {
+ Some(self.node.type_id())
+ } else {
+ None
}
-
- Some(self.node.type_id())
}
#[inline]
@@ -827,22 +839,11 @@ impl<'ln> ThreadSafeLayoutNode for ServoThreadSafeLayoutNode<'ln> {
LayoutIterator(ThreadSafeLayoutNodeChildrenIterator::new(*self))
}
- fn as_element(&self) -> ServoThreadSafeLayoutElement<'ln> {
- unsafe {
- let element = match self.get_jsmanaged().downcast() {
- Some(e) => e.unsafe_get(),
- None => panic!("not an element")
- };
- // FIXME(pcwalton): Workaround until Rust gets multiple lifetime parameters on
- // implementations.
- ServoThreadSafeLayoutElement {
- element: &*element,
- }
- }
- }
-
- fn get_pseudo_element_type(&self) -> PseudoElementType<Option<display::T>> {
- self.pseudo
+ fn as_element(&self) -> Option<ServoThreadSafeLayoutElement<'ln>> {
+ self.node.as_element().map(|el| ServoThreadSafeLayoutElement {
+ element: el,
+ pseudo: self.pseudo,
+ })
}
fn get_style_and_layout_data(&self) -> Option<OpaqueStyleAndLayoutData> {
@@ -932,10 +933,6 @@ impl<'ln> ThreadSafeLayoutNode for ServoThreadSafeLayoutNode<'ln> {
self.get_jsmanaged().downcast::<Element>().unwrap().get_colspan()
}
}
-
- fn get_style_data(&self) -> Option<&AtomicRefCell<NodeData>> {
- self.node.get_style_data()
- }
}
pub struct ThreadSafeLayoutNodeChildrenIterator<ConcreteNode: ThreadSafeLayoutNode> {
@@ -968,6 +965,7 @@ impl<ConcreteNode> Iterator for ThreadSafeLayoutNodeChildrenIterator<ConcreteNod
where ConcreteNode: DangerousThreadSafeLayoutNode {
type Item = ConcreteNode;
fn next(&mut self) -> Option<ConcreteNode> {
+ use ::selectors::Element;
match self.parent_node.get_pseudo_element_type() {
PseudoElementType::Before(_) | PseudoElementType::After(_) => None,
@@ -976,8 +974,8 @@ impl<ConcreteNode> Iterator for ThreadSafeLayoutNodeChildrenIterator<ConcreteNod
loop {
let next_node = if let Some(ref node) = current_node {
if node.is_element() &&
- node.as_element().get_local_name() == &atom!("summary") &&
- node.as_element().get_namespace() == &ns!(html) {
+ node.as_element().unwrap().get_local_name() == &atom!("summary") &&
+ node.as_element().unwrap().get_namespace() == &ns!(html) {
self.current_node = None;
return Some(node.clone());
}
@@ -994,8 +992,8 @@ impl<ConcreteNode> Iterator for ThreadSafeLayoutNodeChildrenIterator<ConcreteNod
let node = self.current_node.clone();
let node = node.and_then(|node| {
if node.is_element() &&
- node.as_element().get_local_name() == &atom!("summary") &&
- node.as_element().get_namespace() == &ns!(html) {
+ node.as_element().unwrap().get_local_name() == &atom!("summary") &&
+ node.as_element().unwrap().get_namespace() == &ns!(html) {
unsafe { node.dangerous_next_sibling() }
} else {
Some(node)
@@ -1042,26 +1040,51 @@ impl<ConcreteNode> Iterator for ThreadSafeLayoutNodeChildrenIterator<ConcreteNod
/// ever access safe properties and cannot race on elements.
#[derive(Copy, Clone, Debug)]
pub struct ServoThreadSafeLayoutElement<'le> {
- element: &'le Element,
+ element: ServoLayoutElement<'le>,
+
+ /// The pseudo-element type, with (optionally)
+ /// a specified display value to override the stylesheet.
+ pseudo: PseudoElementType<Option<display::T>>,
}
impl<'le> ThreadSafeLayoutElement for ServoThreadSafeLayoutElement<'le> {
type ConcreteThreadSafeLayoutNode = ServoThreadSafeLayoutNode<'le>;
- fn get_attr<'a>(&'a self, namespace: &Namespace, name: &Atom) -> Option<&'a str> {
- unsafe {
- self.element.get_attr_val_for_layout(namespace, name)
+ fn as_node(&self) -> ServoThreadSafeLayoutNode<'le> {
+ ServoThreadSafeLayoutNode {
+ node: self.element.as_node(),
+ pseudo: self.pseudo.clone(),
}
}
- #[inline]
- fn get_local_name(&self) -> &Atom {
- self.element.local_name()
+ fn get_pseudo_element_type(&self) -> PseudoElementType<Option<display::T>> {
+ self.pseudo
}
- #[inline]
- fn get_namespace(&self) -> &Namespace {
- self.element.namespace()
+ fn with_pseudo(&self,
+ pseudo: PseudoElementType<Option<display::T>>) -> Self {
+ ServoThreadSafeLayoutElement {
+ element: self.element.clone(),
+ pseudo: pseudo,
+ }
+ }
+
+ fn type_id(&self) -> Option<LayoutNodeType> {
+ self.as_node().type_id()
+ }
+
+ fn get_attr<'a>(&'a self, namespace: &Namespace, name: &Atom) -> Option<&'a str> {
+ self.element.get_attr(namespace, name)
+ }
+
+ fn get_style_data(&self) -> Option<&AtomicRefCell<NodeData>> {
+ unsafe {
+ self.element.as_node().get_style_and_layout_data().map(|d| {
+ let ppld: &AtomicRefCell<PartialPersistentLayoutData> = &**d.ptr;
+ let psd: &AtomicRefCell<NodeData> = transmute(ppld);
+ psd
+ })
+ }
}
}
@@ -1088,7 +1111,7 @@ impl<'le> ::selectors::MatchAttrGeneric for ServoThreadSafeLayoutElement<'le> {
},
NamespaceConstraint::Any => {
unsafe {
- self.element.get_attr_vals_for_layout(&attr.name).iter()
+ (*self.element.element.unsafe_get()).get_attr_vals_for_layout(&attr.name).iter()
.any(|attr| test(*attr))
}
}
@@ -1131,12 +1154,12 @@ impl<'le> ::selectors::Element for ServoThreadSafeLayoutElement<'le> {
#[inline]
fn get_local_name(&self) -> &Atom {
- ThreadSafeLayoutElement::get_local_name(self)
+ self.element.get_local_name()
}
#[inline]
fn get_namespace(&self) -> &Namespace {
- ThreadSafeLayoutElement::get_namespace(self)
+ self.element.get_namespace()
}
fn match_non_ts_pseudo_class(&self, _: NonTSPseudoClass) -> bool {
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;
}