Bug 1318697 - Part 1: Skip composing styles for properties depending on cascade level. r?birtles draft
authorHiroyuki Ikezoe <hiikezoe@mozilla-japan.org>
Tue, 29 Nov 2016 15:04:17 +0900
changeset 445141 151dfc009292581e014213960a7a729bbd84ea10
parent 444725 8387a4ada9a5c4cab059d8fafe0f8c933e83c149
child 538446 17d6056e2d1cf3045fbb831f0d318df9d550409d
push id37427
push userhiikezoe@mozilla-japan.org
push dateTue, 29 Nov 2016 06:24:13 +0000
reviewersbirtles
bugs1318697
milestone53.0a1
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
dom/animation/EffectCompositor.cpp
layout/reftests/css-transitions/reftest.list
layout/reftests/css-transitions/transition-and-animation-with-different-durations-ref.html
layout/reftests/css-transitions/transition-and-animation-with-different-durations.html
layout/style/nsCSSPropertyIDSet.h
--- 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;