mirror of
https://github.com/servo/servo.git
synced 2025-08-04 21:20:23 +01:00
style: Add a query-selector fast path for attribute selectors in the rightmost compound
Differential Revision: https://phabricator.services.mozilla.com/D180553
This commit is contained in:
parent
de9fb7983a
commit
1ada5e9605
1 changed files with 44 additions and 2 deletions
|
@ -355,6 +355,15 @@ fn collect_elements_with_id<E, Q, F>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn has_attr<E>(element: E, local_name: &AtomIdent) -> bool
|
||||||
|
where
|
||||||
|
E: TElement,
|
||||||
|
{
|
||||||
|
let mut found = false;
|
||||||
|
element.each_attr_name(|name| found |= name == local_name);
|
||||||
|
found
|
||||||
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn local_name_matches<E>(element: E, local_name: &LocalName<E::Impl>) -> bool
|
fn local_name_matches<E>(element: E, local_name: &LocalName<E::Impl>) -> bool
|
||||||
where
|
where
|
||||||
|
@ -374,6 +383,23 @@ where
|
||||||
element.local_name() == &**chosen_name
|
element.local_name() == &**chosen_name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_attr_name(component: &Component<SelectorImpl>) -> Option<&AtomIdent> {
|
||||||
|
let (name, name_lower) = match component {
|
||||||
|
Component::AttributeInNoNamespace { ref local_name, .. } => return Some(local_name),
|
||||||
|
Component::AttributeInNoNamespaceExists {
|
||||||
|
ref local_name,
|
||||||
|
ref local_name_lower,
|
||||||
|
..
|
||||||
|
} => (local_name, local_name_lower),
|
||||||
|
Component::AttributeOther(ref attr) => (&attr.local_name, &attr.local_name_lower),
|
||||||
|
_ => return None,
|
||||||
|
};
|
||||||
|
if name != name_lower {
|
||||||
|
return None; // TODO: Maybe optimize this?
|
||||||
|
}
|
||||||
|
Some(name)
|
||||||
|
}
|
||||||
|
|
||||||
fn get_id(component: &Component<SelectorImpl>) -> Option<&AtomIdent> {
|
fn get_id(component: &Component<SelectorImpl>) -> Option<&AtomIdent> {
|
||||||
use selectors::attr::AttrSelectorOperator;
|
use selectors::attr::AttrSelectorOperator;
|
||||||
Some(match component {
|
Some(match component {
|
||||||
|
@ -441,6 +467,7 @@ where
|
||||||
|
|
||||||
enum SimpleFilter<'a> {
|
enum SimpleFilter<'a> {
|
||||||
Class(&'a AtomIdent),
|
Class(&'a AtomIdent),
|
||||||
|
Attr(&'a AtomIdent),
|
||||||
LocalName(&'a LocalName<SelectorImpl>),
|
LocalName(&'a LocalName<SelectorImpl>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -473,12 +500,16 @@ where
|
||||||
let class_and_id_case_sensitivity = matching_context.classes_and_ids_case_sensitivity();
|
let class_and_id_case_sensitivity = matching_context.classes_and_ids_case_sensitivity();
|
||||||
// Let's just care about the easy cases for now.
|
// Let's just care about the easy cases for now.
|
||||||
if selector.len() == 1 {
|
if selector.len() == 1 {
|
||||||
return query_selector_single_query::<E, Q>(
|
if query_selector_single_query::<E, Q>(
|
||||||
root,
|
root,
|
||||||
selector.iter().next().unwrap(),
|
selector.iter().next().unwrap(),
|
||||||
results,
|
results,
|
||||||
class_and_id_case_sensitivity,
|
class_and_id_case_sensitivity,
|
||||||
);
|
)
|
||||||
|
.is_ok()
|
||||||
|
{
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut iter = selector.iter();
|
let mut iter = selector.iter();
|
||||||
|
@ -577,6 +608,11 @@ where
|
||||||
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
if combinator.is_none() && simple_filter.is_none() {
|
||||||
|
if let Some(attr_name) = get_attr_name(other) {
|
||||||
|
simple_filter = Some(SimpleFilter::Attr(attr_name));
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -621,6 +657,12 @@ where
|
||||||
matching::matches_selector_list(selector_list, &element, matching_context)
|
matching::matches_selector_list(selector_list, &element, matching_context)
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
SimpleFilter::Attr(ref local_name) => {
|
||||||
|
collect_all_elements::<E, Q, _>(root, results, |element| {
|
||||||
|
has_attr(element, local_name) &&
|
||||||
|
matching::matches_selector_list(selector_list, &element, matching_context)
|
||||||
|
});
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue