mirror of
https://github.com/servo/servo.git
synced 2025-08-04 05:00:08 +01:00
style: Invalidate shadow part pseudo-class styles correctly.
I was going to send a test for `:focus` via wpt, but then realized it was probably not spec-compliant with the new rules people want to follow for :focus, so I filed https://github.com/w3c/csswg-drafts/issues/4555 instead. Testing `:hover` / `:active` via wpt looked quite a bit of a hassle. Differential Revision: https://phabricator.services.mozilla.com/D55591
This commit is contained in:
parent
6973317a58
commit
7cd59da2a0
3 changed files with 53 additions and 4 deletions
|
@ -807,6 +807,9 @@ pub trait TElement:
|
||||||
/// data if it comes from Shadow DOM.
|
/// data if it comes from Shadow DOM.
|
||||||
///
|
///
|
||||||
/// Returns whether normal document author rules should apply.
|
/// Returns whether normal document author rules should apply.
|
||||||
|
///
|
||||||
|
/// TODO(emilio): We could separate the invalidation data for elements
|
||||||
|
/// matching in other scopes to avoid over-invalidation.
|
||||||
fn each_applicable_non_document_style_rule_data<'a, F>(&self, mut f: F) -> bool
|
fn each_applicable_non_document_style_rule_data<'a, F>(&self, mut f: F) -> bool
|
||||||
where
|
where
|
||||||
Self: 'a,
|
Self: 'a,
|
||||||
|
@ -841,11 +844,42 @@ pub trait TElement:
|
||||||
// Slots can only have assigned nodes when in a shadow tree.
|
// Slots can only have assigned nodes when in a shadow tree.
|
||||||
let shadow = slot.containing_shadow().unwrap();
|
let shadow = slot.containing_shadow().unwrap();
|
||||||
if let Some(data) = shadow.style_data() {
|
if let Some(data) = shadow.style_data() {
|
||||||
f(data, shadow.host());
|
if data.any_slotted_rule() {
|
||||||
|
f(data, shadow.host());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
current = slot.assigned_slot();
|
current = slot.assigned_slot();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if target.has_part_attr() {
|
||||||
|
if let Some(mut inner_shadow) = target.containing_shadow() {
|
||||||
|
loop {
|
||||||
|
let inner_shadow_host = inner_shadow.host();
|
||||||
|
match inner_shadow_host.containing_shadow() {
|
||||||
|
Some(shadow) => {
|
||||||
|
if let Some(data) = shadow.style_data() {
|
||||||
|
if data.any_part_rule() {
|
||||||
|
f(data, shadow.host())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO: Could be more granular.
|
||||||
|
if !shadow.host().exports_any_part() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
inner_shadow = shadow;
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
// TODO(emilio): Should probably distinguish with
|
||||||
|
// MatchesDocumentRules::{No,Yes,IfPart} or
|
||||||
|
// something so that we could skip some work.
|
||||||
|
doc_rules_apply = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
doc_rules_apply
|
doc_rules_apply
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -348,7 +348,9 @@ where
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let outer_shadow = inner_shadow.host().containing_shadow();
|
|
||||||
|
let inner_shadow_host = inner_shadow.host();
|
||||||
|
let outer_shadow = inner_shadow_host.containing_shadow();
|
||||||
let part_rules = match outer_shadow {
|
let part_rules = match outer_shadow {
|
||||||
Some(shadow) => shadow
|
Some(shadow) => shadow
|
||||||
.style_data()
|
.style_data()
|
||||||
|
@ -387,8 +389,6 @@ where
|
||||||
shadow_cascade_order.inc();
|
shadow_cascade_order.inc();
|
||||||
}
|
}
|
||||||
|
|
||||||
let inner_shadow_host = inner_shadow.host();
|
|
||||||
|
|
||||||
inner_shadow = match outer_shadow {
|
inner_shadow = match outer_shadow {
|
||||||
Some(s) => s,
|
Some(s) => s,
|
||||||
None => break, // Nowhere to export to.
|
None => break, // Nowhere to export to.
|
||||||
|
|
|
@ -1889,18 +1889,33 @@ impl CascadeData {
|
||||||
self.host_rules.as_ref().and_then(|d| d.rules(pseudo))
|
self.host_rules.as_ref().and_then(|d| d.rules(pseudo))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Whether there's any host rule that could match in this scope.
|
||||||
|
pub fn any_host_rules(&self) -> bool {
|
||||||
|
self.host_rules.is_some()
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the slotted rule map for a given pseudo-element.
|
/// Returns the slotted rule map for a given pseudo-element.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn slotted_rules(&self, pseudo: Option<&PseudoElement>) -> Option<&SelectorMap<Rule>> {
|
pub fn slotted_rules(&self, pseudo: Option<&PseudoElement>) -> Option<&SelectorMap<Rule>> {
|
||||||
self.slotted_rules.as_ref().and_then(|d| d.rules(pseudo))
|
self.slotted_rules.as_ref().and_then(|d| d.rules(pseudo))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Whether there's any ::slotted rule that could match in this scope.
|
||||||
|
pub fn any_slotted_rule(&self) -> bool {
|
||||||
|
self.slotted_rules.is_some()
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the parts rule map for a given pseudo-element.
|
/// Returns the parts rule map for a given pseudo-element.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn part_rules(&self, pseudo: Option<&PseudoElement>) -> Option<&PartMap> {
|
pub fn part_rules(&self, pseudo: Option<&PseudoElement>) -> Option<&PartMap> {
|
||||||
self.part_rules.as_ref().and_then(|d| d.rules(pseudo))
|
self.part_rules.as_ref().and_then(|d| d.rules(pseudo))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Whether there's any ::part rule that could match in this scope.
|
||||||
|
pub fn any_part_rule(&self) -> bool {
|
||||||
|
self.part_rules.is_some()
|
||||||
|
}
|
||||||
|
|
||||||
/// Collects all the applicable media query results into `results`.
|
/// Collects all the applicable media query results into `results`.
|
||||||
///
|
///
|
||||||
/// This duplicates part of the logic in `add_stylesheet`, which is
|
/// This duplicates part of the logic in `add_stylesheet`, which is
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue