https://github.com/dcodeio/wapi
A minimal yet viable Web-first Wasm/JS bridge.
https://github.com/dcodeio/wapi
webassembly
Last synced: 5 months ago
JSON representation
A minimal yet viable Web-first Wasm/JS bridge.
- Host: GitHub
- URL: https://github.com/dcodeio/wapi
- Owner: dcodeIO
- Created: 2021-03-17T19:12:22.000Z (almost 5 years ago)
- Default Branch: master
- Last Pushed: 2021-03-20T04:56:26.000Z (almost 5 years ago)
- Last Synced: 2025-04-01T18:23:53.746Z (10 months ago)
- Topics: webassembly
- Language: TypeScript
- Homepage:
- Size: 3.91 KB
- Stars: 8
- Watchers: 3
- Forks: 1
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# wapi
An experiment to create a minimal yet viable Web-first Wasm/JS bridge that works today. Similar to Emscripten's `EM_ASM`, but with most glue code contained in the Wasm binary for ease of use.
## Usage
```ts
import wapi from "./index.js"
const wapiEnv = {
getString(ptr) { ... }, // compiler-specific
...
}
const module = await WebAssembly.instantiate(theModule, { wapi: wapi(wapiEnv) })
...
```
## How it works
Constructing a `wapi` environment creates an object to be imported into Wasm with two properties:
* `call`, which executes the JS code given to it from within WebAssembly while caching it for further calls and
* `env`, which is the common environment of all wapi calls
Upon construction, own properties of the initially provided `wapiEnv` (that then becomes `env`) are added to the scope of the JS code that will be executed, just as if these were globals:
```ts
// Init common environment
const wapiEnv = {
hello() { ... }
world(a) { ... }
}
WebAssembly.instantiate(theModule, { wapi: wapi(wapiEnv) })
// Within WebAssembly (pseudo-code)
wapi.call(`() => hello()`)
wapi.call(`(a) => world(a)`, a)
```
Works best with some level of compiler integration abstracting the `wapi.call`s away, but doesn't strictly require it as long as a compiler supports generating imports of the same name with multiple signatures.
## How it performs
The JS magic used has some overhead, as it looks up the cached version of the code using a branch and then calls it indirectly, per call. Experiments indicate that a `wapi.call` (just the call, the code it executes is unaffected) is about 35-50% slower than a normal import call in V8. If the code being run performs non-trivial work anyway, this overhead seems to be neglectable. Otherwise it may depend.
## How large is it
[That large](./index.js) plus compiler-specific integration, e.g. to read strings from linear memory in the respective language's string encoding.
## Building
```
npm install
npm run asbuild
```
## Testing
```
npm test
```