diff options
author | Emilio Cobos Álvarez <emilio@crisal.io> | 2023-05-16 18:02:52 +0000 |
---|---|---|
committer | Martin Robinson <mrobinson@igalia.com> | 2023-11-24 08:57:14 +0100 |
commit | 920a1c1f087854dfad786b821494e6a0d52d4a56 (patch) | |
tree | 6fbbad3a935c68570015113244aefc33b553eca1 | |
parent | 32f1989a5caa3c63c2bf4ffadc3f159c79bae173 (diff) | |
download | servo-920a1c1f087854dfad786b821494e6a0d52d4a56.tar.gz servo-920a1c1f087854dfad786b821494e6a0d52d4a56.zip |
style: [css-nesting] Update cssparser again
This changes the cssparser setup to:
* Avoid having to do copies of the ParsingContext all over the place,
which is useful because I plan to stash more nesting state in there.
* Use the new RuleBodyParser which allows parsing qualified rules,
declarations, and so on. Though we still don't use this anywhere.
The next step is to join NestedRuleParser and PropertyDeclarationParser,
so that we can parse declarations in a lot of the nested rules as well.
Differential Revision: https://phabricator.services.mozilla.com/D178053
-rw-r--r-- | components/style/counter_style/mod.rs | 27 | ||||
-rw-r--r-- | components/style/font_face.rs | 15 | ||||
-rw-r--r-- | components/style/parser.rs | 30 | ||||
-rw-r--r-- | components/style/properties/declaration_block.rs | 27 | ||||
-rw-r--r-- | components/style/properties/properties.mako.rs | 1 | ||||
-rw-r--r-- | components/style/stylesheets/font_feature_values_rule.rs | 55 | ||||
-rw-r--r-- | components/style/stylesheets/font_palette_values_rule.rs | 80 | ||||
-rw-r--r-- | components/style/stylesheets/import_rule.rs | 11 | ||||
-rw-r--r-- | components/style/stylesheets/keyframes_rule.rs | 104 | ||||
-rw-r--r-- | components/style/stylesheets/mod.rs | 6 | ||||
-rw-r--r-- | components/style/stylesheets/rule_parser.rs | 232 | ||||
-rw-r--r-- | components/style/stylesheets/stylesheet.rs | 30 | ||||
-rw-r--r-- | components/style/stylesheets/supports_rule.rs | 18 | ||||
-rw-r--r-- | components/style/stylesheets/viewport_rule.rs | 27 | ||||
-rw-r--r-- | components/style/values/specified/mod.rs | 7 |
15 files changed, 335 insertions, 335 deletions
diff --git a/components/style/counter_style/mod.rs b/components/style/counter_style/mod.rs index 216e5e7fec7..e1953477816 100644 --- a/components/style/counter_style/mod.rs +++ b/components/style/counter_style/mod.rs @@ -13,7 +13,7 @@ use crate::str::CssStringWriter; use crate::values::specified::Integer; use crate::values::CustomIdent; use crate::Atom; -use cssparser::{AtRuleParser, DeclarationListParser, DeclarationParser, QualifiedRuleParser}; +use cssparser::{AtRuleParser, RuleBodyParser, RuleBodyItemParser, DeclarationParser, QualifiedRuleParser}; use cssparser::{CowRcStr, Parser, SourceLocation, Token}; use selectors::parser::SelectorParseErrorKind; use std::fmt::{self, Write}; @@ -86,11 +86,11 @@ pub fn parse_counter_style_body<'i, 't>( let start = input.current_source_location(); let mut rule = CounterStyleRuleData::empty(name, location); { - let parser = CounterStyleRuleParser { - context: context, + let mut parser = CounterStyleRuleParser { + context, rule: &mut rule, }; - let mut iter = DeclarationListParser::new(input, parser); + let mut iter = RuleBodyParser::new(input, &mut parser); while let Some(declaration) = iter.next() { if let Err((error, slice)) = declaration { let location = error.location; @@ -159,6 +159,11 @@ impl<'a, 'b, 'i> QualifiedRuleParser<'i> for CounterStyleRuleParser<'a, 'b> { type Error = StyleParseErrorKind<'i>; } +impl<'a, 'b, 'i> RuleBodyItemParser<'i, (), StyleParseErrorKind<'i>> for CounterStyleRuleParser<'a, 'b> { + fn parse_qualified(&self) -> bool { false } + fn parse_declarations(&self) -> bool { true } +} + macro_rules! checker { ($self:ident._($value:ident)) => {}; ($self:ident. $checker:ident($value:ident)) => { @@ -219,15 +224,17 @@ macro_rules! counter_style_descriptors { type Declaration = (); type Error = StyleParseErrorKind<'i>; - fn parse_value<'t>(&mut self, name: CowRcStr<'i>, input: &mut Parser<'i, 't>) - -> Result<(), ParseError<'i>> { + fn parse_value<'t>( + &mut self, + name: CowRcStr<'i>, + input: &mut Parser<'i, 't>, + ) -> Result<(), ParseError<'i>> { match_ignore_ascii_case! { &*name, $( $name => { - // DeclarationParser also calls parse_entirely - // so we’d normally not need to, - // but in this case we do because we set the value as a side effect - // rather than returning it. + // DeclarationParser also calls parse_entirely so we’d normally not + // need to, but in this case we do because we set the value as a side + // effect rather than returning it. let value = input.parse_entirely(|i| Parse::parse(self.context, i))?; self.rule.$ident = Some(value) }, diff --git a/components/style/font_face.rs b/components/style/font_face.rs index bcf8b91591e..2166523656b 100644 --- a/components/style/font_face.rs +++ b/components/style/font_face.rs @@ -27,8 +27,8 @@ use crate::values::specified::NonNegativePercentage; #[cfg(feature = "gecko")] use cssparser::UnicodeRange; use cssparser::{ - AtRuleParser, CowRcStr, DeclarationListParser, DeclarationParser, Parser, QualifiedRuleParser, - SourceLocation, + AtRuleParser, CowRcStr, RuleBodyParser, RuleBodyItemParser, DeclarationParser, Parser, + QualifiedRuleParser, SourceLocation, }; use selectors::parser::SelectorParseErrorKind; use std::fmt::{self, Write}; @@ -470,11 +470,11 @@ pub fn parse_font_face_block( ) -> FontFaceRuleData { let mut rule = FontFaceRuleData::empty(location); { - let parser = FontFaceRuleParser { - context: context, + let mut parser = FontFaceRuleParser { + context, rule: &mut rule, }; - let mut iter = DeclarationListParser::new(input, parser); + let mut iter = RuleBodyParser::new(input, &mut parser); while let Some(declaration) = iter.next() { if let Err((error, slice)) = declaration { let location = error.location; @@ -566,6 +566,11 @@ impl<'a, 'b, 'i> QualifiedRuleParser<'i> for FontFaceRuleParser<'a, 'b> { type Error = StyleParseErrorKind<'i>; } +impl<'a, 'b, 'i> RuleBodyItemParser<'i, (), StyleParseErrorKind<'i>> for FontFaceRuleParser<'a, 'b> { + fn parse_qualified(&self) -> bool { false } + fn parse_declarations(&self) -> bool { true } +} + fn font_tech_enabled() -> bool { #[cfg(feature = "gecko")] return static_prefs::pref!("layout.css.font-tech.enabled"); diff --git a/components/style/parser.rs b/components/style/parser.rs index 837b9740024..11ef4b51a68 100644 --- a/components/style/parser.rs +++ b/components/style/parser.rs @@ -9,6 +9,7 @@ use crate::error_reporting::{ContextualParseError, ParseErrorReporter}; use crate::stylesheets::{CssRuleType, Namespaces, Origin, UrlExtraData}; use crate::use_counters::UseCounters; use cssparser::{Parser, SourceLocation, UnicodeRange}; +use std::borrow::Cow; use style_traits::{OneOrMoreSeparated, ParseError, ParsingMode, Separator}; /// Asserts that all ParsingMode flags have a matching ParsingMode value in gecko. @@ -53,7 +54,7 @@ pub struct ParserContext<'a> { /// The active error reporter, or none if error reporting is disabled. error_reporter: Option<&'a dyn ParseErrorReporter>, /// The currently active namespaces. - pub namespaces: Option<&'a Namespaces>, + pub namespaces: Cow<'a, Namespaces>, /// The use counters we want to record while parsing style rules, if any. pub use_counters: Option<&'a UseCounters>, } @@ -67,6 +68,7 @@ impl<'a> ParserContext<'a> { rule_type: Option<CssRuleType>, parsing_mode: ParsingMode, quirks_mode: QuirksMode, + namespaces: Cow<'a, Namespaces>, error_reporter: Option<&'a dyn ParseErrorReporter>, use_counters: Option<&'a UseCounters>, ) -> Self { @@ -77,29 +79,17 @@ impl<'a> ParserContext<'a> { parsing_mode, quirks_mode, error_reporter, - namespaces: None, + namespaces, use_counters, } } - /// Create a parser context based on a previous context, but with a modified - /// rule type. - #[inline] - pub fn new_with_rule_type( - context: &'a ParserContext, - rule_type: CssRuleType, - namespaces: &'a Namespaces, - ) -> ParserContext<'a> { - Self { - stylesheet_origin: context.stylesheet_origin, - url_data: context.url_data, - rule_type: Some(rule_type), - parsing_mode: context.parsing_mode, - quirks_mode: context.quirks_mode, - namespaces: Some(namespaces), - error_reporter: context.error_reporter, - use_counters: context.use_counters, - } + /// 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 r = cb(self); + self.rule_type = old_rule_type; + r } /// Whether we're in a @page rule. diff --git a/components/style/properties/declaration_block.rs b/components/style/properties/declaration_block.rs index 7f35ee6410a..68f69f04eda 100644 --- a/components/style/properties/declaration_block.rs +++ b/components/style/properties/declaration_block.rs @@ -26,8 +26,8 @@ use crate::str::{CssString, CssStringWriter}; use crate::stylesheets::{layer_rule::LayerOrder, CssRuleType, Origin, UrlExtraData}; use crate::values::computed::Context; use cssparser::{ - parse_important, AtRuleParser, CowRcStr, DeclarationListParser, DeclarationParser, Delimiter, - ParseErrorKind, Parser, ParserInput, QualifiedRuleParser, + parse_important, AtRuleParser, CowRcStr, DeclarationParser, Delimiter, ParseErrorKind, Parser, + ParserInput, QualifiedRuleParser, RuleBodyItemParser, RuleBodyParser, }; use itertools::Itertools; use selectors::SelectorList; @@ -582,8 +582,9 @@ impl PropertyDeclarationBlock { .all_shorthand .declarations() .any(|decl| { - !self.contains(decl.id()) || - self.declarations + !self.contains(decl.id()) + || self + .declarations .iter() .enumerate() .find(|&(_, ref d)| d.id() == decl.id()) @@ -625,9 +626,9 @@ impl PropertyDeclarationBlock { } return DeclarationUpdate::UpdateInPlace { pos }; } - if !needs_append && - id.logical_group() == Some(logical_group) && - id.is_logical() != longhand_id.is_logical() + if !needs_append + && id.logical_group() == Some(logical_group) + && id.is_logical() != longhand_id.is_logical() { needs_append = true; } @@ -1292,6 +1293,7 @@ pub fn parse_style_attribute( Some(rule_type), ParsingMode::DEFAULT, quirks_mode, + /* namespaces = */ Default::default(), error_reporter, None, ); @@ -1322,6 +1324,7 @@ pub fn parse_one_declaration_into( Some(rule_type), parsing_mode, quirks_mode, + /* namespaces = */ Default::default(), error_reporter, None, ); @@ -1411,6 +1414,12 @@ impl<'a, 'b, 'i> DeclarationParser<'i> for PropertyDeclarationParser<'a, 'b> { } } +impl<'a, 'b, 'i> RuleBodyItemParser<'i, Importance, StyleParseErrorKind<'i>> for PropertyDeclarationParser<'a, 'b> { + fn parse_declarations(&self) -> bool { true } + // TODO(emilio): Nesting. + fn parse_qualified(&self) -> bool { false } +} + type SmallParseErrorVec<'i> = SmallVec<[(ParseError<'i>, &'i str, Option<PropertyId>); 2]>; fn alias_of_known_property(name: &str) -> Option<PropertyId> { @@ -1498,12 +1507,12 @@ pub fn parse_property_declaration_list( ) -> PropertyDeclarationBlock { let mut declarations = SourcePropertyDeclaration::new(); let mut block = PropertyDeclarationBlock::new(); - let parser = PropertyDeclarationParser { + let mut parser = PropertyDeclarationParser { context, last_parsed_property_id: None, declarations: &mut declarations, }; - let mut iter = DeclarationListParser::new(input, parser); + let mut iter = RuleBodyParser::new(input, &mut parser); let mut errors = SmallParseErrorVec::new(); while let Some(declaration) = iter.next() { match declaration { diff --git a/components/style/properties/properties.mako.rs b/components/style/properties/properties.mako.rs index c34569a41ed..a6d713193c1 100644 --- a/components/style/properties/properties.mako.rs +++ b/components/style/properties/properties.mako.rs @@ -1769,6 +1769,7 @@ impl UnparsedValue { None, ParsingMode::DEFAULT, quirks_mode, + /* namespaces = */ Default::default(), None, None, ); diff --git a/components/style/stylesheets/font_feature_values_rule.rs b/components/style/stylesheets/font_feature_values_rule.rs index 093539162fe..f5ce737e068 100644 --- a/components/style/stylesheets/font_feature_values_rule.rs +++ b/components/style/stylesheets/font_feature_values_rule.rs @@ -19,8 +19,8 @@ use crate::values::computed::font::FamilyName; use crate::values::serialize_atom_identifier; use crate::Atom; use cssparser::{ - AtRuleParser, BasicParseErrorKind, CowRcStr, DeclarationListParser, DeclarationParser, Parser, - ParserState, QualifiedRuleParser, RuleListParser, SourceLocation, Token, + AtRuleParser, BasicParseErrorKind, CowRcStr, RuleBodyParser, RuleBodyItemParser, Parser, + ParserState, QualifiedRuleParser, DeclarationParser, SourceLocation, Token, }; use std::fmt::{self, Write}; use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss}; @@ -215,13 +215,21 @@ where let value = input.parse_entirely(|i| T::parse(self.context, i))?; let new = FFVDeclaration { name: Atom::from(&*name), - value: value, + value, }; update_or_push(&mut self.declarations, new); Ok(()) } } +impl<'a, 'b, 'i, T> RuleBodyItemParser<'i, (), StyleParseErrorKind<'i>> for FFVDeclarationsParser<'a, 'b, T> +where + T: Parse, +{ + fn parse_declarations(&self) -> bool { true } + fn parse_qualified(&self) -> bool { false } +} + macro_rules! font_feature_values_blocks { ( blocks = [ @@ -265,18 +273,16 @@ macro_rules! font_feature_values_blocks { location: SourceLocation, ) -> Self { let mut rule = FontFeatureValuesRule::new(family_names, location); - - { - let mut iter = RuleListParser::new_for_nested_rule(input, FontFeatureValuesRuleParser { - context: context, - rule: &mut rule, - }); - while let Some(result) = iter.next() { - if let Err((error, slice)) = result { - let location = error.location; - let error = ContextualParseError::UnsupportedRule(slice, error); - context.log_css_error(location, error); - } + let mut parser = FontFeatureValuesRuleParser { + context, + rule: &mut rule, + }; + let mut iter = RuleBodyParser::new(input, &mut parser); + while let Some(result) = iter.next() { + if let Err((error, slice)) = result { + let location = error.location; + let error = ContextualParseError::UnsupportedRule(slice, error); + context.log_css_error(location, error); } } rule @@ -348,9 +354,8 @@ macro_rules! font_feature_values_blocks { /// Updates with new value if same `ident` exists, otherwise pushes to the vector. fn update_or_push<T>(vec: &mut Vec<FFVDeclaration<T>>, element: FFVDeclaration<T>) { - let position = vec.iter().position(|ref val| val.name == element.name); - if let Some(index) = position { - vec[index].value = element.value; + if let Some(item) = vec.iter_mut().find(|item| item.name == element.name) { + item.value = element.value; } else { vec.push(element); } @@ -409,12 +414,12 @@ macro_rules! font_feature_values_blocks { match prelude { $( BlockType::$ident_camel => { - let parser = FFVDeclarationsParser { + let mut parser = FFVDeclarationsParser { context: &self.context, declarations: &mut self.rule.$ident, }; - let mut iter = DeclarationListParser::new(input, parser); + let mut iter = RuleBodyParser::new(input, &mut parser); while let Some(declaration) = iter.next() { if let Err((error, slice)) = declaration { let location = error.location; @@ -431,6 +436,16 @@ macro_rules! font_feature_values_blocks { Ok(()) } } + + impl<'a, 'i> DeclarationParser<'i> for FontFeatureValuesRuleParser<'a> { + type Declaration = (); + type Error = StyleParseErrorKind<'i>; + } + + impl<'a, 'i> RuleBodyItemParser<'i, (), StyleParseErrorKind<'i>> for FontFeatureValuesRuleParser<'a> { + fn parse_declarations(&self) -> bool { false } + fn parse_qualified(&self) -> bool { true } + } } } diff --git a/components/style/stylesheets/font_palette_values_rule.rs b/components/style/stylesheets/font_palette_values_rule.rs index 55a4ebd4e3b..c604f9b3c6e 100644 --- a/components/style/stylesheets/font_palette_values_rule.rs +++ b/components/style/stylesheets/font_palette_values_rule.rs @@ -7,7 +7,6 @@ //! [font-palette-values]: https://drafts.csswg.org/css-fonts/#font-palette-values use crate::error_reporting::ContextualParseError; -use crate::parser::{Parse, ParserContext}; #[cfg(feature = "gecko")] use crate::gecko_bindings::{ bindings::Gecko_AppendPaletteValueHashEntry, @@ -16,20 +15,22 @@ use crate::gecko_bindings::{ structs::gfx::FontPaletteValueSet_PaletteValues_kDark, structs::gfx::FontPaletteValueSet_PaletteValues_kLight, }; +use crate::parser::{Parse, ParserContext}; use crate::shared_lock::{SharedRwLockReadGuard, ToCssWithGuard}; use crate::str::CssStringWriter; +use crate::stylesheets::font_feature_values_rule::parse_family_name_list; use crate::values::computed::font::FamilyName; use crate::values::specified::Color as SpecifiedColor; use crate::values::specified::NonNegativeInteger; use crate::values::DashedIdent; -use cssparser::{AtRuleParser, CowRcStr}; -use cssparser::{DeclarationParser, DeclarationListParser, Parser}; -use cssparser::{QualifiedRuleParser, SourceLocation}; +use cssparser::{ + AtRuleParser, CowRcStr, DeclarationParser, Parser, QualifiedRuleParser, RuleBodyItemParser, + RuleBodyParser, SourceLocation, +}; +use selectors::parser::SelectorParseErrorKind; use std::fmt::{self, Write}; -use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss}; use style_traits::{Comma, OneOrMoreSeparated}; -use selectors::parser::SelectorParseErrorKind; -use crate::stylesheets::font_feature_values_rule::parse_family_name_list; +use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss}; #[allow(missing_docs)] #[derive(Clone, Debug, MallocSizeOf, PartialEq, ToShmem)] @@ -121,18 +122,17 @@ impl FontPaletteValuesRule { location: SourceLocation, ) -> Self { let mut rule = FontPaletteValuesRule::new(name, location); - { - let parser = FontPaletteValuesDeclarationParser { - context: context, - rule: &mut rule, - }; - let mut iter = DeclarationListParser::new(input, parser); - while let Some(declaration) = iter.next() { - if let Err((error, slice)) = declaration { - let location = error.location; - let error = ContextualParseError::UnsupportedFontPaletteValuesDescriptor(slice, error); - context.log_css_error(location, error); - } + let mut parser = FontPaletteValuesDeclarationParser { + context, + rule: &mut rule, + }; + let mut iter = RuleBodyParser::new(input, &mut parser); + while let Some(declaration) = iter.next() { + if let Err((error, slice)) = declaration { + let location = error.location; + let error = + ContextualParseError::UnsupportedFontPaletteValuesDescriptor(slice, error); + context.log_css_error(location, error); } } rule @@ -167,19 +167,18 @@ impl FontPaletteValuesRule { for ref family in self.family_names.iter() { let family = family.name.to_ascii_lowercase(); let palette_values = unsafe { - Gecko_AppendPaletteValueHashEntry( - dest, - family.as_ptr(), - self.name.0.as_ptr() - ) + Gecko_AppendPaletteValueHashEntry(dest, family.as_ptr(), self.name.0.as_ptr()) }; if let Some(base_palette) = &self.base_palette { unsafe { - Gecko_SetFontPaletteBase(palette_values, match &base_palette { - FontPaletteBase::Light => FontPaletteValueSet_PaletteValues_kLight, - FontPaletteBase::Dark => FontPaletteValueSet_PaletteValues_kDark, - FontPaletteBase::Index(i) => i.0.value() as i32, - }); + Gecko_SetFontPaletteBase( + palette_values, + match &base_palette { + FontPaletteBase::Light => FontPaletteValueSet_PaletteValues_kLight, + FontPaletteBase::Dark => FontPaletteValueSet_PaletteValues_kDark, + FontPaletteBase::Index(i) => i.0.value() as i32, + }, + ); } } for c in &self.override_colors { @@ -233,13 +232,13 @@ fn parse_override_colors<'i, 't>( } impl<'a, 'b, 'i> DeclarationParser<'i> for FontPaletteValuesDeclarationParser<'a> { - type Declaration = (); - type Error = StyleParseErrorKind<'i>; + type Declaration = (); + type Error = StyleParseErrorKind<'i>; - fn parse_value<'t>( - &mut self, - name: CowRcStr<'i>, - input: &mut Parser<'i, 't>, + fn parse_value<'t>( + &mut self, + name: CowRcStr<'i>, + input: &mut Parser<'i, 't>, ) -> Result<(), ParseError<'i>> { match_ignore_ascii_case! { &*name, "font-family" => { @@ -256,3 +255,14 @@ impl<'a, 'b, 'i> DeclarationParser<'i> for FontPaletteValuesDeclarationParser<'a Ok(()) } } + +impl<'a, 'i> RuleBodyItemParser<'i, (), StyleParseErrorKind<'i>> + for FontPaletteValuesDeclarationParser<'a> +{ + fn parse_declarations(&self) -> bool { + true + } + fn parse_qualified(&self) -> bool { + false + } +} diff --git a/components/style/stylesheets/import_rule.rs b/components/style/stylesheets/import_rule.rs index 1e9245d5c27..6af4e0bf93e 100644 --- a/components/style/stylesheets/import_rule.rs +++ b/components/style/stylesheets/import_rule.rs @@ -13,7 +13,7 @@ use crate::shared_lock::{ }; use crate::str::CssStringWriter; use crate::stylesheets::{ - layer_rule::LayerName, stylesheet::Namespaces, supports_rule::SupportsCondition, CssRule, + layer_rule::LayerName, supports_rule::SupportsCondition, CssRule, CssRuleType, StylesheetInDocument, }; use crate::values::CssUrl; @@ -243,8 +243,7 @@ impl ImportRule { /// whole import rule or parse the media query list or what not. pub fn parse_layer_and_supports<'i, 't>( input: &mut Parser<'i, 't>, - context: &ParserContext, - namespaces: &Namespaces, + context: &mut ParserContext, ) -> (ImportLayer, Option<ImportSupportsCondition>) { let layer = if input .try_parse(|input| input.expect_ident_matching("layer")) @@ -273,9 +272,9 @@ impl ImportRule { input .try_parse(SupportsCondition::parse_for_import) .map(|condition| { - let eval_context = - ParserContext::new_with_rule_type(context, CssRuleType::Style, namespaces); - let enabled = condition.eval(&eval_context, namespaces); + let enabled = context.nest_for_rule(CssRuleType::Style, |context| { + condition.eval(context) + }); ImportSupportsCondition { condition, enabled } }) .ok() diff --git a/components/style/stylesheets/keyframes_rule.rs b/components/style/stylesheets/keyframes_rule.rs index d44a7b13f14..0b61ba65528 100644 --- a/components/style/stylesheets/keyframes_rule.rs +++ b/components/style/stylesheets/keyframes_rule.rs @@ -19,11 +19,12 @@ use crate::stylesheets::rule_parser::VendorPrefix; use crate::stylesheets::{CssRuleType, StylesheetContents}; use crate::values::{serialize_percentage, KeyframesName}; use cssparser::{ - parse_one_rule, DeclarationListParser, DeclarationParser, ParserState, SourceLocation, Token, + parse_one_rule, AtRuleParser, CowRcStr, DeclarationParser, Parser, ParserInput, ParserState, + QualifiedRuleParser, RuleBodyItemParser, RuleBodyParser, SourceLocation, Token, }; -use cssparser::{AtRuleParser, CowRcStr, Parser, ParserInput, QualifiedRuleParser, RuleListParser}; use servo_arc::Arc; use std::fmt::{self, Write}; +use std::borrow::Cow; use style_traits::{CssWriter, ParseError, ParsingMode, StyleParseErrorKind, ToCss}; /// A [`@keyframes`][keyframes] rule. @@ -217,16 +218,16 @@ impl Keyframe { Some(CssRuleType::Keyframe), ParsingMode::DEFAULT, parent_stylesheet_contents.quirks_mode, + Cow::Borrowed(&*namespaces), None, None, ); - context.namespaces = Some(&*namespaces); let mut input = ParserInput::new(css); let mut input = Parser::new(&mut input); let mut declarations = SourcePropertyDeclaration::new(); let mut rule_parser = KeyframeListParser { - context: &context, + context: &mut context, shared_lock: &lock, declarations: &mut declarations, }; @@ -526,43 +527,39 @@ impl KeyframesAnimation { /// 40%, 60%, 100% { /// width: 100%; /// } -struct KeyframeListParser<'a> { - context: &'a ParserContext<'a>, +struct KeyframeListParser<'a, 'b> { + context: &'a mut ParserContext<'b>, shared_lock: &'a SharedRwLock, declarations: &'a mut SourcePropertyDeclaration, } /// Parses a keyframe list from CSS input. -pub fn parse_keyframe_list( - context: &ParserContext, +pub fn parse_keyframe_list<'a>( + context: &mut ParserContext<'a>, input: &mut Parser, shared_lock: &SharedRwLock, ) -> Vec<Arc<Locked<Keyframe>>> { - debug_assert!( - context.namespaces.is_some(), - "Parsing a keyframe list from a context without namespaces?" - ); - let mut declarations = SourcePropertyDeclaration::new(); - RuleListParser::new_for_nested_rule( - input, - KeyframeListParser { - context, - shared_lock, - declarations: &mut declarations, - }, - ) - .filter_map(Result::ok) - .collect() + let mut parser = KeyframeListParser { + context, + shared_lock, + declarations: &mut declarations, + }; + RuleBodyParser::new(input, &mut parser).filter_map(Result::ok) .collect() } -impl<'a, 'i> AtRuleParser<'i> for KeyframeListParser<'a> { +impl<'a, 'b, 'i> AtRuleParser<'i> for KeyframeListParser<'a, 'b> { type Prelude = (); type AtRule = Arc<Locked<Keyframe>>; type Error = StyleParseErrorKind<'i>; } -impl<'a, 'i> QualifiedRuleParser<'i> for KeyframeListParser<'a> { +impl<'a, 'b, 'i> DeclarationParser<'i> for KeyframeListParser<'a, 'b> { + type Declaration = Arc<Locked<Keyframe>>; + type Error = StyleParseErrorKind<'i>; +} + +impl<'a, 'b, 'i> QualifiedRuleParser<'i> for KeyframeListParser<'a, 'b> { type Prelude = KeyframeSelector; type QualifiedRule = Arc<Locked<Keyframe>>; type Error = StyleParseErrorKind<'i>; @@ -589,33 +586,30 @@ impl<'a, 'i> QualifiedRuleParser<'i> for KeyframeListParser<'a> { start: &ParserState, input: &mut Parser<'i, 't>, ) -> Result<Self::QualifiedRule, ParseError<'i>> { - let context = ParserContext::new_with_rule_type( - self.context, - CssRuleType::Keyframe, - self.context.namespaces.unwrap(), - ); - - let parser = KeyframeDeclarationParser { - context: &context, - declarations: self.declarations, - }; - let mut iter = DeclarationListParser::new(input, parser); let mut block = PropertyDeclarationBlock::new(); - while let Some(declaration) = iter.next() { - match declaration { - Ok(()) => { - block.extend(iter.parser.declarations.drain(), Importance::Normal); - }, - Err((error, slice)) => { - iter.parser.declarations.clear(); - let location = error.location; - let error = - ContextualParseError::UnsupportedKeyframePropertyDeclaration(slice, error); - context.log_css_error(location, error); - }, + let declarations = &mut self.declarations; + self.context.nest_for_rule(CssRuleType::Keyframe, |context| { + let mut parser = KeyframeDeclarationParser { + context: &context, + declarations, + }; + let mut iter = RuleBodyParser::new(input, &mut parser); + while let Some(declaration) = iter.next() { + match declaration { + Ok(()) => { + block.extend(iter.parser.declarations.drain(), Importance::Normal); + }, + Err((error, slice)) => { + iter.parser.declarations.clear(); + let location = error.location; + let error = + ContextualParseError::UnsupportedKeyframePropertyDeclaration(slice, error); + context.log_css_error(location, error); + }, + } + // `parse_important` is not called here, `!important` is not allowed in keyframe blocks. } - // `parse_important` is not called here, `!important` is not allowed in keyframe blocks. - } + }); Ok(Arc::new(self.shared_lock.wrap(Keyframe { selector, block: Arc::new(self.shared_lock.wrap(block)), @@ -624,6 +618,11 @@ impl<'a, 'i> QualifiedRuleParser<'i> for KeyframeListParser<'a> { } } +impl<'a, 'b, 'i> RuleBodyItemParser<'i, Arc<Locked<Keyframe>>, StyleParseErrorKind<'i>> for KeyframeListParser<'a, 'b> { + fn parse_qualified(&self) -> bool { true } + fn parse_declarations(&self) -> bool { false } +} + struct KeyframeDeclarationParser<'a, 'b: 'a> { context: &'a ParserContext<'b>, declarations: &'a mut SourcePropertyDeclaration, @@ -668,3 +667,8 @@ impl<'a, 'b, 'i> DeclarationParser<'i> for KeyframeDeclarationParser<'a, 'b> { Ok(()) } } + +impl<'a, 'b, 'i> RuleBodyItemParser<'i, (), StyleParseErrorKind<'i>> for KeyframeDeclarationParser<'a, 'b> { + fn parse_qualified(&self) -> bool { false } + fn parse_declarations(&self) -> bool { true } +} diff --git a/components/style/stylesheets/mod.rs b/components/style/stylesheets/mod.rs index 01b0c07d7a9..34c8403fc7d 100644 --- a/components/style/stylesheets/mod.rs +++ b/components/style/stylesheets/mod.rs @@ -39,6 +39,7 @@ use cssparser::{parse_one_rule, Parser, ParserInput}; #[cfg(feature = "gecko")] use malloc_size_of::{MallocSizeOfOps, MallocUnconditionalShallowSizeOf}; use servo_arc::Arc; +use std::borrow::Cow; use std::fmt; #[cfg(feature = "gecko")] use std::mem::{self, ManuallyDrop}; @@ -401,12 +402,14 @@ impl CssRule { allow_import_rules: AllowImportRules, ) -> Result<Self, RulesMutateError> { let url_data = parent_stylesheet_contents.url_data.read(); + let namespaces = parent_stylesheet_contents.namespaces.read(); let context = ParserContext::new( parent_stylesheet_contents.origin, &url_data, None, ParsingMode::DEFAULT, parent_stylesheet_contents.quirks_mode, + Cow::Borrowed(&*namespaces), None, None, ); @@ -414,8 +417,6 @@ impl CssRule { let mut input = ParserInput::new(css); let mut input = Parser::new(&mut input); - let mut guard = parent_stylesheet_contents.namespaces.write(); - // nested rules are in the body state let mut rule_parser = TopLevelRuleParser { context, @@ -423,7 +424,6 @@ impl CssRule { loader, state, dom_error: None, - namespaces: &mut *guard, insert_rule_context: Some(insert_rule_context), allow_import_rules, }; diff --git a/components/style/stylesheets/rule_parser.rs b/components/style/stylesheets/rule_parser.rs index e4000045d11..9b8afbb842a 100644 --- a/components/style/stylesheets/rule_parser.rs +++ b/components/style/stylesheets/rule_parser.rs @@ -19,7 +19,6 @@ use crate::stylesheets::font_feature_values_rule::parse_family_name_list; use crate::stylesheets::import_rule::{ImportRule, ImportLayer, ImportSupportsCondition}; use crate::stylesheets::keyframes_rule::parse_keyframe_list; use crate::stylesheets::layer_rule::{LayerBlockRule, LayerName, LayerStatementRule}; -use crate::stylesheets::stylesheet::Namespaces; use crate::stylesheets::supports_rule::SupportsCondition; use crate::stylesheets::{ viewport_rule, AllowImportRules, CorsMode, CssRule, CssRuleType, CssRules, DocumentRule, @@ -31,8 +30,8 @@ use crate::values::computed::font::FamilyName; use crate::values::{CssUrl, CustomIdent, DashedIdent, KeyframesName}; use crate::{Namespace, Prefix}; use cssparser::{ - AtRuleParser, BasicParseError, BasicParseErrorKind, CowRcStr, Parser, ParserState, - QualifiedRuleParser, RuleListParser, SourcePosition, + AtRuleParser, BasicParseError, BasicParseErrorKind, CowRcStr, DeclarationParser, Parser, + ParserState, QualifiedRuleParser, RuleBodyParser, RuleBodyItemParser, SourcePosition, }; use selectors::SelectorList; use servo_arc::Arc; @@ -83,9 +82,6 @@ pub struct TopLevelRuleParser<'a> { /// A reference to a stylesheet loader if applicable, for `@import` rules. pub loader: Option<&'a dyn StylesheetLoader>, /// The top-level parser context. - /// - /// This won't contain any namespaces, and only nested parsers created with - /// `ParserContext::new_with_rule_type` will. pub context: ParserContext<'a>, /// The current state of the parser. pub state: State, @@ -93,22 +89,17 @@ pub struct TopLevelRuleParser<'a> { /// place (e.g. an @import rule was found while in the `Body` state). Reset /// to `false` when `take_had_hierarchy_error` is called. pub dom_error: Option<RulesMutateError>, - /// The namespace map we use for parsing. Needs to start as `Some()`, and - /// will be taken out after parsing namespace rules, and that reference will - /// be moved to `ParserContext`. - pub namespaces: &'a mut Namespaces, /// The info we need insert a rule in a list. pub insert_rule_context: Option<InsertRuleContext<'a>>, /// Whether @import rules will be allowed. pub allow_import_rules: AllowImportRules, } -impl<'b> TopLevelRuleParser<'b> { - fn nested<'a: 'b>(&'a self) -> NestedRuleParser<'a, 'b> { +impl<'a> TopLevelRuleParser<'a> { + fn nested<'b>(&'b mut self) -> NestedRuleParser<'b, 'a> { NestedRuleParser { shared_lock: self.shared_lock, - context: &self.context, - namespaces: &self.namespaces, + context: &mut self.context, } } @@ -241,7 +232,7 @@ impl<'a, 'i> AtRuleParser<'i> for TopLevelRuleParser<'a> { let url_string = input.expect_url_or_string()?.as_ref().to_owned(); let url = CssUrl::parse_from_string(url_string, &self.context, CorsMode::None); - let (layer, supports) = ImportRule::parse_layer_and_supports(input, &self.context, self.namespaces); + let (layer, supports) = ImportRule::parse_layer_and_supports(input, &mut self.context); let media = MediaList::parse(&self.context, input); let media = Arc::new(self.shared_lock.wrap(media)); @@ -334,11 +325,12 @@ impl<'a, 'i> AtRuleParser<'i> for TopLevelRuleParser<'a> { CssRule::Import(import_rule) }, AtRulePrelude::Namespace(prefix, url) => { + let namespaces = self.context.namespaces.to_mut(); let prefix = if let Some(prefix) = prefix { - self.namespaces.prefixes.insert(prefix.clone(), url.clone()); + namespaces.prefixes.insert(prefix.clone(), url.clone()); Some(prefix) } else { - self.namespaces.default = Some(url.clone()); + namespaces.default = Some(url.clone()); None }; @@ -398,40 +390,40 @@ impl<'a, 'i> QualifiedRuleParser<'i> for TopLevelRuleParser<'a> { } } -#[derive(Clone)] // shallow, relatively cheap .clone struct NestedRuleParser<'a, 'b: 'a> { shared_lock: &'a SharedRwLock, - context: &'a ParserContext<'b>, - namespaces: &'a Namespaces, + context: &'a mut ParserContext<'b>, } impl<'a, 'b> NestedRuleParser<'a, 'b> { + fn nest_for_rule<R>(&mut self, rule_type: CssRuleType, cb: impl FnOnce(&mut Self) -> R) -> R { + let old_rule_type = self.context.rule_type.take(); + self.context.rule_type = Some(rule_type); + let r = cb(self); + self.context.rule_type = old_rule_type; + r + } + fn parse_nested_rules( &mut self, input: &mut Parser, rule_type: CssRuleType, ) -> Arc<Locked<CssRules>> { - let context = ParserContext::new_with_rule_type(self.context, rule_type, self.namespaces); - - let nested_parser = NestedRuleParser { - shared_lock: self.shared_lock, - context: &context, - namespaces: self.namespaces, - }; - - let mut iter = RuleListParser::new_for_nested_rule(input, nested_parser); - let mut rules = Vec::new(); - while let Some(result) = iter.next() { - match result { - Ok(rule) => rules.push(rule), - Err((error, slice)) => { - let location = error.location; - let error = ContextualParseError::InvalidRule(slice, error); - self.context.log_css_error(location, error); - }, + self.nest_for_rule(rule_type, |parser| { + let mut iter = RuleBodyParser::new(input, parser); + let mut rules = Vec::new(); + while let Some(result) = iter.next() { + match result { + Ok(rule) => rules.push(rule), + Err((error, slice)) => { + let location = error.location; + let error = ContextualParseError::InvalidRule(slice, error); + iter.parser.context.log_css_error(location, error); + }, + } } - } - CssRules::new(rules, self.shared_lock) + CssRules::new(rules, iter.parser.shared_lock) + }) } } @@ -536,61 +528,45 @@ impl<'a, 'b, 'i> AtRuleParser<'i> for NestedRuleParser<'a, 'b> { ) -> Result<CssRule, ParseError<'i>> { match prelude { AtRulePrelude::FontFace => { - let context = ParserContext::new_with_rule_type( - self.context, - CssRuleType::FontFace, - self.namespaces, - ); - - Ok(CssRule::FontFace(Arc::new(self.shared_lock.wrap( - parse_font_face_block(&context, input, start.source_location()).into(), - )))) + self.nest_for_rule(CssRuleType::FontFace, |p| { + Ok(CssRule::FontFace(Arc::new(p.shared_lock.wrap( + parse_font_face_block(&p.context, input, start.source_location()).into(), + )))) + }) }, AtRulePrelude::FontFeatureValues(family_names) => { - let context = ParserContext::new_with_rule_type( - self.context, - CssRuleType::FontFeatureValues, - self.namespaces, - ); - - Ok(CssRule::FontFeatureValues(Arc::new(self.shared_lock.wrap( - FontFeatureValuesRule::parse( - &context, - input, - family_names, - start.source_location(), - ), - )))) + self.nest_for_rule(CssRuleType::FontFeatureValues, |p| { + Ok(CssRule::FontFeatureValues(Arc::new(p.shared_lock.wrap( + FontFeatureValuesRule::parse( + &p.context, + input, + family_names, + start.source_location(), + ), + )))) + }) }, AtRulePrelude::FontPaletteValues(name) => { - let context = ParserContext::new_with_rule_type( - self.context, - CssRuleType::FontPaletteValues, - self.namespaces, - ); - - Ok(CssRule::FontPaletteValues(Arc::new(self.shared_lock.wrap( - FontPaletteValuesRule::parse( - &context, - input, - name, - start.source_location(), - ), - )))) + self.nest_for_rule(CssRuleType::FontPaletteValues, |p| { + Ok(CssRule::FontPaletteValues(Arc::new(p.shared_lock.wrap( + FontPaletteValuesRule::parse( + &p.context, + input, + name, + start.source_location(), + ), + )))) + }) }, AtRulePrelude::CounterStyle(name) => { - let context = ParserContext::new_with_rule_type( - self.context, - CssRuleType::CounterStyle, - self.namespaces, - ); - - Ok(CssRule::CounterStyle(Arc::new( - self.shared_lock.wrap( - parse_counter_style_body(name, &context, input, start.source_location())? - .into(), - ), - ))) + self.nest_for_rule(CssRuleType::CounterStyle, |p| { + Ok(CssRule::CounterStyle(Arc::new( + p.shared_lock.wrap( + parse_counter_style_body(name, &p.context, input, start.source_location())? + .into(), + ), + ))) + }) }, AtRulePrelude::Media(media_queries) => { Ok(CssRule::Media(Arc::new(self.shared_lock.wrap(MediaRule { @@ -600,13 +576,9 @@ impl<'a, 'b, 'i> AtRuleParser<'i> for NestedRuleParser<'a, 'b> { })))) }, AtRulePrelude::Supports(condition) => { - let eval_context = ParserContext::new_with_rule_type( - self.context, - CssRuleType::Style, - self.namespaces, - ); - - let enabled = condition.eval(&eval_context, self.namespaces); + let enabled = self.nest_for_rule(CssRuleType::Style, |p| { + condition.eval(&p.context) + }); Ok(CssRule::Supports(Arc::new(self.shared_lock.wrap( SupportsRule { condition, @@ -617,40 +589,28 @@ impl<'a, 'b, 'i> AtRuleParser<'i> for NestedRuleParser<'a, 'b> { )))) }, AtRulePrelude::Viewport => { - let context = ParserContext::new_with_rule_type( - self.context, - CssRuleType::Viewport, - self.namespaces, - ); - - Ok(CssRule::Viewport(Arc::new( - self.shared_lock.wrap(ViewportRule::parse(&context, input)?), - ))) + self.nest_for_rule(CssRuleType::Viewport, |p| { + Ok(CssRule::Viewport(Arc::new( + p.shared_lock.wrap(ViewportRule::parse(&p.context, input)?), + ))) + }) }, AtRulePrelude::Keyframes(name, vendor_prefix) => { - let context = ParserContext::new_with_rule_type( - self.context, - CssRuleType::Keyframes, - self.namespaces, - ); - - Ok(CssRule::Keyframes(Arc::new(self.shared_lock.wrap( - KeyframesRule { - name, - keyframes: parse_keyframe_list(&context, input, self.shared_lock), - vendor_prefix, - source_location: start.source_location(), - }, - )))) + self.nest_for_rule(CssRuleType::Keyframe, |p| { + Ok(CssRule::Keyframes(Arc::new(p.shared_lock.wrap( + KeyframesRule { + name, + keyframes: parse_keyframe_list(&mut p.context, input, p.shared_lock), + vendor_prefix, + source_location: start.source_location(), + }, + )))) + }) }, AtRulePrelude::Page(selectors) => { - let context = ParserContext::new_with_rule_type( - self.context, - CssRuleType::Page, - self.namespaces, - ); - - let declarations = parse_property_declaration_list(&context, input, None); + let declarations = self.nest_for_rule(CssRuleType::Page, |p| { + parse_property_declaration_list(&p.context, input, None) + }); Ok(CssRule::Page(Arc::new(self.shared_lock.wrap(PageRule { selectors, block: Arc::new(self.shared_lock.wrap(declarations)), @@ -763,7 +723,7 @@ impl<'a, 'b, 'i> QualifiedRuleParser<'i> for NestedRuleParser<'a, 'b> { ) -> Result<Self::Prelude, ParseError<'i>> { let selector_parser = SelectorParser { stylesheet_origin: self.context.stylesheet_origin, - namespaces: self.namespaces, + namespaces: &self.context.namespaces, url_data: self.context.url_data, for_supports_rule: false, }; @@ -780,10 +740,9 @@ impl<'a, 'b, 'i> QualifiedRuleParser<'i> for NestedRuleParser<'a, 'b> { start: &ParserState, input: &mut Parser<'i, 't>, ) -> Result<CssRule, ParseError<'i>> { - let context = - ParserContext::new_with_rule_type(self.context, CssRuleType::Style, self.namespaces); - - let declarations = parse_property_declaration_list(&context, input, Some(&selectors)); + let declarations = self.nest_for_rule(CssRuleType::Style, |p| { + parse_property_declaration_list(&p.context, input, Some(&selectors)) + }); let block = Arc::new(self.shared_lock.wrap(declarations)); Ok(CssRule::Style(Arc::new(self.shared_lock.wrap(StyleRule { selectors, @@ -793,3 +752,14 @@ impl<'a, 'b, 'i> QualifiedRuleParser<'i> for NestedRuleParser<'a, 'b> { })))) } } + +impl<'a, 'b, 'i> DeclarationParser<'i> for NestedRuleParser<'a, 'b> { + type Declaration = CssRule; + type Error = StyleParseErrorKind<'i>; +} + +impl<'a, 'b, 'i> RuleBodyItemParser<'i, CssRule, StyleParseErrorKind<'i>> for NestedRuleParser<'a, 'b> { + fn parse_qualified(&self) -> bool { true } + // TODO: Nesting. + fn parse_declarations(&self) -> bool { false } +} diff --git a/components/style/stylesheets/stylesheet.rs b/components/style/stylesheets/stylesheet.rs index a1a678ec436..155a40122e2 100644 --- a/components/style/stylesheets/stylesheet.rs +++ b/components/style/stylesheets/stylesheet.rs @@ -15,13 +15,12 @@ use crate::stylesheets::rules_iterator::{NestedRuleIterationCondition, RulesIter use crate::stylesheets::{CssRule, CssRules, Origin, UrlExtraData}; use crate::use_counters::UseCounters; use crate::{Namespace, Prefix}; -use cssparser::{Parser, ParserInput, RuleListParser}; +use cssparser::{Parser, ParserInput, StyleSheetParser}; use fxhash::FxHashMap; #[cfg(feature = "gecko")] use malloc_size_of::{MallocSizeOfOps, MallocUnconditionalShallowSizeOf}; use parking_lot::RwLock; use servo_arc::Arc; -use std::mem; use std::sync::atomic::{AtomicBool, Ordering}; use style_traits::ParsingMode; @@ -86,12 +85,10 @@ impl StylesheetContents { allow_import_rules: AllowImportRules, sanitization_data: Option<&mut SanitizationData>, ) -> Arc<Self> { - let namespaces = RwLock::new(Namespaces::default()); - let (rules, source_map_url, source_url) = Stylesheet::parse_rules( + let (namespaces, rules, source_map_url, source_url) = Stylesheet::parse_rules( css, &url_data, origin, - &mut *namespaces.write(), &shared_lock, stylesheet_loader, error_reporter, @@ -106,7 +103,7 @@ impl StylesheetContents { rules: CssRules::new(rules, &shared_lock), origin, url_data: RwLock::new(url_data), - namespaces, + namespaces: RwLock::new(namespaces), quirks_mode, source_map_url: RwLock::new(source_map_url), source_url: RwLock::new(source_url), @@ -426,14 +423,11 @@ impl Stylesheet { line_number_offset: u32, allow_import_rules: AllowImportRules, ) { - let namespaces = RwLock::new(Namespaces::default()); - // FIXME: Consider adding use counters to Servo? - let (rules, source_map_url, source_url) = Self::parse_rules( + let (namespaces, rules, source_map_url, source_url) = Self::parse_rules( css, &url_data, existing.contents.origin, - &mut *namespaces.write(), &existing.shared_lock, stylesheet_loader, error_reporter, @@ -445,10 +439,7 @@ impl Stylesheet { ); *existing.contents.url_data.write() = url_data; - mem::swap( - &mut *existing.contents.namespaces.write(), - &mut *namespaces.write(), - ); + *existing.contents.namespaces.write() = namespaces; // Acquire the lock *after* parsing, to minimize the exclusive section. let mut guard = existing.shared_lock.write(); @@ -461,7 +452,6 @@ impl Stylesheet { css: &str, url_data: &UrlExtraData, origin: Origin, - namespaces: &mut Namespaces, shared_lock: &SharedRwLock, stylesheet_loader: Option<&dyn StylesheetLoader>, error_reporter: Option<&dyn ParseErrorReporter>, @@ -470,7 +460,7 @@ impl Stylesheet { use_counters: Option<&UseCounters>, allow_import_rules: AllowImportRules, mut sanitization_data: Option<&mut SanitizationData>, - ) -> (Vec<CssRule>, Option<String>, Option<String>) { + ) -> (Namespaces, Vec<CssRule>, Option<String>, Option<String>) { let mut rules = Vec::new(); let mut input = ParserInput::new_with_line_number_offset(css, line_number_offset); let mut input = Parser::new(&mut input); @@ -481,23 +471,23 @@ impl Stylesheet { None, ParsingMode::DEFAULT, quirks_mode, + /* namespaces = */ Default::default(), error_reporter, use_counters, ); - let rule_parser = TopLevelRuleParser { + let mut rule_parser = TopLevelRuleParser { shared_lock, loader: stylesheet_loader, context, state: State::Start, dom_error: None, insert_rule_context: None, - namespaces, allow_import_rules, }; { - let mut iter = RuleListParser::new_for_stylesheet(&mut input, rule_parser); + let mut iter = StyleSheetParser::new(&mut input, &mut rule_parser); loop { let result = match iter.next() { @@ -532,7 +522,7 @@ impl Stylesheet { let source_map_url = input.current_source_map_url().map(String::from); let source_url = input.current_source_url().map(String::from); - (rules, source_map_url, source_url) + (rule_parser.context.namespaces.into_owned(), rules, source_map_url, source_url) } /// Creates an empty stylesheet and parses it with a given base url, origin diff --git a/components/style/stylesheets/supports_rule.rs b/components/style/stylesheets/supports_rule.rs index be61058fcf1..880af04d997 100644 --- a/components/style/stylesheets/supports_rule.rs +++ b/components/style/stylesheets/supports_rule.rs @@ -11,7 +11,7 @@ use crate::selector_parser::{SelectorImpl, SelectorParser}; use crate::shared_lock::{DeepCloneParams, DeepCloneWithLock, Locked}; use crate::shared_lock::{SharedRwLock, SharedRwLockReadGuard, ToCssWithGuard}; use crate::str::CssStringWriter; -use crate::stylesheets::{CssRuleType, CssRules, Namespaces}; +use crate::stylesheets::{CssRuleType, CssRules}; use cssparser::parse_important; use cssparser::{Delimiter, Parser, SourceLocation, Token}; use cssparser::{ParseError as CssParseError, ParserInput}; @@ -228,15 +228,15 @@ impl SupportsCondition { } /// Evaluate a supports condition - pub fn eval(&self, cx: &ParserContext, namespaces: &Namespaces) -> bool { + pub fn eval(&self, cx: &ParserContext) -> bool { match *self { - SupportsCondition::Not(ref cond) => !cond.eval(cx, namespaces), - SupportsCondition::Parenthesized(ref cond) => cond.eval(cx, namespaces), - SupportsCondition::And(ref vec) => vec.iter().all(|c| c.eval(cx, namespaces)), - SupportsCondition::Or(ref vec) => vec.iter().any(|c| c.eval(cx, namespaces)), + SupportsCondition::Not(ref cond) => !cond.eval(cx), + SupportsCondition::Parenthesized(ref cond) => cond.eval(cx), + SupportsCondition::And(ref vec) => vec.iter().all(|c| c.eval(cx)), + SupportsCondition::Or(ref vec) => vec.iter().any(|c| c.eval(cx)), SupportsCondition::Declaration(ref decl) => decl.eval(cx), SupportsCondition::MozBoolPref(ref name) => eval_moz_bool_pref(name, cx), - SupportsCondition::Selector(ref selector) => selector.eval(cx, namespaces), + SupportsCondition::Selector(ref selector) => selector.eval(cx), SupportsCondition::FontFormat(ref format) => eval_font_format(format), SupportsCondition::FontTech(ref tech) => eval_font_tech(tech), SupportsCondition::FutureSyntax(_) => false, @@ -374,13 +374,13 @@ impl ToCss for RawSelector { impl RawSelector { /// Tries to evaluate a `selector()` function. - pub fn eval(&self, context: &ParserContext, namespaces: &Namespaces) -> bool { + pub fn eval(&self, context: &ParserContext) -> bool { let mut input = ParserInput::new(&self.0); let mut input = Parser::new(&mut input); input .parse_entirely(|input| -> Result<(), CssParseError<()>> { let parser = SelectorParser { - namespaces, + namespaces: &context.namespaces, stylesheet_origin: context.stylesheet_origin, url_data: context.url_data, for_supports_rule: true, diff --git a/components/style/stylesheets/viewport_rule.rs b/components/style/stylesheets/viewport_rule.rs index 6d61d299911..49ed4d463a4 100644 --- a/components/style/stylesheets/viewport_rule.rs +++ b/components/style/stylesheets/viewport_rule.rs @@ -25,8 +25,8 @@ use crate::values::specified::{self, NoCalcLength}; use crate::values::specified::{NonNegativeLengthPercentageOrAuto, ViewportPercentageLength}; use app_units::Au; use cssparser::{ - parse_important, AtRuleParser, CowRcStr, DeclarationListParser, DeclarationParser, Parser, - QualifiedRuleParser, + parse_important, AtRuleParser, CowRcStr, DeclarationParser, Parser, QualifiedRuleParser, + RuleBodyItemParser, RuleBodyParser, }; use euclid::Size2D; use selectors::parser::SelectorParseErrorKind; @@ -233,15 +233,17 @@ fn parse_shorthand<'i, 't>( } } +type ViewportDeclarations = Vec<ViewportDescriptorDeclaration>; + impl<'a, 'b, 'i> AtRuleParser<'i> for ViewportRuleParser<'a, 'b> { type Prelude = (); - type AtRule = Vec<ViewportDescriptorDeclaration>; + type AtRule = ViewportDeclarations; type Error = StyleParseErrorKind<'i>; } impl<'a, 'b, 'i> QualifiedRuleParser<'i> for ViewportRuleParser<'a, 'b> { type Prelude = (); - type QualifiedRule = Vec<ViewportDescriptorDeclaration>; + type QualifiedRule = ViewportDeclarations; type Error = StyleParseErrorKind<'i>; } @@ -308,6 +310,11 @@ impl<'a, 'b, 'i> DeclarationParser<'i> for ViewportRuleParser<'a, 'b> { } } +impl<'a, 'b, 'i> RuleBodyItemParser<'i, ViewportDeclarations, StyleParseErrorKind<'i>> for ViewportRuleParser<'a, 'b> { + fn parse_declarations(&self) -> bool { true } + fn parse_qualified(&self) -> bool { false } +} + /// A `@viewport` rule. #[derive(Clone, Debug, PartialEq, ToShmem)] #[cfg_attr(feature = "servo", derive(MallocSizeOf))] @@ -337,10 +344,10 @@ impl ViewportRule { context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { - let parser = ViewportRuleParser { context }; + let mut parser = ViewportRuleParser { context }; let mut cascade = Cascade::new(); - let mut parser = DeclarationListParser::new(input, parser); + let mut parser = RuleBodyParser::new(input, &mut parser); while let Some(result) = parser.next() { match result { Ok(declarations) => { @@ -455,9 +462,7 @@ impl ViewportRule { let declarations: Vec<_> = declarations.into_iter().filter_map(|entry| entry).collect(); if !declarations.is_empty() { - Some(ViewportRule { - declarations: declarations, - }) + Some(ViewportRule { declarations }) } else { None } @@ -784,8 +789,8 @@ impl MaybeNew for ViewportConstraints { min_zoom: min_zoom.map(PinchZoomFactor::new), max_zoom: max_zoom.map(PinchZoomFactor::new), - user_zoom: user_zoom, - orientation: orientation, + user_zoom, + orientation, }) } } diff --git a/components/style/values/specified/mod.rs b/components/style/values/specified/mod.rs index f9c7d159119..ecba583ad17 100644 --- a/components/style/values/specified/mod.rs +++ b/components/style/values/specified/mod.rs @@ -879,12 +879,7 @@ impl Parse for Attr { /// Get the Namespace for a given prefix from the namespace map. fn get_namespace_for_prefix(prefix: &Prefix, context: &ParserContext) -> Option<Namespace> { - context - .namespaces - .as_ref()? - .prefixes - .get(prefix) - .map(|x| x.clone()) + context.namespaces.prefixes.get(prefix).cloned() } impl Attr { |