diff options
author | bors-servo <lbergstrom+bors@mozilla.com> | 2017-03-16 00:01:19 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-03-16 00:01:19 -0700 |
commit | 78c8edfb0a0556b3a579214c42b5bae37f0d73fd (patch) | |
tree | 7326f655798873efa679cd5a0f08c2f8d32d4922 | |
parent | 261a51a13a4a7742a7362534ae92023dfe38e630 (diff) | |
parent | b37f991cb86aa969e87e16a8d3639ab930a43cb2 (diff) | |
download | servo-78c8edfb0a0556b3a579214c42b5bae37f0d73fd.tar.gz servo-78c8edfb0a0556b3a579214c42b5bae37f0d73fd.zip |
Auto merge of #15976 - Manishearth:stylo-stub-system-metric, r=heycam
stylo: Add parsing support for functional non-ts pseudoclasses, add stub -moz-system-metric pseudo
r=heycam from https://bugzilla.mozilla.org/show_bug.cgi?id=1341086
<!-- 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/15976)
<!-- Reviewable:end -->
-rw-r--r-- | components/style/gecko/non_ts_pseudo_class_list.rs | 51 | ||||
-rw-r--r-- | components/style/gecko/selector_parser.rs | 57 | ||||
-rw-r--r-- | components/style/gecko/wrapper.rs | 3 |
3 files changed, 79 insertions, 32 deletions
diff --git a/components/style/gecko/non_ts_pseudo_class_list.rs b/components/style/gecko/non_ts_pseudo_class_list.rs index ef0ec883d3d..0fc580cdc08 100644 --- a/components/style/gecko/non_ts_pseudo_class_list.rs +++ b/components/style/gecko/non_ts_pseudo_class_list.rs @@ -11,18 +11,18 @@ * * Expected usage is as follows: * ``` - * fn use_pseudo_class() { - * macro_rules! use_pseudo_class_list { - * ( $( - * ($css:expr, $name:ident, $gecko_type:tt, $state:tt, $flags:tt), - * )* ) => { - * // Do stuff. - * } + * macro_rules! pseudo_class_macro{ + * (bare: [$(($css:expr, $name:ident, $gecko_type:tt, $state:tt, $flags:tt),)*], + * string: [$(($s_css:expr, $s_name:ident, $s_gecko_type:tt, $s_state:tt, $s_flags:tt),)*]) => { + * // do stuff * } - * apply_non_ts_list!(use_pseudo_class_list) * } + * apply_non_ts_list!(pseudo_class_macro) * ``` * + * The string variables will be applied to pseudoclasses that are of the form + * of a function with a string argument. + * * $gecko_type can be either "_" or an ident in Gecko's CSSPseudoClassType. * $state can be either "_" or an expression of type ElementState. * $flags can be either "_" or an expression of type NonTSPseudoClassFlag, @@ -32,22 +32,27 @@ macro_rules! apply_non_ts_list { ($apply_macro:ident) => { $apply_macro! { - ("any-link", AnyLink, anyLink, _, _), - ("link", Link, link, _, _), - ("visited", Visited, visited, _, _), - ("active", Active, active, IN_ACTIVE_STATE, _), - ("focus", Focus, focus, IN_FOCUS_STATE, _), - ("fullscreen", Fullscreen, fullscreen, IN_FULLSCREEN_STATE, _), - ("hover", Hover, hover, IN_HOVER_STATE, _), - ("enabled", Enabled, enabled, IN_ENABLED_STATE, _), - ("disabled", Disabled, disabled, IN_DISABLED_STATE, _), - ("checked", Checked, checked, IN_CHECKED_STATE, _), - ("indeterminate", Indeterminate, indeterminate, IN_INDETERMINATE_STATE, _), - ("read-write", ReadWrite, _, IN_READ_WRITE_STATE, _), - ("read-only", ReadOnly, _, IN_READ_WRITE_STATE, _), + bare: [ + ("any-link", AnyLink, anyLink, _, _), + ("link", Link, link, _, _), + ("visited", Visited, visited, _, _), + ("active", Active, active, IN_ACTIVE_STATE, _), + ("focus", Focus, focus, IN_FOCUS_STATE, _), + ("fullscreen", Fullscreen, fullscreen, IN_FULLSCREEN_STATE, _), + ("hover", Hover, hover, IN_HOVER_STATE, _), + ("enabled", Enabled, enabled, IN_ENABLED_STATE, _), + ("disabled", Disabled, disabled, IN_DISABLED_STATE, _), + ("checked", Checked, checked, IN_CHECKED_STATE, _), + ("indeterminate", Indeterminate, indeterminate, IN_INDETERMINATE_STATE, _), + ("read-write", ReadWrite, _, IN_READ_WRITE_STATE, _), + ("read-only", ReadOnly, _, IN_READ_WRITE_STATE, _), - ("-moz-browser-frame", MozBrowserFrame, mozBrowserFrame, _, PSEUDO_CLASS_INTERNAL), - ("-moz-table-border-nonzero", MozTableBorderNonzero, mozTableBorderNonzero, _, PSEUDO_CLASS_INTERNAL), + ("-moz-browser-frame", MozBrowserFrame, mozBrowserFrame, _, PSEUDO_CLASS_INTERNAL), + ("-moz-table-border-nonzero", MozTableBorderNonzero, mozTableBorderNonzero, _, PSEUDO_CLASS_INTERNAL), + ], + string: [ + ("-moz-system-metric", MozSystemMetric, mozSystemMetric, _, PSEUDO_CLASS_INTERNAL), + ] } } } diff --git a/components/style/gecko/selector_parser.rs b/components/style/gecko/selector_parser.rs index efed114f657..d465b7fa791 100644 --- a/components/style/gecko/selector_parser.rs +++ b/components/style/gecko/selector_parser.rs @@ -4,7 +4,7 @@ //! Gecko-specific bits for selector-parsing. -use cssparser::ToCss; +use cssparser::{Parser, ToCss}; use element_state::ElementState; use gecko_bindings::structs::CSSPseudoClassType; use gecko_bindings::structs::nsIAtom; @@ -139,7 +139,8 @@ bitflags! { } macro_rules! pseudo_class_name { - ($(($css:expr, $name:ident, $_gecko_type:tt, $_state:tt, $_flags:tt),)*) => { + (bare: [$(($css:expr, $name:ident, $gecko_type:tt, $state:tt, $flags:tt),)*], + string: [$(($s_css:expr, $s_name:ident, $s_gecko_type:tt, $s_state:tt, $s_flags:tt),)*]) => { #[doc = "Our representation of a non tree-structural pseudo-class."] #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub enum NonTSPseudoClass { @@ -147,6 +148,10 @@ macro_rules! pseudo_class_name { #[doc = $css] $name, )* + $( + #[doc = $s_css] + $s_name(Box<str>), + )* } } } @@ -155,13 +160,18 @@ apply_non_ts_list!(pseudo_class_name); impl ToCss for NonTSPseudoClass { fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { macro_rules! pseudo_class_serialize { - ($(($css:expr, $name:ident, $_gecko_type:tt, $_state:tt, $_flags:tt),)*) => { + (bare: [$(($css:expr, $name:ident, $gecko_type:tt, $state:tt, $flags:tt),)*], + string: [$(($s_css:expr, $s_name:ident, $s_gecko_type:tt, $s_state:tt, $s_flags:tt),)*]) => { match *self { $(NonTSPseudoClass::$name => concat!(":", $css),)* + $(NonTSPseudoClass::$s_name(ref s) => { + return dest.write_str(&format!(":{}({})", $s_css, s)) + }, )* } } } - dest.write_str(apply_non_ts_list!(pseudo_class_serialize)) + let ser = apply_non_ts_list!(pseudo_class_serialize); + dest.write_str(ser) } } @@ -174,9 +184,11 @@ impl NonTSPseudoClass { ($flags:expr) => ($flags.contains(PSEUDO_CLASS_INTERNAL)); } macro_rules! pseudo_class_check_internal { - ($(($_css:expr, $name:ident, $_gecko_type:tt, $_state:tt, $flags:tt),)*) => { + (bare: [$(($css:expr, $name:ident, $gecko_type:tt, $state:tt, $flags:tt),)*], + string: [$(($s_css:expr, $s_name:ident, $s_gecko_type:tt, $s_state:tt, $s_flags:tt),)*]) => { match *self { $(NonTSPseudoClass::$name => check_flag!($flags),)* + $(NonTSPseudoClass::$s_name(..) => check_flag!($s_flags),)* } } } @@ -190,9 +202,11 @@ impl NonTSPseudoClass { ($state:ident) => (::element_state::$state); } macro_rules! pseudo_class_state { - ($(($_css:expr, $name:ident, $_gecko_type:tt, $state:tt, $_flags:tt),)*) => { + (bare: [$(($css:expr, $name:ident, $gecko_type:tt, $state:tt, $flags:tt),)*], + string: [$(($s_css:expr, $s_name:ident, $s_gecko_type:tt, $s_state:tt, $s_flags:tt),)*]) => { match *self { $(NonTSPseudoClass::$name => flag!($state),)* + $(NonTSPseudoClass::$s_name(..) => flag!($s_state),)* } } } @@ -207,9 +221,11 @@ impl NonTSPseudoClass { (Some(::gecko_bindings::structs::CSSPseudoClassType::$gecko_type)); } macro_rules! pseudo_class_geckotype { - ($(($_css:expr, $name:ident, $gecko_type:tt, $_state:tt, $_flags:tt),)*) => { + (bare: [$(($css:expr, $name:ident, $gecko_type:tt, $state:tt, $flags:tt),)*], + string: [$(($s_css:expr, $s_name:ident, $s_gecko_type:tt, $s_state:tt, $s_flags:tt),)*]) => { match *self { $(NonTSPseudoClass::$name => gecko_type!($gecko_type),)* + $(NonTSPseudoClass::$s_name(..) => gecko_type!($s_gecko_type),)* } } } @@ -249,7 +265,8 @@ impl<'a> ::selectors::Parser for SelectorParser<'a> { fn parse_non_ts_pseudo_class(&self, name: Cow<str>) -> Result<NonTSPseudoClass, ()> { macro_rules! pseudo_class_parse { - ($(($css:expr, $name:ident, $_gecko_type:tt, $_state:tt, $_flags:tt),)*) => { + (bare: [$(($css:expr, $name:ident, $gecko_type:tt, $state:tt, $flags:tt),)*], + string: [$(($s_css:expr, $s_name:ident, $s_gecko_type:tt, $s_state:tt, $s_flags:tt),)*]) => { match_ignore_ascii_case! { &name, $($css => NonTSPseudoClass::$name,)* _ => return Err(()) @@ -264,6 +281,30 @@ impl<'a> ::selectors::Parser for SelectorParser<'a> { } } + fn parse_non_ts_functional_pseudo_class(&self, + name: Cow<str>, + parser: &mut Parser) + -> Result<NonTSPseudoClass, ()> { + macro_rules! pseudo_class_string_parse { + (bare: [$(($css:expr, $name:ident, $gecko_type:tt, $state:tt, $flags:tt),)*], + string: [$(($s_css:expr, $s_name:ident, $s_gecko_type:tt, $s_state:tt, $s_flags:tt),)*]) => { + match_ignore_ascii_case! { &name, + $($s_css => { + let name = String::from(parser.expect_ident_or_string()?).into_boxed_str(); + NonTSPseudoClass::$s_name(name) + }, )* + _ => return Err(()) + } + } + } + let pseudo_class = apply_non_ts_list!(pseudo_class_string_parse); + if !pseudo_class.is_internal() || self.in_user_agent_stylesheet() { + Ok(pseudo_class) + } else { + Err(()) + } + } + fn parse_pseudo_element(&self, name: Cow<str>) -> Result<PseudoElement, ()> { match PseudoElement::from_slice(&name, self.in_user_agent_stylesheet()) { Some(pseudo) => Ok(pseudo), diff --git a/components/style/gecko/wrapper.rs b/components/style/gecko/wrapper.rs index 83cf8788bd4..2c1f07b28b1 100644 --- a/components/style/gecko/wrapper.rs +++ b/components/style/gecko/wrapper.rs @@ -661,7 +661,8 @@ impl<'le> ::selectors::Element for GeckoElement<'le> { NonTSPseudoClass::MozTableBorderNonzero | NonTSPseudoClass::MozBrowserFrame => unsafe { Gecko_MatchesElement(pseudo_class.to_gecko_pseudoclasstype().unwrap(), self.0) - } + }, + _ => false } } |