Skip to content
Open
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
27217df
Rename ZigGlobalObject to BunGlobalObject
robobun Jun 4, 2026
285caeb
NodeModuleModule: use defaultGlobalObject in the Module constructor
robobun Jun 4, 2026
32661a6
Merge namespace Zig into namespace Bun and rename remaining Zig-prefi…
robobun Jun 4, 2026
57d1bc2
[autofix.ci] apply automated fixes
autofix-ci[bot] Jun 4, 2026
5f35938
Fix stale ZigGlobalObject mention and zig reference-file paths
robobun Jun 4, 2026
bb72ffa
Clean up remaining rename artifacts
robobun Jun 4, 2026
63d2bdb
ci: retrigger
robobun Jun 5, 2026
909d51c
Update BunException.cpp header prose for the renamed type
robobun Jun 5, 2026
426c007
Apply review cleanups after rebase
robobun Jun 5, 2026
ca257e7
Rename remaining bare zig locals to bunGlobal
robobun Jun 5, 2026
93d2cf8
Address review: delete stale commented-out GlobalObject block, fix do…
robobun Jun 10, 2026
cdad656
Merge branch 'main' into farm/50d63c3b/rename-zigglobalobject
robobun Jun 10, 2026
46452b0
Merge remote-tracking branch 'origin/main' into farm/50d63c3b/rename-…
robobun Jun 11, 2026
8d42ec7
Merge redundant adjacent namespace Bun blocks
robobun Jun 11, 2026
5737a4b
Merge one more redundant adjacent namespace Bun block in NodeModuleMo…
robobun Jun 11, 2026
7638aa0
Merge remote-tracking branch 'origin/main' into farm/50d63c3b/rename-…
robobun Jun 15, 2026
0cf88d3
Merge remote-tracking branch 'origin/main' into farm/50d63c3b/rename-…
robobun Jun 16, 2026
21ca0a3
Merge remote-tracking branch 'origin/main' into farm/50d63c3b/rename-…
robobun Jun 17, 2026
a7d58a4
Merge remote-tracking branch 'origin/main' into farm/50d63c3b/rename-…
robobun Jun 17, 2026
1a1febc
[autofix.ci] apply automated fixes
autofix-ci[bot] Jun 17, 2026
f28363b
Rename Zig::GlobalObject in broadcast-channel-worker-gc test comments
robobun Jun 17, 2026
ba9836d
Merge remote-tracking branch 'origin/main' into farm/50d63c3b/rename-…
robobun Jun 19, 2026
1da9851
Merge remote-tracking branch 'origin/main' into farm/50d63c3b/rename-…
robobun Jun 23, 2026
f0420a5
Fix mismatched namespace-closer trailers in JSFFIFunction and drop de…
robobun Jun 23, 2026
3f2e289
Merge remote-tracking branch 'origin/main' into farm/50d63c3b/rename-…
robobun Jun 24, 2026
a50963c
Merge remote-tracking branch 'origin/main' into farm/50d63c3b/rename-…
robobun Jun 26, 2026
9be0356
Point the reportError test comment at BunStackFrame.rs
robobun Jun 26, 2026
1e988b9
Merge remote-tracking branch 'origin/main' into farm/50d63c3b/rename-…
robobun Jun 28, 2026
3ab5bda
Merge remote-tracking branch 'origin/main' into farm/50d63c3b/rename-…
robobun Jun 29, 2026
86438b9
Merge remote-tracking branch 'origin/main' into farm/50d63c3b/rename-…
robobun Jun 30, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
8 changes: 4 additions & 4 deletions .claude/skills/implementing-jsc-classes-cpp/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,13 +148,13 @@ private:

## Structure Caching

Add to `ZigGlobalObject.h`:
Add to `BunGlobalObject.h`:

```cpp
JSC::LazyClassStructure m_JSFooClassStructure;
```

Initialize in `ZigGlobalObject.cpp`:
Initialize in `BunGlobalObject.cpp`:

```cpp
m_JSFooClassStructure.initLater([](LazyClassStructure::Initializer& init) {
Expand All @@ -171,11 +171,11 @@ m_JSFooClassStructure.visit(visitor);
## Expose to Zig

```cpp
extern "C" JSC::EncodedJSValue Bun__JSFooConstructor(Zig::GlobalObject* globalObject) {
extern "C" JSC::EncodedJSValue Bun__JSFooConstructor(Bun::GlobalObject* globalObject) {
return JSValue::encode(globalObject->m_JSFooClassStructure.constructor(globalObject));
}

extern "C" EncodedJSValue Bun__Foo__toJS(Zig::GlobalObject* globalObject, Foo* foo) {
extern "C" EncodedJSValue Bun__Foo__toJS(Bun::GlobalObject* globalObject, Foo* foo) {
auto* structure = globalObject->m_JSFooClassStructure.get(globalObject);
return JSValue::encode(JSFoo::create(globalObject->vm(), structure, globalObject, WTFMove(foo)));
}
Expand Down
4 changes: 2 additions & 2 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ src/api/schema.d.ts linguist-generated
fixture.*.c linguist-generated
src/api/schema.js linguist-generated
*-fixture* linguist-generated
src/jsc/bindings/ZigGeneratedCode.h linguist-generated
src/jsc/bindings/ZigGeneratedCode.cpp linguist-generated
src/jsc/bindings/BunGeneratedCode.h linguist-generated
Comment thread
claude[bot] marked this conversation as resolved.
Outdated
src/jsc/bindings/BunGeneratedCode.cpp linguist-generated
src/jsc/bindings/headers.h linguist-generated
src/jsc/bindings/headers.zig linguist-generated

Expand Down
4 changes: 2 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ When implementing JavaScript classes in C++:

2. Define properties using HashTableValue arrays
3. Add iso subspaces for classes with C++ fields
4. Cache structures in `ZigGlobalObject`
4. Cache structures in `BunGlobalObject`
Comment thread
robobun marked this conversation as resolved.

### Code Generation

Expand Down Expand Up @@ -335,7 +335,7 @@ Distilled from the review history of ~2,500 merged PRs where review feedback led
### Architecture & layering

- **Fix bugs at the layer that owns the violated invariant, never where the symptom appears.** If a shared helper produces wrong output, fix the helper, not one call site. Escaping/serialization lives in the output layer that sees every producer. A platform-specific patch for a cross-platform bug is the wrong layer. A downstream null-check or isDead() probe on a possibly-freed object is papering over the defect. Don't take a bug report's suggested fix at face value — verify it's the right layer. Prove the mechanism, don't correlate: "the crash goes away" is not a root cause — reproduce the hypothesized path and be able to explain why the fix works; a fix you can't explain hides an adjacent unhandled case. Before changing anything shared, enumerate every consumer first — crash handlers, --watch restore paths, workers, and the WebSocket client share infrastructure; prefer scoping the change to your one caller via an explicit flag. Never change a Bun-native default to fix Node compatibility — that fix belongs in the node: compat layer.
- **One implementation, in the right place.** Never copy a helper or constant table between modules or between the read and write sides of a format — move to a shared module, or derive mirrored lists from the existing source of truth. When adding a variant of existing behavior, parameterize the existing path rather than cloning a parallel branch; when your change supersedes a mechanism, delete the old path in the same PR — the unfixed twin silently misses every future fix. Place new code in the module that owns the feature, never god files (no new fields on ZigGlobalObject, no bindings in monolithic bindings.cpp). Substantial subsystems get their own globally-unique filename (unique names make CMD+F work). No re-export shim files.
- **One implementation, in the right place.** Never copy a helper or constant table between modules or between the read and write sides of a format — move to a shared module, or derive mirrored lists from the existing source of truth. When adding a variant of existing behavior, parameterize the existing path rather than cloning a parallel branch; when your change supersedes a mechanism, delete the old path in the same PR — the unfixed twin silently misses every future fix. Place new code in the module that owns the feature, never god files (no new fields on BunGlobalObject, no bindings in monolithic bindings.cpp). Substantial subsystems get their own globally-unique filename (unique names make CMD+F work). No re-export shim files.
- **Store state on the object whose lifetime matches it.** Per-VM state goes on VirtualMachine/RareData, never process globals or thread-locals (workers share globals; pool threads are reused — a "per-thread" lazy buffer leaks under churn). Per-connection facts live on the socket, never a shared context ("last writer wins" under concurrency was an intermittent TLS race). Reset per-operation state at the start of each use of a reusable object (a flag "only ever set and never reset" made reused HTTP clients skip chunked framing — invisible to single-shot tests). Update every lifecycle method (reset/init/drop/clone) when adding mutable state. Prune bookkeeping keyed by recyclable identifiers (PIDs, fds) on every path that learns of death — stale PID + reuse meant SIGSTOPing an unrelated process. Capture absolute paths at acquisition (cwd changes before cleanup). Don't add fields mirroring recoverable information — compute from the source of truth at use.
- **Use the simplest mechanism the invariants allow.** No vtables when the implementation set is closed at compile time; no bit-packing or lock-free tricks when a stated invariant makes plain code correct; no speculative edge-case handling nobody filed an issue for ("let's wait for someone to file an issue before we add more complexity"). When a heuristic keeps sprouting counterexamples in review, redesign structurally instead of adding tie-breakers. Treat reviewer confusion as a simplification signal: if a maintainer doesn't understand your logic after one explanation, delete or simplify rather than writing a longer justification. New cross-cutting abstractions need maintainer agreement before appearing inside a feature PR.

Expand Down
2 changes: 1 addition & 1 deletion scripts/build/codegen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -993,7 +993,7 @@ function emitObjectLuts({ n, cfg, o, dirStamp }: Ctx): void {
// GENERATED by emitGeneratedClasses, so it's in codegenDir not src/.
const pairs: [src: string, out: string][] = [
[resolve(cfg.cwd, "src/jsc/bindings/BunObject.cpp"), resolve(cfg.codegenDir, "BunObject.lut.h")],
[resolve(cfg.cwd, "src/jsc/bindings/ZigGlobalObject.lut.txt"), resolve(cfg.codegenDir, "ZigGlobalObject.lut.h")],
[resolve(cfg.cwd, "src/jsc/bindings/BunGlobalObject.lut.txt"), resolve(cfg.codegenDir, "BunGlobalObject.lut.h")],
[resolve(cfg.cwd, "src/jsc/bindings/JSBuffer.cpp"), resolve(cfg.codegenDir, "JSBuffer.lut.h")],
[resolve(cfg.cwd, "src/jsc/bindings/BunProcess.cpp"), resolve(cfg.codegenDir, "BunProcess.lut.h")],
[
Expand Down
2 changes: 1 addition & 1 deletion scripts/build/unified.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ import { slash } from "./shell.ts";
const noUnify: readonly string[] = [
// Heavy single-file TUs that already saturate a core. Bundling them with
// siblings would serialize work that should run in parallel.
"src/jsc/bindings/ZigGlobalObject.cpp",
"src/jsc/bindings/BunGlobalObject.cpp",
"src/jsc/bindings/BunObject.cpp",
"src/jsc/bindings/bindings.cpp",
"src/jsc/bindings/BunProcess.cpp",
Expand Down
10 changes: 5 additions & 5 deletions src/ast_jsc/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,19 @@ use bun_core::ZigString;
use bun_jsc::{self as jsc, BuildMessage, JSGlobalObject, JSValue, JsResult, ResolveMessage};

pub fn msg_from_js(global_object: &JSGlobalObject, file: Vec<u8>, err: JSValue) -> JsResult<Msg> {
let mut zig_exception_holder = jsc::zig_exception::Holder::init();
let mut bun_exception_holder = jsc::bun_exception::Holder::init();

if let Some(value) = err.to_error() {
value.to_zig_exception(global_object, zig_exception_holder.zig_exception());
value.to_bun_exception(global_object, bun_exception_holder.bun_exception());
} else {
zig_exception_holder.zig_exception().message = err.to_bun_string(global_object)?;
bun_exception_holder.bun_exception().message = err.to_bun_string(global_object)?;
}

Ok(Msg {
data: Data {
text: Cow::Owned(
zig_exception_holder
.zig_exception()
bun_exception_holder
.bun_exception()
.message
.to_owned_slice(),
),
Expand Down
10 changes: 5 additions & 5 deletions src/bun_bin/phase_c_exports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -244,11 +244,11 @@ pub(crate) extern "C" fn Bun__VM__scriptExecutionStatus(_vm: *const VirtualMachi

// ── bundler analyze ─────────────────────────────────────────────────────────
// REAL: src/bundler/analyze_transpiled_module.rs
// zig__ModuleInfoDeserialized__deinit
// bun__ModuleInfoDeserialized__deinit

// REAL: src/bundler_jsc/analyze_jsc.rs
// zig__ModuleInfoDeserialized__toJSModuleRecord
// zig__renderDiff
// bun__ModuleInfoDeserialized__toJSModuleRecord
// bun__renderDiff

// ════════════════════════════════════════════════════════════════════════════
// Genuinely unimplemented — no C++ body. Kept so the
Expand Down Expand Up @@ -292,5 +292,5 @@ pub(crate) extern "C" fn DNSResolver__getConstructor(_global: *mut JSGlobalObjec
unreachable!("DNSResolver has no JS-visible constructor (no `construct` in .classes.ts)")
}

// (zig__renderDiff now defined in src/runtime/test_runner/diff_format.rs.)
// (zig__ModuleInfoDeserialized__toJSModuleRecord now defined in src/bundler_jsc/analyze_jsc.rs.)
// (bun__renderDiff now defined in src/runtime/test_runner/diff_format.rs.)
// (bun__ModuleInfoDeserialized__toJSModuleRecord now defined in src/bundler_jsc/analyze_jsc.rs.)
2 changes: 1 addition & 1 deletion src/bun_core/string/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1453,7 +1453,7 @@ impl ZigString {
pub fn dupe_for_js(utf8: &[u8]) -> Result<ZigString, strings::ToUTF16Error> {
if let Some(utf16) = strings::to_utf16_alloc(utf8, false, false)? {
// Ownership transferred to JSC: `mark_global()` tags the buffer so
// `Zig::toString*` adopts it into a WTF string and `mi_free`s it on
// `Bun::toString*` adopts it into a WTF string and `mi_free`s it on
// string death. `heap::release` is the hand-off-to-foreign-owner
// spelling.
let leaked: &'static mut [u16] = crate::heap::release(utf16.into_boxed_slice());
Expand Down
6 changes: 3 additions & 3 deletions src/bundler/analyze_transpiled_module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -520,19 +520,19 @@ impl ModuleInfoExt for ModuleInfo {
}
}

// zig__renderDiff, zig__ModuleInfoDeserialized__toJSModuleRecord, and the
// bun__renderDiff, bun__ModuleInfoDeserialized__toJSModuleRecord, and the
// JSModuleRecord/IdentifierArray opaques: see bun_bundler_jsc::analyze_jsc

#[unsafe(no_mangle)]
pub(crate) extern "C" fn zig__ModuleInfo__destroy(info: *mut ModuleInfo) {
pub(crate) extern "C" fn bun__ModuleInfo__destroy(info: *mut ModuleInfo) {
// SAFETY: C++ caller passes a non-null pointer obtained from `ModuleInfo::create`.
let info = unsafe { NonNull::new(info).unwrap_unchecked() };
// SAFETY: `info` came from `bun_core::heap::into_raw` and ownership is transferred back here.
drop(unsafe { bun_core::heap::take(info.as_ptr()) });
}

#[unsafe(no_mangle)]
pub(crate) extern "C" fn zig__ModuleInfoDeserialized__deinit(info: *mut ModuleInfoDeserialized) {
pub(crate) extern "C" fn bun__ModuleInfoDeserialized__deinit(info: *mut ModuleInfoDeserialized) {
// SAFETY: C++ caller passes a non-null pointer obtained from `create` or
// `ModuleInfoExt::into_deserialized`.
let info = unsafe { NonNull::new(info).unwrap_unchecked() };
Expand Down
4 changes: 2 additions & 2 deletions src/bundler_jsc/analyze_jsc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//! `ModuleInfoDeserialized` into a `JSC::JSModuleRecord`. Aliased back so the
//! `extern "C"` symbol names are still discoverable from C++.
//!
//! Note: the `zig__renderDiff` export lives in
//! Note: the `bun__renderDiff` export lives in
//! `bun_runtime::test_runner::diff_format` instead — `DiffFormatter` is a
//! higher-tier type this crate cannot depend on, and the C++ caller only needs
//! the symbol at link time, not a particular crate.
Expand All @@ -13,7 +13,7 @@ use analyze::{ModuleInfoDeserialized, RecordKind, RequestedModuleValue, StringID
use bun_bundler::analyze_transpiled_module as analyze;

#[unsafe(no_mangle)]
pub(crate) extern "C" fn zig__ModuleInfoDeserialized__toJSModuleRecord(
pub(crate) extern "C" fn bun__ModuleInfoDeserialized__toJSModuleRecord(
global_object: &JSGlobalObject,
vm: &VM,
module_key: &IdentifierArray,
Expand Down
12 changes: 6 additions & 6 deletions src/codegen/bundle-functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -440,7 +440,7 @@ export async function bundleBuiltinFunctions({ requireTransformer }: BundleBuilt

// C++ codegen
let bundledCPP = `// Generated by ${import.meta.path}
namespace Zig { class GlobalObject; }
namespace Bun { class GlobalObject; }
#include "root.h"
#include "config.h"
#include "JSDOMGlobalObject.h"
Expand Down Expand Up @@ -556,7 +556,7 @@ JSBuiltinInternalFunctions::JSBuiltinInternalFunctions(JSC::VM& vm) : m_vm(vm)
}

bundledCPP += `
SUPPRESS_ASAN void JSBuiltinInternalFunctions::initialize(Zig::GlobalObject& globalObject)
SUPPRESS_ASAN void JSBuiltinInternalFunctions::initialize(Bun::GlobalObject& globalObject)
{
UNUSED_PARAM(globalObject);
`;
Expand All @@ -569,13 +569,13 @@ JSBuiltinInternalFunctions::JSBuiltinInternalFunctions(JSC::VM& vm) : m_vm(vm)

bundledCPP += `
JSVMClientData& clientData = *static_cast<JSVMClientData*>(m_vm.clientData);
Zig::GlobalObject::GlobalPropertyInfo staticGlobals[] = {
Bun::GlobalObject::GlobalPropertyInfo staticGlobals[] = {
`;

for (const { basename, internal } of files) {
if (internal) {
bundledCPP += `#define DECLARE_GLOBAL_STATIC(name) \\
Zig::GlobalObject::GlobalPropertyInfo( \\
Bun::GlobalObject::GlobalPropertyInfo( \\
clientData.builtinFunctions().${low(basename)}Builtins().name##PrivateName(), ${low(basename)}().m_##name##Function.get() , JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly),
WEBCORE_FOREACH_${basename.toUpperCase()}_BUILTIN_FUNCTION_NAME(DECLARE_GLOBAL_STATIC)
#undef DECLARE_GLOBAL_STATIC
Expand All @@ -596,7 +596,7 @@ JSBuiltinInternalFunctions::JSBuiltinInternalFunctions(JSC::VM& vm) : m_vm(vm)
let bundledHeader = `// Generated by ${import.meta.path}
// Do not edit by hand.
#pragma once
namespace Zig { class GlobalObject; }
namespace Bun { class GlobalObject; }
#include "root.h"
#include <JavaScriptCore/BuiltinUtils.h>
#include <JavaScriptCore/Identifier.h>
Expand Down Expand Up @@ -768,7 +768,7 @@ JSBuiltinInternalFunctions::JSBuiltinInternalFunctions(JSC::VM& vm) : m_vm(vm)
explicit JSBuiltinInternalFunctions(JSC::VM&);

template<typename Visitor> void visit(Visitor&);
void initialize(Zig::GlobalObject&);
void initialize(Bun::GlobalObject&);
`;

for (const { basename, internal } of files) {
Expand Down
8 changes: 4 additions & 4 deletions src/codegen/cppbind.ts
Original file line number Diff line number Diff line change
Expand Up @@ -454,8 +454,8 @@ const rustSharedTypes: Record<string, string> = {
"JSC::EncodedJSValue": "crate::JSValue",
"EncodedJSValue": "crate::JSValue",
"JSC::JSGlobalObject": "crate::JSGlobalObject",
"Zig::GlobalObject": "crate::JSGlobalObject",
"ZigException": "crate::zig_exception::ZigException",
"Bun::GlobalObject": "crate::JSGlobalObject",
"BunException": "crate::bun_exception::BunException",
"ZigString": "bun_core::ZigString",
"JSC::VM": "crate::VM",
"JSC::JSPromise": "crate::JSPromise",
Expand Down Expand Up @@ -574,7 +574,7 @@ function isGlobalObjectPtr(t: CppType): boolean {
return (
t.type === "pointer" &&
t.child.type === "named" &&
(t.child.name === "JSC::JSGlobalObject" || t.child.name === "Zig::GlobalObject")
(t.child.name === "JSC::JSGlobalObject" || t.child.name === "Bun::GlobalObject")
);
}

Expand All @@ -586,7 +586,7 @@ function isGlobalObjectPtr(t: CppType): boolean {
// `JSGlobalObject*` → `&JSGlobalObject` rule.
const rustOpaqueHandles = new Set([
"JSC::JSGlobalObject",
"Zig::GlobalObject",
"Bun::GlobalObject",
"JSC::VM",
"JSC::JSPromise",
"JSC::JSInternalPromise",
Expand Down
Loading
Loading