style: [css-nesting] Do a first pass at parsing nested rules mixed with declarations

Plumb everything up. This factors out declaration and rule parsing so
we share the code with the regular declaration parser.

This could be made a bit nicer in the future. We need to decide what to
do for @page and @keyframe (it seems conditional rules inside ought to
work, but that's not so easy because per spec we create a nested style
rule).

But this is a first pass that passes a good chunk of the tests. There
are other fixups to cssom, and I think some of the tests we fail are
actually wrong...

Differential Revision: https://phabricator.services.mozilla.com/D178266
This commit is contained in:
Emilio Cobos Álvarez 2023-05-17 18:18:29 +00:00 committed by Martin Robinson
parent b92440ef7c
commit 7c4ec6e9cc
13 changed files with 523 additions and 286 deletions

View file

@ -6,7 +6,7 @@
use crate::context::QuirksMode;
use crate::error_reporting::{ContextualParseError, ParseErrorReporter};
use crate::stylesheets::{CssRuleType, Namespaces, Origin, UrlExtraData};
use crate::stylesheets::{CssRuleType, CssRuleTypes, Namespaces, Origin, UrlExtraData};
use crate::use_counters::UseCounters;
use cssparser::{Parser, SourceLocation, UnicodeRange};
use std::borrow::Cow;
@ -45,8 +45,8 @@ pub struct ParserContext<'a> {
pub stylesheet_origin: Origin,
/// The extra data we need for resolving url values.
pub url_data: &'a UrlExtraData,
/// The current rule type, if any.
pub rule_type: Option<CssRuleType>,
/// The current rule types, if any.
pub rule_types: CssRuleTypes,
/// The mode to use when parsing.
pub parsing_mode: ParsingMode,
/// The quirks mode of this stylesheet.
@ -75,7 +75,7 @@ impl<'a> ParserContext<'a> {
Self {
stylesheet_origin,
url_data,
rule_type,
rule_types: rule_type.map(CssRuleTypes::from).unwrap_or_default(),
parsing_mode,
quirks_mode,
error_reporter,
@ -86,23 +86,22 @@ impl<'a> ParserContext<'a> {
/// Temporarily sets the rule_type and executes the callback function, returning its result.
pub fn nest_for_rule<R>(&mut self, rule_type: CssRuleType, cb: impl FnOnce(&mut Self) -> R) -> R {
let old_rule_type = std::mem::replace(&mut self.rule_type, Some(rule_type));
let old_rule_types = self.rule_types;
self.rule_types.insert(rule_type);
let r = cb(self);
self.rule_type = old_rule_type;
self.rule_types = old_rule_types;
r
}
/// Whether we're in a @page rule.
#[inline]
pub fn in_page_rule(&self) -> bool {
self.rule_type
.map_or(false, |rule_type| rule_type == CssRuleType::Page)
self.rule_types.contains(CssRuleType::Page)
}
/// Get the rule type, which assumes that one is available.
pub fn rule_type(&self) -> CssRuleType {
self.rule_type
.expect("Rule type expected, but none was found.")
pub fn rule_types(&self) -> CssRuleTypes {
self.rule_types
}
/// Returns whether CSS error reporting is enabled.