style: Properly check whether a property reset by a shorthand could be disallowed.
authorEmilio Cobos Álvarez <emilio@crisal.io>
Wed, 14 Feb 2018 13:48:00 +0100
changeset 1427319 11ed5568d69f2484daf222f679015a5e848a833f
parent 1427318 3a584fab7862aa0bd8f9d5b4301d6d91816eeaa0
child 1427320 7471d0adb3734c160a9e280ccf1400565073e4fb
child 1427412 9a1343e83135b4f9e5dc5cb90fe100ae71c10b4a
child 1427491 37ca6d7e1c6221c3b33808a7595b6c3db3698e85
child 1427704 f1db9bb1a4f8a423de3a5dd8099b6a9f9b64a259
push id252443
push userecoal95@gmail.com
push dateWed, 14 Feb 2018 12:50:48 +0000
treeherdertry@7471d0adb373 [default view] [failures only]
milestone60.0a1
style: Properly check whether a property reset by a shorthand could be disallowed. MozReview-Commit-ID: 7RY8SjajVfP
servo/components/style/properties/data.py
servo/components/style/properties/helpers.mako.rs
servo/components/style/properties/properties.mako.rs
--- a/servo/components/style/properties/data.py
+++ b/servo/components/style/properties/data.py
@@ -224,16 +224,26 @@ class Longhand(object):
         return self.enabled_in in ["ua", "chrome"]
 
     def explicitly_enabled_in_chrome(self):
         return self.enabled_in == "chrome"
 
     def enabled_in_content(self):
         return self.enabled_in == "content"
 
+    def could_be_disallowed_in(self, shorthand, product):
+        assert self in shorthand.sub_properties
+        # In theory, the shorthand or longhand could be exposed to different
+        # stuff, like chrome or so, or under different prefs compared to the
+        # shorthand.
+        #
+        # Assertions would catch if someone tries to do that, and we'd need to
+        # be more conservative / precise here.
+        return self.experimental(product) and not shorthand.experimental(product)
+
     def base_type(self):
         if self.predefined_type and not self.is_vector:
             return "::values::specified::{}".format(self.predefined_type)
         return "longhands::{}::SpecifiedValue".format(self.ident)
 
     def specified_type(self):
         if self.predefined_type and not self.is_vector:
             ty = "::values::specified::{}".format(self.predefined_type)
--- a/servo/components/style/properties/helpers.mako.rs
+++ b/servo/components/style/properties/helpers.mako.rs
@@ -733,24 +733,44 @@
                     }),
                     _ => Err(())
                 }
             }
         }
 
         /// Parse the given shorthand and fill the result into the
         /// `declarations` vector.
-        pub fn parse_into<'i, 't>(declarations: &mut SourcePropertyDeclaration,
-                                  context: &ParserContext, input: &mut Parser<'i, 't>)
-                                  -> Result<(), ParseError<'i>> {
+        pub fn parse_into<'i, 't>(
+            declarations: &mut SourcePropertyDeclaration,
+            context: &ParserContext,
+            input: &mut Parser<'i, 't>,
+        ) -> Result<(), ParseError<'i>> {
+            use properties::{PropertyId, LonghandId};
+
             input.parse_entirely(|input| parse_value(context, input)).map(|longhands| {
                 % for sub_property in shorthand.sub_properties:
-                    declarations.push(PropertyDeclaration::${sub_property.camel_case}(
-                        longhands.${sub_property.ident}
-                    ));
+                    let id =
+                        PropertyId::Longhand(LonghandId::${sub_property.camel_case});
+
+                    // Don't allow to reset a longhand that is disabled by a
+                    // pref to be reset by a shorthand that isn't.
+                    % if sub_property.could_be_disallowed_in(shorthand, product):
+                    if id.allowed_in(context) {
+                    % endif
+
+                    debug_assert!(id.allowed_in(context));
+                    declarations.push(
+                        PropertyDeclaration::${sub_property.camel_case}(
+                            longhands.${sub_property.ident}
+                        )
+                    );
+
+                    % if sub_property.could_be_disallowed_in(shorthand, product):
+                    }
+                    % endif
                 % endfor
             })
         }
 
         ${caller.body()}
     }
     % endif
 </%def>
@@ -759,18 +779,20 @@
                                  needs_context=True, allow_quirks=False, **kwargs)">
     <% sub_properties=' '.join(sub_property_pattern % side for side in ['top', 'right', 'bottom', 'left']) %>
     <%call expr="self.shorthand(name, sub_properties=sub_properties, **kwargs)">
         #[allow(unused_imports)]
         use parser::Parse;
         use values::generics::rect::Rect;
         use values::specified;
 
-        pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-                                   -> Result<Longhands, ParseError<'i>> {
+        pub fn parse_value<'i, 't>(
+            context: &ParserContext,
+            input: &mut Parser<'i, 't>,
+        ) -> Result<Longhands, ParseError<'i>> {
             let rect = Rect::parse_with(context, input, |_c, i| {
             % if allow_quirks:
                 ${parser_function}_quirky(_c, i, specified::AllowQuirks::Yes)
             % elif needs_context:
                 ${parser_function}(_c, i)
             % else:
                 ${parser_function}(i)
             % endif
--- a/servo/components/style/properties/properties.mako.rs
+++ b/servo/components/style/properties/properties.mako.rs
@@ -776,18 +776,21 @@ impl LonghandId {
 
         match *self {
             % for property in data.longhands:
                 LonghandId::${property.camel_case} => ${property.ident.upper()},
             % endfor
         }
     }
 
-    fn parse_value<'i, 't>(&self, context: &ParserContext, input: &mut Parser<'i, 't>)
-                           -> Result<PropertyDeclaration, ParseError<'i>> {
+    fn parse_value<'i, 't>(
+        &self,
+        context: &ParserContext,
+        input: &mut Parser<'i, 't>,
+    ) -> Result<PropertyDeclaration, ParseError<'i>> {
         match *self {
             % for property in data.longhands:
                 LonghandId::${property.camel_case} => {
                     longhands::${property.ident}::parse_declared(context, input)
                 }
             % endfor
         }
     }