Node.js 此版本调整了错误处理,在无法使用 WebAssembly 的环境中调用相关功能时,会抛出可区分原因的错误。处理受限运行环境的开发者更容易定位失败原因,WebSocket 库开发者则可将对传输数据应用和移除掩码的运算迁移至内置功能。
官方公告将这两项列为本次版本的主要变更,该版本于 2026年10月14日发布。两项均被归类为次要变更。
1. 区分不受支持环境中的失败原因
WebAssembly 是一种运行单独编译模块的技术。根据错误处理变更说明,在无法使用该技术的环境中导入相关模块时,会触发 ERR_WEBASSEMBLY_NOT_SUPPORTED。它通过程序可捕获并处理的错误告知功能不可用。
不过,不应将错误处理变更理解为原本正常的功能现在开始失败。审查讨论将其解释为更恰当地报告既有错误的改进。
高速调用外部库函数的路径也在调整范围内。即使满足其他调用要求,若可读且可执行内存的支持检查失败,也会通过 ERR_RX_MEMORY_NOT_SUPPORTED 告知原因。回调分配失败后也会诊断此项支持情况,但会保留各平台的静态调用衔接方式及其他错误。
文档还明确指出,缺少必要执行能力时,不保证提供替代路径。也就是说,能够捕获错误并不意味着会以其他方式执行该功能。此外,还新增了针对禁用即时编译的运行模式和 Linux 系统调用受限环境的回归测试。
2. 将 WebSocket 的重复运算迁移至内置功能
WebSocket 客户端会对发送的每个帧,也就是传输单元,重复应用 4字节密钥来掩码数据。服务器通过相同运算还原数据。该运算采用异或,即两侧位不同时结果为 1,因此再次使用同一密钥即可恢复原始数据。
http.websocketMask() 接收源数据和输出位置,执行掩码运算;http.websocketUnmask() 则直接在收到的缓冲区中移除掩码。这并非通用数据掩码功能,而是针对 WebSocket 规定的密钥长度设计的功能。
其参数形式与现有原生扩展模块 bufferutil 保持一致。因此,使用该扩展的库可在检查新函数是否存在后切换。变更提案作者表示,该扩展的安装量约为 ws 下载量的 3%,其余用户主要依赖 JavaScript 循环。
3. 仍需负责准备密钥
掩码以 ArrayBufferView 形式传入,它指向一段内存区域。审查中未采纳同时接受数字数组的建议,而是保持与现有扩展的兼容性。作者建议从通信库已有缓冲区中取出 4字节区域,避免为每个帧分配数组。原文给出的表达式如下。
buffer.subarray(bufIdx, bufIdx += 4)这不是新函数的完整调用示例,而是获取存放密钥的内存区域的表达式。运算内置并不意味着可以省略密钥选择。审查讨论引用的规范要求为每个帧使用难以预测的新密钥,也指出服务器实际收到的是已应用掩码的数据。
4. 需结合输入大小看待性能收益
WebSocket 变更的提交说明称,相比 JavaScript 循环,1 KiB 输入的处理速度约为 20倍,64 KiB 时约为 40倍。说明给出的快于现有扩展的范围是 32字节及以上。另一方面,作者解释说,在小于 24字节时,由于内部函数调用开销,循环反而更快。未提供测量所用的硬件和操作系统。
其优势在于,无需安装额外扩展,即可将重复运算迁移至内置实现。不过,库开发者仍需考虑对旧版本进行功能存在性检查,以及按输入大小选择执行路径。因此,不宜将给出的运算速度差异解读为整个 WebSocket 服务的吞吐量提升。
相比扩展普通应用的功能,此版本对处理受限运行环境和 WebSocket 实现的开发者更有意义。
