Base: Add a test for the early return steps of "prepare a script"

This tests the early return steps of "prepare a script" that come
_before_ step 10 "Set the element's "already started" flag". The
relevant steps are steps 6, 7 and 8. If this algorithm returns on any
of these steps, the script can be reinserted matching the requirements
and will run.

https://html.spec.whatwg.org/multipage/scripting.html#prepare-a-script

I wrote this test page up while testing something else, but found a bug
in Firefox where it doesn't allow re-preparing the script if step 8
fails: https://bugzilla.mozilla.org/show_bug.cgi?id=1735590
This commit is contained in:
Luke Wilde 2021-10-13 18:32:15 +01:00 committed by Andreas Kling
parent ceb3328877
commit b7404015aa
2 changed files with 121 additions and 0 deletions

View file

@ -0,0 +1,120 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<p>
This tests the early return steps of <a href="https://html.spec.whatwg.org/multipage/scripting.html#prepare-a-script" target="_blank" rel="noopener noreferrer">"prepare a script"</a>
that come <u>before</u> step 10 "Set the element's "already started" flag". The relevant steps are steps 6, 7 and 8.
If this algorithm returns on any of these steps, the script can be reinserted matching the requirements and will run.
</p>
<p>Expected result:</p>
<ul>
<li>Step 6 test: I ran the second time around!</li>
<li>Step 7 test: I ran the second time around!</li>
<li>Step 8 test: I ran the second time around!</li>
</ul>
<br/>
<p>Actual result:</p>
<ul id="result-list">
</ul>
<!-- Setup code -->
<script>
// This returns a piece of code that will write a result to the actual result section.
function getTestScript(stepNumber, iteration) {
return `(() => {
const resultList = document.getElementById("result-list");
const resultEntry = document.createElement("li");
resultEntry.innerText = "Step ${stepNumber} test: I ran the ${iteration} time around!";
resultList.appendChild(resultEntry);
})();`;
}
</script>
<!-- Step 6 -->
<script>
const stepSixScript = document.createElement("script");
// 6. If the element has no src attribute, and source text is the empty string, then return. The script is not executed.
document.body.appendChild(stepSixScript);
document.body.removeChild(stepSixScript);
// Step 6 now passes.
// 10. Set the element's "already started" flag.
stepSixScript.innerText = getTestScript(6, "second");
document.body.appendChild(stepSixScript);
document.body.removeChild(stepSixScript);
// 1. If the script element is marked as having "already started", then return. The script is not executed.
stepSixScript.innerText = getTestScript(6, "third");
document.body.appendChild(stepSixScript);
</script>
<template id="step-seven-template">
<script>
// This is duplicated from getTestScript as this script will not run because it's not connected.
// See the NOTE in the script block below about why this is done here.
(() => {
const resultList = document.getElementById("result-list");
const resultEntry = document.createElement("li");
resultEntry.innerText = "Step 7 test: I ran the first time around!";
resultList.appendChild(resultEntry);
})();
</script>
</template>
<!-- Step 7 -->
<script>
const stepSevenTemplate = document.getElementById("step-seven-template");
const stepSevenScript = stepSevenTemplate.content.firstElementChild;
// 7. If the element is not connected, then return. The script is not executed.
// NOTE: This is done above because this can only be achieved via the parser, as the script element insertion steps do not prepare the script if the element is not connected.
// Step 7 now passes.
// 10. Set the element's "already started" flag.
stepSevenScript.remove();
stepSevenScript.innerText = getTestScript(7, "second");
document.body.appendChild(stepSevenScript);
document.body.removeChild(stepSevenScript);
// 1. If the script element is marked as having "already started", then return. The script is not executed.
stepSevenScript.innerText = getTestScript(7, "third");
document.body.appendChild(stepSevenScript);
</script>
<!-- Step 8 -->
<script>
const stepEightScript = document.createElement("script");
// 8. If either:
// ...snip...
// Otherwise, if the script element has a type attribute, let the script block's type string for this script element be the value of that attribute.
// Determine the script's type as follows:
// ...snip...
// - If neither of the above conditions are true, then return. No script is executed.
stepEightScript.innerText = getTestScript(8, "first");
stepEightScript.type = "unknown"; // Unknown type - the script won't run.
document.body.appendChild(stepEightScript);
document.body.removeChild(stepEightScript);
// Determine the script's type as follows:
// - If the script block's type string with leading and trailing ASCII whitespace stripped is a JavaScript MIME type essence match, the script's type is "classic".
// 10. Set the element's "already started" flag.
stepEightScript.innerText = getTestScript(8, "second");
stepEightScript.type = "text/javascript"; // Known type - the script should now run!
document.body.appendChild(stepEightScript);
document.body.removeChild(stepEightScript);
// 1. If the script element is marked as having "already started", then return. The script is not executed.
stepEightScript.innerText = getTestScript(8, "third");
document.body.appendChild(stepEightScript);
</script>
</body>
</html>

View file

@ -143,6 +143,7 @@
<li><a href="demo.html">fun demo</a></li>
<li><a href="set-interval.html">setInterval()</a></li>
<li><a href="location.html">window.location property</a></li>
<li><a href="script-preparation-test.html">Test for the early return steps 6-8 of the "prepare a script" algorithm</a></li>
<li><h3>Canvas</h3></li>
<li><a href="canvas.html">canvas 2D test</a></li>
<li><a href="canvas-rotate.html">canvas rotate()</a></li>