WebAssembly 功能检测与模块可移植性
探测运行时能力,区分验证、编译和实例化失败,并在保留用户输入的同时交付可恢复的回退路径。
BotBrowser Team
可移植性是运行时的交付决策。浏览器即使暴露 WebAssembly 对象,也可能拒绝某条指令、某种内存限制或某个宿主导入项。可靠的应用应在实际页面中探测候选产物,区分失败阶段,选择预先准备的回退,并保留用户任务。保护的对象是用户正在完成的工作,而不是抽象的浏览器分数。
运行时能力探测
先建立简短且有名称的能力记录,包含任务编号、模块摘要、功能层级、导入契约版本和页面上下文。检查 API 是否存在、请求是否返回预期字节、页面策略是否允许目标 worker 或窗口。属性检查只是下一步操作的门槛,不是设备指纹。每次探测都应回答一个产品问题,例如 image-filter-v4-simd 是否可用。
对选择器真正会交付的字节运行 WebAssembly.validate(bytes)。返回 true 只表示引擎接受二进制结构和功能集合,并不代表导入、分配或输出都能工作。返回 false 时记录产物摘要并切换到另一层级,不要在同一字节上无休止重试。SIMD、共享内存、大线性内存等可选能力应分别探测,因为一个环境可能支持 SIMD 却不满足页面隔离要求。
探测必须发生在生产上下文建立之后。预览页、worker 和跨源隔离页面的策略及导入面可能不同。把获取失败、策略阻止、网络超时和二进制拒绝分开记录;它们都会阻止首选路径,但只有最后一种直接说明引擎不接受产物。能力信息只保留做出选择和处理用户报告所需的最小字段。
三个失败阶段
代码和支持记录统一使用验证、编译、实例化三个阶段。返回 { stage: 'instantiate', code: 'missing-import' } 这样的应用状态,不要把引擎异常文本当作合同。验证失败表示字节格式或功能层级不被接受,导入尚未解析。编译失败发生在结构通过之后,可能是资源或实现限制。实例化失败表示代码已生成但无法连接宿主,常见原因是导入签名、表或内存不匹配。
导出函数执行后的领域错误属于第四类应用结果,不应误报为“不支持 WebAssembly”。阶段分类能让维护者修复正确边界,也能让用户知道是模块不可用、宿主契约不匹配,还是输入需要调整。记录摘要、阶段、版本和用户任务,不依赖不同浏览器会变化的错误文字。WebAssembly Core 规范提供二进制和执行术语,产品提示应保持易懂。
回退交付
把基础 WebAssembly、标量版本和 JavaScript 实现当作正式交付物。每条路径都定义输入、输出和限制,选择器选择满足任务合同的最快路径。首选路径验证或编译失败后,从本次会话的候选中移除它;实例化失败时只尝试不同的导入图或不同产物。缓存键应包含产物摘要、功能层级和宿主契约版本。
界面要说明当前路径及原因,并提供不会清除输入的重试。较慢但输出相同的路径仍然是成功;精度或输入规模降低时,应在用户确认前说明。使用相同夹具测试有效快路径、验证拒绝、编译压力、缺少导入、基础路径、取消和重试。BotBrowser 文档说明 baseline、Turbo 和 SIMD 管线中的 JavaScript 与 WebAssembly 对齐;该说明只适用于这些记录管线,不保证所有引擎输出相同。
保留用户输入
探测前创建稳定的任务记录,保留原始文件、文本或字节源。若模块取得缓冲区所有权,应先复制或保留可重新读取的来源,失败候选不得消耗唯一副本。适配器从稳定记录转换为每个模块需要的对齐和指针格式,再转换回统一的应用表示。取消时标记任务、释放模块内存,并阻止迟到的 Promise 覆盖当前视图。
隐私要求贯穿每条路径。本地执行并不证明数据没有离开页面;回退可能需要网络请求或服务器处理。能力日志不得包含原始输入。路径切换也要满足可访问性:公告状态、保留焦点、让输入继续可见。可参考浏览器版本验证清单和API 兼容与功能回退指南。
固定发布记录
扩大支持范围前冻结记录:模块和回退摘要、编译链接设置、功能层级、导入版本、夹具、页面策略、浏览器配置及三个阶段结果。正确性证据与耗时证据分开,固定输入后再比较编译器或浏览器变化。保留负面证据,例如最旧配置拒绝 SIMD、标量模块实例化并产生预期输出。修订应创建带原因的新记录,而不是改写旧记录。
发布说明写明任务、首选层级、回退层级、测试范围、缓存刷新和恢复方式,不宣称普遍支持。公共术语可参阅 MDN WebAssembly;BotBrowser 的能力说明见 Advanced features。运行时流程可以简化为:在真实上下文探测,分别分类三个阶段,选择回退,保留输入,发布不可变证据。
BotBrowser 文档记录 baseline、Turbo 和 SIMD 管线中的 WebAssembly 能力,但不保证每个浏览器引擎或宿主产生相同结果。
应用可以在任务开始前显示选中的能力层级。
摘要值用于确认缓存中的字节确实是预期产物。
HTTP 响应应保留声明的类型和长度。
新 worker 需要重新检查自己的导入项。
共享内存需要并非所有页面都具备的条件。
标量版本可能更慢,但仍可提供相同合同。
过大的输入可能触发资源上限。
长时间运行的任务应提供取消操作。
取消状态不应隐藏原始内容。
第二次运行可以发现未释放的内存引用。
支持记录只标识产物,不收集私有数据。
诊断保留期限应在收集前确定。
导入契约版本应随每次发布保存。
编译器更新可能改变可用功能集合。
小型夹具有助于定位验证拒绝。
实例化测试应使用生产中的适配器。
临时输出不应覆盖已确认结果。
错误文字应由稳定的应用代码翻译生成。
旧配置应获得明确且经过测试的路径。
只有路径合同允许时才向服务器发送数据。
离线页面应说明当前可用的模块。
键盘焦点应留在启动任务的控件上。
屏幕阅读器应播报实现路径的变化。
已撤下产物的摘要仍应留在历史记录中。
修正内容应创建新的发布记录。
负面证据能防止误删必要的回退。
最终检查比较任务、输入、输出和可见限制。