此 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 ; }; [Exposed=*]
instance 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
-
将 module 设置为 module_decode(bytes)。如果 module 是 错误,则返回 错误。
-
如果 module_validate(module) 是 错误,则返回 错误。
-
返回 module。
validate(bytes)
方法时,它将执行以下步骤。-
将 stableBytes 设置为 缓冲区 bytes 所持字节的副本。
-
将 stableBytes 编译 为 WebAssembly 模块,并将结果存储为 module。
-
如果 module 是 错误,则返回 false。
-
返回 true。
Module
对象表示单个 WebAssembly 模块。每个 Module
对象都有以下内部槽位。
-
[[Module]] : WebAssembly 模块
-
[[Bytes]] : [[Module]] 的源字节。
-
将 moduleObject 设置为一个新的
Module
对象。 -
将 moduleObject.[[Module]] 设置为 module。
-
将 moduleObject.[[Bytes]] 设置为 bytes。
-
返回 moduleObject。
-
设 promise 为 一个新的 promise。
-
运行以下步骤 并行
-
编译 WebAssembly 模块 bytes 并将结果存储为 module。
-
排队一个任务 来执行以下步骤。如果 taskSource 被提供,则在该任务源上排队任务。
-
如果 module 是 错误,则拒绝 promise 并带有
CompileError
异常。 -
否则,
-
构造一个 WebAssembly 模块对象 从 module 和 bytes,并设 moduleObject 为结果。
-
解析 promise 为 moduleObject。
-
-
-
-
返回 promise。
compile(bytes)
方法,当被调用时,执行以下步骤-
设 stableBytes 为 缓冲区 bytes 持有的字节的副本。
-
异步编译 WebAssembly 模块 从 stableBytes 并返回结果。
-
设 imports 为 « »。
-
对于每个 (moduleName, componentName, externtype) 的 module_imports(module),
-
如果 externtype 形式为 func functype,
-
如果 externtype 形式为 global mut valtype,
-
如果 Type(v) 是 Number 或 BigInt,
-
-
设 globaladdr 为 v.[[Global]]。
-
-
否则,
-
抛出
LinkError
异常。
-
-
设 externglobal 为 global globaladdr。
-
追加 externglobal 到 imports。
-
-
如果 externtype 形式为 mem memtype,
-
如果 externtype 形式为 table tabletype,
-
返回 imports。
注意: 此算法仅验证传递了正确类型的 JavaScript 值。WebAssembly 类型要求的验证被推迟到 “实例化 WebAssembly 模块的核心” 算法中。
-
设 exportsObject 为 ! OrdinaryObjectCreate(null)。
-
对于每个 (name, externtype) 的 module_exports(module),
-
设 externval 为 instance_export(instance, name)。
-
断言:externval 不是 错误。
-
如果 externtype 形式为 func functype,
-
如果 externtype 形式为 global mut globaltype,
-
断言:externval 形式为 global globaladdr。
-
设 global globaladdr 为 externval。
-
设 global 为 从 globaladdr 创建一个新的全局对象。
-
设 value 为 global。
-
-
如果 externtype 形式为 mem memtype,
-
断言:externval 形式为 mem memaddr。
-
设 mem memaddr 为 externval。
-
设 memory 为 从 memaddr 创建一个新的内存对象。
-
设 value 为 memory。
-
-
如果 externtype 形式为 table tabletype,
-
断言: externval 的形式为 table tableaddr。
-
令 table tableaddr 为 externval。
-
令 table 为 一个从 tableaddr 创建的新 Table 对象。
-
令 value 为 table。
-
-
令 status 为 ! CreateDataProperty(exportsObject, name, value).
-
断言: status 为 true。
注意: 在 WebAssembly 模块验证 期间执行的有效性和唯一性检查确保每个属性名称有效并且没有属性定义两次。
-
-
执行 ! SetIntegrityLevel(exportsObject,
"frozen"
)。 -
返回 exportsObject。
-
创建一个导出对象 从 module 和 instance 并且令 exportsObject 为结果。
-
设置 instanceObject.[[Instance]] 为 instance。
-
设置 instanceObject.[[Exports]] 为 exportsObject。
-
令 result 为 module_instantiate(store, module, imports).
-
如果 result 为 error, 抛出一个合适的异常类型
-
一个
LinkError
异常用于在链接期间发生的多数情况。 -
如果错误是在运行启动函数时出现的,则抛出一个
RuntimeError
用于从 WebAssembly 发生的多数错误,或者从内部 ECMAScript 代码传播的错误对象。 -
另一种错误类型(如果合适),例如内存不足异常,如 WebAssembly 错误映射 中所述。
-
-
令 (store, instance) 为 result。
-
返回 instance。
Module
moduleObject 和导入 importObject, 执行以下步骤-
令 promise 为 一个新的 Promise。
-
令 module 为 moduleObject.[[Module]]。
-
读取导入 的 module 与导入 importObject, 并且令 imports 为结果。如果此操作抛出异常,则捕获它,拒绝 promise 使用异常,并返回 promise。
-
以 并行 方式运行以下步骤
-
返回 promise。
-
令 promise 为 一个新的 Promise。
-
在完成 promiseOfModule 使用值 module
-
实例化 WebAssembly 模块 module 导入 importObject, 并且令 innerPromise 为结果。
-
在完成 innerPromise 使用值 instance.
-
令 result 为
WebAssemblyInstantiatedSource
值 «[ "module
" → module, "instance
" → instance ]»。 -
完成 promise 使用 result。
-
-
在拒绝 innerPromise 使用原因 reason
-
拒绝 promise 使用 reason。
-
-
-
在拒绝 promiseOfModule 使用原因 reason
-
拒绝 promise 使用 reason。
-
-
返回 promise。
instantiate(bytes, importObject)
方法,当被调用时,执行以下步骤-
令 stableBytes 为 缓冲区 bytes 所持有的字节的副本。
-
异步编译一个 WebAssembly 模块 从 stableBytes 并且令 promiseOfModule 为结果。
-
实例化 promiseOfModule 与导入 importObject 并且返回结果。
instantiate(moduleObject, importObject)
方法,当被调用时,执行以下步骤-
异步实例化 WebAssembly 模块 moduleObject 导入 importObject, 并且返回结果。
注意: 连续的流式 API 在 WebAssembly Web API 中有说明。
4.1. 模块
enum {
ImportExportKind ,
"function" ,
"table" ,
"memory" };
"global" dictionary {
ModuleExportDescriptor required USVString ;
name required ImportExportKind ; // Note: Other fields such as signature may be added in the future. };
kind 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
exports(moduleObject)
方法,当被调用时,执行以下步骤
imports(moduleObject)
方法,当被调用时,执行以下步骤
customSections(moduleObject, sectionName)
方法,当被调用时,执行以下步骤-
令 bytes 为 moduleObject.[[Bytes]]。
-
令 customSections 为 « »。
-
对于每个 自定义节 customSection 的 bytes, 根据 模块语法 解释,
-
令 name 为 customSection 的
name
, 以 UTF-8 解码。 -
断言: name 不是失败 (moduleObject.[[Module]] 为 有效).
-
如果 name 等于 sectionName 作为字符串值,
-
追加 一个新的
ArrayBuffer
包含 bytes 中字节的副本,用于此 customsec 产生式所匹配的范围到 customSections。
-
-
-
返回 customSections。
Module(bytes)
构造函数被调用时,执行以下步骤:-
令 stableBytes 为缓冲区 bytes 所持有的字节的副本。
-
编译 WebAssembly 模块 stableBytes 并将结果存储为 module。
-
如果 module 为错误,则抛出
CompileError
异常。 -
将 this.[[Module]] 设置为 module。
-
将 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)
构造函数被调用时,执行以下步骤:-
令 module 为 module.[[Module]]。
-
读取 module 的导入,导入为 importObject,并将结果设为 imports。
-
实例化 WebAssembly 模块 module 的核心,导入为 imports,并将结果设为 instance。
-
初始化 this,模块为 module,实例为 instance。
注意: 不建议使用此同步 API,因为一些实现有时在实例化时会进行长时间的编译工作。
Instance
的 exports
属性的 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
对象具有以下内部槽位:
-
[[Memory]]:一个 内存地址
-
[[BufferObject]]:一个
ArrayBuffer
,其数据块 与 上述内存地址对应
-
令 buffer 为一个具有内部槽位 [[ArrayBufferData]]、[[ArrayBufferByteLength]] 和 [[ArrayBufferDetachKey]] 的新的
ArrayBuffer
。 -
将 buffer.[[ArrayBufferData]] 设置为 block。
-
将 buffer.[[ArrayBufferByteLength]] 设置为 block 的长度。
-
将 buffer.[[ArrayBufferDetachKey]] 设置为 "WebAssembly.Memory"。
-
返回 buffer。
-
令 length 为 block 的长度。
-
如果 maxsize > (65536 × 65536),
-
抛出
RangeError
异常。
-
-
令 buffer 为一个具有内部槽位 [[ArrayBufferData]]、[[ArrayBufferByteLength]]、[[ArrayBufferMaxByteLength]] 和 [[ArrayBufferDetachKey]] 的新的
ArrayBuffer
。 -
将 buffer.[[ArrayBufferData]] 设置为 block。
-
将 buffer.[[ArrayBufferByteLength]] 设置为 length。
-
将 buffer.[[ArrayBufferMaxByteLength]] 设置为 maxsize。
-
将 buffer.[[ArrayBufferDetachKey]] 设置为 "WebAssembly.Memory"。
-
返回 buffer。
-
断言:map[memaddr] 不存在。
-
令 buffer 为从 memaddr 创建固定长度内存缓冲区 的结果。
-
将 memory.[[Memory]] 设置为 memaddr。
-
将 memory.[[BufferObject]] 设置为 buffer。
-
设置 map[memaddr] 为 memory。
Memory(descriptor)
构造函数被调用时,执行以下步骤:-
令 initial 为 descriptor["initial"]。
-
如果 descriptor["maximum"] 存在,则令 maximum 为 descriptor["maximum"];否则,令 maximum 为空。
-
如果 maximum 不为空且 maximum < initial,则抛出
RangeError
异常。 -
令 memtype 为 { min initial, max maximum }。
-
令 (store, memaddr) 为mem_alloc(store, memtype)。如果分配失败,则抛出
RangeError
异常。 -
初始化 this,内存地址为 memaddr。
-
断言:map[memaddr] 存在。
-
令 memory 为 map[memaddr]。
-
令 buffer 为 memory.[[BufferObject]]。
-
如果IsFixedLengthArrayBuffer(buffer) 为 true,
-
执行! DetachArrayBuffer(buffer, "WebAssembly.Memory")。
-
令 buffer 为从 memaddr 创建固定长度内存缓冲区 的结果。
-
将 memory.[[BufferObject]] 设置为 buffer。
-
-
否则,
grow(delta)
方法被调用时,执行以下步骤:-
令 memaddr 为 this.[[Memory]]。
-
返回将与 memaddr 关联的内存缓冲区增大 delta 的结果。
在 WebAssembly memory.grow 指令执行后立即执行以下步骤:
toFixedLengthBuffer()
方法在被调用时执行以下步骤-
令 buffer 为 this.[[BufferObject]]。
-
如果 IsFixedLengthArrayBuffer(buffer) 为 true,则返回 buffer。
-
令 memaddr 为 this.[[Memory]]。
-
令 fixedBuffer 为 从 memaddr 创建固定长度内存缓冲区 的结果。
-
执行 ! DetachArrayBuffer(buffer, "WebAssembly.Memory")。
-
将 this.[[BufferObject]] 设置为 fixedBuffer。
-
返回 fixedBuffer。
toResizableBuffer()
方法在被调用时执行以下步骤-
令 buffer 为 this.[[BufferObject]]。
-
如果 IsFixedLengthArrayBuffer(buffer) 为 false,则返回 buffer。
-
令 memaddr 为 this.[[Memory]]。
-
令 memtype 为 mem_type(store, memaddr)。
-
如果 memtype 有最大值,
-
令 maxsize 为 memtype 中的最大值。
-
-
否则,
-
令 maxsize 为 65536 × 65536。
-
-
令 resizableBuffer 为 从 memaddr 和 maxsize 创建可调整大小的内存缓冲区 的结果。
-
执行 ! DetachArrayBuffer(buffer, "WebAssembly.Memory")。
-
将 this.[[BufferObject]] 设置为 resizableBuffer。
-
返回 resizableBuffer。
ArrayBuffer
对象由 Memory
对象返回,其大小必须是 WebAssembly 页面大小(常量 65536)的倍数。因此,HostResizeArrayBuffer 被重新定义如下。
抽象操作 HostResizeArrayBuffer 接受参数 buffer(一个 ArrayBuffer
)和 newLength。在被调用时,它执行以下步骤。
-
如果 buffer.[[ArrayBufferDetachKey]] 为 "WebAssembly.Memory",
-
断言:buffer 是 map 中恰好一个值的 [[BufferObject]]。
-
对于 map 中的每个 memaddr → mem,
-
如果 SameValue(mem.[[BufferObject]], buffer) 为 true,
-
断言:buffer.[[ArrayBufferByteLength]] 模 65536 为 0。
-
令 lengthDelta 为 newLength - buffer.[[ArrayBufferByteLength]]。
-
如果 lengthDelta < 0 或 lengthDelta 模 65536 不为 0,
-
抛出一个
RangeError
异常。
-
-
令 delta 为 lengthDelta ÷ 65536。
-
增长 与 memaddr 关联的内存缓冲区,增长 delta 个页面。
-
-
-
返回
handled .
-
否则,返回
unhandled .
Memory
的 buffer
属性的 getter 返回 this.[[BufferObject]]。4.4. 表格
enum {
TableKind ,
"externref" , // Note: More values may be added in future iterations, // e.g., typed function references, typed GC references };
"anyfunc" 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]] 内部槽,它是一个 表格地址。
Table(descriptor, value)
构造函数在被调用时执行以下步骤-
令 elementType 为 ToValueType(descriptor["element"])。
-
如果 elementType 不是一个 reftype,
-
令 initial 为 descriptor["initial"]。
-
如果 descriptor["maximum"] 存在,则令 maximum 为 descriptor["maximum"];否则,令 maximum 为空。
-
如果 maximum 不为空且 maximum < initial,则抛出一个
RangeError
异常。 -
如果 value 缺失,
-
令 ref 为 DefaultValue(elementType)。
-
-
否则,
-
令 ref 为 ? ToWebAssemblyValue(value, elementType)。
-
-
令 (store, tableaddr) 为 table_alloc(store, type, ref)。
-
初始化 this,从 tableaddr 开始。
grow(delta, value)
方法在被调用时执行以下步骤-
令 tableaddr 为 this.[[Table]]。
-
令 initialSize 为 table_size(store, tableaddr)。
-
令 (limits, elementType) 为 table_type(tableaddr)。
-
如果 value 缺失,
-
令 ref 为 DefaultValue(elementType)。
-
-
否则,
-
令 ref 为 ? ToWebAssemblyValue(value, elementType)。
-
-
令 result 为 table_grow(store, tableaddr, delta, ref)。
-
如果 result 为 error,则抛出一个
RangeError
异常。注意: 上述异常可能是由于内存不足或大小参数无效导致的。
-
返回 initialSize。
Table
的 length
属性的 getter 在被调用时执行以下步骤-
令 tableaddr 为 this.[[Table]]。
-
返回 table_size(store, tableaddr)。
get(index)
方法时,执行以下步骤-
令 tableaddr 为 this.[[Table]]。
-
令 result 为 table_read(store, tableaddr, index)。
-
如果 result 为 错误,则抛出
RangeError
异常。 -
返回 ToJSValue(result)。
set(index, value)
方法时,执行以下步骤-
令 tableaddr 为 this.[[Table]]。
-
令 (limits, elementType) 为 table_type(tableaddr)。
-
如果 value 缺失,
-
令 ref 为 DefaultValue(elementType)。
-
-
否则,
-
令 ref 为 ? ToWebAssemblyValue(value, elementType)。
-
-
令 store 为 table_write(store, tableaddr, index, ref)。
-
如果 store 为 错误,则抛出
RangeError
异常。
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]] : 全局地址
Global(descriptor, v)
构造函数时,执行以下步骤-
令 mutable 为 descriptor["mutable"]。
-
令 valuetype 为 ToValueType(descriptor["value"])。
-
如果 valuetype 为 v128,
-
抛出
TypeError
异常。
-
-
如果 v 缺失,
-
令 value 为 DefaultValue(valuetype)。
-
-
否则,
-
令 value 为 ToWebAssemblyValue(v, valuetype)。
-
-
如果 mutable 为 true,则令 globaltype 为 var valuetype;否则,令 globaltype 为 const valuetype。
-
令 store 为当前代理的 关联存储。
-
令 (store, globaladdr) 为 global_alloc(store, globaltype, value)。
-
将当前代理的 关联存储 设置为 store。
-
初始化 this 来自 globaladdr。
Global
global) 执行以下步骤-
令 store 为当前代理的 关联存储。
-
令 globaladdr 为 global.[[Global]]。
-
令 globaltype 为 global_type(store, globaladdr)。
-
令 value 为 global_read(store, globaladdr)。
-
返回 ToJSValue(value)。
Global
的 value
属性的 getter 时,执行以下步骤-
返回 GetGlobalValue(this)。
当调用 Global
的 value 属性的 setter 时,执行以下步骤
-
令 store 为当前代理的 关联存储。
-
令 globaladdr 为 this.[[Global]]。
-
令 mut valuetype 为 global_type(store, globaladdr)。
-
令 value 为 ToWebAssemblyValue(给定的值, valuetype)。
-
令 store 为 global_write(store, globaladdr, value)。
-
如果 store 为 错误,则抛出
RangeError
异常。 -
将当前代理的 关联存储 设置为 store。
valueOf()
方法在调用时执行以下步骤-
返回 GetGlobalValue(this)。
4.6. 导出函数
WebAssembly 函数在 JavaScript 中以 导出函数 的形式提供。导出函数是 内置函数对象,它们不是构造函数,并且具有 [[FunctionAddress]] 内部槽位。此槽位保存相对于 周围代理 的 关联存储 的 函数地址。
-
令 funcinst 为 store.funcs[funcaddr]。
-
如果 funcinst 的形式为 {type functype, hostcode hostfunc},
-
断言:hostfunc 是一个 JavaScript 对象,并且 IsCallable(hostfunc) 为 true。
-
令 index 为 主机函数 funcaddr 的索引。
-
-
否则,
-
令 moduleinst 为 funcinst.module。
-
断言:funcaddr 包含在 moduleinst.funcaddrs 中。
-
令 index 为 moduleinst.funcaddrs 中 funcaddr 所在的索引。
-
-
如果 map[funcaddr] 存在,
-
返回 map[funcaddr]。
-
-
令 steps 为 "调用导出函数 funcaddr 并带有参数"。
-
令 realm 为 当前领域。
-
令 functype 为 func_type(store, funcaddr).
-
令 [paramTypes] → [resultTypes] 为 functype。
-
令 arity 为 paramTypes 的 大小。
-
令 name 为 WebAssembly 函数 funcaddr 的名称。
-
令 function 为 ! CreateBuiltinFunction(steps, arity, name, « [[FunctionAddress]] », realm).
-
将 function.[[FunctionAddress]] 设置为 funcaddr。
-
设置 map[funcaddr] 为 function。
-
返回 function。
-
令 functype 为 func_type(store, funcaddr).
-
令 [parameters] → [results] 为 functype。
-
如果 parameters 或 results 包含 v128,则抛出
TypeError
。注意: 上述错误将在每次调用 [[Call]] 方法时抛出。
-
令 args 为 « »。
-
令 i 为 0。
-
对于每个 parameters 中的 t,
-
如果 argValues 的 大小 > i,则令 arg 为 argValues[i]。
-
否则,令 arg 为 undefined。
-
追加 ToWebAssemblyValue(arg, t) 到 args。
-
将 i 设置为 i + 1。
-
-
令 (store, ret) 为 func_invoke(store, funcaddr, args) 的结果。
-
如果 ret 为 错误,则抛出异常。此异常应为 WebAssembly
RuntimeError
异常,除非 WebAssembly 错误映射 中另有说明。 -
令 outArity 为 ret 的 大小。
-
如果 outArity 为 0,则返回 undefined。
-
否则,如果 outArity 为 1,则返回 ToJSValue(ret[0])。
-
否则,
-
令 values 为 « »。
-
对于每个 ret 中的 r,
-
返回 CreateArrayFromList(values).
-
注意: 调用导出函数 在被调用导出函数的 [[Realm]] 中执行,如 内置函数对象 的定义中所述。
注意: 导出函数没有 [[Construct]] 方法,因此无法使用 new
运算符调用它们。
-
令 [parameters] → [results] 为 functype。
-
令 jsArguments 为 « »。
-
对于每个 arguments 中的 arg,
-
令 resultsSize 为 results 的 大小。
-
如果 resultsSize 为 0,则返回 « »。
-
否则,如果 resultsSize 为 1,则返回 « ? ToWebAssemblyValue(ret, results[0]) »。
-
否则,
-
令 method 为 ? GetMethod(ret,
%Symbol.iterator%
)。 -
令 values 为 ? IteratorToList(? GetIteratorFromMethod(ret, method)).
-
令 wasmValues 为一个新的空 列表。
-
对于 values 和 results 中的每个 value 和 resultType,线性配对,
-
追加 ToWebAssemblyValue(value, resultType) 到 wasmValues。
-
-
返回 wasmValues。
-
-
断言:IsCallable(func).
-
令 `存储的设置` 为 `当前设置对象`。
-
令 `hostfunc` 为一个 `宿主函数`,当以参数 `参数` 调用时,执行以下步骤
-
令 `领域` 为 `func` 的 `关联的 Realm`。
-
令 `相关设置` 为 `领域` 的 `设置对象`。
-
使用 `相关设置` `准备运行脚本`。
-
使用 `存储的设置` `准备运行回调`。
-
令 `结果` 为从 `func`、`functype` 和 `参数` `运行宿主函数` 的结果。
-
使用 `存储的设置` `清理运行回调后的操作`。
-
使用 `相关设置` `清理运行脚本后的操作`。
-
断言:`结果`.[[类型]] 为
抛出 或正常 . -
如果 `结果`.[[类型]] 为
抛出 ,则触发 WebAssembly 陷阱,并将 `结果`.[[值]] 传播到包围的 JavaScript。 -
否则,返回 `结果`.[[值]]。
-
-
令 (存储, funcaddr) 为 `func_alloc`(存储, functype, hostfunc)。
-
返回 `funcaddr`。
-
断言:`w` 不是 `v128.const` `v128` 的形式。
-
如果 `w` 是 `i64.const` `i64` 的形式,
-
如果 `w` 是 `i32.const` `i32` 的形式,则返回 `𝔽`(signed_32(i32 解释为数学值))。
-
如果 `w` 是 `f32.const` `f32` 的形式,
-
如果 `w` 是 `f64.const` `f64` 的形式,
-
如果 `w` 是 `ref.null` `t` 的形式,则返回 null。
-
如果 `w` 是 `ref.func` `funcaddr` 的形式,则返回从 `funcaddr` 创建 `新的导出函数` 的结果。
-
如果 `w` 是 `ref.extern` `externaddr` 的形式,则返回从 `externaddr` `检索外部值` 的结果。
注意: 等于 NaN 的数字值可能具有各种可观察的 NaN 载荷;有关详细信息,请参阅 `NumericToRawBytes`。
要从 `外部地址` `externaddr` `检索外部值`,请执行以下步骤
-
断言:`type` 不是 `v128`。
-
如果 `type` 是 `i64`,
-
令 `i64` 为 `?` `ToBigInt64`(v)。
-
返回 `i64.const` `i64`。
-
-
如果 `type` 是 `i32`,
-
如果 `type` 是 `f32`,
-
如果 `type` 是 `f64`,
-
如果 `type` 是 `funcref`,
-
如果 `type` 是 `externref`,
-
如果 `v` 为 null,
-
如果存在 `外部地址` `externaddr`,使得 `map`[externaddr] 与 `v` 相同,
-
返回 `ref.extern` `externaddr`。
-
-
令 `外部地址` `externaddr` 为最小的地址,使得 `map`[externaddr] `存在` 为 false。
-
将 `map`[externaddr] `设置` 为 `v`。
-
返回 `ref.extern` `externaddr`。
-
-
断言:此步骤不会被执行。
4.7. 错误对象
WebAssembly 定义了以下错误类:`CompileError
`、`LinkError
` 和 `RuntimeError
`。
WebAssembly
命名空间 创建命名空间对象 时,必须运行以下步骤。-
令 namespaceObject 为 命名空间对象。
-
对于 « "CompileError", "LinkError", "RuntimeError" » 中的每个 error,
-
令 constructor 为一个新的对象,实现 原生错误对象结构,其中 NativeError 设置为 error。
-
! DefineMethodProperty(namespaceObject, error, constructor, false)。
-
注意: 这在 WebAssembly
命名空间上定义了 CompileError
、LinkError
和 RuntimeError
类,这些类是由本规范中定义的 API 生成的。它们公开了与原生 JavaScript 错误(如 TypeError
和 RangeError
)相同的接口。
注意: 目前无法使用 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 并崩溃。这里两者都是有效的。
-
一个
RangeError
,如Memory
grow()
和Table
grow()
操作中指定的那样 -
返回 -1 作为 memory.grow 指令
-
本节中描述的 UA 特定 OOM 行为。
有关进一步的讨论,请参阅 问题 879。
6. 实现定义的限制
WebAssembly 核心规范允许实现定义模块语法结构的限制。虽然 WebAssembly 的每个嵌入都可能选择定义自己的限制,但为了可预测性,本文件中描述的标准 WebAssembly JavaScript 接口定义了以下确切限制。如果实现遇到超出以下限制之一的模块,则必须使用 CompileError
拒绝该模块:在实践中,实现可能会在低于这些限制的有效模块上耗尽资源。
- 模块的最大大小为 1,073,741,824 字节(1 GiB)。
- 类型部分中定义的最大类型数为 1,000,000。
- 模块中定义的最大函数数为 1,000,000。
- 模块中声明的最大导入数为 100,000。
- 模块中声明的最大导出数为 100,000。
- 模块中定义的最大全局变量数为 1,000,000。
- 模块中定义的最大数据段数为 100,000。
- 最大表数(包括声明的或导入的表)为 100,000。
- 一张表的最大大小为 10,000,000。
- 任何表初始化中最大表项数为 10,000,000。
- 最大内存数(包括声明的或导入的内存)为 1。
- 任何函数或块的最大参数数为 1,000。
- 任何函数或块的最大返回值数为 1,000。
- 函数体(包括局部变量声明)的最大大小为 7,654,321 字节。
- 函数中声明的最大局部变量数(包括隐式声明为参数)为 50,000。
如果在运行时超出以下限制之一,实现必须抛出 RuntimeError
:在实践中,实现可能会在低于这些限制的有效模块上耗尽资源。
- 一张表的最大大小为 10,000,000。
- 内存的最大页数为 65,536。
7. 安全和隐私注意事项
本节为非规范性内容。
本文件定义了 WebAssembly 的主机环境。它允许 WebAssembly 实例从 导入对象 中 导入 JavaScript 对象和函数,但除此之外不提供对嵌入环境的任何访问。因此,WebAssembly 实例受与 JavaScript 相同的约束。