rs-loader.ts

2.4 KB · raw

1/**2 * rs-loader.ts — load the Reed-Solomon erasure WASM module.3 *4 * The same code runs in two contexts:5 *  - Extension popup (browser): fetch the WASM via `chrome.runtime.getURL`6 *    so the asset path resolves against the extension package. The WASM7 *    file is shipped from `public/codex/reed_solomon_erasure_bg.wasm`.8 *  - Vitest (Node + jsdom): read the WASM bytes from `node_modules`9 *    synchronously. We avoid the library's `fromCurrentDirectory*` helpers10 *    because they probe `__dirname`, which is unreliable when the test11 *    file is bundled by Vite.12 *13 * The instance is cached — WASM instantiation is non-trivial work and the14 * library is safe to reuse across encode / reconstruct calls.15 */1617import { CodexError } from "../../shared/codex-types";18import { ReedSolomonErasure } from "./reed-solomon";1920const WASM_RELATIVE_PATH = "codex/reed_solomon_erasure_bg.wasm";2122let cached: Promise<ReedSolomonErasure> | null = null;2324export function getReedSolomon(): Promise<ReedSolomonErasure> {25  if (!cached) cached = loadReedSolomon();26  return cached;27}2829async function loadReedSolomon(): Promise<ReedSolomonErasure> {30  try {31    if (isExtensionPopup()) {32      const url = chrome.runtime.getURL(WASM_RELATIVE_PATH);33      const response = await fetch(url);34      if (!response.ok) {35        throw new Error(`fetch ${url} → ${response.status}`);36      }37      const bytes = new Uint8Array(await response.arrayBuffer());38      return ReedSolomonErasure.fromBytes(bytes);39    }4041    const bytes = await readTestWasmBytes();42    return ReedSolomonErasure.fromBytes(bytes);43  } catch (err) {44    throw new CodexError(45      "RS_LIBRARY_FAILED",46      `Failed to load Reed-Solomon WASM module: ${err instanceof Error ? err.message : String(err)}`,47    );48  }49}5051async function readTestWasmBytes(): Promise<Uint8Array<ArrayBuffer>> {52  if (import.meta.env.MODE !== "test") {53    throw new Error("Reed-Solomon WASM can only be loaded through chrome.runtime.getURL outside tests");54  }55  const { readNodeReedSolomonWasmBytes } = await import("./node-wasm");56  return readNodeReedSolomonWasmBytes();57}5859function isExtensionPopup(): boolean {60  return (61    typeof chrome !== "undefined" &&62    typeof chrome.runtime !== "undefined" &&63    typeof chrome.runtime.getURL === "function"64  );65}6667/** Reset the cache. Test-only — never called from production code. */68export function _resetReedSolomonCacheForTest(): void {69  cached = null;70}