Refactor style to be completely backend-independent

This commit refactors the style crate to be completely independent of
the actual implementation and pseudo-elements supported.

This also adds a gecko backend which introduces parsing for the
anonymous box pseudo-elements[1], although there's still no way of
querying them.

https://mxr.mozilla.org/mozilla-central/source/layout/style/nsCSSAnonBoxList.h
This commit is contained in:
Emilio Cobos Álvarez 2016-02-08 02:53:22 +01:00
parent a164176876
commit dd503dfacb
41 changed files with 767 additions and 310 deletions

View file

@ -64,7 +64,7 @@ heapsize_plugin = "0.1.2"
libc = "0.2"
log = "0.3"
rustc-serialize = "0.3"
selectors = {version = "0.4.2", features = ["heap_size"]}
selectors = {version = "0.5", features = ["heap_size"]}
serde = "0.6"
serde_json = "0.5"
serde_macros = "0.6"

View file

@ -25,8 +25,10 @@ use std::hash::BuildHasherDefault;
use std::rc::Rc;
use std::sync::mpsc::Sender;
use std::sync::{Arc, Mutex};
use style::context::{LocalStyleContext, SharedStyleContext, StyleContext};
use style::context::{LocalStyleContext, StyleContext};
use style::matching::{ApplicableDeclarationsCache, StyleSharingCandidateCache};
use style::selector_impl::ServoSelectorImpl;
use style::servo::SharedStyleContext;
use url::Url;
use util::opts;
@ -104,7 +106,7 @@ pub struct LayoutContext<'a> {
cached_local_layout_context: Rc<LocalLayoutContext>,
}
impl<'a> StyleContext<'a> for LayoutContext<'a> {
impl<'a> StyleContext<'a, ServoSelectorImpl> for LayoutContext<'a> {
fn shared_context(&self) -> &'a SharedStyleContext {
&self.shared.style_context
}

View file

@ -4,7 +4,7 @@
use construct::ConstructionResult;
use incremental::RestyleDamage;
use style::data::PrivateStyleData;
use style::servo::PrivateStyleData;
/// Data that layout associates with a node.
pub struct PrivateLayoutData {

View file

@ -62,13 +62,15 @@ use std::sync::mpsc::{channel, Sender, Receiver};
use std::sync::{Arc, Mutex, MutexGuard, RwLock};
use style::animation::Animation;
use style::computed_values::{filter, mix_blend_mode};
use style::context::{SharedStyleContext, StylistWrapper, ReflowGoal};
use style::context::{ReflowGoal, StylistWrapper};
use style::dom::{TDocument, TElement, TNode};
use style::error_reporting::ParseErrorReporter;
use style::media_queries::{Device, MediaType};
use style::parallel::WorkQueueData;
use style::selector_matching::{Stylist, USER_OR_USER_AGENT_STYLESHEETS};
use style::stylesheets::{CSSRuleIteratorExt, Stylesheet};
use style::selector_impl::ServoSelectorImpl;
use style::selector_matching::USER_OR_USER_AGENT_STYLESHEETS;
use style::servo::{SharedStyleContext, Stylesheet, Stylist};
use style::stylesheets::CSSRuleIteratorExt;
use traversal::RecalcStyleAndConstructFlows;
use url::Url;
use util::geometry::MAX_RECT;
@ -477,7 +479,7 @@ impl LayoutThread {
style_context: SharedStyleContext {
viewport_size: self.viewport_size.clone(),
screen_size_changed: screen_size_changed,
stylist: StylistWrapper(&*rw_data.stylist),
stylist: StylistWrapper::<ServoSelectorImpl>(&*rw_data.stylist),
generation: self.generation,
goal: goal,
new_animations_sender: Mutex::new(self.new_animations_sender.clone()),

View file

@ -16,6 +16,7 @@ use incremental::{BUBBLE_ISIZES, REFLOW, REFLOW_OUT_OF_FLOW, REPAINT, RestyleDam
use std::mem;
use style::context::{StyleContext, ReflowGoal};
use style::matching::MatchMethods;
use style::selector_impl::ServoSelectorImpl;
use style::traversal::{DomTraversalContext, STYLE_BLOOM};
use style::traversal::{put_thread_local_bloom_filter, recalc_style_at};
use util::opts;
@ -27,7 +28,8 @@ pub struct RecalcStyleAndConstructFlows<'lc> {
root: OpaqueNode,
}
impl<'lc, 'ln, N: LayoutNode<'ln>> DomTraversalContext<'ln, N> for RecalcStyleAndConstructFlows<'lc> {
impl<'lc, 'ln, N: LayoutNode<'ln>> DomTraversalContext<'ln, N> for RecalcStyleAndConstructFlows<'lc>
where N::ConcreteElement: ::selectors::Element<Impl=ServoSelectorImpl> {
type SharedContext = SharedLayoutContext;
#[allow(unsafe_code)]
fn new<'a>(shared: &'a Self::SharedContext, root: OpaqueNode) -> Self {

View file

@ -64,13 +64,13 @@ use std::sync::Arc;
use string_cache::{Atom, Namespace};
use style::computed_values::content::ContentItem;
use style::computed_values::{content, display};
use style::data::PrivateStyleData;
use style::dom::{TDocument, TElement, TNode, UnsafeNode};
use style::element_state::*;
use style::properties::ComputedValues;
use style::properties::{PropertyDeclaration, PropertyDeclarationBlock};
use style::restyle_hints::ElementSnapshot;
use style::selector_impl::{NonTSPseudoClass, ServoSelectorImpl};
use style::selector_impl::{NonTSPseudoClass, PseudoElement, ServoSelectorImpl};
use style::servo::PrivateStyleData;
use url::Url;
use util::str::{is_whitespace, search_index};
@ -664,14 +664,18 @@ pub trait ThreadSafeLayoutNode<'ln> : Clone + Copy + Sized {
#[inline]
fn get_before_pseudo(&self) -> Option<Self> {
self.borrow_layout_data().unwrap().style_data.before_style.as_ref().map(|style| {
self.borrow_layout_data().unwrap()
.style_data.per_pseudo
.get(&PseudoElement::Before).unwrap_or(&None).as_ref().map(|style| {
self.with_pseudo(PseudoElementType::Before(style.get_box().display))
})
}
#[inline]
fn get_after_pseudo(&self) -> Option<Self> {
self.borrow_layout_data().unwrap().style_data.after_style.as_ref().map(|style| {
self.borrow_layout_data().unwrap()
.style_data.per_pseudo
.get(&PseudoElement::After).unwrap_or(&None).as_ref().map(|style| {
self.with_pseudo(PseudoElementType::After(style.get_box().display))
})
}
@ -696,8 +700,8 @@ pub trait ThreadSafeLayoutNode<'ln> : Clone + Copy + Sized {
fn style(&self) -> Ref<Arc<ComputedValues>> {
Ref::map(self.borrow_layout_data().unwrap(), |data| {
let style = match self.get_pseudo_element_type() {
PseudoElementType::Before(_) => &data.style_data.before_style,
PseudoElementType::After(_) => &data.style_data.after_style,
PseudoElementType::Before(_) => data.style_data.per_pseudo.get(&PseudoElement::Before).unwrap(),
PseudoElementType::After(_) => data.style_data.per_pseudo.get(&PseudoElement::After).unwrap(),
PseudoElementType::Normal => &data.style_data.style,
};
style.as_ref().unwrap()
@ -711,8 +715,18 @@ pub trait ThreadSafeLayoutNode<'ln> : Clone + Copy + Sized {
let mut data = self.mutate_layout_data().unwrap();
let style =
match self.get_pseudo_element_type() {
PseudoElementType::Before(_) => &mut data.style_data.before_style,
PseudoElementType::After (_) => &mut data.style_data.after_style,
PseudoElementType::Before(_) => {
match data.style_data.per_pseudo.get_mut(&PseudoElement::Before) {
None => return,
Some(style) => style,
}
}
PseudoElementType::After(_) => {
match data.style_data.per_pseudo.get_mut(&PseudoElement::After) {
None => return,
Some(style) => style,
}
}
PseudoElementType::Normal => &mut data.style_data.style,
};
@ -934,10 +948,11 @@ impl<'ln> ThreadSafeLayoutNode<'ln> for ServoThreadSafeLayoutNode<'ln> {
let data = &self.borrow_layout_data().unwrap().style_data;
let style = if self.pseudo.is_before() {
&data.before_style
data.per_pseudo.get(&PseudoElement::Before).unwrap()
} else {
&data.after_style
data.per_pseudo.get(&PseudoElement::After).unwrap()
};
return match style.as_ref().unwrap().get_box().content {
content::T::Content(ref value) if !value.is_empty() => {
TextContent::GeneratedContent((*value).clone())

View file

@ -81,7 +81,7 @@ num = "0.1.24"
rand = "0.3"
ref_slice = "0.1.0"
rustc-serialize = "0.3"
selectors = {version = "0.4.2", features = ["heap_size"]}
selectors = {version = "0.5", features = ["heap_size"]}
serde = "0.6"
smallvec = "0.1"
string_cache = {version = "0.2.9", features = ["heap_size", "unstable"]}

View file

@ -105,7 +105,7 @@ use std::sync::Arc;
use string_cache::{Atom, QualName};
use style::context::ReflowGoal;
use style::restyle_hints::ElementSnapshot;
use style::stylesheets::Stylesheet;
use style::servo::Stylesheet;
use time;
use url::{Host, Url};
use util::str::{DOMString, split_html_space_chars, str_join};

View file

@ -36,7 +36,8 @@ use std::mem;
use std::sync::{Arc, Mutex};
use string_cache::Atom;
use style::media_queries::{MediaQueryList, parse_media_query_list};
use style::stylesheets::{Origin, Stylesheet};
use style::servo::Stylesheet;
use style::stylesheets::Origin;
use url::Url;
use util::str::{DOMString, HTML_SPACE_CHARACTERS};

View file

@ -15,7 +15,8 @@ use dom::virtualmethods::VirtualMethods;
use std::ascii::AsciiExt;
use std::sync::Arc;
use string_cache::Atom;
use style::stylesheets::{CSSRule, Origin, Stylesheet};
use style::servo::Stylesheet;
use style::stylesheets::{CSSRule, Origin};
use style::viewport::ViewportRule;
use util::str::{DOMString, HTML_SPACE_CHARACTERS};

View file

@ -17,7 +17,8 @@ use layout_interface::{LayoutChan, Msg};
use std::sync::Arc;
use string_cache::Atom;
use style::media_queries::parse_media_query_list;
use style::stylesheets::{Origin, Stylesheet};
use style::servo::Stylesheet;
use style::stylesheets::Origin;
use util::str::DOMString;
#[dom_struct]

View file

@ -24,7 +24,7 @@ use std::sync::mpsc::{Receiver, Sender, channel};
use string_cache::Atom;
use style::context::ReflowGoal;
use style::selector_impl::PseudoElement;
use style::stylesheets::Stylesheet;
use style::servo::Stylesheet;
use url::Url;
use util::ipc::OptionalOpaqueIpcSender;

View file

@ -1003,7 +1003,7 @@ dependencies = [
"rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
"script 0.0.1",
"script_traits 0.0.1",
"selectors 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"selectors 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_macros 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1590,7 +1590,7 @@ dependencies = [
"ref_slice 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
"script_traits 0.0.1",
"selectors 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"selectors 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"string_cache 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1641,7 +1641,7 @@ dependencies = [
[[package]]
name = "selectors"
version = "0.4.2"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1850,7 +1850,7 @@ dependencies = [
"num 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)",
"plugins 0.0.1",
"rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
"selectors 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"selectors 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_macros 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1870,7 +1870,7 @@ dependencies = [
"euclid 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
"msg 0.0.1",
"plugins 0.0.1",
"selectors 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"selectors 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"string_cache 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
"style 0.0.1",
"style_traits 0.0.1",
@ -1891,7 +1891,7 @@ dependencies = [
"num 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)",
"plugins 0.0.1",
"rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
"selectors 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"selectors 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_macros 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"url 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2049,7 +2049,7 @@ dependencies = [
"plugins 0.0.1",
"rand 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
"selectors 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"selectors 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_macros 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",

View file

@ -32,7 +32,7 @@ log = "0.3"
matches = "0.1"
num = "0.1.24"
rustc-serialize = "0.3"
selectors = {version = "0.4.2", features = ["heap_size", "unstable"]}
selectors = {version = "0.5", features = ["heap_size", "unstable"]}
serde = "0.6"
serde_macros = "0.6"
smallvec = "0.1"

View file

@ -8,19 +8,20 @@ use dom::OpaqueNode;
use error_reporting::ParseErrorReporter;
use euclid::Size2D;
use matching::{ApplicableDeclarationsCache, StyleSharingCandidateCache};
use selector_impl::SelectorImplExt;
use selector_matching::Stylist;
use std::cell::RefCell;
use std::collections::HashMap;
use std::sync::mpsc::Sender;
use std::sync::{Arc, Mutex, RwLock};
pub struct StylistWrapper(pub *const Stylist);
pub struct StylistWrapper<Impl: SelectorImplExt>(pub *const Stylist<Impl>);
// FIXME(#6569) This implementation is unsound.
#[allow(unsafe_code)]
unsafe impl Sync for StylistWrapper {}
unsafe impl<Impl: SelectorImplExt> Sync for StylistWrapper<Impl> {}
pub struct SharedStyleContext {
pub struct SharedStyleContext<Impl: SelectorImplExt> {
/// The current viewport size.
pub viewport_size: Size2D<Au>,
@ -30,7 +31,7 @@ pub struct SharedStyleContext {
/// The CSS selector stylist.
///
/// FIXME(#2604): Make this no longer an unsafe pointer once we have fast `RWArc`s.
pub stylist: StylistWrapper,
pub stylist: StylistWrapper<Impl>,
/// Starts at zero, and increased by one every time a layout completes.
/// This can be used to easily check for invalid stale data.
@ -58,8 +59,9 @@ pub struct LocalStyleContext {
pub style_sharing_candidate_cache: RefCell<StyleSharingCandidateCache>,
}
pub trait StyleContext<'a> {
fn shared_context(&self) -> &'a SharedStyleContext;
pub trait StyleContext<'a, Impl: SelectorImplExt> {
fn shared_context(&self) -> &'a SharedStyleContext<Impl>;
fn local_context(&self) -> &LocalStyleContext;
}

View file

@ -3,29 +3,27 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use properties::ComputedValues;
use selectors::parser::SelectorImpl;
use std::collections::HashMap;
use std::sync::Arc;
use std::sync::atomic::AtomicIsize;
pub struct PrivateStyleData {
pub struct PrivateStyleData<Impl: SelectorImpl> {
/// The results of CSS styling for this node.
pub style: Option<Arc<ComputedValues>>,
/// The results of CSS styling for this node's `before` pseudo-element, if any.
pub before_style: Option<Arc<ComputedValues>>,
/// The results of CSS styling for this node's `after` pseudo-element, if any.
pub after_style: Option<Arc<ComputedValues>>,
/// The results of CSS styling for each pseudo-element (if any).
pub per_pseudo: HashMap<Impl::PseudoElement, Option<Arc<ComputedValues>>>,
/// Information needed during parallel traversals.
pub parallel: DomParallelInfo,
}
impl PrivateStyleData {
pub fn new() -> PrivateStyleData {
impl<Impl: SelectorImpl> PrivateStyleData<Impl> {
pub fn new() -> PrivateStyleData<Impl> {
PrivateStyleData {
style: None,
before_style: None,
after_style: None,
per_pseudo: HashMap::new(),
parallel: DomParallelInfo::new(),
}
}

View file

@ -8,7 +8,8 @@ use data::PrivateStyleData;
use element_state::ElementState;
use properties::{ComputedValues, PropertyDeclaration, PropertyDeclarationBlock};
use restyle_hints::{ElementSnapshot, RESTYLE_DESCENDANTS, RESTYLE_LATER_SIBLINGS, RESTYLE_SELF, RestyleHint};
use selector_impl::ServoSelectorImpl;
use selector_impl::ElementExt;
use selectors::Element;
use selectors::matching::DeclarationBlock;
use smallvec::VecLike;
use std::cell::{Ref, RefMut};
@ -136,15 +137,18 @@ pub trait TNode<'ln> : Sized + Copy + Clone {
/// Borrows the PrivateStyleData without checks.
#[inline(always)]
unsafe fn borrow_data_unchecked(&self) -> Option<*const PrivateStyleData>;
unsafe fn borrow_data_unchecked(&self)
-> Option<*const PrivateStyleData<<Self::ConcreteElement as Element>::Impl>>;
/// Borrows the PrivateStyleData immutably. Fails on a conflicting borrow.
#[inline(always)]
fn borrow_data(&self) -> Option<Ref<PrivateStyleData>>;
fn borrow_data(&self)
-> Option<Ref<PrivateStyleData<<Self::ConcreteElement as Element>::Impl>>>;
/// Borrows the PrivateStyleData mutably. Fails on a conflicting borrow.
#[inline(always)]
fn mutate_data(&self) -> Option<RefMut<PrivateStyleData>>;
fn mutate_data(&self)
-> Option<RefMut<PrivateStyleData<<Self::ConcreteElement as Element>::Impl>>>;
/// Get the description of how to account for recent style changes.
fn restyle_damage(self) -> Self::ConcreteRestyleDamage;
@ -165,7 +169,7 @@ pub trait TNode<'ln> : Sized + Copy + Clone {
/// Returns the style results for the given node. If CSS selector matching
/// has not yet been performed, fails.
fn style(&self) -> Ref<Arc<ComputedValues>> {
fn style(&'ln self) -> Ref<Arc<ComputedValues>> {
Ref::map(self.borrow_data().unwrap(), |data| data.style.as_ref().unwrap())
}
@ -186,7 +190,7 @@ pub trait TDocument<'ld> : Sized + Copy + Clone {
fn drain_modified_elements(&self) -> Vec<(Self::ConcreteElement, ElementSnapshot)>;
}
pub trait TElement<'le> : Sized + Copy + Clone + ::selectors::Element<Impl=ServoSelectorImpl> {
pub trait TElement<'le> : Sized + Copy + Clone + ElementExt {
type ConcreteNode: TNode<'le, ConcreteElement = Self, ConcreteDocument = Self::ConcreteDocument>;
type ConcreteDocument: TDocument<'le, ConcreteNode = Self::ConcreteNode, ConcreteElement = Self>;

View file

@ -62,6 +62,7 @@ pub mod restyle_hints;
pub mod selector_impl;
pub mod selector_matching;
pub mod sequential;
pub mod servo;
pub mod stylesheets;
pub mod traversal;
#[macro_use]

View file

@ -9,13 +9,14 @@ use context::SharedStyleContext;
use data::PrivateStyleData;
use dom::{TElement, TNode, TRestyleDamage};
use properties::{ComputedValues, PropertyDeclaration, cascade};
use selector_impl::{NonTSPseudoClass, PseudoElement};
use selector_impl::SelectorImplExt;
use selector_matching::{DeclarationBlock, Stylist};
use selectors::Element;
use selectors::bloom::BloomFilter;
use selectors::matching::{CommonStyleAffectingAttributeMode, CommonStyleAffectingAttributes};
use selectors::matching::{common_style_affecting_attributes, rare_style_affecting_attributes};
use smallvec::SmallVec;
use std::collections::HashMap;
use std::hash::{Hash, Hasher};
use std::slice::Iter;
use std::sync::mpsc::Sender;
@ -51,23 +52,27 @@ fn create_common_style_affecting_attributes_from_element<'le, E: TElement<'le>>(
flags
}
pub struct ApplicableDeclarations {
pub struct ApplicableDeclarations<Impl: SelectorImplExt> {
pub normal: SmallVec<[DeclarationBlock; 16]>,
pub before: Vec<DeclarationBlock>,
pub after: Vec<DeclarationBlock>,
pub per_pseudo: HashMap<Impl::PseudoElement, Vec<DeclarationBlock>>,
/// Whether the `normal` declarations are shareable with other nodes.
pub normal_shareable: bool,
}
impl ApplicableDeclarations {
pub fn new() -> ApplicableDeclarations {
ApplicableDeclarations {
impl<Impl: SelectorImplExt> ApplicableDeclarations<Impl> {
pub fn new() -> ApplicableDeclarations<Impl> {
let mut applicable_declarations = ApplicableDeclarations {
normal: SmallVec::new(),
before: Vec::new(),
after: Vec::new(),
per_pseudo: HashMap::new(),
normal_shareable: false,
}
};
Impl::each_eagerly_cascaded_pseudo_element(|pseudo| {
applicable_declarations.per_pseudo.insert(pseudo, vec![]);
});
applicable_declarations
}
}
@ -246,7 +251,7 @@ impl StyleSharingCandidate {
local_name: element.get_local_name().clone(),
class: element.get_attr(&ns!(), &atom!("class"))
.map(|string| string.to_owned()),
link: element.match_non_ts_pseudo_class(NonTSPseudoClass::AnyLink),
link: element.is_link(),
namespace: (*element.get_namespace()).clone(),
common_style_affecting_attributes:
create_common_style_affecting_attributes_from_element::<'le, E>(&element)
@ -314,7 +319,7 @@ impl StyleSharingCandidate {
}
}
if element.match_non_ts_pseudo_class(NonTSPseudoClass::AnyLink) != self.link {
if element.is_link() != self.link {
return false
}
@ -359,9 +364,10 @@ pub enum StyleSharingResult<ConcreteRestyleDamage: TRestyleDamage> {
StyleWasShared(usize, ConcreteRestyleDamage),
}
trait PrivateMatchMethods<'ln>: TNode<'ln> {
trait PrivateMatchMethods<'ln>: TNode<'ln>
where <Self::ConcreteElement as Element>::Impl: SelectorImplExt {
fn cascade_node_pseudo_element(&self,
context: &SharedStyleContext,
context: &SharedStyleContext<<Self::ConcreteElement as Element>::Impl>,
parent_style: Option<&Arc<ComputedValues>>,
applicable_declarations: &[DeclarationBlock],
style: &mut Option<Arc<ComputedValues>>,
@ -434,7 +440,7 @@ trait PrivateMatchMethods<'ln>: TNode<'ln> {
}
fn update_animations_for_cascade(&self,
context: &SharedStyleContext,
context: &SharedStyleContext<<Self::ConcreteElement as Element>::Impl>,
style: &mut Option<Arc<ComputedValues>>)
-> bool {
let style = match *style {
@ -478,7 +484,8 @@ trait PrivateMatchMethods<'ln>: TNode<'ln> {
}
}
impl<'ln, N: TNode<'ln>> PrivateMatchMethods<'ln> for N {}
impl<'ln, N: TNode<'ln>> PrivateMatchMethods<'ln> for N
where <N::ConcreteElement as Element>::Impl: SelectorImplExt {}
trait PrivateElementMatchMethods<'le>: TElement<'le> {
fn share_style_with_candidate_if_possible(&self,
@ -490,7 +497,7 @@ trait PrivateElementMatchMethods<'le>: TElement<'le> {
Some(_) | None => return None,
};
let parent_data: Option<&PrivateStyleData> = unsafe {
let parent_data: Option<&PrivateStyleData<_>> = unsafe {
parent_node.borrow_data_unchecked().map(|d| &*d)
};
@ -512,11 +519,12 @@ trait PrivateElementMatchMethods<'le>: TElement<'le> {
impl<'le, E: TElement<'le>> PrivateElementMatchMethods<'le> for E {}
pub trait ElementMatchMethods<'le> : TElement<'le> {
pub trait ElementMatchMethods<'le> : TElement<'le>
where Self::Impl: SelectorImplExt {
fn match_element(&self,
stylist: &Stylist,
stylist: &Stylist<Self::Impl>,
parent_bf: Option<&BloomFilter>,
applicable_declarations: &mut ApplicableDeclarations)
applicable_declarations: &mut ApplicableDeclarations<Self::Impl>)
-> bool {
let style_attribute = self.style_attribute().as_ref();
@ -526,20 +534,16 @@ pub trait ElementMatchMethods<'le> : TElement<'le> {
style_attribute,
None,
&mut applicable_declarations.normal);
Self::Impl::each_eagerly_cascaded_pseudo_element(|pseudo| {
stylist.push_applicable_declarations(self,
parent_bf,
None,
Some(PseudoElement::Before),
&mut applicable_declarations.before);
stylist.push_applicable_declarations(self,
parent_bf,
None,
Some(PseudoElement::After),
&mut applicable_declarations.after);
Some(pseudo.clone()),
applicable_declarations.per_pseudo.entry(pseudo).or_insert(vec![]));
});
applicable_declarations.normal_shareable &&
applicable_declarations.before.is_empty() &&
applicable_declarations.after.is_empty()
applicable_declarations.per_pseudo.values().all(|v| v.is_empty())
}
/// Attempts to share a style with another node. This method is unsafe because it depends on
@ -580,7 +584,8 @@ pub trait ElementMatchMethods<'le> : TElement<'le> {
}
}
impl<'le, E: TElement<'le>> ElementMatchMethods<'le> for E {}
impl<'le, E: TElement<'le>> ElementMatchMethods<'le> for E
where E::Impl: SelectorImplExt {}
pub trait MatchMethods<'ln> : TNode<'ln> {
// The below two functions are copy+paste because I can't figure out how to
@ -632,11 +637,12 @@ pub trait MatchMethods<'ln> : TNode<'ln> {
}
unsafe fn cascade_node(&self,
context: &SharedStyleContext,
context: &SharedStyleContext<<Self::ConcreteElement as Element>::Impl>,
parent: Option<Self>,
applicable_declarations: &ApplicableDeclarations,
applicable_declarations: &ApplicableDeclarations<<Self::ConcreteElement as Element>::Impl>,
applicable_declarations_cache: &mut ApplicableDeclarationsCache,
new_animations_sender: &Mutex<Sender<Animation>>) {
new_animations_sender: &Mutex<Sender<Animation>>)
where <Self::ConcreteElement as Element>::Impl: SelectorImplExt {
// Get our parent's style. This must be unsafe so that we don't touch the parent's
// borrow flags.
//
@ -673,28 +679,24 @@ pub trait MatchMethods<'ln> : TNode<'ln> {
new_animations_sender,
applicable_declarations.normal_shareable,
true);
if !applicable_declarations.before.is_empty() {
<Self::ConcreteElement as Element>::Impl::each_eagerly_cascaded_pseudo_element(|pseudo| {
let applicable_declarations_for_this_pseudo =
applicable_declarations.per_pseudo.get(&pseudo).unwrap();
if !applicable_declarations_for_this_pseudo.is_empty() {
damage = damage | self.cascade_node_pseudo_element(
context,
Some(data.style.as_ref().unwrap()),
&*applicable_declarations.before,
&mut data.before_style,
applicable_declarations_cache,
new_animations_sender,
false,
false);
}
if !applicable_declarations.after.is_empty() {
damage = damage | self.cascade_node_pseudo_element(
context,
Some(data.style.as_ref().unwrap()),
&*applicable_declarations.after,
&mut data.after_style,
&*applicable_declarations_for_this_pseudo,
data.per_pseudo.entry(pseudo).or_insert(None),
applicable_declarations_cache,
new_animations_sender,
false,
false);
}
});
}
// This method needs to borrow the data as mutable, so make sure data_ref goes out of

View file

@ -4,10 +4,10 @@
use attr::{AttrIdentifier, AttrValue};
use element_state::*;
use selector_impl::{NonTSPseudoClass, ServoSelectorImpl};
use selector_impl::SelectorImplExt;
use selectors::Element;
use selectors::matching::matches_compound_selector;
use selectors::parser::{AttrSelector, Combinator, CompoundSelector, NamespaceConstraint, SimpleSelector};
use selectors::parser::{AttrSelector, Combinator, CompoundSelector, NamespaceConstraint, SelectorImpl, SimpleSelector};
use std::clone::Clone;
use std::sync::Arc;
use string_cache::{Atom, Namespace};
@ -78,12 +78,16 @@ impl ElementSnapshot {
static EMPTY_SNAPSHOT: ElementSnapshot = ElementSnapshot { state: None, attrs: None };
struct ElementWrapper<'a, E> where E: Element {
struct ElementWrapper<'a, E>
where E: Element,
E::Impl: SelectorImplExt {
element: E,
snapshot: &'a ElementSnapshot,
}
impl<'a, E> ElementWrapper<'a, E> where E: Element {
impl<'a, E> ElementWrapper<'a, E>
where E: Element,
E::Impl: SelectorImplExt {
pub fn new(el: E) -> ElementWrapper<'a, E> {
ElementWrapper { element: el, snapshot: &EMPTY_SNAPSHOT }
}
@ -93,16 +97,19 @@ impl<'a, E> ElementWrapper<'a, E> where E: Element {
}
}
impl<'a, E> Element for ElementWrapper<'a, E> where E: Element<Impl=ServoSelectorImpl> {
impl<'a, E> Element for ElementWrapper<'a, E>
where E: Element,
E::Impl: SelectorImplExt {
type Impl = E::Impl;
fn match_non_ts_pseudo_class(&self, pseudo_class: NonTSPseudoClass) -> bool {
let flag = pseudo_class.state_flag();
fn match_non_ts_pseudo_class(&self,
pseudo_class: <Self::Impl as SelectorImpl>::NonTSPseudoClass) -> bool {
let flag = Self::Impl::pseudo_class_state_flag(&pseudo_class);
if flag == ElementState::empty() {
self.element.match_non_ts_pseudo_class(pseudo_class)
} else {
match self.snapshot.state {
Some(s) => s.contains(pseudo_class.state_flag()),
Some(s) => s.contains(flag),
None => self.element.match_non_ts_pseudo_class(pseudo_class)
}
}
@ -177,14 +184,14 @@ impl<'a, E> Element for ElementWrapper<'a, E> where E: Element<Impl=ServoSelecto
}
}
fn selector_to_state(sel: &SimpleSelector<ServoSelectorImpl>) -> ElementState {
fn selector_to_state<Impl: SelectorImplExt>(sel: &SimpleSelector<Impl>) -> ElementState {
match *sel {
SimpleSelector::NonTSPseudoClass(ref pc) => pc.state_flag(),
SimpleSelector::NonTSPseudoClass(ref pc) => Impl::pseudo_class_state_flag(pc),
_ => ElementState::empty(),
}
}
fn is_attr_selector(sel: &SimpleSelector<ServoSelectorImpl>) -> bool {
fn is_attr_selector<Impl: SelectorImpl>(sel: &SimpleSelector<Impl>) -> bool {
match *sel {
SimpleSelector::ID(_) |
SimpleSelector::Class(_) |
@ -249,25 +256,25 @@ impl Sensitivities {
// maximum effect that a given state or attribute change may have on the style of
// elements in the document.
#[derive(Debug)]
struct Dependency {
selector: Arc<CompoundSelector<ServoSelectorImpl>>,
struct Dependency<Impl: SelectorImplExt> {
selector: Arc<CompoundSelector<Impl>>,
combinator: Option<Combinator>,
sensitivities: Sensitivities,
}
#[derive(Debug)]
pub struct DependencySet {
deps: Vec<Dependency>,
pub struct DependencySet<Impl: SelectorImplExt> {
deps: Vec<Dependency<Impl>>,
}
impl DependencySet {
pub fn new() -> DependencySet {
impl<Impl: SelectorImplExt> DependencySet<Impl> {
pub fn new() -> DependencySet<Impl> {
DependencySet { deps: Vec::new() }
}
pub fn compute_hint<E>(&self, el: &E, snapshot: &ElementSnapshot, current_state: ElementState)
-> RestyleHint
where E: Element<Impl=ServoSelectorImpl> + Clone {
where E: Element<Impl=Impl> + Clone {
let state_changes = snapshot.state.map_or(ElementState::empty(), |old_state| current_state ^ old_state);
let attrs_changed = snapshot.attrs.is_some();
let mut hint = RestyleHint::empty();
@ -287,7 +294,7 @@ impl DependencySet {
hint
}
pub fn note_selector(&mut self, selector: Arc<CompoundSelector<ServoSelectorImpl>>) {
pub fn note_selector(&mut self, selector: Arc<CompoundSelector<Impl>>) {
let mut cur = selector;
let mut combinator: Option<Combinator> = None;
loop {

View file

@ -2,15 +2,33 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use element_state::ElementState;
use selector_matching::{USER_OR_USER_AGENT_STYLESHEETS, QUIRKS_MODE_STYLESHEET};
use selectors::Element;
use selectors::parser::{ParserContext, SelectorImpl};
use stylesheets::Stylesheet;
#[derive(Clone, Debug, PartialEq, HeapSizeOf)]
pub trait ElementExt: Element {
fn is_link(&self) -> bool;
}
pub trait SelectorImplExt : SelectorImpl + Sized {
fn each_eagerly_cascaded_pseudo_element<F>(mut fun: F)
where F: FnMut(<Self as SelectorImpl>::PseudoElement);
fn pseudo_class_state_flag(pc: &Self::NonTSPseudoClass) -> ElementState;
fn get_user_or_user_agent_stylesheets() -> &'static [Stylesheet<Self>];
fn get_quirks_mode_stylesheet() -> &'static Stylesheet<Self>;
}
#[derive(Clone, Debug, PartialEq, Eq, HeapSizeOf, Hash)]
pub enum PseudoElement {
Before,
After,
}
#[derive(Clone, Debug, PartialEq, HeapSizeOf)]
#[derive(Clone, Debug, PartialEq, Eq, HeapSizeOf, Hash)]
pub enum NonTSPseudoClass {
AnyLink,
Link,
@ -82,10 +100,42 @@ impl SelectorImpl for ServoSelectorImpl {
fn parse_pseudo_element(_context: &ParserContext,
name: &str) -> Result<PseudoElement, ()> {
use self::PseudoElement::*;
match_ignore_ascii_case! { name,
"before" => Ok(Before),
"after" => Ok(After),
_ => Err(())
}
let pseudo_element = match_ignore_ascii_case! { name,
"before" => Before,
"after" => After,
_ => return Err(())
};
Ok(pseudo_element)
}
}
impl<E: Element<Impl=ServoSelectorImpl>> ElementExt for E {
fn is_link(&self) -> bool {
self.match_non_ts_pseudo_class(NonTSPseudoClass::AnyLink)
}
}
impl SelectorImplExt for ServoSelectorImpl {
#[inline]
fn each_eagerly_cascaded_pseudo_element<F>(mut fun: F)
where F: FnMut(PseudoElement) {
fun(PseudoElement::Before);
fun(PseudoElement::After);
}
#[inline]
fn pseudo_class_state_flag(pc: &NonTSPseudoClass) -> ElementState {
pc.state_flag()
}
#[inline]
fn get_user_or_user_agent_stylesheets() -> &'static [Stylesheet<Self>] {
&*USER_OR_USER_AGENT_STYLESHEETS
}
#[inline]
fn get_quirks_mode_stylesheet() -> &'static Stylesheet<Self> {
&*QUIRKS_MODE_STYLESHEET
}
}

View file

@ -11,12 +11,14 @@ use error_reporting::{ParseErrorReporter, StdoutErrorReporter};
use media_queries::{Device, MediaType};
use properties::{PropertyDeclaration, PropertyDeclarationBlock};
use restyle_hints::{ElementSnapshot, RestyleHint, DependencySet};
use selector_impl::{PseudoElement, ServoSelectorImpl};
use selector_impl::{SelectorImplExt, ServoSelectorImpl};
use selectors::Element;
use selectors::bloom::BloomFilter;
use selectors::matching::DeclarationBlock as GenericDeclarationBlock;
use selectors::matching::{Rule, SelectorMap};
use selectors::parser::SelectorImpl;
use smallvec::VecLike;
use std::collections::HashMap;
use std::process;
use std::sync::Arc;
use style_traits::viewport::ViewportConstraints;
@ -30,7 +32,7 @@ use viewport::{MaybeNew, ViewportRuleCascade};
pub type DeclarationBlock = GenericDeclarationBlock<Vec<PropertyDeclaration>>;
lazy_static! {
pub static ref USER_OR_USER_AGENT_STYLESHEETS: Vec<Stylesheet> = {
pub static ref USER_OR_USER_AGENT_STYLESHEETS: Vec<Stylesheet<ServoSelectorImpl>> = {
let mut stylesheets = vec!();
// FIXME: presentational-hints.css should be at author origin with zero specificity.
// (Does it make a difference?)
@ -61,7 +63,7 @@ lazy_static! {
}
lazy_static! {
pub static ref QUIRKS_MODE_STYLESHEET: Stylesheet = {
pub static ref QUIRKS_MODE_STYLESHEET: Stylesheet<ServoSelectorImpl> = {
match read_resource_file(&["quirks-mode.css"]) {
Ok(res) => {
Stylesheet::from_bytes(
@ -80,7 +82,7 @@ lazy_static! {
};
}
pub struct Stylist {
pub struct Stylist<Impl: SelectorImplExt> {
// Device that the stylist is currently evaluating against.
pub device: Device,
@ -95,50 +97,55 @@ pub struct Stylist {
// The current selector maps, after evaluating media
// rules against the current device.
element_map: PerPseudoElementSelectorMap,
before_map: PerPseudoElementSelectorMap,
after_map: PerPseudoElementSelectorMap,
element_map: PerPseudoElementSelectorMap<Impl>,
pseudos_map: HashMap<Impl::PseudoElement, PerPseudoElementSelectorMap<Impl>>,
rules_source_order: usize,
// Selector dependencies used to compute restyle hints.
state_deps: DependencySet,
state_deps: DependencySet<Impl>,
}
impl Stylist {
impl<Impl: SelectorImplExt> Stylist<Impl> {
#[inline]
pub fn new(device: Device) -> Stylist {
Stylist {
pub fn new(device: Device) -> Stylist<Impl> {
let mut stylist = Stylist {
viewport_constraints: None,
device: device,
is_device_dirty: true,
quirks_mode: false,
element_map: PerPseudoElementSelectorMap::new(),
before_map: PerPseudoElementSelectorMap::new(),
after_map: PerPseudoElementSelectorMap::new(),
pseudos_map: HashMap::new(),
rules_source_order: 0,
state_deps: DependencySet::new(),
}
};
Impl::each_eagerly_cascaded_pseudo_element(|pseudo| {
stylist.pseudos_map.insert(pseudo, PerPseudoElementSelectorMap::new());
});
// FIXME: Add iso-8859-9.css when the documents encoding is ISO-8859-8.
stylist
}
pub fn update(&mut self, doc_stylesheets: &[Arc<Stylesheet>],
stylesheets_changed: bool) -> bool {
pub fn update(&mut self, doc_stylesheets: &[Arc<Stylesheet<Impl>>],
stylesheets_changed: bool) -> bool
where Impl: 'static {
if !(self.is_device_dirty || stylesheets_changed) {
return false;
}
self.element_map = PerPseudoElementSelectorMap::new();
self.before_map = PerPseudoElementSelectorMap::new();
self.after_map = PerPseudoElementSelectorMap::new();
self.pseudos_map = HashMap::new();
self.rules_source_order = 0;
self.state_deps.clear();
for ref stylesheet in USER_OR_USER_AGENT_STYLESHEETS.iter() {
for ref stylesheet in Impl::get_user_or_user_agent_stylesheets().iter() {
self.add_stylesheet(&stylesheet);
}
if self.quirks_mode {
self.add_stylesheet(&QUIRKS_MODE_STYLESHEET);
self.add_stylesheet(&Impl::get_quirks_mode_stylesheet());
}
for ref stylesheet in doc_stylesheets.iter() {
@ -149,28 +156,12 @@ impl Stylist {
true
}
fn add_stylesheet(&mut self, stylesheet: &Stylesheet) {
fn add_stylesheet(&mut self, stylesheet: &Stylesheet<Impl>) {
let device = &self.device;
if !stylesheet.is_effective_for_device(device) {
return;
}
let (mut element_map, mut before_map, mut after_map) = match stylesheet.origin {
Origin::UserAgent => (
&mut self.element_map.user_agent,
&mut self.before_map.user_agent,
&mut self.after_map.user_agent,
),
Origin::Author => (
&mut self.element_map.author,
&mut self.before_map.author,
&mut self.after_map.author,
),
Origin::User => (
&mut self.element_map.user,
&mut self.before_map.user,
&mut self.after_map.user,
),
};
let mut rules_source_order = self.rules_source_order;
// Take apart the StyleRule into individual Rules and insert
@ -179,11 +170,14 @@ impl Stylist {
($style_rule: ident, $priority: ident) => {
if $style_rule.declarations.$priority.len() > 0 {
for selector in &$style_rule.selectors {
let map = match selector.pseudo_element {
None => &mut element_map,
Some(PseudoElement::Before) => &mut before_map,
Some(PseudoElement::After) => &mut after_map,
let map = if let Some(ref pseudo) = selector.pseudo_element {
self.pseudos_map.entry(pseudo.clone())
.or_insert_with(PerPseudoElementSelectorMap::new)
.borrow_for_origin(&stylesheet.origin)
} else {
self.element_map.borrow_for_origin(&stylesheet.origin)
};
map.$priority.insert(Rule {
selector: selector.compound_selectors.clone(),
declarations: DeclarationBlock {
@ -216,11 +210,11 @@ impl Stylist {
// more expensive than getting it directly from the caller.
current_state: ElementState)
-> RestyleHint
where E: Element<Impl=ServoSelectorImpl> + Clone {
where E: Element<Impl=Impl> + Clone {
self.state_deps.compute_hint(element, snapshot, current_state)
}
pub fn set_device(&mut self, mut device: Device, stylesheets: &[Arc<Stylesheet>]) {
pub fn set_device(&mut self, mut device: Device, stylesheets: &[Arc<Stylesheet<Impl>>]) {
let cascaded_rule = stylesheets.iter()
.flat_map(|s| s.effective_rules(&self.device).viewport())
.cascade();
@ -256,19 +250,18 @@ impl Stylist {
element: &E,
parent_bf: Option<&BloomFilter>,
style_attribute: Option<&PropertyDeclarationBlock>,
pseudo_element: Option<PseudoElement>,
pseudo_element: Option<Impl::PseudoElement>,
applicable_declarations: &mut V)
-> bool
where E: Element + TElement<'le>,
where E: Element<Impl=Impl> + TElement<'le>,
V: VecLike<DeclarationBlock> {
assert!(!self.is_device_dirty);
assert!(style_attribute.is_none() || pseudo_element.is_none(),
"Style attributes do not apply to pseudo-elements");
let map = match pseudo_element {
Some(ref pseudo) => self.pseudos_map.get(pseudo).unwrap(),
None => &self.element_map,
Some(PseudoElement::Before) => &self.before_map,
Some(PseudoElement::After) => &self.after_map,
};
let mut shareable = true;
@ -336,14 +329,14 @@ impl Stylist {
}
}
struct PerOriginSelectorMap {
normal: SelectorMap<Vec<PropertyDeclaration>, ServoSelectorImpl>,
important: SelectorMap<Vec<PropertyDeclaration>, ServoSelectorImpl>,
struct PerOriginSelectorMap<Impl: SelectorImpl> {
normal: SelectorMap<Vec<PropertyDeclaration>, Impl>,
important: SelectorMap<Vec<PropertyDeclaration>, Impl>,
}
impl PerOriginSelectorMap {
impl<Impl: SelectorImpl> PerOriginSelectorMap<Impl> {
#[inline]
fn new() -> PerOriginSelectorMap {
fn new() -> PerOriginSelectorMap<Impl> {
PerOriginSelectorMap {
normal: SelectorMap::new(),
important: SelectorMap::new(),
@ -351,19 +344,28 @@ impl PerOriginSelectorMap {
}
}
struct PerPseudoElementSelectorMap {
user_agent: PerOriginSelectorMap,
author: PerOriginSelectorMap,
user: PerOriginSelectorMap,
struct PerPseudoElementSelectorMap<Impl: SelectorImpl> {
user_agent: PerOriginSelectorMap<Impl>,
author: PerOriginSelectorMap<Impl>,
user: PerOriginSelectorMap<Impl>,
}
impl PerPseudoElementSelectorMap {
impl<Impl: SelectorImpl> PerPseudoElementSelectorMap<Impl> {
#[inline]
fn new() -> PerPseudoElementSelectorMap {
fn new() -> PerPseudoElementSelectorMap<Impl> {
PerPseudoElementSelectorMap {
user_agent: PerOriginSelectorMap::new(),
author: PerOriginSelectorMap::new(),
user: PerOriginSelectorMap::new(),
}
}
#[inline]
fn borrow_for_origin(&mut self, origin: &Origin) -> &mut PerOriginSelectorMap<Impl> {
match *origin {
Origin::UserAgent => &mut self.user_agent,
Origin::Author => &mut self.author,
Origin::User => &mut self.user,
}
}
}

15
components/style/servo.rs Normal file
View file

@ -0,0 +1,15 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use context;
use data;
use selector_impl::ServoSelectorImpl;
use selector_matching;
use stylesheets;
/// Concrete types for servo Style implementation
pub type Stylesheet = stylesheets::Stylesheet<ServoSelectorImpl>;
pub type PrivateStyleData = data::PrivateStyleData<ServoSelectorImpl>;
pub type Stylist = selector_matching::Stylist<ServoSelectorImpl>;
pub type StylistWrapper = context::StylistWrapper<ServoSelectorImpl>;
pub type SharedStyleContext = context::SharedStyleContext<ServoSelectorImpl>;

View file

@ -10,12 +10,12 @@ use font_face::{FontFaceRule, parse_font_face_block};
use media_queries::{Device, MediaQueryList, parse_media_query_list};
use parser::{ParserContext, log_css_error};
use properties::{PropertyDeclarationBlock, parse_property_declaration_list};
use selector_impl::ServoSelectorImpl;
use selectors::parser::{Selector, parse_selector_list};
use selectors::parser::{Selector, SelectorImpl, parse_selector_list};
use smallvec::SmallVec;
use std::ascii::AsciiExt;
use std::cell::Cell;
use std::iter::Iterator;
use std::marker::PhantomData;
use std::slice;
use string_cache::{Atom, Namespace};
use url::Url;
@ -39,10 +39,10 @@ pub enum Origin {
#[derive(Debug, HeapSizeOf, PartialEq)]
pub struct Stylesheet {
pub struct Stylesheet<Impl: SelectorImpl> {
/// List of rules in the order they were found (important for
/// cascading order)
pub rules: Vec<CSSRule>,
pub rules: Vec<CSSRule<Impl>>,
/// List of media associated with the Stylesheet, if any.
pub media: Option<MediaQueryList>,
pub origin: Origin,
@ -50,22 +50,22 @@ pub struct Stylesheet {
#[derive(Debug, HeapSizeOf, PartialEq)]
pub enum CSSRule {
pub enum CSSRule<Impl: SelectorImpl> {
Charset(String),
Namespace(Option<String>, Namespace),
Style(StyleRule),
Media(MediaRule),
Style(StyleRule<Impl>),
Media(MediaRule<Impl>),
FontFace(FontFaceRule),
Viewport(ViewportRule),
}
#[derive(Debug, HeapSizeOf, PartialEq)]
pub struct MediaRule {
pub struct MediaRule<Impl: SelectorImpl> {
pub media_queries: MediaQueryList,
pub rules: Vec<CSSRule>,
pub rules: Vec<CSSRule<Impl>>,
}
impl MediaRule {
impl<Impl: SelectorImpl> MediaRule<Impl> {
#[inline]
pub fn evaluate(&self, device: &Device) -> bool {
self.media_queries.evaluate(device)
@ -73,17 +73,17 @@ impl MediaRule {
}
#[derive(Debug, HeapSizeOf, PartialEq)]
pub struct StyleRule {
pub selectors: Vec<Selector<ServoSelectorImpl>>,
pub struct StyleRule<Impl: SelectorImpl> {
pub selectors: Vec<Selector<Impl>>,
pub declarations: PropertyDeclarationBlock,
}
impl Stylesheet {
impl<Impl: SelectorImpl> Stylesheet<Impl> {
pub fn from_bytes_iter<I: Iterator<Item=Vec<u8>>>(
input: I, base_url: Url, protocol_encoding_label: Option<&str>,
environment_encoding: Option<EncodingRef>, origin: Origin,
error_reporter: Box<ParseErrorReporter + Send>) -> Stylesheet {
error_reporter: Box<ParseErrorReporter + Send>) -> Stylesheet<Impl> {
let mut bytes = vec![];
// TODO: incremental decoding and tokenization/parsing
for chunk in input {
@ -98,7 +98,7 @@ impl Stylesheet {
protocol_encoding_label: Option<&str>,
environment_encoding: Option<EncodingRef>,
origin: Origin, error_reporter: Box<ParseErrorReporter + Send>)
-> Stylesheet {
-> Stylesheet<Impl> {
// TODO: bytes.as_slice could be bytes.container_as_bytes()
let (string, _) = decode_stylesheet_bytes(
bytes, protocol_encoding_label, environment_encoding);
@ -106,10 +106,11 @@ impl Stylesheet {
}
pub fn from_str(css: &str, base_url: Url, origin: Origin,
error_reporter: Box<ParseErrorReporter + Send>) -> Stylesheet {
error_reporter: Box<ParseErrorReporter + Send>) -> Stylesheet<Impl> {
let rule_parser = TopLevelRuleParser {
context: ParserContext::new(origin, &base_url, error_reporter.clone()),
state: Cell::new(State::Start),
_impl: PhantomData,
};
let mut input = Parser::new(css);
let mut iter = RuleListParser::new_for_stylesheet(&mut input, rule_parser);
@ -158,7 +159,7 @@ impl Stylesheet {
/// Return an iterator over all the rules within the style-sheet.
#[inline]
pub fn rules(&self) -> Rules {
pub fn rules(&self) -> Rules<Impl> {
Rules::new(self.rules.iter(), None)
}
@ -169,7 +170,7 @@ impl Stylesheet {
/// nested rules will be skipped. Use `rules` if all rules need to be
/// examined.
#[inline]
pub fn effective_rules<'a>(&'a self, device: &'a Device) -> Rules<'a> {
pub fn effective_rules<'a>(&'a self, device: &'a Device) -> Rules<'a, Impl> {
Rules::new(self.rules.iter(), Some(device))
}
}
@ -178,25 +179,25 @@ impl Stylesheet {
///
/// The iteration order is pre-order. Specifically, this implies that a
/// conditional group rule will come before its nested rules.
pub struct Rules<'a> {
pub struct Rules<'a, Impl: SelectorImpl + 'a> {
// 2 because normal case is likely to be just one level of nesting (@media)
stack: SmallVec<[slice::Iter<'a, CSSRule>; 2]>,
stack: SmallVec<[slice::Iter<'a, CSSRule<Impl>>; 2]>,
device: Option<&'a Device>
}
impl<'a> Rules<'a> {
fn new(iter: slice::Iter<'a, CSSRule>, device: Option<&'a Device>) -> Rules<'a> {
let mut stack: SmallVec<[slice::Iter<'a, CSSRule>; 2]> = SmallVec::new();
impl<'a, Impl: SelectorImpl + 'a> Rules<'a, Impl> {
fn new(iter: slice::Iter<'a, CSSRule<Impl>>, device: Option<&'a Device>) -> Rules<'a, Impl> {
let mut stack: SmallVec<[slice::Iter<'a, CSSRule<Impl>>; 2]> = SmallVec::new();
stack.push(iter);
Rules { stack: stack, device: device }
}
}
impl<'a> Iterator for Rules<'a> {
type Item = &'a CSSRule;
impl<'a, Impl: SelectorImpl + 'a> Iterator for Rules<'a, Impl> {
type Item = &'a CSSRule<Impl>;
fn next(&mut self) -> Option<&'a CSSRule> {
fn next(&mut self) -> Option<&'a CSSRule<Impl>> {
while !self.stack.is_empty() {
let top = self.stack.len() - 1;
while let Some(rule) = self.stack[top].next() {
@ -231,6 +232,7 @@ impl<'a> Iterator for Rules<'a> {
pub mod rule_filter {
//! Specific `CSSRule` variant iterators.
use selectors::parser::SelectorImpl;
use std::marker::PhantomData;
use super::super::font_face::FontFaceRule;
use super::super::viewport::ViewportRule;
@ -245,7 +247,8 @@ pub mod rule_filter {
_lifetime: PhantomData<&'a ()>
}
impl<'a, I> $variant<'a, I> where I: Iterator<Item=&'a CSSRule> {
impl<'a, I, Impl: SelectorImpl + 'a> $variant<'a, I>
where I: Iterator<Item=&'a CSSRule<Impl>> {
pub fn new(iter: I) -> $variant<'a, I> {
$variant {
iter: iter,
@ -254,7 +257,8 @@ pub mod rule_filter {
}
}
impl<'a, I> Iterator for $variant<'a, I> where I: Iterator<Item=&'a CSSRule> {
impl<'a, I, Impl: SelectorImpl + 'a> Iterator for $variant<'a, I>
where I: Iterator<Item=&'a CSSRule<Impl>> {
type Item = &'a $value;
fn next(&mut self) -> Option<&'a $value> {
@ -275,14 +279,14 @@ pub mod rule_filter {
}
}
rule_filter!(Media -> MediaRule<Impl>);
rule_filter!(Style -> StyleRule<Impl>);
rule_filter!(FontFace -> FontFaceRule);
rule_filter!(Media -> MediaRule);
rule_filter!(Style -> StyleRule);
rule_filter!(Viewport -> ViewportRule);
}
/// Extension methods for `CSSRule` iterators.
pub trait CSSRuleIteratorExt<'a>: Iterator<Item=&'a CSSRule> + Sized {
pub trait CSSRuleIteratorExt<'a, Impl: SelectorImpl + 'a>: Iterator<Item=&'a CSSRule<Impl>> + Sized {
/// Yield only @font-face rules.
fn font_face(self) -> rule_filter::FontFace<'a, Self>;
@ -296,7 +300,7 @@ pub trait CSSRuleIteratorExt<'a>: Iterator<Item=&'a CSSRule> + Sized {
fn viewport(self) -> rule_filter::Viewport<'a, Self>;
}
impl<'a, I> CSSRuleIteratorExt<'a> for I where I: Iterator<Item=&'a CSSRule> {
impl<'a, I, Impl: SelectorImpl + 'a> CSSRuleIteratorExt<'a, Impl> for I where I: Iterator<Item=&'a CSSRule<Impl>> {
#[inline]
fn font_face(self) -> rule_filter::FontFace<'a, I> {
rule_filter::FontFace::new(self)
@ -318,8 +322,12 @@ impl<'a, I> CSSRuleIteratorExt<'a> for I where I: Iterator<Item=&'a CSSRule> {
}
}
fn parse_nested_rules(context: &ParserContext, input: &mut Parser) -> Vec<CSSRule> {
let mut iter = RuleListParser::new_for_nested_rule(input, NestedRuleParser { context: context });
fn parse_nested_rules<Impl: SelectorImpl>(context: &ParserContext, input: &mut Parser) -> Vec<CSSRule<Impl>> {
let mut iter = RuleListParser::new_for_nested_rule(input,
NestedRuleParser {
context: context,
_impl: PhantomData
});
let mut rules = Vec::new();
while let Some(result) = iter.next() {
match result {
@ -335,9 +343,10 @@ fn parse_nested_rules(context: &ParserContext, input: &mut Parser) -> Vec<CSSRul
}
struct TopLevelRuleParser<'a> {
struct TopLevelRuleParser<'a, Impl: SelectorImpl> {
context: ParserContext<'a>,
state: Cell<State>,
_impl: PhantomData<Impl>
}
#[derive(Eq, PartialEq, Ord, PartialOrd, Copy, Clone)]
@ -356,12 +365,12 @@ enum AtRulePrelude {
}
impl<'a> AtRuleParser for TopLevelRuleParser<'a> {
impl<'a, Impl: SelectorImpl> AtRuleParser for TopLevelRuleParser<'a, Impl> {
type Prelude = AtRulePrelude;
type AtRule = CSSRule;
type AtRule = CSSRule<Impl>;
fn parse_prelude(&self, name: &str, input: &mut Parser)
-> Result<AtRuleType<AtRulePrelude, CSSRule>, ()> {
-> Result<AtRuleType<AtRulePrelude, CSSRule<Impl>>, ()> {
match_ignore_ascii_case! { name,
"charset" => {
if self.state.get() <= State::Start {
@ -397,45 +406,46 @@ impl<'a> AtRuleParser for TopLevelRuleParser<'a> {
}
self.state.set(State::Body);
AtRuleParser::parse_prelude(&NestedRuleParser { context: &self.context }, name, input)
AtRuleParser::parse_prelude(&NestedRuleParser { context: &self.context, _impl: PhantomData }, name, input)
}
#[inline]
fn parse_block(&self, prelude: AtRulePrelude, input: &mut Parser) -> Result<CSSRule, ()> {
AtRuleParser::parse_block(&NestedRuleParser { context: &self.context }, prelude, input)
fn parse_block(&self, prelude: AtRulePrelude, input: &mut Parser) -> Result<CSSRule<Impl>, ()> {
AtRuleParser::parse_block(&NestedRuleParser { context: &self.context, _impl: PhantomData }, prelude, input)
}
}
impl<'a> QualifiedRuleParser for TopLevelRuleParser<'a> {
type Prelude = Vec<Selector<ServoSelectorImpl>>;
type QualifiedRule = CSSRule;
impl<'a, Impl: SelectorImpl> QualifiedRuleParser for TopLevelRuleParser<'a, Impl> {
type Prelude = Vec<Selector<Impl>>;
type QualifiedRule = CSSRule<Impl>;
#[inline]
fn parse_prelude(&self, input: &mut Parser) -> Result<Vec<Selector<ServoSelectorImpl>>, ()> {
fn parse_prelude(&self, input: &mut Parser) -> Result<Vec<Selector<Impl>>, ()> {
self.state.set(State::Body);
QualifiedRuleParser::parse_prelude(&NestedRuleParser { context: &self.context }, input)
QualifiedRuleParser::parse_prelude(&NestedRuleParser { context: &self.context, _impl: PhantomData }, input)
}
#[inline]
fn parse_block(&self, prelude: Vec<Selector<ServoSelectorImpl>>, input: &mut Parser) -> Result<CSSRule, ()> {
QualifiedRuleParser::parse_block(&NestedRuleParser { context: &self.context },
fn parse_block(&self, prelude: Vec<Selector<Impl>>, input: &mut Parser) -> Result<CSSRule<Impl>, ()> {
QualifiedRuleParser::parse_block(&NestedRuleParser { context: &self.context, _impl: PhantomData },
prelude, input)
}
}
struct NestedRuleParser<'a, 'b: 'a> {
struct NestedRuleParser<'a, 'b: 'a, Impl: SelectorImpl> {
context: &'a ParserContext<'b>,
_impl: PhantomData<Impl>,
}
impl<'a, 'b> AtRuleParser for NestedRuleParser<'a, 'b> {
impl<'a, 'b, Impl: SelectorImpl> AtRuleParser for NestedRuleParser<'a, 'b, Impl> {
type Prelude = AtRulePrelude;
type AtRule = CSSRule;
type AtRule = CSSRule<Impl>;
fn parse_prelude(&self, name: &str, input: &mut Parser)
-> Result<AtRuleType<AtRulePrelude, CSSRule>, ()> {
-> Result<AtRuleType<AtRulePrelude, CSSRule<Impl>>, ()> {
match_ignore_ascii_case! { name,
"media" => {
let media_queries = parse_media_query_list(input);
@ -455,7 +465,7 @@ impl<'a, 'b> AtRuleParser for NestedRuleParser<'a, 'b> {
}
}
fn parse_block(&self, prelude: AtRulePrelude, input: &mut Parser) -> Result<CSSRule, ()> {
fn parse_block(&self, prelude: AtRulePrelude, input: &mut Parser) -> Result<CSSRule<Impl>, ()> {
match prelude {
AtRulePrelude::FontFace => {
parse_font_face_block(self.context, input).map(CSSRule::FontFace)
@ -474,15 +484,15 @@ impl<'a, 'b> AtRuleParser for NestedRuleParser<'a, 'b> {
}
impl<'a, 'b> QualifiedRuleParser for NestedRuleParser<'a, 'b> {
type Prelude = Vec<Selector<ServoSelectorImpl>>;
type QualifiedRule = CSSRule;
impl<'a, 'b, Impl: SelectorImpl> QualifiedRuleParser for NestedRuleParser<'a, 'b, Impl> {
type Prelude = Vec<Selector<Impl>>;
type QualifiedRule = CSSRule<Impl>;
fn parse_prelude(&self, input: &mut Parser) -> Result<Vec<Selector<ServoSelectorImpl>>, ()> {
fn parse_prelude(&self, input: &mut Parser) -> Result<Vec<Selector<Impl>>, ()> {
parse_selector_list(&self.context.selector_context, input)
}
fn parse_block(&self, prelude: Vec<Selector<ServoSelectorImpl>>, input: &mut Parser) -> Result<CSSRule, ()> {
fn parse_block(&self, prelude: Vec<Selector<Impl>>, input: &mut Parser) -> Result<CSSRule<Impl>, ()> {
Ok(CSSRule::Style(StyleRule {
selectors: prelude,
declarations: parse_property_declaration_list(self.context, input)

View file

@ -5,6 +5,8 @@
use context::{SharedStyleContext, StyleContext};
use dom::{OpaqueNode, TNode, TRestyleDamage, UnsafeNode};
use matching::{ApplicableDeclarations, ElementMatchMethods, MatchMethods, StyleSharingResult};
use selector_impl::SelectorImplExt;
use selectors::Element;
use selectors::bloom::BloomFilter;
use std::cell::RefCell;
use util::opts;
@ -41,9 +43,9 @@ thread_local!(
///
/// If one does not exist, a new one will be made for you. If it is out of date,
/// it will be cleared and reused.
fn take_thread_local_bloom_filter<'ln, N>(parent_node: Option<N>,
fn take_thread_local_bloom_filter<'ln, N, Impl: SelectorImplExt>(parent_node: Option<N>,
root: OpaqueNode,
context: &SharedStyleContext)
context: &SharedStyleContext<Impl>)
-> Box<BloomFilter>
where N: TNode<'ln> {
STYLE_BLOOM.with(|style_bloom| {
@ -77,9 +79,9 @@ fn take_thread_local_bloom_filter<'ln, N>(parent_node: Option<N>,
})
}
pub fn put_thread_local_bloom_filter(bf: Box<BloomFilter>,
pub fn put_thread_local_bloom_filter<Impl: SelectorImplExt>(bf: Box<BloomFilter>,
unsafe_node: &UnsafeNode,
context: &SharedStyleContext) {
context: &SharedStyleContext<Impl>) {
STYLE_BLOOM.with(move |style_bloom| {
assert!(style_bloom.borrow().is_none(),
"Putting into a never-taken thread-local bloom filter");
@ -117,7 +119,12 @@ pub trait DomTraversalContext<'ln, N: TNode<'ln>> {
/// layout computation. This computes the styles applied to each node.
#[inline]
#[allow(unsafe_code)]
pub fn recalc_style_at<'a, 'ln, N: TNode<'ln>, C: StyleContext<'a>> (context: &'a C, root: OpaqueNode, node: N) {
pub fn recalc_style_at<'a, 'ln, N, C>(context: &'a C,
root: OpaqueNode,
node: N)
where N: TNode<'ln>,
C: StyleContext<'a, <N::ConcreteElement as Element>::Impl>,
<N::ConcreteElement as Element>::Impl: SelectorImplExt + 'a {
// Initialize layout data.
//
// FIXME(pcwalton): Stop allocating here. Ideally this should just be done by the HTML

View file

@ -22,7 +22,7 @@ lazy_static = "0.1.10"
log = "0.3"
num = "0.1.24"
rustc-serialize = "0.3"
selectors = {version = "0.4.2", features = ["heap_size"]}
selectors = {version = "0.5", features = ["heap_size"]}
serde = "0.6"
serde_macros = "0.6"
url = {version = "0.5.5", features = ["heap_size"]}

View file

@ -41,7 +41,7 @@ num = "0.1.24"
num_cpus = "0.2.2"
rand = "0.3"
rustc-serialize = "0.3"
selectors = {version = "0.4.2", features = ["heap_size"]}
selectors = {version = "0.5", features = ["heap_size"]}
serde = "0.6"
serde_macros = "0.6"
smallvec = "0.1"

12
ports/cef/Cargo.lock generated
View file

@ -934,7 +934,7 @@ dependencies = [
"rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
"script 0.0.1",
"script_traits 0.0.1",
"selectors 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"selectors 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_macros 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1477,7 +1477,7 @@ dependencies = [
"ref_slice 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
"script_traits 0.0.1",
"selectors 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"selectors 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"string_cache 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1519,7 +1519,7 @@ dependencies = [
[[package]]
name = "selectors"
version = "0.4.2"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1763,7 +1763,7 @@ dependencies = [
"num 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)",
"plugins 0.0.1",
"rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
"selectors 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"selectors 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_macros 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1787,7 +1787,7 @@ dependencies = [
"num 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)",
"plugins 0.0.1",
"rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
"selectors 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"selectors 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_macros 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"url 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1945,7 +1945,7 @@ dependencies = [
"plugins 0.0.1",
"rand 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
"selectors 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"selectors 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_macros 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",

View file

@ -6,10 +6,14 @@ dependencies = [
"bitflags 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"cssparser 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
"euclid 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize_plugin 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
"selectors 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"plugins 0.0.1",
"selectors 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"string_cache 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
"style 0.0.1",
@ -312,7 +316,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "selectors"
version = "0.4.2"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
@ -389,7 +393,7 @@ dependencies = [
"num 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)",
"plugins 0.0.1",
"rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
"selectors 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"selectors 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_macros 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
@ -413,7 +417,7 @@ dependencies = [
"num 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)",
"plugins 0.0.1",
"rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
"selectors 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"selectors 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_macros 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"url 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
@ -492,7 +496,7 @@ dependencies = [
"plugins 0.0.1",
"rand 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
"selectors 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"selectors 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_macros 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",

View file

@ -13,14 +13,20 @@ app_units = {version = "0.2.1", features = ["plugins"]}
bitflags = "0.3"
cssparser = {version = "0.5.3", features = ["heap_size", "serde-serialization"]}
euclid = {version = "0.6.2", features = ["plugins"]}
heapsize = "0.3.0"
heapsize_plugin = "0.1.2"
lazy_static = "0.1"
libc = "0.2"
log = "0.3"
num_cpus = "0.2.2"
selectors = {version = "0.4.2", features = ["heap_size"]}
selectors = {version = "0.5", features = ["heap_size"]}
smallvec = "0.1"
string_cache = {version = "0.2.9", features = ["heap_size"]}
url = {version = "0.5.5", features = ["heap_size"]}
[dependencies.plugins]
path = "../../components/plugins"
[dependencies.util]
path = "../../components/util"

View file

@ -6,17 +6,15 @@ use bindings::ServoStyleSetData;
use euclid::Size2D;
use euclid::size::TypedSize2D;
use num_cpus;
use selector_impl::{Stylist, Stylesheet, SharedStyleContext};
use std::cmp;
use std::collections::HashMap;
use std::sync::mpsc::{channel, Receiver, Sender};
use std::sync::{Arc, RwLock};
use style::animation::Animation;
use style::context::SharedStyleContext;
use style::dom::OpaqueNode;
use style::media_queries::{Device, MediaType};
use style::parallel::WorkQueueData;
use style::selector_matching::Stylist;
use style::stylesheets::Stylesheet;
use util::geometry::ViewportPx;
use util::thread_state;
use util::workqueue::WorkQueue;

View file

@ -9,15 +9,16 @@ use bindings::RawGeckoDocument;
use bindings::{ServoArcStyleSheet, ServoNodeData, ServoStyleSetData, uint8_t, uint32_t};
use data::PerDocumentStyleData;
use euclid::Size2D;
use selector_impl::{SharedStyleContext, Stylesheet};
use std::mem::{forget, transmute};
use std::slice;
use std::str::from_utf8_unchecked;
use std::sync::{Arc, Mutex};
use style::context::{ReflowGoal, SharedStyleContext, StylistWrapper};
use style::context::{ReflowGoal, StylistWrapper};
use style::dom::{TDocument, TNode};
use style::error_reporting::StdoutErrorReporter;
use style::parallel;
use style::stylesheets::{Origin, Stylesheet};
use style::stylesheets::Origin;
use traversal::RecalcStyleOnly;
use url::Url;
use util::arc_ptr_eq;

View file

@ -5,13 +5,24 @@
#![feature(as_unsafe_cell)]
#![feature(box_syntax)]
#![feature(ptr_as_ref)]
#![feature(custom_derive)]
#![feature(plugin)]
#![plugin(heapsize_plugin)]
#![plugin(plugins)]
extern crate app_units;
#[macro_use]
extern crate bitflags;
#[macro_use]
extern crate cssparser;
extern crate euclid;
extern crate heapsize;
#[macro_use]
extern crate lazy_static;
extern crate libc;
#[macro_use]
extern crate log;
extern crate num_cpus;
extern crate selectors;
extern crate smallvec;
@ -26,5 +37,6 @@ mod bindings;
mod data;
#[allow(non_snake_case)]
pub mod glue;
mod selector_impl;
mod traversal;
mod wrapper;

View file

@ -0,0 +1,307 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use selectors::parser::{ParserContext, SelectorImpl};
use std::process;
use style;
use style::element_state::ElementState;
use style::error_reporting::StdoutErrorReporter;
use style::selector_impl::SelectorImplExt;
use style::stylesheets::Origin;
use url::Url;
use util::resource_files::read_resource_file;
pub type Stylist = style::selector_matching::Stylist<GeckoSelectorImpl>;
pub type Stylesheet = style::stylesheets::Stylesheet<GeckoSelectorImpl>;
pub type SharedStyleContext = style::context::SharedStyleContext<GeckoSelectorImpl>;
pub type PrivateStyleData = style::data::PrivateStyleData<GeckoSelectorImpl>;
pub struct GeckoSelectorImpl;
// TODO: Replace this with Gecko's stylesheets
lazy_static! {
static ref USER_OR_USER_AGENT_STYLESHEETS: Vec<Stylesheet> = {
let mut stylesheets = vec!();
// FIXME: presentational-hints.css should be at author origin with zero specificity.
// (Does it make a difference?)
for &filename in &["user-agent.css", "servo.css", "presentational-hints.css"] {
match read_resource_file(&[filename]) {
Ok(res) => {
let ua_stylesheet = Stylesheet::from_bytes(
&res,
Url::parse(&format!("chrome:///{:?}", filename)).unwrap(),
None,
None,
Origin::UserAgent,
box StdoutErrorReporter);
stylesheets.push(ua_stylesheet);
}
Err(..) => {
error!("Failed to load UA stylesheet {}!", filename);
process::exit(1);
}
}
}
stylesheets
};
}
lazy_static! {
static ref QUIRKS_MODE_STYLESHEET: Stylesheet = {
match read_resource_file(&["quirks-mode.css"]) {
Ok(res) => {
Stylesheet::from_bytes(
&res,
url!("chrome:///quirks-mode.css"),
None,
None,
Origin::UserAgent,
box StdoutErrorReporter)
},
Err(..) => {
error!("Stylist failed to load 'quirks-mode.css'!");
process::exit(1);
}
}
};
}
#[derive(Clone, Debug, PartialEq, Eq, HeapSizeOf, Hash)]
pub enum PseudoElement {
Before,
After,
FirstLine,
// TODO: Probably a few more are missing here
// https://mxr.mozilla.org/mozilla-central/source/layout/style/nsCSSAnonBoxList.h
MozNonElement,
MozAnonymousBlock,
MozAnonymousPositionedBlock,
MozMathMLAnonymousBlock,
MozXULAnonymousBlock,
MozHorizontalFramesetBorder,
MozVerticalFramesetBorder,
MozLineFrame,
MozButtonContent,
MozButtonLabel,
MozCellContent,
MozDropdownList,
MozFieldsetContent,
MozFramesetBlank,
MozDisplayComboboxControlFrame,
MozHTMLCanvasContent,
MozInlineTable,
MozTable,
MozTableCell,
MozTableColumnGroup,
MozTableColumn,
MozTableOuter,
MozTableRowGroup,
MozTableRow,
MozCanvas,
MozPageBreak,
MozPage,
MozPageContent,
MozPageSequence,
MozScrolledContent,
MozScrolledCanvas,
MozScrolledPageSequence,
MozColumnContent,
MozViewport,
MozViewportScroll,
MozAnonymousFlexItem,
MozAnonymousGridItem,
MozRuby,
MozRubyBase,
MozRubyBaseContainer,
MozRubyText,
MozRubyTextContainer,
MozTreeColumn,
MozTreeRow,
MozTreeSeparator,
MozTreeCell,
MozTreeIndentation,
MozTreeLine,
MozTreeTwisty,
MozTreeImage,
MozTreeCellText,
MozTreeCheckbox,
MozTreeProgressMeter,
MozTreeDropFeedback,
MozSVGMarkerAnonChild,
MozSVGOuterSVGAnonChild,
MozSVGForeignContent,
MozSVGText,
}
#[derive(Clone, Debug, PartialEq, Eq, HeapSizeOf, Hash)]
pub enum NonTSPseudoClass {
AnyLink,
Link,
Visited,
Active,
Focus,
Hover,
Enabled,
Disabled,
Checked,
Indeterminate,
}
impl NonTSPseudoClass {
pub fn state_flag(&self) -> ElementState {
use self::NonTSPseudoClass::*;
use style::element_state::*;
match *self {
Active => IN_ACTIVE_STATE,
Focus => IN_FOCUS_STATE,
Hover => IN_HOVER_STATE,
Enabled => IN_ENABLED_STATE,
Disabled => IN_DISABLED_STATE,
Checked => IN_CHECKED_STATE,
Indeterminate => IN_INDETERMINATE_STATE,
AnyLink |
Link |
Visited => ElementState::empty(),
}
}
}
impl SelectorImpl for GeckoSelectorImpl {
type PseudoElement = PseudoElement;
type NonTSPseudoClass = NonTSPseudoClass;
fn parse_non_ts_pseudo_class(_context: &ParserContext,
name: &str) -> Result<NonTSPseudoClass, ()> {
use self::NonTSPseudoClass::*;
let pseudo_class = match_ignore_ascii_case! { name,
"any-link" => AnyLink,
"link" => Link,
"visited" => Visited,
"active" => Active,
"focus" => Focus,
"hover" => Hover,
"enabled" => Enabled,
"disabled" => Disabled,
"checked" => Checked,
"indeterminate" => Indeterminate,
_ => return Err(())
};
Ok(pseudo_class)
}
fn parse_pseudo_element(_context: &ParserContext,
name: &str) -> Result<PseudoElement, ()> {
use self::PseudoElement::*;
let pseudo_element = match_ignore_ascii_case! { name,
"before" => Before,
"after" => After,
"first-line" => FirstLine,
"-moz-non-element" => MozNonElement,
"-moz-anonymous-block" => MozAnonymousBlock,
"-moz-anonymous-positioned-block" => MozAnonymousPositionedBlock,
"-moz-mathml-anonymous-block" => MozMathMLAnonymousBlock,
"-moz-xul-anonymous-block" => MozXULAnonymousBlock,
"-moz-hframeset-border" => MozHorizontalFramesetBorder,
"-moz-vframeset-border" => MozVerticalFramesetBorder,
"-moz-line-frame" => MozLineFrame,
"-moz-button-content" => MozButtonContent,
"-moz-buttonlabel" => MozButtonLabel,
"-moz-cell-content" => MozCellContent,
"-moz-dropdown-list" => MozDropdownList,
"-moz-fieldset-content" => MozFieldsetContent,
"-moz-frameset-blank" => MozFramesetBlank,
"-moz-display-comboboxcontrol-frame" => MozDisplayComboboxControlFrame,
"-moz-html-canvas-content" => MozHTMLCanvasContent,
"-moz-inline-table" => MozInlineTable,
"-moz-table" => MozTable,
"-moz-table-cell" => MozTableCell,
"-moz-table-column-group" => MozTableColumnGroup,
"-moz-table-column" => MozTableColumn,
"-moz-table-outer" => MozTableOuter,
"-moz-table-row-group" => MozTableRowGroup,
"-moz-table-row" => MozTableRow,
"-moz-canvas" => MozCanvas,
"-moz-pagebreak" => MozPageBreak,
"-moz-page" => MozPage,
"-moz-pagecontent" => MozPageContent,
"-moz-page-sequence" => MozPageSequence,
"-moz-scrolled-content" => MozScrolledContent,
"-moz-scrolled-canvas" => MozScrolledCanvas,
"-moz-scrolled-page-sequence" => MozScrolledPageSequence,
"-moz-column-content" => MozColumnContent,
"-moz-viewport" => MozViewport,
"-moz-viewport-scroll" => MozViewportScroll,
"-moz-anonymous-flex-item" => MozAnonymousFlexItem,
"-moz-anonymous-grid-item" => MozAnonymousGridItem,
"-moz-ruby" => MozRuby,
"-moz-ruby-base" => MozRubyBase,
"-moz-ruby-base-container" => MozRubyBaseContainer,
"-moz-ruby-text" => MozRubyText,
"-moz-ruby-text-container" => MozRubyTextContainer,
"-moz-tree-column" => MozTreeColumn,
"-moz-tree-row" => MozTreeRow,
"-moz-tree-separator" => MozTreeSeparator,
"-moz-tree-cell" => MozTreeCell,
"-moz-tree-indentation" => MozTreeIndentation,
"-moz-tree-line" => MozTreeLine,
"-moz-tree-twisty" => MozTreeTwisty,
"-moz-tree-image" => MozTreeImage,
"-moz-tree-cell-text" => MozTreeCellText,
"-moz-tree-checkbox" => MozTreeCheckbox,
"-moz-tree-progressmeter" => MozTreeProgressMeter,
"-moz-tree-drop-feedback" => MozTreeDropFeedback,
"-moz-svg-marker-anon-child" => MozSVGMarkerAnonChild,
"-moz-svg-outer-svg-anon-child" => MozSVGOuterSVGAnonChild,
"-moz-svg-foreign-content" => MozSVGForeignContent,
"-moz-svg-text" => MozSVGText,
_ => return Err(())
};
Ok(pseudo_element)
}
}
impl SelectorImplExt for GeckoSelectorImpl {
#[inline]
fn each_eagerly_cascaded_pseudo_element<F>(mut fun: F)
where F: FnMut(PseudoElement) {
fun(PseudoElement::Before);
fun(PseudoElement::After);
// TODO: probably a lot more are missing here
}
#[inline]
fn pseudo_class_state_flag(pc: &NonTSPseudoClass) -> ElementState {
pc.state_flag()
}
// FIXME: Don't use Servo's UA stylesheets, use Gecko's instead
#[inline]
fn get_user_or_user_agent_stylesheets() -> &'static [Stylesheet] {
&*USER_OR_USER_AGENT_STYLESHEETS
}
#[inline]
fn get_quirks_mode_stylesheet() -> &'static Stylesheet {
&*QUIRKS_MODE_STYLESHEET
}
}

View file

@ -2,10 +2,11 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use selector_impl::{GeckoSelectorImpl, SharedStyleContext};
use std::cell::RefCell;
use std::mem;
use std::rc::Rc;
use style::context::{LocalStyleContext, SharedStyleContext, StyleContext};
use style::context::{LocalStyleContext, StyleContext};
use style::dom::{OpaqueNode, TNode};
use style::matching::{ApplicableDeclarationsCache, StyleSharingCandidateCache};
use style::traversal::{DomTraversalContext, recalc_style_at};
@ -48,7 +49,7 @@ impl<'a> StandaloneStyleContext<'a> {
}
}
impl<'a> StyleContext<'a> for StandaloneStyleContext<'a> {
impl<'a> StyleContext<'a, GeckoSelectorImpl> for StandaloneStyleContext<'a> {
fn shared_context(&self) -> &'a SharedStyleContext {
&self.shared
}
@ -63,7 +64,8 @@ pub struct RecalcStyleOnly<'lc> {
root: OpaqueNode,
}
impl<'lc, 'ln, N: TNode<'ln>> DomTraversalContext<'ln, N> for RecalcStyleOnly<'lc> {
impl<'lc, 'ln, N: TNode<'ln>> DomTraversalContext<'ln, N> for RecalcStyleOnly<'lc>
where N::ConcreteElement: ::selectors::Element<Impl=GeckoSelectorImpl> {
type SharedContext = SharedStyleContext;
#[allow(unsafe_code)]
fn new<'a>(shared: &'a Self::SharedContext, root: OpaqueNode) -> Self {

View file

@ -19,6 +19,8 @@ use bindings::{Gecko_LocalName, Gecko_Namespace, Gecko_NodeIsElement, Gecko_SetN
use bindings::{RawGeckoDocument, RawGeckoElement, RawGeckoNode};
use bindings::{ServoNodeData};
use libc::uintptr_t;
use selector_impl::{GeckoSelectorImpl, NonTSPseudoClass, PrivateStyleData};
use selectors::Element;
use selectors::matching::DeclarationBlock;
use selectors::parser::{AttrSelector, NamespaceConstraint};
use smallvec::VecLike;
@ -29,7 +31,6 @@ use std::slice;
use std::str::from_utf8_unchecked;
use std::sync::Arc;
use string_cache::{Atom, Namespace};
use style::data::PrivateStyleData;
use style::dom::{OpaqueNode, TDocument, TElement, TNode, TRestyleDamage, UnsafeNode};
use style::element_state::ElementState;
#[allow(unused_imports)] // Used in commented-out code.
@ -38,7 +39,7 @@ use style::properties::{ComputedValues, PropertyDeclaration, PropertyDeclaration
#[allow(unused_imports)] // Used in commented-out code.
use style::properties::{parse_style_attribute};
use style::restyle_hints::ElementSnapshot;
use style::selector_impl::{NonTSPseudoClass, ServoSelectorImpl};
use style::selector_impl::ElementExt;
#[allow(unused_imports)] // Used in commented-out code.
use url::Url;
@ -357,7 +358,7 @@ impl<'le> TElement<'le> for GeckoElement<'le> {
}
impl<'le> ::selectors::Element for GeckoElement<'le> {
type Impl = ServoSelectorImpl;
type Impl = GeckoSelectorImpl;
fn parent_element(&self) -> Option<Self> {
unsafe {
@ -427,11 +428,6 @@ impl<'le> ::selectors::Element for GeckoElement<'le> {
NonTSPseudoClass::Link => unsafe { Gecko_IsLink(self.element) != 0 },
NonTSPseudoClass::AnyLink => unsafe { Gecko_IsUnvisitedLink(self.element) != 0 },
NonTSPseudoClass::Visited => unsafe { Gecko_IsVisitedLink(self.element) != 0 },
NonTSPseudoClass::ServoNonZeroBorder => {
unimplemented!()
},
NonTSPseudoClass::Active |
NonTSPseudoClass::Focus |
NonTSPseudoClass::Hover |
@ -489,6 +485,12 @@ impl<'le> ::selectors::Element for GeckoElement<'le> {
}
}
impl<'le> ElementExt for GeckoElement<'le> {
fn is_link(&self) -> bool {
self.match_non_ts_pseudo_class(NonTSPseudoClass::AnyLink)
}
}
unsafe fn reinterpret_string<'a>(ptr: *const ::libc::c_char, length: u32) -> Option<&'a str> {
(ptr as *const u8).as_ref().map(|p| from_utf8_unchecked(slice::from_raw_parts(p, length as usize)))
}

12
ports/gonk/Cargo.lock generated
View file

@ -916,7 +916,7 @@ dependencies = [
"rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
"script 0.0.1",
"script_traits 0.0.1",
"selectors 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"selectors 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_macros 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1459,7 +1459,7 @@ dependencies = [
"ref_slice 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
"script_traits 0.0.1",
"selectors 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"selectors 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"string_cache 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1501,7 +1501,7 @@ dependencies = [
[[package]]
name = "selectors"
version = "0.4.2"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1743,7 +1743,7 @@ dependencies = [
"num 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)",
"plugins 0.0.1",
"rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
"selectors 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"selectors 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_macros 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1767,7 +1767,7 @@ dependencies = [
"num 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)",
"plugins 0.0.1",
"rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
"selectors 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"selectors 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_macros 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"url 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1925,7 +1925,7 @@ dependencies = [
"plugins 0.0.1",
"rand 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
"selectors 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"selectors 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_macros 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",

View file

@ -27,6 +27,6 @@ path = "../../../components/util"
app_units = {version = "0.2.1", features = ["plugins"]}
cssparser = {version = "0.5.3", features = ["heap_size"]}
euclid = {version = "0.6.2", features = ["plugins"]}
selectors = {version = "0.4.2", features = ["heap_size"]}
selectors = {version = "0.5", features = ["heap_size"]}
string_cache = {version = "0.2.9", features = ["heap_size"]}
url = {version = "0.5.5", features = ["heap_size"]}

View file

@ -8,7 +8,8 @@ use euclid::size::Size2D;
use std::borrow::ToOwned;
use style::error_reporting::ParseErrorReporter;
use style::media_queries::*;
use style::stylesheets::{Origin, Stylesheet, CSSRuleIteratorExt};
use style::servo::Stylesheet;
use style::stylesheets::{Origin, CSSRuleIteratorExt};
use style::values::specified;
pub struct CSSErrorReporterTest;

View file

@ -10,8 +10,9 @@ use std::sync::Arc;
use std::sync::Mutex;
use string_cache::Atom;
use style::properties::{PropertyDeclaration, PropertyDeclarationBlock, DeclaredValue, longhands};
use style::stylesheets::{CSSRule, StyleRule, Origin, Stylesheet};
use style::stylesheets::{CSSRule, StyleRule, Origin};
use style::error_reporting::ParseErrorReporter;
use style::servo::Stylesheet;
#[test]
fn test_parse_stylesheet() {

View file

@ -9,7 +9,8 @@ use media_queries::CSSErrorReporterTest;
use style::error_reporting::ParseErrorReporter;
use style::media_queries::{Device, MediaType};
use style::parser::ParserContext;
use style::stylesheets::{Origin, Stylesheet, CSSRuleIteratorExt};
use style::servo::Stylesheet;
use style::stylesheets::{Origin, CSSRuleIteratorExt};
use style::values::specified::Length::{self, ViewportPercentage};
use style::values::specified::LengthOrPercentageOrAuto::{self, Auto};
use style::values::specified::ViewportPercentageLength::Vw;