[DeferAllScript] Deactivate ScriptRunnerDelayer on parser detach
Previously, HTMLParserScriptRunner continued to delay
ScriptRunner after detached (e.g. on `document.write()`)
and thus caused DCHECK failures due to conflicts with
new HTMLParserScriptRunner.
This CL fix this by deactivating HTMLParserScriptRunner's
ScriptRunnerDelayer on parser detach.
This CL adds WPTs for `document.write()`-related cases
that would DCHECK-fail before this CL, and
refactors tests using `helper.js`.
Bug: 1340837
Change-Id: I168914447a876afe3fdfb257d6a089a7d11385b6
diff --git a/html/semantics/scripting-1/the-script-element/defer-script/async-script-2.html b/html/semantics/scripting-1/the-script-element/defer-script/async-script-2.html
index 077d4f6..f7377d8 100644
--- a/html/semantics/scripting-1/the-script-element/defer-script/async-script-2.html
+++ b/html/semantics/scripting-1/the-script-element/defer-script/async-script-2.html
@@ -5,25 +5,11 @@
<meta charset="utf-8">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
+ <script src="resources/helper.js"></script>
</head>
<body>
<script>
setup({single_test: true});
- window.result = [];
- function log(msg) {
- window.result.push(msg);
- }
- function checkIfReachedBodyEnd() {
- const endelement = document.getElementById("bodyend");
- if (endelement && endelement.textContent === "End") {
- log("EndOfBody");
- endelement.textContent = "Detected";
- }
- }
- function logScript(msg) {
- checkIfReachedBodyEnd();
- log(msg);
- }
function finish() {
assert_array_equals(
window.result,
@@ -42,7 +28,6 @@
}
logScript("Inline1");
window.addEventListener("load", finish);
- document.addEventListener("DOMContentLoaded", function() { logScript("DOMContentLoaded"); });
</script>
<script src="resources/sync-script-1.js"></script>
<!-- To test the async script loaded before force-deferred scripts
diff --git a/html/semantics/scripting-1/the-script-element/defer-script/async-script.html b/html/semantics/scripting-1/the-script-element/defer-script/async-script.html
index 0e84e2f..ea6c546 100644
--- a/html/semantics/scripting-1/the-script-element/defer-script/async-script.html
+++ b/html/semantics/scripting-1/the-script-element/defer-script/async-script.html
@@ -5,25 +5,11 @@
<meta charset="utf-8">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
+ <script src="resources/helper.js"></script>
</head>
<body>
<script>
setup({single_test: true});
- window.result = [];
- function log(msg) {
- window.result.push(msg);
- }
- function checkIfReachedBodyEnd() {
- const endelement = document.getElementById("bodyend");
- if (endelement && endelement.textContent === "End") {
- log("EndOfBody");
- endelement.textContent = "Detected";
- }
- }
- function logScript(msg) {
- checkIfReachedBodyEnd();
- log(msg);
- }
function finish() {
assert_array_equals(
window.result,
@@ -35,7 +21,6 @@
}
logScript("Inline1");
window.addEventListener("load", finish);
- document.addEventListener("DOMContentLoaded", function() { logScript("DOMContentLoaded"); });
</script>
<script src="resources/sync-script-1.js"></script>
<!-- Delays are added to make DOMContentLoaded be fired before
diff --git a/html/semantics/scripting-1/the-script-element/defer-script/defer-script-xml.xhtml b/html/semantics/scripting-1/the-script-element/defer-script/defer-script-xml.xhtml
index e64ff52..9d02ff3 100644
--- a/html/semantics/scripting-1/the-script-element/defer-script/defer-script-xml.xhtml
+++ b/html/semantics/scripting-1/the-script-element/defer-script/defer-script-xml.xhtml
@@ -5,29 +5,13 @@
<title>Defer Script Execution Order</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
+ <script src="resources/helper.js"></script>
</head>
<body>
<div id="scriptlog"/>
<input id="testElement"/>
<script>
setup({single_test: true});
- window.result = [];
- function log(msg) {
- window.result.push(msg);
- }
- function checkIfReachedBodyEnd() {
- const endelement = document.getElementById("bodyend");
- if (endelement != null) {
- if (endelement.textContent === "End") {
- log("EndOfBody");
- endelement.textContent = "Detected";
- }
- }
- }
- function logScript(msg) {
- checkIfReachedBodyEnd();
- log(msg);
- }
function finish() {
assert_array_equals(
window.result,
@@ -41,7 +25,6 @@
}
logScript("Inline1");
window.addEventListener("load", finish);
- document.addEventListener("DOMContentLoaded", function() { logScript("DOMContentLoaded"); });
</script>
<script src="resources/sync-script-1.js"></script>
diff --git a/html/semantics/scripting-1/the-script-element/defer-script/defer-script.html b/html/semantics/scripting-1/the-script-element/defer-script/defer-script.html
index c764aab..62c3a74 100644
--- a/html/semantics/scripting-1/the-script-element/defer-script/defer-script.html
+++ b/html/semantics/scripting-1/the-script-element/defer-script/defer-script.html
@@ -5,25 +5,11 @@
<meta charset="utf-8">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
+ <script src="resources/helper.js"></script>
</head>
<body>
<script>
setup({single_test: true});
- window.result = [];
- function log(msg) {
- window.result.push(msg);
- }
- function checkIfReachedBodyEnd() {
- const endelement = document.getElementById("bodyend");
- if (endelement && endelement.textContent === "End") {
- log("EndOfBody");
- endelement.textContent = "Detected";
- }
- }
- function logScript(msg) {
- checkIfReachedBodyEnd();
- log(msg);
- }
function finish() {
assert_array_equals(
window.result,
@@ -37,7 +23,6 @@
}
logScript("Inline1");
window.addEventListener("load", finish);
- document.addEventListener("DOMContentLoaded", function() { logScript("DOMContentLoaded"); });
</script>
<script src="resources/sync-script-1.js"></script>
diff --git a/html/semantics/scripting-1/the-script-element/defer-script/document-write.html b/html/semantics/scripting-1/the-script-element/defer-script/document-write.html
new file mode 100644
index 0000000..63e251b
--- /dev/null
+++ b/html/semantics/scripting-1/the-script-element/defer-script/document-write.html
@@ -0,0 +1,67 @@
+<!doctype html>
+<title>DeferAllScript: document.write()</title>
+<html>
+<head>
+ <meta charset="utf-8">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ const t1 = async_test("document.write()");
+ const t2 = async_test("document.write(),close()");
+ const t3 = async_test("document.open(),write()");
+ const t4 = async_test("document.open(),write(),close()");
+ function finish() {
+ const expected = ["Inline1", "Sync2", "Async1", "Sync1",
+ "EndOfBody", "DOMContentLoaded", "WindowLoad"];
+ t1.step_func_done(() => {
+ assert_array_equals(
+ document.getElementById("document-write").contentWindow.result,
+ expected,
+ "Execution order");
+ })();
+
+ t2.step_func_done(() => {
+ assert_array_equals(
+ document.getElementById("document-write-close").contentWindow.result,
+ expected,
+ "Execution order");
+ })();
+
+ t3.step_func_done(() => {
+ assert_array_equals(
+ document.getElementById("document-open-write").contentWindow.result,
+ expected,
+ "Execution order");
+ })();
+
+ t4.step_func_done(() => {
+ assert_array_equals(
+ document.getElementById(
+ "document-open-write-close").contentWindow.result,
+ expected,
+ "Execution order");
+ })();
+ // For cases where documents are kept open, call `document.close()` here
+ // to finish the test harness.
+ for (const iframe of document.querySelectorAll("iframe")) {
+ iframe.contentDocument.close();
+ }
+ }
+
+ // For cases where documents are kept open (that should never occur in
+ // non-intervention cases), schedule `finish()` because Window load events
+ // might be not fired.
+ setTimeout(finish, 5000);
+ </script>
+</head>
+<body onload="finish()">
+<iframe id="document-write"
+ src="resources/document-write-iframe.sub.html?script=document-write.js"></iframe>
+<iframe id="document-write-close"
+ src="resources/document-write-iframe.sub.html?script=document-write-close.js"></iframe>
+<iframe id="document-open-write"
+ src="resources/document-write-iframe.sub.html?script=document-open-write.js"></iframe>
+<iframe id="document-open-write-close"
+ src="resources/document-write-iframe.sub.html?script=document-open-write-close.js"></iframe>
+</body>
+</html>
diff --git a/html/semantics/scripting-1/the-script-element/defer-script/resources/document-open-write-close.js b/html/semantics/scripting-1/the-script-element/defer-script/resources/document-open-write-close.js
new file mode 100644
index 0000000..80703d5
--- /dev/null
+++ b/html/semantics/scripting-1/the-script-element/defer-script/resources/document-open-write-close.js
@@ -0,0 +1,3 @@
+document.open();
+document.write(`<script src="sync-script-2.js"></script>`);
+document.close();
diff --git a/html/semantics/scripting-1/the-script-element/defer-script/resources/document-open-write.js b/html/semantics/scripting-1/the-script-element/defer-script/resources/document-open-write.js
new file mode 100644
index 0000000..178c374
--- /dev/null
+++ b/html/semantics/scripting-1/the-script-element/defer-script/resources/document-open-write.js
@@ -0,0 +1,2 @@
+document.open();
+document.write(`<script src="sync-script-2.js"></script>`);
diff --git a/html/semantics/scripting-1/the-script-element/defer-script/resources/document-write-close.js b/html/semantics/scripting-1/the-script-element/defer-script/resources/document-write-close.js
new file mode 100644
index 0000000..7cdde0d
--- /dev/null
+++ b/html/semantics/scripting-1/the-script-element/defer-script/resources/document-write-close.js
@@ -0,0 +1,2 @@
+document.write(`<script src="sync-script-2.js"></script>`);
+document.close();
diff --git a/html/semantics/scripting-1/the-script-element/defer-script/resources/document-write-iframe.sub.html b/html/semantics/scripting-1/the-script-element/defer-script/resources/document-write-iframe.sub.html
new file mode 100644
index 0000000..e3022e3
--- /dev/null
+++ b/html/semantics/scripting-1/the-script-element/defer-script/resources/document-write-iframe.sub.html
@@ -0,0 +1,14 @@
+<!doctype html>
+<html>
+<body>
+<script src="helper.js"></script>
+<script>
+logScript("Inline1");
+window.addEventListener("load", () => logScript("WindowLoad"));
+</script>
+<script src="{{GET[script]}}?pipe=trickle(d1)"></script>
+<script src="async-script-1.js" async></script>
+<script src="sync-script-1.js?pipe=trickle(d2)"></script>
+<pre id="bodyend">End</pre>
+</body>
+</html>
diff --git a/html/semantics/scripting-1/the-script-element/defer-script/resources/document-write.js b/html/semantics/scripting-1/the-script-element/defer-script/resources/document-write.js
new file mode 100644
index 0000000..413a9bc
--- /dev/null
+++ b/html/semantics/scripting-1/the-script-element/defer-script/resources/document-write.js
@@ -0,0 +1 @@
+document.write(`<script src="sync-script-2.js"></script>`);
diff --git a/html/semantics/scripting-1/the-script-element/defer-script/resources/helper.js b/html/semantics/scripting-1/the-script-element/defer-script/resources/helper.js
new file mode 100644
index 0000000..89c6d1e
--- /dev/null
+++ b/html/semantics/scripting-1/the-script-element/defer-script/resources/helper.js
@@ -0,0 +1,17 @@
+window.result = [];
+function log(msg) {
+ window.result.push(msg);
+}
+function checkIfReachedBodyEnd() {
+ const endelement = document.getElementById("bodyend");
+ // `<pre id="bodyend">End</pre>` is needed at the end of HTML.
+ if (endelement && endelement.textContent === "End") {
+ log("EndOfBody");
+ endelement.textContent = "Detected";
+ }
+}
+function logScript(msg) {
+ checkIfReachedBodyEnd();
+ log(msg);
+}
+document.addEventListener("DOMContentLoaded", function() { logScript("DOMContentLoaded"); });