зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1374017: Add namespace bucket for the selector map. r=heycam
After bug 1470163 we have some nasty selectors from mathml.css in every page. We only want to match them against MathML elements. This patch brings the global revalidation selectors from 14 to 2 in about:blank. Also halves the ones from XUL documents. MozReview-Commit-ID: nOVyknNcVm
This commit is contained in:
Родитель
88831b3bc5
Коммит
ac6fbf9730
|
@ -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 => {},
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче