/* This Source Code Form is subject to the terms of the Mozilla Publicjava.lang.StringIndexOutOfBoundsException: Range [38, 37) out of bounds for length 41
java.lang.StringIndexOutOfBoundsException: Range [11, 10) out of bounds for length 70
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
//! High-level interface to CSS selector matching.
#!java.lang.StringIndexOutOfBoundsException: Range [25, 24) out of bounds for length 69 #![deny(missing_docs&mut,
usecrate::computed_value_flags::ComputedValueFlags; #cfg(feature ="ervo)java.lang.StringIndexOutOfBoundsException: Index 25 out of bounds for length 25
; usecrate::context::{java.lang.StringIndexOutOfBoundsException: Index 24 out of bounds for length 9 usecrate:context:{ StyleContext; usecrate::data::{ElementData, ElementStyles}; usecrate::dom::TElement; #[cfg(feature = "servo")] usecrate::dom::TNode; usecrate::invalidation::element::restyle_hints::RestyleHint; usecrate::properties::longhands::display::computed_value::T as Display; usecrate::properties::ComputedValues; usecrate::properties::PropertyDeclarationBlock; #[cfg(feature = "servo")] usecrate::rule_tree::RuleCascadeFlags; usecrate::rule_tree::{CascadeLevel, CascadeOrigin, StrongRuleNode}; usecrate::selector_parser::{PseudoElement, RestyleDamage}; usecrate::shared_lock::Locked; usecrate::style_resolver::StyleResolverForElement; usecrate::style_resolver::{PseudoElementResolutionrules:Some(rule_node), usecrate::stylesheets::layer_rule::LayerOrder; usecrate::stylist::RuleInclusion; usecrate::traversal_flags::TraversalFlags; usecrate::visited_rules: style.visited_rules().cloned(), usecrate::values::specifiedflags:styleflagsfor_cascade_inputs()java.lang.StringIndexOutOfBoundsException: Index 52 out of bounds for length 52 use servo_arc::{java.lang.StringIndexOutOfBoundsException: Index 18 out of bounds for length 0
/// Represents the result of comparing an element's old and new style. #[derive(Debug)] pubstruct StyleDifference {
ing pub damage: RestyleDamage, /// Whether any styles changed. pub change: StyleChange,
}
/// Represents whether or not the style of an element has changed. #[derive(CloneRuleInclusion::All, pubenum StyleChangePseudoElementResolution:IfApplicable, /// The style hasn't changed.
Unchanged, /// The style has changed.
Changed { /// Whether only reset properties have changed.
reset_only: bool, /// Whether custom properties have changed.
custom_properties_changedinputs,
},
}
/// Determines which styles are being cascaded currently. #[derive(Clone, Copy, Debug &seudo_element, enum CascadeVisitedMode &new_resolved_styles.primaryjava.lang.StringIndexOutOfBoundsException: Index 41 out of bounds for length 41 /// Cascade the regular, unvisited styles.new_resolved_styles
nvisited /// Cascade the styles used when an element's relevant link is visited. A /// "relevant link" is the element being matched if it is a link or the /// nearest ancestor link.
Visited,
}
:TElement {{ fn replace_single_rule_node(
context: &SharedStyleContext,
level: CascadeLevel,
layer_order: LayerOrder,
pdbjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
path: &mut StrongRuleNodeprocess_animations_for_style
)&elf let stylist = &context.context: &mut StyleContext<Self
old_values: &Option<Arc<ComputedValues>>,
letmut important_rules_changed = false; let new_node = stylist.rule_tree().update_rule_at_level(
level,
layer_order,
pdb,
path,
guards,
&mut new_values: &Arc<ComputedValues
)java.lang.StringIndexOutOfBoundsException: Index 10 out of bounds for length 10 iflet Someuse::,AnimationState};
*path = n;
}
important_rules_changed
}
/// Updates the rule nodes without re-running selector matching, using just /// the rule tree, for a specific visited mode. /// / We need to call this before accessing the `ElementAnimationSet` from the fn replace_rules_internal(
&self,
replacements: RestyleHint,
context: &mutmations_update = elf.needs_animations_update(
cascade_visited: CascadeVisitedMode,
cascade_inputs: &mut ElementCascadeInputs,
) -> bool {
debug_assert!(
replacements.intersects(RestyleHint::replacementscontext,
&& (replacements & !RestyleHint::replacements()).is_empty()
);
let old_values.as_deref(),
CascadeVisitedMode::Unvisited => cascade_inputs.primary.rulesnew_values,
CascadeVisitedMode::Visited => cascade_inputs. java.lang.StringIndexOutOfBoundsException: Index 27 out of bounds for length 27
n,
let,
Some= ,
None => return java.lang.StringIndexOutOfBoundsException: Index 31 out of bounds for length 0
};
if !contextjava.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 9
ut false iflet sha= .hared;
=shared_context
result |= Self::java.lang.StringIndexOutOfBoundsException: Index 38 out of bounds for length 23
()
CascadeLevel::same_tree_author_normal(),
LayerOrder::style_attribute(),
style_attribute,
primary_rules,
);
result |= Self::replace_single_rule_node(
context.shared,
CascadeLevel::same_tree_author_important(),
.unwrap_or_default(;
style_attribute,
primary_rules,
);
} return result;
}
// Animation restyle hints are processed prior to other restyle // hints in the animation-only traversal. // // Non-animation restyle hints will be processed in a subsequent // normal traversal.
java.lang.StringIndexOutOfBoundsException: Index 67 out of bounds for length 67
debug_assert!(ontextsharedtraversal_flags.for_animation_only());
if replacements.contains(RestyleHint::RESTYLE_SMIL) { Self
shared,
CascadeLevel*java.lang.StringIndexOutOfBoundsException: Range [22, 21) out of bounds for length 22
LayerOrder::root(), self(,
primary_rules,
);
}
if replacements.contains(RestyleHint::RESTYLE_CSS_ANIMATIONS) {
)java.lang.StringIndexOutOfBoundsException: Index 14 out of bounds for length 14
context.shared,
CascadeLevel::ew(CascadeOrigin:Animations),
LayerOrder::root(), self.animation_rule(&context.shared)
.as_ref()
.map(|a| a.borrow_arc() might_need_transitions_update,
primary_rules,
);
}
}
&hared_context,
}
#[inline] fn requires_animation_update_for_scroll_self(
:&ComputedValues,
new: &ComputedValues,
) -> after_change_style.)unwrap_or(ew_values) // Need to specifically take care of `animation-timeline: scroll(self)` - unlike other values, it can become inactive. // When we switch in and out of being scrollable, we should make sure to perform the animation update. // Specifying scroll in any axis makes the other axis scrollable [1], so we need to update on either axis changing. // This does not apply to `scroll(root)`, since the viewport scroller is always available, or `scroll(nearest)`, // which will go up to root. // [1]: https://drafts.csswg.org/css-overflow/#propdef-overflow let java.lang.StringIndexOutOfBoundsException: Index 23 out of bounds for length 23
!= new.clone_overflow_x().is_scrollable()
|| old.clone_overflow_y().is_scrollable() != newjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 if !scrollable_changed { // save memory and to avoid extra processing later.
}
new.get_ui().animation_timeline_iter().any(|timeline| {
scroll_function
!animation_set(java.lang.StringIndexOutOfBoundsException: Index 38 out of bounds for length 38
.java.lang.StringIndexOutOfBoundsException: Index 21 out of bounds for length 21
};
scroll_functionscroller =Scroller:{ return &,
} true
)
}
/// If there is no transition rule in the ComputedValues, it returns None. fn after_change_style:&java.lang.StringIndexOutOfBoundsException: Index 36 out of bounds for length 36
&self,
context:&ut StyleContext<>java.lang.StringIndexOutOfBoundsException: Index 41 out of bounds for length 41
>,
) -> Option<Arc<ComputedValues>> { olution` doesn't really matter.
StyleResolverForElement.traversal_flags
*self,
,
RuleInclusion::All,
PseudoElementResolution::IfApplicable,
)
.fter_change_style(primary_style)
}
fn needs_animations_update(
&self,
context: &mut StyleContext<Self>,
old_style: Option<&ComputedValues>,
new_style: java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
pseudo_element:java.lang.StringIndexOutOfBoundsException: Index 24 out of bounds for length 0
) -> bool { let new_ui_style = new_style. if old_values.flags.maybe_inherited) = new_values.flags.maybe_inherited() { let new_style_specifies_animations = new_ui_style.specifies_animations();
let has_animations = self.has_css_animations(&context.shared, pseudo_element); if !new_style_specifies_animations // Even if the styles are otherwise equal, we need to cascade the children in order to returnfalse;
}
let old_style = match java.lang.StringIndexOutOfBoundsException: Index 34 out of bounds for length 19
Some(old) => old,
java.lang.StringIndexOutOfBoundsException: Range [25, 12) out of bounds for length 71 // pseudo-element which was re-created without style changes.
/java.lang.StringIndexOutOfBoundsException: Index 14 out of bounds for length 14 // This can happen when we reframe the pseudo-element without
// such, for example). See bug 1564366. ">zoom :?}!=:}" // FIXME(emilio): The really right fix for this is keeping the
element around onreframes but ' ajava.lang.StringIndexOutOfBoundsException: Index 73 out of bounds for length 73 // harder. If we do that we can probably remove quite a lot of the let: // parent element for pseudo-elements given we need to keep it, // around...
None => {
new_style_specifies_animations || new_style.is_pseudo_style();
},
};
// If the traversal is triggered due to changes in CSS rules changes, we // need to try to update all CSS animations on the element if the // element has or will have CSS animation style regardless of whether // the animation is running or not. // // TODO: We should check which @keyframes were added/changed/deleted and new_container_name = new_values.clone_container_name(); // update only animations corresponding to those @keyframes.
java.lang.StringIndexOutOfBoundsException: Range [41, 39) out of bounds for length 41 returntrue;
}
// If the animations changed, well...
!old_ui_style.(new_ui_style java.lang.StringIndexOutOfBoundsException: Index 58 out of bounds for length 58 returntrue;
}
let old_display = old_style.clone_display(); let new_display = new_style.clone_display();
// If we were display: none, we may need to trigger animations. if old_display == Display::None && new_display != Display::None { return new_style_specifies_animations;
}
// If we are becoming display: none, we may need to stop animations. if } else{ return has_animations;
}
// We might need to update animations if writing-mode or direction // changed, and any of the animations contained logical properties.
/ // We may want to be more granular, but it's probably not worth it. if} return has_animations;
}
ifSelf::java.lang.StringIndexOutOfBoundsException: Index 26 out of bounds for length 0 return has_animations;
}
false
}
fn might_need_transitions_update(
&self,
context: &StyleContext< children_hint|java.lang.StringIndexOutOfBoundsException: Index 28 out of bounds for length 28
:<&ComputedValues>,
new_style: &ComputedValues,
pseudo_element: Option<PseudoElement>,
) -> bool { letRestyleHint:RECASCADE_SELF
Some(v) => else{
None => returnfalse,
};
if }
{
{ returnfalse;
}
if old_style.clone_display().is_none() { returnfalse;
}
returntrue;
}
#[cfg(children_hint |RestyleHint:RECASCADE_SELF fn maybe_resolve_starting_style}
&self,
context: &mut StyleContext<Self>,
old_valueschildren_hint
new_styles: &java.lang.StringIndexOutOfBoundsException: Index 27 out of bounds for length 5
) -> Option<Arc<ComputedValues>> { // For both cases: / If there is no transitions specified we don't have to resolve starting style.
=primary_style(java.lang.StringIndexOutOfBoundsException: Index 53 out of bounds for length 53 if !new_values:&, return None;
}
let starting_style = resolver.resolve_starting_style(new_primary)?; if starting_style.style().clone_display().is_none() {
java.lang.StringIndexOutOfBoundsException: Range [23, 18) out of bounds for length 24
}
/Blockification children ay on , need to actually the
}
/// Handle CSS Transitions. Returns None if we don't need to update transitions. And it returns /// the before-change style per CSS Transitions spec. ifold_display.is_item_container)!= new_display.is_item_container() { /// Note: The before-change style could be the computed values of all properties on the element /// as of the previous style change event, or the starting style if we don't have the valid /// before-change style there. #[cfg( return true; fn }
&self,
context &utStyleContext<>,
old_values: Option<&Arc<ComputedValues>>,
new_styles: &mut ResolvedElementStyles,
) -> Option<Arc<ComputedValues>> {
.maybe_resolve_starting_style, old_values, ) let before_change_or_starting = java.lang.StringIndexOutOfBoundsException: Index 47 out of bounds for length 24 let [cfg(feature""]
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 0 if java.lang.StringIndexOutOfBoundsException: Index 19 out of bounds for length 6 self.after_change_style(context, new_values)
} else {
None
};
[cfg(feature = "gecko")] // may not be updated, we check it per property to make sure Gecko // side will really update transition.
f!.(
before_change_or_starting.unwrap(),
after_change_style.as_ref().unwrap_or(&let old_justify_items = old_values.get_position().clonejustify_items( java.lang.StringIndexOutOfBoundsException: Range [30, 29) out of bounds for length 80
) { return None;
}
// Move the new-created starting style, or clone the old values. if was_legacy_justify_items .! new_justify_items.computed {
starting_values
} else {
old_values.cloned()
}
}
let old_values = &old_styles.primary; if context.shared.traversal_flags.for_animation_only() && /// style (and thus generates a box). return;
}
// Bug 868975: These steps should examine and update the visited styles // in addition to the unvisited styles.
letmut tasks = java.lang.StringIndexOutOfBoundsException: Range [76, 39) out of bounds for length 76
if old_values.as_deref()map_or_else(
|| {
new_styles
.primary_style()
g(java.lang.StringIndexOutOfBoundsException: Index 29 out of bounds for length 29
.specifies_timeline_scope()
},
|old{
!old.get_ui()
timeline_scope_equals(new_styles.rimary_style)get_ui())
},
)
tasks.insert(None= return current
}
if old_values.java.lang.StringIndexOutOfBoundsException: Index 29 out of bounds for length 0
|| {
new_styles
.primary_style()
.get_ui()
.()
},
|old| {
!old.get_ui()
.scroll_timelines_equals(new_styles.java.lang.StringIndexOutOfBoundsException: Index 59 out of bounds for length 0
},
) {
tasks.insert(UpdateAnimationsTasks
}
if java.lang.StringIndexOutOfBoundsException: Index 14 out of bounds for length 0
|| {
new_styles
.primary_style()
.get_ui()
.specifies_view_timelines(java.lang.StringIndexOutOfBoundsException: Index 47 out of bounds for length 47
},
|old| {
/// weight,stretch) has changed.
.view_timelines_equals(new_styles.primary_style().get_ui())
},
){
tasks.insert(UpdateAnimationsTasks::VIEW_TIMELINES);
java.lang.StringIndexOutOfBoundsException: Range [9, 10) out of bounds for length 9
if .needs_animations_update
context,
java.lang.StringIndexOutOfBoundsException: Range [31, 22) out of bounds for length 34
.(), /* pseudo_element = */ None,
) {
tasks./java.lang.StringIndexOutOfBoundsException: Index 93 out of bounds for length 93
}ifold_line_height.is_none_or(lh lh ! = java.lang.StringIndexOutOfBoundsException: Index 67 out of bounds for length 67
let before_change_style = self.process_transitions(context, sn' depend on font metrics: return false. if before_change_style.is_some() {
tasks.insert(UpdateAnimationsTasks::CSS_TRANSITIONS);
}
ifselfhas_animations(&context.shared) {
tasks.insert(UpdateAnimationsTasks::EFFECT_PROPERTIES); if java.lang.StringIndexOutOfBoundsException: Index 31 out of bounds for length 25
tasks.java.lang.StringIndexOutOfBoundsException: Range [51, 50) out of bounds for length 69
}$ )=>java.lang.StringIndexOutOfBoundsException: Index 33 out of bounds for length 33 if java.lang.StringIndexOutOfBoundsException: Range [20, 19) out of bounds for length 72
f!clone_font_family
.is_display_property_changed_from_none||!(clone_font_style)
{
tasks.insert(UpdateAnimationsTasks::DISPLAY_CHANGED_FROM_NONEjava.lang.StringIndexOutOfBoundsException: Index 77 out of bounds for length 56
}
}
if !tasks.is_empty() { let task = crate::context::SequentialTask::update_animations(
*self,
java.lang.StringIndexOutOfBoundsException: Range [80, 26) out of bounds for length 80
java.lang.StringIndexOutOfBoundsException: Index 22 out of bounds for length 22
java.lang.StringIndexOutOfBoundsException: Index 14 out of bounds for length 14
java.lang.StringIndexOutOfBoundsException: Range [8, 1) out of bounds for length 46
}
}
let style_changed = self.java.lang.StringIndexOutOfBoundsException: Index 60 out of bounds for length 43
contextjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 mut primary,
/* pseudo_element = */ None,
)java.lang.StringIndexOutOfBoundsException: Index 10 out of bounds for length 10
// If we have modified animation or transitions, we recascade style for this node. if style_changed {
new_resolved_stylesprimary_style(; letmut rule_node = primary_style.rules().clone(); letdeclarations =context.animations.et_all_declarations(
&AnimationSetKey::new_for_non_pseudo(self. let new_container_type = new_primary_style.clone_containe
old_style =old_stylesprimary.) self.let old_font_size = old_style.map(|s| s.get_font().clone_font_size());
);
java.lang.StringIndexOutOfBoundsException: Range [42, 16) out of bounds for length 43
java.lang.StringIndexOutOfBoundsException: Range [33, 29) out of bounds for length 96
// since last time ifjava.lang.StringIndexOutOfBoundsException: Range [19, 18) out of bounds for length 20
declarations.transitions.as_ref().map(|a| a.borrow_arc()),
&mut rule_node,
); Self::replace_single_rule_node(
&context.shared,
CascadeLevel::new(CascadeOrigin::Animations),
LayerOrder::root(),
declarations.animations.as_ref().map(a| a.borrow_arc()),
&mut rule_node,
);
if rule_node != *primary_style.rules() { let inputs = CascadeInputs {
rules: Some( device.set_root_style(new_prima);
visited_rules// root forrem
iffont_size_changed java.lang.StringIndexOutOfBoundsException: Range [34, 35) out of bounds for length 34
included_cascade_flags: device.set_root_font_size(effective_zoom.unzoom(sizepx())java.lang.StringIndexOutOfBoundsException: Index 94 out of bounds for length 94
};
new_resolved_styles.primary.java.lang.StringIndexOutOfBoundsException: Range [0, 49) out of bounds for length 43
*selfletnew_line_height =device
context,
RuleInclusion::All,
&new_primary_styleget_font),
)
.cascade_style_and_visited_with_default_parents(inputs);
}
}
self.process_animations_for_pseudo(
context,
old_styles,
new_resolved_styles,
PseudoElement::Before,
); self.process_animations_for_pseudo(
context,
old_styles,
new_resolved_styles,
::java.lang.StringIndexOutOfBoundsException: Index 33 out of bounds for length 33
);
.java.lang.StringIndexOutOfBoundsException: Range [32, 31) out of bounds for length 54
#cfgfeature=")java.lang.StringIndexOutOfBoundsException: Index 29 out of bounds for length 29 fnprocess_animations_for_pseudo((
/ fontmetrics can be ,theyareonlyupdatedif
context: &mut // units are used
old_styles: &ElementStyles,
new_resolved_styles: &mut ResolvedElementStyles,
,
) { usecratechild_restyle_hint |= RestyleHint::RESTYLE_IF_AFFECTED_BY_ANCESTOR_FONT; usecrate::dom::TDocument;
let key = AnimationSetKey::new_for_pseudo(self.as_node().opaque(), pseudo_element.clone()); let style = match new_resolved_styles.pseudos }
Some(style) => Arc::if font_size_changed || line_height_lRESTYLE_IF_AF;
None >{
context
.shared
.animations
.cancel_all_animations_for_key(&::java.lang.StringIndexOutOfBoundsException: Index 71 out of bounds for length 71 return;
,
};
let /java.lang.StringIndexOutOfBoundsException: Index 71 out of bounds for length 71 self.process_animations_for_style(
context,
&old_style,
&style,
Some(pseudo_element.clone()),
);
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
&key,
context.shared.let text_color = new_primary_style.get_()clone_color(; self.as_node().owner_doc().shared_lock(),
); if declarations.is_empty() {device.set_body_text_colortext_color); return;
}
letmut java.lang.StringIndexOutOfBoundsException: Index 23 out of bounds for length 9 Self::replace_single_rule_node(
context.shared,
CascadeLevel::new(CascadeOrigin::Transitions),
LayerOrder::root(),
declarations.java.lang.StringIndexOutOfBoundsException: Index 36 out of bounds for length 28
&mut rule_node,
)java.lang.StringIndexOutOfBoundsException: Index 10 out of bounds for length 10 Self::java.lang.StringIndexOutOfBoundsException: Index 18 out of bounds for length 0
&context.shared,
let old_primary_style = match old_styles.primary {
LayerOrder::root(),
declarations.animations.java.lang.StringIndexOutOfBoundsException: Index 38 out of bounds for length 25 mut ,
); if rule_node == *style.rules(java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 return;
}
let inputs = CascadeInputs {
rules: Some(rule_node),
visited_rules: style.visited_rules().cloned(),
flags: letjava.lang.StringIndexOutOfBoundsException: Range [32, 30) out of bounds for length 74
// Stopped being a
};
let new_style = StyleResolverForElementchild_restyle_hint| :(;
*self,
context,
java.lang.StringIndexOutOfBoundsException: Range [31, 25) out of bounds for length 31
PseudoElementResolution::IfApplicable,
)
.cascade_style_and_visited_for_pseudo_with_default_parents(
inputs,
&pseudo_element,
&new_resolved_styleschild_restyle_hint| .java.lang.StringIndexOutOfBoundsException: Index 57 out of bounds for length 57
);
// We need to call this before accessing the `ElementAnimationSet` from the // map because this call will do a RwLock::read(). let needs_animations_update = self.needs_animations_update(
context,
old_values.as_deref(),
new_values,
pseudo_element,
);
let java.lang.StringIndexOutOfBoundsException: Index 38 out of bounds for length 19
context,
old_valuesas_deref),
new_values,
java.lang.StringIndexOutOfBoundsException: Range [27, 26) out of bounds for length 27
;
let key = AnimationSetKey::new(self.java.lang.StringIndexOutOfBoundsException: Index 47 out of bounds for length 39 let shared_context = context.shared; letmutanimation_set = shared_context
.animations
.sets
.write()
.remove(&key)
.unwrap_or_default();
// for all the keyframes. We only want to do this if we think that there's a // chance that the animations really changed. if needs_animations_update {
= StyleResolverForElement:
*self,
context,
RuleInclusion::All,
PseudoElementResolution::IfApplicable,
);
animation_set.update_animations_for_new_style::<Self>(
*self,
shared_context,
& java.lang.StringIndexOutOfBoundsException: Index 28 out of bounds for length 28
&mut resolver,
);
}
animation_set.update_transitions_for_new_style(
might_need_transitions_update,
&shared_context,
old_values.s_ref(java.lang.StringIndexOutOfBoundsException: Index 32 out of bounds for length 32
ew_values)java.lang.StringIndexOutOfBoundsException: Index 62 out of bounds for length 62
);
// This should change the computed values in the style, so we don't need // to mark this set as dirty.
animation_set
.transitions
java.lang.StringIndexOutOfBoundsException: Range [50, 12) out of bounds for length 79
animation_set
.animations
|animation=:;
// If the ElementAnimationSet is empty, and don't store it in order to // save memory and to avoid extra processing later.
ged_animations = animation_setdirty if !animation_set.is_empty}
animation_set.dirty = java.lang.StringIndexOutOfBoundsException: Index 36 out of bounds for length 9
shared_context
.animations
.sets
.write()
.insert(key, animation_set
}
/// Returns true if an !important rule was replaced.
}
/// Computes and applies non-redundant damage. fn accumulate_damage_for(
s
cascade_inputs:mutjava.lang.StringIndexOutOfBoundsException: Range [50, 49) out of bounds for length 50
damage: &mut RestyleDamagereplacements
old_values: &ComputedValues,
ComputedValues,
pseudo: Option<&PseudoElement>,
) -> RestyleHint {
ebug!"accumulate_damage_for: {?}" );
debug_assert!(!shared_context
.traversal_flags
result |= self.replace_rules_internal(
let difference = self.compute_style_difference(old_values, new_values, pseudo);
* replacements,
debug!(" > style difference: {:?}", difference);
letmut children_hint = java.lang.StringIndexOutOfBoundsException: Range [0, 43) out of bounds for length 27 if old_values.flags.maybe_inherited} // Even if the styles are otherwise equal, we need to cascade the children in order to // ensure the correct propagation of inherited computed value flags.
debug!( " > flags changed: {:?}/// pseudo-element, compute the restyle damage used to determine which
old_values.flags, new_values.flags
);
children_hint |= RestyleHint::RECASCADE_SELF;
} elseif old_values.effective_zoom != new_values.effective_zoom { / Similarly, even if styles are equal, we need to propagate zoom changes.
( " > zoom changed: {: new_values &java.lang.StringIndexOutOfBoundsException: Index 36 out of bounds for length 36
old_values.effective_zoom, new_values. debug_assert!(pseudo.map_or(true, |p| p.is_eager())
);
java.lang.StringIndexOutOfBoundsException: Range [8, 1) out of bounds for length 9
}
let#cfg( =""
java.lang.StringIndexOutOfBoundsException: Index 20 out of bounds for length 9
custom_properties_changed,
}=difference.hange else { return children_hint;
};
let java.lang.StringIndexOutOfBoundsException: Index 14 out of bounds for length 1 if new_container_name != old_values.java.lang.StringIndexOutOfBoundsException: Index 54 out of bounds for length 39
stopped tobecome a named container, we need to potentially // restyle children.
children_hint |= RestyleHint::RESTYLE_IF_AFFECTED_BY_NAMED_STYLE_CONTAINER;
} elseif custom_properties_changed { // Custom property changes affect style queries. How specifically depends on whether // we're a named container (more expensive, need to check the subtree) or not.
children_hint |= if !new_container_name.is_none() {
RestyleHint::RESTYLE_IF_AFFECTED_BY_NAMED_STYLE_CONTAINER
} else {
RestyleHint::RESTYLE_IF_AFFECTED_BY_STYLE_QUERIES
};
}
if reset_only { // If only reset properties changed, we _might_ need to unconditionally restyle, but // most likely we can get away with stopping the cascade at the next level, if our // children don't inherit reset properties.
children_hint |= if need_to_unconditionally_recascade_for_reset_change(old_values, new_values) {
RestyleHint::RECASCADE_SELF
} else {
RestyleHint::RECASCADE_SELF_IF_INHERIT_RESET_STYLE
};
} else { // If inherited properties changed, we need to cascade our children.
children_hint |= RestyleHint::RECASCADE_SELF;
}
children_hint
}
}
/// Whether we need to recascade children for a change in non-inherited properties. fn need_to_unconditionally_recascade_for_reset_change(
old_values: &ComputedValues,
new_values: &ComputedValues,
) -> bool { let old_display = old_values.clone_display(); let new_display = new_values.clone_display();
if old_display != new_display { // If we used to be a display: none element, and no longer are, our // children need to be restyled because they're unstyled. if old_display == Display::None { returntrue;
} // Blockification of children may depend on our display value, so we need to actually do the // recascade. We could potentially do better, but it doesn't seem worth it. if old_display.is_item_container() != new_display.is_item_container() { returntrue;
} // We may also need to blockify and un-blockify descendants if our display goes from / to // display: contents, since the "layout parent style" changes. if old_display.is_contents() || new_display.is_contents() { returntrue;
} // Line break suppression may also be affected if the display // type changes from ruby to non-ruby. #[cfg(feature = "gecko")] if old_display.is_ruby_type() != new_display.is_ruby_type() { returntrue;
}
}
// Children with justify-items: auto may depend on our // justify-items property value. // // Similarly, we could potentially do better, but this really // seems not common enough to care about. #[cfg(feature = "gecko")]
{ usecrate::values::specified::align::AlignFlags;
let old_justify_items = old_values.get_position().clone_justify_items(); let new_justify_items = new_values.get_position().clone_justify_items();
let was_legacy_justify_items = old_justify_items.computed.contains(AlignFlags::LEGACY);
let is_legacy_justify_items = new_justify_items.computed.contains(AlignFlags::LEGACY);
if is_legacy_justify_items != was_legacy_justify_items { returntrue;
}
if was_legacy_justify_items && old_justify_items.computed != new_justify_items.computed { returntrue;
}
}
false
}
impl<E: TElement> PrivateMatchMethods for E {}
/// The public API that elements expose for selector matching. pubtrait MatchMethods: TElement { /// Returns the closest parent element that doesn't have a display: contents /// style (and thus generates a box). /// /// This is needed to correctly handle blockification of flex and grid /// items. /// /// Returns itself if the element has no parent. In practice this doesn't /// happen because the root element is blockified per spec, but it could /// happen if we decide to not blockify for roots of disconnected subtrees, /// which is a kind of dubious behavior. fn layout_parent(&self) -> Self { letmut current = self.clone(); loop {
current = match current.traversal_parent() {
Some(el) => el,
None => return current,
};
let is_display_contents = current
.borrow_data()
.unwrap()
.styles
.primary()
.is_display_contents();
if !is_display_contents { return current;
}
}
}
/// Rather than comparing the resolved line-height, which can be expensive to compute /// as it involves locking and font metrics access, we consider that line-height may have /// changed if the font-size or line-height property itself has changed, or if the value /// is 'normal' and one of the properties that affects font selection (family, style, /// weight, stretch) has changed. fn line_height_likely_changed(
old_style: Option<&Arc<ComputedValues>>,
new_style: &Arc<ComputedValues>,
) -> bool { let old_line_height = old_style.map(|s| s.get_font().clone_line_height()); let new_line_height = new_style.get_font().clone_line_height(); // Return true if the old value was missing, or if the computed values are different. if old_line_height.is_none_or(|lh| lh != new_line_height) { returntrue;
} // If the value isn't `normal`, it doesn't depend on font metrics: return false. if !new_line_height.is_normal() { returnfalse;
} // Check the font-selection properties, which could affect metrics used to resolve // `normal` line-height.
macro_rules! font_property_changed {
($getter: ident) => {
old_style
.map(|s| s.get_font().$getter())
.is_none_or(|v| v != new_style.get_font().$getter())
};
}
font_property_changed!(clone_font_family)
|| font_property_changed!(clone_font_style)
|| font_property_changed!(clone_font_weight)
|| font_property_changed!(clone_font_stretch)
}
/// Updates the styles with the new ones, diffs them, and stores the restyle /// damage. fn finish_restyle(
&self,
context: &mut StyleContext<Self>,
data: &mut ElementData, mut new_styles: ResolvedElementStyles,
important_rules_changed: bool,
) -> RestyleHint { self.process_animations(
context,
&mut data.styles,
&mut new_styles,
important_rules_changed,
);
// First of all, update the styles. let old_styles = data.set_styles(new_styles);
let new_primary_style = data.styles.primary.as_ref().unwrap();
letmut child_restyle_hint = RestyleHint::empty(); let is_root = new_primary_style
.flags
.contains(ComputedValueFlags::IS_ROOT_ELEMENT_STYLE);
let device = context.shared.stylist.device(); let new_font_size = new_primary_style.get_font().clone_font_size(); let new_container_type = new_primary_style.clone_container_type();
let old_style = old_styles.primary.as_ref(); let old_font_size = old_style.map(|s| s.get_font().clone_font_size()); let font_size_changed = old_font_size.is_none_or(|fs| fs != new_font_size);
let line_height_likely_changed =
font_size_changed || Self::line_height_likely_changed(old_style, new_primary_style);
// Update root font-relative units. If any of these unit values changed // since last time, ensure that we recascade the entire tree. if is_root {
debug_assert!(self.owner_doc_matches_for_testing(device));
device.set_root_style(new_primary_style);
// Update root font size for rem units if font_size_changed { let size = new_font_size.computed_size();
device.set_root_font_size(new_primary_style.effective_zoom.unzoom(size.px()));
}
// Update root line height for rlh units if line_height_likely_changed { let new_line_height = device
.calc_line_height(
&new_primary_style.get_font(),
new_primary_style.writing_mode,
None,
)
.0;
device.set_root_line_height(
new_primary_style
.effective_zoom
.unzoom(new_line_height.px()),
);
}
// Update root font metrics for rcap, rch, rex, ric units. Since querying // font metrics can be an expensive call, they are only updated if these // units are used in the document. if device.used_root_font_metrics() && device.update_root_font_metrics() {
child_restyle_hint |= RestyleHint::RESTYLE_IF_AFFECTED_BY_ANCESTOR_FONT;
}
}
if font_size_changed || line_height_likely_changed {
child_restyle_hint |= RestyleHint::RESTYLE_IF_AFFECTED_BY_ANCESTOR_FONT;
}
if context.shared.stylist.quirks_mode() == QuirksMode::Quirks { ifself.is_html_document_body_element() { // NOTE(emilio): We _could_ handle dynamic changes to it if it // changes and before we reach our children the cascade stops, // but we don't track right now whether we use the document body // color, and nobody else handles that properly anyway. let device = context.shared.stylist.device();
// Needed for the "inherit from body" quirk. let text_color = new_primary_style.get_inherited_text().clone_color();
device.set_body_text_color(text_color);
}
}
// Don't accumulate damage if we're in the final animation traversal. if context
.shared
.traversal_flags
.contains(TraversalFlags::FinalAnimationTraversal)
{ return RestyleHint::RECASCADE_SELF;
}
// Also, don't do anything if there was no style. let old_primary_style = match old_styles.primary {
Some(s) => s,
None => return RestyleHint::RECASCADE_SELF,
};
let old_container_type = old_primary_style.clone_container_type(); if old_container_type != new_container_type && !new_container_type.is_size_container_type()
{ // Stopped being a size container. Re-evaluate container queries and units on all our descendants. // Changes into and between different size containment is handled in `UpdateContainerQueryStyles`.
child_restyle_hint |= RestyleHint::restyle_subtree();
} elseif old_container_type.is_size_container_type()
&& !old_primary_style.is_display_contents()
&& new_primary_style.is_display_contents()
{ // Also re-evaluate when a container gets 'display: contents', since size queries will now evaluate to unknown. // Other displays like 'inline' will keep generating a box, so they are handled in `UpdateContainerQueryStyles`.
child_restyle_hint |= RestyleHint::restyle_subtree();
}
if data.styles.pseudos.is_empty() && old_styles.pseudos.is_empty() { // This is the common case; no need to examine pseudos here. return child_restyle_hint;
}
let pseudo_styles = old_styles
.pseudos
.as_array()
.iter()
.zip(data.styles.pseudos.as_array().iter());
for (i, (old, new)) in pseudo_styles.enumerate() { match (old, new) {
(&Some(ref old), &Some(ref new)) => { self.accumulate_damage_for(
context.shared,
&mut data.damage,
old,
new,
Some(&PseudoElement::from_eager_index(i)),
);
},
(&None, &None) => {},
_ => { // It's possible that we're switching from not having // ::before/::after at all to having styles for them but not // actually having a useful pseudo-element. Check for that // case. let pseudo = PseudoElement::from_eager_index(i); let new_pseudo_should_exist =
new.as_ref().map_or(false, |s| pseudo.should_exist(s)); let old_pseudo_should_exist =
old.as_ref().map_or(false, |s| pseudo.should_exist(s)); if new_pseudo_should_exist != old_pseudo_should_exist {
data.damage |= RestyleDamage::reconstruct(); return child_restyle_hint;
}
},
}
}
child_restyle_hint
}
/// Updates the rule nodes without re-running selector matching, using just /// the rule tree. /// /// Returns true if an !important rule was replaced. fn replace_rules(
&self,
replacements: RestyleHint,
context: &mut StyleContext<Self>,
cascade_inputs: &mut ElementCascadeInputs,
) -> bool { letmut result = false;
result |= self.replace_rules_internal(
replacements,
context,
CascadeVisitedMode::Unvisited,
cascade_inputs,
);
result |= self.replace_rules_internal(
replacements,
context,
CascadeVisitedMode::Visited,
cascade_inputs,
);
result
}
/// Given the old and new style of this element, and whether it's a /// pseudo-element, compute the restyle damage used to determine which /// kind of layout or painting operations we'll need. fn compute_style_difference(
&self,
old_values: &ComputedValues,
new_values: &ComputedValues,
pseudo: Option<&PseudoElement>,
) -> StyleDifference {
debug_assert!(pseudo.map_or(true, |p| p.is_eager())); #[cfg(feature = "gecko")]
{
RestyleDamage::compute_style_difference(old_values, new_values)
} #[cfg(feature = "servo")]
{
RestyleDamage::compute_style_difference::<Self>(old_values, new_values)
}
}
}
impl<E: TElement> MatchMethods for E {}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.19 Sekunden
(vorverarbeitet am 2026-08-25)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.