author | Kris Maglione <maglione.k@gmail.com> |
Sun, 02 Apr 2017 15:05:51 -0700 | |
changeset 352883 | dd2c353c32bce83784c93f7511795290c621da75 |
parent 352882 | b59c6604cafa5ba52a6c741b2e8424cad9398c13 |
child 352884 | 31efcf6136159b6d670c37916f9bc6b447c8be7f |
push id | 40736 |
push user | maglione.k@gmail.com |
push date | Thu, 13 Apr 2017 20:23:04 +0000 |
treeherder | autoland@dd2c353c32bc [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | hsivonen |
bugs | 1352827 |
milestone | 55.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
dom/base/nsDocument.cpp | file | annotate | diff | comparison | revisions | |
dom/base/test/test_blockParsing.html | file | annotate | diff | comparison | revisions |
--- a/dom/base/nsDocument.cpp +++ b/dom/base/nsDocument.cpp @@ -10638,24 +10638,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> - -