feat: add environment-aware WASM loading for Chrome/Firefox
This commit is contained in:
@@ -1,4 +1,7 @@
|
|||||||
/// Service worker entry point for the idfoto Chrome extension.
|
/// Background script entry point for the idfoto browser extension.
|
||||||
|
///
|
||||||
|
/// In Chrome this runs as a service worker (MV3). In Firefox this runs
|
||||||
|
/// as a persistent background script. WASM loading adapts automatically.
|
||||||
///
|
///
|
||||||
/// Loads the WASM module, manages vault state (master key, manifest, git host),
|
/// Loads the WASM module, manages vault state (master key, manifest, git host),
|
||||||
/// and routes all messages from the popup and content scripts.
|
/// and routes all messages from the popup and content scripts.
|
||||||
@@ -22,14 +25,14 @@ const totpSecretCache: Map<string, string> = new Map();
|
|||||||
|
|
||||||
// --- WASM initialization ---
|
// --- WASM initialization ---
|
||||||
|
|
||||||
// Chrome MV3 service workers do NOT support dynamic import().
|
// Chrome MV3 uses service workers which do NOT support dynamic import().
|
||||||
// Instead we load the WASM binary via fetch() and use the synchronous
|
// Firefox MV3 uses background scripts which DO support dynamic import().
|
||||||
// initSync() function exported by wasm-pack's --target web output.
|
// We detect the environment at runtime and use the appropriate loading strategy.
|
||||||
// The JS glue is imported statically so webpack bundles it into
|
|
||||||
// the service worker script.
|
|
||||||
|
|
||||||
// @ts-ignore TS2307 — resolved by webpack alias / copy
|
// @ts-ignore TS2307 — resolved by webpack alias / copy
|
||||||
import initSync, * as wasmBindings from '../../wasm/idfoto_wasm.js';
|
import initDefault, { initSync } from '../../wasm/idfoto_wasm.js';
|
||||||
|
// @ts-ignore TS2307
|
||||||
|
import * as wasmBindings from '../../wasm/idfoto_wasm.js';
|
||||||
|
|
||||||
type WasmModule = typeof wasmBindings;
|
type WasmModule = typeof wasmBindings;
|
||||||
let wasm: WasmModule | null = null;
|
let wasm: WasmModule | null = null;
|
||||||
@@ -37,10 +40,21 @@ let wasm: WasmModule | null = null;
|
|||||||
async function initWasm(): Promise<WasmModule> {
|
async function initWasm(): Promise<WasmModule> {
|
||||||
if (wasm) return wasm;
|
if (wasm) return wasm;
|
||||||
|
|
||||||
// Fetch the .wasm binary and instantiate synchronously
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
const SWGlobalScope = (globalThis as any).ServiceWorkerGlobalScope as (new () => ServiceWorker) | undefined;
|
||||||
|
const isServiceWorker = typeof SWGlobalScope !== 'undefined'
|
||||||
|
&& self instanceof (SWGlobalScope as unknown as typeof EventTarget);
|
||||||
|
|
||||||
|
if (isServiceWorker) {
|
||||||
|
// Chrome: fetch WASM binary and instantiate synchronously
|
||||||
const wasmResponse = await fetch(chrome.runtime.getURL('idfoto_wasm_bg.wasm'));
|
const wasmResponse = await fetch(chrome.runtime.getURL('idfoto_wasm_bg.wasm'));
|
||||||
const wasmBytes = await wasmResponse.arrayBuffer();
|
const wasmBytes = await wasmResponse.arrayBuffer();
|
||||||
initSync({ module: new WebAssembly.Module(wasmBytes) });
|
initSync({ module: new WebAssembly.Module(wasmBytes) });
|
||||||
|
} else {
|
||||||
|
// Firefox: background script — async init works
|
||||||
|
const wasmUrl = chrome.runtime.getURL('idfoto_wasm_bg.wasm');
|
||||||
|
await initDefault(wasmUrl);
|
||||||
|
}
|
||||||
|
|
||||||
vault.setWasm(wasmBindings);
|
vault.setWasm(wasmBindings);
|
||||||
wasm = wasmBindings;
|
wasm = wasmBindings;
|
||||||
|
|||||||
Reference in New Issue
Block a user