style: Move the single simple selector optimizations to a different function. draft
authorEmilio Cobos Álvarez <emilio@crisal.io>
Fri, 27 Oct 2017 11:58:35 +0200
changeset 690478 d925490a884bedba8c81459914c679a20bc3a7b7
parent 690477 6b97923790f04e48b9c4e7d6eb2fa7229328c96f
child 690479 d072aa344d893ce7079f466d5d66a55344fc2613
push id87308
push userbmo:emilio@crisal.io
push dateThu, 02 Nov 2017 01:16:37 +0000
milestone58.0a1
style: Move the single simple selector optimizations to a different function. MozReview-Commit-ID: EEM3AzW2A9s
servo/components/style/dom_apis.rs
--- 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