mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +01:00
style: Add a very simple invalidation-based querySelector.
MozReview-Commit-ID: Fimc8tz4OWX Signed-off-by: Emilio Cobos Álvarez <emilio@crisal.io>
This commit is contained in:
parent
7f5536d5bc
commit
6d78e9ba54
1 changed files with 128 additions and 0 deletions
|
@ -6,8 +6,11 @@
|
|||
//! and Gecko.
|
||||
|
||||
use context::QuirksMode;
|
||||
use dom::{TElement, TNode};
|
||||
use invalidation::element::invalidator::{Invalidation, InvalidationProcessor, InvalidationVector};
|
||||
use selectors::{Element, NthIndexCache, SelectorList};
|
||||
use selectors::matching::{self, MatchingContext, MatchingMode};
|
||||
use smallvec::SmallVec;
|
||||
|
||||
/// <https://dom.spec.whatwg.org/#dom-element-matches>
|
||||
pub fn element_matches<E>(
|
||||
|
@ -57,3 +60,128 @@ where
|
|||
|
||||
return None;
|
||||
}
|
||||
|
||||
/// The result of a querySelector call.
|
||||
pub type QuerySelectorResult<E> = SmallVec<[E; 128]>;
|
||||
|
||||
/// The query kind we're doing (either only the first descendant that matches or
|
||||
/// all of them).
|
||||
pub enum QuerySelectorKind {
|
||||
/// <https://dom.spec.whatwg.org/#dom-parentnode-queryselectorall>
|
||||
All,
|
||||
/// <https://dom.spec.whatwg.org/#dom-parentnode-queryselector>
|
||||
First,
|
||||
}
|
||||
|
||||
struct QuerySelectorProcessor<'a, E: TElement + 'a> {
|
||||
kind: QuerySelectorKind,
|
||||
results: &'a mut QuerySelectorResult<E>,
|
||||
matching_context: MatchingContext<'a, E::Impl>,
|
||||
selector_list: &'a SelectorList<E::Impl>,
|
||||
}
|
||||
|
||||
impl<'a, E> InvalidationProcessor<'a, E> for QuerySelectorProcessor<'a, E>
|
||||
where
|
||||
E: TElement + 'a,
|
||||
{
|
||||
fn collect_invalidations(
|
||||
&mut self,
|
||||
_element: E,
|
||||
self_invalidations: &mut InvalidationVector<'a>,
|
||||
descendant_invalidations: &mut InvalidationVector<'a>,
|
||||
_sibling_invalidations: &mut InvalidationVector<'a>,
|
||||
) -> bool {
|
||||
// FIXME(emilio): If the element is not a root element, and
|
||||
// selector_list has any descendant combinator, we need to do extra work
|
||||
// in order to handle properly things like:
|
||||
//
|
||||
// <div id="a">
|
||||
// <div id="b">
|
||||
// <div id="c"></div>
|
||||
// </div>
|
||||
// </div>
|
||||
//
|
||||
// b.querySelector('#a div'); // Should return "c".
|
||||
//
|
||||
let target_vector =
|
||||
if self.matching_context.scope_element.is_some() {
|
||||
descendant_invalidations
|
||||
} else {
|
||||
self_invalidations
|
||||
};
|
||||
|
||||
for selector in self.selector_list.0.iter() {
|
||||
target_vector.push(Invalidation::new(selector, 0))
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
fn matching_context(&mut self) -> &mut MatchingContext<'a, E::Impl> {
|
||||
&mut self.matching_context
|
||||
}
|
||||
|
||||
fn should_process_descendants(&mut self, _: E) -> bool {
|
||||
match self.kind {
|
||||
QuerySelectorKind::All => true,
|
||||
QuerySelectorKind::First => self.results.is_empty(),
|
||||
}
|
||||
}
|
||||
|
||||
fn invalidated_self(&mut self, e: E) {
|
||||
self.results.push(e);
|
||||
}
|
||||
|
||||
fn recursion_limit_exceeded(&mut self, _e: E) {}
|
||||
fn invalidated_descendants(&mut self, _e: E, _child: E) {}
|
||||
}
|
||||
|
||||
/// <https://dom.spec.whatwg.org/#dom-parentnode-queryselector>
|
||||
pub fn query_selector<E: TElement>(
|
||||
root: E::ConcreteNode,
|
||||
selector_list: &SelectorList<E::Impl>,
|
||||
results: &mut QuerySelectorResult<E>,
|
||||
kind: QuerySelectorKind,
|
||||
quirks_mode: QuirksMode,
|
||||
) {
|
||||
use invalidation::element::invalidator::TreeStyleInvalidator;
|
||||
|
||||
let mut nth_index_cache = NthIndexCache::default();
|
||||
let mut matching_context = MatchingContext::new(
|
||||
MatchingMode::Normal,
|
||||
None,
|
||||
Some(&mut nth_index_cache),
|
||||
quirks_mode,
|
||||
);
|
||||
|
||||
let root_element = root.as_element();
|
||||
matching_context.scope_element = root_element.map(|e| e.opaque());
|
||||
|
||||
let mut processor = QuerySelectorProcessor {
|
||||
kind,
|
||||
results,
|
||||
matching_context,
|
||||
selector_list,
|
||||
};
|
||||
|
||||
match root_element {
|
||||
Some(e) => {
|
||||
TreeStyleInvalidator::new(
|
||||
e,
|
||||
/* stack_limit_checker = */ None,
|
||||
&mut processor,
|
||||
).invalidate();
|
||||
}
|
||||
None => {
|
||||
for node in root.dom_children() {
|
||||
if let Some(e) = node.as_element() {
|
||||
TreeStyleInvalidator::new(
|
||||
e,
|
||||
/* stack_limit_checker = */ None,
|
||||
&mut processor,
|
||||
).invalidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue