Allow disabling invalidation-based querySelector from C++ draft
authorEmilio Cobos Álvarez <emilio@crisal.io>
Mon, 30 Oct 2017 19:23:59 +0100
changeset 690495 1d405550746833a50385a679d1c221ca9e668ed1
parent 690494 8f38f864941b721a72d6560d5140e12895f97f91
child 690496 ea49bbcecea1e5b9bfbceb7292e470c237a37f95
push id87312
push userbmo:emilio@crisal.io
push dateThu, 02 Nov 2017 01:46:03 +0000
milestone58.0a1
Allow disabling invalidation-based querySelector from C++ Rust compile times are hard. MozReview-Commit-ID: 9Xhtf7f3Vzv
dom/base/nsINode.cpp
layout/style/ServoBindingList.h
servo/components/style/dom_apis.rs
servo/ports/geckolib/glue.rs
--- a/dom/base/nsINode.cpp
+++ b/dom/base/nsINode.cpp
@@ -2931,17 +2931,19 @@ nsINode::QuerySelector(const nsAString& 
 {
   return WithSelectorList<Element*>(
     aSelector,
     aResult,
     [&](const RawServoSelectorList* aList) -> Element* {
       if (!aList) {
         return nullptr;
       }
-      return const_cast<Element*>(Servo_SelectorList_QueryFirst(this, aList));
+      const bool useInvalidation = false;
+      return const_cast<Element*>(
+          Servo_SelectorList_QueryFirst(this, aList, useInvalidation));
     },
     [&](nsCSSSelectorList* aList) -> Element* {
       if (!aList) {
         // Either we failed (and aResult already has the exception), or this
         // is a pseudo-element-only selector that matches nothing.
         return nullptr;
       }
       ElementHolder holder;
@@ -2958,17 +2960,19 @@ nsINode::QuerySelectorAll(const nsAStrin
 
   WithSelectorList<void>(
     aSelector,
     aResult,
     [&](const RawServoSelectorList* aList) {
       if (!aList) {
         return;
       }
-      Servo_SelectorList_QueryAll(this, aList, contentList.get());
+      const bool useInvalidation = false;
+      Servo_SelectorList_QueryAll(
+        this, aList, contentList.get(), useInvalidation);
     },
     [&](nsCSSSelectorList* aList) {
       if (!aList) {
         return;
       }
       FindMatchingElements<false, AutoTArray<Element*, 128>>(
         this, aList, *contentList, aResult);
     }
--- a/layout/style/ServoBindingList.h
+++ b/layout/style/ServoBindingList.h
@@ -134,20 +134,22 @@ SERVO_BINDING_FUNC(Servo_SelectorList_Dr
 SERVO_BINDING_FUNC(Servo_SelectorList_Parse,
                    RawServoSelectorList*,
                    const nsACString* selector_list)
 SERVO_BINDING_FUNC(Servo_SelectorList_Matches, bool,
                    RawGeckoElementBorrowed, RawServoSelectorListBorrowed)
 SERVO_BINDING_FUNC(Servo_SelectorList_Closest, const RawGeckoElement*,
                    RawGeckoElementBorrowed, RawServoSelectorListBorrowed)
 SERVO_BINDING_FUNC(Servo_SelectorList_QueryFirst, const RawGeckoElement*,
-                   RawGeckoNodeBorrowed, RawServoSelectorListBorrowed)
+                   RawGeckoNodeBorrowed, RawServoSelectorListBorrowed,
+                   bool may_use_invalidation)
 SERVO_BINDING_FUNC(Servo_SelectorList_QueryAll, void,
                    RawGeckoNodeBorrowed, RawServoSelectorListBorrowed,
-                   nsSimpleContentList* content_list)
+                   nsSimpleContentList* content_list,
+                   bool may_use_invalidation)
 SERVO_BINDING_FUNC(Servo_StyleSet_AddSizeOfExcludingThis, void,
                    mozilla::MallocSizeOf malloc_size_of,
                    mozilla::MallocSizeOf malloc_enclosing_size_of,
                    mozilla::ServoStyleSetSizes* sizes,
                    RawServoStyleSetBorrowed set)
 SERVO_BINDING_FUNC(Servo_UACache_AddSizeOf, void,
                    mozilla::MallocSizeOf malloc_size_of,
                    mozilla::MallocSizeOf malloc_enclosing_size_of,
--- a/servo/components/style/dom_apis.rs
+++ b/servo/components/style/dom_apis.rs
@@ -497,21 +497,31 @@ where
     E: TElement,
     Q: SelectorQuery<E>,
 {
     collect_all_elements::<E, Q, _>(root, results, |element| {
         matching::matches_selector_list(selector_list, &element, matching_context)
     });
 }
 
+/// Whether the invalidation machinery should be used for this query.
+#[derive(PartialEq)]
+pub enum MayUseInvalidation {
+    /// We may use it if we deem it useful.
+    Yes,
+    /// Don't use it.
+    No,
+}
+
 /// <https://dom.spec.whatwg.org/#dom-parentnode-queryselector>
 pub fn query_selector<E, Q>(
     root: E::ConcreteNode,
     selector_list: &SelectorList<E::Impl>,
     results: &mut Q::Output,
+    may_use_invalidation: MayUseInvalidation,
 )
 where
     E: TElement,
     Q: SelectorQuery<E>,
 {
     use invalidation::element::invalidator::TreeStyleInvalidator;
 
     let quirks_mode = root.owner_doc().quirks_mode();
@@ -546,16 +556,17 @@ where
     // The invalidation mechanism is only useful in presence of combinators.
     //
     // We could do that check properly here, though checking the length of the
     // selectors is a good heuristic.
     //
     // A selector with a combinator needs to have a length of at least 3: A
     // simple selector, a combinator, and another simple selector.
     let invalidation_may_be_useful =
+        may_use_invalidation == MayUseInvalidation::Yes &&
         selector_list.0.iter().any(|s| s.len() > 2);
 
     if root_element.is_some() || !invalidation_may_be_useful {
         query_selector_slow::<E, Q>(
             root,
             selector_list,
             results,
             &mut matching_context,
--- a/servo/ports/geckolib/glue.rs
+++ b/servo/ports/geckolib/glue.rs
@@ -1690,50 +1690,69 @@ pub unsafe extern "C" fn Servo_SelectorL
         quirks_mode,
     )
 }
 
 #[no_mangle]
 pub unsafe extern "C" fn Servo_SelectorList_QueryFirst(
     node: RawGeckoNodeBorrowed,
     selectors: RawServoSelectorListBorrowed,
+    may_use_invalidation: bool,
 ) -> *const structs::RawGeckoElement {
     use std::borrow::Borrow;
-    use style::dom_apis::{self, QueryFirst};
+    use style::dom_apis::{self, MayUseInvalidation, QueryFirst};
 
     let node = GeckoNode(node);
     let selectors = ::selectors::SelectorList::from_ffi(selectors).borrow();
     let mut result = None;
+
+    let may_use_invalidation =
+        if may_use_invalidation {
+            MayUseInvalidation::Yes
+        } else {
+            MayUseInvalidation::No
+        };
+
     dom_apis::query_selector::<GeckoElement, QueryFirst>(
         node,
         &selectors,
         &mut result,
+        may_use_invalidation,
     );
 
     result.map_or(ptr::null(), |e| e.0)
 }
 
 #[no_mangle]
 pub unsafe extern "C" fn Servo_SelectorList_QueryAll(
     node: RawGeckoNodeBorrowed,
     selectors: RawServoSelectorListBorrowed,
     content_list: *mut structs::nsSimpleContentList,
+    may_use_invalidation: bool,
 ) {
     use smallvec::SmallVec;
     use std::borrow::Borrow;
-    use style::dom_apis::{self, QueryAll};
+    use style::dom_apis::{self, MayUseInvalidation, QueryAll};
 
     let node = GeckoNode(node);
     let selectors = ::selectors::SelectorList::from_ffi(selectors).borrow();
     let mut result = SmallVec::new();
 
+    let may_use_invalidation =
+        if may_use_invalidation {
+            MayUseInvalidation::Yes
+        } else {
+            MayUseInvalidation::No
+        };
+
     dom_apis::query_selector::<GeckoElement, QueryAll>(
         node,
         &selectors,
         &mut result,
+        may_use_invalidation,
     );
 
     if !result.is_empty() {
         // NOTE(emilio): This relies on a slice of GeckoElement having the same
         // memory representation than a slice of element pointers.
         bindings::Gecko_ContentList_AppendAll(
             content_list,
             result.as_ptr() as *mut *const _,