WASI 0.3.0 获批发布。版本号不吓人,真正值得看的是一句话:WASI 开始把异步 I/O 放回 WebAssembly Component Model 的原生 async 里处理。

这不是 WebAssembly 突然更快了。材料只支持一个判断:接口模型变干净了,开发和适配路径会跟着变。0.2 时代为了表达异步绕出来的 pollable、input/output-stream、start/finish、outparam,现在被 future、stream 和 async func 接管。

发生了什么:0.2 的异步绕法,被 0.3 收束了

WASI 0.2 的问题,不是语义错了,而是表达方式太像临时脚手架。

没有 Component Model 原生 async 时,标准只能用资源、轮询、开始/结束函数、输出参数去拼异步调用。能用,但不顺。到了 0.3,很多接口变成了语言级抽象能直接表达的样子。

变化点WASI 0.2WASI 0.3
等待异步结果pollable + pollfuture<T> + await
字节流input-stream / output-stream resourcestream<u8>
异步函数start-foo / finish-foofoo: async func
HTTP 返回response-outparamasync handle 返回 response
完成信号额外资源或 pollablefuture<result<_, error-code>>

几个接口最能说明问题。

CLI stdio 不再是拿到 output-stream 再写入,而是转向 stream<u8>,并用 future 表达完成信号。filesystem 的读写也类似:数据流用 stream,完成与错误用 future 交代。

sockets 删除了 network resource。这里容易误读:网络权限没有被放宽,安全边界也没有消失。变化是授权位置挪到 world imports。TCP、UDP、name-lookup 的错误码也做了统一,连接、监听、接受连接等 start/finish 模式改成 async func。

wasi:http 是最显眼的一刀。0.2 里靠 incoming/outgoing、request/response、body、future response/trailers 等 8 类资源拼出 HTTP 流程。0.3 压到 request 和 response 两个核心资源。body 用 stream<u8>,trailers 用 future。handler 也从带 response-outparam 的函数,变成 async func(request) -> response。

它还新增了 service 和 middleware world。对做服务端 Wasm、边缘网关、插件式中间件的人来说,这比接口名字更关键:请求链路终于有了更正式的组件位置。

clocks 变化小一些,主要是命名规范化。wall-clock 改 system-clock,datetime 改 instant;定时器从 pollable 转向 await host 提供的 timer future。

谁受影响:终端用户先不用急,runtime 和工具链要动

这次发布不太会马上改变普通用户的体验。它更像一次底层接口换轨。

最相关的是两类人。

一类是 WASI runtime、组件框架、测试套件维护者。他们要把 0.2 的适配层迁到 0.3 的 async 模型上。接口变化多数可以机械迁移,但测试不能省。尤其是 HTTP、sockets、filesystem 这些高频 I/O 路径,任何一处抽象没对齐,都会变成兼容坑。

另一类是已经吃进 WASI 0.2 接口的库和工具链团队。他们的动作不会是“立刻全量切换”,更现实的是先做兼容分支、迁移封装层、延后把 0.3 设为默认目标。已经围绕 pollable、start/finish、outparam 写过胶水代码的团队,会发现旧抽象成了迁移负担。

这就是这次的现实约束:官方说很多变化是机械性的,这个判断大体可信;但机械性不等于零成本。代码能批量改,语义边界、测试用例、文档和开发者心智都要重新对齐。

采购或技术选型也要克制一点。如果团队正在评估服务端 Wasm 平台,不该只看“是否宣布支持 WASI 0.3”。更该问三件事:runtime 是否支持 Component Model async,HTTP 和 sockets 是否按 0.3 模型落地,测试套件是否跟上。

这几个问题答不上来,所谓支持就还停在 README 里。

真正的信号:标准成熟,常常先表现为删东西

我更在意的不是接口改名,而是 WASI 在补服务端 Wasm 的基本秩序。

过去几年,浏览器之外的 Wasm 叙事很热:边缘计算、插件系统、安全沙箱、云函数、可移植组件。听起来都对。但真要跑服务端和中间件,绕不开网络 I/O、HTTP、文件系统、时钟、流式数据。

接口一绕,生态就跟着绕。

runtime 绕一层,框架绕一层,测试再绕一层。最后大家都说自己兼容,细节里全是分叉。WASI 0.2 的设计不是失败,它是在缺少原生 async 的条件下,把异步语义硬表达出来。

这有点像早期铁路的轨距问题。不完全一样,但逻辑相近:工程先跑,标准后追;等网络越铺越大,临时方案就会变成成本。

WASI 0.3 做的事,就是拆脚手架。

标准成熟不总是加新能力。很多时候,成熟先表现为删除多余路径,把同一件事收束到一种更稳的表达里。future、stream、async func 不是花活,它们让 I/O、HTTP、文件系统这些基础接口回到更正常的形态。

当然,账还没结完。

接下来最该看的,不是有没有更多发布新闻,而是下游执行速度:主流 runtime 什么时候稳定支持 0.3,组件框架多久完成迁移,测试套件能不能覆盖 HTTP、sockets、filesystem 这些容易出错的边界。

如果这些地方跟不上,0.3 就只是标准文本变漂亮。生态真正变顺,要等工具链把脏活做完。

“名不正,则言不顺。”放在这里很贴切:async 的名分不正,I/O 就总要绕路。WASI 0.3 把名分补上了,剩下看 runtime 和工具链能不能把旧账结清。