oven-sh/bun
C++ JSC bindings
The bridge between Zig and JavaScriptCore lives in src/bun.js/bindings/. Most of Bun's JS-visible APIs are defined as Zig structs with a *.classes.ts declaration; the C++ glue is auto-generated from those declarations by src/codegen/generate-classes.ts.
Files
| Area | Path | Notes |
|---|---|---|
| Generated classes | src/bun.js/bindings/ (output of generate-classes.ts) |
Boilerplate prototype/constructor/instance wiring. |
| Manual bindings | src/bun.js/bindings/*.cpp |
Hand-written when generation can't express the shape (e.g. JSC::JSDestructibleObject with custom finalisers). |
ZigGlobalObject |
src/bun.js/bindings/ZigGlobalObject.cpp |
The JSC::JSGlobalObject subclass for every Bun realm. Holds cached structures and lazy properties. |
BakeGlobalObject |
src/bake/BakeGlobalObject.cpp |
A ZigGlobalObject subclass for the dev-server SSR realm. |
| Algo / utilities | src/bun.js/bindings/Algo/ |
Hash, base64, hex helpers shared across bindings. |
| Built-in JSC builtins | src/js/builtins/ (TS), generated to build/<profile>/codegen/ |
ReadableStream, WritableStream, Buffer, process shimming. |
| Inspector | BunDebugger.cpp, BunInspector*.cpp |
WebSocket inspector protocol. |
| CPU/Heap profiler | BunCPUProfiler.{h,cpp,zig}, heap profiler bindings |
Wraps JSC profilers. |
How a JSC class is defined
Pattern for any JS-visible Bun class with a public constructor:
- Zig implementation in
src/bun.js/api/,src/bun.js/webcore/, etc. Holds the actual logic. *.classes.tsdeclaration describing the JS shape — constructor signature, prototype methods, getters/setters, structure flags, iterator protocol, finalisers. Schema insrc/codegen/class-definitions.ts.generate-classes.tsreads the.classes.tsfile at build time and writes:- A C++ header for the class (
<Name>.h). - A C++ source file (
<Name>.cpp) with prototype/constructor/instance C++ classes. - Zig glue (
<Name>.classes.zig) exposing call/get/set callbacks.
- A C++ header for the class (
ZigGlobalObjectis patched to register the class structure and add it to the iso subspace.- HashTableValue arrays are emitted to bind property names to C++ functions.
Example: src/bun.js/api/Glob.classes.ts declares the Bun.Glob class. generate-classes.ts produces JSGlob.cpp, JSGlob.h. The Zig logic is in src/bun.js/api/glob.zig. The constructor body, match, matchSync, scan, scanSync methods are all defined in Zig; the C++ side is pure plumbing.
For classes without a public constructor (returned by some other API only), only two C++ classes are needed: Foo and FooPrototype. The Constructor class is omitted.
Iso subspaces and structures
Each Bun-defined JSC class lives in its own iso subspace — a JSC garbage-collection partition that holds a single concrete JS class. Subspaces are registered in ZigGlobalObject::finishCreation(). Each class also has a cached Structure so JSObject::createStructure doesn't have to be called per-instance.
Structures are referenced via getStructureForFoo(globalObject) helpers; the generated C++ produces these automatically.
ZigGlobalObject lazy properties
Many globals (e.g. globalThis.Bun, globalThis.process, the WebKit URL, the timers setTimeout) are exposed as lazy properties. They materialise on first access via static helper functions in ZigGlobalObject.cpp. Custom getters live in the same file (search for JSC_DEFINE_HOST_FUNCTION and the corresponding registration).
The list of registered globals is large — search ZigGlobalObject.cpp for JSC_BUILTIN_FUNCTION_DECLARE and JSC_DEFINE_CUSTOM_GETTER to enumerate them.
CommonJS interop
src/bun.js/bindings/CommonJSModuleRecord.{h,cpp} implements CJS as a JSC module record. module.exports, the require() function, and the __filename/__dirname pair are wired here. The parser (src/js_parser.zig) detects CJS shape and the runtime decides whether to run the module under the CJS shim or as ESM.
Bindgen v2
src/codegen/bindgen.ts and src/codegen/bindgenv2/ are an evolving system for declaring one-off cross-language exports. Mark a C++ function with [[ZIG_EXPORT(...)]] and cppbind.ts produces the Zig signature automatically. Useful for small APIs that don't justify a full *.classes.ts.
Inspector and debugger
src/bun.js/bindings/BunInspector.cpp plus a small JS shim launch the WebSocket inspector protocol when bun --inspect is set. The protocol is JSC's standard one (compatible with Chrome DevTools and chrome://inspect).
src/bun.js/Debugger.zig (Zig side) handles the wire format for breakpoints set by bun-vscode. Source under packages/bun-vscode/.
Generated classes file naming
Generated outputs live under build/<profile>/codegen/ and are committed-as-symlink-only (the build re-creates them). For each <Foo>.classes.ts:
JSFoo.cpp/JSFoo.h— class wiring.Foo.classes.zig— Zig glue.- Entries in
ZigGeneratedClasses.cpp/ZigGeneratedClasses.h— registration. - Optionally a HashTable header for static properties.
Performance considerations
- Inline cache friendliness — generated property tables match what JSC's inline caches expect, so a
getteron a generated class is as fast as one on a built-in. - Iso subspaces let JSC allocate without consulting type information at GC time.
JSC::CallFrameand direct argument access avoid an intermediateJSValue[].
Integration points
- Code generation —
src/codegen/generate-classes.ts. See Code generation. - Runtime — Every Bun API on the
Bun.*namespace, every Web API class, everynode:*class. - Bake —
BakeGlobalObject.cppextends the same machinery for SSR. - Inspector — Hooked into
ZigGlobalObjectand the event loop viaBunInspector.cpp.
Entry points for modification
- To add a JS class, write the
.classes.tsdeclaration and the.zigimplementation. Runbun run buildto regenerate. - To add a global function or property, edit
ZigGlobalObject.cpp's registration. - To add a hand-written binding (no
.classes.ts), drop a.cpp/.hpair insrc/bun.js/bindings/and reference it fromZigGlobalObject.cpp. - To debug structure caching, look at
getStructureFor*helpers — a new class needs both a structure cache and an iso subspace.
Key source files
| File | Purpose |
|---|---|
src/codegen/generate-classes.ts |
Generates C++/Zig glue from .classes.ts. |
src/bun.js/bindings/ZigGlobalObject.cpp |
Realm root in C++. |
src/bun.js/bindings/CommonJSModuleRecord.cpp |
CommonJS shim. |
src/bun.js/bindings/BunInspector.cpp |
DevTools inspector. |
src/bake/BakeGlobalObject.cpp |
SSR realm subclass. |
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.