mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +01:00
Report invalid selectors (bug 1384216).
This commit is contained in:
parent
408c34a76d
commit
9a7cceb0a1
3 changed files with 51 additions and 14 deletions
|
@ -90,6 +90,12 @@ impl<Impl: SelectorImpl> SelectorBuilder<Impl> {
|
|||
self.simple_selectors.is_empty()
|
||||
}
|
||||
|
||||
/// Returns true if combinators have ever been pushed to this builder.
|
||||
#[inline(always)]
|
||||
pub fn has_combinators(&self) -> bool {
|
||||
!self.combinators.is_empty()
|
||||
}
|
||||
|
||||
/// Consumes the builder, producing a Selector.
|
||||
#[inline(always)]
|
||||
pub fn build(&mut self, parsed_pseudo: bool) -> ThinArc<SpecificityAndFlags, Component<Impl>> {
|
||||
|
|
|
@ -54,16 +54,19 @@ pub enum SelectorParseError<'i, T> {
|
|||
NegationSelectorComponentNotNamespace,
|
||||
NegationSelectorComponentNotLocalName,
|
||||
EmptySelector,
|
||||
DanglingCombinator,
|
||||
NonSimpleSelectorInNegation,
|
||||
UnexpectedTokenInAttributeSelector(Token<'i>),
|
||||
PseudoElementExpectedColon,
|
||||
PseudoElementExpectedIdent,
|
||||
PseudoElementExpectedColon(Token<'i>),
|
||||
PseudoElementExpectedIdent(Token<'i>),
|
||||
NoIdentForPseudo(Token<'i>),
|
||||
UnsupportedPseudoClassOrElement(CowRcStr<'i>),
|
||||
UnexpectedIdent(CowRcStr<'i>),
|
||||
ExpectedNamespace(CowRcStr<'i>),
|
||||
ExpectedBarInAttr(Token<'i>),
|
||||
BadValueInAttr(Token<'i>),
|
||||
InvalidQualNameInAttr(Token<'i>),
|
||||
ExplicitNamespaceUnexpectedToken(Token<'i>),
|
||||
Custom(T),
|
||||
}
|
||||
|
||||
|
@ -1044,7 +1047,12 @@ fn parse_selector<'i, 't, P, E, Impl>(
|
|||
let mut parsed_pseudo_element;
|
||||
'outer_loop: loop {
|
||||
// Parse a sequence of simple selectors.
|
||||
parsed_pseudo_element = parse_compound_selector(parser, input, &mut builder)?;
|
||||
parsed_pseudo_element = match parse_compound_selector(parser, input, &mut builder) {
|
||||
Ok(result) => result,
|
||||
Err(ParseError::Custom(SelectorParseError::EmptySelector)) if builder.has_combinators() =>
|
||||
return Err(SelectorParseError::DanglingCombinator.into()),
|
||||
Err(e) => return Err(e),
|
||||
};
|
||||
if parsed_pseudo_element {
|
||||
break;
|
||||
}
|
||||
|
@ -1109,9 +1117,10 @@ fn parse_type_selector<'i, 't, P, E, Impl, S>(parser: &P, input: &mut CssParser<
|
|||
Impl: SelectorImpl,
|
||||
S: Push<Component<Impl>>,
|
||||
{
|
||||
match parse_qualified_name(parser, input, /* in_attr_selector = */ false)? {
|
||||
OptionalQName::None(_) => Ok(false),
|
||||
OptionalQName::Some(namespace, local_name) => {
|
||||
match parse_qualified_name(parser, input, /* in_attr_selector = */ false) {
|
||||
Err(ParseError::Basic(BasicParseError::EndOfInput)) |
|
||||
Ok(OptionalQName::None(_)) => Ok(false),
|
||||
Ok(OptionalQName::Some(namespace, local_name)) => {
|
||||
match namespace {
|
||||
QNamePrefix::ImplicitAnyNamespace => {}
|
||||
QNamePrefix::ImplicitDefaultNamespace(url) => {
|
||||
|
@ -1160,6 +1169,7 @@ fn parse_type_selector<'i, 't, P, E, Impl, S>(parser: &P, input: &mut CssParser<
|
|||
}
|
||||
Ok(true)
|
||||
}
|
||||
Err(e) => Err(e)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1212,7 +1222,7 @@ fn parse_qualified_name<'i, 't, P, E, Impl>
|
|||
Ok(OptionalQName::Some(namespace, Some(local_name.clone())))
|
||||
},
|
||||
Ok(t) if in_attr_selector => Err(SelectorParseError::InvalidQualNameInAttr(t.clone()).into()),
|
||||
Ok(t) => Err(ParseError::Basic(BasicParseError::UnexpectedToken(t.clone()))),
|
||||
Ok(t) => Err(SelectorParseError::ExplicitNamespaceUnexpectedToken(t.clone()).into()),
|
||||
Err(e) => Err(ParseError::Basic(e)),
|
||||
}
|
||||
};
|
||||
|
@ -1499,14 +1509,15 @@ fn parse_compound_selector<'i, 't, P, E, Impl>(
|
|||
match input.next_including_whitespace() {
|
||||
Ok(&Token::Colon) => {},
|
||||
Ok(&Token::WhiteSpace(_)) | Err(_) => break,
|
||||
_ => return Err(SelectorParseError::PseudoElementExpectedColon.into()),
|
||||
Ok(t) =>
|
||||
return Err(SelectorParseError::PseudoElementExpectedColon(t.clone()).into()),
|
||||
}
|
||||
|
||||
// TODO(emilio): Functional pseudo-classes too?
|
||||
// We don't need it for now.
|
||||
let name = match input.next_including_whitespace() {
|
||||
Ok(&Token::Ident(ref name)) => name.clone(),
|
||||
_ => return Err(SelectorParseError::PseudoElementExpectedIdent.into()),
|
||||
let name = match input.next_including_whitespace()? {
|
||||
&Token::Ident(ref name) => name.clone(),
|
||||
t => return Err(SelectorParseError::NoIdentForPseudo(t.clone()).into()),
|
||||
};
|
||||
|
||||
let pseudo_class =
|
||||
|
@ -1626,7 +1637,7 @@ fn parse_one_simple_selector<'i, 't, P, E, Impl>(parser: &P,
|
|||
let (name, is_functional) = match next_token {
|
||||
Token::Ident(name) => (name, false),
|
||||
Token::Function(name) => (name, true),
|
||||
t => return Err(ParseError::Basic(BasicParseError::UnexpectedToken(t))),
|
||||
t => return Err(SelectorParseError::PseudoElementExpectedIdent(t).into()),
|
||||
};
|
||||
let is_pseudo_element = !is_single_colon ||
|
||||
P::is_pseudo_element_allows_single_colon(&name);
|
||||
|
|
|
@ -161,7 +161,7 @@ fn token_to_str<'a>(t: Token<'a>) -> String {
|
|||
format!("{}{}", i, escape_css_ident(&*unit)),
|
||||
Token::Dimension { value, ref unit, .. } =>
|
||||
format!("{}{}", value, escape_css_ident(&*unit)),
|
||||
Token::WhiteSpace(_) => "whitespace".into(),
|
||||
Token::WhiteSpace(s) => s.into(),
|
||||
Token::Comment(_) => "comment".into(),
|
||||
Token::Colon => ":".into(),
|
||||
Token::Semicolon => ";".into(),
|
||||
|
@ -251,7 +251,11 @@ fn extract_error_params<'a>(err: ParseError<'a>) -> Option<ErrorParams<'a>> {
|
|||
CssParseError::Custom(SelectorParseError::BadValueInAttr(t)) |
|
||||
CssParseError::Custom(SelectorParseError::ExpectedBarInAttr(t)) |
|
||||
CssParseError::Custom(SelectorParseError::NoQualifiedNameInAttributeSelector(t)) |
|
||||
CssParseError::Custom(SelectorParseError::InvalidQualNameInAttr(t)) =>
|
||||
CssParseError::Custom(SelectorParseError::InvalidQualNameInAttr(t)) |
|
||||
CssParseError::Custom(SelectorParseError::ExplicitNamespaceUnexpectedToken(t)) |
|
||||
CssParseError::Custom(SelectorParseError::PseudoElementExpectedIdent(t)) |
|
||||
CssParseError::Custom(SelectorParseError::NoIdentForPseudo(t)) |
|
||||
CssParseError::Custom(SelectorParseError::PseudoElementExpectedColon(t)) =>
|
||||
(None, Some(ErrorString::UnexpectedToken(t))),
|
||||
|
||||
CssParseError::Custom(SelectorParseError::ExpectedNamespace(namespace)) =>
|
||||
|
@ -260,6 +264,10 @@ fn extract_error_params<'a>(err: ParseError<'a>) -> Option<ErrorParams<'a>> {
|
|||
CssParseError::Custom(SelectorParseError::UnsupportedPseudoClassOrElement(p)) =>
|
||||
(None, Some(ErrorString::Ident(p))),
|
||||
|
||||
CssParseError::Custom(SelectorParseError::EmptySelector) |
|
||||
CssParseError::Custom(SelectorParseError::DanglingCombinator) =>
|
||||
(None, None),
|
||||
|
||||
err => match extract_error_param(err) {
|
||||
Some(e) => (Some(e), None),
|
||||
None => return None,
|
||||
|
@ -344,10 +352,22 @@ impl<'a> ErrorHelpers<'a> for ContextualParseError<'a> {
|
|||
Some(&b"PEAttributeNameOrNamespaceExpected\0"[..]),
|
||||
CssParseError::Custom(SelectorParseError::InvalidQualNameInAttr(_)) =>
|
||||
Some(&b"PEAttributeNameExpected\0"[..]),
|
||||
CssParseError::Custom(SelectorParseError::ExplicitNamespaceUnexpectedToken(_)) =>
|
||||
Some(&b"PETypeSelNotType\0"[..]),
|
||||
CssParseError::Custom(SelectorParseError::ExpectedNamespace(_)) =>
|
||||
Some(&b"PEUnknownNamespacePrefix\0"[..]),
|
||||
CssParseError::Custom(SelectorParseError::EmptySelector) =>
|
||||
Some(&b"PESelectorGroupNoSelector\0"[..]),
|
||||
CssParseError::Custom(SelectorParseError::DanglingCombinator) =>
|
||||
Some(&b"PESelectorGroupExtraCombinator\0"[..]),
|
||||
CssParseError::Custom(SelectorParseError::UnsupportedPseudoClassOrElement(_)) =>
|
||||
Some(&b"PEPseudoSelUnknown\0"[..]),
|
||||
CssParseError::Custom(SelectorParseError::PseudoElementExpectedColon(_)) =>
|
||||
Some(&b"PEPseudoSelEndOrUserActionPC\0"[..]),
|
||||
CssParseError::Custom(SelectorParseError::NoIdentForPseudo(_)) =>
|
||||
Some(&b"PEPseudoClassArgNotIdent\0"[..]),
|
||||
CssParseError::Custom(SelectorParseError::PseudoElementExpectedIdent(_)) =>
|
||||
Some(&b"PEPseudoSelBadName\0"[..]),
|
||||
_ => None,
|
||||
};
|
||||
return (prefix, b"PEBadSelectorRSIgnored\0", Action::Nothing);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue