diff --git a/components/style/stylesheets/import_rule.rs b/components/style/stylesheets/import_rule.rs index d82906b1e7d..6921e708aa7 100644 --- a/components/style/stylesheets/import_rule.rs +++ b/components/style/stylesheets/import_rule.rs @@ -7,14 +7,17 @@ //! [import]: https://drafts.csswg.org/css-cascade-3/#at-import use crate::media_queries::MediaList; -use crate::shared_lock::{DeepCloneParams, DeepCloneWithLock}; -use crate::shared_lock::{SharedRwLock, SharedRwLockReadGuard, ToCssWithGuard}; +use crate::parser::{Parse, ParserContext}; +use crate::shared_lock::{ + DeepCloneParams, DeepCloneWithLock, SharedRwLock, SharedRwLockReadGuard, ToCssWithGuard, +}; use crate::str::CssStringWriter; -use crate::stylesheets::supports_rule::SupportsCondition; -use crate::stylesheets::layer_rule::LayerName; -use crate::stylesheets::{CssRule, StylesheetInDocument}; +use crate::stylesheets::{ + layer_rule::LayerName, stylesheet::Namespaces, supports_rule::SupportsCondition, CssRule, + CssRuleType, StylesheetInDocument, +}; use crate::values::CssUrl; -use cssparser::SourceLocation; +use cssparser::{Parser, SourceLocation}; use std::fmt::{self, Write}; use style_traits::{CssWriter, ToCss}; use to_shmem::{self, SharedMemoryBuilder, ToShmem}; @@ -62,8 +65,7 @@ impl ImportSheet { } Some(s) }, - ImportSheet::Refused | - ImportSheet::Pending => None, + ImportSheet::Refused | ImportSheet::Pending => None, } } @@ -181,7 +183,7 @@ pub struct ImportSupportsCondition { pub condition: SupportsCondition, /// If the import is enabled, from the result of the import condition. - pub enabled: bool + pub enabled: bool, } impl ToCss for ImportLayer { @@ -223,6 +225,54 @@ pub struct ImportRule { pub source_location: SourceLocation, } +impl ImportRule { + /// Parses the layer() / layer / supports() part of the import header, as per + /// https://drafts.csswg.org/css-cascade-5/#at-import: + /// + /// [ layer | layer() ]? + /// [ supports([ | ]) ]? + /// + /// We do this here so that the import preloader can look at this without having to parse the + /// 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, + ) -> (Option, Option) { + let layer = if input + .try_parse(|input| input.expect_ident_matching("layer")) + .is_ok() + { + Some(ImportLayer { name: None }) + } else { + input + .try_parse(|input| { + input.expect_function_matching("layer")?; + input + .parse_nested_block(|input| LayerName::parse(context, input)) + .map(|name| ImportLayer { name: Some(name) }) + }) + .ok() + }; + + let supports = if !static_prefs::pref!("layout.css.import-supports.enabled") { + None + } else { + 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); + ImportSupportsCondition { condition, enabled } + }) + .ok() + }; + + (layer, supports) + } +} + impl ToShmem for ImportRule { fn to_shmem(&self, _builder: &mut SharedMemoryBuilder) -> to_shmem::Result { Err(String::from( diff --git a/components/style/stylesheets/rule_parser.rs b/components/style/stylesheets/rule_parser.rs index 185d549ef0f..0a7ce5dac17 100644 --- a/components/style/stylesheets/rule_parser.rs +++ b/components/style/stylesheets/rule_parser.rs @@ -16,7 +16,7 @@ use crate::str::starts_with_ignore_ascii_case; use crate::stylesheets::container_rule::{ContainerCondition, ContainerRule}; use crate::stylesheets::document_rule::DocumentCondition; use crate::stylesheets::font_feature_values_rule::parse_family_name_list; -use crate::stylesheets::import_rule::{ImportLayer, ImportSupportsCondition}; +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; @@ -241,43 +241,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 = if input.try_parse(|input| input.expect_ident_matching("layer")).is_ok() { - Some(ImportLayer { - name: None, - }) - } else { - input.try_parse(|input| { - input.expect_function_matching("layer")?; - input.parse_nested_block(|input| { - LayerName::parse(&self.context, input) - }).map(|name| ImportLayer { - name: Some(name), - }) - }).ok() - }; - - #[cfg(feature = "gecko")] - let supports_enabled = static_prefs::pref!("layout.css.import-supports.enabled"); - #[cfg(feature = "servo")] - let supports_enabled = false; - - let supports = if !supports_enabled { - None - } else { - input.try_parse(SupportsCondition::parse_for_import).map(|condition| { - let eval_context = ParserContext::new_with_rule_type( - &self.context, - CssRuleType::Style, - self.namespaces, - ); - - let enabled = condition.eval(&eval_context, self.namespaces); - ImportSupportsCondition { - condition, - enabled - } - }).ok() - }; + let (layer, supports) = ImportRule::parse_layer_and_supports(input, &self.context, self.namespaces); let media = MediaList::parse(&self.context, input); let media = Arc::new(self.shared_lock.wrap(media));