Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

style: Split style resolution and dynamic change computation. #17688

Merged
merged 11 commits into from Jul 12, 2017

style: Undo the optimization for grabbing animation rules from the st…

…yle 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
  • Loading branch information
emilio committed Jul 12, 2017
commit cc94a8b7cb1849baef91280e6fd078aece4cd58c
@@ -8,11 +8,11 @@ use arrayvec::ArrayVec;
use context::SharedStyleContext;
use dom::TElement;
use invalidation::element::restyle_hints::RestyleHint;
use properties::{AnimationRules, ComputedValues, PropertyDeclarationBlock};
use properties::ComputedValues;
use properties::longhands::display::computed_value as display;
use rule_tree::StrongRuleNode;
use selector_parser::{EAGER_PSEUDO_COUNT, PseudoElement, RestyleDamage};
use shared_lock::{Locked, StylesheetGuards};
use shared_lock::StylesheetGuards;
use std::ops::{Deref, DerefMut};
use stylearc::Arc;

@@ -402,29 +402,4 @@ impl ElementData {
pub fn clear_restyle_state(&mut self) {
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),
}
}
}
@@ -15,7 +15,7 @@ use data::ElementData;
use element_state::ElementState;
use font_metrics::FontMetricsProvider;
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::TransitionProperty;
use rule_tree::CascadeLevel;
@@ -379,6 +379,18 @@ pub trait TElement : Eq + PartialEq + Debug + Hash + Sized + Copy + Clone +
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.
fn get_animation_rule(&self)
-> Option<Arc<Locked<PropertyDeclarationBlock>>> {
@@ -237,7 +237,7 @@ impl CascadeVisitedMode {

/// Returns whether there might be visited values that should be inserted
/// 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
}

@@ -258,7 +258,7 @@ impl CascadeVisitedMode {

/// Returns whether the cascade should filter to only visited dependent
/// properties based on the cascade mode.
fn visited_dependent_only(&self) -> bool {
pub fn visited_dependent_only(&self) -> bool {
*self == CascadeVisitedMode::Visited
}
}
@@ -446,7 +446,7 @@ trait PrivateMatchMethods: TElement {
debug_assert!(pseudo.is_before_or_after());
let parent = self.parent_element().unwrap();
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 pseudo_style =
parent_data.styles.pseudos.get(&pseudo).unwrap();
@@ -994,12 +994,12 @@ impl MatchingResults {
pub trait MatchMethods : TElement {
/// Performs selector matching and property cascading on an element and its
/// eager pseudos.
fn match_and_cascade(&self,
context: &mut StyleContext<Self>,
data: &mut ElementData,
sharing: StyleSharingBehavior)
-> ChildCascadeRequirement
{
fn match_and_cascade(
&self,
context: &mut StyleContext<Self>,
data: &mut ElementData,
sharing: StyleSharingBehavior
) -> ChildCascadeRequirement {
debug!("Match and cascade for {:?}", self);

// Perform selector matching for the primary style.
@@ -1021,16 +1021,24 @@ pub trait MatchMethods : TElement {
// if our parent has visited styles.
let parent_and_styles = self.get_inherited_style_and_parent();
if relevant_link_found || parent_and_styles.has_visited_style() {
self.cascade_primary(context, data, important_rules_changed,
&parent_and_styles,
CascadeVisitedMode::Visited);
self.cascade_primary(
context,
data,
important_rules_changed,
&parent_and_styles,
CascadeVisitedMode::Visited
);
}

// Cascade properties and compute primary values.
let child_cascade_requirement =
self.cascade_primary(context, data, important_rules_changed,
&parent_and_styles,
CascadeVisitedMode::Unvisited);
self.cascade_primary(
context,
data,
important_rules_changed,
&parent_and_styles,
CascadeVisitedMode::Unvisited
);

// Match and cascade eager pseudo-elements.
if !data.styles.is_display_none() {
@@ -1109,12 +1117,12 @@ pub trait MatchMethods : TElement {
///
/// Returns `MatchingResults` with the new rules and other associated data
/// from the matching process.
fn match_primary(&self,
context: &mut StyleContext<Self>,
data: &mut ElementData,
visited_handling: VisitedHandlingMode)
-> MatchingResults
{
fn match_primary(
&self,
context: &mut StyleContext<Self>,
data: &mut ElementData,
visited_handling: VisitedHandlingMode
) -> MatchingResults {
debug!("Match primary for {:?}, visited: {:?}", self, visited_handling);

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();
let mut rules = pseudo_style.rules().clone();
if parent.may_have_animations() {
let animation_rules = data.get_animation_rules();
let animation_rules = self.get_animation_rules();

// Handle animations here.
if let Some(animation_rule) = animation_rules.0 {
@@ -1208,12 +1216,8 @@ pub trait MatchMethods : TElement {
context.shared.quirks_mode);

{
let smil_override = data.get_smil_override();
let animation_rules = if self.may_have_animations() {
data.get_animation_rules()
} else {
AnimationRules(None, None)
};
let smil_override = self.get_smil_override();
let animation_rules = self.get_animation_rules();

// Compute the primary rule node.
stylist.push_applicable_declarations(self,
@@ -28,10 +28,10 @@ use values::computed::Context;
///
/// The first one is for Animation cascade level, and the second one is for
/// Transition cascade level.
pub struct AnimationRules<'a>(pub Option<&'a Arc<Locked<PropertyDeclarationBlock>>>,
pub Option<&'a Arc<Locked<PropertyDeclarationBlock>>>);
pub struct AnimationRules(pub Option<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.
pub fn is_empty(&self) -> bool {
self.0.is_none() && self.1.is_none()
@@ -9,7 +9,7 @@
use applicable_declarations::ApplicableDeclarationList;
#[cfg(feature = "servo")]
use heapsize::HeapSizeOf;
use properties::{AnimationRules, Importance, LonghandIdSet, PropertyDeclarationBlock};
use properties::{Importance, LonghandIdSet, PropertyDeclarationBlock};
use shared_lock::{Locked, StylesheetGuards, SharedRwLockReadGuard};
use smallvec::SmallVec;
use std::io::{self, Write};
@@ -1321,32 +1321,6 @@ impl StrongRuleNode {
.find(|node| node.cascade_level() == CascadeLevel::SMILOverride)
.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.
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.