aboutsummaryrefslogtreecommitdiffstats
path: root/components/style/selector_map.rs
diff options
context:
space:
mode:
authorbors-servo <lbergstrom+bors@mozilla.com>2018-07-01 05:14:21 -0400
committerGitHub <noreply@github.com>2018-07-01 05:14:21 -0400
commitc71c55e542c57f6ec4e5e77be750f74f50340e56 (patch)
tree730aad03158a733d126d8cabe09e92792b31e05e /components/style/selector_map.rs
parent9c243a115ea4983bec5e79b06c49469354cfa1f9 (diff)
parent36495d677f6e5e928c74f8eb372caaae7a303047 (diff)
downloadservo-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.rs51
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 => {},
}
}