Skip to content

Commit

Permalink
Auto merge of #20046 - emilio:less-dumb, r=nox
Browse files Browse the repository at this point in the history
style: Move most of allowed_in to NonCustomPropertyId.

Also simplify the servo property id to gecko property id conversion to be faster
and less repetitive.

This is in preparation of some patches to properly allow disabled longhands on enabled shorthands, something that we don't contemplate right now.

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/20046)
<!-- Reviewable:end -->
  • Loading branch information
bors-servo committed Feb 14, 2018
2 parents 7945dff + 1548520 commit bdbb298
Showing 1 changed file with 108 additions and 125 deletions.
233 changes: 108 additions & 125 deletions components/style/properties/properties.mako.rs
Expand Up @@ -413,10 +413,112 @@ pub mod animated_properties {
<%include file="/helpers/animated_properties.mako.rs" />
}

/// A longhand or shorthand porperty
/// A longhand or shorthand property.
#[derive(Clone, Copy, Debug)]
pub struct NonCustomPropertyId(usize);

impl NonCustomPropertyId {
#[cfg(feature = "gecko")]
fn to_nscsspropertyid(self) -> nsCSSPropertyID {
static MAP: [nsCSSPropertyID; ${len(data.longhands) + len(data.shorthands) + len(data.all_aliases())}] = [
% for property in data.longhands:
${helpers.to_nscsspropertyid(property.ident)},
% endfor
% for property in data.shorthands:
${helpers.to_nscsspropertyid(property.ident)},
% endfor
% for property in data.all_aliases():
${helpers.alias_to_nscsspropertyid(property.ident)},
% endfor
];

MAP[self.0]
}

fn allowed_in(self, context: &ParserContext) -> bool {
debug_assert!(
matches!(
context.rule_type(),
CssRuleType::Keyframe | CssRuleType::Page | CssRuleType::Style
),
"Declarations are only expected inside a keyframe, page, or style rule."
);

<% id_set = static_non_custom_property_id_set %>

${id_set("DISALLOWED_IN_KEYFRAME_BLOCK", lambda p: not p.allowed_in_keyframe_block)}
${id_set("DISALLOWED_IN_PAGE_RULE", lambda p: not p.allowed_in_page_rule)}
match context.rule_type() {
CssRuleType::Keyframe if DISALLOWED_IN_KEYFRAME_BLOCK.contains(self) => {
return false;
}
CssRuleType::Page if DISALLOWED_IN_PAGE_RULE.contains(self) => {
return false;
}
_ => {}
}

// 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 p.enabled_in_content())}

let passes_pref_check = || {
% if product == "servo":
static PREF_NAME: [Option< &str>; ${len(data.longhands) + len(data.shorthands)}] = [
% for property in data.longhands + data.shorthands:
% if property.servo_pref:
Some("${property.servo_pref}"),
% else:
None,
% endif
% endfor
];
let pref = match PREF_NAME[self.0] {
None => return true,
Some(pref) => pref,
};

PREFS.get(pref).as_boolean().unwrap_or(false)
% else:
unsafe { structs::nsCSSProps_gPropertyEnabled[self.to_nscsspropertyid() as usize] }
% endif
};

if ALWAYS_ENABLED.contains(self) {
return true
}

if EXPERIMENTAL.contains(self) && passes_pref_check() {
return true
}

if context.stylesheet_origin == Origin::UserAgent &&
ENABLED_IN_UA_SHEETS.contains(self)
{
return true
}

if context.chrome_rules_enabled() && ENABLED_IN_CHROME.contains(self) {
return true
}

false
}
}

impl From<LonghandId> for NonCustomPropertyId {
fn from(id: LonghandId) -> Self {
NonCustomPropertyId(id as usize)
Expand Down Expand Up @@ -816,14 +918,9 @@ impl LonghandId {

/// Converts from a LonghandId to an adequate nsCSSPropertyID.
#[cfg(feature = "gecko")]
#[inline]
pub fn to_nscsspropertyid(self) -> nsCSSPropertyID {
match self {
% for property in data.longhands:
LonghandId::${property.camel_case} => {
${helpers.to_nscsspropertyid(property.ident)}
}
% endfor
}
NonCustomPropertyId::from(self).to_nscsspropertyid()
}

#[cfg(feature = "gecko")]
Expand Down Expand Up @@ -1038,14 +1135,9 @@ impl ShorthandId {

/// Converts from a ShorthandId to an adequate nsCSSPropertyID.
#[cfg(feature = "gecko")]
#[inline]
pub fn to_nscsspropertyid(self) -> nsCSSPropertyID {
match self {
% for property in data.shorthands:
ShorthandId::${property.camel_case} => {
${helpers.to_nscsspropertyid(property.ident)}
}
% endfor
}
NonCustomPropertyId::from(self).to_nscsspropertyid()
}

/// Get the longhand ids that form this shorthand.
Expand Down Expand Up @@ -1521,19 +1613,6 @@ impl PropertyId {
}
}

/// Returns an nsCSSPropertyID.
#[cfg(feature = "gecko")]
#[allow(non_upper_case_globals)]
pub fn to_nscsspropertyid(&self) -> Result<nsCSSPropertyID, ()> {
match *self {
PropertyId::Longhand(id) => Ok(id.to_nscsspropertyid()),
PropertyId::Shorthand(id) => Ok(id.to_nscsspropertyid()),
PropertyId::LonghandAlias(_, alias) => Ok(alias.to_nscsspropertyid()),
PropertyId::ShorthandAlias(_, alias) => Ok(alias.to_nscsspropertyid()),
_ => Err(())
}
}

/// Given this property id, get it either as a shorthand or as a
/// `PropertyDeclarationId`.
pub fn as_shorthand(&self) -> Result<ShorthandId, PropertyDeclarationId> {
Expand Down Expand Up @@ -1571,86 +1650,7 @@ impl PropertyId {
PropertyId::LonghandAlias(_, alias_id) => alias_id.into(),
};

debug_assert!(
matches!(
context.rule_type(),
CssRuleType::Keyframe | CssRuleType::Page | CssRuleType::Style
),
"Declarations are only expected inside a keyframe, page, or style rule."
);

<% id_set = static_non_custom_property_id_set %>

${id_set("DISALLOWED_IN_KEYFRAME_BLOCK", lambda p: not p.allowed_in_keyframe_block)}
${id_set("DISALLOWED_IN_PAGE_RULE", lambda p: not p.allowed_in_page_rule)}
match context.rule_type() {
CssRuleType::Keyframe if DISALLOWED_IN_KEYFRAME_BLOCK.contains(id) => {
return false;
}
CssRuleType::Page if DISALLOWED_IN_PAGE_RULE.contains(id) => {
return false;
}
_ => {}
}

// 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 p.enabled_in_content())}

let passes_pref_check = || {
% if product == "servo":
static PREF_NAME: [Option< &str>; ${len(data.longhands) + len(data.shorthands)}] = [
% for property in data.longhands + data.shorthands:
% if property.servo_pref:
Some("${property.servo_pref}"),
% else:
None,
% endif
% endfor
];
let pref = match PREF_NAME[id.0] {
None => return true,
Some(pref) => pref,
};

PREFS.get(pref).as_boolean().unwrap_or(false)
% else:
unsafe { structs::nsCSSProps_gPropertyEnabled[self.to_nscsspropertyid().unwrap() as usize] }
% endif
};

if ALWAYS_ENABLED.contains(id) {
return true
}

if EXPERIMENTAL.contains(id) && passes_pref_check() {
return true
}

if context.stylesheet_origin == Origin::UserAgent &&
ENABLED_IN_UA_SHEETS.contains(id)
{
return true
}

if context.chrome_rules_enabled() && ENABLED_IN_CHROME.contains(id) {
return true
}

false
id.allowed_in(context)
}
}

Expand Down Expand Up @@ -3859,23 +3859,6 @@ impl fmt::Debug for AliasId {
}
}

impl AliasId {
/// Returns an nsCSSPropertyID.
#[cfg(feature = "gecko")]
#[allow(non_upper_case_globals)]
pub fn to_nscsspropertyid(&self) -> nsCSSPropertyID {
use gecko_bindings::structs::*;

match *self {
% for property in data.all_aliases():
AliasId::${property.camel_case} => {
${helpers.alias_to_nscsspropertyid(property.ident)}
},
% endfor
}
}
}

// FIXME(emilio): This macro doesn't account for experimental properties, so
// even with the pref disabled you can set them from CSSOM in Servo.
#[macro_export]
Expand Down

0 comments on commit bdbb298

Please sign in to comment.