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, 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(&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); 2]>; fn alias_of_known_property(name: &str) -> Option { @@ -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(vec: &mut Vec>, element: FFVDeclaration) { - 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 std::fmt::{self, Write}; -use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss}; -use style_traits::{Comma, OneOrMoreSeparated}; +use cssparser::{ + AtRuleParser, CowRcStr, DeclarationParser, Parser, QualifiedRuleParser, RuleBodyItemParser, + RuleBodyParser, SourceLocation, +}; use selectors::parser::SelectorParseErrorKind; -use crate::stylesheets::font_feature_values_rule::parse_family_name_list; +use std::fmt::{self, Write}; +use style_traits::{Comma, OneOrMoreSeparated}; +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) { 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>> { - 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>; 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>; + type Error = StyleParseErrorKind<'i>; +} + +impl<'a, 'b, 'i> QualifiedRuleParser<'i> for KeyframeListParser<'a, 'b> { type Prelude = KeyframeSelector; type QualifiedRule = Arc>; type Error = StyleParseErrorKind<'i>; @@ -589,33 +586,30 @@ impl<'a, 'i> QualifiedRuleParser<'i> for KeyframeListParser<'a> { start: &ParserState, input: &mut Parser<'i, 't>, ) -> Result> { - 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>, 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 { 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, - /// 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>, /// 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(&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> { - 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> { 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> { 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> { - 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 { - 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, Option, Option) { + ) -> (Namespaces, Vec, Option, Option) { 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; + impl<'a, 'b, 'i> AtRuleParser<'i> for ViewportRuleParser<'a, 'b> { type Prelude = (); - type AtRule = Vec; + type AtRule = ViewportDeclarations; type Error = StyleParseErrorKind<'i>; } impl<'a, 'b, 'i> QualifiedRuleParser<'i> for ViewportRuleParser<'a, 'b> { type Prelude = (); - type QualifiedRule = Vec; + 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> { - 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 { - context - .namespaces - .as_ref()? - .prefixes - .get(prefix) - .map(|x| x.clone()) + context.namespaces.prefixes.get(prefix).cloned() } impl Attr {