Loading src/services/tiny-pipeline.ts +67 −6 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ type TinyModuleFactory = (opts: { print: (text: string) => void; printErr: (text: string) => void; locateFile?: (path: string) => string; wasmBinary?: Uint8Array; }) => Promise<TinyModule>; export type PipelineResult = { Loading @@ -40,6 +41,11 @@ const defaultModulePaths: Record<TinyModuleKind, string> = { as: "../public/wasm/tinyas.js", vm: "../public/wasm/tinyvm.js", }; const wasmNameByKind: Record<TinyModuleKind, string> = { cc: "tinycc.wasm", as: "tinyas.wasm", vm: "tinyvm.wasm", }; function getModulePaths(): Record<TinyModuleKind, string> { const injected = (globalThis as { Loading @@ -58,6 +64,65 @@ function getInlineWasmBinaries(): Record<string, string> { }).__TINY_WASM_INLINE_BINARIES ?? {}; } const inlineWasmByteCache = new Map<string, Uint8Array>(); function basename(path: string): string { return path.replace(/^.*[\\/]/, ""); } function decodeDataUrlToBytes(dataUrl: string): Uint8Array { const commaIndex = dataUrl.indexOf(","); if (commaIndex < 0 || !dataUrl.startsWith("data:")) { throw new Error("invalid wasm data URL"); } const header = dataUrl.slice(0, commaIndex); const payload = dataUrl.slice(commaIndex + 1); const isBase64 = /;base64(?:;|$)/i.test(header); if (isBase64) { const binary = atob(payload); const bytes = new Uint8Array(binary.length); for (let i = 0; i < binary.length; i += 1) { bytes[i] = binary.charCodeAt(i); } return bytes; } const decoded = decodeURIComponent(payload); const bytes = new Uint8Array(decoded.length); for (let i = 0; i < decoded.length; i += 1) { bytes[i] = decoded.charCodeAt(i); } return bytes; } function resolveInlineWasmDataUrl(moduleKind: TinyModuleKind, requestedPath: string): string | undefined { const inline = getInlineWasmBinaries(); const candidates = [requestedPath, basename(requestedPath), wasmNameByKind[moduleKind]]; for (const key of candidates) { const value = inline[key]; if (value) { return value; } } return undefined; } function resolveInlineWasmBytes(moduleKind: TinyModuleKind): Uint8Array | undefined { const dataUrl = resolveInlineWasmDataUrl(moduleKind, wasmNameByKind[moduleKind]); if (!dataUrl) { return undefined; } const cached = inlineWasmByteCache.get(dataUrl); if (cached) { return cached; } const bytes = decodeDataUrlToBytes(dataUrl); inlineWasmByteCache.set(dataUrl, bytes); return bytes; } let cachedFactories: | { cc: TinyModuleFactory; Loading Loading @@ -114,16 +179,12 @@ async function runTool( noInitialRun: true, print: (text) => stdout.push(text), printErr: (text) => stderr.push(text), wasmBinary: resolveInlineWasmBytes(moduleKind), locateFile: (path) => { const inlineWasm = getInlineWasmBinaries()[path]; const inlineWasm = resolveInlineWasmDataUrl(moduleKind, path); if (inlineWasm) { return inlineWasm; } const wasmNameByKind: Record<TinyModuleKind, string> = { cc: "tinycc.wasm", as: "tinyas.wasm", vm: "tinyvm.wasm", }; return `../public/wasm/${wasmNameByKind[moduleKind]}`; }, }); Loading Loading
src/services/tiny-pipeline.ts +67 −6 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ type TinyModuleFactory = (opts: { print: (text: string) => void; printErr: (text: string) => void; locateFile?: (path: string) => string; wasmBinary?: Uint8Array; }) => Promise<TinyModule>; export type PipelineResult = { Loading @@ -40,6 +41,11 @@ const defaultModulePaths: Record<TinyModuleKind, string> = { as: "../public/wasm/tinyas.js", vm: "../public/wasm/tinyvm.js", }; const wasmNameByKind: Record<TinyModuleKind, string> = { cc: "tinycc.wasm", as: "tinyas.wasm", vm: "tinyvm.wasm", }; function getModulePaths(): Record<TinyModuleKind, string> { const injected = (globalThis as { Loading @@ -58,6 +64,65 @@ function getInlineWasmBinaries(): Record<string, string> { }).__TINY_WASM_INLINE_BINARIES ?? {}; } const inlineWasmByteCache = new Map<string, Uint8Array>(); function basename(path: string): string { return path.replace(/^.*[\\/]/, ""); } function decodeDataUrlToBytes(dataUrl: string): Uint8Array { const commaIndex = dataUrl.indexOf(","); if (commaIndex < 0 || !dataUrl.startsWith("data:")) { throw new Error("invalid wasm data URL"); } const header = dataUrl.slice(0, commaIndex); const payload = dataUrl.slice(commaIndex + 1); const isBase64 = /;base64(?:;|$)/i.test(header); if (isBase64) { const binary = atob(payload); const bytes = new Uint8Array(binary.length); for (let i = 0; i < binary.length; i += 1) { bytes[i] = binary.charCodeAt(i); } return bytes; } const decoded = decodeURIComponent(payload); const bytes = new Uint8Array(decoded.length); for (let i = 0; i < decoded.length; i += 1) { bytes[i] = decoded.charCodeAt(i); } return bytes; } function resolveInlineWasmDataUrl(moduleKind: TinyModuleKind, requestedPath: string): string | undefined { const inline = getInlineWasmBinaries(); const candidates = [requestedPath, basename(requestedPath), wasmNameByKind[moduleKind]]; for (const key of candidates) { const value = inline[key]; if (value) { return value; } } return undefined; } function resolveInlineWasmBytes(moduleKind: TinyModuleKind): Uint8Array | undefined { const dataUrl = resolveInlineWasmDataUrl(moduleKind, wasmNameByKind[moduleKind]); if (!dataUrl) { return undefined; } const cached = inlineWasmByteCache.get(dataUrl); if (cached) { return cached; } const bytes = decodeDataUrlToBytes(dataUrl); inlineWasmByteCache.set(dataUrl, bytes); return bytes; } let cachedFactories: | { cc: TinyModuleFactory; Loading Loading @@ -114,16 +179,12 @@ async function runTool( noInitialRun: true, print: (text) => stdout.push(text), printErr: (text) => stderr.push(text), wasmBinary: resolveInlineWasmBytes(moduleKind), locateFile: (path) => { const inlineWasm = getInlineWasmBinaries()[path]; const inlineWasm = resolveInlineWasmDataUrl(moduleKind, path); if (inlineWasm) { return inlineWasm; } const wasmNameByKind: Record<TinyModuleKind, string> = { cc: "tinycc.wasm", as: "tinyas.wasm", vm: "tinyvm.wasm", }; return `../public/wasm/${wasmNameByKind[moduleKind]}`; }, }); Loading