RuleStack

Configs

Stacks

Compare

Diff

RuleStack

Configs

Stacks

Compare

Diff

Read API

RuleStack

Configs

Stacks

Compare

Diff

Read API

Configs/oven-sh/bun/diff

Two files, one repository

oven-sh/bun ships 2 formats across 9 indexed files. The question worth asking is whether the second one says anything the first does not.

CompareCLAUDE.md ↔ AGENTS.md
A · src/jsc/bindings/v8/AGENTS.md · 1279 wordsB · CLAUDE.md · 2285 words
What each file covers, counted
DimensionSharedOnly in AOnly in BOverlap
Sections030190%
Commands04370%
Section tags44336%

What each file covers

Sections

0 shared · 30 only in A · 19 only in B
  • − V8 C++ API Implementation Guide
  • − Architecture Overview
  • − Directory Structure
  • − Implementing New V8 APIs
  • − 1. Create Header and Implementation Files
  • − 2. Add Symbol Exports
  • − Build your changes first
  • − Extract symbols
  • − Use the provided PowerShell script in the comments:
  • − 3. Add Tests
  • − 4. Handle Special Cases
  • − Memory Management Guidelines
  • − Handle Scopes
  • − JSC Integration
  • − Tagged Pointers
  • − Testing Strategy
  • − Comprehensive Testing
  • − Test Categories
  • − Adding New Tests
  • − Debugging Tips
  • − Build and Test
  • − Build debug version (takes ~5 minutes)
  • − Run V8 tests
  • − Run specific test
  • − Common Issues
  • − Debug Logging
  • − Advanced Topics
  • − Inline Function Compatibility
  • − Cross-Platform Considerations
  • − Contributing
  • + Building and Running Bun
  • + Build Commands
  • + Changes that don't require a build
  • + Testing
  • + Running Tests
  • + Test Organization
  • + Writing Tests
  • + Code Architecture
  • + Language Structure
  • + Core Source Organization
  • + JavaScript Class Implementation (C++)
  • + Code Generation
  • + JavaScript Modules (`src/js/`)
  • + Landing PRs: What Bun Reviewers Catch
  • + Important Development Notes
  • + Debugging CI Failures
  • + Reading PR Feedback
  • + Machine-readable output for jq pipelines — one object per entry.
  • + Resolved threads and bot noise (robobun CI status, CodeRabbit summaries) are filtered out.

Commands

0 shared · 4 only in A · 37 only in B
  • − bun bd --help
  • − bun bd test test/v8/v8.test.ts
  • − bun bd test test/v8/v8.test.ts -t "can create small integer"
  • − bun bd test test/v8/v8.test.ts -t "your test name"
  • + bun bd test foo.test.ts
  • + bun run build test foo.test.ts
  • + bun run build:release -p 'Bun.version'
  • + bun run build:local run script.ts
  • + bun test test/integration/bun-types/bun-types.test.ts
  • + bun run ci:errors
  • + bun run ci:errors '#26173'
  • + bun run ci:status
  • + bun run ci:logs
  • + bun run ci:find
  • + bun run ci:watch
  • + bun run pr:comments
  • + bun run pr:comments 28838
  • + bun run pr:comments --include-resolved
  • + bun run pr:comments --json | jq '.[] | select(.user == "Jarred-Sumner")'
  • + bun bd
  • + bun bd test <test-file>
  • + bun test
  • + bun bd <command>
  • + bun run build
  • + tsc
  • + bun bd test test/js/bun/http/serve.test.ts
  • + bun bd test http/serve.test.ts
  • + bun bd test test/js/bun/http/serve.test.ts -t "should handle"
  • + bun bd test <file>
  • + bun/
  • + bun.sys
  • + node:crypto
  • + npm.rs
  • + node:fs
  • + node:*
  • + node:path
  • + bun:ffi
  • + bun:sqlite
  • + bun <file>
  • + bun bd test
  • + bun run rust:check-all

Section tags

4 shared · 4 only in A · 3 only in B
  • − testing-strategy
  • − api
  • − performance
  • − deployment
  • + code-style
  • + git-pr
  • + do-not
  •   build
  •   test
  •   architecture
  •   docs

Line diff

+174 added−272 removed66 unchanged19.5% identical
oven-sh/bun · src/jsc/bindings/v8/AGENTS.md
@@ −1 @@
1# V8 C++ API Implementation Guide
2 
3This directory contains Bun's implementation of the V8 C++ API on top of JavaScriptCore. This allows native Node.js modules that use V8 APIs to work with Bun.
4 
5## Architecture Overview
6 
7Bun implements V8 APIs by creating a compatibility layer that:
 
 
 
 
 
 
 
8 
9- Maps V8's `Local<T>` handles to JSC's `JSValue` system
10- Uses handle scopes to manage memory lifetimes similar to V8
11- Provides V8-compatible object layouts that inline V8 functions can read
12- Manages tagged pointers for efficient value representation
13 
14For detailed background, see the blog series:
15 
16- [Part 1: Introduction and challenges](https://bun.com/blog/how-bun-supports-v8-apis-without-using-v8-part-1.md)
17- [Part 2: Memory layout and object representation](https://bun.com/blog/how-bun-supports-v8-apis-without-using-v8-part-2.md)
18- [Part 3: Garbage collection and primitives](https://bun.com/blog/how-bun-supports-v8-apis-without-using-v8-part-3.md)
19 
20## Directory Structure
21 
22```
23src/jsc/bindings/v8/
24├── v8.h # Main header with V8_UNIMPLEMENTED macro
25├── v8_*.h # V8 compatibility headers
26├── V8*.h # V8 class headers (Number, String, Object, etc.)
27├── V8*.cpp # V8 class implementations
28├── shim/ # Internal implementation details
29│ ├── Handle.h # Handle and ObjectLayout implementation
30│ ├── HandleScopeBuffer.h # Handle scope memory management
31│ ├── TaggedPointer.h # V8-style tagged pointer implementation
32│ ├── Map.h # V8 Map objects for inline function compatibility
33│ ├── GlobalInternals.h # V8 global state management
34│ ├── InternalFieldObject.h # Objects with internal fields
35│ └── Oddball.h # Primitive values (undefined, null, true, false)
36├── node.h # Node.js module registration compatibility
37└── real_v8.h # Includes real V8 headers when needed
38```
39 
40## Implementing New V8 APIs
41 
42### 1. Create Header and Implementation Files
43 
44Create `V8NewClass.h`:
45 
46```cpp
47#pragma once
48 
49#include "v8.h"
50#include "V8Local.h"
51#include "V8Isolate.h"
52 
53namespace v8 {
54 
55class NewClass : public Data {
56public:
57 BUN_EXPORT static Local<NewClass> New(Isolate* isolate, /* parameters */);
58 BUN_EXPORT /* return_type */ SomeMethod() const;
59 
60 // Add other methods as needed
61};
62 
63} // namespace v8
64```
65 
66Create `V8NewClass.cpp`:
67 
68```cpp
69#include "V8NewClass.h"
70#include "V8HandleScope.h"
71#include "v8_compatibility_assertions.h"
72 
73ASSERT_V8_TYPE_LAYOUT_MATCHES(v8::NewClass)
74 
75namespace v8 {
 
 
76 
77Local<NewClass> NewClass::New(Isolate* isolate, /* parameters */)
78{
79 // Implementation - typically:
80 // 1. Create JSC value
81 // 2. Get current handle scope
82 // 3. Create local handle
83 return isolate->currentHandleScope()->createLocal<NewClass>(isolate->vm(), /* JSC value */);
84}
85 
86/* return_type */ NewClass::SomeMethod() const
87{
88 // Implementation - typically:
89 // 1. Convert this Local to JSValue via localToJSValue()
90 // 2. Perform JSC operations
91 // 3. Return converted result
92 auto jsValue = localToJSValue();
93 // ... JSC operations ...
94 return /* result */;
95}
96 
97} // namespace v8
98```
 
 
 
 
 
 
99 
100### 2. Add Symbol Exports
101 
102For each new C++ method, you must add the mangled symbol names to multiple files:
103 
104#### a. Add to `src/runtime/napi/napi_body.rs`
105 
106Find the `v8_api` module and add entries to both the `#[cfg(not(windows))]` (Itanium) and `#[cfg(windows)]` (MSVC) `extern "C"` blocks:
 
 
107 
108```rust
109#[cfg(not(windows))]
110mod v8_api {
111 use core::ffi::c_void;
112 unsafe extern "C" {
113 // ... existing functions ...
114 pub(super) fn _ZN2v88NewClass3NewEPNS_7IsolateE/* parameters */() -> *mut c_void;
115 pub(super) fn _ZNK2v88NewClass10SomeMethodEv() -> *mut c_void;
116 }
117}
118#[cfg(windows)]
119mod v8_api {
120 use core::ffi::c_void;
121 unsafe extern "C" {
122 // ... existing functions ...
123 #[link_name = "?New@NewClass@v8@@SA?AV?$Local@VNewClass@v8@@@2@PEAVIsolate@2@/* parameters */@Z"]
124 pub(super) fn NewClass_New() -> *mut c_void;
125 #[link_name = "?SomeMethod@NewClass@v8@@QEBA/* return_type */XZ"]
126 pub(super) fn NewClass_SomeMethod() -> *mut c_void;
127 }
128}
129```
130 
131**To get the correct mangled names:**
 
 
 
 
132 
133For **GCC/Clang** (Unix):
 
134 
135```bash
136# Build your changes first
137bun bd --help # This compiles your code
138 
139# Extract symbols
140nm build/CMakeFiles/bun-debug.dir/src/jsc/bindings/v8/V8NewClass.cpp.o | grep "T _ZN2v8"
141```
142 
143For **MSVC** (Windows):
144 
145```powershell
146# Use the provided PowerShell script in the comments:
147dumpbin .\build\CMakeFiles\bun-debug.dir\src\jsc\bindings\v8\V8NewClass.cpp.obj /symbols | where-object { $_.Contains(' v8::') } | foreach-object { (($_ -split "\|")[1] -split " ")[1] } | ForEach-Object { "#[link_name = `"${_}`"] pub(super) fn ___() -> *mut c_void;" }
148```
149 
150#### b. Add to Symbol Files
151 
152Add to `src/symbols.txt` (without leading underscore):
153 
154```
155_ZN2v88NewClass3NewEPNS_7IsolateE...
156_ZNK2v88NewClass10SomeMethodEv
157```
158 
159Add to `src/symbols.dyn` (with leading underscore and semicolons):
160 
161```
162{
163 __ZN2v88NewClass3NewEPNS_7IsolateE...;
164 __ZNK2v88NewClass10SomeMethodEv;
165}
166```
167 
168**Note:** `src/symbols.def` is Windows-only and typically doesn't contain V8 symbols.
169 
170### 3. Add Tests
171 
172Create tests in `test/v8/v8-module/main.cpp`:
173 
174```cpp
175void test_new_class_feature(const FunctionCallbackInfo<Value> &info) {
176 Isolate* isolate = info.GetIsolate();
177 
178 // Test your new V8 API
179 Local<NewClass> obj = NewClass::New(isolate, /* parameters */);
180 auto result = obj->SomeMethod();
181 
182 // Print results for comparison with Node.js
183 std::cout << "Result: " << result << std::endl;
184 
185 info.GetReturnValue().Set(Undefined(isolate));
186}
187```
188 
189Add the test to the registration section:
190 
191```cpp
192void Init(Local<Object> exports, Local<Value> module, Local<Context> context) {
193 // ... existing functions ...
194 NODE_SET_METHOD(exports, "test_new_class_feature", test_new_class_feature);
195}
196```
197 
198Add test case to `test/v8/v8.test.ts`:
199 
200```typescript
201describe("NewClass", () => {
202 it("can use new feature", async () => {
203 await checkSameOutput("test_new_class_feature", []);
204 });
205});
206```
207 
208### 4. Handle Special Cases
 
 
 
 
 
 
 
 
 
 
209 
210#### Objects with Internal Fields
211 
212If implementing objects that need internal fields, extend `InternalFieldObject`:
213 
214```cpp
215// In your .h file
216class MyObject : public InternalFieldObject {
217 // ... implementation
218};
219```
220 
221#### Primitive Values
222 
223For primitive values, ensure they work with the `Oddball` system in `shim/Oddball.h`.
224 
225#### Template Classes
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
226 
227For `ObjectTemplate` or `FunctionTemplate` implementations, see existing patterns in `V8ObjectTemplate.cpp` and `V8FunctionTemplate.cpp`.
228 
229## Memory Management Guidelines
230 
231### Handle Scopes
232 
233- All V8 values must be created within an active handle scope
234- Use `isolate->currentHandleScope()->createLocal<T>()` to create handles
235- Handle scopes automatically clean up when destroyed
236 
237### JSC Integration
 
 
 
 
 
 
238 
239- Use `localToJSValue()` to convert V8 handles to JSC values
240- Use `JSC::WriteBarrier` for heap-allocated references
241- Implement `visitChildren()` for custom heap objects
242 
243### Tagged Pointers
244 
245- Small integers (±2^31) are stored directly as Smis
246- Objects use pointer tagging with map pointers
247- Doubles are stored in object layouts with special maps
 
248 
249## Testing Strategy
250 
251### Comprehensive Testing
252 
253The V8 test suite compares output between Node.js and Bun for the same C++ code:
254 
2551. **Install Phase**: Sets up identical module builds for Node.js and Bun
2562. **Build Phase**: Compiles native modules using node-gyp
2573. **Test Phase**: Runs identical C++ functions and compares output
 
 
258 
259### Test Categories
260 
261- **Primitives**: undefined, null, booleans, numbers, strings
262- **Objects**: creation, property access, internal fields
263- **Arrays**: creation, length, iteration, element access
264- **Functions**: callbacks, templates, argument handling
265- **Memory**: handle scopes, garbage collection, external data
266- **Advanced**: templates, inheritance, error handling
267 
268### Adding New Tests
269 
2701. Add C++ test function to `test/v8/v8-module/main.cpp`
2712. Register function in the module exports
2723. Add test case to `test/v8/v8.test.ts` using `checkSameOutput()`
2734. Run with: `bun bd test test/v8/v8.test.ts -t "your test name"`
274 
275## Debugging Tips
 
 
 
 
 
 
 
 
 
 
 
 
 
276 
277### Build and Test
278 
279```bash
280# Build debug version (takes ~5 minutes)
281bun bd --help
282 
283# Run V8 tests
284bun bd test test/v8/v8.test.ts
285 
286# Run specific test
287bun bd test test/v8/v8.test.ts -t "can create small integer"
 
 
 
 
 
288```
289 
290### Common Issues
291 
292**Symbol Not Found**: Ensure mangled names are correctly added to `napi_body.rs` and symbol files.
293 
294**Segmentation Fault**: Usually indicates inline V8 functions are reading incorrect memory layouts. Check `Map` setup and `ObjectLayout` structure.
295 
296**GC Issues**: Objects being freed prematurely. Ensure proper `WriteBarrier` usage and `visitChildren()` implementation.
297 
298**Type Mismatches**: Use `v8_compatibility_assertions.h` macros to verify type layouts match V8 expectations.
 
 
 
299 
300### Debug Logging
301 
302Use `V8_UNIMPLEMENTED()` macro for functions not yet implemented:
303 
304```cpp
305void MyClass::NotYetImplemented() {
306 V8_UNIMPLEMENTED();
307}
308```
309 
310## Advanced Topics
311 
312### Inline Function Compatibility
313 
314Many V8 functions are inline and compiled into native modules. The memory layout must exactly match what these functions expect:
315 
316- Objects start with tagged pointer to `Map`
317- Maps have instance type at offset 12
318- Handle scopes store tagged pointers
319- Primitive values at fixed global offsets
320 
321### Cross-Platform Considerations
322 
323- Symbol mangling differs between GCC/Clang and MSVC
324- Handle calling conventions (JSC uses System V on Unix)
325- Ensure `BUN_EXPORT` visibility on all public functions
326- Test on all target platforms via CI
327 
328## Contributing
329 
330When contributing V8 API implementations:
331 
3321. **Follow existing patterns** in similar classes
3332. **Add comprehensive tests** that compare with Node.js
3343. **Update all symbol files** with correct mangled names
3354. **Document any special behavior** or limitations
336 
337For questions about V8 API implementation, refer to the blog series linked above or examine existing implementations in this directory.
338 
oven-sh/bun · CLAUDE.md
@@ +1 @@
1This is the Bun repository - an all-in-one JavaScript runtime & toolkit designed for speed, with a bundler, test runner, and Node.js-compatible package manager. It's written primarily in Rust with C++ for JavaScriptCore integration, powered by WebKit's JavaScriptCore engine.
2 
3## Building and Running Bun
4 
5### Build Commands
6 
7- **Build Bun**: `bun bd`
8 - Creates a debug build at `./build/debug/bun-debug`
9 - **CRITICAL**: do not set a timeout when running `bun bd`
10- **Run tests with your debug build**: `bun bd test <test-file>`
11 - **CRITICAL**: Never use `bun test` directly - it won't include your changes
12- **Run any command with debug build**: `bun bd <command>`
13- **Run with JavaScript exception scope verification**: `BUN_JSC_validateExceptionChecks=1
14BUN_JSC_dumpSimulatedThrows=1 bun bd <command>`
15 
16Tip: Bun is already installed and in $PATH. The `bd` subcommand is a package.json script.
 
 
 
17 
18**All build scripts support build-then-exec.** Any `bun run build*` command (and `bun bd`) accepts trailing args which are passed to the built executable after building — you never invoke `./build/debug/bun-debug` directly.
19 
20```sh
21bun bd test foo.test.ts # debug build + quiet debug logs
22bun run build test foo.test.ts # debug build
23bun run build:release -p 'Bun.version' # release build
24bun run build:local run script.ts # debug build with local WebKit
 
25```
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26 
27When exec args are present, build output is suppressed unless the build fails — you see only the binary's output. Build flags (e.g. `--asan=off`) go before the exec args; see `scripts/build.ts` header for the full arg routing rules.
28 
29### Changes that don't require a build
30 
31Edits to **TypeScript type declarations** (`packages/bun-types/**/*.d.ts`) do not touch any compiled code, so `bun bd` is unnecessary. The types test just packs the `.d.ts` files and runs `tsc` against fixtures — it never executes your build. Run it directly with the system Bun (an explicit exception to the "never use `bun test` directly" rule):
32 
33```sh
34bun test test/integration/bun-types/bun-types.test.ts
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35```
36 
37This is an explicit exception to the "never use `bun test` directly" rule. There are no native changes for a debug build to pick up, so don't wait on one.
38 
39## Testing
 
 
 
40 
41### Running Tests
42 
43- **Single test file**: `bun bd test test/js/bun/http/serve.test.ts`
44- **Fuzzy match test file**: `bun bd test http/serve.test.ts`
45- **With filter**: `bun bd test test/js/bun/http/serve.test.ts -t "should handle"`
46 
47### Test Organization
 
 
 
 
 
 
 
48 
49**Default: add your test to the existing test file for the code you're changing.** Do not create a new file. A fetch bug goes in `test/js/web/fetch/fetch.test.ts`, a `Bun.serve` bug goes in `test/js/bun/http/serve.test.ts`, and so on. Keeping tests next to related coverage is what makes them discoverable and prevents duplicated setup.
 
 
 
 
 
 
 
 
 
50 
51- `test/js/bun/` - Bun-specific API tests (http, crypto, ffi, shell, etc.)
52- `test/js/node/` - Node.js compatibility tests
53- `test/js/web/` - Web API tests (fetch, WebSocket, streams, etc.)
54- `test/cli/` - CLI command tests (install, run, test, etc.)
55- `test/bundler/` - Bundler and transpiler tests. Use `itBundled` helper.
56- `test/integration/` - End-to-end integration tests
57- `test/napi/` - N-API compatibility tests
58- `test/v8/` - V8 C++ API compatibility tests
59 
60**Exception:** `test/regression/issue/${issueNumber}.test.ts` is reserved for bugs with a GitHub issue number **and** that are true regressions (worked in a previous release, then broke). If the behavior was never correct, it's not a regression — the test belongs in the existing file for that module. The issue number must be **REAL**, not a placeholder.
61 
62### Writing Tests
63 
64Tests use Bun's Jest-compatible test runner. For **single-file tests**, prefer spawning with `-e`; for **multi-file tests**, prefer `tempDir` and `Bun.spawn`:
65 
66```typescript
67import { test, expect } from "bun:test";
68import { bunEnv, bunExe, normalizeBunSnapshot, tempDir } from "harness";
69 
70 const [stdout, stderr, exitCode] = await Promise.all([
71test("(multi-file test) my feature", async () => {
72 using dir = tempDir("test-prefix", {
73 "index.js": `import { foo } from "./foo.ts"; foo();`,
74 "foo.ts": `export function foo() { console.log("foo"); }`,
75 });
76 // For a single-file test, use: cmd: [bunExe(), "-e", `console.log("foo")`] and omit cwd.
77 await using proc = Bun.spawn({
78 cmd: [bunExe(), "index.js"],
79 env: bunEnv,
80 cwd: String(dir),
81 stderr: "pipe",
82 });
 
 
 
 
 
 
 
 
 
83 
84 const [stdout, stderr, exitCode] = await Promise.all([
85 proc.stdout.text(),
86 proc.stderr.text(),
87 proc.exited,
88 ]);
89 
90 // Prefer snapshot tests over expect(stdout).toBe("hello\n");
91 expect(normalizeBunSnapshot(stdout, dir)).toMatchInlineSnapshot(`"foo"`);
92 
93 // Assert the exit code last. This gives you a more useful error message on test failure.
94 expect(exitCode).toBe(0);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
95});
96```
97 
98- Always use `port: 0`. Do not hardcode ports. Do not use your own random port number function.
99- Use `normalizeBunSnapshot` to normalize snapshot output of the test.
100- NEVER write tests that check for no "panic" or "uncaught exception" or similar in the test output. These tests will never fail in CI.
101- Use `tempDir` from `"harness"` to create a temporary directory. **Do not** use `tmpdirSync` or `fs.mkdtempSync` to create temporary directories.
102- When spawning processes, tests should expect(stdout).toBe(...) BEFORE expect(exitCode).toBe(0). This gives you a more useful error message on test failure.
103- Keep tests fast: budget roughly 1s per test and 10s per file. Debug+ASAN builds run 10-100x slower than release, so a 1s local test can take a minute in CI. Use `test.concurrent` for independent subprocess-spawning tests.
104- Never contact the public internet (registry.npmjs.org, github.com, CDNs). Use `VerdaccioRegistry` from `"harness"` for package installs and a local `Bun.serve({ port: 0 })` for HTTP.
105- `setDefaultTimeout` is a ceiling, not a target. Leave the default and pass a per-test timeout only for the rare outlier; a 5-minute file default multiplies across retries when one test hangs.
106- Leak tests branch their RSS threshold on `isASAN`/`isDebug` and keep the bound well below what the unfixed leak produces. An un-branched absolute delta flakes under ASAN quarantine and GC jitter.
107- **CRITICAL**: Do not write flaky tests. Do not use `setTimeout` or `await sleep(N)` to wait for a condition; poll with a deadline or `await` the event itself. You are not testing the TIME PASSING, you are testing the CONDITION.
108- **CRITICAL**: Verify your test fails with `USE_SYSTEM_BUN=1 bun test <file>` and passes with `bun bd test <file>`. Your test is NOT VALID if it passes with `USE_SYSTEM_BUN=1`.
109 
110## Code Architecture
111 
112### Language Structure
113 
114- **Rust code** (`src/**/*.rs`): Core runtime, JavaScript bindings, bundler, package manager. This is what compiles and ships.
115- **C++ code** (`src/jsc/bindings/*.cpp`): JavaScriptCore bindings, Web APIs
116- **TypeScript** (`src/js/`): Built-in JavaScript modules with special syntax (see JavaScript Modules section)
117- **Generated code**: Many `.rs` and `.cpp` files are auto-generated from `.classes.ts` and other sources. The build regenerates them automatically when their inputs change.
 
 
118 
119### Core Source Organization
120 
121The Rust side is a Cargo workspace of ~200 crates rooted at `Cargo.toml`. The key ones:
122 
123- `src/bun_core/` - The `bun.*`-namespace foundation: strings/`String` (`string/`), formatting (`fmt.rs`), logging (`output.rs`), feature flags, env vars, allocator helpers
124- `src/sys/` - Cross-platform syscall wrappers (`file.rs`, `dir.rs`, `fd.rs`, `Error.rs`, `tmp.rs`) — the `bun.sys` equivalent
125- `src/collections/`, `src/threading/`, `src/paths/`, `src/semver/`, `src/sourcemap/` - shared utilities
126- `src/bun_bin/` - Cargo entrypoint; produces `libbun_rust.a`, linked into the final binary
127- `src/runtime/cli/` - CLI argument parsing and command dispatch
128- `src/js_parser/`, `src/js_printer/` - JavaScript/TypeScript parsing and printing (each is its own crate; the lexer is `src/js_parser/lexer.rs`)
129- `src/transpiler/` - Wrapper around the parser/printer with sourcemap support
130- `src/resolver/` - Module resolution system
131- `src/ast/` - AST node types and arena allocation
132- `src/jsc/bindings/` - C++ JavaScriptCore bindings (generated classes from `.classes.ts` + manual bindings)
133- `src/jsc/` - Rust-side JSC glue (`VirtualMachine.rs`, `web_worker.rs`, `event_loop.rs`, FFI imports)
134- `src/runtime/api/` - Bun-specific JS-visible APIs (`BunObject.rs`, `JSBundler.rs`, `Glob`, `Archive`, …)
135- `src/runtime/server/` - `Bun.serve` HTTP/WebSocket server
136- `src/runtime/node/` - Node.js compatibility layer (fs, path, process, Buffer, …)
137- `src/runtime/crypto/` - WebCrypto + `node:crypto` (`EVP.rs`, `HMAC.rs`, `CryptoHasher.rs`, …)
138- `src/runtime/webcore/` - Web API implementations (`fetch.rs`, `streams.rs`, `Blob.rs`, `Response.rs`, `Request.rs`, …)
139- `src/event_loop/` - Event loop and task management
140- `src/bundler/` - JavaScript bundler (tree-shaking, CSS processing, HTML handling)
141- `src/install/` - Package manager (`lockfile/`, `npm.rs` registry client, `lifecycle_script_runner.rs`)
142- `src/shell/` - Cross-platform shell implementation
143- `src/css/` - CSS parser and processor
144- `src/http/` - HTTP client + `websocket_client/` (WebSocket, deflate)
145- `src/sql/` - SQL database integrations (Postgres, MySQL, SQLite)
146- `src/bake/` - Server-side rendering / dev server framework
147 
148#### Vendored Dependencies (`vendor/`)
149 
150Third-party C/C++ libraries are vendored locally and can be read from disk (not git submodules): boringssl (TLS/crypto), brotli, cares (async DNS), hdrhistogram, highway (SIMD), libarchive (tar/zip), libdeflate, libuv (Windows event loop), lolhtml (HTML rewriter), lshpack (HTTP/2 HPACK), lsqpack + lsquic (HTTP/3), mimalloc (allocator), nodejs (headers), picohttpparser, tinycc (FFI JIT, fork: oven-sh/tinycc), WebKit (JavaScriptCore), zlib (zlib-ng), zstd. Build configuration for these is in `scripts/build/deps/*.ts`.
151 
152### JavaScript Class Implementation (C++)
153 
154When implementing JavaScript classes in C++:
 
 
155 
1561. Create three classes if there's a public constructor:
157 - `class Foo : public JSC::JSDestructibleObject` (if has C++ fields)
158 - `class FooPrototype : public JSC::JSNonFinalObject`
159 - `class FooConstructor : public JSC::InternalFunction`
1602. Define properties using HashTableValue arrays
1613. Add iso subspaces for classes with C++ fields
1624. Cache structures in `ZigGlobalObject`
163 
164### Code Generation
 
 
165 
166Code generation happens automatically as part of the build process. The main scripts are:
167 
168- `src/codegen/generate-classes.ts` - Generates Rust & C++ bindings from `*.classes.ts` files
169- `src/codegen/generate-jssink.ts` - Generates stream-related classes
170- `src/codegen/bundle-modules.ts` - Bundles built-in modules like `node:fs`
171- `src/codegen/bundle-functions.ts` - Bundles global functions like `ReadableStream`
172 
173In development, bundled JS modules can be reloaded without rebuilding native code by running `bun run build`.
174 
175## JavaScript Modules (`src/js/`)
176 
177Built-in JavaScript modules use special syntax and are organized as:
178 
179- `node/` - Node.js compatibility modules (`node:fs`, `node:path`, etc.)
180- `bun/` - Bun-specific modules (`bun:ffi`, `bun:sqlite`, etc.)
181- `thirdparty/` - NPM modules we replace (like `ws`)
182- `internal/` - Internal modules not exposed to users
183- `builtins/` - Core JavaScript builtins (streams, console, etc.)
184 
185## Landing PRs: What Bun Reviewers Catch
186 
187The code review rules — what blocks merges, distilled from ~2,500 merged PRs — live in `REVIEW.md`. Read it before writing code that makes a non-obvious choice.
 
 
 
 
 
188 
189Several situational sections live in `.claude/docs/landing-prs.md` — read the relevant one before the work it covers: **Node/Web compat** (touching `node:*` modules, Web APIs, or `src/runtime/node/`), **API design** (adding or changing user-facing API surface), **Performance** (optimizing, touching hot paths, or making perf claims), **Cross-platform** (platform-gated code, FFI/ABI, or platform-sensitive tests), **Dependencies & vendoring** (bumping deps or touching `vendor/`), **Docs, types, and comments** (docs, `.d.ts`, JSDoc), and **PR process** (opening or responding to a PR).
190 
191## Important Development Notes
 
 
 
192 
1931. **Never use `bun test` or `bun <file>` directly** - always use `bun bd test` or `bun bd <command>`. `bun bd` compiles & runs the debug build.
1942. **All changes must be tested** - if you're not testing your changes, you're not done.
1953. **Get your tests to pass**. If you didn't run the tests, your code does not work.
1964. **Follow existing code style** - check neighboring files for patterns
1975. **Create tests in the right folder** in `test/` and the test must end in `.test.ts` or `.test.tsx`
1986. **Use absolute paths** - Always use absolute paths in file operations
1997. **Avoid shell commands** - Don't use `find` or `grep` in tests; use Bun's Glob and built-in tools
2008. **Memory management** - Prefer RAII (`Drop`) over manual cleanup. Arena edge case: values allocated in an arena (`Arena<T>`/`bumpalo`) do **not** run `Drop` on arena reset — types owning a heap allocation or refcount must be freed/deref'd explicitly first, mirroring the original Zig `deinit()` order.
2019. **Cross-platform** - Run `bun run rust:check-all` to compile across all targets (linux/macos/windows × x64/aarch64) when making platform-specific changes. `#[cfg(...)]`-gated code is not type-checked unless the matching target is built.
20210. **Debug builds** - Use `BUN_DEBUG_QUIET_LOGS=1` to disable debug logging, or `BUN_DEBUG_<SCOPE>=1` to enable a specific `bun_core::output` scoped logger
20311. **Be humble & honest** - NEVER overstate what you got done or what actually works in commits, PRs or in messages to the user.
20412. **Branch names must start with `claude/`** - This is a requirement for the CI to work.
20513. **If you need a paragraph-long comment to justify why the workaround is OK, the code is wrong — fix the code.**.
20614. After every code comment you write, ask yourself, "Is this information the next Claude would spend multiple tool calls trying to understand?". If the answer isn't clearly yes, the code comment is noise - delete it.
207 
208**ONLY** push up changes after running `bun bd test <file>` and ensuring your tests pass.
209 
210## Debugging CI Failures
 
 
211 
212Requires the BuildKite CLI (`brew install buildkite/buildkite/bk`) and a read-scoped token in `BUILDKITE_API_TOKEN`. The repo's `.bk.yaml` sets the org/pipeline so `-p bun` is not needed.
 
213 
214```bash
215bun run ci:errors # rendered test-failure output for this branch's latest build, [new] vs [also on main]
216bun run ci:errors '#26173' # or a PR number / URL / branch / build number
217bun run ci:status # one-screen progress summary (job counts, failed jobs, failing tests so far)
218bun run ci:logs # save full logs for every failed job to ./tmp/ci-<build>/
219bun run ci:find # just the build number, e.g. bk job log <job-uuid> -b $(bun run ci:find)
220bun run ci:watch # watch the current branch's build until it finishes
221```
222 
223For anything else, use `bk` directly — `bk build list`, `bk api`, `bk artifacts`, etc.
224 
225If output from these commands looks wrong (mis-parsed annotation HTML, a field BuildKite changed shape on), fix `scripts/find-build.ts` directly rather than working around it — it's a thin presenter over `bk`.
226 
227## Reading PR Feedback
228 
229`gh pr view --comments` silently omits review summaries and line-level review comments. For the complete picture — especially when responding to a review — use `bun run pr:comments`, which fetches issue comments, reviews, and line comments in one chronological, labelled listing.
230 
231```bash
232bun run pr:comments # current branch's PR — resolved threads hidden
233bun run pr:comments 28838 # by PR number; '#28838' and full URLs also work
234bun run pr:comments --include-resolved # also show threads already marked resolved
235 
236# Machine-readable output for jq pipelines — one object per entry.
237# Resolved threads and bot noise (robobun CI status, CodeRabbit summaries) are filtered out.
238bun run pr:comments --json | jq '.[] | select(.user == "Jarred-Sumner")'
 
 
 
 
 
239```
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
240 
@@ −1 +1 @@
1−# V8 C++ API Implementation Guide
1+This is the Bun repository - an all-in-one JavaScript runtime & toolkit designed for speed, with a bundler, test runner, and Node.js-compatible package manager. It's written primarily in Rust with C++ for JavaScriptCore integration, powered by WebKit's JavaScriptCore engine.
22  
3−This directory contains Bun's implementation of the V8 C++ API on top of JavaScriptCore. This allows native Node.js modules that use V8 APIs to work with Bun.
3+## Building and Running Bun
44  
5−## Architecture Overview
5+### Build Commands
66  
7−Bun implements V8 APIs by creating a compatibility layer that:
7+- **Build Bun**: `bun bd`
8+ - Creates a debug build at `./build/debug/bun-debug`
9+ - **CRITICAL**: do not set a timeout when running `bun bd`
10+- **Run tests with your debug build**: `bun bd test <test-file>`
11+ - **CRITICAL**: Never use `bun test` directly - it won't include your changes
12+- **Run any command with debug build**: `bun bd <command>`
13+- **Run with JavaScript exception scope verification**: `BUN_JSC_validateExceptionChecks=1
14+BUN_JSC_dumpSimulatedThrows=1 bun bd <command>`
815  
9−- Maps V8's `Local<T>` handles to JSC's `JSValue` system
10−- Uses handle scopes to manage memory lifetimes similar to V8
11−- Provides V8-compatible object layouts that inline V8 functions can read
12−- Manages tagged pointers for efficient value representation
16+Tip: Bun is already installed and in $PATH. The `bd` subcommand is a package.json script.
1317  
14−For detailed background, see the blog series:
18+**All build scripts support build-then-exec.** Any `bun run build*` command (and `bun bd`) accepts trailing args which are passed to the built executable after building — you never invoke `./build/debug/bun-debug` directly.
1519  
16−- [Part 1: Introduction and challenges](https://bun.com/blog/how-bun-supports-v8-apis-without-using-v8-part-1.md)
17−- [Part 2: Memory layout and object representation](https://bun.com/blog/how-bun-supports-v8-apis-without-using-v8-part-2.md)
18−- [Part 3: Garbage collection and primitives](https://bun.com/blog/how-bun-supports-v8-apis-without-using-v8-part-3.md)
19− 
20−## Directory Structure
21− 
20+```sh
21+bun bd test foo.test.ts # debug build + quiet debug logs
22+bun run build test foo.test.ts # debug build
23+bun run build:release -p 'Bun.version' # release build
24+bun run build:local run script.ts # debug build with local WebKit
2225 ```
23−src/jsc/bindings/v8/
24−├── v8.h # Main header with V8_UNIMPLEMENTED macro
25−├── v8_*.h # V8 compatibility headers
26−├── V8*.h # V8 class headers (Number, String, Object, etc.)
27−├── V8*.cpp # V8 class implementations
28−├── shim/ # Internal implementation details
29−│ ├── Handle.h # Handle and ObjectLayout implementation
30−│ ├── HandleScopeBuffer.h # Handle scope memory management
31−│ ├── TaggedPointer.h # V8-style tagged pointer implementation
32−│ ├── Map.h # V8 Map objects for inline function compatibility
33−│ ├── GlobalInternals.h # V8 global state management
34−│ ├── InternalFieldObject.h # Objects with internal fields
35−│ └── Oddball.h # Primitive values (undefined, null, true, false)
36−├── node.h # Node.js module registration compatibility
37−└── real_v8.h # Includes real V8 headers when needed
38−```
3926  
40−## Implementing New V8 APIs
27+When exec args are present, build output is suppressed unless the build fails — you see only the binary's output. Build flags (e.g. `--asan=off`) go before the exec args; see `scripts/build.ts` header for the full arg routing rules.
4128  
42−### 1. Create Header and Implementation Files
29+### Changes that don't require a build
4330  
44−Create `V8NewClass.h`:
31+Edits to **TypeScript type declarations** (`packages/bun-types/**/*.d.ts`) do not touch any compiled code, so `bun bd` is unnecessary. The types test just packs the `.d.ts` files and runs `tsc` against fixtures — it never executes your build. Run it directly with the system Bun (an explicit exception to the "never use `bun test` directly" rule):
4532  
46−```cpp
47−#pragma once
48− 
49−#include "v8.h"
50−#include "V8Local.h"
51−#include "V8Isolate.h"
52− 
53−namespace v8 {
54− 
55−class NewClass : public Data {
56−public:
57− BUN_EXPORT static Local<NewClass> New(Isolate* isolate, /* parameters */);
58− BUN_EXPORT /* return_type */ SomeMethod() const;
59− 
60− // Add other methods as needed
61−};
62− 
63−} // namespace v8
33+```sh
34+bun test test/integration/bun-types/bun-types.test.ts
6435 ```
6536  
66−Create `V8NewClass.cpp`:
37+This is an explicit exception to the "never use `bun test` directly" rule. There are no native changes for a debug build to pick up, so don't wait on one.
6738  
68−```cpp
69−#include "V8NewClass.h"
70−#include "V8HandleScope.h"
71−#include "v8_compatibility_assertions.h"
39+## Testing
7240  
73−ASSERT_V8_TYPE_LAYOUT_MATCHES(v8::NewClass)
41+### Running Tests
7442  
75−namespace v8 {
43+- **Single test file**: `bun bd test test/js/bun/http/serve.test.ts`
44+- **Fuzzy match test file**: `bun bd test http/serve.test.ts`
45+- **With filter**: `bun bd test test/js/bun/http/serve.test.ts -t "should handle"`
7646  
77−Local<NewClass> NewClass::New(Isolate* isolate, /* parameters */)
78−{
79− // Implementation - typically:
80− // 1. Create JSC value
81− // 2. Get current handle scope
82− // 3. Create local handle
83− return isolate->currentHandleScope()->createLocal<NewClass>(isolate->vm(), /* JSC value */);
84−}
47+### Test Organization
8548  
86−/* return_type */ NewClass::SomeMethod() const
87−{
88− // Implementation - typically:
89− // 1. Convert this Local to JSValue via localToJSValue()
90− // 2. Perform JSC operations
91− // 3. Return converted result
92− auto jsValue = localToJSValue();
93− // ... JSC operations ...
94− return /* result */;
95−}
49+**Default: add your test to the existing test file for the code you're changing.** Do not create a new file. A fetch bug goes in `test/js/web/fetch/fetch.test.ts`, a `Bun.serve` bug goes in `test/js/bun/http/serve.test.ts`, and so on. Keeping tests next to related coverage is what makes them discoverable and prevents duplicated setup.
9650  
97−} // namespace v8
98−```
51+- `test/js/bun/` - Bun-specific API tests (http, crypto, ffi, shell, etc.)
52+- `test/js/node/` - Node.js compatibility tests
53+- `test/js/web/` - Web API tests (fetch, WebSocket, streams, etc.)
54+- `test/cli/` - CLI command tests (install, run, test, etc.)
55+- `test/bundler/` - Bundler and transpiler tests. Use `itBundled` helper.
56+- `test/integration/` - End-to-end integration tests
57+- `test/napi/` - N-API compatibility tests
58+- `test/v8/` - V8 C++ API compatibility tests
9959  
100−### 2. Add Symbol Exports
60+**Exception:** `test/regression/issue/${issueNumber}.test.ts` is reserved for bugs with a GitHub issue number **and** that are true regressions (worked in a previous release, then broke). If the behavior was never correct, it's not a regression — the test belongs in the existing file for that module. The issue number must be **REAL**, not a placeholder.
10161  
102−For each new C++ method, you must add the mangled symbol names to multiple files:
62+### Writing Tests
10363  
104−#### a. Add to `src/runtime/napi/napi_body.rs`
64+Tests use Bun's Jest-compatible test runner. For **single-file tests**, prefer spawning with `-e`; for **multi-file tests**, prefer `tempDir` and `Bun.spawn`:
10565  
106−Find the `v8_api` module and add entries to both the `#[cfg(not(windows))]` (Itanium) and `#[cfg(windows)]` (MSVC) `extern "C"` blocks:
66+```typescript
67+import { test, expect } from "bun:test";
68+import { bunEnv, bunExe, normalizeBunSnapshot, tempDir } from "harness";
10769  
108−```rust
109−#[cfg(not(windows))]
110−mod v8_api {
111− use core::ffi::c_void;
112− unsafe extern "C" {
113− // ... existing functions ...
114− pub(super) fn _ZN2v88NewClass3NewEPNS_7IsolateE/* parameters */() -> *mut c_void;
115− pub(super) fn _ZNK2v88NewClass10SomeMethodEv() -> *mut c_void;
116− }
117−}
118−#[cfg(windows)]
119−mod v8_api {
120− use core::ffi::c_void;
121− unsafe extern "C" {
122− // ... existing functions ...
123− #[link_name = "?New@NewClass@v8@@SA?AV?$Local@VNewClass@v8@@@2@PEAVIsolate@2@/* parameters */@Z"]
124− pub(super) fn NewClass_New() -> *mut c_void;
125− #[link_name = "?SomeMethod@NewClass@v8@@QEBA/* return_type */XZ"]
126− pub(super) fn NewClass_SomeMethod() -> *mut c_void;
127− }
128−}
129−```
70+ const [stdout, stderr, exitCode] = await Promise.all([
71+test("(multi-file test) my feature", async () => {
72+ using dir = tempDir("test-prefix", {
73+ "index.js": `import { foo } from "./foo.ts"; foo();`,
74+ "foo.ts": `export function foo() { console.log("foo"); }`,
75+ });
76+ // For a single-file test, use: cmd: [bunExe(), "-e", `console.log("foo")`] and omit cwd.
77+ await using proc = Bun.spawn({
78+ cmd: [bunExe(), "index.js"],
79+ env: bunEnv,
80+ cwd: String(dir),
81+ stderr: "pipe",
82+ });
13083  
131−**To get the correct mangled names:**
84+ const [stdout, stderr, exitCode] = await Promise.all([
85+ proc.stdout.text(),
86+ proc.stderr.text(),
87+ proc.exited,
88+ ]);
13289  
133−For **GCC/Clang** (Unix):
90+ // Prefer snapshot tests over expect(stdout).toBe("hello\n");
91+ expect(normalizeBunSnapshot(stdout, dir)).toMatchInlineSnapshot(`"foo"`);
13492  
135−```bash
136−# Build your changes first
137−bun bd --help # This compiles your code
138− 
139−# Extract symbols
140−nm build/CMakeFiles/bun-debug.dir/src/jsc/bindings/v8/V8NewClass.cpp.o | grep "T _ZN2v8"
141−```
142− 
143−For **MSVC** (Windows):
144− 
145−```powershell
146−# Use the provided PowerShell script in the comments:
147−dumpbin .\build\CMakeFiles\bun-debug.dir\src\jsc\bindings\v8\V8NewClass.cpp.obj /symbols | where-object { $_.Contains(' v8::') } | foreach-object { (($_ -split "\|")[1] -split " ")[1] } | ForEach-Object { "#[link_name = `"${_}`"] pub(super) fn ___() -> *mut c_void;" }
148−```
149− 
150−#### b. Add to Symbol Files
151− 
152−Add to `src/symbols.txt` (without leading underscore):
153− 
154−```
155−_ZN2v88NewClass3NewEPNS_7IsolateE...
156−_ZNK2v88NewClass10SomeMethodEv
157−```
158− 
159−Add to `src/symbols.dyn` (with leading underscore and semicolons):
160− 
161−```
162−{
163− __ZN2v88NewClass3NewEPNS_7IsolateE...;
164− __ZNK2v88NewClass10SomeMethodEv;
165−}
166−```
167− 
168−**Note:** `src/symbols.def` is Windows-only and typically doesn't contain V8 symbols.
169− 
170−### 3. Add Tests
171− 
172−Create tests in `test/v8/v8-module/main.cpp`:
173− 
174−```cpp
175−void test_new_class_feature(const FunctionCallbackInfo<Value> &info) {
176− Isolate* isolate = info.GetIsolate();
177− 
178− // Test your new V8 API
179− Local<NewClass> obj = NewClass::New(isolate, /* parameters */);
180− auto result = obj->SomeMethod();
181− 
182− // Print results for comparison with Node.js
183− std::cout << "Result: " << result << std::endl;
184− 
185− info.GetReturnValue().Set(Undefined(isolate));
186−}
187−```
188− 
189−Add the test to the registration section:
190− 
191−```cpp
192−void Init(Local<Object> exports, Local<Value> module, Local<Context> context) {
193− // ... existing functions ...
194− NODE_SET_METHOD(exports, "test_new_class_feature", test_new_class_feature);
195−}
196−```
197− 
198−Add test case to `test/v8/v8.test.ts`:
199− 
200−```typescript
201−describe("NewClass", () => {
202− it("can use new feature", async () => {
203− await checkSameOutput("test_new_class_feature", []);
204− });
93+ // Assert the exit code last. This gives you a more useful error message on test failure.
94+ expect(exitCode).toBe(0);
20595 });
20696 ```
20797  
208−### 4. Handle Special Cases
98+- Always use `port: 0`. Do not hardcode ports. Do not use your own random port number function.
99+- Use `normalizeBunSnapshot` to normalize snapshot output of the test.
100+- NEVER write tests that check for no "panic" or "uncaught exception" or similar in the test output. These tests will never fail in CI.
101+- Use `tempDir` from `"harness"` to create a temporary directory. **Do not** use `tmpdirSync` or `fs.mkdtempSync` to create temporary directories.
102+- When spawning processes, tests should expect(stdout).toBe(...) BEFORE expect(exitCode).toBe(0). This gives you a more useful error message on test failure.
103+- Keep tests fast: budget roughly 1s per test and 10s per file. Debug+ASAN builds run 10-100x slower than release, so a 1s local test can take a minute in CI. Use `test.concurrent` for independent subprocess-spawning tests.
104+- Never contact the public internet (registry.npmjs.org, github.com, CDNs). Use `VerdaccioRegistry` from `"harness"` for package installs and a local `Bun.serve({ port: 0 })` for HTTP.
105+- `setDefaultTimeout` is a ceiling, not a target. Leave the default and pass a per-test timeout only for the rare outlier; a 5-minute file default multiplies across retries when one test hangs.
106+- Leak tests branch their RSS threshold on `isASAN`/`isDebug` and keep the bound well below what the unfixed leak produces. An un-branched absolute delta flakes under ASAN quarantine and GC jitter.
107+- **CRITICAL**: Do not write flaky tests. Do not use `setTimeout` or `await sleep(N)` to wait for a condition; poll with a deadline or `await` the event itself. You are not testing the TIME PASSING, you are testing the CONDITION.
108+- **CRITICAL**: Verify your test fails with `USE_SYSTEM_BUN=1 bun test <file>` and passes with `bun bd test <file>`. Your test is NOT VALID if it passes with `USE_SYSTEM_BUN=1`.
209109  
210−#### Objects with Internal Fields
110+## Code Architecture
211111  
212−If implementing objects that need internal fields, extend `InternalFieldObject`:
112+### Language Structure
213113  
214−```cpp
215−// In your .h file
216−class MyObject : public InternalFieldObject {
217− // ... implementation
218−};
219−```
114+- **Rust code** (`src/**/*.rs`): Core runtime, JavaScript bindings, bundler, package manager. This is what compiles and ships.
115+- **C++ code** (`src/jsc/bindings/*.cpp`): JavaScriptCore bindings, Web APIs
116+- **TypeScript** (`src/js/`): Built-in JavaScript modules with special syntax (see JavaScript Modules section)
117+- **Generated code**: Many `.rs` and `.cpp` files are auto-generated from `.classes.ts` and other sources. The build regenerates them automatically when their inputs change.
220118  
221−#### Primitive Values
119+### Core Source Organization
222120  
223−For primitive values, ensure they work with the `Oddball` system in `shim/Oddball.h`.
121+The Rust side is a Cargo workspace of ~200 crates rooted at `Cargo.toml`. The key ones:
224122  
225−#### Template Classes
123+- `src/bun_core/` - The `bun.*`-namespace foundation: strings/`String` (`string/`), formatting (`fmt.rs`), logging (`output.rs`), feature flags, env vars, allocator helpers
124+- `src/sys/` - Cross-platform syscall wrappers (`file.rs`, `dir.rs`, `fd.rs`, `Error.rs`, `tmp.rs`) — the `bun.sys` equivalent
125+- `src/collections/`, `src/threading/`, `src/paths/`, `src/semver/`, `src/sourcemap/` - shared utilities
126+- `src/bun_bin/` - Cargo entrypoint; produces `libbun_rust.a`, linked into the final binary
127+- `src/runtime/cli/` - CLI argument parsing and command dispatch
128+- `src/js_parser/`, `src/js_printer/` - JavaScript/TypeScript parsing and printing (each is its own crate; the lexer is `src/js_parser/lexer.rs`)
129+- `src/transpiler/` - Wrapper around the parser/printer with sourcemap support
130+- `src/resolver/` - Module resolution system
131+- `src/ast/` - AST node types and arena allocation
132+- `src/jsc/bindings/` - C++ JavaScriptCore bindings (generated classes from `.classes.ts` + manual bindings)
133+- `src/jsc/` - Rust-side JSC glue (`VirtualMachine.rs`, `web_worker.rs`, `event_loop.rs`, FFI imports)
134+- `src/runtime/api/` - Bun-specific JS-visible APIs (`BunObject.rs`, `JSBundler.rs`, `Glob`, `Archive`, …)
135+- `src/runtime/server/` - `Bun.serve` HTTP/WebSocket server
136+- `src/runtime/node/` - Node.js compatibility layer (fs, path, process, Buffer, …)
137+- `src/runtime/crypto/` - WebCrypto + `node:crypto` (`EVP.rs`, `HMAC.rs`, `CryptoHasher.rs`, …)
138+- `src/runtime/webcore/` - Web API implementations (`fetch.rs`, `streams.rs`, `Blob.rs`, `Response.rs`, `Request.rs`, …)
139+- `src/event_loop/` - Event loop and task management
140+- `src/bundler/` - JavaScript bundler (tree-shaking, CSS processing, HTML handling)
141+- `src/install/` - Package manager (`lockfile/`, `npm.rs` registry client, `lifecycle_script_runner.rs`)
142+- `src/shell/` - Cross-platform shell implementation
143+- `src/css/` - CSS parser and processor
144+- `src/http/` - HTTP client + `websocket_client/` (WebSocket, deflate)
145+- `src/sql/` - SQL database integrations (Postgres, MySQL, SQLite)
146+- `src/bake/` - Server-side rendering / dev server framework
226147  
227−For `ObjectTemplate` or `FunctionTemplate` implementations, see existing patterns in `V8ObjectTemplate.cpp` and `V8FunctionTemplate.cpp`.
148+#### Vendored Dependencies (`vendor/`)
228149  
229−## Memory Management Guidelines
150+Third-party C/C++ libraries are vendored locally and can be read from disk (not git submodules): boringssl (TLS/crypto), brotli, cares (async DNS), hdrhistogram, highway (SIMD), libarchive (tar/zip), libdeflate, libuv (Windows event loop), lolhtml (HTML rewriter), lshpack (HTTP/2 HPACK), lsqpack + lsquic (HTTP/3), mimalloc (allocator), nodejs (headers), picohttpparser, tinycc (FFI JIT, fork: oven-sh/tinycc), WebKit (JavaScriptCore), zlib (zlib-ng), zstd. Build configuration for these is in `scripts/build/deps/*.ts`.
230151  
231−### Handle Scopes
152+### JavaScript Class Implementation (C++)
232153  
233−- All V8 values must be created within an active handle scope
234−- Use `isolate->currentHandleScope()->createLocal<T>()` to create handles
235−- Handle scopes automatically clean up when destroyed
154+When implementing JavaScript classes in C++:
236155  
237−### JSC Integration
156+1. Create three classes if there's a public constructor:
157+ - `class Foo : public JSC::JSDestructibleObject` (if has C++ fields)
158+ - `class FooPrototype : public JSC::JSNonFinalObject`
159+ - `class FooConstructor : public JSC::InternalFunction`
160+2. Define properties using HashTableValue arrays
161+3. Add iso subspaces for classes with C++ fields
162+4. Cache structures in `ZigGlobalObject`
238163  
239−- Use `localToJSValue()` to convert V8 handles to JSC values
240−- Use `JSC::WriteBarrier` for heap-allocated references
241−- Implement `visitChildren()` for custom heap objects
164+### Code Generation
242165  
243−### Tagged Pointers
166+Code generation happens automatically as part of the build process. The main scripts are:
244167  
245−- Small integers (±2^31) are stored directly as Smis
246−- Objects use pointer tagging with map pointers
247−- Doubles are stored in object layouts with special maps
168+- `src/codegen/generate-classes.ts` - Generates Rust & C++ bindings from `*.classes.ts` files
169+- `src/codegen/generate-jssink.ts` - Generates stream-related classes
170+- `src/codegen/bundle-modules.ts` - Bundles built-in modules like `node:fs`
171+- `src/codegen/bundle-functions.ts` - Bundles global functions like `ReadableStream`
248172  
249−## Testing Strategy
173+In development, bundled JS modules can be reloaded without rebuilding native code by running `bun run build`.
250174  
251−### Comprehensive Testing
175+## JavaScript Modules (`src/js/`)
252176  
253−The V8 test suite compares output between Node.js and Bun for the same C++ code:
177+Built-in JavaScript modules use special syntax and are organized as:
254178  
255−1. **Install Phase**: Sets up identical module builds for Node.js and Bun
256−2. **Build Phase**: Compiles native modules using node-gyp
257−3. **Test Phase**: Runs identical C++ functions and compares output
179+- `node/` - Node.js compatibility modules (`node:fs`, `node:path`, etc.)
180+- `bun/` - Bun-specific modules (`bun:ffi`, `bun:sqlite`, etc.)
181+- `thirdparty/` - NPM modules we replace (like `ws`)
182+- `internal/` - Internal modules not exposed to users
183+- `builtins/` - Core JavaScript builtins (streams, console, etc.)
258184  
259−### Test Categories
185+## Landing PRs: What Bun Reviewers Catch
260186  
261−- **Primitives**: undefined, null, booleans, numbers, strings
262−- **Objects**: creation, property access, internal fields
263−- **Arrays**: creation, length, iteration, element access
264−- **Functions**: callbacks, templates, argument handling
265−- **Memory**: handle scopes, garbage collection, external data
266−- **Advanced**: templates, inheritance, error handling
187+The code review rules — what blocks merges, distilled from ~2,500 merged PRs — live in `REVIEW.md`. Read it before writing code that makes a non-obvious choice.
267188  
268−### Adding New Tests
189+Several situational sections live in `.claude/docs/landing-prs.md` — read the relevant one before the work it covers: **Node/Web compat** (touching `node:*` modules, Web APIs, or `src/runtime/node/`), **API design** (adding or changing user-facing API surface), **Performance** (optimizing, touching hot paths, or making perf claims), **Cross-platform** (platform-gated code, FFI/ABI, or platform-sensitive tests), **Dependencies & vendoring** (bumping deps or touching `vendor/`), **Docs, types, and comments** (docs, `.d.ts`, JSDoc), and **PR process** (opening or responding to a PR).
269190  
270−1. Add C++ test function to `test/v8/v8-module/main.cpp`
271−2. Register function in the module exports
272−3. Add test case to `test/v8/v8.test.ts` using `checkSameOutput()`
273−4. Run with: `bun bd test test/v8/v8.test.ts -t "your test name"`
191+## Important Development Notes
274192  
275−## Debugging Tips
193+1. **Never use `bun test` or `bun <file>` directly** - always use `bun bd test` or `bun bd <command>`. `bun bd` compiles & runs the debug build.
194+2. **All changes must be tested** - if you're not testing your changes, you're not done.
195+3. **Get your tests to pass**. If you didn't run the tests, your code does not work.
196+4. **Follow existing code style** - check neighboring files for patterns
197+5. **Create tests in the right folder** in `test/` and the test must end in `.test.ts` or `.test.tsx`
198+6. **Use absolute paths** - Always use absolute paths in file operations
199+7. **Avoid shell commands** - Don't use `find` or `grep` in tests; use Bun's Glob and built-in tools
200+8. **Memory management** - Prefer RAII (`Drop`) over manual cleanup. Arena edge case: values allocated in an arena (`Arena<T>`/`bumpalo`) do **not** run `Drop` on arena reset — types owning a heap allocation or refcount must be freed/deref'd explicitly first, mirroring the original Zig `deinit()` order.
201+9. **Cross-platform** - Run `bun run rust:check-all` to compile across all targets (linux/macos/windows × x64/aarch64) when making platform-specific changes. `#[cfg(...)]`-gated code is not type-checked unless the matching target is built.
202+10. **Debug builds** - Use `BUN_DEBUG_QUIET_LOGS=1` to disable debug logging, or `BUN_DEBUG_<SCOPE>=1` to enable a specific `bun_core::output` scoped logger
203+11. **Be humble & honest** - NEVER overstate what you got done or what actually works in commits, PRs or in messages to the user.
204+12. **Branch names must start with `claude/`** - This is a requirement for the CI to work.
205+13. **If you need a paragraph-long comment to justify why the workaround is OK, the code is wrong — fix the code.**.
206+14. After every code comment you write, ask yourself, "Is this information the next Claude would spend multiple tool calls trying to understand?". If the answer isn't clearly yes, the code comment is noise - delete it.
276207  
277−### Build and Test
208+**ONLY** push up changes after running `bun bd test <file>` and ensuring your tests pass.
278209  
279−```bash
280−# Build debug version (takes ~5 minutes)
281−bun bd --help
210+## Debugging CI Failures
282211  
283−# Run V8 tests
284−bun bd test test/v8/v8.test.ts
212+Requires the BuildKite CLI (`brew install buildkite/buildkite/bk`) and a read-scoped token in `BUILDKITE_API_TOKEN`. The repo's `.bk.yaml` sets the org/pipeline so `-p bun` is not needed.
285213  
286−# Run specific test
287−bun bd test test/v8/v8.test.ts -t "can create small integer"
214+```bash
215+bun run ci:errors # rendered test-failure output for this branch's latest build, [new] vs [also on main]
216+bun run ci:errors '#26173' # or a PR number / URL / branch / build number
217+bun run ci:status # one-screen progress summary (job counts, failed jobs, failing tests so far)
218+bun run ci:logs # save full logs for every failed job to ./tmp/ci-<build>/
219+bun run ci:find # just the build number, e.g. bk job log <job-uuid> -b $(bun run ci:find)
220+bun run ci:watch # watch the current branch's build until it finishes
288221 ```
289222  
290−### Common Issues
223+For anything else, use `bk` directly — `bk build list`, `bk api`, `bk artifacts`, etc.
291224  
292−**Symbol Not Found**: Ensure mangled names are correctly added to `napi_body.rs` and symbol files.
225+If output from these commands looks wrong (mis-parsed annotation HTML, a field BuildKite changed shape on), fix `scripts/find-build.ts` directly rather than working around it — it's a thin presenter over `bk`.
293226  
294−**Segmentation Fault**: Usually indicates inline V8 functions are reading incorrect memory layouts. Check `Map` setup and `ObjectLayout` structure.
227+## Reading PR Feedback
295228  
296−**GC Issues**: Objects being freed prematurely. Ensure proper `WriteBarrier` usage and `visitChildren()` implementation.
229+`gh pr view --comments` silently omits review summaries and line-level review comments. For the complete picture — especially when responding to a review — use `bun run pr:comments`, which fetches issue comments, reviews, and line comments in one chronological, labelled listing.
297230  
298−**Type Mismatches**: Use `v8_compatibility_assertions.h` macros to verify type layouts match V8 expectations.
231+```bash
232+bun run pr:comments # current branch's PR — resolved threads hidden
233+bun run pr:comments 28838 # by PR number; '#28838' and full URLs also work
234+bun run pr:comments --include-resolved # also show threads already marked resolved
299235  
300−### Debug Logging
301− 
302−Use `V8_UNIMPLEMENTED()` macro for functions not yet implemented:
303− 
304−```cpp
305−void MyClass::NotYetImplemented() {
306− V8_UNIMPLEMENTED();
307−}
236+# Machine-readable output for jq pipelines — one object per entry.
237+# Resolved threads and bot noise (robobun CI status, CodeRabbit summaries) are filtered out.
238+bun run pr:comments --json | jq '.[] | select(.user == "Jarred-Sumner")'
308239 ```
309− 
310−## Advanced Topics
311− 
312−### Inline Function Compatibility
313− 
314−Many V8 functions are inline and compiled into native modules. The memory layout must exactly match what these functions expect:
315− 
316−- Objects start with tagged pointer to `Map`
317−- Maps have instance type at offset 12
318−- Handle scopes store tagged pointers
319−- Primitive values at fixed global offsets
320− 
321−### Cross-Platform Considerations
322− 
323−- Symbol mangling differs between GCC/Clang and MSVC
324−- Handle calling conventions (JSC uses System V on Unix)
325−- Ensure `BUN_EXPORT` visibility on all public functions
326−- Test on all target platforms via CI
327− 
328−## Contributing
329− 
330−When contributing V8 API implementations:
331− 
332−1. **Follow existing patterns** in similar classes
333−2. **Add comprehensive tests** that compare with Node.js
334−3. **Update all symbol files** with correct mangled names
335−4. **Document any special behavior** or limitations
336− 
337−For questions about V8 API implementation, refer to the blog series linked above or examine existing implementations in this directory.
338240  

Also from Kynth Studios

Built for the same person as RuleStack

ToolDrift

What the AI coding tools changed last night

tooldrift.kynth.studio

StillShipping

Which agent tools have stopped shipping

stillshipping.kynth.studio

BlockDex

Search inside every shadcn registry

blockdex.kynth.studio

The studio list

One product, taken apart, once a month

Kynth Studios pulls one shipped product open every month — what it does, what it cost to build, what the pipeline behind it looks like, and what the numbers did. One email a month, nothing in between.

Double opt-in — we send one confirmation link and nothing else until you click it.

RuleStack

Built by

Kynth Studios

the studio behind ToolDrift, StillShipping and BlockDex

part of Toolproof, the measurement layer for AI agent tooling

Directory

Configs
Stacks
Compare formats
AGENTS.md vs CLAUDE.md
Cursor rules alternatives
Diff two configs
Best AGENTS.md examples
Best Cursor rules examples
What goes in a CLAUDE.md

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

© 2026 RuleStack. A Kynth Studios product. Changelog

RuleStack

The studio list

One product, taken apart, once a month

Kynth Studios pulls one shipped product open every month — what it does, what it cost to build, what the pipeline behind it looks like, and what the numbers did. One email a month, nothing in between.

Double opt-in — we send one confirmation link and nothing else until you click it.

RuleStack

Built by

Kynth Studios

the studio behind ToolDrift, StillShipping and BlockDex

part of Toolproof, the measurement layer for AI agent tooling

Directory

Configs
Stacks
Compare formats
AGENTS.md vs CLAUDE.md
Cursor rules alternatives
Diff two configs
Best AGENTS.md examples
Best Cursor rules examples
What goes in a CLAUDE.md

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

© 2026 RuleStack. A Kynth Studios product. Changelog

RuleStack

The studio list

One product, taken apart, once a month

Kynth Studios pulls one shipped product open every month — what it does, what it cost to build, what the pipeline behind it looks like, and what the numbers did. One email a month, nothing in between.

Double opt-in — we send one confirmation link and nothing else until you click it.

RuleStack

Built by

Kynth Studios

the studio behind ToolDrift, StillShipping and BlockDex

part of Toolproof, the measurement layer for AI agent tooling

Directory

Configs
Stacks
Compare formats
AGENTS.md vs CLAUDE.md
Cursor rules alternatives
Diff two configs
Best AGENTS.md examples
Best Cursor rules examples
What goes in a CLAUDE.md

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

© 2026 RuleStack. A Kynth Studios product. Changelog

RuleStack