@tybys/wasm-util
WebAssembly related utils for browser environment
The output code is ES2019
Features
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.
WASI polyfill for browser
The API is similar to the require('wasi').WASI
in Node.js.
You can use memfs-browser
to provide filesystem capability.
import { load, WASI } from '@tybys/wasm-util'
import { Volumn, createFsFromVolume } from 'memfs-browser'
const fs = createFsFromVolume(Volume.from({
'/home/wasi': null
}))
const wasi = new WASI({
args: ['chrome', 'file.wasm'],
env: {
NODE_ENV: 'development',
WASI_SDK_PATH: '/opt/wasi-sdk'
},
preopens: {
'/': '/'
},
fs,
})
const imports = {
wasi_snapshot_preview1: wasi.wasiImport
}
const { module, instance } = await load('/path/to/file.wasm', imports)
wasi.start(instance)
Implemented syscalls: wasi_snapshot_preview1
load
/ loadSync
loadSync
has 4KB wasm size limit in browser.
import { load, loadSync } from '@tybys/wasm-util'
const imports = { }
const { module, instance } = await load('/path/to/file.wasm', imports)
const { module, instance } = loadSync('/path/to/file.wasm', imports)
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)
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)
const {
module,
instance: asyncifiedInstance
} = await load(buffer, imports, { })
asyncifiedInstance.exports.fn()
Extend Memory instance
import { Memory, extendMemory } from '@tybys/wasm-util'
const memory = new WebAssembly.Memory({ initial: 256 })
extendMemory(memory)
console.log(memory instanceof Memory)
console.log(memory instanceof WebAssembly.Memory)
const { HEAPU8, HEAPU32, view } = memory
Asyncify wrap
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)
})
})
}
}
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)
wasi_snapshot_preview1