Manual Wasm instantiation with WASI Overrides
When a Wasm component depends on functionality provided by WASI, the jco transpile
produces a WebAssembly
module that can be loaded from NodeJS or the Browser that includes usages of unresolved imports like wasi:random/random
.
note
Normally, WASI imports that need to be sourced from elsewhere would be mapped, using the
--map
option to jco transpile
.
These instructions are for when mapping is insufficient or implementations must be redirected or changed at instantiation time.
A common usage of transpilation is to map the imports to a known package, like @bytecodealliance/preview2-shim
:
jco transpile \
component.wasm \
--output dist/transpiled \
--map wasi:cli/*@0.2.0=@bytecodealliance/preview2-shim/cli#*
note
For more information, see the Map Configuration section of the Transpiling documentation
Sometimes you may want to use your own implementation of WASI interfaces (whether partial or complete), known/resolved only at instantiation time.
Using custom WASI overrides during instantiation
To use custom instantiations, we start with the ability to use the default instantiations:
import { WASIShim } from "@bytecodealliance/preview2-shim/instantiation";
async function main() {
const wasmESModule = await import("path/to/transpiled/component.js");
const component = wasmESModule.instantiate(null, new WASIShim().getImportObject());
}
await main();
This is identical to mapping all imports to those provided by @bytecodealliance/preview2-shim
.
Sometimes, when using a transpiled module produced by jco
, it's necessary to override
some of the WASI imports at instantiation time rather than when transpiling the module to begin with.
import { random } from "@bytecodealliance/preview2-shim";
import { WASIShim } from "@bytecodealliance/preview2-shim/instantiation";
async function main() {
/// Load the ES module generated by `jco transpile`
const wasmESModule = await import("path/to/transpiled/component.js");
// Build a customized WASI shim by mizing custom implementations
// and the provided implementation
const customShim = new WASIShim({
random: {
// For these two interfaces we re-use the default provided shim
random: random.random,
insecure-seed: random.insecureSeed,
// For insecure, we can supply our own custom implementation
// (in this case, one that is *VERY* insecure)
insecure: {
getInsecureRandomBytes: (len) => {
return new Uint8Array(len).fill(0);
}
getInsecureRandomU64: () => 42n,
}
}
});
// Instantiate the Wasm component's ES module
const component = wasmESModule.instantiate(null, customShim);
}
await main();
Using WASIShim
, you can generate your own custom implementations of WASI, making use of the published shims where
necessary.