diff options
author | Cameron McCormack <cam@mcc.id.au> | 2017-06-07 12:30:10 +0800 |
---|---|---|
committer | Cameron McCormack <cam@mcc.id.au> | 2017-06-08 09:37:09 +0800 |
commit | f492c8fe6ee08d67c5b91bfcbaac8a6f0097c410 (patch) | |
tree | f3274c4537289af4e9a734832878d3b152045930 /components/script/layout_wrapper.rs | |
parent | c7e25003111166cfe55d663bdf44ac112eac2dc6 (diff) | |
download | servo-f492c8fe6ee08d67c5b91bfcbaac8a6f0097c410.tar.gz servo-f492c8fe6ee08d67c5b91bfcbaac8a6f0097c410.zip |
style: Match :lang() using snapshots correctly.
Diffstat (limited to 'components/script/layout_wrapper.rs')
-rw-r--r-- | components/script/layout_wrapper.rs | 42 |
1 files changed, 36 insertions, 6 deletions
diff --git a/components/script/layout_wrapper.rs b/components/script/layout_wrapper.rs index 9ce38c6a187..f7f5396dc8d 100644 --- a/components/script/layout_wrapper.rs +++ b/components/script/layout_wrapper.rs @@ -69,7 +69,8 @@ use style::dom::{PresentationalHintsSynthesizer, TElement, TNode, UnsafeNode}; use style::element_state::*; use style::font_metrics::ServoMetricsProvider; use style::properties::{ComputedValues, PropertyDeclarationBlock}; -use style::selector_parser::{NonTSPseudoClass, PseudoElement, SelectorImpl, extended_filtering}; +use style::selector_parser::{AttrValue as SelectorAttrValue, NonTSPseudoClass, PseudoClassStringArg}; +use style::selector_parser::{PseudoElement, SelectorImpl, extended_filtering}; use style::shared_lock::{SharedRwLock as StyleSharedRwLock, Locked as StyleLocked}; use style::sink::Push; use style::str::is_whitespace; @@ -498,6 +499,39 @@ impl<'le> TElement for ServoLayoutElement<'le> { fn has_css_transitions(&self) -> bool { unreachable!("this should be only called on gecko"); } + + #[inline] + fn lang_attr(&self) -> Option<SelectorAttrValue> { + self.get_attr(&ns!(xml), &local_name!("lang")) + .or_else(|| self.get_attr(&ns!(), &local_name!("lang"))) + .map(|v| String::from(v as &str)) + } + + fn match_element_lang(&self, + override_lang: Option<Option<SelectorAttrValue>>, + value: &PseudoClassStringArg) + -> bool + { + // Servo supports :lang() from CSS Selectors 4, which can take a comma- + // separated list of language tags in the pseudo-class, and which + // performs RFC 4647 extended filtering matching on them. + // + // FIXME(heycam): This is wrong, since extended_filtering accepts + // a string containing commas (separating each language tag in + // a list) but the pseudo-class instead should be parsing and + // storing separate <ident> or <string>s for each language tag. + // + // FIXME(heycam): Look at `element`'s document's Content-Language + // HTTP header for language tags to match `value` against. To + // do this, we should make `get_lang_for_layout` return an Option, + // so we can decide when to fall back to the Content-Language check. + let element_lang = match override_lang { + Some(Some(lang)) => lang, + Some(None) => String::new(), + None => self.element.get_lang_for_layout(), + }; + extended_filtering(&element_lang, &*value) + } } impl<'le> PartialEq for ServoLayoutElement<'le> { @@ -690,11 +724,7 @@ impl<'le> ::selectors::Element for ServoLayoutElement<'le> { NonTSPseudoClass::AnyLink => self.is_link(), NonTSPseudoClass::Visited => false, - // FIXME(heycam): This is wrong, since extended_filtering accepts - // a string containing commas (separating each language tag in - // a list) but the pseudo-class instead should be parsing and - // storing separate <ident> or <string>s for each language tag. - NonTSPseudoClass::Lang(ref lang) => extended_filtering(&*self.element.get_lang_for_layout(), &*lang), + NonTSPseudoClass::Lang(ref lang) => self.match_element_lang(None, &*lang), NonTSPseudoClass::ServoNonZeroBorder => unsafe { match (*self.element.unsafe_get()).get_attr_for_layout(&ns!(), &local_name!("border")) { |