/** * Runs 7-Zip for johnmcm.com's Archive Toolkit. The page sends the archive * once; each request after that is a fresh run of 7zz on it. * * Messages in: { id, type: 'open', file: File, others?: { paths: string[], file: File }[] } * (others: a differencing disk's parents or a VMDK's extents, at the * path the archive names them by) * { id, type: 'list', op: { type?, inner? } } * { id, type: 'extract', op: { type?, inner?, paths } } * Messages out: { id } after open; { id, entries, warning } after list; * { id, files: { path, data, error }[] } after extract; * or { id, error }. * * Written for johnmcm.com (2026); part of the module published at /source/7zip/. */ import create7z from './7zz.mjs'; import { extract, list } from './run.mjs'; let compiled = null; let file = null; let others = []; function wasmModule() { // A failed fetch or compile is not kept, so the next request tries again. compiled ??= WebAssembly.compileStreaming(fetch(new URL('./7zz.wasm', import.meta.url))).catch((err) => { compiled = null; throw err; }); return compiled; } async function options() { let module; try { module = await wasmModule(); } catch { throw new Error('load'); } return { instantiateWasm(imports, done) { WebAssembly.instantiate(module, imports).then((i) => done(i)); return {}; }, }; } self.onmessage = async (e) => { const msg = e.data; try { if (msg.type === 'open') { file = msg.file; others = (msg.others ?? []).map((o) => ({ paths: o.paths ?? [o.path], blob: o.file })); await options(); self.postMessage({ id: msg.id }); return; } if (!file) throw new Error('No archive was opened.'); const input = { name: file.name, blob: file, others }; if (msg.type === 'list') { const r = await list(create7z, input, msg.op, await options()); self.postMessage({ id: msg.id, ...r }); } else if (msg.type === 'extract') { const files = await extract(create7z, input, msg.op, await options()); self.postMessage({ id: msg.id, files }, files.filter((f) => f.data).map((f) => f.data.buffer)); } } catch (err) { self.postMessage({ id: msg.id, error: String(err?.message || err) }); } };