--- a/servo/components/style/dom_apis.rs
+++ b/servo/components/style/dom_apis.rs
@@ -5,17 +5,19 @@
//! Generic implementations of some DOM APIs so they can be shared between Servo
//! and Gecko.
use context::QuirksMode;
use dom::{TDocument, TElement, TNode};
use invalidation::element::invalidator::{Invalidation, InvalidationProcessor, InvalidationVector};
use selectors::{Element, NthIndexCache, SelectorList};
use selectors::matching::{self, MatchingContext, MatchingMode};
+use selectors::parser::{Component, LocalName};
use smallvec::SmallVec;
+use std::borrow::Borrow;
/// <https://dom.spec.whatwg.org/#dom-element-matches>
pub fn element_matches<E>(
element: &E,
selector_list: &SelectorList<E::Impl>,
quirks_mode: QuirksMode,
) -> bool
where
@@ -213,50 +215,28 @@ where
Q::append_element(results, element);
if Q::should_stop_after_first_match() {
return;
}
}
}
-/// 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>(
+
+/// Fast paths for querySelector with a single simple selector.
+fn query_selector_single_query<E, Q>(
root: E::ConcreteNode,
- selector_list: &SelectorList<E::Impl>,
+ component: &Component<E::Impl>,
results: &mut Q::Output,
quirks_mode: QuirksMode,
) -> Result<(), ()>
where
E: TElement,
Q: SelectorQuery<E>,
{
- use selectors::parser::{Component, LocalName};
- 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| {
@@ -282,16 +262,53 @@ where
_ => {
return Err(())
}
}
Ok(())
}
+/// 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>(
+ root: E::ConcreteNode,
+ selector_list: &SelectorList<E::Impl>,
+ results: &mut Q::Output,
+ quirks_mode: QuirksMode,
+) -> Result<(), ()>
+where
+ E: TElement,
+ Q: SelectorQuery<E>,
+{
+ // 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.
+ if selector.len() == 1 {
+ return query_selector_single_query::<E, Q>(
+ root,
+ selector.iter().next().unwrap(),
+ results,
+ quirks_mode,
+ );
+ }
+
+ // FIXME(emilio): Implement better optimizations for compound selectors and
+ // such.
+ Err(())
+}
+
// Slow path for a given selector query.
fn query_selector_slow<E, Q>(
root: E::ConcreteNode,
selector_list: &SelectorList<E::Impl>,
results: &mut Q::Output,
matching_context: &mut MatchingContext<E::Impl>,
)
where