@tybys/wasm-util
TypeScript icon, indicating that this package has built-in type declarations

0.9.0 • Public • Published

@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 { 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

load / loadSync

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

Extend Memory instance

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

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)
      })
    })
  }
}

// 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)

wasi_snapshot_preview1

  • [x] args_get
  • [x] args_sizes_get
  • [x] environ_get
  • [x] environ_sizes_get
  • [x] clock_res_get
  • [x] clock_time_get
  • [ ] fd_advise
  • [x] fd_allocate
  • [x] fd_close
  • [x] fd_datasync
  • [x] fd_fdstat_get
  • [ ] fd_fdstat_set_flags
  • [x] fd_fdstat_set_rights
  • [x] fd_filestat_get
  • [x] fd_filestat_set_size
  • [x] fd_filestat_set_times
  • [x] fd_pread
  • [x] fd_prestat_get
  • [x] fd_prestat_dir_name
  • [x] fd_pwrite
  • [x] fd_read
  • [x] fd_readdir
  • [x] fd_renumber
  • [x] fd_seek
  • [x] fd_sync
  • [x] fd_tell
  • [x] fd_write
  • [x] path_create_directory
  • [x] path_filestat_get
  • [x] path_filestat_set_times
  • [x] path_link
  • [x] path_open
  • [x] path_readlink
  • [x] path_remove_directory
  • [x] path_rename
  • [x] path_symlink
  • [x] path_unlink_file
  • [x] poll_oneoff (timer only)
  • [x] proc_exit
  • [ ] proc_raise
  • [x] sched_yield
  • [x] random_get
  • [ ] sock_recv
  • [ ] sock_send
  • [ ] sock_shutdown

Package Sidebar

Install

npm i @tybys/wasm-util

Weekly Downloads

637,558

Version

0.9.0

License

MIT

Unpacked Size

770 kB

Total Files

39

Last publish

Collaborators

  • toyobayashi