-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
43f2f40
commit a8ca59e
Showing
3 changed files
with
55 additions
and
55 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,60 +3,63 @@ import { | |
OpenFile, | ||
File, | ||
ConsoleStdout, | ||
PreopenDirectory, | ||
} from "https://cdn.jsdelivr.net/npm/@bjorn3/[email protected]/dist/index.js"; | ||
|
||
const mod = await WebAssembly.compileStreaming(fetch("./pandoc.wasm")); | ||
|
||
const instance_promise_pool_size = 8; | ||
const args = ["pandoc.wasm", "+RTS", "-H64m", "-RTS"]; | ||
const env = []; | ||
const in_file = new File(new Uint8Array(), { readonly: true }); | ||
const out_file = new File(new Uint8Array(), { readonly: false }); | ||
const fds = [ | ||
new OpenFile(new File(new Uint8Array(), { readonly: true })), | ||
ConsoleStdout.lineBuffered((msg) => console.log(`[WASI stdout] ${msg}`)), | ||
ConsoleStdout.lineBuffered((msg) => console.warn(`[WASI stderr] ${msg}`)), | ||
new PreopenDirectory("/", [ | ||
["in", in_file], | ||
["out", out_file], | ||
]), | ||
]; | ||
const options = { debug: false }; | ||
const wasi = new WASI(args, env, fds, options); | ||
const { instance } = await WebAssembly.instantiateStreaming( | ||
fetch("./pandoc.wasm"), | ||
{ | ||
wasi_snapshot_preview1: wasi.wasiImport, | ||
} | ||
); | ||
|
||
const instance_promise_pool = []; | ||
wasi.initialize(instance); | ||
instance.exports.__wasm_call_ctors(); | ||
|
||
function instance_promise_pool_fill() { | ||
if (instance_promise_pool.length < instance_promise_pool_size) { | ||
for ( | ||
let i = instance_promise_pool.length; | ||
i < instance_promise_pool_size; | ||
++i | ||
) { | ||
const args = []; | ||
const env = []; | ||
const stdin_file = new File(new Uint8Array(), { readonly: true }); | ||
const stdout_file = new File(new Uint8Array(), { readonly: false }); | ||
const fds = [ | ||
new OpenFile(stdin_file), | ||
new OpenFile(stdout_file), | ||
ConsoleStdout.lineBuffered((msg) => | ||
console.warn(`[WASI stderr] ${msg}`) | ||
), | ||
]; | ||
const options = { debug: false }; | ||
const wasi = new WASI(args, env, fds, options); | ||
instance_promise_pool.push( | ||
WebAssembly.instantiate(mod, { | ||
wasi_snapshot_preview1: wasi.wasiImport, | ||
}).then((instance) => ({ instance, wasi, stdin_file, stdout_file })) | ||
); | ||
} | ||
} | ||
function memory_data_view() { | ||
return new DataView(instance.exports.memory.buffer); | ||
} | ||
|
||
instance_promise_pool_fill(); | ||
const argc_ptr = instance.exports.malloc(4); | ||
memory_data_view().setUint32(argc_ptr, args.length, true); | ||
const argv = instance.exports.malloc(4 * (args.length + 1)); | ||
for (let i = 0; i < args.length; ++i) { | ||
const arg = instance.exports.malloc(args[i].length + 1); | ||
new TextEncoder().encodeInto( | ||
args[i], | ||
new Uint8Array(instance.exports.memory.buffer, arg, args[i].length) | ||
); | ||
memory_data_view().setUint8(arg + args[i].length, 0); | ||
memory_data_view().setUint32(argv + 4 * i, arg, true); | ||
} | ||
memory_data_view().setUint32(argv + 4 * args.length, 0, true); | ||
const argv_ptr = instance.exports.malloc(4); | ||
memory_data_view().setUint32(argv_ptr, argv, true); | ||
|
||
const instances = (async function* () { | ||
while (true) { | ||
yield await instance_promise_pool.shift(); | ||
instance_promise_pool_fill(); | ||
} | ||
})(); | ||
instance.exports.hs_init_with_rtsopts(argc_ptr, argv_ptr); | ||
|
||
export async function run_pandoc(args, stdin_str) { | ||
const { instance, wasi, stdin_file, stdout_file } = (await instances.next()) | ||
.value; | ||
wasi.args = ["pandoc.wasm", ...args]; | ||
stdin_file.data = new TextEncoder().encode(stdin_str); | ||
const ec = wasi.start(instance); | ||
if (ec !== 0) { | ||
throw new Error(`Non-zero exit code ${ec}`); | ||
} | ||
return new TextDecoder("utf-8", { fatal: true }).decode(stdout_file.data); | ||
export function pandoc(args_str, in_str) { | ||
const args_ptr = instance.exports.malloc(args_str.length); | ||
new TextEncoder().encodeInto( | ||
args_str, | ||
new Uint8Array(instance.exports.memory.buffer, args_ptr, args_str.length) | ||
); | ||
in_file.data = new TextEncoder().encode(in_str); | ||
instance.exports.wasm_main(args_ptr, args_str.length); | ||
return new TextDecoder("utf-8", { fatal: true }).decode(out_file.data); | ||
} |