Bug 1164813 - Make nsAnimationManager update cached in-effect status even when there is no frame; r=dbaron
authorBrian Birtles <birtles@gmail.com>
Fri, 22 May 2015 13:46:26 +0900
changeset 266216 7be1fe5cd273c9922640f40050b860d7275cc909
parent 266215 65cdf88a1ee2a35c0ec9c348ade1a231ae8add66
child 266217 59c302146319ba0c4f1764d8bc703c5467b69476
push id2231
push usermichael.l.comella@gmail.com
push dateFri, 22 May 2015 20:04:59 +0000
reviewersdbaron
bugs1164813
milestone41.0a1
Bug 1164813 - Make nsAnimationManager update cached in-effect status even when there is no frame; r=dbaron
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
@@ -112,10 +112,11 @@ 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 1161320-1.html
 pref(dom.animations-api.core.enabled,true) load 1161320-2.html
 load 1161366-1.html
 load 1163446-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
@@ -241,23 +241,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;
     }
   }
 }