style: Share code for Element::Closest.

This commit is contained in:
Emilio Cobos Álvarez 2017-10-13 13:04:35 +02:00
parent 9e6c49d479
commit f64f8b8be2
No known key found for this signature in database
GPG key ID: 056B727BB9C1027C
3 changed files with 47 additions and 40 deletions

View file

@ -2217,26 +2217,18 @@ impl ElementMethods for Element {
// https://dom.spec.whatwg.org/#dom-element-closest // https://dom.spec.whatwg.org/#dom-element-closest
fn Closest(&self, selectors: DOMString) -> Fallible<Option<DomRoot<Element>>> { fn Closest(&self, selectors: DOMString) -> Fallible<Option<DomRoot<Element>>> {
match SelectorParser::parse_author_origin_no_namespace(&selectors) { let selectors =
Err(_) => Err(Error::Syntax), match SelectorParser::parse_author_origin_no_namespace(&selectors) {
Ok(selectors) => { Err(_) => return Err(Error::Syntax),
let self_root = DomRoot::from_ref(self); Ok(selectors) => selectors,
let root = self.upcast::<Node>(); };
for element in root.inclusive_ancestors() {
if let Some(element) = DomRoot::downcast::<Element>(element) { let quirks_mode = document_from_node(self).quirks_mode();
let quirks_mode = document_from_node(self).quirks_mode(); Ok(dom_apis::element_closest(
// FIXME(bholley): Consider an nth-index cache here. DomRoot::from_ref(self),
let mut ctx = MatchingContext::new(MatchingMode::Normal, None, None, &selectors,
quirks_mode); quirks_mode,
ctx.scope_element = Some(self_root.opaque()); ))
if matches_selector_list(&selectors, &element, &mut ctx) {
return Ok(Some(element));
}
}
}
Ok(None)
}
}
} }
// https://dom.spec.whatwg.org/#dom-element-insertadjacentelement // https://dom.spec.whatwg.org/#dom-element-insertadjacentelement

View file

@ -6,7 +6,7 @@
//! and Gecko. //! and Gecko.
use context::QuirksMode; use context::QuirksMode;
use selectors::{Element, SelectorList}; use selectors::{Element, NthIndexCache, SelectorList};
use selectors::matching::{self, MatchingContext, MatchingMode}; use selectors::matching::{self, MatchingContext, MatchingMode};
/// https://dom.spec.whatwg.org/#dom-element-matches /// https://dom.spec.whatwg.org/#dom-element-matches
@ -27,3 +27,33 @@ where
context.scope_element = Some(element.opaque()); context.scope_element = Some(element.opaque());
matching::matches_selector_list(selector_list, element, &mut context) matching::matches_selector_list(selector_list, element, &mut context)
} }
/// https://dom.spec.whatwg.org/#dom-element-closest
pub fn element_closest<E>(
element: E,
selector_list: &SelectorList<E::Impl>,
quirks_mode: QuirksMode,
) -> Option<E>
where
E: Element,
{
let mut nth_index_cache = NthIndexCache::default();
let mut context = MatchingContext::new(
MatchingMode::Normal,
None,
Some(&mut nth_index_cache),
quirks_mode,
);
context.scope_element = Some(element.opaque());
let mut current = Some(element);
while let Some(element) = current.take() {
if matching::matches_selector_list(selector_list, &element, &mut context) {
return Some(element);
}
current = element.parent_element();
}
return None;
}

View file

@ -6,7 +6,7 @@ use cssparser::{Parser, ParserInput};
use cssparser::ToCss as ParserToCss; use cssparser::ToCss as ParserToCss;
use env_logger::LogBuilder; use env_logger::LogBuilder;
use malloc_size_of::MallocSizeOfOps; use malloc_size_of::MallocSizeOfOps;
use selectors::{self, Element, NthIndexCache}; use selectors::Element;
use selectors::matching::{MatchingContext, MatchingMode, matches_selector}; use selectors::matching::{MatchingContext, MatchingMode, matches_selector};
use servo_arc::{Arc, ArcBorrow, RawOffsetArc}; use servo_arc::{Arc, ArcBorrow, RawOffsetArc};
use std::cell::RefCell; use std::cell::RefCell;
@ -1526,28 +1526,13 @@ pub unsafe extern "C" fn Servo_SelectorList_Closest<'a>(
selectors: RawServoSelectorListBorrowed, selectors: RawServoSelectorListBorrowed,
) -> RawGeckoElementBorrowedOrNull<'a> { ) -> RawGeckoElementBorrowedOrNull<'a> {
use std::borrow::Borrow; use std::borrow::Borrow;
use style::dom_apis;
let mut nth_index_cache = NthIndexCache::default();
let element = GeckoElement(element); let element = GeckoElement(element);
let mut context = MatchingContext::new(
MatchingMode::Normal,
None,
Some(&mut nth_index_cache),
element.owner_document_quirks_mode(),
);
context.scope_element = Some(element.opaque());
let selectors = ::selectors::SelectorList::from_ffi(selectors).borrow(); let selectors = ::selectors::SelectorList::from_ffi(selectors).borrow();
let mut current = Some(element);
while let Some(element) = current.take() {
if selectors::matching::matches_selector_list(&selectors, &element, &mut context) {
return Some(element.0);
}
current = element.parent_element();
}
return None; dom_apis::element_closest(element, &selectors, element.owner_document_quirks_mode())
.map(|e| e.0)
} }
#[no_mangle] #[no_mangle]