Update cssparser to 0.18

https://github.com/servo/rust-cssparser/pull/171
This commit is contained in:
Simon Sapin 2017-07-20 21:03:53 +02:00
parent 30d6d6024b
commit eb98ae6e04
64 changed files with 541 additions and 512 deletions

View file

@ -25,7 +25,7 @@ unstable = []
[dependencies]
bitflags = "0.7"
matches = "0.1"
cssparser = "0.17.0"
cssparser = "0.18"
log = "0.3"
fnv = "1.0"
phf = "0.7.18"

View file

@ -7,7 +7,7 @@ use attr::{ParsedCaseSensitivity, SELECTOR_WHITESPACE, NamespaceConstraint};
use bloom::BLOOM_HASH_MASK;
use builder::{SelectorBuilder, SpecificityAndFlags};
use context::QuirksMode;
use cssparser::{ParseError, BasicParseError, CompactCowStr};
use cssparser::{ParseError, BasicParseError, CowRcStr};
use cssparser::{Token, Parser as CssParser, parse_nth, ToCss, serialize_identifier, CssStringWriter};
use precomputed_hash::PrecomputedHash;
use servo_arc::ThinArc;
@ -59,8 +59,8 @@ pub enum SelectorParseError<'i, T> {
PseudoElementExpectedColon,
PseudoElementExpectedIdent,
UnsupportedPseudoClass,
UnexpectedIdent(CompactCowStr<'i>),
ExpectedNamespace(CompactCowStr<'i>),
UnexpectedIdent(CowRcStr<'i>),
ExpectedNamespace(CowRcStr<'i>),
Custom(T),
}
@ -76,13 +76,6 @@ macro_rules! with_all_bounds {
[ $( $CommonBounds: tt )* ]
[ $( $FromStr: tt )* ]
) => {
fn from_cow_str<T>(cow: Cow<str>) -> T where T: $($FromStr)* {
match cow {
Cow::Borrowed(s) => T::from(s),
Cow::Owned(s) => T::from(s),
}
}
/// This trait allows to define the parser implementation in regards
/// of pseudo-classes/elements
///
@ -125,7 +118,7 @@ macro_rules! with_bounds {
with_bounds! {
[Clone + Eq]
[From<String> + for<'a> From<&'a str>]
[for<'a> From<&'a str>]
}
pub trait Parser<'i> {
@ -134,34 +127,34 @@ pub trait Parser<'i> {
/// Whether the name is a pseudo-element that can be specified with
/// the single colon syntax in addition to the double-colon syntax.
fn is_pseudo_element_allows_single_colon(name: &CompactCowStr<'i>) -> bool {
fn is_pseudo_element_allows_single_colon(name: &CowRcStr<'i>) -> bool {
is_css2_pseudo_element(name)
}
/// This function can return an "Err" pseudo-element in order to support CSS2.1
/// pseudo-elements.
fn parse_non_ts_pseudo_class(&self, name: CompactCowStr<'i>)
fn parse_non_ts_pseudo_class(&self, name: CowRcStr<'i>)
-> Result<<Self::Impl as SelectorImpl>::NonTSPseudoClass,
ParseError<'i, SelectorParseError<'i, Self::Error>>> {
Err(ParseError::Custom(SelectorParseError::UnexpectedIdent(name)))
}
fn parse_non_ts_functional_pseudo_class<'t>
(&self, name: CompactCowStr<'i>, _arguments: &mut CssParser<'i, 't>)
(&self, name: CowRcStr<'i>, _arguments: &mut CssParser<'i, 't>)
-> Result<<Self::Impl as SelectorImpl>::NonTSPseudoClass,
ParseError<'i, SelectorParseError<'i, Self::Error>>>
{
Err(ParseError::Custom(SelectorParseError::UnexpectedIdent(name)))
}
fn parse_pseudo_element(&self, name: CompactCowStr<'i>)
fn parse_pseudo_element(&self, name: CowRcStr<'i>)
-> Result<<Self::Impl as SelectorImpl>::PseudoElement,
ParseError<'i, SelectorParseError<'i, Self::Error>>> {
Err(ParseError::Custom(SelectorParseError::UnexpectedIdent(name)))
}
fn parse_functional_pseudo_element<'t>
(&self, name: CompactCowStr<'i>, _arguments: &mut CssParser<'i, 't>)
(&self, name: CowRcStr<'i>, _arguments: &mut CssParser<'i, 't>)
-> Result<<Self::Impl as SelectorImpl>::PseudoElement,
ParseError<'i, SelectorParseError<'i, Self::Error>>> {
Err(ParseError::Custom(SelectorParseError::UnexpectedIdent(name)))
@ -1060,16 +1053,16 @@ fn parse_selector<'i, 't, P, E, Impl>(
let position = input.position();
match input.next_including_whitespace() {
Err(_e) => break 'outer_loop,
Ok(Token::WhiteSpace(_)) => any_whitespace = true,
Ok(Token::Delim('>')) => {
Ok(&Token::WhiteSpace(_)) => any_whitespace = true,
Ok(&Token::Delim('>')) => {
combinator = Combinator::Child;
break
}
Ok(Token::Delim('+')) => {
Ok(&Token::Delim('+')) => {
combinator = Combinator::NextSibling;
break
}
Ok(Token::Delim('~')) => {
Ok(&Token::Delim('~')) => {
combinator = Combinator::LaterSibling;
break
}
@ -1154,8 +1147,8 @@ fn parse_type_selector<'i, 't, P, E, Impl, S>(parser: &P, input: &mut CssParser<
match local_name {
Some(name) => {
sink.push(Component::LocalName(LocalName {
lower_name: from_cow_str(to_ascii_lowercase(&name)),
name: from_cow_str(name.into()),
lower_name: to_ascii_lowercase(&name).as_ref().into(),
name: name.as_ref().into(),
}))
}
None => {
@ -1189,7 +1182,7 @@ enum QNamePrefix<Impl: SelectorImpl> {
fn parse_qualified_name<'i, 't, P, E, Impl>
(parser: &P, input: &mut CssParser<'i, 't>,
in_attr_selector: bool)
-> Result<Option<(QNamePrefix<Impl>, Option<CompactCowStr<'i>>)>,
-> Result<Option<(QNamePrefix<Impl>, Option<CowRcStr<'i>>)>,
ParseError<'i, SelectorParseError<'i, E>>>
where P: Parser<'i, Impl=Impl, Error=E>, Impl: SelectorImpl
{
@ -1203,27 +1196,28 @@ fn parse_qualified_name<'i, 't, P, E, Impl>
let explicit_namespace = |input: &mut CssParser<'i, 't>, namespace| {
match input.next_including_whitespace() {
Ok(Token::Delim('*')) if !in_attr_selector => {
Ok(&Token::Delim('*')) if !in_attr_selector => {
Ok(Some((namespace, None)))
},
Ok(Token::Ident(local_name)) => {
Ok(Some((namespace, Some(local_name))))
Ok(&Token::Ident(ref local_name)) => {
Ok(Some((namespace, Some(local_name.clone()))))
},
Ok(t) => Err(ParseError::Basic(BasicParseError::UnexpectedToken(t))),
Ok(t) => Err(ParseError::Basic(BasicParseError::UnexpectedToken(t.clone()))),
Err(e) => Err(ParseError::Basic(e)),
}
};
let position = input.position();
match input.next_including_whitespace() {
// FIXME: remove clone() when lifetimes are non-lexical
match input.next_including_whitespace().map(|t| t.clone()) {
Ok(Token::Ident(value)) => {
let position = input.position();
match input.next_including_whitespace() {
Ok(Token::Delim('|')) => {
let prefix = from_cow_str(value.clone().into());
Ok(&Token::Delim('|')) => {
let prefix = value.as_ref().into();
let result = parser.namespace_for_prefix(&prefix);
let url = result.ok_or(ParseError::Custom(
SelectorParseError::ExpectedNamespace(value.into())))?;
SelectorParseError::ExpectedNamespace(value)))?;
explicit_namespace(input, QNamePrefix::ExplicitNamespace(prefix, url))
},
_ => {
@ -1238,7 +1232,8 @@ fn parse_qualified_name<'i, 't, P, E, Impl>
},
Ok(Token::Delim('*')) => {
let position = input.position();
match input.next_including_whitespace() {
// FIXME: remove clone() when lifetimes are non-lexical
match input.next_including_whitespace().map(|t| t.clone()) {
Ok(Token::Delim('|')) => {
explicit_namespace(input, QNamePrefix::ExplicitAnyNamespace)
}
@ -1247,7 +1242,7 @@ fn parse_qualified_name<'i, 't, P, E, Impl>
if in_attr_selector {
match result {
Ok(t) => Err(ParseError::Basic(BasicParseError::UnexpectedToken(t))),
Err(e) => Err(ParseError::Basic(e)),
Err(e) => Err(ParseError::Basic(e)),
}
} else {
default_namespace(None)
@ -1303,8 +1298,8 @@ fn parse_attribute_selector<'i, 't, P, E, Impl>(parser: &P, input: &mut CssParse
match input.next() {
// [foo]
Err(_) => {
let local_name_lower = from_cow_str(to_ascii_lowercase(&local_name));
let local_name = from_cow_str(local_name.into());
let local_name_lower = to_ascii_lowercase(&local_name).as_ref().into();
let local_name = local_name.as_ref().into();
if let Some(namespace) = namespace {
return Ok(Component::AttributeOther(Box::new(AttrSelectorWithNamespace {
namespace: namespace,
@ -1322,38 +1317,38 @@ fn parse_attribute_selector<'i, 't, P, E, Impl>(parser: &P, input: &mut CssParse
}
// [foo=bar]
Ok(Token::Delim('=')) => {
value = input.expect_ident_or_string()?;
Ok(&Token::Delim('=')) => {
value = input.expect_ident_or_string()?.clone();
never_matches = false;
operator = AttrSelectorOperator::Equal;
}
// [foo~=bar]
Ok(Token::IncludeMatch) => {
value = input.expect_ident_or_string()?;
Ok(&Token::IncludeMatch) => {
value = input.expect_ident_or_string()?.clone();
never_matches = value.is_empty() || value.contains(SELECTOR_WHITESPACE);
operator = AttrSelectorOperator::Includes;
}
// [foo|=bar]
Ok(Token::DashMatch) => {
value = input.expect_ident_or_string()?;
Ok(&Token::DashMatch) => {
value = input.expect_ident_or_string()?.clone();
never_matches = false;
operator = AttrSelectorOperator::DashMatch;
}
// [foo^=bar]
Ok(Token::PrefixMatch) => {
value = input.expect_ident_or_string()?;
Ok(&Token::PrefixMatch) => {
value = input.expect_ident_or_string()?.clone();
never_matches = value.is_empty();
operator = AttrSelectorOperator::Prefix;
}
// [foo*=bar]
Ok(Token::SubstringMatch) => {
value = input.expect_ident_or_string()?;
Ok(&Token::SubstringMatch) => {
value = input.expect_ident_or_string()?.clone();
never_matches = value.is_empty();
operator = AttrSelectorOperator::Substring;
}
// [foo$=bar]
Ok(Token::SuffixMatch) => {
value = input.expect_ident_or_string()?;
Ok(&Token::SuffixMatch) => {
value = input.expect_ident_or_string()?.clone();
never_matches = value.is_empty();
operator = AttrSelectorOperator::Suffix;
}
@ -1362,7 +1357,7 @@ fn parse_attribute_selector<'i, 't, P, E, Impl>(parser: &P, input: &mut CssParse
let mut case_sensitivity = parse_attribute_flags(input)?;
let value = from_cow_str(value.into());
let value = value.as_ref().into();
let local_name_lower;
{
let local_name_lower_cow = to_ascii_lowercase(&local_name);
@ -1375,9 +1370,9 @@ fn parse_attribute_selector<'i, 't, P, E, Impl>(parser: &P, input: &mut CssParse
ParsedCaseSensitivity::AsciiCaseInsensitiveIfInHtmlElementInHtmlDocument
}
}
local_name_lower = from_cow_str(local_name_lower_cow.into());
local_name_lower = local_name_lower_cow.as_ref().into();
}
let local_name = from_cow_str(local_name.into());
let local_name = local_name.as_ref().into();
if let Some(namespace) = namespace {
Ok(Component::AttributeOther(Box::new(AttrSelectorWithNamespace {
namespace: namespace,
@ -1411,10 +1406,10 @@ fn parse_attribute_flags<'i, 't, E>(input: &mut CssParser<'i, 't>)
// Selectors spec says language-defined, but HTML says sensitive.
Ok(ParsedCaseSensitivity::CaseSensitive)
}
Ok(Token::Ident(ref value)) if value.eq_ignore_ascii_case("i") => {
Ok(&Token::Ident(ref value)) if value.eq_ignore_ascii_case("i") => {
Ok(ParsedCaseSensitivity::AsciiCaseInsensitive)
}
Ok(t) => Err(ParseError::Basic(BasicParseError::UnexpectedToken(t)))
Ok(t) => Err(ParseError::Basic(BasicParseError::UnexpectedToken(t.clone())))
}
}
@ -1433,7 +1428,7 @@ fn parse_negation<'i, 't, P, E, Impl>(parser: &P,
// Consume any leading whitespace.
loop {
let position = input.position();
if !matches!(input.next_including_whitespace(), Ok(Token::WhiteSpace(_))) {
if !matches!(input.next_including_whitespace(), Ok(&Token::WhiteSpace(_))) {
input.reset(position);
break
}
@ -1476,7 +1471,7 @@ fn parse_compound_selector<'i, 't, P, E, Impl>(
// Consume any leading whitespace.
loop {
let position = input.position();
if !matches!(input.next_including_whitespace(), Ok(Token::WhiteSpace(_))) {
if !matches!(input.next_including_whitespace(), Ok(&Token::WhiteSpace(_))) {
input.reset(position);
break
}
@ -1508,15 +1503,15 @@ fn parse_compound_selector<'i, 't, P, E, Impl>(
loop {
match input.next_including_whitespace() {
Ok(Token::Colon) => {},
Ok(Token::WhiteSpace(_)) | Err(_) => break,
Ok(&Token::Colon) => {},
Ok(&Token::WhiteSpace(_)) | Err(_) => break,
_ => return Err(SelectorParseError::PseudoElementExpectedColon.into()),
}
// TODO(emilio): Functional pseudo-classes too?
// We don't need it for now.
let name = match input.next_including_whitespace() {
Ok(Token::Ident(name)) => name,
Ok(&Token::Ident(ref name)) => name.clone(),
_ => return Err(SelectorParseError::PseudoElementExpectedIdent.into()),
};
@ -1553,7 +1548,7 @@ fn parse_compound_selector<'i, 't, P, E, Impl>(
fn parse_functional_pseudo_class<'i, 't, P, E, Impl>(parser: &P,
input: &mut CssParser<'i, 't>,
name: CompactCowStr<'i>,
name: CowRcStr<'i>,
inside_negation: bool)
-> Result<Component<Impl>,
ParseError<'i, SelectorParseError<'i, E>>>
@ -1589,7 +1584,7 @@ where Impl: SelectorImpl, F: FnOnce(i32, i32) -> Component<Impl> {
/// Returns whether the name corresponds to a CSS2 pseudo-element that
/// can be specified with the single colon syntax (in addition to the
/// double-colon syntax, which can be used for all pseudo-elements).
pub fn is_css2_pseudo_element<'i>(name: &CompactCowStr<'i>) -> bool {
pub fn is_css2_pseudo_element<'i>(name: &CowRcStr<'i>) -> bool {
// ** Do not add to this list! **
return name.eq_ignore_ascii_case("before") ||
name.eq_ignore_ascii_case("after") ||
@ -1610,18 +1605,19 @@ fn parse_one_simple_selector<'i, 't, P, E, Impl>(parser: &P,
where P: Parser<'i, Impl=Impl, Error=E>, Impl: SelectorImpl
{
let start_position = input.position();
match input.next_including_whitespace() {
// FIXME: remove clone() when lifetimes are non-lexical
match input.next_including_whitespace().map(|t| t.clone()) {
Ok(Token::IDHash(id)) => {
let id = Component::ID(from_cow_str(id.into()));
let id = Component::ID(id.as_ref().into());
Ok(Some(SimpleSelectorParseResult::SimpleSelector(id)))
}
Ok(Token::Delim('.')) => {
match input.next_including_whitespace()? {
Token::Ident(class) => {
let class = Component::Class(from_cow_str(class.into()));
match *input.next_including_whitespace()? {
Token::Ident(ref class) => {
let class = Component::Class(class.as_ref().into());
Ok(Some(SimpleSelectorParseResult::SimpleSelector(class)))
}
t => Err(ParseError::Basic(BasicParseError::UnexpectedToken(t))),
ref t => Err(ParseError::Basic(BasicParseError::UnexpectedToken(t.clone()))),
}
}
Ok(Token::SquareBracketBlock) => {
@ -1629,8 +1625,8 @@ fn parse_one_simple_selector<'i, 't, P, E, Impl>(parser: &P,
Ok(Some(SimpleSelectorParseResult::SimpleSelector(attr)))
}
Ok(Token::Colon) => {
let (is_single_colon, next_token) = match input.next_including_whitespace()? {
Token::Colon => (false, input.next_including_whitespace()?),
let (is_single_colon, next_token) = match input.next_including_whitespace()?.clone() {
Token::Colon => (false, input.next_including_whitespace()?.clone()),
t => (true, t),
};
let (name, is_functional) = match next_token {
@ -1667,7 +1663,7 @@ fn parse_one_simple_selector<'i, 't, P, E, Impl>(parser: &P,
}
}
fn parse_simple_pseudo_class<'i, P, E, Impl>(parser: &P, name: CompactCowStr<'i>)
fn parse_simple_pseudo_class<'i, P, E, Impl>(parser: &P, name: CowRcStr<'i>)
-> Result<Component<Impl>,
ParseError<'i, SelectorParseError<'i, E>>>
where P: Parser<'i, Impl=Impl, Error=E>, Impl: SelectorImpl
@ -1821,7 +1817,7 @@ pub mod tests {
type Impl = DummySelectorImpl;
type Error = ();
fn parse_non_ts_pseudo_class(&self, name: CompactCowStr<'i>)
fn parse_non_ts_pseudo_class(&self, name: CowRcStr<'i>)
-> Result<PseudoClass,
ParseError<'i, SelectorParseError<'i, ()>>> {
match_ignore_ascii_case! { &name,
@ -1831,17 +1827,17 @@ pub mod tests {
}
}
fn parse_non_ts_functional_pseudo_class<'t>(&self, name: CompactCowStr<'i>,
fn parse_non_ts_functional_pseudo_class<'t>(&self, name: CowRcStr<'i>,
parser: &mut CssParser<'i, 't>)
-> Result<PseudoClass,
ParseError<'i, SelectorParseError<'i, ()>>> {
match_ignore_ascii_case! { &name,
"lang" => Ok(PseudoClass::Lang(parser.expect_ident_or_string()?.into_owned())),
"lang" => Ok(PseudoClass::Lang(parser.expect_ident_or_string()?.as_ref().to_owned())),
_ => Err(SelectorParseError::Custom(()).into())
}
}
fn parse_pseudo_element(&self, name: CompactCowStr<'i>)
fn parse_pseudo_element(&self, name: CowRcStr<'i>)
-> Result<PseudoElement,
ParseError<'i, SelectorParseError<'i, ()>>> {
match_ignore_ascii_case! { &name,