tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit 8d56d54bd397c7533da83c40ff8e7a25542ff7a3
parent b59ff82f68bfd7993040b334b63f78b760c76c63
Author: Tooru Fujisawa <arai_a@mac.com>
Date:   Wed,  5 Nov 2025 04:09:45 +0000

Bug 1853173 - Part 1: Add basic tests for modules. r=nbp

Differential Revision: https://phabricator.services.mozilla.com/D271022

Diffstat:
Mdom/base/test/browser.toml | 4++++
Mdom/base/test/browser_script_loader_js_cache.js | 432+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
Adom/base/test/file_js_cache_imported1.mjs | 18++++++++++++++++++
Adom/base/test/file_js_cache_imported2.mjs | 22++++++++++++++++++++++
Adom/base/test/file_js_cache_imported3.mjs | 18++++++++++++++++++
Adom/base/test/file_js_cache_importer.mjs | 19+++++++++++++++++++
6 files changed, 503 insertions(+), 10 deletions(-)

diff --git a/dom/base/test/browser.toml b/dom/base/test/browser.toml @@ -160,6 +160,10 @@ support-files = [ "file_js_cache_small.js", "file_js_cache_large.js", "file_js_cache_large_syntax_error.js", + "file_js_cache_importer.mjs", + "file_js_cache_imported1.mjs", + "file_js_cache_imported2.mjs", + "file_js_cache_imported3.mjs", ] ["browser_set_focus_after_reuse_bcg.js"] diff --git a/dom/base/test/browser_script_loader_js_cache.js b/dom/base/test/browser_script_loader_js_cache.js @@ -7,7 +7,60 @@ function ev(event, file, hasElement = !!file) { hasElement, }; } -async function contentTask(item) { + +function unordered(list) { + return { + unordered: list, + }; +} + +async function contentTask(test, item) { + function match(param, event) { + if (event.event !== param.event) { + return false; + } + + if (param.url && event.url !== param.url) { + return false; + } + + if (event.hasElement) { + if (param.id !== "watchme") { + return false; + } + } else { + if (param.id) { + return false; + } + } + + return true; + } + + function consumeIfMatched(param, events) { + if ("unordered" in events[0]) { + const unordered = events[0].unordered; + for (let i = 0; i < unordered.length; i++) { + if (match(param, unordered[i])) { + unordered.splice(i, 1); + if (!unordered.length) { + events.shift(); + } + return true; + } + } + + return false; + } + + if (match(param, events[0])) { + events.shift(); + return true; + } + + return false; + } + const { promise, resolve, reject } = Promise.withResolvers(); const observer = function (subject, topic, data) { const param = {}; @@ -20,26 +73,23 @@ async function contentTask(item) { return; } - const event = item.events[0]; - if ( - event.event === param.event && - (!param.url || event.url === param.url) && - (event.hasElement ? param.id === "watchme" : !param.id) - ) { + if (consumeIfMatched(param, item.events)) { dump("@@@ Got expected event: " + data + "\n"); - item.events.shift(); if (item.events.length === 0) { resolve(); } } else { dump("@@@ Got unexpected event: " + data + "\n"); - dump("@@@ Expected: " + JSON.stringify(event) + "\n"); + dump("@@@ Expected: " + JSON.stringify(item.events[0]) + "\n"); } }; Services.obs.addObserver(observer, "ScriptLoaderTest"); const script = content.document.createElement("script"); script.id = "watchme"; + if (test.module) { + script.type = "module"; + } script.src = item.file; content.document.body.appendChild(script); @@ -50,6 +100,8 @@ async function contentTask(item) { async function runTests(tests) { await BrowserTestUtils.withNewTab(BASE_URL + "empty.html", async browser => { + const tab = gBrowser.getTabForBrowser(browser); + for (const test of tests) { ChromeUtils.clearResourceCache(); Services.cache2.clear(); @@ -57,6 +109,10 @@ async function runTests(tests) { for (let i = 0; i < test.items.length; i++) { const item = test.items[i]; info(`start: ${test.title} (item ${i})`); + + // Make sure the test starts in clean document. + await BrowserTestUtils.reloadTab(tab); + if (item.clearMemory) { info("clear memory cache"); ChromeUtils.clearResourceCache(); @@ -65,7 +121,7 @@ async function runTests(tests) { info("clear disk cache"); Services.cache2.clear(); } - await SpecialPowers.spawn(browser, [item], contentTask); + await SpecialPowers.spawn(browser, [test, item], contentTask); } ok(true, "end: " + test.title); @@ -79,6 +135,8 @@ add_task(async function testDiskCache() { await SpecialPowers.pushPrefEnv({ set: [ ["dom.expose_test_interfaces", true], + ["dom.script_loader.bytecode_cache.enabled", true], + ["dom.script_loader.bytecode_cache.strategy", 0], ["dom.script_loader.experimental.navigation_cache", false], ], }); @@ -228,6 +286,8 @@ add_task(async function testMemoryCache() { await SpecialPowers.pushPrefEnv({ set: [ ["dom.expose_test_interfaces", true], + ["dom.script_loader.bytecode_cache.enabled", true], + ["dom.script_loader.bytecode_cache.strategy", 0], ["dom.script_loader.experimental.navigation_cache", true], ], }); @@ -398,3 +458,355 @@ add_task(async function testMemoryCache() { await SpecialPowers.popPrefEnv(); }); + +add_task(async function testDiskCache_modules() { + await SpecialPowers.pushPrefEnv({ + set: [ + ["dom.expose_test_interfaces", true], + ["dom.script_loader.bytecode_cache.enabled", true], + ["dom.script_loader.bytecode_cache.strategy", 0], + ["dom.script_loader.experimental.navigation_cache", false], + ], + }); + + await runTests([ + // A small module shouldn't be saved to the disk. + { + title: "small module", + module: true, + items: [ + { + file: "file_js_cache_small.js", + events: [ + ev("load:source", "file_js_cache_small.js"), + ev("evaluate:module", "file_js_cache_small.js"), + ev("diskcache:disabled", "file_js_cache_small.js"), + ], + }, + { + file: "file_js_cache_small.js", + events: [ + ev("load:source", "file_js_cache_small.js"), + ev("evaluate:module", "file_js_cache_small.js"), + ev("diskcache:disabled", "file_js_cache_small.js"), + ], + }, + { + file: "file_js_cache_small.js", + events: [ + ev("load:source", "file_js_cache_small.js"), + ev("evaluate:module", "file_js_cache_small.js"), + ev("diskcache:disabled", "file_js_cache_small.js"), + ], + }, + { + file: "file_js_cache_small.js", + events: [ + ev("load:source", "file_js_cache_small.js"), + ev("evaluate:module", "file_js_cache_small.js"), + ev("diskcache:disabled", "file_js_cache_small.js"), + ], + }, + ], + }, + + // A large module file should be saved to the disk. + { + title: "large module", + module: true, + items: [ + { + file: "file_js_cache_large.js", + events: [ + ev("load:source", "file_js_cache_large.js"), + ev("evaluate:module", "file_js_cache_large.js"), + ev("diskcache:disabled", "file_js_cache_large.js"), + ], + }, + { + file: "file_js_cache_large.js", + events: [ + ev("load:source", "file_js_cache_large.js"), + ev("evaluate:module", "file_js_cache_large.js"), + ev("diskcache:disabled", "file_js_cache_large.js"), + ], + }, + { + file: "file_js_cache_large.js", + events: [ + ev("load:source", "file_js_cache_large.js"), + ev("evaluate:module", "file_js_cache_large.js"), + ev("diskcache:disabled", "file_js_cache_large.js"), + ], + }, + { + file: "file_js_cache_large.js", + events: [ + ev("load:source", "file_js_cache_large.js"), + ev("evaluate:module", "file_js_cache_large.js"), + ev("diskcache:register", "file_js_cache_large.js"), + ev("diskcache:saved", "file_js_cache_large.js", false), + ], + }, + ], + }, + + // All imported modules should be saved to the disk. + { + title: "imported modules", + module: true, + items: [ + { + file: "file_js_cache_importer.mjs", + events: [ + ev("load:source", "file_js_cache_importer.mjs"), + ev("load:source", "file_js_cache_imported1.mjs", false), + ev("load:source", "file_js_cache_imported2.mjs", false), + ev("load:source", "file_js_cache_imported3.mjs", false), + ev("evaluate:module", "file_js_cache_importer.mjs"), + ev("diskcache:disabled", "file_js_cache_importer.mjs"), + // non-top-level modules that don't pass the condition + // don't emit events. + ], + }, + { + file: "file_js_cache_importer.mjs", + events: [ + ev("load:source", "file_js_cache_importer.mjs"), + ev("load:source", "file_js_cache_imported1.mjs", false), + ev("load:source", "file_js_cache_imported2.mjs", false), + ev("load:source", "file_js_cache_imported3.mjs", false), + ev("evaluate:module", "file_js_cache_importer.mjs"), + ev("diskcache:disabled", "file_js_cache_importer.mjs"), + ], + }, + { + file: "file_js_cache_importer.mjs", + events: [ + ev("load:source", "file_js_cache_importer.mjs"), + ev("load:source", "file_js_cache_imported1.mjs", false), + ev("load:source", "file_js_cache_imported2.mjs", false), + ev("load:source", "file_js_cache_imported3.mjs", false), + ev("evaluate:module", "file_js_cache_importer.mjs"), + ev("diskcache:disabled", "file_js_cache_importer.mjs"), + ], + }, + { + file: "file_js_cache_importer.mjs", + events: [ + ev("load:source", "file_js_cache_importer.mjs"), + ev("load:source", "file_js_cache_imported1.mjs", false), + ev("load:source", "file_js_cache_imported2.mjs", false), + ev("load:source", "file_js_cache_imported3.mjs", false), + ev("evaluate:module", "file_js_cache_importer.mjs"), + ev("diskcache:register", "file_js_cache_importer.mjs"), + ev("diskcache:register", "file_js_cache_imported1.mjs", false), + ev("diskcache:register", "file_js_cache_imported2.mjs", false), + ev("diskcache:register", "file_js_cache_imported3.mjs", false), + ev("diskcache:saved", "file_js_cache_importer.mjs", false), + ev("diskcache:saved", "file_js_cache_imported1.mjs", false), + ev("diskcache:saved", "file_js_cache_imported2.mjs", false), + ev("diskcache:saved", "file_js_cache_imported3.mjs", false), + ], + }, + { + file: "file_js_cache_importer.mjs", + events: [ + ev("load:diskcache", "file_js_cache_importer.mjs"), + ev("load:diskcache", "file_js_cache_imported1.mjs", false), + ev("load:diskcache", "file_js_cache_imported2.mjs", false), + ev("load:diskcache", "file_js_cache_imported3.mjs", false), + ev("evaluate:module", "file_js_cache_importer.mjs"), + ev("diskcache:disabled", "file_js_cache_importer.mjs"), + ], + }, + ], + }, + ]); + + await SpecialPowers.popPrefEnv(); +}); + +add_task(async function testMemoryCache_modules() { + if (!AppConstants.NIGHTLY_BUILD) { + todo(false, "navigation cache is not yet enabled on non-nightly"); + return; + } + + await SpecialPowers.pushPrefEnv({ + set: [ + ["dom.expose_test_interfaces", true], + ["dom.script_loader.bytecode_cache.enabled", true], + ["dom.script_loader.bytecode_cache.strategy", 0], + ["dom.script_loader.experimental.navigation_cache", true], + ], + }); + + await runTests([ + // A small module shouldn't be saved to the disk. + { + title: "small module", + module: true, + items: [ + { + file: "file_js_cache_small.js", + events: [ + ev("load:source", "file_js_cache_small.js"), + ev("memorycache:saved", "file_js_cache_small.js"), + ev("evaluate:module", "file_js_cache_small.js"), + ev("diskcache:noschedule"), + ], + }, + { + file: "file_js_cache_small.js", + events: [ + ev("load:memorycache", "file_js_cache_small.js"), + ev("evaluate:module", "file_js_cache_small.js"), + ev("diskcache:noschedule"), + ], + }, + { + file: "file_js_cache_small.js", + events: [ + ev("load:memorycache", "file_js_cache_small.js"), + ev("evaluate:module", "file_js_cache_small.js"), + ev("diskcache:noschedule"), + ], + }, + { + file: "file_js_cache_small.js", + events: [ + ev("load:memorycache", "file_js_cache_small.js"), + ev("evaluate:module", "file_js_cache_small.js"), + ev("diskcache:noschedule"), + ], + }, + ], + }, + + // A large module file should be saved to the disk. + { + title: "large module", + module: true, + items: [ + { + file: "file_js_cache_large.js", + events: [ + ev("load:source", "file_js_cache_large.js"), + ev("memorycache:saved", "file_js_cache_large.js"), + ev("evaluate:module", "file_js_cache_large.js"), + ev("diskcache:noschedule"), + ], + }, + { + file: "file_js_cache_large.js", + events: [ + ev("load:memorycache", "file_js_cache_large.js"), + ev("evaluate:module", "file_js_cache_large.js"), + ev("diskcache:noschedule"), + ], + }, + { + file: "file_js_cache_large.js", + events: [ + ev("load:memorycache", "file_js_cache_large.js"), + ev("evaluate:module", "file_js_cache_large.js"), + ev("diskcache:noschedule"), + ], + }, + { + file: "file_js_cache_large.js", + events: [ + ev("load:memorycache", "file_js_cache_large.js"), + ev("evaluate:module", "file_js_cache_large.js"), + ev("diskcache:saved", "file_js_cache_large.js", false), + ], + }, + { + file: "file_js_cache_large.js", + events: [ + ev("load:memorycache", "file_js_cache_large.js"), + ev("evaluate:module", "file_js_cache_large.js"), + ev("diskcache:noschedule"), + ], + }, + ], + }, + + // All imported modules should be saved to the disk. + { + title: "imported modules", + module: true, + items: [ + { + file: "file_js_cache_importer.mjs", + events: [ + ev("load:source", "file_js_cache_importer.mjs"), + ev("memorycache:saved", "file_js_cache_importer.mjs"), + ev("load:source", "file_js_cache_imported1.mjs", false), + ev("memorycache:saved", "file_js_cache_imported1.mjs", false), + ev("load:source", "file_js_cache_imported2.mjs", false), + ev("memorycache:saved", "file_js_cache_imported2.mjs", false), + ev("load:source", "file_js_cache_imported3.mjs", false), + ev("memorycache:saved", "file_js_cache_imported3.mjs", false), + ev("evaluate:module", "file_js_cache_importer.mjs"), + ev("diskcache:noschedule"), + ], + }, + { + file: "file_js_cache_importer.mjs", + events: [ + ev("load:memorycache", "file_js_cache_importer.mjs"), + ev("load:memorycache", "file_js_cache_imported1.mjs", false), + ev("load:memorycache", "file_js_cache_imported2.mjs", false), + ev("load:memorycache", "file_js_cache_imported3.mjs", false), + ev("evaluate:module", "file_js_cache_importer.mjs"), + ev("diskcache:noschedule"), + ], + }, + { + file: "file_js_cache_importer.mjs", + events: [ + ev("load:memorycache", "file_js_cache_importer.mjs"), + ev("load:memorycache", "file_js_cache_imported1.mjs", false), + ev("load:memorycache", "file_js_cache_imported2.mjs", false), + ev("load:memorycache", "file_js_cache_imported3.mjs", false), + ev("evaluate:module", "file_js_cache_importer.mjs"), + ev("diskcache:noschedule"), + ], + }, + { + file: "file_js_cache_importer.mjs", + events: [ + ev("load:memorycache", "file_js_cache_importer.mjs"), + ev("load:memorycache", "file_js_cache_imported1.mjs", false), + ev("load:memorycache", "file_js_cache_imported2.mjs", false), + ev("load:memorycache", "file_js_cache_imported3.mjs", false), + ev("evaluate:module", "file_js_cache_importer.mjs"), + // SharedScriptCache iterates over unordered hashmap while + // saving. + unordered([ + ev("diskcache:saved", "file_js_cache_importer.mjs", false), + ev("diskcache:saved", "file_js_cache_imported1.mjs", false), + ev("diskcache:saved", "file_js_cache_imported2.mjs", false), + ev("diskcache:saved", "file_js_cache_imported3.mjs", false), + ]), + ], + }, + { + file: "file_js_cache_importer.mjs", + events: [ + ev("load:memorycache", "file_js_cache_importer.mjs"), + ev("load:memorycache", "file_js_cache_imported1.mjs", false), + ev("load:memorycache", "file_js_cache_imported2.mjs", false), + ev("load:memorycache", "file_js_cache_imported3.mjs", false), + ev("evaluate:module", "file_js_cache_importer.mjs"), + ev("diskcache:noschedule"), + ], + }, + ], + }, + ]); + + await SpecialPowers.popPrefEnv(); +}); diff --git a/dom/base/test/file_js_cache_imported1.mjs b/dom/base/test/file_js_cache_imported1.mjs @@ -0,0 +1,18 @@ +// A large comment block to make the file size pass the condition. +// A large comment block to make the file size pass the condition. +// A large comment block to make the file size pass the condition. +// A large comment block to make the file size pass the condition. +// A large comment block to make the file size pass the condition. +// A large comment block to make the file size pass the condition. +// A large comment block to make the file size pass the condition. +// A large comment block to make the file size pass the condition. +// A large comment block to make the file size pass the condition. +// A large comment block to make the file size pass the condition. +// A large comment block to make the file size pass the condition. +// A large comment block to make the file size pass the condition. +// A large comment block to make the file size pass the condition. +// A large comment block to make the file size pass the condition. +// A large comment block to make the file size pass the condition. +// A large comment block to make the file size pass the condition. + +export function func1() {} diff --git a/dom/base/test/file_js_cache_imported2.mjs b/dom/base/test/file_js_cache_imported2.mjs @@ -0,0 +1,22 @@ +// A large comment block to make the file size pass the condition. +// A large comment block to make the file size pass the condition. +// A large comment block to make the file size pass the condition. +// A large comment block to make the file size pass the condition. +// A large comment block to make the file size pass the condition. +// A large comment block to make the file size pass the condition. +// A large comment block to make the file size pass the condition. +// A large comment block to make the file size pass the condition. +// A large comment block to make the file size pass the condition. +// A large comment block to make the file size pass the condition. +// A large comment block to make the file size pass the condition. +// A large comment block to make the file size pass the condition. +// A large comment block to make the file size pass the condition. +// A large comment block to make the file size pass the condition. +// A large comment block to make the file size pass the condition. +// A large comment block to make the file size pass the condition. + +import { func3 } from "./file_js_cache_imported3.mjs"; + +export function func2() { + func3(); +} diff --git a/dom/base/test/file_js_cache_imported3.mjs b/dom/base/test/file_js_cache_imported3.mjs @@ -0,0 +1,18 @@ +// A large comment block to make the file size pass the condition. +// A large comment block to make the file size pass the condition. +// A large comment block to make the file size pass the condition. +// A large comment block to make the file size pass the condition. +// A large comment block to make the file size pass the condition. +// A large comment block to make the file size pass the condition. +// A large comment block to make the file size pass the condition. +// A large comment block to make the file size pass the condition. +// A large comment block to make the file size pass the condition. +// A large comment block to make the file size pass the condition. +// A large comment block to make the file size pass the condition. +// A large comment block to make the file size pass the condition. +// A large comment block to make the file size pass the condition. +// A large comment block to make the file size pass the condition. +// A large comment block to make the file size pass the condition. +// A large comment block to make the file size pass the condition. + +export function func3() {} diff --git a/dom/base/test/file_js_cache_importer.mjs b/dom/base/test/file_js_cache_importer.mjs @@ -0,0 +1,19 @@ +// A large comment block to make the file size pass the condition. +// A large comment block to make the file size pass the condition. +// A large comment block to make the file size pass the condition. +// A large comment block to make the file size pass the condition. +// A large comment block to make the file size pass the condition. +// A large comment block to make the file size pass the condition. +// A large comment block to make the file size pass the condition. +// A large comment block to make the file size pass the condition. +// A large comment block to make the file size pass the condition. +// A large comment block to make the file size pass the condition. +// A large comment block to make the file size pass the condition. +// A large comment block to make the file size pass the condition. +// A large comment block to make the file size pass the condition. +// A large comment block to make the file size pass the condition. +// A large comment block to make the file size pass the condition. +// A large comment block to make the file size pass the condition. + +import { func1 } from "./file_js_cache_imported1.mjs"; +import { func2 } from "./file_js_cache_imported2.mjs";