Bun
    Bun

Bun v1.0.30


Jarred Sumner · 2024年3月4日

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

此版本修正了 27 個錯誤(解決了 103 個 👍 反應),修復了 Bun.serve() 中 8 倍效能衰退的問題,為 bun build 和 Bun 的執行環境新增了 --conditions 標記,在 Bun 的測試執行器中新增了對 expect.assertions()expect.hasAssertions() 的支援,修正了崩潰問題並改善了 Node.js 相容性。

先前的版本

  • v1.0.29 修正了 8 個錯誤。Bun.stringWidth(a) 是 'string-width' 這個熱門套件的超快速 (約 6,756 倍) 可直接替換版本。bunx 檢查更新的頻率更高。在 bun:test 中新增了 expect().toBeOneOf()。修正了影響 Prisma 的記憶體洩漏問題。Shell 現在支援進階重新導向,例如 '2>&1'、'&>'。提升了 bunx、bun install、WebSocket client 和 Bun Shell 的可靠性
  • v1.0.28 修正了 6 個錯誤(解決了 26 個 👍 反應)。修正了影響 Prisma 和 Astro、node:eventsnode:readlinenode:http2 的錯誤。修正了 Bun Shell 中涉及 stdin 重新導向的錯誤,並修正了 bun:testtest.eachdescribe.only 的錯誤。
  • v1.0.27 修正了 72 個錯誤(解決了 192 個 👍 反應),Bun Shell 支援在非零退出代碼時拋出錯誤,使用 async generators 串流 Response bodies,提升了 fetch()、http2 client、Bun.Glob 的可靠性。修正了 Linux 上 bun --watch 的衰退問題。改善了 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.serve() 中出現 8 倍效能衰退的問題

已修正在 Bun.serve() 中,使用串流將單一資料塊精確地寫入到回應主體時,在事件迴圈的單一滴答中發生的效能衰退問題。此衰退問題是在 v1.0.4 中引入的。

以下程式碼有時會重現此問題

Bun.serve({
  async fetch(req) {
    return new Response(
      new ReadableStream({
        type: "direct",
        async pull(controller) {
          controller.write("hello");
          await controller.end();
        },
      }),
    );
  },
});

提示:當將 nginx 與 Bun 搭配使用時,請務必在您的 nginx 設定中設定 proxy_http_version 1.1。HTTP Keep-Alive 對於效能至關重要,而 nginx 預設會停用它。

新標記:--conditions

--conditions 標記可讓您指定在從 package.json "exports" 解析套件時要使用的條件清單。

bun build 和 Bun 的執行環境都支援此標記。

# Use it with bun build:
bun build --conditions="react-server" --target=bun ./app/foo/route.js

# Use it with bun's runtime:
bun --conditions="react-server" ./app/foo/route.js

Bun 已經支援 package.json "exports",此版本新增了為目標新增額外條件的支援。

您也可以使用 Bun.build 以程式方式使用 conditions

await Bun.build({
  conditions: ["react-server"],
  target: "bun",
  entryPoints: ["./app/foo/route.js"],
});

Node.js 也支援這個 CLI 標記,語法相同。

感謝 @igorwessel 實作此功能!

現在支援 expect.assertions()expect.hasAssertions()

現在 Bun 的測試執行器中支援 expect.assertions()expect.hasAssertions()

test("expect.assertions()", () => {
  expect.assertions(1);
  expect(true).toBe(true);
});

test("expect.hasAssertions()", () => {
  expect.hasAssertions();
  expect(true).toBe(true);
});

感謝 @Yash-Singh1 實作此功能!

Bun.fileURLToPath(url) 現在支援字串

Bun.fileURLToPath(url) 現在同時支援字串和 URL 物件。

// new:
Bun.fileURLToPath("file:///path/to/file.txt");

// old (still works):
Bun.fileURLToPath(new URL("file:///path/to/file.txt"));

Bun Shell 在錯誤時提供更佳的堆疊追蹤

Bun Shell 現在在錯誤時提供更佳的堆疊追蹤。

先前,當發生錯誤時,Bun Shell 不會包含完整的堆疊追蹤。此問題已修正,感謝 @zackradisic

已修正:在 Bun.serve() 中,使用延遲請求主體時可能發生的崩潰問題

已修正在接收請求主體後傳送緩衝回應時,可能發生的崩潰問題。

以下程式碼有時會重現此問題

Bun.serve({
  development: true,
  async fetch(request: Request): Promise<Response> {
    await Bun.sleep(200 + Math.random() * 100);
    const body = await (async function () {
      return await request.json();
    })();
    return new Response(JSON.stringify(body));
  },
});

此崩潰的發生原因為,當請求中止時,Bun 會自動拒絕使用請求的待處理 Promise,而 Bun 的程式碼在嘗試拒絕 Promise 之前,並未檢查讀取請求主體的 Promise 是否仍在待處理狀態。拒絕 Promise 會在內部觸發斷言失敗,進而導致崩潰。

已修正:Bun.serve() 中具有底線和英文大寫名稱的標頭

Bun v1.0.28 新增了在 Bun.serve() 中接收具有底線標頭的支援。基於多種原因,Bun.serve() 會自動將所有傳入的標頭名稱轉換為小寫(根據規範,HTTP 標頭不區分大小寫)。HTTP 伺服器中用於將標頭名稱轉換為小寫的程式碼存在錯誤,導致底線在標頭名稱中無效,進而導致非預期的行為。此問題已修正。

已修正:在特定條件下 textEncoder.encode() JIT 錯誤

TextEncoder.prototype.encode 中副作用設定中的一個錯誤,導致在短迴圈中呼叫數千次,且呼叫之間未發生任何配置時,可能會傳回非預期的結果。此問題已修正。

已修正:在列印具有模擬函式的錯誤堆疊時發生崩潰的問題

Bun 的模擬函式實作中的一個錯誤,導致在列印包含匿名模擬函式的錯誤堆疊追蹤時發生崩潰。此問題已修正。

以下測試重現了此崩潰問題

test("#8794", () => {
  const target = {
    a() {
      throw new Error("a");
      return 1;
    },
    method() {
      return target.a();
    },
  };
  spyOn(target, "method");

  for (let i = 0; i < 20; i++) {
    try {
      target.method();
      expect.unreachable();
    } catch (e) {
      e.stack;
      expect(e.stack).toContain("at method ");
      expect(e.stack).toContain("at a ");
    }
    Bun.gc(false);
  }
});

已修正:在 expect(undefined).toContainKeys(a) 中發生崩潰的問題

expect(undefined).toContainKeys(array) 不再導致測試執行器崩潰。此崩潰的發生原因為,在 toContainKeys matcher 中遺失了對類似物件 expect() 值的檢查。

感謝 @dylan-conway 修正此錯誤。

已修正:在事件迴圈中使用計時器時可能發生的崩潰問題

Bun 使用的事件迴圈程式庫中,一個未初始化的記憶體存取可能會導致大約 16 分鐘後在特定情況下發生崩潰。此崩潰最常在 Bun 的 Linux ARM64 建置版本上重現。感謝 @argosphil 修正此錯誤。

Node.js 相容性改善

此版本包含多項 Node.js 相容性改善。

已實作 util/types 中的 isKeyObject

已實作 node:util/types 中的 isKeyObject 函式。如果輸入為 KeyObject,此函式會傳回 true。

import { isKeyObject } from "node:util/types";
import { generateKeyPairSync } from "node:crypto";
isKeyObject({}); // false
isKeyObject(generateKeyPairSync("ed25519").publicKey); // true

已實作 node:fs 中的 fdatasync

Bun 現在在 node:fs 中實作了 fdatasync。此函式會同步將對檔案所做的所有變更寫入磁碟。

import { fdatasync } from "node:fs";

fdatasync(fd);

現在,當將 require.main 與符號連結搭配使用時,Bun 的行為與 Node.js 相同。

ln -s /path/to/real.js /path/to/symlink.js
// symlink.js
console.log(require.main === module); // true

這有助於解決使用 Bun 執行 prisma generate 時的相容性問題。

已修正:在 napi_get_buffer_info 中發生崩潰的問題

當在本機附加元件中使用 napi_get_buffer_info 函式,並為 size 引數傳遞空指標時,Bun 不再崩潰。

已修正:在 Node.js Readable 中正確發出檔案結尾

我們的 node:stream 實作中的一個錯誤,導致 readable 事件在微任務中發出,而不是在 process.nextTick 中發出。此問題已修正,感謝 @camero2734

此錯誤影響了 prisma generate 和其他使用 Node.js 串流的工具。

已修正:node:streams 中遺失事件,影響 node-fetch

我們的 node:streams 實作中的一個錯誤,在呼叫 this.push(null) 後的下一個滴答中,我們在串流上呼叫了 destroy,導致 node:streams 未正確終止串流。此錯誤導致 node-fetch 永遠無法完成讀取回應主體。此錯誤影響了 prisma generate 和其他將 node-fetch 捆綁到其套件中的工具。

Bun 內部會覆寫 node-fetch 以使用 Bun 提供的 fetch 全域變數,因此直接使用 node-fetch 的套件不受此錯誤影響。

感謝 @camero2734 修正此錯誤。

已修正:Next.js 中出現 'request.endsWith is not a function' 錯誤

當使用 Bun 執行 Next.js 應用程式時,在大量請求之後,您可能會遇到類似這樣的錯誤

57 | }).bind(null, resolveFilename, hookPropertyMap);
58 | // This is a hack to make sure that if a user requires a Next.js module that wasn't bundled
59 | // that needs to point to the rendering runtime version, it will point to the correct one.
60 | // This can happen on `pages` when a user requires a dependency that uses next/image for example.
61 | mod.prototype.require = function(request) {
62 |     if (request.endsWith(".shared-runtime")) {
             ^
TypeError: request.endsWith is not a function. (In 'request.endsWith(".shared-runtime")', 'request.endsWith' is undefined)
      at node_modules/next/dist/server/require-hook.js:62:9
      at getMiddleware (node_modules/next/dist/server/next-server.js:904:26)
      at node_modules/next/dist/server/base-server.js:173:32
      at node_modules/next/dist/server/base-server.js:172:50
      at node_modules/next/dist/server/base-server.js:275:34

此錯誤已修正。我們的 require 實作在 JavaScriptCore 中錯誤地使用了尾部呼叫內建函式,有時會導致函式中的引數錯誤地轉發到綁定的函式。

已修正:node:fs 中使用相對路徑的 cp 函式

v1.0.27 中用於 Windows 支援的一個衰退問題,導致 node:fs 中的 cp 函式無法正確處理相對路徑。此錯誤已修正,感謝 @argosphil

已修正:process.stdin 過早結束

給定足夠大的輸入,以下程式碼會錯誤地遺失最後一個資料塊之一

const { Transform } = require("node:stream");

let totalChunkSize = 0;
const uppercase = new Transform({
  transform(chunk, _encoding, callback) {
    totalChunkSize += chunk.length;
    callback(null, "");
  },
});

process.stdin.pipe(uppercase).pipe(process.stdout);
process.stdin.on("end", () => console.log(totalChunkSize));

這影響了 prisma generate 等等。感謝 @camero2734 修正此問題。

Windows 支援即將在 Bun v1.1.0 中推出

我們仍在努力開發 Windows 支援。我們正在取得進展,但尚未準備就緒。您很快就會看到包含 Windows 支援的版本發佈。

感謝 14 位貢獻者!