Bun

Bun v1.0.26


Jarred Sumner · 2024年2月3日

Bun 是一個速度驚人的 JavaScript 執行環境、打包器、轉譯器和套件管理器 — 功能All-in-one。如果您錯過了,這裡是一些 Bun 最近的變更。

此版本修復了 30 個錯誤,在 bun:sqlite 中新增了對多語句查詢的支援,使 bun --watch 在長時間運行的會話中更可靠,Bun.FileSystemRouter 現在支援超過 64 個路由,修復了 expect().toStrictEqual() 的錯誤,修復了 error.stack 的 2 個錯誤,修復了 fileURLToPath 的錯誤,並改善了 Node.js 的相容性

先前的版本

  • v1.0.25 修復了 4 個錯誤,新增了 vm.createScript。修復了 fs.readFile 中的崩潰、Bun.file().text() 中的崩潰、IPC 中的崩潰,以及涉及鬆散相等的轉譯器錯誤
  • v1.0.24 修復了 9 個錯誤,並新增了 Bun Shell,這是一個快速的跨平台 shell,具有無縫的 JavaScript 互操作性。修復了 socket 超時錯誤、socket 關閉時可能發生的崩潰、Hapi 的 Node.js 相容性問題、process.exit 錯誤,以及 bun install binlinking 錯誤、bun inspect 回歸和 bun:test expect().toContain 錯誤
  • v1.0.23 修復了 40 個錯誤(解決了 194 個 👍 表情符號)。在 Bun 中導入和嵌入 sqlite 資料庫、資源管理('using' TC39 stage3)支援、為 Node.js 建置時的打包器改進、對等依賴項解析的錯誤修復、semver 錯誤修復、Linux 上 TCP 速度提高 4%、Node.js 相容性改進等等"

安裝 Bun

curl
npm
brew
docker
curl
curl -fsSL https://bun.dev.org.tw/install | bash
npm
npm install -g 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

bun:sqlite 中的多語句查詢

bun:sqlite 獲得了對多語句查詢的支援。這讓您可以在單次呼叫 db.run() 中執行多個 SQL 語句,並以 ; 分隔,類似於在 sqlite 命令列工具中的運作方式。

import { Database } from "bun:sqlite";

const db = new Database(":memory:");

db.run(`
  CREATE TABLE users (
    id INTEGER PRIMARY KEY,
    name TEXT
  );

  INSERT INTO users (name) VALUES ("Alice");
  INSERT INTO users (name) VALUES ("Bob");
`);

const names = db
  .query("SELECT name FROM users")
  .all()
  .map(({ name }) => name)
  .join(", ");
console.log(names); // Alice, Bob

只有 Database.prototype.runDatabase.prototype.exec 支援多語句查詢。db.querydb.prepare 則不支援。

bun --watch 可靠性改進

bun --watch 現在會在重新載入時防禦性地關閉所有檔案描述符。檔案系統監視器本質上需要在監視許多檔案時保持開啟許多檔案描述符,但長時間保持檔案描述符開啟可能會導致資源耗盡和許多其他問題。Bun 已經在內部設定了 O_CLOEXEC,但這並不總是意味著所有檔案描述符都已關閉。

使 bun --watch 快速的部分原因是,當導入的檔案變更時,我們會立即重新載入整個進程。在檔案變更和進程重新載入之間發生的工作非常少。這與其他工具形成對比,這些工具可能會重新編譯檔案以檢查變更,並且僅在變更時重新執行進程。

在 Linux 上,Bun 現在使用 close_range(2) 系統呼叫來關閉重新載入進程之前的所有檔案描述符 > 8。這可靠地確保了所有檔案描述符都已關閉(對於那些執行現代 Linux 核心的人來說)。

在 macOS 上,我們使用 POSIX_SPAWN_CLOEXEC_DEFAULT 標誌來關閉產生時的所有檔案描述符。我們還修復了一個問題,即訊號未在重新載入時重設為其預設行為。

abort-controller polyfill 現在使用原生 AbortController

流行的 abort-controller npm 套件 polyfill 現在在 Bun 中使用原生 AbortController,而不是 polyfill。

這修復了一個問題,即當程式庫將 abort-controller polyfill 與 fetchRequestResponse 一起使用時,Bun 會報告類似 "Expected signal to be an AbortSignal" 的錯誤。

abort-controller polyfill 是 AbortControllerAbortSignal Web API 的 polyfill

已修復:Bun.FileSystemRouter 現在支援超過 64 個路由

Bun.FileSystemRouter 是 Bun 內建的 Next.js pages 啟發的檔案系統路由器。它現在支援超過 64 個路由。

先前,當您嘗試使用超過 64 個路由時,Bun 會拋出無法捕捉的例外。這是由於在 JavascriptCore 中定義物件時,如果物件具有超過 63 個「內聯」屬性,則會發生斷言失敗。此問題已修復。

已修復:error.stack 有時為 undefined

Bun 實作了 V8 Stack Trace API(儘管 Bun 使用 JavaScriptCore 引擎),這為 Error 物件新增了 Error.prepareStackTraceError.captureStackTrace 等方法。

存在一個錯誤,在應該是字串的情況下,error.stack 有時為 undefined。此問題已修復。

此錯誤影響了 Firebase 和 Google Cloud 程式庫在即將記錄錯誤時的情況。它導致這些程式庫在嘗試記錄錯誤時拋出不同的錯誤,這沒有幫助。

已修復:error.stack CallSite lineNumber 有時為負數

以下程式碼有時會印出負數

Error.prepareStackTrace = (error, stack) => {
  return [stack[0].getLineNumber(), stack[0].getColumnNumber()];
};

const error = new Error();
console.log(error.stack);

當行號不可用時,Bun 會傳回負數。不幸的是,這破壞了流行的 source-map-support 程式庫,因為它斷言行號和列號為正整數。此問題已透過永遠不傳回負數來「修復」。

已修復:Error.prepareStackTrace 現在預設為函數

在 Node.js 中,Error.prepareStackTrace 預設為函數。在 Bun 中,它預設為 undefined。此問題已修復。

預設的 Error.prepareStackTrace 函數會執行您期望的操作:它會傳回堆疊追蹤的字串。您可以繼續將 Error.prepareStackTrace 設定為自訂函數來自訂堆疊追蹤,或設定為 undefined(在這種情況下,將使用預設函數)。

已修復:module.path 現在是 __dirname 而不是 module.id

在 Node.js 中,module 物件具有 path 屬性,該屬性應為模組的目錄,相當於 __dirname。在 Bun 中,module.path 錯誤地是 module.id 的別名。此問題已修復。

已修復:expect(a).toStrictEqual(b) 帶有已刪除的屬性

bun:testexpect.toStrictEqual 實作中的一個錯誤導致在比較具有已刪除屬性的物件時行為不正確。此問題已修復,感謝 @dylan-conway

import { test, expect } from "bun:test";

test("expect.toStrictEqual", () => {
  const a = { a: 1, b: 2 };
  const b = { a: 1, b: 2 };
  delete b.b;
  expect(a).toStrictEqual(b);
});

先前,這會拋出一個錯誤,並帶有一個令人困惑的空白差異

hey.test.ts:
2 |
3 | test("expect.toStrictEqual", () => {
4 |   var obj1 = { a: 1 };
5 |   var obj2 = {};
6 |   delete obj1.a;
7 |   expect(obj1).toStrictEqual(obj2);
      ^
error: expect(received).toStrictEqual(expected)

  {}

- Expected  - 0
+ Received  + 0

      at hey.test.ts:7:3
✗ expect.toStrictEqual [0.29ms]

現在它可以正確通過。

發生這種情況是因為 toStrictEqual 使用了一個快速路徑,該路徑在某些情況下無法正確處理已刪除的屬性。

已修復:Bun.serve() websocket 中的事件迴圈排程錯誤

我們進行了一些基礎架構調整,以確保在執行事件迴圈回呼後始終清空微任務。在 websocket、Bun.spawn() 和 IPC 處理器中,我們跳過了執行此操作,這是一個錯誤。忽略清空微任務佇列可能會導致非常高的記憶體增長,直到微任務被清空為止(想像一下,如果您只是不斷地向佇列中新增內容,而從不刪除任何內容)。

已修復:new Response(Bun.file()) 有時會將錯誤記錄到 stderr

當您將 Bun.file() 傳遞給 new Response() 以連接到 HTTP(而非 HTTPS)的 Bun.serve() 時,如果用戶端在正確的時間中止請求,Bun 會將 Error: NOTCONN 記錄到 stderr,且無法抑制。這是令人困惑且沒有幫助的。中止請求是 Web 的正常組成部分,Bun 不應在發生這種情況時記錄無法抑制的錯誤。

Windows 將於 2 月 15 日推出

Bun 在 Windows 上的測試通過率為 78%,但仍不足以發布。

此版本中的大多數變更都與 Windows 相關,但此變更日誌排除了這些變更,因為它尚未「發布」。

感謝 28 位貢獻者!