mirror of
https://github.com/servo/servo.git
synced 2025-08-07 22:45:34 +01:00
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):
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:
parent
75b3bf1842
commit
4ed0f518fb
1 changed files with 31 additions and 22 deletions
|
@ -177,6 +177,14 @@ pub type MozImageRect = generic::GenericMozImageRect<NumberOrPercentage, Specifi
|
||||||
/// Empty enum on non-Gecko
|
/// Empty enum on non-Gecko
|
||||||
pub enum MozImageRect {}
|
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 {
|
impl Parse for Image {
|
||||||
fn parse<'i, 't>(
|
fn parse<'i, 't>(
|
||||||
context: &ParserContext,
|
context: &ParserContext,
|
||||||
|
@ -186,8 +194,7 @@ impl Parse for Image {
|
||||||
context,
|
context,
|
||||||
input,
|
input,
|
||||||
CorsMode::None,
|
CorsMode::None,
|
||||||
/* allow_none = */ true,
|
ParseImageFlags::empty()
|
||||||
/* only_url = */ false,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -197,10 +204,9 @@ impl Image {
|
||||||
context: &ParserContext,
|
context: &ParserContext,
|
||||||
input: &mut Parser<'i, 't>,
|
input: &mut Parser<'i, 't>,
|
||||||
cors_mode: CorsMode,
|
cors_mode: CorsMode,
|
||||||
allow_none: bool,
|
flags: ParseImageFlags
|
||||||
only_url: bool,
|
|
||||||
) -> Result<Image, ParseError<'i>> {
|
) -> 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);
|
return Ok(generic::Image::None);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -210,13 +216,15 @@ impl Image {
|
||||||
return Ok(generic::Image::Url(url));
|
return Ok(generic::Image::Url(url));
|
||||||
}
|
}
|
||||||
|
|
||||||
if image_set_enabled() {
|
if !flags.contains(ParseImageFlags::FORBID_IMAGE_SET) && image_set_enabled() {
|
||||||
if let Ok(is) = input.try_parse(|input| ImageSet::parse(context, input, cors_mode, only_url)) {
|
if let Ok(is) =
|
||||||
|
input.try_parse(|input| ImageSet::parse(context, input, cors_mode, flags))
|
||||||
|
{
|
||||||
return Ok(generic::Image::ImageSet(Box::new(is)));
|
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));
|
return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -225,7 +233,7 @@ impl Image {
|
||||||
}
|
}
|
||||||
|
|
||||||
if cross_fade_enabled() {
|
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)));
|
return Ok(generic::Image::CrossFade(Box::new(cf)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -279,8 +287,7 @@ impl Image {
|
||||||
context,
|
context,
|
||||||
input,
|
input,
|
||||||
CorsMode::Anonymous,
|
CorsMode::Anonymous,
|
||||||
/* allow_none = */ true,
|
ParseImageFlags::empty()
|
||||||
/* only_url = */ false,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -293,8 +300,7 @@ impl Image {
|
||||||
context,
|
context,
|
||||||
input,
|
input,
|
||||||
CorsMode::None,
|
CorsMode::None,
|
||||||
/* allow_none = */ false,
|
ParseImageFlags::FORBID_NONE | ParseImageFlags::FORBID_NON_URL
|
||||||
/* only_url = */ true,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -305,10 +311,11 @@ impl CrossFade {
|
||||||
context: &ParserContext,
|
context: &ParserContext,
|
||||||
input: &mut Parser<'i, 't>,
|
input: &mut Parser<'i, 't>,
|
||||||
cors_mode: CorsMode,
|
cors_mode: CorsMode,
|
||||||
|
flags: ParseImageFlags
|
||||||
) -> Result<Self, ParseError<'i>> {
|
) -> Result<Self, ParseError<'i>> {
|
||||||
input.expect_function_matching("cross-fade")?;
|
input.expect_function_matching("cross-fade")?;
|
||||||
let elements = input.parse_nested_block(|input| {
|
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);
|
let elements = crate::OwnedSlice::from(elements);
|
||||||
Ok(Self { elements })
|
Ok(Self { elements })
|
||||||
|
@ -335,11 +342,12 @@ impl CrossFadeElement {
|
||||||
context: &ParserContext,
|
context: &ParserContext,
|
||||||
input: &mut Parser<'i, 't>,
|
input: &mut Parser<'i, 't>,
|
||||||
cors_mode: CorsMode,
|
cors_mode: CorsMode,
|
||||||
|
flags: ParseImageFlags
|
||||||
) -> Result<Self, ParseError<'i>> {
|
) -> Result<Self, ParseError<'i>> {
|
||||||
// Try and parse a leading percent sign.
|
// Try and parse a leading percent sign.
|
||||||
let mut percent = Self::parse_percentage(context, input);
|
let mut percent = Self::parse_percentage(context, input);
|
||||||
// Parse the image
|
// 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.
|
// Try and parse a trailing percent sign.
|
||||||
if percent.is_none() {
|
if percent.is_none() {
|
||||||
percent = Self::parse_percentage(context, input);
|
percent = Self::parse_percentage(context, input);
|
||||||
|
@ -356,11 +364,12 @@ impl CrossFadeImage {
|
||||||
context: &ParserContext,
|
context: &ParserContext,
|
||||||
input: &mut Parser<'i, 't>,
|
input: &mut Parser<'i, 't>,
|
||||||
cors_mode: CorsMode,
|
cors_mode: CorsMode,
|
||||||
|
flags: ParseImageFlags
|
||||||
) -> Result<Self, ParseError<'i>> {
|
) -> Result<Self, ParseError<'i>> {
|
||||||
if let Ok(image) = input.try_parse(|input| {
|
if let Ok(image) = input.try_parse(|input| {
|
||||||
Image::parse_with_cors_mode(
|
Image::parse_with_cors_mode(
|
||||||
context, input, cors_mode, /* allow_none = */ false,
|
context, input, cors_mode,
|
||||||
/* only_url = */ false,
|
flags | ParseImageFlags::FORBID_NONE
|
||||||
)
|
)
|
||||||
}) {
|
}) {
|
||||||
return Ok(Self::Image(image));
|
return Ok(Self::Image(image));
|
||||||
|
@ -374,7 +383,7 @@ impl ImageSet {
|
||||||
context: &ParserContext,
|
context: &ParserContext,
|
||||||
input: &mut Parser<'i, 't>,
|
input: &mut Parser<'i, 't>,
|
||||||
cors_mode: CorsMode,
|
cors_mode: CorsMode,
|
||||||
only_url: bool,
|
flags: ParseImageFlags
|
||||||
) -> Result<Self, ParseError<'i>> {
|
) -> Result<Self, ParseError<'i>> {
|
||||||
let function = input.expect_function()?;
|
let function = input.expect_function()?;
|
||||||
match_ignore_ascii_case! { &function,
|
match_ignore_ascii_case! { &function,
|
||||||
|
@ -386,7 +395,7 @@ impl ImageSet {
|
||||||
}
|
}
|
||||||
let items = input.parse_nested_block(|input| {
|
let items = input.parse_nested_block(|input| {
|
||||||
input.parse_comma_separated(|input| {
|
input.parse_comma_separated(|input| {
|
||||||
ImageSetItem::parse(context, input, cors_mode, only_url)
|
ImageSetItem::parse(context, input, cors_mode, flags)
|
||||||
})
|
})
|
||||||
})?;
|
})?;
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
|
@ -406,7 +415,7 @@ impl ImageSetItem {
|
||||||
context: &ParserContext,
|
context: &ParserContext,
|
||||||
input: &mut Parser<'i, 't>,
|
input: &mut Parser<'i, 't>,
|
||||||
cors_mode: CorsMode,
|
cors_mode: CorsMode,
|
||||||
only_url: bool,
|
flags: ParseImageFlags
|
||||||
) -> Result<Self, ParseError<'i>> {
|
) -> Result<Self, ParseError<'i>> {
|
||||||
let image = match input.try_parse(|i| i.expect_url_or_string()) {
|
let image = match input.try_parse(|i| i.expect_url_or_string()) {
|
||||||
Ok(url) => Image::Url(SpecifiedImageUrl::parse_from_string(
|
Ok(url) => Image::Url(SpecifiedImageUrl::parse_from_string(
|
||||||
|
@ -415,8 +424,8 @@ impl ImageSetItem {
|
||||||
cors_mode,
|
cors_mode,
|
||||||
)),
|
)),
|
||||||
Err(..) => Image::parse_with_cors_mode(
|
Err(..) => Image::parse_with_cors_mode(
|
||||||
context, input, cors_mode, /* allow_none = */ false,
|
context, input, cors_mode,
|
||||||
/* only_url = */ only_url,
|
flags | ParseImageFlags::FORBID_NONE | ParseImageFlags::FORBID_IMAGE_SET
|
||||||
)?,
|
)?,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue