Important: All contributions need test coverage. If you are adding a new feature, please add a test. If you are fixing a bug, please add a test that fails before your fix and passes after your fix.
Bun is written mostly in Zig, but WebKit & JavaScriptCore (the JavaScript engine) is written in C++.
Today (February 2023), Bun's codebase has five distinct parts:
- JavaScript, JSX, & TypeScript transpiler, module resolver, and related code
- JavaScript runtime (
src/bun.js/
) - JavaScript runtime bindings (
src/bun.zig/bindings/**/*.cpp
) - Package manager (
src/install/
) - Shared utilities (
src/string_immutable.zig
)
The JavaScript transpiler & module resolver is mostly independent from the runtime. It predates the runtime and is entirely in Zig. The JavaScript parser is mostly in src/js_parser.zig
. The JavaScript AST data structures are mostly in src/js_ast.zig
. The JavaScript lexer is in src/js_lexer.zig
. A lot of this code started as a port of esbuild's equivalent code from Go to Zig, but has had many small changes since then.
Please refer to Bun's Development Guide to get your dev environment setup!
For the Zig code, please:
- Do your best to avoid dynamically allocating memory.
- If we need to allocate memory, carefully consider the owner of that memory. If it's a JavaScript object, it will need a finalizer. If it's in Zig, it will need to be freed either via an arena or manually.
- Prefer arenas over manual memory management. Manually freeing memory is leak & crash prone.
- If the memory needs to be accessed across threads, use
bun.default_allocator
. Mimalloc threadlocal heaps are not safe to free across threads.
The JavaScript transpiler has special-handling for memory management. The parser allocates into a single arena and the memory is recycled after each parse.
Most of Bun's JavaScript runtime code lives in src/bun.js
.
TODO: document this (see bindings.zig
and bindings.cpp
for now)
- Add a new file in
src/bun.js/*.classes.ts
to define the instance and static methods for the class. - Add a new file in
src/bun.js/**/*.zig
and expose the struct insrc/bun.js/generated_classes_list.zig
- Run
make codegen
Copy from examples like Subprocess
or Response
.
Bun implements ESM modules in a mix of native code and JavaScript.
Several Node.js modules are implemented in JavaScript and loosely based on browserify polyfills.
The ESM modules in Bun are located in src/bun.js/*.exports.js
. Unlike other code in Bun, these files are NOT transpiled. They are loaded directly into the JavaScriptCore VM. That means require
does not work in these files. Instead, you must use import.meta.require
, or ideally, not use require/import other files at all.
The module loader is in src/bun.js/module_loader.zig
.
TODO: update this with the new build process that uses TypeScript and $
instead of @
.
JavaScript builtins are located in src/js/builtins/*.ts
.
These files support a JavaScriptCore-only syntax for internal slots. @
is used to access an internal slot. For example: new @Array(123)
will create a new Array
similar to new Array(123)
, except if a library modifies the Array
global, it will not affect the internal slot (@Array
). These names must be allow-listed in BunBuiltinNames.h
(though JavaScriptCore allowlists some names by default).
They can not use or reference ESM-modules. The files that end with *Internals.js
are automatically loaded globally. Most usage of internals right now are the stream implementations (which share a lot of code from Safari/WebKit) and ImportMetaObject (which is how require
is implemented in the runtime)
To regenerate the builtins:
make clean-bindings && make generate-builtins && make bindings -j10
It is recommended that you have ccache installed or else you will spend a lot of time waiting for the bindings to compile.
TODO: fill this out (for now, use JSC.Strong
in most cases)
TODO: fill this out (for now, use JSValue.toSlice()
in most cases)
Do not copy from examples leveraging the JavaScriptCore C API. Please do not use this in new code. We will not accept PRs that add new code that uses the JavaScriptCore C API.
See test/README.md
for information on how to run tests.