我們正在舊金山招聘系統工程師,共同打造 JavaScript 的未來!
此版本修正了 61 個錯誤(解決了 99 個 👍)。它引入了 bun.lock
,一種新的文字型鎖定檔格式。它使快取 bun install
速度提升了 30%。它增加了對 fetch()
請求主體串流的支援。它將 Node.js 的 string_decoder
、punycode
和 querystring
提升到 100% Node.js 相容性。它為 Bun.build()
新增了原生插件 API,以及與 napi.rs 集成的 Rust crate。它實作了 expect().toMatchInlineSnapshot()
。它增加了更精確的堆積快照。它減少了 WebSocket 伺服器記憶體用量。它升級了 WebKit,帶來了 Error.isError
、更快的 String.prototype.at
等功能。
安裝 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
bun.lock
是 bun 的新文字型鎖定檔
在此版本中,我們新增了一種新的可讀鎖定檔格式:bun.lock
。這使 git diff 和合併衝突更好地工作,並解鎖了 Dependabot、Renovate、Turbo prune 等工具。
要試用它,請執行
bun install --save-text-lockfile
在此過程中,我們還將快取 bun install
速度提升了 30%。特別是,當先前已安裝套件,且需要驗證每個已安裝套件的版本以確保它們沒有變更時(在本地執行 bun install
時的常見情境)。
非常感謝 @dylan-conway 實作此功能!
fetch() 請求主體串流
您現在可以將 fetch()
Request
主體作為串流傳送。先前,只有 Response
主體可以在用戶端中串流(Bun.serve() 始終支援兩者)。
這在用戶端上使用 HTTP/1.1 Transfer-Encoding: chunked
。當內容長度事先已知時,它會改用 Content-Length
。
在下一個版本的 Bun 中
— Bun (@bunjavascript) 2024 年 12 月 5 日
fetch() 的主體支援串流 ReadableStream、Node.js 串流和 async generator* 函式 pic.twitter.com/s6V2ugfEkK
感謝 @cirospaciari 實作此功能!
Node.js 相容性
已修正:postgres
套件連線錯誤時的凍結
兩個不同的錯誤可能導致 postgres
套件凍結
- 當傳遞給
net.connect
的AbortSignal
發出訊號時,Bun 在net.Socket
上呼叫destroy
而不是發出abort
事件。此問題已修正,感謝 @cirospaciari! - 在來自升級 TLS 連線的
net.Socket
上呼叫pause
可能會導致底層 socket 暫停,而不僅僅是 node:stream。
感謝 @cirospaciari 進行修正!
100% 的 Node 的 string_decoder
測試通過
我們修正了 "string_decoder"
模組處理不完整多位元組字元的邊緣案例,使其與 Node.js 一致,現在所有 Node.js 的 string_decoder 測試都通過了。
感謝 @paperclover!
100% 的 Node 的 punycode
測試通過
Bun 現在與 Node.js punycode 實作完全相容。
感謝 @snoglobe!
100% 的 Node 的 querystring
測試通過
我們修正了 "querystring"
模組中的一些邊緣案例,使其與 Node.js 一致。
感謝 @pfgithub!
改進的 node:path 測試覆蓋率
除了 Node 的 path
測試現在都通過了(新加入的方法 path.matchesGlob
的測試尚未實作)。
感謝 @DonIsaac!
改進的 node:os 測試覆蓋率
os
模組中僅剩一個測試失敗。
已修正:crypto.createHash(alg, options)
缺少選項
感謝 @heimskr!
已修正:napi_wrap
napi_wrap
函式現在的行為與 Node.js 中相同。
感謝 @190n!
已修正:node:zlib 中的錯誤代碼
Bun 對於 zlib 錯誤未拋出與 Node.js 完全相同的 error.code
屬性。此問題已修正,感謝 @nektro!
已修正:在物件中使用 flag
參數的 fs.readFileSync
以下程式碼會錯誤地忽略 flag
參數
import fs from "fs";
fs.readFileSync("data.txt", { encoding: "utf8", flag: "w+" });
此問題已修正,感謝 @pfgithub!
Bundler 改進
onBeforeParse
- Rust/C/Zig 插件 API
此版本為 Bun.build()
引入了新的零複製原生插件 API。與我們的 JavaScript 插件 API 不同,這會在 Bun 的線程池內、緊接在剖析之前執行,無需複製原始程式碼、無需經過字串轉換,且幾乎沒有額外負荷。
bun add -g @napi-rs/cli
napi new
cargo add bun-native-plugin
從那裡,您可以實作 onBeforeParse
hook
use bun_native_plugin::{define_bun_plugin, OnBeforeParse, bun, Result, anyhow, BunLoader};
use napi_derive::napi;
/// Define the plugin and its name
define_bun_plugin!("replace-foo-with-bar");
/// Here we'll implement `onBeforeParse` with code that replaces all occurrences of
/// `foo` with `bar`.
///
/// We use the #[bun] macro to generate some of the boilerplate code.
///
/// The argument of the function (`handle: &mut OnBeforeParse`) tells
/// the macro that this function implements the `onBeforeParse` hook.
#[bun]
pub fn replace_foo_with_bar(handle: &mut OnBeforeParse) -> Result<()> {
// Fetch the input source code.
let input_source_code = handle.input_source_code()?;
// Get the Loader for the file
let loader = handle.output_loader();
let output_source_code = input_source_code.replace("foo", "bar");
handle.set_output_source_code(output_source_code, BunLoader::BUN_LOADER_JSX);
Ok(())
}
在 Bun.build()
中使用
import myNativeAddon from "./my-native-addon";
Bun.build({
entrypoints: ["./app.tsx"],
plugins: [
{
name: "my-plugin",
setup(build) {
build.onBeforeParse(
{
namespace: "file",
filter: "**/*.tsx",
},
{
napiModule: myNativeAddon,
symbol: "replace_foo_with_bar",
// external: myNativeAddon.getSharedState()
},
);
},
},
],
});
此插件 API 旨在與 NAPI 附加元件一起使用,以便現有程式庫可以新增這些附加元件,而無需過多考慮如何初始化它們。
感謝 @zackradisic 實作此功能!
CSS 剖析器改進
修正了多個 CSS 剖析器和列印器邊緣案例,感謝 @zackradisic!
在 Bun.build()
中注入環境變數
此版本增加了對在 Bun.build()
和 bun build
中注入環境變數的支援
// In Bun.build()
await Bun.build({
entrypoints: ['./app.tsx'],
outdir: './out',
// All environment variables starting with "PUBLIC_"
// will be injected in the build as process.env.PUBLIC_*
env: "PUBLIC_*",
// eg
// console.log(process.env.PUBLIC_FOO); => "bar"
});
await Bun.build({
entrypoints: ['./app.tsx'],
outdir: './out',
// Inject all environment variables in the build when used.
env: "inline",
});
bun build ./app.tsx --env='PUBLIC_*'
bun build ./app.tsx --env=inline
內嵌快照測試
此版本在 bun:test
中實作了 expect().toMatchInlineSnapshot()
。內嵌快照直接儲存在測試檔案中,並使用 bun test -u
更新。
import { expect, test } from "bun:test";
test("format user profile", () => {
const result = formatProfile({
name: "Jarred",
role: "admin",
});
// Snapshot stored directly in test file
expect(result).toMatchInlineSnapshot(`{
"displayName": "Jarred",
"permissions": ["admin"],
"createdAt": "2024-12-13T00:00:00.000Z"
}`);
});
test("validate input", () => {
// Match error messages
expect(() => validateInput({})).toThrowErrorMatchingInlineSnapshot(`
"Invalid input:
- Missing required field: name"
`);
});
使用以下命令更新快照
bun test -u
我們也新增了
expect().toThrowErrorMatchingSnapshot()
expect().toThrowErrorMatchingInlineSnapshot()
感謝 @pfgithub 實作此功能!
記憶體分析器改進
我們已實作在 JavaScriptCore <> Zig 類別綁定產生器中報告來自原生程式碼的記憶體用量的支援。這使堆積快照報告更準確
Blob
、Request
和Response
現在報告的大小包括它們的主體、URL 和底層結構,而不僅僅是 JavaScript 包裝器物件大小。URLSearchParams
和Headers
現在報告 C++ 類別的大小以及每個字串的大小。ServerWebSocket
和WebSocket
現在報告底層結構和緩衝資料的大小FormData
的大小現在包括每個字串的大小、底層 C++ 類別以及其中包含的任何檔案的大小。Subprocess
(Bun.spawn
) 報告底層結構和緩衝資料的大小Bun.file().writer()
報告緩衝資料的大小- 所有其他在 Zig 中實作的類別都會報告其內部結構的大小
這不會影響垃圾收集器或執行階段的記憶體用量,但這確實讓您更容易偵錯使用 Bun 的應用程式中佔用記憶體的內容。
新增:"bun:jsc"
中的 estimateShallowMemoryUsageOf
"bun:jsc"
中的 estimateShallowMemoryUsageOf
函式估計 JavaScript 值的記憶體用量,但不包括其子項、屬性或內部插槽的記憶體用量。
import { estimateShallowMemoryUsageOf } from "bun:jsc";
const obj = { foo: "bar" };
const usage = estimateShallowMemoryUsageOf(obj);
console.log(usage); // => 16
const buffer = Buffer.alloc(1024 * 1024);
estimateShallowMemoryUsageOf(buffer);
// => 1048624
WebSocket 伺服器記憶體減少
此版本減少了 Bun 內建 WebSocket 伺服器 Bun.serve()
的記憶體用量,特別是對於開啟和關閉許多 WebSocket 伺服器連線的長時間執行程序。
在這個在迴圈中開啟和關閉 200,000 個 WebSocket 連線的微基準測試中,峰值 RSS 下降了 15%。
微基準測試
依賴項升級
我們已更新多個依賴項
- c-ares 至 v1.34.3
- lshpack 至 v2.3.3
- libdeflate 至 v1.22
- SQLite 至 3.470.200
- BoringSSL
WebKit 升級
此版本升級了來自上游 WebKit 的 JavaScriptCore 內部版本,其中包括迴圈展開、Intl.PluralRules
和 Intl.NumberFormat
等方面的改進。
Error.isError
如果 object
確實是 Error
實例,則 Error.isError(object)
方法會傳回 true
。
Error.isError(new Error()); // => true
Error.isError({}); // => false
Error.isError(new Error("foo")); // => true
Error.isError(new Error("foo").message); // => false
Error.isError({ [Symbol.toStringTag]: "Error" }); // => false
Error.isError(new (class Error {})()); // => false
Error.isError({ constructor: function Error() {} }); // => false
Error.isError
是 stage3 TC39 提案.
更快的 String.prototype.at
在下一個版本的 Bun 和 Safari 中
— Bun (@bunjavascript) 2024 年 12 月 12 日
"foo".at(i) 速度提升 44%,感謝 @__sosukesuzuki pic.twitter.com/UtkkJSp6Vb
錯誤修正
已修正:VSCode 中偵錯器的不穩定性
程序有時會在偵錯器可以附加之前退出。如果您仍然遇到此問題,請告知我們!
此問題已修正,感謝 @RiskyMH
已修正:POSIX 訊號處理中的崩潰
在註冊訊號處理常式(例如 process.on('SIGINT')
或 process.on('SIGTERM')
)並重複接收訊號後可能發生的崩潰或死鎖已修正。
已修正:Bun Shell 和 Bun.spawn
中罕見的檔案描述符洩漏
Bun Shell 和 Bun.spawn
中理論上的檔案描述符洩漏已修正。這可能會在舊版 Linux 中於其他線程上產生程序時發生。
事實證明,我們也並非總是正確地將檔案描述符標記為非阻塞,此問題也已修正。
已修正:使用 "Connection: close"
的 fetch 重定向處理
當 fetch()
使用 "Connection": "close"
重新導向時,Bun 可能會報告連線錯誤,而不是按預期處理重新導向。感謝 @cirospaciari 進行修正!
已修正:在工作區中使用無效 package.json 執行 bun install 時崩潰
在具有無效 package.json
檔案的工作區上執行 bun install
時可能發生的崩潰已修正。
已修正:Bun.build() 插件中罕見的崩潰
Bun.build() 插件中可能發生的罕見崩潰已修正。如果插件中使用 "file"
加載器,則可能會發生這種情況。
已修正:在 TypeScript 檔案中包含大量註解時 Bun.build() 崩潰
在某些情況下,當 TypeScript 檔案中存在大量註解時可能發生的崩潰已修正,感謝 @dylan-conway!
已修正:全域 .npmrc 未使用驗證
驗證配置僅針對每個 .npmrc 檔案應用,然後被捨棄。因此,在全域 .npmrc 中定義的驗證不會應用於專案 .npmrc 中的登錄檔。
此問題已修正,感謝 @robertshuford!