Bug 1835066 - Make our nesting implementation match the new spec better. r=tlouw

Differential Revision: https://phabricator.services.mozilla.com/D179687
This commit is contained in:
Emilio Cobos Álvarez 2023-06-04 10:22:29 +00:00
parent a84f470d7f
commit a01ea76d78
5 changed files with 45 additions and 46 deletions

View File

@ -105,11 +105,6 @@ git = "https://github.com/mozilla/uniffi-rs.git"
rev = "bc7ff8977bf38d0fdd1a458810b14f434d4dc4de"
replace-with = "vendored-sources"
[source."git+https://github.com/servo/rust-cssparser?rev=6ce91afdf292c4290118843e7421e146f0a4c48b"]
git = "https://github.com/servo/rust-cssparser"
rev = "6ce91afdf292c4290118843e7421e146f0a4c48b"
replace-with = "vendored-sources"
# Take advantage of the fact that cargo will treat lines starting with #
# as comments to add preprocessing directives. This file can thus by copied

2
Cargo.lock generated
View File

@ -1004,7 +1004,6 @@ dependencies = [
[[package]]
name = "cssparser"
version = "0.31.0"
source = "git+https://github.com/servo/rust-cssparser?rev=6ce91afdf292c4290118843e7421e146f0a4c48b#6ce91afdf292c4290118843e7421e146f0a4c48b"
dependencies = [
"cssparser-macros",
"dtoa-short",
@ -1019,7 +1018,6 @@ dependencies = [
[[package]]
name = "cssparser-macros"
version = "0.6.0"
source = "git+https://github.com/servo/rust-cssparser?rev=6ce91afdf292c4290118843e7421e146f0a4c48b#6ce91afdf292c4290118843e7421e146f0a4c48b"
dependencies = [
"quote",
"syn",

View File

@ -152,9 +152,11 @@ moz_asserts = { path = "mozglue/static/rust/moz_asserts" }
# Workaround for https://github.com/rust-lang/cargo/issues/11232
rure = { path = "third_party/rust/rure" }
# To-be-published changes.
cssparser = { git = "https://github.com/servo/rust-cssparser", rev = "6ce91afdf292c4290118843e7421e146f0a4c48b" }
cssparser-macros = { git = "https://github.com/servo/rust-cssparser", rev = "6ce91afdf292c4290118843e7421e146f0a4c48b" }
# 0.31.1 but without rust-cssparser#342.
# TODO: Remove these, and just use v0.31.1 once bug 1836219 lands
# (which will get syn 2 into the tree).
cssparser = { path = "third_party/rust/cssparser" }
cssparser-macros = { path = "third_party/rust/cssparser-macros" }
# Other overrides
chardetng = { git = "https://github.com/hsivonen/chardetng", rev="3484d3e3ebdc8931493aa5df4d7ee9360a90e76b" }

View File

@ -37,7 +37,6 @@ smallvec = "1.0"
[dependencies.cssparser-macros]
version = "0.6"
path = "./macros"
[dependencies.phf]
version = ">=0.8,<=0.11"

View File

@ -4,7 +4,9 @@
// https://drafts.csswg.org/css-syntax/#parsing
use super::{BasicParseError, BasicParseErrorKind, Delimiter, Delimiters, ParseError, Parser, Token};
use super::{
BasicParseError, BasicParseErrorKind, Delimiter, Delimiters, ParseError, Parser, Token,
};
use crate::cow_rc_str::CowRcStr;
use crate::parser::{parse_nested_block, parse_until_after, parse_until_before, ParserState};
@ -239,8 +241,7 @@ impl<'i, 't, 'a, P, I, E> RuleBodyParser<'i, 't, 'a, P, I, E> {
}
}
/// `DeclarationListParser` is an iterator that yields `Ok(_)` for a valid declaration or at-rule
/// or `Err(())` for an invalid one.
/// https://drafts.csswg.org/css-syntax/#consume-a-blocks-contents
impl<'i, 't, 'a, I, P, E: 'i> Iterator for RuleBodyParser<'i, 't, 'a, P, I, E>
where
P: RuleBodyItemParser<'i, I, E>,
@ -252,47 +253,51 @@ where
self.input.skip_whitespace();
let start = self.input.state();
match self.input.next_including_whitespace_and_comments().ok()? {
Token::CloseCurlyBracket |
Token::WhiteSpace(..) |
Token::Semicolon |
Token::Comment(..) => continue,
Token::Semicolon if self.parser.parse_declarations() => continue,
Token::Ident(ref name) if self.parser.parse_declarations() => {
let name = name.clone();
let parse_qualified = self.parser.parse_qualified();
let delimiters = if parse_qualified {
Delimiter::Semicolon | Delimiter::CurlyBracketBlock
} else {
Delimiter::Semicolon
};
let mut result = {
let parser = &mut self.parser;
parse_until_after(self.input, delimiters, |input| {
input.expect_colon()?;
parser.parse_value(name, input)
})
};
if result.is_err() && parse_qualified {
self.input.reset(&start);
result =
parse_qualified_rule(&start, self.input, &mut *self.parser, delimiters);
}
return Some(result.map_err(|e| (e, self.input.slice_from(start.position()))));
}
Token::AtKeyword(ref name) => {
let name = name.clone();
return Some(parse_at_rule(&start, name, self.input, &mut *self.parser));
}
token => {
let result = if self.parser.parse_qualified() {
// https://drafts.csswg.org/css-syntax/#consume-a-declaration bails out just to
// keep parsing as a qualified rule if the token is not an ident, so we implement
// that in a slightly more straight-forward way
Token::Ident(ref name) if self.parser.parse_declarations() => {
let name = name.clone();
let result = {
let parser = &mut self.parser;
parse_until_after(self.input, Delimiter::Semicolon, |input| {
input.expect_colon()?;
parser.parse_value(name, input)
})
};
if result.is_err() && self.parser.parse_qualified() {
self.input.reset(&start);
// TODO(emilio, nesting): do we need to, if we fail, consume only until the
// next semicolon, rather than until the next `{`?
parse_qualified_rule(
// We ignore the resulting error here. The property declaration parse error
// is likely to be more relevant.
if let Ok(qual) = parse_qualified_rule(
&start,
self.input,
&mut *self.parser,
Delimiter::CurlyBracketBlock,
)
Delimiter::Semicolon | Delimiter::CurlyBracketBlock,
) {
return Some(Ok(qual))
}
}
return Some(result.map_err(|e| (e, self.input.slice_from(start.position()))));
}
token => {
let result = if self.parser.parse_qualified() {
self.input.reset(&start);
let delimiters = if self.parser.parse_declarations() {
Delimiter::Semicolon | Delimiter::CurlyBracketBlock
} else {
Delimiter::CurlyBracketBlock
};
parse_qualified_rule(&start, self.input, &mut *self.parser, delimiters)
} else {
let token = token.clone();
self.input.parse_until_after(Delimiter::Semicolon, |_| {