Bun

Bun v1.2.2


Jarred Sumner · 2025年2月1日

我們正在舊金山招聘系統工程師,共同打造 JavaScript 的未來!

此版本修正了 38 個錯誤 (解決了 129 個 👍)。JavaScript 閒置記憶體用量降低了 10–30%。修復了影響 vite 建置的迴歸問題。改善了 Bun.SQL、Bun.S3Client、Bun 的 CSS 解析器的可靠性。Node.js 相容性改進:fs.glob、fs.globSync、fs.promises.glob、fs.Dir、fs.accessSync 錯誤修復、node:http WebSocket 導出。

安裝 Bun

curl
npm
powershell
scoop
brew
docker
curl
curl -fsSL https://bun.dev.org.tw/install | bash
npm
npm install -g bun
powershell
powershell -c "irm bun.sh/install.ps1|iex"
scoop
scoop install bun
brew
brew tap oven-sh/bun
brew install bun
docker
docker pull oven/bun
docker run --rm --init --ulimit memlock=-1:-1 oven/bun

升級 Bun

bun upgrade

JavaScript 在閒置時減少 10% - 30% 的記憶體用量

已修復排程問題,該問題導致 JavaScriptCore 的垃圾收集器計時器並非總是執行。現在 Bun 會在其事件迴圈中同時執行 Bun 自己的垃圾收集計時器和 JavaScriptCore 的垃圾收集計時器。

Next.js 閒置記憶體用量降低了 28%

Elysia 閒置記憶體用量降低了 11%

此變更影響從 Next.js、Express 和 Elysia 到 TypeScript (tsc)、CLI 工具等等的所有項目。

計時器與 GC

JavaScriptCore 的垃圾收集器有多個計時器,用於在記憶體分配的適當時間觸發垃圾收集(在記憶體分配期間可能會發生單獨的垃圾收集執行)。

先前,這些計時器未與 Bun 的事件迴圈整合。現在已修復此問題,並且當事件迴圈在系統呼叫中被封鎖時,現在會觸發這些垃圾收集計時器。

SIGPWR GC 信號

當垃圾收集器執行時,它需要某種方式來暫停執行緒。

在 macOS 和 Windows 上,有系統 API 可用於暫停執行緒。

Linux 不提供任何用於暫停執行緒的 API,因此許多語言執行時期的垃圾收集器都依賴 POSIX 信號來暫停執行緒。

JavaScriptCore 預設使用 SIGUSR1 用於此目的,但許多應用程式依賴 SIGUSR1 進行其應用程式邏輯(最常見於重新啟動伺服器之類的事情)。這是一個衝突,它會中斷垃圾收集或中斷依賴 SIGUSR1 的應用程式。

Bun 現在在 Linux 上使用 SIGPWR,這是最初旨在提醒系統機器電源已切斷的信號。Mono (.NET 的執行時期) 也將此信號用於相同的目的。

感謝 @190n 的貢獻!

Bun.SQL 可靠性改進

我們修復了 Bun 內建 PostgreSQL 用戶端中的幾個錯誤,這些錯誤可能會在特定邊緣情況下同時執行許多不同的預處理語句時,導致查詢掛起或意外失敗。

import { sql } from "bun";

// Queries now execute reliably in sequence
const results = await Promise.all([
  sql`SELECT 1`,
  sql`SELECT 2`,
  sql`SELECT 3`,
]);

這些變更還改善了錯誤處理,並修復了當連線意外關閉時可能導致失敗查詢掛起的一些情況。

感謝 @cirospaciari 的貢獻!

$NODE_PATH 支援

Bun 現在支援從 $NODE_PATH 環境變數中指定的路徑載入 node_modules。這與 Node.js 從父 node_modules 資料夾外部解析模組的行為一致。

export NODE_PATH="/path/to/global/modules"
bun run my-script.js

執行

my-script.js
// Bun will now check NODE_PATH when resolving imports
import { someModule } from "some-module";

感謝 @paperclover 的貢獻!

已修復:Bun v1.2.1 中的 vite build 迴歸問題

vite build 命令現在再次正確運作。

在 Bun v1.2.1 中,對 fs.WriteStream 實作的微小變更暴露了 Bun 的事件迴圈在非同步寫入檔案時的錯誤。此錯誤導致 vite build 在某些情況下寫入不正確或交錯的資料,導致建置失敗。底層錯誤已修復,並且我們透過編寫更多單元測試、整合測試以及新增額外的 node.js 測試來改進我們的測試覆蓋率,以在未來捕獲類似問題。

我們還新增了在 Bun 程序退出之前自動刷新待處理寫入到檔案系統的支援,以便 Bun.file(path).writer() API 不再需要顯式呼叫 flush 來確保刷新任何待處理的寫入。

感謝 @dylan-conway 的貢獻!

已修復:動態導入 "bun" 套件

現在,動態導入 "bun" 套件在 Vite 6 中可以正確運作。先前,使用 import("bun") 會傳回一個解析為 {default: globalThis.Bun} 的模組,而不是實際 Bun 物件的具名導出。在建置時,Bun 的轉譯器會自動將 import("bun") 重寫為 globalThis.Bun,這幾乎總是有效,但是 Vite 6 繞過了 Bun 的轉譯器,從而破壞了此行為。

// Now works correctly
const { SQL, serve, pathToFileURL /* ... */ } = await import("bun");

// Previously returned {default: globalThis.Bun}

Node.js 相容性改進

Nuxt & Vite 6

當從磁碟上不存在的虛擬路徑解析時,createRequire() API 現在可以正確運作。這修復了 Vite 6 中與 Nuxt 的相容性。

const { createRequire } = require("module");

// Virtual path that doesn't exist on disk
const req = createRequire("file:///app/@vue/server-renderer");
const vue = req("vue"); // Now resolves correctly

感謝 @paperclover 的貢獻!

pnpm 現在可與 Bun 搭配使用

Bun 現在將 ResolveMessageBuildMessage 錯誤報告為原生錯誤,這允許 pnpm 在 Bun 內部正確執行。先前,pnpm 會因判斷提示檢查錯誤類型而失敗。

// This now works properly
const types = require("util").types;
assert(types.isNativeError(resolveMessage)); // Previously failed

fs.globfs.globSyncfs.promises.glob

現在您可以使用 glob 模式來尋找具有 fs.globfs.globSyncfs.promises.glob 的檔案。這與 Node.js API 相符

import { glob } from "node:fs/promises";

// Find all JavaScript files recursively
for await (const file of glob("**/*.js")) {
  console.log(file);
}

// With options
for await (const file of glob("**/*.js", {
  cwd: "./src",
  exclude: (path) => path.includes("node_modules"),
})) {
  console.log(file);
}

感謝 @DonIsaac 的貢獻!

注意:目前實作僅支援單一 glob 模式。對陣列模式和 withFileTypes 選項的支援將在未來版本中新增。

已改進:fs.Dir 相容性

fs.Dir 實作現在透過改進的驗證和錯誤處理,更好地符合 Node.js 行為。現在,當嘗試關閉已關閉的目錄或傳遞無效參數時,API 會拋出適當的錯誤。

import { opendir } from "node:fs";

// Now throws if trying to use a closed directory
const dir = await opendir("./");
await dir.close();
await dir.close(); // Throws ERR_DIR_CLOSED

// Validates callback parameters
dir.read("not a function"); // Throws type error for invalid callback

感謝 @nektro 的貢獻!

已修復:Bun 中的 DuckDB 原生模組

DuckDB 原生模組現在可以在 Bun 中正確運作。先前,它會因 napi_register_module_v1 中的空值傳回原生模組而崩潰。

// Native module that returns null
module.exports = require("./null_addon.node");

感謝 @190n 的貢獻!

已修復:file:// URL 編碼

Bun v1.2.1 中的迴歸問題導致 file:// URL 在不應該的情況下錯誤地拋出錯誤。此問題已修復。

已修復:macOS 上的 node:os loadavg() 值

修復了 os.loadavg() 在 macOS 上報告的系統 CPU 負載平均值。這些值現在準確,並且與 uptime 命令報告的值相符。

const os = require("node:os");

// Now returns accurate values on macOS
console.log(os.loadavg()); // [0.23, 0.15, 0.12]

感謝 @190n 的貢獻!

減少 fs.readdirwithFileTypes 的記憶體用量

當使用 fs.readdirwithFileTypes 選項時,已透過最佳化 Dirent 類別的內部實作來減少記憶體用量。

const files = await fs.readdir("./", { withFileTypes: true });
console.log(files[0] instanceof fs.Dirent); // true

此變更影響使用 fs.readdirfs.readdirSyncwithFileTypes: true 的程式碼。API 行為保持不變,但內部使用的記憶體更少。

已修復:Windows 上的 fs.accessSync("../")

Bun 現在可以正確處理 node:fs 函數中包含 ../ 區段的相對路徑。先前,路徑解析在轉換為 Windows 長路徑時會錯誤地剝離這些區段。

import * as fs from "node:fs";

// This now correctly resolves "../.." paths
fs.existsSync("../../config");
fs.accessSync("../../config");

感謝 @dylan-conway 的貢獻!

已新增:node:http 中的 WebSocket 導出

WebSocketCloseEventMessageEvent 全域變數現在從 node:http 重新導出,以獲得更好的 Node.js 相容性。

const { WebSocket, CloseEvent, MessageEvent } = require("node:http");

// These match the global objects
assert.strictEqual(WebSocket, globalThis.WebSocket);
assert.strictEqual(CloseEvent, globalThis.CloseEvent);
assert.strictEqual(MessageEvent, globalThis.MessageEvent);

已修復:node:fs 中 AbortSignal 的記憶體洩漏

修復了當訊號中止時,AbortSignal 物件在 fs.promises.writeFilefs.promises.readFile 和其他檔案系統操作中未正確取消參考的記憶體洩漏問題。

// Previously leaked memory
const signal = AbortSignal.abort();
try {
  await fs.promises.readFile("file.txt", { signal });
} catch (e) {}

// Also fixed for later aborts
const controller = new AbortController();
const signal = controller.signal;
const promise = fs.promises.writeFile("file.txt", "data", { signal });
controller.abort();
try {
  await promise;
} catch (e) {}

CSS 解析器改進

浮點數精確度

CSS 中浮點數的列印已變更為在所有情況下都列印到小數點後 6 位(先前僅在有條件下發生這種情況)。這可以在可忽略的精確度損失下縮小套件大小。

已更新供應商前綴

在 Bun 的編譯時間,Bun 的 CSS 解析器在內部使用 autoprefixer 程式庫來產生 Zig 程式碼,該程式碼會為 CSS 屬性新增供應商前綴。這已更新至最新版本。

穩定性改進

已新增超過 275 個測試,以改進 CSS 解析器的可靠性和穩定性,並且已修復幾個細微的錯誤。

更多錯誤修復

已改進:S3 多部分上傳可靠性

我們修復了 Bun 的 S3 多部分上傳實作中的一個邊緣情況,該情況可能會在某些情況下導致程序崩潰。

已修復:在具有相同原型之空物件上的 Bun.deepEquals

Bun.deepEquals 現在可以正確比較共用相同原型但具有不同內部類型的物件。這修復了在 Node.js 測試套件中發現的邊緣情況。

function FakeDate() {}
FakeDate.prototype = Date.prototype;
const a = new Date("2016");
const b = new FakeDate();

// Now correctly returns false in both directions
console.log(Bun.deepEquals(a, b)); // false
console.log(Bun.deepEquals(b, a)); // false

這也會影響具有數字屬性名稱的物件與 TypedArrays 之間的比較

const a = { 0: 5, 1: 6, 2: 7 };
const b = new Uint8Array([5, 6, 7]);
console.log(Bun.deepEquals(a, b)); // was true, now false

最後,由於我們的 expect(...).toEqual() 實作依賴於 Bun.deepEquals,因此此變更也使我們的測試系統更加嚴格,並使其更緊密地與 Jest 對齊。

感謝 @DonIsaac 的貢獻!

已修復:require("my-virtual-module").default

當導入模組時,loader: "object" 外掛程式現在可以正確處理 __esModule 屬性。這使行為與 CommonJS 模組載入一致。

// Plugin configuration
builder.module("my-module", () => {
  return {
    exports: {
      default: "hello",
      __esModule: true,
    },
    loader: "object",
  };
});

// Now works correctly
import myModule from "my-module";
console.log(myModule); // "hello"

// And with require
const myModule = require("my-module");
console.log(myModule); // "hello"

已修復:來自具有額外萬用字元的無效 Semver 的判斷提示失敗

已修復在套件安裝期間處理具有額外萬用字元的無效 Semver 版本時可能發生的判斷提示失敗。

// These no longer trigger an assertion failure
{
  "dependencies": {
    "package": "1.2.3x",
    "package2": "1.2x.3",
    "package3": "1x.2.3",
  }
}

感謝 @DonIsaac 的貢獻!

已修復:bun init -h 顯示說明文字

bun init 命令的 -h 簡寫旗標現在可以正確顯示說明文字,與 --help 的行為一致。

bun init -h

感謝 @riskymh 的貢獻!

感謝 12 位貢獻者!