WebAssembly JavaScript 接口

编辑草案

有关此文档的更多详细信息
此版本
https://github.webassembly.net.cn/spec/js-api/
最新发布版本
https://www.w3.org/TR/wasm-js-api-2/
实施报告
https://webassembly.net.cn/features/
反馈
GitHub
规范内联
编辑
Ms2ger (Igalia)
问题跟踪
GitHub 问题

摘要

本文档提供了一个显式的 JavaScript API 用于与 WebAssembly 交互。

这是相关文档集合的一部分:WebAssembly 核心规范WebAssembly JS 接口WebAssembly Web API

本文档的状态

这是一个公开的编辑草案副本。它仅供讨论,可能会随时更改。在此发布并不意味着 W3C 对其内容的认可。不要引用本文档,除非是作为正在进行的工作。

GitHub 问题 是讨论此规范的首选方式。所有问题和评论均已存档

本文档由WebAssembly 工作组 编制。

本文档由一个根据W3C 专利政策运作的小组编制。W3C 维护着与该小组交付成果相关的任何专利公开的公开列表;该页面还包含公开专利的说明。任何了解一项专利,并且认为该专利包含必要权利要求的个人,必须根据W3C 专利政策第 6 节披露相关信息。

本文档受2023 年 11 月 3 日 W3C 流程文档 的约束。

此 API 提供了一种通过桥接 JavaScript [ECMASCRIPT] 来访问 WebAssembly [WEBASSEMBLY] 的方式,以显式地从 JavaScript 构造模块。

1. 示例 API 用法

本节为非规范性内容。

给定 demo.wat(编码为 demo.wasm

(module
    (import "js" "import1" (func $i1))
    (import "js" "import2" (func $i2))
    (func $main (call $i1))
    (start $main)
    (func (export "f") (call $i2))
)

以及以下在浏览器中运行的 JavaScript 代码

var importObj = {js: {
    import1: () => console.log("hello,"),
    import2: () => console.log("world!")
}};
fetch('demo.wasm').then(response =>
    response.arrayBuffer()
).then(buffer =>
    WebAssembly.instantiate(buffer, importObj)
).then(({module, instance}) =>
    instance.exports.f()
);

2. 符号

此规范依赖于 Infra 标准。 [INFRA]

WebAssembly 序列 类型等效于此处定义的 列表 类型;一种的值被透明地视为另一种的值。

3. 内部存储

3.1. WebAssembly 存储与 JavaScript 的交互

注意: WebAssembly 语义是根据一个抽象的 存储 来定义的,该存储表示 WebAssembly 抽象机的状态。WebAssembly 操作接受一个存储,并返回一个更新后的存储。

每个 代理 都有一个 关联存储。当创建一个新代理时,其关联存储被设置为 store_init() 的结果。

注意: 在此规范中,任何与 WebAssembly 相关的对象、内存或地址都不能在 代理集群 中的代理之间共享。在 WebAssembly 的未来版本中,这可能会发生变化。

WebAssembly 存储的元素可以使用 JavaScript 值 标识。特别是,每个具有对应 Memory 对象的 WebAssembly 内存实例 都使用 JavaScript 数据块 标识;对该数据块的修改被标识为将代理的存储更新为反映这些更改的存储,反之亦然。

3.2. WebAssembly JS 对象缓存

注意: 有几个 WebAssembly 对象可能具有对应的 JavaScript 对象。这种对应关系存储在每个代理的映射中,该映射从 WebAssembly 地址 映射到 JavaScript 对象。此映射用于确保对于给定的 代理,特定 WebAssembly 地址最多存在一个 JavaScript 对象。但是,此属性不适用于共享对象。

每个 代理 都与以下 有序映射 相关联

4. WebAssembly 命名空间

dictionary WebAssemblyInstantiatedSource {
    required Module module;
    required Instance instance;
};

[Exposed=*]
namespace WebAssembly {
    boolean validate(BufferSource bytes);
    Promise<Module> compile(BufferSource bytes);

    Promise<WebAssemblyInstantiatedSource> instantiate(
        BufferSource bytes, optional object importObject);

    Promise<Instance> instantiate(
        Module moduleObject, optional object importObject);
};
编译 WebAssembly 模块,需要执行以下步骤,并使用源字节 bytes 作为参数。
  1. module 设置为 module_decode(bytes)。如果 module错误,则返回 错误

  2. 如果 module_validate(module) 是 错误,则返回 错误

  3. 返回 module

当调用 validate(bytes) 方法时,它将执行以下步骤。
  1. stableBytes 设置为 缓冲区 bytes 所持字节的副本

  2. stableBytes 编译 为 WebAssembly 模块,并将结果存储为 module

  3. 如果 module错误,则返回 false。

  4. 返回 true。

Module 对象表示单个 WebAssembly 模块。每个 Module 对象都有以下内部槽位。

构造一个 WebAssembly 模块对象,需要执行以下步骤,并使用模块 module 和源字节 bytes 作为参数。
  1. moduleObject 设置为一个新的 Module 对象。

  2. moduleObject.[[Module]] 设置为 module

  3. moduleObject.[[Bytes]] 设置为 bytes

  4. 返回 moduleObject

异步编译 WebAssembly 模块 从源字节 bytes,使用可选的 任务来源 taskSource,执行以下步骤
  1. promise一个新的 promise

  2. 运行以下步骤 并行

    1. 编译 WebAssembly 模块 bytes 并将结果存储为 module

    2. 排队一个任务 来执行以下步骤。如果 taskSource 被提供,则在该任务源上排队任务。

      1. 如果 module错误,则拒绝 promise 并带有 CompileError 异常。

      2. 否则,

        1. 构造一个 WebAssembly 模块对象modulebytes,并设 moduleObject 为结果。

        2. 解析 promisemoduleObject

  3. 返回 promise

The compile(bytes) 方法,当被调用时,执行以下步骤
  1. stableBytes缓冲区 bytes 持有的字节的副本

  2. 异步编译 WebAssembly 模块stableBytes 并返回结果。

读取 WebAssembly 模块 module 的导入 从导入对象 importObject,执行以下步骤
  1. 如果 module.导入 不是空的,并且 importObject 是未定义的,则抛出 TypeError 异常。

  2. imports 为 « »。

  3. 对于每个 (moduleName, componentName, externtype) 的 module_imports(module),

    1. o? Get(importObject, moduleName)。

    2. 如果 Type(o) 不是 Object,则抛出 TypeError 异常。

    3. v? Get(o, componentName)。

    4. 如果 externtype 形式为 func functype

      1. 如果 IsCallable(v) 为 false,则抛出 LinkError 异常。

      2. 如果 v 具有 [[FunctionAddress]] 内部槽,因此是 导出的函数

        1. funcaddrv 的 [[FunctionAddress]] 内部槽的值。

      3. 否则,

        1. 创建一个宿主函数vfunctype,并设 funcaddr 为结果。

        2. indeximports 中的外部函数数量。此值 index 被称为 宿主函数 funcaddr 的索引

      4. externfunc外部值 func funcaddr

      5. 追加 externfuncimports

    5. 如果 externtype 形式为 global mut valtype

      1. 如果 Type(v) 是 Number 或 BigInt,

        1. 如果 valtypei64 并且 Type(v) 是 Number,

          1. 抛出 LinkError 异常。

        2. 如果 valtype 不是 i64 并且 Type(v) 是 BigInt,

          1. 抛出 LinkError 异常。

        3. 如果 valtypev128

          1. 抛出 LinkError 异常。

        4. valueToWebAssemblyValue(v, valtype)。

        5. store周围代理关联存储

        6. 设 (store, globaladdr) 为 global_alloc(store, const valtype, value)。

        7. 周围代理关联存储 设置为 store

      2. 否则,如果 v 实现 Global

        1. globaladdrv.[[Global]]。

      3. 否则,

        1. 抛出 LinkError 异常。

      4. externglobalglobal globaladdr

      5. 追加 externglobalimports

    6. 如果 externtype 形式为 mem memtype

      1. 如果 v实现 Memory,则抛出 LinkError 异常。

      2. externmem外部值 mem v.[[Memory]]。

      3. 追加 externmemimports

    7. 如果 externtype 形式为 table tabletype

      1. 如果 v实现 Table,则抛出 LinkError 异常。

      2. tableaddrv.[[Table]]。

      3. externtable外部值 table tableaddr

      4. 追加 externtableimports

  4. 返回 imports

注意: 此算法仅验证传递了正确类型的 JavaScript 值。WebAssembly 类型要求的验证被推迟到 “实例化 WebAssembly 模块的核心” 算法中。

创建一个导出对象 从 WebAssembly 模块 module 和实例 instance,执行以下步骤
  1. exportsObject! OrdinaryObjectCreate(null)。

  2. 对于每个 (name, externtype) 的 module_exports(module),

    1. externvalinstance_export(instance, name)。

    2. 断言:externval 不是 错误

    3. 如果 externtype 形式为 func functype

      1. 断言:externval 形式为 func funcaddr

      2. func funcaddrexternval

      3. func 为从 funcaddr 创建 一个新的导出函数 的结果。

      4. valuefunc

    4. 如果 externtype 形式为 global mut globaltype

      1. 断言:externval 形式为 global globaladdr

      2. global globaladdrexternval

      3. globalglobaladdr 创建一个新的全局对象

      4. valueglobal

    5. 如果 externtype 形式为 mem memtype

      1. 断言:externval 形式为 mem memaddr

      2. mem memaddrexternval

      3. memorymemaddr 创建一个新的内存对象

      4. valuememory

    6. 如果 externtype 形式为 table tabletype

      1. 断言: externval 的形式为 table tableaddr

      2. table tableaddrexternval

      3. table一个从 tableaddr 创建的新 Table 对象

      4. valuetable

    7. status! CreateDataProperty(exportsObject, name, value).

    8. 断言: status 为 true。

    注意:WebAssembly 模块验证 期间执行的有效性和唯一性检查确保每个属性名称有效并且没有属性定义两次。

  3. 执行 ! SetIntegrityLevel(exportsObject, "frozen")。

  4. 返回 exportsObject

初始化一个实例对象 instanceObject 从一个 WebAssembly 模块 module 和实例 instance, 执行以下步骤
  1. 创建一个导出对象moduleinstance 并且令 exportsObject 为结果。

  2. 设置 instanceObject.[[Instance]] 为 instance

  3. 设置 instanceObject.[[Exports]] 为 exportsObject

实例化 WebAssembly 模块的核心 从一个模块 module 和导入 imports, 执行以下步骤
  1. store周围代理关联存储

  2. resultmodule_instantiate(store, module, imports).

  3. 如果 resulterror, 抛出一个合适的异常类型

    • 一个 LinkError 异常用于在链接期间发生的多数情况。

    • 如果错误是在运行启动函数时出现的,则抛出一个 RuntimeError 用于从 WebAssembly 发生的多数错误,或者从内部 ECMAScript 代码传播的错误对象。

    • 另一种错误类型(如果合适),例如内存不足异常,如 WebAssembly 错误映射 中所述。

  4. 令 (store, instance) 为 result

  5. 设置 周围代理关联存储store

  6. 返回 instance

异步实例化一个 WebAssembly 模块 从一个 Module moduleObject 和导入 importObject, 执行以下步骤
  1. promise一个新的 Promise

  2. modulemoduleObject.[[Module]]。

  3. 读取导入module 与导入 importObject, 并且令 imports 为结果。如果此操作抛出异常,则捕获它,拒绝 promise 使用异常,并返回 promise

  4. 并行 方式运行以下步骤

    1. 排队一个任务 以执行以下步骤: 注意: 这里可以执行实现特定的工作。

      1. 实例化 WebAssembly 模块的核心 moduleimports, 并且令 instance 为结果。如果此操作抛出异常,则捕获它,拒绝 promise 使用异常,并终止这些子步骤。

      2. instanceObject 为一个 新的 Instance

      3. 初始化 instanceObjectmoduleinstance. 如果此操作抛出异常,则捕获它,拒绝 promise 使用异常,并终止这些子步骤。

      4. 完成 promise 使用 instanceObject

  5. 返回 promise

实例化一个模块的 Promise promiseOfModule 与导入 importObject, 执行以下步骤
  1. promise一个新的 Promise

  2. 在完成 promiseOfModule 使用值 module

    1. 实例化 WebAssembly 模块 module 导入 importObject, 并且令 innerPromise 为结果。

    2. 在完成 innerPromise 使用值 instance.

      1. resultWebAssemblyInstantiatedSource 值 «[ "module" → module, "instance" → instance ]»。

      2. 完成 promise 使用 result

    3. 在拒绝 innerPromise 使用原因 reason

      1. 拒绝 promise 使用 reason

  3. 在拒绝 promiseOfModule 使用原因 reason

    1. 拒绝 promise 使用 reason

  4. 返回 promise

instantiate(bytes, importObject) 方法,当被调用时,执行以下步骤
  1. stableBytes缓冲区 bytes 所持有的字节的副本

  2. 异步编译一个 WebAssembly 模块stableBytes 并且令 promiseOfModule 为结果。

  3. 实例化 promiseOfModule 与导入 importObject 并且返回结果。

instantiate(moduleObject, importObject) 方法,当被调用时,执行以下步骤
  1. 异步实例化 WebAssembly 模块 moduleObject 导入 importObject, 并且返回结果。

注意: 连续的流式 API 在 WebAssembly Web API 中有说明。

4.1. 模块

enum ImportExportKind {
  "function",
  "table",
  "memory",
  "global"
};

dictionary ModuleExportDescriptor {
  required USVString name;
  required ImportExportKind kind;
  // Note: Other fields such as signature may be added in the future.
};

dictionary ModuleImportDescriptor {
  required USVString module;
  required USVString name;
  required ImportExportKind kind;
};

[LegacyNamespace=WebAssembly, Exposed=*]
interface Module {
  constructor(BufferSource bytes);
  static sequence<ModuleExportDescriptor> exports(Module moduleObject);
  static sequence<ModuleImportDescriptor> imports(Module moduleObject);
  static sequence<ArrayBuffer> customSections(Module moduleObject, DOMString sectionName);
};
外部类型的字符串值 type
exports(moduleObject) 方法,当被调用时,执行以下步骤
  1. modulemoduleObject.[[Module]]。

  2. exports 为 « »。

  3. 对于每个 (name, type) 的 module_exports(module),

    1. kind外部类型的字符串值 type

    2. obj 为 «[ "name" → name, "kind" → kind ]»。

    3. 追加 objexports

  4. 返回 exports

imports(moduleObject) 方法,当被调用时,执行以下步骤
  1. modulemoduleObject.[[Module]]。

  2. imports 为 « »。

  3. 对于每个 (moduleName, name, type) 的 module_imports(module),

    1. kind外部类型的字符串值 type

    2. obj 为 «[ "module" → moduleName, "name" → name, "kind" → kind ]»。

    3. 追加 objimports

  4. 返回 imports

customSections(moduleObject, sectionName) 方法,当被调用时,执行以下步骤
  1. bytesmoduleObject.[[Bytes]]。

  2. customSections 为 « »。

  3. 对于每个 自定义节 customSectionbytes, 根据 模块语法 解释,

    1. namecustomSectionname, 以 UTF-8 解码

    2. 断言: name 不是失败 (moduleObject.[[Module]] 为 有效).

    3. 如果 name 等于 sectionName 作为字符串值,

      1. 追加 一个新的 ArrayBuffer 包含 bytes 中字节的副本,用于此 customsec 产生式所匹配的范围到 customSections

  4. 返回 customSections

Module(bytes) 构造函数被调用时,执行以下步骤:
  1. stableBytes 为缓冲区 bytes 所持有的字节的副本

  2. 编译 WebAssembly 模块 stableBytes 并将结果存储为 module

  3. 如果 module错误,则抛出CompileError 异常。

  4. this.[[Module]] 设置为 module

  5. this.[[Bytes]] 设置为 stableBytes

注意: 一些实现对 bytes 的大小有限制。建议使用异步 API 而不是此 API。

4.2. 实例

[LegacyNamespace=WebAssembly, Exposed=*]
interface Instance {
  constructor(Module module, optional object importObject);
  readonly attribute object exports;
};
Instance(module, importObject) 构造函数被调用时,执行以下步骤:
  1. modulemodule.[[Module]]。

  2. 读取 module 的导入,导入为 importObject,并将结果设为 imports

  3. 实例化 WebAssembly 模块 module 的核心,导入为 imports,并将结果设为 instance

  4. 初始化 this,模块为 module,实例为 instance

注意: 不建议使用此同步 API,因为一些实现有时在实例化时会进行长时间的编译工作。

Instanceexports 属性的 getter 返回 this.[[Exports]]。

4.3. 内存

dictionary MemoryDescriptor {
  required [EnforceRange] unsigned long initial;
  [EnforceRange] unsigned long maximum;
};

[LegacyNamespace=WebAssembly, Exposed=*]
interface Memory {
  constructor(MemoryDescriptor descriptor);
  unsigned long grow([EnforceRange] unsigned long delta);
  ArrayBuffer toFixedLengthBuffer();
  ArrayBuffer toResizableBuffer();
  readonly attribute ArrayBuffer buffer;
};

一个 Memory 对象表示一个内存实例,多个 Instance 对象可以同时引用该实例。每个 Memory 对象具有以下内部槽位:

从内存地址 memaddr 创建一个固定长度的内存缓冲区,执行以下步骤:
  1. block 为一个数据块,该数据块 memaddr 的底层内存对应

  2. buffer 为一个具有内部槽位 [[ArrayBufferData]]、[[ArrayBufferByteLength]] 和 [[ArrayBufferDetachKey]] 的新的 ArrayBuffer

  3. buffer.[[ArrayBufferData]] 设置为 block

  4. buffer.[[ArrayBufferByteLength]] 设置为 block 的长度。

  5. buffer.[[ArrayBufferDetachKey]] 设置为 "WebAssembly.Memory"。

  6. 返回 buffer

从内存地址 memaddrmaxsize 创建一个可调整大小的内存缓冲区,执行以下步骤:
  1. block 为一个数据块,该数据块 memaddr 的底层内存对应

  2. lengthblock 的长度。

  3. 如果 maxsize > (65536 × 65536),

    1. 抛出RangeError 异常。

  4. buffer 为一个具有内部槽位 [[ArrayBufferData]]、[[ArrayBufferByteLength]]、[[ArrayBufferMaxByteLength]] 和 [[ArrayBufferDetachKey]] 的新的 ArrayBuffer

  5. buffer.[[ArrayBufferData]] 设置为 block

  6. buffer.[[ArrayBufferByteLength]] 设置为 length

  7. buffer.[[ArrayBufferMaxByteLength]] 设置为 maxsize

  8. buffer.[[ArrayBufferDetachKey]] 设置为 "WebAssembly.Memory"。

  9. 返回 buffer

从内存地址 memaddr 初始化内存对象 memory,执行以下步骤:
  1. map周围代理 的关联内存对象缓存

  2. 断言:map[memaddr] 不存在

  3. buffermemaddr 创建固定长度内存缓冲区 的结果。

  4. memory.[[Memory]] 设置为 memaddr

  5. memory.[[BufferObject]] 设置为 buffer

  6. 设置 map[memaddr] 为 memory

从内存地址 memaddr 创建一个内存对象,执行以下步骤:
  1. map周围代理 的关联内存对象缓存

  2. 如果 map[memaddr] 存在

    1. 返回 map[memaddr]。

  3. memory 为一个新的 Memory

  4. 初始化 memory,内存地址为 memaddr

  5. 返回 memory

Memory(descriptor) 构造函数被调用时,执行以下步骤:
  1. initialdescriptor["initial"]。

  2. 如果 descriptor["maximum"] 存在,则令 maximumdescriptor["maximum"];否则,令 maximum 为空。

  3. 如果 maximum 不为空且 maximum < initial,则抛出RangeError 异常。

  4. memtype 为 { min initial, max maximum }。

  5. store周围代理关联存储

  6. 令 (store, memaddr) 为mem_alloc(store, memtype)。如果分配失败,则抛出RangeError 异常。

  7. 周围代理关联存储 设置为 store

  8. 初始化 this,内存地址为 memaddr

刷新 memaddr 的内存缓冲区,执行以下步骤:
  1. map周围代理 的关联内存对象缓存

  2. 断言:map[memaddr] 存在

  3. memorymap[memaddr]。

  4. buffermemory.[[BufferObject]]。

  5. 如果IsFixedLengthArrayBuffer(buffer) 为 true,

    1. 执行! DetachArrayBuffer(buffer, "WebAssembly.Memory")。

    2. buffermemaddr 创建固定长度内存缓冲区 的结果。

    3. memory.[[BufferObject]] 设置为 buffer

  6. 否则,

    1. block 为一个数据块,该数据块 memaddr 的底层内存对应

    2. buffer.[[ArrayBufferData]] 设置为 block

    3. buffer.[[ArrayBufferByteLength]] 设置为 block 的长度。

将与内存地址 memaddr 关联的内存缓冲区增大 delta,执行以下步骤:
  1. store周围代理关联存储

  2. retmem_size(store, memaddr)。

  3. storemem_grow(store, memaddr, delta)。

  4. 如果 store错误,则抛出RangeError 异常。

  5. 周围代理关联存储 设置为 store

  6. 刷新 memaddr 的内存缓冲区。

  7. 返回 ret

grow(delta) 方法被调用时,执行以下步骤:
  1. memaddrthis.[[Memory]]。

  2. 返回将与 memaddr 关联的内存缓冲区增大 delta 的结果。

在 WebAssembly memory.grow 指令执行后立即执行以下步骤:

  1. 如果栈顶不是i32.const (−1),

    1. frame当前帧

    2. 断言:由于验证,frame.module.memaddrs[0] 存在。

    3. memaddr 为内存地址 frame.module.memaddrs[0]。

    4. 刷新 memaddr 的内存缓冲区。

toFixedLengthBuffer() 方法在被调用时执行以下步骤
  1. bufferthis.[[BufferObject]]。

  2. 如果 IsFixedLengthArrayBuffer(buffer) 为 true,则返回 buffer

  3. memaddrthis.[[Memory]]。

  4. fixedBuffermemaddr 创建固定长度内存缓冲区 的结果。

  5. 执行 ! DetachArrayBuffer(buffer, "WebAssembly.Memory")。

  6. this.[[BufferObject]] 设置为 fixedBuffer

  7. 返回 fixedBuffer

toResizableBuffer() 方法在被调用时执行以下步骤
  1. bufferthis.[[BufferObject]]。

  2. 如果 IsFixedLengthArrayBuffer(buffer) 为 false,则返回 buffer

  3. memaddrthis.[[Memory]]。

  4. store周围代理关联存储

  5. memtypemem_type(store, memaddr)。

  6. 如果 memtype 有最大值,

    1. maxsizememtype 中的最大值。

  7. 否则,

    1. maxsize 为 65536 × 65536。

  8. resizableBuffermemaddrmaxsize 创建可调整大小的内存缓冲区 的结果。

  9. 执行 ! DetachArrayBuffer(buffer, "WebAssembly.Memory")。

  10. this.[[BufferObject]] 设置为 resizableBuffer

  11. 返回 resizableBuffer

ArrayBuffer 对象由 Memory 对象返回,其大小必须是 WebAssembly 页面大小(常量 65536)的倍数。因此,HostResizeArrayBuffer 被重新定义如下。

抽象操作 HostResizeArrayBuffer 接受参数 buffer(一个 ArrayBuffer)和 newLength。在被调用时,它执行以下步骤。

  1. 如果 buffer.[[ArrayBufferDetachKey]] 为 "WebAssembly.Memory",

    1. map周围代理 的关联 内存对象缓存

    2. 断言:buffermap 中恰好一个值的 [[BufferObject]]。

    3. 对于 map 中的每个 memaddrmem

      1. 如果 SameValue(mem.[[BufferObject]], buffer) 为 true,

        1. 断言:buffer.[[ArrayBufferByteLength]] 模 65536 为 0。

        2. lengthDeltanewLength - buffer.[[ArrayBufferByteLength]]。

        3. 如果 lengthDelta < 0 或 lengthDelta 模 65536 不为 0,

          1. 抛出一个 RangeError 异常。

        4. deltalengthDelta ÷ 65536。

        5. 增长memaddr 关联的内存缓冲区,增长 delta 个页面。

    4. 返回handled.

  2. 否则,返回unhandled.

Memorybuffer 属性的 getter 返回 this.[[BufferObject]]。

4.4. 表格

enum TableKind {
  "externref",
  "anyfunc",
  // Note: More values may be added in future iterations,
  // e.g., typed function references, typed GC references
};

dictionary TableDescriptor {
  required TableKind element;
  required [EnforceRange] unsigned long initial;
  [EnforceRange] unsigned long maximum;
};

[LegacyNamespace=WebAssembly, Exposed=*]
interface Table {
  constructor(TableDescriptor descriptor, optional any value);
  unsigned long grow([EnforceRange] unsigned long delta, optional any value);
  any get([EnforceRange] unsigned long index);
  undefined set([EnforceRange] unsigned long index, optional any value);
  readonly attribute unsigned long length;
};

一个 Table 对象表示一个单一的 表格实例,它可以被多个 Instance 对象同时引用。每个 Table 对象都有一个 [[Table]] 内部槽,它是一个 表格地址

初始化表格地址 tableaddr 创建的表格对象 table,执行以下步骤
  1. map周围代理 的关联 表格对象缓存

  2. 断言:map[tableaddr] 不存在

  3. table.[[Table]] 设置为 tableaddr

  4. 设置 map[tableaddr] 为 table

创建表格地址 tableaddr 创建的表格对象,执行以下步骤
  1. map周围代理 的关联 表格对象缓存

  2. 如果 map[tableaddr] 存在

    1. 返回 map[tableaddr]。

  3. table 为一个 新的 Table

  4. 初始化 table,从 tableaddr 开始。

  5. 返回 table

Table(descriptor, value) 构造函数在被调用时执行以下步骤
  1. elementTypeToValueType(descriptor["element"])。

  2. 如果 elementType 不是一个 reftype

    1. 抛出一个 TypeError 异常。

  3. initialdescriptor["initial"]。

  4. 如果 descriptor["maximum"] 存在,则令 maximumdescriptor["maximum"];否则,令 maximum 为空。

  5. 如果 maximum 不为空且 maximum < initial,则抛出一个 RangeError 异常。

  6. 如果 value 缺失,

    1. refDefaultValue(elementType)。

  7. 否则,

    1. ref? ToWebAssemblyValue(value, elementType)。

  8. type表格类型 {min initial, max maximum} elementType

  9. store周围代理关联存储

  10. 令 (store, tableaddr) 为 table_alloc(store, type, ref)。

  11. 周围代理关联存储 设置为 store

  12. 初始化 this,从 tableaddr 开始。

grow(delta, value) 方法在被调用时执行以下步骤
  1. tableaddrthis.[[Table]]。

  2. store周围代理关联存储

  3. initialSizetable_size(store, tableaddr)。

  4. 令 (limits, elementType) 为 table_type(tableaddr)。

  5. 如果 value 缺失,

    1. refDefaultValue(elementType)。

  6. 否则,

    1. ref? ToWebAssemblyValue(value, elementType)。

  7. resulttable_grow(store, tableaddr, delta, ref)。

  8. 如果 resulterror,则抛出一个 RangeError 异常。

    注意: 上述异常可能是由于内存不足或大小参数无效导致的。

  9. 周围代理关联存储 设置为 result

  10. 返回 initialSize

Tablelength 属性的 getter 在被调用时执行以下步骤
  1. tableaddrthis.[[Table]]。

  2. store周围代理关联存储

  3. 返回 table_size(store, tableaddr)。

当调用 get(index) 方法时,执行以下步骤
  1. tableaddrthis.[[Table]]。

  2. store周围代理关联存储

  3. resulttable_read(store, tableaddr, index)。

  4. 如果 result错误,则抛出 RangeError 异常。

  5. 返回 ToJSValue(result)。

当调用 set(index, value) 方法时,执行以下步骤
  1. tableaddrthis.[[Table]]。

  2. 令 (limits, elementType) 为 table_type(tableaddr)。

  3. 如果 value 缺失,

    1. refDefaultValue(elementType)。

  4. 否则,

    1. ref? ToWebAssemblyValue(value, elementType)。

  5. store周围代理关联存储

  6. storetable_write(store, tableaddr, index, ref)。

  7. 如果 store错误,则抛出 RangeError 异常。

  8. 周围代理关联存储 设置为 store

4.5. 全局变量

enum ValueType {
  "i32",
  "i64",
  "f32",
  "f64",
  "v128",
  "externref",
  "anyfunc",
};

注意: 这种类型可能会在 WebAssembly 的未来版本中添加更多案例。

dictionary GlobalDescriptor {
  required ValueType value;
  boolean mutable = false;
};

[LegacyNamespace=WebAssembly, Exposed=*]
interface Global {
  constructor(GlobalDescriptor descriptor, optional any v);
  any valueOf();
  attribute any value;
};

一个 Global 对象表示单个 全局实例,它可以被多个 Instance 对象同时引用。每个 Global 对象有一个内部槽位

为了 初始化一个全局对象 global 来自一个 全局地址 globaladdr,执行以下步骤
  1. map周围代理 的关联 全局对象缓存

  2. 断言:map[globaladdr] 不 存在

  3. global.[[Global]] 设置为 globaladdr

  4. 设置 map[globaladdr] 为 global

为了 创建一个全局对象 来自一个 全局地址 globaladdr,执行以下步骤
  1. map周围代理 的关联 全局对象缓存

  2. 如果 map[globaladdr] 存在

    1. 返回 map[globaladdr]。

  3. global 为一个 新的 Global

  4. 初始化 global 来自 globaladdr

  5. 返回 global

算法 ToValueType(s) 执行以下步骤
  1. 如果 s 等于 "i32",返回 i32

  2. 如果 s 等于 "i64",返回 i64

  3. 如果 s 等于 "f32",返回 f32

  4. 如果 s 等于 "f64",返回 f64

  5. 如果 s 等于 "v128",返回 v128

  6. 如果 s 等于 "anyfunc",返回 funcref

  7. 如果 s 等于 "externref",返回 externref

  8. 断言:此步骤不会被执行。

算法 DefaultValue(valuetype) 执行以下步骤
  1. 如果 valuetype 等于 i32,返回 i32.const 0。

  2. 如果 valuetype 等于 i64,返回 i64.const 0。

  3. 如果 valuetype 等于 f32,返回 f32.const 0。

  4. 如果 valuetype 等于 f64,返回 f64.const 0。

  5. 如果 valuetype 等于 funcref,返回 ref.null funcref

  6. 如果 valuetype 等于 externref,返回 ToWebAssemblyValue(undefined, valuetype)。

  7. 断言:此步骤不会被执行。

当调用 Global(descriptor, v) 构造函数时,执行以下步骤
  1. mutabledescriptor["mutable"]。

  2. valuetypeToValueType(descriptor["value"])。

  3. 如果 valuetypev128

    1. 抛出 TypeError 异常。

  4. 如果 v 缺失,

    1. valueDefaultValue(valuetype)。

  5. 否则,

    1. valueToWebAssemblyValue(v, valuetype)。

  6. 如果 mutable 为 true,则令 globaltypevar valuetype;否则,令 globaltypeconst valuetype

  7. store 为当前代理的 关联存储

  8. 令 (store, globaladdr) 为 global_alloc(store, globaltype, value)。

  9. 将当前代理的 关联存储 设置为 store

  10. 初始化 this 来自 globaladdr

算法 GetGlobalValue(Global global) 执行以下步骤
  1. store 为当前代理的 关联存储

  2. globaladdrglobal.[[Global]]。

  3. globaltypeglobal_type(store, globaladdr)。

  4. 如果 globaltype 的形式为 mut v128,则抛出 TypeError

  5. valueglobal_read(store, globaladdr)。

  6. 返回 ToJSValue(value)。

当调用 Globalvalue 属性的 getter 时,执行以下步骤
  1. 返回 GetGlobalValue(this)。

当调用 Global 的 value 属性的 setter 时,执行以下步骤

  1. store 为当前代理的 关联存储

  2. globaladdrthis.[[Global]]。

  3. mut valuetypeglobal_type(store, globaladdr)。

  4. 如果 valuetypev128,则抛出 TypeError

  5. 如果 mutconst,则抛出 TypeError

  6. valueToWebAssemblyValue(给定的值, valuetype)。

  7. storeglobal_write(store, globaladdr, value)。

  8. 如果 store错误,则抛出 RangeError 异常。

  9. 将当前代理的 关联存储 设置为 store

valueOf() 方法在调用时执行以下步骤
  1. 返回 GetGlobalValue(this)。

4.6. 导出函数

WebAssembly 函数在 JavaScript 中以 导出函数 的形式提供。导出函数是 内置函数对象,它们不是构造函数,并且具有 [[FunctionAddress]] 内部槽位。此槽位保存相对于 周围代理关联存储函数地址

通过执行以下步骤可以找到 WebAssembly 函数 funcaddr 的名称
  1. store周围代理关联存储

  2. funcinststore.funcs[funcaddr]。

  3. 如果 funcinst 的形式为 {type functype, hostcode hostfunc},

    1. 断言:hostfunc 是一个 JavaScript 对象,并且 IsCallable(hostfunc) 为 true。

    2. index主机函数 funcaddr 的索引。

  4. 否则,

    1. moduleinstfuncinst.module。

    2. 断言:funcaddr 包含在 moduleinst.funcaddrs 中。

    3. indexmoduleinst.funcaddrs 中 funcaddr 所在的索引。

  5. 返回 ! ToString(index).

要从 WebAssembly 函数地址 funcaddr 创建 新的导出函数,请执行以下步骤
  1. map周围代理 的关联 导出函数缓存

  2. 如果 map[funcaddr] 存在

    1. 返回 map[funcaddr]。

  3. steps 为 "调用导出函数 funcaddr 并带有参数"。

  4. realm当前领域

  5. store周围代理关联存储

  6. functypefunc_type(store, funcaddr).

  7. 令 [paramTypes] → [resultTypes] 为 functype

  8. arityparamTypes大小

  9. nameWebAssembly 函数 funcaddr 的名称。

  10. function! CreateBuiltinFunction(steps, arity, name, « [[FunctionAddress]] », realm).

  11. function.[[FunctionAddress]] 设置为 funcaddr

  12. 设置 map[funcaddr] 为 function

  13. 返回 function

要使用 函数地址 funcaddr 和 JavaScript 参数列表 argValues 调用导出函数,请执行以下步骤
  1. store周围代理关联存储

  2. functypefunc_type(store, funcaddr).

  3. 令 [parameters] → [results] 为 functype

  4. 如果 parametersresults 包含 v128,则抛出 TypeError

    注意: 上述错误将在每次调用 [[Call]] 方法时抛出。

  5. args 为 « »。

  6. i 为 0。

  7. 对于每个 parameters 中的 t

    1. 如果 argValues大小 > i,则令 argargValues[i]。

    2. 否则,令 arg 为 undefined。

    3. 追加 ToWebAssemblyValue(arg, t) 到 args

    4. i 设置为 i + 1。

  8. 令 (store, ret) 为 func_invoke(store, funcaddr, args) 的结果。

  9. 周围代理关联存储 设置为 store

  10. 如果 ret错误,则抛出异常。此异常应为 WebAssembly RuntimeError 异常,除非 WebAssembly 错误映射 中另有说明。

  11. outArityret大小

  12. 如果 outArity 为 0,则返回 undefined。

  13. 否则,如果 outArity 为 1,则返回 ToJSValue(ret[0])。

  14. 否则,

    1. values 为 « »。

    2. 对于每个 ret 中的 r

      1. 追加 ToJSValue(r) 到 values

    3. 返回 CreateArrayFromList(values).

注意: 调用导出函数 在被调用导出函数的 [[Realm]] 中执行,如 内置函数对象 的定义中所述。

注意: 导出函数没有 [[Construct]] 方法,因此无法使用 new 运算符调用它们。

要从 JavaScript 对象 func、类型 functype列表 中的 WebAssembly 值 arguments 运行主机函数,请执行以下步骤
  1. 令 [parameters] → [results] 为 functype

  2. 如果 parametersresults 包含 v128,则抛出 TypeError

  3. jsArguments 为 « »。

  4. 对于每个 arguments 中的 arg

    1. 追加 ! ToJSValue(arg) 到 jsArguments

  5. ret? Call(func, undefined, jsArguments).

  6. resultsSizeresults大小

  7. 如果 resultsSize 为 0,则返回 « »。

  8. 否则,如果 resultsSize 为 1,则返回 « ? ToWebAssemblyValue(ret, results[0]) »。

  9. 否则,

    1. method? GetMethod(ret, %Symbol.iterator%)。

    2. 如果 method 为 undefined,则 抛出 TypeError

    3. values? IteratorToList(? GetIteratorFromMethod(ret, method)).

    4. wasmValues 为一个新的空 列表

    5. 如果 values大小 不等于 resultsSize,则抛出 TypeError 异常。

    6. 对于 valuesresults 中的每个 valueresultType,线性配对,

      1. 追加 ToWebAssemblyValue(value, resultType) 到 wasmValues

    7. 返回 wasmValues

要从 JavaScript 对象 func 和类型 functype 创建主机函数,请执行以下步骤
  1. 断言:IsCallable(func).

  2. 令 `存储的设置` 为 `当前设置对象`。

  3. 令 `hostfunc` 为一个 `宿主函数`,当以参数 `参数` 调用时,执行以下步骤

    1. 令 `领域` 为 `func` 的 `关联的 Realm`。

    2. 令 `相关设置` 为 `领域` 的 `设置对象`。

    3. 使用 `相关设置` `准备运行脚本`。

    4. 使用 `存储的设置` `准备运行回调`。

    5. 令 `结果` 为从 `func`、`functype` 和 `参数` `运行宿主函数` 的结果。

    6. 使用 `存储的设置` `清理运行回调后的操作`。

    7. 使用 `相关设置` `清理运行脚本后的操作`。

    8. 断言:`结果`.[[类型]] 为抛出正常.

    9. 如果 `结果`.[[类型]] 为抛出,则触发 WebAssembly 陷阱,并将 `结果`.[[值]] 传播到包围的 JavaScript。

    10. 否则,返回 `结果`.[[值]]。

  4. 令 `存储` 为 `包围代理` 的 `关联存储`。

  5. 令 (存储, funcaddr) 为 `func_alloc`(存储, functype, hostfunc)。

  6. 将 `包围代理` 的 `关联存储` 设置为 `存储`。

  7. 返回 `funcaddr`。

算法 `ToJSValue`(w) 通过执行以下步骤将 `WebAssembly 值` 强制转换为 JavaScript 值
  1. 断言:`w` 不是 `v128.const` `v128` 的形式。

  2. 如果 `w` 是 `i64.const` `i64` 的形式,

    1. 令 `v` 为 `signed_64`(i64)。

    2. 返回 ``(v 解释为数学值)。

  3. 如果 `w` 是 `i32.const` `i32` 的形式,则返回 `𝔽`(signed_32(i32 解释为数学值))。

  4. 如果 `w` 是 `f32.const` `f32` 的形式,

    1. 如果 `f32` 是 `+∞` 或 `−∞`,则分别返回 +∞𝔽-∞𝔽

    2. 如果 `f32` 是 `nan`,则返回 NaN

    3. 返回 `𝔽`(f32 解释为数学值)。

  5. 如果 `w` 是 `f64.const` `f64` 的形式,

    1. 如果 `f64` 是 `+∞` 或 `−∞`,则分别返回 +∞𝔽-∞𝔽

    2. 如果 `f64` 是 `nan`,则返回 NaN

    3. 返回 `𝔽`(f64 解释为数学值)。

  6. 如果 `w` 是 `ref.null` `t` 的形式,则返回 null。

  7. 如果 `w` 是 `ref.func` `funcaddr` 的形式,则返回从 `funcaddr` 创建 `新的导出函数` 的结果。

  8. 如果 `w` 是 `ref.extern` `externaddr` 的形式,则返回从 `externaddr` `检索外部值` 的结果。

注意: 等于 NaN 的数字值可能具有各种可观察的 NaN 载荷;有关详细信息,请参阅 `NumericToRawBytes`。

要从 `外部地址` `externaddr` `检索外部值`,请执行以下步骤

  1. 令 `map` 为 `包围代理` 关联的 `外部值缓存`。

  2. 断言:`map`[externaddr] `存在`。

  3. 返回 `map`[externaddr]。

算法 `ToWebAssemblyValue`(v, type) 通过执行以下步骤将 JavaScript 值强制转换为 `WebAssembly 值`
  1. 断言:`type` 不是 `v128`。

  2. 如果 `type` 是 `i64`,

    1. 令 `i64` 为 `?` `ToBigInt64`(v)。

    2. 返回 `i64.const` `i64`。

  3. 如果 `type` 是 `i32`,

    1. 令 `i32` 为 `?` `ToInt32`(v)。

    2. 返回 `i32.const` `i32`。

  4. 如果 `type` 是 `f32`,

    1. 令 `number` 为 `?` `ToNumber`(v)。

    2. 如果 `number` 是 NaN

      1. 令 `n` 为一个实现定义的整数,使得 `canon`32 ≤ `n` < 2signif(32)

      2. 令 `f32` 为 `nan`(n)。

    3. 否则,

      1. 令 `f32` 为使用 IEEE 754-2008 舍入到最接近的、偶数舍入模式舍入到最近的可表示值的 `number`。`[IEEE-754]`

    4. 返回 `f32.const` `f32`。

  5. 如果 `type` 是 `f64`,

    1. 令 `number` 为 `?` `ToNumber`(v)。

    2. 如果 `number` 是 NaN

      1. 令 `n` 为一个实现定义的整数,使得 `canon`64 ≤ `n` < 2signif(64)

      2. 令 `f64` 为 `nan`(n)。

    3. 否则,

      1. 令 `f64` 为 `number`。

    4. 返回 `f64.const` `f64`。

  6. 如果 `type` 是 `funcref`,

    1. 如果 `v` 为 null,

      1. 返回 `ref.null` `funcref`。

    2. 如果 `v` 是 `导出函数`,

      1. funcaddrv 的 [[FunctionAddress]] 内部槽的值。

      2. 返回 `ref.func` `funcaddr`。

    3. 抛出一个 `TypeError

  7. 如果 `type` 是 `externref`,

    1. 如果 `v` 为 null,

      1. 返回 `ref.null` `externref`。

    2. 令 `map` 为 `包围代理` 关联的 `外部值缓存`。

    3. 如果存在 `外部地址` `externaddr`,使得 `map`[externaddr] 与 `v` 相同,

      1. 返回 `ref.extern` `externaddr`。

    4. 令 `外部地址` `externaddr` 为最小的地址,使得 `map`[externaddr] `存在` 为 false。

    5. 将 `map`[externaddr] `设置` 为 `v`。

    6. 返回 `ref.extern` `externaddr`。

  8. 断言:此步骤不会被执行。

4.7. 错误对象

WebAssembly 定义了以下错误类:`CompileError`、`LinkError` 和 `RuntimeError`。

当为 WebAssembly 命名空间 创建命名空间对象 时,必须运行以下步骤。
  1. namespaceObject命名空间对象

  2. 对于 « "CompileError", "LinkError", "RuntimeError" » 中的每个 error

    1. constructor 为一个新的对象,实现 原生错误对象结构,其中 NativeError 设置为 error

    2. ! DefineMethodProperty(namespaceObject, error, constructor, false)。

注意: 这在 WebAssembly 命名空间上定义了 CompileErrorLinkErrorRuntimeError 类,这些类是由本规范中定义的 API 生成的。它们公开了与原生 JavaScript 错误(如 TypeErrorRangeError)相同的接口。

注意: 目前无法使用 Web IDL 来定义这种行为。

5. 错误条件映射到 JavaScript

运行 WebAssembly 程序会遇到某些事件,这些事件会停止 WebAssembly 代码的执行。WebAssembly 代码(目前)无法捕获这些条件,因此异常必然会传播到封闭的非 WebAssembly 调用者(无论是浏览器、JavaScript 还是其他运行时系统),在那里它会被像普通的 JavaScript 异常一样处理。

如果 WebAssembly 通过导入调用 JavaScript,而 JavaScript 抛出异常,则该异常会通过 WebAssembly 激活传播到封闭的调用者。

由于 JavaScript 异常可以被处理,并且 JavaScript 可以继续在捕获到陷阱后调用 WebAssembly 导出,因此陷阱通常不会阻止未来的执行。

5.1. 堆栈溢出

只要 WebAssembly 代码中发生堆栈溢出,就会抛出与 JavaScript 中堆栈溢出相同的异常类。这里的特定异常在两种情况下都是实现定义的。

注意: ECMAScript 并没有指定任何关于堆栈溢出行为的规范;观察到实现会抛出 RangeError、InternalError 或 Error。这里任何一种都是有效的。

5.2. 内存不足

只要验证、编译或实例化运行时内存不足,就会抛出与 JavaScript 中内存不足条件相同的异常类。这里的特定异常在两种情况下都是实现定义的。

注意: ECMAScript 并没有指定任何关于内存不足条件行为的规范;观察到实现会抛出 OOMError 并崩溃。这里两者都是有效的。

大表或内存的分配失败可能会导致以下结果:在未来的修订中,我们可能会重新考虑对大量内存分配进行更可靠和可恢复的错误处理。

有关进一步的讨论,请参阅 问题 879

6. 实现定义的限制

WebAssembly 核心规范允许实现定义模块语法结构的限制。虽然 WebAssembly 的每个嵌入都可能选择定义自己的限制,但为了可预测性,本文件中描述的标准 WebAssembly JavaScript 接口定义了以下确切限制。如果实现遇到超出以下限制之一的模块,则必须使用 CompileError 拒绝该模块:在实践中,实现可能会在低于这些限制的有效模块上耗尽资源。

如果在运行时超出以下限制之一,实现必须抛出 RuntimeError:在实践中,实现可能会在低于这些限制的有效模块上耗尽资源。

7. 安全和隐私注意事项

本节为非规范性内容。

本文件定义了 WebAssembly 的主机环境。它允许 WebAssembly 实例从 导入对象导入 JavaScript 对象和函数,但除此之外不提供对嵌入环境的任何访问。因此,WebAssembly 实例受与 JavaScript 相同的约束。

一致性

文档约定

一致性要求通过描述性断言和 RFC 2119 术语的组合来表达。本文件规范性部分中的关键词“必须”、“不得”、“要求”、“应”、“不应”、“建议”、“不建议”、“推荐”、“可以”和“可选”应按 RFC 2119 中的描述进行解释。但是,为了可读性,这些词在本规范中不会以全部大写字母出现。

本规范的所有文本都是规范性的,除了明确标记为非规范性的部分、示例和注释。 [RFC2119]

本规范中的示例以“例如”开头,或者使用 class="example" 与规范性文本分开,例如

这是一个说明性示例。

说明性注释以“注意”开头,并使用 class="note" 与规范性文本分开,例如

注意,这是一个说明性注释。

一致性算法

用命令式表达的要求作为算法的一部分(例如“去除任何前导空格字符”或“返回 false 并中止这些步骤”)应以介绍算法中使用的关键词(“必须”、“应”、“可以”等)的含义来解释。

用算法或特定步骤表达的一致性要求可以用任何方式实现,只要最终结果相同即可。特别地,本规范中定义的算法旨在易于理解,并非旨在高效。鼓励实施者进行优化。

索引

本规范定义的术语

参考定义的术语

参考资料

规范性引用

[ECMASCRIPT]
ECMAScript 语言规范. URL: https://tc39.es/ecma262/multipage/
[ENCODING]
Anne van Kesteren. 编码标准. 活跃标准. URL: https://encoding.spec.whatwg.org/
[HTML]
Anne van Kesteren; et al. HTML 标准. 活跃标准. URL: https://html.whatwg.com.cn/multipage/
[INFRA]
Anne van Kesteren; Domenic Denicola. 基础设施标准. 活跃标准. URL: https://infra.spec.whatwg.org/
[RFC2119]
S. Bradner. RFC 中用于指示要求级别的关键词. 1997 年 3 月. 最佳当前实践. URL: https://datatracker.ietf.org/doc/html/rfc2119
[WEBASSEMBLY]
WebAssembly 核心规范. 草案. URL: https://github.webassembly.net.cn/spec/core/
[WEBIDL]
Edgar Chen; Timothy Gu. Web IDL 标准. 活跃标准. URL: https://webidl.spec.whatwg.org/

信息性引用

[IEEE-754]
IEEE 浮点运算标准. 2008 年 8 月 29 日. URL: http://ieeexplore.ieee.org/servlet/opac?punumber=4610933

IDL 索引

dictionary WebAssemblyInstantiatedSource {
    required Module module;
    required Instance instance;
};

[Exposed=*]
namespace WebAssembly {
    boolean validate(BufferSource bytes);
    Promise<Module> compile(BufferSource bytes);

    Promise<WebAssemblyInstantiatedSource> instantiate(
        BufferSource bytes, optional object importObject);

    Promise<Instance> instantiate(
        Module moduleObject, optional object importObject);
};

enum ImportExportKind {
  "function",
  "table",
  "memory",
  "global"
};

dictionary ModuleExportDescriptor {
  required USVString name;
  required ImportExportKind kind;
  // Note: Other fields such as signature may be added in the future.
};

dictionary ModuleImportDescriptor {
  required USVString module;
  required USVString name;
  required ImportExportKind kind;
};

[LegacyNamespace=WebAssembly, Exposed=*]
interface Module {
  constructor(BufferSource bytes);
  static sequence<ModuleExportDescriptor> exports(Module moduleObject);
  static sequence<ModuleImportDescriptor> imports(Module moduleObject);
  static sequence<ArrayBuffer> customSections(Module moduleObject, DOMString sectionName);
};

[LegacyNamespace=WebAssembly, Exposed=*]
interface Instance {
  constructor(Module module, optional object importObject);
  readonly attribute object exports;
};

dictionary MemoryDescriptor {
  required [EnforceRange] unsigned long initial;
  [EnforceRange] unsigned long maximum;
};

[LegacyNamespace=WebAssembly, Exposed=*]
interface Memory {
  constructor(MemoryDescriptor descriptor);
  unsigned long grow([EnforceRange] unsigned long delta);
  ArrayBuffer toFixedLengthBuffer();
  ArrayBuffer toResizableBuffer();
  readonly attribute ArrayBuffer buffer;
};

enum TableKind {
  "externref",
  "anyfunc",
  // Note: More values may be added in future iterations,
  // e.g., typed function references, typed GC references
};

dictionary TableDescriptor {
  required TableKind element;
  required [EnforceRange] unsigned long initial;
  [EnforceRange] unsigned long maximum;
};

[LegacyNamespace=WebAssembly, Exposed=*]
interface Table {
  constructor(TableDescriptor descriptor, optional any value);
  unsigned long grow([EnforceRange] unsigned long delta, optional any value);
  any get([EnforceRange] unsigned long index);
  undefined set([EnforceRange] unsigned long index, optional any value);
  readonly attribute unsigned long length;
};

enum ValueType {
  "i32",
  "i64",
  "f32",
  "f64",
  "v128",
  "externref",
  "anyfunc",
};

dictionary GlobalDescriptor {
  required ValueType value;
  boolean mutable = false;
};

[LegacyNamespace=WebAssembly, Exposed=*]
interface Global {
  constructor(GlobalDescriptor descriptor, optional any v);
  any valueOf();
  attribute any value;
};

问题索引

大型表格或内存分配失败可能会导致在未来的修订中,我们可能会重新考虑对大量内存分配进行更可靠和可恢复的错误处理。

有关进一步的讨论,请参阅 问题 879