diff --git a/servo/ports/geckolib/glue.rs b/servo/ports/geckolib/glue.rs index 0cf07c469c5f..f7a1357549b6 100644 --- a/servo/ports/geckolib/glue.rs +++ b/servo/ports/geckolib/glue.rs @@ -6,7 +6,7 @@ use cssparser::{Parser, ParserInput}; use cssparser::ToCss as ParserToCss; use env_logger::LogBuilder; use malloc_size_of::MallocSizeOfOps; -use selectors::{self, Element}; +use selectors::{self, Element, NthIndexCache}; use selectors::matching::{MatchingContext, MatchingMode, matches_selector}; use servo_arc::{Arc, ArcBorrow, RawOffsetArc}; use std::cell::RefCell; @@ -1520,6 +1520,36 @@ pub extern "C" fn Servo_StyleRule_SelectorMatchesElement(rule: RawServoStyleRule }) } +#[no_mangle] +pub unsafe extern "C" fn Servo_SelectorList_Closest<'a>( + element: RawGeckoElementBorrowed<'a>, + selectors: RawServoSelectorListBorrowed, +) -> RawGeckoElementBorrowedOrNull<'a> { + use std::borrow::Borrow; + + let mut nth_index_cache = NthIndexCache::default(); + + 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 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; +} + #[no_mangle] pub unsafe extern "C" fn Servo_SelectorList_Matches( element: RawGeckoElementBorrowed,