diff options
author | bors-servo <lbergstrom+bors@mozilla.com> | 2018-07-01 05:14:21 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-07-01 05:14:21 -0400 |
commit | c71c55e542c57f6ec4e5e77be750f74f50340e56 (patch) | |
tree | 730aad03158a733d126d8cabe09e92792b31e05e /components/style/selector_map.rs | |
parent | 9c243a115ea4983bec5e79b06c49469354cfa1f9 (diff) | |
parent | 36495d677f6e5e928c74f8eb372caaae7a303047 (diff) | |
download | servo-c71c55e542c57f6ec4e5e77be750f74f50340e56.tar.gz servo-c71c55e542c57f6ec4e5e77be750f74f50340e56.zip |
Auto merge of #21109 - emilio:gecko-sync, r=SimonSapin
style: sync changes from mozilla-central.
See each individual commit for details..
<!-- 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/21109)
<!-- Reviewable:end -->
Diffstat (limited to 'components/style/selector_map.rs')
-rw-r--r-- | components/style/selector_map.rs | 51 |
1 files changed, 42 insertions, 9 deletions
diff --git a/components/style/selector_map.rs b/components/style/selector_map.rs index 3b9b6f20184..3b0dcca9525 100644 --- a/components/style/selector_map.rs +++ b/components/style/selector_map.rs @@ -5,7 +5,7 @@ //! A data structure to efficiently index structs containing selectors by local //! name, ids and hash. -use {Atom, LocalName, WeakAtom}; +use {Atom, LocalName, Namespace, WeakAtom}; use applicable_declarations::ApplicableDeclarationList; use context::QuirksMode; use dom::TElement; @@ -102,6 +102,8 @@ pub struct SelectorMap<T: 'static> { pub class_hash: MaybeCaseInsensitiveHashMap<Atom, SmallVec<[T; 1]>>, /// A hash from local name to rules which contain that local name selector. pub local_name_hash: PrecomputedHashMap<LocalName, SmallVec<[T; 1]>>, + /// A hash from namespace to rules which contain that namespace selector. + pub namespace_hash: PrecomputedHashMap<Namespace, SmallVec<[T; 1]>>, /// Rules that don't have ID, class, or element selectors. pub other: SmallVec<[T; 1]>, /// The number of entries in this map. @@ -125,6 +127,7 @@ impl<T: 'static> SelectorMap<T> { id_hash: MaybeCaseInsensitiveHashMap::new(), class_hash: MaybeCaseInsensitiveHashMap::new(), local_name_hash: HashMap::default(), + namespace_hash: HashMap::default(), other: SmallVec::new(), count: 0, } @@ -135,6 +138,7 @@ impl<T: 'static> SelectorMap<T> { self.id_hash.clear(); self.class_hash.clear(); self.local_name_hash.clear(); + self.namespace_hash.clear(); self.other.clear(); self.count = 0; } @@ -217,6 +221,18 @@ impl SelectorMap<Rule> { ) } + if let Some(rules) = self.namespace_hash.get(rule_hash_target.namespace()) { + SelectorMap::get_matching_rules( + element, + rules, + matching_rules_list, + context, + flags_setter, + cascade_level, + shadow_cascade_order, + ) + } + SelectorMap::get_matching_rules( element, &self.other, @@ -261,7 +277,8 @@ impl SelectorMap<Rule> { } impl<T: SelectorMapEntry> SelectorMap<T> { - /// Inserts into the correct hash, trying id, class, and localname. + /// Inserts into the correct hash, trying id, class, localname and + /// namespace. pub fn insert( &mut self, entry: T, @@ -298,13 +315,17 @@ impl<T: SelectorMapEntry> SelectorMap<T> { .try_entry(name.clone())? .or_insert_with(SmallVec::new) }, + Bucket::Namespace(url) => self.namespace_hash + .try_entry(url.clone())? + .or_insert_with(SmallVec::new), Bucket::Universal => &mut self.other, }; vector.try_push(entry) } - /// Looks up entries by id, class, local name, and other (in order). + /// Looks up entries by id, class, local name, namespace, and other (in + /// order). /// /// Each entry is passed to the callback, which returns true to continue /// iterating entries, or false to terminate the lookup. @@ -319,7 +340,6 @@ impl<T: SelectorMapEntry> SelectorMap<T> { E: TElement, F: FnMut(&'a T) -> bool, { - // Id. if let Some(id) = element.id() { if let Some(v) = self.id_hash.get(id, quirks_mode) { for entry in v.iter() { @@ -330,7 +350,6 @@ impl<T: SelectorMapEntry> SelectorMap<T> { } } - // Class. let mut done = false; element.each_class(|class| { if !done { @@ -348,7 +367,6 @@ impl<T: SelectorMapEntry> SelectorMap<T> { return false; } - // Local name. if let Some(v) = self.local_name_hash.get(element.local_name()) { for entry in v.iter() { if !f(&entry) { @@ -357,7 +375,14 @@ impl<T: SelectorMapEntry> SelectorMap<T> { } } - // Other. + if let Some(v) = self.namespace_hash.get(element.namespace()) { + for entry in v.iter() { + if !f(&entry) { + return false; + } + } + } + for entry in self.other.iter() { if !f(&entry) { return false; @@ -425,6 +450,7 @@ enum Bucket<'a> { name: &'a LocalName, lower_name: &'a LocalName, }, + Namespace(&'a Namespace), Universal, } @@ -436,6 +462,8 @@ fn specific_bucket_for<'a>(component: &'a Component<SelectorImpl>) -> Bucket<'a> name: &selector.name, lower_name: &selector.lower_name, }, + Component::Namespace(_, ref url) | + Component::DefaultNamespace(ref url) => Bucket::Namespace(url), // ::slotted(..) isn't a normal pseudo-element, so we can insert it on // the rule hash normally without much problem. For example, in a // selector like: @@ -470,7 +498,7 @@ fn find_bucket<'a>(mut iter: SelectorIter<'a, SelectorImpl>) -> Bucket<'a> { // We basically want to find the most specific bucket, // where: // - // id > class > local name > universal. + // id > class > local name > namespace > universal. // for ss in &mut iter { let new_bucket = specific_bucket_for(ss); @@ -480,10 +508,15 @@ fn find_bucket<'a>(mut iter: SelectorIter<'a, SelectorImpl>) -> Bucket<'a> { current_bucket = new_bucket; }, Bucket::LocalName { .. } => { - if matches!(current_bucket, Bucket::Universal) { + if matches!(current_bucket, Bucket::Universal | Bucket::Namespace(..)) { current_bucket = new_bucket; } }, + Bucket::Namespace(..) => { + if matches!(current_bucket, Bucket::Universal) { + current_bucket = new_bucket; + } + } Bucket::Universal => {}, } } |