|
1 | | -/* |
2 | | -import { WASI } from 'wasi'; |
3 | | -
|
4 | | -// https://nodejs.org/api/wasi.html |
5 | | -const wasi = new WASI({ |
6 | | - args: argv, |
7 | | - env, |
8 | | - preopens: {} |
9 | | -}); |
10 | | -*/ |
11 | | - |
12 | 1 | // Stubs for WASI, needed because tree-sitter uses `fwrite(stderr, ...)` for error printing |
13 | 2 | function clock_time_get() { return 0; } |
14 | 3 | function fd_close() { return 0; } |
15 | 4 | function fd_seek() { return 0; } |
16 | 5 | function fd_write() { return 0; } |
17 | 6 | function proc_exit() { return 0; } |
18 | 7 |
|
19 | | -// Some WASI binaries require: |
20 | | -// const importObject = { wasi_unstable: wasi.wasiImport }; |
21 | | -// const importObject = { wasi_snapshot_preview1: wasi.wasiImport }; |
22 | | - |
23 | 8 | // Our own glue code |
24 | | -function jsConsoleLog(ptr, len) { console.log(toJsString(ptr, len)); } |
25 | | -function jsAbort(ptr, len) { throw new Error(toJsString(ptr, len)) } |
| 9 | +function jsConsoleLog(len, ptr) { console.log(toJsString(ptr, len)); } |
| 10 | +function jsConsoleError(len, ptr) { console.error(toJsString(ptr, len)); } |
| 11 | +function jsAbort(len, ptr) { throw new Error(toJsString(ptr, len)); } |
26 | 12 | function jsGetTimeMillis() { return new Date().getTime(); } |
27 | 13 |
|
28 | | -var wasmInstance; |
| 14 | +var wasm; |
29 | 15 |
|
30 | 16 | function toJsString(ptr, len) { |
31 | 17 | try { |
32 | | - var buffer = new Uint8Array(wasmInstance.exports.memory.buffer, ptr, len); |
33 | | - return string = new TextDecoder().decode(buffer); |
| 18 | + var buffer = new Uint8Array(wasm.exports.memory.buffer, ptr, len); |
| 19 | + return new TextDecoder().decode(buffer); |
34 | 20 | } catch (err) { |
35 | | - return "eh?"; |
| 21 | + console.error(err); |
| 22 | + return ""; |
36 | 23 | } |
37 | 24 | } |
38 | 25 |
|
39 | 26 | /// Send strings from JS to webassembly |
40 | 27 | function wasmSendString(str, type) { |
41 | | - const bytes = new TextEncoder().encode(str); // Encode in utf-8 |
42 | | - // Copy the string into memory allocated in the WebAssembly |
43 | | - const ptr = wasmInstance.exports.getStringMessageBuffer(); |
44 | | - const len = wasmInstance.exports.getStringMessageBufferLen(); |
45 | | - if (bytes.byteLength > len) { |
| 28 | + let buf = wasmStoreJsString(str, wasm.exports.getStringMessageBuffer(), wasm.exports.getStringMessageBufferLen()) |
| 29 | + wasm.exports.receiveStringMessage(buffer.byteOffset, bytes.byteLength + 1, type); |
| 30 | + return buffer; |
| 31 | +} |
| 32 | + |
| 33 | +function wasmStoreJsString(str, ptr, len) { |
| 34 | + const bytes = new TextEncoder().encode(str); |
| 35 | + if (bytes.byteLength > len) |
| 36 | + { |
46 | 37 | alert("input too big, must be at most " + len + " bytes") // #meh |
47 | 38 | return null; |
48 | 39 | } |
49 | | - const buffer = new Uint8Array(wasmInstance.exports.memory.buffer, ptr, bytes.byteLength + 1); // '0' terminator |
| 40 | + const buffer = new Uint8Array(wasm.exports.memory.buffer, ptr, bytes.byteLength + 1); // '0' terminator |
50 | 41 | buffer.set(bytes); |
51 | 42 | buffer[bytes.byteLength] = 0; // while Uint8Array is initialized to 0, don't rely on that |
52 | | - wasmInstance.exports.receiveStringMessage(buffer.byteOffset, bytes.byteLength + 1, type); |
53 | 43 | return buffer; |
54 | 44 | } |
55 | 45 |
|
56 | 46 | async function loadWasm(fileName, imports) { |
57 | 47 | const importObject = { |
58 | 48 | wasi_snapshot_preview1: { clock_time_get, fd_close, fd_seek, fd_write, proc_exit }, |
59 | | - env: { ...imports, jsConsoleLog, jsAbort, jsGetTimeMillis } |
| 49 | + env: { ...imports, jsConsoleLog, jsConsoleError, jsAbort, jsGetTimeMillis } |
60 | 50 | }; |
61 | | - const fetchPromise = new Promise(resolve => { |
62 | | - var request = new XMLHttpRequest(); |
63 | | - request.open('GET', fileName); |
64 | | - request.responseType = 'arraybuffer'; |
65 | | - request.onload = e => resolve(request.response); |
66 | | - request.onerror = function () { |
67 | | - resolve(undefined); |
68 | | - console.error("Could not retrieve WebAssembly object"); |
69 | | - }; |
70 | | - request.send(); |
71 | | - }) |
72 | 51 |
|
73 | | - const buffer = await fetchPromise; |
74 | | - const module = await WebAssembly.compile(buffer); |
75 | | - wasmInstance = await WebAssembly.instantiate(module, importObject); |
76 | | - return wasmInstance; |
| 52 | + const { instance } = await WebAssembly.instantiateStreaming(fetch(fileName), importObject); |
| 53 | + wasm = instance; |
| 54 | + return instance; |
77 | 55 | } |
0 commit comments