aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/layout_wrapper.rs
diff options
context:
space:
mode:
authorCameron McCormack <cam@mcc.id.au>2017-06-07 12:30:10 +0800
committerCameron McCormack <cam@mcc.id.au>2017-06-08 09:37:09 +0800
commitf492c8fe6ee08d67c5b91bfcbaac8a6f0097c410 (patch)
treef3274c4537289af4e9a734832878d3b152045930 /components/script/layout_wrapper.rs
parentc7e25003111166cfe55d663bdf44ac112eac2dc6 (diff)
downloadservo-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.rs42
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")) {