我們正在舊金山招聘系統工程師,以打造 JavaScript 的未來!
此版本修正了 32 個錯誤。S3 儲存類別支援、crypto.generateKeyPair 中的 X25519 支援。fs.stat 使用更少的記憶體。node:fs、node:child_process 和 node:process 相容性改進。CSS 解析器錯誤修正。使用 --zero-fill-buffers
標記的零填充緩衝區。bun test 中縮排的內嵌快照。已改進:字串 GC 報告準確性。修正了 Bun.serve()、Bun.pathToFileURL 和某些字串中的記憶體洩漏。停用 HTML 匯入中的最小化。
安裝 Bun
curl -fsSL https://bun.dev.org.tw/install | bash
npm install -g bun
powershell -c "irm bun.sh/install.ps1|iex"
scoop install bun
brew tap oven-sh/bun
brew install bun
docker pull oven/bun
docker run --rm --init --ulimit memlock=-1:-1 oven/bun
升級 Bun
bun upgrade
S3 儲存類別支援
您現在可以將 storageClass
選項傳遞給 Bun 的內建 S3 用戶端。
這可讓您設定 S3 物件儲存如何儲存您的物件,以便您可以針對成本或延遲進行最佳化。
it("should work with storage class", async () => {
const s3file = s3("s3://bucket/credentials-test", s3Options);
const url = s3file.presign({
expiresIn: 10,
storageClass: "GLACIER_IR",
});
expect(url).toBeDefined();
expect(url.includes("X-Amz-Expires=10")).toBe(true);
expect(url.includes("x-amz-storage-class=GLACIER_IR")).toBe(true);
expect(url.includes("X-Amz-Date")).toBe(true);
expect(url.includes("X-Amz-Signature")).toBe(true);
expect(url.includes("X-Amz-Credential")).toBe(true);
expect(url.includes("X-Amz-Algorithm")).toBe(true);
expect(url.includes("X-Amz-SignedHeaders")).toBe(true);
});
crypto.generateKeyPair 中的 X25519 支援
crypto.generateKeyPair
API 現在支援 X25519 曲線,用於金鑰產生和 Diffie-Hellman 金鑰交換。
import crypto from "node:crypto";
// Generate Alice's keys
const alice = crypto.generateKeyPairSync("x25519", {
publicKeyEncoding: {
type: "spki",
format: "der",
},
privateKeyEncoding: {
type: "pkcs8",
format: "der",
},
});
// Generate Bob's keys
const bob = crypto.generateKeyPairSync("x25519", {
publicKeyEncoding: {
type: "spki",
format: "der",
},
privateKeyEncoding: {
type: "pkcs8",
format: "der",
},
});
// Convert keys for DH computation
const alicePrivateKey = crypto.createPrivateKey({
key: alice.privateKey,
format: "der",
type: "pkcs8",
});
const bobPublicKey = crypto.createPublicKey({
key: bob.publicKey,
format: "der",
type: "spki",
});
先前,這會擲回 DOMException
NotSupportedError: The operation is not supported.
bun test 中縮排的內嵌快照
測試中 Jest 樣式的內嵌快照現在支援縮排,使測試檔案更易於閱讀。更新快照時,會自動偵測並保留縮排。
test("my test", () => {
expect(value).toMatchInlineSnapshot(`
{
"foo": "bar",
"baz": 123
}
`);
});
感謝 @pfgithub 的修正!
已改進:字串 GC 報告準確性
在 WebKit(和 Bun)中,字串是參考計數的。JavaScript 字串(會進行垃圾回收)會保留對參考計數字串的參考。垃圾收集器會將參考計數字串的記憶體使用量報告為字串的位元組長度除以參考計數
inline size_t StringImpl::costDuringGC()
{
if (isStatic())
return 0;
if (bufferOwnership() == BufferSubstring)
return divideRoundedUp(substringBuffer()->costDuringGC(), refCount());
size_t result = m_length;
if (!is8Bit())
result <<= 1;
return divideRoundedUp(result, refCount());
}
先前,Bun 的 JavaScriptCore 繫結通常會有如下模式,用於建立要讓 JavaScript 取用的字串
fn myFunction(globalObject: *JSC.JSGlobalObject, input: []const u8) JSC.JSValue {
// Reference count: 1
const string = bun.String.createUTF8(input);
// - Reference count: 1 (after the function returns)
defer string.deref();
// + Reference count: 2 (before the function returns)
return string.toJS(globalObject);
}
因此,如果您使用 fs.readFileSync(path, "utf-8")
之類的函式來讀取包含 64 KB ASCII 資料的檔案,記憶體使用量會向 JavaScriptCore 的垃圾收集器報告為 32 KB 而不是 64 KB。
我們已更新繫結以使用不同的模式,將為 JavaScript 建立字串的步驟合併為單一步驟,以便在傳回 JavaScript 字串之前,參考計數不會額外遞增一次。
fn myFunction(globalObject: *JSC.JSGlobalObject, input: []const u8) JSC.JSValue {
// Reference count: 1
return bun.String.createUTF8ForJS(globalObject, input);
}
這會減少記憶體使用量嗎?
可能偶爾會。
停用 HTML 匯入中的最小化
您現在可以透過在 bunfig.toml
中設定 minify
選項,來停用HTML 匯入的最小化。
[serve.static]
plugins = ["bun-plugin-tailwind"]
minify = false
# or
# minify.whitespace = false
# minify.identifiers = false
# minify.syntax = false
如果您遇到任何僅在 development: false
時發生的問題,請嘗試停用最小化。
如果未指定
- 當您將
development: true
傳遞給 Bun.serve() 時,minify
為false
- 當您將
development: false
傳遞給 Bun.serve() 時,minify
為true
當您想要擁有最佳化組建,並減少要傳送給用戶端的程式碼時,最小化在生產環境中會有所幫助。
我們將在不久的將來公開 Bun.build
中的其餘選項。
使用 --zero-fill-buffers
標記的零填充緩衝區
Bun 現在支援 Node.js 的 --zero-fill-buffers
標記,這會強制所有新配置的緩衝區都進行零填充,以提高安全性。啟用後,Buffer.allocUnsafe()
之類的方法將始終傳回零填充的緩衝區。
// Run with: bun --zero-fill-buffers script.js
const buf = Buffer.allocUnsafe(20);
console.log(buf); // Will contain all zeros instead of arbitrary memory
感謝 @nektro!
node:process 相容性改進
- 修正了導致
process.stdin.ref
和process.stdin.unref
在不應為undefined
時卻為undefined
的錯誤。 - 修正了一個可能導致
process.stdout.write
在極少數情況下無法阻止程序退出的錯誤。
這些修正共同解決了影響 ink
的回歸問題。
node:fs 相容性改進
此版本修正了數個與以下項目相關的相容性問題
fs.{s,f}statSync
fs.promises.{s,f}stat
fs.promises.{s,f}statSync
fs.Stats
fs.Stats
建構函式現在與 Node.js 的行為一致。
以下差異;
const fs = require("fs");
const stats = new fs.Stats();
console.log(stats);
之前 vs 現在
Stats {
atime: 1970-01-01T00:00:00.000Z,
atime: Invalid Date,
atimeMs: 0,
atimeMs: undefined,
birthtime: 1970-01-01T00:00:00.000Z,
birthtime: Invalid Date,
birthtimeMs: 0,
birthtimeMs: undefined,
blksize: 0,
blksize: undefined,
blocks: 0,
blocks: undefined,
ctime: 1970-01-01T00:00:00.000Z,
ctime: Invalid Date,
ctimeMs: 0,
ctimeMs: undefined,
dev: 0,
dev: undefined,
gid: 0,
gid: undefined,
ino: 0,
ino: undefined,
isBlockDevice: [Function: isBlockDevice],
isCharacterDevice: [Function: isCharacterDevice],
isDirectory: [Function: isDirectory],
isFIFO: [Function: isFIFO],
isFile: [Function: isFile],
isSocket: [Function: isSocket],
isSymbolicLink: [Function: isSymbolicLink],
mode: 0,
mode: undefined,
mtime: 1970-01-01T00:00:00.000Z,
mtime: Invalid Date,
mtimeMs: 0,
mtimeMs: undefined,
nlink: 0,
nlink: undefined,
rdev: 0,
rdev: undefined,
size: 0,
size: undefined,
uid: 0,
uid: undefined,
}
Node.js
Stats {
dev: undefined,
mode: undefined,
nlink: undefined,
uid: undefined,
gid: undefined,
rdev: undefined,
blksize: undefined,
ino: undefined,
size: undefined,
blocks: undefined,
atimeMs: undefined,
mtimeMs: undefined,
ctimeMs: undefined,
birthtimeMs: undefined,
atime: Invalid Date,
mtime: Invalid Date,
ctime: Invalid Date,
birthtime: Invalid Date
}
fs.fstatSync bigint 支援
先前,fs.fstatSync
方法忽略了 bigint
選項。
const fs = require("fs");
const stats = fs.fstatSync(0, { bigint: true });
console.log(stats);
現在它支援了。
BigIntStats {
dev: 0n,
ino: 15807n,
mode: 8592n,
nlink: 1n,
uid: 501n,
gid: 4n,
rdev: 268435812n,
size: 0n,
blksize: 65536n,
blocks: 0n,
atimeMs: 1737726280078n,
mtimeMs: 1737726280452n,
ctimeMs: 1737726280452n,
birthtimeMs: 0n,
atimeNs: 1737726280078692000n,
mtimeNs: 1737726280452662000n,
ctimeNs: 1737726280452662000n,
birthtimeNs: 0n,
atime: 2025-01-24T13:44:40.078Z,
mtime: 2025-01-24T13:44:40.452Z,
ctime: 2025-01-24T13:44:40.452Z,
birthtime: 1970-01-01T00:00:00.000Z,
}
EINTR
在某些情況下,Bun 未在 fs.writeFile
和 fs.readFile
中處理 EINTR。
這些問題已修正。EINTR 可能會中斷系統呼叫,例如 read()
、write()
、truncate()
、ftruncate()
、fchmod()
等。正確的行為是在中斷時重試系統呼叫。
Stat 使用更少記憶體
在下一個版本的 Bun 中
— Jarred Sumner (@jarredsumner) 2025年1月24日
fs.stat 使用更少記憶體,通過更多 node.js 測試,並且速度更快一些 pic.twitter.com/Zx8FSwN6jP
node:child_process 錯誤修正
修正了在 child_process.spawn
中,當把多個通訊端作為額外檔案描述器關閉時,在控制代碼與子程序關聯之前發生的競爭條件,感謝 @anaisbetts。
Worker 可靠性改進
我們對 Bun 的 Worker
實作進行了數項可靠性改進。Worker 仍然是實驗性的(如文件中所述),但現在更可靠了。
- 修正了不會發出「close」等事件的情況。
- 修正了
terminate
的 Promise 不會解析的情況。
更多錯誤修正
bun run
不再嘗試執行 JSON 檔案
先前,如果您執行 bun .
且存在 index.json
檔案,Bun 會嘗試執行它。現在,Bun 不會這樣做了。
感謝 @pfgithub 的修正!
已修正:fs.Dir.close 回歸
修正了 fs.Dir.close 中的回歸問題,感謝 @DonIsaac。
Buffer.prototype.toLocaleString === Buffer.prototype.toString
Buffer.prototype.toLocaleString 現在是 Buffer.prototype.toString 的別名,與 Node.js 行為一致。
const buf = Buffer.from("Hello world");
console.log(buf.toString === buf.toLocaleString); // true
已修正:dgram 通訊端位址/埠重複使用
UDP 通訊端中的 reuseAddr
和 reusePort
選項現在可以在跨平台更可靠地運作。在 Linux 上,reusePort
啟用了多個程序之間的負載平衡。在其他平台上,reuseAddr
允許重複使用已在使用的位址。
import { createSocket } from "node:dgram";
// Enable address reuse
const socket = createSocket({
reuseAddr: true, // Allow reusing address
reusePort: true, // Enable load balancing on Linux
});
socket.bind(8000);
感謝 @heimskr!
已修正:Bun.inspect 中的 Symbol() 格式設定
現在,當使用 Bun.inspect()
或 console.log()
時,具有空描述的空 Symbols 和 Symbols 會以括號正確格式化。
console.log(Symbol()); // Symbol()
console.log(Symbol("")); // Symbol()
已修正:Bun.pathToFileURL 中的記憶體洩漏
修正了 Bun.pathToFileURL
中的記憶體洩漏。這是由於參考計數遞增太多次所造成的。
已修正:Bun.serve() 中影響某些請求的記憶體洩漏
在某些情況下,對於具有特定 URL 的請求可能會發生記憶體洩漏。此問題已修正。這是由於在一個程式碼路徑中未遞減參考計數所造成的。
已修正:Bun v1.2 中某些字串的記憶體洩漏回歸
Bun 的 JavaScriptCore <> Zig 繫結中的一個問題導致某些字串的參考計數未遞減。此問題已修正。
已修正:AbortSignal GC 過早
修正了 AbortSignal
可能會過早進行垃圾回收的錯誤。當傳遞給 fetch
或 Bun.spawn
且未附加 "abort"
事件監聽器時,就會發生這種情況。此錯誤可能會導致不發出 "abort"
事件。