Bug 1164813 - Make nsAnimationManager update cached in-effect status even when there is no frame. r=dbaron, a=sledru
authorBrian Birtles <birtles@gmail.com>
Fri, 22 May 2015 13:46:26 +0900
changeset 274779 03b141fb2c6842462c987099ad0a0d4a691ac094
parent 274778 1136061964e9863cb19012e7accec770ee053613
child 274780 f4151f46d4d0f5259b199e786c6eeb8eacd17814
push id863
push userraliiev@mozilla.com
push dateMon, 03 Aug 2015 13:22:43 +0000
treeherdermozilla-release@f6321b14228d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdbaron, sledru
bugs1164813
milestone40.0a2
Bug 1164813 - Make nsAnimationManager update cached in-effect status even when there is no frame. r=dbaron, a=sledru
layout/style/crashtests/1164813-1.html
layout/style/crashtests/crashtests.list
layout/style/nsAnimationManager.cpp
new file mode 100644
--- /dev/null
+++ b/layout/style/crashtests/1164813-1.html
@@ -0,0 +1,33 @@
+<!doctype html>
+<html class="reftest-wait">
+<style>
+#parent.hidden {
+  display: none;
+}
+.icon {
+  opacity: 0;
+  transition: opacity 0.5s;
+}
+.icon.shrink {
+  animation: shrink 1s;
+}
+@keyframes shrink {
+  to { transform: scale(0); }
+}
+</style>
+<div id="parent">
+  <div class="icon">Searching</div>
+</div>
+<script>
+var icon = document.querySelector('.icon');
+getComputedStyle(icon).opacity;
+icon.style.opacity = 1;
+icon.classList.add('shrink');
+setTimeout(function() {
+  document.getElementById('parent').classList.add('hidden');
+  setTimeout(function() {
+    document.documentElement.removeAttribute('class');
+  }, 500);
+}, 500);
+</script>
+</html>
--- a/layout/style/crashtests/crashtests.list
+++ b/layout/style/crashtests/crashtests.list
@@ -109,10 +109,11 @@ load 992333-1.html
 pref(dom.webcomponents.enabled,true) load 1017798-1.html
 load 1028514-1.html
 load 1066089-1.html
 load 1074651-1.html
 pref(dom.webcomponents.enabled,true) load 1089463-1.html
 pref(layout.css.expensive-style-struct-assertions.enabled,true) load 1136010-1.html
 load 1153693-1.html
 load 1161366-1.html
+load 1164813-1.html
 load large_border_image_width.html
 load border-image-visited-link.html
--- a/layout/style/nsAnimationManager.cpp
+++ b/layout/style/nsAnimationManager.cpp
@@ -225,23 +225,35 @@ nsAnimationManager::QueueEvents(Animatio
 void
 nsAnimationManager::MaybeUpdateCascadeResults(AnimationCollection* aCollection)
 {
   for (size_t animIdx = aCollection->mAnimations.Length(); animIdx-- != 0; ) {
     CSSAnimation* anim = aCollection->mAnimations[animIdx]->AsCSSAnimation();
     if (anim->IsInEffect() != anim->mInEffectForCascadeResults) {
       // Update our own cascade results.
       mozilla::dom::Element* element = aCollection->GetElementToRestyle();
+      bool updatedCascadeResults = false;
       if (element) {
         nsIFrame* frame = element->GetPrimaryFrame();
         if (frame) {
           UpdateCascadeResults(frame->StyleContext(), aCollection);
+          updatedCascadeResults = true;
         }
       }
 
+      if (!updatedCascadeResults) {
+        // If we don't have a style context we can't do the work of updating
+        // cascading results but we need to make sure to update
+        // mInEffectForCascadeResults or else we'll keep running this
+        // code every time (potentially leading to infinite recursion due
+        // to the fact that this method both calls and is (indirectly) called
+        // by nsTransitionManager).
+        anim->mInEffectForCascadeResults = anim->IsInEffect();
+      }
+
       // Notify the transition manager, whose results might depend on ours.
       mPresContext->TransitionManager()->
         UpdateCascadeResultsWithAnimations(aCollection);
 
       return;
     }
   }
 }