WebAssembly JavaScript 接口

W3C 候选推荐草案

关于本文档的更多细节
本版本:
https://www.w3.org/TR/2025/CRD-wasm-js-api-2-20251102/
最新发布版本:
https://www.w3.org/TR/wasm-js-api-2/
编辑草案:
https://webassembly.github.io/spec/js-api/
历史记录:
https://www.w3.org/standards/history/wasm-js-api-2/
实现报告:
https://webassembly.org/features/
反馈:
GitHub
规范内嵌反馈
编辑:
Ms2ger (Igalia)
问题追踪:
GitHub Issues

摘要

本文档为与 WebAssembly 交互提供了明确的 JavaScript API。

这是一组相关文档的一部分: WebAssembly 核心规范WebAssembly JS 接口, 以及 WebAssembly Web API

本文档状态

本节描述了本文档在发布时的状态。当前 W3C 出版物列表及本技术报告的最新修订版可在 W3C 技术报告索引 中找到。

本文件由 WebAssembly 工作组 作为候选推荐草案通过 推荐路径 发布。

作为候选推荐(Candidate Recommendation)发布并不意味着 W3C 及其成员的背书。候选推荐草案融合了工作组计划在后续候选推荐快照中纳入的对前一候选推荐的修改。

WebAssembly 工作组计划将本出版物维持在候选推荐状态并持续更新为“动态标准”,而不是转为最终推荐。在任何情况下,推荐(REC)流程转阶段不会早于 2025 年 12 月 2 日申请。

本文档随时维护并可能更新。文档部分内容仍在开发中。

讨论本规范,推荐优先在 GitHub Issues 提出。 所有问题与评论均有 存档

本文档由 WebAssembly 工作组 制定。

本文档由采纳 W3C 专利政策 的工作组制定。 W3C 维护着一份 所有专利披露的公开名单 ,该页面也包含专利披露说明。 任何个人确实知悉某专利并认为该专利包含必要专利声明 ,务必依据 W3C 专利政策第 6 节 披露相关信息。

本文档受 2025 年 8 月 18 日 W3C 流程文件 约束。

1. 简介

根据设计,WebAssembly 核心规范 范围 [WEBASSEMBLY] 并不包含 WebAssembly 程序如何与其外部执行环境交互的描述。 它定义了 WebAssembly 与其环境(称为 嵌入者)之间的抽象嵌入接口。 嵌入者仅通过该接口与 WebAssembly 语义交互,并实现其宿主环境与嵌入 API 之间的连接。 本文档描述了 WebAssembly 嵌入到 JavaScript [ECMASCRIPT] 环境的方式,包括如何构建和实例化 WebAssembly 模块,如何调用导入与导出函数,如何交换数据,以及如何处理错误。 当 JavaScript 环境本身被嵌入在 Web 浏览器中时,Web API 规范 [WASMWEB] 描述了与 Web 环境相关的额外行为。

2. 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()
);

3. 符号说明

本规范依赖 Infra 标准。[INFRA]

WebAssembly 的 sequence 类型等价于该标准中定义的 list 类型;二者的值可直接转换,无需特殊处理。

4. 内部存储

4.1. WebAssembly Store 与 JavaScript 的交互

注: WebAssembly 语义是基于抽象的store定义的,store 表示 WebAssembly 抽象机的状态。 WebAssembly 操作接受 store 并返回更新后的 store。

每个 agent 都有一个 关联 store。当新 agent 创建时,其关联 store 初始化为 store_init() 的结果。

注: 本规范下,任何 WebAssembly 相关对象、内存或地址都不能在同一个agent cluster中的 agent 之间共享。未来版本的 WebAssembly 可能会改变这一点。

WebAssembly store 的各元素可通过 JavaScript 值标识。特别是,有对应 Memory 对象的 WebAssembly memory instance 会被标识为一个 JavaScript Data Block;对该 Data Block 的修改等价于将 agent 的 store 更新为反映这些变化的新 store,反之亦然。

4.2. WebAssembly JS 对象缓存

注: 某些 WebAssembly 对象可能有对应的 JavaScript 对象。这种对应关系保存在每个 agent 的 WebAssembly 地址到 JavaScript 对象的映射中。 该映射用于确保针对同一 agent,同一个 WebAssembly 地址至多对应一个 JavaScript 对象。但该属性对共享对象不成立。

每个 agent 都关联如下 有序映射

5. WebAssembly 命名空间

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

dictionary WebAssemblyCompileOptions {
    USVString? importedStringConstants;
    sequence<USVString> builtins;
};

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

    Promise<WebAssemblyInstantiatedSource> instantiate(
        BufferSource bytes, optional object importObject, optional WebAssemblyCompileOptions options = {});

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

    readonly attribute Tag JSTag;
};
若要从源字节 bytes 编译 WebAssembly 模块,请执行以下步骤:
  1. modulemodule_decode(bytes)。如 moduleerror,则返回 error

  2. module_validate(module) 为 error,则返回 error

  3. 返回 module

要对模块 module、已启用的内建 builtinSetNamesimportedStringModule 验证 WebAssembly 模块的内建和导入字符串,请执行以下步骤:

  1. 若对 builtinSetNames 进行内建集合名验证 的结果为 false,则返回 false。

  2. 遍历 module_imports(module) 中每个 import

    1. importedStringModule 不为 null 且 import[0] 等于 importedStringModule

      1. importExternTypeimport[2]。

      2. stringExternTypeglobal const (ref extern)

      3. match_externtype(stringExternType, importExternType) 结果为 false,则返回 false

    2. 否则,

      1. 若用 importbuiltinSetNames 验证 import 是否为内建导入结果为 false,则返回 false。

  3. 返回 true。

当调用 validate(bytes, options) 方法时, 执行如下步骤:
  1. stableBytesbuffer 所持有字节的副本 bytes

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

  3. 如果 moduleerror,则返回 false。

  4. builtinSetNamesoptions["builtins"]。

  5. importedStringModuleoptions["importedStringConstants"]。

  6. 如果对 modulebuiltinSetNamesimportedStringModule 验证内建与导入字符串 的结果为 false,则返回 false。

  7. 返回 true。

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

要从模块 module、源字节 bytes、已启用的内建 builtinSetNamesimportedStringModule 构造一个 WebAssembly 模块对象,执行以下步骤:
  1. moduleObject 为一个新的 Module 对象。

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

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

  4. moduleObject.[[BuiltinSets]] 设为 builtinSetNames

  5. moduleObject.[[ImportedStringModule]] 设为 importedStringModule

  6. 返回 moduleObject

要从源字节 bytesWebAssemblyCompileOptions options 异步编译一个 WebAssembly 模块,并使用可选的 task source taskSource,执行以下步骤:
  1. promise一个新的 promise

  2. 并行执行以下步骤:

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

    2. 排队一个任务(Queue a task) 以执行以下步骤。若提供了 taskSource,则在该 task source 上排队该任务。

      1. 如果 moduleerror,则以 CompileError 异常拒绝 promise

      2. builtinSetNamesoptions["builtins"]。

      3. importedStringModuleoptions["importedStringConstants"]。

      4. 如果对 modulebuiltinSetNamesimportedStringModule 验证内建与导入字符串 的结果为 false,则以 CompileError 异常拒绝 promise

      5. 否则,

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

        2. Resolve promise,其值为 moduleObject

  3. 返回 promise

当调用 compile(bytes, options) 方法时, 执行如下步骤:
  1. stableBytesbuffer 所持有字节的副本 bytes

  2. 使用 optionsstableBytes 异步编译一个 WebAssembly 模块 并返回结果。

要用模块 moduleimportedStringModule 实例化导入的字符串,执行以下步骤:

  1. 断言:importedStringModule 不为 null。

  2. exportsObject! OrdinaryObjectCreate(null)。

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

    1. 如果 moduleName 不等于 importedStringModule,则继续

    2. stringConstantcomponentName

    3. status! CreateDataProperty(exportsObject, stringConstant, stringConstant)。

    4. 断言:status 为 true。

  4. 返回 exportsObject

要从 WebAssembly 模块 module、imports 对象 importObject、已启用内建 builtinSetNamesimportedStringModule 读取导入(read the imports),执行以下步骤:
  1. 如果 module.imports 非空importObject 为 undefined,则抛出 TypeError 异常。

  2. builtinOrStringImports 为有序映射 « »。

  3. 对于每个 builtinSetName 属于 builtinSetNames

    1. 断言:builtinOrStringImports 不包含 builtinSetName

    2. 如果 builtinSetName 不指代一个 builtin set,则继续

    3. exportsObject 为使用 builtinSetName 实例化一个 builtin set 的结果。

    4. builtinSetQualifiedName 为以 "wasm:" 作为前缀的 builtinSetName

    5. builtinOrStringImports[builtinSetQualifiedName] 设为 exportsObject

  4. 如果 importedStringModule 不为 null,

    1. exportsObject 为以 moduleimportedStringModule 实例化导入的字符串 的结果。

    2. builtinOrStringImports[importedStringModule] 设为 exportsObject

  5. imports 为 « »。

  6. 对于每个 (moduleName, componentName, externtype) 属于 module_imports(module),

    1. 如果 builtinOrStringImports 包含 moduleName

      1. obuiltinOrStringImports[moduleName]。

      2. 如果 o 不是对象,或 o 不包含 componentName

        1. o 设为 ? Get(importObject, moduleName) 的结果。

    2. 否则,

      1. o? Get(importObject, moduleName) 的结果。

    3. 如果 o 不是对象,抛出 TypeError 异常。

    4. v? Get(o, componentName) 的结果。

    5. externtype 形式为 func functype

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

      2. v 具有 [[FunctionAddress]] 内部槽,因此是一个 导出函数(Exported Function)

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

      3. 否则,

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

        2. indeximports 中外部函数的数量。该值 index宿主函数的索引 funcaddr

      4. externfuncexternal value func funcaddr

      5. externfunc 追加到 imports

    6. externtype 形式为 global mut valtype

      1. 如果 v 实现(implements)Global

        1. globaladdrv.[[Global]]。

      2. 否则,

        1. valtypei64v 不是 BigInt

          1. 抛出 LinkError 异常。

        2. valtype 属于 i32f32f64v 不是 Number

          1. 抛出 LinkError 异常。

        3. valtypev128

          1. 抛出 LinkError 异常。

        4. valueToWebAssemblyValue(v, valtype)。若该操作抛出 TypeError, 捕获之,并抛出 LinkError 异常。

        5. store外围 agent关联 store

        6. 令 (store, globaladdr) 为 global_alloc(storeconst valtypevalue) 的结果。

        7. 外围 agent关联 store 设为 store

      3. externglobalglobal globaladdr

      4. externglobal 追加到 imports

    7. externtype 形式为 mem memtype

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

      2. externmemexternal value mem v.[[Memory]]。

      3. externmem 追加到 imports

    8. externtype 形式为 table tabletype

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

      2. tableaddrv.[[Table]]。

      3. externtableexternal value table tableaddr

      4. externtable 追加到 imports

    9. externtype 形式为 tag attribute functype

      1. 断言:attributeexception

      2. v实现 Tag, 则抛出 LinkError 异常。

      3. tagaddrv.[[Address]]。

      4. externtagexternal value tag tagaddr

      5. externtag 追加到 imports

  7. 返回 imports

注: 此算法只验证传入的 JavaScript 值类型是否正确。 对 WebAssembly 类型需求的验证被推迟到 “实例化 WebAssembly 模块核心” 算法。

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

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

    1. externvalinstance_export(instance, name)。

    2. 断言:externval 不是 error

    3. externtype 形式为 func functype

      1. 断言:externval 形式为 func funcaddr

      2. func funcaddrexternval

      3. func 为从 funcaddr 创建的新导出函数(Exported Function)

      4. valuefunc

    4. externtype 形式为 global mut globaltype

      1. 断言:externval 形式为 global globaladdr

      2. global globaladdrexternval

      3. global 为从 globaladdr 创建的新 Global 对象

      4. valueglobal

    5. externtype 形式为 mem memtype

      1. 断言:externval 形式为 mem memaddr

      2. mem memaddrexternval

      3. memory 为从 memaddr 创建的新 Memory 对象

      4. valuememory

    6. externtype 形式为 table tabletype

      1. 断言:externval 形式为 table tableaddr

      2. table tableaddrexternval

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

      4. valuetable

    7. externtype 形式为 tag attribute functype

      1. 断言:attributeexception

      2. 断言:externval 形式为 tag tagaddr

      3. tag tagaddrexternval

      4. tag 为从 tagaddr 创建的新 Tag 对象

      5. valuetag

    8. status! CreateDataProperty(exportsObject, name, value)。

    9. 断言:status 为 true。

    注:WebAssembly 模块验证 过程中执行的有效性与唯一性检查可确保每个属性名有效,且无属性被定义两次。

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

  4. 返回 exportsObject

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

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

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

要从模块 module 与导入 imports 实例化 WebAssembly 模块的核心,执行以下步骤:
  1. store外围 agent关联 store

  2. resultmodule_instantiate(storemoduleimports)。

  3. 如果 resulterror,则抛出适当的异常类型:

    • 大多数链接时发生的错误,抛出 LinkError 异常。

    • 若错误来自运行 start 函数,则对于多数由 WebAssembly 产生的错误抛出 RuntimeError, 或抛出从内部 ECMAScript 代码传播的错误对象。

    • 如适用,抛出其它错误类型,例如内存耗尽异常,详见 WebAssembly 错误映射

  4. 令 (store, instance) 为 result

  5. 外围 agent关联 store 设为 store

  6. 返回 instance

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

  2. modulemoduleObject.[[Module]]。

  3. builtinSetNamesmoduleObject.[[BuiltinSets]]。

  4. importedStringModulemoduleObject.[[ImportedStringModule]]。

  5. 读取导入(read the imports) module 的导入,使用 importObjectbuiltinSetNamesimportedStringModule,并令 imports 为结果。 如果此操作抛出异常,则捕获之,以该异常拒绝 promise,并返回 promise

  6. 并行执行以下步骤:

    1. 排队一个任务(Queue a task) 以执行以下步骤: 注:此处可执行与实现相关的工作。

      1. imports 实例化 WebAssembly 模块的核心 module,令 instance 为结果。 若此步骤抛出异常,捕获之,以该异常拒绝 promise,并终止这些子步骤。

      2. instanceObject 为一个 newInstance

      3. 初始化 instanceObject,来自 moduleinstance。 若此步骤抛出异常,捕获之,以该异常拒绝 promise,并终止这些子步骤。

      4. Resolve promise,其值为 instanceObject

  7. 返回 promise

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

  2. promiseOfModule 作出响应(React)

  3. 返回 promise

当调用 instantiate(bytes, importObject, options) 方法时,执行如下步骤:
  1. stableBytesbuffer 所持有字节的副本 bytes

  2. 使用 optionsstableBytes 异步编译一个 WebAssembly 模块,并令 promiseOfModule 为结果。

  3. 实例化 promiseOfModule,使用导入 importObject,并返回结果。

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

注: 后续的流式 API 记录于 WebAssembly Web API 中。

当调用 WebAssembly 命名空间的 JSTag 属性的 getter 时,执行如下步骤:

  1. JSTagAddr获取 JavaScript 异常标签 的结果。

  2. JSTagObject 为从 JSTagAddr 创建 Tag 对象 的结果。

  3. 返回 JSTagObject

5.1. 模块

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

enum AddressType {
  "i32",
  "i64",
};

typedef any AddressValue;

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, optional WebAssemblyCompileOptions options = {});
  static sequence<ModuleExportDescriptor> exports(Module moduleObject);
  static sequence<ModuleImportDescriptor> imports(Module moduleObject);
  static sequence<ArrayBuffer> customSections(Module moduleObject, DOMString sectionName);
};
extern 类型的字符串值 type
当调用 exports(moduleObject) 方法时,执行如下步骤:
  1. modulemoduleObject.[[Module]]。

  2. exports 为 « »。

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

    1. kindextern 类型的字符串值 type

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

    3. obj 追加到 exports

  4. 返回 exports

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

  2. builtinSetNamesmoduleObject.[[BuiltinSets]]。

  3. importedStringModulemoduleObject.[[ImportedStringModule]]。

  4. imports 为 « »。

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

    1. 如果对 (moduleName, name, type) 和 builtinSetNames 查找内建(find a builtin) 的结果不为 null,则继续

    2. 如果 importedStringModule 不为 null 且 moduleName 等于 importedStringModule,则继续

    3. kindextern 类型的字符串值 type

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

    5. obj 追加到 imports

  6. 返回 imports

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

  2. customSections 为 « »。

  3. 对于每个 custom section customSection 属于 bytes, 按照 module 语法 进行解释,

    1. namecustomSectionname按 UTF-8 解码

    2. 断言:name 非失败(moduleObject.[[Module]] 有效)。

    3. name 作为字符串等于 sectionName

      1. 一个新的 ArrayBuffer (其包含 bytes 中由该 customsec 产生式匹配范围的字节副本)追加到 customSections

  4. 返回 customSections

当调用 Module(bytes, options) 构造函数时,执行如下步骤:
  1. stableBytesbuffer 所持有字节的副本 bytes

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

  3. moduleerror,则抛出 CompileError 异常。

  4. builtinSetNamesoptions["builtins"]。

  5. importedStringModuleoptions["importedStringConstants"]。

  6. 如果对 modulebuiltinSetNamesimportedStringModule 验证内建与导入字符串 的结果为 false,则抛出 CompileError 异常。

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

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

  9. 设置 this.[[BuiltinSets]] 为 builtinSetNames

  10. 设置 this.[[ImportedStringModule]] 为 importedStringModule

注: 某些实现会对 bytes 施加大小限制。不推荐使用此 API,建议使用异步 API。

5.2. 实例

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

  2. builtinSetNamesmodule.[[BuiltinSets]]。

  3. importedStringModulemodule.[[ImportedStringModule]]。

  4. 读取导入(read the imports) module 的导入,使用 importObjectbuiltinSetNamesimportedStringModule,并令 imports 为结果。

  5. 实例化 WebAssembly 模块核心 module,使用 imports,并令 instance 为结果。

  6. 初始化 this,来自 moduleinstance

注: 不推荐使用该同步 API,因为某些实现会在实例化时进行耗时的编译工作。

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

5.3. 内存

dictionary MemoryDescriptor {
  required AddressValue initial;
  AddressValue maximum;
  AddressType address;
};

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

Memory 对象表示一个 memory instance, 可被多个 Instance 对象同时引用。每个 Memory 对象具有以下内部槽:

要从 memory address memaddr 创建定长内存缓冲区,执行如下步骤:
  1. block 为一个 Data Block,其 memaddr 的底层内存相对应。

  2. buffer 为一个新的 ArrayBuffer, 其内部槽包含 [[ArrayBufferData]]、[[ArrayBufferByteLength]] 和 [[ArrayBufferDetachKey]]。

  3. buffer.[[ArrayBufferData]] 为 block

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

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

  6. 返回 buffer

要从 memory address memaddrmaxsize 创建可调整大小的内存缓冲区,执行如下步骤:
  1. block 为一个 Data Block,其 memaddr 的底层内存相对应。

  2. lengthblock 的长度。

  3. buffer 为一个新的 ArrayBuffer, 其内部槽包含 [[ArrayBufferData]]、[[ArrayBufferByteLength]]、[[ArrayBufferMaxByteLength]] 和 [[ArrayBufferDetachKey]]。

  4. buffer.[[ArrayBufferData]] 为 block

  5. buffer.[[ArrayBufferByteLength]] 为 length

  6. buffer.[[ArrayBufferMaxByteLength]] 为 maxsize

  7. buffer.[[ArrayBufferDetachKey]] 为 "WebAssembly.Memory"。

  8. 返回 buffer

要从 memory address memaddr 初始化一个内存对象 memory,执行如下步骤:
  1. map外围 agent 关联的 Memory object cache

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

  3. buffer 为从 memaddr 创建定长内存缓冲区 的结果。

  4. memory.[[Memory]] 为 memaddr

  5. memory.[[BufferObject]] 为 buffer

  6. 设置 map[memaddr] 为 memory

要从 memory address memaddr 创建一个内存对象,执行如下步骤:
  1. map外围 agent 关联的 Memory object cache

  2. 如果 map[memaddr] 存在

    1. 返回 map[memaddr]。

  3. memory 为一个 newMemory

  4. 初始化 memory,来自 memaddr

  5. 返回 memory

当调用 Memory(descriptor) 构造函数时,执行如下步骤:
  1. descriptor["address"] 存在,令 addrtypedescriptor["address"];否则,令 addrtype 为 "i32"。

  2. initial? AddressValueToU64(descriptor["initial"], addrtype)。

  3. descriptor["maximum"] 存在,令 maximum? AddressValueToU64(descriptor["maximum"], addrtype);否则,令 maximum 为空。

  4. memtypememory type addrtype { min initial, max maximum }。

  5. memtype有效,抛出 RangeError 异常。

  6. store外围 agent关联 store

  7. 令 (store, memaddr) 为 mem_alloc(store, memtype)。若分配失败,抛出 RangeError 异常。

  8. 外围 agent关联 store 设为 store

  9. 初始化 this,来自 memaddr

刷新 Memory 缓冲区 memaddr,执行如下步骤:
  1. map外围 agent 关联的 Memory object cache

  2. 断言:map[memaddr] 存在

  3. memorymap[memaddr]。

  4. buffermemory.[[BufferObject]]。

  5. IsFixedLengthArrayBuffer(buffer) 为 true,

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

    2. buffer 为从 memaddr 创建定长内存缓冲区 的结果。

    3. memory.[[BufferObject]] 为 buffer

  6. 否则,

    1. block 为一个 Data Block,其 memaddr 的底层内存相对应。

    2. buffer.[[ArrayBufferData]] 为 block

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

要将与 memory address memaddr 关联的 内存缓冲区扩展 delta,执行如下步骤:
  1. store外围 agent关联 store

  2. retmem_size(store, memaddr)。

  3. storemem_grow(store, memaddr, delta)。

  4. storeerror,抛出 RangeError 异常。

  5. 外围 agent关联 store 设为 store

  6. 刷新 Memory 缓冲区 memaddr

  7. 返回 ret

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

  2. store外围 agent关联 store

  3. addrtypeaddress type,来自 mem_type(store, memaddr)。

  4. delta64? AddressValueToU64(delta, addrtype)。

  5. ret扩展内存缓冲区(与 memaddr 关联)delta64 的结果。

  6. 返回 U64ToAddressValue(ret, addrtype)。

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

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

    1. frame当前帧(current frame)

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

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

    4. 刷新 Memory 缓冲区 memaddr

当调用 toFixedLengthBuffer() 方法时,执行如下步骤:
  1. bufferthis.[[BufferObject]]。

  2. IsFixedLengthArrayBuffer(buffer) 为 true,返回 buffer

  3. memaddrthis.[[Memory]]。

  4. fixedBuffer 为从 memaddr 创建定长内存缓冲区 的结果。

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

  6. this.[[BufferObject]] 为 fixedBuffer

  7. 返回 fixedBuffer

当调用 toResizableBuffer() 方法时,执行如下步骤:
  1. memaddrthis.[[Memory]]。

  2. store外围 agent关联 store

  3. memtypemem_type(store, memaddr)。

  4. memtype 没有 max,

    1. 抛出 TypeError 异常。

  5. bufferthis.[[BufferObject]]。

  6. IsFixedLengthArrayBuffer(buffer) 为 false,返回 buffer

  7. 断言:memtype 具有 max。

  8. maxsizememtype 中的 max 值 * 65536。

  9. resizableBuffer 为从 memaddrmaxsize 创建可调整大小的内存缓冲区 的结果。

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

  11. this.[[BufferObject]] 为 resizableBuffer

  12. 返回 resizableBuffer

ArrayBuffer 对象(由 Memory 对象返回)必须具有 WebAssembly page size(常量 65536)的整数倍大小。因此 HostResizeArrayBuffer 重新定义如下。

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

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

    1. map外围 agent 关联的 Memory object cache

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

    3. 对于每个 memaddrmem 属于 map

      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]]。

5.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 AddressValue initial;
  AddressValue maximum;
  AddressType address;
};

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

Table 对象表示一个 table 实例,可同时被多个 Instance 对象引用。 每个 Table 对象都有一个 [[Table]] 内部槽,其值为一个 table address

要从 table address tableaddr 初始化一个 table 对象 table,执行以下步骤:
  1. map外围 agent 关联的 Table object cache

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

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

  4. 设置 map[tableaddr] 为 table

要从 table address tableaddr 创建一个 table 对象,执行以下步骤:
  1. map外围 agent 关联的 Table object cache

  2. map[tableaddr] 存在

    1. 返回 map[tableaddr]。

  3. table 为一个 newTable

  4. 初始化 table,来自 tableaddr

  5. 返回 table

当调用 Table(descriptor, value) 构造函数时,执行如下步骤:
  1. elementtypeToValueType(descriptor["element"])。

  2. elementtype 不是一个 reftype

    1. 抛出 TypeError 异常。

  3. descriptor["address"] 存在,令 addrtypedescriptor["address"];否则令 addrtype 为 "i32"。

  4. initial? AddressValueToU64(descriptor["initial"], addrtype)。

  5. descriptor["maximum"] 存在,令 maximum? AddressValueToU64(descriptor["maximum"], addrtype);否则令 maximum 为空。

  6. typetable type addrtype { min initial, max maximum } elementType

  7. type有效,抛出 RangeError 异常。

  8. value 缺失,

    1. refDefaultValue(elementtype)。

    2. 断言:referror

  9. 否则,

    1. ref? ToWebAssemblyValue(value, elementType)。

  10. store外围 agent关联 store

  11. 令 (store, tableaddr) 为 table_alloc(store, type, ref)。若分配失败,抛出 RangeError 异常。

  12. 外围 agent关联 store 设为 store

  13. 初始化 this,来自 tableaddr

当调用 grow(delta, value) 方法时,执行如下步骤:
  1. tableaddrthis.[[Table]]。

  2. store外围 agent关联 store

  3. initialSizetable_size(store, tableaddr)。

  4. 令 (addrtype, limits, elementtype) 为 table_type(store, tableaddr)。

  5. delta64? AddressValueToU64(delta, addrtype)。

  6. value 缺失,

    1. refDefaultValue(elementtype)。

    2. referror,抛出 TypeError 异常。

  7. 否则,

    1. ref? ToWebAssemblyValue(value, elementtype)。

  8. resulttable_grow(store, tableaddr, delta64, ref)。

  9. resulterror,抛出 RangeError 异常。

    注: 上述异常可能由内存不足或无效的尺寸参数导致。

  10. 外围 agent关联 store 设为 result

  11. 返回 initialSize

当访问 Tablelength 属性的 getter 时,执行如下步骤:
  1. tableaddrthis.[[Table]]。

  2. store外围 agent关联 store

  3. addrtypeaddress type,来自 table_type(store, tableaddr)。

  4. length64table_size(store, tableaddr)。

  5. 返回 U64ToAddressValue(length64, addrtype)。

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

  2. store外围 agent关联 store

  3. 令 (addrtype, limits, elementtype) 为 table_type(store, tableaddr)。

  4. elementtype 匹配 exnref

    1. 抛出 TypeError 异常。

  5. index64? AddressValueToU64(index, addrtype)。

  6. resulttable_read(store, tableaddr, index64)。

  7. resulterror,抛出 RangeError 异常。

  8. 返回 ToJSValue(result)。

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

  2. store外围 agent关联 store

  3. 令 (addrtype, limits, elementtype) 为 table_type(store, tableaddr)。

  4. elementtype 匹配 exnref

    1. 抛出 TypeError 异常。

  5. index64? AddressValueToU64(index, addrtype)。

  6. value 缺失,

    1. refDefaultValue(elementtype)。

    2. referror,抛出 TypeError 异常。

  7. 否则,

    1. ref? ToWebAssemblyValue(value, elementtype)。

  8. storetable_write(store, tableaddr, index64, ref)。

  9. storeerror,抛出 RangeError 异常。

  10. 外围 agent关联 store 设为 store

5.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 对象表示一个 global 实例, 可同时被多个 Instance 对象引用。 每个 Global 对象有一个内部槽:

要从 global address globaladdr 初始化一个 global 对象 global,执行以下步骤:
  1. map外围 agent 关联的 Global object cache

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

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

  4. 设置 map[globaladdr] 为 global

要从 global address globaladdr 创建一个 global 对象,执行以下步骤:
  1. map外围 agent 关联的 Global object cache

  2. map[globaladdr] 存在

    1. 返回 map[globaladdr]。

  3. global 为一个 newGlobal

  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 等于 externref,返回 ToWebAssemblyValue(undefined, valuetype)。

  2. 返回 val_default(valuetype)。

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

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

  3. valuetype 匹配 v128exnref

    1. 抛出 TypeError 异常。

  4. v 缺失,

    1. valueDefaultValue(valuetype)。

    2. 断言:valueerror

  5. 否则,

    1. valueToWebAssemblyValue(v, valuetype)。

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

  7. store 为当前 agent 的 关联 store

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

  9. 将当前 agent 的 关联 store 设为 store

  10. 初始化 this,来自 globaladdr

算法 GetGlobalValue(Global global) 执行以下步骤:
  1. store 为当前 agent 的 关联 store

  2. globaladdrglobal.[[Global]]。

  3. globaltypeglobal_type(store, globaladdr)。

  4. globaltype 形式为 mut valuetypevaluetype 匹配 v128exnref,抛出 TypeError

  5. valueglobal_read(store, globaladdr)。

  6. 返回 ToJSValue(value)。

当访问 Globalvalue 属性的 getter 时,执行如下步骤:
  1. 返回 GetGlobalValue(this)。

当设置 Global 的 value 属性时,执行如下步骤:

  1. store 为当前 agent 的 关联 store

  2. globaladdrthis.[[Global]]。

  3. mut valuetypeglobal_type(store, globaladdr)。

  4. valuetype 匹配 v128exnref,抛出 TypeError

  5. mutconst,抛出 TypeError

  6. valueToWebAssemblyValue(the given value, valuetype)。

  7. storeglobal_write(store, globaladdr, value)。

  8. storeerror,抛出 RangeError 异常。

  9. 将当前 agent 的 关联 store 设为 store

当调用 valueOf() 方法时,执行如下步骤:
  1. 返回 GetGlobalValue(this)。

5.6. 导出函数

WebAssembly 函数以 导出函数(Exported Function) 的形式在 JavaScript 中可用。 导出函数是内建函数对象(Built-in Function Objects),不是构造函数,且具有 [[FunctionAddress]] 内部槽。 该内部槽保存一个相对于外围 agent关联 store函数地址

WebAssembly 函数的名称 funcaddr 通过以下步骤获得:
  1. store外围 agent关联 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. index 为在 moduleinst.funcaddrs 中找到 funcaddr 的索引。

  5. 返回 ! ToString(index)。

要从 WebAssembly 函数地址 funcaddr 创建一个新的导出函数(Exported Function),执行以下步骤:
  1. map外围 agent 关联的 导出函数缓存(Exported Function cache)

  2. map[funcaddr] 存在

    1. 返回 map[funcaddr]。

  3. steps 为 “调用导出函数 funcaddr 并传入参数”。

  4. realm当前 Realm

  5. store外围 agent关联 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外围 agent关联 store

  2. functypefunc_type(store, funcaddr)。

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

  4. parametersresults 中的任一类型匹配 v128exnref,抛出 TypeError

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

  5. args 为 « »。

  6. i 为 0。

  7. 对于每个 t 属于 parameters

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

    2. 否则,令 arg 为 undefined。

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

    4. ii + 1。

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

  9. 外围 agent关联 store 设为 store

  10. reterror,则抛出异常。除非 WebAssembly 错误映射 另有说明,否则该异常应为 WebAssembly RuntimeError

  11. retTHROW ref.exn exnaddr,则

    1. tagaddrexn_tag(store, exnaddr)。

    2. payloadexn_read(store, exnaddr)。

    3. jsTagAddr获取 JavaScript 异常标签的结果。

    4. tagaddr 等于 jsTagAddr

      1. 抛出从 payload[0] 检索宿主值 的结果。

    5. 否则,

      1. exception 为从 exnaddr 创建的新 Exception

      2. 抛出 exception

  12. outArity大小ret 的值。

  13. outArity 为 0,返回 undefined。

  14. 否则,若 outArity 为 1,返回 ToJSValue(ret[0])。

  15. 否则,

    1. values 为 « »。

    2. 对于每个 r 属于 ret

      1. ToJSValue(r) 追加到 values

    3. 返回 CreateArrayFromList(values)。

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

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

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

  2. parametersresults 中任一类型匹配 v128exnref,抛出 TypeError

  3. jsArguments 为 « »。

  4. 对于每个 arg 属于 arguments

    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. stored settings在任设置对象(incumbent settings object)

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

    1. realmfunc关联 Realm

    2. relevant settingsrealm设置对象

    3. 准备运行脚本,使用 relevant settings

    4. 准备运行回调,使用 stored settings

    5. result 为从 funcfunctypearguments 运行宿主函数 的结果。

    6. 回调运行后的清理,使用 stored settings

    7. 脚本运行后的清理,使用 relevant settings

    8. 断言:result.[[Type]] 为 thrownormal

    9. store外围 agent关联 store

    10. result.[[Type]] 为 throw,则:

      1. vresult.[[Value]]。

      2. v 实现Exception

        1. addressv.[[Address]]。

      3. 否则,

        1. type获取 JavaScript 异常标签 的结果。

        2. payload! ToWebAssemblyValue(v, externref)。

        3. 令 (store, address) 为 exn_alloc(store, type, « payload »)。

        4. 外围 agent关联 store 设为 store

      4. 执行 WebAssembly 指令(ref.exn address)(throw_ref)。

    11. 否则,返回 result.[[Value]]。

  4. 令 (store, funcaddr) 为 func_alloc(store, functype, hostfunc)。

  5. 外围 agent关联 store 设为 store

  6. 返回 funcaddr

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

  2. 断言:w 的形式不是 ref.exn exnaddr

  3. w 形式为 i64.const u64

    1. i64signed_64(u64)。

    2. 返回 (作为数学值解读的 i64)。

  4. w 形式为 i32.const u32

    1. i32signed_32(u32)。

    2. 返回 𝔽(作为数学值解读的 i32)。

  5. w 形式为 f32.const f32

    1. f32+∞−∞,分别返回 +∞𝔽-∞𝔽

    2. f32nan,返回 NaN

    3. 返回 𝔽(作为数学值解读的 f32)。

  6. w 形式为 f64.const f64

    1. f64+∞−∞,分别返回 +∞𝔽-∞𝔽

    2. f64nan,返回 NaN

    3. 返回 𝔽(作为数学值解读的 f64)。

  7. w 形式为 ref.null t,返回 null。

  8. w 形式为 ref.i31 u31

    1. i31signed_31(u31)。

    2. 返回 𝔽(i31)。

  9. w 形式为 ref.struct structaddr,返回从 structaddr 与 "struct" 创建新的导出 GC 对象 的结果。

  10. w 形式为 ref.array arrayaddr,返回从 arrayaddr 与 "array" 创建新的导出 GC 对象 的结果。

  11. w 形式为 ref.func funcaddr,返回从 funcaddr 创建新的导出函数 的结果。

  12. w 形式为 ref.host hostaddr,返回从 hostaddr 检索宿主值 的结果。

  13. w 形式为 ref.extern ref,返回 ToJSValue(ref)。

注: 值为 NaN 的 Number 可能具有不同的可观察 NaN 载荷;详见 NumericToRawBytes

对于从宿主地址 hostaddr 检索宿主值,执行以下步骤:

  1. map外围 agent 关联的 宿主值缓存

  2. 断言:map[hostaddr] 存在

  3. 返回 map[hostaddr]。

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

  2. 断言:type匹配 exnref

  3. typei64

    1. i64? ToBigInt64(v)。

    2. u64 为满足 i64signed_64(u64) 的无符号整数。

    3. 返回 i64.const u64

  4. typei32

    1. i32? ToInt32(v)。

    2. u32 为满足 i32signed_32(u32) 的无符号整数。

    3. 返回 i32.const u32

  5. typef32

    1. number? ToNumber(v)。

    2. numberNaN

      1. n 为实现定义的整数,满足 canon32n < 2signif(32)

      2. f32nan(n)。

    3. 否则,

      1. f32 为将 number 按 IEEE 754-2019 最近偶数舍入规则四舍五入至可表示值所得的结果。[IEEE-754]

    4. 返回 f32.const f32

  6. typef64

    1. number? ToNumber(v)。

    2. numberNaN

      1. n 为实现定义的整数,满足 canon64n < 2signif(64)

      2. f64nan(n)。

    3. 否则,

      1. f64number

    4. 返回 f64.const f64

  7. type 形式为 ref null heaptype

    1. v 为 null,

      1. rref.null heaptype

    2. 否则若 match_valtype(type, ref null extern),

      1. refToWebAssemblyValue(v, ref any)。

      2. rref.extern ref

    3. 否则若 v 是一个 导出函数(Exported Function)match_valtype(type, ref null func),

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

      2. rref.func funcaddr

    4. 否则若 v 是 Numberv 等于 ? ToInt32(v) 且 (v) < 230(v) ⩾ -230

      1. i31? ToInt32(v)。

      2. u31 为满足 i31signed_31(i31) 的无符号整数。

      3. rref.i31 u31

    5. 否则若 v导出 GC 对象(Exported GC Object)

      1. objectaddrv 的 [[ObjectAddress]] 内部槽。

      2. objectkindv 的 [[ObjectKind]] 内部槽。

      3. objectkind 为 "array",

        1. rref.array objectaddr

      4. objectkind 为 "struct",

        1. rref.struct objectaddr

    6. 否则,

      1. map外围 agent 关联的 宿主值缓存

      2. 若存在宿主地址 hostaddr,使得 map[hostaddr] 与 v 相同,

        1. 返回 ref.host hostaddr

      3. 宿主地址 hostaddr 为最小的地址,使得 map[hostaddr] 不存在

      4. 设置 map[hostaddr] 为 v

      5. rref.host hostaddr

    7. store 为当前 agent 的 关联 store

    8. actualtyperef_type(store, r)。

    9. match_valtype(actualtype, type) 为 false,

      1. 抛出 TypeError

    10. 返回 r

  8. 断言:不会到达此步骤。

算法 AddressValueToU64(v, addrtype) 将 JavaScript 值转换为用于嵌入操作的 WebAssembly u64。它设计为对 AddressType "i32" 的行为与 [EnforceRange]unsigned long 相同,并将这些语义扩展到 AddressType "i64",执行以下步骤:
  1. addrtype 为 "i32",

    1. n? ConvertToInt(v, 32, "unsigned") 的结果,其中目标类型关联 [EnforceRange]

      注: 这等价于 JS 转换规则 中的 [EnforceRange] unsigned long

    2. 返回 (n) 作为 WebAssembly u64

  2. addrtype 为 "i64",

    1. n? ToBigInt(v)。

    2. n < 0 或 n > 264 − 1,抛出 TypeError

      注: 此操作旨在模拟 [EnforceRange]

    3. 返回 (n) 作为 WebAssembly u64

  3. 断言:不会到达此步骤。

算法 U64ToAddressValue(v, addrtype) 将嵌入操作中的 u64 值转换为对应的 AddressValue 变体(由 AddressType 指定),执行以下步骤:
  1. addrtype 为 "i32",返回 𝔽(作为数学值解读的 v)。

  2. 否则若 addrtype 为 "i64",返回 (作为数学值解读的 v)。

  3. 断言:不会到达此步骤。

5.7. 标签

tag_alloc(store, parameters) 算法在 store 中为 parameters 创建一个新的标签地址,并返回更新后的 store 与该标签地址

5.7.1. 标签类型

dictionary TagType {
  required sequence<ValueType> parameters;
};

[LegacyNamespace=WebAssembly, Exposed=(Window,Worker,Worklet)]
interface Tag {
  constructor(TagType type);
};

Tag 值表示一个异常标签。

要从标签地址 tagAddress 初始化一个 Tag 对象 tag,执行以下步骤:

  1. map外围 agent 关联的 Tag 对象缓存

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

  3. tag.[[Address]] 设为 tagAddress

  4. 设置 map[tagAddress] 为 tag

要从标签地址 tagAddress 创建一个 Tag 对象,执行以下步骤:
  1. map外围 agent 关联的 Tag 对象缓存

  2. map[tagAddress] 存在

    1. 返回 map[tagAddress]。

  3. tag 为一个 newTag

  4. 初始化 tag,来自 tagAddress

  5. 返回 tag

new Tag(type) 构造函数步骤为:

  1. parameterstype["parameters"]。

  2. wasmParameters 为 «»。

  3. 对于每个 type 属于 parameters

    1. ToValueType(type) 追加到 wasmParameters

  4. store 为当前 agent 的 关联 store

  5. 令 (store, tagAddress) 为 tag_alloc(store, wasmParameters)。

  6. 将当前 agent 的 关联 store 设为 store

  7. 初始化 this,来自 tagAddress

5.8. 垃圾回收对象

WebAssembly 的 struct 或 array 在 JavaScript 中以 导出 GC 对象(Exported GC Object) 的形式提供。 导出 GC 对象 是一种封装了垃圾回收的 WebAssembly 引用值的异质对象。 对 导出 GC 对象 的大多数 JavaScript 操作将抛出异常或返回 undefined。

注: 这些操作未来可能进一步细化,以允许在 JavaScript 中与 WebAssembly 的 struct 与 array 进行更丰富的交互。

导出 GC 对象 包含 [[ObjectAddress]] 内部槽,其中保存相对于外围 agent关联 storeobject address, 以及 [[ObjectKind]] 内部槽,保存字符串 "struct" 或 "array"。

导出 GC 对象 的内部方法如下实现。

导出 GC 对象的 [[GetPrototypeOf]] 内部方法 O 不接受参数并返回 null。被调用时执行以下步骤:
  1. 返回 null。

导出 GC 对象的 [[SetPrototypeOf]] 内部方法 O 接受参数 V(一个对象或 null)并返回布尔值。被调用时执行以下步骤:
  1. 返回 false。

导出 GC 对象的 [[IsExtensible]] 内部方法 O 不接受参数并返回布尔值。被调用时执行以下步骤:
  1. 返回 false。

导出 GC 对象的 [[PreventExtensions]] 内部方法 O 不接受参数并返回布尔值。被调用时执行以下步骤:
  1. 返回 false。

导出 GC 对象的 [[GetOwnProperty]] 内部方法 O 接受参数 P(属性键)并返回 undefined。被调用时执行以下步骤:
  1. 返回 undefined。

导出 GC 对象的 [[DefineOwnProperty]] 内部方法 O 接受参数 P(属性键)与 Desc(属性描述符),返回布尔值。被调用时执行以下步骤:
  1. 返回 false。

导出 GC 对象的 [[HasProperty]] 内部方法 O 接受参数 P(属性键)并返回布尔值。被调用时执行以下步骤:
  1. 返回 false。

导出 GC 对象的 [[Get]] 内部方法 O 接受参数 P(属性键)与 Receiver(ECMAScript 语言值)并返回 undefined。被调用时执行以下步骤:
  1. 返回 undefined。

导出 GC 对象的 [[Set]] 内部方法 O 接受参数 P(属性键)、V(ECMAScript 语言值)与 Receiver(ECMAScript 语言值)并抛出异常。被调用时执行以下步骤:
  1. 抛出 TypeError

导出 GC 对象的 [[Delete]] 内部方法 O 接受参数 P(属性键)并抛出异常。被调用时执行以下步骤:
  1. 抛出 TypeError

导出 GC 对象的 [[OwnPropertyKeys]] 内部方法 O 不接受参数并返回列表。被调用时执行以下步骤:
  1. 令 keys 为一个新的空列表。

  2. 返回 keys。

要从 WebAssembly object address objectaddr 与字符串 objectkind 创建新的导出 GC 对象,执行以下步骤:
  1. 断言:objectkind 为 "array" 或 "struct"。

  2. map外围 agent 关联的 导出 GC 对象缓存

  3. map[objectaddr] 存在

    1. 返回 map[objectaddr]。

  4. objectMakeBasicObject(« [[ObjectAddress]] »)。

  5. object.[[ObjectAddress]] 设为 objectaddr

  6. object.[[ObjectKind]] 设为 objectkind

  7. 导出 GC 对象的 [[GetPrototypeOf]] 内部方法 指定设置 object.[[GetPrototypeOf]]。

  8. 导出 GC 对象的 [[SetPrototypeOf]] 内部方法 指定设置 object.[[SetPrototypeOf]]。

  9. 导出 GC 对象的 [[IsExtensible]] 内部方法 指定设置 object.[[IsExtensible]]。

  10. 导出 GC 对象的 [[PreventExtensions]] 内部方法 指定设置 object.[[PreventExtensions]]。

  11. 导出 GC 对象的 [[GetOwnProperty]] 内部方法 指定设置 object.[[GetOwnProperty]]。

  12. 导出 GC 对象的 [[DefineOwnProperty]] 内部方法 指定设置 object.[[DefineOwnProperty]]。

  13. 导出 GC 对象的 [[HasProperty]] 内部方法 指定设置 object.[[HasProperty]]。

  14. 导出 GC 对象的 [[Get]] 内部方法 指定设置 object.[[Get]]。

  15. 导出 GC 对象的 [[Set]] 内部方法 指定设置 object.[[Set]]。

  16. 导出 GC 对象的 [[Delete]] 内部方法 指定设置 object.[[Delete]]。

  17. 导出 GC 对象的 [[OwnPropertyKeys]] 内部方法 指定设置 object.[[OwnPropertyKeys]]。

  18. 设置 map[objectaddr] 为 object

  19. 返回 object

5.9. 异常

dictionary ExceptionOptions {
  boolean traceStack = false;
};

[LegacyNamespace=WebAssembly, Exposed=(Window,Worker,Worklet)]
interface Exception {
  constructor(Tag exceptionTag, sequence<any> payload, optional ExceptionOptions options = {});
  any getArg([EnforceRange] unsigned long index);
  boolean is(Tag exceptionTag);
  readonly attribute (DOMString or undefined) stack;
};

Exception 值表示一个异常。

要从 Exception address exnAddress 初始化一个 Exception 对象 exn,执行以下步骤:

  1. map外围 agent 关联的 Exception 对象缓存

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

  3. exn.[[Address]] 设为 exnAddress

  4. 设置 map[exnAddress] 为 exn

  5. store外围 agent关联 store

  6. tagaddrexn_tag(store, exnAddress)。

  7. payloadexn_read(store, exnAddress)。

  8. exn.[[Type]] 设为 tagaddr

  9. exn.[[Payload]] 设为 payload

  10. exn.[[Stack]] 设为 undefined。

要从 exception address exnAddress 创建一个 Exception 对象,执行以下步骤:

  1. map外围 agent 关联的 Exception 对象缓存

  2. map[exnAddress] 存在

    1. 返回 map[exnAddress]。

  3. exn 为一个 newException

  4. 初始化 exn,来自 exnAddress

  5. 返回 exn

new Exception(exceptionTag, payload, options) 构造函数步骤为:

  1. JSTagAddr获取 JavaScript 异常标签 的结果。

  2. exceptionTag.[[Address]] 等于 JSTagAddr

    1. 抛出 TypeError

  3. store外围 agent关联 store

  4. 令 [types] → [] 为 tag_type(store, exceptionTag.[[Address]])。

  5. types大小 不等于 payload大小

    1. 抛出 TypeError

  6. wasmPayload 为 « »。

  7. 对于每个 valueresultType(来自 payloadtypes,按顺序配对),

    1. resultType 匹配 v128exnref

      1. 抛出 TypeError

    2. ? ToWebAssemblyValue(value, resultType) 追加到 wasmPayload

  8. 令 (store, exceptionAddr) 为 exn_alloc(store, exceptionTag.[[Address]], wasmPayload)

  9. 外围 agent关联 store 设为 store

  10. 初始化 this,来自 exceptionAddr

  11. options["traceStack"] 为 true,

    1. this.[[Stack]] 设为当前调用栈的 DOMString 表示,或设为 undefined。

getArg(index) 方法的步骤为:

  1. store外围 agent关联 store

  2. tagaddrexn_tag(store, this.[[Address]])。

  3. payloadexn_read(store, this.[[Address]])。

  4. 断言:tagaddr 等于 this.[[Type]]。

  5. indexpayload大小

    1. 抛出 RangeError

  6. 令 [types] → [] 为 tag_type(store, tagaddr)。

  7. types[index] 匹配 v128exnref

    1. 抛出 TypeError

  8. 返回 ToJSValue(payload[index])。

is(exceptionTag) 方法的步骤为:

  1. this.[[Type]] 不等于 exceptionTag.[[Address]],

    1. 返回 false。

  2. 返回 true。

stack 的 getter 步骤为:

  1. 返回 this.[[Stack]]。

5.9.1. JavaScript 异常

JavaScript 异常标签是一个与外围 agent 关联的 标签地址。它会在该 agent 的 关联 store 中首次使用时分配并被缓存。它始终具有 标签类型 « externref » → « »。

获取 JavaScript 异常标签,执行以下步骤:

  1. 如果 外围 agent 关联的 JavaScript 异常标签 已初始化,

    1. 返回该 外围 agent 关联的 JavaScript 异常标签

  2. store外围 agent关联 store

  3. 令 (store, tagAddress) 为 tag_alloc(store, « externref » → « »)。

  4. 将当前 agent 的 关联 store 设为 store

  5. 将当前 agent 关联的 JavaScript 异常标签 设为 tagAddress

  6. 返回 tagAddress

5.10. 错误对象

WebAssembly 定义了以下 Error 类:CompileErrorLinkErrorRuntimeError

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

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

    1. constructor 为一个新对象,按 NativeError 对象结构 实现,并将 NativeError 设为 error

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

注: 这会在 CompileErrorLinkErrorRuntimeError 类在 WebAssembly 命名空间上进行定义,这些类由本规范定义的 API 产生。它们公开的接口与原生 JavaScript 错误(如 TypeErrorRangeError)一致。

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

6. 内建函数

JS-API 定义了一组可在编译模块时通过 options 导入的内建函数集合。WebAssembly 的内建函数反映现有的 JavaScript 内建函数,但将其适配为可以直接作为 WebAssembly 函数使用,且开销最小。

所有内建函数被分组为若干集合。每个内建集合都有一个在 WebAssemblyCompileOptions 中使用的 name,以及一个带有 wasm: 前缀、在导入查找期间使用的 qualified name

获取某个内建集合的内建函数,给定 builtinSetName,执行以下步骤:

  1. 返回该名称为 builtinSetName 的集合(在本节中定义)的 (name, funcType, steps) 列表。

要用 import 与已启用的内建集合 builtinSetNames 查找内建函数,执行以下步骤:

  1. 断言:验证内建集合名称 builtinSetNames 的结果为 true。

  2. importModuleNameimport[0]。

  3. importNameimport[1]。

  4. 对于每个 builtinSetName 属于 builtinSetNames

    1. builtinSetName 不指向一个内建集合,则继续

    2. builtinSetQualifiedName 为在 builtinSetName 前加前缀 "wasm:" 的结果。

    3. importModuleName 等于 builtinSetQualifiedName

      1. builtins获取某个内建集合的内建函数 builtinSetName 的结果。

      2. 对于每个 builtin 属于 builtins

        1. builtinNamebuiltin[0]。

        2. importName 等于 builtinName,返回 (builtinSetName, builtin)。

  5. 返回 null。

要对 builtinSetNames 验证内建集合名称,执行以下步骤:

  1. builtinSetNames 包含任何重复项,返回 false。

  2. 返回 true。

要从类型 funcType 和执行步骤 steps 创建一个内建函数,执行以下步骤:

  1. hostfunc 为一个 宿主函数,当被调用时执行 steps

  2. 令 (store, funcaddr) 为 func_alloc(store, functype, hostfunc)。

  3. 外围 agent关联 store 设为 store

  4. 返回 funcaddr

要用名称 builtinSetName 实例化一个内建集合,执行以下步骤:

  1. builtins获取某个内建集合的内建函数 builtinSetName 的结果。

  2. exportsObject! OrdinaryObjectCreate(null)。

  3. 对于每个 (name, funcType, steps) 属于 builtins

    1. funcaddr 为用 funcTypesteps 创建一个内建函数 的结果。

    2. func 为从 funcaddr 创建 新的导出函数(Exported Function) 的结果。

    3. valuefunc

    4. status! CreateDataProperty(exportsObject, name, value)。

    5. 断言:status 为 true。

  4. 返回 exportsObject

要用 import 与已启用的内建集合 builtinSetNames 验证内建导入,执行以下步骤:

  1. 断言:验证内建集合名称 builtinSetNames 的结果为 true。

  2. maybeBuiltin 为针对 importbuiltinSetNames 查找内建函数 的结果。

  3. maybeBuiltin 为 null,返回 true。

  4. importExternTypeimport[2]。

  5. builtinFuncTypemaybeBuiltin[0][1]。

  6. builtinExternTypefunc |builtinFuncType|

  7. 返回 match_externtype(builtinExternType, importExternType)。

6.1. 字符串内建

字符串内建适配了 String 内建对象的接口。该集合的 namejs-string,其 qualified namewasm:js-string

注: 本节中的算法引用定义在 String 上的 JS 内建函数。这里指的是实际的内建函数,不会对 String 对象进行动态查找。

6.1.1. 抽象操作

UnwrapString(v) 抽象操作被调用时,执行以下步骤:

  1. v 不是 String

    1. 抛出 RuntimeError 异常,就像执行了一个 trap 一样。

  2. 返回 v

FromCharCode(v) 抽象操作被调用时,执行以下步骤:

  1. 断言:v 的类型为 i32

  2. 返回 ! Call(String.fromCharCode,undefined,« ToJSValue(v) »)。

CharCodeAt(string, index) 抽象操作被调用时,执行以下步骤:

  1. 断言:index 的类型为 i32

  2. 返回 ! Call(String.prototype.charCodeAtstring,« ToJSValue(index) »)。

6.1.2. cast

此内建的 funcType(rec (type (func (param externref) (result externref)))).0

当以参数 v 调用该内建时,必须运行以下步骤:

  1. 返回 ? UnwrapString(v)

6.1.3. test

此内建的 funcType(rec (type (func (param externref) (result i32)))).0

当以参数 v 调用该内建时,必须运行以下步骤:

  1. v 不是 String

    1. 返回 0。

  2. 返回 1。

6.1.4. fromCharCodeArray

arrayType(rec (type (array (mut i16)))).0

此内建的 funcType(rec (type (func (param (ref null arrayType) i32 i32) (result externref)))).0

当以参数 arraystartend 调用该内建时,必须运行以下步骤:

  1. array 为 null,

    1. 抛出 RuntimeError 异常,就像执行了一个 trap 一样。

  2. lengtharray 中元素的数量。

  3. start > endend > length

    1. 抛出 RuntimeError 异常,就像执行了一个 trap 一样。

  4. result 为空字符串。

  5. istart

  6. i < end 时:

    1. charCodearray 中索引 i 处存储的元素值。

    2. charCodeStringFromCharCode(charCode)。

    3. resultresultcharCodeString 的拼接结果。

    4. i 设为 i + 1。

  7. 返回 result

6.1.5. intoCharCodeArray

arrayType(rec (type (array (mut i16)))).0

此内建的 funcType(rec (type (func (param externref (ref null arrayType) i32) (result i32)))).0

当以参数 stringarraystart 调用该内建时,必须运行以下步骤:

  1. array 为 null,

    1. 抛出 RuntimeError 异常,就像执行了一个 trap 一样。

  2. string? UnwrapString(string) 的结果。

  3. stringLengthstring长度

  4. arrayLengtharray 中元素的数量。

  5. start + stringLength > arrayLength

    1. 抛出 RuntimeError 异常,就像执行了一个 trap 一样。

  6. i 为 0。

  7. i < stringLength 时:

    1. charCodeCharCodeAt(stringi)。

    2. array 中索引 start + i 处的元素设为 ToWebAssemblyValue(charCode)。

    3. i 设为 i + 1。

  8. 返回 stringLength

6.1.6. fromCharCode

此内建的 funcType(rec (type (func (param i32) (result externref)))).0

当以参数 v 调用该内建时,必须运行以下步骤:

  1. 返回 FromCharCode(v)。

6.1.7. fromCodePoint

此内建的 funcType(rec (type (func (param i32) (result externref)))).0

当以参数 v 调用该内建时,必须运行以下步骤:

  1. v > 0x10ffff,

    1. 抛出 RuntimeError 异常,就像执行了一个 trap 一样。

  2. 返回 ! Call(String.fromCodePoint,undefined,« ToJSValue(v) »)。

6.1.8. charCodeAt

此函数的类型为 (rec (type (func (param externref i32) (result i32)))).0

当以参数 stringindex 调用该内建时,必须运行以下步骤:

  1. string? UnwrapString(string) 的结果。

  2. length长度, 即 string 的长度。

  3. index >= length

    1. 抛出 RuntimeError 异常,就像执行了一个 trap 一样。

  4. 返回 CharCodeAt(string, index)。

6.1.9. codePointAt

此函数的类型为 (rec (type (func (param externref i32) (result i32)))).0

当以参数 stringindex 调用该内建时,必须运行以下步骤:

  1. string? UnwrapString(string) 的结果。

  2. length长度, 即 string 的长度。

  3. index >= length

    1. 抛出 RuntimeError 异常,就像执行了一个 trap 一样。

  4. 返回 ! Call(String.prototype.codePointAtstring,« ToJSValue(index) »)。

6.1.10. length

该内建的 funcType(rec (type (func (param externref) (result i32)))).0

当以参数 v 调用该内建时,必须运行以下步骤:

  1. string? UnwrapString(v) 的结果。

  2. 返回 string长度

6.1.11. concat

该内建的 funcType(rec (type (func (param externref externref) (result externref)))).0

当以参数 firstsecond 调用该内建时,必须运行以下步骤:

  1. first? UnwrapString(first) 的结果。

  2. second? UnwrapString(second) 的结果。

  3. 返回 ! Call(String.prototype.concatfirst,« second »)。

6.1.12. substring

该内建的 funcType(rec (type (func (param externref i32 i32) (result externref)))).0

当以参数 stringstartend 调用该内建时,必须运行以下步骤:

  1. string? UnwrapString(string) 的结果。

  2. length长度, 即 string 的长度。

  3. start > endstart > length

    1. 返回空字符串。

  4. 返回 ! Call(String.prototype.substringstring,« ToJSValue(start),ToJSValue(end) »)。

6.1.13. equals

该内建的 funcType(rec (type (func (param externref externref) (result i32)))).0

注: 明确允许对 null 字符串进行相等性比较,因为这具有意义。

当以参数 firstsecond 调用该内建时,必须运行以下步骤:

  1. first 非 null 且 first 不是 String

    1. 抛出 RuntimeError 异常,就像执行了一个 trap 一样。

  2. second 非 null 且 second 不是 String

    1. 抛出 RuntimeError 异常,就像执行了一个 trap 一样。

  3. ! IsStrictlyEqual(first, second) 为 true,

    1. 返回 1。

  4. 返回 0。

6.1.14. compare

该内建的 funcType(rec (type (func (param externref externref) (result i32)))).0

当以参数 firstsecond 调用该内建时,必须运行以下步骤:

  1. first? UnwrapString(first) 的结果。

  2. second? UnwrapString(second) 的结果。

  3. ! IsStrictlyEqual(first, second) 为 true,

    1. 返回 0。

  4. ! IsLessThan(first, second, true) 为 true,

    1. 返回 -1。

  5. 返回 1。

7. 错误条件到 JavaScript 的映射

运行 WebAssembly 程序时会遇到某些事件,导致 WebAssembly 代码停止执行。WebAssembly 代码(当前) 无法捕获这些条件,因此异常将必然传播到外层的非 WebAssembly 调用方(无论是浏览器、 JavaScript 还是其他运行时系统),并在其中像普通的 JavaScript 异常一样被处理。

如果 WebAssembly 通过 import 调用 JavaScript,而 JavaScript 抛出了异常,则该异常会通过 WebAssembly 的激活帧传播到 外层调用方。

由于 JavaScript 异常是可处理的,且在 trap 被处理后 JavaScript 仍可继续调用 WebAssembly 的导出函数,一般而言, trap 并不会阻止后续执行。

7.1. 栈溢出

每当 WebAssembly 代码发生栈溢出时,将抛出与 JavaScript 栈溢出相同类别的异常。具体抛出的异常在两种情况下均为实现定义。

注: ECMAScript 并未规定栈溢出的具体行为;已有实现会抛出 RangeError、 InternalError 或 Error。以上任一行为在此均视为有效。

7.2. 内存不足

当验证、编译或实例化出现内存不足时,将抛出与 JavaScript 中内存不足情况相同类别的异常。 具体抛出的异常在两种情况下均为实现定义。

注: ECMAScript 并未规定内存不足的具体行为;已有实现会抛出 OOMError 或直接崩溃。两者在此均视为有效。

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

更多讨论参见 Issue 879

8. 实现定义的限制

WebAssembly 核心规范允许实现对模块的句法结构设定限制。 虽然每个 WebAssembly 的嵌入环境可以选择定义自身的限制,但为增强可预测性,本文档所述的标准 WebAssembly JavaScript 接口 定义了以下精确限制。实现必须在模块超过以下任一限制时,抛出 CompileError 来拒绝该模块。 实际上,实现也可能在低于这些限制的有效模块上耗尽资源。

在运行时若超过以下任一限制,实现必须抛出 RuntimeError: 实际上,实现也可能在低于这些限制的有效模块上耗尽资源。

9. 安全与隐私注意事项

本节为非规范性内容。

本文档为 WebAssembly 定义了宿主环境。它使 WebAssembly 实例能够从一个 import 的 JavaScript 对象与函数(来自一个导入对象)中进行导入,但除此之外不提供对嵌入环境的访问。 因此,一个 WebAssembly 实例受与 JavaScript 相同的约束。

10. 变更历史

本节为非规范性内容。

自 WebAssembly 规范 1.0 最初发布以来,已有若干扩展提案被集成。 下列小节概述了发生的变更。

10.1. 版本 2.0

多返回值

多个值可以作为 Array 对象在 JavaScript 函数与 WebAssembly 之间相互返回。

BigInt 集成

WebAssembly 的 i64 值可以在 JavaScript 与 WebAssembly 之间传递(通过导入或导出的全局、表的 get/set 操作、函数返回值或参数),并以 BigInt 对象表示。

引用类型

JavaScript 值可以作为 externref 值在 WebAssembly 与 JavaScript 间传递(通过导入或导出的全局、表的 set/get 操作,以及函数参数或返回值)。

多表

可以在 JavaScript 与 WebAssembly 之间导出与导入多个表。

10.2. 版本 3.0

多内存

可以在 JavaScript 与 WebAssembly 之间导出与导入多个内存对象。

JS 字符串内建

在编译模块时新增了 builtins 选项,并提供了一组用于操作 JS 字符串的内建函数集合。

一致性

文档约定

一致性要求通过描述性断言与 RFC 2119 术语的组合来表达。 规范性部分中的关键词 “MUST”、“MUST NOT”、“REQUIRED”、“SHALL”、“SHALL NOT”、“SHOULD”、“SHOULD NOT”、“RECOMMENDED”、“MAY” 与 “OPTIONAL” 的解释参见 RFC 2119。 然而,为了可读性,本规范中并未将这些词全部使用大写形式。

除明确标注为非规范性的章节、示例与注释外,本规范的所有文本均为规范性内容。[RFC2119]

本规范中的示例以 “for example” 引介,或通过 class="example" 与规范性文本区分, 如下所示:

这是一个信息性示例。

信息性注释以 “Note” 开头,并通过 class="note" 与规范性文本区分, 如下所示:

Note,此处为信息性注释。

一致性算法

在算法中以祈使语气表述的要求(例如 “strip any leading space characters” 或 “return false and abort these steps”)应结合引介该算法时所用关键词(“must”、“should”、“may” 等)的含义进行理解。

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

索引

本规范定义的术语

通过引用定义的术语

参考文献

规范性引用

[ECMASCRIPT]
ECMAScript Language Specification. URL: https://tc39.es/ecma262/multipage/
[ENCODING]
Anne van Kesteren. Encoding Standard. Living Standard. URL: https://encoding.spec.whatwg.org/
[HTML]
Anne van Kesteren; et al. HTML Standard. Living Standard. URL: https://html.spec.whatwg.org/multipage/
[INFRA]
Anne van Kesteren; Domenic Denicola. Infra Standard. Living Standard. URL: https://infra.spec.whatwg.org/
[RFC2119]
S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. March 1997. Best Current Practice. URL: https://datatracker.ietf.org/doc/html/rfc2119
[WEBASSEMBLY]
WebAssembly Core Specification. Draft. URL: https://webassembly.github.io/spec/core/
[WEBIDL]
Edgar Chen; Timothy Gu. Web IDL Standard. Living Standard. URL: https://webidl.spec.whatwg.org/

非规范性引用

[IEEE-754]
IEEE Standard for Floating-Point Arithmetic. 22 July 2019. URL: https://ieeexplore.ieee.org/document/8766229
[WASMWEB]
WebAssembly Web API Specification. Draft. URL: https://webassembly.github.io/spec/web-api/

IDL 索引

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

dictionary WebAssemblyCompileOptions {
    USVString? importedStringConstants;
    sequence<USVString> builtins;
};

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

    Promise<WebAssemblyInstantiatedSource> instantiate(
        BufferSource bytes, optional object importObject, optional WebAssemblyCompileOptions options = {});

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

    readonly attribute Tag JSTag;
};

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

enum AddressType {
  "i32",
  "i64",
};

typedef any AddressValue;

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, optional WebAssemblyCompileOptions options = {});
  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 AddressValue initial;
  AddressValue maximum;
  AddressType address;
};

[LegacyNamespace=WebAssembly, Exposed=*]
interface Memory {
  constructor(MemoryDescriptor descriptor);
  AddressValue grow(AddressValue 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 AddressValue initial;
  AddressValue maximum;
  AddressType address;
};

[LegacyNamespace=WebAssembly, Exposed=*]
interface Table {
  constructor(TableDescriptor descriptor, optional any value);
  AddressValue grow(AddressValue delta, optional any value);
  any get(AddressValue index);
  undefined set(AddressValue index, optional any value);
  readonly attribute AddressValue 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;
};

dictionary TagType {
  required sequence<ValueType> parameters;
};

[LegacyNamespace=WebAssembly, Exposed=(Window,Worker,Worklet)]
interface Tag {
  constructor(TagType type);
};

dictionary ExceptionOptions {
  boolean traceStack = false;
};

[LegacyNamespace=WebAssembly, Exposed=(Window,Worker,Worklet)]
interface Exception {
  constructor(Tag exceptionTag, sequence<any> payload, optional ExceptionOptions options = {});
  any getArg([EnforceRange] unsigned long index);
  boolean is(Tag exceptionTag);
  readonly attribute (DOMString or undefined) stack;
};

问题索引

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

参见 Issue 879 以获取进一步讨论。