зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1818598 - Fix parsing nested image-set funcs as valid r=layout-reviewers,emilio
Nested image-set CSS functions should fail to parse as per spec.
WPT tests (2 newly pass):
a2154e3f97/css/css-images/image-set/image-set-parsing.html (L223-L239)
Differential Revision: https://phabricator.services.mozilla.com/D170829
This commit is contained in:
Родитель
a3a9112d4d
Коммит
d17b6e45fc
|
@ -262,7 +262,6 @@ var validNonUrlImageValues = [
|
|||
"image-set(url(foobar.png) 2x)",
|
||||
"image-set(url(foobar.png) 1x, url(bar.png) 2x, url(baz.png) 3x)",
|
||||
"image-set('foobar.png', 'bar.png' 2x, url(baz.png) 3x)",
|
||||
"image-set(image-set('foobar.png', 'bar.png' 2x) 1x, url(baz.png) 3x)",
|
||||
"image-set(url(foobar.png) type('image/png'))",
|
||||
"image-set(url(foobar.png) 1x type('image/png'))",
|
||||
"image-set(url(foobar.png) type('image/png') 1x)",
|
||||
|
@ -804,6 +803,7 @@ var invalidNonUrlImageValues = [
|
|||
|
||||
"image-set(url(foobar.png) 1x, none)",
|
||||
"image-set(garbage)",
|
||||
"image-set(image-set('foobar.png', 'bar.png' 2x) 1x, url(baz.png) 3x)", // Nested image-sets should fail to parse
|
||||
"image-set(image-set(garbage))",
|
||||
"image-set()",
|
||||
"image-set(type('image/png') url(foobar.png) 1x)",
|
||||
|
|
|
@ -165,6 +165,14 @@ pub type MozImageRect = generic::GenericMozImageRect<NumberOrPercentage, Specifi
|
|||
/// Empty enum on non-Gecko
|
||||
pub enum MozImageRect {}
|
||||
|
||||
bitflags! {
|
||||
struct ParseImageFlags: u8 {
|
||||
const FORBID_NONE = 1 << 0;
|
||||
const FORBID_IMAGE_SET = 1 << 1;
|
||||
const FORBID_NON_URL = 1 << 2;
|
||||
}
|
||||
}
|
||||
|
||||
impl Parse for Image {
|
||||
fn parse<'i, 't>(
|
||||
context: &ParserContext,
|
||||
|
@ -174,8 +182,7 @@ impl Parse for Image {
|
|||
context,
|
||||
input,
|
||||
CorsMode::None,
|
||||
/* allow_none = */ true,
|
||||
/* only_url = */ false,
|
||||
ParseImageFlags::empty()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -185,10 +192,9 @@ impl Image {
|
|||
context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
cors_mode: CorsMode,
|
||||
allow_none: bool,
|
||||
only_url: bool,
|
||||
flags: ParseImageFlags
|
||||
) -> Result<Image, ParseError<'i>> {
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -198,13 +204,15 @@ impl Image {
|
|||
return Ok(generic::Image::Url(url));
|
||||
}
|
||||
|
||||
if let Ok(is) =
|
||||
input.try_parse(|input| ImageSet::parse(context, input, cors_mode, only_url))
|
||||
{
|
||||
return Ok(generic::Image::ImageSet(Box::new(is)));
|
||||
if !flags.contains(ParseImageFlags::FORBID_IMAGE_SET) {
|
||||
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));
|
||||
}
|
||||
|
||||
|
@ -213,7 +221,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)));
|
||||
}
|
||||
}
|
||||
|
@ -267,8 +275,7 @@ impl Image {
|
|||
context,
|
||||
input,
|
||||
CorsMode::Anonymous,
|
||||
/* allow_none = */ true,
|
||||
/* only_url = */ false,
|
||||
ParseImageFlags::empty()
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -281,8 +288,7 @@ impl Image {
|
|||
context,
|
||||
input,
|
||||
CorsMode::None,
|
||||
/* allow_none = */ false,
|
||||
/* only_url = */ true,
|
||||
ParseImageFlags::FORBID_NONE | ParseImageFlags::FORBID_NON_URL
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -293,10 +299,11 @@ impl CrossFade {
|
|||
context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
cors_mode: CorsMode,
|
||||
flags: ParseImageFlags
|
||||
) -> Result<Self, ParseError<'i>> {
|
||||
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 })
|
||||
|
@ -323,11 +330,12 @@ impl CrossFadeElement {
|
|||
context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
cors_mode: CorsMode,
|
||||
flags: ParseImageFlags
|
||||
) -> Result<Self, ParseError<'i>> {
|
||||
// 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);
|
||||
|
@ -344,11 +352,12 @@ impl CrossFadeImage {
|
|||
context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
cors_mode: CorsMode,
|
||||
flags: ParseImageFlags
|
||||
) -> Result<Self, ParseError<'i>> {
|
||||
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));
|
||||
|
@ -362,7 +371,7 @@ impl ImageSet {
|
|||
context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
cors_mode: CorsMode,
|
||||
only_url: bool,
|
||||
flags: ParseImageFlags
|
||||
) -> Result<Self, ParseError<'i>> {
|
||||
let function = input.expect_function()?;
|
||||
match_ignore_ascii_case! { &function,
|
||||
|
@ -374,7 +383,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 {
|
||||
|
@ -394,7 +403,7 @@ impl ImageSetItem {
|
|||
context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
cors_mode: CorsMode,
|
||||
only_url: bool,
|
||||
flags: ParseImageFlags
|
||||
) -> Result<Self, ParseError<'i>> {
|
||||
let image = match input.try_parse(|i| i.expect_url_or_string()) {
|
||||
Ok(url) => Image::Url(SpecifiedImageUrl::parse_from_string(
|
||||
|
@ -403,8 +412,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
|
||||
)?,
|
||||
};
|
||||
|
||||
|
|
|
@ -10,9 +10,3 @@
|
|||
|
||||
[e.style['content'\] = "-webkit-image-set(url(\\"example.png\\") 192dpi, linear-gradient(black, white) 1x)" should set the property value]
|
||||
expected: FAIL
|
||||
|
||||
[e.style['background-image'\] = "image-set(image-set(url(example.png)) 2x)" should not set the property value]
|
||||
expected: FAIL
|
||||
|
||||
[e.style['background-image'\] = "-webkit-image-set(image-set(url(example.png)) 2x)" should not set the property value]
|
||||
expected: FAIL
|
||||
|
|
Загрузка…
Ссылка в новой задаче