Skip to content

Commit 3f260fe

Browse files
committed
frontend: use single wasm instance
1 parent 43f2f40 commit 3f260fe

File tree

3 files changed

+55
-55
lines changed

3 files changed

+55
-55
lines changed

.github/workflows/build.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ jobs:
6868
6969
- name: test
7070
run: |
71-
$CROSS_EMULATOR dist/pandoc.wasm pandoc/README.md -o pandoc/README.rst
71+
wasmtime run --dir $PWD::/ -- dist/pandoc.wasm pandoc/README.md -o pandoc/README.rst
7272
head --lines=20 pandoc/README.rst
7373
7474
- name: upload-pages-artifact

frontend/index.html

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -67,16 +67,13 @@
6767
<input type="text" id="arguments" value="-f markdown -t rst" />
6868
</div>
6969
<script type="module">
70-
import { run_pandoc } from "./index.js";
70+
import { pandoc } from "./index.js";
7171

7272
async function updateOutput() {
7373
const inputText = document.getElementById("input").value;
74-
const argumentsText = document
75-
.getElementById("arguments")
76-
.value.trim()
77-
.split(" ");
74+
const argumentsText = document.getElementById("arguments").value;
7875
try {
79-
const output = await run_pandoc(argumentsText, inputText);
76+
const output = pandoc(argumentsText, inputText);
8077
document.getElementById("output").value = output;
8178
} catch (err) {
8279
document.getElementById("output").value = `Error: ${err.message}`;

frontend/index.js

Lines changed: 51 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -3,60 +3,63 @@ import {
33
OpenFile,
44
File,
55
ConsoleStdout,
6+
PreopenDirectory,
67
} from "https://cdn.jsdelivr.net/npm/@bjorn3/[email protected]/dist/index.js";
78

8-
const mod = await WebAssembly.compileStreaming(fetch("./pandoc.wasm"));
9-
10-
const instance_promise_pool_size = 8;
9+
const args = ["pandoc.wasm", "+RTS", "-H64m", "-RTS"];
10+
const env = [];
11+
const in_file = new File(new Uint8Array(), { readonly: true });
12+
const out_file = new File(new Uint8Array(), { readonly: false });
13+
const fds = [
14+
new OpenFile(new File(new Uint8Array(), { readonly: true })),
15+
ConsoleStdout.lineBuffered((msg) => console.log(`[WASI stdout] ${msg}`)),
16+
ConsoleStdout.lineBuffered((msg) => console.warn(`[WASI stderr] ${msg}`)),
17+
new PreopenDirectory("/", [
18+
["in", in_file],
19+
["out", out_file],
20+
]),
21+
];
22+
const options = { debug: false };
23+
const wasi = new WASI(args, env, fds, options);
24+
const { instance } = await WebAssembly.instantiateStreaming(
25+
fetch("./pandoc.wasm"),
26+
{
27+
wasi_snapshot_preview1: wasi.wasiImport,
28+
}
29+
);
1130

12-
const instance_promise_pool = [];
31+
wasi.initialize(instance);
32+
instance.exports.__wasm_call_ctors();
1333

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-
}
34+
function memory_data_view() {
35+
return new DataView(instance.exports.memory.buffer);
4136
}
4237

43-
instance_promise_pool_fill();
38+
const argc_ptr = instance.exports.malloc(4);
39+
memory_data_view().setUint32(argc_ptr, args.length, true);
40+
const argv = instance.exports.malloc(4 * (args.length + 1));
41+
for (let i = 0; i < args.length; ++i) {
42+
const arg = instance.exports.malloc(args[i].length + 1);
43+
new TextEncoder().encodeInto(
44+
args[i],
45+
new Uint8Array(instance.exports.memory.buffer, arg, args[i].length)
46+
);
47+
memory_data_view().setUint8(arg + args[i].length, 0);
48+
memory_data_view().setUint32(argv + 4 * i, arg, true);
49+
}
50+
memory_data_view().setUint32(argv + 4 * args.length, 0, true);
51+
const argv_ptr = instance.exports.malloc(4);
52+
memory_data_view().setUint32(argv_ptr, argv, true);
4453

45-
const instances = (async function* () {
46-
while (true) {
47-
yield await instance_promise_pool.shift();
48-
instance_promise_pool_fill();
49-
}
50-
})();
54+
instance.exports.hs_init_with_rtsopts(argc_ptr, argv_ptr);
5155

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);
56+
export function pandoc(args_str, in_str) {
57+
const args_ptr = instance.exports.malloc(args_str.length);
58+
new TextEncoder().encodeInto(
59+
args_str,
60+
new Uint8Array(instance.exports.memory.buffer, args_ptr, args_str.length)
61+
);
62+
in_file.data = new TextEncoder().encode(in_str);
63+
instance.exports.wasm_main(args_ptr, args_str.length);
64+
return new TextDecoder("utf-8", { fatal: true }).decode(out_file.data);
6265
}

0 commit comments

Comments
 (0)