/
wasm-parser.ts
56 lines (51 loc) · 1.64 KB
/
wasm-parser.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
import fs from "fs";
export interface WasmInfo {
imports: {
from: string;
names: string[];
}[];
exports: string[];
}
export async function parseWasm(wasmFilePath: string): Promise<WasmInfo> {
try {
const wasmBinary = await fs.promises.readFile(wasmFilePath);
const wasmModule = await WebAssembly.compile(wasmBinary);
const imports = Object.entries(
WebAssembly.Module.imports(wasmModule).reduce(
(result, item) => ({
...result,
[item.module]: [...(result[item.module] || []), item.name]
}),
{} as Record<string, string[]>
)
).map(([from, names]) => ({ from, names }));
const exports = WebAssembly.Module.exports(wasmModule).map(item => item.name);
return { imports, exports };
} catch (e) {
throw new Error(`Failed to parse WASM file: ${e.message}`);
}
}
export async function generateGlueCode(
wasmFilePath: string,
names: { initWasm: string; wasmUrl: string }
): Promise<string> {
const { imports, exports } = await parseWasm(wasmFilePath);
return `
${imports
.map(
({ from, names }, i) =>
`import { ${names.map((name, j) => `${name} as __vite__wasmImport_${i}_${j}`).join(", ")} } from ${JSON.stringify(
from
)};`
)
.join("\n")}
const __vite__wasmModule = await ${names.initWasm}({ ${imports
.map(
({ from, names }, i) =>
`${JSON.stringify(from)}: { ${names.map((name, j) => `${name}: __vite__wasmImport_${i}_${j}`).join(", ")} }`
)
.join(", ")} }, ${names.wasmUrl});
${exports
.map(name => `export ${name === "default" ? "default" : `const ${name} =`} __vite__wasmModule.${name};`)
.join("\n")}`;
}