The Bun Global Object provides the primary namespace for Bun-specific APIs accessible as globalThis.Bun in JavaScript. This document covers the implementation architecture, property types, binding system, and how new APIs are added to the Bun namespace.
For information about the JavaScript runtime environment that hosts this object, see Global Object and JSC Integration. For specific Bun APIs like Bun.serve, Bun.file, etc., see Bun-Specific APIs.
The Bun global object is implemented using a multi-layer architecture spanning Zig, C++, and JavaScript. The object is defined in Zig, exposed through C++ bindings, and registered with JavaScriptCore as a global property.
Sources: src/bun.js/api/BunObject.zig1-208 src/bun.js/bindings/BunObject.cpp1-100 src/bun.js/bindings/BunObject+exports.h1-103
The Bun global object supports four types of properties, each optimized for different use cases:
Callbacks are functions directly exported and immediately available on the Bun object. They use the toJSCallback helper (alias for jsc.toJSHostFn) to convert Zig functions into JavaScript-callable functions.
Example Callback Definitions:
| Callback | Zig Function | Purpose |
|---|---|---|
serve | Bun.serve | HTTP/WebSocket server |
file | WebCore.Blob.constructBunFile | File API |
spawn | api.Subprocess.spawn | Process spawning |
build | Bun.JSBundler.buildFn | Bundler API |
write | jsc.WebCore.Blob.writeFile | File writing |
Sources: src/bun.js/api/BunObject.zig12-46
Lazy properties are initialized only when first accessed, reducing startup overhead. They use the toJSLazyPropertyCallback helper which wraps a getter function.
Example Lazy Properties:
| Property | Getter Function | Type |
|---|---|---|
Transpiler | Bun.getTranspilerConstructor | Constructor |
Glob | Bun.getGlobConstructor | Constructor |
CryptoHasher | Crypto.CryptoHasher.getter | Constructor |
hash | Bun.getHashObject | Object |
inspect | Bun.getInspect | Function |
unsafe | Bun.getUnsafe | Object |
argv | Bun.getArgv | Array |
Sources: src/bun.js/api/BunObject.zig50-85 src/bun.js/bindings/BunObject+exports.h5-40
Getters and setters provide dynamic property access with custom logic. Unlike lazy properties, they execute on every access.
Example - Bun.main Getter:
The main getter returns the entry point path, with special logic for symlinks and overrides:
src/bun.js/api/BunObject.zig567-617
The getter first checks for a JavaScript override (vm.overridden_main), then attempts to resolve the filesystem path of the main module, and falls back to the original path if resolution fails.
Sources: src/bun.js/api/BunObject.zig88-93
The binding layer connects Zig implementations to JavaScript through C++. This uses a three-step process:
Functions are defined in Zig and exported with specific naming conventions:
For lazy properties:
BunObject_lazyPropCb_<name>BunObject_lazyPropCb_wrap_<name>For regular callbacks:
BunObject_callback_<name>Sources: src/bun.js/api/BunObject.zig95-207
The header file uses macros to generate declarations:
src/bun.js/bindings/BunObject+exports.h1-103
These macros:
FOR_EACH_GETTER - Lists all lazy propertiesFOR_EACH_CALLBACK - Lists all callbacksDECLARE_ZIG_BUN_OBJECT_GETTER - Declares extern C functionsDEFINE_ZIG_BUN_OBJECT_GETTER_WRAPPER - Creates C++ wrapper functionsSources: src/bun.js/bindings/BunObject+exports.h5-102
The C++ implementation registers properties with JavaScriptCore:
The @begin bunObjectTable marker in BunObject.cpp indicates where code generation inserts the property registration table.
Sources: src/bun.js/bindings/BunObject.cpp1-100
To add a new function or property to the Bun global object, follow this process documented at src/bun.js/api/BunObject.zig3-10:
Add the callback to the BunObject struct:
Export it in exportAll():
Update @begin bunObjectTable in BunObject.cpp
Update BunObject+exports.h to add to FOR_EACH_CALLBACK macro
Run bun run build
Add the lazy property to the BunObject struct:
Export it in exportAll():
Update @begin bunObjectTable in BunObject.cpp with a getter wrapper call
Update BunObject+exports.h to add to FOR_EACH_GETTER macro
Run bun run build
Sources: src/bun.js/api/BunObject.zig3-10
The Shell API (Bun.$) provides a template tag for executing shell commands. It's implemented through lazy initialization in TypeScript:
The shell implementation uses:
.text(), .json(), .quiet() methods src/js/builtins/shell.ts106-250Sources: src/bun.js/bindings/BunObject.cpp355-388 src/js/builtins/shell.ts1-368 src/shell/interpreter.zig1-100
Bun.file() creates file handles using the WebCore.Blob.constructBunFile callback:
src/bun.js/api/BunObject.zig20
This integrates with the WebCore Blob implementation to provide high-performance file I/O.
Sources: src/bun.js/api/BunObject.zig20
Bun.build() invokes the bundler programmatically:
src/bun.js/api/BunObject.zig14
This connects to the JSBundler implementation that handles transpilation, bundling, and code generation.
Sources: src/bun.js/api/BunObject.zig14
Some APIs are constructed through special C++ functions rather than lazy properties:
The DNS object is constructed in C++ with multiple resolve methods:
Each method is registered as a native function with the DNS object.
Sources: src/bun.js/bindings/BunObject.cpp390-437
The SQL object is loaded from an internal module:
src/bun.js/bindings/BunObject.cpp312-335
This pattern loads the implementation from the BunSql internal module registry rather than direct Zig exports.
Sources: src/bun.js/bindings/BunObject.cpp312-335
The BunObject uses several memory management strategies:
Lazy properties are computed once and cached on the Bun object. The JavaScriptCore lazy property mechanism handles this automatically.
Some getters like Bun.argv return values that may be cached at the VM level:
src/bun.js/api/BunObject.zig624-626
The implementation delegates to node.process.getArgv() which manages its own caching.
The Bun global object implementation uses standard allocators and doesn't maintain its own allocation scope, relying on the global object's lifetime to manage memory.
Sources: src/bun.js/api/BunObject.zig624-626
The binding system relies on code generation during the build:
@begin bunObjectTable marker indicates where properties are registeredThe build command bun run build must be executed after modifying the BunObject structure to regenerate bindings.
Sources: src/bun.js/api/BunObject.zig3-10 src/bun.js/bindings/BunObject+exports.h84-102
Refresh this wiki