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:
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);
}
}