Robobun 修復 Bun 模組載入器的 UTF-8 編碼錯誤
Bun 的 PR #33864 修復了一個模組載入器錯誤:當使用 `--target=bun` 且包含非 ASCII 的 banner/footer 時,UTF-8 位元組被錯誤地解釋為 Latin-1,導致文本亂碼和語法錯誤。修復後,載入器正確解碼 UTF-8,同時保持 ASCII 快速路徑。此外,還修復了位元組碼快取鍵不匹配的問題。
Bun 專案的 PR #33864 近日修復了一個影響模組載入器的編碼問題。當開發者使用 bun build --target=bun 並新增自定義 banner 或 footer 時,如果這些內容包含非 ASCII 字元(如中文或表情符號),Bun 會錯誤地將 UTF-8 編碼的位元組當作 Latin-1(ISO 8859-1)處理。這種誤解導致字串字面量出現亂碼(mojibake),而非 ASCII 識別符號則直接丟擲 SyntaxError。
問題根源在於,Bun 的內建模組載入器在遇到 // @Bun 編譯指示時,會將檔案直接交給 JavaScriptCore(JSC)處理。然而,載入器在構建內部字串時使用了 String::clone_latin1 方法,該方法將每個位元組視為一個 Latin-1 程式碼單元。對於大部分由 ASCII 字元組成的程式碼來說,這並無問題;但當 banner/footer 包含 UTF-8 編碼的非 ASCII 字元時,多位元組序列被拆解為多個 Latin-1 字元,導致資料損壞。
Robobun 的修復方案是將兩處載入邏輯改為使用 String::clone_utf8。新方法利用了 simdutf 庫:對於純 ASCII 輸入,它仍透過快速路徑使用 Latin-1 複製(效能不變);對於非 ASCII 輸入,則正確執行 UTF-8 解碼。這一改動確保了無論是原始碼還是附加的 banner/footer,都能以正確的編碼格式傳遞給 JSC。
修復並未止步於此。隨後的提交(68c1594)發現,當同時啟用 --bytecode 標誌時,位元組碼快取也會受到影響。由於快取鍵(SourceCodeKey)在載入器和程式碼生成器之間使用了不同的字串構造方式——載入器生成 UTF-8 解碼的鍵,而快取生成器仍使用 Latin-1 鍵——導致 decodeCodeBlock 拒絕匹配,JSC 不得不重新解析程式碼,使得預編譯的 .jsc 檔案成為無效的負擔。該提交透過一個輔助函式統一了兩種場景下的字串構造,該函式同樣利用 simdutf 進行 ASCII 快速路徑或 UTF-8 解碼。
PR #33864 由 Robobun 編寫,Claude 機器人進行了程式碼審查,並標記了“claude”和“slop”標籤。雖然 CI 在多種平臺上出現了 5 項測試失敗(包括 WebSocket、WebView 和代理壓力測試),但其中部分失敗與本次編碼修復無關。最終,該 PR 在 2026 年 7 月 9 日被關閉併合並。此修復對於需要國際化支援或使用自定義 banner 的 Bun 使用者來說至關重要,它消除了一個可能在生產環境中引發隱蔽錯誤的源頭。