Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Warnings

<!DOCTYPE html>
<html>
<!-- The JS bytecode cache is not supposed to be observable. To make it
observable, the ScriptLoader is instrumented to trigger events on the
script tag.
-->
<head>
<meta charset="utf-8">
<title>Test for saving and loading module bytecode in/from the necko cache</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
</head>
<body>
<script type="application/javascript">
// List of testcases
//
// src
// HTML file loaded twice in an iframe
// encodeEvents
// Non-ordered multi-set of expected events dispatched during loading the
// HTML file at the first time
// decodeEvents
// Non-ordered multi-set of expected events dispatched during loading the
// HTML file at the second time
const tests = [
// Module without import.
{
src: "file_script_module_single.html",
encodeEvents: [
// file_script_module_single.mjs
"scriptloader_load_source",
"scriptloader_evaluate_module",
"scriptloader_encode",
"scriptloader_bytecode_saved",
"test_evaluated",
],
decodeEvents: [
// file_script_module_single.mjs
"scriptloader_load_bytecode",
"scriptloader_evaluate_module",
"test_evaluated",
],
},
// Module with import.
{
src: "file_script_module_import.html",
encodeEvents: [
// file_script_module_import.mjs
"scriptloader_load_source",
"scriptloader_evaluate_module", // dispatched only for top-level
"scriptloader_encode",
"scriptloader_bytecode_saved",
"test_evaluated",
// file_script_module_import_imported.mjs
"scriptloader_load_source",
"scriptloader_encode",
],
decodeEvents: [
// file_script_module_import.mjs
"scriptloader_load_bytecode",
"scriptloader_evaluate_module", // dispatched only for top-level
"test_evaluated",
// file_script_module_import_imported.mjs
"scriptloader_load_bytecode",
],
},
// Single module is imported twice.
{
src: "file_script_module_import_multi.html",
encodeEvents: [
// file_script_module_import_multi.mjs
"scriptloader_load_source",
"scriptloader_evaluate_module", // dispatched only for top-level
"scriptloader_encode",
"scriptloader_bytecode_saved",
"test_evaluated",
// file_script_module_import_multi_imported_once.mjs
"scriptloader_load_source",
"scriptloader_encode",
"scriptloader_bytecode_saved",
// file_script_module_import_multi_imported_twice.mjs
"scriptloader_load_source",
"scriptloader_encode",
"scriptloader_bytecode_saved",
],
decodeEvents: [
// file_script_module_import_multi.mjs
"scriptloader_load_bytecode",
"scriptloader_evaluate_module", // dispatched only for top-level
"test_evaluated",
// file_script_module_import_multi_imported_once.mjs
"scriptloader_load_bytecode",
// file_script_module_import_multi_imported_twice.mjs
"scriptloader_load_bytecode",
],
},
// Single module is imported twice from different elements.
{
src: "file_script_module_import_multi_elems.html",
encodeEvents: [
// file_script_module_import_multi_elems_1.mjs
"scriptloader_load_source",
"scriptloader_evaluate_module", // dispatched only for top-level
"scriptloader_encode",
"scriptloader_bytecode_saved",
"test_evaluated",
// file_script_module_import_multi_elems_2.mjs
"scriptloader_load_source",
"scriptloader_evaluate_module", // dispatched only for top-level
"scriptloader_encode",
"scriptloader_bytecode_saved",
"test_evaluated",
// file_script_module_import_multi_elems_imported_once_1.mjs
"scriptloader_load_source",
"scriptloader_encode",
"scriptloader_bytecode_saved",
// file_script_module_import_multi_elems_imported_once_2.mjs
"scriptloader_load_source",
"scriptloader_encode",
"scriptloader_bytecode_saved",
// file_script_module_import_multi_elems_imported_once_3.mjs
"scriptloader_load_source",
"scriptloader_encode",
"scriptloader_bytecode_saved",
// file_script_module_import_multi_elems_imported_twice.mjs
"scriptloader_load_source",
"scriptloader_encode",
"scriptloader_bytecode_saved",
],
decodeEvents: [
// file_script_module_import_multi_elems_1.mjs
"scriptloader_load_bytecode",
"scriptloader_evaluate_module", // dispatched only for top-level
"test_evaluated",
// file_script_module_import_multi_elems_2.mjs
"scriptloader_load_bytecode",
"scriptloader_evaluate_module", // dispatched only for top-level
"test_evaluated",
// file_script_module_import_multi_elems_imported_once_1.mjs
"scriptloader_load_bytecode",
// file_script_module_import_multi_elems_imported_once_2.mjs
"scriptloader_load_bytecode",
// file_script_module_import_multi_elems_imported_once_3.mjs
"scriptloader_load_bytecode",
// file_script_module_import_multi_elems_imported_twice.mjs
"scriptloader_load_bytecode",
],
},
// Single module is imported, and then loaded by element.
{
src: "file_script_module_import_and_element.html",
encodeEvents: [
// file_script_module_import_and_element.mjs
"scriptloader_load_source",
"scriptloader_evaluate_module", // dispatched only for top-level
"scriptloader_encode",
"scriptloader_bytecode_saved",
"test_evaluated",
// file_script_module_import_and_element_imported_1.mjs
"scriptloader_load_source",
"scriptloader_evaluate_module", // dispatched only for top-level
"scriptloader_encode",
"scriptloader_bytecode_saved",
// file_script_module_import_and_element_imported_2.mjs
"scriptloader_load_source",
"scriptloader_encode",
"scriptloader_bytecode_saved",
// file_script_module_import_and_element_imported_3.mjs
"scriptloader_load_source",
"scriptloader_encode",
"scriptloader_bytecode_saved",
],
decodeEvents: [
// file_script_module_import_and_element.mjs
"scriptloader_load_bytecode",
"scriptloader_evaluate_module", // dispatched only for top-level
"test_evaluated",
// file_script_module_import_and_element_imported_1.mjs
"scriptloader_load_bytecode",
"scriptloader_evaluate_module", // dispatched only for top-level
// file_script_module_import_and_element_imported_2.mjs
"scriptloader_load_bytecode",
// file_script_module_import_and_element_imported_3.mjs
"scriptloader_load_bytecode",
],
},
// Single module is loaded by element, and then imported.
{
src: "file_script_module_element_and_import.html",
encodeEvents: [
// file_script_module_element_and_import.mjs
"scriptloader_load_source",
"scriptloader_evaluate_module", // dispatched only for top-level
"scriptloader_encode",
"scriptloader_bytecode_saved",
"test_evaluated",
// file_script_module_element_and_import_imported_1.mjs
"scriptloader_load_source",
"scriptloader_evaluate_module", // dispatched only for top-level
"scriptloader_encode",
"scriptloader_bytecode_saved",
// file_script_module_element_and_import_imported_2.mjs
"scriptloader_load_source",
"scriptloader_encode",
"scriptloader_bytecode_saved",
// file_script_module_element_and_import_imported_3.mjs
"scriptloader_load_source",
"scriptloader_encode",
"scriptloader_bytecode_saved",
],
decodeEvents: [
// file_script_module_element_and_import.mjs
"scriptloader_load_bytecode",
"scriptloader_evaluate_module", // dispatched only for top-level
"test_evaluated",
// file_script_module_element_and_import_imported_1.mjs
"scriptloader_load_bytecode",
"scriptloader_evaluate_module", // dispatched only for top-level
// file_script_module_element_and_import_imported_2.mjs
"scriptloader_load_bytecode",
// file_script_module_element_and_import_imported_3.mjs
"scriptloader_load_bytecode",
],
},
// Module with dynamic import.
{
src: "file_script_module_dynamic_import.html",
encodeEvents: [
// file_script_module_dynamic_import.mjs
"scriptloader_load_source",
"scriptloader_evaluate_module", // dispatched only for top-level (element)
"scriptloader_encode",
"scriptloader_bytecode_saved",
"test_evaluated",
// file_script_module_dynamic_import_imported.mjs
"scriptloader_load_source",
"scriptloader_evaluate_module", // dispatched only for top-level (dynamic)
"scriptloader_encode",
"scriptloader_bytecode_saved",
],
decodeEvents: [
// file_script_module_dynamic_import.mjs
"scriptloader_load_bytecode",
"scriptloader_evaluate_module", // dispatched only for top-level (element)
"test_evaluated",
// file_script_module_dynamic_import_imported.mjs
"scriptloader_load_bytecode",
"scriptloader_evaluate_module", // dispatched only for top-level (dynamic)
],
},
// Single module is imported dynamically, and then loaded by element.
{
src: "file_script_module_dynamic_and_element.html",
encodeEvents: [
// file_script_module_dynamic_and_element.mjs
"scriptloader_load_source",
"scriptloader_evaluate_module", // dispatched only for top-level (element)
"scriptloader_encode",
"scriptloader_bytecode_saved",
"test_evaluated",
// file_script_module_dynamic_and_element_imported_1.mjs
"scriptloader_load_source",
"scriptloader_evaluate_module", // dispatched only for top-level (element)
"scriptloader_evaluate_module", // dispatched only for top-level (dynamic)
"scriptloader_encode",
"scriptloader_bytecode_saved",
// file_script_module_dynamic_and_element_imported_2.mjs
"scriptloader_load_source",
"scriptloader_encode",
"scriptloader_bytecode_saved",
// file_script_module_dynamic_and_element_imported_3.mjs
"scriptloader_load_source",
"scriptloader_encode",
"scriptloader_bytecode_saved",
],
decodeEvents: [
// file_script_module_dynamic_and_element.mjs
"scriptloader_load_bytecode",
"scriptloader_evaluate_module", // dispatched only for top-level (element)
"test_evaluated",
// file_script_module_dynamic_and_element_imported_1.mjs
"scriptloader_load_bytecode",
"scriptloader_evaluate_module", // dispatched only for top-level (element)
"scriptloader_evaluate_module", // dispatched only for top-level (dynamic)
// file_script_module_dynamic_and_element_imported_2.mjs
"scriptloader_load_bytecode",
// file_script_module_dynamic_and_element_imported_3.js
"scriptloader_load_bytecode",
],
},
// Single module is loaded by element, and then imported dynamically.
{
src: "file_script_module_element_and_dynamic.html",
encodeEvents: [
// file_script_module_element_and_dynamic.mjs
"scriptloader_load_source",
"scriptloader_evaluate_module", // dispatched only for top-level (element)
"scriptloader_encode",
"scriptloader_bytecode_saved",
"test_evaluated",
// file_script_module_element_and_dynamic_imported_1.mjs
"scriptloader_load_source",
"scriptloader_evaluate_module", // dispatched only for top-level (element)
"scriptloader_evaluate_module", // dispatched only for top-level (dynamic)
"scriptloader_encode",
"scriptloader_bytecode_saved",
// file_script_module_element_and_dynamic_imported_2.mjs
"scriptloader_load_source",
"scriptloader_encode",
"scriptloader_bytecode_saved",
// file_script_module_element_and_dynamic_imported_3.mjs
"scriptloader_load_source",
"scriptloader_encode",
"scriptloader_bytecode_saved",
],
decodeEvents: [
// file_script_module_element_and_dynamic.mjs
"scriptloader_load_bytecode",
"scriptloader_evaluate_module", // dispatched only for top-level (element)
"test_evaluated",
// file_script_module_element_and_dynamic_imported_1.mjs
"scriptloader_load_bytecode",
"scriptloader_evaluate_module", // dispatched only for top-level (element)
"scriptloader_evaluate_module", // dispatched only for top-level (dynamic)
// file_script_module_element_and_dynamic_imported_2.mjs
"scriptloader_load_bytecode",
// file_script_module_element_and_dynamic_imported_3.mjs
"scriptloader_load_bytecode",
],
},
// Single module is imported dynamically, and then statically.
{
src: "file_script_module_dynamic_and_static.html",
encodeEvents: [
// file_script_module_dynamic_and_static.mjs
"scriptloader_load_source",
"scriptloader_evaluate_module", // dispatched only for top-level (element)
"scriptloader_encode",
"scriptloader_bytecode_saved",
"test_evaluated",
// file_script_module_dynamic_and_static_imported_1.mjs
"scriptloader_load_source",
"scriptloader_evaluate_module", // dispatched only for top-level (dynamic)
"scriptloader_encode",
"scriptloader_bytecode_saved",
// file_script_module_dynamic_and_static_imported_2.mjs
"scriptloader_load_source",
"scriptloader_encode",
"scriptloader_bytecode_saved",
// file_script_module_dynamic_and_static_imported_3.mjs
"scriptloader_load_source",
"scriptloader_encode",
"scriptloader_bytecode_saved",
],
decodeEvents: [
// file_script_module_dynamic_and_static.mjs
"scriptloader_load_bytecode",
"scriptloader_evaluate_module", // dispatched only for top-level (element)
"test_evaluated",
// file_script_module_dynamic_and_static_imported_1.mjs
"scriptloader_load_bytecode",
"scriptloader_evaluate_module", // dispatched only for top-level (dynamic)
// file_script_module_dynamic_and_static_imported_2.mjs
"scriptloader_load_bytecode",
// file_script_module_dynamic_and_static_imported_3.mjs
"scriptloader_load_bytecode",
],
},
// Single module is imported statically and then dynamically.
{
src: "file_script_module_static_and_dynamic.html",
encodeEvents: [
// file_script_module_static_and_dynamic.mjs
"scriptloader_load_source",
"scriptloader_evaluate_module", // dispatched only for top-level (element)
"scriptloader_encode",
"scriptloader_bytecode_saved",
"test_evaluated",
// file_script_module_static_and_dynamic_imported_1.mjs
"scriptloader_load_source",
"scriptloader_evaluate_module", // dispatched only for top-level (dynamic)
"scriptloader_encode",
"scriptloader_bytecode_saved",
// file_script_module_static_and_dynamic_imported_2.mjs
"scriptloader_load_source",
"scriptloader_encode",
"scriptloader_bytecode_saved",
// file_script_module_static_and_dynamic_imported_3.mjs
"scriptloader_load_source",
"scriptloader_encode",
"scriptloader_bytecode_saved",
],
decodeEvents: [
// file_script_module_static_and_dynamic.mjs
"scriptloader_load_bytecode",
"scriptloader_evaluate_module", // dispatched only for top-level (element)
"test_evaluated",
// file_script_module_static_and_dynamic_imported_1.mjs
"scriptloader_load_bytecode",
"scriptloader_evaluate_module", // dispatched only for top-level (dynamic)
// file_script_module_static_and_dynamic_imported_2.mjs
"scriptloader_load_bytecode",
// file_script_module_static_and_dynamic_imported_3.mjs
"scriptloader_load_bytecode",
],
},
];
promise_test(async function() {
await SpecialPowers.pushPrefEnv({set: [
['dom.script_loader.bytecode_cache.enabled', true],
['dom.expose_test_interfaces', true],
['dom.script_loader.bytecode_cache.strategy', -1]
]});
for (const { src, encodeEvents, decodeEvents } of tests) {
for (let i = 0; i < 2; i++) {
const expectedEvents = i == 0 ? encodeEvents : decodeEvents;
const iframe = document.createElement("iframe");
document.body.appendChild(iframe);
const iwin = iframe.contentWindow;
dump("## Start: " + src + "\n");
let observedEvents = [];
await new Promise(resolve => {
function logEvent(evt) {
if (evt.type != "test_evaluated") {
if (!/^watchme/.test(evt.target.id)) {
return;
}
}
dump("## ScriptLoader event: " + evt.type + "\n");
observedEvents.push(evt.type);
if (observedEvents.length == expectedEvents.length) {
resolve();
}
}
iwin.addEventListener("scriptloader_load_source", logEvent);
iwin.addEventListener("scriptloader_load_bytecode", logEvent);
iwin.addEventListener("scriptloader_execute", logEvent);
iwin.addEventListener("scriptloader_evaluate_module", logEvent);
iwin.addEventListener("scriptloader_encode", logEvent);
iwin.addEventListener("scriptloader_no_encode", logEvent);
iwin.addEventListener("scriptloader_bytecode_saved", logEvent);
iwin.addEventListener("scriptloader_bytecode_failed", logEvent);
iwin.addEventListener("scriptloader_fallback", logEvent);
iwin.addEventListener("test_evaluated", logEvent);
iframe.src = src;
});
// The event order is non-deterministic.
// Just compare them as multi-set.
expectedEvents.sort();
observedEvents.sort();
assert_equals(
JSON.stringify(observedEvents),
JSON.stringify(expectedEvents),
`Expected events should be observed for ${src} during ${i == 0 ? "encoding" : "decoding"}`);
document.body.removeChild(iframe);
}
}
}, "Test module bytecode save and load");
done();
</script>
</body>
</html>