From 4ed0f518fb9b16096506f31f6a542c2b6571e5c6 Mon Sep 17 00:00:00 2001 From: CanadaHonk Date: Sat, 25 Feb 2023 23:53:02 +0000 Subject: [PATCH] style: Fix parsing nested image-set funcs as valid Nested image-set CSS functions should fail to parse as per spec. WPT tests (2 newly pass): https://github.com/web-platform-tests/wpt/blob/a2154e3f971f3630643741206ce02bbbc5f31d6f/css/css-images/image-set/image-set-parsing.html#L223-L239 Differential Revision: https://phabricator.services.mozilla.com/D170829 --- components/style/values/specified/image.rs | 53 +++++++++++++--------- 1 file changed, 31 insertions(+), 22 deletions(-) diff --git a/components/style/values/specified/image.rs b/components/style/values/specified/image.rs index 3be84c5a7b2..a9eb6bf6571 100644 --- a/components/style/values/specified/image.rs +++ b/components/style/values/specified/image.rs @@ -177,6 +177,14 @@ pub type MozImageRect = generic::GenericMozImageRect( context: &ParserContext, @@ -186,8 +194,7 @@ impl Parse for Image { context, input, CorsMode::None, - /* allow_none = */ true, - /* only_url = */ false, + ParseImageFlags::empty() ) } } @@ -197,10 +204,9 @@ impl Image { context: &ParserContext, input: &mut Parser<'i, 't>, cors_mode: CorsMode, - allow_none: bool, - only_url: bool, + flags: ParseImageFlags ) -> Result> { - if allow_none && input.try_parse(|i| i.expect_ident_matching("none")).is_ok() { + if !flags.contains(ParseImageFlags::FORBID_NONE) && input.try_parse(|i| i.expect_ident_matching("none")).is_ok() { return Ok(generic::Image::None); } @@ -210,13 +216,15 @@ impl Image { return Ok(generic::Image::Url(url)); } - if image_set_enabled() { - if let Ok(is) = input.try_parse(|input| ImageSet::parse(context, input, cors_mode, only_url)) { + if !flags.contains(ParseImageFlags::FORBID_IMAGE_SET) && image_set_enabled() { + if let Ok(is) = + input.try_parse(|input| ImageSet::parse(context, input, cors_mode, flags)) + { return Ok(generic::Image::ImageSet(Box::new(is))); } } - if only_url { + if flags.contains(ParseImageFlags::FORBID_NON_URL) { return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)); } @@ -225,7 +233,7 @@ impl Image { } if cross_fade_enabled() { - if let Ok(cf) = input.try_parse(|input| CrossFade::parse(context, input, cors_mode)) { + if let Ok(cf) = input.try_parse(|input| CrossFade::parse(context, input, cors_mode, flags)) { return Ok(generic::Image::CrossFade(Box::new(cf))); } } @@ -279,8 +287,7 @@ impl Image { context, input, CorsMode::Anonymous, - /* allow_none = */ true, - /* only_url = */ false, + ParseImageFlags::empty() ) } @@ -293,8 +300,7 @@ impl Image { context, input, CorsMode::None, - /* allow_none = */ false, - /* only_url = */ true, + ParseImageFlags::FORBID_NONE | ParseImageFlags::FORBID_NON_URL ) } } @@ -305,10 +311,11 @@ impl CrossFade { context: &ParserContext, input: &mut Parser<'i, 't>, cors_mode: CorsMode, + flags: ParseImageFlags ) -> Result> { input.expect_function_matching("cross-fade")?; let elements = input.parse_nested_block(|input| { - input.parse_comma_separated(|input| CrossFadeElement::parse(context, input, cors_mode)) + input.parse_comma_separated(|input| CrossFadeElement::parse(context, input, cors_mode, flags)) })?; let elements = crate::OwnedSlice::from(elements); Ok(Self { elements }) @@ -335,11 +342,12 @@ impl CrossFadeElement { context: &ParserContext, input: &mut Parser<'i, 't>, cors_mode: CorsMode, + flags: ParseImageFlags ) -> Result> { // Try and parse a leading percent sign. let mut percent = Self::parse_percentage(context, input); // Parse the image - let image = CrossFadeImage::parse(context, input, cors_mode)?; + let image = CrossFadeImage::parse(context, input, cors_mode, flags)?; // Try and parse a trailing percent sign. if percent.is_none() { percent = Self::parse_percentage(context, input); @@ -356,11 +364,12 @@ impl CrossFadeImage { context: &ParserContext, input: &mut Parser<'i, 't>, cors_mode: CorsMode, + flags: ParseImageFlags ) -> Result> { if let Ok(image) = input.try_parse(|input| { Image::parse_with_cors_mode( - context, input, cors_mode, /* allow_none = */ false, - /* only_url = */ false, + context, input, cors_mode, + flags | ParseImageFlags::FORBID_NONE ) }) { return Ok(Self::Image(image)); @@ -374,7 +383,7 @@ impl ImageSet { context: &ParserContext, input: &mut Parser<'i, 't>, cors_mode: CorsMode, - only_url: bool, + flags: ParseImageFlags ) -> Result> { let function = input.expect_function()?; match_ignore_ascii_case! { &function, @@ -386,7 +395,7 @@ impl ImageSet { } let items = input.parse_nested_block(|input| { input.parse_comma_separated(|input| { - ImageSetItem::parse(context, input, cors_mode, only_url) + ImageSetItem::parse(context, input, cors_mode, flags) }) })?; Ok(Self { @@ -406,7 +415,7 @@ impl ImageSetItem { context: &ParserContext, input: &mut Parser<'i, 't>, cors_mode: CorsMode, - only_url: bool, + flags: ParseImageFlags ) -> Result> { let image = match input.try_parse(|i| i.expect_url_or_string()) { Ok(url) => Image::Url(SpecifiedImageUrl::parse_from_string( @@ -415,8 +424,8 @@ impl ImageSetItem { cors_mode, )), Err(..) => Image::parse_with_cors_mode( - context, input, cors_mode, /* allow_none = */ false, - /* only_url = */ only_url, + context, input, cors_mode, + flags | ParseImageFlags::FORBID_NONE | ParseImageFlags::FORBID_IMAGE_SET )?, };