WebAssembly.instantiate()

Baseline 广泛可用 *

此功能已非常成熟,可在多种设备和浏览器版本上使用。自 2017 年 10 月以来,它已在各大浏览器中可用。

* 此特性的某些部分可能存在不同级别的支持。

WebAssembly.instantiate() 静态方法允许您编译和实例化 WebAssembly 代码。此函数有两个重载。

  • 主要重载接收 WebAssembly 二进制代码,形式为 类型化数组ArrayBuffer,并在一个步骤中执行编译和实例化。返回的 Promise 会解析为一个已编译的 WebAssembly.Module 和它的第一个 WebAssembly.Instance
  • 次要重载接收一个已编译的 WebAssembly.Module,并返回一个解析为该 ModuleInstancePromise。如果 Module 已经被编译,则此重载很有用。

警告: 此方法不是获取和实例化 Wasm 模块的最有效方式。如果可能,您应该使用新的 WebAssembly.instantiateStreaming() 方法,该方法直接从原始字节码获取、编译和实例化模块,因此不需要转换为 ArrayBuffer

语法

js
// Taking Wasm binary code
WebAssembly.instantiate(bufferSource)
WebAssembly.instantiate(bufferSource, importObject)
WebAssembly.instantiate(bufferSource, importObject, compileOptions)

// Taking a module object instance
WebAssembly.instantiate(module)
WebAssembly.instantiate(module, importObject)
WebAssembly.instantiate(module, importObject, compileOptions)

参数

bufferSource

包含您要编译的 Wasm 模块的二进制代码的 类型化数组ArrayBuffer

模块

要实例化的 WebAssembly.Module 对象。

importObject 可选

一个对象,包含要导入到新创建的 Instance 中的值,例如函数或 WebAssembly.Memory 对象。对于已编译模块声明的每个导入,都必须有一个匹配的属性,否则将抛出 WebAssembly.LinkError

compileOptions 可选

一个包含编译选项的对象。属性可以包括:

builtins 可选

一个字符串数组,用于启用在已编译的 Wasm 模块中使用 JavaScript 内置函数。这些字符串定义了您要启用的内置函数。目前唯一可用的值是 "js-string",它启用 JavaScript 字符串内置函数。

importedStringConstants 可选

一个字符串,指定 导入的全局字符串常量 的命名空间。如果您希望在 Wasm 模块中使用导入的全局字符串常量,则需要指定此属性。

返回值

如果传递了 bufferSource,则返回一个 Promise,该 Promise 解析为一个 ResultObject,其中包含两个字段:

如果传递了 module,则返回一个 Promise,该 Promise 解析为一个 WebAssembly.Instance 对象。

异常

示例

注意:在大多数情况下,您可能希望使用 WebAssembly.instantiateStreaming(),因为它比 instantiate() 更高效。

第一个重载示例

使用 fetch 获取一些 WebAssembly 字节码后,我们使用 WebAssembly.instantiate() 函数编译和实例化模块,同时将 JavaScript 函数导入到 WebAssembly 模块中。然后,我们调用由 Instance 导出的导出的 WebAssembly 函数

js
const importObject = {
  my_namespace: {
    imported_func(arg) {
      console.log(arg);
    },
  },
};

fetch("simple.wasm")
  .then((response) => response.arrayBuffer())
  .then((bytes) => WebAssembly.instantiate(bytes, importObject))
  .then((result) => result.instance.exports.exported_func());

注意:您也可以在 GitHub 上的 index.html 中找到此示例(也可以在线查看)。

第二个重载示例

以下示例(请参阅 GitHub 上的 index-compile.html 演示,同样也可以在线查看)使用 WebAssembly.compileStreaming() 方法编译加载的 simple.wasm 字节码,然后使用 postMessage() 将其发送到 worker

js
const worker = new Worker("wasm_worker.js");

WebAssembly.compileStreaming(fetch("simple.wasm")).then((mod) =>
  worker.postMessage(mod),
);

在 worker 中(请参阅 wasm_worker.js),我们为模块定义了一个导入对象,然后设置一个事件处理程序以接收主线程发送过来的模块。收到模块后,我们使用 WebAssembly.instantiate() 方法从中创建一个实例,并调用其中导出的一个函数。

js
const importObject = {
  my_namespace: {
    imported_func(arg) {
      console.log(arg);
    },
  },
};

onmessage = (e) => {
  console.log("module received from main thread");
  const mod = e.data;

  WebAssembly.instantiate(mod, importObject).then((instance) => {
    instance.exports.exported_func();
  });
};

启用 JavaScript 内置函数和全局字符串导入

此示例在使用 instantiate() 编译和实例化 Wasm 模块时,启用了 JavaScript 字符串内置函数和导入的全局字符串常量,然后运行导出的 main() 函数(该函数会将 "hello world!" 记录到控制台)。在线查看示例效果

js
const importObject = {
  // Regular import
  m: {
    log: console.log,
  },
};

const compileOptions = {
  builtins: ["js-string"], // Enable JavaScript string builtins
  importedStringConstants: "string_constants", // Enable imported global string constants
};

fetch("log-concat.wasm")
  .then((response) => response.arrayBuffer())
  .then((bytes) => WebAssembly.instantiate(bytes, importObject, compileOptions))
  .then((result) => result.instance.exports.main());

规范

规范
WebAssembly JavaScript 接口
# dom-webassembly-instantiate

浏览器兼容性

另见