From 26a029d407be480d791972afb5975cf62c9360a6 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 02:47:55 +0200 Subject: Adding upstream version 124.0.1. Signed-off-by: Daniel Baumann --- servo/components/style/parser.rs | 178 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 178 insertions(+) create mode 100644 servo/components/style/parser.rs (limited to 'servo/components/style/parser.rs') diff --git a/servo/components/style/parser.rs b/servo/components/style/parser.rs new file mode 100644 index 0000000000..893625854f --- /dev/null +++ b/servo/components/style/parser.rs @@ -0,0 +1,178 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +//! The context within which CSS code is parsed. + +use crate::context::QuirksMode; +use crate::error_reporting::{ContextualParseError, ParseErrorReporter}; +use crate::stylesheets::{CssRuleType, CssRuleTypes, Namespaces, Origin, UrlExtraData}; +use crate::use_counters::UseCounters; +use cssparser::{Parser, SourceLocation, UnicodeRange}; +use std::borrow::Cow; +use style_traits::{OneOrMoreSeparated, ParseError, ParsingMode, Separator}; + +/// The data that the parser needs from outside in order to parse a stylesheet. +pub struct ParserContext<'a> { + /// The `Origin` of the stylesheet, whether it's a user, author or + /// user-agent stylesheet. + pub stylesheet_origin: Origin, + /// The extra data we need for resolving url values. + pub url_data: &'a UrlExtraData, + /// The current rule types, if any. + pub rule_types: CssRuleTypes, + /// The mode to use when parsing. + pub parsing_mode: ParsingMode, + /// The quirks mode of this stylesheet. + pub quirks_mode: QuirksMode, + /// The active error reporter, or none if error reporting is disabled. + error_reporter: Option<&'a dyn ParseErrorReporter>, + /// The currently active 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>, +} + +impl<'a> ParserContext<'a> { + /// Create a parser context. + #[inline] + pub fn new( + stylesheet_origin: Origin, + url_data: &'a UrlExtraData, + 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 { + Self { + stylesheet_origin, + url_data, + rule_types: rule_type.map(CssRuleTypes::from).unwrap_or_default(), + parsing_mode, + quirks_mode, + error_reporter, + namespaces, + 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_types = self.rule_types; + self.rule_types.insert(rule_type); + let r = cb(self); + self.rule_types = old_rule_types; + r + } + + /// Whether we're in a @page rule. + #[inline] + pub fn in_page_rule(&self) -> bool { + self.rule_types.contains(CssRuleType::Page) + } + + /// Get the rule type, which assumes that one is available. + pub fn rule_types(&self) -> CssRuleTypes { + self.rule_types + } + + /// Returns whether CSS error reporting is enabled. + #[inline] + pub fn error_reporting_enabled(&self) -> bool { + self.error_reporter.is_some() + } + + /// Record a CSS parse error with this context’s error reporting. + pub fn log_css_error(&self, location: SourceLocation, error: ContextualParseError) { + let error_reporter = match self.error_reporter { + Some(r) => r, + None => return, + }; + + error_reporter.report_error(self.url_data, location, error) + } + + /// Whether we're in a user-agent stylesheet. + #[inline] + pub fn in_ua_sheet(&self) -> bool { + self.stylesheet_origin == Origin::UserAgent + } + + /// Returns whether chrome-only rules should be parsed. + #[inline] + pub fn chrome_rules_enabled(&self) -> bool { + self.url_data.chrome_rules_enabled() || self.stylesheet_origin != Origin::Author + } +} + +/// A trait to abstract parsing of a specified value given a `ParserContext` and +/// CSS input. +/// +/// This can be derived on keywords with `#[derive(Parse)]`. +/// +/// The derive code understands the following attributes on each of the variants: +/// +/// * `#[parse(aliases = "foo,bar")]` can be used to alias a value with another +/// at parse-time. +/// +/// * `#[parse(condition = "function")]` can be used to make the parsing of the +/// value conditional on `function`, which needs to fulfill +/// `fn(&ParserContext) -> bool`. +pub trait Parse: Sized { + /// Parse a value of this type. + /// + /// Returns an error on failure. + fn parse<'i, 't>( + context: &ParserContext, + input: &mut Parser<'i, 't>, + ) -> Result>; +} + +impl Parse for Vec +where + T: Parse + OneOrMoreSeparated, + ::S: Separator, +{ + fn parse<'i, 't>( + context: &ParserContext, + input: &mut Parser<'i, 't>, + ) -> Result> { + ::S::parse(input, |i| T::parse(context, i)) + } +} + +impl Parse for Box +where + T: Parse, +{ + fn parse<'i, 't>( + context: &ParserContext, + input: &mut Parser<'i, 't>, + ) -> Result> { + T::parse(context, input).map(Box::new) + } +} + +impl Parse for crate::OwnedStr { + fn parse<'i, 't>( + _: &ParserContext, + input: &mut Parser<'i, 't>, + ) -> Result> { + Ok(input.expect_string()?.as_ref().to_owned().into()) + } +} + +impl Parse for UnicodeRange { + fn parse<'i, 't>( + _: &ParserContext, + input: &mut Parser<'i, 't>, + ) -> Result> { + Ok(UnicodeRange::parse(input)?) + } +} -- cgit v1.2.3