开发者生态
morning
用 Rust 重写 Bun
2026-07-09
1 阅读
约7分钟阅读
afturner
字号:
披露:Bun 于 2025 年 12 月被 Anthropic 收购。我和 Bun 团队的其他人在 Anthropic 工作。我使用 Claude Fable 5 的预发布版本进行大部分 Rust 重写。 Bun 最初是作为 esbuild 的 JavaScript 和 TypeScript 转译器从 Go 到 Zig 的逐行移植。我于 2021 年 4 月 16 日写了第一行 Zig 。在看到 Hacker News 上的单页 Zig 语言参考并对底层控制和对性能的关注感到非常兴奋后,我押注于 Zig。从一开始,Bun 的范围就很大:JavaScript、TypeScript 和 CSS 转译器、压缩器和捆绑器 npm 兼容的包管理器 Jest 式测试运行器 Node.js 和 TypeScript 兼容的模块解析 HTTP/1.1 和 WebSocket 客户端 Node.js API 实现,如 fs 、 net 、 tls 和数十个其他模块 Bun 的初始版本是我在一年内编写的,在 Zig 的奥克兰一间狭窄的公寓中,预科法学硕士。像 Bun 这样规模宏大的项目的默认结果是加入 GitHub 个人资料页面上的死角项目的墓地。 Zig 使 Bun 成为可能。如果没有 Zig,我不可能在一年内建造这么多。如今,Bun 的 CLI 每月下载量超过 2200 万次。 Claude Code 和 OpenCode 等流行工具都将 Bun 作为它们的运行时。 Vercel、Railway、DigitalOcean 等都为 Bun 提供第一方支持。 Bun 的范围也对稳定性构成了挑战。以下是我们在 Bun v1.3.14 中修复的一小部分错误: 在 zlib、Brotli 或 Zstd 流上调用 .reset() 时,node:zlib 中的堆释放后使用崩溃,而异步 .write() 仍在线程池上释放后使用崩溃 当 onerror 回调在本机句柄上发出可重入 write() 后紧跟 close() 时,释放后使用崩溃node:http2 当可重入的 JS 回调(例如超时侦听器、选项 getter 或写入回调内的 session.request())触发哈希图重新哈希时,使 UDPSocket.send() 和 sendMany() 中的内部流指针释放后使用无效,其中 valueOf() 或 toString() 回调中的用户代码可能会在有效负载捕获和实际发送崩溃之间分离 ArrayBuffer,并在 Buffer#copy 和中读取越界Buffer#fill 当 valueOf 回调在参数强制期间分离或调整底层 ArrayBuffer 大小时 UDPSocket.sendMany() 中的越界写入 当套接字的连接状态通过用户 JS 回调在迭代中更改时 crypto.scrypt 中的内存泄漏 当输出缓冲区分配失败时,回调和受保护的密码/盐缓冲区从未被释放 SSLWrapper.init 在错误路径上泄漏了 strdup 密码短语 内存泄漏tlsSocket.setSession() 其中,由于 d2i_SSL_SESSION 内存泄漏后缺少 SSL_SESSION_free,每个调用泄漏了一个 SSL_SESSION (每次调用约 6.5 KB),其中 fs.watch() 观察者在 .close() 之后从未进行垃圾收集,这是由于引用计数下溢导致,当背景剪辑具有供应商前缀和多层背景时,引用计数下溢将每个观察者永久固定为 CSS 解析器中的 GC 根双释放崩溃DuplexUpgradeContext 从未被释放 - MessageEvent 中的 tls.connect({ socket: duplex }) 竞争条件崩溃导致完全泄漏,其中 GC 标记线程可以在从 BroadcastChannel 或 MessagePort 并发访问期间观察到 m_data 中的撕裂变体。我们本可以永久地一次性修复此类错误,但我们应该感谢我们的用户,他们指望我们做得更好,并系统地防止此类错误再次出现。我们已经在做什么 我们修补了 Zig 编译器以添加 Address Sanitizer 支持。我们在每次提交时都使用 ASAN 运行测试套件。我们在 Windows 上发布 Zig 安全检查的 ReleaseSafe 版本 我们使用 V8 和 JavaScriptCore 使用的 JavaScript 引擎模糊器 Fuzzilli 对 Bun 的运行时 API 24/7 进行模糊测试 我们进行了大量的端到端内存泄漏测试 这比许多项目所做的还要多。只是要非常聪明并且不犯错误吗?我们的错误修复列表感觉很糟糕,我厌倦了睡觉时担心 Bun 的崩溃。我不会为此责怪 Zig - Zig 的其他用户没有我们遇到的错误,并且将 GC 与手动管理内存混合对于软件来说是一件不常见的事情,没有语言真正为此设计。如果没有 Zig,我们不可能走到这一步,我将永远感激不已。直到最近,对于像 Bun 这样的项目来说,编程语言的选择还是一种单向决策。 JavaScript 是一种垃圾收集语言,像 JavaScriptCore(和 V8)这样的现代 JavaScript 引擎对于异常处理和垃圾收集器有严格的规则。 Zig 与 C 一样,不为您管理内存,这是一个权衡,对于许多项目来说,这是使用 Zig 的一个重要原因。 Zig 没有构造函数/析构函数,并且大多数清理工作预计会在每个调用站点使用 defer 显式编写。对于 Bun 来说,正确处理垃圾收集值和手动管理值的生命周期一直是稳定性问题的主要根源 - 大多数情况下
这篇文章对您有帮助吗?
订阅66必读
每日精选科技资讯,直达你的邮箱