Automatic update from web-platform-tests [CSS Modules] Adding WPT's for Import Map statefulness For CSS Modules (https://github.com/whatwg/html/issues/10673), Domenic suggested offline to follow the static behaviors of Import Maps. Specifically that they can't be modified into classic scripts once the Already Started flag is set, that they don't update the underlying import map when innerText changes, and that import map scripts can be created dynamically as long as the Already Started flag has not been set. There are no WPT's specifically testing these behaviors, so this CL adds them. Bug: 449621064 Change-Id: I84ad6a03f4b2f9c5fa80e9d642fb14d7f303d2b9 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7004710 Reviewed-by: Shunya Shishido <sisidovski@chromium.org> Commit-Queue: Kurt Catti-Schmidt <kschmi@microsoft.com> Cr-Commit-Position: refs/heads/main@{#1526624} -- wpt-commits: a5677a5cf5423c03a8126747688fe832e5356288 wpt-pr: 55291
159 lines
5.6 KiB
HTML
159 lines
5.6 KiB
HTML
<!DOCTYPE html>
|
|
<script src="/resources/testharness.js"></script>
|
|
<script src="/resources/testharnessreport.js"></script>
|
|
|
|
<script>
|
|
setup({allow_uncaught_exception : true});
|
|
|
|
const t_parse = async_test("Import maps shouldn't be parsed as scripts");
|
|
const t_already_started = async_test("The Already Started flag is passed through cloneNode");
|
|
const t_evaluate = async_test("Import maps shouldn't be executed as scripts");
|
|
const t_external = async_test(
|
|
"External import maps shouldn't be executed as scripts");
|
|
const t_change_type = async_test(
|
|
"Import maps shouldn't be executed as scripts after changing type");
|
|
|
|
const parseErrorHandler = event => {
|
|
event.preventDefault();
|
|
t_parse.unreached_func("An import map is parsed as a classic script")();
|
|
};
|
|
|
|
window.addEventListener("error", parseErrorHandler, {once: true});
|
|
</script>
|
|
|
|
<!-- This import map causes a parse error when parsed as a classic script. -->
|
|
<script type="importmap">
|
|
{
|
|
"imports": {
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<script>
|
|
window.removeEventListener("error", parseErrorHandler);
|
|
t_parse.done();
|
|
|
|
const alreadyStartedErrorHandler = event => {
|
|
event.preventDefault();
|
|
t_already_started.unreached_func("An import map is evaluated as a classic script")();
|
|
};
|
|
|
|
window.addEventListener("error", alreadyStartedErrorHandler, {once: true});
|
|
</script>
|
|
|
|
<script>
|
|
// Once Already Started is true on a classic script, it cannot be
|
|
// converted into an import map.
|
|
const dynamicScriptClassic = document.createElement("script");
|
|
dynamicScriptClassic.type = "text/javascript";
|
|
dynamicScriptClassic.innerText = "t_already_started.step(function() { assert_true(true, 'Classic script connected dynamically.');});";
|
|
|
|
// Inserting a <script> with contents sets Already Started to true.
|
|
document.head.appendChild(dynamicScriptClassic);
|
|
document.head.removeChild(dynamicScriptClassic);
|
|
|
|
// The existing innerText would be a parse error if parsed as an import
|
|
// map, but is valid as a classic script.
|
|
dynamicScriptClassic.type = "importmap";
|
|
document.head.appendChild(dynamicScriptClassic);
|
|
|
|
// The Already Started flag on a script is persisted upon cloning, so
|
|
// the clone won't be parsed as an import map even though its `type`
|
|
// was set to "importmap" when it was connected.
|
|
const clonedClassicScript = dynamicScriptClassic.cloneNode(/*deep=*/true);
|
|
t_already_started.step(function() {
|
|
assert_equals(clonedClassicScript.type, "importmap");
|
|
assert_equals(clonedClassicScript.innerText, dynamicScriptClassic.innerText);
|
|
});
|
|
document.head.appendChild(clonedClassicScript);
|
|
|
|
// Creating an empty <script> tag does not set Already Started to true,
|
|
// so the type can be changed later.
|
|
const dynamicScriptEmpty = document.createElement("script");
|
|
dynamicScriptEmpty.type = "text/javascript";
|
|
document.head.appendChild(dynamicScriptEmpty);
|
|
|
|
// The Already Started flag is copied onto clones, so the type can be
|
|
// changed later.
|
|
const clonedDynamicScriptEmpty = dynamicScriptEmpty.cloneNode(/*deep=*/true);
|
|
t_already_started.step(function() {
|
|
assert_equals(clonedDynamicScriptEmpty.type, "text/javascript");
|
|
});
|
|
clonedDynamicScriptEmpty.setAttribute("type", "importmap");
|
|
t_already_started.step(function() {
|
|
assert_equals(clonedDynamicScriptEmpty.type, "importmap");
|
|
});
|
|
|
|
// Since the contents are not empty, connecting the clone will set the
|
|
// Already Started flag to true and lock the type into an import map.
|
|
document.head.appendChild(clonedDynamicScriptEmpty);
|
|
document.head.removeChild(clonedDynamicScriptEmpty);
|
|
|
|
// This would cause a parse error when parsed as a classic script.
|
|
clonedDynamicScriptEmpty.innerText = "{ \"imports\": { } }";
|
|
document.head.appendChild(clonedDynamicScriptEmpty);
|
|
|
|
// The original element can have its contents set and will executed
|
|
// as a classic script. Ensure this is executed by completing the test.
|
|
dynamicScriptEmpty.innerText = "t_already_started.done();";
|
|
document.head.appendChild(dynamicScriptEmpty);
|
|
</script>
|
|
|
|
<script>
|
|
// Remove prior error handler, because the following import maps can
|
|
// causes parse errors.
|
|
window.removeEventListener("error", alreadyStartedErrorHandler);
|
|
</script>
|
|
|
|
<script>
|
|
// A dynamically created import map isn't parsed as a classic script.
|
|
const dynamicScript = document.createElement("script");
|
|
dynamicScript.type = "importmap";
|
|
t_evaluate.step(function() {
|
|
assert_equals(dynamicScript.type, "importmap");
|
|
});
|
|
dynamicScript.innerText = "t_evaluate.unreached_func('A dynamically-created import map is evaluated')();";
|
|
document.head.appendChild(dynamicScript);
|
|
|
|
// Changing the type shouldn't execute script.
|
|
dynamicScript.type = "text/javascript";
|
|
t_evaluate.step(function() {
|
|
assert_equals(dynamicScript.type, "text/javascript");
|
|
});
|
|
|
|
// Nor should removing it and re-inserting it.
|
|
document.head.removeChild(dynamicScript);
|
|
document.head.appendChild(dynamicScript);
|
|
</script>
|
|
|
|
<!-- Test the same with markup. -->
|
|
<script type="importmap">
|
|
t_evaluate.unreached_func("An import map is evaluated")();
|
|
</script>
|
|
|
|
<script>
|
|
t_evaluate.done();
|
|
</script>
|
|
|
|
<script type="importmap" id="changeType">
|
|
t_change_type.unreached_func("An import map is evaluated after changing type")();
|
|
</script>
|
|
|
|
<script>
|
|
// Change the type from "importmap" to other valid values and ensure
|
|
// script never executes.
|
|
let changeType = document.getElementById("changeType");
|
|
changeType.setAttribute("type", "text/javascript");
|
|
changeType.setAttribute("type", "module");
|
|
changeType.setAttribute("type", "");
|
|
changeType.removeAttribute("type");
|
|
t_change_type.done();
|
|
</script>
|
|
|
|
<!-- Import Maps do not execute external scripts. -->
|
|
<script type="importmap" src="data:text/javascript,t_external.unreached_func('An external import map is evaluated')();"></script>
|
|
|
|
<script>
|
|
t_external.done();
|
|
</script>
|