diff --git a/components/style/gecko/non_ts_pseudo_class_list.rs b/components/style/gecko/non_ts_pseudo_class_list.rs index f18bbf839748..fce2c2968290 100644 --- a/components/style/gecko/non_ts_pseudo_class_list.rs +++ b/components/style/gecko/non_ts_pseudo_class_list.rs @@ -67,6 +67,11 @@ macro_rules! apply_non_ts_list { ], string: [ ("-moz-system-metric", MozSystemMetric, mozSystemMetric, _, PSEUDO_CLASS_INTERNAL), + ("-moz-locale-dir", MozLocaleDir, mozLocaleDir, _, PSEUDO_CLASS_INTERNAL), + ("-moz-empty-except-children-with-localname", MozEmptyExceptChildrenWithLocalname, + mozEmptyExceptChildrenWithLocalname, _, PSEUDO_CLASS_INTERNAL), + ("dir", Dir, dir, _, _), + ("lang", Lang, lang, _, _), ] } } diff --git a/components/style/gecko/selector_parser.rs b/components/style/gecko/selector_parser.rs index 25785beee023..3eccac4443c6 100644 --- a/components/style/gecko/selector_parser.rs +++ b/components/style/gecko/selector_parser.rs @@ -151,7 +151,7 @@ macro_rules! pseudo_class_name { )* $( #[doc = $s_css] - $s_name(Box), + $s_name(Box<[u16]>), )* /// The non-standard `:-moz-any` pseudo-class. MozAny(Vec>), @@ -162,13 +162,20 @@ apply_non_ts_list!(pseudo_class_name); impl ToCss for NonTSPseudoClass { fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + use cssparser::CssStringWriter; + use 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),)*]) => { match *self { $(NonTSPseudoClass::$name => concat!(":", $css),)* $(NonTSPseudoClass::$s_name(ref s) => { - return dest.write_str(&format!(":{}({})", $s_css, s)) + write!(dest, ":{}(", $s_css)?; + { + let mut css = CssStringWriter::new(dest); + css.write_str(&String::from_utf16(&s).unwrap())?; + } + return dest.write_str(")") }, )* NonTSPseudoClass::MozAny(ref selectors) => { dest.write_str(":-moz-any(")?; @@ -334,8 +341,11 @@ impl<'a> ::selectors::Parser for SelectorParser<'a> { 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) + let name = parser.expect_ident_or_string()?; + // convert to null terminated utf16 string + // since that's what Gecko deals with + let utf16: Vec = name.encode_utf16().chain(Some(0u16)).collect(); + NonTSPseudoClass::$s_name(utf16.into_boxed_slice()) }, )* "-moz-any" => { let selectors = parser.parse_comma_separated(|input| { diff --git a/components/style/gecko/wrapper.rs b/components/style/gecko/wrapper.rs index b9cab601f2c4..d98546734b36 100644 --- a/components/style/gecko/wrapper.rs +++ b/components/style/gecko/wrapper.rs @@ -35,6 +35,7 @@ use gecko_bindings::bindings::Gecko_GetAnimationRule; use gecko_bindings::bindings::Gecko_GetHTMLPresentationAttrDeclarationBlock; use gecko_bindings::bindings::Gecko_GetStyleAttrDeclarationBlock; use gecko_bindings::bindings::Gecko_GetStyleContext; +use gecko_bindings::bindings::Gecko_MatchStringArgPseudo; use gecko_bindings::bindings::Gecko_UpdateAnimations; use gecko_bindings::structs; use gecko_bindings::structs::{RawGeckoElement, RawGeckoNode}; @@ -702,10 +703,26 @@ impl<'le> ::selectors::Element for GeckoElement<'le> { NonTSPseudoClass::MozBrowserFrame => unsafe { Gecko_MatchesElement(pseudo_class.to_gecko_pseudoclasstype().unwrap(), self.0) }, - NonTSPseudoClass::MozSystemMetric(_) => false, NonTSPseudoClass::MozAny(ref sels) => { sels.iter().any(|s| matches_complex_selector(s, self, None, relations, flags)) } + NonTSPseudoClass::MozSystemMetric(ref s) | + NonTSPseudoClass::MozLocaleDir(ref s) | + NonTSPseudoClass::MozEmptyExceptChildrenWithLocalname(ref s) | + NonTSPseudoClass::Dir(ref s) | + NonTSPseudoClass::Lang(ref s) => { + use selectors::matching::HAS_SLOW_SELECTOR; + unsafe { + let mut set_slow_selector = false; + let matches = Gecko_MatchStringArgPseudo(self.0, + pseudo_class.to_gecko_pseudoclasstype().unwrap(), + s.as_ptr(), &mut set_slow_selector); + if set_slow_selector { + *flags |= HAS_SLOW_SELECTOR; + } + matches + } + } } } diff --git a/components/style/gecko_bindings/bindings.rs b/components/style/gecko_bindings/bindings.rs index b28183c6ab38..7c2ccb6450c4 100644 --- a/components/style/gecko_bindings/bindings.rs +++ b/components/style/gecko_bindings/bindings.rs @@ -1003,6 +1003,12 @@ extern "C" { RawGeckoPresContextBorrowed) -> nscolor; } +extern "C" { + pub fn Gecko_MatchStringArgPseudo(element: RawGeckoElementBorrowed, + type_: CSSPseudoClassType, + ident: *const u16, + set_slow_selector: *mut bool) -> bool; +} extern "C" { pub fn Gecko_Construct_Default_nsStyleFont(ptr: *mut nsStyleFont, pres_context: