接下来看一下浏览器中WebAssemblyAPI的用法。
浏览器加载wasm流程
我们从上一节的getModules方法来看看wsam的加载流程
async function getModules(url, imports = {}) {
const data = await fetch(url);
const arrayBuffer = await data.arrayBuffer()
const module = await WebAssembly.compile(arrayBuffer);
return WebAssembly.instantiate(module, imports);
}
可以看到,加载wsam分为三步:
-
从网络上获取wasm文件,并将数据转换成ArrayBuffer(注意:wsam获取严格遵循同源策略)
-
将ArrayBuffer二进制码编译成浏览器Module
-
最后实例化编译出来的Module

接下来从编译所需要的API来详细说明一下编译的流程。
WebAssembly编译
1.compile
WebAssembly.compile的作用就是将从网络获取回来的wsam二进制码编译成Module,它只接收一个byte的参数。
WebAssembly.compile(bytes)
2.instantiate & Instance
instantiate 和 Instance 都是可以实例化模块,方法接收两个参数:Module和imports
const moduleA = WebAssembly.instantiate(module, imports);
const moduleB = new WebAssembly.Instance(module, imports);
- Module: 从
WebAssymbly.compile编译出来的模块。
- imports: 这个模块需要引入的函数,imports非常重要,这个关乎到我们的Module能不能正常编译成功。
再来写一个需要分配内存的方法
#include <stdlib.h>
#include <string.h>
char *helloworld()
{
char* c = (char *)malloc(14);
strcpy(c, "hello world\n");
return c;
}

可以看到,编译到wat后会出现import "env" "malloc"的代码。这些模块是需要我们在实例化时的imports导入的,如果在实例化中没有import这些模块,则会抛出异常。
const mem = new WenAssembly.Memory({
initial: 100,
})
const module = WebAssembly.instantiate(module, {
env: {
malloc: () => {},
memory: mem,
}
})
那么,我们又该如何找到这些模块呢?
对于这些公共模块,我们可以通过CDN找到,比如malloc模块就在memory模块中能找到。
3. instantiateStreaming
instantiateStreaming方法是toArrayBuffer,compile和instantiate的集合,一个方法就包含这三步
const module = WebAssembly.instantiateStreaming(fetch('xxx.wsam'), imports);
4.Memory
Memory用于表示编译模块使用的堆,在JS中他是一种可调整大小的ArrayBuffer的形式存在的。上文中也可以看到,在声明一个模块都需要import一个内存实例到模块中。
const mem = new WebAssembly.Memory({
initial: 1,
maximum: 100,
share: true,
})
initial,maximum内存的单位是WebAssembly pages,固定每页是64KB。最大可支持6.4MB
参考
- WebAssembly
- MDN