mirror of
https://github.com/servo/servo.git
synced 2025-08-06 06:00:15 +01:00
Update to selectors 0.15
This commit is contained in:
parent
a89ba50180
commit
82b13d50e3
21 changed files with 215 additions and 146 deletions
|
@ -44,7 +44,7 @@ quickersort = "2.0.0"
|
|||
rand = "0.3"
|
||||
rayon = "0.5"
|
||||
rustc-serialize = "0.3"
|
||||
selectors = "0.14"
|
||||
selectors = "0.15"
|
||||
serde = {version = "0.8", optional = true}
|
||||
serde_derive = {version = "0.8", optional = true}
|
||||
servo_atoms = {path = "../atoms", optional = true}
|
||||
|
|
|
@ -4,14 +4,15 @@
|
|||
|
||||
use cssparser::ToCss;
|
||||
use element_state::ElementState;
|
||||
use selector_parser::{SelectorParser, PseudoElementCascadeType};
|
||||
use selector_parser::{attr_equals_selector_is_shareable, attr_exists_selector_is_shareable};
|
||||
use selector_parser::PseudoElementCascadeType;
|
||||
use selectors::parser::{AttrSelector, ParserContext, SelectorImpl};
|
||||
use selectors::parser::AttrSelector;
|
||||
use std::borrow::Cow;
|
||||
use std::fmt;
|
||||
use string_cache::{Atom, Namespace, WeakAtom, WeakNamespace};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct GeckoSelectorImpl;
|
||||
// FIXME remove
|
||||
pub use self::SelectorImpl as GeckoSelectorImpl;
|
||||
|
||||
/// NOTE: The boolean field represents whether this element is an anonymous box.
|
||||
///
|
||||
|
@ -161,7 +162,10 @@ impl NonTSPseudoClass {
|
|||
}
|
||||
}
|
||||
|
||||
impl SelectorImpl for GeckoSelectorImpl {
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct SelectorImpl;
|
||||
|
||||
impl ::selectors::SelectorImpl for SelectorImpl {
|
||||
type AttrValue = Atom;
|
||||
type Identifier = Atom;
|
||||
type ClassName = Atom;
|
||||
|
@ -182,11 +186,14 @@ impl SelectorImpl for GeckoSelectorImpl {
|
|||
value: &Self::AttrValue) -> bool {
|
||||
attr_equals_selector_is_shareable(attr_selector, value)
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_non_ts_pseudo_class(_context: &ParserContext<Self>,
|
||||
name: &str) -> Result<NonTSPseudoClass, ()> {
|
||||
impl<'a> ::selectors::Parser for SelectorParser<'a> {
|
||||
type Impl = SelectorImpl;
|
||||
|
||||
fn parse_non_ts_pseudo_class(&self, name: Cow<str>) -> Result<NonTSPseudoClass, ()> {
|
||||
use self::NonTSPseudoClass::*;
|
||||
let pseudo_class = match_ignore_ascii_case! { name,
|
||||
let pseudo_class = match_ignore_ascii_case! { &name,
|
||||
"any-link" => AnyLink,
|
||||
"link" => Link,
|
||||
"visited" => Visited,
|
||||
|
@ -205,16 +212,23 @@ impl SelectorImpl for GeckoSelectorImpl {
|
|||
Ok(pseudo_class)
|
||||
}
|
||||
|
||||
fn parse_pseudo_element(context: &ParserContext<Self>,
|
||||
name: &str) -> Result<PseudoElement, ()> {
|
||||
match PseudoElement::from_slice(name, context.in_user_agent_stylesheet) {
|
||||
fn parse_pseudo_element(&self, name: Cow<str>) -> Result<PseudoElement, ()> {
|
||||
match PseudoElement::from_slice(&name, self.in_user_agent_stylesheet()) {
|
||||
Some(pseudo) => Ok(pseudo),
|
||||
None => Err(()),
|
||||
}
|
||||
}
|
||||
|
||||
fn default_namespace(&self) -> Option<Namespace> {
|
||||
self.namespaces.default.clone()
|
||||
}
|
||||
|
||||
fn namespace_for_prefix(&self, prefix: &Atom) -> Option<Namespace> {
|
||||
self.namespaces.prefixes.get(prefix).cloned()
|
||||
}
|
||||
}
|
||||
|
||||
impl GeckoSelectorImpl {
|
||||
impl SelectorImpl {
|
||||
#[inline]
|
||||
pub fn pseudo_element_cascade_type(pseudo: &PseudoElement) -> PseudoElementCascadeType {
|
||||
if Self::pseudo_is_before_or_after(pseudo) {
|
||||
|
|
|
@ -8,8 +8,6 @@ use cssparser::{Parser, SourcePosition};
|
|||
use error_reporting::ParseErrorReporter;
|
||||
#[cfg(feature = "gecko")]
|
||||
use gecko_bindings::sugar::refptr::{GeckoArcPrincipal, GeckoArcURI};
|
||||
use selector_parser::TheSelectorImpl;
|
||||
use selectors::parser::ParserContext as SelectorParserContext;
|
||||
use servo_url::ServoUrl;
|
||||
use stylesheets::Origin;
|
||||
|
||||
|
@ -38,7 +36,6 @@ impl ParserContextExtraData {
|
|||
pub struct ParserContext<'a> {
|
||||
pub stylesheet_origin: Origin,
|
||||
pub base_url: &'a ServoUrl,
|
||||
pub selector_context: SelectorParserContext<TheSelectorImpl>,
|
||||
pub error_reporter: Box<ParseErrorReporter + Send>,
|
||||
pub extra_data: ParserContextExtraData,
|
||||
}
|
||||
|
@ -48,12 +45,9 @@ impl<'a> ParserContext<'a> {
|
|||
error_reporter: Box<ParseErrorReporter + Send>,
|
||||
extra_data: ParserContextExtraData)
|
||||
-> ParserContext<'a> {
|
||||
let mut selector_context = SelectorParserContext::new();
|
||||
selector_context.in_user_agent_stylesheet = stylesheet_origin == Origin::UserAgent;
|
||||
ParserContext {
|
||||
stylesheet_origin: stylesheet_origin,
|
||||
base_url: base_url,
|
||||
selector_context: selector_context,
|
||||
error_reporter: error_reporter,
|
||||
extra_data: extra_data,
|
||||
}
|
||||
|
|
|
@ -4,11 +4,17 @@
|
|||
|
||||
//! The pseudo-classes and pseudo-elements supported by the style system.
|
||||
|
||||
use cssparser::Parser as CssParser;
|
||||
use matching::{common_style_affecting_attributes, CommonStyleAffectingAttributeMode};
|
||||
use selectors::Element;
|
||||
use selectors::parser::{AttrSelector, SelectorImpl};
|
||||
use selectors::parser::{AttrSelector, SelectorList};
|
||||
use stylesheets::{Origin, Namespaces};
|
||||
|
||||
pub type AttrValue = <TheSelectorImpl as SelectorImpl>::AttrValue;
|
||||
pub type AttrValue = <TheSelectorImpl as ::selectors::SelectorImpl>::AttrValue;
|
||||
|
||||
// FIXME remove
|
||||
pub use self::SelectorImpl as TheSelectorImpl;
|
||||
pub use self::SelectorImpl as ServoSelectorImpl;
|
||||
|
||||
#[cfg(feature = "servo")]
|
||||
pub use servo::selector_parser::*;
|
||||
|
@ -16,12 +22,6 @@ pub use servo::selector_parser::*;
|
|||
#[cfg(feature = "gecko")]
|
||||
pub use gecko::selector_parser::*;
|
||||
|
||||
#[cfg(feature = "servo")]
|
||||
pub use servo::selector_parser::ServoSelectorImpl as TheSelectorImpl;
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
pub use gecko::selector_parser::GeckoSelectorImpl as TheSelectorImpl;
|
||||
|
||||
#[cfg(feature = "servo")]
|
||||
pub use servo::selector_parser::ServoElementSnapshot as Snapshot;
|
||||
|
||||
|
@ -34,6 +34,28 @@ pub use servo::restyle_damage::ServoRestyleDamage as RestyleDamage;
|
|||
#[cfg(feature = "gecko")]
|
||||
pub use gecko::restyle_damage::GeckoRestyleDamage as RestyleDamage;
|
||||
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
pub struct SelectorParser<'a> {
|
||||
pub stylesheet_origin: Origin,
|
||||
pub namespaces: &'a Namespaces,
|
||||
}
|
||||
|
||||
impl<'a> SelectorParser<'a> {
|
||||
pub fn parse_author_origin_no_namespace(input: &str)
|
||||
-> Result<SelectorList<SelectorImpl>, ()> {
|
||||
let namespaces = Namespaces::default();
|
||||
let parser = SelectorParser {
|
||||
stylesheet_origin: Origin::Author,
|
||||
namespaces: &namespaces,
|
||||
};
|
||||
SelectorList::parse(&parser, &mut CssParser::new(input))
|
||||
}
|
||||
|
||||
pub fn in_user_agent_stylesheet(&self) -> bool {
|
||||
matches!(self.stylesheet_origin, Origin::UserAgent)
|
||||
}
|
||||
}
|
||||
|
||||
/// This function determines if a pseudo-element is eagerly cascaded or not.
|
||||
///
|
||||
/// Eagerly cascaded pseudo-elements are "normal" pseudo-elements (i.e.
|
||||
|
@ -85,7 +107,7 @@ pub trait ElementExt: Element<Impl=TheSelectorImpl> {
|
|||
fn is_link(&self) -> bool;
|
||||
}
|
||||
|
||||
impl TheSelectorImpl {
|
||||
impl SelectorImpl {
|
||||
#[inline]
|
||||
pub fn each_eagerly_cascaded_pseudo_element<F>(mut fun: F)
|
||||
where F: FnMut(PseudoElement)
|
||||
|
|
|
@ -7,10 +7,11 @@ use attr::{AttrIdentifier, AttrValue};
|
|||
use cssparser::ToCss;
|
||||
use element_state::ElementState;
|
||||
use restyle_hints::ElementSnapshot;
|
||||
use selector_parser::{ElementExt, PseudoElementCascadeType, TheSelectorImpl};
|
||||
use selector_parser::{ElementExt, PseudoElementCascadeType, SelectorParser};
|
||||
use selector_parser::{attr_equals_selector_is_shareable, attr_exists_selector_is_shareable};
|
||||
use selectors::{Element, MatchAttrGeneric};
|
||||
use selectors::parser::{AttrSelector, ParserContext, SelectorImpl};
|
||||
use selectors::parser::AttrSelector;
|
||||
use std::borrow::Cow;
|
||||
use std::fmt;
|
||||
|
||||
/// NB: If you add to this list, be sure to update `each_pseudo_element` too.
|
||||
|
@ -150,9 +151,9 @@ impl NonTSPseudoClass {
|
|||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
pub struct ServoSelectorImpl;
|
||||
pub struct SelectorImpl;
|
||||
|
||||
impl SelectorImpl for ServoSelectorImpl {
|
||||
impl ::selectors::SelectorImpl for SelectorImpl {
|
||||
type PseudoElement = PseudoElement;
|
||||
type NonTSPseudoClass = NonTSPseudoClass;
|
||||
|
||||
|
@ -173,11 +174,14 @@ impl SelectorImpl for ServoSelectorImpl {
|
|||
value: &Self::AttrValue) -> bool {
|
||||
attr_equals_selector_is_shareable(attr_selector, value)
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_non_ts_pseudo_class(context: &ParserContext<TheSelectorImpl>,
|
||||
name: &str) -> Result<NonTSPseudoClass, ()> {
|
||||
impl<'a> ::selectors::Parser for SelectorParser<'a> {
|
||||
type Impl = SelectorImpl;
|
||||
|
||||
fn parse_non_ts_pseudo_class(&self, name: Cow<str>) -> Result<NonTSPseudoClass, ()> {
|
||||
use self::NonTSPseudoClass::*;
|
||||
let pseudo_class = match_ignore_ascii_case! { name,
|
||||
let pseudo_class = match_ignore_ascii_case! { &name,
|
||||
"any-link" => AnyLink,
|
||||
"link" => Link,
|
||||
"visited" => Visited,
|
||||
|
@ -193,7 +197,7 @@ impl SelectorImpl for ServoSelectorImpl {
|
|||
"placeholder-shown" => PlaceholderShown,
|
||||
"target" => Target,
|
||||
"-servo-nonzero-border" => {
|
||||
if !context.in_user_agent_stylesheet {
|
||||
if !self.in_user_agent_stylesheet() {
|
||||
return Err(());
|
||||
}
|
||||
ServoNonZeroBorder
|
||||
|
@ -204,63 +208,62 @@ impl SelectorImpl for ServoSelectorImpl {
|
|||
Ok(pseudo_class)
|
||||
}
|
||||
|
||||
fn parse_pseudo_element(context: &ParserContext<TheSelectorImpl>,
|
||||
name: &str) -> Result<PseudoElement, ()> {
|
||||
fn parse_pseudo_element(&self, name: Cow<str>) -> Result<PseudoElement, ()> {
|
||||
use self::PseudoElement::*;
|
||||
let pseudo_element = match_ignore_ascii_case! { name,
|
||||
let pseudo_element = match_ignore_ascii_case! { &name,
|
||||
"before" => Before,
|
||||
"after" => After,
|
||||
"selection" => Selection,
|
||||
"-servo-details-summary" => {
|
||||
if !context.in_user_agent_stylesheet {
|
||||
if !self.in_user_agent_stylesheet() {
|
||||
return Err(())
|
||||
}
|
||||
DetailsSummary
|
||||
},
|
||||
"-servo-details-content" => {
|
||||
if !context.in_user_agent_stylesheet {
|
||||
if !self.in_user_agent_stylesheet() {
|
||||
return Err(())
|
||||
}
|
||||
DetailsContent
|
||||
},
|
||||
"-servo-input-text" => {
|
||||
if !context.in_user_agent_stylesheet {
|
||||
if !self.in_user_agent_stylesheet() {
|
||||
return Err(())
|
||||
}
|
||||
ServoInputText
|
||||
},
|
||||
"-servo-table-wrapper" => {
|
||||
if !context.in_user_agent_stylesheet {
|
||||
if !self.in_user_agent_stylesheet() {
|
||||
return Err(())
|
||||
}
|
||||
ServoTableWrapper
|
||||
},
|
||||
"-servo-anonymous-table-wrapper" => {
|
||||
if !context.in_user_agent_stylesheet {
|
||||
if !self.in_user_agent_stylesheet() {
|
||||
return Err(())
|
||||
}
|
||||
ServoAnonymousTableWrapper
|
||||
},
|
||||
"-servo-anonymous-table" => {
|
||||
if !context.in_user_agent_stylesheet {
|
||||
if !self.in_user_agent_stylesheet() {
|
||||
return Err(())
|
||||
}
|
||||
ServoAnonymousTable
|
||||
},
|
||||
"-servo-anonymous-table-row" => {
|
||||
if !context.in_user_agent_stylesheet {
|
||||
if !self.in_user_agent_stylesheet() {
|
||||
return Err(())
|
||||
}
|
||||
ServoAnonymousTableRow
|
||||
},
|
||||
"-servo-anonymous-table-cell" => {
|
||||
if !context.in_user_agent_stylesheet {
|
||||
if !self.in_user_agent_stylesheet() {
|
||||
return Err(())
|
||||
}
|
||||
ServoAnonymousTableCell
|
||||
},
|
||||
"-servo-anonymous-block" => {
|
||||
if !context.in_user_agent_stylesheet {
|
||||
if !self.in_user_agent_stylesheet() {
|
||||
return Err(())
|
||||
}
|
||||
ServoAnonymousBlock
|
||||
|
@ -270,9 +273,17 @@ impl SelectorImpl for ServoSelectorImpl {
|
|||
|
||||
Ok(pseudo_element)
|
||||
}
|
||||
|
||||
fn default_namespace(&self) -> Option<Namespace> {
|
||||
self.namespaces.default.clone()
|
||||
}
|
||||
|
||||
fn namespace_for_prefix(&self, prefix: &Prefix) -> Option<Namespace> {
|
||||
self.namespaces.prefixes.get(prefix).cloned()
|
||||
}
|
||||
}
|
||||
|
||||
impl ServoSelectorImpl {
|
||||
impl SelectorImpl {
|
||||
#[inline]
|
||||
pub fn pseudo_element_cascade_type(pseudo: &PseudoElement) -> PseudoElementCascadeType {
|
||||
pseudo.cascade_type()
|
||||
|
@ -368,9 +379,9 @@ impl ElementSnapshot for ServoElementSnapshot {
|
|||
}
|
||||
|
||||
impl MatchAttrGeneric for ServoElementSnapshot {
|
||||
type Impl = ServoSelectorImpl;
|
||||
type Impl = SelectorImpl;
|
||||
|
||||
fn match_attr<F>(&self, attr: &AttrSelector<ServoSelectorImpl>, test: F) -> bool
|
||||
fn match_attr<F>(&self, attr: &AttrSelector<SelectorImpl>, test: F) -> bool
|
||||
where F: Fn(&str) -> bool
|
||||
{
|
||||
use selectors::parser::NamespaceConstraint;
|
||||
|
@ -383,7 +394,7 @@ impl MatchAttrGeneric for ServoElementSnapshot {
|
|||
}
|
||||
}
|
||||
|
||||
impl<E: Element<Impl=TheSelectorImpl>> ElementExt for E {
|
||||
impl<E: Element<Impl=SelectorImpl>> ElementExt for E {
|
||||
fn is_link(&self) -> bool {
|
||||
self.match_non_ts_pseudo_class(NonTSPseudoClass::AnyLink)
|
||||
}
|
||||
|
|
|
@ -16,14 +16,15 @@ use media_queries::{Device, MediaList, parse_media_query_list};
|
|||
use parking_lot::RwLock;
|
||||
use parser::{ParserContext, ParserContextExtraData, log_css_error};
|
||||
use properties::{PropertyDeclarationBlock, parse_property_declaration_list};
|
||||
use selector_parser::TheSelectorImpl;
|
||||
use selectors::parser::{Selector, parse_selector_list};
|
||||
use selector_parser::{SelectorImpl, SelectorParser};
|
||||
use selectors::parser::{Selector, SelectorList};
|
||||
use servo_url::ServoUrl;
|
||||
use std::cell::Cell;
|
||||
use std::fmt;
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use style_traits::ToCss;
|
||||
use stylist::FnvHashMap;
|
||||
use viewport::ViewportRule;
|
||||
|
||||
|
||||
|
@ -43,6 +44,13 @@ pub enum Origin {
|
|||
User,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
pub struct Namespaces {
|
||||
pub default: Option<Namespace>,
|
||||
pub prefixes: FnvHashMap<Prefix , Namespace>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct CssRules(pub Arc<RwLock<Vec<CssRule>>>);
|
||||
|
||||
|
@ -188,7 +196,7 @@ impl ToCss for MediaRule {
|
|||
|
||||
#[derive(Debug)]
|
||||
pub struct StyleRule {
|
||||
pub selectors: Vec<Selector<TheSelectorImpl>>,
|
||||
pub selectors: Vec<Selector<SelectorImpl>>,
|
||||
pub block: Arc<RwLock<PropertyDeclarationBlock>>,
|
||||
}
|
||||
|
||||
|
@ -246,7 +254,10 @@ impl Stylesheet {
|
|||
pub fn from_str(css: &str, base_url: ServoUrl, origin: Origin, media: MediaList,
|
||||
error_reporter: Box<ParseErrorReporter + Send>,
|
||||
extra_data: ParserContextExtraData) -> Stylesheet {
|
||||
let mut namespaces = Namespaces::default();
|
||||
let rule_parser = TopLevelRuleParser {
|
||||
stylesheet_origin: origin,
|
||||
namespaces: &mut namespaces,
|
||||
context: ParserContext::new_with_extra_data(origin, &base_url, error_reporter.clone(),
|
||||
extra_data),
|
||||
state: Cell::new(State::Start),
|
||||
|
@ -356,29 +367,23 @@ rule_filter! {
|
|||
effective_keyframes_rules(Keyframes => KeyframesRule),
|
||||
}
|
||||
|
||||
fn parse_nested_rules(context: &ParserContext, input: &mut Parser) -> CssRules {
|
||||
let mut iter = RuleListParser::new_for_nested_rule(input,
|
||||
NestedRuleParser { context: context });
|
||||
let mut rules = Vec::new();
|
||||
while let Some(result) = iter.next() {
|
||||
match result {
|
||||
Ok(rule) => rules.push(rule),
|
||||
Err(range) => {
|
||||
let pos = range.start;
|
||||
let message = format!("Unsupported rule: '{}'", iter.input.slice(range));
|
||||
log_css_error(iter.input, pos, &*message, &context);
|
||||
}
|
||||
}
|
||||
}
|
||||
rules.into()
|
||||
}
|
||||
|
||||
|
||||
struct TopLevelRuleParser<'a> {
|
||||
stylesheet_origin: Origin,
|
||||
namespaces: &'a mut Namespaces,
|
||||
context: ParserContext<'a>,
|
||||
state: Cell<State>,
|
||||
}
|
||||
|
||||
impl<'b> TopLevelRuleParser<'b> {
|
||||
fn nested<'a: 'b>(&'a self) -> NestedRuleParser<'a, 'b> {
|
||||
NestedRuleParser {
|
||||
stylesheet_origin: self.stylesheet_origin,
|
||||
context: &self.context,
|
||||
namespaces: self.namespaces,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Eq, PartialEq, Ord, PartialOrd, Copy, Clone)]
|
||||
enum State {
|
||||
Start = 1,
|
||||
|
@ -425,11 +430,10 @@ impl<'a> AtRuleParser for TopLevelRuleParser<'a> {
|
|||
|
||||
let opt_prefix = if let Ok(prefix) = prefix_result {
|
||||
let prefix = Prefix::from(prefix);
|
||||
self.context.selector_context.namespace_prefixes.insert(
|
||||
prefix.clone(), url.clone());
|
||||
self.namespaces.prefixes.insert(prefix.clone(), url.clone());
|
||||
Some(prefix)
|
||||
} else {
|
||||
self.context.selector_context.default_namespace = Some(url.clone());
|
||||
self.namespaces.default = Some(url.clone());
|
||||
None
|
||||
};
|
||||
|
||||
|
@ -450,39 +454,57 @@ impl<'a> AtRuleParser for TopLevelRuleParser<'a> {
|
|||
}
|
||||
|
||||
self.state.set(State::Body);
|
||||
AtRuleParser::parse_prelude(&mut NestedRuleParser { context: &self.context }, name, input)
|
||||
AtRuleParser::parse_prelude(&mut self.nested(), name, input)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn parse_block(&mut self, prelude: AtRulePrelude, input: &mut Parser) -> Result<CssRule, ()> {
|
||||
AtRuleParser::parse_block(&mut NestedRuleParser { context: &self.context }, prelude, input)
|
||||
AtRuleParser::parse_block(&mut self.nested(), prelude, input)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl<'a> QualifiedRuleParser for TopLevelRuleParser<'a> {
|
||||
type Prelude = Vec<Selector<TheSelectorImpl>>;
|
||||
type Prelude = SelectorList<SelectorImpl>;
|
||||
type QualifiedRule = CssRule;
|
||||
|
||||
#[inline]
|
||||
fn parse_prelude(&mut self, input: &mut Parser) -> Result<Vec<Selector<TheSelectorImpl>>, ()> {
|
||||
fn parse_prelude(&mut self, input: &mut Parser) -> Result<SelectorList<SelectorImpl>, ()> {
|
||||
self.state.set(State::Body);
|
||||
QualifiedRuleParser::parse_prelude(&mut NestedRuleParser { context: &self.context }, input)
|
||||
QualifiedRuleParser::parse_prelude(&mut self.nested(), input)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn parse_block(&mut self, prelude: Vec<Selector<TheSelectorImpl>>, input: &mut Parser)
|
||||
fn parse_block(&mut self, prelude: SelectorList<SelectorImpl>, input: &mut Parser)
|
||||
-> Result<CssRule, ()> {
|
||||
QualifiedRuleParser::parse_block(&mut NestedRuleParser { context: &self.context },
|
||||
prelude, input)
|
||||
QualifiedRuleParser::parse_block(&mut self.nested(), prelude, input)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Clone)] // shallow, relatively cheap clone
|
||||
struct NestedRuleParser<'a, 'b: 'a> {
|
||||
stylesheet_origin: Origin,
|
||||
context: &'a ParserContext<'b>,
|
||||
namespaces: &'b Namespaces,
|
||||
}
|
||||
|
||||
impl<'a, 'b> NestedRuleParser<'a, 'b> {
|
||||
fn parse_nested_rules(&self, input: &mut Parser) -> CssRules {
|
||||
let mut iter = RuleListParser::new_for_nested_rule(input, self.clone());
|
||||
let mut rules = Vec::new();
|
||||
while let Some(result) = iter.next() {
|
||||
match result {
|
||||
Ok(rule) => rules.push(rule),
|
||||
Err(range) => {
|
||||
let pos = range.start;
|
||||
let message = format!("Unsupported rule: '{}'", iter.input.slice(range));
|
||||
log_css_error(iter.input, pos, &*message, self.context);
|
||||
}
|
||||
}
|
||||
}
|
||||
rules.into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b> AtRuleParser for NestedRuleParser<'a, 'b> {
|
||||
type Prelude = AtRulePrelude;
|
||||
|
@ -528,7 +550,7 @@ impl<'a, 'b> AtRuleParser for NestedRuleParser<'a, 'b> {
|
|||
AtRulePrelude::Media(media_queries) => {
|
||||
Ok(CssRule::Media(Arc::new(RwLock::new(MediaRule {
|
||||
media_queries: media_queries,
|
||||
rules: parse_nested_rules(self.context, input),
|
||||
rules: self.parse_nested_rules(input),
|
||||
}))))
|
||||
}
|
||||
AtRulePrelude::Viewport => {
|
||||
|
@ -546,17 +568,21 @@ impl<'a, 'b> AtRuleParser for NestedRuleParser<'a, 'b> {
|
|||
}
|
||||
|
||||
impl<'a, 'b> QualifiedRuleParser for NestedRuleParser<'a, 'b> {
|
||||
type Prelude = Vec<Selector<TheSelectorImpl>>;
|
||||
type Prelude = SelectorList<SelectorImpl>;
|
||||
type QualifiedRule = CssRule;
|
||||
|
||||
fn parse_prelude(&mut self, input: &mut Parser) -> Result<Vec<Selector<TheSelectorImpl>>, ()> {
|
||||
parse_selector_list(&self.context.selector_context, input)
|
||||
fn parse_prelude(&mut self, input: &mut Parser) -> Result<SelectorList<SelectorImpl>, ()> {
|
||||
let selector_parser = SelectorParser {
|
||||
stylesheet_origin: self.stylesheet_origin,
|
||||
namespaces: self.namespaces,
|
||||
};
|
||||
SelectorList::parse(&selector_parser, input)
|
||||
}
|
||||
|
||||
fn parse_block(&mut self, prelude: Vec<Selector<TheSelectorImpl>>, input: &mut Parser)
|
||||
fn parse_block(&mut self, prelude: SelectorList<SelectorImpl>, input: &mut Parser)
|
||||
-> Result<CssRule, ()> {
|
||||
Ok(CssRule::Style(Arc::new(RwLock::new(StyleRule {
|
||||
selectors: prelude,
|
||||
selectors: prelude.0,
|
||||
block: Arc::new(RwLock::new(parse_property_declaration_list(self.context, input)))
|
||||
}))))
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue