style: Add a pref for a simpler -moz- gradient parsing.

This won't reintroduce any of the regressions that were triggered by our
previous attempts to turn off -moz prefixed gradients, and lets us massively
simplify the gradient code, if it sticks.

Differential Revision: https://phabricator.services.mozilla.com/D29346
This commit is contained in:
Emilio Cobos Álvarez 2019-04-30 19:48:27 +00:00
parent bec81dc9c2
commit e40500622e

View file

@ -8,6 +8,8 @@
//! [image]: https://drafts.csswg.org/css-images/#image-values //! [image]: https://drafts.csswg.org/css-images/#image-values
use crate::custom_properties::SpecifiedValue; use crate::custom_properties::SpecifiedValue;
#[cfg(feature = "gecko")]
use crate::gecko_bindings::structs;
use crate::parser::{Parse, ParserContext}; use crate::parser::{Parse, ParserContext};
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
use crate::values::computed::{Context, Position as ComputedPosition, ToComputedValue}; use crate::values::computed::{Context, Position as ComputedPosition, ToComputedValue};
@ -266,16 +268,6 @@ impl Parse for Gradient {
}, },
}; };
#[cfg(feature = "gecko")]
{
use crate::gecko_bindings::structs;
if compat_mode == CompatMode::Moz &&
!unsafe { structs::StaticPrefs_sVarCache_layout_css_prefixes_gradients }
{
return Err(input.new_custom_error(StyleParseErrorKind::UnexpectedFunction(func)));
}
}
let (kind, items) = input.parse_nested_block(|i| { let (kind, items) = input.parse_nested_block(|i| {
let shape = match shape { let shape = match shape {
Shape::Linear => GradientKind::parse_linear(context, i, &mut compat_mode)?, Shape::Linear => GradientKind::parse_linear(context, i, &mut compat_mode)?,
@ -548,6 +540,16 @@ impl Gradient {
} }
} }
#[inline]
fn simple_moz_gradient() -> bool {
#[cfg(feature = "gecko")]
unsafe {
return structs::StaticPrefs_sVarCache_layout_css_simple_moz_gradient_enabled;
}
#[cfg(not(feature = "gecko"))]
return false;
}
impl GradientKind { impl GradientKind {
/// Parses a linear gradient. /// Parses a linear gradient.
/// CompatMode can change during `-moz-` prefixed gradient parsing if it come across a `to` keyword. /// CompatMode can change during `-moz-` prefixed gradient parsing if it come across a `to` keyword.
@ -583,16 +585,6 @@ impl GradientKind {
}); });
(shape, position.ok(), None, None) (shape, position.ok(), None, None)
}, },
CompatMode::WebKit => {
let position = input.try(|i| Position::parse(context, i));
let shape = input.try(|i| {
if position.is_ok() {
i.expect_comma()?;
}
EndingShape::parse(context, i, *compat_mode)
});
(shape, position.ok(), None, None)
},
// The syntax of `-moz-` prefixed radial gradient is: // The syntax of `-moz-` prefixed radial gradient is:
// -moz-radial-gradient( // -moz-radial-gradient(
// [ [ <position> || <angle> ]? [ ellipse | [ <length> | <percentage> ]{2} ] , | // [ [ <position> || <angle> ]? [ ellipse | [ <length> | <percentage> ]{2} ] , |
@ -603,7 +595,7 @@ impl GradientKind {
// where <extent-keyword> = closest-corner | closest-side | farthest-corner | farthest-side | // where <extent-keyword> = closest-corner | closest-side | farthest-corner | farthest-side |
// cover | contain // cover | contain
// and <color-stop> = <color> [ <percentage> | <length> ]? // and <color-stop> = <color> [ <percentage> | <length> ]?
CompatMode::Moz => { CompatMode::Moz if !simple_moz_gradient() => {
let mut position = input.try(|i| LegacyPosition::parse(context, i)); let mut position = input.try(|i| LegacyPosition::parse(context, i));
let angle = input.try(|i| Angle::parse(context, i)).ok(); let angle = input.try(|i| Angle::parse(context, i)).ok();
if position.is_err() { if position.is_err() {
@ -619,6 +611,16 @@ impl GradientKind {
(shape, None, angle, position.ok()) (shape, None, angle, position.ok())
}, },
_ => {
let position = input.try(|i| Position::parse(context, i));
let shape = input.try(|i| {
if position.is_ok() {
i.expect_comma()?;
}
EndingShape::parse(context, i, *compat_mode)
});
(shape, position.ok(), None, None)
},
}; };
if shape.is_ok() || position.is_some() || angle.is_some() || moz_position.is_some() { if shape.is_ok() || position.is_some() || angle.is_some() || moz_position.is_some() {
@ -631,7 +633,7 @@ impl GradientKind {
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
{ {
if *compat_mode == CompatMode::Moz { if *compat_mode == CompatMode::Moz && !simple_moz_gradient() {
// If this form can be represented in Modern mode, then convert the compat_mode to Modern. // If this form can be represented in Modern mode, then convert the compat_mode to Modern.
if angle.is_none() { if angle.is_none() {
*compat_mode = CompatMode::Modern; *compat_mode = CompatMode::Modern;
@ -751,7 +753,7 @@ impl LineDirection {
input: &mut Parser<'i, 't>, input: &mut Parser<'i, 't>,
compat_mode: &mut CompatMode, compat_mode: &mut CompatMode,
) -> Result<Self, ParseError<'i>> { ) -> Result<Self, ParseError<'i>> {
let mut _angle = if *compat_mode == CompatMode::Moz { let mut _angle = if *compat_mode == CompatMode::Moz && !simple_moz_gradient() {
input.try(|i| Angle::parse(context, i)).ok() input.try(|i| Angle::parse(context, i)).ok()
} else { } else {
// Gradients allow unitless zero angles as an exception, see: // Gradients allow unitless zero angles as an exception, see:
@ -784,7 +786,7 @@ impl LineDirection {
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
{ {
// `-moz-` prefixed linear gradient can be both Angle and Position. // `-moz-` prefixed linear gradient can be both Angle and Position.
if *compat_mode == CompatMode::Moz { if *compat_mode == CompatMode::Moz && !simple_moz_gradient(){
let position = i.try(|i| LegacyPosition::parse(context, i)).ok(); let position = i.try(|i| LegacyPosition::parse(context, i)).ok();
if _angle.is_none() { if _angle.is_none() {
_angle = i.try(|i| Angle::parse(context, i)).ok(); _angle = i.try(|i| Angle::parse(context, i)).ok();
@ -874,7 +876,7 @@ impl EndingShape {
} }
// -moz- prefixed radial gradient doesn't allow EndingShape's Length or LengthPercentage // -moz- prefixed radial gradient doesn't allow EndingShape's Length or LengthPercentage
// to come before shape keyword. Otherwise it conflicts with <position>. // to come before shape keyword. Otherwise it conflicts with <position>.
if compat_mode != CompatMode::Moz { if compat_mode != CompatMode::Moz || simple_moz_gradient() {
if let Ok(length) = input.try(|i| Length::parse(context, i)) { if let Ok(length) = input.try(|i| Length::parse(context, i)) {
if let Ok(y) = input.try(|i| LengthPercentage::parse(context, i)) { if let Ok(y) = input.try(|i| LengthPercentage::parse(context, i)) {
if compat_mode == CompatMode::Modern { if compat_mode == CompatMode::Modern {