Bug 1318697 - Part 1: Skip composing styles for properties depending on cascade level. r?birtles
When we are composing style for the Animations level of the cascade,
if we have transitions-level animations, we *also* need to compose them if we
have animations-level animations that build on top of them using additive or
accumulative composite modes.
However, we should not build those transitions-level animations unless they will
be built on or overridden by a regular animations-level animation. Otherwise
we will end up with transitions-level animations in the animations-level and
while transitions-level will override the animations-level in the cascade,
once the transition finishes there will be nothing to remove the cached
animations-level animation rule.
MozReview-Commit-ID: LaRabzDSsO5
--- a/dom/animation/EffectCompositor.cpp
+++ b/dom/animation/EffectCompositor.cpp
@@ -621,17 +621,17 @@ EffectCompositor::ComposeAnimationRule(d
effects->AnimationRule(aCascadeLevel);
animationRule = nullptr;
// If multiple animations affect the same property, animations with higher
// composite order (priority) override or add or animations with lower
// priority except properties in propertiesToSkip.
const nsCSSPropertyIDSet& propertiesToSkip =
aCascadeLevel == CascadeLevel::Animations
- ? nsCSSPropertyIDSet()
+ ? effects->PropertiesForAnimationsLevel().Invert()
: effects->PropertiesForAnimationsLevel();
for (KeyframeEffectReadOnly* effect : sortedEffectList) {
effect->GetAnimation()->ComposeStyle(animationRule, propertiesToSkip);
}
MOZ_ASSERT(effects == EffectSet::GetEffectSet(aElement, aPseudoType),
"EffectSet should not change while composing style");
--- a/layout/reftests/css-transitions/reftest.list
+++ b/layout/reftests/css-transitions/reftest.list
@@ -1,8 +1,9 @@
== transitions-inline-already-wrapped-1.html transitions-inline-ref.html
== transitions-inline-already-wrapped-2.html transitions-inline-ref.html
== transitions-inline-rewrap-1.html transitions-inline-ref.html
== transitions-inline-rewrap-2.html transitions-inline-ref.html
== stacking-context-opacity-lose-to-animation.html stacking-context-transition-ref.html
== stacking-context-transform-lose-to-animation.html stacking-context-transition-ref.html
== stacking-context-opacity-wins-over-important-style.html stacking-context-transition-ref.html
== stacking-context-transform-wins-over-important-style.html stacking-context-transition-ref.html
+== transition-and-animation-with-different-durations.html transition-and-animation-with-different-durations-ref.html
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-transitions/transition-and-animation-with-different-durations-ref.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<title>A reference of 100x100 blue box</title>
+<style>
+div {
+ width: 100px; height: 100px;
+ background: blue;
+}
+</style>
+<div></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-transitions/transition-and-animation-with-different-durations.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>
+Transform animation and opacity transition with different durations
+</title>
+<style>
+div {
+ width: 100px; height: 100px;
+ background: blue;
+}
+@keyframes translate {
+ from { transform: translateY(0px); }
+ to { transform: translateY(0px); }
+}
+</style>
+<div id="target"></div>
+<script>
+window.addEventListener("load", () => {
+ var target = document.getElementById("target");
+ target.style = "opacity: 0;";
+
+ getComputedStyle(target).transform;
+
+ target.style = "transition: opacity 0.2s; opacity: 1; " +
+ "animation: translate 0.1s;";
+
+ target.addEventListener("transitionend", () => {
+ document.documentElement.classList.remove("reftest-wait");
+ }, false);
+});
+</script>
--- a/layout/style/nsCSSPropertyIDSet.h
+++ b/layout/style/nsCSSPropertyIDSet.h
@@ -62,16 +62,25 @@ public:
NS_ASSERTION(mProperties[i] == 0, aText);
}
}
bool Equals(const nsCSSPropertyIDSet& aOther) const {
return mozilla::PodEqual(mProperties, aOther.mProperties);
}
+ // Return a new nsCSSPropertyIDSet which is the inverse of this set.
+ nsCSSPropertyIDSet Invert() const {
+ nsCSSPropertyIDSet result;
+ for (size_t i = 0; i < mozilla::ArrayLength(mProperties); ++i) {
+ result.mProperties[i] = ~mProperties[i];
+ }
+ return result;
+ }
+
private:
typedef unsigned long property_set_type;
public:
// number of bits in |property_set_type|.
static const size_t kBitsInChunk = sizeof(property_set_type)*CHAR_BIT;
// number of |property_set_type|s in the set
static const size_t kChunkCount =
(eCSSProperty_COUNT_no_shorthands + kBitsInChunk - 1) / kBitsInChunk;