Allow disabling invalidation-based querySelector from C++
Rust compile times are hard.
MozReview-Commit-ID: 9Xhtf7f3Vzv
--- 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 _,