Update web-platform-tests to revision b'b728032f59a396243864b0f8584e7211e3632005'

This commit is contained in:
WPT Sync Bot 2022-11-10 01:22:36 +00:00
parent ace9b32b1c
commit df68c4e5d1
15632 changed files with 514865 additions and 155000 deletions

View file

@ -0,0 +1,7 @@
The tests in this directory is intended for Chromium's DeferAllScript
experiment https://crbug.com/1339112, containing scenarios that would be
affected by DeferAllScript, to monitor the behavior on Chromium and other
browsers.
The same set of expectations (when async/defer scripts are evaluated) should
already be covered somewhere in WPT.

View file

@ -0,0 +1,40 @@
<!doctype html>
<title>Async Script Execution Order</title>
<html>
<head>
<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});
function finish() {
assert_array_equals(
window.result,
["Inline1", "Sync1", "Async1", "Sync2", "EndOfBody",
"DOMContentLoaded"],
"Execution order");
// Chromium's force-defer order would be:
// ["EndOfBody", "Inline1", "Sync1", "Sync2",
// "DOMContentLoaded", "Async1"]
//
// If we delay async script e.g. after DOMContentLoaded,
// the order would be:
// ["Inline1", "Sync1", "Sync2", "EndOfBody",
// "DOMContentLoaded", "Async1"]
done();
}
logScript("Inline1");
window.addEventListener("load", finish);
</script>
<script src="resources/sync-script-1.js"></script>
<!-- To test the async script loaded before force-deferred scripts
should be evaluated after the force-deferred scripts
in Chromium's force-defer order. -->
<script src="resources/async-script-1.js?pipe=trickle(d1)" async></script>
<script src="resources/sync-script-2.js?pipe=trickle(d2)"></script>
<pre id="bodyend">End</pre>
</body>
</html>

View file

@ -0,0 +1,22 @@
<!doctype html>
<title>Async Script Execution Order</title>
<html>
<head>
<meta charset="utf-8">
<meta name=variant content="">
<meta name=variant content="?reload">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/helper.js"></script>
</head>
<body>
<script>
let child_path = 'support/async-script.html';
if (location.search == '?reload') {
child_path += '?reload';
}
const child_window = window.open(child_path);
fetch_tests_from_window(child_window);
</script>
</body>
</html>

View file

@ -0,0 +1,40 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<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});
function finish() {
assert_array_equals(
window.result,
["Inline1", "Sync1", "Inline2", "Sync2", "EndOfBody",
"Defer1", "Defer2", "DOMContentLoaded"],
"Execution order");
// Chromium order is (due to https://crbug.com/874749):
// ["Inline1", "Sync1", "Defer1", "Inline2", "Defer2", "Sync2",
// "EndOfBody", "DOMContentLoaded"]
done();
}
logScript("Inline1");
window.addEventListener("load", finish);
</script>
<script src="resources/sync-script-1.js"></script>
<script src="resources/defer-script-1.js" defer="defer"></script>
<script>
logScript("Inline2");
</script>
<script src="resources/defer-script-2.js" defer="defer"></script>
<script src="resources/sync-script-2.js"></script>
<pre id="bodyend">End</pre>
</body>
</html>

View file

@ -0,0 +1,37 @@
<!doctype html>
<title>Defer Script Execution Order</title>
<html>
<head>
<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});
function finish() {
assert_array_equals(
window.result,
["Inline1", "Sync1", "Inline2", "Sync2", "EndOfBody",
"Defer1", "Defer2", "DOMContentLoaded"],
"Execution order");
// Chromium's force defer order would be:
// ["EndOfBody", "Inline1", "Sync1", "Inline2", "Sync2",
// "Defer1", "Defer2", "DOMContentLoaded"]
done();
}
logScript("Inline1");
window.addEventListener("load", finish);
</script>
<script src="resources/sync-script-1.js"></script>
<script src="resources/defer-script-1.js" defer></script>
<script>
logScript("Inline2");
</script>
<script src="resources/defer-script-2.js" defer></script>
<script src="resources/sync-script-2.js"></script>
<pre id="bodyend">End</pre>
</body>
</html>

View file

@ -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>

View file

@ -0,0 +1,3 @@
document.open();
document.write(`<script src="sync-script-2.js"></script>`);
document.close();

View file

@ -0,0 +1,2 @@
document.open();
document.write(`<script src="sync-script-2.js"></script>`);

View file

@ -0,0 +1,2 @@
document.write(`<script src="sync-script-2.js"></script>`);
document.close();

View file

@ -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>

View file

@ -0,0 +1 @@
document.write(`<script src="sync-script-2.js"></script>`);

View file

@ -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"); });

View file

@ -0,0 +1,44 @@
<!doctype html>
<title>Child Async Script Execution Order</title>
<html>
<head>
<meta charset="utf-8">
<script src="/resources/testharness.js"></script>
<script src="../resources/helper.js"></script>
</head>
<body>
<script>
const reload_key = 'run-after-reload';
if (location.search == '?reload' && !window.localStorage.getItem(reload_key)) {
window.localStorage.setItem(reload_key, true);
location.reload();
} else {
window.localStorage.clear();
test();
}
function test() {
setup({ single_test: true });
function finish() {
assert_array_equals(
window.result,
["Inline1", "Sync1", "EndOfBody", "DOMContentLoaded", "Async1"],
"Execution order");
// Chromium's force-defer order would be:
// ["EndOfBody", "Inline1", "Sync1", "DOMContentLoaded", "Async1"]
done();
}
logScript("Inline1");
window.addEventListener("load", finish);
}
</script>
<script src="../resources/sync-script-1.js"></script>
<!-- Delays are added to make DOMContentLoaded be fired before
async script load completion -->
<script src="../resources/async-script-1.js?pipe=trickle(d1)" async></script>
<pre id="bodyend">End</pre>
</body>
</html>

View file

@ -1,10 +0,0 @@
<!DOCTYPE html>
<title>Testing evaluation order</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
const worker = new SharedWorker(
"evaluation-order-1-nothrow-worker-setup.js");
fetch_tests_from_worker(worker);
</script>

View file

@ -1,4 +0,0 @@
importScripts("/resources/testharness.js");
importScripts("module/evaluation-order-setup.mjs");
importScripts("module/evaluation-order-1-nothrow-worker.mjs");
importScripts("module/evaluation-order-1-nothrow.mjs");

View file

@ -1,10 +0,0 @@
<!DOCTYPE html>
<title>Testing evaluation order</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
const worker = new Worker(
"evaluation-order-1-nothrow-worker-setup.js");
fetch_tests_from_worker(worker);
</script>

View file

@ -1,19 +0,0 @@
<!DOCTYPE html>
<title>Testing evaluation order</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="module/evaluation-order-setup.mjs"></script>
<script>
window.addEventListener("load", ev => globalThis.testDone());
globalThis.expectedLog = [
"step-1-1", "step-1-2",
"microtask",
"script-load",
"global-load",
];
</script>
<script src="module/evaluation-order-1-nothrow.mjs"
onerror="globalThis.unreachable()"
onload="globalThis.log.push('script-load')"></script>

View file

@ -1,10 +0,0 @@
<!DOCTYPE html>
<title>Testing evaluation order</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
const worker = new SharedWorker(
"evaluation-order-1-worker-setup.js");
fetch_tests_from_worker(worker);
</script>

View file

@ -1,4 +0,0 @@
importScripts("/resources/testharness.js");
importScripts("module/evaluation-order-setup.mjs");
importScripts("evaluation-order-1-worker.js");
importScripts("module/evaluation-order-1.mjs");

View file

@ -1,10 +0,0 @@
<!DOCTYPE html>
<title>Testing evaluation order</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
const worker = new Worker(
"evaluation-order-1-worker-setup.js");
fetch_tests_from_worker(worker);
</script>

View file

@ -1,9 +0,0 @@
globalThis.expectedLog = [
"step-1-1", "step-1-2",
"global-error", "error",
"microtask",
];
globalThis.test_load.step_timeout(() => globalThis.testDone(), 0);
done();

View file

@ -1,19 +0,0 @@
<!DOCTYPE html>
<title>Testing evaluation order</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="module/evaluation-order-setup.mjs"></script>
<script>
window.addEventListener("load", event => globalThis.testDone());
globalThis.expectedLog = [
"step-1-1", "step-1-2",
"global-error", "error",
"microtask",
"script-load",
"global-load"
];
</script>
<script src="module/evaluation-order-1.mjs"
onerror="unreachable()" onload="log.push('script-load')"></script>

View file

@ -1,53 +0,0 @@
<!DOCTYPE html>
<html><head>
<title> scheduler: javascript: URL in HREF</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="testlib/testlib.js"></script>
</head>
<body>
<div id="log">FAILED (This TC requires JavaScript enabled)</div>
<p><a href="javascript:log('JS URL')"></a></p>
<script>log('inline script #1');
window.addEventListener("beforeunload", function( event ) {
log('beforeunload event');
});
if(document.links[0].click){
document.links[0].click();
}else{
var evt = document.createEvent("MouseEvents");
evt.initMouseEvent("click", true, true, window,
0, 0, 0, 0, 0, false, false, false, false, 0, null);
document.links[0].dispatchEvent(evt);
}
log('end script #1');
</script>
<script type="text/javascript">
log( 'inline script #2' );
var t = async_test()
function final_test() {
// The JS URL part is required to run in an additional task,
// altough that is not fully consistently implemented,
// see https://github.com/whatwg/html/issues/3730#issuecomment-492071447
assert_any(assert_array_equals, eventOrder, [
['inline script #1', 'end script #1', 'beforeunload event', 'inline script #2', 'JS URL'],
['inline script #1', 'end script #1', 'inline script #2', 'beforeunload event', 'JS URL']]);
t.done();
}
function test_on_load() {
// When the page loads, a task to run the navigate steps
// previously enqueued as part of following-hyperlinks,
// should have run, and have enqueued another task to execute the JS URL.
assert_any(assert_array_equals, eventOrder, [
['inline script #1', 'end script #1', 'beforeunload event', 'inline script #2'],
['inline script #1', 'end script #1', 'inline script #2', 'beforeunload event']]);
t.step_timeout(final_test, 1000)
}
onload = t.step_func(test_on_load);
</script>
</body></html>

View file

@ -1,30 +0,0 @@
<!DOCTYPE html>
<html><head>
<title>scheduler: IFRAMEs added with DOM (appendChild), javascript: URL</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="testlib/testlib.js"></script>
</head>
<body>
<div id="log">FAILED (This TC requires JavaScript enabled)</div>
<div></div>
<script>log('inline script #1');
var iframe=document.createElement('iframe');
iframe.src='javascript:parent.log(\'JS URL\');\'<html><script>parent.log(\\\'frame script\\\')<\/script></html>\'';
document.getElementsByTagName('div')[1].appendChild(iframe);
log('end script #1');
</script>
<script type="text/javascript">
log( 'inline script #2' );
var t = async_test()
function test() {
assert_array_equals(eventOrder, ['inline script #1', 'end script #1', 'inline script #2', 'JS URL', 'frame script']);
t.done();
}
onload = t.step_func(function(){setTimeout(t.step_func(test), 400);})
</script>
</body></html>

View file

@ -0,0 +1,11 @@
// META: global=dedicatedworker,sharedworker
// META: script=./resources/evaluation-order-setup.js
// Spec: https://html.spec.whatwg.org/C/#run-a-classic-script
// called from https://html.spec.whatwg.org/C/#import-scripts-into-worker-global-scope
setupTest("importScripts() queueing a microtask then throwing an exception", [
"body",
"microtask",
]);
importScripts('./resources/evaluation-order-1-nothrow.js');

View file

@ -0,0 +1,5 @@
// META: global=dedicatedworker-module,sharedworker-module
// META: script=./resources/evaluation-order-setup.js
import './resources/evaluation-order-1-nothrow-setup.js';
import './resources/evaluation-order-1-nothrow.js';

View file

@ -0,0 +1,22 @@
// META: global=dedicatedworker,sharedworker
// META: script=./resources/evaluation-order-setup.js
// Spec: https://html.spec.whatwg.org/C/#run-a-classic-script
// called from https://html.spec.whatwg.org/C/#import-scripts-into-worker-global-scope
setupTest("importScripts() queueing a microtask then throwing an exception", [
// Step 6 of #run-a-classic-script.
"body",
// Step 7.1.1 ("Clean up after running script") is no-op because JavaScript
// execution context stack is still non-empty immediately after
// importScripts() as the outer script is still executing.
// Step 7.1.2 (Rethrowing an exception) causes worker onerror.
"global-error",
// Microtask checkpoint is performed later, perhaps
// "Clean up after running script" after the outer script is finished.
"microtask",
]);
importScripts('./resources/evaluation-order-1-throw.js');

View file

@ -0,0 +1,5 @@
// META: global=dedicatedworker-module,sharedworker-module
// META: script=./resources/evaluation-order-setup.js
import './resources/evaluation-order-1-throw-setup.js';
import './resources/evaluation-order-1-throw.js';

View file

@ -0,0 +1,34 @@
<!DOCTYPE html>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/evaluation-order-setup.js"></script>
<script>
// Spec: https://html.spec.whatwg.org/C/#run-a-classic-script
setupTest("Classic script queueing a microtask then throwing an exception", [
"body", // Step 6.
"global-error", // "Report the exception" at Step 7.3.
"microtask", // "Clean up after running script" at Step 7.2.
]);
</script>
<script src="resources/evaluation-order-1-throw.js"
onerror="unreachable()" onload="testDone()"></script>
<script>
// Spec: https://html.spec.whatwg.org/C/#run-a-classic-script
setupTest("Classic script queueing a microtask", [
"body", // Step 6.
"microtask", // "Clean up after running script" at Step 7.2.
]);
</script>
<script src="resources/evaluation-order-1-nothrow.js"
onerror="unreachable()" onload="testDone()"></script>
<script type="module" src="resources/evaluation-order-1-throw-setup.js"></script>
<script type="module" src="resources/evaluation-order-1-throw.js"
onerror="unreachable()" onload="testDone()"></script>
<script type="module" src="resources/evaluation-order-1-nothrow-setup.js"></script>
<script type="module" src="resources/evaluation-order-1-nothrow.js"
onerror="unreachable()" onload="testDone()"></script>

View file

@ -0,0 +1,5 @@
// META: global=dedicatedworker-module,sharedworker-module
// META: script=./resources/evaluation-order-setup.js
import './resources/evaluation-order-2-setup.js';
import './resources/evaluation-order-2.1.mjs';

View file

@ -0,0 +1,8 @@
<!DOCTYPE html>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/evaluation-order-setup.js"></script>
<script type="module" src="resources/evaluation-order-2-setup.js"></script>
<script type="module" src="resources/evaluation-order-2.1.mjs"
onerror="unreachable()" onload="testDone()"></script>

View file

@ -0,0 +1,5 @@
// META: global=dedicatedworker-module,sharedworker-module
// META: script=./resources/evaluation-order-setup.js
import './resources/evaluation-order-3-setup.js';
import './resources/evaluation-order-3.1.mjs';

View file

@ -0,0 +1,8 @@
<!DOCTYPE html>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/evaluation-order-setup.js"></script>
<script type="module" src="resources/evaluation-order-3-setup.js"></script>
<script type="module" src="resources/evaluation-order-3.1.mjs"
onerror="unreachable()"></script>

View file

@ -0,0 +1,18 @@
<!DOCTYPE html>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/evaluation-order-setup.js"></script>
<script>
// Spec: https://html.spec.whatwg.org/C/#run-a-module-script
setupTest("Module script queueing a microtask then top-level await", [
"step-4.1-1", "step-4.1-2",
"microtask-4.1",
"script-load",
"step-4.2-1", "step-4.2-2",
"microtask-4.2",
]);
window.onerror = testDone;
</script>
<script type="module" src="resources/evaluation-order-4.1.mjs"
onerror="unreachable()" onload="log.push('script-load')"></script>

View file

@ -0,0 +1,5 @@
// Spec: https://html.spec.whatwg.org/C/#run-a-module-script
setupTest("Module script queueing a microtask", [
"body", // Step 6.
"microtask", // "Clean up after running script" at Step 8.
]);

View file

@ -0,0 +1,2 @@
queueMicrotask(() => globalThis.log.push("microtask"));
globalThis.log.push("body");

View file

@ -0,0 +1,10 @@
// Spec: https://html.spec.whatwg.org/C/#run-a-module-script
setupTest("Module script queueing a microtask then throwing an exception", [
"body", // Step 6.
"microtask", // "Clean up after running script" at Step 8.
"global-error", // "Clean up after running script" at Step 8, because
// `evaluationPromise` is synchronously rejected and the rejection is
// processed in the microtask checkpoint here (See also Step 7).
// As `evaluationPromise` is rejected after the microtask queued during
// evaluation, "global-error" occurs after "microtask".
]);

View file

@ -0,0 +1,4 @@
queueMicrotask(() => globalThis.log.push("microtask"));
globalThis.log.push("body");
throw new Error("error");

View file

@ -0,0 +1,10 @@
// Spec: https://html.spec.whatwg.org/C/#run-a-module-script
setupTest("Module script queueing a microtask then throwing an exception", [
"step-2.2-1", "step-2.2-2", // Step 6.
"microtask-2.2", // "Clean up after running script" at Step 8.
"global-error", // "Clean up after running script" at Step 8,
// because `evaluationPromise` is synchronously rejected and the rejection
// is processed in the microtask checkpoint here (See also Step 7).
// As `evaluationPromise` is rejected after the microtask queued during
// evaluation, "global-error" occurs after "microtask".
]);

View file

@ -1,8 +1,7 @@
globalThis.expectedLog = [
setupTest("Module script queueing a microtask then throwing an exception", [
"step-3.1-1", "step-3.1-2", "step-3.1-3",
"microtask-3.1",
"step-3.2-1", "step-3.2-2",
"microtask-3.2",
"import-catch", "error",
];
done();
]);

View file

@ -0,0 +1,30 @@
globalThis.setup({allow_uncaught_exception: true});
// Must be called after previous tests are completed.
globalThis.setupTest = (description, expectedLog) => {
globalThis.log = [];
globalThis.onerror = message => {
globalThis.log.push("global-error");
return true;
};
globalThis.onunhandledrejection =
() => globalThis.log.push('unhandled-promise-rejection');
globalThis.unreachable = () => globalThis.log.push("unreachable");
globalThis.test_load = async_test(description);
globalThis.testDone = globalThis.test_load.step_func_done(() => {
assert_array_equals(globalThis.log, expectedLog);
});
if (!('Window' in globalThis && globalThis instanceof Window)) {
// In workers, there are no <script> load event, so scheduling `testDone()`
// here, assuming the target script is loaded and evaluated soon.
globalThis.test_load.step_timeout(() => globalThis.testDone(), 1000);
// In workers, call `done()` here because the auto-generated `done()` calls
// by `any.js` etc. are at the end of main script and thus are not
// evaluated when the target script throws an exception.
done();
}
};

View file

@ -0,0 +1,25 @@
<!DOCTYPE html>
<title>Dynamic imports don't delay the load event</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
// Dynamic imports don't #delay-the-load-event.
// Therefore, Window load event would be fired
// just after the dynamic import() below starts.
window.loaded = [];
window.addEventListener('load', () => loaded.push('Window load event'));
promise_test(t => {
loaded.push('import start');
// This 'loading' log is added to detect the previous Chromium behavior
// where the Window load event is delayed until just before script
// element's load event.
t.step_timeout(() => loaded.push('loading'), 1000);
return import("../resources/slow-module.js?pipe=trickle(d2)")
.then(() => {
assert_array_equals(
loaded,
['import start', 'Window load event', 'loading', 'slow'],
"Window load event shouldn't be delayed by dynamic imports");
});
}, "Dynamic imports don't delay the load event.");
</script>

View file

@ -0,0 +1,32 @@
// META: global=window,dedicatedworker,sharedworker
// META: script=ticker.js
promise_test(async t => {
const getCount = ticker(1000);
const importP = import("<invalid>");
await promise_rejects_js(t, TypeError, importP, 'import() should reject');
assert_less_than(getCount(), 1000);
}, "import() should not drain the microtask queue if it fails during specifier resolution");
promise_test(async t => {
// Use Date.now() to ensure that the module is not in the module map
const specifier = "./empty-module.js?" + Date.now();
await import(specifier);
const getCount = ticker(1000);
await import(specifier);
assert_less_than(getCount(), 1000);
}, "import() should not drain the microtask queue when loading an already loaded module");
promise_test(async t => {
// Use Date.now() to ensure that the module is not in the module map
const specifier = "./empty-module.js?" + Date.now();
const getCount = ticker(1e7);
await import(specifier);
assert_equals(getCount(), 1e7);
}, "import() should drain the microtask queue when fetching a new module");

View file

@ -0,0 +1,14 @@
// META: global=dedicatedworker,sharedworker
// META: script=ticker.js
promise_test(async t => {
// Use Date.now() to ensure that the module is not in the module map
const specifier = "./empty-module.css?" + Date.now();
const getCount = ticker(1000);
const importP = import(specifier, { assert: { type: "css" } });
await promise_rejects_js(t, TypeError, importP, 'import() should reject');
assert_less_than(getCount(), 1000);
}, "import() should not drain the microtask queue if it fails because of the 'type: css' assertion in a worker");

View file

@ -0,0 +1,4 @@
/*
This file is empty, because all it matters is if the
dynamic import that loads it fails or succedes.
*/

View file

@ -0,0 +1,4 @@
/*
This file is empty, because all it matters is if the
dynamic import that loads it fails or succedes.
*/

View file

@ -0,0 +1,14 @@
// META: global=serviceworker
// META: script=ticker.js
promise_test(async t => {
// Use Date.now() to ensure that the module is not in the module map
const specifier = "./empty-module.js?" + Date.now();
const getCount = ticker(1000);
const importP = import(specifier);
await promise_rejects_js(t, TypeError, importP, 'import() should reject');
assert_less_than(getCount(), 1000);
}, "import() should not drain the microtask queue if it fails because it's used in a ServiceWorker");

View file

@ -0,0 +1,13 @@
globalThis.ticker = function ticker(max) {
let i = 0;
let stop = false;
Promise.resolve().then(function loop() {
if (stop || i >= max) return;
i++;
Promise.resolve().then(loop);
});
return () => {
stop = true;
return i;
};
};

View file

@ -0,0 +1,15 @@
// META: global=window,dedicatedworker,sharedworker
// META: script=ticker.js
promise_test(async t => {
// Use Date.now() to ensure that the module is not in the module map
const specifier = "./empty-module.js?" + Date.now();
const getCount = ticker(1000);
const importP = import(specifier, { assert: { type: "<invalid>" } });
await promise_rejects_js(t, TypeError, importP, 'import() should reject');
assert_less_than(getCount(), 1000);
}, "import() should not drain the microtask queue if it fails while validating the 'type' assertion");

View file

@ -0,0 +1,10 @@
<!DOCTYPE html>
<canvas id ="output" width="100" height="100" style="background: blue;"></canvas>
<script>
"use strict";
const canvas = document.getElementById('output');
const ctx = canvas.getContext('2d');
ctx.fillStyle = 'green';
ctx.fillRect(0, 0, 100, 100);
</script>

View file

@ -0,0 +1,43 @@
<!DOCTYPE html>
<html class="reftest-wait">
<link rel="help" href="https://html.spec.whatwg.org/#hostimportmoduledynamically(referencingscriptormodule,-specifier,-promisecapability)">
<link rel="match" href="worklet-ref.https.html">
<style>
#output {
width: 100px;
height: 100px;
background-image: paint(rects);
background-color: blue;
}
</style>
<script src="/common/reftest-wait.js"></script>
<script src="/common/worklet-reftest.js"></script>
<body>
<div id="output"></div>
<script id="code" type="text/worklet">
registerPaint('rects', class {
async paint(ctx, geom) {
ctx.fillStyle = 'red';
const getCount = ticker(1000);
try {
// Use Date.now() to ensure that the module is not in the module map
await import("./empty-module.js?" + Date.now());
} catch (e) {
if (getCount() < 1000) {
ctx.fillStyle = 'green';
}
}
ctx.fillRect(0, 0, geom.width, geom.height);
}
});
</script>
<script>
"use strict";
CSS.paintWorklet.addModule("./ticker.js").then(() =>
importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent)
);
</script>

View file

@ -1,10 +0,0 @@
<!DOCTYPE html>
<title>Testing evaluation order</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
const worker = new SharedWorker(
"evaluation-order-1-nothrow-worker-setup.mjs", {type:"module"});
fetch_tests_from_worker(worker);
</script>

View file

@ -1,6 +0,0 @@
import "/resources/testharness.js";
import "./evaluation-order-setup.mjs";
import "./evaluation-order-1-nothrow-worker.mjs";
import "./evaluation-order-1-nothrow.mjs";

View file

@ -1,10 +0,0 @@
<!DOCTYPE html>
<title>Testing evaluation order</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
const worker = new Worker(
"evaluation-order-1-nothrow-worker-setup.mjs", {type:"module"});
fetch_tests_from_worker(worker);
</script>

View file

@ -1,7 +0,0 @@
globalThis.expectedLog = [
"step-1-1", "step-1-2",
"microtask",
];
globalThis.test_load.step_timeout(() => globalThis.testDone(), 0);
done();

View file

@ -1,19 +0,0 @@
<!DOCTYPE html>
<title>Testing evaluation order</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script type="module">
import "./evaluation-order-setup.mjs";
window.addEventListener("load", ev => globalThis.testDone());
globalThis.expectedLog = [
"step-1-1", "step-1-2",
"microtask",
"script-load",
"global-load",
];
</script>
<script type="module" src="evaluation-order-1-nothrow.mjs"
onerror="globalThis.unreachable()"
onload="globalThis.log.push('script-load')"></script>

View file

@ -1,3 +0,0 @@
globalThis.log.push("step-1-1");
queueMicrotask(() => globalThis.log.push("microtask"));
globalThis.log.push("step-1-2");

View file

@ -1,10 +0,0 @@
<!DOCTYPE html>
<title>Testing evaluation order</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
const worker = new SharedWorker(
"evaluation-order-1-worker-setup.mjs", {type:"module"});
fetch_tests_from_worker(worker);
</script>

View file

@ -1,6 +0,0 @@
import "/resources/testharness.js";
import "./evaluation-order-setup.mjs";
import "./evaluation-order-1-worker.mjs";
import "./evaluation-order-1.mjs";

View file

@ -1,10 +0,0 @@
<!DOCTYPE html>
<title>Testing evaluation order</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
const worker = new Worker(
"evaluation-order-1-worker-setup.mjs", {type:"module"});
fetch_tests_from_worker(worker);
</script>

View file

@ -1,9 +0,0 @@
globalThis.expectedLog = [
"step-1-1", "step-1-2",
"microtask",
"global-error", "error",
];
globalThis.test_load.step_timeout(() => globalThis.testDone(), 0);
done();

View file

@ -1,20 +0,0 @@
<!DOCTYPE html>
<title>Testing evaluation order</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script type="module">
import "./evaluation-order-setup.mjs";
window.addEventListener("load", event => globalThis.testDone());
globalThis.expectedLog = [
"step-1-1", "step-1-2",
"microtask",
"global-error", "error",
"script-load",
"global-load"
];
</script>
<script type="module" src="evaluation-order-1.mjs"
onerror="unreachable()" onload="log.push('script-load')"></script>

View file

@ -1,5 +0,0 @@
globalThis.log.push("step-1-1");
queueMicrotask(() => log.push("microtask"));
globalThis.log.push("step-1-2");
throw new Error("error");

View file

@ -1,10 +0,0 @@
<!DOCTYPE html>
<title>Testing evaluation order</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
const worker = new SharedWorker(
"evaluation-order-2-import-worker-setup.mjs", {type:"module"});
fetch_tests_from_worker(worker);
</script>

View file

@ -1,6 +0,0 @@
import "/resources/testharness.js";
import "./evaluation-order-setup.mjs";
import "./evaluation-order-2-import-worker.mjs";
import "./evaluation-order-2.1.mjs";

View file

@ -1,10 +0,0 @@
<!DOCTYPE html>
<title>Testing evaluation order</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
const worker = new Worker(
"evaluation-order-2-import-worker-setup.mjs", {type:"module"});
fetch_tests_from_worker(worker);
</script>

View file

@ -1,7 +0,0 @@
globalThis.expectedLog = [
"step-2.2-1", "step-2.2-2",
"microtask-2.2",
"global-error", "error",
];
done();

View file

@ -1,20 +0,0 @@
<!DOCTYPE html>
<title>Testing evaluation order</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script type="module">
import "./evaluation-order-setup.mjs";
globalThis.expectedLog = [
"step-2.2-1", "step-2.2-2",
"microtask-2.2",
"global-error", "error",
"script-load",
"global-load",
];
</script>
<script type="module" src="evaluation-order-2.1.mjs"
onerror="globalThis.unreachable()"
onload="globalThis.log.push('script-load')">
</script>

View file

@ -1,11 +0,0 @@
<!DOCTYPE html>
<title>Testing evaluation order</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
const worker = new SharedWorker(
"evaluation-order-3-dynamic-worker-setup.mjs", {type:"module"});
fetch_tests_from_worker(worker);
</script>

View file

@ -1,6 +0,0 @@
import "/resources/testharness.js";
import "./evaluation-order-setup.mjs";
import "./evaluation-order-3-dynamic-worker.mjs";
import "./evaluation-order-3.1.mjs";

View file

@ -1,11 +0,0 @@
<!DOCTYPE html>
<title>Testing evaluation order</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
const worker = new Worker(
"evaluation-order-3-dynamic-worker-setup.mjs", {type:"module"});
fetch_tests_from_worker(worker);
</script>

View file

@ -1,19 +0,0 @@
<!DOCTYPE html>
<title>Testing evaluation order</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script type="module">
import "./evaluation-order-setup.mjs";
globalThis.expectedLog = [
"step-3.1-1", "step-3.1-2", "step-3.1-3", "microtask-3.1",
"script-load",
"step-3.2-1", "step-3.2-2", "microtask-3.2",
"import-catch", "error"
];
</script>
<script type="module" src="evaluation-order-3.1.mjs"
onerror="globalThis.unreachable()"
onload="globalThis.log.push('script-load')">
</script>

View file

@ -1,33 +0,0 @@
<!DOCTYPE html>
<title>Testing evaluation order</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
setup({allow_uncaught_exception: true});
window.log = [];
window.addEventListener("error", ev => testDone());
window.addEventListener("onunhandledrejection", unreachable);
const test_load = async_test("Test evaluation order of modules");
window.addEventListener("load", ev => log.push("window-load"));
function unreachable() { log.push("unexpected"); }
function testDone() {
test_load.step(() => {
assert_array_equals(log, [
"step-4.1-1", "step-4.1-2", "microtask-4.1",
"script-load", "window-load",
"step-4.2-1", "step-4.2-2", "microtask-4.2",
]);
});
test_load.done();
}
</script>
<script type="module" src="evaluation-order-4.1.mjs"
onerror="unreachable()" onload="log.push('script-load')">
</script>

View file

@ -1,19 +0,0 @@
globalThis.setup({allow_uncaught_exception: true});
globalThis.log = [];
globalThis.addEventListener("error",
event => globalThis.log.push("global-error", event.error.message));
globalThis.addEventListener("onunhandledrejection",
event => globalThis.log.push('unhandled-promise-rejection'));
globalThis.addEventListener("load",
event => globalThis.log.push("global-load"));
globalThis.unreachable = function() {
globalThis.log.push("unreachable");
}
globalThis.test_load = async_test("Test evaluation order of modules");
globalThis.testDone = globalThis.test_load.step_func_done(() => {
assert_array_equals(globalThis.log, globalThis.expectedLog);
});

View file

@ -0,0 +1,20 @@
// META: global=dedicatedworker-module,sharedworker-module,serviceworker-module
test(() => {
assert_equals(typeof import.meta, "object");
assert_not_equals(import.meta, null);
}, "import.meta is an object");
test(() => {
import.meta.newProperty = 1;
assert_true(Object.isExtensible(import.meta));
}, "import.meta is extensible");
test(() => {
for (const name of Reflect.ownKeys(import.meta)) {
const desc = Object.getOwnPropertyDescriptor(import.meta, name);
assert_equals(desc.writable, true);
assert_equals(desc.enumerable, true);
assert_equals(desc.configurable, true);
}
}, "import.meta's properties are writable, configurable, and enumerable");

View file

@ -0,0 +1,57 @@
<!DOCTYPE html>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<!--
More extensive tests of import maps and import.meta.resolve() will be
located in the import maps test suite. This contains some basic tests plus
tests some tricky parts of the import.meta.resolve() algorithm around string
conversion which are only testable with import maps.
-->
<script type="importmap">
{
"imports": {
"bare": "https://example.com/",
"https://example.com/rewrite": "https://example.com/rewritten",
"1": "https://example.com/PASS-1",
"null": "https://example.com/PASS-null",
"undefined": "https://example.com/PASS-undefined",
"[object Object]": "https://example.com/PASS-object",
"./start": "./resources/export-1.mjs",
"./resources/export-1.mjs": "./resources/export-2.mjs"
}
}
</script>
<script type="module">
test(() => {
assert_equals(import.meta.resolve("bare"), "https://example.com/");
}, "import.meta.resolve() given an import mapped bare specifier");
test(() => {
assert_equals(import.meta.resolve("https://example.com/rewrite"), "https://example.com/rewritten");
}, "import.meta.resolve() given an import mapped URL-like specifier");
test(() => {
assert_equals(import.meta.resolve(), "https://example.com/PASS-undefined", "no-arg case");
assert_equals(import.meta.resolve(1), "https://example.com/PASS-1");
assert_equals(import.meta.resolve(null), "https://example.com/PASS-null");
assert_equals(import.meta.resolve(undefined), "https://example.com/PASS-undefined");
// Only toString() methods are consulted by ToString, not valueOf() ones.
// So this becomes "[object Object]".
assert_equals(import.meta.resolve({ valueOf() { return "./x"; } }), "https://example.com/PASS-object");
}, "Testing the ToString() step of import.meta.resolve() via import maps");
promise_test(async () => {
const one = (await import("./start")).default;
assert_equals(one, 1);
const two = (await import(import.meta.resolve("./start"))).default;
assert_equals(two, 2);
}, "import(import.meta.resolve(x)) can be different from import(x)");
</script>

View file

@ -0,0 +1,39 @@
<!DOCTYPE html>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<iframe src="resources/store-import-meta.html"></iframe>
<script type="module">
import * as otherImportMeta from "./resources/export-import-meta.mjs";
setup({ explicit_done: true });
window.onload = () => {
test(() => {
assert_not_equals(frames[0].importMetaURL, import.meta.url,
"Precondition check: we've set things up so that the other script has a different import.meta.url");
const expected = (new URL("resources/x", location.href)).href;
assert_equals(frames[0].importMetaResolve("./x"), expected);
}, "import.meta.resolve resolves URLs relative to the import.meta.url, not relative to the active script when it is called: another global's inline script");
test(() => {
const otherFrameImportMetaResolve = frames[0].importMetaResolve;
document.querySelector("iframe").remove();
const expected = (new URL("resources/x", location.href)).href;
assert_equals(otherFrameImportMetaResolve("./x"), expected);
}, "import.meta.resolve still works if its global has been destroyed (by detaching the iframe)");
test(() => {
assert_not_equals(otherImportMeta.url, import.meta.url,
"Precondition check: we've set things up so that the other script has a different import.meta.url");
const expected = (new URL("resources/x", location.href)).href;
assert_equals(otherImportMeta.resolve("./x"), expected);
}, "import.meta.resolve resolves URLs relative to the import.meta.url, not relative to the active script when it is called: another module script");
done();
};
</script>

View file

@ -0,0 +1,77 @@
// META: global=dedicatedworker-module,sharedworker-module,serviceworker-module
import { importMetaOnRootModule, importMetaOnDependentModule }
from "./import-meta-root.js";
test(() => {
assert_equals(typeof import.meta.resolve, "function");
assert_equals(import.meta.resolve.name, "resolve");
assert_equals(import.meta.resolve.length, 1);
assert_equals(Object.getPrototypeOf(import.meta.resolve), Function.prototype);
}, "import.meta.resolve is a function with the right properties");
test(() => {
assert_false(isConstructor(import.meta.resolve));
assert_throws_js(TypeError, () => new import.meta.resolve("./x"));
}, "import.meta.resolve is not a constructor");
test(() => {
// See also tests in ./import-meta-resolve-importmap.html.
assert_equals(import.meta.resolve({ toString() { return "./x"; } }), resolveURL("x"));
assert_throws_js(TypeError, () => import.meta.resolve(Symbol("./x")),
"symbol");
assert_throws_js(TypeError, () => import.meta.resolve(),
"no argument (which is treated like \"undefined\")");
}, "import.meta.resolve ToString()s its argument");
test(() => {
assert_equals(import.meta.resolve("./x"), resolveURL("x"),
"current module import.meta");
assert_equals(importMetaOnRootModule.resolve("./x"), resolveURL("x"),
"sibling module import.meta");
assert_equals(importMetaOnDependentModule.resolve("./x"), resolveURL("x"),
"dependency module import.meta");
}, "Relative URL-like specifier resolution");
test(() => {
assert_equals(import.meta.resolve("https://example.com/"), "https://example.com/",
"current module import.meta");
assert_equals(importMetaOnRootModule.resolve("https://example.com/"), "https://example.com/",
"sibling module import.meta");
assert_equals(importMetaOnDependentModule.resolve("https://example.com/"), "https://example.com/",
"dependency module import.meta");
}, "Absolute URL-like specifier resolution");
test(() => {
const invalidSpecifiers = [
"https://eggplant:b/c",
"pumpkins.js",
".tomato",
"..zuccini.mjs",
".\\yam.es"
];
for (const specifier of invalidSpecifiers) {
assert_throws_js(TypeError, () => import.meta.resolve(specifier), specifier);
}
}, "Invalid module specifiers");
test(() => {
const { resolve } = import.meta;
assert_equals(resolve("https://example.com/"), "https://example.com/", "current module import.meta");
}, "Works fine with no this value");
function resolveURL(urlRelativeToThisTest) {
return (new URL(urlRelativeToThisTest, location.href)).href;
}
function isConstructor(o) {
try {
new (new Proxy(o, { construct: () => ({}) }));
return true;
} catch {
return false;
}
}

View file

@ -15,26 +15,6 @@ test(() => {
base + "/import-meta-dependent.js");
}, "import.meta.url in a dependent external script");
test(() => {
assert_equals(typeof importMetaOnRootModule, "object");
assert_not_equals(importMetaOnRootModule, null);
}, "import.meta is an object");
test(() => {
importMetaOnRootModule.newProperty = 1;
assert_true(Object.isExtensible(importMetaOnRootModule));
}, "import.meta is extensible");
test(() => {
const names = new Set(Reflect.ownKeys(importMetaOnRootModule));
for (const name of names) {
var desc = Object.getOwnPropertyDescriptor(importMetaOnRootModule, name);
assert_equals(desc.writable, true);
assert_equals(desc.enumerable, true);
assert_equals(desc.configurable, true);
}
}, "import.meta's properties are writable, configurable, and enumerable");
import { importMetaOnRootModule as hashedImportMetaOnRootModule1,
importMetaOnDependentModule as hashedImportMetaOnDependentModule1 }

View file

@ -0,0 +1,2 @@
export const url = import.meta.url;
export const resolve = import.meta.resolve;

View file

@ -0,0 +1,5 @@
<!DOCTYPE html>
<script type="module">
window.importMetaURL = import.meta.url;
window.importMetaResolve = import.meta.resolve;
</script>

View file

@ -6,7 +6,7 @@ Use
$ tools/generate.py
```
to generate test HTML files.
to generate test HTML files (except for tests in subdirectories).
Background:

View file

@ -0,0 +1,6 @@
The tests in this directory checks side effects (other than script
evaluation/event firing, which is covered by the tests in the parent directory)
caused by scripts moved between Documents.
The tests assume that script loading is not canceled when moved between
documents (which is not explicitly specified as of Jan 2022).

View file

@ -0,0 +1,10 @@
<!DOCTYPE html>
<meta charset="utf-8">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="helper.js"></script>
<body>
<script>
runDelayEventTest('Script elements (parser-blocking)');
</script>
<script id="to-be-moved" src="../../resources/throw.js?pipe=trickle(d3)"></script>

View file

@ -0,0 +1,14 @@
<!DOCTYPE html>
<meta charset="utf-8">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="helper.js"></script>
<body>
<script>
runDelayEventTest('Script elements (async)');
const script = document.createElement('script');
script.setAttribute('id', 'to-be-moved');
script.setAttribute('src', '../../resources/throw.js?pipe=trickle(d3)');
document.body.appendChild(script);
</script>

View file

@ -0,0 +1,5 @@
<!DOCTYPE html>
<meta charset="utf-8">
<body onload="parent.onloadIframe()">
<script src="../../resources/throw.js?pipe=trickle(d2)"></script>
</body>

View file

@ -0,0 +1,31 @@
function runDelayEventTest(description) {
const t = async_test(description +
' still delay the load event in the original Document after move');
const t_new = async_test(description +
' does not delay the load event in the new Document after move');
const start_time = performance.now();
const iframe = document.createElement('iframe');
iframe.setAttribute('src', 'delay-load-event-iframe.html');
document.body.appendChild(iframe);
window.onload = t.step_func_done(() => {
// The `#to-be-moved` script should delay the load event until it is loaded
// (i.e. 3 seconds), not just until it is moved out to another Document
// (i.e. 1 second). Here we expect the delay should be at least 2 seconds,
// as the latency can be slightly less than 3 seconds due to preloading.
assert_greater_than(performance.now() - start_time, 2000,
'Load event should be delayed until script is loaded');
});
window.onloadIframe = t_new.step_func_done(() => {
// The iframe's load event is fired after 2 seconds of its subresource
// loading, and shouldn't wait for the `#to-be-moved` script.
assert_less_than(performance.now() - start_time, 2500,
'Load event should not be delayed until moved script is loaded');
});
t.step_timeout(() => {
const script = document.querySelector('#to-be-moved');
iframe.contentDocument.body.appendChild(script);
}, 1000);
}

Some files were not shown because too many files have changed in this diff Show more