style: Undo the optimization for grabbing animation rules from the style data.

This is unfortunate, but for now it complicates things, I would like not needing
a ElementData to get the style of an Element in order to fix all the
getDefaultComputedStyle bugs.

MozReview-Commit-ID: LZvsdFEqrDE
This commit is contained in:
Emilio Cobos Álvarez 2017-07-09 21:01:00 +02:00
parent 95a2ac51c4
commit cc94a8b7cb
No known key found for this signature in database
GPG key ID: 056B727BB9C1027C
5 changed files with 51 additions and 86 deletions

View file

@ -8,11 +8,11 @@ use arrayvec::ArrayVec;
use context::SharedStyleContext; use context::SharedStyleContext;
use dom::TElement; use dom::TElement;
use invalidation::element::restyle_hints::RestyleHint; use invalidation::element::restyle_hints::RestyleHint;
use properties::{AnimationRules, ComputedValues, PropertyDeclarationBlock}; use properties::ComputedValues;
use properties::longhands::display::computed_value as display; use properties::longhands::display::computed_value as display;
use rule_tree::StrongRuleNode; use rule_tree::StrongRuleNode;
use selector_parser::{EAGER_PSEUDO_COUNT, PseudoElement, RestyleDamage}; use selector_parser::{EAGER_PSEUDO_COUNT, PseudoElement, RestyleDamage};
use shared_lock::{Locked, StylesheetGuards}; use shared_lock::StylesheetGuards;
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
use stylearc::Arc; use stylearc::Arc;
@ -402,29 +402,4 @@ impl ElementData {
pub fn clear_restyle_state(&mut self) { pub fn clear_restyle_state(&mut self) {
self.restyle.clear(); self.restyle.clear();
} }
/// Returns SMIL overriden value if exists.
pub fn get_smil_override(&self) -> Option<&Arc<Locked<PropertyDeclarationBlock>>> {
if cfg!(feature = "servo") {
// Servo has no knowledge of a SMIL rule, so just avoid looking for it.
return None;
}
match self.styles.get_primary() {
Some(v) => v.rules().get_smil_animation_rule(),
None => None,
}
}
/// Returns AnimationRules that has processed during animation-only restyles.
pub fn get_animation_rules(&self) -> AnimationRules {
if cfg!(feature = "servo") {
return AnimationRules(None, None)
}
match self.styles.get_primary() {
Some(v) => v.rules().get_animation_rules(),
None => AnimationRules(None, None),
}
}
} }

View file

@ -15,7 +15,7 @@ use data::ElementData;
use element_state::ElementState; use element_state::ElementState;
use font_metrics::FontMetricsProvider; use font_metrics::FontMetricsProvider;
use media_queries::Device; use media_queries::Device;
use properties::{ComputedValues, PropertyDeclarationBlock}; use properties::{AnimationRules, ComputedValues, PropertyDeclarationBlock};
#[cfg(feature = "gecko")] use properties::animated_properties::AnimationValue; #[cfg(feature = "gecko")] use properties::animated_properties::AnimationValue;
#[cfg(feature = "gecko")] use properties::animated_properties::TransitionProperty; #[cfg(feature = "gecko")] use properties::animated_properties::TransitionProperty;
use rule_tree::CascadeLevel; use rule_tree::CascadeLevel;
@ -379,6 +379,18 @@ pub trait TElement : Eq + PartialEq + Debug + Hash + Sized + Copy + Clone +
None None
} }
/// Get the combined animation and transition rules.
fn get_animation_rules(&self) -> AnimationRules {
if !self.may_have_animations() {
return AnimationRules(None, None)
}
AnimationRules(
self.get_animation_rule(),
self.get_transition_rule(),
)
}
/// Get this element's animation rule. /// Get this element's animation rule.
fn get_animation_rule(&self) fn get_animation_rule(&self)
-> Option<Arc<Locked<PropertyDeclarationBlock>>> { -> Option<Arc<Locked<PropertyDeclarationBlock>>> {

View file

@ -237,7 +237,7 @@ impl CascadeVisitedMode {
/// Returns whether there might be visited values that should be inserted /// Returns whether there might be visited values that should be inserted
/// within the regular computed values based on the cascade mode. /// within the regular computed values based on the cascade mode.
fn visited_values_for_insertion(&self) -> bool { pub fn visited_values_for_insertion(&self) -> bool {
*self == CascadeVisitedMode::Unvisited *self == CascadeVisitedMode::Unvisited
} }
@ -258,7 +258,7 @@ impl CascadeVisitedMode {
/// Returns whether the cascade should filter to only visited dependent /// Returns whether the cascade should filter to only visited dependent
/// properties based on the cascade mode. /// properties based on the cascade mode.
fn visited_dependent_only(&self) -> bool { pub fn visited_dependent_only(&self) -> bool {
*self == CascadeVisitedMode::Visited *self == CascadeVisitedMode::Visited
} }
} }
@ -446,7 +446,7 @@ trait PrivateMatchMethods: TElement {
debug_assert!(pseudo.is_before_or_after()); debug_assert!(pseudo.is_before_or_after());
let parent = self.parent_element().unwrap(); let parent = self.parent_element().unwrap();
if !parent.may_have_animations() || if !parent.may_have_animations() ||
primary_inputs.rules().get_animation_rules().is_empty() { self.get_animation_rules().is_empty() {
let parent_data = parent.borrow_data().unwrap(); let parent_data = parent.borrow_data().unwrap();
let pseudo_style = let pseudo_style =
parent_data.styles.pseudos.get(&pseudo).unwrap(); parent_data.styles.pseudos.get(&pseudo).unwrap();
@ -994,12 +994,12 @@ impl MatchingResults {
pub trait MatchMethods : TElement { pub trait MatchMethods : TElement {
/// Performs selector matching and property cascading on an element and its /// Performs selector matching and property cascading on an element and its
/// eager pseudos. /// eager pseudos.
fn match_and_cascade(&self, fn match_and_cascade(
&self,
context: &mut StyleContext<Self>, context: &mut StyleContext<Self>,
data: &mut ElementData, data: &mut ElementData,
sharing: StyleSharingBehavior) sharing: StyleSharingBehavior
-> ChildCascadeRequirement ) -> ChildCascadeRequirement {
{
debug!("Match and cascade for {:?}", self); debug!("Match and cascade for {:?}", self);
// Perform selector matching for the primary style. // Perform selector matching for the primary style.
@ -1021,16 +1021,24 @@ pub trait MatchMethods : TElement {
// if our parent has visited styles. // if our parent has visited styles.
let parent_and_styles = self.get_inherited_style_and_parent(); let parent_and_styles = self.get_inherited_style_and_parent();
if relevant_link_found || parent_and_styles.has_visited_style() { if relevant_link_found || parent_and_styles.has_visited_style() {
self.cascade_primary(context, data, important_rules_changed, self.cascade_primary(
context,
data,
important_rules_changed,
&parent_and_styles, &parent_and_styles,
CascadeVisitedMode::Visited); CascadeVisitedMode::Visited
);
} }
// Cascade properties and compute primary values. // Cascade properties and compute primary values.
let child_cascade_requirement = let child_cascade_requirement =
self.cascade_primary(context, data, important_rules_changed, self.cascade_primary(
context,
data,
important_rules_changed,
&parent_and_styles, &parent_and_styles,
CascadeVisitedMode::Unvisited); CascadeVisitedMode::Unvisited
);
// Match and cascade eager pseudo-elements. // Match and cascade eager pseudo-elements.
if !data.styles.is_display_none() { if !data.styles.is_display_none() {
@ -1109,12 +1117,12 @@ pub trait MatchMethods : TElement {
/// ///
/// Returns `MatchingResults` with the new rules and other associated data /// Returns `MatchingResults` with the new rules and other associated data
/// from the matching process. /// from the matching process.
fn match_primary(&self, fn match_primary(
&self,
context: &mut StyleContext<Self>, context: &mut StyleContext<Self>,
data: &mut ElementData, data: &mut ElementData,
visited_handling: VisitedHandlingMode) visited_handling: VisitedHandlingMode
-> MatchingResults ) -> MatchingResults {
{
debug!("Match primary for {:?}, visited: {:?}", self, visited_handling); debug!("Match primary for {:?}, visited: {:?}", self, visited_handling);
let mut primary_inputs = context.thread_local.current_element_info let mut primary_inputs = context.thread_local.current_element_info
@ -1145,7 +1153,7 @@ pub trait MatchMethods : TElement {
parent_data.styles.pseudos.get(&pseudo).unwrap(); parent_data.styles.pseudos.get(&pseudo).unwrap();
let mut rules = pseudo_style.rules().clone(); let mut rules = pseudo_style.rules().clone();
if parent.may_have_animations() { if parent.may_have_animations() {
let animation_rules = data.get_animation_rules(); let animation_rules = self.get_animation_rules();
// Handle animations here. // Handle animations here.
if let Some(animation_rule) = animation_rules.0 { if let Some(animation_rule) = animation_rules.0 {
@ -1208,12 +1216,8 @@ pub trait MatchMethods : TElement {
context.shared.quirks_mode); context.shared.quirks_mode);
{ {
let smil_override = data.get_smil_override(); let smil_override = self.get_smil_override();
let animation_rules = if self.may_have_animations() { let animation_rules = self.get_animation_rules();
data.get_animation_rules()
} else {
AnimationRules(None, None)
};
// Compute the primary rule node. // Compute the primary rule node.
stylist.push_applicable_declarations(self, stylist.push_applicable_declarations(self,

View file

@ -28,10 +28,10 @@ use values::computed::Context;
/// ///
/// The first one is for Animation cascade level, and the second one is for /// The first one is for Animation cascade level, and the second one is for
/// Transition cascade level. /// Transition cascade level.
pub struct AnimationRules<'a>(pub Option<&'a Arc<Locked<PropertyDeclarationBlock>>>, pub struct AnimationRules(pub Option<Arc<Locked<PropertyDeclarationBlock>>>,
pub Option<&'a Arc<Locked<PropertyDeclarationBlock>>>); pub Option<Arc<Locked<PropertyDeclarationBlock>>>);
impl<'a> AnimationRules<'a> { impl AnimationRules {
/// Returns whether these animation rules represents an actual rule or not. /// Returns whether these animation rules represents an actual rule or not.
pub fn is_empty(&self) -> bool { pub fn is_empty(&self) -> bool {
self.0.is_none() && self.1.is_none() self.0.is_none() && self.1.is_none()

View file

@ -9,7 +9,7 @@
use applicable_declarations::ApplicableDeclarationList; use applicable_declarations::ApplicableDeclarationList;
#[cfg(feature = "servo")] #[cfg(feature = "servo")]
use heapsize::HeapSizeOf; use heapsize::HeapSizeOf;
use properties::{AnimationRules, Importance, LonghandIdSet, PropertyDeclarationBlock}; use properties::{Importance, LonghandIdSet, PropertyDeclarationBlock};
use shared_lock::{Locked, StylesheetGuards, SharedRwLockReadGuard}; use shared_lock::{Locked, StylesheetGuards, SharedRwLockReadGuard};
use smallvec::SmallVec; use smallvec::SmallVec;
use std::io::{self, Write}; use std::io::{self, Write};
@ -1321,32 +1321,6 @@ impl StrongRuleNode {
.find(|node| node.cascade_level() == CascadeLevel::SMILOverride) .find(|node| node.cascade_level() == CascadeLevel::SMILOverride)
.map(|node| node.get_animation_style()) .map(|node| node.get_animation_style())
} }
/// Returns AnimationRules that has processed during animation-only restyles.
pub fn get_animation_rules(&self) -> AnimationRules {
if cfg!(feature = "servo") {
return AnimationRules(None, None);
}
let mut animation = None;
let mut transition = None;
for node in self.self_and_ancestors()
.take_while(|node| node.cascade_level() >= CascadeLevel::Animations) {
match node.cascade_level() {
CascadeLevel::Animations => {
debug_assert!(animation.is_none());
animation = Some(node.get_animation_style())
},
CascadeLevel::Transitions => {
debug_assert!(transition.is_none());
transition = Some(node.get_animation_style())
},
_ => {},
}
}
AnimationRules(animation, transition)
}
} }
/// An iterator over a rule node and its ancestors. /// An iterator over a rule node and its ancestors.