oven-sh/bun
Three flows walked end to end. Startup (`bun foo.ts`): C runtime → `main` → allocator/crash/stdio init → `Cli::start` → `Command::start` → fast-path detection of a run entrypoint → `init` → `RunCommand::exec_with_cfg` → `boot` → `VirtualMachine::init_with_module_graph` → `Run::start` → `load_entry_point` → event-loop drain → `on_before_exit`. Install: `Tag::InstallCommand` → `InstallCommand::exec` → `PackageManager::init` → `install_with_manager` → lockfile load → resolution → task run → scanner → installer → lifecycle scripts → `save_lockfile`. Serve/dev: `Bun.serve` constructs a monomorphized `NewServer`, uWS delivers a request into `RequestContext`, and under Bake the DevServer checks the Host header, resolves a route through `FrameworkRouter`, incrementally bundles, and pushes HMR events over a WebSocket.
- Startup step 0 is argv capture (`bun_core::init_argv`) explicitly before `bun_crash_handler::init()`, because the crash handler's panic path prints the command line from `bun_core::argv()`.
- On Linux, `main()` calls `pregrow_fd_table()` — a `dup_at_least(stdin, 1023)` followed by `close` — before any thread exists, because `expand_fdtable()` waits for an RCU grace period once the process is multi-threaded.
- `Cli::start` sets the main-thread id for crash reporting, records the start time, initializes a process-lifetime `Log` and a `CLI_ARENA` mimalloc arena via `RacyCell` (sound because it runs single-threaded), then calls `Command::start(log)` and routes any error through `handle_root_error` after printing accumulated diagnostics.
- `Command::start` short-circuits: if `argv[1]` `looks_like_run_entrypoint`, it jumps straight to `exec_auto_or_run(Tag::AutoCommand)` without decoding the subcommand keyword table at all, and only otherwise calls `which()` to classify.
- `RunCommand::boot` calls `VirtualMachine::init_with_module_graph`, then moves preloads and passthrough argv onto the VM, leaks the entry path to `'static` (because `vm.main` is a backref and the runner never returns), wires the transpiler from the context, calls `configure_defines()`, and loads env into the HTTP client before constructing `Run` and calling `.start()`.
- `Run::start` takes the JSC API lock and never drops it (the function is `-> !`), then in order: enables CPU/heap profilers, adds conditional globals (`Bun__ExposeNodeModuleGlobals` for `--eval`, `addGc` for `--expose-gc`), performs optional Redis and SQL preconnects under the lock, enables the hot/watch reloader, and only then loads the entry point.
- After the entry graph evaluates, `Run::start` runs one opportunistic `release_weak_refs()` + `run_gc(false)` to drop transpiler garbage — but skips it for standalone executables, whose code blocks came from an embedded bytecode cache and would only need re-decoding.
- The core run-loop has two shapes: under `--watch`/`--hot` it loops forever (`tick` → `auto_tick_active` → `on_before_exit` → `tick_possibly_forever`) so a rejected entry keeps the process alive; otherwise it drains until the loop is no longer alive, optionally prints the entry result for `--print`, and calls `on_before_exit` once.
- For `--print` with a pending top-level promise, the runner attaches `Bun__onResolveEntryPointResult`/`Bun__onRejectEntryPointResult` (C-ABI shims emitted by `generate-host-exports.ts`), re-drains the loop, and then prints through `ConsoleObject::message_with_type_and_level`.
- `bun install` begins by prefetching DNS for the default registry — but only when there is no HTTP proxy, the mode is not offline, and the registry hostname is not already an IP address.
- Lockfile loading uses a single raw-pointer provenance root with an explicit SAFETY note, because `load_from_cwd` needs `manager`, `manager.lockfile`, and `manager.log` borrowed simultaneously and borrowck cannot express the disjointness.
- The install path decides whether to force a lockfile rewrite by OR-ing four conditions — an explicit force flag, a changed config version, a migration from another package manager, and a binary lockfile encountered while `save-text-lockfile` is set.
- Standalone-executable boot forces lazy argv init before reading `bun_options_argc()`, temporarily narrows `bun.argv` to executable + parsed options so user flags like `--version` are not intercepted by Bun's own parser, restores full argv, then computes the passthrough offset and calls `RunCommand::boot_standalone`.
- The dev server gates every request on `is_allowed_host_header`, which accepts a missing-Host request never, then allows `localhost`, any `*.localhost` suffix, any bare IP literal (after stripping IPv6 brackets), or an exact case-insensitive match against the configured bind hostname — a DNS-rebinding guard on the local dev origin.