Bug 735943 - Don't crash if nsSMILAnimationController::FlushResampleRequests destroyed the pres shell. r=bz a=akeybl
authorMats Palmgren <matspal@gmail.com>
Tue, 20 Mar 2012 19:02:38 +0100
changeset 90644 18753a4ee7cdc2ef365a1ebc1c66f5d32ec81926
parent 90643 d28f72430f65fe3003b8021078653e777d4854eb
child 90645 2fe257c037f1efe835db9090f7b800983d480a76
push id1058
push usermpalmgren@mozilla.com
push dateTue, 03 Apr 2012 09:06:10 +0000
treeherdermozilla-aurora@18753a4ee7cd [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz, akeybl
bugs735943
milestone13.0a2
Bug 735943 - Don't crash if nsSMILAnimationController::FlushResampleRequests destroyed the pres shell. r=bz a=akeybl
content/smil/nsSMILAnimationController.cpp
content/smil/nsSMILAnimationController.h
layout/base/crashtests/735943.html
layout/base/crashtests/crashtests.list
layout/base/nsPresShell.cpp
--- a/content/smil/nsSMILAnimationController.cpp
+++ b/content/smil/nsSMILAnimationController.cpp
@@ -394,18 +394,24 @@ nsSMILAnimationController::DoSample(bool
     NS_ERROR("Shouldn't be sampling after document has disconnected");
     return;
   }
 
   mResampleNeeded = false;
   // Set running sample flag -- do this before flushing styles so that when we
   // flush styles we don't end up requesting extra samples
   mRunningSample = true;
+  nsCOMPtr<nsIDocument> kungFuDeathGrip(mDocument);  // keeps 'this' alive too
   mDocument->FlushPendingNotifications(Flush_Style);
 
+  // WARNING: 
+  // WARNING: the above flush may have destroyed the pres shell and/or
+  // WARNING: frames and other layout related objects.
+  // WARNING:
+  
   // STEP 1: Bring model up to date
   // (i)  Rewind elements where necessary
   // (ii) Run milestone samples
   RewindElements();
   DoMilestoneSamples();
 
   // STEP 2: Sample the child time containers
   //
--- a/content/smil/nsSMILAnimationController.h
+++ b/content/smil/nsSMILAnimationController.h
@@ -90,27 +90,30 @@ public:
 
   // Methods for registering and enumerating animation elements
   void RegisterAnimationElement(nsISMILAnimationElement* aAnimationElement);
   void UnregisterAnimationElement(nsISMILAnimationElement* aAnimationElement);
 
   // Methods for resampling all animations
   // (A resample performs the same operations as a sample but doesn't advance
   // the current time and doesn't check if the container is paused)
+  // This will flush pending style changes for the document.
   void Resample() { DoSample(false); }
 
   void SetResampleNeeded()
   {
     if (!mRunningSample) {
       if (!mResampleNeeded) {
         FlagDocumentNeedsFlush();
       }
       mResampleNeeded = true;
     }
   }
+
+  // This will flush pending style changes for the document.
   void FlushResampleRequests()
   {
     if (!mResampleNeeded)
       return;
 
     Resample();
   }
 
new file mode 100644
--- /dev/null
+++ b/layout/base/crashtests/735943.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<head>
+<script>
+
+var asvg = '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><script xlink:href="data:text/javascript," /><rect width="100" height="100" fill="green"><set attributeName="fill" attributeType="CSS" to="red" begin="0s" end="2s" dur="2s" fill="remove" /></rect></svg>';
+
+function boom()
+{
+  var f = document.createElementNS("http://www.w3.org/1999/xhtml", "iframe"); f.src = "data:text/html,1"; document.body.appendChild(f);
+  var w;
+
+  setTimeout(function() {
+    w = window.open("data:text/html,<body onload=window.close()>", "_blank", "width=200,height=200");
+    // Note that most of the code below will execute before the window appears, and in fact before "w" becomes non-null.
+  }, 0);
+
+  setTimeout(function() {
+    setTimeout(function() { }, 0);
+    f.contentWindow.location = "data:image/svg+xml," + encodeURIComponent(asvg);
+
+    setTimeout(function() {
+      setTimeout(function() {
+        setTimeout(function() {
+          document.body.style.MozColumnCount = "2";
+          document.documentElement.className = "";
+        }, 20);
+      }, 0);
+    }, 0);
+  }, 20);
+}
+
+    window.addEventListener("MozReftestInvalidate", boom, false);
+</script>
+</head>
+
+<body></body>
+</html>
--- a/layout/base/crashtests/crashtests.list
+++ b/layout/base/crashtests/crashtests.list
@@ -346,9 +346,10 @@ asserts(2) load 675246-1.xhtml # Bug 675
 load 691118-1.html
 load 695861.html
 load 698335.html
 needs-focus pref(accessibility.browsewithcaret,true) load 699353-1.html
 load 707098.html
 load 722137.html
 load 725535.html
 load 727601.html
-load 736389-1.xhtml
+asserts(0-2) pref(dom.disable_open_during_load,false) load 735943.html # the assertion is bug 735966
+asserts(0-2) load 736389-1.xhtml # sometimes the above assertions are delayed and is reported on this test instead
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -3948,19 +3948,22 @@ PresShell::FlushPendingNotifications(moz
       // reflow).
       mPresContext->FlushUserFontSet();
 
       // Flush any requested SMIL samples.
       if (mDocument->HasAnimationController()) {
         mDocument->GetAnimationController()->FlushResampleRequests();
       }
 
-      nsAutoScriptBlocker scriptBlocker;
-      mFrameConstructor->CreateNeededFrames();
-      mFrameConstructor->ProcessPendingRestyles();
+      // The FlushResampleRequests() above flushed style changes.
+      if (!mIsDestroying) {
+        nsAutoScriptBlocker scriptBlocker;
+        mFrameConstructor->CreateNeededFrames();
+        mFrameConstructor->ProcessPendingRestyles();
+      }
     }
 
     // Dispatch any 'animationstart' events those (or earlier) restyles
     // queued up.
     if (!mIsDestroying) {
       mPresContext->AnimationManager()->DispatchEvents();
     }