mirror of
https://github.com/servo/servo.git
synced 2025-06-27 02:23:41 +01:00
Update web-platform-tests to revision b'b728032f59a396243864b0f8584e7211e3632005'
This commit is contained in:
parent
ace9b32b1c
commit
df68c4e5d1
15632 changed files with 514865 additions and 155000 deletions
|
@ -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.
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
||||
|
|
@ -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>
|
|
@ -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>
|
|
@ -0,0 +1 @@
|
|||
logScript("Async1");
|
|
@ -0,0 +1 @@
|
|||
logScript("Defer1");
|
|
@ -0,0 +1 @@
|
|||
logScript("Defer2");
|
|
@ -0,0 +1,3 @@
|
|||
document.open();
|
||||
document.write(`<script src="sync-script-2.js"></script>`);
|
||||
document.close();
|
|
@ -0,0 +1,2 @@
|
|||
document.open();
|
||||
document.write(`<script src="sync-script-2.js"></script>`);
|
|
@ -0,0 +1,2 @@
|
|||
document.write(`<script src="sync-script-2.js"></script>`);
|
||||
document.close();
|
|
@ -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>
|
|
@ -0,0 +1 @@
|
|||
document.write(`<script src="sync-script-2.js"></script>`);
|
|
@ -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"); });
|
|
@ -0,0 +1 @@
|
|||
logScript("Sync1");
|
|
@ -0,0 +1 @@
|
|||
logScript("Sync2");
|
|
@ -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>
|
|
@ -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>
|
|
@ -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");
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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");
|
|
@ -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>
|
|
@ -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();
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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');
|
|
@ -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';
|
|
@ -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');
|
|
@ -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';
|
|
@ -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>
|
|
@ -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';
|
|
@ -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>
|
|
@ -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';
|
|
@ -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>
|
|
@ -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>
|
|
@ -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.
|
||||
]);
|
|
@ -0,0 +1,2 @@
|
|||
queueMicrotask(() => globalThis.log.push("microtask"));
|
||||
globalThis.log.push("body");
|
|
@ -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".
|
||||
]);
|
|
@ -0,0 +1,4 @@
|
|||
queueMicrotask(() => globalThis.log.push("microtask"));
|
||||
globalThis.log.push("body");
|
||||
|
||||
throw new Error("error");
|
|
@ -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".
|
||||
]);
|
|
@ -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();
|
||||
]);
|
|
@ -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();
|
||||
}
|
||||
};
|
|
@ -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>
|
|
@ -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");
|
||||
|
|
@ -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");
|
|
@ -0,0 +1,4 @@
|
|||
/*
|
||||
This file is empty, because all it matters is if the
|
||||
dynamic import that loads it fails or succedes.
|
||||
*/
|
|
@ -0,0 +1,4 @@
|
|||
/*
|
||||
This file is empty, because all it matters is if the
|
||||
dynamic import that loads it fails or succedes.
|
||||
*/
|
|
@ -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");
|
|
@ -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;
|
||||
};
|
||||
};
|
|
@ -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");
|
||||
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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";
|
|
@ -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>
|
|
@ -1,7 +0,0 @@
|
|||
globalThis.expectedLog = [
|
||||
"step-1-1", "step-1-2",
|
||||
"microtask",
|
||||
];
|
||||
|
||||
globalThis.test_load.step_timeout(() => globalThis.testDone(), 0);
|
||||
done();
|
|
@ -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>
|
|
@ -1,3 +0,0 @@
|
|||
globalThis.log.push("step-1-1");
|
||||
queueMicrotask(() => globalThis.log.push("microtask"));
|
||||
globalThis.log.push("step-1-2");
|
|
@ -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>
|
|
@ -1,6 +0,0 @@
|
|||
import "/resources/testharness.js";
|
||||
import "./evaluation-order-setup.mjs";
|
||||
|
||||
import "./evaluation-order-1-worker.mjs";
|
||||
|
||||
import "./evaluation-order-1.mjs";
|
|
@ -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>
|
|
@ -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();
|
|
@ -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>
|
|
@ -1,5 +0,0 @@
|
|||
globalThis.log.push("step-1-1");
|
||||
queueMicrotask(() => log.push("microtask"));
|
||||
globalThis.log.push("step-1-2");
|
||||
|
||||
throw new Error("error");
|
|
@ -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>
|
|
@ -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";
|
|
@ -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>
|
|
@ -1,7 +0,0 @@
|
|||
globalThis.expectedLog = [
|
||||
"step-2.2-1", "step-2.2-2",
|
||||
"microtask-2.2",
|
||||
"global-error", "error",
|
||||
];
|
||||
|
||||
done();
|
|
@ -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>
|
|
@ -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>
|
|
@ -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";
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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);
|
||||
});
|
|
@ -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");
|
|
@ -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>
|
|
@ -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>
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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 }
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
export default 1;
|
|
@ -0,0 +1 @@
|
|||
export default 2;
|
|
@ -0,0 +1,2 @@
|
|||
export const url = import.meta.url;
|
||||
export const resolve = import.meta.resolve;
|
|
@ -0,0 +1,5 @@
|
|||
<!DOCTYPE html>
|
||||
<script type="module">
|
||||
window.importMetaURL = import.meta.url;
|
||||
window.importMetaResolve = import.meta.resolve;
|
||||
</script>
|
|
@ -6,7 +6,7 @@ Use
|
|||
$ tools/generate.py
|
||||
```
|
||||
|
||||
to generate test HTML files.
|
||||
to generate test HTML files (except for tests in subdirectories).
|
||||
|
||||
Background:
|
||||
|
||||
|
|
|
@ -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).
|
|
@ -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>
|
|
@ -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>
|
|
@ -0,0 +1,5 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<body onload="parent.onloadIframe()">
|
||||
<script src="../../resources/throw.js?pipe=trickle(d2)"></script>
|
||||
</body>
|
|
@ -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
Loading…
Add table
Add a link
Reference in a new issue