diff --git a/components/style/properties/data.py b/components/style/properties/data.py index ac7f9e427f7..1d46ff9481b 100644 --- a/components/style/properties/data.py +++ b/components/style/properties/data.py @@ -149,6 +149,7 @@ class Longhand(object): predefined_type=None, servo_pref=None, gecko_pref=None, enabled_in="content", need_index=False, gecko_ffi_name=None, + is_gecko_size_type_hack=False, allowed_in_keyframe_block=True, cast_type='u8', logical=False, alias=None, extra_prefixes=None, boxed=False, flags=None, allowed_in_page_rule=False, allow_quirks=False, ignored_when_colors_disabled=False, @@ -185,6 +186,7 @@ class Longhand(object): self.allow_quirks = allow_quirks self.ignored_when_colors_disabled = ignored_when_colors_disabled self.is_vector = vector + self.is_gecko_size_type_hack = is_gecko_size_type_hack # https://drafts.csswg.org/css-animations/#keyframes # > The inside of accepts any CSS property diff --git a/components/style/properties/declaration_block.rs b/components/style/properties/declaration_block.rs index 284c8230b5d..8612c1244c3 100644 --- a/components/style/properties/declaration_block.rs +++ b/components/style/properties/declaration_block.rs @@ -430,7 +430,9 @@ impl PropertyDeclarationBlock { AllShorthand::NotSet => {} AllShorthand::CSSWideKeyword(keyword) => { for &id in ShorthandId::All.longhands() { - let decl = PropertyDeclaration::CSSWideKeyword(id, keyword); + let decl = PropertyDeclaration::CSSWideKeyword( + WideKeywordDeclaration { id, keyword }, + ); changed |= self.push( decl, importance, @@ -440,7 +442,9 @@ impl PropertyDeclarationBlock { } AllShorthand::WithVariables(unparsed) => { for &id in ShorthandId::All.longhands() { - let decl = PropertyDeclaration::WithVariables(id, unparsed.clone()); + let decl = PropertyDeclaration::WithVariables( + VariableDeclaration { id, value: unparsed.clone() }, + ); changed |= self.push( decl, importance, @@ -639,14 +643,15 @@ impl PropertyDeclarationBlock { // in Gecko's getKeyframes() implementation for CSS animations, if // |computed_values| is supplied, we use it to expand such variable // declarations. This will be fixed properly in Gecko bug 1391537. - (&PropertyDeclaration::WithVariables(id, ref unparsed), - Some(ref _computed_values)) => { - unparsed.substitute_variables( - id, + ( + &PropertyDeclaration::WithVariables(ref declaration), + Some(ref _computed_values), + ) => { + declaration.value.substitute_variables( + declaration.id, custom_properties.as_ref(), QuirksMode::NoQuirks, - ) - .to_css(dest) + ).to_css(dest) }, (ref d, _) => d.to_css(dest), } @@ -726,8 +731,8 @@ impl PropertyDeclarationBlock { let mut builder = CustomPropertiesBuilder::new(inherited_custom_properties); for declaration in self.normal_declaration_iter() { - if let PropertyDeclaration::Custom(ref name, ref value) = *declaration { - builder.cascade(name, value.borrow()); + if let PropertyDeclaration::Custom(ref declaration) = *declaration { + builder.cascade(&declaration.name, declaration.value.borrow()); } } diff --git a/components/style/properties/helpers.mako.rs b/components/style/properties/helpers.mako.rs index af6d978657d..cfb7fbbfa45 100644 --- a/components/style/properties/helpers.mako.rs +++ b/components/style/properties/helpers.mako.rs @@ -302,9 +302,9 @@ PropertyDeclaration::${property.camel_case}(ref value) => { DeclaredValue::Value(value) }, - PropertyDeclaration::CSSWideKeyword(id, value) => { - debug_assert!(id == LonghandId::${property.camel_case}); - DeclaredValue::CSSWideKeyword(value) + PropertyDeclaration::CSSWideKeyword(ref declaration) => { + debug_assert!(declaration.id == LonghandId::${property.camel_case}); + DeclaredValue::CSSWideKeyword(declaration.keyword) }, PropertyDeclaration::WithVariables(..) => { panic!("variables should already have been substituted") @@ -903,6 +903,7 @@ <%call expr="longhand(name, predefined_type=length_type, logical=logical, + is_gecko_size_type_hack=True, **kwargs)"> % if not logical: use values::specified::AllowQuirks; diff --git a/components/style/properties/helpers/animated_properties.mako.rs b/components/style/properties/helpers/animated_properties.mako.rs index a6d6d4e7a2e..feda388935b 100644 --- a/components/style/properties/helpers/animated_properties.mako.rs +++ b/components/style/properties/helpers/animated_properties.mako.rs @@ -435,14 +435,14 @@ impl AnimationValue { }, % endif % endfor - PropertyDeclaration::CSSWideKeyword(id, keyword) => { - match id { + PropertyDeclaration::CSSWideKeyword(ref declaration) => { + match declaration.id { // We put all the animatable properties first in the hopes // that it might increase match locality. % for prop in data.longhands: % if prop.animatable: LonghandId::${prop.camel_case} => { - let style_struct = match keyword { + let style_struct = match declaration.keyword { % if not prop.style_struct.inherited: CSSWideKeyword::Unset | % endif @@ -472,15 +472,15 @@ impl AnimationValue { % endfor } }, - PropertyDeclaration::WithVariables(id, ref unparsed) => { + PropertyDeclaration::WithVariables(ref declaration) => { let substituted = { let custom_properties = extra_custom_properties.or_else(|| context.style().custom_properties()); - unparsed.substitute_variables( - id, + declaration.value.substitute_variables( + declaration.id, custom_properties, - context.quirks_mode + context.quirks_mode, ) }; return AnimationValue::from_declaration( diff --git a/components/style/properties/properties.mako.rs b/components/style/properties/properties.mako.rs index 9f610fc3964..78c3865b999 100644 --- a/components/style/properties/properties.mako.rs +++ b/components/style/properties/properties.mako.rs @@ -1074,7 +1074,10 @@ impl UnparsedValue { } else { CSSWideKeyword::Initial }; - PropertyDeclaration::CSSWideKeyword(longhand_id, keyword) + PropertyDeclaration::CSSWideKeyword(WideKeywordDeclaration { + id: longhand_id, + keyword, + }) }) } } @@ -1443,33 +1446,51 @@ impl PropertyId { #[derive(Clone, PartialEq)] pub enum PropertyDeclaration { % for property in data.longhands: - /// ${property.name} <% - if property.predefined_type and not property.is_vector: + if property.predefined_type and not property.is_vector and not property.is_gecko_size_type_hack: ty = "::values::specified::{}".format(property.predefined_type) else: ty = "longhands::{}::SpecifiedValue".format(property.ident) if property.boxed: ty = "Box<{}>".format(ty) %> + /// ${property.name} ${property.camel_case}(${ty}), % endfor /// A css-wide keyword. - CSSWideKeyword(LonghandId, CSSWideKeyword), - /// An unparsed value that contains `var()` functions. - WithVariables( - LonghandId, - #[cfg_attr(feature = "gecko", ignore_malloc_size_of = "XXX: how to handle this?")] - Arc - ), - /// A custom property declaration, with the property name and the declared - /// value. + CSSWideKeyword(WideKeywordDeclaration), + /// An unparsed declaration. + WithVariables(VariableDeclaration), + /// A custom property declaration. + Custom(CustomDeclaration), +} + +/// A declaration using a CSS-wide keyword. +#[cfg_attr(feature = "gecko", derive(MallocSizeOf))] +#[derive(Clone, PartialEq)] +pub struct WideKeywordDeclaration { + id: LonghandId, + keyword: CSSWideKeyword, +} + +/// An unparsed declaration that contains `var()` functions. +#[cfg_attr(feature = "gecko", derive(MallocSizeOf))] +#[derive(Clone, PartialEq)] +pub struct VariableDeclaration { + id: LonghandId, #[cfg_attr(feature = "gecko", ignore_malloc_size_of = "XXX: how to handle this?")] - Custom( - ::custom_properties::Name, - #[cfg_attr(feature = "gecko", ignore_malloc_size_of = "XXX: how to handle this?")] - DeclaredValueOwned> - ), + value: Arc, +} + +/// A custom property declaration with the property name and the declared value. +#[cfg_attr(feature = "gecko", derive(MallocSizeOf))] +#[derive(Clone, PartialEq)] +pub struct CustomDeclaration { + /// The name of the custom property. + pub name: ::custom_properties::Name, + /// The value of the custom property. + #[cfg_attr(feature = "gecko", ignore_malloc_size_of = "XXX: how to handle this?")] + pub value: DeclaredValueOwned>, } impl fmt::Debug for PropertyDeclaration { @@ -1497,24 +1518,24 @@ impl PropertyDeclaration { value.to_css(&mut CssWriter::new(dest)) } % endfor - PropertyDeclaration::CSSWideKeyword(_, keyword) => { - keyword.to_css(&mut CssWriter::new(dest)) + PropertyDeclaration::CSSWideKeyword(ref declaration) => { + declaration.keyword.to_css(&mut CssWriter::new(dest)) }, - PropertyDeclaration::WithVariables(_, ref with_variables) => { + PropertyDeclaration::WithVariables(ref declaration) => { // https://drafts.csswg.org/css-variables/#variables-in-shorthands - match with_variables.from_shorthand { + match declaration.value.from_shorthand { // Normally, we shouldn't be printing variables here if they came from // shorthands. But we should allow properties that came from shorthand // aliases. That also matches with the Gecko behavior. Some(shorthand) if shorthand.flags().contains(PropertyFlags::SHORTHAND_ALIAS_PROPERTY) => - dest.write_str(&*with_variables.css)?, - None => dest.write_str(&*with_variables.css)?, + dest.write_str(&*declaration.value.css)?, + None => dest.write_str(&*declaration.value.css)?, _ => {}, } Ok(()) }, - PropertyDeclaration::Custom(_, ref value) => { - value.borrow().to_css(&mut CssWriter::new(dest)) + PropertyDeclaration::Custom(ref declaration) => { + declaration.value.borrow().to_css(&mut CssWriter::new(dest)) }, } } @@ -1524,12 +1545,14 @@ impl PropertyDeclaration { /// Given a property declaration, return the property declaration id. pub fn id(&self) -> PropertyDeclarationId { match *self { - PropertyDeclaration::Custom(ref name, _) => { - return PropertyDeclarationId::Custom(name) + PropertyDeclaration::Custom(ref declaration) => { + return PropertyDeclarationId::Custom(&declaration.name) } - PropertyDeclaration::CSSWideKeyword(id, _) | - PropertyDeclaration::WithVariables(id, _) => { - return PropertyDeclarationId::Longhand(id) + PropertyDeclaration::CSSWideKeyword(ref declaration) => { + return PropertyDeclarationId::Longhand(declaration.id); + } + PropertyDeclaration::WithVariables(ref declaration) => { + return PropertyDeclarationId::Longhand(declaration.id); } _ => {} } @@ -1554,10 +1577,10 @@ impl PropertyDeclaration { fn with_variables_from_shorthand(&self, shorthand: ShorthandId) -> Option< &str> { match *self { - PropertyDeclaration::WithVariables(_, ref with_variables) => { - if let Some(s) = with_variables.from_shorthand { + PropertyDeclaration::WithVariables(ref declaration) => { + if let Some(s) = declaration.value.from_shorthand { if s == shorthand { - Some(&*with_variables.css) + Some(&*declaration.value.css) } else { None } } else { // Normally, longhand property that doesn't come from a shorthand @@ -1565,7 +1588,7 @@ impl PropertyDeclaration { // came from a shorthand alias. Because for example, we should be able to // get -moz-transform's value from transform. if shorthand.flags().contains(PropertyFlags::SHORTHAND_ALIAS_PROPERTY) { - return Some(&*with_variables.css); + return Some(&*declaration.value.css); } None } @@ -1577,7 +1600,9 @@ impl PropertyDeclaration { /// Returns a CSS-wide keyword if the declaration's value is one. pub fn get_css_wide_keyword(&self) -> Option { match *self { - PropertyDeclaration::CSSWideKeyword(_, keyword) => Some(keyword), + PropertyDeclaration::CSSWideKeyword(ref declaration) => { + Some(declaration.keyword) + }, _ => None, } } @@ -1640,8 +1665,8 @@ impl PropertyDeclaration { pub fn value_is_unparsed(&self) -> bool { match *self { PropertyDeclaration::WithVariables(..) => true, - PropertyDeclaration::Custom(_, ref value) => { - !matches!(value.borrow(), DeclaredValue::CSSWideKeyword(..)) + PropertyDeclaration::Custom(ref declaration) => { + !matches!(declaration.value.borrow(), DeclaredValue::CSSWideKeyword(..)) } _ => false, } @@ -1667,7 +1692,7 @@ impl PropertyDeclaration { /// Returns true if this property is a custom property, false /// otherwise. pub fn is_custom(&self) -> bool { - matches!(*self, PropertyDeclaration::Custom(_, _)) + matches!(*self, PropertyDeclaration::Custom(..)) } /// The `context` parameter controls this: @@ -1708,14 +1733,19 @@ impl PropertyDeclaration { Err(e) => return Err(StyleParseErrorKind::new_invalid(name, e)), } }; - declarations.push(PropertyDeclaration::Custom(property_name, value)); + declarations.push(PropertyDeclaration::Custom(CustomDeclaration { + name: property_name, + value, + })); Ok(()) } PropertyId::LonghandAlias(id, _) | PropertyId::Longhand(id) => { input.skip_whitespace(); // Unnecessary for correctness, but may help try() rewind less. input.try(|i| CSSWideKeyword::parse(i)).map(|keyword| { - PropertyDeclaration::CSSWideKeyword(id, keyword) + PropertyDeclaration::CSSWideKeyword( + WideKeywordDeclaration { id, keyword }, + ) }).or_else(|()| { input.look_for_var_functions(); input.parse_entirely(|input| id.parse_value(context, input)) @@ -1727,12 +1757,15 @@ impl PropertyDeclaration { ::custom_properties::parse_non_custom_with_var(input).map_err(|e| { StyleParseErrorKind::new_invalid(name, e) })?; - Ok(PropertyDeclaration::WithVariables(id, Arc::new(UnparsedValue { + Ok(PropertyDeclaration::WithVariables(VariableDeclaration { + id, + value: Arc::new(UnparsedValue { css: css.into_owned(), first_token_type: first_token_type, url_data: context.url_data.clone(), from_shorthand: None, - }))) + }), + })) } else { Err(StyleParseErrorKind::new_invalid(name, err)) } @@ -1749,7 +1782,12 @@ impl PropertyDeclaration { declarations.all_shorthand = AllShorthand::CSSWideKeyword(keyword) } else { for &longhand in id.longhands() { - declarations.push(PropertyDeclaration::CSSWideKeyword(longhand, keyword)) + declarations.push(PropertyDeclaration::CSSWideKeyword( + WideKeywordDeclaration { + id: longhand, + keyword, + }, + )) } } Ok(()) @@ -1774,9 +1812,12 @@ impl PropertyDeclaration { if id == ShorthandId::All { declarations.all_shorthand = AllShorthand::WithVariables(unparsed) } else { - for &longhand in id.longhands() { + for &id in id.longhands() { declarations.push( - PropertyDeclaration::WithVariables(longhand, unparsed.clone()) + PropertyDeclaration::WithVariables(VariableDeclaration { + id, + value: unparsed.clone(), + }) ) } } @@ -3283,8 +3324,8 @@ where CustomPropertiesBuilder::new(inherited_style.custom_properties()); for (declaration, _cascade_level) in iter_declarations() { - if let PropertyDeclaration::Custom(ref name, ref value) = *declaration { - builder.cascade(name, value.borrow()); + if let PropertyDeclaration::Custom(ref declaration) = *declaration { + builder.cascade(&declaration.name, declaration.value.borrow()); } } @@ -3372,13 +3413,13 @@ where } let mut declaration = match *declaration { - PropertyDeclaration::WithVariables(id, ref unparsed) => { - if !id.inherited() { + PropertyDeclaration::WithVariables(ref declaration) => { + if !declaration.id.inherited() { context.rule_cache_conditions.borrow_mut() .set_uncacheable(); } - Cow::Owned(unparsed.substitute_variables( - id, + Cow::Owned(declaration.value.substitute_variables( + declaration.id, context.builder.custom_properties.as_ref(), context.quirks_mode )) @@ -3537,8 +3578,10 @@ where seen.contains(LonghandId::MozMinFontSizeRatio) || font_family.is_some() { let discriminant = LonghandId::FontSize as usize; - let size = PropertyDeclaration::CSSWideKeyword( - LonghandId::FontSize, CSSWideKeyword::Inherit); + let size = PropertyDeclaration::CSSWideKeyword(WideKeywordDeclaration { + id: LonghandId::FontSize, + keyword: CSSWideKeyword::Inherit, + }); (CASCADE_PROPERTY[discriminant])(&size, &mut context); % endif diff --git a/tests/unit/style/stylesheets.rs b/tests/unit/style/stylesheets.rs index 30e20aea8dd..de12d6c763d 100644 --- a/tests/unit/style/stylesheets.rs +++ b/tests/unit/style/stylesheets.rs @@ -18,9 +18,9 @@ use std::sync::atomic::AtomicBool; use style::context::QuirksMode; use style::error_reporting::{ParseErrorReporter, ContextualParseError}; use style::media_queries::MediaList; -use style::properties::Importance; -use style::properties::{CSSWideKeyword, DeclaredValueOwned, PropertyDeclaration, PropertyDeclarationBlock}; -use style::properties::DeclarationSource; +use style::properties::{CSSWideKeyword, CustomDeclaration, DeclarationSource}; +use style::properties::{DeclaredValueOwned, Importance}; +use style::properties::{PropertyDeclaration, PropertyDeclarationBlock}; use style::properties::longhands::{self, animation_timing_function}; use style::shared_lock::SharedRwLock; use style::stylesheets::{Origin, Namespaces}; @@ -108,11 +108,17 @@ fn test_parse_stylesheet() { ), (0 << 20) + (1 << 10) + (1 << 0)) )), block: Arc::new(stylesheet.shared_lock.wrap(block_from(vec![ - (PropertyDeclaration::Display(longhands::display::SpecifiedValue::None), - Importance::Important), - (PropertyDeclaration::Custom(Atom::from("a"), - DeclaredValueOwned::CSSWideKeyword(CSSWideKeyword::Inherit)), - Importance::Important), + ( + PropertyDeclaration::Display(longhands::display::SpecifiedValue::None), + Importance::Important, + ), + ( + PropertyDeclaration::Custom(CustomDeclaration { + name: Atom::from("a"), + value: DeclaredValueOwned::CSSWideKeyword(CSSWideKeyword::Inherit), + }), + Importance::Important, + ), ]))), source_location: SourceLocation { line: 3,