-
Notifications
You must be signed in to change notification settings - Fork 117
/
wasm.js
111 lines (103 loc) · 3.46 KB
/
wasm.js
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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
// make the "require" function available to all
Tarp.require({expose: true});
// Have a global variable:
if (typeof window !== 'undefined') {
window.global = window;
}
// and a Buffer variable
var Buffer = require('buffer').Buffer;
var process = require('process');
// Functions to deal with WebAssembly:
// These should load a wasm program: http://andrewsweeney.net/post/llvm-to-wasm/
/* Array of bytes to base64 string decoding */
// Modules for @wasmer:
const WASI = require('@wasmer/wasi/lib').WASI;
const browserBindings = require('@wasmer/wasi/lib/bindings/browser').default;
const WasmFs = require('@wasmer/wasmfs').WasmFs;
// Experiment: don't call lowerI64Imports, see if that works.
// const lowerI64Imports = require("@wasmer/wasm-transformer").lowerI64Imports
function b64ToUint6 (nChr) {
return nChr > 64 && nChr < 91 ?
nChr - 65
: nChr > 96 && nChr < 123 ?
nChr - 71
: nChr > 47 && nChr < 58 ?
nChr + 4
: nChr === 43 ?
62
: nChr === 47 ?
63
:
0;
}
function base64DecToArr (sBase64, nBlockSize) {
var
sB64Enc = sBase64.replace(/[^A-Za-z0-9\+\/]/g, ""), nInLen = sB64Enc.length,
nOutLen = nBlockSize ? Math.ceil((nInLen * 3 + 1 >>> 2) / nBlockSize) * nBlockSize : nInLen * 3 + 1 >>> 2, aBytes = new Uint8Array(nOutLen);
for (var nMod3, nMod4, nUint24 = 0, nOutIdx = 0, nInIdx = 0; nInIdx < nInLen; nInIdx++) {
nMod4 = nInIdx & 3;
nUint24 |= b64ToUint6(sB64Enc.charCodeAt(nInIdx)) << 18 - 6 * nMod4;
if (nMod4 === 3 || nInLen - nInIdx === 1) {
for (nMod3 = 0; nMod3 < 3 && nOutIdx < nOutLen; nMod3++, nOutIdx++) {
aBytes[nOutIdx] = nUint24 >>> (16 >>> nMod3 & 24) & 255;
}
nUint24 = 0;
}
}
return aBytes;
}
// bufferString: program in base64 format
// args: arguments (argv[argc])
// stdinBuffer: standard input
// cwd: current working directory
function executeWebAssembly(bufferString, args, cwd, tty, env) {
// Input: base64 encoded binary wasm file
if (typeof window !== 'undefined') {
if (!('WebAssembly' in window)) {
window.webkit.messageHandlers.aShell.postMessage('WebAssembly not supported');
return;
}
}
var arrayBuffer = base64DecToArr(bufferString);
// Experiment: don't call lowerI64Imports, see if that works.
const loweredWasmBytes = arrayBuffer; // lowerI64Imports(arrayBuffer);
var errorMessage = '';
var errorCode = 0;
// TODO: link with other libraries/frameworks? impossible, I guess.
// TODO: keyboard input (directly from onkeypress)
try {
const wasmFs = new WasmFs(); // local file system. Used less often.
let wasi = new WASI({
preopens: {'.': cwd, '/': '/'},
args: args,
env: env,
bindings: {
...browserBindings,
fs: wasmFs.fs,
}
})
wasi.args = args
if (tty != 1) {
wasi.bindings.isTTY = (fd) => false;
}
const module = new WebAssembly.Module(loweredWasmBytes);
const instance = new WebAssembly.Instance(module, wasi.getImports(module));
wasi.start(instance);
}
catch (error) {
// WASI returns an error even in some cases where things went well.
// We find the type of the error, and return the appropriate error message
// This line must be commented on release (it breaks tlmgr):
// console.log("Wasm error: " + error.message + " Error code: " + error.code);
if (error.code === undefined) {
errorCode = 1;
errorMessage = '\nwasm: ' + error + '\n';
} else if (error.code != null) {
// Numerical error code. Send the return code back to Swift.
errorCode = error.code;
} else {
errorCode = 1;
}
}
return [errorCode, errorMessage];
}