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 in iframe
// saveEvents
// Non-ordered multi-set of expected events dispatched during loading the
// "save" iframe in the HTML file
// loadEvents
// Non-ordered multi-set of expected events dispatched during loading the
// "load" iframe in the HTML file
const tests = [
// Same module is loaded by script element in 2 frames.
{
src: "file_script_module_frames_element.html",
saveEvents: [
// file_script_module_frames_element_shared.mjs
"scriptloader_load_source",
"scriptloader_evaluate_module",
"scriptloader_encode",
"scriptloader_bytecode_saved",
"test_evaluated",
],
loadEvents: [
// file_script_module_frames_element_shared.mjs
"scriptloader_load_bytecode",
"scriptloader_evaluate_module",
"test_evaluated",
],
},
// Same module is imported in 2 frames.
{
src: "file_script_module_frames_import.html",
saveEvents: [
// file_script_module_frames_import_save.mjs
"scriptloader_load_source",
"scriptloader_evaluate_module",
"scriptloader_encode",
"scriptloader_bytecode_saved",
"test_evaluated",
// file_script_module_frames_import_shared.mjs
"scriptloader_load_source",
"scriptloader_encode",
"scriptloader_bytecode_saved",
],
loadEvents: [
// file_script_module_frames_import_load.mjs
"scriptloader_load_source",
"scriptloader_evaluate_module",
"scriptloader_encode",
"scriptloader_bytecode_saved",
"test_evaluated",
// file_script_module_frames_import_shared.mjs
"scriptloader_load_bytecode",
],
},
// Same module is dynamically imported in 2 frames.
{
src: "file_script_module_frames_dynamic.html",
saveEvents: [
// file_script_module_frames_dynamic_save.mjs
"scriptloader_load_source",
"scriptloader_evaluate_module",
"scriptloader_encode",
"scriptloader_bytecode_saved",
"test_evaluated",
// file_script_module_frames_dynamic_shared.mjs
"scriptloader_load_source",
"scriptloader_evaluate_module",
"scriptloader_encode",
"scriptloader_bytecode_saved",
],
loadEvents: [
// file_script_module_frames_dynamic_load.mjs
"scriptloader_load_source",
"scriptloader_evaluate_module",
"scriptloader_encode",
"scriptloader_bytecode_saved",
"test_evaluated",
// file_script_module_frames_dynamic_shared.mjs
"scriptloader_load_bytecode",
"scriptloader_evaluate_module",
],
},
];
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, saveEvents, loadEvents } of tests) {
const iframe = document.createElement("iframe");
document.body.appendChild(iframe);
const iwin = iframe.contentWindow;
dump("## Start: " + src + "\n");
let observedSaveEvents = [];
await new Promise(resolve => {
function logEvent(evt) {
const type = evt.type.replace(/^save_/, "");
dump("## ScriptLoader event: " + type + "\n");
observedSaveEvents.push(type);
if (observedSaveEvents.length == saveEvents.length) {
resolve();
}
}
iwin.addEventListener("save_scriptloader_load_source", logEvent);
iwin.addEventListener("save_scriptloader_load_bytecode", logEvent);
iwin.addEventListener("save_scriptloader_execute", logEvent);
iwin.addEventListener("save_scriptloader_evaluate_module", logEvent);
iwin.addEventListener("save_scriptloader_encode", logEvent);
iwin.addEventListener("save_scriptloader_no_encode", logEvent);
iwin.addEventListener("save_scriptloader_bytecode_saved", logEvent);
iwin.addEventListener("save_scriptloader_bytecode_failed", logEvent);
iwin.addEventListener("save_scriptloader_fallback", logEvent);
iwin.addEventListener("save_test_evaluated", logEvent);
iframe.src = src;
});
// The event order is non-deterministic.
// Just compare them as multi-set.
saveEvents.sort();
observedSaveEvents.sort();
assert_equals(
JSON.stringify(observedSaveEvents),
JSON.stringify(saveEvents),
`Expected events should be observed for ${src} while saving`);
let observedLoadEvents = [];
const loadFrameEventPromise = new Promise(resolve => {
function logEvent(evt) {
const type = evt.type.replace(/^load_/, "");
dump("## ScriptLoader event: " + type + "\n");
observedLoadEvents.push(type);
if (observedLoadEvents.length == loadEvents.length) {
resolve();
}
}
iwin.addEventListener("load_scriptloader_load_source", logEvent);
iwin.addEventListener("load_scriptloader_load_bytecode", logEvent);
iwin.addEventListener("load_scriptloader_execute", logEvent);
iwin.addEventListener("load_scriptloader_evaluate_module", logEvent);
iwin.addEventListener("load_scriptloader_encode", logEvent);
iwin.addEventListener("load_scriptloader_no_encode", logEvent);
iwin.addEventListener("load_scriptloader_bytecode_saved", logEvent);
iwin.addEventListener("load_scriptloader_bytecode_failed", logEvent);
iwin.addEventListener("load_scriptloader_fallback", logEvent);
iwin.addEventListener("load_test_evaluated", logEvent);
});
// Make sure the "load" iframe is fully loaded.
await iwin.loadFramePromise;
iwin.document.getElementById("load").contentWindow.doLoad();
await loadFrameEventPromise;
// The event order is non-deterministic.
// Just compare them as multi-set.
loadEvents.sort();
observedLoadEvents.sort();
assert_equals(
JSON.stringify(observedLoadEvents),
JSON.stringify(loadEvents),
`Expected events should be observed for ${src} while loading`);
document.body.removeChild(iframe);
}
}, "Test module bytecode save and load");
done();
</script>
</body>
</html>