Bug 1463589 - Add contain:size parse functionality. draft
authorMorgan Rae Reschenberg <mreschenberg@mozilla.com>
Fri, 25 May 2018 13:39:26 -0700
changeset 800085 174a717de4fc0b3e2e8ba24947355e62091a4c32
parent 800084 755984cd12949aa06493c5dbebc8975669313470
child 800086 208fe2e632fb9005d7fe043c1d12c813d1075a6f
push id111265
push userbmo:mreschenberg@berkeley.edu
push dateFri, 25 May 2018 21:01:03 +0000
bugs1463589
milestone62.0a1
Bug 1463589 - Add contain:size parse functionality. MozReview-Commit-ID: LriIVuQNzxT
layout/style/nsCSSKeywordList.h
layout/style/nsCSSProps.cpp
layout/style/nsComputedDOMStyle.cpp
layout/style/nsStyleConsts.h
layout/style/test/property_database.js
servo/components/style/properties/gecko.mako.rs
servo/components/style/values/specified/box.rs
--- a/layout/style/nsCSSKeywordList.h
+++ b/layout/style/nsCSSKeywordList.h
@@ -30,17 +30,17 @@
   'name' entries *must* use only lowercase characters.
 
   ** Break these invariants and bad things will happen. **
 
  ******/
 
 // OUTPUT_CLASS=nsCSSKeywords
 // MACRO_NAME=CSS_KEY
-
+CSS_KEY(size, size)
 CSS_KEY(-moz-activehyperlinktext, _moz_activehyperlinktext)
 CSS_KEY(-moz-all, _moz_all)
 CSS_KEY(-moz-alt-content, _moz_alt_content)
 CSS_KEY(-moz-available, _moz_available)
 CSS_KEY(-moz-box, _moz_box)
 CSS_KEY(-moz-button, _moz_button)
 CSS_KEY(-moz-buttondefault, _moz_buttondefault)
 CSS_KEY(-moz-buttonhoverface, _moz_buttonhoverface)
--- a/layout/style/nsCSSProps.cpp
+++ b/layout/style/nsCSSProps.cpp
@@ -1047,16 +1047,17 @@ const KTableEntry nsCSSProps::kListStyle
 
 const KTableEntry nsCSSProps::kContainKTable[] = {
   { eCSSKeyword_none,    NS_STYLE_CONTAIN_NONE },
   { eCSSKeyword_strict,  NS_STYLE_CONTAIN_STRICT },
   { eCSSKeyword_content, NS_STYLE_CONTAIN_CONTENT },
   { eCSSKeyword_layout,  NS_STYLE_CONTAIN_LAYOUT },
   { eCSSKeyword_style,   NS_STYLE_CONTAIN_STYLE },
   { eCSSKeyword_paint,   NS_STYLE_CONTAIN_PAINT },
+  { eCSSKeyword_size,    NS_STYLE_CONTAIN_SIZE },
   { eCSSKeyword_UNKNOWN, -1 }
 };
 
 const KTableEntry nsCSSProps::kObjectFitKTable[] = {
   { eCSSKeyword_fill,       NS_STYLE_OBJECT_FIT_FILL },
   { eCSSKeyword_contain,    NS_STYLE_OBJECT_FIT_CONTAIN },
   { eCSSKeyword_cover,      NS_STYLE_OBJECT_FIT_COVER },
   { eCSSKeyword_none,       NS_STYLE_OBJECT_FIT_NONE },
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -5040,28 +5040,29 @@ nsComputedDOMStyle::DoGetContain()
   RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
 
   int32_t mask = StyleDisplay()->mContain;
 
   if (mask == 0) {
     val->SetIdent(eCSSKeyword_none);
   } else if (mask & NS_STYLE_CONTAIN_STRICT) {
     NS_ASSERTION(mask == (NS_STYLE_CONTAIN_STRICT | NS_STYLE_CONTAIN_ALL_BITS),
-                 "contain: strict should imply contain: layout style paint");
+                 "contain: strict should imply contain: size layout style paint");
     val->SetIdent(eCSSKeyword_strict);
   } else if (mask & NS_STYLE_CONTAIN_CONTENT) {
     NS_ASSERTION(mask == (NS_STYLE_CONTAIN_CONTENT | NS_STYLE_CONTAIN_CONTENT_BITS), 
                  "contain: content should imply contain: layout style paint");
     val->SetIdent(eCSSKeyword_content);
   }  else {
     nsAutoString valueStr;
 
     nsStyleUtil::AppendBitmaskCSSValue(nsCSSProps::kContainKTable,
-                                       mask, NS_STYLE_CONTAIN_LAYOUT,
-                                       NS_STYLE_CONTAIN_PAINT, valueStr);
+                                       mask, 
+                                       NS_STYLE_CONTAIN_SIZE, NS_STYLE_CONTAIN_PAINT,
+                                       valueStr);
     val->SetString(valueStr);
   }
 
   return val.forget();
 }
 
 already_AddRefed<CSSValue>
 nsComputedDOMStyle::DoGetPosition()
--- a/layout/style/nsStyleConsts.h
+++ b/layout/style/nsStyleConsts.h
@@ -453,16 +453,17 @@ enum class StyleDisplay : uint8_t {
   MozPopup,
 #endif
 };
 
 // See nsStyleDisplay
 // If these are re-ordered, nsComputedDOMStyle::DoGetContain() and
 // nsCSSValue::AppendToString() must be updated.
 #define NS_STYLE_CONTAIN_NONE                   0
+#define NS_STYLE_CONTAIN_SIZE                   0x01
 #define NS_STYLE_CONTAIN_LAYOUT                 0x02
 #define NS_STYLE_CONTAIN_STYLE                  0x04
 #define NS_STYLE_CONTAIN_PAINT                  0x08
 #define NS_STYLE_CONTAIN_STRICT                 0x10
 #define NS_STYLE_CONTAIN_CONTENT                0x20
 // NS_STYLE_CONTAIN_ALL_BITS does not correspond to a keyword.
 #define NS_STYLE_CONTAIN_ALL_BITS               (NS_STYLE_CONTAIN_LAYOUT | \
                                                  NS_STYLE_CONTAIN_STYLE  | \
--- a/layout/style/test/property_database.js
+++ b/layout/style/test/property_database.js
@@ -7273,24 +7273,28 @@ if (IsCSSPropertyPrefEnabled("layout.css
     domProp: "contain",
     inherited: false,
     type: CSS_TYPE_LONGHAND,
     initial_values: [ "none" ],
     other_values: [
       "strict",
       "layout",
       "style",
+      "size",
       "content",
       "layout style",
       "style layout",
       "paint",
       "layout paint",
       "paint layout",
       "style paint",
       "paint style",
+      "size layout",
+      "style size",
+      "paint size",
       "layout style paint",
       "layout paint style",
       "style paint layout",
       "paint style layout",
     ],
     invalid_values: [
       "none strict",
       "strict layout",
--- a/servo/components/style/properties/gecko.mako.rs
+++ b/servo/components/style/properties/gecko.mako.rs
@@ -3623,16 +3623,17 @@ fn static_assert() {
     }
 
     <% impl_shape_source("shape_outside", "mShapeOutside") %>
 
     pub fn set_contain(&mut self, v: longhands::contain::computed_value::T) {
         use gecko_bindings::structs::NS_STYLE_CONTAIN_NONE;
         use gecko_bindings::structs::NS_STYLE_CONTAIN_STRICT;
         use gecko_bindings::structs::NS_STYLE_CONTAIN_CONTENT;
+        use gecko_bindings::structs::NS_STYLE_CONTAIN_SIZE;
         use gecko_bindings::structs::NS_STYLE_CONTAIN_LAYOUT;
         use gecko_bindings::structs::NS_STYLE_CONTAIN_STYLE;
         use gecko_bindings::structs::NS_STYLE_CONTAIN_PAINT;
         use gecko_bindings::structs::NS_STYLE_CONTAIN_ALL_BITS;
         use gecko_bindings::structs::NS_STYLE_CONTAIN_CONTENT_BITS;
         use properties::longhands::contain::SpecifiedValue;
 
         if v.is_empty() {
@@ -3654,23 +3655,27 @@ fn static_assert() {
             bitfield |= NS_STYLE_CONTAIN_LAYOUT;
         }
         if v.contains(SpecifiedValue::STYLE) {
             bitfield |= NS_STYLE_CONTAIN_STYLE;
         }
         if v.contains(SpecifiedValue::PAINT) {
             bitfield |= NS_STYLE_CONTAIN_PAINT;
         }
+        if v.contains(SpecifiedValue::SIZE) {
+            bitfield |= NS_STYLE_CONTAIN_SIZE;
+        }
 
         self.gecko.mContain = bitfield as u8;
     }
 
     pub fn clone_contain(&self) -> longhands::contain::computed_value::T {
         use gecko_bindings::structs::NS_STYLE_CONTAIN_STRICT;
         use gecko_bindings::structs::NS_STYLE_CONTAIN_CONTENT;
+        use gecko_bindings::structs::NS_STYLE_CONTAIN_SIZE;
         use gecko_bindings::structs::NS_STYLE_CONTAIN_LAYOUT;
         use gecko_bindings::structs::NS_STYLE_CONTAIN_STYLE;
         use gecko_bindings::structs::NS_STYLE_CONTAIN_PAINT;
         use gecko_bindings::structs::NS_STYLE_CONTAIN_ALL_BITS;
         use gecko_bindings::structs::NS_STYLE_CONTAIN_CONTENT_BITS;
         use properties::longhands::contain::{self, SpecifiedValue};
 
         let mut servo_flags = contain::computed_value::T::empty();
@@ -3691,16 +3696,19 @@ fn static_assert() {
             servo_flags.insert(SpecifiedValue::LAYOUT);
         }
         if gecko_flags & (NS_STYLE_CONTAIN_STYLE as u8) != 0 {
             servo_flags.insert(SpecifiedValue::STYLE);
         }
         if gecko_flags & (NS_STYLE_CONTAIN_PAINT as u8) != 0 {
             servo_flags.insert(SpecifiedValue::PAINT);
         }
+        if gecko_flags & (NS_STYLE_CONTAIN_SIZE as u8) != 0 {
+            servo_flags.insert(SpecifiedValue::SIZE);
+        }
 
         return servo_flags;
     }
 
     ${impl_simple_copy("contain", "mContain")}
 
     ${impl_simple_type_with_conversion("touch_action")}
 </%self:impl_trait>
--- a/servo/components/style/values/specified/box.rs
+++ b/servo/components/style/values/specified/box.rs
@@ -520,31 +520,33 @@ pub fn assert_touch_action_matches() {
         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, SpecifiedValueInfo, ToComputedValue)]
-    #[value_info(other_values = "none,strict,layout,style,paint")]
+    #[value_info(other_values = "none,strict,content,size,layout,style,paint")]
     /// Constants for contain: https://drafts.csswg.org/css-contain/#contain-property
     pub struct Contain: u8 {
+        /// 'size' variant, turns on size containment
+        const SIZE = 0x01;
         /// `layout` variant, turns on layout containment
         const LAYOUT = 0x02;
         /// `style` variant, turns on style containment
         const STYLE = 0x04;
         /// `paint` variant, turns on paint containment
         const PAINT = 0x08;
         /// `strict` variant, turns on all types of containment
         const STRICT = 0x10;
         /// 'content' variant, turns on style, layout, and paint containment
         const CONTENT = 0x20;
         /// variant with all the bits that contain: strict turns on
-        const STRICT_BITS = Contain::LAYOUT.bits | Contain::STYLE.bits | Contain::PAINT.bits;
+        const STRICT_BITS = Contain::LAYOUT.bits | Contain::STYLE.bits | Contain::PAINT.bits | Contain::SIZE.bits;
         /// variant with all the bits that contain: content turns on
         const CONTENT_BITS = Contain::STYLE.bits | Contain::LAYOUT.bits | Contain::PAINT.bits;
     }
 }
 
 impl ToCss for Contain {
     fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
     where
@@ -567,16 +569,17 @@ impl ToCss for Contain {
                     if has_any {
                         dest.write_str(" ")?;
                     }
                     has_any = true;
                     dest.write_str($str)?;
                 }
             };
         }
+        maybe_write_value!(Contain::SIZE => "size");
         maybe_write_value!(Contain::LAYOUT => "layout");
         maybe_write_value!(Contain::STYLE => "style");
         maybe_write_value!(Contain::PAINT => "paint");
 
         debug_assert!(has_any);
         Ok(())
     }
 }
@@ -585,16 +588,17 @@ 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,
+                "size" => Some(Contain::SIZE),
                 "layout" => Some(Contain::LAYOUT),
                 "style" => Some(Contain::STYLE),
                 "paint" => Some(Contain::PAINT),
                 "strict" if result.is_empty() => return Ok(Contain::STRICT | Contain::STRICT_BITS),
                 "content" if result.is_empty() => return Ok(Contain::CONTENT | Contain::CONTENT_BITS),
                 "none" if result.is_empty() => return Ok(result),
                 _ => None
             };