工具函数
使用 Bun 的实用函数操作运行时环境
Bun.version
包含当前正在运行的 bun CLI 版本的字符串。
Bun.version;
// => "1.3.3"
Bun.revision
用于构建当前 bun CLI 的 Bun 的 git 提交哈希值。
Bun.revision;
// => "f02561530fda1ee9396f51c8bc99b38716e38296"
Bun.env
process.env 的别名。
Bun.main
当前程序入口点的绝对路径(即你通过 bun run 执行的文件)。
Bun.main;
// /path/to/script.ts
使用此属性可确定脚本是直接运行,还是由另一个脚本导入。
if (import.meta.path === Bun.main) {
// 这个脚本被直接执行
} else {
// 这个文件被其他脚本导入
}
此检查类似于 Node.js 中的 require.main = module 技巧。
Bun.sleep()
Bun.sleep(ms: number)
返回一个在指定毫秒后完成的 Promise。
console.log("hello");
await Bun.sleep(1000);
console.log("hello one second later!");
或者,传入一个 Date 对象,返回在该时间点完成的 Promise。
const oneSecondInFuture = new Date(Date.now() + 1000);
console.log("hello");
await Bun.sleep(oneSecondInFuture);
console.log("hello one second later!");
Bun.sleepSync()
Bun.sleepSync(ms: number)
同步阻塞版本的 Bun.sleep。
console.log("hello");
Bun.sleepSync(1000); // 阻塞线程一秒钟
console.log("hello one second later!");
Bun.which()
Bun.which(bin: string)
返回可执行文件的路径,类似于终端中输入 which。
const ls = Bun.which("ls");
console.log(ls); // "/usr/bin/ls"
默认情况下,Bun 会查看当前的 PATH 环境变量。要自定义 PATH:
const ls = Bun.which("ls", {
PATH: "/usr/local/bin:/usr/bin:/bin",
});
console.log(ls); // "/usr/bin/ls"
传入 cwd 选项,可从特定目录中解析可执行文件。
const ls = Bun.which("ls", {
cwd: "/tmp",
PATH: "",
});
console.log(ls); // null
这是 which npm 包的内置替代方案。
Bun.randomUUIDv7()
Bun.randomUUIDv7() 生成一个 UUID v7,它具有单调性,适合排序和数据库使用。
import { randomUUIDv7 } from "bun";
const id = randomUUIDv7();
// => "0192ce11-26d5-7dc3-9305-1426de888c5a"
UUID v7 是一种 128 位值,其中编码了当前时间戳、一个随机值和一个计数器。时间戳使用最高有效的 48 位进行编码,随机值和计数器则使用剩余位进行编码。
timestamp 参数默认为当前时间(以毫秒为单位)。当时钟前进时,Bun 会将计数器重新设定为一个新的伪随机整数。Bun 在重新设定计数器时会将其 12 位中的最高位清零,因此在回绕之前至少还剩 2048 个值。如果时钟尚未前进到超过上次发出的时间戳,Bun 会重用上次发出的时间戳并递增计数器。如果计数器回绕,Bun 会将发出的时间戳向前推进,而不是让计数器回绕,因此返回的 UUID 会保持严格递增(RFC 9562 §6.2)。计数器是原子操作且线程安全的,因此同一进程中多个 Worker 在同一时间戳下调用 Bun.randomUUIDv7() 时,不会产生冲突的计数器值。
传入显式的 timestamp 时,Bun 会原样编码该值,并为其跟踪单独的计数器,因此显式时间戳调用不会观察或更改默认路径使用的单调状态。使用相同的显式时间戳重复调用时,会递增该独立计数器;计数器回绕时,也会向前推进发出的时间戳,因此生成的 UUID 始终可排序。使用不同的显式时间戳调用时,会重新设定该计数器。
UUID 的最后 8 个字节(除两个变体位外)是一个密码学安全的随机值。Bun.randomUUIDv7() 使用与 crypto.randomUUID() 相同的随机数生成器。该生成器来自 BoringSSL。BoringSSL 的随机性则来自平台专用的系统随机数生成器,而底层硬件通常会提供该生成器。
namespace Bun {
function randomUUIDv7(encoding?: "hex" | "base64" | "base64url" = "hex", timestamp?: number = Date.now()): string;
/**
* 传入 "buffer" 时,返回 16 字节的 Buffer 而非字符串。
*/
function randomUUIDv7(encoding: "buffer", timestamp?: number = Date.now()): Buffer;
// 只传时间戳参数时返回十六进制字符串
function randomUUIDv7(timestamp?: number = Date.now()): string;
}
将 "buffer" 作为编码传入,即可获取一个 16 字节的缓冲区,而不是字符串。这样可以避免字符串转换开销。
const buffer = Bun.randomUUIDv7("buffer");
还支持 base64 和 base64url 编码,以获得更短的字符串。
const base64 = Bun.randomUUIDv7("base64");
const base64url = Bun.randomUUIDv7("base64url");
Bun.peek()
Bun.peek(prom: Promise)
读取 Promise 的结果而无须 await 或 .then,前提是 Promise 已经完成或拒绝。
import { peek } from "bun";
const promise = Promise.resolve("hi");
// 不用 await!
const result = peek(promise);
console.log(result); // "hi"
在对性能敏感的代码中使用它来避免多余的微任务。这是一个高级 API;在生产环境中使用前,请先查看以下示例。
import { peek } from "bun";
import { expect, test } from "bun:test";
test("peek", () => {
const promise = Promise.resolve(true);
// 不用 await
expect(peek(promise)).toBe(true);
// 再次 peek 返回相同值
const again = peek(promise);
expect(again).toBe(true);
// peek 非 Promise 类型返回原值
const value = peek(42);
expect(value).toBe(42);
// peek 一个挂起的 Promise 返回该 Promise
const pending = new Promise(() => {});
expect(peek(pending)).toBe(pending);
// peek 拒绝的 Promise:
// - 返回错误对象
// - 不标记 Promise 已处理
const rejected = Promise.reject(new Error("Successfully tested promise rejection"));
expect(peek(rejected).message).toBe("Successfully tested promise rejection");
});
peek.status 读取 Promise 的状态,而不会解析它。
import { peek } from "bun";
import { expect, test } from "bun:test";
test("peek.status", () => {
const promise = Promise.resolve(true);
expect(peek.status(promise)).toBe("fulfilled");
const pending = new Promise(() => {});
expect(peek.status(pending)).toBe("pending");
const rejected = Promise.reject(new Error("oh nooo"));
expect(peek.status(rejected)).toBe("rejected");
});
Bun.openInEditor()
在默认编辑器中打开文件。Bun 会根据 $VISUAL 或 $EDITOR 环境变量自动检测编辑器。
const currentFile = import.meta.url;
Bun.openInEditor(currentFile);
你可以通过 bunfig.toml 中的 debug.editor 设置覆盖此行为。
[debug] # [!code ++]
editor = "code" # [!code ++]
或者通过 editor 参数指定编辑器,并指定行列号。
Bun.openInEditor(import.meta.url, {
editor: "vscode", // 或 "subl"
line: 10,
column: 5,
});
Bun.deepEquals()
递归检查两个对象是否等价。bun:test 中的 expect().toEqual() 内部使用了这个方法。
const foo = { a: 1, b: 2, c: { d: 3 } };
// true
Bun.deepEquals(foo, { a: 1, b: 2, c: { d: 3 } });
// false
Bun.deepEquals(foo, { a: 1, b: 2, c: { d: 4 } });
传入第三个布尔参数以启用“严格”模式。测试运行器中的 expect().toStrictEqual() 使用这个模式。
const a = { entries: [1, 2] };
const b = { entries: [1, 2], extra: undefined };
Bun.deepEquals(a, b); // => true
Bun.deepEquals(a, b, true); // => false
在严格模式下,Bun 会将以下情况视为不相等:
// undefined 值
Bun.deepEquals({}, { a: undefined }, true); // false
// 数组中的 undefined
Bun.deepEquals(["asdf"], ["asdf", undefined], true); // false
// 稀疏数组
Bun.deepEquals([, 1], [undefined, 1], true); // false
// 对象字面量与类实例(即使属性相同)
class Foo {
a = 1;
}
Bun.deepEquals(new Foo(), { a: 1 }, true); // false
Bun.escapeHTML()
Bun.escapeHTML(value: string | object | number | boolean): string
转义输入字符串中的以下字符:
"转为"&转为&'转为'<转为<>转为>
此函数针对大型输入进行了优化。在 M1 Max 上,其处理速度为 480 MB/s 至 20 GB/s,具体取决于要转义的数据量以及是否包含非 ASCII 文本。Bun 会先将非字符串类型转换为字符串,再进行转义。
Bun.stringWidth()
获取字符串在终端中显示时所占的列数。支持 ANSI 转义码、表情符号和宽字符。
示例:
Bun.stringWidth("hello"); // => 5
Bun.stringWidth("\u001b[31mhello\u001b[0m"); // => 5
Bun.stringWidth("\u001b[31mhello\u001b[0m", { countAnsiEscapeCodes: true }); // => 12
用于在终端中对齐文本,或检查字符串是否包含 ANSI 转义码。
此 API 与 "string-width" npm 包相同,因此你可以将现有代码移植到 Bun,反之亦然。
在此基准测试中,对于长度大于约 500 个字符的输入,Bun.stringWidth 比 string-width npm 包快约 6,756 倍。非常感谢 sindresorhus 在 string-width 方面所做的工作。
❯ bun string-width.mjs
cpu: 13th Gen Intel(R) Core(TM) i9-13900
runtime: bun 1.0.29 (x64-linux)
benchmark time (avg) (min … max) p75 p99 p995
------------------------------------------------------------------------------------- -----------------------------
Bun.stringWidth 500 chars ascii 37.09 ns/iter (36.77 ns … 41.11 ns) 37.07 ns 38.84 ns 38.99 ns
❯ node string-width.mjs
benchmark time (avg) (min … max) p75 p99 p995
------------------------------------------------------------------------------------- -----------------------------
npm/string-width 500 chars ascii 249,710 ns/iter (239,970 ns … 293,180 ns) 250,930 ns 276,700 ns 281,450 ns
Bun.stringWidth 使用原生代码和 SIMD 指令实现,并支持 Latin1、UTF-16 和 UTF-8 编码。它通过了 string-width 的测试。
查看完整基准测试
1 纳秒(ns)是十亿分之一秒。单位换算如下:
| 单位 | 1 毫秒等于 |
|---|---|
| ns | 1,000,000 |
| µs | 1,000 |
| ms | 1 |
❯ bun string-width.mjs
cpu: 13th Gen Intel(R) Core(TM) i9-13900
runtime: bun 1.0.29 (x64-linux)
benchmark time (avg) (min … max) p75 p99 p995
------------------------------------------------------------------------------------- -----------------------------
Bun.stringWidth 5 chars ascii 16.45 ns/iter (16.27 ns … 19.71 ns) 16.48 ns 16.93 ns 17.21 ns
Bun.stringWidth 50 chars ascii 19.42 ns/iter (18.61 ns … 27.85 ns) 19.35 ns 21.7 ns 22.31 ns
Bun.stringWidth 500 chars ascii 37.09 ns/iter (36.77 ns … 41.11 ns) 37.07 ns 38.84 ns 38.99 ns
Bun.stringWidth 5,000 chars ascii 216.9 ns/iter (215.8 ns … 228.54 ns) 216.23 ns 228.52 ns 228.53 ns
Bun.stringWidth 25,000 chars ascii 1.01 µs/iter (1.01 µs … 1.01 µs) 1.01 µs 1.01 µs 1.01 µs
Bun.stringWidth 7 chars ascii+emoji 54.2 ns/iter (53.36 ns … 58.19 ns) 54.23 ns 57.55 ns 57.94 ns
Bun.stringWidth 70 chars ascii+emoji 354.26 ns/iter (350.51 ns … 363.96 ns) 355.93 ns 363.11 ns 363.96 ns
Bun.stringWidth 700 chars ascii+emoji 3.3 µs/iter (3.27 µs … 3.4 µs) 3.3 µs 3.4 µs 3.4 µs
Bun.stringWidth 7,000 chars ascii+emoji 32.69 µs/iter (32.22 µs … 45.27 µs) 32.7 µs 34.57 µs 34.68 µs
Bun.stringWidth 35,000 chars ascii+emoji 163.35 µs/iter (161.17 µs … 170.79 µs) 163.82 µs 169.66 µs 169.93 µs
Bun.stringWidth 8 chars ansi+emoji 66.15 ns/iter (65.17 ns … 69.97 ns) 66.12 ns 69.8 ns 69.87 ns
Bun.stringWidth 80 chars ansi+emoji 492.95 ns/iter (488.05 ns … 499.5 ns) 494.8 ns 498.58 ns 499.5 ns
Bun.stringWidth 800 chars ansi+emoji 4.73 µs/iter (4.71 µs … 4.88 µs) 4.72 µs 4.88 µs 4.88 µs
Bun.stringWidth 8,000 chars ansi+emoji 47.02 µs/iter (46.37 µs … 67.44 µs) 46.96 µs 49.57 µs 49.63 µs
Bun.stringWidth 40,000 chars ansi+emoji 234.45 µs/iter (231.78 µs … 240.98 µs) 234.92 µs 236.34 µs 236.62 µs
Bun.stringWidth 19 chars ansi+emoji+ascii 135.46 ns/iter (133.67 ns … 143.26 ns) 135.32 ns 142.55 ns 142.77 ns
Bun.stringWidth 190 chars ansi+emoji+ascii 1.17 µs/iter (1.16 µs … 1.17 µs) 1.17 µs 1.17 µs 1.17 µs
Bun.stringWidth 1,900 chars ansi+emoji+ascii 11.45 µs/iter (11.26 µs … 20.41 µs) 11.45 µs 12.08 µs 12.11 µs
Bun.stringWidth 19,000 chars ansi+emoji+ascii 114.06 µs/iter (112.86 µs … 120.06 µs) 114.25 µs 115.86 µs 116.15 µs
Bun.stringWidth 95,000 chars ansi+emoji+ascii 572.69 µs/iter (565.52 µs … 607.22 µs) 572.45 µs 604.86 µs 605.21 µs
❯ node string-width.mjs
cpu: 13th Gen Intel(R) Core(TM) i9-13900
runtime: node v21.4.0 (x64-linux)
benchmark time (avg) (min … max) p75 p99 p995
-------------------------------------------------------------------------------------- -----------------------------
npm/string-width 5 chars ascii 3.19 µs/iter (3.13 µs … 3.48 µs) 3.25 µs 3.48 µs 3.48 µs
npm/string-width 50 chars ascii 20.09 µs/iter (18.93 µs … 435.06 µs) 19.49 µs 21.89 µs 22.59 µs
npm/string-width 500 chars ascii 249.71 µs/iter (239.97 µs … 293.18 µs) 250.93 µs 276.7 µs 281.45 µs
npm/string-width 5,000 chars ascii 6.69 ms/iter (6.58 ms … 6.76 ms) 6.72 ms 6.76 ms 6.76 ms
npm/string-width 25,000 chars ascii 139.57 ms/iter (137.17 ms … 143.28 ms) 140.49 ms 143.28 ms 143.28 ms
npm/string-width 7 chars ascii+emoji 3.7 µs/iter (3.62 µs … 3.94 µs) 3.73 µs 3.94 µs 3.94 µs
npm/string-width 70 chars ascii+emoji 23.93 µs/iter (22.44 µs … 331.2 µs) 23.15 µs 25.98 µs 30.2 µs
npm/string-width 700 chars ascii+emoji 251.65 µs/iter (237.78 µs … 444.69 µs) 252.92 µs 325.89 µs 354.08 µs
npm/string-width 7,000 chars ascii+emoji 4.95 ms/iter (4.82 ms … 5.19 ms) 5 ms 5.04 ms 5.19 ms
npm/string-width 35,000 chars ascii+emoji 96.93 ms/iter (94.39 ms … 102.58 ms) 97.68 ms 102.58 ms 102.58 ms
npm/string-width 8 chars ansi+emoji 3.92 µs/iter (3.45 µs … 4.57 µs) 4.09 µs 4.57 µs 4.57 µs
npm/string-width 80 chars ansi+emoji 24.46 µs/iter (22.87 µs … 4.2 ms) 23.54 µs 25.89 µs 27.41 µs
npm/string-width 800 chars ansi+emoji 259.62 µs/iter (246.76 µs … 480.12 µs) 258.65 µs 349.84 µs 372.55 µs
npm/string-width 8,000 chars ansi+emoji 5.46 ms/iter (5.41 ms … 5.57 ms) 5.48 ms 5.55 ms 5.57 ms
npm/string-width 40,000 chars ansi+emoji 108.91 ms/iter (107.55 ms … 109.5 ms) 109.25 ms 109.5 ms 109.5 ms
npm/string-width 19 chars ansi+emoji+ascii 6.53 µs/iter (6.35 µs … 6.75 µs) 6.54 µs 6.75 µs 6.75 µs
npm/string-width 190 chars ansi+emoji+ascii 55.52 µs/iter (52.59 µs … 352.73 µs) 54.19 µs 80.77 µs 167.21 µs
npm/string-width 1,900 chars ansi+emoji+ascii 701.71 µs/iter (653.94 µs … 893.78 µs) 715.3 µs 855.37 µs 872.9 µs
npm/string-width 19,000 chars ansi+emoji+ascii 27.19 ms/iter (26.89 ms … 27.41 ms) 27.28 ms 27.41 ms 27.41 ms
npm/string-width 95,000 chars ansi+emoji+ascii 3.68 s/iter (3.66 s … 3.7 s) 3.69 s 3.7 s 3.7 s
TypeScript 定义:
namespace Bun {
export function stringWidth(
/**
* 要测量的字符串
*/
input: string,
options?: {
/**
* 为 `true` 时,计算 ANSI 转义码为字符串宽度一部分。为 `false` 时忽略 ANSI 转义码。
*
* @default false
*/
countAnsiEscapeCodes?: boolean;
/**
* 模糊情况下,为 `true` 时表情符号宽度算作 1,`false` 视作 2。
*
* @default true
*/
ambiguousIsNarrow?: boolean;
},
): number;
}
Bun.fileURLToPath()
将 file:// URL 转换成绝对路径。
const path = Bun.fileURLToPath(new URL("file:///foo/bar.txt"));
console.log(path); // "/foo/bar.txt"
Bun.pathToFileURL()
将绝对路径转换成 file:// URL。
const url = Bun.pathToFileURL("/foo/bar.txt");
console.log(url); // "file:///foo/bar.txt"
Bun.gzipSync()
使用 zlib 的 GZIP 算法压缩 Uint8Array。
const buf = Buffer.from("hello".repeat(100)); // Buffer 继承自 Uint8Array
const compressed = Bun.gzipSync(buf);
buf; // => Uint8Array(500)
compressed; // => Uint8Array(30)
可选传入配置参数:
zlib 压缩选项
export type ZlibCompressionOptions = {
/**
* 压缩级别,范围 -1 到 9。
* - `-1` 默认压缩级别(当前为 6)
* - `0` 无压缩
* - `1` 最低压缩,最快速度
* - `9` 最佳压缩,最慢速度
*/
level?: -1 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9;
/**
* 内部压缩状态分配内存量。
*
* 值为 `1` 表示最小内存但较慢且压缩率低。
*
* 值为 `9` 表示最大内存以优化速度,默认 8。
*/
memLevel?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9;
/**
* 窗口大小的 base 2 对数(历史数据缓冲区大小)。
*
* 较大值提高压缩但增加内存消耗。
*
* 支持范围:
* - 9..15: 输出包含 zlib 头尾(Deflate)
* - -9..-15: 输出无 zlib 头尾(Raw Deflate)
* - 25..31 (16+9..15): 输出有 gzip 头尾(gzip)
*
* gzip 头部无文件名、无额外数据、无注释、无修改时间(置零)、无头部 CRC。
*/
windowBits?:
| -9
| -10
| -11
| -12
| -13
| -14
| -15
| 9
| 10
| 11
| 12
| 13
| 14
| 15
| 25
| 26
| 27
| 28
| 29
| 30
| 31;
/**
* 调整压缩算法策略。
*
* - `Z_DEFAULT_STRATEGY`: 普通数据(默认)
* - `Z_FILTERED`: 过滤器或预测器产生的数据
* - `Z_HUFFMAN_ONLY`: 仅 Huffman 编码(无字符串匹配)
* - `Z_RLE`: 限制匹配距离为 1(游程编码)
* - `Z_FIXED`: 禁止使用动态 Huffman 编码
*
* `Z_RLE` 性能接近 `Z_HUFFMAN_ONLY`,但对 PNG 等数据压缩更优。
*
* `Z_FILTERED` 强制更多 Huffman 编码,通常用于包含小且随机分布值的数据。
*/
strategy?: number;
};
Bun.gunzipSync()
使用 zlib 的 GUNZIP 算法解压 Uint8Array。
const buf = Buffer.from("hello".repeat(100)); // Buffer 继承自 Uint8Array
const compressed = Bun.gzipSync(buf);
const dec = new TextDecoder();
const uncompressed = Bun.gunzipSync(compressed);
dec.decode(uncompressed);
// => "hellohellohello..."
Bun.deflateSync()
使用 zlib 的 DEFLATE 算法压缩 Uint8Array。
const buf = Buffer.from("hello".repeat(100));
const compressed = Bun.deflateSync(buf);
buf; // => Buffer(500)
compressed; // => Uint8Array(12)
第二个参数支持与 Bun.gzipSync 相同的配置选项。
Bun.inflateSync()
使用 zlib 的 INFLATE 算法解压 Uint8Array。
const buf = Buffer.from("hello".repeat(100));
const compressed = Bun.deflateSync(buf);
const dec = new TextDecoder();
const decompressed = Bun.inflateSync(compressed);
dec.decode(decompressed);
// => "hellohellohello..."
Bun.zstdCompress() / Bun.zstdCompressSync()
使用 Zstandard 算法压缩 Uint8Array。
const buf = Buffer.from("hello".repeat(100));
// 同步压缩
const compressedSync = Bun.zstdCompressSync(buf);
// 异步压缩
const compressedAsync = await Bun.zstdCompress(buf);
// 指定压缩等级(1-22,默认 3)
const compressedLevel = Bun.zstdCompressSync(buf, { level: 6 });
Bun.zstdDecompress() / Bun.zstdDecompressSync()
使用 Zstandard 算法解压 Uint8Array。
const buf = Buffer.from("hello".repeat(100));
const compressed = Bun.zstdCompressSync(buf);
// 同步解压
const decompressedSync = Bun.zstdDecompressSync(compressed);
// 异步解压
const decompressedAsync = await Bun.zstdDecompress(compressed);
const dec = new TextDecoder();
dec.decode(decompressedSync);
// => "hellohellohello..."
Bun.inspect()
将对象序列化为 string,其格式与 console.log 打印出的内容完全相同。
const obj = { foo: "bar" };
Bun.inspect(obj);
// => '{\n foo: "bar",\n}'
const arr = new Uint8Array([1, 2, 3]);
Bun.inspect(arr);
// => "Uint8Array(3) [ 1, 2, 3 ]"
Bun.inspect.custom
Bun 用于实现 Bun.inspect 的符号。重写它可自定义 Bun 打印对象的方式。它与 Node.js 中的 util.inspect.custom 完全相同。
class Foo {
[Bun.inspect.custom]() {
return "foo";
}
}
const foo = new Foo();
console.log(foo); // => "foo"
Bun.inspect.table(tabularData, properties, options)
将表格数据格式化为字符串。类似 console.table,但返回字符串而非打印。
console.log(
Bun.inspect.table([
{ a: 1, b: 2, c: 3 },
{ a: 4, b: 5, c: 6 },
{ a: 7, b: 8, c: 9 },
]),
);
//
// ┌───┬───┬───┬───┐
// │ │ a │ b │ c │
// ├───┼───┼───┼───┤
// │ 0 │ 1 │ 2 │ 3 │
// │ 1 │ 4 │ 5 │ 6 │
// │ 2 │ 7 │ 8 │ 9 │
// └───┴───┴───┴───┘
传入属性名称数组,只显示这些属性。
console.log(
Bun.inspect.table(
[
{ a: 1, b: 2, c: 3 },
{ a: 4, b: 5, c: 6 },
],
["a", "c"],
),
);
//
// ┌───┬───┬───┐
// │ │ a │ c │
// ├───┼───┼───┤
// │ 0 │ 1 │ 3 │
// │ 1 │ 4 │ 6 │
// └───┴───┴───┘
传入 { colors: true } 以启用 ANSI 颜色。
console.log(
Bun.inspect.table(
[
{ a: 1, b: 2, c: 3 },
{ a: 4, b: 5, c: 6 },
],
{
colors: true,
},
),
);
Bun.nanoseconds()
返回当前 bun 进程启动以来的纳秒数(number 类型)。适合高精度计时和基准测试。
Bun.nanoseconds();
// => 7288958
Bun.readableStreamTo*()
Bun 实现了一组方便函数,可异步消费 ReadableStream 的内容并转换成各种二进制格式。
const stream = (await fetch("https://bun.sh")).body;
stream; // => ReadableStream
await Bun.readableStreamToArrayBuffer(stream);
// => ArrayBuffer
await Bun.readableStreamToBytes(stream);
// => Uint8Array
await Bun.readableStreamToBlob(stream);
// => Blob
await Bun.readableStreamToJSON(stream);
// => object
await Bun.readableStreamToText(stream);
// => string
// 返回所有块组成的数组
await Bun.readableStreamToArray(stream);
// => unknown[]
// 返回所有块组成的 FormData,编码为 x-www-form-urlencoded
await Bun.readableStreamToFormData(stream);
// 返回所有块组成的 FormData,编码为 multipart/form-data
await Bun.readableStreamToFormData(stream, multipartFormBoundary);
Bun.resolveSync()
使用 Bun 的内部模块解析算法解析文件路径或模块说明符。第一个参数是要解析的路径,第二个参数是“根目录”。如果没有匹配项,则会抛出一个 Error。
Bun.resolveSync("./foo.ts", "/path/to/project");
// => "/path/to/project/foo.ts"
Bun.resolveSync("zod", "/path/to/project");
// => "/path/to/project/node_modules/zod/index.ts"
若想相对于当前工作目录解析,传入 process.cwd() 或 "."。
Bun.resolveSync("./foo.ts", process.cwd());
Bun.resolveSync("./foo.ts", "/path/to/project");
相对于当前文件所在目录解析,传入 import.meta.dir。
Bun.resolveSync("./foo.ts", import.meta.dir);
Bun.stripANSI()
Bun.stripANSI(text: string): string
从字符串中移除 ANSI 转义码。可用于移除终端输出中的颜色和格式。
const coloredText = "\u001b[31mHello\u001b[0m \u001b[32mWorld\u001b[0m";
const plainText = Bun.stripANSI(coloredText);
console.log(plainText); // => "Hello World"
// 支持各种 ANSI 码
const formatted = "\u001b[1m\u001b[4mBold and underlined\u001b[0m";
console.log(Bun.stripANSI(formatted)); // => "Bold and underlined"
Bun.stripANSI 比 strip-ansi npm 包更快:
bun bench/snippets/strip-ansi.mjs
cpu: Apple M3 Max
runtime: bun 1.2.21 (arm64-darwin)
benchmark avg (min … max) p75 / p99
------------------------------------------------------- ----------
Bun.stripANSI 11 chars no-ansi 8.13 ns/iter 8.27 ns
(7.45 ns … 33.59 ns) 10.29 ns
Bun.stripANSI 13 chars ansi 51.68 ns/iter 52.51 ns
(46.16 ns … 113.71 ns) 57.71 ns
Bun.stripANSI 16,384 chars long-no-ansi 298.39 ns/iter 305.44 ns
(281.50 ns … 331.65 ns) 320.70 ns
Bun.stripANSI 212,992 chars long-ansi 227.65 µs/iter 234.50 µs
(216.46 µs … 401.92 µs) 262.25 µs
node bench/snippets/strip-ansi.mjs
cpu: Apple M3 Max
runtime: node 24.6.0 (arm64-darwin)
benchmark avg (min … max) p75 / p99
-------------------------------------------------------- ---------
npm/strip-ansi 11 chars no-ansi 466.79 ns/iter 468.67 ns
(454.08 ns … 570.67 ns) 543.67 ns
npm/strip-ansi 13 chars ansi 546.77 ns/iter 550.23 ns
(532.74 ns … 651.08 ns) 590.35 ns
npm/strip-ansi 16,384 chars long-no-ansi 4.85 µs/iter 4.89 µs
(4.71 µs … 5.00 µs) 4.98 µs
npm/strip-ansi 212,992 chars long-ansi 1.36 ms/iter 1.38 ms
(1.27 ms … 1.73 ms) 1.49 ms
serialize 和 deserialize 来自 bun:jsc
Bun.wrapAnsi(input: string, columns: number, options?: WrapAnsiOptions): string
将文本换行至指定的列宽。它会保留 ANSI 转义码和超链接,并正确处理 Unicode/表情符号的宽度。这是 wrap-ansi npm 包的原生替代方案。
// 在 20 列处进行基本换行
Bun.wrapAnsi("The quick brown fox jumps over the lazy dog", 20);
// => "The quick brown fox\njumps over the lazy\ndog"
// 保留 ANSI 转义码:开放样式会在每行末尾关闭,
// 并在下一行重新打开,以确保每一行单独渲染时都能正确显示
Bun.wrapAnsi("\u001b[31mThe quick brown fox jumps over the lazy dog\u001b[0m", 20);
// => "\u001b[31mThe quick brown fox\u001b[39m\n\u001b[31mjumps over the lazy\u001b[39m\n\u001b[31mdog\u001b[0m"
选项
Bun.wrapAnsi("Hello World", 5, {
hard: true, // 拆分超过列宽的单词(默认值:false)
wordWrap: true, // 在单词边界处换行(默认值:true)
trim: true, // 去除每行开头和结尾的空白字符(默认值:true)
ambiguousIsNarrow: true, // 将不明确宽度的字符视为窄字符(默认值:true)
});
| 选项 | 默认值 | 描述 |
|---|---|---|
hard | false | 如果为 true,当单词超过列宽时,在单词中间进行拆分。 |
wordWrap | true | 如果为 true,在单词边界处换行。如果为 false,则每行都严格在列宽处断开。 |
trim | true | 如果为 true,去除每行开头和结尾的空白字符。 |
ambiguousIsNarrow | true | 如果为 true,将不明确宽度的 Unicode 字符视为占 1 列。如果为 false,则视为占 2 列。 |
TypeScript 定义:
namespace Bun {
export function wrapAnsi(
/**
* 要换行的字符串
*/
input: string,
/**
* 最大列宽
*/
columns: number,
/**
* 换行选项
*/
options?: {
/**
* 如果为 `true`,当单词无法适应一行时,在单词中间进行拆分。
* 如果为 `false`,仅在单词边界处断开。
*
* @default false
*/
hard?: boolean;
/**
* 如果为 `true`,则尽可能在单词边界处换行。
* 如果为 `false`,则每行都严格在列宽处断开(字符会在限制所在位置被拆分,
* 忽略单词边界)。
*
* @default true
*/
wordWrap?: boolean;
/**
* 如果为 `true`,去除每行开头和结尾的空白字符。
* 如果为 `false`,保留空白字符。
*
* @default true
*/
trim?: boolean;
/**
* 当字符宽度不明确且该选项为 `true` 时,将不明确宽度的字符按占 1 列计算。
* 如果为 `false`,则按占 2 列计算。
*
* @default true
*/
ambiguousIsNarrow?: boolean;
},
): string;
}
serialize 和 deserialize 来自 bun:jsc
要将 JavaScript 值保存到 SharedArrayBuffer 中并取回,请使用 "bun:jsc" 模块中的 serialize 和 deserialize。
import { serialize, deserialize } from "bun:jsc";
const buf = serialize({ foo: "bar" });
const obj = deserialize(buf);
console.log(obj); // => { foo: "bar" }
在内部,structuredClone 和 postMessage 使用相同的方式进行序列化和反序列化。serialize 和 deserialize 将底层的 HTML 结构化克隆算法作为 SharedArrayBuffer 暴露给 JavaScript。
estimateShallowMemoryUsageOf 来自 bun:jsc
estimateShallowMemoryUsageOf 函数返回对象的浅层内存占用估计,单位是字节,不包括其属性或引用对象的内存。要准确测量单个对象的内存,推荐使用 Bun.generateHeapSnapshot。
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
const req = new Request("https://bun.sh");
estimateShallowMemoryUsageOf(req);
// => 167
const array = Array(1024).fill({ a: 1 });
// 数组通常不连续存储,返回结果不可用于衡量完整内存占用(非错误)。
estimateShallowMemoryUsageOf(array);
// => 16