mirror of
https://github.com/servo/servo.git
synced 2025-06-21 07:38:59 +01:00
style: Add a fast path for querySelector/All with a single id selector using the doc ID table.
MozReview-Commit-ID: JVnDO890kn4 Signed-off-by: Emilio Cobos Álvarez <emilio@crisal.io>
This commit is contained in:
parent
f993693eb2
commit
60aec43dad
1 changed files with 47 additions and 1 deletions
|
@ -9,6 +9,7 @@ use context::QuirksMode;
|
||||||
use dom::{TDocument, TElement, TNode};
|
use dom::{TDocument, TElement, TNode};
|
||||||
use invalidation::element::invalidator::{Invalidation, InvalidationProcessor, InvalidationVector};
|
use invalidation::element::invalidator::{Invalidation, InvalidationProcessor, InvalidationVector};
|
||||||
use selectors::{Element, NthIndexCache, SelectorList};
|
use selectors::{Element, NthIndexCache, SelectorList};
|
||||||
|
use selectors::attr::CaseSensitivity;
|
||||||
use selectors::matching::{self, MatchingContext, MatchingMode};
|
use selectors::matching::{self, MatchingContext, MatchingMode};
|
||||||
use selectors::parser::{Component, LocalName};
|
use selectors::parser::{Component, LocalName};
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
|
@ -220,6 +221,23 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns whether a given element is descendant of a given `root` node.
|
||||||
|
///
|
||||||
|
/// NOTE(emilio): if root == element, this returns false.
|
||||||
|
fn element_is_descendant_of<E>(element: E, root: E::ConcreteNode) -> bool
|
||||||
|
where
|
||||||
|
E: TElement,
|
||||||
|
{
|
||||||
|
let mut current = element.as_node().parent_node();
|
||||||
|
while let Some(n) = current.take() {
|
||||||
|
if n == root {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
current = n.parent_node();
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
/// Fast paths for querySelector with a single simple selector.
|
/// Fast paths for querySelector with a single simple selector.
|
||||||
fn query_selector_single_query<E, Q>(
|
fn query_selector_single_query<E, Q>(
|
||||||
|
@ -237,8 +255,36 @@ where
|
||||||
collect_all_elements::<E, Q, _>(root, results, |_| true)
|
collect_all_elements::<E, Q, _>(root, results, |_| true)
|
||||||
}
|
}
|
||||||
Component::ID(ref id) => {
|
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();
|
let case_sensitivity = quirks_mode.classes_and_ids_case_sensitivity();
|
||||||
|
|
||||||
|
if case_sensitivity == CaseSensitivity::CaseSensitive &&
|
||||||
|
root.is_in_document()
|
||||||
|
{
|
||||||
|
let doc = root.owner_doc();
|
||||||
|
if let Ok(elements) = doc.elements_with_id(id) {
|
||||||
|
if root == doc.as_node() {
|
||||||
|
for element in elements {
|
||||||
|
Q::append_element(results, *element);
|
||||||
|
if Q::should_stop_after_first_match() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for element in elements {
|
||||||
|
if !element_is_descendant_of(*element, root) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Q::append_element(results, *element);
|
||||||
|
if Q::should_stop_after_first_match() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
collect_all_elements::<E, Q, _>(root, results, |element| {
|
collect_all_elements::<E, Q, _>(root, results, |element| {
|
||||||
element.has_id(id, case_sensitivity)
|
element.has_id(id, case_sensitivity)
|
||||||
})
|
})
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue