Bun

Bun v1.0.36


Ashcon Partovi · 2024年3月29日

Bun 是一個速度極快的 JavaScript 執行環境、打包器、轉譯器和套件管理器 — 功能All-in-One。

Bun v1.0.36 修復了 13 個錯誤。新增了對 fs.openAsBlobfs.opendir 的支援,修復了在 package.json 中有多個 bin 條目時 bun install 的邊緣案例,修復了 bun build --target bun 編碼問題,修復了 process.stdin 和 process.stdout 的錯誤,修復了 http2 中的錯誤,修復了 bun run 中 .env 的錯誤,修復了各種 Bun shell 錯誤並改進了 Node.js 相容性。

Bun v1.1 (Bundows) 將於 4 月 1 日發布。

先前的版本

  • v1.0.35 修復了 Bun v1.0.34 的回歸錯誤
  • v1.0.34 修復了 7 個錯誤,bunx 使用更少的記憶體,bun install 在 Docker 和 WSL 上變得更快,修復了衝突的 devDependency hoisting 錯誤,修復了循環的 CommonJS 和 ESM 導入崩潰問題,跨掛載的 fs.cp 和 fs.copyFile 在 Linux 上速度提升了 50%,以及 bun install 和 bun 執行環境的可靠性改進。
  • v1.0.33 修復了 2 個錯誤,包括 Bun Shell 中 mv 命令以及 node:crypto 建立和驗證簽名的錯誤
  • v1.0.32 修復了 13 個錯誤並改進了 Node.js 相容性。'ws' 套件現在可以發送和接收 ping/pong 事件。util.promisify'd setTimeout setInterval、setImmediate 現在可以運作了。FileHandle 方法已實作。

安裝 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

Node.js 相容性改進

新功能:fs.openAsBlob

Bun 現在支援最近新增的 fs.openAsBlob() API,它允許您將檔案作為 Blob 開啟。這會傳回與 Bun.file 相同的底層 Blob

import { openAsBlob } from "node:fs";

const blob = await openAsBlob("hello.txt");
console.log(await blob.text()); // "Hello, world!"

新功能:fs.opendir

我們也新增了對 fs.opendir() 的支援,它允許您開啟目錄並讀取其內容。

import { opendir } from "node:fs";

const dir = await opendir(".");
for await (const dirent of dir) {
  console.log(dirent.name); // "hello.txt", "world.txt"
}

已修復:process.stdin 管道輸出至 process.stdout 時卡住的問題

當至少 16 KB 的資料通過管道傳輸到 process.stdout 時,進程有時會卡住。此問題已修復。

已修復:http2 中的崩潰問題

使用 http2 client 時可能發生的崩潰問題已修復。此崩潰與未實作的 HTTP2 功能有關。

已修復:Readable.toWeb(process.stdin)

process.stdin 讀取時,Readable.toWeb() 函數無法正常運作。此問題已修復。

現在 `Readable.toWeb(process.stdin)` 實際上與 `Bun.stdin.stream()` 相同。

已修復:使用 process.stdout.moveCursor() 時的回歸錯誤

Bun v1.0.34 中的回歸錯誤導致 `process.stdout.moveCursor()` 拋出 `ReferenceError: Can't find variable: readline`。此問題已修復。

已修復:TextDecoder 錯誤缺少 code 屬性

當使用 `TextDecoder` 解碼無效的 UTF-8 字串時,錯誤物件不會有 `code` 屬性。Web API 不會為無效的 UTF-8 字串傳回 `code` 屬性,但 Node.js 會。為了相容性,我們現在傳回與 Node.js 相同的 `code` 屬性。

這修復了一個阻止 `@angular/cli new` 使用 Bun 執行的錯誤。

已修復:非阻塞 fs.readv 和 fs.writev

node:fs API fs.readvfs.writev 以阻塞方式執行。此問題已修復。現在,當未呼叫其 sync 版本時,我們會將 readv 和 writev 函數排入線程池。

已修復:package.json 中有多個 bin 條目的邊緣案例

先前,在以下情況下存在一個錯誤:

  1. 只有一個版本的套件在 NPM Registry API 中有 bin 條目
  2. 所有其他版本都沒有 bin 條目
  3. bin 物件有多個條目

此錯誤導致 bun install 無法正確連結二進制檔案。

package.json
{
  "bin": {
    "a": "bin",
    "b": "bin",
  }
}

感謝 @dylan-conway 修復了此問題。

已修復:ws 伺服器中缺少 terminate 方法

Bun 中的 ws polyfill 在 WebSocketServer 的 WebSocket 實例中缺少 terminate 方法。此問題已修復。

感謝 @paperclover 修復了此問題。

執行環境改進

檔案描述符洩漏預防機制

POSIX 預設檔案描述符由子進程繼承。這經常以各種方式導致檔案描述符洩漏。Bun 一直使用 O_CLOEXEC 標誌來防止檔案描述符被繼承,但在某些情況下這還不夠。

在現代 Linux 核心上,Bun 現在使用 close_range 系統呼叫來防止檔案描述符在沒有 O_CLOEXEC 標誌的情況下被繼承。這是一種更可靠的方式來防止檔案描述符洩漏。

在 macOS 上,Bun 專門使用 posix_spawn 來產生子進程,它具有等效的機制來防止檔案描述符洩漏,這使得洩漏更難以發生。

在 SIGINT/SIGTERM 上將 stdin/stdout 還原到其原始狀態

先前,Bun 並非總是在 SIGINT/SIGTERM 上將 stdin/stdout 還原到其原始狀態。此問題已修復。

非阻塞 TTY 讀取

在 POSIX 上,Bun 現在以非阻塞方式從 stdin 讀取資料。通常,這也會導致管道的另一端也變成非阻塞,但我們有一個解決方案(感謝閱讀 libuv 中的一些程式碼)。我們使用 ttyname_r 將 TTY 作為非阻塞檔案描述符開啟,而不會影響管道的另一端。

已修復:使用 Bun.escapeHTML 時的崩潰問題

我們修復了一個特定輸入可能導致 `Bun.escapeHTML` 崩潰的問題,此問題是由於差一錯誤引起的。

感謝 Querijn Voet 回報了此問題。

已修復:WebSocket 握手邊緣案例

`WebSocket` client 實作中的一個錯誤可能導致非 101 狀態碼被視為 WebSocket 升級請求。此錯誤已知從未在實際環境中存在過,但我們仍然修復了它。

已修復:Bun.spawn 中潛在的檔案描述符重定向錯誤

一個可能導致重定向 `stdin`、`stdout` 或 `stderr` 的錯誤,導致 Bun 在子進程完成啟動之前關閉檔案描述符。此錯誤是由於誤解 `dup2` libc 函數的工作方式引起的。當 `dup2` 接收到與目標相同的檔案描述符時,它不會執行任何操作。現在,當重定向相同的檔案描述符時,Bun 將改為從檔案描述符中移除 `O_CLOEXEC` 標誌,這允許子進程繼承檔案描述符。此錯誤僅影響 Linux,並且比僅繼承檔案描述符更難以重現。

已修復:`bun run` 中不正確的 .env 傳播

一個回歸錯誤導致在使用 `bun run` 之前,`.env` 檔案被意外載入。此回歸錯誤已修復,並且我們改進了我們的測試套件,以防止再次發生這種情況。

Shell (Bun.$) 穩定性改進

我們修復了 Bun shell 的各種錯誤和回歸問題,包括:

  • Shell 可能會卡住的競爭條件。
  • 當子進程在事件迴圈準備就緒之前退出時,可能發生的崩潰。
  • 當 stdin 大於 128kb 時,可能發生的崩潰。
  • 當產生使用互動模式的子進程時,使用者輸入將不會發送到子進程。這影響了像 `@inquirer/prompts` 這樣的套件。
shell.js
prompt.js
input.js
shell.js
import { $ } from "bun";

await $`bun input.js | bun prompt.js`;
prompt.js
const { select } = require("@inquirer/prompts");

async function run() {
  const foobar = await select({
    message: "Foo or Bar",
    choices: [
      { name: "Foo", value: "foo" },
      { name: "Bar", value: "bar" },
    ],
  });
  console.error("Choice:", foobar);
}

run();
input.js
// Simulate pressing the down arrow key
const writer = Bun.stdout.writer();
await Bun.sleep(100);
writer.write("\\x1b[B");

// Simulate pressing the enter key
await Bun.sleep(100);
writer.write("\\x0D");
writer.flush();

感謝 @zackradisic 修復了這些問題。

已修復:bun build --target bun 使用了錯誤的編碼

Bun 將檔案轉譯為 latin1,因為以 utf-16 儲存時檔案大小會減小。存在一個錯誤,其中 `bun build --target bun` 會改為編碼為 utf-8,這導致了非 latin1 字元的問題。此問題已修復。

給定以下檔案,先前它將按原樣以 utf-8 編碼。

console.log({ 我: "a" });

現在,它已正確地以 latin1 編碼。

// @bun
console.log({ "\u{6211}": "a" });

感謝 @pfgithub 修復了此問題。

Bundows (Bun v1.1) 將於 4 月 1 日發布

Bun v1.1 將於 4 月 1 日發布。

感謝 13 位貢獻者!