WebAssembly related utils for browser environment
The output code is ES2019
All example code below need to be bundled by ES module bundlers like webpack
/ rollup
, or specify import map in browser native ES module runtime.
The API is similar to the require('wasi').WASI
in Node.js.
You can use memfs-browser
to provide filesystem capability.
- Example: https://github.com/toyobayashi/wasi-wabt
- Demo: https://toyobayashi.github.io/wasi-wabt/
import { load, WASI } from '@tybys/wasm-util'
import { Volume, createFsFromVolume } from 'memfs-browser'
const fs = createFsFromVolume(Volume.fromJSON({
'/home/wasi': null
}))
const wasi = new WASI({
args: ['chrome', 'file.wasm'],
env: {
NODE_ENV: 'development',
WASI_SDK_PATH: '/opt/wasi-sdk'
},
preopens: {
'/': '/'
},
fs,
// redirect stdout / stderr
// print (text) { console.log(text) },
// printErr (text) { console.error(text) }
})
const imports = {
wasi_snapshot_preview1: wasi.wasiImport
}
const { module, instance } = await load('/path/to/file.wasm', imports)
wasi.start(instance)
// wasi.initialize(instance)
Implemented syscalls: wasi_snapshot_preview1
loadSync
has 4KB wasm size limit in browser.
// bundler
import { load, loadSync } from '@tybys/wasm-util'
const imports = { /* ... */ }
// using path
const { module, instance } = await load('/path/to/file.wasm', imports)
const { module, instance } = loadSync('/path/to/file.wasm', imports)
// using URL
const { module, instance } = await load(new URL('./file.wasm', import.meta.url), imports)
const { module, instance } = loadSync(new URL('./file.wasm', import.meta.url), imports)
// using Uint8Array
const buffer = new Uint8Array([
0x00, 0x61, 0x73, 0x6d,
0x01, 0x00, 0x00, 0x00
])
const { module, instance } = await load(buffer, imports)
const { module, instance } = loadSync(buffer, imports)
// auto asyncify
const {
module,
instance: asyncifiedInstance
} = await load(buffer, imports, { /* asyncify options */})
asyncifiedInstance.exports.fn() // => return Promise
import { Memory, extendMemory } from '@tybys/wasm-util'
const memory = new WebAssembly.Memory({ initial: 256 })
// const memory = instance.exports.memory
extendMemory(memory)
console.log(memory instanceof Memory)
console.log(memory instanceof WebAssembly.Memory)
// expose memory view getters like Emscripten
const { HEAPU8, HEAPU32, view } = memory
Build the C code using clang
, wasm-ld
and wasm-opt
void async_sleep(int ms);
int main() {
async_sleep(200);
return 0;
}
import { Asyncify } from '@tybys/wasm-util'
const asyncify = new Asyncify()
const imports = {
env: {
async_sleep: asyncify.wrapImportFunction(function (ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms)
})
})
}
}
// async_sleep(200)
const bytes = await (await fetch('/asyncfied_by_wasm-opt.wasm')).arrayBuffer()
const { instance } = await WebAssembly.instantiate(bytes, imports)
const asyncifiedInstance = asyncify.init(instance.exports.memory, instance, {
wrapExports: ['_start']
})
const p = asyncifedInstance._start()
console.log(typeof p.then === 'function')
const now = Date.now()
await p
console.log(Date.now() - now >= 200)
- args_get
- args_sizes_get
- environ_get
- environ_sizes_get
- clock_res_get
- clock_time_get
-
fd_advise - fd_allocate
- fd_close
- fd_datasync
- fd_fdstat_get
-
fd_fdstat_set_flags - fd_fdstat_set_rights
- fd_filestat_get
- fd_filestat_set_size
- fd_filestat_set_times
- fd_pread
- fd_prestat_get
- fd_prestat_dir_name
- fd_pwrite
- fd_read
- fd_readdir
- fd_renumber
- fd_seek
- fd_sync
- fd_tell
- fd_write
- path_create_directory
- path_filestat_get
- path_filestat_set_times
- path_link
- path_open
- path_readlink
- path_remove_directory
- path_rename
- path_symlink
- path_unlink_file
- poll_oneoff (timer only)
- proc_exit
-
proc_raise - sched_yield
- random_get
-
sock_recv -
sock_send -
sock_shutdown