|
| 1 | +import { |
| 2 | + WASI, |
| 3 | + OpenFile, |
| 4 | + File, |
| 5 | + ConsoleStdout, |
| 6 | +} from "https://cdn.jsdelivr.net/npm/@bjorn3/[email protected]/dist/index.js"; |
| 7 | + |
| 8 | +const mod = await WebAssembly.compileStreaming(fetch("./pandoc.wasm")); |
| 9 | + |
| 10 | +const instance_promise_pool_size = 8; |
| 11 | + |
| 12 | +const instance_promise_pool = []; |
| 13 | + |
| 14 | +function instance_promise_pool_fill() { |
| 15 | + if (instance_promise_pool.length < instance_promise_pool_size) { |
| 16 | + for ( |
| 17 | + let i = instance_promise_pool.length; |
| 18 | + i < instance_promise_pool_size; |
| 19 | + ++i |
| 20 | + ) { |
| 21 | + const args = []; |
| 22 | + const env = []; |
| 23 | + const stdin_file = new File(new Uint8Array(), { readonly: true }); |
| 24 | + const stdout_file = new File(new Uint8Array(), { readonly: false }); |
| 25 | + const fds = [ |
| 26 | + new OpenFile(stdin_file), |
| 27 | + new OpenFile(stdout_file), |
| 28 | + ConsoleStdout.lineBuffered((msg) => |
| 29 | + console.warn(`[WASI stderr] ${msg}`) |
| 30 | + ), |
| 31 | + ]; |
| 32 | + const options = { debug: false }; |
| 33 | + const wasi = new WASI(args, env, fds, options); |
| 34 | + instance_promise_pool.push( |
| 35 | + WebAssembly.instantiate(mod, { |
| 36 | + wasi_snapshot_preview1: wasi.wasiImport, |
| 37 | + }).then((instance) => ({ instance, wasi, stdin_file, stdout_file })) |
| 38 | + ); |
| 39 | + } |
| 40 | + } |
| 41 | +} |
| 42 | + |
| 43 | +instance_promise_pool_fill(); |
| 44 | + |
| 45 | +const instances = (async function* () { |
| 46 | + while (true) { |
| 47 | + yield await instance_promise_pool.shift(); |
| 48 | + instance_promise_pool_fill(); |
| 49 | + } |
| 50 | +})(); |
| 51 | + |
| 52 | +export async function run_pandoc(args, stdin_str) { |
| 53 | + const { instance, wasi, stdin_file, stdout_file } = (await instances.next()) |
| 54 | + .value; |
| 55 | + wasi.args = ["pandoc.wasm", ...args]; |
| 56 | + stdin_file.data = new TextEncoder().encode(stdin_str); |
| 57 | + const ec = wasi.start(instance); |
| 58 | + if (ec !== 0) { |
| 59 | + throw new Error(`Non-zero exit code ${ec}`); |
| 60 | + } |
| 61 | + return new TextDecoder("utf-8", { fatal: true }).decode(stdout_file.data); |
| 62 | +} |
0 commit comments