mirror of
https://github.com/servo/servo.git
synced 2025-08-04 21:20:23 +01:00
style: Disallow forgiving selector-parsing in @supports
As per spec, see https://github.com/w3c/csswg-drafts/issues/7280 Differential Revision: https://phabricator.services.mozilla.com/D156468
This commit is contained in:
parent
ab36c8a39b
commit
9f6341b83a
6 changed files with 25 additions and 23 deletions
|
@ -276,6 +276,11 @@ pub trait Parser<'i> {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Whether to allow forgiving selector-list parsing.
|
||||||
|
fn allow_forgiving_selectors(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
/// Parses non-tree-structural pseudo-classes. Tree structural pseudo-classes,
|
/// Parses non-tree-structural pseudo-classes. Tree structural pseudo-classes,
|
||||||
/// like `:first-child`, are built into this library.
|
/// like `:first-child`, are built into this library.
|
||||||
///
|
///
|
||||||
|
@ -400,7 +405,11 @@ impl<Impl: SelectorImpl> SelectorList<Impl> {
|
||||||
Ok(selector) => values.push(selector),
|
Ok(selector) => values.push(selector),
|
||||||
Err(err) => match recovery {
|
Err(err) => match recovery {
|
||||||
ParseErrorRecovery::DiscardList => return Err(err),
|
ParseErrorRecovery::DiscardList => return Err(err),
|
||||||
ParseErrorRecovery::IgnoreInvalidSelector => {},
|
ParseErrorRecovery::IgnoreInvalidSelector => {
|
||||||
|
if !parser.allow_forgiving_selectors() {
|
||||||
|
return Err(err);
|
||||||
|
}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -184,7 +184,7 @@ impl PseudoElement {
|
||||||
///
|
///
|
||||||
/// Returns `None` if the pseudo-element is not recognised.
|
/// Returns `None` if the pseudo-element is not recognised.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_slice(name: &str) -> Option<Self> {
|
pub fn from_slice(name: &str, allow_unkown_webkit: bool) -> Option<Self> {
|
||||||
// We don't need to support tree pseudos because functional
|
// We don't need to support tree pseudos because functional
|
||||||
// pseudo-elements needs arguments, and thus should be created
|
// pseudo-elements needs arguments, and thus should be created
|
||||||
// via other methods.
|
// via other methods.
|
||||||
|
@ -209,7 +209,7 @@ impl PseudoElement {
|
||||||
return PseudoElement::tree_pseudo_element(name, Box::new([]))
|
return PseudoElement::tree_pseudo_element(name, Box::new([]))
|
||||||
}
|
}
|
||||||
const WEBKIT_PREFIX: &str = "-webkit-";
|
const WEBKIT_PREFIX: &str = "-webkit-";
|
||||||
if starts_with_ignore_ascii_case(name, WEBKIT_PREFIX) {
|
if allow_unkown_webkit && starts_with_ignore_ascii_case(name, WEBKIT_PREFIX) {
|
||||||
let part = string_as_ascii_lowercase(&name[WEBKIT_PREFIX.len()..]);
|
let part = string_as_ascii_lowercase(&name[WEBKIT_PREFIX.len()..]);
|
||||||
return Some(PseudoElement::UnknownWebkit(part.into()));
|
return Some(PseudoElement::UnknownWebkit(part.into()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -320,6 +320,11 @@ impl<'a, 'i> ::selectors::Parser<'i> for SelectorParser<'a> {
|
||||||
function.eq_ignore_ascii_case("-moz-any")
|
function.eq_ignore_ascii_case("-moz-any")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn allow_forgiving_selectors(&self) -> bool {
|
||||||
|
!self.for_supports_rule
|
||||||
|
}
|
||||||
|
|
||||||
fn parse_non_ts_pseudo_class(
|
fn parse_non_ts_pseudo_class(
|
||||||
&self,
|
&self,
|
||||||
location: SourceLocation,
|
location: SourceLocation,
|
||||||
|
@ -373,7 +378,8 @@ impl<'a, 'i> ::selectors::Parser<'i> for SelectorParser<'a> {
|
||||||
location: SourceLocation,
|
location: SourceLocation,
|
||||||
name: CowRcStr<'i>,
|
name: CowRcStr<'i>,
|
||||||
) -> Result<PseudoElement, ParseError<'i>> {
|
) -> Result<PseudoElement, ParseError<'i>> {
|
||||||
if let Some(pseudo) = PseudoElement::from_slice(&name) {
|
let allow_unkown_webkit = !self.for_supports_rule;
|
||||||
|
if let Some(pseudo) = PseudoElement::from_slice(&name, allow_unkown_webkit) {
|
||||||
if self.is_pseudo_element_enabled(&pseudo) {
|
if self.is_pseudo_element_enabled(&pseudo) {
|
||||||
return Ok(pseudo);
|
return Ok(pseudo);
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,6 +47,8 @@ pub struct SelectorParser<'a> {
|
||||||
/// The extra URL data of the stylesheet, which is used to look up
|
/// The extra URL data of the stylesheet, which is used to look up
|
||||||
/// whether we are parsing a chrome:// URL style sheet.
|
/// whether we are parsing a chrome:// URL style sheet.
|
||||||
pub url_data: &'a UrlExtraData,
|
pub url_data: &'a UrlExtraData,
|
||||||
|
/// Whether we're parsing selectors for `@supports`
|
||||||
|
pub for_supports_rule: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> SelectorParser<'a> {
|
impl<'a> SelectorParser<'a> {
|
||||||
|
@ -63,6 +65,7 @@ impl<'a> SelectorParser<'a> {
|
||||||
stylesheet_origin: Origin::Author,
|
stylesheet_origin: Origin::Author,
|
||||||
namespaces: &namespaces,
|
namespaces: &namespaces,
|
||||||
url_data,
|
url_data,
|
||||||
|
for_supports_rule: false,
|
||||||
};
|
};
|
||||||
let mut input = ParserInput::new(input);
|
let mut input = ParserInput::new(input);
|
||||||
SelectorList::parse(&parser, &mut CssParser::new(&mut input))
|
SelectorList::parse(&parser, &mut CssParser::new(&mut input))
|
||||||
|
|
|
@ -785,6 +785,7 @@ impl<'a, 'b, 'i> QualifiedRuleParser<'i> for NestedRuleParser<'a, 'b> {
|
||||||
stylesheet_origin: self.context.stylesheet_origin,
|
stylesheet_origin: self.context.stylesheet_origin,
|
||||||
namespaces: self.namespaces,
|
namespaces: self.namespaces,
|
||||||
url_data: self.context.url_data,
|
url_data: self.context.url_data,
|
||||||
|
for_supports_rule: false,
|
||||||
};
|
};
|
||||||
let selectors = SelectorList::parse(&selector_parser, input)?;
|
let selectors = SelectorList::parse(&selector_parser, input)?;
|
||||||
if self.context.error_reporting_enabled() {
|
if self.context.error_reporting_enabled() {
|
||||||
|
|
|
@ -385,29 +385,12 @@ impl RawSelector {
|
||||||
namespaces,
|
namespaces,
|
||||||
stylesheet_origin: context.stylesheet_origin,
|
stylesheet_origin: context.stylesheet_origin,
|
||||||
url_data: context.url_data,
|
url_data: context.url_data,
|
||||||
|
for_supports_rule: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[allow(unused_variables)]
|
Selector::<SelectorImpl>::parse(&parser, input)
|
||||||
let selector = Selector::<SelectorImpl>::parse(&parser, input)
|
|
||||||
.map_err(|_| input.new_custom_error(()))?;
|
.map_err(|_| input.new_custom_error(()))?;
|
||||||
|
|
||||||
#[cfg(feature = "gecko")]
|
|
||||||
{
|
|
||||||
use crate::selector_parser::PseudoElement;
|
|
||||||
use selectors::parser::Component;
|
|
||||||
|
|
||||||
let has_any_unknown_webkit_pseudo = selector.has_pseudo_element() &&
|
|
||||||
selector.iter_raw_match_order().any(|component| {
|
|
||||||
matches!(
|
|
||||||
*component,
|
|
||||||
Component::PseudoElement(PseudoElement::UnknownWebkit(..))
|
|
||||||
)
|
|
||||||
});
|
|
||||||
if has_any_unknown_webkit_pseudo {
|
|
||||||
return Err(input.new_custom_error(()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
.is_ok()
|
.is_ok()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue