mirror of
https://github.com/servo/servo.git
synced 2025-08-06 14:10:11 +01:00
style: Implement shadow part forwarding (minus invalidation).
Some of the stuff, in particular inside GeckoBindings stuff should be refactored to be less ugly and duplicate a bit less code, but the rest of the code should be landable as is. Some invalidation changes are already needed because we weren't matching with the right shadow host during invalidation (which made existing ::part() tests fail). Pending invalidation work: * Making exportparts work right on the snapshots. * Invalidating parts from descendant hosts. They're not very hard but I need to think how to best implement it: * Maybe get rid of ShadowRoot::mParts and just walk DOM descendants in the Shadow DOM. * Maybe implement a ElementHasExportPartsAttr much like HasPartAttr and use that to keep the list of elements. * Maybe invalidate :host and ::part() together in here[1] * Maybe something else. Opinions? [1]: https://searchfox.org/mozilla-central/rev/131338e5017bc0283d86fb73844407b9a2155c98/servo/components/style/invalidation/element/invalidator.rs#561 Differential Revision: https://phabricator.services.mozilla.com/D53730
This commit is contained in:
parent
576883d538
commit
e3009a4de9
9 changed files with 180 additions and 47 deletions
|
@ -8,6 +8,7 @@ use crate::nth_index_cache::NthIndexCacheInner;
|
|||
use crate::parser::{AncestorHashes, Combinator, Component, LocalName};
|
||||
use crate::parser::{NonTSPseudoClass, Selector, SelectorImpl, SelectorIter, SelectorList};
|
||||
use crate::tree::Element;
|
||||
use smallvec::SmallVec;
|
||||
use std::borrow::Borrow;
|
||||
use std::iter;
|
||||
|
||||
|
@ -667,7 +668,41 @@ where
|
|||
|
||||
match *selector {
|
||||
Component::Combinator(_) => unreachable!(),
|
||||
Component::Part(ref parts) => parts.iter().all(|part| element.is_part(part)),
|
||||
Component::Part(ref parts) => {
|
||||
let mut hosts = SmallVec::<[E; 4]>::new();
|
||||
|
||||
let mut host = match element.containing_shadow_host() {
|
||||
Some(h) => h,
|
||||
None => return false,
|
||||
};
|
||||
|
||||
loop {
|
||||
let outer_host = host.containing_shadow_host();
|
||||
if outer_host.as_ref().map(|h| h.opaque()) == context.shared.current_host {
|
||||
break;
|
||||
}
|
||||
let outer_host = match outer_host {
|
||||
Some(h) => h,
|
||||
None => return false,
|
||||
};
|
||||
// TODO(emilio): if worth it, we could early return if
|
||||
// host doesn't have the exportparts attribute.
|
||||
hosts.push(host);
|
||||
host = outer_host;
|
||||
}
|
||||
|
||||
// Translate the part into the right scope.
|
||||
parts.iter().all(|part| {
|
||||
let mut part = part.clone();
|
||||
for host in hosts.iter().rev() {
|
||||
part = match host.imported_part(&part) {
|
||||
Some(p) => p,
|
||||
None => return false,
|
||||
};
|
||||
}
|
||||
element.is_part(&part)
|
||||
})
|
||||
},
|
||||
Component::Slotted(ref selector) => {
|
||||
// <slots> are never flattened tree slottables.
|
||||
!element.is_html_slot_element() &&
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue