mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +01:00
style: Implement the functional :host(..) selector.
We could invalidate in a slightly more fine-grained way, but I don't think it's worth the churn vs. keeping the special-cases minimal. Bug: 1452640 Reviewed-by: xidorn MozReview-Commit-ID: 5DkQrgwg9GW
This commit is contained in:
parent
bfb9fe6159
commit
eaefaa890e
8 changed files with 82 additions and 47 deletions
|
@ -794,6 +794,14 @@ pub trait TElement
|
|||
);
|
||||
}
|
||||
|
||||
if let Some(shadow) = self.shadow_root() {
|
||||
f(
|
||||
shadow.style_data(),
|
||||
self.as_node().owner_doc().quirks_mode(),
|
||||
Some(shadow.host()),
|
||||
);
|
||||
}
|
||||
|
||||
let mut current = self.assigned_slot();
|
||||
while let Some(slot) = current {
|
||||
// Slots can only have assigned nodes when in a shadow tree.
|
||||
|
|
|
@ -207,16 +207,6 @@ impl InvalidationMap {
|
|||
})
|
||||
}
|
||||
|
||||
/// Adds a selector to this `InvalidationMap`. Returns Err(..) to
|
||||
/// signify OOM.
|
||||
pub fn note_selector(
|
||||
&mut self,
|
||||
selector: &Selector<SelectorImpl>,
|
||||
quirks_mode: QuirksMode,
|
||||
) -> Result<(), FailedAllocationError> {
|
||||
self.collect_invalidations_for(selector, quirks_mode)
|
||||
}
|
||||
|
||||
/// Clears this map, leaving it empty.
|
||||
pub fn clear(&mut self) {
|
||||
self.class_to_selector.clear();
|
||||
|
@ -228,13 +218,14 @@ impl InvalidationMap {
|
|||
self.has_class_attribute_selectors = false;
|
||||
}
|
||||
|
||||
// Returns Err(..) to signify OOM.
|
||||
fn collect_invalidations_for(
|
||||
/// Adds a selector to this `InvalidationMap`. Returns Err(..) to
|
||||
/// signify OOM.
|
||||
pub fn note_selector(
|
||||
&mut self,
|
||||
selector: &Selector<SelectorImpl>,
|
||||
quirks_mode: QuirksMode
|
||||
quirks_mode: QuirksMode,
|
||||
) -> Result<(), FailedAllocationError> {
|
||||
debug!("InvalidationMap::collect_invalidations_for({:?})", selector);
|
||||
debug!("InvalidationMap::note_selector({:?})", selector);
|
||||
|
||||
let mut iter = selector.iter();
|
||||
let mut combinator;
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
//! element styles need to be invalidated.
|
||||
|
||||
use context::StackLimitChecker;
|
||||
use dom::{TElement, TNode};
|
||||
use dom::{TElement, TNode, TShadowRoot};
|
||||
use selector_parser::SelectorImpl;
|
||||
use selectors::matching::{CompoundSelectorMatchingResult, MatchingContext};
|
||||
use selectors::matching::matches_compound_selector_from;
|
||||
|
@ -534,20 +534,22 @@ where
|
|||
|
||||
let mut any_descendant = false;
|
||||
|
||||
// NOTE(emilio): This should not be needed for Shadow DOM for normal
|
||||
// element state / attribute invalidations (it's needed for XBL though,
|
||||
// due to the weird way the anon content there works (it doesn't block
|
||||
// combinators)).
|
||||
// NOTE(emilio): This is only needed for Shadow DOM to invalidate
|
||||
// correctly on :host(..) changes. Instead of doing this, we could add
|
||||
// a third kind of invalidation list that walks shadow root children,
|
||||
// but it's not clear it's worth it.
|
||||
//
|
||||
// However, it's needed as of right now for document state invalidation,
|
||||
// were we rely on iterating every element that ends up in the composed
|
||||
// doc.
|
||||
//
|
||||
// Also, we could avoid having that special-case for document state
|
||||
// invalidations if we invalidate for document state changes per
|
||||
// subtree, though that's kind of annoying because we need to invalidate
|
||||
// the shadow host subtree (to handle :host and ::slotted), and the
|
||||
// actual shadow tree (to handle all other rules in the ShadowRoot).
|
||||
// Also, it's needed as of right now for document state invalidation,
|
||||
// where we rely on iterating every element that ends up in the composed
|
||||
// doc, but we could fix that invalidating per subtree.
|
||||
if let Some(root) = self.element.shadow_root() {
|
||||
any_descendant |=
|
||||
self.invalidate_dom_descendants_of(root.as_node(), invalidations);
|
||||
}
|
||||
|
||||
// This is needed for XBL (technically) unconditionally, because XBL
|
||||
// bindings do not block combinators in any way. However this is kinda
|
||||
// broken anyway, since we should be looking at XBL rules too.
|
||||
if let Some(anon_content) = self.element.xbl_binding_anonymous_content() {
|
||||
any_descendant |=
|
||||
self.invalidate_dom_descendants_of(anon_content, invalidations);
|
||||
|
|
|
@ -457,6 +457,7 @@ fn specific_bucket_for<'a>(
|
|||
//
|
||||
// Meanwhile taking the code path below is slower, but still correct.
|
||||
// Component::Slotted(ref selector) => find_bucket(selector.iter()),
|
||||
Component::Host(Some(ref selector)) => find_bucket(selector.iter()),
|
||||
_ => Bucket::Universal
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2238,7 +2238,10 @@ impl CascadeData {
|
|||
);
|
||||
|
||||
if rebuild_kind.should_rebuild_invalidation() {
|
||||
self.invalidation_map.note_selector(&rule.selector, quirks_mode)?;
|
||||
self.invalidation_map.note_selector(
|
||||
selector,
|
||||
quirks_mode,
|
||||
)?;
|
||||
let mut visitor = StylistSelectorVisitor {
|
||||
needs_revalidation: false,
|
||||
passed_rightmost_selector: false,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue