forked from mirrors/gecko-dev
Bug 1834876 - Part 2: Resolve starting style if we don't have before-change style. r=layout-reviewers,firefox-style-system-reviewers,emilio
Per spec, we define starting style for an element as the after-change style with @starting-style rules applied in addition. If an element does not have a before-change style for a given style change event, the starting style is used instead of the before-change style to compare with the after-change style to start transitions. The basic idea in this patch is: 1. We add a flag to indicate if this element may have starting style. We set this flag during its full matching, and store this flag in the element data. 2. So during process animations, we check this flag, if this element may have starting style and specifies transitions, we resolve the starting style. Use it as the before-change style. The implmentation in process_animations() and tests are in the following patches. Differential Revision: https://phabricator.services.mozilla.com/D208570
This commit is contained in:
parent
4c920b2d33
commit
d975b03929
11 changed files with 243 additions and 28 deletions
|
|
@ -70,6 +70,19 @@ impl VisitedHandlingMode {
|
|||
}
|
||||
}
|
||||
|
||||
/// The mode to use whether we should matching rules inside @starting-style.
|
||||
/// https://drafts.csswg.org/css-transitions-2/#starting-style
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub enum IncludeStartingStyle {
|
||||
/// All without rules inside @starting-style. This is for the most common case because the
|
||||
/// primary/pseudo styles doesn't use rules inside @starting-style.
|
||||
No,
|
||||
/// Get the starting style. The starting style for an element as the after-change style with
|
||||
/// @starting-style rules applied in addition. In other words, this matches all rules,
|
||||
/// including rules inside @starting-style.
|
||||
Yes,
|
||||
}
|
||||
|
||||
/// Whether we need to set selector invalidation flags on elements for this
|
||||
/// match request.
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
|
|
@ -191,6 +204,12 @@ where
|
|||
/// Controls how matching for links is handled.
|
||||
visited_handling: VisitedHandlingMode,
|
||||
|
||||
/// Controls if we should match rules in @starting-style.
|
||||
pub include_starting_style: IncludeStartingStyle,
|
||||
|
||||
/// Whether there are any rules inside @starting-style.
|
||||
pub has_starting_style: bool,
|
||||
|
||||
/// The current nesting level of selectors that we're matching.
|
||||
nesting_level: usize,
|
||||
|
||||
|
|
@ -239,6 +258,7 @@ where
|
|||
bloom_filter,
|
||||
selector_caches,
|
||||
VisitedHandlingMode::AllLinksUnvisited,
|
||||
IncludeStartingStyle::No,
|
||||
quirks_mode,
|
||||
needs_selector_flags,
|
||||
matching_for_invalidation,
|
||||
|
|
@ -251,6 +271,7 @@ where
|
|||
bloom_filter: Option<&'a BloomFilter>,
|
||||
selector_caches: &'a mut SelectorCaches,
|
||||
visited_handling: VisitedHandlingMode,
|
||||
include_starting_style: IncludeStartingStyle,
|
||||
quirks_mode: QuirksMode,
|
||||
needs_selector_flags: NeedsSelectorFlags,
|
||||
matching_for_invalidation: MatchingForInvalidation,
|
||||
|
|
@ -259,6 +280,8 @@ where
|
|||
matching_mode,
|
||||
bloom_filter,
|
||||
visited_handling,
|
||||
include_starting_style,
|
||||
has_starting_style: false,
|
||||
quirks_mode,
|
||||
classes_and_ids_case_sensitivity: quirks_mode.classes_and_ids_case_sensitivity(),
|
||||
needs_selector_flags,
|
||||
|
|
|
|||
|
|
@ -45,6 +45,9 @@ bitflags! {
|
|||
/// The former gives us stronger transitive guarantees that allows us to
|
||||
/// apply the style sharing cache to cousins.
|
||||
const PRIMARY_STYLE_REUSED_VIA_RULE_NODE = 1 << 2;
|
||||
|
||||
/// Whether this element may have matched rules inside @starting-style.
|
||||
const MAY_HAVE_STARTING_STYLE = 1 << 3;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -344,22 +347,28 @@ impl ElementData {
|
|||
let reused_via_rule_node = self
|
||||
.flags
|
||||
.contains(ElementDataFlags::PRIMARY_STYLE_REUSED_VIA_RULE_NODE);
|
||||
let may_have_starting_style = self
|
||||
.flags
|
||||
.contains(ElementDataFlags::MAY_HAVE_STARTING_STYLE);
|
||||
|
||||
PrimaryStyle {
|
||||
style: ResolvedStyle(self.styles.primary().clone()),
|
||||
reused_via_rule_node,
|
||||
may_have_starting_style,
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets a new set of styles, returning the old ones.
|
||||
pub fn set_styles(&mut self, new_styles: ResolvedElementStyles) -> ElementStyles {
|
||||
if new_styles.primary.reused_via_rule_node {
|
||||
self.flags
|
||||
.insert(ElementDataFlags::PRIMARY_STYLE_REUSED_VIA_RULE_NODE);
|
||||
} else {
|
||||
self.flags
|
||||
.remove(ElementDataFlags::PRIMARY_STYLE_REUSED_VIA_RULE_NODE);
|
||||
}
|
||||
self.flags.set(
|
||||
ElementDataFlags::PRIMARY_STYLE_REUSED_VIA_RULE_NODE,
|
||||
new_styles.primary.reused_via_rule_node,
|
||||
);
|
||||
self.flags.set(
|
||||
ElementDataFlags::MAY_HAVE_STARTING_STYLE,
|
||||
new_styles.primary.may_have_starting_style,
|
||||
);
|
||||
|
||||
mem::replace(&mut self.styles, new_styles.into())
|
||||
}
|
||||
|
||||
|
|
@ -542,4 +551,11 @@ impl ElementData {
|
|||
|
||||
n
|
||||
}
|
||||
|
||||
/// Returns true if this element data may need to compute the starting style for CSS
|
||||
/// transitions.
|
||||
#[inline]
|
||||
pub fn may_have_starting_style(&self) -> bool {
|
||||
self.flags.contains(ElementDataFlags::MAY_HAVE_STARTING_STYLE)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,8 +14,8 @@ use crate::invalidation::element::state_and_attributes;
|
|||
use crate::stylist::CascadeData;
|
||||
use dom::DocumentState;
|
||||
use selectors::matching::{
|
||||
MatchingContext, MatchingForInvalidation, MatchingMode, NeedsSelectorFlags, QuirksMode,
|
||||
SelectorCaches, VisitedHandlingMode,
|
||||
IncludeStartingStyle, MatchingContext, MatchingForInvalidation, MatchingMode,
|
||||
NeedsSelectorFlags, QuirksMode, SelectorCaches, VisitedHandlingMode,
|
||||
};
|
||||
|
||||
/// A struct holding the members necessary to invalidate document state
|
||||
|
|
@ -59,6 +59,7 @@ impl<'a, 'b, E: TElement, I> DocumentStateInvalidationProcessor<'a, 'b, E, I> {
|
|||
None,
|
||||
selector_caches,
|
||||
VisitedHandlingMode::AllLinksVisitedAndUnvisited,
|
||||
IncludeStartingStyle::No,
|
||||
quirks_mode,
|
||||
NeedsSelectorFlags::No,
|
||||
MatchingForInvalidation::No,
|
||||
|
|
|
|||
|
|
@ -26,8 +26,8 @@ use dom::ElementState;
|
|||
use fxhash::FxHashMap;
|
||||
use selectors::matching::{
|
||||
matches_compound_selector_from, matches_selector, CompoundSelectorMatchingResult,
|
||||
ElementSelectorFlags, MatchingContext, MatchingForInvalidation, MatchingMode,
|
||||
NeedsSelectorFlags, QuirksMode, SelectorCaches, VisitedHandlingMode,
|
||||
ElementSelectorFlags, IncludeStartingStyle, MatchingContext, MatchingForInvalidation,
|
||||
MatchingMode, NeedsSelectorFlags, QuirksMode, SelectorCaches, VisitedHandlingMode,
|
||||
};
|
||||
use selectors::parser::{Combinator, SelectorKey};
|
||||
use selectors::OpaqueElement;
|
||||
|
|
@ -822,6 +822,7 @@ where
|
|||
None,
|
||||
&mut selector_caches,
|
||||
VisitedHandlingMode::AllLinksVisitedAndUnvisited,
|
||||
IncludeStartingStyle::No,
|
||||
self.quirks_mode,
|
||||
NeedsSelectorFlags::No,
|
||||
MatchingForInvalidation::Yes,
|
||||
|
|
@ -1032,6 +1033,7 @@ where
|
|||
None,
|
||||
selector_caches,
|
||||
VisitedHandlingMode::AllLinksVisitedAndUnvisited,
|
||||
IncludeStartingStyle::No,
|
||||
quirks_mode,
|
||||
NeedsSelectorFlags::No,
|
||||
MatchingForInvalidation::Yes,
|
||||
|
|
|
|||
|
|
@ -24,7 +24,8 @@ use dom::ElementState;
|
|||
use selectors::attr::CaseSensitivity;
|
||||
use selectors::kleene_value::KleeneValue;
|
||||
use selectors::matching::{
|
||||
matches_selector_kleene, MatchingContext, MatchingForInvalidation, MatchingMode, NeedsSelectorFlags, SelectorCaches, VisitedHandlingMode
|
||||
matches_selector_kleene, IncludeStartingStyle, MatchingContext, MatchingForInvalidation,
|
||||
MatchingMode, NeedsSelectorFlags, SelectorCaches, VisitedHandlingMode
|
||||
};
|
||||
use smallvec::SmallVec;
|
||||
|
||||
|
|
@ -73,6 +74,7 @@ impl<'a, 'b: 'a, E: TElement + 'b> StateAndAttrInvalidationProcessor<'a, 'b, E>
|
|||
None,
|
||||
selector_caches,
|
||||
VisitedHandlingMode::AllLinksVisitedAndUnvisited,
|
||||
IncludeStartingStyle::No,
|
||||
shared_context.quirks_mode(),
|
||||
NeedsSelectorFlags::No,
|
||||
MatchingForInvalidation::Yes,
|
||||
|
|
|
|||
|
|
@ -21,8 +21,10 @@ use crate::properties::PropertyDeclarationBlock;
|
|||
use crate::rule_tree::{CascadeLevel, StrongRuleNode};
|
||||
use crate::selector_parser::{PseudoElement, RestyleDamage};
|
||||
use crate::shared_lock::Locked;
|
||||
use crate::style_resolver::ResolvedElementStyles;
|
||||
use crate::style_resolver::{PseudoElementResolution, StyleResolverForElement};
|
||||
use crate::style_resolver::{PseudoElementResolution, ResolvedElementStyles};
|
||||
#[cfg(feature = "gecko")]
|
||||
use crate::style_resolver::ResolvedStyle;
|
||||
use crate::style_resolver::StyleResolverForElement;
|
||||
use crate::stylesheets::layer_rule::LayerOrder;
|
||||
use crate::stylist::RuleInclusion;
|
||||
use crate::traversal_flags::TraversalFlags;
|
||||
|
|
@ -384,6 +386,96 @@ trait PrivateMatchMethods: TElement {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
fn resolve_starting_style(
|
||||
&self,
|
||||
context: &mut StyleContext<Self>,
|
||||
) -> ResolvedStyle {
|
||||
use selectors::matching::IncludeStartingStyle;
|
||||
|
||||
// Compute after-change style for the parent and the layout parent.
|
||||
// Per spec, starting style inherits from the parent’s after-change style just like
|
||||
// after-change style does.
|
||||
let parent_el = self.inheritance_parent();
|
||||
let parent_data = parent_el.as_ref().and_then(|e| e.borrow_data());
|
||||
let parent_style = parent_data.as_ref().map(|d| d.styles.primary());
|
||||
let parent_after_change_style =
|
||||
parent_style.and_then(|s| self.after_change_style(context, s));
|
||||
let parent_values = parent_after_change_style
|
||||
.as_ref()
|
||||
.or(parent_style)
|
||||
.map(|x| &**x);
|
||||
|
||||
let mut layout_parent_el = parent_el.clone();
|
||||
let layout_parent_data;
|
||||
let layout_parent_after_change_style;
|
||||
let layout_parent_values = if parent_style.map_or(false, |s| s.is_display_contents()) {
|
||||
layout_parent_el = Some(layout_parent_el.unwrap().layout_parent());
|
||||
layout_parent_data = layout_parent_el.as_ref().unwrap().borrow_data().unwrap();
|
||||
let layout_parent_style = Some(layout_parent_data.styles.primary());
|
||||
layout_parent_after_change_style =
|
||||
layout_parent_style.and_then(|s| self.after_change_style(context, s));
|
||||
layout_parent_after_change_style
|
||||
.as_ref()
|
||||
.or(layout_parent_style)
|
||||
.map(|x| &**x)
|
||||
} else {
|
||||
parent_values
|
||||
};
|
||||
|
||||
// Note: Basically, we have to remove transition rules because the starting style for an
|
||||
// element is the after-change style with @starting-style rules applied in addition.
|
||||
// However, we expect there is no transition rules for this element when calling this
|
||||
// function because we do this only when we don't have before-change style and it's
|
||||
// unlikely to have running transitions on this element.
|
||||
let mut resolver = StyleResolverForElement::new(
|
||||
*self,
|
||||
context,
|
||||
RuleInclusion::All,
|
||||
PseudoElementResolution::IfApplicable,
|
||||
);
|
||||
resolver
|
||||
.resolve_primary_style(
|
||||
parent_values,
|
||||
layout_parent_values,
|
||||
IncludeStartingStyle::Yes,
|
||||
)
|
||||
.style
|
||||
}
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
fn maybe_resolve_starting_style(
|
||||
&self,
|
||||
context: &mut StyleContext<Self>,
|
||||
old_styles: &ElementStyles,
|
||||
new_styles: &ResolvedElementStyles,
|
||||
) -> Option<Arc<ComputedValues>> {
|
||||
// For both cases:
|
||||
// 1. If we didn't see any starting-style rules for this given element during full matching.
|
||||
// 2. If there is no transitions specified.
|
||||
// We don't have to resolve starting style.
|
||||
if !new_styles.may_have_starting_style()
|
||||
|| !new_styles.primary_style().get_ui().specifies_transitions()
|
||||
{
|
||||
return None;
|
||||
}
|
||||
|
||||
// If we don't have before-change-style, we don't have to resolve starting style.
|
||||
// FIXME: we may have to resolve starting style if the old style is display:none and the new
|
||||
// style change the display property. We will have a tentative solution in the following
|
||||
// patches.
|
||||
if old_styles.primary.is_some() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let starting_style = self.resolve_starting_style(context);
|
||||
if starting_style.style().clone_display().is_none() {
|
||||
return None;
|
||||
}
|
||||
|
||||
Some(starting_style.0)
|
||||
}
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
fn process_animations(
|
||||
&self,
|
||||
|
|
@ -395,18 +487,21 @@ trait PrivateMatchMethods: TElement {
|
|||
) {
|
||||
use crate::context::UpdateAnimationsTasks;
|
||||
|
||||
let new_values = new_styles.primary_style_mut();
|
||||
let old_values = &old_styles.primary;
|
||||
if context.shared.traversal_flags.for_animation_only() {
|
||||
self.handle_display_change_for_smil_if_needed(
|
||||
context,
|
||||
old_values.as_deref(),
|
||||
new_values,
|
||||
new_styles.primary_style(),
|
||||
restyle_hint,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Use this in the following patches.
|
||||
let _starting_styles = self.maybe_resolve_starting_style(context, old_styles, new_styles);
|
||||
let new_values = new_styles.primary_style_mut();
|
||||
|
||||
// Bug 868975: These steps should examine and update the visited styles
|
||||
// in addition to the unvisited styles.
|
||||
|
||||
|
|
|
|||
|
|
@ -330,6 +330,10 @@ impl SelectorMap<Rule> {
|
|||
) where
|
||||
E: TElement,
|
||||
{
|
||||
use selectors::matching::IncludeStartingStyle;
|
||||
|
||||
let include_starting_style =
|
||||
matches!(matching_context.include_starting_style, IncludeStartingStyle::Yes);
|
||||
for rule in rules {
|
||||
if !matches_selector(
|
||||
&rule.selector,
|
||||
|
|
@ -352,6 +356,17 @@ impl SelectorMap<Rule> {
|
|||
}
|
||||
}
|
||||
|
||||
if rule.is_starting_style {
|
||||
// Set this flag if there are any rules inside @starting-style. This flag is for
|
||||
// optimization to avoid any redundant resolution of starting style if the author
|
||||
// doesn't specify for this element.
|
||||
matching_context.has_starting_style = true;
|
||||
|
||||
if !include_starting_style {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
matching_rules.push(rule.to_applicable_declaration_block(cascade_level, cascade_data));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,8 @@ use crate::selector_parser::{PseudoElement, SelectorImpl};
|
|||
use crate::stylist::RuleInclusion;
|
||||
use log::Level::Trace;
|
||||
use selectors::matching::{
|
||||
MatchingContext, MatchingForInvalidation, MatchingMode, NeedsSelectorFlags, VisitedHandlingMode,
|
||||
IncludeStartingStyle, MatchingContext, MatchingForInvalidation, MatchingMode,
|
||||
NeedsSelectorFlags, VisitedHandlingMode,
|
||||
};
|
||||
use servo_arc::Arc;
|
||||
|
||||
|
|
@ -47,11 +48,20 @@ where
|
|||
struct MatchingResults {
|
||||
rule_node: StrongRuleNode,
|
||||
flags: ComputedValueFlags,
|
||||
has_starting_style: bool,
|
||||
}
|
||||
|
||||
/// A style returned from the resolver machinery.
|
||||
pub struct ResolvedStyle(pub Arc<ComputedValues>);
|
||||
|
||||
impl ResolvedStyle {
|
||||
/// Convenience accessor for the style.
|
||||
#[inline]
|
||||
pub fn style(&self) -> &ComputedValues {
|
||||
&*self.0
|
||||
}
|
||||
}
|
||||
|
||||
/// The primary style of an element or an element-backed pseudo-element.
|
||||
pub struct PrimaryStyle {
|
||||
/// The style itself.
|
||||
|
|
@ -59,6 +69,11 @@ pub struct PrimaryStyle {
|
|||
/// Whether the style was reused from another element via the rule node (see
|
||||
/// `StyleSharingCache::lookup_by_rules`).
|
||||
pub reused_via_rule_node: bool,
|
||||
/// The element may have matched rules inside @starting-style.
|
||||
/// Basically, we don't apply @starting-style rules to |style|. This is a sugar to let us know
|
||||
/// if we should resolve the element again for starting style, which is the after-change style
|
||||
/// with @starting-style rules applied in addition.
|
||||
pub may_have_starting_style: bool,
|
||||
}
|
||||
|
||||
/// A set of style returned from the resolver machinery.
|
||||
|
|
@ -79,6 +94,12 @@ impl ResolvedElementStyles {
|
|||
pub fn primary_style_mut(&mut self) -> &mut Arc<ComputedValues> {
|
||||
&mut self.primary.style.0
|
||||
}
|
||||
|
||||
/// Returns true if this element may have starting style rules.
|
||||
#[inline]
|
||||
pub fn may_have_starting_style(&self) -> bool {
|
||||
self.primary.may_have_starting_style
|
||||
}
|
||||
}
|
||||
|
||||
impl PrimaryStyle {
|
||||
|
|
@ -186,16 +207,22 @@ where
|
|||
&mut self,
|
||||
parent_style: Option<&ComputedValues>,
|
||||
layout_parent_style: Option<&ComputedValues>,
|
||||
include_starting_style: IncludeStartingStyle,
|
||||
) -> PrimaryStyle {
|
||||
let primary_results = self.match_primary(VisitedHandlingMode::AllLinksUnvisited);
|
||||
let primary_results = self.match_primary(
|
||||
VisitedHandlingMode::AllLinksUnvisited,
|
||||
include_starting_style,
|
||||
);
|
||||
|
||||
let inside_link = parent_style.map_or(false, |s| s.visited_style().is_some());
|
||||
|
||||
let visited_rules = if self.context.shared.visited_styles_enabled &&
|
||||
(inside_link || self.element.is_link())
|
||||
{
|
||||
let visited_matching_results =
|
||||
self.match_primary(VisitedHandlingMode::RelevantLinkVisited);
|
||||
let visited_matching_results = self.match_primary(
|
||||
VisitedHandlingMode::RelevantLinkVisited,
|
||||
IncludeStartingStyle::No,
|
||||
);
|
||||
Some(visited_matching_results.rule_node)
|
||||
} else {
|
||||
None
|
||||
|
|
@ -209,6 +236,7 @@ where
|
|||
},
|
||||
parent_style,
|
||||
layout_parent_style,
|
||||
primary_results.has_starting_style,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -217,6 +245,7 @@ where
|
|||
inputs: CascadeInputs,
|
||||
parent_style: Option<&ComputedValues>,
|
||||
layout_parent_style: Option<&ComputedValues>,
|
||||
may_have_starting_style: bool,
|
||||
) -> PrimaryStyle {
|
||||
// Before doing the cascade, check the sharing cache and see if we can
|
||||
// reuse the style via rule node identity.
|
||||
|
|
@ -253,6 +282,7 @@ where
|
|||
/* pseudo = */ None,
|
||||
),
|
||||
reused_via_rule_node: false,
|
||||
may_have_starting_style,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -262,7 +292,11 @@ where
|
|||
parent_style: Option<&ComputedValues>,
|
||||
layout_parent_style: Option<&ComputedValues>,
|
||||
) -> ResolvedElementStyles {
|
||||
let primary_style = self.resolve_primary_style(parent_style, layout_parent_style);
|
||||
let primary_style = self.resolve_primary_style(
|
||||
parent_style,
|
||||
layout_parent_style,
|
||||
IncludeStartingStyle::No,
|
||||
);
|
||||
|
||||
let mut pseudo_styles = EagerPseudoStyles::default();
|
||||
|
||||
|
|
@ -375,10 +409,15 @@ where
|
|||
pub fn cascade_styles_with_default_parents(
|
||||
&mut self,
|
||||
inputs: ElementCascadeInputs,
|
||||
may_have_starting_style: bool,
|
||||
) -> ResolvedElementStyles {
|
||||
with_default_parent_styles(self.element, move |parent_style, layout_parent_style| {
|
||||
let primary_style =
|
||||
self.cascade_primary_style(inputs.primary, parent_style, layout_parent_style);
|
||||
let primary_style = self.cascade_primary_style(
|
||||
inputs.primary,
|
||||
parent_style,
|
||||
layout_parent_style,
|
||||
may_have_starting_style,
|
||||
);
|
||||
|
||||
let mut pseudo_styles = EagerPseudoStyles::default();
|
||||
if let Some(mut pseudo_array) = inputs.pseudos.into_array() {
|
||||
|
|
@ -427,6 +466,7 @@ where
|
|||
let MatchingResults {
|
||||
rule_node,
|
||||
mut flags,
|
||||
has_starting_style: _,
|
||||
} = self.match_pseudo(
|
||||
&originating_element_style.style.0,
|
||||
pseudo,
|
||||
|
|
@ -459,7 +499,11 @@ where
|
|||
))
|
||||
}
|
||||
|
||||
fn match_primary(&mut self, visited_handling: VisitedHandlingMode) -> MatchingResults {
|
||||
fn match_primary(
|
||||
&mut self,
|
||||
visited_handling: VisitedHandlingMode,
|
||||
include_starting_style: IncludeStartingStyle,
|
||||
) -> MatchingResults {
|
||||
debug!(
|
||||
"Match primary for {:?}, visited: {:?}",
|
||||
self.element, visited_handling
|
||||
|
|
@ -473,6 +517,7 @@ where
|
|||
Some(bloom_filter),
|
||||
selector_caches,
|
||||
visited_handling,
|
||||
include_starting_style,
|
||||
self.context.shared.quirks_mode(),
|
||||
NeedsSelectorFlags::Yes,
|
||||
MatchingForInvalidation::No,
|
||||
|
|
@ -512,6 +557,7 @@ where
|
|||
MatchingResults {
|
||||
rule_node,
|
||||
flags: matching_context.extra_data.cascade_input_flags,
|
||||
has_starting_style: matching_context.has_starting_style,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -550,6 +596,7 @@ where
|
|||
Some(bloom_filter),
|
||||
selector_caches,
|
||||
visited_handling,
|
||||
IncludeStartingStyle::No,
|
||||
self.context.shared.quirks_mode(),
|
||||
NeedsSelectorFlags::Yes,
|
||||
MatchingForInvalidation::No,
|
||||
|
|
@ -580,6 +627,7 @@ where
|
|||
Some(MatchingResults {
|
||||
rule_node,
|
||||
flags: matching_context.extra_data.cascade_input_flags,
|
||||
has_starting_style: false, // We don't care.
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1263,6 +1263,7 @@ impl Stylist {
|
|||
None,
|
||||
&mut selector_caches,
|
||||
VisitedHandlingMode::RelevantLinkVisited,
|
||||
selectors::matching::IncludeStartingStyle::No,
|
||||
self.quirks_mode,
|
||||
needs_selector_flags,
|
||||
MatchingForInvalidation::No,
|
||||
|
|
|
|||
|
|
@ -350,7 +350,11 @@ where
|
|||
rule_inclusion,
|
||||
PseudoElementResolution::IfApplicable,
|
||||
)
|
||||
.resolve_primary_style(style.as_deref(), layout_parent_style.as_deref());
|
||||
.resolve_primary_style(
|
||||
style.as_deref(),
|
||||
layout_parent_style.as_deref(),
|
||||
selectors::matching::IncludeStartingStyle::No,
|
||||
);
|
||||
|
||||
let is_display_contents = primary_style.style().is_display_contents();
|
||||
|
||||
|
|
@ -639,7 +643,10 @@ where
|
|||
PseudoElementResolution::IfApplicable,
|
||||
);
|
||||
|
||||
resolver.cascade_styles_with_default_parents(cascade_inputs)
|
||||
resolver.cascade_styles_with_default_parents(
|
||||
cascade_inputs,
|
||||
data.may_have_starting_style(),
|
||||
)
|
||||
},
|
||||
CascadeOnly => {
|
||||
// Skipping full matching, load cascade inputs from previous values.
|
||||
|
|
@ -653,7 +660,10 @@ where
|
|||
PseudoElementResolution::IfApplicable,
|
||||
);
|
||||
|
||||
resolver.cascade_styles_with_default_parents(cascade_inputs)
|
||||
resolver.cascade_styles_with_default_parents(
|
||||
cascade_inputs,
|
||||
data.may_have_starting_style(),
|
||||
)
|
||||
};
|
||||
|
||||
// Insert into the cache, but only if this style isn't reused from a
|
||||
|
|
|
|||
|
|
@ -2587,7 +2587,8 @@ pub extern "C" fn Servo_StyleRule_SelectorMatchesElement(
|
|||
relevant_link_visited: bool,
|
||||
) -> bool {
|
||||
use selectors::matching::{
|
||||
matches_selector, MatchingContext, MatchingMode, NeedsSelectorFlags, VisitedHandlingMode,
|
||||
matches_selector, IncludeStartingStyle, MatchingContext, MatchingMode, NeedsSelectorFlags,
|
||||
VisitedHandlingMode,
|
||||
};
|
||||
let selectors = desugared_selector_list(rules);
|
||||
let Some(selector) = selectors.slice().get(index as usize) else {
|
||||
|
|
@ -2628,6 +2629,7 @@ pub extern "C" fn Servo_StyleRule_SelectorMatchesElement(
|
|||
/* bloom_filter = */ None,
|
||||
&mut selector_caches,
|
||||
visited_mode,
|
||||
IncludeStartingStyle::No,
|
||||
quirks_mode,
|
||||
NeedsSelectorFlags::No,
|
||||
MatchingForInvalidation::No,
|
||||
|
|
|
|||
Loading…
Reference in a new issue