aboutsummaryrefslogtreecommitdiff
path: root/CONTRIBUTING.md
blob: 5f7ddbc9c674edc16befa6515d0f9fb7172d05da (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# Contributing to Bun

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's codebase

Bun is written mostly in Zig, but WebKit & JavaScriptCore (the JavaScript engine) is written in C++.

Today (Feburary 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.

## Memory management in Bun

For the Zig code, please:

1. Do your best to avoid dynamically allocating memory.
2. 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.
3. Prefer arenas over manual memory management. Manually freeing memory is leak & crash prone.
4. 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.

## JavaScript runtime

Most of Bun's JavaScript runtime code lives in `src/bun.js`.

### Calling C++ from Zig & Zig from C++

TODO: document this (see bindings.zig and bindings.cpp for now)

### Adding a new JavaScript class

1. Add a new file in `src/bun.js/*.classes.ts` to define the instance and static methods for the class.
2. Add a new file in `src/bun.js/**/*.zig` and expose the struct in `src/bun.js/generated_classes_list.zig`
3. Run `make codegen`

Copy from examples like `Subprocess` or `Response`.

### ESM modules

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`.

### JavaScript Builtins

JavaScript builtins are located in `src/bun.js/builtins/*.js`.

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:

```sh
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.

### Memory management in Bun's JavaScript runtime

TODO: fill this out (for now, use `JSC.Strong` in most cases)

### Strings

TODO: fill this out (for now, use `JSValue.toSlice()` in most cases)

#### JavaScriptCore C API

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.

## Testing

See `../test/README.md` for information on how to run tests.