tor-browser

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

commit d19df0f07a948f3b0b940b9528fbe7bd09249939
parent e4c7b4bde930191b7551404e67eb8462285475da
Author: Tooru Fujisawa <arai_a@mac.com>
Date:   Sat, 15 Nov 2025 05:09:16 +0000

Bug 1999465 - Part 1: Add testcase for JS cache + ServiceWorker. r=bthrall

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

Diffstat:
Mdom/base/test/browser.toml | 7+++++++
Adom/base/test/browser_script_loader_js_cache_serviceworker.js | 145+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adom/base/test/file_js_cache_sw.js | 7+++++++
Mdom/base/test/head.js | 36++++++++++++++++++++++++++++++++++--
4 files changed, 193 insertions(+), 2 deletions(-)

diff --git a/dom/base/test/browser.toml b/dom/base/test/browser.toml @@ -194,6 +194,13 @@ support-files = [ "file_js_cache_imported3.mjs", ] +["browser_script_loader_js_cache_serviceworker.js"] +support-files = [ + "empty.html", + "file_js_cache_large.js", + "file_js_cache_sw.js", +] + ["browser_script_loader_js_cache_sri_after_save.js"] support-files = [ "empty.html", diff --git a/dom/base/test/browser_script_loader_js_cache_serviceworker.js b/dom/base/test/browser_script_loader_js_cache_serviceworker.js @@ -0,0 +1,145 @@ +// ev, unordered, and runJSCacheTests are defined in head.js + +add_task(async function testDiskCache_ServiceWorker() { + 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], + ["dom.serviceWorkers.enabled", true], + ["dom.serviceWorkers.testing.enabled", true], + ], + }); + + // The response from the ServiceWorker doesn't have the expiration time and + // the fetch count (bug 1829240), and thus it's marked as Expired, and + // the disk cache is not created. + await runJSCacheTests([ + { + title: "service worker", + useServiceWorker: true, + skipReload: true, + items: [ + { + file: "file_js_cache_large.js", + events: [ + ev("load:source", "file_js_cache_large.js"), + ev("evaluate:classic", "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:classic", "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:classic", "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:classic", "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:classic", "file_js_cache_large.js"), + ev("diskcache:disabled", "file_js_cache_large.js"), + ], + }, + ], + }, + ]); + + await SpecialPowers.popPrefEnv(); +}); + +add_task(async function testMemoryCache_ServiceWorker() { + 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], + ["dom.serviceWorkers.enabled", true], + ["dom.serviceWorkers.testing.enabled", true], + ], + }); + + // The response from the ServiceWorker doesn't have the expiration time and + // the fetch count (bug 1829240), and thus it's marked as Expired, and + // the memory cache and the disk cache are not created. + // + // The memorycache:evict notification happens when the script is expired, + // regardless of whether there was in-memory cache entry. + await runJSCacheTests([ + { + title: "service worker", + useServiceWorker: true, + skipReload: true, + items: [ + { + file: "file_js_cache_large.js", + events: [ + ev("load:source", "file_js_cache_large.js"), + ev("memorycache:evict", "file_js_cache_large.js"), + ev("evaluate:classic", "file_js_cache_large.js"), + ev("diskcache:noschedule"), + ], + }, + { + file: "file_js_cache_large.js", + events: [ + ev("load:source", "file_js_cache_large.js"), + ev("memorycache:evict", "file_js_cache_large.js"), + ev("evaluate:classic", "file_js_cache_large.js"), + ev("diskcache:noschedule"), + ], + }, + { + file: "file_js_cache_large.js", + events: [ + ev("load:source", "file_js_cache_large.js"), + ev("memorycache:evict", "file_js_cache_large.js"), + ev("evaluate:classic", "file_js_cache_large.js"), + ev("diskcache:noschedule"), + ], + }, + { + file: "file_js_cache_large.js", + events: [ + ev("load:source", "file_js_cache_large.js"), + ev("memorycache:evict", "file_js_cache_large.js"), + ev("evaluate:classic", "file_js_cache_large.js"), + ev("diskcache:noschedule"), + ], + }, + { + file: "file_js_cache_large.js", + events: [ + ev("load:source", "file_js_cache_large.js"), + ev("memorycache:evict", "file_js_cache_large.js"), + ev("evaluate:classic", "file_js_cache_large.js"), + ev("diskcache:noschedule"), + ], + }, + ], + }, + ]); + + await SpecialPowers.popPrefEnv(); +}); diff --git a/dom/base/test/file_js_cache_sw.js b/dom/base/test/file_js_cache_sw.js @@ -0,0 +1,7 @@ +addEventListener("fetch", function (event) { + event.respondWith(fetch(event.request)); +}); + +addEventListener("activate", function (event) { + event.waitUntil(clients.claim()); +}); diff --git a/dom/base/test/head.js b/dom/base/test/head.js @@ -154,12 +154,36 @@ async function runJSCacheTests(tests) { ChromeUtils.clearResourceCache(); Services.cache2.clear(); + if (test.useServiceWorker) { + await SpecialPowers.spawn(browser, [], async () => { + const registration = await content.navigator.serviceWorker.register( + "file_js_cache_sw.js", + { scope: "./" } + ); + + const sw = registration.installing || registration.active; + + await new Promise(resolve => { + function onStateChange() { + if (sw.state === "activated") { + sw.removeEventListener("statechange", onStateChange); + resolve(); + } + } + sw.addEventListener("statechange", onStateChange); + onStateChange(); + }); + }); + } + 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 (!test.skipReload) { + // Make sure the test starts in clean document. + await BrowserTestUtils.reloadTab(tab); + } if (item.clearMemory) { info("clear memory cache"); @@ -177,6 +201,14 @@ async function runJSCacheTests(tests) { ok(result, "Received expected events"); } + if (test.useServiceWorker) { + await SpecialPowers.spawn(browser, [], async () => { + const registration = + await content.navigator.serviceWorker.getRegistration(); + registration.unregister(); + }); + } + ok(true, "end: " + test.title); } }