Bun

Bun v0.6.13


Ashcon Partovi · 2023 年 7 月 4 日

我們正在招募 C/C++ 和 Zig 工程師,以建構 JavaScript 的未來!加入我們的團隊 →

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

我們最近發布了許多 Bun 的變更,這裡有一個回顧,以防您錯過了

  • v0.6.0 - 推出 bun build,Bun 的全新 JavaScript 打包器。
  • v0.6.2 - 效能提升:JSON.parse 速度提升 20%,Proxyarguments 速度提升高達 2 倍。
  • v0.6.3 - 實作 node:vm,修復了許多 node:httpnode:tls 的問題。
  • v0.6.4 - 實作 require.cacheprocess.env.TZ,以及 bun test 速度提升 80%。
  • v0.6.5 - 原生支援 CommonJS 模組 (先前,Bun 對 CJS 進行 ESM 轉譯),
  • v0.6.6 - bun test 改善,包括 Github Actions 支援、test.only()test.if()describe.skip(),以及 15 個以上的 expect() 匹配器;也支援使用 fetch() 串流檔案上傳。
  • v0.6.7 - 改善 Node.js 相容性,以解除對 Discord.js、Prisma 和 Puppeteer 的封鎖
  • v0.6.8 - 推出 Bun.passwordbun test 中的模擬 (mocking),以及 toMatchObject()
  • v0.6.9 - 減少記憶體使用量並支援非 ASCII 檔名
  • v0.6.10 - fs.watch()bun install 錯誤修復、bun test 功能,以及改善 CommonJS 支援
  • v0.6.11 - 解決了 v0.6.10 中的發布版本問題。
  • v0.6.12 - Error.stack 中的 Sourcemap 支援、Bun.file().exists() 和 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 test 中模擬 Date

您現在可以在 Bun 的測試執行器中模擬 new Date() 的值。這會影響任何可以檢索系統時間的 API,包括:Date.now()new Date()Intl.DateTimeFormat().format()

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

test("time travel", () => {
  const past = new Date("2022-07-05");
  setSystemTime(past);

  expect(new Date()).toBe(past);
  expect(Date.now()).toBe(past.getTime());
  expect(new Intl.DateTimeFormat("en-US").format()).toBe("07/05/2022");

  setSystemTime(); // resets
  expect(Date.now()).toBeGreaterThan(past.getTime());
});

與 Jest 不同,當您模擬時間時,Date 物件不會變異。這防止了一整類令人困惑的僅限測試的錯誤。

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

test("Date.prototype", () => {
  const OriginalDate = Date;
  setSystemTime(new Date("2022-07-05"));

  // both pass in Bun, but fail in Jest
  expect(OriginalDate).toBe(Date);
  expect(OriginalDate.now).toBe(Date.now);
});

Buffer.toString("base64") 速度提升 10 倍

node:tlsnode:net 的改進

@cirospaciari 對 Bun 的 node:tlsnode:net 實作進行了許多改進。這解鎖了各種依賴這些變更的 npm 套件。

Postgres with TLS 可運作了

您現在可以使用 postgres 套件,透過 TLS 連接到 Postgres 資料庫。先前,您可以不使用 TLS 連接,但有一些未解決的問題阻止 TLS 運作。

import { postgres } from "postgres";

const sql = postgres(process.env.DATABASE_URI);
const name = "ThePrimeagen",
  age = 69;
const users = await sql`
  select
    name,
    age
  from users
  where
    name like ${name + "%"}
    and age > ${age}
`;
console.log(users); // [{ name: "ThePrimeagen", age: 69 }]

Nodemailer 可運作了

您現在可以使用 nodemailer 套件來發送電子郵件。

import nodemailer from "nodemailer";

nodemailer.createTestAccount(async (err, account) => {
  const transporter = nodemailer.createTransport({
    host: account.smtp.host,
    port: account.smtp.port,
    secure: account.smtp.secure,
    debug: true,
    auth: {
      user: account.user,
      pass: account.pass,
    },
  });

  let info = await transporter.sendMail({
    from: '"Fred Foo 👻" <foo@example.com>',
    to: "example@gmail.com",
    subject: "Hello ✔",
    text: "Hello world?",
    html: "<b>Hello world?</b>",
  });

  console.log("Message sent: %s", info.messageId);
  // Message sent: <b658f8ca-6296-ccf4-8306-87d57a0b4321@example.com>

  console.log("Preview URL: %s", nodemailer.getTestMessageUrl(info));
  // Preview URL: https://ethereal.email/message/WaQKMgKddxQDoou...
});

.isUtf8().isAscii()

您現在可以使用 Node 的 buffer 模組中的 isUtf8()isAscii()

import { test, expect } from "bun:test";
import { isUtf8, isAscii } from "node:buffer";

test("isUtf8 and isAscii", () => {
  expect(isUtf8(new Buffer("What did the 🦊 say?"))).toBeTrue();
  expect(isAscii(new Buffer("What did the 🦊 say?"))).toBeFalse();
});

HTTP 請求的記憶體用量稍微減少

現在 Bun 每個 HTTP 請求使用的記憶體減少了 8 個位元組,這要歸功於 Zig 的 packed struct。這讓我們能夠以更節省記憶體的佈局來儲存相同的資訊。

在下面的範例中,每個 bool 都儲存為 1 個位元組。

const Request = struct {
  is_transfer_encoding: bool,
  is_waiting_body: bool,
  // ...
  aborted: bool,
};

現在,使用 packed struct,每個 bool 都儲存為 1 個位元

const Request = struct {
  const Flags = packed struct {
    is_transfer_encoding: bool,
    is_waiting_body: bool,
    // ...
    aborted: bool,
  };
  flags: Flags,
};

WebSocket 用戶端可靠性改進

此版本修復了 Bun 的 WebSocket 用戶端實作中的許多錯誤。

支援零長度訊息

您知道可以使用 WebSocket 發送和接收零長度訊息嗎?先前,Bun 會忽略這些訊息,但現在已支援。

const ws = new WebSocket("wss://ws.postman-echo.com/raw");
ws.onopen = () => {
  ws.send("");
  ws.send(new ArrayBuffer(0));
};

ws.onmessage = (event) => {
  console.log(event.data); // ""
  console.log(event.data); // ArrayBuffer(0)
};

初始有效負載競爭條件修復

先前,當收到初始 HTTP 回應並且在同一個事件迴圈滴答中發送 WebSocket 訊息時,Bun 有時會忽略這些訊息。現在已修復此問題。

同樣地,在某種邊緣情況下,初始訊息可能會在後續訊息收到後才被分派 (第二個訊息會出現在第一個訊息之前)。此問題也已修復。

錯誤修復

已變更 .toEqual() 以忽略私有屬性 (以 # 為前綴)。

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

test("toEqual() with #property", () => {
  class Foo {
    bar = 1;
    #baz = "";
  }
  class Bar {
    bar = 1;
  }
  expect(new Foo()).toEqual(new Bar());
});

已修復 在 package.json 中使用 workspace: 依賴項時發生的崩潰。

先前,如果您使用以下 package.json 執行 bun add,Bun 會崩潰。現在已修復此問題。

package.json
{
  "dependencies": {
    "foo": "workspace:bar"
  }
}

已修復 零長度環境變數無法運作的問題。

先前,如果您使用以下 .env 檔案執行 bun run,Bun 將無法偵測到環境變數。現在已修復此問題。

.env
FOO=

已修復HTMLRewriter 進行錯誤的文字解碼。

先前,如果您在 Bun 中執行以下程式碼,它會輸出錯誤的結果。現在已修復此問題。

new HTMLRewriter()
  .on("p", {
    element(element) {
      console.log(element.getAttribute("id"));
    },
  })
  .transform(new Response('<p id="Šžõäöü"></p>'));

// Before fix: Šžõäöü
// After fix: Šžõäöü

已修復 Buffer.toString() 的多載。

先前,如果您在 Node.js Buffer 上使用 toString(),Bun 將無法正確處理第二個多載。第一個多載指定了開始和結束,而第二個多載指定了偏移量和長度而不是結束。

interface Buffer {
  toString(encoding?: BufferEncoding, start?: number, end?: number): string;
  toString(offset: number, length: number, encoding?: BufferEncoding): string;
}
const { Buffer } = require("node:buffer");
const buf = Buffer.from("hello world", "latin1");

console.log(buf.toString("latin1", 1, 2));
console.log(buf.toString(1, 2, "latin1"));

感謝 @Hanaasagi 的修復!

已修復node:http 模組中遺失的匯出。

我們遺漏了兩個匯出。抱歉!

var defaultObject = {
   globalAgent,
+  ClientRequest,
+  OutgoingMessage,
   [Symbol.for("CommonJS")]: 0,
};

感謝 @stijnvanhulle 的修復!

其他錯誤修復

  • 已修復 某些 Node-API 的 utf-8 解碼。

  • 已修復 在載入新的 JavaScript 檔案時,檔案描述符洩漏的問題。

更新日誌

在 GitHub 上查看更新日誌