style: Check transitions per longhand to know which transitions to keep.

This fixes the fishy TransitionProperty mapping which I complained about in my
previous refactor.

Turns out that those properties could only be longhands, and thus the expansion
we did before that (and which I removed) was correct.

This fixes the bug by moving back to the previous correct behavior but using the
correct types.

The optimization to avoid creating a HashSet if we're transitioning all
properties or had no existing transition is removed since now we're creating a
LonghandIdSet, which is cheap, and that was only a performance optimization.
This commit is contained in:
Emilio Cobos Álvarez 2017-10-05 20:07:10 +02:00
parent f2879a568d
commit c60b8288bc
No known key found for this signature in database
GPG key ID: 056B727BB9C1027C
2 changed files with 28 additions and 30 deletions

View file

@ -19,7 +19,6 @@ use media_queries::Device;
use properties::{AnimationRules, ComputedValues, PropertyDeclarationBlock}; use properties::{AnimationRules, ComputedValues, PropertyDeclarationBlock};
#[cfg(feature = "gecko")] use properties::LonghandId; #[cfg(feature = "gecko")] use properties::LonghandId;
#[cfg(feature = "gecko")] use properties::animated_properties::AnimationValue; #[cfg(feature = "gecko")] use properties::animated_properties::AnimationValue;
#[cfg(feature = "gecko")] use properties::animated_properties::TransitionProperty;
use rule_tree::CascadeLevel; use rule_tree::CascadeLevel;
use selector_parser::{AttrValue, ElementExt}; use selector_parser::{AttrValue, ElementExt};
use selector_parser::{PseudoClassStringArg, PseudoElement}; use selector_parser::{PseudoClassStringArg, PseudoElement};
@ -651,7 +650,7 @@ pub trait TElement : Eq + PartialEq + Debug + Hash + Sized + Copy + Clone +
/// Gets the current existing CSS transitions, by |property, end value| pairs in a FnvHashMap. /// Gets the current existing CSS transitions, by |property, end value| pairs in a FnvHashMap.
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
fn get_css_transitions_info(&self) fn get_css_transitions_info(&self)
-> FnvHashMap<TransitionProperty, Arc<AnimationValue>>; -> FnvHashMap<LonghandId, Arc<AnimationValue>>;
/// Does a rough (and cheap) check for whether or not transitions might need to be updated that /// Does a rough (and cheap) check for whether or not transitions might need to be updated that
/// will quickly return false for the common case of no transitions specified or running. If /// will quickly return false for the common case of no transitions specified or running. If
@ -684,7 +683,7 @@ pub trait TElement : Eq + PartialEq + Debug + Hash + Sized + Copy + Clone +
combined_duration: f32, combined_duration: f32,
before_change_style: &ComputedValues, before_change_style: &ComputedValues,
after_change_style: &ComputedValues, after_change_style: &ComputedValues,
existing_transitions: &FnvHashMap<TransitionProperty, Arc<AnimationValue>> existing_transitions: &FnvHashMap<LonghandId, Arc<AnimationValue>>
) -> bool; ) -> bool;
/// Returns the value of the `xml:lang=""` attribute (or, if appropriate, /// Returns the value of the `xml:lang=""` attribute (or, if appropriate,

View file

@ -1303,19 +1303,30 @@ impl<'le> TElement for GeckoElement<'le> {
fn get_css_transitions_info( fn get_css_transitions_info(
&self, &self,
) -> FnvHashMap<TransitionProperty, Arc<AnimationValue>> { ) -> FnvHashMap<LonghandId, Arc<AnimationValue>> {
use gecko_bindings::bindings::Gecko_ElementTransitions_EndValueAt; use gecko_bindings::bindings::Gecko_ElementTransitions_EndValueAt;
use gecko_bindings::bindings::Gecko_ElementTransitions_Length; use gecko_bindings::bindings::Gecko_ElementTransitions_Length;
use gecko_bindings::bindings::Gecko_ElementTransitions_PropertyAt; use gecko_bindings::bindings::Gecko_ElementTransitions_PropertyAt;
let collection_length = let collection_length =
unsafe { Gecko_ElementTransitions_Length(self.0) }; unsafe { Gecko_ElementTransitions_Length(self.0) } as usize;
let mut map = FnvHashMap::with_capacity_and_hasher(collection_length, Default::default()); let mut map = FnvHashMap::with_capacity_and_hasher(
collection_length,
Default::default()
);
for i in 0..collection_length { for i in 0..collection_length {
let (property, raw_end_value) = unsafe { let property = unsafe {
(Gecko_ElementTransitions_PropertyAt(self.0, i as usize).into(), Gecko_ElementTransitions_PropertyAt(self.0, i as usize)
Gecko_ElementTransitions_EndValueAt(self.0, i as usize))
}; };
let property = LonghandId::from_nscsspropertyid(property)
.expect("Only longhands should be in the element transitions");
let raw_end_value = unsafe {
Gecko_ElementTransitions_EndValueAt(self.0, i)
};
let end_value = AnimationValue::arc_from_borrowed(&raw_end_value); let end_value = AnimationValue::arc_from_borrowed(&raw_end_value);
debug_assert!(end_value.is_some()); debug_assert!(end_value.is_some());
map.insert(property, end_value.unwrap().clone_arc()); map.insert(property, end_value.unwrap().clone_arc());
@ -1363,7 +1374,7 @@ impl<'le> TElement for GeckoElement<'le> {
after_change_style: &ComputedValues after_change_style: &ComputedValues
) -> bool { ) -> bool {
use gecko_bindings::structs::nsCSSPropertyID; use gecko_bindings::structs::nsCSSPropertyID;
use std::collections::HashSet; use properties::LonghandIdSet;
debug_assert!(self.might_need_transitions_update(Some(before_change_style), debug_assert!(self.might_need_transitions_update(Some(before_change_style),
after_change_style), after_change_style),
@ -1381,13 +1392,7 @@ impl<'le> TElement for GeckoElement<'le> {
property == nsCSSPropertyID::eCSSProperty_UNKNOWN; property == nsCSSPropertyID::eCSSProperty_UNKNOWN;
}; };
let mut transitions_to_keep = if !existing_transitions.is_empty() && let mut transitions_to_keep = LonghandIdSet::new();
(after_change_box_style.transition_nscsspropertyid_at(0) !=
nsCSSPropertyID::eCSSPropertyExtra_all_properties) {
Some(HashSet::<TransitionProperty>::with_capacity(transitions_count))
} else {
None
};
for i in 0..transitions_count { for i in 0..transitions_count {
let property = after_change_box_style.transition_nscsspropertyid_at(i); let property = after_change_box_style.transition_nscsspropertyid_at(i);
@ -1400,7 +1405,8 @@ impl<'le> TElement for GeckoElement<'le> {
let transition_property: TransitionProperty = property.into(); let transition_property: TransitionProperty = property.into();
let property_check_helper = |property: &LonghandId| -> bool { let mut property_check_helper = |property: &LonghandId| -> bool {
transitions_to_keep.insert(*property);
self.needs_transitions_update_per_property( self.needs_transitions_update_per_property(
property, property,
combined_duration, combined_duration,
@ -1427,17 +1433,13 @@ impl<'le> TElement for GeckoElement<'le> {
return true; return true;
} }
}, },
};
if let Some(ref mut transitions_to_keep) = transitions_to_keep {
transitions_to_keep.insert(transition_property);
} }
} }
// Check if we have to cancel the running transition because this is not // Check if we have to cancel the running transition because this is not
// a matching transition-property value. // a matching transition-property value.
transitions_to_keep.map_or(false, |set| { existing_transitions.keys().any(|property| {
existing_transitions.keys().any(|property| !set.contains(property)) !transitions_to_keep.contains(*property)
}) })
} }
@ -1447,7 +1449,7 @@ impl<'le> TElement for GeckoElement<'le> {
combined_duration: f32, combined_duration: f32,
before_change_style: &ComputedValues, before_change_style: &ComputedValues,
after_change_style: &ComputedValues, after_change_style: &ComputedValues,
existing_transitions: &FnvHashMap<TransitionProperty, Arc<AnimationValue>>, existing_transitions: &FnvHashMap<LonghandId, Arc<AnimationValue>>,
) -> bool { ) -> bool {
use values::animated::{Animate, Procedure}; use values::animated::{Animate, Procedure};
@ -1457,13 +1459,10 @@ impl<'le> TElement for GeckoElement<'le> {
// If the end value has not changed, we should leave the currently // If the end value has not changed, we should leave the currently
// running transition as-is since we don't want to interrupt its timing // running transition as-is since we don't want to interrupt its timing
// function. // function.
// if let Some(ref existing) = existing_transitions.get(longhand_id) {
// FIXME(emilio): The shorthand / longhand mapping with transitions
// looks pretty fishy!
if let Some(ref existing) = existing_transitions.get(&TransitionProperty::Longhand(*longhand_id)) {
let after_value = let after_value =
AnimationValue::from_computed_values( AnimationValue::from_computed_values(
&longhand_id, longhand_id,
after_change_style after_change_style
).unwrap(); ).unwrap();