WebAssembly JavaScript Interface
An effective way to learn WASM from JS (or JS from WASM) is to go through the official specification in detail.
WebAssembly JavaScript Interface defines JavaScript classes and objects for accessing WebAssembly from within JavaScript, including methods for validation, compilation, instantiation, and classes for representing and manipulating imports and exports as JavaScript objects.
Sample
WebAssembly.instantiate
chapter_wasm_js_api/sample/sample.wat
(module
(import "js" "import1" (func $i1))
(import "js" "import2" (func $i2))
(func $main (call $i1))
(start $main)
(func (export "f") (call $i2))
)
$ wat2wasm sample.wat
$ hexdump -C sample.wasm
00000000 00 61 73 6d 01 00 00 00 01 04 01 60 00 00 02 1b |.asm.......`....|
00000010 02 02 6a 73 07 69 6d 70 6f 72 74 31 00 00 02 6a |..js.import1...j|
00000020 73 07 69 6d 70 6f 72 74 32 00 00 03 03 02 00 00 |s.import2.......|
00000030 07 05 01 01 66 00 03 08 01 02 0a 0b 02 04 00 10 |....f...........|
00000040 00 0b 04 00 10 01 0b |.......|
00000047
chapter_wasm_js_api/sample/sample.js
var importObj = {
js: {
import1: () => console.log("hello,"),
import2: () => console.log("world!")
}
};
fetch('/chapter_wasm_js_api/sample/sample.wasm').then(response =>
response.arrayBuffer()
).then(buffer =>
WebAssembly.instantiate(buffer, importObj)
).then(({ module, instance }) =>
instance.exports.f()
);
The result is in console log.
WebAssembly.validate | compile | instantiate
chapter_wasm_js_api/sample/validate_compile_instantiate.js
var importObj = {
js: {
import1: () => console.log("hello,"),
import2: () => console.log("world!")
}
};
fetch('/chapter_wasm_js_api/sample/sample.wasm').then(response => {
console.log({ response });
return response.arrayBuffer();
}).then(buffer => {
console.log({ buffer });
if (WebAssembly.validate(buffer)) {
return WebAssembly.compile(buffer);
}
else {
throw 'invalid WASM';
}
}).then(module => {
console.log({ module });
return WebAssembly.instantiate(module, importObj);
}).then(instance => {
console.log({ instance });
const { exports } = instance;
const { f } = exports;
f();
}).catch((error) => {
console.error(error);
});
The result is in console log.
Async/await instantiate
chapter_wasm_js_api/sample/async_instantiate.js
(async () => {
const importObj1 = {
js: {
import1: () => console.log("From importObj1"),
import2: () => console.log("hello world!")
}
};
const importObj2 = {
js: {
import1: () => console.log("From importObj2"),
import2: () => console.log("hello world!")
}
};
const response = await fetch('/chapter_wasm_js_api/sample/sample.wasm');
console.log({ response });
const buffer = await response.arrayBuffer();
console.log({ buffer });
if (WebAssembly.validate(buffer)) {
const module = await WebAssembly.compile(buffer);
console.log({ module });
const instance1 = await WebAssembly.instantiate(module, importObj1);
instance1.exports.f();
const instance2 = await WebAssembly.instantiate(module, importObj2);
instance2.exports.f();
}
else {
console.error('invalid WASM');
}
})();
The result is in console log.