servo: Merge #19682 - style: Move contain outside of mako (from stevel98:moveContain); r=emilio
authorlizhixun <lizhixun@berkeley.edu>
Thu, 04 Jan 2018 04:28:23 -0600
changeset 449593 0bf62601f709d0619e221f3229f148ffc2cc061b
parent 449592 2cda01d56646008ab350a027bd92b4c35af69127
child 449594 da52ff7129ad5c91aedc1f81a0a916aece58e361
push id8527
push userCallek@gmail.com
push dateThu, 11 Jan 2018 21:05:50 +0000
treeherdermozilla-beta@95342d212a7a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersemilio
milestone59.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
servo: Merge #19682 - style: Move contain outside of mako (from stevel98:moveContain); r=emilio <!-- Please describe your changes on the following line: --> Sub-PR for #19015. --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [X] `./mach build -d` does not report any errors - [X] `./mach test-tidy` does not report any errors - [X] These changes fix #19656 (github issue number if applicable). <!-- Either: --> - [ ] There are tests for these changes OR - [X] These changes do not require tests because refactoring <!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.--> <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> Source-Repo: https://github.com/servo/servo Source-Revision: 7a9f99eda881d500ea344382d02037bfd11789da
servo/components/style/properties/longhand/box.mako.rs
servo/components/style/values/computed/box.rs
servo/components/style/values/computed/mod.rs
servo/components/style/values/specified/box.rs
servo/components/style/values/specified/mod.rs
--- a/servo/components/style/properties/longhand/box.mako.rs
+++ b/servo/components/style/properties/longhand/box.mako.rs
@@ -538,110 +538,24 @@
                           "TransformOrigin",
                           "computed::TransformOrigin::initial_value()",
                           animation_value_type="ComputedValue",
                           extra_prefixes="moz webkit",
                           gecko_ffi_name="mTransformOrigin",
                           boxed=True,
                           spec="https://drafts.csswg.org/css-transforms/#transform-origin-property")}
 
-// FIXME: `size` and `content` values are not implemented and `strict` is implemented
-// like `content`(layout style paint) in gecko. We should implement `size` and `content`,
-// also update the glue once they are implemented in gecko.
-<%helpers:longhand name="contain" animation_value_type="discrete" products="gecko"
-                   flags="FIXPOS_CB"
-                   gecko_pref="layout.css.contain.enabled",
-                   spec="https://drafts.csswg.org/css-contain/#contain-property">
-    use std::fmt;
-    use style_traits::ToCss;
-
-    pub mod computed_value {
-        pub type T = super::SpecifiedValue;
-    }
-
-    bitflags! {
-        #[derive(MallocSizeOf, ToComputedValue)]
-        pub struct SpecifiedValue: u8 {
-            const LAYOUT = 0x01;
-            const STYLE = 0x02;
-            const PAINT = 0x04;
-            const STRICT = 0x8;
-            const STRICT_BITS = SpecifiedValue::LAYOUT.bits | SpecifiedValue::STYLE.bits | SpecifiedValue::PAINT.bits;
-        }
-    }
-
-    impl ToCss for SpecifiedValue {
-        fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
-            if self.is_empty() {
-                return dest.write_str("none")
-            }
-            if self.contains(SpecifiedValue::STRICT) {
-                return dest.write_str("strict")
-            }
-
-            let mut has_any = false;
-            macro_rules! maybe_write_value {
-                ($ident:path => $str:expr) => {
-                    if self.contains($ident) {
-                        if has_any {
-                            dest.write_str(" ")?;
-                        }
-                        has_any = true;
-                        dest.write_str($str)?;
-                    }
-                }
-            }
-            maybe_write_value!(SpecifiedValue::LAYOUT => "layout");
-            maybe_write_value!(SpecifiedValue::STYLE => "style");
-            maybe_write_value!(SpecifiedValue::PAINT => "paint");
-
-            debug_assert!(has_any);
-            Ok(())
-        }
-    }
-
-    #[inline]
-    pub fn get_initial_value() -> computed_value::T {
-        computed_value::T::empty()
-    }
-
-    /// none | strict | content | [ size || layout || style || paint ]
-    pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
-                         -> Result<SpecifiedValue, ParseError<'i>> {
-        let mut result = SpecifiedValue::empty();
-
-        if input.try(|input| input.expect_ident_matching("none")).is_ok() {
-            return Ok(result)
-        }
-        if input.try(|input| input.expect_ident_matching("strict")).is_ok() {
-            result.insert(SpecifiedValue::STRICT | SpecifiedValue::STRICT_BITS);
-            return Ok(result)
-        }
-
-        while let Ok(name) = input.try(|i| i.expect_ident_cloned()) {
-            let flag = match_ignore_ascii_case! { &name,
-                "layout" => Some(SpecifiedValue::LAYOUT),
-                "style" => Some(SpecifiedValue::STYLE),
-                "paint" => Some(SpecifiedValue::PAINT),
-                _ => None
-            };
-            let flag = match flag {
-                Some(flag) if !result.contains(flag) => flag,
-                _ => return Err(input.new_custom_error(SelectorParseErrorKind::UnexpectedIdent(name.clone())))
-            };
-            result.insert(flag);
-        }
-
-        if !result.is_empty() {
-            Ok(result)
-        } else {
-            Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
-        }
-    }
-</%helpers:longhand>
+${helpers.predefined_type("contain",
+                          "Contain",
+                          "specified::Contain::empty()",
+                          animation_value_type="discrete",
+                          products="gecko",
+                          flags="FIXPOS_CB",
+                          gecko_pref="layout.css.contain.enabled",
+                          spec="https://drafts.csswg.org/css-contain/#contain-property")}
 
 // Non-standard
 ${helpers.single_keyword("-moz-appearance",
                          """none button button-arrow-down button-arrow-next button-arrow-previous button-arrow-up
                             button-bevel button-focus caret checkbox checkbox-container checkbox-label checkmenuitem
                             dialog dualbutton groupbox inner-spin-button listbox listitem menuarrow menubar menucheckbox
                             menuimage menuitem menuitemtext menulist menulist-button menulist-text menulist-textfield
                             menupopup menuradio menuseparator meterbar meterchunk number-input progressbar
--- a/servo/components/style/values/computed/box.rs
+++ b/servo/components/style/values/computed/box.rs
@@ -4,17 +4,17 @@
 
 //! Computed types for box properties.
 
 use values::computed::Number;
 use values::computed::length::LengthOrPercentage;
 use values::generics::box_::AnimationIterationCount as GenericAnimationIterationCount;
 use values::generics::box_::VerticalAlign as GenericVerticalAlign;
 
-pub use values::specified::box_::{AnimationName, Display, OverflowClipBox};
+pub use values::specified::box_::{AnimationName, Display, OverflowClipBox, Contain};
 pub use values::specified::box_::{OverscrollBehavior, ScrollSnapType, TouchAction, WillChange};
 
 /// A computed value for the `vertical-align` property.
 pub type VerticalAlign = GenericVerticalAlign<LengthOrPercentage>;
 
 /// A computed value for the `animation-iteration-count` property.
 pub type AnimationIterationCount = GenericAnimationIterationCount<Number>;
 
--- a/servo/components/style/values/computed/mod.rs
+++ b/servo/components/style/values/computed/mod.rs
@@ -35,17 +35,17 @@ pub use self::align::{AlignItems, AlignJ
 pub use self::angle::Angle;
 pub use self::background::{BackgroundSize, BackgroundRepeat};
 pub use self::border::{BorderImageSlice, BorderImageWidth, BorderImageSideWidth};
 pub use self::border::{BorderRadius, BorderCornerRadius, BorderSpacing};
 pub use self::font::{FontSize, FontSizeAdjust, FontSynthesis, FontWeight, FontVariantAlternates};
 pub use self::font::{FontFamily, FontLanguageOverride, FontVariantSettings, FontVariantEastAsian};
 pub use self::font::{FontVariantLigatures, FontVariantNumeric, FontFeatureSettings};
 pub use self::font::{MozScriptLevel, MozScriptMinSize, MozScriptSizeMultiplier, XTextZoom, XLang};
-pub use self::box_::{AnimationIterationCount, AnimationName, Display, OverscrollBehavior};
+pub use self::box_::{AnimationIterationCount, AnimationName, Display, OverscrollBehavior, Contain};
 pub use self::box_::{OverflowClipBox, ScrollSnapType, TouchAction, VerticalAlign, WillChange};
 pub use self::color::{Color, ColorPropertyValue, RGBAColor};
 pub use self::effects::{BoxShadow, Filter, SimpleShadow};
 pub use self::flex::FlexBasis;
 pub use self::image::{Gradient, GradientItem, Image, ImageLayer, LineDirection, MozImageRect};
 #[cfg(feature = "gecko")]
 pub use self::gecko::ScrollSnapPoint;
 pub use self::rect::LengthOrNumberRect;
--- a/servo/components/style/values/specified/box.rs
+++ b/servo/components/style/values/specified/box.rs
@@ -4,18 +4,19 @@
 
 //! Specified types for box properties.
 
 use Atom;
 use cssparser::Parser;
 use parser::{Parse, ParserContext};
 #[cfg(feature = "servo")]
 use properties::{longhands, PropertyDeclaration};
+use selectors::parser::SelectorParseErrorKind;
 use std::fmt;
-use style_traits::{ParseError, ToCss};
+use style_traits::{ParseError, ToCss, StyleParseErrorKind};
 use values::CustomIdent;
 use values::KeyframesName;
 #[cfg(feature = "servo")]
 use values::computed::Context;
 use values::generics::box_::AnimationIterationCount as GenericAnimationIterationCount;
 use values::generics::box_::VerticalAlign as GenericVerticalAlign;
 use values::specified::{AllowQuirks, Number};
 use values::specified::length::LengthOrPercentage;
@@ -487,8 +488,97 @@ pub fn assert_touch_action_matches() {
     check_touch_action! {
         NS_STYLE_TOUCH_ACTION_NONE => TouchAction::TOUCH_ACTION_NONE,
         NS_STYLE_TOUCH_ACTION_AUTO => TouchAction::TOUCH_ACTION_AUTO,
         NS_STYLE_TOUCH_ACTION_PAN_X => TouchAction::TOUCH_ACTION_PAN_X,
         NS_STYLE_TOUCH_ACTION_PAN_Y => TouchAction::TOUCH_ACTION_PAN_Y,
         NS_STYLE_TOUCH_ACTION_MANIPULATION => TouchAction::TOUCH_ACTION_MANIPULATION,
     }
 }
+
+bitflags! {
+    #[derive(MallocSizeOf, ToComputedValue)]
+    /// Constants for contain: https://drafts.csswg.org/css-contain/#contain-property
+    pub struct Contain: u8 {
+        /// `layout` variant, turns on layout containment
+        const LAYOUT = 0x01;
+        /// `style` variant, turns on style containment
+        const STYLE = 0x02;
+        /// `paint` variant, turns on paint containment
+        const PAINT = 0x04;
+        /// `strict` variant, turns on all types of containment
+        const STRICT = 0x8;
+        /// variant with all the bits that contain: strict turns on
+        const STRICT_BITS = Contain::LAYOUT.bits | Contain::STYLE.bits | Contain::PAINT.bits;
+    }
+}
+
+impl ToCss for Contain {
+    fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
+        if self.is_empty() {
+            return dest.write_str("none")
+        }
+        if self.contains(Contain::STRICT) {
+            return dest.write_str("strict")
+        }
+
+        let mut has_any = false;
+        macro_rules! maybe_write_value {
+            ($ident:path => $str:expr) => {
+                if self.contains($ident) {
+                    if has_any {
+                        dest.write_str(" ")?;
+                    }
+                    has_any = true;
+                    dest.write_str($str)?;
+                }
+            }
+        }
+        maybe_write_value!(Contain::LAYOUT => "layout");
+        maybe_write_value!(Contain::STYLE => "style");
+        maybe_write_value!(Contain::PAINT => "paint");
+
+        debug_assert!(has_any);
+        Ok(())
+    }
+}
+
+impl Parse for Contain {
+    /// none | strict | content | [ size || layout || style || paint ]
+    fn parse<'i, 't>(
+        _context: &ParserContext,
+        input: &mut Parser<'i, 't>
+    ) -> Result<Contain, ParseError<'i>> {
+        let mut result = Contain::empty();
+        while let Ok(name) = input.try(|i| i.expect_ident_cloned()) {
+            let flag = match_ignore_ascii_case! { &name,
+                "layout" => Some(Contain::LAYOUT),
+                "style" => Some(Contain::STYLE),
+                "paint" => Some(Contain::PAINT),
+                "strict" => {
+                    if result.is_empty() {
+                        return Ok(Contain::STRICT | Contain::STRICT_BITS)
+                    }
+                    None
+                },
+                "none" => {
+                    if result.is_empty() {
+                        return Ok(result)
+                    }
+                    None
+                },
+                _ => None
+            };
+
+            let flag = match flag {
+                Some(flag) if !result.contains(flag) => flag,
+                _ => return Err(input.new_custom_error(SelectorParseErrorKind::UnexpectedIdent(name)))
+            };
+            result.insert(flag);
+        }
+
+        if !result.is_empty() {
+            Ok(result)
+        } else {
+            Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
+        }
+    }
+}
--- a/servo/components/style/values/specified/mod.rs
+++ b/servo/components/style/values/specified/mod.rs
@@ -29,17 +29,17 @@ pub use self::angle::Angle;
 pub use self::align::{AlignItems, AlignJustifyContent, AlignJustifySelf, JustifyItems};
 pub use self::background::{BackgroundRepeat, BackgroundSize};
 pub use self::border::{BorderCornerRadius, BorderImageSlice, BorderImageWidth};
 pub use self::border::{BorderImageSideWidth, BorderRadius, BorderSideWidth, BorderSpacing};
 pub use self::font::{FontSize, FontSizeAdjust, FontSynthesis, FontWeight, FontVariantAlternates};
 pub use self::font::{FontFamily, FontLanguageOverride, FontVariantSettings, FontVariantEastAsian};
 pub use self::font::{FontVariantLigatures, FontVariantNumeric, FontFeatureSettings};
 pub use self::font::{MozScriptLevel, MozScriptMinSize, MozScriptSizeMultiplier, XTextZoom, XLang};
-pub use self::box_::{AnimationIterationCount, AnimationName, Display, OverscrollBehavior};
+pub use self::box_::{AnimationIterationCount, AnimationName, Display, OverscrollBehavior, Contain};
 pub use self::box_::{OverflowClipBox, ScrollSnapType, TouchAction, VerticalAlign, WillChange};
 pub use self::color::{Color, ColorPropertyValue, RGBAColor};
 pub use self::effects::{BoxShadow, Filter, SimpleShadow};
 pub use self::flex::FlexBasis;
 #[cfg(feature = "gecko")]
 pub use self::gecko::ScrollSnapPoint;
 pub use self::image::{ColorStop, EndingShape as GradientEndingShape, Gradient};
 pub use self::image::{GradientItem, GradientKind, Image, ImageLayer, MozImageRect};