mirror of
https://github.com/servo/servo.git
synced 2025-07-23 07:13:52 +01:00
Move ServoSelectorImpl to a dedicated module.
This commit is contained in:
parent
2f967893f3
commit
b2a7e44373
7 changed files with 269 additions and 249 deletions
|
@ -107,8 +107,8 @@ use style::media_queries::{Device, MediaType};
|
||||||
use style::parallel::WorkQueueData;
|
use style::parallel::WorkQueueData;
|
||||||
use style::properties::ComputedValues;
|
use style::properties::ComputedValues;
|
||||||
use style::refcell::RefCell;
|
use style::refcell::RefCell;
|
||||||
use style::selector_matching::USER_OR_USER_AGENT_STYLESHEETS;
|
|
||||||
use style::servo::{Animation, LocalStyleContextCreationInfo, SharedStyleContext, Stylesheet, Stylist};
|
use style::servo::{Animation, LocalStyleContextCreationInfo, SharedStyleContext, Stylesheet, Stylist};
|
||||||
|
use style::servo_selector_impl::USER_OR_USER_AGENT_STYLESHEETS;
|
||||||
use style::stylesheets::CSSRuleIteratorExt;
|
use style::stylesheets::CSSRuleIteratorExt;
|
||||||
use style::workqueue::WorkQueue;
|
use style::workqueue::WorkQueue;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
|
@ -97,6 +97,7 @@ pub mod selector_impl;
|
||||||
pub mod selector_matching;
|
pub mod selector_matching;
|
||||||
pub mod sequential;
|
pub mod sequential;
|
||||||
pub mod servo;
|
pub mod servo;
|
||||||
|
pub mod servo_selector_impl;
|
||||||
pub mod sink;
|
pub mod sink;
|
||||||
pub mod str;
|
pub mod str;
|
||||||
pub mod stylesheets;
|
pub mod stylesheets;
|
||||||
|
|
|
@ -5,13 +5,21 @@
|
||||||
//! The pseudo-classes and pseudo-elements supported by the style system.
|
//! The pseudo-classes and pseudo-elements supported by the style system.
|
||||||
|
|
||||||
use element_state::ElementState;
|
use element_state::ElementState;
|
||||||
use properties::{self, ServoComputedValues};
|
use properties;
|
||||||
use selector_matching::{USER_OR_USER_AGENT_STYLESHEETS, QUIRKS_MODE_STYLESHEET};
|
|
||||||
use selectors::Element;
|
use selectors::Element;
|
||||||
use selectors::parser::{ParserContext, SelectorImpl};
|
use selectors::parser::SelectorImpl;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use stylesheets::Stylesheet;
|
use stylesheets::Stylesheet;
|
||||||
|
|
||||||
|
#[cfg(feature = "servo")]
|
||||||
|
pub use servo_selector_impl::ServoSelectorImpl;
|
||||||
|
|
||||||
|
#[cfg(feature = "servo")]
|
||||||
|
pub use servo_selector_impl::{ServoSelectorImpl as TheSelectorImpl, PseudoElement, NonTSPseudoClass};
|
||||||
|
|
||||||
|
#[cfg(feature = "gecko")]
|
||||||
|
pub use gecko_selector_impl::{GeckoSelectorImpl as TheSelectorImpl, PseudoElement, NonTSPseudoClass};
|
||||||
|
|
||||||
/// This function determines if a pseudo-element is eagerly cascaded or not.
|
/// This function determines if a pseudo-element is eagerly cascaded or not.
|
||||||
///
|
///
|
||||||
/// Eagerly cascaded pseudo-elements are "normal" pseudo-elements (i.e.
|
/// Eagerly cascaded pseudo-elements are "normal" pseudo-elements (i.e.
|
||||||
|
@ -101,186 +109,3 @@ pub trait SelectorImplExt : SelectorImpl + Clone + Debug + Sized + 'static {
|
||||||
|
|
||||||
fn get_quirks_mode_stylesheet() -> Option<&'static Stylesheet<Self>>;
|
fn get_quirks_mode_stylesheet() -> Option<&'static Stylesheet<Self>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
|
||||||
pub enum PseudoElement {
|
|
||||||
Before,
|
|
||||||
After,
|
|
||||||
Selection,
|
|
||||||
DetailsSummary,
|
|
||||||
DetailsContent,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PseudoElement {
|
|
||||||
#[inline]
|
|
||||||
pub fn is_before_or_after(&self) -> bool {
|
|
||||||
match *self {
|
|
||||||
PseudoElement::Before |
|
|
||||||
PseudoElement::After => true,
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn cascade_type(&self) -> PseudoElementCascadeType {
|
|
||||||
match *self {
|
|
||||||
PseudoElement::Before |
|
|
||||||
PseudoElement::After |
|
|
||||||
PseudoElement::Selection => PseudoElementCascadeType::Eager,
|
|
||||||
PseudoElement::DetailsSummary => PseudoElementCascadeType::Lazy,
|
|
||||||
PseudoElement::DetailsContent => PseudoElementCascadeType::Precomputed,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
|
||||||
pub enum NonTSPseudoClass {
|
|
||||||
AnyLink,
|
|
||||||
Link,
|
|
||||||
Visited,
|
|
||||||
Active,
|
|
||||||
Focus,
|
|
||||||
Hover,
|
|
||||||
Enabled,
|
|
||||||
Disabled,
|
|
||||||
Checked,
|
|
||||||
Indeterminate,
|
|
||||||
ServoNonZeroBorder,
|
|
||||||
ReadWrite,
|
|
||||||
ReadOnly,
|
|
||||||
PlaceholderShown,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl NonTSPseudoClass {
|
|
||||||
pub fn state_flag(&self) -> ElementState {
|
|
||||||
use element_state::*;
|
|
||||||
use self::NonTSPseudoClass::*;
|
|
||||||
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,
|
|
||||||
ReadOnly | ReadWrite => IN_READ_WRITE_STATE,
|
|
||||||
PlaceholderShown => IN_PLACEHOLDER_SHOWN_STATE,
|
|
||||||
|
|
||||||
AnyLink |
|
|
||||||
Link |
|
|
||||||
Visited |
|
|
||||||
ServoNonZeroBorder => ElementState::empty(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
|
||||||
pub struct ServoSelectorImpl;
|
|
||||||
|
|
||||||
impl SelectorImpl for ServoSelectorImpl {
|
|
||||||
type AttrString = String;
|
|
||||||
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,
|
|
||||||
"read-write" => ReadWrite,
|
|
||||||
"read-only" => ReadOnly,
|
|
||||||
"placeholder-shown" => PlaceholderShown,
|
|
||||||
"-servo-nonzero-border" => {
|
|
||||||
if !context.in_user_agent_stylesheet {
|
|
||||||
return Err(());
|
|
||||||
}
|
|
||||||
ServoNonZeroBorder
|
|
||||||
},
|
|
||||||
_ => 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,
|
|
||||||
"selection" => Selection,
|
|
||||||
"-servo-details-summary" => {
|
|
||||||
if !context.in_user_agent_stylesheet {
|
|
||||||
return Err(())
|
|
||||||
}
|
|
||||||
DetailsSummary
|
|
||||||
},
|
|
||||||
"-servo-details-content" => {
|
|
||||||
if !context.in_user_agent_stylesheet {
|
|
||||||
return Err(())
|
|
||||||
}
|
|
||||||
DetailsContent
|
|
||||||
},
|
|
||||||
_ => return Err(())
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(pseudo_element)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SelectorImplExt for ServoSelectorImpl {
|
|
||||||
type ComputedValues = ServoComputedValues;
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn pseudo_element_cascade_type(pseudo: &PseudoElement) -> PseudoElementCascadeType {
|
|
||||||
pseudo.cascade_type()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn each_pseudo_element<F>(mut fun: F)
|
|
||||||
where F: FnMut(PseudoElement) {
|
|
||||||
fun(PseudoElement::Before);
|
|
||||||
fun(PseudoElement::After);
|
|
||||||
fun(PseudoElement::DetailsContent);
|
|
||||||
fun(PseudoElement::DetailsSummary);
|
|
||||||
fun(PseudoElement::Selection);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn pseudo_class_state_flag(pc: &NonTSPseudoClass) -> ElementState {
|
|
||||||
pc.state_flag()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn pseudo_is_before_or_after(pseudo: &PseudoElement) -> bool {
|
|
||||||
pseudo.is_before_or_after()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn get_user_or_user_agent_stylesheets() -> &'static [Stylesheet<Self>] {
|
|
||||||
&*USER_OR_USER_AGENT_STYLESHEETS
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn get_quirks_mode_stylesheet() -> Option<&'static Stylesheet<Self>> {
|
|
||||||
Some(&*QUIRKS_MODE_STYLESHEET)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<E: Element<Impl=ServoSelectorImpl, AttrString=String>> ElementExt for E {
|
|
||||||
fn is_link(&self) -> bool {
|
|
||||||
self.match_non_ts_pseudo_class(NonTSPseudoClass::AnyLink)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -9,10 +9,9 @@ use element_state::*;
|
||||||
use error_reporting::StdoutErrorReporter;
|
use error_reporting::StdoutErrorReporter;
|
||||||
use keyframes::KeyframesAnimation;
|
use keyframes::KeyframesAnimation;
|
||||||
use media_queries::{Device, MediaType};
|
use media_queries::{Device, MediaType};
|
||||||
use parser::ParserContextExtraData;
|
|
||||||
use properties::{self, PropertyDeclaration, PropertyDeclarationBlock};
|
use properties::{self, PropertyDeclaration, PropertyDeclarationBlock};
|
||||||
use restyle_hints::{ElementSnapshot, RestyleHint, DependencySet};
|
use restyle_hints::{ElementSnapshot, RestyleHint, DependencySet};
|
||||||
use selector_impl::{SelectorImplExt, ServoSelectorImpl};
|
use selector_impl::SelectorImplExt;
|
||||||
use selectors::bloom::BloomFilter;
|
use selectors::bloom::BloomFilter;
|
||||||
use selectors::matching::DeclarationBlock as GenericDeclarationBlock;
|
use selectors::matching::DeclarationBlock as GenericDeclarationBlock;
|
||||||
use selectors::matching::{Rule, SelectorMap};
|
use selectors::matching::{Rule, SelectorMap};
|
||||||
|
@ -22,73 +21,15 @@ use sink::Push;
|
||||||
use smallvec::VecLike;
|
use smallvec::VecLike;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::hash::BuildHasherDefault;
|
use std::hash::BuildHasherDefault;
|
||||||
use std::process;
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use string_cache::Atom;
|
use string_cache::Atom;
|
||||||
use style_traits::viewport::ViewportConstraints;
|
use style_traits::viewport::ViewportConstraints;
|
||||||
use stylesheets::{CSSRule, CSSRuleIteratorExt, Origin, Stylesheet};
|
use stylesheets::{CSSRule, CSSRuleIteratorExt, Origin, Stylesheet};
|
||||||
use url::Url;
|
|
||||||
use util::opts;
|
|
||||||
use util::resource_files::read_resource_file;
|
|
||||||
use viewport::{MaybeNew, ViewportRuleCascade};
|
use viewport::{MaybeNew, ViewportRuleCascade};
|
||||||
|
|
||||||
|
|
||||||
pub type DeclarationBlock = GenericDeclarationBlock<Vec<PropertyDeclaration>>;
|
pub type DeclarationBlock = GenericDeclarationBlock<Vec<PropertyDeclaration>>;
|
||||||
|
|
||||||
lazy_static! {
|
|
||||||
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?)
|
|
||||||
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://resources/{:?}", filename)).unwrap(),
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
Origin::UserAgent,
|
|
||||||
Box::new(StdoutErrorReporter),
|
|
||||||
ParserContextExtraData::default());
|
|
||||||
stylesheets.push(ua_stylesheet);
|
|
||||||
}
|
|
||||||
Err(..) => {
|
|
||||||
error!("Failed to load UA stylesheet {}!", filename);
|
|
||||||
process::exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for &(ref contents, ref url) in &opts::get().user_stylesheets {
|
|
||||||
stylesheets.push(Stylesheet::from_bytes(
|
|
||||||
&contents, url.clone(), None, None, Origin::User, Box::new(StdoutErrorReporter),
|
|
||||||
ParserContextExtraData::default()));
|
|
||||||
}
|
|
||||||
stylesheets
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
lazy_static! {
|
|
||||||
pub static ref QUIRKS_MODE_STYLESHEET: Stylesheet<ServoSelectorImpl> = {
|
|
||||||
match read_resource_file("quirks-mode.css") {
|
|
||||||
Ok(res) => {
|
|
||||||
Stylesheet::from_bytes(
|
|
||||||
&res,
|
|
||||||
Url::parse("chrome://resources/quirks-mode.css").unwrap(),
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
Origin::UserAgent,
|
|
||||||
Box::new(StdoutErrorReporter),
|
|
||||||
ParserContextExtraData::default())
|
|
||||||
},
|
|
||||||
Err(..) => {
|
|
||||||
error!("Stylist failed to load 'quirks-mode.css'!");
|
|
||||||
process::exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// This structure holds all the selectors and device characteristics
|
/// This structure holds all the selectors and device characteristics
|
||||||
/// for a given document. The selectors are converted into `Rule`s
|
/// for a given document. The selectors are converted into `Rule`s
|
||||||
/// (defined in rust-selectors), and introduced in a `SelectorMap`
|
/// (defined in rust-selectors), and introduced in a `SelectorMap`
|
||||||
|
|
|
@ -7,8 +7,8 @@ use animation;
|
||||||
use context;
|
use context;
|
||||||
use data;
|
use data;
|
||||||
use properties::ServoComputedValues;
|
use properties::ServoComputedValues;
|
||||||
use selector_impl::ServoSelectorImpl;
|
|
||||||
use selector_matching;
|
use selector_matching;
|
||||||
|
use servo_selector_impl::ServoSelectorImpl;
|
||||||
use stylesheets;
|
use stylesheets;
|
||||||
|
|
||||||
pub type Stylesheet = stylesheets::Stylesheet<ServoSelectorImpl>;
|
pub type Stylesheet = stylesheets::Stylesheet<ServoSelectorImpl>;
|
||||||
|
|
253
components/style/servo_selector_impl.rs
Normal file
253
components/style/servo_selector_impl.rs
Normal file
|
@ -0,0 +1,253 @@
|
||||||
|
/* 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 element_state::ElementState;
|
||||||
|
use error_reporting::StdoutErrorReporter;
|
||||||
|
use parser::ParserContextExtraData;
|
||||||
|
use properties::ServoComputedValues;
|
||||||
|
use selector_impl::{SelectorImplExt, ElementExt, PseudoElementCascadeType};
|
||||||
|
use selectors::Element;
|
||||||
|
use selectors::parser::{ParserContext, SelectorImpl};
|
||||||
|
use std::process;
|
||||||
|
use stylesheets::{Stylesheet, Origin};
|
||||||
|
use url::Url;
|
||||||
|
use util::opts;
|
||||||
|
use util::resource_files::read_resource_file;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
pub enum PseudoElement {
|
||||||
|
Before,
|
||||||
|
After,
|
||||||
|
Selection,
|
||||||
|
DetailsSummary,
|
||||||
|
DetailsContent,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PseudoElement {
|
||||||
|
#[inline]
|
||||||
|
pub fn is_before_or_after(&self) -> bool {
|
||||||
|
match *self {
|
||||||
|
PseudoElement::Before |
|
||||||
|
PseudoElement::After => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn cascade_type(&self) -> PseudoElementCascadeType {
|
||||||
|
match *self {
|
||||||
|
PseudoElement::Before |
|
||||||
|
PseudoElement::After |
|
||||||
|
PseudoElement::Selection => PseudoElementCascadeType::Eager,
|
||||||
|
PseudoElement::DetailsSummary => PseudoElementCascadeType::Lazy,
|
||||||
|
PseudoElement::DetailsContent => PseudoElementCascadeType::Precomputed,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
pub enum NonTSPseudoClass {
|
||||||
|
AnyLink,
|
||||||
|
Link,
|
||||||
|
Visited,
|
||||||
|
Active,
|
||||||
|
Focus,
|
||||||
|
Hover,
|
||||||
|
Enabled,
|
||||||
|
Disabled,
|
||||||
|
Checked,
|
||||||
|
Indeterminate,
|
||||||
|
ServoNonZeroBorder,
|
||||||
|
ReadWrite,
|
||||||
|
ReadOnly,
|
||||||
|
PlaceholderShown,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NonTSPseudoClass {
|
||||||
|
pub fn state_flag(&self) -> ElementState {
|
||||||
|
use element_state::*;
|
||||||
|
use self::NonTSPseudoClass::*;
|
||||||
|
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,
|
||||||
|
ReadOnly | ReadWrite => IN_READ_WRITE_STATE,
|
||||||
|
PlaceholderShown => IN_PLACEHOLDER_SHOWN_STATE,
|
||||||
|
|
||||||
|
AnyLink |
|
||||||
|
Link |
|
||||||
|
Visited |
|
||||||
|
ServoNonZeroBorder => ElementState::empty(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
pub struct ServoSelectorImpl;
|
||||||
|
|
||||||
|
impl SelectorImpl for ServoSelectorImpl {
|
||||||
|
type AttrString = String;
|
||||||
|
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,
|
||||||
|
"read-write" => ReadWrite,
|
||||||
|
"read-only" => ReadOnly,
|
||||||
|
"placeholder-shown" => PlaceholderShown,
|
||||||
|
"-servo-nonzero-border" => {
|
||||||
|
if !context.in_user_agent_stylesheet {
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
ServoNonZeroBorder
|
||||||
|
},
|
||||||
|
_ => 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,
|
||||||
|
"selection" => Selection,
|
||||||
|
"-servo-details-summary" => {
|
||||||
|
if !context.in_user_agent_stylesheet {
|
||||||
|
return Err(())
|
||||||
|
}
|
||||||
|
DetailsSummary
|
||||||
|
},
|
||||||
|
"-servo-details-content" => {
|
||||||
|
if !context.in_user_agent_stylesheet {
|
||||||
|
return Err(())
|
||||||
|
}
|
||||||
|
DetailsContent
|
||||||
|
},
|
||||||
|
_ => return Err(())
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(pseudo_element)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SelectorImplExt for ServoSelectorImpl {
|
||||||
|
type ComputedValues = ServoComputedValues;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn pseudo_element_cascade_type(pseudo: &PseudoElement) -> PseudoElementCascadeType {
|
||||||
|
pseudo.cascade_type()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn each_pseudo_element<F>(mut fun: F)
|
||||||
|
where F: FnMut(PseudoElement) {
|
||||||
|
fun(PseudoElement::Before);
|
||||||
|
fun(PseudoElement::After);
|
||||||
|
fun(PseudoElement::DetailsContent);
|
||||||
|
fun(PseudoElement::DetailsSummary);
|
||||||
|
fun(PseudoElement::Selection);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn pseudo_class_state_flag(pc: &NonTSPseudoClass) -> ElementState {
|
||||||
|
pc.state_flag()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn pseudo_is_before_or_after(pseudo: &PseudoElement) -> bool {
|
||||||
|
pseudo.is_before_or_after()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn get_user_or_user_agent_stylesheets() -> &'static [Stylesheet<Self>] {
|
||||||
|
&*USER_OR_USER_AGENT_STYLESHEETS
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn get_quirks_mode_stylesheet() -> Option<&'static Stylesheet<Self>> {
|
||||||
|
Some(&*QUIRKS_MODE_STYLESHEET)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E: Element<Impl=ServoSelectorImpl, AttrString=String>> ElementExt for E {
|
||||||
|
fn is_link(&self) -> bool {
|
||||||
|
self.match_non_ts_pseudo_class(NonTSPseudoClass::AnyLink)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
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?)
|
||||||
|
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://resources/{:?}", filename)).unwrap(),
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
Origin::UserAgent,
|
||||||
|
Box::new(StdoutErrorReporter),
|
||||||
|
ParserContextExtraData::default());
|
||||||
|
stylesheets.push(ua_stylesheet);
|
||||||
|
}
|
||||||
|
Err(..) => {
|
||||||
|
error!("Failed to load UA stylesheet {}!", filename);
|
||||||
|
process::exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for &(ref contents, ref url) in &opts::get().user_stylesheets {
|
||||||
|
stylesheets.push(Stylesheet::from_bytes(
|
||||||
|
&contents, url.clone(), None, None, Origin::User, Box::new(StdoutErrorReporter),
|
||||||
|
ParserContextExtraData::default()));
|
||||||
|
}
|
||||||
|
stylesheets
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
pub static ref QUIRKS_MODE_STYLESHEET: Stylesheet<ServoSelectorImpl> = {
|
||||||
|
match read_resource_file("quirks-mode.css") {
|
||||||
|
Ok(res) => {
|
||||||
|
Stylesheet::from_bytes(
|
||||||
|
&res,
|
||||||
|
Url::parse("chrome://resources/quirks-mode.css").unwrap(),
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
Origin::UserAgent,
|
||||||
|
Box::new(StdoutErrorReporter),
|
||||||
|
ParserContextExtraData::default())
|
||||||
|
},
|
||||||
|
Err(..) => {
|
||||||
|
error!("Stylist failed to load 'quirks-mode.css'!");
|
||||||
|
process::exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
|
@ -139,7 +139,7 @@ that you didn't find it here so it can be added :)
|
||||||
[stylo]: https://public.etherpad-mozilla.org/p/stylo
|
[stylo]: https://public.etherpad-mozilla.org/p/stylo
|
||||||
[selector-impl]: http://doc.servo.org/selectors/parser/trait.SelectorImpl.html
|
[selector-impl]: http://doc.servo.org/selectors/parser/trait.SelectorImpl.html
|
||||||
[selector-impl-ext]: http://doc.servo.org/style/selector_impl/trait.SelectorImplExt.html
|
[selector-impl-ext]: http://doc.servo.org/style/selector_impl/trait.SelectorImplExt.html
|
||||||
[servo-selector-impl]: http://doc.servo.org/style/selector_impl/struct.ServoSelectorImpl.html
|
[servo-selector-impl]: http://doc.servo.org/style/servo_selector_impl/struct.ServoSelectorImpl.html
|
||||||
[tree-structural-pseudo-classes]: https://www.w3.org/TR/selectors4/#structural-pseudos
|
[tree-structural-pseudo-classes]: https://www.w3.org/TR/selectors4/#structural-pseudos
|
||||||
[style-dom-traits]: http://doc.servo.org/style/dom/index.html
|
[style-dom-traits]: http://doc.servo.org/style/dom/index.html
|
||||||
[layout-wrapper]: http://doc.servo.org/layout/wrapper/index.html
|
[layout-wrapper]: http://doc.servo.org/layout/wrapper/index.html
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue