mirror of
https://github.com/servo/servo.git
synced 2025-08-05 13:40:08 +01:00
style: Add a few QuerySelector fast-paths.
Signed-off-by: Emilio Cobos Álvarez <emilio@crisal.io>
This commit is contained in:
parent
2274fd7ef3
commit
d73af807b7
1 changed files with 90 additions and 21 deletions
|
@ -189,19 +189,100 @@ where
|
||||||
fn invalidated_descendants(&mut self, _e: E, _child: E) {}
|
fn invalidated_descendants(&mut self, _e: E, _child: E) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn collect_all_elements<E, Q, F>(
|
||||||
|
root: E::ConcreteNode,
|
||||||
|
results: &mut Q::Output,
|
||||||
|
mut filter: F,
|
||||||
|
)
|
||||||
|
where
|
||||||
|
E: TElement,
|
||||||
|
Q: SelectorQuery<E>,
|
||||||
|
F: FnMut(E) -> bool,
|
||||||
|
{
|
||||||
|
for node in root.dom_descendants() {
|
||||||
|
let element = match node.as_element() {
|
||||||
|
Some(e) => e,
|
||||||
|
None => continue,
|
||||||
|
};
|
||||||
|
|
||||||
|
if !filter(element) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Q::append_element(results, element);
|
||||||
|
if Q::should_stop_after_first_match() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Fast paths for a given selector query.
|
/// Fast paths for a given selector query.
|
||||||
|
///
|
||||||
|
/// FIXME(emilio, nbp): This may very well be a good candidate for code to be
|
||||||
|
/// replaced by HolyJit :)
|
||||||
fn query_selector_fast<E, Q>(
|
fn query_selector_fast<E, Q>(
|
||||||
_root: E::ConcreteNode,
|
root: E::ConcreteNode,
|
||||||
_selector_list: &SelectorList<E::Impl>,
|
selector_list: &SelectorList<E::Impl>,
|
||||||
_results: &mut Q::Output,
|
results: &mut Q::Output,
|
||||||
_quirks_mode: QuirksMode,
|
quirks_mode: QuirksMode,
|
||||||
) -> Result<(), ()>
|
) -> Result<(), ()>
|
||||||
where
|
where
|
||||||
E: TElement,
|
E: TElement,
|
||||||
Q: SelectorQuery<E>,
|
Q: SelectorQuery<E>,
|
||||||
{
|
{
|
||||||
// FIXME(emilio): Implement :-)
|
use selectors::parser::{Component, LocalName};
|
||||||
Err(())
|
use std::borrow::Borrow;
|
||||||
|
|
||||||
|
// We need to return elements in document order, and reordering them
|
||||||
|
// afterwards is kinda silly.
|
||||||
|
if selector_list.0.len() > 1 {
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let selector = &selector_list.0[0];
|
||||||
|
|
||||||
|
// Let's just care about the easy cases for now.
|
||||||
|
//
|
||||||
|
// FIXME(emilio): Blink has a fast path for classes in ancestor combinators
|
||||||
|
// that may be worth stealing.
|
||||||
|
if selector.len() > 1 {
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let component = selector.iter().next().unwrap();
|
||||||
|
match *component {
|
||||||
|
Component::ExplicitUniversalType => {
|
||||||
|
collect_all_elements::<E, Q, _>(root, results, |_| true)
|
||||||
|
}
|
||||||
|
Component::ID(ref id) => {
|
||||||
|
// TODO(emilio): We may want to reuse Gecko's document ID table.
|
||||||
|
let case_sensitivity = quirks_mode.classes_and_ids_case_sensitivity();
|
||||||
|
collect_all_elements::<E, Q, _>(root, results, |element| {
|
||||||
|
element.has_id(id, case_sensitivity)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
Component::Class(ref class) => {
|
||||||
|
let case_sensitivity = quirks_mode.classes_and_ids_case_sensitivity();
|
||||||
|
collect_all_elements::<E, Q, _>(root, results, |element| {
|
||||||
|
element.has_class(class, case_sensitivity)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
Component::LocalName(LocalName { ref name, ref lower_name }) => {
|
||||||
|
collect_all_elements::<E, Q, _>(root, results, |element| {
|
||||||
|
if element.is_html_element_in_html_document() {
|
||||||
|
element.get_local_name() == lower_name.borrow()
|
||||||
|
} else {
|
||||||
|
element.get_local_name() == name.borrow()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// TODO(emilio): More fast paths?
|
||||||
|
_ => {
|
||||||
|
return Err(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Slow path for a given selector query.
|
// Slow path for a given selector query.
|
||||||
|
@ -215,21 +296,9 @@ where
|
||||||
E: TElement,
|
E: TElement,
|
||||||
Q: SelectorQuery<E>,
|
Q: SelectorQuery<E>,
|
||||||
{
|
{
|
||||||
for node in root.dom_descendants() {
|
collect_all_elements::<E, Q, _>(root, results, |element| {
|
||||||
let element = match node.as_element() {
|
matching::matches_selector_list(selector_list, &element, matching_context)
|
||||||
Some(e) => e,
|
});
|
||||||
None => continue,
|
|
||||||
};
|
|
||||||
|
|
||||||
if !matching::matches_selector_list(selector_list, &element, matching_context) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
Q::append_element(results, element);
|
|
||||||
if Q::should_stop_after_first_match() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <https://dom.spec.whatwg.org/#dom-parentnode-queryselector>
|
/// <https://dom.spec.whatwg.org/#dom-parentnode-queryselector>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue