diff --git a/rollup.config.js b/rollup.config.js index 5b7898b0d148..12043ae600e5 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -119,6 +119,7 @@ const rollup = { targets: [ {src: './source/manifest.json', dest: 'distribution'}, {src: './source/*.+(html|png)', dest: 'distribution/assets'}, + {src: './source/background-loader.js', dest: 'distribution/assets'}, {src: './source/options-preflight.js', dest: 'distribution/assets'}, ], }), diff --git a/source/background-loader.js b/source/background-loader.js new file mode 100644 index 000000000000..890c45a6285b --- /dev/null +++ b/source/background-loader.js @@ -0,0 +1,19 @@ +function storeBackgroundLoadError(error) { + localStorage.backgroundLoadErrors ??= ''; + localStorage.backgroundLoadErrors += `${error?.stack ?? error?.message ?? String(error)}\n\n`; +} + +function backgroundLoadErrorListener(event) { + storeBackgroundLoadError(event.error ?? event.message); +} + +globalThis.addEventListener('error', backgroundLoadErrorListener); + +try { + // eslint-disable-next-line import-x/extensions -- The loader is copied to `distribution/assets`, where the built file is `background.js`. + await import('./background.js'); + globalThis.removeEventListener('error', backgroundLoadErrorListener); +} catch (error) { + storeBackgroundLoadError(error); + throw error; +} diff --git a/source/background.ts b/source/background.ts index e05c04e7cebd..25bc462f6b3c 100644 --- a/source/background.ts +++ b/source/background.ts @@ -115,3 +115,5 @@ chrome.runtime.onInstalled.addListener(async () => { // Call after the reset above just in case we nuked Safari's base permissions await showWelcomePage(); }); + +delete localStorage.backgroundLoadErrors; diff --git a/source/manifest.json b/source/manifest.json index 614ddbe83c80..f31433a88a6b 100644 --- a/source/manifest.json +++ b/source/manifest.json @@ -37,10 +37,10 @@ }, "options_page": "assets/options.html", "background": { - "service_worker": "assets/background.js", + "service_worker": "assets/background-loader.js", "type": "module", "scripts": [ - "assets/background.js" + "assets/background-loader.js" ] }, "content_scripts": [ diff --git a/source/options.css b/source/options.css index 5c6a0e0d542f..ed9d16e7a708 100644 --- a/source/options.css +++ b/source/options.css @@ -239,3 +239,10 @@ summary:hover { border: 1px solid var(--rgh-red); background: color-mix(in srgb, var(--rgh-red) 10%, transparent); } + +.js-background-fail-error { + overflow: auto; + white-space: pre-wrap; + margin: 1em 0 0; + font-size: 12px; +} diff --git a/source/options.html b/source/options.html index e3d91c6274a8..f5e789557079 100644 --- a/source/options.html +++ b/source/options.html @@ -24,9 +24,12 @@ - +
🔑 Personal token diff --git a/source/options.tsx b/source/options.tsx index 7f524471e366..29dd3a7f8629 100644 --- a/source/options.tsx +++ b/source/options.tsx @@ -7,8 +7,6 @@ import {isChrome, isFirefox} from 'webext-detect'; import type {SyncedForm} from 'webext-options-sync-per-domain'; import 'webext-bugs/target-blank'; -import {messageRuntime} from 'webext-msg'; - import {startFeatureIdentification} from './helpers/bisect.js'; import clearCacheHandler from './helpers/clear-cache-handler.js'; import {doesBrowserActionOpenOptions} from './helpers/feature-utils.js'; @@ -104,10 +102,16 @@ async function fetchHotfixes(event: MouseEvent): Promise { } } -async function validateBackgroundPage(): Promise { - if (await messageRuntime({ping: true}) !== 'pong') { - $('.js-background-fail-banner').hidden = false; +function validateBackgroundPage(): void { + const backgroundLoadErrors = localStorage.backgroundLoadErrors?.trim(); + if (!backgroundLoadErrors) { + return; } + + const errorField = $('.js-background-fail-error'); + errorField.textContent = backgroundLoadErrors; + errorField.hidden = false; + $('.js-background-fail-banner').hidden = false; } async function generateDom(): Promise { @@ -138,7 +142,7 @@ async function generateDom(): Promise { // Show stored CSS hotfixes void showStoredCssHotfixes(); - void validateBackgroundPage(); + validateBackgroundPage(); } function addEventListeners(): void {