servo: Merge #10461 - Add some machinery to allow us to disable CSS properties/values per-product (from bholley:per_product); r=SimonSapin
authorBobby Holley <bobbyholley@gmail.com>
Fri, 08 Apr 2016 18:27:13 +0500
changeset 476624 9a4db2ae0cd5a3c3e7fa1efb8028ec967e3878bf
parent 476623 bee9e1d462a155be71c8001abec88f80a2293534
child 476625 a0c9c9dc3b04834a265c2fd1b1bcdef56db5b786
push id44079
push userbmo:gps@mozilla.com
push dateSat, 04 Feb 2017 00:14:49 +0000
reviewersSimonSapin
servo: Merge #10461 - Add some machinery to allow us to disable CSS properties/values per-product (from bholley:per_product); r=SimonSapin Here's an initial stab at solving the issues @SimonSapin brought up in #10408. Source-Repo: https://github.com/servo/servo Source-Revision: 2491af84fc8e95e4e5741e6fc12db4275527aaba
servo/components/style/Cargo.toml
servo/components/style/build.rs
servo/components/style/list_properties.py
servo/components/style/properties.mako.rs
servo/ports/geckolib/Cargo.toml
servo/ports/geckolib/build.rs
--- a/servo/components/style/Cargo.toml
+++ b/servo/components/style/Cargo.toml
@@ -5,16 +5,19 @@ authors = ["The Servo Project Developers
 publish = false
 
 build = "build.rs"
 
 [lib]
 name = "style"
 path = "lib.rs"
 
+[features]
+gecko = []
+
 [dependencies.plugins]
 path = "../plugins"
 
 [dependencies.util]
 path = "../util"
 
 [dependencies.style_traits]
 path = "../style_traits"
--- a/servo/components/style/build.rs
+++ b/servo/components/style/build.rs
@@ -33,27 +33,30 @@ fn find_python() -> String {
 fn main() {
     let python = match env::var("PYTHON") {
         Ok(python_path) => python_path,
         Err(_) => find_python(),
     };
     let style = Path::new(file!()).parent().unwrap();
     let mako = style.join("Mako-0.9.1.zip");
     let template = style.join("properties.mako.rs");
+    let product = if cfg!(feature = "gecko") { "gecko" } else { "servo" };
     let result = Command::new(python)
         .env("PYTHONPATH", &mako)
         .env("TEMPLATE", &template)
+        .env("PRODUCT", product)
         .arg("-c")
         .arg(r#"
 import os
 import sys
 from mako.template import Template
 from mako import exceptions
 try:
-    print(Template(filename=os.environ['TEMPLATE'], input_encoding='utf8').render().encode('utf8'))
+    print(Template(filename=os.environ['TEMPLATE'], input_encoding='utf8').render(PRODUCT=os.environ['PRODUCT'])
+                                                                          .encode('utf8'))
 except:
     sys.stderr.write(exceptions.text_error_template().render().encode('utf8'))
     sys.exit(1)
 "#)
         .stderr(Stdio::inherit())
         .output()
         .unwrap();
     if !result.status.success() {
--- a/servo/components/style/list_properties.py
+++ b/servo/components/style/list_properties.py
@@ -8,17 +8,17 @@ import os.path
 import sys
 import json
 
 style = os.path.dirname(__file__)
 sys.path.insert(0, os.path.join(style, "Mako-0.9.1.zip"))
 from mako.template import Template
 
 template = Template(filename=os.path.join(style, "properties.mako.rs"), input_encoding='utf8')
-template.render()
+template.render(PRODUCT='servo')
 properties = dict(
     (p.name, {
         "flag": p.experimental,
         "shorthand": hasattr(p, "sub_properties")
     })
     for p in template.module.LONGHANDS + template.module.SHORTHANDS
 )
 
--- a/servo/components/style/properties.mako.rs
+++ b/servo/components/style/properties.mako.rs
@@ -42,20 +42,39 @@ def to_rust_ident(name):
     name = name.replace("-", "_")
     if name in ["static", "super", "box", "move"]:  # Rust keywords
         name += "_"
     return name
 
 def to_camel_case(ident):
     return re.sub("_([a-z])", lambda m: m.group(1).upper(), ident.strip("_").capitalize())
 
+class Keyword(object):
+    def __init__(self, name, values, extra_gecko_values=None, extra_servo_values=None):
+        self.name = name
+        self.values = values
+        self.extra_gecko_values = extra_gecko_values or []
+        self.extra_servo_values = extra_servo_values or []
+    def gecko_values(self):
+        return self.values + self.extra_gecko_values
+    def servo_values(self):
+        return self.values + self.extra_servo_values
+    def values_for(self, product):
+        if product == "gecko":
+            return self.gecko_values()
+        elif product == "servo":
+            return self.servo_values()
+        else:
+            raise Exception("Bad product: " + product)
+
 class Longhand(object):
-    def __init__(self, name, derived_from=None, custom_cascade=False, experimental=False,
-                 internal=False):
+    def __init__(self, name, derived_from=None, keyword=None,
+                 custom_cascade=False, experimental=False, internal=False):
         self.name = name
+        self.keyword = keyword
         self.ident = to_rust_ident(name)
         self.camel_case = to_camel_case(self.ident)
         self.style_struct = THIS_STYLE_STRUCT
         self.experimental = ("layout.%s.enabled" % name) if experimental else None
         self.custom_cascade = custom_cascade
         self.internal = internal
         if derived_from is None:
             self.derived_from = None
@@ -102,16 +121,21 @@ class StyleStruct(object):
         self.additional_methods = additional_methods or []
 
 STYLE_STRUCTS = []
 THIS_STYLE_STRUCT = None
 LONGHANDS = []
 LONGHANDS_BY_NAME = {}
 DERIVED_LONGHANDS = {}
 SHORTHANDS = []
+CONFIG = {}
+
+def set_product(p):
+    global CONFIG
+    CONFIG['product'] = p
 
 def new_style_struct(name, is_inherited, gecko_name=None, additional_methods=None):
     global THIS_STYLE_STRUCT
 
     style_struct = StyleStruct(name, is_inherited, gecko_name, additional_methods)
     STYLE_STRUCTS.append(style_struct)
     THIS_STYLE_STRUCT = style_struct
     return ""
@@ -121,29 +145,42 @@ def switch_to_style_struct(name):
 
     for style_struct in STYLE_STRUCTS:
         if style_struct.name == name:
             THIS_STYLE_STRUCT = style_struct
             return ""
     fail()
 %>
 
+// Work around Mako's really annoying namespacing setup.
+//
+// The above code runs when the template is loaded, rather than when it's
+// rendered, so it can create global variables, doesn't have access to
+// arguments passed to render(). On the flip side, there are various situations,
+// such as code in the body of a def-used-as-tag, where our python code has
+// access to global variables but not to render() arguments. Hack around this
+// by stashing render arguments in a global.
+<% CONFIG['product'] = PRODUCT %>
+
 pub mod longhands {
     use cssparser::Parser;
     use parser::ParserContext;
     use values::specified;
 
-    <%def name="raw_longhand(name, derived_from=None, custom_cascade=False, experimental=False,
-                             internal=False)">
+    <%def name="raw_longhand(name, keyword=None, derived_from=None, products='gecko,servo',
+                             custom_cascade=False, experimental=False, internal=False)">
     <%
+        if not CONFIG['product'] in products:
+            return ""
         if derived_from is not None:
             derived_from = derived_from.split()
 
         property = Longhand(name,
                             derived_from=derived_from,
+                            keyword=keyword,
                             custom_cascade=custom_cascade,
                             experimental=experimental,
                             internal=internal)
         property.style_struct = THIS_STYLE_STRUCT
         THIS_STYLE_STRUCT.longhands.append(property)
         LONGHANDS.append(property)
         LONGHANDS_BY_NAME[name] = property
 
@@ -262,66 +299,71 @@ pub mod longhands {
                             specified
                         }
                     }
                 }
             % endif
         }
     </%def>
 
-    <%def name="longhand(name, derived_from=None, custom_cascade=False, experimental=False,
-                         internal=False)">
-        <%self:raw_longhand name="${name}" derived_from="${derived_from}"
-                custom_cascade="${custom_cascade}" experimental="${experimental}"
-                internal="${internal}">
+    <%def name="longhand(name, derived_from=None, keyword=None, products='gecko,servo',
+                         custom_cascade=False, experimental=False, internal=False)">
+        <%self:raw_longhand name="${name}" derived_from="${derived_from}" keyword="${keyword}"
+                products="${products}" custom_cascade="${custom_cascade}"
+                experimental="${experimental}" internal="${internal}">
             ${caller.body()}
             % if derived_from is None:
                 pub fn parse_specified(context: &ParserContext, input: &mut Parser)
                                    -> Result<DeclaredValue<SpecifiedValue>, ()> {
                     parse(context, input).map(DeclaredValue::Value)
                 }
             % endif
         </%self:raw_longhand>
     </%def>
 
-    <%def name="single_keyword_computed(name, values, custom_cascade=False, experimental=False,
-                                        internal=False)">
-        <%self:longhand name="${name}" custom_cascade="${custom_cascade}"
-            experimental="${experimental}" internal="${internal}">
+    <%def name="single_keyword_computed(name, values, products='gecko,servo',
+                                        extra_gecko_values=None, extra_servo_values=None,
+                                        custom_cascade=False, experimental=False, internal=False)">
+        <%self:longhand name="${name}" keyword="${Keyword(name, values.split(),
+                                                          extra_gecko_values,
+                                                          extra_servo_values)}"
+                        products="${products}" custom_cascade="${custom_cascade}"
+                        experimental="${experimental}" internal="${internal}">
             pub use self::computed_value::T as SpecifiedValue;
             ${caller.body()}
             pub mod computed_value {
                 define_css_keyword_enum! { T:
-                    % for value in values.split():
+                    % for value in LONGHANDS_BY_NAME[name].keyword.values_for(CONFIG['product']):
                         "${value}" => ${to_rust_ident(value)},
                     % endfor
                 }
             }
             #[inline] pub fn get_initial_value() -> computed_value::T {
                 computed_value::T::${to_rust_ident(values.split()[0])}
             }
             pub fn parse(_context: &ParserContext, input: &mut Parser)
                          -> Result<SpecifiedValue, ()> {
                 computed_value::T::parse(input)
             }
         </%self:longhand>
     </%def>
 
-    <%def name="single_keyword(name, values, experimental=False, internal=False)">
+    <%def name="single_keyword(name, values, products='gecko,servo', experimental=False, internal=False)">
         <%self:single_keyword_computed name="${name}"
                                        values="${values}"
+                                       products="${products}"
                                        experimental="${experimental}"
                                        internal="${internal}">
             use values::computed::ComputedValueAsSpecified;
             impl ComputedValueAsSpecified for SpecifiedValue {}
         </%self:single_keyword_computed>
     </%def>
 
-    <%def name="predefined_type(name, type, initial_value, parse_method='parse')">
-        <%self:longhand name="${name}">
+    <%def name="predefined_type(name, type, initial_value, parse_method='parse', products='gecko,servo')">
+        <%self:longhand name="${name}" products="${products}">
             #[allow(unused_imports)]
             use app_units::Au;
             pub type SpecifiedValue = specified::${type};
             pub mod computed_value {
                 pub use values::computed::${type} as T;
             }
             #[inline] pub fn get_initial_value() -> computed_value::T { ${initial_value} }
             #[inline] pub fn parse(_context: &ParserContext, input: &mut Parser)
--- a/servo/ports/geckolib/Cargo.toml
+++ b/servo/ports/geckolib/Cargo.toml
@@ -32,8 +32,9 @@ features = ["release_max_level_info"]
 [dependencies.plugins]
 path = "../../components/plugins"
 
 [dependencies.util]
 path = "../../components/util"
 
 [dependencies.style]
 path = "../../components/style"
+features = ["gecko"]
--- a/servo/ports/geckolib/build.rs
+++ b/servo/ports/geckolib/build.rs
@@ -54,17 +54,17 @@ fn main() {
         .arg(r#"
 import json
 import os
 import sys
 from mako.template import Template
 from mako import exceptions
 try:
     style_template = Template(filename=os.environ['STYLE_TEMPLATE'], input_encoding='utf8')
-    style_template.render()
+    style_template.render(PRODUCT='gecko')
 
     geckolib_template = Template(filename=os.environ['GECKOLIB_TEMPLATE'], input_encoding='utf8')
     output = geckolib_template.render(STYLE_STRUCTS = style_template.module.STYLE_STRUCTS,
                                       LONGHANDS = style_template.module.LONGHANDS)
     print(output.encode('utf8'))
 except:
     sys.stderr.write(exceptions.text_error_template().render().encode('utf8'))
     sys.exit(1)