aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/layout/wrapper.rs180
-rw-r--r--components/style/dom.rs10
-rw-r--r--components/style/selector_impl.rs12
-rw-r--r--components/style/selector_matching.rs7
-rw-r--r--ports/geckolib/selector_impl.rs3
-rw-r--r--ports/geckolib/wrapper.rs17
6 files changed, 172 insertions, 57 deletions
diff --git a/components/layout/wrapper.rs b/components/layout/wrapper.rs
index 29ebb919368..928ae1777ac 100644
--- a/components/layout/wrapper.rs
+++ b/components/layout/wrapper.rs
@@ -66,7 +66,7 @@ use std::sync::Arc;
use string_cache::{Atom, Namespace};
use style::computed_values::content::ContentItem;
use style::computed_values::{content, display};
-use style::dom::{TDocument, TElement, TNode, UnsafeNode};
+use style::dom::{PresentationalHintsSynthetizer, TDocument, TElement, TNode, UnsafeNode};
use style::element_state::*;
use style::properties::{ComputedValues, ServoComputedValues};
use style::properties::{PropertyDeclaration, PropertyDeclarationBlock};
@@ -81,7 +81,7 @@ pub type NonOpaqueStyleAndLayoutData = *mut RefCell<PrivateLayoutData>;
/// 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: TNode {
type ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode;
fn to_threadsafe(&self) -> Self::ConcreteThreadSafeLayoutNode;
@@ -401,6 +401,16 @@ pub struct ServoLayoutElement<'le> {
chain: PhantomData<&'le ()>,
}
+impl<'le> PresentationalHintsSynthetizer for ServoLayoutElement<'le> {
+ fn synthesize_presentational_hints_for_legacy_attributes<V>(&self, hints: &mut V)
+ where V: VecLike<DeclarationBlock<Vec<PropertyDeclaration>>>
+ {
+ unsafe {
+ self.element.synthesize_presentational_hints_for_legacy_attributes(hints);
+ }
+ }
+}
+
impl<'le> TElement for ServoLayoutElement<'le> {
type ConcreteNode = ServoLayoutNode<'le>;
type ConcreteDocument = ServoLayoutDocument<'le>;
@@ -419,14 +429,6 @@ impl<'le> TElement for ServoLayoutElement<'le> {
self.element.get_state_for_layout()
}
- fn synthesize_presentational_hints_for_legacy_attributes<V>(&self, hints: &mut V)
- where V: VecLike<DeclarationBlock<Vec<PropertyDeclaration>>>
- {
- unsafe {
- self.element.synthesize_presentational_hints_for_legacy_attributes(hints);
- }
- }
-
#[inline]
fn get_attr(&self, namespace: &Namespace, name: &Atom) -> Option<&str> {
unsafe {
@@ -665,8 +667,10 @@ impl<T> PseudoElementType<T> {
/// 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 + Sized + PartialEq {
- type ConcreteThreadSafeLayoutElement: ThreadSafeLayoutElement<ConcreteThreadSafeLayoutNode = Self>;
+pub trait ThreadSafeLayoutNode: Clone + Copy + Sized + PartialEq {
+ type ConcreteThreadSafeLayoutElement:
+ ThreadSafeLayoutElement<ConcreteThreadSafeLayoutNode = Self>
+ + ::selectors::Element<Impl=ServoSelectorImpl>;
type ChildrenIterator: Iterator<Item = Self> + Sized;
/// Creates a new `ThreadSafeLayoutNode` for the same `LayoutNode`
@@ -680,6 +684,18 @@ pub trait ThreadSafeLayoutNode : Clone + Copy + Sized + PartialEq {
/// Returns `None` if this is a pseudo-element; otherwise, returns `Some`.
fn type_id(&self) -> Option<NodeTypeId>;
+ /// Returns the type ID of this node, without discarding pseudo-elements as
+ /// `type_id` does.
+ fn type_id_without_excluding_pseudo_elements(&self) -> NodeTypeId;
+
+ #[inline]
+ fn is_element_or_elements_pseudo(&self) -> bool {
+ match self.type_id_without_excluding_pseudo_elements() {
+ NodeTypeId::Element(..) => true,
+ _ => false,
+ }
+ }
+
fn debug_id(self) -> usize;
fn flow_debug_id(self) -> usize;
@@ -791,23 +807,20 @@ pub trait ThreadSafeLayoutNode : Clone + Copy + Sized + PartialEq {
}
}
PseudoElementCascadeType::Lazy => {
- panic!("Lazy pseudo-elements can't be used in Servo \
- since accessing the DOM tree during layout \
- could be unsafe.")
- // debug_assert!(self.is_element());
- // if !self.borrow_layout_data()
- // .unwrap().style_data
- // .per_pseudo.contains_key(&style_pseudo) {
- // let mut data = self.mutate_layout_data().unwrap();
- // let new_style =
- // context.stylist
- // .lazily_compute_pseudo_element_style(
- // &self.as_element(),
- // &style_pseudo,
- // data.style_data.style.as_ref().unwrap());
- // data.style_data.per_pseudo
- // .insert(style_pseudo.clone(), new_style.unwrap())
- // }
+ debug_assert!(self.is_element_or_elements_pseudo());
+ if !self.borrow_layout_data()
+ .unwrap().style_data
+ .per_pseudo.contains_key(&style_pseudo) {
+ let mut data = self.mutate_layout_data().unwrap();
+ let new_style =
+ context.stylist
+ .lazily_compute_pseudo_element_style(
+ &self.as_element(),
+ &style_pseudo,
+ data.style_data.style.as_ref().unwrap());
+ data.style_data.per_pseudo
+ .insert(style_pseudo.clone(), new_style.unwrap());
+ }
}
}
@@ -932,12 +945,14 @@ pub trait ThreadSafeLayoutNode : Clone + Copy + Sized + PartialEq {
// 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 {
+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 {
+pub trait ThreadSafeLayoutElement: Clone + Copy + Sized +
+ ::selectors::Element<Impl=ServoSelectorImpl> +
+ PresentationalHintsSynthetizer {
type ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode<ConcreteThreadSafeLayoutElement = Self>;
#[inline]
@@ -1027,6 +1042,11 @@ impl<'ln> ThreadSafeLayoutNode for ServoThreadSafeLayoutNode<'ln> {
Some(self.node.type_id())
}
+ #[inline]
+ fn type_id_without_excluding_pseudo_elements(&self) -> NodeTypeId {
+ self.node.type_id()
+ }
+
fn debug_id(self) -> usize {
self.node.debug_id()
}
@@ -1320,3 +1340,101 @@ impl TextContent {
}
}
}
+
+impl <'le> ::selectors::Element for ServoThreadSafeLayoutElement<'le> {
+ type Impl = ServoSelectorImpl;
+
+ fn parent_element(&self) -> Option<Self> {
+ warn!("ServoThreadSafeLayoutElement::parent_element called");
+ None
+ }
+
+ fn first_child_element(&self) -> Option<Self> {
+ warn!("ServoThreadSafeLayoutElement::first_child_element called");
+ None
+ }
+
+ // Skips non-element nodes
+ fn last_child_element(&self) -> Option<Self> {
+ warn!("ServoThreadSafeLayoutElement::last_child_element called");
+ None
+ }
+
+ // Skips non-element nodes
+ fn prev_sibling_element(&self) -> Option<Self> {
+ warn!("ServoThreadSafeLayoutElement::prev_sibling_element called");
+ None
+ }
+
+ // Skips non-element nodes
+ fn next_sibling_element(&self) -> Option<Self> {
+ warn!("ServoThreadSafeLayoutElement::next_sibling_element called");
+ None
+ }
+
+ fn is_html_element_in_html_document(&self) -> bool {
+ warn!("ServoThreadSafeLayoutElement::is_html_element_in_html_document called");
+ true
+ }
+
+ #[inline]
+ fn get_local_name(&self) -> &Atom {
+ ThreadSafeLayoutElement::get_local_name(self)
+ }
+
+ #[inline]
+ fn get_namespace(&self) -> &Namespace {
+ ThreadSafeLayoutElement::get_namespace(self)
+ }
+
+ fn match_non_ts_pseudo_class(&self, _: NonTSPseudoClass) -> bool {
+ // NB: This could maybe be implemented
+ warn!("ServoThreadSafeLayoutElement::match_non_ts_pseudo_class called");
+ false
+ }
+
+ fn get_id(&self) -> Option<Atom> {
+ warn!("ServoThreadSafeLayoutElement::get_id called");
+ None
+ }
+
+ fn has_class(&self, _name: &Atom) -> bool {
+ warn!("ServoThreadSafeLayoutElement::has_class called");
+ false
+ }
+
+ fn match_attr<F>(&self, attr: &AttrSelector, test: F) -> bool
+ where F: Fn(&str) -> bool {
+ match attr.namespace {
+ NamespaceConstraint::Specific(ref ns) => {
+ self.get_attr(ns, &attr.name).map_or(false, |attr| test(attr))
+ },
+ NamespaceConstraint::Any => {
+ unsafe {
+ self.element.get_attr_vals_for_layout(&attr.name).iter()
+ .any(|attr| test(*attr))
+ }
+ }
+ }
+ }
+
+ fn is_empty(&self) -> bool {
+ warn!("ServoThreadSafeLayoutElement::is_empty called");
+ false
+ }
+
+ fn is_root(&self) -> bool {
+ warn!("ServoThreadSafeLayoutElement::is_root called");
+ false
+ }
+
+ fn each_class<F>(&self, _callback: F)
+ where F: FnMut(&Atom) {
+ warn!("ServoThreadSafeLayoutElement::each_class called");
+ }
+}
+
+impl<'le> PresentationalHintsSynthetizer for ServoThreadSafeLayoutElement<'le> {
+ fn synthesize_presentational_hints_for_legacy_attributes<V>(&self, _hints: &mut V)
+ where V: VecLike<DeclarationBlock<Vec<PropertyDeclaration>>> {}
+}
diff --git a/components/style/dom.rs b/components/style/dom.rs
index fed1597c627..badd4f31065 100644
--- a/components/style/dom.rs
+++ b/components/style/dom.rs
@@ -195,7 +195,12 @@ pub trait TDocument : Sized + Copy + Clone {
fn drain_modified_elements(&self) -> Vec<(Self::ConcreteElement, ElementSnapshot)>;
}
-pub trait TElement : Sized + Copy + Clone + ElementExt {
+pub trait PresentationalHintsSynthetizer {
+ fn synthesize_presentational_hints_for_legacy_attributes<V>(&self, hints: &mut V)
+ where V: VecLike<DeclarationBlock<Vec<PropertyDeclaration>>>;
+}
+
+pub trait TElement : Sized + Copy + Clone + ElementExt + PresentationalHintsSynthetizer {
type ConcreteNode: TNode<ConcreteElement = Self, ConcreteDocument = Self::ConcreteDocument>;
type ConcreteDocument: TDocument<ConcreteNode = Self::ConcreteNode, ConcreteElement = Self>;
@@ -205,9 +210,6 @@ pub trait TElement : Sized + Copy + Clone + ElementExt {
fn get_state(&self) -> ElementState;
- fn synthesize_presentational_hints_for_legacy_attributes<V>(&self, &mut V)
- where V: VecLike<DeclarationBlock<Vec<PropertyDeclaration>>>;
-
fn get_attr<'a>(&'a self, namespace: &Namespace, attr: &Atom) -> Option<&'a str>;
fn get_attrs<'a>(&'a self, attr: &Atom) -> Vec<&'a str>;
diff --git a/components/style/selector_impl.rs b/components/style/selector_impl.rs
index e0c1b2c3f98..b424affb101 100644
--- a/components/style/selector_impl.rs
+++ b/components/style/selector_impl.rs
@@ -104,19 +104,11 @@ pub enum PseudoElement {
impl PseudoElement {
#[inline]
pub fn cascade_type(&self) -> PseudoElementCascadeType {
- // TODO: Make PseudoElementCascadeType::Lazy work for Servo.
- //
- // This can't be done right now since it would require
- // ServoThreadSafeLayoutElement to implement ::selectors::Element,
- // and it might not be thread-safe.
- //
- // After that, we'd probably want ::selection and
- // ::-servo-details-summary to be lazy.
match *self {
PseudoElement::Before |
PseudoElement::After |
- PseudoElement::Selection |
- PseudoElement::DetailsSummary => PseudoElementCascadeType::Eager,
+ PseudoElement::Selection => PseudoElementCascadeType::Eager,
+ PseudoElement::DetailsSummary => PseudoElementCascadeType::Lazy,
PseudoElement::DetailsContent => PseudoElementCascadeType::Precomputed,
}
}
diff --git a/components/style/selector_matching.rs b/components/style/selector_matching.rs
index e59955f3a0e..4faf9aa0eb4 100644
--- a/components/style/selector_matching.rs
+++ b/components/style/selector_matching.rs
@@ -5,7 +5,7 @@
// For lazy_static
#![allow(unsafe_code)]
-use dom::TElement;
+use dom::PresentationalHintsSynthetizer;
use element_state::*;
use error_reporting::{ParseErrorReporter, StdoutErrorReporter};
use media_queries::{Device, MediaType};
@@ -281,7 +281,8 @@ impl<Impl: SelectorImplExt> Stylist<Impl> {
pseudo: &Impl::PseudoElement,
parent: &Arc<Impl::ComputedValues>)
-> Option<Arc<Impl::ComputedValues>>
- where E: Element<Impl=Impl> + TElement {
+ where E: Element<Impl=Impl> +
+ PresentationalHintsSynthetizer {
debug_assert!(Impl::pseudo_element_cascade_type(pseudo).is_lazy());
if self.pseudos_map.get(pseudo).is_none() {
return None;
@@ -358,7 +359,7 @@ impl<Impl: SelectorImplExt> Stylist<Impl> {
pseudo_element: Option<&Impl::PseudoElement>,
applicable_declarations: &mut V)
-> bool
- where E: Element<Impl=Impl> + TElement,
+ where E: Element<Impl=Impl> + PresentationalHintsSynthetizer,
V: VecLike<DeclarationBlock> {
assert!(!self.is_device_dirty);
assert!(style_attribute.is_none() || pseudo_element.is_none(),
diff --git a/ports/geckolib/selector_impl.rs b/ports/geckolib/selector_impl.rs
index bedac08a025..ddc26f6c541 100644
--- a/ports/geckolib/selector_impl.rs
+++ b/ports/geckolib/selector_impl.rs
@@ -23,7 +23,6 @@ pub enum PseudoElement {
// TODO: Probably a few more are missing here
AnonBox(AnonBoxPseudoElement),
-
}
// https://mxr.mozilla.org/mozilla-central/source/layout/style/nsCSSAnonBoxList.h
@@ -262,8 +261,8 @@ impl SelectorImplExt for GeckoSelectorImpl {
#[inline]
fn each_pseudo_element<F>(mut fun: F)
where F: FnMut(PseudoElement) {
- use self::PseudoElement::*;
use self::AnonBoxPseudoElement::*;
+ use self::PseudoElement::*;
fun(Before);
fun(After);
diff --git a/ports/geckolib/wrapper.rs b/ports/geckolib/wrapper.rs
index edf007a0016..f27cf770bf0 100644
--- a/ports/geckolib/wrapper.rs
+++ b/ports/geckolib/wrapper.rs
@@ -32,7 +32,8 @@ use std::slice;
use std::str::from_utf8_unchecked;
use std::sync::Arc;
use string_cache::{Atom, Namespace};
-use style::dom::{OpaqueNode, TDocument, TElement, TNode, TRestyleDamage, UnsafeNode};
+use style::dom::{OpaqueNode, PresentationalHintsSynthetizer};
+use style::dom::{TDocument, TElement, TNode, TRestyleDamage, UnsafeNode};
use style::element_state::ElementState;
#[allow(unused_imports)] // Used in commented-out code.
use style::error_reporting::StdoutErrorReporter;
@@ -339,12 +340,6 @@ impl<'le> TElement for GeckoElement<'le> {
}
}
- fn synthesize_presentational_hints_for_legacy_attributes<V>(&self, _hints: &mut V)
- where V: VecLike<DeclarationBlock<Vec<PropertyDeclaration>>>
- {
- // FIXME(bholley) - Need to implement this.
- }
-
#[inline]
fn get_attr<'a>(&'a self, namespace: &Namespace, name: &Atom) -> Option<&'a str> {
unsafe {
@@ -360,6 +355,14 @@ impl<'le> TElement for GeckoElement<'le> {
}
}
+impl<'le> PresentationalHintsSynthetizer for GeckoElement<'le> {
+ fn synthesize_presentational_hints_for_legacy_attributes<V>(&self, _hints: &mut V)
+ where V: VecLike<DeclarationBlock<Vec<PropertyDeclaration>>>
+ {
+ // FIXME(bholley) - Need to implement this.
+ }
+}
+
impl<'le> ::selectors::Element for GeckoElement<'le> {
type Impl = GeckoSelectorImpl;