内容提要
本文介绍了WebAssembly中的Table对象及其在JavaScript与wasm模块之间的交互。Table用于存储函数引用,支持funcref和externref类型。通过示例,展示了如何将wasm函数存储在Table中并通过JavaScript调用,以及如何将JavaScript函数存储在Table中供wasm模块使用。文章还讨论了call_indirect指令的使用,并强调了wasm对externref的限制。
延伸解读
Table 与 Memory 的差异
文章指出,Memory 面向二进制字节读写,使用不便;而 Table 存储的是对象引用,可直接读取消费。Table 目前仅支持 funcref 和 externref 两种引用类型,分别对应 wasm 原生函数和宿主 JavaScript 对象。这种设计让 Table 更适合传递函数引用,而非原始数据。
call_indirect 的签名约束
通过 call_indirect 间接执行 Table 中的 wasm 函数时,必须指定函数类型签名。文章示例中四个运算函数签名一致,因此定义了一个 $i32_i32_i32 类型。这意味着 Table 中存储的函数必须与 call_indirect 指定的类型匹配,否则无法正确调用。
externref 的消费限制
文章强调,JavaScript 函数只能以 externref 形式存入 Table,wasm 模块无法直接解引用或消费这些函数。但可以通过导入宿主函数(如 $apply)将 externref 回传到 JavaScript 中执行。这揭示了 wasm 与宿主交互时的一种常见模式:wasm 负责调度,宿主负责执行。
Q&A
WebAssembly中的Table对象有什么作用?
Table对象用于存储函数引用,支持funcref和externref类型,方便在JavaScript与wasm模块之间进行交互。
如何在JavaScript中调用存储在Table中的wasm函数?
可以通过获取Table对象并使用get方法来调用存储在Table中的wasm函数,例如table.get(index)(参数)。
为什么JavaScript函数不能直接存储在Table中供wasm模块使用?
因为JavaScript函数只能以externref形式存储在Table中,而wasm模块无法对externref进行解引用,因此不能直接消费这些函数。
call_indirect指令在WebAssembly中如何使用?
call_indirect指令用于间接调用存储在Table中的wasm函数,需指定函数的类型和参数。
如何将JavaScript函数回传到宿主应用中执行?
可以将JavaScript函数以externref形式存储在Table中,然后通过wasm模块调用宿主应用中的函数。
WebAssembly中的funcref和externref有什么区别?
funcref用于存储wasm原生函数,而externref用于存储宿主程序提供的JavaScript对象。