/** * rs-loader.ts — load the Reed-Solomon erasure WASM module. * * The same code runs in two contexts: * - Extension popup (browser): fetch the WASM via `chrome.runtime.getURL` * so the asset path resolves against the extension package. The WASM * file is shipped from `public/codex/reed_solomon_erasure_bg.wasm`. * - Vitest (Node + jsdom): read the WASM bytes from `node_modules` * synchronously. We avoid the library's `fromCurrentDirectory*` helpers * because they probe `__dirname`, which is unreliable when the test * file is bundled by Vite. * * The instance is cached — WASM instantiation is non-trivial work and the * library is safe to reuse across encode / reconstruct calls. */ import { CodexError } from "../../shared/codex-types"; import { ReedSolomonErasure } from "./reed-solomon"; const WASM_RELATIVE_PATH = "codex/reed_solomon_erasure_bg.wasm"; let cached: Promise | null = null; export function getReedSolomon(): Promise { if (!cached) cached = loadReedSolomon(); return cached; } async function loadReedSolomon(): Promise { try { if (isExtensionPopup()) { const url = chrome.runtime.getURL(WASM_RELATIVE_PATH); const response = await fetch(url); if (!response.ok) { throw new Error(`fetch ${url} → ${response.status}`); } const bytes = new Uint8Array(await response.arrayBuffer()); return ReedSolomonErasure.fromBytes(bytes); } const bytes = await readTestWasmBytes(); return ReedSolomonErasure.fromBytes(bytes); } catch (err) { throw new CodexError( "RS_LIBRARY_FAILED", `Failed to load Reed-Solomon WASM module: ${err instanceof Error ? err.message : String(err)}`, ); } } async function readTestWasmBytes(): Promise> { if (import.meta.env.MODE !== "test") { throw new Error("Reed-Solomon WASM can only be loaded through chrome.runtime.getURL outside tests"); } const { readNodeReedSolomonWasmBytes } = await import("./node-wasm"); return readNodeReedSolomonWasmBytes(); } function isExtensionPopup(): boolean { return ( typeof chrome !== "undefined" && typeof chrome.runtime !== "undefined" && typeof chrome.runtime.getURL === "function" ); } /** Reset the cache. Test-only — never called from production code. */ export function _resetReedSolomonCacheForTest(): void { cached = null; }