diff options
Diffstat (limited to '')
-rw-r--r-- | dom/base/test/test_script_loader_js_cache_module_sri.html | 425 |
1 files changed, 425 insertions, 0 deletions
diff --git a/dom/base/test/test_script_loader_js_cache_module_sri.html b/dom/base/test/test_script_loader_js_cache_module_sri.html new file mode 100644 index 0000000000..9a7c7a57e8 --- /dev/null +++ b/dom/base/test/test_script_loader_js_cache_module_sri.html @@ -0,0 +1,425 @@ +<!DOCTYPE html> +<html> +<!-- https://bugzilla.mozilla.org/show_bug.cgi?id=1436400 --> +<!-- 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 request fallback for SRI mismatch on module bytecode</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +</head> +<body> + <script type="application/javascript"> + +// List of testcases +// +// prep +// HTML file loaded in iframe that prepares the bytecode cache +// prepEvents +// Non-ordered multi-set of expected events dispatched during loading the +// "prep" HTML file +// src +// HTML file loaded in iframe after preparation finishes +// events +// Non-ordered multi-set of expected events dispatched during loading the +// "src" HTML file +const tests = [ + // 1. Module bytecode is saved with integrity + // 2. Module bytecode is loaded by script element with integrity + { + prep: "file_script_module_sri_basic_prep.html", + prepEvents: [ + "scriptloader_load_source", + "scriptloader_evaluate_module", + "scriptloader_encode", + "scriptloader_bytecode_saved", + "test_evaluated", + ], + src: "file_script_module_sri_basic.html", + events: [ + "scriptloader_load_bytecode", + "scriptloader_evaluate_module", + "test_evaluated", + ], + }, + + // 1. Module bytecode is saved without integrity + // 2. Module bytecode is loaded by script element with integrity + { + prep: "file_script_module_sri_fallback_prep.html", + prepEvents: [ + "scriptloader_load_source", + "scriptloader_evaluate_module", + "scriptloader_encode", + "scriptloader_bytecode_saved", + "test_evaluated", + ], + src: "file_script_module_sri_fallback.html", + events: [ + "scriptloader_load_bytecode", + "scriptloader_fallback", + "scriptloader_load_source", + "scriptloader_evaluate_module", + "scriptloader_encode", + "scriptloader_bytecode_saved", + "test_evaluated", + ], + }, + + // 1. Module bytecode is saved without integrity + // 2. Module bytecode is loaded by script element with wrong integrity + // + // The module script is not evaluated + { + prep: "file_script_module_sri_fallback_failure_prep.html", + prepEvents: [ + "scriptloader_load_source", + "scriptloader_evaluate_module", + "scriptloader_encode", + "scriptloader_bytecode_saved", + "test_evaluated", + ], + src: "file_script_module_sri_fallback_failure.html", + events: [ + "scriptloader_load_bytecode", + "scriptloader_fallback", + "scriptloader_load_source", + + // This event is dispatched by another script, after the first module + // script load is terminated. + "test_evaluated", + ], + }, + + // 1. Module bytecode is saved without integrity + // 2. Module bytecode is loaded by script element without integrity, and then + // loaded by script element with integrity + // + // The integrity attribute is ignored because the first request without + // integrity is shared between them. + { + prep: "file_script_module_sri_elem_elem_1_prep.html", + prepEvents: [ + "scriptloader_load_source", + "scriptloader_evaluate_module", + "scriptloader_encode", + "scriptloader_bytecode_saved", + "test_evaluated", + ], + src: "file_script_module_sri_elem_elem_1.html", + events: [ + "scriptloader_load_bytecode", + "scriptloader_evaluate_module", + "test_evaluated", + + // NOTE: scriptloader_evaluate_module is dispatched even if + // the module is already evaluated before and it's evaluation is + // skipped this time. + "scriptloader_evaluate_module", + ], + }, + + // 1. Module bytecode is saved without integrity + // 2. Module bytecode is loaded by script element with integrity, and then + // loaded by script element without integrity + // + // The request with integrity is shared between them. + { + prep: "file_script_module_sri_elem_elem_2_prep.html", + prepEvents: [ + "scriptloader_load_source", + "scriptloader_evaluate_module", + "scriptloader_encode", + "scriptloader_bytecode_saved", + "test_evaluated", + ], + src: "file_script_module_sri_elem_elem_2.html", + events: [ + "scriptloader_load_bytecode", + "scriptloader_fallback", + "scriptloader_load_source", + "scriptloader_evaluate_module", + "scriptloader_encode", + "scriptloader_bytecode_saved", + "test_evaluated", + + "scriptloader_evaluate_module", + ], + }, + + // 1. Module bytecode is saved without integrity + // 2. Module bytecode is loaded by script element with integrity, and then + // imported statically. + // + // The request with integrity is shared between them. + { + prep: "file_script_module_sri_elem_import_prep.html", + prepEvents: [ + // file_script_module_sri_elem_import_imported.js + "scriptloader_load_source", + "scriptloader_evaluate_module", + "scriptloader_encode", + "scriptloader_bytecode_saved", + "test_evaluated", + ], + src: "file_script_module_sri_elem_import.html", + events: [ + // file_script_module_sri_elem_import_imported.js + "scriptloader_load_bytecode", + "scriptloader_fallback", + "scriptloader_load_source", + "scriptloader_evaluate_module", + "scriptloader_encode", + "scriptloader_bytecode_saved", + "test_evaluated", + + // file_script_module_sri_elem_import.js + "scriptloader_load_source", + "scriptloader_evaluate_module", + "scriptloader_encode", + "scriptloader_bytecode_saved", + "test_evaluated", + ], + }, + + // 1. Module bytecode is saved without integrity + // 2. Module bytecode is imported statically, and + // loaded by script element with integrity + // + // Even if the import is performed first, the script element's request + // with integrity is used because of preload. + { + prep: "file_script_module_sri_import_elem_prep.html", + prepEvents: [ + // file_script_module_sri_import_elem_imported.js + "scriptloader_load_source", + "scriptloader_evaluate_module", + "scriptloader_encode", + "scriptloader_bytecode_saved", + "test_evaluated", + ], + src: "file_script_module_sri_import_elem.html", + events: [ + // file_script_module_sri_import_elem.js + "scriptloader_load_source", + "scriptloader_evaluate_module", + "scriptloader_encode", + "scriptloader_bytecode_saved", + "test_evaluated", + + // file_script_module_sri_import_elem_imported.js + "scriptloader_load_bytecode", + "scriptloader_fallback", + "scriptloader_load_source", + "scriptloader_evaluate_module", + "scriptloader_encode", + "scriptloader_bytecode_saved", + "test_evaluated", + ], + }, + + // 1. Module bytecode is saved without integrity + // 2. Module bytecode is imported statically, and + // loaded by script element with integrity, without preload + // + // The request without integrity triggered by import is shared between + // them. + { + prep: "file_script_module_sri_import_elem_nopreload_prep.html", + prepEvents: [ + // file_script_module_sri_import_elem_nopreload_imported.js + "scriptloader_load_source", + "scriptloader_evaluate_module", + "scriptloader_encode", + "scriptloader_bytecode_saved", + "test_evaluated", + ], + src: "file_script_module_sri_import_elem_nopreload.html", + events: [ + // file_script_module_sri_import_elem_nopreload.js + "scriptloader_load_source", + "scriptloader_evaluate_module", + "scriptloader_encode", + "scriptloader_bytecode_saved", + "test_evaluated", + + // file_script_module_sri_import_elem_nopreload_imported.js + "scriptloader_load_bytecode", + "scriptloader_evaluate_module", + "test_evaluated", + ], + }, + + // 1. Module bytecode is saved without integrity + // 2. Module bytecode is loaded by script element with integrity, and then + // imported dynamically. + // + // The request with integrity is shared between them. + { + prep: "file_script_module_sri_elem_dynamic_prep.html", + prepEvents: [ + // file_script_module_sri_elem_dynamic_imported.js + "scriptloader_load_source", + "scriptloader_evaluate_module", + "scriptloader_encode", + "scriptloader_bytecode_saved", + "test_evaluated", + ], + src: "file_script_module_sri_elem_dynamic.html", + events: [ + // file_script_module_sri_elem_dynamic_imported.js + "scriptloader_load_bytecode", + "scriptloader_fallback", + "scriptloader_load_source", + "scriptloader_evaluate_module", // (element) + "scriptloader_evaluate_module", // (dynamic) + "scriptloader_encode", + "scriptloader_bytecode_saved", + "test_evaluated", + + // file_script_module_sri_elem_dynamic.js + "scriptloader_load_source", + "scriptloader_evaluate_module", + "scriptloader_encode", + "scriptloader_bytecode_saved", + "test_evaluated", + ], + }, + + // 1. Module bytecode is saved without integrity + // 2. Module bytecode is imported dynamically, and then + // loaded by script element with integrity + // + // Even if the dynamic import is performed first, the script element's + // request with integrity is used because of preload. + { + prep: "file_script_module_sri_dynamic_elem_prep.html", + prepEvents: [ + // file_script_module_sri_dynamic_elem_imported.js + "scriptloader_load_source", + "scriptloader_evaluate_module", + "scriptloader_encode", + "scriptloader_bytecode_saved", + "test_evaluated", + ], + src: "file_script_module_sri_dynamic_elem.html", + events: [ + // file_script_module_sri_dynamic_elem_imported.js + "scriptloader_load_bytecode", + "scriptloader_fallback", + "scriptloader_load_source", + "scriptloader_evaluate_module", // (element) + "scriptloader_evaluate_module", // (dynamic) + "scriptloader_encode", + "test_evaluated", + + // file_script_module_sri_dynamic_elem.js + "scriptloader_load_source", + "scriptloader_evaluate_module", + "scriptloader_encode", + "scriptloader_bytecode_saved", + "test_evaluated", + ], + }, + + // 1. Module bytecode is saved without integrity + // 2. Module bytecode is imported dynamically, and then + // loaded by script element with integrity, without preload + // + // The request without integrity triggered by dynamic import is shared + // between them. + { + prep: "file_script_module_sri_dynamic_elem_nopreload_prep.html", + prepEvents: [ + // file_script_module_sri_dynamic_elem_nopreload_imported.js + "scriptloader_load_source", + "scriptloader_evaluate_module", + "scriptloader_encode", + "scriptloader_bytecode_saved", + "test_evaluated", + ], + src: "file_script_module_sri_dynamic_elem_nopreload.html", + events: [ + // file_script_module_sri_dynamic_elem_nopreload_imported.js + "scriptloader_load_bytecode", + "scriptloader_evaluate_module", // (element) + "scriptloader_evaluate_module", // (dynamic) + "test_evaluated", + + // file_script_module_sri_dynamic_elem_nopreload.js + "scriptloader_load_source", + "scriptloader_evaluate_module", + "scriptloader_encode", + "scriptloader_bytecode_saved", + "test_evaluated", + ], + }, +]; + +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 { prep, prepEvents, src, events } of tests) { + for (let i = 0; i < 2; i++) { + const expectedEvents = i == 0 ? prepEvents : events; + const currentSrc = i == 0 ? prep : src; + + const iframe = document.createElement("iframe"); + document.body.appendChild(iframe); + + const iwin = iframe.contentWindow; + + dump("## Start: " + currentSrc + "\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 = currentSrc; + }); + + // 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 ${currentSrc}`); + + document.body.removeChild(iframe); + } + } +}, "Test module bytecode save and load"); + +done(); + </script> + <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1436400">Mozilla Bug 1436400</a> +</body> +</html> |