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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
|
"use strict";
const fs = require("fs");
const {WASI} = require("wasi");
const separatorIndex = process.argv.indexOf("--");
const runWasmArgs = process.argv.slice(1, separatorIndex)
const isWasm64 = runWasmArgs.includes("--wasm64");
const isPatioTest = runWasmArgs.includes("--patio-test");
const wasmExecutablePath = process.argv[separatorIndex + 1];
const createWasi = isWasm64 ? createWasiForWasm64 : createWasiForWasm32;
function createWasiForWasm32() {
return new WASI({
version: "preview1",
args: process.argv.slice(2),
env: process.env,
returnOnExit: false,
});
}
function createWasiForWasm64() {
// When using the builtin WASI with wasm64, nothing seems to get printed to
// stdout. It's not clear whether the compiler makes an incorrect assumption
// about what node thinks the API for fd_write is on wasm64, or whether WASI
// isn't supported by node on wasm64, but given that (so far as I known)
// WASI isn't really defined for wasm64, it seems reasonable to roll our own
// implementation for now.
let runningInstance = null;
const wasiImport = {
fd_write: (fd, iovsPtr, iovsLen, nwritten) => {
iovsPtr = Number(iovsPtr);
const memoryBuffer = runningInstance.exports.memory.buffer;
const memoryDataView = new DataView(memoryBuffer);
for (let iovsIndex = 0; iovsIndex < iovsLen; iovsIndex++) {
const iovPtr = iovsPtr + iovsIndex * 16;
const bufPtr = Number(memoryDataView.getBigUint64(iovPtr, true));
const bufLen = Number(memoryDataView.getBigUint64(iovPtr + 8, true));
const buf = Buffer.from(memoryBuffer, bufPtr, bufLen);
// TODO: handle fd !== 1
process.stdout.write(buf);
}
// TODO: update nwritten
},
proc_exit: (exitCode) => {
process.exit(exitCode);
},
};
const start = (instance) => {
runningInstance = instance;
instance.exports._start();
};
return {wasiImport, start};
}
(async () => {
const wasi = createWasi();
const importObject = {
"wasi_snapshot_preview1": wasi.wasiImport,
};
if (isPatioTest) {
importObject["env"] = {
patio__test__emit_int: (value) => {
console.log(value.toString());
},
};
}
const wasm = await WebAssembly.compile(fs.readFileSync(wasmExecutablePath));
const instance = await WebAssembly.instantiate(wasm, importObject);
wasi.start(instance);
})();
|