initial commit

This commit is contained in:
i2p
2026-08-27 21:09:14 +00:00
commit a5b6d59437
12681 changed files with 3253832 additions and 0 deletions
+301
View File
@@ -0,0 +1,301 @@
---
title: Benchmarking
description: How to benchmark Bun
---
Bun is designed for speed. We profile and benchmark hot paths extensively. The source code for all of Bun's public benchmarks is in the [`/bench`](https://github.com/oven-sh/bun/tree/main/bench) directory of the Bun repo.
## Measuring time
To measure time precisely, Bun offers two runtime APIs:
1. The Web-standard [`performance.now()`](https://developer.mozilla.org/en-US/docs/Web/API/Performance/now) function
2. `Bun.nanoseconds()`, which is like `performance.now()` except it returns the time since the application started in nanoseconds. Use `performance.timeOrigin` to convert this to a Unix timestamp.
## Benchmarking tools
- For microbenchmarks, we recommend [`mitata`](https://github.com/evanwashere/mitata).
- For load testing, you _must use_ an HTTP benchmarking tool that is at least as fast as `Bun.serve()`, or your results will be skewed. Some popular Node.js-based benchmarking tools like [`autocannon`](https://github.com/mcollina/autocannon) are not fast enough. We recommend one of the following:
- [`bombardier`](https://github.com/codesenberg/bombardier)
- [`oha`](https://github.com/hatoo/oha)
- [`http_load_test`](https://github.com/uNetworking/uSockets/blob/master/examples/http_load_test.c)
- For benchmarking scripts or CLI commands, we recommend [`hyperfine`](https://github.com/sharkdp/hyperfine).
## Measuring memory usage
Bun has two heaps: one for the JavaScript runtime, and one for everything else.
### JavaScript heap stats
The `bun:jsc` module exposes a few functions for measuring memory usage:
```ts
import { heapStats } from "bun:jsc";
console.log(heapStats());
```
<Accordion title="View example statistics">
```ts expandable icon="/icons/typescript.svg"
{
heapSize: 1657575,
heapCapacity: 2872775,
extraMemorySize: 598199,
objectCount: 13790,
protectedObjectCount: 62,
globalObjectCount: 1,
protectedGlobalObjectCount: 1,
// A count of every object type in the heap
objectTypeCounts: {
CallbackObject: 25,
FunctionExecutable: 2078,
AsyncGeneratorFunction: 2,
'RegExp String Iterator': 1,
FunctionCodeBlock: 188,
ModuleProgramExecutable: 13,
String: 1,
UnlinkedModuleProgramCodeBlock: 13,
JSON: 1,
AsyncGenerator: 1,
Symbol: 1,
GetterSetter: 68,
ImportMeta: 10,
DOMAttributeGetterSetter: 1,
UnlinkedFunctionCodeBlock: 174,
RegExp: 52,
ModuleLoader: 1,
Intl: 1,
WeakMap: 4,
Generator: 2,
PropertyTable: 95,
'Array Iterator': 1,
JSLexicalEnvironment: 75,
UnlinkedFunctionExecutable: 2067,
WeakSet: 1,
console: 1,
Map: 23,
SparseArrayValueMap: 14,
StructureChain: 19,
Set: 18,
'String Iterator': 1,
FunctionRareData: 3,
JSGlobalLexicalEnvironment: 1,
Object: 481,
BigInt: 2,
StructureRareData: 55,
Array: 179,
AbortController: 2,
ModuleNamespaceObject: 11,
ShadowRealm: 1,
'Immutable Butterfly': 103,
Primordials: 1,
'Set Iterator': 1,
JSGlobalProxy: 1,
AsyncFromSyncIterator: 1,
ModuleRecord: 13,
FinalizationRegistry: 1,
AsyncIterator: 1,
InternalPromise: 22,
Iterator: 1,
CustomGetterSetter: 65,
Promise: 19,
WeakRef: 1,
InternalPromisePrototype: 1,
Function: 2381,
AsyncFunction: 2,
GlobalObject: 1,
ArrayBuffer: 2,
Boolean: 1,
Math: 1,
CallbackConstructor: 1,
Error: 2,
JSModuleEnvironment: 13,
WebAssembly: 1,
HashMapBucket: 300,
Callee: 3,
symbol: 37,
string: 2484,
Performance: 1,
ModuleProgramCodeBlock: 12,
JSSourceCode: 13,
JSPropertyNameEnumerator: 3,
NativeExecutable: 290,
Number: 1,
Structure: 1550,
SymbolTable: 108,
GeneratorFunction: 2,
'Map Iterator': 1
},
protectedObjectTypeCounts: {
CallbackConstructor: 1,
BigInt: 1,
RegExp: 2,
GlobalObject: 1,
UnlinkedModuleProgramCodeBlock: 13,
HashMapBucket: 2,
Structure: 41,
JSPropertyNameEnumerator: 1
}
}
```
</Accordion>
JavaScript is a garbage-collected language, not reference counted. It's normal and correct for objects to not be freed immediately in all cases, though it's not normal for objects to never be freed.
To force garbage collection to run manually:
```ts
Bun.gc(true); // synchronous
Bun.gc(false); // asynchronous
```
Heap snapshots show which objects are not being freed. Use `Bun.generateHeapSnapshot()` to take a heap snapshot, then view it with Safari or WebKit GTK developer tools. To generate a heap snapshot:
```ts
import { generateHeapSnapshot } from "bun";
const snapshot = generateHeapSnapshot();
await Bun.write("heap.json", JSON.stringify(snapshot, null, 2));
```
To view the snapshot, open the `heap.json` file in Safari's Developer Tools (or WebKit GTK):
1. Open the Developer Tools
2. Click "Timeline"
3. Click "JavaScript Allocations" in the menu on the left. It might not be visible until you click the pencil icon to show all the timelines
4. Click "Import" and select your heap snapshot JSON
<Frame>
<img
src="https://user-images.githubusercontent.com/709451/204428943-ba999e8f-8984-4f23-97cb-b4e3e280363e.png"
alt="Importing a heap snapshot"
/>
</Frame>
Once imported, you should see something like this:
<Frame>
<img
alt="Viewing heap snapshot in Safari"
src="https://user-images.githubusercontent.com/709451/204429337-b0d8935f-3509-4071-b991-217794d1fb27.png"
caption="Viewing heap snapshot in Safari Dev Tools"
/>
</Frame>
> The [web debugger](/runtime/debugger#inspect) timeline also tracks the memory usage of the running debug session.
### Native heap stats
Bun uses mimalloc for the other heap. To print a summary of non-JavaScript memory usage, call `Bun.unsafe.mimallocDump()`.
```ts
Bun.unsafe.mimallocDump();
```
```txt
heap stats: peak total freed current unit count
reserved: 64.0 MiB 64.0 MiB 0 64.0 MiB not all freed!
committed: 64.0 MiB 64.0 MiB 0 64.0 MiB not all freed!
reset: 0 0 0 0 ok
touched: 128.5 KiB 128.5 KiB 5.4 MiB -5.3 MiB ok
segments: 1 1 0 1 not all freed!
-abandoned: 0 0 0 0 ok
-cached: 0 0 0 0 ok
pages: 0 0 53 -53 ok
-abandoned: 0 0 0 0 ok
-extended: 0
-noretire: 0
mmaps: 0
commits: 0
threads: 0 0 0 0 ok
searches: 0.0 avg
numa nodes: 1
elapsed: 0.068 s
process: user: 0.061 s, system: 0.014 s, faults: 0, rss: 57.4 MiB, commit: 64.0 MiB
```
## CPU profiling
Profile JavaScript execution to identify performance bottlenecks with the `--cpu-prof` flag.
```sh terminal icon="terminal"
bun --cpu-prof script.js
```
`--cpu-prof` writes a `.cpuprofile` file you can open in Chrome DevTools (Performance tab → Load profile) or VS Code's CPU profiler.
### Markdown output
Use `--cpu-prof-md` to generate a markdown CPU profile, which is grep-friendly and designed for LLM analysis:
```sh terminal icon="terminal"
bun --cpu-prof-md script.js
```
Combine `--cpu-prof` and `--cpu-prof-md` to generate both formats at once:
```sh terminal icon="terminal"
bun --cpu-prof --cpu-prof-md script.js
```
You can also pass the flag through the `BUN_OPTIONS` environment variable:
```sh terminal icon="terminal"
BUN_OPTIONS="--cpu-prof-md" bun script.js
```
### Options
```sh terminal icon="terminal"
bun --cpu-prof --cpu-prof-name my-profile.cpuprofile script.js
bun --cpu-prof --cpu-prof-dir ./profiles script.js
```
| Flag | Description |
| ---------------------------- | ----------------------------------------------------------- |
| `--cpu-prof` | Generate a `.cpuprofile` JSON file (Chrome DevTools format) |
| `--cpu-prof-md` | Generate a markdown CPU profile (grep/LLM-friendly) |
| `--cpu-prof-name <filename>` | Set output filename |
| `--cpu-prof-dir <dir>` | Set output directory |
## Heap profiling
Write a heap profile on exit to analyze memory usage and find memory leaks.
```sh terminal icon="terminal"
bun --heap-prof script.js
```
`--heap-prof` writes a full V8-format heap snapshot on exit, using Node.js's
diagnostic filename format
(`Heap.<yyyymmdd>.<hhmmss>.<pid>.<tid>.<seq>.heapprofile`). The extension
follows Node's `--heap-prof` filename contract. The content is the same as
`v8.writeHeapSnapshot()` /
`Bun.generateHeapSnapshot("v8")`. Load it in Chrome DevTools via
Memory tab → Load. Pick "All Files", or rename the file to `.heapsnapshot`.
### Markdown output
Use `--heap-prof-md` to generate a markdown heap profile for CLI analysis:
```sh terminal icon="terminal"
bun --heap-prof-md script.js
```
<Note>If you specify both `--heap-prof` and `--heap-prof-md`, Bun uses the markdown format.</Note>
### Options
```sh terminal icon="terminal"
bun --heap-prof --heap-prof-name my-profile.heapprofile script.js
bun --heap-prof --heap-prof-dir ./profiles script.js
```
| Flag | Description |
| ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------ |
| `--heap-prof` | Write a `.heapprofile` file on exit |
| `--heap-prof-md` | Generate a markdown heap profile on exit |
| `--heap-prof-name <filename>` | Set output filename |
| `--heap-prof-dir <dir>` | Set output directory |
| `--heap-prof-interval <bytes>` | Accepted for Node.js compatibility (the snapshot is taken once at exit; JavaScriptCore has no allocation sampling to apply an interval to) |
+285
View File
@@ -0,0 +1,285 @@
---
title: Bindgen
description: Bindgen for Bun
---
<Note>This document is for maintainers and contributors to Bun, and describes internal implementation details.</Note>
The bindings generator scans for `*.bind.ts` files to find function and class
definitions, and generates glue code to interop between JavaScript and native
code.
There are other code generators and systems that achieve similar purposes;
the following will all eventually be phased out in favor of this one:
- "Classes generator", converting `*.classes.ts` for custom classes.
- "JS2Native", allowing ad-hoc calls from `src/js` to native code.
## Creating JS Functions in Rust
Given a file implementing a function, such as `add`:
```rust src/jsc/bindgen_test.rs
use crate::{JSGlobalObject, JsResult};
use crate::r#gen::bindgen_test as generated;
pub fn add(global: &JSGlobalObject, a: i32, b: i32) -> JsResult<i32> {
match a.checked_add(b) {
Some(v) => Ok(v),
None => {
// Binding functions can propagate out-of-memory and JS exceptions
// directly; other failures (like this integer overflow) must be
// converted into a thrown error. Remember to be descriptive.
Err(global.throw(format_args!("Integer overflow while adding")))
}
}
}
```
Then describe the API schema using a `.bind.ts` file. The binding file goes
next to the Rust file.
```ts src/jsc/bindgen_test.bind.ts icon="/icons/typescript.svg"
import { fn, t } from "bindgen";
export const add = fn({
args: {
global: t.globalObject,
a: t.i32,
b: t.i32.default(-1),
},
ret: t.i32,
});
```
This function declaration is equivalent to:
```ts
/**
* Throws if zero arguments are provided.
* Wraps out of range numbers using modulo.
*/
declare function add(a: number, b: number = -1): number;
```
The code generator emits a C++ thunk that validates and coerces the JS
arguments, then calls the Rust implementation. On the Rust side bindgen emits
nothing; both the dispatch shim the thunk calls
(`bindgen_Bindgen_test_dispatchAdd1` in `src/runtime/hw_exports.rs`, which
calls `add`) and the `create_*_callback` module in
`src/jsc/bindings/GeneratedBindings.rs` are hand-written. The module is
reachable as `crate::r#gen::<basename>` (for `bindgen_test.bind.ts`, that's
`crate::r#gen::bindgen_test`). To construct a `JSFunction` wrapping the
native implementation, use `generated::create_add_callback(global)`:
```rust
use crate::r#gen::bindgen_test as generated;
let js_fn: JSValue = generated::create_add_callback(global);
```
In JS files in `src/js/`, `$bindgenFn("bindgen_test.bind.ts", "add")` returns
a handle to the implementation, through a hand-written
`js2native_bindgen_<basename>_<fn>` export in `src/runtime/hw_exports.rs`.
Exported bindgen functions are snake_cased on the Rust side
(`requiredAndOptionalArg` → `required_and_optional_arg`). The hand-written
callback constructor follows the same convention
(`create_required_and_optional_arg_callback`).
## Strings
To receive a string, use [`t.DOMString`](https://webidl.spec.whatwg.org/#idl-DOMString), [`t.ByteString`](https://webidl.spec.whatwg.org/#idl-ByteString), or [`t.USVString`](https://webidl.spec.whatwg.org/#idl-USVString). These map directly to their WebIDL counterparts and have slightly different conversion logic. Bindgen passes `bun_core::String` to native code in all cases.
When in doubt, use DOMString.
`t.UTF8String` works in place of `t.DOMString`, but eagerly converts to UTF-8.
The native callback receives a `&[u8]` slice (WTF-8 data) that is
freed after the function returns.
TLDRs from the WebIDL spec:
- ByteString can only contain valid latin1 characters. It is not safe to assume `bun_core::String` is already in 8-bit format, but it is extremely likely.
- USVString does not contain invalid surrogate pairs, so its text can be represented correctly in UTF-8.
- DOMString is the loosest but also the most recommended strategy.
## Function Variants
The `variants` key declares multiple variants (also known as overloads) of a function.
```ts
import { fn, t } from "bindgen";
export const action = fn({
variants: [
{
args: {
a: t.i32,
},
ret: t.i32,
},
{
args: {
a: t.DOMString,
},
ret: t.DOMString,
},
],
});
```
Each variant gets a numbered Rust function:
```rust
pub fn action1(a: i32) -> i32 {
a
}
pub fn action2(a: bun_core::String) -> bun_core::String {
a
}
```
## `t.dictionary`
A `dictionary` describes a JavaScript object, typically a function input. For function outputs, prefer a class type so you can add methods and support destructuring.
## Enumerations
`t.stringEnum` creates a [WebIDL enumeration](https://webidl.spec.whatwg.org/#idl-enums) and generates a new enum type for it.
An example of `stringEnum` from `fmt_jsc.bind.ts` / `bun:internal-for-testing`:
```ts
export const Formatter = t.stringEnum("highlight-javascript", "highlight-javascript-redacted", "escape-powershell");
export const fmtString = fn({
args: {
global: t.globalObject,
code: t.UTF8String,
formatter: Formatter,
},
ret: t.DOMString,
});
```
On the Rust side, the enum is mirrored as a `#[repr(u8)]` enum. Bindgen
**sorts `t.stringEnum` values alphabetically** before emitting the C++
`enum class`, so discriminants must match the generated header's order, not
the `.bind.ts` declaration order:
```rust
#[repr(u8)]
#[derive(Copy, Clone, Eq, PartialEq)]
pub enum Formatter {
EscapePowershell = 0,
HighlightJavascript = 1,
HighlightJavascriptRedacted = 2,
}
pub fn fmt_string(
global: &JSGlobalObject,
code: &[u8],
formatter_id: Formatter,
) -> JsResult<bun_core::String> {
// ...
}
```
WebIDL strongly encourages kebab-case for enumeration values, to be consistent with existing Web APIs.
## `t.oneOf`
A `oneOf` is a union of two or more types. It is represented as a Rust
`enum` with one variant per member type.
## Attributes
You can chain attributes onto `t.*` types. On all types:
- `.required`, in dictionary parameters only
- `.optional`, in function arguments only
- `.default(T)`
When a value is `.optional`, it is lowered to a Rust `Option<T>`:
```ts
export const requiredAndOptionalArg = fn({
args: {
a: t.boolean,
b: t.usize.optional,
c: t.i32.enforceRange(0, 100).default(42),
d: t.u8.optional,
},
ret: t.i32,
});
```
```rust
pub fn required_and_optional_arg(a: bool, b: Option<usize>, c: i32, d: Option<u8>) -> i32 {
// ...
}
```
Depending on the type, more attributes are available. See the type definitions
in auto-complete for details. You can apply only one of these three attributes,
and you must apply it last.
### Integer Attributes
Integer types take `clamp` or `enforceRange` to customize overflow behavior:
```ts
import { fn, t } from "bindgen";
export const add = fn({
args: {
global: t.globalObject,
// enforce in i32 range
a: t.i32.enforceRange(),
// clamp to u16 range
b: t.u16,
// enforce in arbitrary range, with a default if not provided
c: t.i32.enforceRange(0, 1000).default(5),
// clamp to arbitrary range, or None
d: t.u16.clamp(0, 10).optional,
},
ret: t.i32,
});
```
Node.js validator functions such as `validateInteger` and `validateNumber`
are also available. Use these when implementing Node.js APIs so the error
messages match Node exactly.
Unlike `enforceRange`, which is taken from WebIDL, the `validate*` functions
are much stricter about the input they accept. For example, Node's numerical
validator checks `typeof value === 'number'`, while WebIDL uses `ToNumber` for
lossy conversion.
```ts
import { fn, t } from "bindgen";
export const add = fn({
args: {
global: t.globalObject,
// throw if not given a number
a: t.f64.validateNumber(),
// valid in i32 range
b: t.i32.validateInt32(),
// f64 within safe integer range
c: t.f64.validateInteger(),
// f64 in given range
d: t.f64.validateNumber(-10000, 10000),
},
ret: t.i32,
});
```
## Callbacks
TODO
## Classes
TODO
+195
View File
@@ -0,0 +1,195 @@
---
title: Building Windows
description: Building Bun on Windows
---
Use [PowerShell 7 (`pwsh.exe`)](https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell-on-windows?view=powershell-7.4) instead of the default `powershell.exe`. If you run into problems, ask in the [#contributing channel on our Discord](http://bun.com/discord).
## Prerequisites
### Enable Scripts
By default, running unverified scripts is blocked.
```ps1
Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy Unrestricted
```
### System Dependencies
Bun v1.1 or later. The build uses Bun to run its own code generators.
```ps1
irm bun.sh/install.ps1 | iex
```
[Visual Studio](https://visualstudio.microsoft.com) with the "Desktop Development with C++" workload. While installing, also install Git if Git for Windows is not already installed.
Install Visual Studio with the graphical wizard or through WinGet:
```ps1
winget install "Visual Studio Community 2022" --override "--add Microsoft.VisualStudio.Workload.NativeDesktop Microsoft.VisualStudio.Component.Git " -s msstore
```
After Visual Studio, you need the following:
- LLVM 21.1.8
- Go
- Rust (via rustup)
- NASM
- Perl
- Ruby
- Node.js
<Note>rustup installs the Rust nightly toolchain pinned in `rust-toolchain.toml` on the first build.</Note>
Use [Scoop](https://scoop.sh) to install these remaining tools.
```ps1 Scoop (x64)
irm https://get.scoop.sh | iex
scoop install nodejs-lts go rustup nasm ruby perl ccache
# scoop seems to be buggy if you install llvm and the rest at the same time
scoop install [email protected]
```
For Windows ARM64, download LLVM 21.1.8 directly from GitHub releases (first version with ARM64 Windows builds):
```ps1 ARM64
# Download and install LLVM for ARM64
Invoke-WebRequest -Uri "https://github.com/llvm/llvm-project/releases/download/llvmorg-21.1.8/LLVM-21.1.8-woa64.exe" -OutFile "$env:TEMP\LLVM-21.1.8-woa64.exe"
Start-Process -FilePath "$env:TEMP\LLVM-21.1.8-woa64.exe" -ArgumentList "/S" -Wait
```
<Note>
Do not install these with WinGet or another package manager: you will likely get Strawberry Perl instead of a more
minimal installation of Perl. Strawberry Perl adds many other utilities to `$Env:PATH` that conflict with MSVC and
break the build.
</Note>
To build WebKit locally (optional, x64 only), install these packages:
```ps1 Scoop
scoop install make cygwin python
```
<Note>ARM64 builds do not need Cygwin because WebKit is provided as a pre-built binary.</Note>
From here on out, **use a PowerShell terminal with `.\scripts\vs-shell.ps1` sourced**. Load the script by running it:
```ps1
.\scripts\vs-shell.ps1
```
To verify, check for an MSVC-only command such as `mt.exe`:
```ps1
Get-Command mt
```
<Note>
Avoid installing `ninja` / `cmake` into your global path: you may end up building Bun without `.\scripts\vs-shell.ps1`
sourced.
</Note>
## Building
```ps1
bun run build
# after the initial `bun run build` you can use the following to build
ninja -Cbuild/debug
```
A successful build writes `bun-debug.exe` to the `build/debug` folder.
```ps1
.\build\debug\bun-debug.exe --revision
```
Add this folder to `$Env:PATH`: open the Start menu, type "Path", and use the environment variables menu to add `C:\.....\bun\build\debug` to the user environment variable `PATH`. Then restart your editor (if it still does not pick up the change, log out and log back in).
## Extra paths
- The build extracts WebKit to `$Env:BUN_INSTALL\build-cache\webkit-<version>-debug` (`webkit-<version>-arm64-debug` on ARM64); `BUN_INSTALL` defaults to `~\.bun`
## Tests
Run the test suite with `bun-debug test <path>` or with the wrapper script `bun run test <path>`. The `bun run test` command runs every test file in a separate instance of `bun-debug.exe`, so a crash in the test runner does not stop the entire suite.
```ps1
# Run the entire test suite with reporter
# the package.json script "test" uses "build/debug/bun-debug.exe" by default
bun run test
# Run an individual test file:
bun-debug test node\fs
bun-debug test "C:\bun\test\js\bun\resolve\import-meta.test.js"
```
## Troubleshooting
### .rc file fails to build
`llvm-rc.exe` is odd; don't use it. Use `rc.exe` instead: make sure you are in a Visual Studio dev terminal, and check `rc /?` to confirm it is `Microsoft Resource Compiler`.
### failed to write output 'bun-debug.exe': permission denied
You cannot overwrite `bun-debug.exe` while it is open. You likely have a running instance, maybe in the VS Code debugger.
## Cross-compiling from Linux
You can also build Windows binaries (both x64 and arm64) on a Linux host. The build uses the host LLVM's `clang-cl`, `lld-link`, `llvm-lib` and `llvm-rc` (part of every LLVM distribution). For headers and import libraries, the build also uses an "xwin splat" of the MSVC CRT/STL and Windows SDK.
### Prerequisites
1. The same LLVM version a native build uses (see `scripts/bootstrap.sh` `llvm_version_exact`), installed so that `clang-cl`, `lld-link`, `llvm-lib` and `llvm-rc` are available. On Debian/Ubuntu, `apt.llvm.org` packages provide all of them.
2. `nasm` (only needed for Windows x64; BoringSSL's x64 assembly is NASM syntax).
3. Rust std for the Windows targets (`rust-toolchain.toml` lists them; `rustup target add x86_64-pc-windows-msvc aarch64-pc-windows-msvc` if missing).
4. A Windows sysroot: an [xwin](https://github.com/Jake-Shadle/xwin) splat of the MSVC CRT, Windows SDK, and ATL laid out like a Visual Studio install. Downloading these components means accepting Microsoft's license terms for them.
```bash
cargo install xwin # or download a release binary
xwin --accept-license --arch x86_64,aarch64 --sdk-version 10.0.26100 --crt-version 14.44.17.14 --include-atl splat \
--use-winsysroot-style --preserve-ms-arch-notation --include-debug-libs \
--output /opt/winsysroot
# clang-cl/lld-link look up SDK paths as "Include"/"Lib"; the splat writes
# them lowercase, so alias both spellings (needs the same privileges as the
# splat — configure creates these itself when the directory is writable).
ln -s include "/opt/winsysroot/Windows Kits/10/Include"
ln -s lib "/opt/winsysroot/Windows Kits/10/Lib"
```
The build looks for the sysroot at `/opt/winsysroot` (or `/opt/xwin`) automatically. If the sysroot is elsewhere, set `WINDOWS_SYSROOT=<path>` or pass `--winsysroot=<path>`. A user-writable path also lets configure manage the aliases for you. Configure validates the splat at the start of every cross build. CI agents bake the same splat into their images (`.buildkite/Dockerfile`, `scripts/bootstrap.sh`); when an agent doesn't have one, the build fetches it into its cache dir at configure time.
### Building
```bash
# Debug builds
bun run build --profile=windows-x64
bun run build --profile=windows-arm64
# Release builds
bun run build --profile=windows-x64-release
bun run build --profile=windows-arm64-release
```
Output lands in `build/debug-windows-x64/bun-debug.exe`, `build/release-windows-aarch64/bun-profile.exe` + `bun.exe`, and so on. Equivalent raw flags: `bun run build --os=windows --arch=aarch64`.
The build does not run cross-compiled executables on the host (it skips the `--revision` smoke test), so test them on a Windows machine or under Wine.
### LTO
x64 release cross builds support ThinLTO with cross-language (Rust↔C++) LTO. It's opt-in:
```bash
bun run build --profile=windows-x64-release --lto=on
```
`--lto=on` does the following:
- compiles Bun's C/C++ with `-flto=thin`
- makes rustc emit LLVM bitcode (`-Clinker-plugin-lto`)
- pulls the `bun-webkit-windows-amd64-lto` ThinLTO prebuilt
- links everything with rustc's bundled `lld-link` (its LLVM is new enough to read both compilers' bitcode)
There is no LTO for arm64, because there is no `-lto` WebKit prebuilt: LLVM's CodeView emitter can't handle ARM64 NEON tuple registers during LTO codegen. There is also no LTO for `--baseline`.
+399
View File
@@ -0,0 +1,399 @@
---
title: Contributing
description: Contributing to Bun
---
Configuring a development environment for Bun can take 10-30 minutes depending on your internet connection and computer speed. You will need ~10GB of free disk space for the repository and build artifacts.
If you are using Windows, see [Building Windows](/project/building-windows).
## Using Nix (Alternative)
The repository includes a Nix flake as an alternative to installing dependencies manually:
```bash
nix develop
bun bd
```
`nix develop` provides all dependencies in an isolated, reproducible environment without requiring sudo.
## Install Dependencies (Manual)
Using your system's package manager, install Bun's dependencies:
<CodeGroup>
```bash macOS (Homebrew)
brew install automake ccache cmake coreutils gnu-sed go icu4c libiconv libtool ninja pkg-config rustup-init ruby
```
```bash Ubuntu/Debian
sudo apt install curl wget lsb-release software-properties-common cmake git golang libtool ninja-build pkg-config ruby-full xz-utils
```
```bash Arch
sudo pacman -S base-devel cmake git go libiconv libtool make ninja pkg-config python rustup sed unzip ruby
```
```bash Fedora
sudo dnf install clang21 llvm21 lld21 cmake git golang libtool ninja-build pkg-config ruby libatomic-static libstdc++-static sed unzip which libicu-devel 'perl(Math::BigInt)'
```
```bash openSUSE Tumbleweed
sudo zypper install go cmake ninja automake git icu rustup
```
</CodeGroup>
Bun is written in Rust and requires a specific nightly toolchain (pinned in `rust-toolchain.toml`). Install Rust with [rustup](https://rustup.rs) rather than your distro's `rust`/`cargo` packages — the build scripts use rustup to automatically install and update the pinned nightly:
```bash
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
```
Before starting, install a release build of Bun: the build uses Bun's bundler to transpile and minify code, and to run the code generation scripts.
<CodeGroup>
```bash Native
curl -fsSL https://bun.com/install | bash
```
```bash npm
npm install -g bun
```
```bash Homebrew
brew tap oven-sh/bun
brew install bun
```
</CodeGroup>
### Optional: Install `ccache`
`ccache` caches compilation artifacts, which speeds up rebuilds:
```bash
# For macOS
brew install ccache
# For Ubuntu/Debian
sudo apt install ccache
# For Arch
sudo pacman -S ccache
# For Fedora
sudo dnf install ccache
# For openSUSE
sudo zypper install ccache
```
The build scripts detect and use `ccache` automatically if it's available. Check cache statistics with `ccache --show-stats`.
## Install LLVM
Bun requires LLVM 21.1.8 (`clang` is part of LLVM). The build system enforces this version: a mismatched version causes memory allocation failures at runtime. In most cases, you can install LLVM through your system package manager:
<CodeGroup>
```bash macOS (Homebrew)
brew install llvm@21
```
```bash Ubuntu/Debian
# LLVM has an automatic installation script that is compatible with all versions of Ubuntu
wget https://apt.llvm.org/llvm.sh -O - | sudo bash -s -- 21 all
```
```bash Arch
sudo pacman -S llvm clang lld
```
```bash Fedora
sudo dnf install llvm clang lld-devel
```
```bash openSUSE Tumbleweed
sudo zypper install clang21 lld21 llvm21
```
</CodeGroup>
If none of these work, install it [manually](https://github.com/llvm/llvm-project/releases/tag/llvmorg-21.1.8).
Make sure Clang/LLVM 21 is in your path:
```bash
which clang-21
```
If not, add it manually:
<CodeGroup>
```bash macOS (Homebrew)
# use fish_add_path if you're using fish
# use path+="$(brew --prefix llvm@21)/bin" if you are using zsh
export PATH="$(brew --prefix llvm@21)/bin:$PATH"
```
```bash Arch
# use fish_add_path if you're using fish
export PATH="$PATH:/usr/lib/llvm21/bin"
```
</CodeGroup>
<Warning>
⚠️ On Ubuntu \<= 20.04, you may need to install the C++ standard library separately. See the [troubleshooting section](#span-file-not-found-on-ubuntu).
</Warning>
## Building Bun
After cloning the repository, run the following command to build. This can take a while: it downloads and builds dependencies.
```bash
bun run build
```
The binary is at `./build/debug/bun-debug`. It is recommended to add this to your `$PATH`. To verify the build worked, print its version:
```bash
build/debug/bun-debug --version
x.y.z_debug
```
## VSCode
VSCode is the recommended IDE for working on Bun; the repository includes configuration for it. After opening the repository, run `Extensions: Show Recommended Extensions` to install the recommended extensions for Rust and C++. rust-analyzer picks up the workspace `Cargo.toml` automatically and uses the pinned toolchain in `rust-toolchain.toml` for analysis, so diagnostics match the build.
If you use a different editor, point rust-analyzer (or your editor's Rust plugin) at the repo root — the Cargo workspace and `rust-toolchain.toml` are discovered automatically.
We recommend adding `./build/debug` to your `$PATH` so that you can run `bun-debug` in your terminal:
```sh
bun-debug
```
## Running debug builds
The `bd` package.json script compiles and runs a debug build of Bun, only printing the output of the build process if it fails.
```sh
bun bd <args>
bun bd test foo.test.ts
bun bd ./foo.ts
```
A full debug build can take a few minutes when Rust or C++ has changed; cargo's incremental compilation makes subsequent Rust-only rebuilds much faster. If your development workflow is "change one line, save, rebuild", you will still spend too much time waiting for the link step. Instead:
- Batch up your changes
- Use `cargo check -p <crate>` (or `bun run rust:check` for the whole workspace) to type-check Rust changes without linking. `bun run watch` runs `cargo check` on every save.
- Ensure rust-analyzer is running for inline diagnostics (the recommended VSCode extensions set this up)
- Prefer using the debugger ("CodeLLDB" in VSCode) to step through the code.
- Use debug logs. `BUN_DEBUG_<scope>=1` enables debug logging for the corresponding `declare_scope!(<scope>, ...)` / `scoped_log!(<scope>, ...)` logs. Set `BUN_DEBUG_QUIET_LOGS=1` to disable all debug logging that isn't explicitly enabled. To dump debug logs into a file, set `BUN_DEBUG=<path-to-file>.log`. Debug logs are removed in release builds.
- src/js/\*\*.ts changes rebuild almost instantly. Single-crate Rust changes and C++ changes are incremental; only the final link is unavoidable.
## Code generation scripts
Bun's build process runs several code generation scripts automatically when certain files change:
- `./src/codegen/generate-jssink.ts` -- Generates `build/debug/codegen/JSSink.cpp`, `build/debug/codegen/JSSink.h` which implement various classes for interfacing with `ReadableStream`. This is internally how `FileSink`, `ArrayBufferSink`, `"type": "direct"` streams and other code related to streams work.
- `./src/codegen/generate-classes.ts` -- Generates Rust & C++ bindings for JavaScriptCore classes implemented in Rust. `**/*.classes.ts` files define the interfaces for classes, methods, prototypes, and getters/setters; the code generator reads them to generate the boilerplate that implements the JavaScript objects in C++ and wires them up to Rust.
- `./src/codegen/cppbind.ts` -- Scans the C++ bindings for functions marked with an export attribute and generates automatic Rust FFI wrappers (`cpp.rs`) for them.
- `./src/codegen/bundle-modules.ts` -- Bundles built-in modules like `node:fs`, `bun:ffi` into files included in the final binary. In development, these can be reloaded without rebuilding native code (you still need to run `bun run build`, but it re-reads the transpiled files from disk afterwards). In release builds, these are embedded into the binary.
- `./src/codegen/bundle-functions.ts` -- Bundles globally-accessible functions implemented in JavaScript/TypeScript like `ReadableStream` and `WritableStream`. These are used similarly to the builtin modules, but the output more closely aligns with what WebKit/Safari does for Safari's built-in functions, so implementations can be copy-pasted from WebKit as a starting point.
## Modifying ESM modules
Certain modules like `node:fs`, `node:stream`, `bun:sqlite`, and `ws` are implemented in JavaScript. These live in `src/js/{node,bun,thirdparty}` files and are pre-bundled using Bun.
## Release build
To compile a release build of Bun, run:
```bash
bun run build:release
```
The binaries are at `./build/release/bun` and `./build/release/bun-profile`.
### Download release build from pull requests
You can run the release build from a pull request without building it locally, which is useful for manually testing changes before they are merged.
Use the `bun-pr` npm package:
```sh
bunx bun-pr <pr-number>
bunx bun-pr <branch-name>
bunx bun-pr "https://github.com/oven-sh/bun/pull/1234566"
bunx bun-pr --asan <pr-number> # Linux x64 only
```
`bun-pr` downloads the release build from the pull request's GitHub Actions artifacts and adds it to `$PATH` as `bun-${pr-number}`, so you can run it directly:
```sh
bun-1234566 --version
```
You may need the `gh` CLI installed to authenticate with GitHub.
### Viewing CI failures from the terminal
Bun's CI runs on BuildKite. Install the [BuildKite CLI](https://github.com/buildkite/cli) (`brew install buildkite/buildkite/bk`) and set `BUILDKITE_API_TOKEN` to a read-scoped [API token](https://buildkite.com/user/api-access-tokens). The repo includes a `.bk.yaml` so `bk` commands default to the `bun` pipeline.
```sh
bun run ci:status # progress summary for the current branch's latest build
bun run ci:errors # rendered test-failure output, tagged [new] vs [also on main]
bun run ci:logs # save full logs for each failed job to ./tmp/ci-<build>/
bun run ci:watch # watch until the build finishes
bun run ci:find # print the build number (compose with raw `bk`)
```
All of these accept a target: `#1234` (PR number), a PR URL, a branch name, or a build number. Without one they use the current git branch.
## AddressSanitizer
[AddressSanitizer](https://en.wikipedia.org/wiki/AddressSanitizer) helps find memory issues, and is enabled by default in debug builds of Bun on Linux and macOS. This covers the Rust code, the C++ bindings, and all dependencies. It makes the build take about 2x longer; if that's stopping you from being productive you can disable it with `bun run build:debug:noasan` (or pass `--asan=off` to `scripts/build.ts`), but generally we recommend batching your changes up between builds.
To build a release build with AddressSanitizer, run:
```bash
bun run build:asan
```
CI runs the test suite with at least one target built with AddressSanitizer.
## Building WebKit locally + Debug mode of JSC
WebKit is not cloned by default (to save time and disk space). To clone and build WebKit locally, run:
```bash
# Clone WebKit into ./vendor/WebKit
git clone https://github.com/oven-sh/WebKit vendor/WebKit
# Check out the version pinned in WEBKIT_VERSION in scripts/build/deps/webkit.ts
# (a commit sha or an autobuild-* release tag; this handles both)
bun sync-webkit-source
# Build bun with the local JSC build — this automatically configures and builds JSC
bun run build:local
```
`bun run build:local` handles everything: configuring JSC, building JSC, and building Bun. On subsequent runs, JSC rebuilds incrementally if any WebKit sources changed. `ninja -Cbuild/debug-local` also works after the first build, and builds both Bun and JSC.
The build output goes to `./build/debug-local` (instead of `./build/debug`), so you'll need to update a couple of places:
- The first line in `src/js/builtins.d.ts`
- The `CompilationDatabase` line in `.clangd` config should be `CompilationDatabase: build/debug-local`
- In `.vscode/launch.json`, many configurations use `./build/debug/`, change them as you see fit
The WebKit folder, including build artifacts, is 8GB+ in size.
If you are using a JSC debug build with VSCode, run the `C/C++: Select a Configuration` command so IntelliSense finds the debug headers.
If you make changes to Bun's [WebKit fork](https://github.com/oven-sh/WebKit), you also have to change `WEBKIT_VERSION` in `scripts/build/deps/webkit.ts` to point to your commit hash or release tag.
## Troubleshooting
### 'span' file not found on Ubuntu
<Warning>
⚠️ These instructions are specific to Ubuntu. The same issues are unlikely on other Linux distributions.
</Warning>
Clang uses `libstdc++`, the C++ standard library implementation provided by the GNU Compiler Collection (GCC), by default. Clang can link against `libc++` instead, but that requires explicitly passing the `-stdlib` flag.
Bun relies on C++20 features like `std::span`, which are not available in GCC versions lower than 11. As a result, running `bun run build` may fail with the following error:
```txt
fatal error: 'span' file not found
#include <span>
^~~~~~
```
The issue may also surface when first running `bun run build`, with Clang unable to compile a simple program:
```txt
The C++ compiler
"/usr/bin/clang++-21"
is not able to compile a simple test program.
```
To fix the error, update GCC to version 11. It may be available in your distribution's official repositories; otherwise, add a third-party repository that provides GCC 11 packages:
```bash
sudo apt update
sudo apt install gcc-11 g++-11
# If the above command fails with `Unable to locate package gcc-11` we need
# to add the APT repository
sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
# Now run `apt install` again
sudo apt install gcc-11 g++-11
```
Then set GCC 11 as the default compiler:
```bash
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-11 100
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-11 100
```
### libarchive
If you see an error on macOS when compiling `libarchive`, run:
```bash
brew install pkg-config
```
### macOS `library not found for -lSystem`
If you see this error when compiling, run:
```bash
xcode-select --install
```
### Cannot find `libatomic.a`
Bun defaults to linking `libatomic` statically, as not all systems have it. If you are building on a distro that does not have a static libatomic available, enable dynamic linking with:
```bash
bun run build --static-libatomic=off
```
The built version of Bun may not work on other systems if compiled this way.
## Using bun-debug
- Disable logging: `BUN_DEBUG_QUIET_LOGS=1 bun-debug ...` (to disable all debug logging)
- Enable logging for a specific scope: `BUN_DEBUG_EventLoop=1 bun-debug ...` (to enable `scoped_log!(EventLoop, ...)` output)
- Bun transpiles every file it runs. To see the actual executed source in a debug build, find it in `/tmp/bun-debug-src/...path/to/file`. For example, the transpiled version of `/home/bun/index.ts` is in `/tmp/bun-debug-src/home/bun/index.ts`
## Contributing to the docs
The docs are the MDX files in `docs/` in the Bun repository. [bun.com/docs](https://bun.com/docs) is built from them.
### Voice
A docs page describes what Bun does and what you can do with it. Write it so that a developer who is new to Bun can read the page once and act on it. These guidelines are adapted from the [Next.js docs contribution guide](https://nextjs.org/docs/community/contribution-guide#voice):
- Write short sentences that each make one point. If a sentence needs several commas or a parenthetical, split it up or turn it into a list.
- Use plain words: "use" rather than "utilize", "to" rather than "in order to". Cut filler such as "Note that" and "Please".
- Use the active voice and name the actor: "Bun reads `bunfig.toml`", rather than "`bunfig.toml` is read". A sentence built around "is" and "by" is usually passive.
- Describe current behavior in the present tense: "Bun installs the package", rather than "Bun will install the package".
- Name the subject when "this" or "it" could refer to more than one thing: "`--isolate` is how Jest behaves by default", rather than "This is how Jest behaves by default".
- Address the reader as "you", and make Bun (or the specific tool) the other actor: "Bun caches the tarball", rather than "we cache the tarball" or "let's cache the tarball".
- Leave out "easy", "simple", "just", and "quick". They add nothing when a task is easy and discourage readers when it is not. State the concrete property instead: "one command", "no configuration".
- Say what to do rather than what to avoid: "use `port: 0` so the operating system picks a free port", rather than "don't hardcode ports". State limitations plainly; a limitation is a fact, not a warning to the reader.
- Use gender-neutral language: "developers", "users", "they".
- Make link text name its destination: "see [`bun install`](/pm/cli/install)", rather than "see here".
- Run every code example before you publish it, and check option names and defaults against the implementation on `main`.
+90
View File
@@ -0,0 +1,90 @@
---
title: License
description: License for Bun
---
Bun itself is MIT-licensed.
## JavaScriptCore
Bun statically links JavaScriptCore (and WebKit), which is LGPL-2 licensed. WebCore files from WebKit are also licensed under LGPL-2. Per LGPL-2:
> (1) If you statically link against an LGPL'd library, you must also provide your application in an object (not necessarily source) format, so that a user has the opportunity to modify the library and relink the application.
Bun's patched version of WebKit lives at https://github.com/oven-sh/webkit. To relink Bun with changes:
- `git clone https://github.com/oven-sh/WebKit vendor/WebKit`
- `bun sync-webkit-source` (checks out the version pinned in `WEBKIT_VERSION` in `scripts/build/deps/webkit.ts`)
- `bun run build:local`
`bun run build:local` compiles JavaScriptCore, compiles Bun's `.cpp` bindings for JavaScriptCore (the object files that use JavaScriptCore), and outputs a new `bun` binary with your changes.
## Linked libraries
Bun statically links these libraries:
| Library | License |
| ------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------- |
| [`boringssl`](https://boringssl.googlesource.com/boringssl/) | [several licenses](https://boringssl.googlesource.com/boringssl/+/refs/heads/master/LICENSE) |
| [`brotli`](https://github.com/google/brotli) | MIT |
| [`libarchive`](https://github.com/libarchive/libarchive) | [several licenses](https://github.com/libarchive/libarchive/blob/master/COPYING) |
| [`lol-html`](https://github.com/cloudflare/lol-html/tree/master/c-api) | BSD 3-Clause |
| [`ls-hpack`](https://github.com/litespeedtech/ls-hpack) | MIT (bundled xxhash is BSD 2-Clause) |
| [`ls-qpack`](https://github.com/litespeedtech/ls-qpack) | MIT |
| [`lsquic`](https://github.com/litespeedtech/lsquic) | MIT (portions derived from Chromium proto-quic, BSD 3-Clause) |
| [`mimalloc`](https://github.com/microsoft/mimalloc) | MIT |
| [`picohttp`](https://github.com/h2o/picohttpparser) | dual-licensed under the Perl License or the MIT License |
| [`zstd`](https://github.com/facebook/zstd) | dual-licensed under the BSD License or GPLv2 license |
| [`simdutf`](https://github.com/simdutf/simdutf) | Apache 2.0 |
| [`tinycc`](https://github.com/tinycc/tinycc) | LGPL v2.1 |
| [`uSockets`](https://github.com/uNetworking/uSockets) | Apache 2.0 |
| [`zlib-ng`](https://github.com/zlib-ng/zlib-ng) | zlib |
| [`c-ares`](https://github.com/c-ares/c-ares) | MIT licensed |
| [`libicu`](https://github.com/unicode-org/icu) 78 | [ICU license](https://github.com/unicode-org/icu/blob/main/icu4c/LICENSE) |
| [`libbase64`](https://github.com/aklomp/base64/blob/master/LICENSE) | BSD 2-Clause |
| [`libuv`](https://github.com/libuv/libuv) (on Windows) | MIT |
| [`libdeflate`](https://github.com/ebiggers/libdeflate) | MIT |
| [`libjpeg-turbo`](https://github.com/libjpeg-turbo/libjpeg-turbo) | BSD 3-Clause / IJG / zlib |
| [`libspng`](https://github.com/randy408/libspng) | BSD 2-Clause (portions derived from libpng, PNG Reference Library License v2) |
| [`libwebp`](https://github.com/webmproject/libwebp) | BSD 3-Clause |
| [`highway`](https://github.com/google/highway) | Apache 2.0 |
| [`HdrHistogram_c`](https://github.com/HdrHistogram/HdrHistogram_c) | dual-licensed under CC0 1.0 or the BSD 2-Clause License |
| [`sqlite`](https://sqlite.org) (on Linux and Windows) | [public domain](https://sqlite.org/copyright.html) |
| A fork of [`uWebsockets`](https://github.com/jarred-sumner/uwebsockets) | Apache 2.0 licensed |
| Parts of [Tigerbeetle's IO code](https://github.com/tigerbeetle/tigerbeetle/blob/532c8b70b9142c17e07737ab6d3da68d7500cbca/src/io/windows.zig#L1) | Apache 2.0 licensed |
## Polyfills
For compatibility, Bun embeds the following packages into its binary and injects them if imported.
| Package | License |
| ------------------------------------------------------------------------ | ------- |
| [`acorn`](https://github.com/acornjs/acorn) | MIT |
| [`acorn-walk`](https://github.com/acornjs/acorn) | MIT |
| [`assert`](https://npmjs.com/package/assert) | MIT |
| [`browserify-zlib`](https://npmjs.com/package/browserify-zlib) | MIT |
| [`buffer`](https://npmjs.com/package/buffer) | MIT |
| [`constants-browserify`](https://npmjs.com/package/constants-browserify) | MIT |
| [`crypto-browserify`](https://npmjs.com/package/crypto-browserify) | MIT |
| [`domain-browser`](https://npmjs.com/package/domain-browser) | MIT |
| [`events`](https://npmjs.com/package/events) | MIT |
| [`https-browserify`](https://npmjs.com/package/https-browserify) | MIT |
| [`os-browserify`](https://npmjs.com/package/os-browserify) | MIT |
| [`path-browserify`](https://npmjs.com/package/path-browserify) | MIT |
| [`process`](https://npmjs.com/package/process) | MIT |
| [`punycode`](https://npmjs.com/package/punycode) | MIT |
| [`querystring-es3`](https://npmjs.com/package/querystring-es3) | MIT |
| [`stream-browserify`](https://npmjs.com/package/stream-browserify) | MIT |
| [`stream-http`](https://npmjs.com/package/stream-http) | MIT |
| [`string_decoder`](https://npmjs.com/package/string_decoder) | MIT |
| [`timers-browserify`](https://npmjs.com/package/timers-browserify) | MIT |
| [`tty-browserify`](https://npmjs.com/package/tty-browserify) | MIT |
| [`url`](https://npmjs.com/package/url) | MIT |
| [`util`](https://npmjs.com/package/util) | MIT |
| [`vm-browserify`](https://npmjs.com/package/vm-browserify) | MIT |
## Additional credits
- Bun's JS transpiler and Node.js module resolver source code is a port of [@evanw](https://github.com/evanw)s [esbuild](https://github.com/evanw/esbuild) project.
- Bun's CSS parser source code is derived from the [Lightning CSS](https://github.com/parcel-bundler/lightningcss) and [Servo](https://github.com/servo/servo) projects.
- Credit to [@kipply](https://github.com/kipply) for the name "Bun".
+8
View File
@@ -0,0 +1,8 @@
---
title: Roadmap
description: Bun's roadmap and long-term plans
---
Bun is a project with a large scope and is still in its early days. Long-term, Bun aims to provide an all-in-one toolkit to replace the complex, fragmented toolchains common today: Node.js, Jest, Webpack, esbuild, Babel, yarn, PostCSS, and others.
See [Bun's Roadmap](https://github.com/oven-sh/bun/issues/159) on GitHub for the project's long-term plans and priorities.