WebAssembly.Exception

Baseline 广泛可用 *

此功能已成熟,并可在许多设备和浏览器版本上使用。自 2022 年 5 月以来,它已在各个浏览器中可用。

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

注意:此功能在 Web Workers 中可用。

WebAssembly.Exception 对象表示从 WebAssembly 抛出到 JavaScript 的运行时异常,或者从 JavaScript 抛出到 WebAssembly 异常处理程序的异常。

构造函数接受一个WebAssembly.Tag、一个值数组和一个 options 对象作为参数。标签唯一地定义了异常的类型,包括其参数的顺序和数据类型。为了访问已抛出异常的参数,需要使用创建 Exception 时使用的相同标签。提供了方法来测试异常是否与特定标签匹配,以及按索引获取特定值(如果异常与指定的标签匹配)。

仅当关联的标签共享时,JavaScript 和其他客户端代码才能访问 WebAssembly 异常值(反之亦然)(不能仅仅使用另一个碰巧定义了相同数据类型的标签)。如果没有匹配的标签,可以捕获并重新抛出异常,但无法对其进行检查。

为了使异常抛出速度更快,从 WebAssembly 抛出的异常通常不包含堆栈跟踪。需要提供堆栈跟踪的 WebAssembly 代码必须调用 JavaScript 函数来创建异常,在构造函数中传递 options.traceStack=true 参数。然后,构造函数可能会返回一个带有附加到 stack 属性的堆栈跟踪的异常。

构造函数

WebAssembly.Exception()

创建一个新的 WebAssembly.Exception 对象。

实例方法

Exception.prototype.is()

测试异常是否与特定标签匹配。

Exception.prototype.getArg()

返回与指定标签匹配的异常的数据字段。

实例属性

Exception.prototype.stack 非标准

返回异常的堆栈跟踪,或者 undefined

示例

此示例演示了如何定义一个标签并将其导入模块,然后使用它来抛出一个在 JavaScript 中捕获的异常。

考虑以下 WebAssembly 代码,假设它已被编译为文件 example.wasm

  • 模块导入一个在内部称为 $tagname 的标签,该标签具有单个 i32 参数。该标签期望使用模块 extmod 和标签 exttag 传递该标签。
  • $throwException 函数使用 throw 指令抛出一个异常,该异常接受 $tagname 和参数。
  • 模块导出 run() 函数,该函数抛出一个值为 "42" 的异常。
wat
(module
  ;; import tag that will be referred to here as $tagname
  (import "extmod" "exttag" (tag $tagname (param i32)))

  ;; $throwException function throws i32 param as a $tagname exception
  (func $throwException (param $errorValueArg i32)
    local.get $errorValueArg
    throw $tagname
  )

  ;; Exported function "run" that calls $throwException
  (func (export "run")
    i32.const 42
    call $throwException
  )
)

下面的代码调用 WebAssembly.instantiateStreaming 来导入 example.wasm 文件,并传入一个“导入对象”(importObject),该对象包含一个名为 tagToImport 的新 WebAssembly.Tag。导入对象定义了一个属性与 WebAssembly 代码中的 import 语句匹配的对象。

文件实例化后,代码将调用导出的 WebAssembly run() 方法,该方法将立即抛出异常。

js
const tagToImport = new WebAssembly.Tag({ parameters: ["i32"] });

// Note: import object properties match the WebAssembly import statement!
const importObject = {
  extmod: {
    exttag: tagToImport,
  },
};

WebAssembly.instantiateStreaming(fetch("example.wasm"), importObject)
  .then((obj) => {
    console.log(obj.instance.exports.run());
  })
  .catch((e) => {
    console.error(e);
    // Check we have the right tag for the exception
    // If so, use getArg() to inspect it
    if (e.is(tagToImport)) {
      console.log(`getArg 0 : ${e.getArg(tagToImport, 0)}`);
    }
  });

/* Log output
example.js:40 WebAssembly.Exception: wasm exception
example.js:41 getArg 0 : 42
*/

异常使用 catch 块在 JavaScript 中捕获。我们可以看到它的类型是 WebAssembly.Exception,但如果我们没有正确的标签,我们就无法做太多其他事情。

但是,因为我们有标签,所以我们使用 Exception.prototype.is() 来检查它是否是正确的标签,并且因为它是正确的,所以我们调用 Exception.prototype.getArg() 来读取值 "42"。

规范

规范
WebAssembly JavaScript 接口:异常处理
# runtime-exceptions

浏览器兼容性

另见