Open-Source Wikis

/

Bun

/

Systems

/

C++ JSC bindings

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:

  1. Zig implementation in src/bun.js/api/, src/bun.js/webcore/, etc. Holds the actual logic.
  2. *.classes.ts declaration describing the JS shape — constructor signature, prototype methods, getters/setters, structure flags, iterator protocol, finalisers. Schema in src/codegen/class-definitions.ts.
  3. generate-classes.ts reads the .classes.ts file 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.
  4. ZigGlobalObject is patched to register the class structure and add it to the iso subspace.
  5. 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 getter on 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::CallFrame and direct argument access avoid an intermediate JSValue[].

Integration points

  • Code generationsrc/codegen/generate-classes.ts. See Code generation.
  • Runtime — Every Bun API on the Bun.* namespace, every Web API class, every node:* class.
  • BakeBakeGlobalObject.cpp extends the same machinery for SSR.
  • Inspector — Hooked into ZigGlobalObject and the event loop via BunInspector.cpp.

Entry points for modification

  • To add a JS class, write the .classes.ts declaration and the .zig implementation. Run bun run build to 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/.h pair in src/bun.js/bindings/ and reference it from ZigGlobalObject.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.

C++ JSC bindings – Bun wiki | Factory