From bbfb7a47eb5a96a21357c4615e2f7311c5dccbfb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Thu, 16 Nov 2017 03:06:07 +0100 Subject: [PATCH] style: Add machinery to handle properties enabled in chrome. --- components/style/properties/data.py | 24 +++++++ .../style/properties/properties.mako.rs | 72 ++++++++++++------- 2 files changed, 69 insertions(+), 27 deletions(-) diff --git a/components/style/properties/data.py b/components/style/properties/data.py index f312861095d..3aa4ad38b76 100644 --- a/components/style/properties/data.py +++ b/components/style/properties/data.py @@ -210,6 +210,13 @@ class Longhand(object): return bool(self.gecko_pref) return bool(self.servo_pref) + # FIXME(emilio): Shorthand and Longhand should really share a base class. + def explicitly_enabled_in_ua_sheets(self): + return self.internal + + # TODO(emilio): Change the `internal` field to something like `enabled_in`. + def explicitly_enabled_in_chrome(self): + return False class Shorthand(object): @@ -264,6 +271,12 @@ class Shorthand(object): return bool(self.gecko_pref) return bool(self.servo_pref) + def explicitly_enabled_in_ua_sheets(self): + return self.internal + + def explicitly_enabled_in_chrome(self): + return False + class Alias(object): def __init__(self, name, original): @@ -276,6 +289,17 @@ class Alias(object): self.allowed_in_page_rule = original.allowed_in_page_rule self.allowed_in_keyframe_block = original.allowed_in_keyframe_block + def experimental(self, product): + if product == "gecko": + return bool(self.gecko_pref) + return bool(self.servo_pref) + + def explicitly_enabled_in_ua_sheets(self): + return self.internal + + def explicitly_enabled_in_chrome(self): + return False + class Method(object): def __init__(self, name, return_type=None, arg_types=None, is_mut=False): diff --git a/components/style/properties/properties.mako.rs b/components/style/properties/properties.mako.rs index a2695a08c22..a3471dc41d3 100644 --- a/components/style/properties/properties.mako.rs +++ b/components/style/properties/properties.mako.rs @@ -239,7 +239,7 @@ impl NonCustomPropertyIdSet { static ${name}: NonCustomPropertyIdSet = NonCustomPropertyIdSet { <% storage = [0] * ((len(data.longhands) + len(data.shorthands) + len(data.all_aliases()) - 1 + 32) / 32) - for i, property in enumerate(data.longhands + data.shorthands): + for i, property in enumerate(data.longhands + data.shorthands + data.all_aliases()): if is_member(property): storage[i / 32] |= 1 << (i % 32) %> @@ -1158,6 +1158,7 @@ impl PropertyId { Some(context) => context, None => { default = PropertyParserContext { + in_chrome_stylesheet: false, stylesheet_origin: Origin::Author, rule_type: CssRuleType::Style, }; @@ -1287,12 +1288,22 @@ impl PropertyId { _ => {} } - // For properties that are experimental but not internal, the pref will - // control its availability in all sheets. For properties that are - // both experimental and internal, the pref only controls its - // availability in non-UA sheets (and in UA sheets it is always available). - ${id_set("INTERNAL", lambda p: p.internal)} + // The semantics of these are kinda hard to reason about, what follows + // is a description of the different combinations that can happen with + // these three sets. + // + // Experimental properties are generally controlled by prefs, but an + // experimental property explicitly enabled in certain context (UA or + // chrome sheets) is always usable in the context regardless of the + // pref value. + // + // Non-experimental properties are either normal properties which are + // usable everywhere, or internal-only properties which are only usable + // in certain context they are explicitly enabled in. + ${id_set("ENABLED_IN_UA_SHEETS", lambda p: p.explicitly_enabled_in_ua_sheets())} + ${id_set("ENABLED_IN_CHROME", lambda p: p.explicitly_enabled_in_chrome())} ${id_set("EXPERIMENTAL", lambda p: p.experimental(product))} + ${id_set("ALWAYS_ENABLED", lambda p: not p.experimental(product) and not p.explicitly_enabled_in_ua_sheets())} let passes_pref_check = || { % if product == "servo": @@ -1305,42 +1316,48 @@ impl PropertyId { % endif % endfor ]; - match PREF_NAME[id.0] { - None => true, - Some(pref) => PREFS.get(pref).as_boolean().unwrap_or(false) - } - % endif - % if product == "gecko": + let pref = match PREF_NAME[id.0] { + None => return true, + Some(pref) => pref, + }; + + PREFS.get(pref).as_boolean().unwrap_or(false) + % else: let id = match alias { Some(alias_id) => alias_id.to_nscsspropertyid().unwrap(), None => self.to_nscsspropertyid().unwrap(), }; + unsafe { structs::nsCSSProps_gPropertyEnabled[id as usize] } % endif }; - if INTERNAL.contains(id) { - if context.stylesheet_origin != Origin::UserAgent { - if EXPERIMENTAL.contains(id) { - if !passes_pref_check() { - return Err(()) - } - } else { - return Err(()) - } - } - } else { - if EXPERIMENTAL.contains(id) && !passes_pref_check() { - return Err(()); - } + if ALWAYS_ENABLED.contains(id) { + return Ok(()) } - Ok(()) + if EXPERIMENTAL.contains(id) && passes_pref_check() { + return Ok(()) + } + + if context.stylesheet_origin == Origin::UserAgent && + ENABLED_IN_UA_SHEETS.contains(id) + { + return Ok(()) + } + + if context.in_chrome_stylesheet && ENABLED_IN_CHROME.contains(id) { + return Ok(()) + } + + Err(()) } } /// Parsing Context for PropertyId. pub struct PropertyParserContext { + /// Whether the property is parsed in a chrome:// stylesheet. + pub in_chrome_stylesheet: bool, /// The Origin of the stylesheet, whether it's a user, /// author or user-agent stylesheet. pub stylesheet_origin: Origin, @@ -1352,6 +1369,7 @@ impl PropertyParserContext { /// Creates a PropertyParserContext with given stylesheet origin and rule type. pub fn new(context: &ParserContext) -> Self { Self { + in_chrome_stylesheet: context.in_chrome_stylesheet(), stylesheet_origin: context.stylesheet_origin, rule_type: context.rule_type(), }