Bug 1487615 - Simplify the Lang pseudo-class stuff a bit. r=xidorn,firefox-style-system-reviewers
authorEmilio Cobos Álvarez <emilio@crisal.io>
Sun, 02 Sep 2018 22:54:12 +0000
changeset 492221 db4be1902e26e7f24954916a63dd718abcff9e96
parent 492220 f2ded2a48b5cc785b29103aa9ae40d1e6d28107d
child 492225 eb7bf7bd5b70241403e3c06b15447f98c06b144e
push id1815
push userffxbld-merge
push dateMon, 15 Oct 2018 10:40:45 +0000
treeherdermozilla-release@18d4c09e9378 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersxidorn, firefox-style-system-reviewers
bugs1487615
milestone63.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1487615 - Simplify the Lang pseudo-class stuff a bit. r=xidorn,firefox-style-system-reviewers Differential Revision: https://phabricator.services.mozilla.com/D4754
servo/components/style/dom.rs
servo/components/style/gecko/non_ts_pseudo_class_list.rs
servo/components/style/gecko/selector_parser.rs
servo/components/style/gecko/wrapper.rs
servo/components/style/servo/selector_parser.rs
--- a/servo/components/style/dom.rs
+++ b/servo/components/style/dom.rs
@@ -14,17 +14,17 @@ use atomic_refcell::{AtomicRef, AtomicRe
 use context::PostAnimationTasks;
 #[cfg(feature = "gecko")]
 use context::UpdateAnimationsTasks;
 use data::ElementData;
 use element_state::ElementState;
 use font_metrics::FontMetricsProvider;
 use media_queries::Device;
 use properties::{AnimationRules, ComputedValues, PropertyDeclarationBlock};
-use selector_parser::{AttrValue, PseudoClassStringArg, PseudoElement, SelectorImpl};
+use selector_parser::{AttrValue, Lang, PseudoElement, SelectorImpl};
 use selectors::Element as SelectorsElement;
 use selectors::matching::{ElementSelectorFlags, QuirksMode, VisitedHandlingMode};
 use selectors::sink::Push;
 use servo_arc::{Arc, ArcBorrow};
 use shared_lock::Locked;
 use std::fmt;
 use std::fmt::Debug;
 use std::hash::Hash;
@@ -890,17 +890,17 @@ pub trait TElement:
     /// Returns whether this element's language matches the language tag
     /// `value`.  If `override_lang` is not `None`, it specifies the value
     /// of the `xml:lang=""` or `lang=""` attribute to use in place of
     /// looking at the element and its ancestors.  (This argument is used
     /// to implement matching of `:lang()` against snapshots.)
     fn match_element_lang(
         &self,
         override_lang: Option<Option<AttrValue>>,
-        value: &PseudoClassStringArg,
+        value: &Lang,
     ) -> bool;
 
     /// Returns whether this element is the main body element of the HTML
     /// document it is on.
     fn is_html_document_body_element(&self) -> bool;
 
     /// Generate the proper applicable declarations due to presentational hints,
     /// and insert them into `hints`.
--- a/servo/components/style/gecko/non_ts_pseudo_class_list.rs
+++ b/servo/components/style/gecko/non_ts_pseudo_class_list.rs
@@ -7,44 +7,35 @@
  * pseudo-classes.
  *
 
  * FIXME: Find a way to autogenerate this file.
  *
  * Expected usage is as follows:
  * ```
  * 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),)*]) => {
- *      keyword: [$(($k_css:expr, $k_name:ident, $k_gecko_type:tt, $k_state:tt, $k_flags:tt),)*]) => {
+ *     ([$(($css:expr, $name:ident, $gecko_type:tt, $state:tt, $flags:tt),)*]) => {
  *         // do stuff
  *     }
  * }
  * apply_non_ts_list!(pseudo_class_macro)
  * ```
  *
- * The `string` and `keyword` variables will be applied to pseudoclasses that are of the form of
- * functions with string or keyword arguments.
- *
- * Pending pseudo-classes:
- *
- *  :scope -> <style scoped>, pending discussion.
- *
  * $gecko_type can be either "_" or an ident in Gecko's CSSPseudoClassType.
  * $state can be either "_" or an expression of type ElementState.  If present,
  *        the semantics are that the pseudo-class matches if any of the bits in
  *        $state are set on the element.
  * $flags can be either "_" or an expression of type NonTSPseudoClassFlag,
  * see selector_parser.rs for more details.
  */
 
 macro_rules! apply_non_ts_list {
     ($apply_macro:ident) => {
         $apply_macro! {
-            bare: [
+            [
                 ("-moz-table-border-nonzero", MozTableBorderNonzero, mozTableBorderNonzero, _, PSEUDO_CLASS_ENABLED_IN_UA_SHEETS),
                 ("-moz-browser-frame", MozBrowserFrame, mozBrowserFrame, _, PSEUDO_CLASS_ENABLED_IN_UA_SHEETS_AND_CHROME),
                 ("link", Link, link, IN_UNVISITED_STATE, _),
                 ("any-link", AnyLink, anyLink, IN_VISITED_OR_UNVISITED_STATE, _),
                 ("visited", Visited, visited, IN_VISITED_STATE, _),
                 ("active", Active, active, IN_ACTIVE_STATE, _),
                 ("checked", Checked, checked, IN_CHECKED_STATE, _),
                 ("defined", Defined, defined, IN_DEFINED_STATE, PSEUDO_CLASS_ENABLED_IN_UA_SHEETS_AND_CHROME),
@@ -106,15 +97,12 @@ macro_rules! apply_non_ts_list {
                 ("-moz-native-anonymous", MozNativeAnonymous, mozNativeAnonymous, _, PSEUDO_CLASS_ENABLED_IN_UA_SHEETS),
                 ("-moz-use-shadow-tree-root", MozUseShadowTreeRoot, mozUseShadowTreeRoot, _, PSEUDO_CLASS_ENABLED_IN_UA_SHEETS),
                 ("-moz-is-html", MozIsHTML, mozIsHTML, _, _),
                 ("-moz-placeholder", MozPlaceholder, mozPlaceholder, _, _),
                 ("-moz-lwtheme", MozLWTheme, mozLWTheme, _, _),
                 ("-moz-lwtheme-brighttext", MozLWThemeBrightText, mozLWThemeBrightText, _, _),
                 ("-moz-lwtheme-darktext", MozLWThemeDarkText, mozLWThemeDarkText, _, _),
                 ("-moz-window-inactive", MozWindowInactive, mozWindowInactive, _, _),
-            ],
-            string: [
-                ("lang", Lang, lang, _, _),
             ]
         }
     }
 }
--- a/servo/components/style/gecko/selector_parser.rs
+++ b/servo/components/style/gecko/selector_parser.rs
@@ -32,33 +32,30 @@ bitflags! {
         const PSEUDO_CLASS_ENABLED_IN_UA_SHEETS = 1 << 0;
         const PSEUDO_CLASS_ENABLED_IN_CHROME = 1 << 1;
         const PSEUDO_CLASS_ENABLED_IN_UA_SHEETS_AND_CHROME =
             NonTSPseudoClassFlag::PSEUDO_CLASS_ENABLED_IN_UA_SHEETS.bits |
             NonTSPseudoClassFlag::PSEUDO_CLASS_ENABLED_IN_CHROME.bits;
     }
 }
 
-/// The type used for storing pseudo-class string arguments.
-pub type PseudoClassStringArg = Atom;
+/// The type used to store the language argument to the `:lang` pseudo-class.
+pub type Lang = Atom;
 
 macro_rules! pseudo_class_name {
-    (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),)*]) => {
+    ([$(($css:expr, $name:ident, $gecko_type:tt, $state:tt, $flags:tt),)*]) => {
         /// Our representation of a non tree-structural pseudo-class.
         #[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq)]
         pub enum NonTSPseudoClass {
             $(
                 #[doc = $css]
                 $name,
             )*
-            $(
-                #[doc = $s_css]
-                $s_name(PseudoClassStringArg),
-            )*
+            /// The `:lang` pseudo-class.
+            Lang(Lang),
             /// The `:dir` pseudo-class.
             Dir(Direction),
             /// The non-standard `:-moz-any` pseudo-class.
             ///
             /// TODO(emilio): We disallow combinators and pseudos here, so we
             /// should use SimpleSelector instead
             MozAny(ThinBoxedSlice<Selector<SelectorImpl>>),
             /// The non-standard `:-moz-locale-dir` pseudo-class.
@@ -69,25 +66,24 @@ macro_rules! pseudo_class_name {
 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 {
-            (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),)*]) => {
+            ([$(($css:expr, $name:ident, $gecko_type:tt, $state:tt, $flags:tt),)*]) => {
                 match *self {
                     $(NonTSPseudoClass::$name => concat!(":", $css),)*
-                    $(NonTSPseudoClass::$s_name(ref s) => {
-                        write!(dest, concat!(":", $s_css, "("))?;
+                    NonTSPseudoClass::Lang(ref s) => {
+                        dest.write_str(":lang(")?;
                         serialize_atom_identifier(s, dest)?;
                         return dest.write_char(')');
-                    }, )*
+                    },
                     NonTSPseudoClass::MozLocaleDir(ref dir) => {
                         dest.write_str(":-moz-locale-dir(")?;
                         dir.to_css(&mut CssWriter::new(dest))?;
                         return dest.write_char(')')
                     },
                     NonTSPseudoClass::Dir(ref dir) => {
                         dest.write_str(":dir(")?;
                         dir.to_css(&mut CssWriter::new(dest))?;
@@ -132,18 +128,17 @@ impl Visit for NonTSPseudoClass {
 }
 
 impl NonTSPseudoClass {
     /// Parses the name and returns a non-ts-pseudo-class if succeeds.
     /// None otherwise. It doesn't check whether the pseudo-class is enabled
     /// in a particular state.
     pub fn parse_non_functional(name: &str) -> Option<Self> {
         macro_rules! pseudo_class_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),)*]) => {
+            ([$(($css:expr, $name:ident, $gecko_type:tt, $state:tt, $flags:tt),)*]) => {
                 match_ignore_ascii_case! { &name,
                     $($css => Some(NonTSPseudoClass::$name),)*
                     _ => None,
                 }
             }
         }
         apply_non_ts_list!(pseudo_class_parse)
     }
@@ -154,22 +149,21 @@ impl NonTSPseudoClass {
             (_) => {
                 false
             };
             ($flags:ident) => {
                 NonTSPseudoClassFlag::$flags.intersects(flags)
             };
         }
         macro_rules! pseudo_class_check_is_enabled_in {
-            (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),)*]) => {
+            ([$(($css:expr, $name:ident, $gecko_type:tt, $state:tt, $flags:tt),)*]) => {
                 match *self {
                     $(NonTSPseudoClass::$name => check_flag!($flags),)*
-                    $(NonTSPseudoClass::$s_name(..) => check_flag!($s_flags),)*
                     NonTSPseudoClass::MozLocaleDir(_) |
+                    NonTSPseudoClass::Lang(_) |
                     NonTSPseudoClass::Dir(_) |
                     NonTSPseudoClass::MozAny(_) => false,
                 }
             }
         }
         apply_non_ts_list!(pseudo_class_check_is_enabled_in)
     }
 
@@ -209,23 +203,22 @@ impl NonTSPseudoClass {
             (_) => {
                 ElementState::empty()
             };
             ($state:ident) => {
                 ElementState::$state
             };
         }
         macro_rules! pseudo_class_state {
-            (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),)*]) => {
+            ([$(($css:expr, $name:ident, $gecko_type:tt, $state:tt, $flags:tt),)*]) => {
                 match *self {
                     $(NonTSPseudoClass::$name => flag!($state),)*
-                    $(NonTSPseudoClass::$s_name(..) => flag!($s_state),)*
                     NonTSPseudoClass::Dir(..) |
                     NonTSPseudoClass::MozLocaleDir(..) |
+                    NonTSPseudoClass::Lang(..) |
                     NonTSPseudoClass::MozAny(..) => ElementState::empty(),
                 }
             }
         }
         apply_non_ts_list!(pseudo_class_state)
     }
 
     /// Get the document state flag associated with a pseudo-class, if any.
@@ -386,45 +379,39 @@ impl<'a, 'i> ::selectors::Parser<'i> for
         )
     }
 
     fn parse_non_ts_functional_pseudo_class<'t>(
         &self,
         name: CowRcStr<'i>,
         parser: &mut Parser<'i, 't>,
     ) -> Result<NonTSPseudoClass, ParseError<'i>> {
-        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 = parser.expect_ident_or_string()?;
-                        NonTSPseudoClass::$s_name(Atom::from(name.as_ref()))
-                    }, )*
-                    "-moz-locale-dir" => {
-                        NonTSPseudoClass::MozLocaleDir(Direction::parse(parser)?)
-                    },
-                    "dir" => {
-                        NonTSPseudoClass::Dir(Direction::parse(parser)?)
-                    },
-                    "-moz-any" => {
-                        NonTSPseudoClass::MozAny(
-                            selector_parser::parse_compound_selector_list(
-                                self,
-                                parser,
-                            )?.into()
-                        )
-                    }
-                    _ => return Err(parser.new_custom_error(
-                        SelectorParseErrorKind::UnsupportedPseudoClassOrElement(name.clone())
-                    ))
-                }
+        let pseudo_class = match_ignore_ascii_case! { &name,
+            "lang" => {
+                let name = parser.expect_ident_or_string()?;
+                NonTSPseudoClass::Lang(Atom::from(name.as_ref()))
+            },
+            "-moz-locale-dir" => {
+                NonTSPseudoClass::MozLocaleDir(Direction::parse(parser)?)
+            },
+            "dir" => {
+                NonTSPseudoClass::Dir(Direction::parse(parser)?)
+            },
+            "-moz-any" => {
+                NonTSPseudoClass::MozAny(
+                    selector_parser::parse_compound_selector_list(
+                        self,
+                        parser,
+                    )?.into()
+                )
             }
-        }
-        let pseudo_class = apply_non_ts_list!(pseudo_class_string_parse);
+            _ => return Err(parser.new_custom_error(
+                SelectorParseErrorKind::UnsupportedPseudoClassOrElement(name.clone())
+            ))
+        };
         if self.is_pseudo_class_enabled(&pseudo_class) {
             Ok(pseudo_class)
         } else {
             Err(
                 parser.new_custom_error(SelectorParseErrorKind::UnsupportedPseudoClassOrElement(
                     name,
                 )),
             )
--- a/servo/components/style/gecko/wrapper.rs
+++ b/servo/components/style/gecko/wrapper.rs
@@ -64,17 +64,17 @@ use gecko_bindings::sugar::ownership::{H
 use hash::FxHashMap;
 use logical_geometry::WritingMode;
 use media_queries::Device;
 use properties::{ComputedValues, LonghandId};
 use properties::{Importance, PropertyDeclaration, PropertyDeclarationBlock};
 use properties::animated_properties::{AnimationValue, AnimationValueMap};
 use properties::style_structs::Font;
 use rule_tree::CascadeLevel as ServoCascadeLevel;
-use selector_parser::{AttrValue, HorizontalDirection, PseudoClassStringArg};
+use selector_parser::{AttrValue, HorizontalDirection, Lang};
 use selectors::{Element, OpaqueElement};
 use selectors::attr::{AttrSelectorOperation, AttrSelectorOperator};
 use selectors::attr::{CaseSensitivity, NamespaceConstraint};
 use selectors::matching::{ElementSelectorFlags, MatchingContext};
 use selectors::matching::VisitedHandlingMode;
 use selectors::sink::Push;
 use servo_arc::{Arc, ArcBorrow, RawOffsetArc};
 use shared_lock::Locked;
@@ -1711,17 +1711,17 @@ impl<'le> TElement for GeckoElement<'le>
         } else {
             Some(unsafe { Atom::from_addrefed(ptr) })
         }
     }
 
     fn match_element_lang(
         &self,
         override_lang: Option<Option<AttrValue>>,
-        value: &PseudoClassStringArg,
+        value: &Lang,
     ) -> bool {
         // Gecko supports :lang() from CSS Selectors 3, which only accepts a
         // single language tag, and which performs simple dash-prefix matching
         // on it.
         let override_lang_ptr = match &override_lang {
             &Some(Some(ref atom)) => atom.as_ptr(),
             _ => ptr::null_mut(),
         };
--- a/servo/components/style/servo/selector_parser.rs
+++ b/servo/components/style/servo/selector_parser.rs
@@ -279,35 +279,35 @@ impl PseudoElement {
         if self.is_before_or_after() && style.ineffective_content_property() {
             return false;
         }
 
         true
     }
 }
 
-/// The type used for storing pseudo-class string arguments.
-pub type PseudoClassStringArg = Box<str>;
+/// The type used for storing `:lang` arguments.
+pub type Lang = Box<str>;
 
 /// A non tree-structural pseudo-class.
 /// See https://drafts.csswg.org/selectors-4/#structural-pseudos
 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
 #[cfg_attr(feature = "servo", derive(MallocSizeOf))]
 #[allow(missing_docs)]
 pub enum NonTSPseudoClass {
     Active,
     AnyLink,
     Checked,
     Disabled,
     Enabled,
     Focus,
     Fullscreen,
     Hover,
     Indeterminate,
-    Lang(PseudoClassStringArg),
+    Lang(Lang),
     Link,
     PlaceholderShown,
     ReadWrite,
     ReadOnly,
     ServoNonZeroBorder,
     ServoCaseSensitiveTypeAttr(Atom),
     Target,
     Visited,