diff options
76 files changed, 1024 insertions, 814 deletions
diff --git a/Cargo.lock b/Cargo.lock index b1e23405138..814337eed4d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1930,6 +1930,7 @@ dependencies = [ "malloc_size_of 0.0.1", "msg 0.0.1", "net_traits 0.0.1", + "num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "ordered-float 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", "profile_traits 0.0.1", diff --git a/components/layout/Cargo.toml b/components/layout/Cargo.toml index 9a960b51305..06de13c951f 100644 --- a/components/layout/Cargo.toml +++ b/components/layout/Cargo.toml @@ -29,6 +29,7 @@ log = "0.4" malloc_size_of = { path = "../malloc_size_of" } msg = {path = "../msg"} net_traits = {path = "../net_traits"} +num-traits = "0.2" ordered-float = "1.0" parking_lot = "0.6" profile_traits = {path = "../profile_traits"} diff --git a/components/layout/flow.rs b/components/layout/flow.rs index 4bf7622636c..b25d3ba028d 100644 --- a/components/layout/flow.rs +++ b/components/layout/flow.rs @@ -49,6 +49,7 @@ use crate::table_wrapper::TableWrapperFlow; use euclid::{Point2D, Rect, Size2D, Vector2D}; use gfx_traits::print_tree::PrintTree; use gfx_traits::StackingContextId; +use num_traits::cast::FromPrimitive; use serde::ser::{Serialize, SerializeStruct, Serializer}; use servo_geometry::{au_rect_to_f32_rect, f32_rect_to_au_rect, MaxRect}; use std::fmt; diff --git a/components/style/cbindgen.toml b/components/style/cbindgen.toml index 50252690054..06c1730622a 100644 --- a/components/style/cbindgen.toml +++ b/components/style/cbindgen.toml @@ -49,6 +49,7 @@ include = [ "FontDisplay", "FontFaceSourceListComponent", "FontLanguageOverride", + "OverflowWrap", "TimingFunction", "PathCommand", "UnicodeRange", diff --git a/components/style/counter_style/mod.rs b/components/style/counter_style/mod.rs index 59556a04a88..a346f9d21af 100644 --- a/components/style/counter_style/mod.rs +++ b/components/style/counter_style/mod.rs @@ -370,7 +370,7 @@ impl Parse for System { "symbolic" => Ok(System::Symbolic), "additive" => Ok(System::Additive), "fixed" => { - let first_symbol_value = input.r#try(|i| Integer::parse(context, i)).ok(); + let first_symbol_value = input.try(|i| Integer::parse(context, i)).ok(); Ok(System::Fixed { first_symbol_value: first_symbol_value }) } "extends" => { @@ -457,7 +457,7 @@ impl Parse for Negative { ) -> Result<Self, ParseError<'i>> { Ok(Negative( Symbol::parse(context, input)?, - input.r#try(|input| Symbol::parse(context, input)).ok(), + input.try(|input| Symbol::parse(context, input)).ok(), )) } } @@ -483,7 +483,7 @@ impl Parse for Ranges { input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { if input - .r#try(|input| input.expect_ident_matching("auto")) + .try(|input| input.expect_ident_matching("auto")) .is_ok() { Ok(Ranges(Vec::new())) @@ -512,7 +512,7 @@ fn parse_bound<'i, 't>( context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result<CounterBound, ParseError<'i>> { - if let Ok(integer) = input.r#try(|input| Integer::parse(context, input)) { + if let Ok(integer) = input.try(|input| Integer::parse(context, input)) { return Ok(CounterBound::Integer(integer)); } input.expect_ident_matching("infinite")?; @@ -556,7 +556,7 @@ impl Parse for Pad { context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { - let pad_with = input.r#try(|input| Symbol::parse(context, input)); + let pad_with = input.try(|input| Symbol::parse(context, input)); let min_length = Integer::parse_non_negative(context, input)?; let pad_with = pad_with.or_else(|_| Symbol::parse(context, input))?; Ok(Pad(min_length, pad_with)) @@ -588,7 +588,7 @@ impl Parse for Symbols { ) -> Result<Self, ParseError<'i>> { let mut symbols = Vec::new(); loop { - if let Ok(s) = input.r#try(|input| Symbol::parse(context, input)) { + if let Ok(s) = input.try(|input| Symbol::parse(context, input)) { symbols.push(s) } else { if symbols.is_empty() { @@ -640,7 +640,7 @@ impl Parse for AdditiveTuple { context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { - let symbol = input.r#try(|input| Symbol::parse(context, input)); + let symbol = input.try(|input| Symbol::parse(context, input)); let weight = Integer::parse_non_negative(context, input)?; let symbol = symbol.or_else(|_| Symbol::parse(context, input))?; Ok(AdditiveTuple { @@ -673,7 +673,7 @@ impl Parse for SpeakAs { input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { let mut is_spell_out = false; - let result = input.r#try(|input| { + let result = input.try(|input| { let ident = input.expect_ident().map_err(|_| ())?; match_ignore_ascii_case! { &*ident, "auto" => Ok(SpeakAs::Auto), diff --git a/components/style/custom_properties.rs b/components/style/custom_properties.rs index 5bd97241b67..31c3dc207f5 100644 --- a/components/style/custom_properties.rs +++ b/components/style/custom_properties.rs @@ -553,7 +553,7 @@ fn parse_var_function<'i, 't>( let name = parse_name(&name).map_err(|()| { input.new_custom_error(SelectorParseErrorKind::UnexpectedIdent(name.clone())) })?; - if input.r#try(|input| input.expect_comma()).is_ok() { + if input.try(|input| input.expect_comma()).is_ok() { parse_fallback(input)?; } if let Some(refs) = references { @@ -569,7 +569,7 @@ fn parse_env_function<'i, 't>( // TODO(emilio): This should be <custom-ident> per spec, but no other // browser does that, see https://github.com/w3c/csswg-drafts/issues/3262. input.expect_ident()?; - if input.r#try(|input| input.expect_comma()).is_ok() { + if input.try(|input| input.expect_comma()).is_ok() { parse_fallback(input)?; } if let Some(references) = references { diff --git a/components/style/font_face.rs b/components/style/font_face.rs index 92444b7b145..c434e0957c6 100644 --- a/components/style/font_face.rs +++ b/components/style/font_face.rs @@ -14,12 +14,12 @@ use crate::shared_lock::{SharedRwLockReadGuard, ToCssWithGuard}; use crate::str::CssStringWriter; use crate::values::computed::font::FamilyName; use crate::values::generics::font::FontStyle as GenericFontStyle; +#[cfg(feature = "gecko")] +use crate::values::specified::font::SpecifiedFontFeatureSettings; use crate::values::specified::font::SpecifiedFontStyle; -use crate::values::specified::font::{AbsoluteFontWeight, FontStretch}; #[cfg(feature = "gecko")] -use crate::values::specified::font::{ - SpecifiedFontFeatureSettings, SpecifiedFontVariationSettings, -}; +use crate::values::specified::font::SpecifiedFontVariationSettings; +use crate::values::specified::font::{AbsoluteFontWeight, FontStretch}; use crate::values::specified::url::SpecifiedUrl; use crate::values::specified::Angle; #[cfg(feature = "gecko")] @@ -120,7 +120,7 @@ macro_rules! impl_range { ) -> Result<Self, ParseError<'i>> { let first = $component::parse(context, input)?; let second = input - .r#try(|input| $component::parse(context, input)) + .try(|input| $component::parse(context, input)) .unwrap_or_else(|_| first.clone()); Ok($range(first, second)) } @@ -234,7 +234,7 @@ impl Parse for FontStyle { GenericFontStyle::Italic => FontStyle::Italic, GenericFontStyle::Oblique(angle) => { let second_angle = input - .r#try(|input| SpecifiedFontStyle::parse_angle(context, input)) + .try(|input| SpecifiedFontStyle::parse_angle(context, input)) .unwrap_or_else(|_| angle.clone()); FontStyle::Oblique(angle, second_angle) @@ -380,7 +380,7 @@ impl Parse for Source { input: &mut Parser<'i, 't>, ) -> Result<Source, ParseError<'i>> { if input - .r#try(|input| input.expect_function_matching("local")) + .try(|input| input.expect_function_matching("local")) .is_ok() { return input @@ -392,7 +392,7 @@ impl Parse for Source { // Parsing optional format() let format_hints = if input - .r#try(|input| input.expect_function_matching("format")) + .try(|input| input.expect_function_matching("format")) .is_ok() { input.parse_nested_block(|input| { diff --git a/components/style/gecko/arc_types.rs b/components/style/gecko/arc_types.rs index 5ce096270f2..b2f86f477e0 100644 --- a/components/style/gecko/arc_types.rs +++ b/components/style/gecko/arc_types.rs @@ -38,9 +38,8 @@ use crate::rule_tree::StrongRuleNode; use crate::shared_lock::Locked; use crate::stylesheets::keyframes_rule::Keyframe; use crate::stylesheets::{CounterStyleRule, CssRules, FontFaceRule, FontFeatureValuesRule}; -use crate::stylesheets::{ - DocumentRule, ImportRule, KeyframesRule, MediaRule, NamespaceRule, PageRule, -}; +use crate::stylesheets::{DocumentRule, ImportRule, KeyframesRule, MediaRule}; +use crate::stylesheets::{NamespaceRule, PageRule}; use crate::stylesheets::{StyleRule, StylesheetContents, SupportsRule}; use servo_arc::{Arc, ArcBorrow}; use std::{mem, ptr}; diff --git a/components/style/gecko/conversions.rs b/components/style/gecko/conversions.rs index 1611e286e6e..cf8c1de1ba1 100644 --- a/components/style/gecko/conversions.rs +++ b/components/style/gecko/conversions.rs @@ -18,9 +18,8 @@ use crate::stylesheets::{Origin, RulesMutateError}; use crate::values::computed::image::LineDirection; use crate::values::computed::url::ComputedImageUrl; use crate::values::computed::{Angle, CalcLengthOrPercentage, Gradient, Image}; -use crate::values::computed::{ - Integer, LengthOrPercentage, LengthOrPercentageOrAuto, NonNegativeLengthOrPercentageOrAuto, -}; +use crate::values::computed::{Integer, LengthOrPercentage}; +use crate::values::computed::{LengthOrPercentageOrAuto, NonNegativeLengthOrPercentageOrAuto}; use crate::values::computed::{Percentage, TextAlign}; use crate::values::generics::box_::VerticalAlign; use crate::values::generics::grid::{TrackListValue, TrackSize}; diff --git a/components/style/gecko/global_style_data.rs b/components/style/gecko/global_style_data.rs index 70cd452f904..7e40d12e5f6 100644 --- a/components/style/gecko/global_style_data.rs +++ b/components/style/gecko/global_style_data.rs @@ -5,10 +5,7 @@ //! Global style data use crate::context::StyleSystemOptions; -use crate::gecko_bindings::bindings::Gecko_SetJemallocThreadLocalArena; -use crate::gecko_bindings::bindings::{ - Gecko_RegisterProfilerThread, Gecko_UnregisterProfilerThread, -}; +use crate::gecko_bindings::bindings; use crate::parallel::STYLE_THREAD_STACK_SIZE_KB; use crate::shared_lock::SharedRwLock; use crate::thread_state; @@ -43,20 +40,20 @@ fn thread_name(index: usize) -> String { fn thread_startup(index: usize) { thread_state::initialize_layout_worker_thread(); unsafe { - Gecko_SetJemallocThreadLocalArena(true); + bindings::Gecko_SetJemallocThreadLocalArena(true); } let name = thread_name(index); let name = CString::new(name).unwrap(); unsafe { // Gecko_RegisterProfilerThread copies the passed name here. - Gecko_RegisterProfilerThread(name.as_ptr()); + bindings::Gecko_RegisterProfilerThread(name.as_ptr()); } } fn thread_shutdown(_: usize) { unsafe { - Gecko_UnregisterProfilerThread(); - Gecko_SetJemallocThreadLocalArena(false); + bindings::Gecko_UnregisterProfilerThread(); + bindings::Gecko_SetJemallocThreadLocalArena(false); } } diff --git a/components/style/gecko/pseudo_element.rs b/components/style/gecko/pseudo_element.rs index 21eb2322a00..32b7db63a20 100644 --- a/components/style/gecko/pseudo_element.rs +++ b/components/style/gecko/pseudo_element.rs @@ -27,12 +27,14 @@ include!(concat!( impl ::selectors::parser::PseudoElement for PseudoElement { type Impl = SelectorImpl; + // ::slotted() should support all tree-abiding pseudo-elements, see + // https://drafts.csswg.org/css-scoping/#slotted-pseudo + // https://drafts.csswg.org/css-pseudo-4/#treelike fn valid_after_slotted(&self) -> bool { - // TODO(emilio): Remove this function or this comment after [1] is - // resolved. - // - // [1]: https://github.com/w3c/csswg-drafts/issues/3150 - self.is_before_or_after() + matches!( + *self, + PseudoElement::Before | PseudoElement::After | PseudoElement::Placeholder + ) } fn supports_pseudo_class(&self, pseudo_class: &NonTSPseudoClass) -> bool { diff --git a/components/style/gecko/values.rs b/components/style/gecko/values.rs index 16236b025c2..f7debc860f3 100644 --- a/components/style/gecko/values.rs +++ b/components/style/gecko/values.rs @@ -14,13 +14,12 @@ use crate::gecko_bindings::sugar::ns_style_coord::{CoordData, CoordDataMut, Coor use crate::media_queries::Device; use crate::values::computed::basic_shape::ShapeRadius as ComputedShapeRadius; use crate::values::computed::FlexBasis as ComputedFlexBasis; +use crate::values::computed::NonNegativeNumber; use crate::values::computed::{Angle, ExtremumLength, Length, LengthOrPercentage}; use crate::values::computed::{LengthOrPercentageOrAuto, Percentage}; use crate::values::computed::{LengthOrPercentageOrNone, Number, NumberOrPercentage}; use crate::values::computed::{MaxLength as ComputedMaxLength, MozLength as ComputedMozLength}; -use crate::values::computed::{ - NonNegativeLength, NonNegativeLengthOrPercentage, NonNegativeNumber, -}; +use crate::values::computed::{NonNegativeLength, NonNegativeLengthOrPercentage}; use crate::values::generics::basic_shape::ShapeRadius; use crate::values::generics::box_::Perspective; use crate::values::generics::flex::FlexBasis; diff --git a/components/style/gecko_bindings/sugar/ns_style_coord.rs b/components/style/gecko_bindings/sugar/ns_style_coord.rs index 90d2440010d..e4958999b28 100644 --- a/components/style/gecko_bindings/sugar/ns_style_coord.rs +++ b/components/style/gecko_bindings/sugar/ns_style_coord.rs @@ -6,9 +6,8 @@ use crate::gecko_bindings::bindings; use crate::gecko_bindings::structs::{nsStyleCoord, nsStyleCoord_Calc, nsStyleCoord_CalcValue}; -use crate::gecko_bindings::structs::{ - nsStyleCorners, nsStyleSides, nsStyleUnion, nsStyleUnit, nscoord, -}; +use crate::gecko_bindings::structs::{nsStyleCorners, nsStyleSides}; +use crate::gecko_bindings::structs::{nsStyleUnion, nsStyleUnit, nscoord}; use std::mem; impl nsStyleCoord { diff --git a/components/style/gecko_string_cache/mod.rs b/components/style/gecko_string_cache/mod.rs index d822600afd9..6d9e5c60f80 100644 --- a/components/style/gecko_string_cache/mod.rs +++ b/components/style/gecko_string_cache/mod.rs @@ -14,7 +14,7 @@ use crate::gecko_bindings::bindings::Gecko_AddRefAtom; use crate::gecko_bindings::bindings::Gecko_Atomize; use crate::gecko_bindings::bindings::Gecko_Atomize16; use crate::gecko_bindings::bindings::Gecko_ReleaseAtom; -use crate::gecko_bindings::structs::{nsAtom, nsAtom_AtomKind, nsDynamicAtom, nsStaticAtom}; +use crate::gecko_bindings::structs::{nsAtom, nsDynamicAtom, nsStaticAtom}; use nsstring::{nsAString, nsStr}; use precomputed_hash::PrecomputedHash; use std::borrow::{Borrow, Cow}; @@ -175,7 +175,7 @@ impl WeakAtom { /// Returns whether this atom is static. #[inline] pub fn is_static(&self) -> bool { - unsafe { (*self.as_ptr()).mKind() == nsAtom_AtomKind::Static as u32 } + unsafe { (*self.as_ptr()).mIsStatic() != 0 } } /// Returns the length of the atom string. diff --git a/components/style/lib.rs b/components/style/lib.rs index 6694f776ab8..77927826523 100644 --- a/components/style/lib.rs +++ b/components/style/lib.rs @@ -143,6 +143,7 @@ pub mod media_queries; pub mod parallel; pub mod parser; pub mod rule_cache; +pub mod rule_collector; pub mod rule_tree; pub mod scoped_tls; pub mod selector_map; diff --git a/components/style/media_queries/media_condition.rs b/components/style/media_queries/media_condition.rs index c0b8f49b566..b7da1503b33 100644 --- a/components/style/media_queries/media_condition.rs +++ b/components/style/media_queries/media_condition.rs @@ -114,7 +114,7 @@ impl MediaCondition { // ParenthesisBlock. let first_condition = Self::parse_paren_block(context, input)?; - let operator = match input.r#try(Operator::parse) { + let operator = match input.try(Operator::parse) { Ok(op) => op, Err(..) => return Ok(first_condition), }; @@ -133,7 +133,7 @@ impl MediaCondition { }; loop { - if input.r#try(|i| i.expect_ident_matching(delim)).is_err() { + if input.try(|i| i.expect_ident_matching(delim)).is_err() { return Ok(MediaCondition::Operation( conditions.into_boxed_slice(), operator, @@ -159,7 +159,7 @@ impl MediaCondition { ) -> Result<Self, ParseError<'i>> { input.parse_nested_block(|input| { // Base case. - if let Ok(inner) = input.r#try(|i| Self::parse(context, i)) { + if let Ok(inner) = input.try(|i| Self::parse(context, i)) { return Ok(MediaCondition::InParens(Box::new(inner))); } let expr = MediaFeatureExpression::parse_in_parenthesis_block(context, input)?; diff --git a/components/style/media_queries/media_feature_expression.rs b/components/style/media_queries/media_feature_expression.rs index 67c1f3b527a..b6bfc03179d 100644 --- a/components/style/media_queries/media_feature_expression.rs +++ b/components/style/media_queries/media_feature_expression.rs @@ -221,14 +221,14 @@ fn consume_operation_or_colon(input: &mut Parser) -> Result<Option<Operator>, () Ok(Some(match first_delim { '=' => Operator::Equal, '>' => { - if input.r#try(|i| i.expect_delim('=')).is_ok() { + if input.try(|i| i.expect_delim('=')).is_ok() { Operator::GreaterThanEqual } else { Operator::GreaterThan } }, '<' => { - if input.r#try(|i| i.expect_delim('=')).is_ok() { + if input.try(|i| i.expect_delim('=')).is_ok() { Operator::LessThanEqual } else { Operator::LessThan @@ -350,7 +350,7 @@ impl MediaFeatureExpression { } } - let operator = input.r#try(consume_operation_or_colon); + let operator = input.try(consume_operation_or_colon); let operator = match operator { Err(..) => { // If there's no colon, this is a media query of the diff --git a/components/style/media_queries/media_query.rs b/components/style/media_queries/media_query.rs index 61e2e06c573..88ad288bf3b 100644 --- a/components/style/media_queries/media_query.rs +++ b/components/style/media_queries/media_query.rs @@ -125,8 +125,8 @@ impl MediaQuery { input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { let (qualifier, explicit_media_type) = input - .r#try(|input| -> Result<_, ()> { - let qualifier = input.r#try(Qualifier::parse).ok(); + .try(|input| -> Result<_, ()> { + let qualifier = input.try(Qualifier::parse).ok(); let ident = input.expect_ident().map_err(|_| ())?; let media_type = MediaQueryType::parse(&ident)?; Ok((qualifier, Some(media_type))) @@ -135,7 +135,7 @@ impl MediaQuery { let condition = if explicit_media_type.is_none() { Some(MediaCondition::parse(context, input)?) - } else if input.r#try(|i| i.expect_ident_matching("and")).is_ok() { + } else if input.try(|i| i.expect_ident_matching("and")).is_ok() { Some(MediaCondition::parse_disallow_or(context, input)?) } else { None diff --git a/components/style/properties/data.py b/components/style/properties/data.py index 38fb9b71c6d..10f64484693 100644 --- a/components/style/properties/data.py +++ b/components/style/properties/data.py @@ -324,6 +324,7 @@ class Longhand(object): "Opacity", "OutlineStyle", "OverflowClipBox", + "OverflowWrap", "OverscrollBehavior", "Percentage", "Resize", diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index b41e84a3be8..b845d382623 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -1419,6 +1419,7 @@ impl Clone for ${style_struct.gecko_struct_name} { "NonNegativeNumber": impl_simple, "Number": impl_simple, "Opacity": impl_simple, + "OverflowWrap": impl_simple, "Perspective": impl_style_coord, "Position": impl_position, "RGBAColor": impl_rgba_color, diff --git a/components/style/properties/helpers/animated_properties.mako.rs b/components/style/properties/helpers/animated_properties.mako.rs index 284e35877df..5ff4a10c3c0 100644 --- a/components/style/properties/helpers/animated_properties.mako.rs +++ b/components/style/properties/helpers/animated_properties.mako.rs @@ -2102,12 +2102,12 @@ impl Matrix3D { /// <https://drafts.csswg.org/css-transforms-2/#propdef-rotate> impl ComputedRotate { - fn resolve(rotate: &ComputedRotate) -> (Number, Number, Number, Angle) { + fn resolve(&self) -> (Number, Number, Number, Angle) { // According to the spec: // https://drafts.csswg.org/css-transforms-2/#individual-transforms // // If the axis is unspecified, it defaults to "0 0 1" - match *rotate { + match *self { Rotate::None => (0., 0., 1., Angle::zero()), Rotate::Rotate3D(rx, ry, rz, angle) => (rx, ry, rz, angle), Rotate::Rotate(angle) => (0., 0., 1., angle), @@ -2122,8 +2122,7 @@ impl Animate for ComputedRotate { other: &Self, procedure: Procedure, ) -> Result<Self, ()> { - let from = ComputedRotate::resolve(self); - let to = ComputedRotate::resolve(other); + let (from, to) = (self.resolve(), other.resolve()); let (mut fx, mut fy, mut fz, fa) = transform::get_normalized_vector_and_angle(from.0, from.1, from.2, from.3); @@ -2163,24 +2162,17 @@ impl Animate for ComputedRotate { /// <https://drafts.csswg.org/css-transforms-2/#propdef-translate> impl ComputedTranslate { - fn resolve( - translate: &ComputedTranslate, - ) -> (LengthOrPercentage, LengthOrPercentage, Length) { + fn resolve(&self) -> (LengthOrPercentage, LengthOrPercentage, Length) { // According to the spec: // https://drafts.csswg.org/css-transforms-2/#individual-transforms // // Unspecified translations default to 0px - match *translate { + match *self { Translate::None => { - ( - LengthOrPercentage::Length(Length::zero()), - LengthOrPercentage::Length(Length::zero()), - Length::zero(), - ) + (LengthOrPercentage::zero(), LengthOrPercentage::zero(), Length::zero()) }, Translate::Translate3D(tx, ty, tz) => (tx, ty, tz), Translate::Translate(tx, ty) => (tx, ty, Length::zero()), - Translate::TranslateX(tx) => (tx, LengthOrPercentage::Length(Length::zero()), Length::zero()), } } } @@ -2192,23 +2184,31 @@ impl Animate for ComputedTranslate { other: &Self, procedure: Procedure, ) -> Result<Self, ()> { - let from = ComputedTranslate::resolve(self); - let to = ComputedTranslate::resolve(other); - - Ok(Translate::Translate3D(from.0.animate(&to.0, procedure)?, - from.1.animate(&to.1, procedure)?, - from.2.animate(&to.2, procedure)?)) + match (self, other) { + (&Translate::None, &Translate::None) => Ok(Translate::None), + (&Translate::Translate3D(_, ..), _) | (_, &Translate::Translate3D(_, ..)) => { + let (from, to) = (self.resolve(), other.resolve()); + Ok(Translate::Translate3D(from.0.animate(&to.0, procedure)?, + from.1.animate(&to.1, procedure)?, + from.2.animate(&to.2, procedure)?)) + }, + (&Translate::Translate(_, ..), _) | (_, &Translate::Translate(_, ..)) => { + let (from, to) = (self.resolve(), other.resolve()); + Ok(Translate::Translate(from.0.animate(&to.0, procedure)?, + from.1.animate(&to.1, procedure)?)) + }, + } } } /// <https://drafts.csswg.org/css-transforms-2/#propdef-scale> impl ComputedScale { - fn resolve(scale: &ComputedScale) -> (Number, Number, Number) { + fn resolve(&self) -> (Number, Number, Number) { // According to the spec: // https://drafts.csswg.org/css-transforms-2/#individual-transforms // // Unspecified scales default to 1 - match *scale { + match *self { Scale::None => (1.0, 1.0, 1.0), Scale::Scale3D(sx, sy, sz) => (sx, sy, sz), Scale::Scale(sx, sy) => (sx, sy, 1.), @@ -2226,8 +2226,7 @@ impl Animate for ComputedScale { match (self, other) { (&Scale::None, &Scale::None) => Ok(Scale::None), (&Scale::Scale3D(_, ..), _) | (_, &Scale::Scale3D(_, ..)) => { - let from = ComputedScale::resolve(self); - let to = ComputedScale::resolve(other); + let (from, to) = (self.resolve(), other.resolve()); // FIXME(emilio, bug 1464791): why does this do something different than // Scale3D / TransformOperation::Scale3D? if procedure == Procedure::Add { @@ -2241,8 +2240,7 @@ impl Animate for ComputedScale { )) }, (&Scale::Scale(_, ..), _) | (_, &Scale::Scale(_, ..)) => { - let from = ComputedScale::resolve(self); - let to = ComputedScale::resolve(other); + let (from, to) = (self.resolve(), other.resolve()); // FIXME(emilio, bug 1464791): why does this do something different than // Scale / TransformOperation::Scale? if procedure == Procedure::Add { diff --git a/components/style/properties/longhands/box.mako.rs b/components/style/properties/longhands/box.mako.rs index c06ed16a22e..685e97aa3b0 100644 --- a/components/style/properties/longhands/box.mako.rs +++ b/components/style/properties/longhands/box.mako.rs @@ -370,7 +370,7 @@ ${helpers.predefined_type( "generics::transform::Translate::None", animation_value_type="ComputedValue", boxed=True, - flags="CREATES_STACKING_CONTEXT FIXPOS_CB GETCS_NEEDS_LAYOUT_FLUSH", + flags="CREATES_STACKING_CONTEXT FIXPOS_CB", gecko_pref="layout.css.individual-transform.enabled", spec="https://drafts.csswg.org/css-transforms-2/#individual-transforms", servo_restyle_damage="reflow_out_of_flow", diff --git a/components/style/properties/longhands/column.mako.rs b/components/style/properties/longhands/column.mako.rs index 4f223ceb856..d4bae90c96b 100644 --- a/components/style/properties/longhands/column.mako.rs +++ b/components/style/properties/longhands/column.mako.rs @@ -65,6 +65,7 @@ ${helpers.predefined_type( spec="https://drafts.csswg.org/css-multicol/#propdef-column-rule-color", )} +// FIXME: Remove enabled_in="ua" once column-span is enabled on nightly (bug 1423383). ${helpers.single_keyword( "column-span", "none all", @@ -72,6 +73,7 @@ ${helpers.single_keyword( animation_value_type="discrete", gecko_enum_prefix="StyleColumnSpan", gecko_pref="layout.css.column-span.enabled", + enabled_in="ua", spec="https://drafts.csswg.org/css-multicol/#propdef-column-span", extra_prefixes="moz:layout.css.column-span.enabled", )} diff --git a/components/style/properties/longhands/inherited_text.mako.rs b/components/style/properties/longhands/inherited_text.mako.rs index 5b6cf609826..e8c5629c300 100644 --- a/components/style/properties/longhands/inherited_text.mako.rs +++ b/components/style/properties/longhands/inherited_text.mako.rs @@ -61,15 +61,16 @@ ${helpers.predefined_type( servo_restyle_damage = "reflow", )} -// Also known as "word-wrap" (which is more popular because of IE), but this is the preferred -// name per CSS-TEXT 6.2. -${helpers.single_keyword( +// Also known as "word-wrap" (which is more popular because of IE), but this is +// the preferred name per CSS-TEXT 6.2. +${helpers.predefined_type( "overflow-wrap", - "normal break-word", - gecko_constant_prefix="NS_STYLE_OVERFLOWWRAP", + "OverflowWrap", + "computed::OverflowWrap::Normal", animation_value_type="discrete", spec="https://drafts.csswg.org/css-text/#propdef-overflow-wrap", alias="word-wrap", + needs_context=False, servo_restyle_damage="rebuild_and_reflow", )} @@ -136,7 +137,7 @@ ${helpers.single_keyword( ${helpers.predefined_type( "text-align", "TextAlign", - "computed::TextAlign::start()", + "computed::TextAlign::Start", animation_value_type="discrete", flags="APPLIES_TO_PLACEHOLDER", spec="https://drafts.csswg.org/css-text/#propdef-text-align", diff --git a/components/style/rule_collector.rs b/components/style/rule_collector.rs new file mode 100644 index 00000000000..f39dc0e6acb --- /dev/null +++ b/components/style/rule_collector.rs @@ -0,0 +1,391 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//! Collects a series of applicable rules for a given element. + +use crate::applicable_declarations::{ApplicableDeclarationBlock, ApplicableDeclarationList}; +use crate::dom::{TElement, TShadowRoot}; +use crate::properties::{AnimationRules, PropertyDeclarationBlock}; +use crate::rule_tree::{CascadeLevel, ShadowCascadeOrder}; +use crate::selector_map::SelectorMap; +use crate::selector_parser::PseudoElement; +use crate::shared_lock::Locked; +use crate::stylesheets::Origin; +use crate::stylist::{AuthorStylesEnabled, Rule, RuleInclusion, Stylist}; +use selectors::matching::{ElementSelectorFlags, MatchingContext}; +use servo_arc::ArcBorrow; +use smallvec::SmallVec; + +/// An object that we use with all the intermediate state needed for the +/// cascade. +/// +/// This is done basically to be able to organize the cascade in smaller +/// functions, and be able to reason about it easily. +pub struct RuleCollector<'a, 'b: 'a, E, F: 'a> +where + E: TElement, +{ + element: E, + rule_hash_target: E, + stylist: &'a Stylist, + pseudo_element: Option<&'a PseudoElement>, + style_attribute: Option<ArcBorrow<'a, Locked<PropertyDeclarationBlock>>>, + smil_override: Option<ArcBorrow<'a, Locked<PropertyDeclarationBlock>>>, + animation_rules: AnimationRules, + rule_inclusion: RuleInclusion, + rules: &'a mut ApplicableDeclarationList, + context: &'a mut MatchingContext<'b, E::Impl>, + flags_setter: &'a mut F, + shadow_cascade_order: ShadowCascadeOrder, + matches_user_and_author_rules: bool, + matches_document_author_rules: bool, +} + +impl<'a, 'b: 'a, E, F: 'a> RuleCollector<'a, 'b, E, F> +where + E: TElement, + F: FnMut(&E, ElementSelectorFlags), +{ + /// Trivially construct a new collector. + pub fn new( + stylist: &'a Stylist, + element: E, + pseudo_element: Option<&'a PseudoElement>, + style_attribute: Option<ArcBorrow<'a, Locked<PropertyDeclarationBlock>>>, + smil_override: Option<ArcBorrow<'a, Locked<PropertyDeclarationBlock>>>, + animation_rules: AnimationRules, + rule_inclusion: RuleInclusion, + rules: &'a mut ApplicableDeclarationList, + context: &'a mut MatchingContext<'b, E::Impl>, + flags_setter: &'a mut F, + ) -> Self { + let rule_hash_target = element.rule_hash_target(); + let matches_user_and_author_rules = rule_hash_target.matches_user_and_author_rules(); + + // Gecko definitely has pseudo-elements with style attributes, like + // ::-moz-color-swatch. + debug_assert!( + cfg!(feature = "gecko") || style_attribute.is_none() || pseudo_element.is_none(), + "Style attributes do not apply to pseudo-elements" + ); + debug_assert!(pseudo_element.map_or(true, |p| !p.is_precomputed())); + + Self { + element, + rule_hash_target, + stylist, + pseudo_element, + style_attribute, + smil_override, + animation_rules, + rule_inclusion, + context, + flags_setter, + rules, + matches_user_and_author_rules, + shadow_cascade_order: 0, + matches_document_author_rules: matches_user_and_author_rules, + } + } + + fn collect_stylist_rules(&mut self, origin: Origin) { + let cascade_level = match origin { + Origin::UserAgent => CascadeLevel::UANormal, + Origin::User => CascadeLevel::UserNormal, + Origin::Author => CascadeLevel::SameTreeAuthorNormal, + }; + + let cascade_data = self.stylist.cascade_data().borrow_for_origin(origin); + let map = match cascade_data.normal_rules(self.pseudo_element) { + Some(m) => m, + None => return, + }; + + map.get_all_matching_rules( + self.element, + self.rule_hash_target, + self.rules, + self.context, + self.flags_setter, + cascade_level, + 0, + ); + } + + fn collect_user_agent_rules(&mut self) { + self.collect_stylist_rules(Origin::UserAgent); + } + + fn collect_user_rules(&mut self) { + if !self.matches_user_and_author_rules { + return; + } + + self.collect_stylist_rules(Origin::User); + } + + /// Presentational hints. + /// + /// These go before author rules, but after user rules, see: + /// https://drafts.csswg.org/css-cascade/#preshint + fn collect_presentational_hints(&mut self) { + if self.pseudo_element.is_some() { + return; + } + + let length_before_preshints = self.rules.len(); + self.element + .synthesize_presentational_hints_for_legacy_attributes( + self.context.visited_handling(), + self.rules, + ); + if cfg!(debug_assertions) { + if self.rules.len() != length_before_preshints { + for declaration in &self.rules[length_before_preshints..] { + assert_eq!(declaration.level(), CascadeLevel::PresHints); + } + } + } + } + + fn collect_rules_in_shadow_tree( + &mut self, + shadow_host: E, + map: &SelectorMap<Rule>, + cascade_level: CascadeLevel, + ) { + debug_assert!(shadow_host.shadow_root().is_some()); + let element = self.element; + let rule_hash_target = self.rule_hash_target; + let rules = &mut self.rules; + let flags_setter = &mut self.flags_setter; + let shadow_cascade_order = self.shadow_cascade_order; + self.context.with_shadow_host(Some(shadow_host), |context| { + map.get_all_matching_rules( + element, + rule_hash_target, + rules, + context, + flags_setter, + cascade_level, + shadow_cascade_order, + ); + }); + self.shadow_cascade_order += 1; + } + + /// Collects the rules for the ::slotted pseudo-element. + fn collect_slotted_rules(&mut self) { + let mut slots = SmallVec::<[_; 3]>::new(); + let mut current = self.rule_hash_target.assigned_slot(); + while let Some(slot) = current { + debug_assert!( + self.matches_user_and_author_rules, + "We should not slot NAC anywhere" + ); + slots.push(slot); + current = slot.assigned_slot(); + } + + // Match slotted rules in reverse order, so that the outer slotted rules + // come before the inner rules (and thus have less priority). + for slot in slots.iter().rev() { + let shadow = slot.containing_shadow().unwrap(); + let data = match shadow.style_data() { + Some(d) => d, + None => continue, + }; + let slotted_rules = match data.slotted_rules(self.pseudo_element) { + Some(r) => r, + None => continue, + }; + self.collect_rules_in_shadow_tree( + shadow.host(), + slotted_rules, + CascadeLevel::InnerShadowNormal, + ); + } + } + + fn collect_normal_rules_from_containing_shadow_tree(&mut self) { + if !self.matches_user_and_author_rules { + return; + } + + let mut current_containing_shadow = self.rule_hash_target.containing_shadow(); + while let Some(containing_shadow) = current_containing_shadow { + let cascade_data = containing_shadow.style_data(); + let host = containing_shadow.host(); + if let Some(map) = cascade_data.and_then(|data| data.normal_rules(self.pseudo_element)) + { + self.collect_rules_in_shadow_tree(host, map, CascadeLevel::SameTreeAuthorNormal); + } + let host_is_svg_use_element = + host.is_svg_element() && host.local_name() == &*local_name!("use"); + if !host_is_svg_use_element { + self.matches_document_author_rules = false; + break; + } + + debug_assert!( + cascade_data.is_none(), + "We allow no stylesheets in <svg:use> subtrees" + ); + + // NOTE(emilio): Hack so <svg:use> matches the rules of the + // enclosing tree. + // + // This is not a problem for invalidation and that kind of stuff + // because they still don't match rules based on elements + // outside of the shadow tree, and because the <svg:use> + // subtrees are immutable and recreated each time the source + // tree changes. + // + // We historically allow cross-document <svg:use> to have these + // rules applied, but I think that's not great. Gecko is the + // only engine supporting that. + // + // See https://github.com/w3c/svgwg/issues/504 for the relevant + // spec discussion. + current_containing_shadow = host.containing_shadow(); + self.matches_document_author_rules = current_containing_shadow.is_none(); + } + } + + /// Collects the rules for the :host pseudo-class. + fn collect_host_rules(&mut self) { + let shadow = match self.rule_hash_target.shadow_root() { + Some(s) => s, + None => return, + }; + + debug_assert!( + self.matches_user_and_author_rules, + "NAC should not be a shadow host" + ); + + let style_data = match shadow.style_data() { + Some(d) => d, + None => return, + }; + + let host_rules = match style_data.host_rules(self.pseudo_element) { + Some(rules) => rules, + None => return, + }; + + let rule_hash_target = self.rule_hash_target; + self.collect_rules_in_shadow_tree( + rule_hash_target, + host_rules, + CascadeLevel::InnerShadowNormal, + ); + } + + fn collect_document_author_rules(&mut self) { + if !self.matches_document_author_rules { + return; + } + + self.collect_stylist_rules(Origin::Author); + } + + fn collect_xbl_rules(&mut self) { + let element = self.element; + let cut_xbl_binding_inheritance = + element.each_xbl_cascade_data(|cascade_data, quirks_mode| { + let map = match cascade_data.normal_rules(self.pseudo_element) { + Some(m) => m, + None => return, + }; + + // NOTE(emilio): This is needed because the XBL stylist may + // think it has a different quirks mode than the document. + let mut matching_context = MatchingContext::new( + self.context.matching_mode(), + self.context.bloom_filter, + self.context.nth_index_cache.as_mut().map(|s| &mut **s), + quirks_mode, + ); + matching_context.pseudo_element_matching_fn = + self.context.pseudo_element_matching_fn; + + // SameTreeAuthorNormal instead of InnerShadowNormal to + // preserve behavior, though that's kinda fishy... + map.get_all_matching_rules( + self.element, + self.rule_hash_target, + self.rules, + &mut matching_context, + self.flags_setter, + CascadeLevel::SameTreeAuthorNormal, + self.shadow_cascade_order, + ); + }); + + self.matches_document_author_rules &= !cut_xbl_binding_inheritance; + } + + fn collect_style_attribute_and_animation_rules(&mut self) { + if let Some(sa) = self.style_attribute { + self.rules + .push(ApplicableDeclarationBlock::from_declarations( + sa.clone_arc(), + CascadeLevel::StyleAttributeNormal, + )); + } + + if let Some(so) = self.smil_override { + self.rules + .push(ApplicableDeclarationBlock::from_declarations( + so.clone_arc(), + CascadeLevel::SMILOverride, + )); + } + + // The animations sheet (CSS animations, script-generated + // animations, and CSS transitions that are no longer tied to CSS + // markup). + if let Some(anim) = self.animation_rules.0.take() { + self.rules + .push(ApplicableDeclarationBlock::from_declarations( + anim, + CascadeLevel::Animations, + )); + } + + // The transitions sheet (CSS transitions that are tied to CSS + // markup). + if let Some(anim) = self.animation_rules.1.take() { + self.rules + .push(ApplicableDeclarationBlock::from_declarations( + anim, + CascadeLevel::Transitions, + )); + } + } + + /// Collects all the rules, leaving the result in `self.rules`. + /// + /// Note that `!important` rules are handled during rule tree insertion. + pub fn collect_all(mut self) { + self.collect_user_agent_rules(); + self.collect_user_rules(); + if self.rule_inclusion == RuleInclusion::DefaultOnly { + return; + } + self.collect_presentational_hints(); + // FIXME(emilio): Should the author styles enabled stuff avoid the + // presentational hints from getting pushed? See bug 1505770. + if self.stylist.author_styles_enabled() == AuthorStylesEnabled::No { + return; + } + self.collect_host_rules(); + self.collect_slotted_rules(); + self.collect_normal_rules_from_containing_shadow_tree(); + self.collect_xbl_rules(); + self.collect_document_author_rules(); + self.collect_style_attribute_and_animation_rules(); + } +} diff --git a/components/style/servo/selector_parser.rs b/components/style/servo/selector_parser.rs index a959a820edc..b71d81c2978 100644 --- a/components/style/servo/selector_parser.rs +++ b/components/style/servo/selector_parser.rs @@ -13,9 +13,8 @@ use crate::invalidation::element::document_state::InvalidationMatchingData; use crate::invalidation::element::element_wrapper::ElementSnapshot; use crate::properties::longhands::display::computed_value::T as Display; use crate::properties::{ComputedValues, PropertyFlags}; -use crate::selector_parser::{ - AttrValue as SelectorAttrValue, PseudoElementCascadeType, SelectorParser, -}; +use crate::selector_parser::AttrValue as SelectorAttrValue; +use crate::selector_parser::{PseudoElementCascadeType, SelectorParser}; use crate::{Atom, CaseSensitivityExt, LocalName, Namespace, Prefix}; use cssparser::{serialize_identifier, CowRcStr, Parser as CssParser, SourceLocation, ToCss}; use fxhash::FxHashMap; diff --git a/components/style/style_resolver.rs b/components/style/style_resolver.rs index 515f9ad39a9..b96d6d871f4 100644 --- a/components/style/style_resolver.rs +++ b/components/style/style_resolver.rs @@ -15,9 +15,8 @@ use crate::rule_tree::StrongRuleNode; use crate::selector_parser::{PseudoElement, SelectorImpl}; use crate::stylist::RuleInclusion; use log::Level::Trace; -use selectors::matching::{ - ElementSelectorFlags, MatchingContext, MatchingMode, VisitedHandlingMode, -}; +use selectors::matching::{ElementSelectorFlags, MatchingContext}; +use selectors::matching::{MatchingMode, VisitedHandlingMode}; use servo_arc::Arc; /// Whether pseudo-elements should be resolved or not. diff --git a/components/style/stylesheets/document_rule.rs b/components/style/stylesheets/document_rule.rs index f0389b8fec9..6a3571910be 100644 --- a/components/style/stylesheets/document_rule.rs +++ b/components/style/stylesheets/document_rule.rs @@ -135,7 +135,7 @@ impl DocumentMatchingFunction { context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { - if let Ok(url) = input.r#try(|input| CssUrl::parse(context, input)) { + if let Ok(url) = input.try(|input| CssUrl::parse(context, input)) { return Ok(DocumentMatchingFunction::Url(url)); } diff --git a/components/style/stylesheets/rule_parser.rs b/components/style/stylesheets/rule_parser.rs index afb6debc1e1..bb51536d3f1 100644 --- a/components/style/stylesheets/rule_parser.rs +++ b/components/style/stylesheets/rule_parser.rs @@ -202,7 +202,7 @@ impl<'a, 'i> AtRuleParser<'i> for TopLevelRuleParser<'a> { return Err(input.new_custom_error(StyleParseErrorKind::UnexpectedNamespaceRule)) } - let prefix = input.r#try(|i| i.expect_ident_cloned()) + let prefix = input.try(|i| i.expect_ident_cloned()) .map(|s| Prefix::from(s.as_ref())).ok(); let maybe_namespace = match input.expect_url_or_string() { Ok(url_or_string) => url_or_string, diff --git a/components/style/stylesheets/stylesheet.rs b/components/style/stylesheets/stylesheet.rs index 2749225f2aa..81e42f3da7e 100644 --- a/components/style/stylesheets/stylesheet.rs +++ b/components/style/stylesheets/stylesheet.rs @@ -7,9 +7,8 @@ use crate::error_reporting::{ContextualParseError, ParseErrorReporter}; use crate::invalidation::media_queries::{MediaListKey, ToMediaListKey}; use crate::media_queries::{Device, MediaList}; use crate::parser::ParserContext; -use crate::shared_lock::{ - DeepCloneParams, DeepCloneWithLock, Locked, SharedRwLock, SharedRwLockReadGuard, -}; +use crate::shared_lock::{DeepCloneParams, DeepCloneWithLock, Locked}; +use crate::shared_lock::{SharedRwLock, SharedRwLockReadGuard}; use crate::stylesheets::loader::StylesheetLoader; use crate::stylesheets::rule_parser::{State, TopLevelRuleParser}; use crate::stylesheets::rules_iterator::{EffectiveRules, EffectiveRulesIterator}; diff --git a/components/style/stylesheets/supports_rule.rs b/components/style/stylesheets/supports_rule.rs index 10033d324a4..bc49b95238b 100644 --- a/components/style/stylesheets/supports_rule.rs +++ b/components/style/stylesheets/supports_rule.rs @@ -103,7 +103,7 @@ impl SupportsCondition { /// /// <https://drafts.csswg.org/css-conditional/#supports_condition> pub fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> { - if input.r#try(|i| i.expect_ident_matching("not")).is_ok() { + if input.try(|i| i.expect_ident_matching("not")).is_ok() { let inner = SupportsCondition::parse_in_parens(input)?; return Ok(SupportsCondition::Not(Box::new(inner))); } @@ -129,7 +129,7 @@ impl SupportsCondition { loop { conditions.push(SupportsCondition::parse_in_parens(input)?); if input - .r#try(|input| input.expect_ident_matching(keyword)) + .try(|input| input.expect_ident_matching(keyword)) .is_err() { // Did not find the expected keyword. @@ -175,20 +175,20 @@ impl SupportsCondition { fn parse_in_parens<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> { // Whitespace is normally taken care of in `Parser::next`, // but we want to not include it in `pos` for the SupportsCondition::FutureSyntax cases. - while input.r#try(Parser::expect_whitespace).is_ok() {} + while input.try(Parser::expect_whitespace).is_ok() {} let pos = input.position(); let location = input.current_source_location(); // FIXME: remove clone() when lifetimes are non-lexical match input.next()?.clone() { Token::ParenthesisBlock => { let nested = - input.r#try(|input| input.parse_nested_block(parse_condition_or_declaration)); + input.try(|input| input.parse_nested_block(parse_condition_or_declaration)); if nested.is_ok() { return nested; } }, Token::Function(ident) => { - let nested = input.r#try(|input| { + let nested = input.try(|input| { input.parse_nested_block(|input| { SupportsCondition::parse_functional(&ident, input) }) @@ -240,7 +240,7 @@ fn eval_moz_bool_pref(_: &CStr, _: &ParserContext) -> bool { pub fn parse_condition_or_declaration<'i, 't>( input: &mut Parser<'i, 't>, ) -> Result<SupportsCondition, ParseError<'i>> { - if let Ok(condition) = input.r#try(SupportsCondition::parse) { + if let Ok(condition) = input.try(SupportsCondition::parse) { Ok(SupportsCondition::Parenthesized(Box::new(condition))) } else { Declaration::parse(input).map(SupportsCondition::Declaration) @@ -418,7 +418,7 @@ impl Declaration { PropertyDeclaration::parse_into(&mut declarations, id, &context, input) .map_err(|_| input.new_custom_error(())) })?; - let _ = input.r#try(parse_important); + let _ = input.try(parse_important); Ok(()) }) .is_ok() diff --git a/components/style/stylesheets/viewport_rule.rs b/components/style/stylesheets/viewport_rule.rs index de2fd55fb7b..ef2d58ecf0d 100644 --- a/components/style/stylesheets/viewport_rule.rs +++ b/components/style/stylesheets/viewport_rule.rs @@ -265,7 +265,7 @@ fn parse_shorthand<'i, 't>( input: &mut Parser<'i, 't>, ) -> Result<(ViewportLength, ViewportLength), ParseError<'i>> { let min = ViewportLength::parse(context, input)?; - match input.r#try(|i| ViewportLength::parse(context, i)) { + match input.try(|i| ViewportLength::parse(context, i)) { Err(_) => Ok((min.clone(), min)), Ok(max) => Ok((min, max)), } @@ -289,8 +289,8 @@ impl<'a, 'b, 'i> DeclarationParser<'i> for ViewportRuleParser<'a, 'b> { ) -> Result<Vec<ViewportDescriptorDeclaration>, ParseError<'i>> { macro_rules! declaration { ($declaration:ident($parse:expr)) => { - declaration!($declaration(value: r#try!($parse(input)), - important: input.r#try(parse_important).is_ok())) + declaration!($declaration(value: try!($parse(input)), + important: input.try(parse_important).is_ok())) }; ($declaration:ident(value: $value:expr, important: $important:expr)) => { ViewportDescriptorDeclaration::new( @@ -306,7 +306,7 @@ impl<'a, 'b, 'i> DeclarationParser<'i> for ViewportRuleParser<'a, 'b> { }; (shorthand -> [$min:ident, $max:ident]) => {{ let shorthand = parse_shorthand(self.context, input)?; - let important = input.r#try(parse_important).is_ok(); + let important = input.try(parse_important).is_ok(); Ok(vec![ declaration!($min(value: shorthand.0, important: important)), diff --git a/components/style/stylist.rs b/components/style/stylist.rs index 749ba82ccb2..7a4bbedab52 100644 --- a/components/style/stylist.rs +++ b/components/style/stylist.rs @@ -17,6 +17,7 @@ use crate::media_queries::Device; use crate::properties::{self, CascadeMode, ComputedValues}; use crate::properties::{AnimationRules, PropertyDeclarationBlock}; use crate::rule_cache::{RuleCache, RuleCacheConditions}; +use crate::rule_collector::RuleCollector; use crate::rule_tree::{CascadeLevel, RuleTree, ShadowCascadeOrder, StrongRuleNode, StyleSource}; use crate::selector_map::{PrecomputedHashMap, PrecomputedHashSet, SelectorMap, SelectorMapEntry}; use crate::selector_parser::{PerPseudoElementMap, PseudoElement, SelectorImpl, SnapshotMap}; @@ -47,7 +48,6 @@ use selectors::visitor::SelectorVisitor; use selectors::NthIndexCache; use servo_arc::{Arc, ArcBorrow}; use smallbitvec::SmallBitVec; -use smallvec::SmallVec; use std::ops; use std::sync::Mutex; use style_traits::viewport::ViewportConstraints; @@ -180,10 +180,11 @@ impl UserAgentCascadeData { } } -/// All the computed information for a stylesheet. +/// All the computed information for all the stylesheets that apply to the +/// document. #[derive(Default)] #[cfg_attr(feature = "servo", derive(MallocSizeOf))] -struct DocumentCascadeData { +pub struct DocumentCascadeData { #[cfg_attr( feature = "servo", ignore_malloc_size_of = "Arc, owned by UserAgentCascadeDataCache" @@ -210,7 +211,9 @@ impl<'a> Iterator for DocumentCascadeDataIter<'a> { } impl DocumentCascadeData { - fn borrow_for_origin(&self, origin: Origin) -> &CascadeData { + /// Borrows the cascade data for a given origin. + #[inline] + pub fn borrow_for_origin(&self, origin: Origin) -> &CascadeData { match origin { Origin::UserAgent => &self.user_agent.cascade_data, Origin::Author => &self.author, @@ -412,10 +415,16 @@ impl Stylist { } } - /// Returns the cascade data for the author level. + /// Returns the document cascade data. + #[inline] + pub fn cascade_data(&self) -> &DocumentCascadeData { + &self.cascade_data + } + + /// Returns whether author styles are enabled or not. #[inline] - pub fn author_cascade_data(&self) -> &CascadeData { - &self.cascade_data.author + pub fn author_styles_enabled(&self) -> AuthorStylesEnabled { + self.author_styles_enabled } /// Iterate through all the cascade datas from the document. @@ -1098,11 +1107,6 @@ impl Stylist { } /// Returns the applicable CSS declarations for the given element. - /// - /// This corresponds to `ElementRuleCollector` in WebKit, and should push to - /// elements in the list in the order defined by: - /// - /// https://drafts.csswg.org/css-cascade/#cascade-origin pub fn push_applicable_declarations<E, F>( &self, element: E, @@ -1118,284 +1122,19 @@ impl Stylist { E: TElement, F: FnMut(&E, ElementSelectorFlags), { - // Gecko definitely has pseudo-elements with style attributes, like - // ::-moz-color-swatch. - debug_assert!( - cfg!(feature = "gecko") || style_attribute.is_none() || pseudo_element.is_none(), - "Style attributes do not apply to pseudo-elements" - ); - debug_assert!(pseudo_element.map_or(true, |p| !p.is_precomputed())); - - let rule_hash_target = element.rule_hash_target(); - - let matches_user_and_author_rules = rule_hash_target.matches_user_and_author_rules(); - - // Normal user-agent rules. - if let Some(map) = self - .cascade_data - .user_agent - .cascade_data - .normal_rules(pseudo_element) - { - map.get_all_matching_rules( - element, - rule_hash_target, - applicable_declarations, - context, - flags_setter, - CascadeLevel::UANormal, - 0, - ); - } - - // NB: the following condition, although it may look somewhat - // inaccurate, would be equivalent to something like: - // - // element.matches_user_and_author_rules() || - // (is_implemented_pseudo && - // rule_hash_target.matches_user_and_author_rules()) - // - // Which may be more what you would probably expect. - if matches_user_and_author_rules { - // User normal rules. - if let Some(map) = self.cascade_data.user.normal_rules(pseudo_element) { - map.get_all_matching_rules( - element, - rule_hash_target, - applicable_declarations, - context, - flags_setter, - CascadeLevel::UserNormal, - 0, - ); - } - } - - if rule_inclusion == RuleInclusion::DefaultOnly { - return; - } - - if pseudo_element.is_none() { - // Presentational hints. - // - // These go before author rules, but after user rules, see: - // https://drafts.csswg.org/css-cascade/#preshint - let length_before_preshints = applicable_declarations.len(); - element.synthesize_presentational_hints_for_legacy_attributes( - context.visited_handling(), - applicable_declarations, - ); - if cfg!(debug_assertions) { - if applicable_declarations.len() != length_before_preshints { - for declaration in &applicable_declarations[length_before_preshints..] { - assert_eq!(declaration.level(), CascadeLevel::PresHints); - } - } - } - } - - if self.author_styles_enabled == AuthorStylesEnabled::No { - return; - } - - let mut match_document_author_rules = matches_user_and_author_rules; - let mut shadow_cascade_order = 0; - - // XBL / Shadow DOM rules, which are author rules too. - if let Some(shadow) = rule_hash_target.shadow_root() { - debug_assert!( - matches_user_and_author_rules, - "NAC should not be a shadow host" - ); - if let Some(map) = shadow - .style_data() - .and_then(|data| data.host_rules(pseudo_element)) - { - context.with_shadow_host(Some(rule_hash_target), |context| { - map.get_all_matching_rules( - element, - rule_hash_target, - applicable_declarations, - context, - flags_setter, - CascadeLevel::InnerShadowNormal, - shadow_cascade_order, - ); - }); - shadow_cascade_order += 1; - } - } - - // Match slotted rules in reverse order, so that the outer slotted - // rules come before the inner rules (and thus have less priority). - let mut slots = SmallVec::<[_; 3]>::new(); - let mut current = rule_hash_target.assigned_slot(); - while let Some(slot) = current { - debug_assert!( - matches_user_and_author_rules, - "We should not slot NAC anywhere" - ); - slots.push(slot); - current = slot.assigned_slot(); - } - - for slot in slots.iter().rev() { - let shadow = slot.containing_shadow().unwrap(); - if let Some(map) = shadow - .style_data() - .and_then(|data| data.slotted_rules(pseudo_element)) - { - context.with_shadow_host(Some(shadow.host()), |context| { - map.get_all_matching_rules( - element, - rule_hash_target, - applicable_declarations, - context, - flags_setter, - CascadeLevel::InnerShadowNormal, - shadow_cascade_order, - ); - }); - shadow_cascade_order += 1; - } - } - - if matches_user_and_author_rules { - let mut current_containing_shadow = rule_hash_target.containing_shadow(); - while let Some(containing_shadow) = current_containing_shadow { - let cascade_data = containing_shadow.style_data(); - let host = containing_shadow.host(); - if let Some(map) = cascade_data.and_then(|data| data.normal_rules(pseudo_element)) { - context.with_shadow_host(Some(host), |context| { - map.get_all_matching_rules( - element, - rule_hash_target, - applicable_declarations, - context, - flags_setter, - CascadeLevel::SameTreeAuthorNormal, - shadow_cascade_order, - ); - }); - shadow_cascade_order += 1; - } - - let host_is_svg_use_element = - host.is_svg_element() && host.local_name() == &*local_name!("use"); - - if !host_is_svg_use_element { - match_document_author_rules = false; - break; - } - - debug_assert!( - cascade_data.is_none(), - "We allow no stylesheets in <svg:use> subtrees" - ); - - // NOTE(emilio): Hack so <svg:use> matches the rules of the - // enclosing tree. - // - // This is not a problem for invalidation and that kind of stuff - // because they still don't match rules based on elements - // outside of the shadow tree, and because the <svg:use> - // subtrees are immutable and recreated each time the source - // tree changes. - // - // We historically allow cross-document <svg:use> to have these - // rules applied, but I think that's not great. Gecko is the - // only engine supporting that. - // - // See https://github.com/w3c/svgwg/issues/504 for the relevant - // spec discussion. - current_containing_shadow = host.containing_shadow(); - match_document_author_rules = current_containing_shadow.is_none(); - } - } - - let cut_xbl_binding_inheritance = - element.each_xbl_cascade_data(|cascade_data, quirks_mode| { - if let Some(map) = cascade_data.normal_rules(pseudo_element) { - // NOTE(emilio): This is needed because the XBL stylist may - // think it has a different quirks mode than the document. - let mut matching_context = MatchingContext::new( - context.matching_mode(), - context.bloom_filter, - context.nth_index_cache.as_mut().map(|s| &mut **s), - quirks_mode, - ); - matching_context.pseudo_element_matching_fn = - context.pseudo_element_matching_fn; - - // SameTreeAuthorNormal instead of InnerShadowNormal to - // preserve behavior, though that's kinda fishy... - map.get_all_matching_rules( - element, - rule_hash_target, - applicable_declarations, - &mut matching_context, - flags_setter, - CascadeLevel::SameTreeAuthorNormal, - shadow_cascade_order, - ); - } - }); - - match_document_author_rules &= !cut_xbl_binding_inheritance; - - if match_document_author_rules { - // Author normal rules. - if let Some(map) = self.cascade_data.author.normal_rules(pseudo_element) { - map.get_all_matching_rules( - element, - rule_hash_target, - applicable_declarations, - context, - flags_setter, - CascadeLevel::SameTreeAuthorNormal, - shadow_cascade_order, - ); - } - } - - // Style attribute ("Normal override declarations"). - if let Some(sa) = style_attribute { - applicable_declarations.push(ApplicableDeclarationBlock::from_declarations( - sa.clone_arc(), - CascadeLevel::StyleAttributeNormal, - )); - } - - // Declarations from SVG SMIL animation elements. - if let Some(so) = smil_override { - applicable_declarations.push(ApplicableDeclarationBlock::from_declarations( - so.clone_arc(), - CascadeLevel::SMILOverride, - )); - } - - // The animations sheet (CSS animations, script-generated - // animations, and CSS transitions that are no longer tied to CSS - // markup). - if let Some(anim) = animation_rules.0 { - applicable_declarations.push(ApplicableDeclarationBlock::from_declarations( - anim.clone(), - CascadeLevel::Animations, - )); - } - - // - // !important rules are handled during rule tree insertion. - // - - // The transitions sheet (CSS transitions that are tied to CSS - // markup). - if let Some(anim) = animation_rules.1 { - applicable_declarations.push(ApplicableDeclarationBlock::from_declarations( - anim.clone(), - CascadeLevel::Transitions, - )); - } + RuleCollector::new( + self, + element, + pseudo_element, + style_attribute, + smil_override, + animation_rules, + rule_inclusion, + applicable_declarations, + context, + flags_setter, + ) + .collect_all(); } /// Given an id, returns whether there might be any rules for that id in any @@ -2100,18 +1839,21 @@ impl CascadeData { self.attribute_dependencies.contains(local_name) } + /// Returns the normal rule map for a given pseudo-element. #[inline] - fn normal_rules(&self, pseudo: Option<&PseudoElement>) -> Option<&SelectorMap<Rule>> { + pub fn normal_rules(&self, pseudo: Option<&PseudoElement>) -> Option<&SelectorMap<Rule>> { self.normal_rules.rules(pseudo) } + /// Returns the host pseudo rule map for a given pseudo-element. #[inline] - fn host_rules(&self, pseudo: Option<&PseudoElement>) -> Option<&SelectorMap<Rule>> { + pub fn host_rules(&self, pseudo: Option<&PseudoElement>) -> Option<&SelectorMap<Rule>> { self.host_rules.as_ref().and_then(|d| d.rules(pseudo)) } + /// Returns the slotted rule map for a given pseudo-element. #[inline] - fn slotted_rules(&self, pseudo: Option<&PseudoElement>) -> Option<&SelectorMap<Rule>> { + pub fn slotted_rules(&self, pseudo: Option<&PseudoElement>) -> Option<&SelectorMap<Rule>> { self.slotted_rules.as_ref().and_then(|d| d.rules(pseudo)) } diff --git a/components/style/values/computed/font.rs b/components/style/values/computed/font.rs index a60eb82f0d2..058c211a802 100644 --- a/components/style/values/computed/font.rs +++ b/components/style/values/computed/font.rs @@ -13,9 +13,8 @@ use crate::gecko_bindings::{bindings, structs}; use crate::values::animated::{ToAnimatedValue, ToAnimatedZero}; use crate::values::computed::{Angle, Context, Integer, NonNegativeLength, NonNegativePercentage}; use crate::values::computed::{Number, Percentage, ToComputedValue}; -use crate::values::generics::font::{ - self as generics, FeatureTagValue, FontSettings, VariationValue, -}; +use crate::values::generics::font as generics; +use crate::values::generics::font::{FeatureTagValue, FontSettings, VariationValue}; use crate::values::specified::font::{self as specified, MAX_FONT_WEIGHT, MIN_FONT_WEIGHT}; use crate::values::specified::length::{FontBaseSize, NoCalcLength}; use crate::values::CSSFloat; @@ -30,9 +29,8 @@ use std::slice; use style_traits::{CssWriter, ParseError, ToCss}; pub use crate::values::computed::Length as MozScriptMinSize; -pub use crate::values::specified::font::{ - FontSynthesis, MozScriptSizeMultiplier, XLang, XTextZoom, -}; +pub use crate::values::specified::font::{FontSynthesis, MozScriptSizeMultiplier}; +pub use crate::values::specified::font::{XLang, XTextZoom}; /// A value for the font-weight property per: /// @@ -374,7 +372,7 @@ impl SingleFontFamily { /// Parse a font-family value pub fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> { - if let Ok(value) = input.r#try(|i| i.expect_string_cloned()) { + if let Ok(value) = input.try(|i| i.expect_string_cloned()) { return Ok(SingleFontFamily::FamilyName(FamilyName { name: Atom::from(&*value), syntax: FamilyNameSyntax::Quoted, @@ -419,7 +417,7 @@ impl SingleFontFamily { value.push(' '); value.push_str(&ident); } - while let Ok(ident) = input.r#try(|i| i.expect_ident_cloned()) { + while let Ok(ident) = input.try(|i| i.expect_ident_cloned()) { value.push(' '); value.push_str(&ident); } diff --git a/components/style/values/computed/length.rs b/components/style/values/computed/length.rs index 4c7fe16dcfc..8060227d10e 100644 --- a/components/style/values/computed/length.rs +++ b/components/style/values/computed/length.rs @@ -8,9 +8,9 @@ use super::{Context, Number, Percentage, ToComputedValue}; use app_units::Au; use crate::values::animated::{Animate, Procedure, ToAnimatedValue, ToAnimatedZero}; use crate::values::distance::{ComputeSquaredDistance, SquaredDistance}; -use crate::values::generics::length::{ - MaxLength as GenericMaxLength, MozLength as GenericMozLength, -}; +use crate::values::generics::length::MaxLength as GenericMaxLength; +use crate::values::generics::length::MozLength as GenericMozLength; +use crate::values::generics::transform::IsZeroLength; use crate::values::generics::NonNegative; use crate::values::specified::length::ViewportPercentageLength; use crate::values::specified::length::{AbsoluteLength, FontBaseSize, FontRelativeLength}; @@ -496,6 +496,17 @@ impl ToComputedValue for specified::LengthOrPercentage { } } +impl IsZeroLength for LengthOrPercentage { + #[inline] + fn is_zero_length(&self) -> bool { + match *self { + LengthOrPercentage::Length(l) => l.0 == 0.0, + LengthOrPercentage::Percentage(p) => p.0 == 0.0, + LengthOrPercentage::Calc(c) => c.unclamped_length().0 == 0.0 && c.percentage() == 0.0, + } + } +} + #[allow(missing_docs)] #[animate(fallback = "Self::animate_fallback")] #[css(derive_debug)] diff --git a/components/style/values/computed/mod.rs b/components/style/values/computed/mod.rs index 5b43b964c6f..e24472a8068 100644 --- a/components/style/values/computed/mod.rs +++ b/components/style/values/computed/mod.rs @@ -77,8 +77,8 @@ pub use self::svg::{SVGLength, SVGOpacity, SVGPaint, SVGPaintKind}; pub use self::svg::{SVGPaintOrder, SVGStrokeDashArray, SVGWidth}; pub use self::table::XSpan; pub use self::text::{InitialLetter, LetterSpacing, LineHeight, MozTabSize}; +pub use self::text::{OverflowWrap, TextOverflow, WordSpacing}; pub use self::text::{TextAlign, TextEmphasisPosition, TextEmphasisStyle}; -pub use self::text::{TextOverflow, WordSpacing}; pub use self::time::Time; pub use self::transform::{Rotate, Scale, Transform, TransformOperation}; pub use self::transform::{TransformOrigin, TransformStyle, Translate}; diff --git a/components/style/values/computed/text.rs b/components/style/values/computed/text.rs index 0f16f2d26fd..40ac77b6135 100644 --- a/components/style/values/computed/text.rs +++ b/components/style/values/computed/text.rs @@ -12,13 +12,13 @@ use crate::values::generics::text::InitialLetter as GenericInitialLetter; use crate::values::generics::text::LineHeight as GenericLineHeight; use crate::values::generics::text::MozTabSize as GenericMozTabSize; use crate::values::generics::text::Spacing; -use crate::values::specified::text::{ - TextEmphasisFillMode, TextEmphasisShapeKeyword, TextOverflowSide, -}; +use crate::values::specified::text::TextOverflowSide; +use crate::values::specified::text::{TextEmphasisFillMode, TextEmphasisShapeKeyword}; use crate::values::{CSSFloat, CSSInteger}; use std::fmt::{self, Write}; use style_traits::{CssWriter, ToCss}; +pub use crate::values::specified::OverflowWrap; pub use crate::values::specified::TextAlignKeyword as TextAlign; pub use crate::values::specified::TextEmphasisPosition; diff --git a/components/style/values/computed/transform.rs b/components/style/values/computed/transform.rs index 079c1e2535b..b4493265aef 100644 --- a/components/style/values/computed/transform.rs +++ b/components/style/values/computed/transform.rs @@ -334,7 +334,6 @@ impl Translate { pub fn to_transform_operation(&self) -> Option<TransformOperation> { match *self { generic::Translate::None => None, - generic::Translate::TranslateX(tx) => Some(generic::TransformOperation::TranslateX(tx)), generic::Translate::Translate(tx, ty) => { Some(generic::TransformOperation::Translate(tx, Some(ty))) }, @@ -347,7 +346,6 @@ impl Translate { /// Convert Translate to TransformOperation. pub fn from_transform_operation(operation: &TransformOperation) -> Translate { match *operation { - generic::TransformOperation::TranslateX(tx) => generic::Translate::TranslateX(tx), generic::TransformOperation::Translate(tx, Some(ty)) => { generic::Translate::Translate(tx, ty) }, diff --git a/components/style/values/generics/background.rs b/components/style/values/generics/background.rs index e1514959837..35130836991 100644 --- a/components/style/values/generics/background.rs +++ b/components/style/values/generics/background.rs @@ -4,9 +4,9 @@ //! Generic types for CSS values related to backgrounds. +use crate::values::IsAuto; use std::fmt::{self, Write}; use style_traits::{CssWriter, ToCss}; -use values::IsAuto; /// A generic value for the `background-size` property. #[derive( diff --git a/components/style/values/generics/font.rs b/components/style/values/generics/font.rs index 204de699db3..7f62b15dd3c 100644 --- a/components/style/values/generics/font.rs +++ b/components/style/values/generics/font.rs @@ -85,7 +85,7 @@ impl<T: Parse> Parse for FontSettings<T> { context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { - if input.r#try(|i| i.expect_ident_matching("normal")).is_ok() { + if input.try(|i| i.expect_ident_matching("normal")).is_ok() { return Ok(Self::normal()); } diff --git a/components/style/values/generics/grid.rs b/components/style/values/generics/grid.rs index c565ca6c320..8a26cbd2b16 100644 --- a/components/style/values/generics/grid.rs +++ b/components/style/values/generics/grid.rs @@ -86,7 +86,7 @@ impl Parse for GridLine<specified::Integer> { input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { let mut grid_line = Self::auto(); - if input.r#try(|i| i.expect_ident_matching("auto")).is_ok() { + if input.try(|i| i.expect_ident_matching("auto")).is_ok() { return Ok(grid_line); } @@ -99,7 +99,7 @@ impl Parse for GridLine<specified::Integer> { for _ in 0..3 { // Maximum possible entities for <grid-line> let location = input.current_source_location(); - if input.r#try(|i| i.expect_ident_matching("span")).is_ok() { + if input.try(|i| i.expect_ident_matching("span")).is_ok() { if grid_line.is_span { return Err(location.new_custom_error(StyleParseErrorKind::UnspecifiedError)); } @@ -109,14 +109,14 @@ impl Parse for GridLine<specified::Integer> { } grid_line.is_span = true; - } else if let Ok(i) = input.r#try(|i| specified::Integer::parse(context, i)) { + } else if let Ok(i) = input.try(|i| specified::Integer::parse(context, i)) { // FIXME(emilio): Probably shouldn't reject if it's calc()... if i.value() == 0 || val_before_span || grid_line.line_num.is_some() { return Err(location.new_custom_error(StyleParseErrorKind::UnspecifiedError)); } grid_line.line_num = Some(i); - } else if let Ok(name) = input.r#try(|i| i.expect_ident_cloned()) { + } else if let Ok(name) = input.try(|i| i.expect_ident_cloned()) { if val_before_span || grid_line.ident.is_some() { return Err(location.new_custom_error(StyleParseErrorKind::UnspecifiedError)); } @@ -375,7 +375,7 @@ impl Parse for RepeatCount<specified::Integer> { ) -> Result<Self, ParseError<'i>> { // Maximum number of repeat is 10000. The greater numbers should be clamped. const MAX_LINE: i32 = 10000; - if let Ok(mut i) = input.r#try(|i| specified::Integer::parse_positive(context, i)) { + if let Ok(mut i) = input.try(|i| specified::Integer::parse_positive(context, i)) { if i.value() > MAX_LINE { i = specified::Integer::new(MAX_LINE); } @@ -605,14 +605,14 @@ impl Parse for LineNameList { let mut fill_idx = None; loop { - let repeat_parse_result = input.r#try(|input| { + let repeat_parse_result = input.try(|input| { input.expect_function_matching("repeat")?; input.parse_nested_block(|input| { let count = RepeatCount::parse(context, input)?; input.expect_comma()?; let mut names_list = vec![]; names_list.push(parse_line_names(input)?); // there should be at least one - while let Ok(names) = input.r#try(parse_line_names) { + while let Ok(names) = input.try(parse_line_names) { names_list.push(names); } @@ -643,7 +643,7 @@ impl Parse for LineNameList { }, _ => return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)), } - } else if let Ok(names) = input.r#try(parse_line_names) { + } else if let Ok(names) = input.try(parse_line_names) { line_names.push(names); } else { break; diff --git a/components/style/values/generics/mod.rs b/components/style/values/generics/mod.rs index f1c5acd602e..862ebef459f 100644 --- a/components/style/values/generics/mod.rs +++ b/components/style/values/generics/mod.rs @@ -111,19 +111,16 @@ impl Parse for CounterStyleOrNone { context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { - if let Ok(name) = input.r#try(|i| parse_counter_style_name(i)) { + if let Ok(name) = input.try(|i| parse_counter_style_name(i)) { return Ok(CounterStyleOrNone::Name(name)); } - if input.r#try(|i| i.expect_ident_matching("none")).is_ok() { + if input.try(|i| i.expect_ident_matching("none")).is_ok() { return Ok(CounterStyleOrNone::None); } - if input - .r#try(|i| i.expect_function_matching("symbols")) - .is_ok() - { + if input.try(|i| i.expect_function_matching("symbols")).is_ok() { return input.parse_nested_block(|input| { let symbols_type = input - .r#try(|i| SymbolsType::parse(i)) + .try(|i| SymbolsType::parse(i)) .unwrap_or(SymbolsType::Symbolic); let symbols = Symbols::parse(context, input)?; // There must be at least two symbols for alphabetic or diff --git a/components/style/values/generics/rect.rs b/components/style/values/generics/rect.rs index 6ba11570dfe..fa5caab3e4b 100644 --- a/components/style/values/generics/rect.rs +++ b/components/style/values/generics/rect.rs @@ -50,7 +50,7 @@ where Parse: Fn(&ParserContext, &mut Parser<'i, 't>) -> Result<T, ParseError<'i>>, { let first = parse(context, input)?; - let second = if let Ok(second) = input.r#try(|i| parse(context, i)) { + let second = if let Ok(second) = input.try(|i| parse(context, i)) { second } else { // <first> @@ -61,13 +61,13 @@ where first, )); }; - let third = if let Ok(third) = input.r#try(|i| parse(context, i)) { + let third = if let Ok(third) = input.try(|i| parse(context, i)) { third } else { // <first> <second> return Ok(Self::new(first.clone(), second.clone(), first, second)); }; - let fourth = if let Ok(fourth) = input.r#try(|i| parse(context, i)) { + let fourth = if let Ok(fourth) = input.try(|i| parse(context, i)) { fourth } else { // <first> <second> <third> diff --git a/components/style/values/generics/size.rs b/components/style/values/generics/size.rs index 24fba15d59c..7271aaa3922 100644 --- a/components/style/values/generics/size.rs +++ b/components/style/values/generics/size.rs @@ -55,7 +55,7 @@ impl<L> Size<L> { { let first = parse_one(context, input)?; let second = input - .r#try(|i| parse_one(context, i)) + .try(|i| parse_one(context, i)) .unwrap_or_else(|_| first.clone()); Ok(Self::new(first, second)) } diff --git a/components/style/values/generics/svg.rs b/components/style/values/generics/svg.rs index cdbca333441..1b439657def 100644 --- a/components/style/values/generics/svg.rs +++ b/components/style/values/generics/svg.rs @@ -84,10 +84,10 @@ fn parse_fallback<'i, 't, ColorType: Parse>( context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Option<Either<ColorType, None_>> { - if input.r#try(|i| i.expect_ident_matching("none")).is_ok() { + if input.try(|i| i.expect_ident_matching("none")).is_ok() { Some(Either::Second(None_)) } else { - if let Ok(color) = input.r#try(|i| ColorType::parse(context, i)) { + if let Ok(color) = input.try(|i| ColorType::parse(context, i)) { Some(Either::First(color)) } else { None @@ -100,12 +100,12 @@ impl<ColorType: Parse, UrlPaintServer: Parse> Parse for SVGPaint<ColorType, UrlP context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { - if let Ok(url) = input.r#try(|i| UrlPaintServer::parse(context, i)) { + if let Ok(url) = input.try(|i| UrlPaintServer::parse(context, i)) { Ok(SVGPaint { kind: SVGPaintKind::PaintServer(url), fallback: parse_fallback(context, input), }) - } else if let Ok(kind) = input.r#try(SVGPaintKind::parse_ident) { + } else if let Ok(kind) = input.try(SVGPaintKind::parse_ident) { if let SVGPaintKind::None = kind { Ok(SVGPaint { kind: kind, @@ -117,7 +117,7 @@ impl<ColorType: Parse, UrlPaintServer: Parse> Parse for SVGPaint<ColorType, UrlP fallback: parse_fallback(context, input), }) } - } else if let Ok(color) = input.r#try(|i| ColorType::parse(context, i)) { + } else if let Ok(color) = input.try(|i| ColorType::parse(context, i)) { Ok(SVGPaint { kind: SVGPaintKind::Color(color), fallback: None, @@ -158,7 +158,7 @@ impl<LengthOrPercentageType: Parse, NumberType: Parse> Parse context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { - if let Ok(num) = input.r#try(|i| NumberType::parse(context, i)) { + if let Ok(num) = input.try(|i| NumberType::parse(context, i)) { return Ok(SvgLengthOrPercentageOrNumber::Number(num)); } diff --git a/components/style/values/generics/text.rs b/components/style/values/generics/text.rs index 0be499c6933..ccd5c192270 100644 --- a/components/style/values/generics/text.rs +++ b/components/style/values/generics/text.rs @@ -58,7 +58,7 @@ impl<Value> Spacing<Value> { where F: FnOnce(&ParserContext, &mut Parser<'i, 't>) -> Result<Value, ParseError<'i>>, { - if input.r#try(|i| i.expect_ident_matching("normal")).is_ok() { + if input.try(|i| i.expect_ident_matching("normal")).is_ok() { return Ok(Spacing::Normal); } parse(context, input).map(Spacing::Value) diff --git a/components/style/values/generics/transform.rs b/components/style/values/generics/transform.rs index c48c37e552a..12cc97fb10f 100644 --- a/components/style/values/generics/transform.rs +++ b/components/style/values/generics/transform.rs @@ -610,7 +610,6 @@ impl<Number: ToCss + PartialEq> ToCss for Scale<Number> { SpecifiedValueInfo, ToAnimatedZero, ToComputedValue, - ToCss, )] /// A value of the `Translate` property /// @@ -618,14 +617,56 @@ impl<Number: ToCss + PartialEq> ToCss for Scale<Number> { pub enum Translate<LengthOrPercentage, Length> { /// 'none' None, - /// '<length-percentage>' - TranslateX(LengthOrPercentage), - /// '<length-percentage> <length-percentage>' + /// '<length-percentage>' or '<length-percentage> <length-percentage>' Translate(LengthOrPercentage, LengthOrPercentage), /// '<length-percentage> <length-percentage> <length>' Translate3D(LengthOrPercentage, LengthOrPercentage, Length), } +/// A trait to check if this is a zero length. +/// An alternative way is use num_traits::Zero. However, in order to implement num_traits::Zero, +/// we also have to implement Add, which may be complicated for LengthOrPercentage::Calc. +/// We could do this if other types also need it. If so, we could drop this trait. +pub trait IsZeroLength { + /// Returns true if this is a zero length. + fn is_zero_length(&self) -> bool; +} + +impl<LoP: ToCss + IsZeroLength, L: ToCss> ToCss for Translate<LoP, L> { + fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result + where + W: fmt::Write, + { + // The spec says: + // 1. If a 2d translation is specified, the property must serialize with only one or two + // values (per usual, if the second value is 0px, the default, it must be omitted when + // serializing). + // 2. If a 3d translation is specified, all three values must be serialized. + // https://drafts.csswg.org/css-transforms-2/#individual-transform-serialization + // + // We don't omit the 3rd component even if it is 0px for now, and the related + // spec issue is https://github.com/w3c/csswg-drafts/issues/3305 + match *self { + Translate::None => dest.write_str("none"), + Translate::Translate(ref x, ref y) => { + x.to_css(dest)?; + if !y.is_zero_length() { + dest.write_char(' ')?; + y.to_css(dest)?; + } + Ok(()) + }, + Translate::Translate3D(ref x, ref y, ref z) => { + x.to_css(dest)?; + dest.write_char(' ')?; + y.to_css(dest)?; + dest.write_char(' ')?; + z.to_css(dest) + }, + } + } +} + #[allow(missing_docs)] #[derive( Clone, Copy, Debug, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss, diff --git a/components/style/values/generics/url.rs b/components/style/values/generics/url.rs index ccd50b235b9..51ad8055be1 100644 --- a/components/style/values/generics/url.rs +++ b/components/style/values/generics/url.rs @@ -44,7 +44,7 @@ where context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result<UrlOrNone<Url>, ParseError<'i>> { - if let Ok(url) = input.r#try(|input| Url::parse(context, input)) { + if let Ok(url) = input.try(|input| Url::parse(context, input)) { return Ok(UrlOrNone::Url(url)); } input.expect_ident_matching("none")?; diff --git a/components/style/values/mod.rs b/components/style/values/mod.rs index 9b78be371d3..a03875b96a8 100644 --- a/components/style/values/mod.rs +++ b/components/style/values/mod.rs @@ -155,7 +155,7 @@ impl<A: Parse, B: Parse> Parse for Either<A, B> { context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result<Either<A, B>, ParseError<'i>> { - if let Ok(v) = input.r#try(|i| A::parse(context, i)) { + if let Ok(v) = input.try(|i| A::parse(context, i)) { Ok(Either::First(v)) } else { B::parse(context, input).map(Either::Second) diff --git a/components/style/values/specified/align.rs b/components/style/values/specified/align.rs index 9e8fa8ecd40..8ab097c45bf 100644 --- a/components/style/values/specified/align.rs +++ b/components/style/values/specified/align.rs @@ -195,25 +195,25 @@ impl ContentDistribution { // when this function is updated. // Try to parse normal first - if input.r#try(|i| i.expect_ident_matching("normal")).is_ok() { + if input.try(|i| i.expect_ident_matching("normal")).is_ok() { return Ok(ContentDistribution::normal()); } // Parse <baseline-position>, but only on the block axis. if axis == AxisDirection::Block { - if let Ok(value) = input.r#try(parse_baseline) { + if let Ok(value) = input.try(parse_baseline) { return Ok(ContentDistribution::new(value)); } } // <content-distribution> - if let Ok(value) = input.r#try(parse_content_distribution) { + if let Ok(value) = input.try(parse_content_distribution) { return Ok(ContentDistribution::new(value)); } // <overflow-position>? <content-position> let overflow_position = input - .r#try(parse_overflow_position) + .try(parse_overflow_position) .unwrap_or(AlignFlags::empty()); let content_position = try_match_ident_ignore_ascii_case! { input, @@ -358,18 +358,18 @@ impl SelfAlignment { // // It's weird that this accepts <baseline-position>, but not // justify-content... - if let Ok(value) = input.r#try(parse_baseline) { + if let Ok(value) = input.try(parse_baseline) { return Ok(SelfAlignment(value)); } // auto | normal | stretch - if let Ok(value) = input.r#try(parse_auto_normal_stretch) { + if let Ok(value) = input.try(parse_auto_normal_stretch) { return Ok(SelfAlignment(value)); } // <overflow-position>? <self-position> let overflow_position = input - .r#try(parse_overflow_position) + .try(parse_overflow_position) .unwrap_or(AlignFlags::empty()); let self_position = parse_self_position(input, axis)?; Ok(SelfAlignment(overflow_position | self_position)) @@ -484,17 +484,17 @@ impl Parse for AlignItems { // this function is updated. // <baseline-position> - if let Ok(baseline) = input.r#try(parse_baseline) { + if let Ok(baseline) = input.try(parse_baseline) { return Ok(AlignItems(baseline)); } // normal | stretch - if let Ok(value) = input.r#try(parse_normal_stretch) { + if let Ok(value) = input.try(parse_normal_stretch) { return Ok(AlignItems(value)); } // <overflow-position>? <self-position> let overflow = input - .r#try(parse_overflow_position) + .try(parse_overflow_position) .unwrap_or(AlignFlags::empty()); let self_position = parse_self_position(input, AxisDirection::Block)?; Ok(AlignItems(self_position | overflow)) @@ -542,23 +542,23 @@ impl Parse for JustifyItems { // // It's weird that this accepts <baseline-position>, but not // justify-content... - if let Ok(baseline) = input.r#try(parse_baseline) { + if let Ok(baseline) = input.try(parse_baseline) { return Ok(JustifyItems(baseline)); } // normal | stretch - if let Ok(value) = input.r#try(parse_normal_stretch) { + if let Ok(value) = input.try(parse_normal_stretch) { return Ok(JustifyItems(value)); } // legacy | [ legacy && [ left | right | center ] ] - if let Ok(value) = input.r#try(parse_legacy) { + if let Ok(value) = input.try(parse_legacy) { return Ok(JustifyItems(value)); } // <overflow-position>? <self-position> let overflow = input - .r#try(parse_overflow_position) + .try(parse_overflow_position) .unwrap_or(AlignFlags::empty()); let self_position = parse_self_position(input, AxisDirection::Inline)?; Ok(JustifyItems(overflow | self_position)) @@ -714,7 +714,7 @@ fn parse_legacy<'i, 't>(input: &mut Parser<'i, 't>) -> Result<AlignFlags, ParseE // when this function is updated. let flags = try_match_ident_ignore_ascii_case! { input, "legacy" => { - let flags = input.r#try(parse_left_right_center) + let flags = input.try(parse_left_right_center) .unwrap_or(AlignFlags::empty()); return Ok(AlignFlags::LEGACY | flags) diff --git a/components/style/values/specified/background.rs b/components/style/values/specified/background.rs index 29e1812dbbc..9aa47fb522c 100644 --- a/components/style/values/specified/background.rs +++ b/components/style/values/specified/background.rs @@ -19,9 +19,9 @@ impl Parse for BackgroundSize { context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { - if let Ok(width) = input.r#try(|i| NonNegativeLengthOrPercentageOrAuto::parse(context, i)) { + if let Ok(width) = input.try(|i| NonNegativeLengthOrPercentageOrAuto::parse(context, i)) { let height = input - .r#try(|i| NonNegativeLengthOrPercentageOrAuto::parse(context, i)) + .try(|i| NonNegativeLengthOrPercentageOrAuto::parse(context, i)) .unwrap_or(NonNegativeLengthOrPercentageOrAuto::auto()); return Ok(GenericBackgroundSize::Explicit { width, height }); } @@ -106,7 +106,7 @@ impl Parse for BackgroundRepeat { }, }; - let vertical = input.r#try(BackgroundRepeatKeyword::parse).ok(); + let vertical = input.try(BackgroundRepeatKeyword::parse).ok(); Ok(BackgroundRepeat::Keywords(horizontal, vertical)) } } diff --git a/components/style/values/specified/basic_shape.rs b/components/style/values/specified/basic_shape.rs index 0631c7f0a7d..d394d8881dd 100644 --- a/components/style/values/specified/basic_shape.rs +++ b/components/style/values/specified/basic_shape.rs @@ -70,12 +70,12 @@ impl Parse for ClippingShape { input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { if is_clip_path_path_enabled(context) { - if let Ok(p) = input.r#try(|i| Path::parse(context, i)) { + if let Ok(p) = input.try(|i| Path::parse(context, i)) { return Ok(ShapeSource::Path(p)); } } - if let Ok(url) = input.r#try(|i| SpecifiedUrl::parse(context, i)) { + if let Ok(url) = input.try(|i| SpecifiedUrl::parse(context, i)) { return Ok(ShapeSource::ImageOrUrl(url)); } @@ -89,7 +89,7 @@ impl Parse for FloatAreaShape { context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { - if let Ok(image) = input.r#try(|i| Image::parse_with_cors_anonymous(context, i)) { + if let Ok(image) = input.try(|i| Image::parse_with_cors_anonymous(context, i)) { return Ok(ShapeSource::ImageOrUrl(image)); } @@ -106,7 +106,7 @@ where context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { - if input.r#try(|i| i.expect_ident_matching("none")).is_ok() { + if input.try(|i| i.expect_ident_matching("none")).is_ok() { return Ok(ShapeSource::None); } @@ -119,7 +119,7 @@ where return false; // already parsed this component } - *component = input.r#try(|i| U::parse(context, i)).ok(); + *component = input.try(|i| U::parse(context, i)).ok(); component.is_some() } @@ -147,7 +147,7 @@ impl Parse for GeometryBox { _context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { - if let Ok(shape_box) = input.r#try(|i| ShapeBox::parse(i)) { + if let Ok(shape_box) = input.try(|i| ShapeBox::parse(i)) { return Ok(GeometryBox::ShapeBox(shape_box)); } @@ -197,7 +197,7 @@ impl InsetRect { input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { let rect = Rect::parse_with(context, input, LengthOrPercentage::parse)?; - let round = if input.r#try(|i| i.expect_ident_matching("round")).is_ok() { + let round = if input.try(|i| i.expect_ident_matching("round")).is_ok() { Some(BorderRadius::parse(context, input)?) } else { None @@ -225,9 +225,9 @@ impl Circle { input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { let radius = input - .r#try(|i| ShapeRadius::parse(context, i)) + .try(|i| ShapeRadius::parse(context, i)) .unwrap_or_default(); - let position = if input.r#try(|i| i.expect_ident_matching("at")).is_ok() { + let position = if input.try(|i| i.expect_ident_matching("at")).is_ok() { Position::parse(context, input)? } else { Position::center() @@ -270,14 +270,14 @@ impl Ellipse { input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { let (a, b) = input - .r#try(|i| -> Result<_, ParseError> { + .try(|i| -> Result<_, ParseError> { Ok(( ShapeRadius::parse(context, i)?, ShapeRadius::parse(context, i)?, )) }) .unwrap_or_default(); - let position = if input.r#try(|i| i.expect_ident_matching("at")).is_ok() { + let position = if input.try(|i| i.expect_ident_matching("at")).is_ok() { Position::parse(context, input)? } else { Position::center() @@ -315,7 +315,7 @@ impl Parse for ShapeRadius { context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { - if let Ok(lop) = input.r#try(|i| LengthOrPercentage::parse_non_negative(context, i)) { + if let Ok(lop) = input.try(|i| LengthOrPercentage::parse_non_negative(context, i)) { return Ok(generic::ShapeRadius::Length(lop)); } @@ -419,7 +419,7 @@ impl Polygon { input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { let fill = input - .r#try(|i| -> Result<_, ParseError> { + .try(|i| -> Result<_, ParseError> { let fill = FillRule::parse(i)?; i.expect_comma()?; // only eat the comma if there is something before it Ok(fill) @@ -457,7 +457,7 @@ impl Path { input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { let fill = input - .r#try(|i| -> Result<_, ParseError> { + .try(|i| -> Result<_, ParseError> { let fill = FillRule::parse(i)?; i.expect_comma()?; Ok(fill) diff --git a/components/style/values/specified/border.rs b/components/style/values/specified/border.rs index 27b9355c21d..c64e5c99985 100644 --- a/components/style/values/specified/border.rs +++ b/components/style/values/specified/border.rs @@ -58,7 +58,7 @@ impl BorderSideWidth { allow_quirks: AllowQuirks, ) -> Result<Self, ParseError<'i>> { if let Ok(length) = - input.r#try(|i| Length::parse_non_negative_quirky(context, i, allow_quirks)) + input.try(|i| Length::parse_non_negative_quirky(context, i, allow_quirks)) { return Ok(BorderSideWidth::Length(length)); } @@ -115,11 +115,11 @@ impl Parse for BorderImageSideWidth { context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { - if input.r#try(|i| i.expect_ident_matching("auto")).is_ok() { + if input.try(|i| i.expect_ident_matching("auto")).is_ok() { return Ok(GenericBorderImageSideWidth::Auto); } - if let Ok(len) = input.r#try(|i| LengthOrPercentage::parse_non_negative(context, i)) { + if let Ok(len) = input.try(|i| LengthOrPercentage::parse_non_negative(context, i)) { return Ok(GenericBorderImageSideWidth::Length(len)); } @@ -133,10 +133,10 @@ impl Parse for BorderImageSlice { context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { - let mut fill = input.r#try(|i| i.expect_ident_matching("fill")).is_ok(); + let mut fill = input.try(|i| i.expect_ident_matching("fill")).is_ok(); let offsets = Rect::parse_with(context, input, NumberOrPercentage::parse_non_negative)?; if !fill { - fill = input.r#try(|i| i.expect_ident_matching("fill")).is_ok(); + fill = input.try(|i| i.expect_ident_matching("fill")).is_ok(); } Ok(GenericBorderImageSlice { offsets: offsets, @@ -151,7 +151,7 @@ impl Parse for BorderRadius { input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { let widths = Rect::parse_with(context, input, LengthOrPercentage::parse_non_negative)?; - let heights = if input.r#try(|i| i.expect_delim('/')).is_ok() { + let heights = if input.try(|i| i.expect_delim('/')).is_ok() { Rect::parse_with(context, input, LengthOrPercentage::parse_non_negative)? } else { widths.clone() @@ -236,7 +236,7 @@ impl Parse for BorderImageRepeat { input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { let horizontal = BorderImageRepeatKeyword::parse(input)?; - let vertical = input.r#try(BorderImageRepeatKeyword::parse).ok(); + let vertical = input.try(BorderImageRepeatKeyword::parse).ok(); Ok(BorderImageRepeat( horizontal, vertical.unwrap_or(horizontal), diff --git a/components/style/values/specified/box.rs b/components/style/values/specified/box.rs index ffa59a4d50e..a5761d3f9b2 100644 --- a/components/style/values/specified/box.rs +++ b/components/style/values/specified/box.rs @@ -6,9 +6,8 @@ use crate::custom_properties::Name as CustomPropertyName; use crate::parser::{Parse, ParserContext}; -use crate::properties::{ - LonghandId, PropertyDeclarationId, PropertyFlags, PropertyId, ShorthandId, -}; +use crate::properties::{LonghandId, PropertyDeclarationId, PropertyFlags}; +use crate::properties::{PropertyId, ShorthandId}; use crate::values::generics::box_::AnimationIterationCount as GenericAnimationIterationCount; use crate::values::generics::box_::Perspective as GenericPerspective; use crate::values::generics::box_::VerticalAlign as GenericVerticalAlign; @@ -310,7 +309,7 @@ impl Parse for VerticalAlign { input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { if let Ok(lop) = - input.r#try(|i| LengthOrPercentage::parse_quirky(context, i, AllowQuirks::Yes)) + input.try(|i| LengthOrPercentage::parse_quirky(context, i, AllowQuirks::Yes)) { return Ok(GenericVerticalAlign::Length(lop)); } @@ -341,7 +340,7 @@ impl Parse for AnimationIterationCount { input: &mut ::cssparser::Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { if input - .r#try(|input| input.expect_ident_matching("infinite")) + .try(|input| input.expect_ident_matching("infinite")) .is_ok() { return Ok(GenericAnimationIterationCount::Infinite); @@ -394,7 +393,7 @@ impl Parse for AnimationName { context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { - if let Ok(name) = input.r#try(|input| KeyframesName::parse(context, input)) { + if let Ok(name) = input.try(|input| KeyframesName::parse(context, input)) { return Ok(AnimationName(Some(name))); } @@ -557,7 +556,7 @@ impl Parse for WillChange { input: &mut Parser<'i, 't>, ) -> Result<WillChange, ParseError<'i>> { if input - .r#try(|input| input.expect_ident_matching("auto")) + .try(|input| input.expect_ident_matching("auto")) .is_ok() { return Ok(WillChange::Auto); @@ -646,14 +645,14 @@ impl Parse for TouchAction { "none" => Ok(TouchAction::TOUCH_ACTION_NONE), "manipulation" => Ok(TouchAction::TOUCH_ACTION_MANIPULATION), "pan-x" => { - if input.r#try(|i| i.expect_ident_matching("pan-y")).is_ok() { + if input.try(|i| i.expect_ident_matching("pan-y")).is_ok() { Ok(TouchAction::TOUCH_ACTION_PAN_X | TouchAction::TOUCH_ACTION_PAN_Y) } else { Ok(TouchAction::TOUCH_ACTION_PAN_X) } }, "pan-y" => { - if input.r#try(|i| i.expect_ident_matching("pan-x")).is_ok() { + if input.try(|i| i.expect_ident_matching("pan-x")).is_ok() { Ok(TouchAction::TOUCH_ACTION_PAN_X | TouchAction::TOUCH_ACTION_PAN_Y) } else { Ok(TouchAction::TOUCH_ACTION_PAN_Y) @@ -757,7 +756,7 @@ impl Parse for Contain { input: &mut Parser<'i, 't>, ) -> Result<Contain, ParseError<'i>> { let mut result = Contain::empty(); - while let Ok(name) = input.r#try(|i| i.expect_ident_cloned()) { + while let Ok(name) = input.try(|i| i.expect_ident_cloned()) { let flag = match_ignore_ascii_case! { &name, "size" => Some(Contain::SIZE), "layout" => Some(Contain::LAYOUT), @@ -794,7 +793,7 @@ impl Parse for Perspective { context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { - if input.r#try(|i| i.expect_ident_matching("none")).is_ok() { + if input.try(|i| i.expect_ident_matching("none")).is_ok() { return Ok(GenericPerspective::None); } Ok(GenericPerspective::Length(NonNegativeLength::parse( @@ -1036,8 +1035,10 @@ pub enum Appearance { #[parse(condition = "in_ua_or_chrome_sheet")] Menuimage, /// A horizontal meter bar. - Meterbar, + #[parse(aliases = "meterbar")] + Meter, /// The meter bar's meter indicator. + #[parse(condition = "in_ua_or_chrome_sheet")] Meterchunk, /// The "arrowed" part of the dropdown button that open up a dropdown list. #[parse(condition = "in_ua_or_chrome_sheet")] @@ -1045,13 +1046,13 @@ pub enum Appearance { /// For HTML's <input type=number> NumberInput, /// A horizontal progress bar. - Progressbar, + #[parse(aliases = "progressbar")] + ProgressBar, /// The progress bar's progress indicator + #[parse(condition = "in_ua_or_chrome_sheet")] Progresschunk, /// A vertical progress bar. ProgressbarVertical, - /// A vertical progress chunk. - ProgresschunkVertical, /// A checkbox element. Checkbox, /// A radio element within a radio group. diff --git a/components/style/values/specified/color.rs b/components/style/values/specified/color.rs index ab24d1a157c..a0f3c3bbde4 100644 --- a/components/style/values/specified/color.rs +++ b/components/style/values/specified/color.rs @@ -142,7 +142,7 @@ impl Parse for Color { input.reset(&start); let compontent_parser = ColorComponentParser(&*context); - match input.r#try(|i| CSSParserColor::parse_with(&compontent_parser, i)) { + match input.try(|i| CSSParserColor::parse_with(&compontent_parser, i)) { Ok(value) => Ok(match value { CSSParserColor::CurrentColor => Color::CurrentColor, CSSParserColor::RGBA(rgba) => Color::Numeric { @@ -245,7 +245,7 @@ impl Color { input: &mut Parser<'i, 't>, allow_quirks: AllowQuirks, ) -> Result<Self, ParseError<'i>> { - input.r#try(|i| Self::parse(context, i)).or_else(|e| { + input.try(|i| Self::parse(context, i)).or_else(|e| { if !allow_quirks.allowed(context.quirks_mode) { return Err(e); } diff --git a/components/style/values/specified/column.rs b/components/style/values/specified/column.rs index 2b6a919b232..0a77dd24687 100644 --- a/components/style/values/specified/column.rs +++ b/components/style/values/specified/column.rs @@ -18,7 +18,7 @@ impl Parse for ColumnCount { context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { - if input.r#try(|i| i.expect_ident_matching("auto")).is_ok() { + if input.try(|i| i.expect_ident_matching("auto")).is_ok() { return Ok(GenericColumnCount::Auto); } Ok(GenericColumnCount::Integer(PositiveInteger::parse( diff --git a/components/style/values/specified/counters.rs b/components/style/values/specified/counters.rs index 718dd07a5fb..fb2b64dbc86 100644 --- a/components/style/values/specified/counters.rs +++ b/components/style/values/specified/counters.rs @@ -52,7 +52,7 @@ fn parse_counters<'i, 't>( default_value: i32, ) -> Result<Vec<CounterPair<Integer>>, ParseError<'i>> { if input - .r#try(|input| input.expect_ident_matching("none")) + .try(|input| input.expect_ident_matching("none")) .is_ok() { return Ok(vec![]); @@ -68,7 +68,7 @@ fn parse_counters<'i, 't>( }; let value = input - .r#try(|input| Integer::parse(context, input)) + .try(|input| Integer::parse(context, input)) .unwrap_or(Integer::new(default_value)); counters.push(CounterPair { name, value }); } @@ -90,7 +90,7 @@ impl Content { #[cfg(feature = "servo")] fn parse_counter_style(_: &ParserContext, input: &mut Parser) -> ListStyleType { input - .r#try(|input| { + .try(|input| { input.expect_comma()?; ListStyleType::parse(input) }) @@ -100,7 +100,7 @@ impl Content { #[cfg(feature = "gecko")] fn parse_counter_style(context: &ParserContext, input: &mut Parser) -> CounterStyleOrNone { input - .r#try(|input| { + .try(|input| { input.expect_comma()?; CounterStyleOrNone::parse(context, input) }) @@ -117,13 +117,13 @@ impl Parse for Content { input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { if input - .r#try(|input| input.expect_ident_matching("normal")) + .try(|input| input.expect_ident_matching("normal")) .is_ok() { return Ok(generics::Content::Normal); } if input - .r#try(|input| input.expect_ident_matching("none")) + .try(|input| input.expect_ident_matching("none")) .is_ok() { return Ok(generics::Content::None); @@ -131,7 +131,7 @@ impl Parse for Content { #[cfg(feature = "gecko")] { if input - .r#try(|input| input.expect_ident_matching("-moz-alt-content")) + .try(|input| input.expect_ident_matching("-moz-alt-content")) .is_ok() { return Ok(generics::Content::MozAltContent); @@ -142,7 +142,7 @@ impl Parse for Content { loop { #[cfg(feature = "gecko")] { - if let Ok(url) = input.r#try(|i| SpecifiedImageUrl::parse(context, i)) { + if let Ok(url) = input.try(|i| SpecifiedImageUrl::parse(context, i)) { content.push(generics::ContentItem::Url(url)); continue; } diff --git a/components/style/values/specified/easing.rs b/components/style/values/specified/easing.rs index d65f1897d4c..f7cd72a3747 100644 --- a/components/style/values/specified/easing.rs +++ b/components/style/values/specified/easing.rs @@ -21,10 +21,10 @@ impl Parse for TimingFunction { context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { - if let Ok(keyword) = input.r#try(TimingKeyword::parse) { + if let Ok(keyword) = input.try(TimingKeyword::parse) { return Ok(GenericTimingFunction::Keyword(keyword)); } - if let Ok(ident) = input.r#try(|i| i.expect_ident_cloned()) { + if let Ok(ident) = input.try(|i| i.expect_ident_cloned()) { let position = match_ignore_ascii_case! { &ident, "step-start" => StepPosition::Start, "step-end" => StepPosition::End, @@ -57,7 +57,7 @@ impl Parse for TimingFunction { }, "steps" => { let steps = Integer::parse_positive(context, i)?; - let position = i.r#try(|i| { + let position = i.try(|i| { i.expect_comma()?; StepPosition::parse(context, i) }).unwrap_or(StepPosition::End); diff --git a/components/style/values/specified/effects.rs b/components/style/values/specified/effects.rs index 758827ae5ec..bae46e70c88 100644 --- a/components/style/values/specified/effects.rs +++ b/components/style/values/specified/effects.rs @@ -7,9 +7,8 @@ use crate::parser::{Parse, ParserContext}; use crate::values::computed::effects::BoxShadow as ComputedBoxShadow; use crate::values::computed::effects::SimpleShadow as ComputedSimpleShadow; -use crate::values::computed::{ - Context, NonNegativeNumber as ComputedNonNegativeNumber, ToComputedValue, -}; +use crate::values::computed::NonNegativeNumber as ComputedNonNegativeNumber; +use crate::values::computed::{Context, ToComputedValue}; use crate::values::generics::effects::BoxShadow as GenericBoxShadow; use crate::values::generics::effects::Filter as GenericFilter; use crate::values::generics::effects::SimpleShadow as GenericSimpleShadow; @@ -109,7 +108,7 @@ impl Parse for BoxShadow { loop { if !inset { if input - .r#try(|input| input.expect_ident_matching("inset")) + .try(|input| input.expect_ident_matching("inset")) .is_ok() { inset = true; @@ -117,14 +116,14 @@ impl Parse for BoxShadow { } } if lengths.is_none() { - let value = input.r#try::<_, _, ParseError>(|i| { + let value = input.try::<_, _, ParseError>(|i| { let horizontal = Length::parse(context, i)?; let vertical = Length::parse(context, i)?; let (blur, spread) = match i - .r#try::<_, _, ParseError>(|i| Length::parse_non_negative(context, i)) + .try::<_, _, ParseError>(|i| Length::parse_non_negative(context, i)) { Ok(blur) => { - let spread = i.r#try(|i| Length::parse(context, i)).ok(); + let spread = i.try(|i| Length::parse(context, i)).ok(); (Some(blur.into()), spread) }, Err(_) => (None, None), @@ -137,7 +136,7 @@ impl Parse for BoxShadow { } } if color.is_none() { - if let Ok(value) = input.r#try(|i| Color::parse(context, i)) { + if let Ok(value) = input.try(|i| Color::parse(context, i)) { color = Some(value); continue; } @@ -194,7 +193,7 @@ impl Parse for Filter { ) -> Result<Self, ParseError<'i>> { #[cfg(feature = "gecko")] { - if let Ok(url) = input.r#try(|i| SpecifiedUrl::parse(context, i)) { + if let Ok(url) = input.try(|i| SpecifiedUrl::parse(context, i)) { return Ok(GenericFilter::Url(url)); } } @@ -253,12 +252,12 @@ impl Parse for SimpleShadow { context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { - let color = input.r#try(|i| Color::parse(context, i)).ok(); + let color = input.try(|i| Color::parse(context, i)).ok(); let horizontal = Length::parse(context, input)?; let vertical = Length::parse(context, input)?; - let blur = input.r#try(|i| Length::parse_non_negative(context, i)).ok(); + let blur = input.try(|i| Length::parse_non_negative(context, i)).ok(); let blur = blur.map(NonNegative::<Length>); - let color = color.or_else(|| input.r#try(|i| Color::parse(context, i)).ok()); + let color = color.or_else(|| input.try(|i| Color::parse(context, i)).ok()); Ok(SimpleShadow { color, diff --git a/components/style/values/specified/flex.rs b/components/style/values/specified/flex.rs index 8efe96ed556..01fbbb7f304 100644 --- a/components/style/values/specified/flex.rs +++ b/components/style/values/specified/flex.rs @@ -25,7 +25,7 @@ impl Parse for FlexBasis { context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { - if let Ok(width) = input.r#try(|i| Width::parse(context, i)) { + if let Ok(width) = input.try(|i| Width::parse(context, i)) { return Ok(GenericFlexBasis::Width(width)); } try_match_ident_ignore_ascii_case! { input, diff --git a/components/style/values/specified/font.rs b/components/style/values/specified/font.rs index eabb878f311..467c7062bf3 100644 --- a/components/style/values/specified/font.rs +++ b/components/style/values/specified/font.rs @@ -11,10 +11,9 @@ use crate::gecko_bindings::bindings; use crate::parser::{Parse, ParserContext}; use crate::properties::longhands::system_font::SystemFont; use crate::values::computed::font::{FamilyName, FontFamilyList, FontStyleAngle, SingleFontFamily}; -use crate::values::computed::{ - font as computed, Context, Length, NonNegativeLength, ToComputedValue, -}; +use crate::values::computed::{font as computed, Length, NonNegativeLength}; use crate::values::computed::{Angle as ComputedAngle, Percentage as ComputedPercentage}; +use crate::values::computed::{Context, ToComputedValue}; use crate::values::generics::font::{self as generics, FeatureTagValue, FontSettings, FontTag}; use crate::values::generics::font::{KeywordSize, VariationValue}; use crate::values::generics::NonNegative; @@ -117,7 +116,7 @@ impl Parse for FontWeight { context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result<FontWeight, ParseError<'i>> { - if let Ok(absolute) = input.r#try(|input| AbsoluteFontWeight::parse(context, input)) { + if let Ok(absolute) = input.try(|input| AbsoluteFontWeight::parse(context, input)) { return Ok(FontWeight::Absolute(absolute)); } @@ -190,7 +189,7 @@ impl Parse for AbsoluteFontWeight { context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { - if let Ok(number) = input.r#try(|input| Number::parse(context, input)) { + if let Ok(number) = input.try(|input| Number::parse(context, input)) { // We could add another AllowedNumericType value, but it doesn't // seem worth it just for a single property with such a weird range, // so we do the clamping here manually. @@ -242,7 +241,7 @@ impl Parse for SpecifiedFontStyle { "normal" => generics::FontStyle::Normal, "italic" => generics::FontStyle::Italic, "oblique" => { - let angle = input.r#try(|input| Self::parse_angle(context, input)) + let angle = input.try(|input| Self::parse_angle(context, input)) .unwrap_or_else(|_| Self::default_angle()); generics::FontStyle::Oblique(angle) @@ -481,8 +480,7 @@ impl Parse for FontStretch { // // Values less than 0% are not allowed and are treated as parse // errors. - if let Ok(percentage) = input.r#try(|input| Percentage::parse_non_negative(context, input)) - { + if let Ok(percentage) = input.try(|input| Percentage::parse_non_negative(context, input)) { return Ok(FontStretch::Stretch(percentage)); } @@ -682,7 +680,7 @@ impl Parse for FontSizeAdjust { input: &mut Parser<'i, 't>, ) -> Result<FontSizeAdjust, ParseError<'i>> { if input - .r#try(|input| input.expect_ident_matching("none")) + .try(|input| input.expect_ident_matching("none")) .is_ok() { return Ok(FontSizeAdjust::None); @@ -990,12 +988,12 @@ impl FontSize { allow_quirks: AllowQuirks, ) -> Result<FontSize, ParseError<'i>> { if let Ok(lop) = - input.r#try(|i| LengthOrPercentage::parse_non_negative_quirky(context, i, allow_quirks)) + input.try(|i| LengthOrPercentage::parse_non_negative_quirky(context, i, allow_quirks)) { return Ok(FontSize::Length(lop)); } - if let Ok(kw) = input.r#try(KeywordSize::parse) { + if let Ok(kw) = input.try(KeywordSize::parse) { return Ok(FontSize::Keyword(kw.into())); } @@ -1177,7 +1175,7 @@ impl Parse for FontVariantAlternates { ) -> Result<FontVariantAlternates, ParseError<'i>> { let mut alternates = Vec::new(); if input - .r#try(|input| input.expect_ident_matching("normal")) + .try(|input| input.expect_ident_matching("normal")) .is_ok() { return Ok(FontVariantAlternates::Value(VariantAlternatesList( @@ -1194,7 +1192,7 @@ impl Parse for FontVariantAlternates { parsed_alternates |= $flag; ) ); - while let Ok(_) = input.r#try(|input| { + while let Ok(_) = input.try(|input| { // FIXME: remove clone() when lifetimes are non-lexical match input.next()?.clone() { Token::Ident(ref value) if value.eq_ignore_ascii_case("historical-forms") => { @@ -1409,13 +1407,13 @@ impl Parse for FontVariantEastAsian { let mut result = VariantEastAsian::empty(); if input - .r#try(|input| input.expect_ident_matching("normal")) + .try(|input| input.expect_ident_matching("normal")) .is_ok() { return Ok(FontVariantEastAsian::Value(result)); } - while let Ok(flag) = input.r#try(|input| { + while let Ok(flag) = input.try(|input| { Ok( match_ignore_ascii_case! { &input.expect_ident().map_err(|_| ())?, "jis78" => @@ -1633,19 +1631,19 @@ impl Parse for FontVariantLigatures { let mut result = VariantLigatures::empty(); if input - .r#try(|input| input.expect_ident_matching("normal")) + .try(|input| input.expect_ident_matching("normal")) .is_ok() { return Ok(FontVariantLigatures::Value(result)); } if input - .r#try(|input| input.expect_ident_matching("none")) + .try(|input| input.expect_ident_matching("none")) .is_ok() { return Ok(FontVariantLigatures::Value(VariantLigatures::NONE)); } - while let Ok(flag) = input.r#try(|input| { + while let Ok(flag) = input.try(|input| { Ok( match_ignore_ascii_case! { &input.expect_ident().map_err(|_| ())?, "common-ligatures" => @@ -1842,13 +1840,13 @@ impl Parse for FontVariantNumeric { let mut result = VariantNumeric::empty(); if input - .r#try(|input| input.expect_ident_matching("normal")) + .try(|input| input.expect_ident_matching("normal")) .is_ok() { return Ok(FontVariantNumeric::Value(result)); } - while let Ok(flag) = input.r#try(|input| { + while let Ok(flag) = input.try(|input| { Ok( match_ignore_ascii_case! { &input.expect_ident().map_err(|_| ())?, "ordinal" => @@ -1982,14 +1980,14 @@ impl Parse for FontSynthesis { "none" => Ok(result), "weight" => { result.weight = true; - if input.r#try(|input| input.expect_ident_matching("style")).is_ok() { + if input.try(|input| input.expect_ident_matching("style")).is_ok() { result.style = true; } Ok(result) }, "style" => { result.style = true; - if input.r#try(|input| input.expect_ident_matching("weight")).is_ok() { + if input.try(|input| input.expect_ident_matching("weight")).is_ok() { result.weight = true; } Ok(result) @@ -2128,7 +2126,7 @@ impl Parse for FontLanguageOverride { input: &mut Parser<'i, 't>, ) -> Result<FontLanguageOverride, ParseError<'i>> { if input - .r#try(|input| input.expect_ident_matching("normal")) + .try(|input| input.expect_ident_matching("normal")) .is_ok() { return Ok(FontLanguageOverride::Normal); @@ -2195,7 +2193,7 @@ fn parse_one_feature_value<'i, 't>( context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result<Integer, ParseError<'i>> { - if let Ok(integer) = input.r#try(|i| Integer::parse_non_negative(context, i)) { + if let Ok(integer) = input.try(|i| Integer::parse_non_negative(context, i)) { return Ok(integer); } @@ -2213,7 +2211,7 @@ impl Parse for FeatureTagValue<Integer> { ) -> Result<Self, ParseError<'i>> { let tag = FontTag::parse(context, input)?; let value = input - .r#try(|i| parse_one_feature_value(context, i)) + .try(|i| parse_one_feature_value(context, i)) .unwrap_or_else(|_| Integer::new(1)); Ok(Self { tag, value }) @@ -2331,7 +2329,7 @@ impl Parse for MozScriptLevel { input: &mut Parser<'i, 't>, ) -> Result<MozScriptLevel, ParseError<'i>> { // We don't bother to handle calc here. - if let Ok(i) = input.r#try(|i| i.expect_integer()) { + if let Ok(i) = input.try(|i| i.expect_integer()) { return Ok(MozScriptLevel::Relative(i)); } input.expect_ident_matching("auto")?; diff --git a/components/style/values/specified/gecko.rs b/components/style/values/specified/gecko.rs index 5c1e502604d..1d8118fce1b 100644 --- a/components/style/values/specified/gecko.rs +++ b/components/style/values/specified/gecko.rs @@ -25,7 +25,7 @@ impl Parse for ScrollSnapPoint { context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { - if input.r#try(|i| i.expect_ident_matching("none")).is_ok() { + if input.try(|i| i.expect_ident_matching("none")).is_ok() { return Ok(GenericScrollSnapPoint::None); } input.expect_function_matching("repeat")?; diff --git a/components/style/values/specified/grid.rs b/components/style/values/specified/grid.rs index c26dd04908e..663971b8a43 100644 --- a/components/style/values/specified/grid.rs +++ b/components/style/values/specified/grid.rs @@ -36,11 +36,11 @@ impl Parse for TrackBreadth<LengthOrPercentage> { context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { - if let Ok(lop) = input.r#try(|i| LengthOrPercentage::parse_non_negative(context, i)) { + if let Ok(lop) = input.try(|i| LengthOrPercentage::parse_non_negative(context, i)) { return Ok(TrackBreadth::Breadth(lop)); } - if let Ok(f) = input.r#try(parse_flex) { + if let Ok(f) = input.try(parse_flex) { return Ok(TrackBreadth::Fr(f)); } @@ -53,17 +53,14 @@ impl Parse for TrackSize<LengthOrPercentage> { context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { - if let Ok(b) = input.r#try(|i| TrackBreadth::parse(context, i)) { + if let Ok(b) = input.try(|i| TrackBreadth::parse(context, i)) { return Ok(TrackSize::Breadth(b)); } - if input - .r#try(|i| i.expect_function_matching("minmax")) - .is_ok() - { + if input.try(|i| i.expect_function_matching("minmax")).is_ok() { return input.parse_nested_block(|input| { let inflexible_breadth = - match input.r#try(|i| LengthOrPercentage::parse_non_negative(context, i)) { + match input.try(|i| LengthOrPercentage::parse_non_negative(context, i)) { Ok(lop) => TrackBreadth::Breadth(lop), Err(..) => { let keyword = TrackKeyword::parse(input)?; @@ -95,7 +92,7 @@ pub fn parse_line_names<'i, 't>( input.expect_square_bracket_block()?; input.parse_nested_block(|input| { let mut values = vec![]; - while let Ok((loc, ident)) = input.r#try(|i| -> Result<_, CssParseError<()>> { + while let Ok((loc, ident)) = input.try(|i| -> Result<_, CssParseError<()>> { Ok((i.current_source_location(), i.expect_ident_cloned()?)) }) { let ident = CustomIdent::from_ident(loc, &ident, &["span", "auto"])?; @@ -126,7 +123,7 @@ impl TrackRepeat<LengthOrPercentage, Integer> { input: &mut Parser<'i, 't>, ) -> Result<(Self, RepeatType), ParseError<'i>> { input - .r#try(|i| i.expect_function_matching("repeat").map_err(|e| e.into())) + .try(|i| i.expect_function_matching("repeat").map_err(|e| e.into())) .and_then(|_| { input.parse_nested_block(|input| { let count = RepeatCount::parse(context, input)?; @@ -146,9 +143,9 @@ impl TrackRepeat<LengthOrPercentage, Integer> { loop { current_names = input - .r#try(parse_line_names) + .try(parse_line_names) .unwrap_or(vec![].into_boxed_slice()); - if let Ok(track_size) = input.r#try(|i| TrackSize::parse(context, i)) { + if let Ok(track_size) = input.try(|i| TrackSize::parse(context, i)) { if !track_size.is_fixed() { if is_auto { // should be <fixed-size> for <auto-repeat> @@ -172,7 +169,7 @@ impl TrackRepeat<LengthOrPercentage, Integer> { // gecko implements new spec. names.push( input - .r#try(parse_line_names) + .try(parse_line_names) .unwrap_or(vec![].into_boxed_slice()), ); break; @@ -226,10 +223,10 @@ impl Parse for TrackList<LengthOrPercentage, Integer> { loop { current_names.extend_from_slice( &mut input - .r#try(parse_line_names) + .try(parse_line_names) .unwrap_or(vec![].into_boxed_slice()), ); - if let Ok(track_size) = input.r#try(|i| TrackSize::parse(context, i)) { + if let Ok(track_size) = input.try(|i| TrackSize::parse(context, i)) { if !track_size.is_fixed() { atleast_one_not_fixed = true; if auto_repeat.is_some() { @@ -242,7 +239,7 @@ impl Parse for TrackList<LengthOrPercentage, Integer> { names.push(vec.into_boxed_slice()); values.push(TrackListValue::TrackSize(track_size)); } else if let Ok((repeat, type_)) = - input.r#try(|i| TrackRepeat::parse_with_repeat_type(context, i)) + input.try(|i| TrackRepeat::parse_with_repeat_type(context, i)) { if list_type == TrackListType::Explicit { list_type = TrackListType::Normal; // <explicit-track-list> doesn't contain repeat() @@ -404,7 +401,7 @@ impl Parse for GridTemplateComponent<LengthOrPercentage, Integer> { context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { - if input.r#try(|i| i.expect_ident_matching("none")).is_ok() { + if input.try(|i| i.expect_ident_matching("none")).is_ok() { return Ok(GridTemplateComponent::None); } @@ -419,7 +416,7 @@ impl GridTemplateComponent<LengthOrPercentage, Integer> { input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { if allow_grid_template_subgrids() { - if let Ok(t) = input.r#try(|i| LineNameList::parse(context, i)) { + if let Ok(t) = input.try(|i| LineNameList::parse(context, i)) { return Ok(GridTemplateComponent::Subgrid(t)); } } diff --git a/components/style/values/specified/image.rs b/components/style/values/specified/image.rs index fdf7630a9b2..6366facf049 100644 --- a/components/style/values/specified/image.rs +++ b/components/style/values/specified/image.rs @@ -39,7 +39,7 @@ impl ImageLayer { context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { - if let Ok(v) = input.r#try(|i| None_::parse(context, i)) { + if let Ok(v) = input.try(|i| None_::parse(context, i)) { return Ok(Either::First(v)); } Image::parse_with_cors_anonymous(context, input).map(Either::Second) @@ -142,19 +142,19 @@ impl Parse for Image { context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result<Image, ParseError<'i>> { - if let Ok(url) = input.r#try(|input| SpecifiedImageUrl::parse(context, input)) { + if let Ok(url) = input.try(|input| SpecifiedImageUrl::parse(context, input)) { return Ok(generic::Image::Url(url)); } - if let Ok(gradient) = input.r#try(|i| Gradient::parse(context, i)) { + if let Ok(gradient) = input.try(|i| Gradient::parse(context, i)) { return Ok(generic::Image::Gradient(Box::new(gradient))); } #[cfg(feature = "servo")] { - if let Ok(paint_worklet) = input.r#try(|i| PaintWorklet::parse(context, i)) { + if let Ok(paint_worklet) = input.try(|i| PaintWorklet::parse(context, i)) { return Ok(generic::Image::PaintWorklet(paint_worklet)); } } - if let Ok(image_rect) = input.r#try(|input| MozImageRect::parse(context, input)) { + if let Ok(image_rect) = input.try(|input| MozImageRect::parse(context, input)) { return Ok(generic::Image::Rect(Box::new(image_rect))); } Ok(generic::Image::Element(Image::parse_element(input)?)) @@ -172,7 +172,7 @@ impl Image { /// Parses a `-moz-element(# <element-id>)`. fn parse_element<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Atom, ParseError<'i>> { - input.r#try(|i| i.expect_function_matching("-moz-element"))?; + input.try(|i| i.expect_function_matching("-moz-element"))?; let location = input.current_source_location(); input.parse_nested_block(|i| match *i.next()? { Token::IDHash(ref id) => Ok(Atom::from(id.as_ref())), @@ -190,7 +190,7 @@ impl Image { input: &mut Parser<'i, 't>, ) -> Result<Image, ParseError<'i>> { if let Ok(url) = - input.r#try(|input| SpecifiedImageUrl::parse_with_cors_anonymous(context, input)) + input.try(|input| SpecifiedImageUrl::parse_with_cors_anonymous(context, input)) { return Ok(generic::Image::Url(url)); } @@ -350,7 +350,7 @@ impl Gradient { context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { - input.r#try(|i| { + input.try(|i| { let x = Component::parse(context, i)?; let y = Component::parse(context, i)?; @@ -413,13 +413,13 @@ impl Gradient { context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { - if let Ok(side) = input.r#try(|i| S::parse(context, i)) { + if let Ok(side) = input.try(|i| S::parse(context, i)) { return Ok(Component::Side(side)); } - if let Ok(number) = input.r#try(|i| NumberOrPercentage::parse(context, i)) { + if let Ok(number) = input.try(|i| NumberOrPercentage::parse(context, i)) { return Ok(Component::Number(number)); } - input.r#try(|i| i.expect_ident_matching("center"))?; + input.try(|i| i.expect_ident_matching("center"))?; Ok(Component::Center) } } @@ -477,7 +477,7 @@ impl Gradient { }; let mut items = input - .r#try(|i| { + .try(|i| { i.expect_comma()?; i.parse_comma_separated(|i| { let function = i.expect_function()?.clone(); @@ -572,16 +572,16 @@ impl GradientKind { input: &mut Parser<'i, 't>, compat_mode: &mut CompatMode, ) -> Result<Self, ParseError<'i>> { - let direction = - if let Ok(d) = input.r#try(|i| LineDirection::parse(context, i, compat_mode)) { - input.expect_comma()?; - d - } else { - match *compat_mode { - CompatMode::Modern => LineDirection::Vertical(Y::Bottom), - _ => LineDirection::Vertical(Y::Top), - } - }; + let direction = if let Ok(d) = input.try(|i| LineDirection::parse(context, i, compat_mode)) + { + input.expect_comma()?; + d + } else { + match *compat_mode { + CompatMode::Modern => LineDirection::Vertical(Y::Bottom), + _ => LineDirection::Vertical(Y::Top), + } + }; Ok(generic::GradientKind::Linear(direction)) } @@ -592,16 +592,16 @@ impl GradientKind { ) -> Result<Self, ParseError<'i>> { let (shape, position, angle, moz_position) = match *compat_mode { CompatMode::Modern => { - let shape = input.r#try(|i| EndingShape::parse(context, i, *compat_mode)); - let position = input.r#try(|i| { + let shape = input.try(|i| EndingShape::parse(context, i, *compat_mode)); + let position = input.try(|i| { i.expect_ident_matching("at")?; Position::parse(context, i) }); (shape, position.ok(), None, None) }, CompatMode::WebKit => { - let position = input.r#try(|i| Position::parse(context, i)); - let shape = input.r#try(|i| { + let position = input.try(|i| Position::parse(context, i)); + let shape = input.try(|i| { if position.is_ok() { i.expect_comma()?; } @@ -620,13 +620,13 @@ impl GradientKind { // cover | contain // and <color-stop> = <color> [ <percentage> | <length> ]? CompatMode::Moz => { - let mut position = input.r#try(|i| LegacyPosition::parse(context, i)); - let angle = input.r#try(|i| Angle::parse(context, i)).ok(); + let mut position = input.try(|i| LegacyPosition::parse(context, i)); + let angle = input.try(|i| Angle::parse(context, i)).ok(); if position.is_err() { - position = input.r#try(|i| LegacyPosition::parse(context, i)); + position = input.try(|i| LegacyPosition::parse(context, i)); } - let shape = input.r#try(|i| { + let shape = input.try(|i| { if position.is_ok() || angle.is_some() { i.expect_comma()?; } @@ -768,18 +768,18 @@ impl LineDirection { compat_mode: &mut CompatMode, ) -> Result<Self, ParseError<'i>> { let mut _angle = if *compat_mode == CompatMode::Moz { - input.r#try(|i| Angle::parse(context, i)).ok() + input.try(|i| Angle::parse(context, i)).ok() } else { // Gradients allow unitless zero angles as an exception, see: // https://github.com/w3c/csswg-drafts/issues/1162 - if let Ok(angle) = input.r#try(|i| Angle::parse_with_unitless(context, i)) { + if let Ok(angle) = input.try(|i| Angle::parse_with_unitless(context, i)) { return Ok(LineDirection::Angle(angle)); } None }; - input.r#try(|i| { - let to_ident = i.r#try(|i| i.expect_ident_matching("to")); + input.try(|i| { + let to_ident = i.try(|i| i.expect_ident_matching("to")); match *compat_mode { // `to` keyword is mandatory in modern syntax. CompatMode::Modern => to_ident?, @@ -801,9 +801,9 @@ impl LineDirection { { // `-moz-` prefixed linear gradient can be both Angle and Position. if *compat_mode == CompatMode::Moz { - let position = i.r#try(|i| LegacyPosition::parse(context, i)).ok(); + let position = i.try(|i| LegacyPosition::parse(context, i)).ok(); if _angle.is_none() { - _angle = i.r#try(|i| Angle::parse(context, i)).ok(); + _angle = i.try(|i| Angle::parse(context, i)).ok(); }; if _angle.is_none() && position.is_none() { @@ -813,14 +813,14 @@ impl LineDirection { } } - if let Ok(x) = i.r#try(X::parse) { - if let Ok(y) = i.r#try(Y::parse) { + if let Ok(x) = i.try(X::parse) { + if let Ok(y) = i.try(Y::parse) { return Ok(LineDirection::Corner(x, y)); } return Ok(LineDirection::Horizontal(x)); } let y = Y::parse(i)?; - if let Ok(x) = i.r#try(X::parse) { + if let Ok(x) = i.try(X::parse) { return Ok(LineDirection::Corner(x, y)); } Ok(LineDirection::Vertical(y)) @@ -850,20 +850,19 @@ impl EndingShape { input: &mut Parser<'i, 't>, compat_mode: CompatMode, ) -> Result<Self, ParseError<'i>> { - if let Ok(extent) = input.r#try(|i| ShapeExtent::parse_with_compat_mode(i, compat_mode)) { - if input.r#try(|i| i.expect_ident_matching("circle")).is_ok() { + if let Ok(extent) = input.try(|i| ShapeExtent::parse_with_compat_mode(i, compat_mode)) { + if input.try(|i| i.expect_ident_matching("circle")).is_ok() { return Ok(generic::EndingShape::Circle(Circle::Extent(extent))); } - let _ = input.r#try(|i| i.expect_ident_matching("ellipse")); + let _ = input.try(|i| i.expect_ident_matching("ellipse")); return Ok(generic::EndingShape::Ellipse(Ellipse::Extent(extent))); } - if input.r#try(|i| i.expect_ident_matching("circle")).is_ok() { - if let Ok(extent) = input.r#try(|i| ShapeExtent::parse_with_compat_mode(i, compat_mode)) - { + if input.try(|i| i.expect_ident_matching("circle")).is_ok() { + if let Ok(extent) = input.try(|i| ShapeExtent::parse_with_compat_mode(i, compat_mode)) { return Ok(generic::EndingShape::Circle(Circle::Extent(extent))); } if compat_mode == CompatMode::Modern { - if let Ok(length) = input.r#try(|i| Length::parse(context, i)) { + if let Ok(length) = input.try(|i| Length::parse(context, i)) { return Ok(generic::EndingShape::Circle(Circle::Radius(length))); } } @@ -871,13 +870,12 @@ impl EndingShape { ShapeExtent::FarthestCorner, ))); } - if input.r#try(|i| i.expect_ident_matching("ellipse")).is_ok() { - if let Ok(extent) = input.r#try(|i| ShapeExtent::parse_with_compat_mode(i, compat_mode)) - { + if input.try(|i| i.expect_ident_matching("ellipse")).is_ok() { + if let Ok(extent) = input.try(|i| ShapeExtent::parse_with_compat_mode(i, compat_mode)) { return Ok(generic::EndingShape::Ellipse(Ellipse::Extent(extent))); } if compat_mode == CompatMode::Modern { - let pair: Result<_, ParseError> = input.r#try(|i| { + let pair: Result<_, ParseError> = input.try(|i| { let x = LengthOrPercentage::parse(context, i)?; let y = LengthOrPercentage::parse(context, i)?; Ok((x, y)) @@ -893,10 +891,10 @@ impl EndingShape { // -moz- prefixed radial gradient doesn't allow EndingShape's Length or LengthOrPercentage // to come before shape keyword. Otherwise it conflicts with <position>. if compat_mode != CompatMode::Moz { - if let Ok(length) = input.r#try(|i| Length::parse(context, i)) { - if let Ok(y) = input.r#try(|i| LengthOrPercentage::parse(context, i)) { + if let Ok(length) = input.try(|i| Length::parse(context, i)) { + if let Ok(y) = input.try(|i| LengthOrPercentage::parse(context, i)) { if compat_mode == CompatMode::Modern { - let _ = input.r#try(|i| i.expect_ident_matching("ellipse")); + let _ = input.try(|i| i.expect_ident_matching("ellipse")); } return Ok(generic::EndingShape::Ellipse(Ellipse::Radii( length.into(), @@ -904,7 +902,7 @@ impl EndingShape { ))); } if compat_mode == CompatMode::Modern { - let y = input.r#try(|i| { + let y = input.try(|i| { i.expect_ident_matching("ellipse")?; LengthOrPercentage::parse(context, i) }); @@ -914,17 +912,17 @@ impl EndingShape { y, ))); } - let _ = input.r#try(|i| i.expect_ident_matching("circle")); + let _ = input.try(|i| i.expect_ident_matching("circle")); } return Ok(generic::EndingShape::Circle(Circle::Radius(length))); } } - input.r#try(|i| { + input.try(|i| { let x = Percentage::parse(context, i)?; - let y = if let Ok(y) = i.r#try(|i| LengthOrPercentage::parse(context, i)) { + let y = if let Ok(y) = i.try(|i| LengthOrPercentage::parse(context, i)) { if compat_mode == CompatMode::Modern { - let _ = i.r#try(|i| i.expect_ident_matching("ellipse")); + let _ = i.try(|i| i.expect_ident_matching("ellipse")); } y } else { @@ -965,7 +963,7 @@ impl GradientItem { loop { input.parse_until_before(Delimiter::Comma, |input| { if seen_stop { - if let Ok(hint) = input.r#try(|i| LengthOrPercentage::parse(context, i)) { + if let Ok(hint) = input.try(|i| LengthOrPercentage::parse(context, i)) { seen_stop = false; items.push(generic::GradientItem::InterpolationHint(hint)); return Ok(()); @@ -974,7 +972,7 @@ impl GradientItem { let stop = ColorStop::parse(context, input)?; - if let Ok(multi_position) = input.r#try(|i| LengthOrPercentage::parse(context, i)) { + if let Ok(multi_position) = input.try(|i| LengthOrPercentage::parse(context, i)) { let stop_color = stop.color.clone(); items.push(generic::GradientItem::ColorStop(stop)); items.push(generic::GradientItem::ColorStop(ColorStop { @@ -1010,7 +1008,7 @@ impl Parse for ColorStop { ) -> Result<Self, ParseError<'i>> { Ok(ColorStop { color: Color::parse(context, input)?, - position: input.r#try(|i| LengthOrPercentage::parse(context, i)).ok(), + position: input.try(|i| LengthOrPercentage::parse(context, i)).ok(), }) } } @@ -1024,7 +1022,7 @@ impl Parse for PaintWorklet { input.parse_nested_block(|input| { let name = Atom::from(&**input.expect_ident()?); let arguments = input - .r#try(|input| { + .try(|input| { input.expect_comma()?; input.parse_comma_separated(|input| SpecifiedValue::parse(input)) }) @@ -1039,7 +1037,7 @@ impl Parse for MozImageRect { context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { - input.r#try(|i| i.expect_function_matching("-moz-image-rect"))?; + input.try(|i| i.expect_function_matching("-moz-image-rect"))?; input.parse_nested_block(|i| { let string = i.expect_url_or_string()?; let url = SpecifiedImageUrl::parse_from_string(string.as_ref().to_owned(), context); diff --git a/components/style/values/specified/length.rs b/components/style/values/specified/length.rs index 4dd4ab42935..94202944064 100644 --- a/components/style/values/specified/length.rs +++ b/components/style/values/specified/length.rs @@ -11,9 +11,9 @@ use app_units::Au; use crate::font_metrics::FontMetricsQueryResult; use crate::parser::{Parse, ParserContext}; use crate::values::computed::{self, CSSPixelLength, Context, ExtremumLength}; -use crate::values::generics::length::{ - MaxLength as GenericMaxLength, MozLength as GenericMozLength, -}; +use crate::values::generics::length::MaxLength as GenericMaxLength; +use crate::values::generics::length::MozLength as GenericMozLength; +use crate::values::generics::transform::IsZeroLength; use crate::values::generics::NonNegative; use crate::values::specified::calc::CalcNode; use crate::values::{Auto, CSSFloat, Either, IsAuto, Normal}; @@ -99,6 +99,16 @@ impl FontBaseSize { } impl FontRelativeLength { + /// Return true if this is a zero value. + fn is_zero(&self) -> bool { + match *self { + FontRelativeLength::Em(v) | + FontRelativeLength::Ex(v) | + FontRelativeLength::Ch(v) | + FontRelativeLength::Rem(v) => v == 0.0, + } + } + /// Computes the font-relative length. pub fn to_computed_value(&self, context: &Context, base_size: FontBaseSize) -> CSSPixelLength { use std::f32; @@ -232,6 +242,16 @@ pub enum ViewportPercentageLength { } impl ViewportPercentageLength { + /// Return true if this is a zero value. + fn is_zero(&self) -> bool { + match *self { + ViewportPercentageLength::Vw(v) | + ViewportPercentageLength::Vh(v) | + ViewportPercentageLength::Vmin(v) | + ViewportPercentageLength::Vmax(v) => v == 0.0, + } + } + /// Computes the given viewport-relative length for the given viewport size. pub fn to_computed_value(&self, viewport_size: Size2D<Au>) -> CSSPixelLength { let (factor, length) = match *self { @@ -487,6 +507,18 @@ impl NoCalcLength { impl SpecifiedValueInfo for NoCalcLength {} +impl IsZeroLength for NoCalcLength { + #[inline] + fn is_zero_length(&self) -> bool { + match *self { + NoCalcLength::Absolute(v) => v.is_zero(), + NoCalcLength::FontRelative(v) => v.is_zero(), + NoCalcLength::ViewportPercentage(v) => v.is_zero(), + NoCalcLength::ServoCharacterWidth(v) => v.0 == 0, + } + } +} + /// An extension to `NoCalcLength` to parse `calc` expressions. /// This is commonly used for the `<length>` values. /// @@ -841,6 +873,17 @@ impl LengthOrPercentage { } } +impl IsZeroLength for LengthOrPercentage { + #[inline] + fn is_zero_length(&self) -> bool { + match *self { + LengthOrPercentage::Length(l) => l.is_zero_length(), + LengthOrPercentage::Percentage(p) => p.0 == 0.0, + LengthOrPercentage::Calc(_) => false, + } + } +} + /// Either a `<length>`, a `<percentage>`, or the `auto` keyword. #[allow(missing_docs)] #[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)] @@ -1184,7 +1227,7 @@ impl LengthOrNumber { // We try to parse as a Number first because, for cases like // LengthOrNumber, we want "0" to be parsed as a plain Number rather // than a Length (0px); this matches the behaviour of all major browsers - if let Ok(v) = input.r#try(|i| Number::parse_non_negative(context, i)) { + if let Ok(v) = input.try(|i| Number::parse_non_negative(context, i)) { return Ok(Either::Second(v)); } @@ -1228,7 +1271,7 @@ impl MozLength { input: &mut Parser<'i, 't>, allow_quirks: AllowQuirks, ) -> Result<Self, ParseError<'i>> { - if let Ok(l) = input.r#try(ExtremumLength::parse) { + if let Ok(l) = input.try(ExtremumLength::parse) { return Ok(GenericMozLength::ExtremumLength(l)); } @@ -1280,7 +1323,7 @@ impl MaxLength { input: &mut Parser<'i, 't>, allow_quirks: AllowQuirks, ) -> Result<Self, ParseError<'i>> { - if let Ok(l) = input.r#try(ExtremumLength::parse) { + if let Ok(l) = input.try(ExtremumLength::parse) { return Ok(GenericMaxLength::ExtremumLength(l)); } diff --git a/components/style/values/specified/list.rs b/components/style/values/specified/list.rs index a793bf29238..2bdd3c10397 100644 --- a/components/style/values/specified/list.rs +++ b/components/style/values/specified/list.rs @@ -63,7 +63,7 @@ impl Parse for ListStyleType { context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { - if let Ok(style) = input.r#try(|i| CounterStyleOrNone::parse(context, i)) { + if let Ok(style) = input.try(|i| CounterStyleOrNone::parse(context, i)) { return Ok(ListStyleType::CounterStyle(style)); } @@ -97,7 +97,7 @@ impl Parse for Quotes { input: &mut Parser<'i, 't>, ) -> Result<Quotes, ParseError<'i>> { if input - .r#try(|input| input.expect_ident_matching("none")) + .try(|input| input.expect_ident_matching("none")) .is_ok() { return Ok(Quotes(Arc::new(Box::new([])))); diff --git a/components/style/values/specified/mod.rs b/components/style/values/specified/mod.rs index 0fb510543f7..3b7a3d0e04e 100644 --- a/components/style/values/specified/mod.rs +++ b/components/style/values/specified/mod.rs @@ -75,8 +75,8 @@ pub use self::svg::{SVGPaintOrder, SVGStrokeDashArray, SVGWidth}; pub use self::svg_path::SVGPathData; pub use self::table::XSpan; pub use self::text::{InitialLetter, LetterSpacing, LineHeight, MozTabSize, TextAlign}; +pub use self::text::{OverflowWrap, TextEmphasisPosition, TextEmphasisStyle}; pub use self::text::{TextAlignKeyword, TextDecorationLine, TextOverflow, WordSpacing}; -pub use self::text::{TextEmphasisPosition, TextEmphasisStyle}; pub use self::time::Time; pub use self::transform::{Rotate, Scale, Transform}; pub use self::transform::{TransformOrigin, TransformStyle, Translate}; @@ -359,7 +359,7 @@ impl NumberOrPercentage { input: &mut Parser<'i, 't>, type_: AllowedNumericType, ) -> Result<Self, ParseError<'i>> { - if let Ok(per) = input.r#try(|i| Percentage::parse_with_clamping_mode(context, i, type_)) { + if let Ok(per) = input.try(|i| Percentage::parse_with_clamping_mode(context, i, type_)) { return Ok(NumberOrPercentage::Percentage(per)); } @@ -703,7 +703,7 @@ impl ClipRect { allow_quirks: AllowQuirks, ) -> Result<Option<Length>, ParseError<'i>> { if input - .r#try(|input| input.expect_ident_matching("auto")) + .try(|input| input.expect_ident_matching("auto")) .is_ok() { Ok(None) @@ -720,7 +720,7 @@ impl ClipRect { let bottom; let left; - if input.r#try(|input| input.expect_comma()).is_ok() { + if input.try(|input| input.expect_comma()).is_ok() { right = parse_argument(context, input, allow_quirks)?; input.expect_comma()?; bottom = parse_argument(context, input, allow_quirks)?; @@ -751,7 +751,7 @@ impl ClipRectOrAuto { input: &mut Parser<'i, 't>, allow_quirks: AllowQuirks, ) -> Result<Self, ParseError<'i>> { - if let Ok(v) = input.r#try(|i| ClipRect::parse_quirky(context, i, allow_quirks)) { + if let Ok(v) = input.try(|i| ClipRect::parse_quirky(context, i, allow_quirks)) { Ok(Either::First(v)) } else { Auto::parse(context, input).map(Either::Second) @@ -816,8 +816,8 @@ impl Attr { ) -> Result<Attr, ParseError<'i>> { // Syntax is `[namespace? `|`]? ident` // no spaces allowed - let first = input.r#try(|i| i.expect_ident_cloned()).ok(); - if let Ok(token) = input.r#try(|i| i.next_including_whitespace().map(|t| t.clone())) { + let first = input.try(|i| i.expect_ident_cloned()).ok(); + if let Ok(token) = input.try(|i| i.next_including_whitespace().map(|t| t.clone())) { match token { Token::Delim('|') => { let location = input.current_source_location(); diff --git a/components/style/values/specified/motion.rs b/components/style/values/specified/motion.rs index 632b29a45b9..80fb8630f22 100644 --- a/components/style/values/specified/motion.rs +++ b/components/style/values/specified/motion.rs @@ -50,7 +50,7 @@ impl Parse for OffsetPath { input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { // Parse none. - if input.r#try(|i| i.expect_ident_matching("none")).is_ok() { + if input.try(|i| i.expect_ident_matching("none")).is_ok() { return Ok(OffsetPath::none()); } diff --git a/components/style/values/specified/outline.rs b/components/style/values/specified/outline.rs index 46f1acd0b89..890f9dc3020 100644 --- a/components/style/values/specified/outline.rs +++ b/components/style/values/specified/outline.rs @@ -53,7 +53,7 @@ impl Parse for OutlineStyle { _context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result<OutlineStyle, ParseError<'i>> { - if let Ok(border_style) = input.r#try(BorderStyle::parse) { + if let Ok(border_style) = input.try(BorderStyle::parse) { if let BorderStyle::Hidden = border_style { return Err(input .new_custom_error(SelectorParseErrorKind::UnexpectedIdent("hidden".into()))); diff --git a/components/style/values/specified/position.rs b/components/style/values/specified/position.rs index fa14825caed..ef012160726 100644 --- a/components/style/values/specified/position.rs +++ b/components/style/values/specified/position.rs @@ -10,9 +10,8 @@ use crate::hash::FxHashMap; use crate::parser::{Parse, ParserContext}; use crate::str::HTML_SPACE_CHARACTERS; -use crate::values::computed::{ - CalcLengthOrPercentage, LengthOrPercentage as ComputedLengthOrPercentage, -}; +use crate::values::computed::CalcLengthOrPercentage; +use crate::values::computed::LengthOrPercentage as ComputedLengthOrPercentage; use crate::values::computed::{Context, Percentage, ToComputedValue}; use crate::values::generics::position::Position as GenericPosition; use crate::values::generics::position::ZIndex as GenericZIndex; @@ -102,28 +101,28 @@ impl Position { input: &mut Parser<'i, 't>, allow_quirks: AllowQuirks, ) -> Result<Self, ParseError<'i>> { - match input.r#try(|i| PositionComponent::parse_quirky(context, i, allow_quirks)) { + match input.try(|i| PositionComponent::parse_quirky(context, i, allow_quirks)) { Ok(x_pos @ PositionComponent::Center) => { if let Ok(y_pos) = - input.r#try(|i| PositionComponent::parse_quirky(context, i, allow_quirks)) + input.try(|i| PositionComponent::parse_quirky(context, i, allow_quirks)) { return Ok(Self::new(x_pos, y_pos)); } let x_pos = input - .r#try(|i| PositionComponent::parse_quirky(context, i, allow_quirks)) + .try(|i| PositionComponent::parse_quirky(context, i, allow_quirks)) .unwrap_or(x_pos); let y_pos = PositionComponent::Center; return Ok(Self::new(x_pos, y_pos)); }, Ok(PositionComponent::Side(x_keyword, lop)) => { - if input.r#try(|i| i.expect_ident_matching("center")).is_ok() { + if input.try(|i| i.expect_ident_matching("center")).is_ok() { let x_pos = PositionComponent::Side(x_keyword, lop); let y_pos = PositionComponent::Center; return Ok(Self::new(x_pos, y_pos)); } - if let Ok(y_keyword) = input.r#try(Y::parse) { + if let Ok(y_keyword) = input.try(Y::parse) { let y_lop = input - .r#try(|i| LengthOrPercentage::parse_quirky(context, i, allow_quirks)) + .try(|i| LengthOrPercentage::parse_quirky(context, i, allow_quirks)) .ok(); let x_pos = PositionComponent::Side(x_keyword, lop); let y_pos = PositionComponent::Side(y_keyword, y_lop); @@ -134,30 +133,30 @@ impl Position { return Ok(Self::new(x_pos, y_pos)); }, Ok(x_pos @ PositionComponent::Length(_)) => { - if let Ok(y_keyword) = input.r#try(Y::parse) { + if let Ok(y_keyword) = input.try(Y::parse) { let y_pos = PositionComponent::Side(y_keyword, None); return Ok(Self::new(x_pos, y_pos)); } if let Ok(y_lop) = - input.r#try(|i| LengthOrPercentage::parse_quirky(context, i, allow_quirks)) + input.try(|i| LengthOrPercentage::parse_quirky(context, i, allow_quirks)) { let y_pos = PositionComponent::Length(y_lop); return Ok(Self::new(x_pos, y_pos)); } let y_pos = PositionComponent::Center; - let _ = input.r#try(|i| i.expect_ident_matching("center")); + let _ = input.try(|i| i.expect_ident_matching("center")); return Ok(Self::new(x_pos, y_pos)); }, Err(_) => {}, } let y_keyword = Y::parse(input)?; - let lop_and_x_pos: Result<_, ParseError> = input.r#try(|i| { + let lop_and_x_pos: Result<_, ParseError> = input.try(|i| { let y_lop = i - .r#try(|i| LengthOrPercentage::parse_quirky(context, i, allow_quirks)) + .try(|i| LengthOrPercentage::parse_quirky(context, i, allow_quirks)) .ok(); - if let Ok(x_keyword) = i.r#try(X::parse) { + if let Ok(x_keyword) = i.try(X::parse) { let x_lop = i - .r#try(|i| LengthOrPercentage::parse_quirky(context, i, allow_quirks)) + .try(|i| LengthOrPercentage::parse_quirky(context, i, allow_quirks)) .ok(); let x_pos = PositionComponent::Side(x_keyword, x_lop); return Ok((y_lop, x_pos)); @@ -230,16 +229,15 @@ impl<S: Parse> PositionComponent<S> { input: &mut Parser<'i, 't>, allow_quirks: AllowQuirks, ) -> Result<Self, ParseError<'i>> { - if input.r#try(|i| i.expect_ident_matching("center")).is_ok() { + if input.try(|i| i.expect_ident_matching("center")).is_ok() { return Ok(PositionComponent::Center); } - if let Ok(lop) = input.r#try(|i| LengthOrPercentage::parse_quirky(context, i, allow_quirks)) - { + if let Ok(lop) = input.try(|i| LengthOrPercentage::parse_quirky(context, i, allow_quirks)) { return Ok(PositionComponent::Length(lop)); } let keyword = S::parse(context, input)?; let lop = input - .r#try(|i| LengthOrPercentage::parse_quirky(context, i, allow_quirks)) + .try(|i| LengthOrPercentage::parse_quirky(context, i, allow_quirks)) .ok(); Ok(PositionComponent::Side(keyword, lop)) } @@ -360,51 +358,51 @@ impl LegacyPosition { input: &mut Parser<'i, 't>, allow_quirks: AllowQuirks, ) -> Result<Self, ParseError<'i>> { - match input.r#try(|i| OriginComponent::parse(context, i)) { + match input.try(|i| OriginComponent::parse(context, i)) { Ok(x_pos @ OriginComponent::Center) => { - if let Ok(y_pos) = input.r#try(|i| OriginComponent::parse(context, i)) { + if let Ok(y_pos) = input.try(|i| OriginComponent::parse(context, i)) { return Ok(Self::new(x_pos, y_pos)); } let x_pos = input - .r#try(|i| OriginComponent::parse(context, i)) + .try(|i| OriginComponent::parse(context, i)) .unwrap_or(x_pos); let y_pos = OriginComponent::Center; return Ok(Self::new(x_pos, y_pos)); }, Ok(OriginComponent::Side(x_keyword)) => { - if let Ok(y_keyword) = input.r#try(Y::parse) { + if let Ok(y_keyword) = input.try(Y::parse) { let x_pos = OriginComponent::Side(x_keyword); let y_pos = OriginComponent::Side(y_keyword); return Ok(Self::new(x_pos, y_pos)); } let x_pos = OriginComponent::Side(x_keyword); if let Ok(y_lop) = - input.r#try(|i| LengthOrPercentage::parse_quirky(context, i, allow_quirks)) + input.try(|i| LengthOrPercentage::parse_quirky(context, i, allow_quirks)) { return Ok(Self::new(x_pos, OriginComponent::Length(y_lop))); } - let _ = input.r#try(|i| i.expect_ident_matching("center")); + let _ = input.try(|i| i.expect_ident_matching("center")); return Ok(Self::new(x_pos, OriginComponent::Center)); }, Ok(x_pos @ OriginComponent::Length(_)) => { - if let Ok(y_keyword) = input.r#try(Y::parse) { + if let Ok(y_keyword) = input.try(Y::parse) { let y_pos = OriginComponent::Side(y_keyword); return Ok(Self::new(x_pos, y_pos)); } if let Ok(y_lop) = - input.r#try(|i| LengthOrPercentage::parse_quirky(context, i, allow_quirks)) + input.try(|i| LengthOrPercentage::parse_quirky(context, i, allow_quirks)) { let y_pos = OriginComponent::Length(y_lop); return Ok(Self::new(x_pos, y_pos)); } - let _ = input.r#try(|i| i.expect_ident_matching("center")); + let _ = input.try(|i| i.expect_ident_matching("center")); return Ok(Self::new(x_pos, OriginComponent::Center)); }, Err(_) => {}, } let y_keyword = Y::parse(input)?; - let x_pos: Result<_, ParseError> = input.r#try(|i| { - if let Ok(x_keyword) = i.r#try(X::parse) { + let x_pos: Result<_, ParseError> = input.try(|i| { + if let Ok(x_keyword) = i.try(X::parse) { let x_pos = OriginComponent::Side(x_keyword); return Ok(x_pos); } @@ -649,7 +647,7 @@ impl Parse for TemplateAreas { input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { let mut strings = vec![]; - while let Ok(string) = input.r#try(|i| i.expect_string().map(|s| s.as_ref().into())) { + while let Ok(string) = input.try(|i| i.expect_string().map(|s| s.as_ref().into())) { strings.push(string); } @@ -743,7 +741,7 @@ impl Parse for ZIndex { context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { - if input.r#try(|i| i.expect_ident_matching("auto")).is_ok() { + if input.try(|i| i.expect_ident_matching("auto")).is_ok() { return Ok(GenericZIndex::Auto); } Ok(GenericZIndex::Integer(Integer::parse(context, input)?)) diff --git a/components/style/values/specified/source_size_list.rs b/components/style/values/specified/source_size_list.rs index c7a15c3bfb2..9096b53905b 100644 --- a/components/style/values/specified/source_size_list.rs +++ b/components/style/values/specified/source_size_list.rs @@ -92,7 +92,7 @@ impl Parse for SourceSizeOrLength { context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { - if let Ok(size) = input.r#try(|input| SourceSize::parse(context, input)) { + if let Ok(size) = input.try(|input| SourceSize::parse(context, input)) { return Ok(SourceSizeOrLength::SourceSize(size)); } diff --git a/components/style/values/specified/svg.rs b/components/style/values/specified/svg.rs index a09a2236c92..4bdebc6426a 100644 --- a/components/style/values/specified/svg.rs +++ b/components/style/values/specified/svg.rs @@ -8,9 +8,8 @@ use crate::parser::{Parse, ParserContext}; use crate::values::generics::svg as generic; use crate::values::specified::color::Color; use crate::values::specified::url::SpecifiedUrl; -use crate::values::specified::{ - LengthOrPercentage, NonNegativeLengthOrPercentage, NonNegativeNumber, -}; +use crate::values::specified::LengthOrPercentage; +use crate::values::specified::{NonNegativeLengthOrPercentage, NonNegativeNumber}; use crate::values::specified::{Number, Opacity}; use crate::values::CustomIdent; use cssparser::Parser; @@ -63,7 +62,7 @@ impl Parse for SVGLength { input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { input - .r#try(|i| SvgLengthOrPercentageOrNumber::parse(context, i)) + .try(|i| SvgLengthOrPercentageOrNumber::parse(context, i)) .map(Into::into) .or_else(|_| parse_context_value(input, generic::SVGLength::ContextValue)) } @@ -89,7 +88,7 @@ impl Parse for SVGWidth { input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { input - .r#try(|i| NonNegativeSvgLengthOrPercentageOrNumber::parse(context, i)) + .try(|i| NonNegativeSvgLengthOrPercentageOrNumber::parse(context, i)) .map(Into::into) .or_else(|_| parse_context_value(input, generic::SVGLength::ContextValue)) } @@ -109,13 +108,13 @@ impl Parse for SVGStrokeDashArray { context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { - if let Ok(values) = input.r#try(|i| { + if let Ok(values) = input.try(|i| { CommaWithSpace::parse(i, |i| { NonNegativeSvgLengthOrPercentageOrNumber::parse(context, i) }) }) { Ok(generic::SVGStrokeDashArray::Values(values)) - } else if let Ok(_) = input.r#try(|i| i.expect_ident_matching("none")) { + } else if let Ok(_) = input.try(|i| i.expect_ident_matching("none")) { Ok(generic::SVGStrokeDashArray::Values(vec![])) } else { parse_context_value(input, generic::SVGStrokeDashArray::ContextValue) @@ -131,7 +130,7 @@ impl Parse for SVGOpacity { context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { - if let Ok(opacity) = input.r#try(|i| Opacity::parse(context, i)) { + if let Ok(opacity) = input.try(|i| Opacity::parse(context, i)) { return Ok(generic::SVGOpacity::Opacity(opacity)); } @@ -196,7 +195,7 @@ impl Parse for SVGPaintOrder { _context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result<SVGPaintOrder, ParseError<'i>> { - if let Ok(()) = input.r#try(|i| i.expect_ident_matching("normal")) { + if let Ok(()) = input.try(|i| i.expect_ident_matching("normal")) { return Ok(SVGPaintOrder::normal()); } @@ -207,7 +206,7 @@ impl Parse for SVGPaintOrder { let mut pos = 0; loop { - let result: Result<_, ParseError> = input.r#try(|input| { + let result: Result<_, ParseError> = input.try(|input| { try_match_ident_ignore_ascii_case! { input, "fill" => Ok(PaintOrder::Fill), "stroke" => Ok(PaintOrder::Stroke), diff --git a/components/style/values/specified/text.rs b/components/style/values/specified/text.rs index 43106a1083f..5ea323d59d1 100644 --- a/components/style/values/specified/text.rs +++ b/components/style/values/specified/text.rs @@ -15,9 +15,8 @@ use crate::values::generics::text::InitialLetter as GenericInitialLetter; use crate::values::generics::text::LineHeight as GenericLineHeight; use crate::values::generics::text::MozTabSize as GenericMozTabSize; use crate::values::generics::text::Spacing; -use crate::values::specified::length::{ - FontRelativeLength, Length, LengthOrPercentage, NoCalcLength, -}; +use crate::values::specified::length::{FontRelativeLength, Length}; +use crate::values::specified::length::{LengthOrPercentage, NoCalcLength}; use crate::values::specified::length::{NonNegativeLength, NonNegativeLengthOrPercentage}; use crate::values::specified::{AllowQuirks, Integer, NonNegativeNumber, Number}; use cssparser::{Parser, Token}; @@ -45,11 +44,11 @@ impl Parse for InitialLetter { context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { - if input.r#try(|i| i.expect_ident_matching("normal")).is_ok() { + if input.try(|i| i.expect_ident_matching("normal")).is_ok() { return Ok(GenericInitialLetter::Normal); } let size = Number::parse_at_least_one(context, input)?; - let sink = input.r#try(|i| Integer::parse_positive(context, i)).ok(); + let sink = input.try(|i| Integer::parse_positive(context, i)).ok(); Ok(GenericInitialLetter::Specified(size, sink)) } } @@ -81,10 +80,10 @@ impl Parse for LineHeight { context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { - if let Ok(number) = input.r#try(|i| NonNegativeNumber::parse(context, i)) { + if let Ok(number) = input.try(|i| NonNegativeNumber::parse(context, i)) { return Ok(GenericLineHeight::Number(number)); } - if let Ok(nlop) = input.r#try(|i| NonNegativeLengthOrPercentage::parse(context, i)) { + if let Ok(nlop) = input.try(|i| NonNegativeLengthOrPercentage::parse(context, i)) { return Ok(GenericLineHeight::Length(nlop)); } let location = input.current_source_location(); @@ -215,7 +214,7 @@ impl Parse for TextOverflow { ) -> Result<TextOverflow, ParseError<'i>> { let first = TextOverflowSide::parse(context, input)?; let second = input - .r#try(|input| TextOverflowSide::parse(context, input)) + .try(|input| TextOverflowSide::parse(context, input)) .ok(); Ok(TextOverflow { first, second }) } @@ -295,14 +294,14 @@ macro_rules! impl_text_decoration_line { ) -> Result<TextDecorationLine, ParseError<'i>> { let mut result = TextDecorationLine::NONE; if input - .r#try(|input| input.expect_ident_matching("none")) + .try(|input| input.expect_ident_matching("none")) .is_ok() { return Ok(result); } loop { - let result = input.r#try(|input| { + let result = input.try(|input| { let ident = input.expect_ident().map_err(|_| ())?; match_ignore_ascii_case! { ident, $( @@ -380,71 +379,44 @@ impl TextDecorationLine { } } -macro_rules! define_text_align_keyword { - ($( - $(#[$($meta:tt)+])* - $name: ident => $discriminant: expr, - )+) => { - /// Specified value of text-align keyword value. - #[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, Parse, PartialEq, - SpecifiedValueInfo, ToComputedValue, ToCss)] - #[allow(missing_docs)] - pub enum TextAlignKeyword { - $( - $(#[$($meta)+])* - $name = $discriminant, - )+ - } - - impl TextAlignKeyword { - /// Construct a TextAlignKeyword from u32. - pub fn from_u32(discriminant: u32) -> Option<TextAlignKeyword> { - match discriminant { - $( - $discriminant => Some(TextAlignKeyword::$name), - )+ - _ => None - } - } - } - } -} - -// FIXME(emilio): Why reinventing the world? -#[cfg(feature = "gecko")] -define_text_align_keyword! { - Start => 0, - End => 1, - Left => 2, - Right => 3, - Center => 4, - Justify => 5, - MozCenter => 6, - MozLeft => 7, - MozRight => 8, +/// Specified value of text-align keyword value. +#[derive( + Clone, + Copy, + Debug, + Eq, + FromPrimitive, + Hash, + MallocSizeOf, + Parse, + PartialEq, + SpecifiedValueInfo, + ToComputedValue, + ToCss, +)] +#[allow(missing_docs)] +pub enum TextAlignKeyword { + Start, + End, + Left, + Right, + Center, + Justify, + #[cfg(feature = "gecko")] + MozCenter, + #[cfg(feature = "gecko")] + MozLeft, + #[cfg(feature = "gecko")] + MozRight, + #[cfg(feature = "servo")] + ServoCenter, + #[cfg(feature = "servo")] + ServoLeft, + #[cfg(feature = "servo")] + ServoRight, #[css(skip)] - Char => 10, -} - -#[cfg(feature = "servo")] -define_text_align_keyword! { - Start => 0, - End => 1, - Left => 2, - Right => 3, - Center => 4, - Justify => 5, - ServoCenter => 6, - ServoLeft => 7, - ServoRight => 8, -} - -impl TextAlignKeyword { - /// Return the initial value of TextAlignKeyword. - #[inline] - pub fn start() -> TextAlignKeyword { - TextAlignKeyword::Start - } + #[cfg(feature = "gecko")] + Char, } /// Specified value of text-align property. @@ -471,7 +443,7 @@ impl Parse for TextAlign { input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { // MozCenterOrInherit cannot be parsed, only set directly on the elements - if let Ok(key) = input.r#try(TextAlignKeyword::parse) { + if let Ok(key) = input.try(TextAlignKeyword::parse) { return Ok(TextAlign::Keyword(key)); } #[cfg(feature = "gecko")] @@ -510,7 +482,7 @@ impl ToComputedValue for TextAlign { // but we want to set it to right -- instead set it to the default (`start`), // which will do the right thing in this case (but not the general case) if _context.is_root_element { - return TextAlignKeyword::start(); + return TextAlignKeyword::Start; } let parent = _context .builder @@ -661,6 +633,8 @@ impl ToComputedValue for TextEmphasisStyle { fn to_computed_value(&self, context: &Context) -> Self::ComputedValue { match *self { TextEmphasisStyle::Keyword(ref keyword) => { + // FIXME(emilio): This should set the rule_cache_conditions + // properly. let default_shape = if context.style().get_inherited_box().clone_writing_mode() == SpecifiedWritingMode::HorizontalTb { @@ -682,6 +656,7 @@ impl ToComputedValue for TextEmphasisStyle { }, } } + #[inline] fn from_computed_value(computed: &Self::ComputedValue) -> Self { match *computed { @@ -702,22 +677,22 @@ impl Parse for TextEmphasisStyle { input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { if input - .r#try(|input| input.expect_ident_matching("none")) + .try(|input| input.expect_ident_matching("none")) .is_ok() { return Ok(TextEmphasisStyle::None); } - if let Ok(s) = input.r#try(|i| i.expect_string().map(|s| s.as_ref().to_owned())) { + if let Ok(s) = input.try(|i| i.expect_string().map(|s| s.as_ref().to_owned())) { // Handle <string> return Ok(TextEmphasisStyle::String(s)); } // Handle a pair of keywords - let mut shape = input.r#try(TextEmphasisShapeKeyword::parse).ok(); - let fill = input.r#try(TextEmphasisFillMode::parse).ok(); + let mut shape = input.try(TextEmphasisShapeKeyword::parse).ok(); + let fill = input.try(TextEmphasisFillMode::parse).ok(); if shape.is_none() { - shape = input.r#try(TextEmphasisShapeKeyword::parse).ok(); + shape = input.try(TextEmphasisShapeKeyword::parse).ok(); } // At least one of shape or fill must be handled @@ -817,7 +792,7 @@ impl Parse for TextEmphasisPosition { input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { if let Ok(horizontal) = - input.r#try(|input| TextEmphasisHorizontalWritingModeValue::parse(input)) + input.try(|input| TextEmphasisHorizontalWritingModeValue::parse(input)) { let vertical = TextEmphasisVerticalWritingModeValue::parse(input)?; Ok(TextEmphasisPosition(horizontal, vertical)) @@ -869,7 +844,7 @@ impl Parse for MozTabSize { context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { - if let Ok(number) = input.r#try(|i| NonNegativeNumber::parse(context, i)) { + if let Ok(number) = input.try(|i| NonNegativeNumber::parse(context, i)) { // Numbers need to be parsed first because `0` must be recognised // as the number `0` and not the length `0px`. return Ok(GenericMozTabSize::Number(number)); @@ -879,3 +854,24 @@ impl Parse for MozTabSize { )?)) } } + +/// Values for the `overflow-wrap` property. +#[repr(u8)] +#[derive( + Clone, + Copy, + Debug, + Eq, + MallocSizeOf, + Parse, + PartialEq, + SpecifiedValueInfo, + ToComputedValue, + ToCss, +)] +#[allow(missing_docs)] +pub enum OverflowWrap { + Normal, + BreakWord, + Anywhere, +} diff --git a/components/style/values/specified/transform.rs b/components/style/values/specified/transform.rs index 51c38a30ba8..c1ffe202a79 100644 --- a/components/style/values/specified/transform.rs +++ b/components/style/values/specified/transform.rs @@ -38,7 +38,7 @@ impl Transform { use style_traits::{Separator, Space}; if input - .r#try(|input| input.expect_ident_matching("none")) + .try(|input| input.expect_ident_matching("none")) .is_ok() { return Ok(generic::Transform(Vec::new())); @@ -106,7 +106,7 @@ impl Transform { }, "translate" => { let sx = specified::LengthOrPercentage::parse(context, input)?; - if input.r#try(|input| input.expect_comma()).is_ok() { + if input.try(|input| input.expect_comma()).is_ok() { let sy = specified::LengthOrPercentage::parse(context, input)?; Ok(generic::TransformOperation::Translate(sx, Some(sy))) } else { @@ -135,7 +135,7 @@ impl Transform { }, "scale" => { let sx = Number::parse(context, input)?; - if input.r#try(|input| input.expect_comma()).is_ok() { + if input.try(|input| input.expect_comma()).is_ok() { let sy = Number::parse(context, input)?; Ok(generic::TransformOperation::Scale(sx, Some(sy))) } else { @@ -191,7 +191,7 @@ impl Transform { }, "skew" => { let ax = specified::Angle::parse_with_unitless(context, input)?; - if input.r#try(|input| input.expect_comma()).is_ok() { + if input.try(|input| input.expect_comma()).is_ok() { let ay = specified::Angle::parse_with_unitless(context, input)?; Ok(generic::TransformOperation::Skew(ax, Some(ay))) } else { @@ -248,17 +248,17 @@ impl Parse for TransformOrigin { ) -> Result<Self, ParseError<'i>> { let parse_depth = |input: &mut Parser| { input - .r#try(|i| Length::parse(context, i)) + .try(|i| Length::parse(context, i)) .unwrap_or(Length::from_px(0.)) }; - match input.r#try(|i| OriginComponent::parse(context, i)) { + match input.try(|i| OriginComponent::parse(context, i)) { Ok(x_origin @ OriginComponent::Center) => { - if let Ok(y_origin) = input.r#try(|i| OriginComponent::parse(context, i)) { + if let Ok(y_origin) = input.try(|i| OriginComponent::parse(context, i)) { let depth = parse_depth(input); return Ok(Self::new(x_origin, y_origin, depth)); } let y_origin = OriginComponent::Center; - if let Ok(x_keyword) = input.r#try(X::parse) { + if let Ok(x_keyword) = input.try(X::parse) { let x_origin = OriginComponent::Side(x_keyword); let depth = parse_depth(input); return Ok(Self::new(x_origin, y_origin, depth)); @@ -267,7 +267,7 @@ impl Parse for TransformOrigin { return Ok(Self::new(x_origin, y_origin, depth)); }, Ok(x_origin) => { - if let Ok(y_origin) = input.r#try(|i| OriginComponent::parse(context, i)) { + if let Ok(y_origin) = input.try(|i| OriginComponent::parse(context, i)) { let depth = parse_depth(input); return Ok(Self::new(x_origin, y_origin, depth)); } @@ -279,12 +279,12 @@ impl Parse for TransformOrigin { } let y_keyword = Y::parse(input)?; let y_origin = OriginComponent::Side(y_keyword); - if let Ok(x_keyword) = input.r#try(X::parse) { + if let Ok(x_keyword) = input.try(X::parse) { let x_origin = OriginComponent::Side(x_keyword); let depth = parse_depth(input); return Ok(Self::new(x_origin, y_origin, depth)); } - if input.r#try(|i| i.expect_ident_matching("center")).is_ok() { + if input.try(|i| i.expect_ident_matching("center")).is_ok() { let x_origin = OriginComponent::Center; let depth = parse_depth(input); return Ok(Self::new(x_origin, y_origin, depth)); @@ -303,10 +303,10 @@ where context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { - if input.r#try(|i| i.expect_ident_matching("center")).is_ok() { + if input.try(|i| i.expect_ident_matching("center")).is_ok() { return Ok(OriginComponent::Center); } - if let Ok(lop) = input.r#try(|i| LengthOrPercentage::parse(context, i)) { + if let Ok(lop) = input.try(|i| LengthOrPercentage::parse(context, i)) { return Ok(OriginComponent::Length(lop)); } let keyword = S::parse(context, input)?; @@ -353,11 +353,11 @@ impl Parse for Rotate { context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { - if input.r#try(|i| i.expect_ident_matching("none")).is_ok() { + if input.try(|i| i.expect_ident_matching("none")).is_ok() { return Ok(generic::Rotate::None); } - if let Ok(rx) = input.r#try(|i| Number::parse(context, i)) { + if let Ok(rx) = input.try(|i| Number::parse(context, i)) { // 'rotate: <number>{3} <angle>' let ry = Number::parse(context, input)?; let rz = Number::parse(context, input)?; @@ -379,13 +379,13 @@ impl Parse for Translate { context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { - if input.r#try(|i| i.expect_ident_matching("none")).is_ok() { + if input.try(|i| i.expect_ident_matching("none")).is_ok() { return Ok(generic::Translate::None); } let tx = specified::LengthOrPercentage::parse(context, input)?; - if let Ok(ty) = input.r#try(|i| specified::LengthOrPercentage::parse(context, i)) { - if let Ok(tz) = input.r#try(|i| specified::Length::parse(context, i)) { + if let Ok(ty) = input.try(|i| specified::LengthOrPercentage::parse(context, i)) { + if let Ok(tz) = input.try(|i| specified::Length::parse(context, i)) { // 'translate: <length-percentage> <length-percentage> <length>' return Ok(generic::Translate::Translate3D(tx, ty, tz)); } @@ -395,7 +395,10 @@ impl Parse for Translate { } // 'translate: <length-percentage> ' - Ok(generic::Translate::TranslateX(tx)) + Ok(generic::Translate::Translate( + tx, + specified::LengthOrPercentage::zero(), + )) } } @@ -407,13 +410,13 @@ impl Parse for Scale { context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { - if input.r#try(|i| i.expect_ident_matching("none")).is_ok() { + if input.try(|i| i.expect_ident_matching("none")).is_ok() { return Ok(generic::Scale::None); } let sx = Number::parse(context, input)?; - if let Ok(sy) = input.r#try(|i| Number::parse(context, i)) { - if let Ok(sz) = input.r#try(|i| Number::parse(context, i)) { + if let Ok(sy) = input.try(|i| Number::parse(context, i)) { + if let Ok(sz) = input.try(|i| Number::parse(context, i)) { // 'scale: <number> <number> <number>' return Ok(generic::Scale::Scale3D(sx, sy, sz)); } diff --git a/components/style/values/specified/ui.rs b/components/style/values/specified/ui.rs index e3ea599aa4c..5adfcaa7f70 100644 --- a/components/style/values/specified/ui.rs +++ b/components/style/values/specified/ui.rs @@ -32,7 +32,7 @@ impl Parse for Cursor { ) -> Result<Self, ParseError<'i>> { let mut images = vec![]; loop { - match input.r#try(|input| CursorImage::parse(context, input)) { + match input.try(|input| CursorImage::parse(context, input)) { Ok(image) => images.push(image), Err(_) => break, } @@ -64,7 +64,7 @@ impl Parse for CursorImage { ) -> Result<Self, ParseError<'i>> { Ok(Self { url: SpecifiedImageUrl::parse(context, input)?, - hotspot: match input.r#try(|input| Number::parse(context, input)) { + hotspot: match input.try(|input| Number::parse(context, input)) { Ok(number) => Some((number, Number::parse(context, input)?)), Err(_) => None, }, @@ -131,7 +131,7 @@ impl Parse for ScrollbarColor { context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { - if input.r#try(|i| i.expect_ident_matching("auto")).is_ok() { + if input.try(|i| i.expect_ident_matching("auto")).is_ok() { return Ok(generics::ScrollbarColor::Auto); } Ok(generics::ScrollbarColor::Colors { diff --git a/components/style_traits/values.rs b/components/style_traits/values.rs index 575bf5183d9..0fe3ba767c6 100644 --- a/components/style_traits/values.rs +++ b/components/style_traits/values.rs @@ -324,7 +324,7 @@ impl Separator for Space { let mut results = vec![parse_one(input)?]; loop { input.skip_whitespace(); // Unnecessary for correctness, but may help try() rewind less. - if let Ok(item) = input.r#try(&mut parse_one) { + if let Ok(item) = input.try(&mut parse_one) { results.push(item); } else { return Ok(results); @@ -350,9 +350,9 @@ impl Separator for CommaWithSpace { loop { input.skip_whitespace(); // Unnecessary for correctness, but may help try() rewind less. let comma_location = input.current_source_location(); - let comma = input.r#try(|i| i.expect_comma()).is_ok(); + let comma = input.try(|i| i.expect_comma()).is_ok(); input.skip_whitespace(); // Unnecessary for correctness, but may help try() rewind less. - if let Ok(item) = input.r#try(&mut parse_one) { + if let Ok(item) = input.try(&mut parse_one) { results.push(item); } else if comma { return Err(comma_location.new_unexpected_token_error(Token::Comma)); |