summaryrefslogtreecommitdiffstats
path: root/dom/base/test/test_blockParsing.html
diff options
context:
space:
mode:
Diffstat (limited to 'dom/base/test/test_blockParsing.html')
-rw-r--r--dom/base/test/test_blockParsing.html136
1 files changed, 136 insertions, 0 deletions
diff --git a/dom/base/test/test_blockParsing.html b/dom/base/test/test_blockParsing.html
new file mode 100644
index 0000000000..af4c8aaac5
--- /dev/null
+++ b/dom/base/test/test_blockParsing.html
@@ -0,0 +1,136 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test for document.blockParsing</title>
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" href="chrome://mochikit/content/tests/SimpleTest/test.css">
+</head>
+<body>
+<script>
+const {TestUtils} = ChromeUtils.importESModule(
+ "resource://testing-common/TestUtils.sys.mjs"
+);
+
+async function runTest(url, initialHTML, finalHTML) {
+ let iframe = document.createElement("iframe");
+ iframe.src = url;
+
+ let blockerPromise;
+ let promise = TestUtils.topicObserved("document-element-inserted", document => {
+ if (document !== iframe.contentDocument) {
+ return false;
+ }
+
+ blockerPromise = new Promise(resolve => {
+ setTimeout(resolve, 0);
+ }).then(() => {
+ return new Promise(resolve => setTimeout(resolve, 0));
+ }).then(() => {
+ return new Promise(resolve => setTimeout(resolve, 0));
+ });
+
+ is(document.documentElement.outerHTML, initialHTML,
+ "Should have initial HTML during document-element-inserted");
+ is(document.defaultView.wrappedJSObject.scriptRan, undefined,
+ "Script node should not have run");
+
+ document.blockParsing(blockerPromise);
+
+ return true;
+ }).then(([document]) => {
+ return document;
+ });
+
+ document.body.appendChild(iframe);
+
+ // Wait for document-element-inserted to fire.
+ let doc = await promise;
+ let win = doc.defaultView.wrappedJSObject;
+ let root = doc.documentElement;
+
+ // At this point, if the parser was successfully blocked, we should still
+ // have the initial skeleton HTML for the page.
+ is(root.outerHTML, initialHTML, "Should have initial HTML after document-element-inserted returns");
+ is(win.scriptRan, undefined, "Script node should still not have run");
+
+ await blockerPromise;
+
+ // Just after the promise that's blocking the parser fires, we shouldn't have
+ // returned to the main event loop, so we should still have the initial HTML.
+ is(root.outerHTML, initialHTML, "Should still have initial HTML");
+ is(win.scriptRan, undefined, "Script node should still not have run");
+
+ await new Promise(resolve => win.addEventListener("DOMContentLoaded", resolve, {once: true}));
+
+ // Parsing should have resumed, and we should have finished loading the document.
+ is(root.outerHTML, finalHTML, "Should have final HTML");
+ is(win.scriptRan, true, "Script node should have run");
+
+ iframe.remove();
+}
+
+add_task(async function() {
+ await runTest("http://mochi.test:8888/chrome/dom/base/test/file_inline_script.html",
+ '<html lang="en"></html>',
+ '<html lang="en"><head>\n <script>window.scriptRan = true;<\/script>\n <meta charset="utf-8">\n <title></title>\n</head>\n<body>\n <p>Hello Mochitest</p>\n\n\n</body></html>');
+
+ await runTest("http://mochi.test:8888/chrome/dom/base/test/file_inline_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>window.scriptRan = true;<\/script>\n <title></title>\n</head>\n<body>\n <p>Hello Mochitest</p>\n</body>\n</html>');
+
+ await 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>');
+
+ await 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(async function test_cleanup() {
+ const TOPIC = "blocking-promise-destroyed";
+
+ const finalizationWitness = Cc["@mozilla.org/toolkit/finalizationwitness;1"]
+ .getService(Ci.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);
+ await 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();
+
+ Cu.forceGC();
+ Cu.forceCC();
+ Cu.forceGC();
+
+ // Make sure the blocker promise has been collected.
+ let [, data] = await destroyedPromise;
+ is(data, url, "Should have correct finalizer URL");
+ }
+});
+</script>
+</body>
+</html>