Bun کامل از Zig به Rust بازنویسی شد
خلاصهٔ کاملتر
Bun اولش یه پورتِ خطبهخط از ترنسپایلر جاوااسکریپت و تایپاسکریپتِ esbuild از Go به زبان Zig بود. نویسنده میگه دامنهٔ کار از همون اول عظیم بود: ترنسپایلر و باندلر، پکیجمنیجرِ سازگار با npm، تسترانرِ شبیه Jest، پیادهسازی APIهای Node.js و کلی چیز دیگه. الان CLIِ Bun ماهانه بیش از ۲۲ میلیون بار دانلود میشه و ابزارهایی مثل Claude Code و OpenCode روش حساب باز کردن.
ولی همین دامنهٔ بزرگ، پایداری رو هم سخت کرده. به گفتهٔ نویسنده، ریشهٔ خیلی از باگها اینه که Bun باید همزمان با حافظهٔ garbage-collectedِ موتور JavaScriptCore و هم با حافظهٔ دستیمدیریتشدهٔ Zig سروکله بزنه. Zig مثل C حافظه رو برات مدیریت نمیکنه و سازنده/مخرب (destructor) نداره، برای همین پاکسازی باید دستی با کلمهٔ کلیدی defer نوشته شه. همین باعث نشتی حافظه و گاهی کرشهای use-after-free میشد.
نویسنده میگه بیشتر این باگها از نوع use-after-free، double-free یا «یادمون رفت آزاد کنیم» تو مسیرهای خطا بودن؛ چیزهایی که تو Rustِ امن اصلاً خطای کامپایلرن و با Drop خودکار تمیز میشن. اونها قبلاً به فکر افتاده بودن یه اشارهگر هوشمندِ دستسازِ شبیه Rust به Zig اضافه کنن، ولی نویسنده میگه این کار هم بدقوارهست و هیچکدوم از تضمینهای Rust رو نداره. کدِ Zig با این اشارهگرها یه چیزی تو این مایهها میشد:
fn foo(a_ptr: SharedPtr(TCPSocket)) !void {
const a: *TCPSocket = a_ptr.get();
defer a_ptr.deref();
const b = try do_something_with_a(a);
defer b.deref();
// ...
}بهجای این راه، سازنده تصمیم گرفت یه هفته امتحان کنه ببینه مدل جدید Anthropic میتونه Bun رو به Rust بازنویسی کنه یا نه. نویسنده میگه بازنویسیها معمولاً ایدهٔ بدیان، برای همین بهجای بازنویسی تدریجی، یه پورتِ مکانیکیِ Zig به Rust رو انتخاب کرد که معماری و مجموعهقابلیتها عین قبل بمونه. نکتهٔ کلیدی این بود که تستسوئیتِ خودِ Bun با تایپاسکریپت نوشته شده، پس به زبانِ runtime وابسته نیست و میشد باهاش کدِ جدید رو سنجید.
کل کار با حدود ۵۰ ورکفلوی پویا تو Claude Code و در طول ۱۱ روز انجام شد. نویسنده یه ترفند جالب داشت به اسم «بازبینیِ خصمانه»: یه Claude نقش پیادهساز رو داشت و دو Claudeِ دیگه فقط بازبین بودن؛ بازبینها تو کانتکستِ جدا فقط diff رو میدیدن و بهشون گفته شده بود فرض کنن کد غلطه و دنبال باگ بگردن. همین روش چند باگ واقعی مثل use-after-free تو بستنِ ناهمگامِ لولهها و یه پنیکِ ناشی از ارزیابیِ زودهنگام رو قبل از merge گرفت.
این مسیر بیدردسر نبود؛ نویسنده میگه اولش چند Claude با دستورهای git stash و reset افتادن به جونِ همدیگه، برای همین کار به چند worktree جدا تقسیم شد و اجرای دستورهای کندی مثل cargo و git تا آخر ممنوع شد. تقسیم کد به حدود ۱۰۰ کریت هم حدود ۱۶ هزار خطای کامپایلر درآورد که کریتبهکریت رفع شدن. یه نکتهٔ مهم هم اینه که شرکت Anthropic دسامبر ۲۰۲۵ صاحبِ Bun شده و تیمش الان اونجا کار میکنن.
نکات کلیدی:
- Bun داره از Zig به Rust بازنویسی میشه تا باگهای حافظه ریشهای حل شن
- ریشهٔ اصلیِ باگها ترکیبِ حافظهٔ GCِ JavaScriptCore با مدیریت دستیِ Zig بود
- Rustِ امن این خطاها رو موقع کامپایل میگیره، برخلاف Zig
- بازنویسی عمدتاً با مدل جدید Claude و در ۱۱ روز و ۶٬۵۰۲ کامیت انجام شد
- روش «بازبینیِ خصمانه» با Claudeهای جدا چند باگ واقعی رو قبل از merge گرفت




