Bug 1352827: Handle potential null reference during cleanup by CC. r=hsivonen draft
authorKris Maglione <maglione.k@gmail.com>
Sun, 02 Apr 2017 15:05:51 -0700
changeset 559331 310c40d7105488fa3d04eaf222fc708b9721a74a
parent 554854 31dd0a3e931a22133fe3d4e21abfc1c2e1fb891f
child 623362 a50e547d37ea75df66f7ad4443fb614cdaec3196
push id53057
push usermaglione.k@gmail.com
push dateSun, 09 Apr 2017 21:27:54 +0000
reviewershsivonen
bugs1352827
milestone55.0a1
Bug 1352827: Handle potential null reference during cleanup by CC. r=hsivonen MozReview-Commit-ID: G7BM3nuEKY1
dom/base/nsDocument.cpp
dom/base/test/test_blockParsing.html
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -10572,24 +10572,28 @@ public:
     MaybeUnblockParser();
 
     mPromise->MaybeReject(aCx, aValue);
   }
 
 protected:
   virtual ~UnblockParsingPromiseHandler()
   {
-    MaybeUnblockParser();
+    // If we're being cleaned up by the cycle collector, our mDocument reference
+    // may have been unlinked while our mParser weak reference is still alive.
+    if (mDocument) {
+      MaybeUnblockParser();
+    }
   }
 
 private:
   void MaybeUnblockParser() {
     nsCOMPtr<nsIParser> parser = do_QueryReferent(mParser);
     if (parser) {
-      MOZ_ASSERT(mDocument);
+      MOZ_DIAGNOSTIC_ASSERT(mDocument);
       nsCOMPtr<nsIParser> docParser = mDocument->CreatorParserOrNull();
       if (parser == docParser) {
         parser->UnblockParser();
         parser->ContinueInterruptedParsingAsync();
       }
     }
     mParser = nullptr;
     mDocument = nullptr;
--- a/dom/base/test/test_blockParsing.html
+++ b/dom/base/test/test_blockParsing.html
@@ -76,13 +76,56 @@ add_task(function* () {
   yield runTest("http://mochi.test:8888/chrome/dom/base/test/file_external_script.html",
                 '<html lang="en"></html>',
                 '<html lang="en"><head>\n  <script src="file_script.js"><\/script>\n  <meta charset="utf-8">\n  <title></title>\n</head>\n<body>\n  <p>Hello Mochitest</p>\n\n\n</body></html>');
 
   yield runTest("http://mochi.test:8888/chrome/dom/base/test/file_external_script.xhtml",
                 '<html xml:lang="en" xmlns="http://www.w3.org/1999/xhtml"></html>',
                 '<html xml:lang="en" xmlns="http://www.w3.org/1999/xhtml">\n<head>\n  <script src="file_script.js"><\/script>\n  <title></title>\n</head>\n<body>\n  <p>Hello Mochitest</p>\n</body>\n</html>');
 });
+
+add_task(function* test_cleanup() {
+  const TOPIC = "blocking-promise-destroyed";
+
+  const finalizationWitness = Components.classes["@mozilla.org/toolkit/finalizationwitness;1"]
+      .getService(Components.interfaces.nsIFinalizationWitnessService);
+
+  for (let url of ["http://mochi.test:8888/chrome/dom/base/test/file_inline_script.html",
+                   "http://mochi.test:8888/chrome/dom/base/test/file_inline_script.xhtml"]) {
+    let iframe = document.createElement("iframe");
+    iframe.src = url;
+
+    // Create a promise that never resolves.
+    let blockerPromise = new Promise(() => {});
+
+    // Create a finalization witness so we can be sure that the promises
+    // have been collected before the end of the test.
+    let destroyedPromise = TestUtils.topicObserved(TOPIC);
+    let witness = finalizationWitness.make(TOPIC, url);
+    blockerPromise.witness = witness;
+
+    let insertedPromise = TestUtils.topicObserved("document-element-inserted", document => {
+      document.blockParsing(blockerPromise).witness = witness;
+
+      return true;
+    });
+
+    document.body.appendChild(iframe);
+    yield insertedPromise;
+
+    // Clear the promise reference, destroy the document, and force GC/CC. This should
+    // trigger any potential leaks or cleanup issues.
+    blockerPromise = null;
+    witness = null;
+    iframe.remove();
+
+    Components.utils.forceGC();
+    Components.utils.forceCC();
+    Components.utils.forceGC();
+
+    // Make sure the blocker promise has been collected.
+    let [, data] = yield destroyedPromise;
+    is(data, url, "Should have correct finalizer URL");
+  }
+});
 </script>
 </body>
 </html>
-
-