servo: Merge #15972 - Parsing / serialization for CSS contain (from jryans:ps-contain); r=emilio
authorJ. Ryan Stinnett <jryans@gmail.com>
Thu, 23 Mar 2017 13:23:51 -0700
changeset 504125 62ad11a0991e6d9a3414eac9d41b00dc1098f7cc
parent 504124 4470faf1886e5fa14845e218eb73f6b89d3b3a6c
child 504126 c0542709971fc9d6b512ab1719b9e7eb1896fe4c
child 504140 3948d3c59817457a27114a00646cb93e00a21f24
child 504189 5b712a9e7e597cefe23fa916bda2b55351e5046e
child 504563 377c33c931fe4e5abd8f37d8a0cdccecc7956ccc
push id50739
push userbmo:emilio+bugs@crisal.io
push dateThu, 23 Mar 2017 23:47:46 +0000
reviewersemilio
milestone55.0a1
servo: Merge #15972 - Parsing / serialization for CSS contain (from jryans:ps-contain); r=emilio Adds parsing / serialization for CSS contain to the style package. - [x] `./mach build -d` does not report any errors - [x] `./mach test-tidy` does not report any errors - [x] These changes fix #15955 - [x] There are tests for these changes Source-Repo: https://github.com/servo/servo Source-Revision: 636f8ceb50cef61e34fd5fbd74ed55f098fff72a
servo/components/style/properties/longhand/box.mako.rs
servo/tests/unit/style/parsing/containment.rs
servo/tests/unit/style/parsing/mod.rs
--- a/servo/components/style/properties/longhand/box.mako.rs
+++ b/servo/components/style/properties/longhand/box.mako.rs
@@ -1894,16 +1894,119 @@
                 horizontal: ToComputedValue::from_computed_value(&computed.horizontal),
                 vertical: ToComputedValue::from_computed_value(&computed.vertical),
                 depth: ToComputedValue::from_computed_value(&computed.depth),
             }
         }
     }
 </%helpers:longhand>
 
+<%helpers:longhand name="contain" animatable="False" products="none"
+                   spec="https://drafts.csswg.org/css-contain/#contain-property">
+    use std::fmt;
+    use style_traits::ToCss;
+    use values::HasViewportPercentage;
+    use values::computed::ComputedValueAsSpecified;
+
+    impl ComputedValueAsSpecified for SpecifiedValue {}
+    no_viewport_percentage!(SpecifiedValue);
+
+    pub mod computed_value {
+        pub type T = super::SpecifiedValue;
+    }
+
+    bitflags! {
+        #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
+        pub flags SpecifiedValue: u8 {
+            const SIZE = 0x01,
+            const LAYOUT = 0x02,
+            const STYLE = 0x04,
+            const PAINT = 0x08,
+            const STRICT = SIZE.bits | LAYOUT.bits | STYLE.bits | PAINT.bits,
+            const CONTENT = LAYOUT.bits | STYLE.bits | 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(STRICT) {
+                return dest.write_str("strict")
+            }
+            if self.contains(CONTENT) {
+                return dest.write_str("content")
+            }
+
+            let mut has_any = false;
+            macro_rules! maybe_write_value {
+                ($ident:ident => $str:expr) => {
+                    if self.contains($ident) {
+                        if has_any {
+                            try!(dest.write_str(" "));
+                        }
+                        has_any = true;
+                        try!(dest.write_str($str));
+                    }
+                }
+            }
+            maybe_write_value!(SIZE => "size");
+            maybe_write_value!(LAYOUT => "layout");
+            maybe_write_value!(STYLE => "style");
+            maybe_write_value!(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(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
+        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(STRICT);
+            return Ok(result)
+        }
+        if input.try(|input| input.expect_ident_matching("content")).is_ok() {
+            result.insert(CONTENT);
+            return Ok(result)
+        }
+
+        while let Ok(name) = input.try(|input| input.expect_ident()) {
+            let flag = match_ignore_ascii_case! { &name,
+                "size" => SIZE,
+                "layout" => LAYOUT,
+                "style" => STYLE,
+                "paint" => PAINT,
+                _ => return Err(())
+            };
+            if result.contains(flag) {
+                return Err(())
+            }
+            result.insert(flag);
+        }
+
+        if !result.is_empty() {
+            Ok(result)
+        } else {
+            Err(())
+        }
+    }
+</%helpers:longhand>
+
 // 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
                             dualbutton groupbox listbox listitem menuarrow menubar menucheckbox menuimage menuitem
                             menuitemtext menulist menulist-button menulist-text menulist-textfield menupopup menuradio
                             menuseparator meterbar meterchunk progressbar progressbar-vertical progresschunk
                             progresschunk-vertical radio radio-container radio-label radiomenuitem range range-thumb
new file mode 100644
--- /dev/null
+++ b/servo/tests/unit/style/parsing/containment.rs
@@ -0,0 +1,26 @@
+/* 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/. */
+
+use cssparser::Parser;
+use media_queries::CSSErrorReporterTest;
+use style::parser::ParserContext;
+use style::stylesheets::Origin;
+
+#[test]
+fn contain_longhand_should_parse_correctly() {
+    use style::properties::longhands::contain;
+    use style::properties::longhands::contain::SpecifiedValue;
+
+    let none = parse_longhand!(contain, "none");
+    assert_eq!(none, SpecifiedValue::empty());
+
+    let strict = parse_longhand!(contain, "strict");
+    assert_eq!(strict, contain::STRICT);
+
+    let style_paint = parse_longhand!(contain, "style paint");
+    assert_eq!(style_paint, contain::STYLE | contain::PAINT);
+
+    // Assert that the `2px` is not consumed, which would trigger parsing failure in real use
+    assert_parser_exhausted!(contain, "layout 2px", false);
+}
--- a/servo/tests/unit/style/parsing/mod.rs
+++ b/servo/tests/unit/style/parsing/mod.rs
@@ -82,16 +82,17 @@ macro_rules! parse_longhand {
 }
 
 mod animation;
 mod background;
 mod basic_shape;
 mod border;
 mod box_;
 mod column;
+mod containment;
 mod effects;
 mod font;
 mod image;
 mod inherited_box;
 mod inherited_text;
 mod length;
 mod mask;
 mod outline;