Conversation
…wo Rust helpers Link-level reachability over the debug objects found functions that nothing reaches: the toWrapped() statics of 17 wrapper classes, the reference taking toJS() overloads of 11 types, unused DeferredPromise and DOMPromise entry points, unused Event and ErrorEvent constructors, and a number of single leaf functions. Header-only items (per-name accessors in HTTPHeaderIdentifiers and MarkdownTagStrings, the Set variant of JSDOMIterator, FetchHeaders guard helpers, two common strings) and the unused construct() method that generate-jssink.ts emitted for every sink are removed as well.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (73)
💤 Files with no reviewable changes (67)
Included review availability: 4 reviews are currently available. Your included PR review attempts over the past 7 days set your current allowance at 5 reviews per hour. WalkthroughChangesThe PR removes obsolete generated and WebCore binding APIs. It narrows wrapper conversions to newly created objects, simplifies iterator and promise APIs, removes event-listener metadata, and adds constructor and FormData iteration tests. Binding API cleanup
Suggested reviewers: Merge Risk: ⚪ Minimal · up to This PR removes unreachable binding, code-generation, and Rust helpers while preserving the tested behavior; no actionable merge-blocking risk remains beyond normal focused test checks. 🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
Full details: Description checkExplanation The description explains the problem, lists the removed code, documents intentional exclusions, and provides detailed build, test, platform, formatting, and reference-search verification. It does not use the exact template headings, but it includes all required information. Comment |
These pin the surfaces that the edited sink codegen and JSDOMIterator.h serve: the generated constructor's name, length, call and construct behaviour, and the Map style entries(), keys(), values() and forEach() of FormData.
|
Updated 12:15 AM PT - Aug 25th, 2026
✅ @alii, your commit 1d35ff50a08767b6319e33da3537b86b75084e1d passed in 🧪 To try this PR locally: bunx bun-pr 39929That installs a local version of the PR into your bun-39929 --bun |
…ner accessors With wasCreatedFromMarkup() gone, m_wasCreatedFromMarkup was only ever written. Drop the field, the CreatedFromMarkup enum, the constructor parameter, and the two call sites that passed CreatedFromMarkup::No.
#39618 removes the rest of the DOMPromise class. Deleting this last member here would leave the two pull requests fighting over JSDOMPromise.h, and the header and JSDOMPromise.cpp can be deleted together once both have landed.
…ns left behind With the Set iterator gone, JSDOMIteratorType has one value and EnableIfMap is always true. Drop both, the type member of the four traits structs, and the <type_traits> include. The removed ErrorEvent constructors were the only users of Strong.h, StrongInlines.h and EventNames.h in ErrorEvent.h and ErrorEvent.cpp.
There was a problem hiding this comment.
I re-reviewed after 82d96bf / 59b6a89 / c31c835 — the three follow-ups I asked for (the m_wasCreatedFromMarkup chain, the JSDOMIteratorType/EnableIfMap scaffolding, and the orphaned ErrorEvent includes) are all done, and this pass found no new issues. Given the scope (73 files across the WebCore/JSC bindings, plus the JSDOMIterator template rework and the jssink codegen edit), a human sign-off is still worthwhile. One doc nit: the description still lists DOMPromise::whenPromiseIsSettled() / JSDOMPromise.cpp as deleted, but 59b6a89 kept it.
What was reviewed:
- Spot-checked that removed
toWrapped/toJS(T&)overloads have no remaining callers and thatIDLInterface<T>conversions for these types aren't instantiated. - Verified the
JSDOMIterator.hde-templating keepsasJS/appendForEachArgumentssemantics for the four Map-style traits; new FormData iteration tests cover it. - Confirmed
PathSeparators::POSIXremoval leavesfrom_u8(2) → Posixand all enum-variant match arms intact. - Confirmed
HTTPHeaderIdentifiers::Indexis still referenced (Index::Count,Index::Authoritystatic_asserts) after the accessor macro removal.
Extended reasoning...
Overview
Dead-code removal across 73 files: 17 toWrapped() statics, 11 toJS(..., T&) overloads, unused Event/ErrorEvent/CustomEvent constructors, four DeferredPromise::reject overloads plus promise(), header-only accessor macros (HTTPHeaderIdentifiers, MarkdownTagStrings), the Set half of JSDOMIterator's SFINAE dispatch (then, per my earlier comment, the whole dispatch), the per-sink ::construct in generate-jssink.ts, two BunCommonStrings entries, FetchHeaders guard accessors + EnumTraits, JSEventListener::functionName/wasCreatedFromMarkup and its plumbing, and two Rust items (PluginRunner::could_be_plugin re-export, PathSeparators::POSIX). Two new test blocks pin the surfaces that were edited rather than only pruned.
Security risks
None. Pure deletions of unreferenced symbols; no new inputs, no changed validation, no auth/crypto surface.
Level of scrutiny
Medium-high. Each individual deletion is mechanical and self-verifying (declaration removed with definition → any missed caller fails to compile, not link), and the methodology (link-level reachability rooted at Rust/WebKit/export lists, then rg re-check) is sound. But the aggregate touches ~70 core-binding files, includes a small template refactor in JSDOMIterator.h used by four iterator types, and edits a codegen script. That's beyond what I'd auto-approve.
Other factors
- All three of my prior inline findings were addressed in 82d96bf and c31c835; threads are resolved.
- 59b6a89 reverted the
whenPromiseIsSettleddeletion but the PR description still lists it as removed — worth syncing before merge. - The PR notes overlap with six open dead-code PRs (esp. #39618, which also deletes
JSErrorHandler.cpp); whichever lands second needs a rebase, so a maintainer should sequence these. - CI build #102577 was still building at last timeline update; result not yet visible here.
- The two candidate issues raised and refuted this run (stale
could_be_pluginmention in thePluginRunner.rsmodule doc) are cosmetic — the doc line still accurately describes where the helper lives.
|
The description is already in sync with 59b6a89: the symbol list no longer includes |
|
Status: ready for review at c31c835. CI (build 102577) builds on every platform and passes on 177 of 179 jobs. The two red jobs are not related to this change and are reported separately: Because this PR only deletes unreachable code, the new tests pass before and after the change by design; they pin the two surfaces whose code was edited (the sink constructor and FormData iteration). The evidence that the removed functions are unreachable is in the description. Sequencing: #39618 edits ten of these files in other places and deletes JSErrorHandler.cpp, so whichever of the two lands second needs a small rebase. |
|
Binary size impact? |
|
Note GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer. |
…sc JSC bindings (#40413) ### Problem - Four Rust host exports have no C++ caller: `Bun__WebSocketClient__writeBlob`, `Bun__WebSocketClientTLS__writeBlob`, `Bun__WebSocketClientTLS__initWithTunnel`, and `Bun__internal_drainTimers`. `WebSocket.cpp` converts a Blob to bytes itself and calls `writeBinaryData`, and the tunnel path only creates the non-TLS client. The `HOST_EXPORT` marker roots each of them, so neither rustc nor hawk can see that they are dead. - A handful of C++ methods are declared and defined but never called: `HTTPParser::lessThan`, one `JSNodePerformanceHooksHistogram::create` overload, `JSAbortAlgorithm::callbackData` and `toJS(AbortAlgorithm&)`, `JSPerformance::toWrapped`, `JSCStackFrame::typeName`, `root(CryptoKey*)`, the `String` overload of `throwNodeRangeError`, and 16 ncrypto helpers. - Two `pub` Rust items have no caller in any crate: `bun_base64::simdutf_encode_url_safe_alloc` and `CowSliceZ::init_unchecked`. ### Fix - Delete the items above. `WebSocketClient::write_blob` goes with its exports. `encode_append_impl` folds into `encode_append`, its only remaining caller. The ncrypto `Ec` class keeps its one live member, `GetCurveIdFromName`. - Every deletion is confirmed two ways: `rg` over `src/`, `build/debug/codegen/`, `src/codegen/`, `packages/`, and `vendor/WebKit` finds no reference, and a `bun-debug` relink with `--gc-sections --print-gc-sections` discards each symbol. `host_fn_this_value` and `root(MessagePort*)` looked the same way and stay: codegen emits the first, and #39841 is editing `MessagePort.cpp`, so the second waits for that fix to land. - New source lint `test/internal/source-lints/host-export-callers.test.ts`: every `c`/`jsc` `HOST_EXPORT` marker must be named by a C or C++ source. It fails on main with exactly the four exports above and passes here. - Verified: `bun bd` builds, `bun run rust:check-all` passes on all 12 targets, `clang-format` and `cargo fmt` are clean. Ran `test/js/web/websocket/` (blob, client, bidir proxy), `test/js/node/crypto/` (crypto, ecdh, hmac, sign, x509), `node-http`, `node-http-parser`, `perf_hooks`, and `abort`. ### Background - `// HOST_EXPORT(Name, c)` marks a Rust fn that `src/codegen/generate-host-exports.ts` wraps in an `extern "C"` thunk for C++. The thunk exists whether or not C++ calls it, so an orphaned export compiles without a warning. - ncrypto (`src/jsc/bindings/ncrypto.{cpp,h}`) is Bun's copy of Node's OpenSSL helper layer. Node still uses the removed helpers; Bun's callers never did. - The linker check: a debug link with `-Wl,--gc-sections -Wl,--print-gc-sections` lists every function section nothing references. A function that is discarded and also absent from the linked binary has no caller on that platform. Platform-gated code then needs a source check, which is why the darwin-only `Bun__noOrphans_*` and the Windows-only `windowsEnv` builtin stay. <details><summary>Notes</summary> Removed, by file: - `src/http_jsc/websocket_client.rs`: `bun__websocketclient__write_blob`, `bun__websocketclienttls__write_blob`, `bun__websocketclienttls__init_with_tunnel`, `WebSocketClient::write_blob`, and the now unused `JSValue` import. - `src/runtime/timer/Timer.rs`: `drain_timers_export` (`Bun__internal_drainTimers`). - `src/base64/lib.rs`: `simdutf_encode_url_safe_alloc`; `encode_append_impl` folded into `encode_append`. - `src/ptr/CowSlice.rs`: `CowSliceZ::init_unchecked`. - `src/jsc/bindings/node/http/NodeHTTPParser.{cpp,h}`: `HTTPParser::lessThan`. - `src/jsc/bindings/JSNodePerformanceHooksHistogram.{cpp,h}`: `create(VM&, Structure*, JSGlobalObject*, HistogramData&&)`. - `src/jsc/bindings/webcore/JSAbortAlgorithm.{cpp,h}`: `callbackData()`, `toJS(AbortAlgorithm&)`, `toJS(AbortAlgorithm*)`. - `src/jsc/bindings/webcore/JSPerformance.{cpp,h}`: `JSPerformance::toWrapped`. - `src/jsc/bindings/ErrorStackTrace.{cpp,h}`: `JSCStackFrame::typeName`, `retrieveTypeName`, `m_typeName`. - `src/jsc/bindings/webcrypto/CryptoKey.{cpp,h}`: `root(CryptoKey*)` and the `WebCoreOpaqueRoot` forward declaration and include it needed. - `src/jsc/bindings/webcore/JSDOMOperation.{cpp,h}`: `throwNodeRangeError(JSGlobalObject*, ThrowScope&, const String&)`; every caller passes an `ASCIILiteral`. - `src/jsc/bindings/ncrypto.{cpp,h}`: `CryptoErrorList::add`, `CryptoErrorList::pop_front`, `BignumPointer::encode`, `BignumPointer::encodeInto`, `X509View::clone`, `BIOPointer::New(const BIO_METHOD*)`, `BIOPointer::Write`, `EVPKeyPointer::bits`, `Cipher::EMPTY`, `ECKeyPointer::New(const EC_GROUP*)`, `EVPKeyCtxPointer::derive`, `HMACCtxPointer::digest`, `Ec::Ec()`, `Ec::Ec(const EC_KEY*)`, `Ec::getGroup`, and the `Ec` conversion operators and field. Scan summary for this run. Areas: Rust in `src/runtime`, `src/http_jsc`, `src/bun_core`, `src/base64`, `src/ptr`, and the JSC bindings outside the files that open dead-code PRs (#39929, #40232, #40367, #40294, #40172, #40122) already touch; the TS builtins in `src/js`. - hawk over `x86_64-unknown-linux-gnu`, `x86_64-pc-windows-msvc`, `aarch64-apple-darwin` (release profile, per `hawk.toml`): 847 `dead_public` findings. 668 are fields of FFI mirror structs (`libuv.rs`, `windows_sys/externs.rs`, `boringssl.rs`). Most of the rest are in files the open PRs own, are debug-only (`has_resolve_breakpoint`, `StoredTrace::capture`, `ArrayHashMap::unlock_pointers`), are codegen targets (`host_fn_this_value`), or are FFI enum mirrors (`tty::Mode::Io`, `ImplementationVisibility`). - oxlint with `no-unused-vars`, `no-unused-private-class-members`, `no-unreachable` over `src/js`: 0 findings. No `src/js` file is unimported. No `.rs` file is outside a `mod` tree except the three `[[bench]]` targets. - `--gc-sections` relink of `bun-debug`: 1005 non-generated discarded symbols, 283 of them in files no open PR touches. After removing sqlite3.c, llhttp, vendored shims, platform-gated code, and generated `ZigGeneratedClasses` helpers, the list above is what remains. Possibly dead, left alone: - `bun_core::strings::split_once` / `rsplit_once`: no caller today, but `clippy.toml` names them as the replacement for the denied `str::split_once` / `bstr::split_once_str` forms. Kept as API surface. - `src/jsc/bindings/webcore/streams/JSCrossRealmTransformState.{cpp,h}` (135 lines): the `CrossRealm` source and sink kinds in `StreamsForward.h` are never constructed. It reads as scaffolding for stream transfer in the native streams work, so it stays. - `ECDSASigPointer`, `ECGroupPointer`, `ECPointPointer`, `HMACCtxPointer`: default constructor, move constructor, and `release()` are unreferenced, but they are the smart-pointer idiom the rest of ncrypto follows. - `src/threading/Futex.rs` `wasm_impl` and `unsupported_impl`: no shipped target compiles them. - `bun_core::Global::StoredTrace::{EMPTY, capture}`, `has_resolve_breakpoint`, `ArrayHashMap::unlock_pointers`, `TaskTag::name`: release-dead, used under `debug_assertions`. </details>
|
@robobun binary size impact? |
|
Binary size impact: none on the shipped binary. Release builds (linux x64,
The only shrinkage is DWARF ( Why zero: the release link already dead-strips unreferenced functions ( |
…her crates (#40610) ### Problem - The workspace denies `dead_code` and `unreachable_pub`, and earlier sweeps removed the `pub` items a cross-crate analysis can see. What is left is code no lint reports: branches behind constant conditions, `pub` enum variants that nothing constructs, `pub` struct fields that nothing reads, and commented-out code. - The largest case is the js lexer: `LexerType` carried seven const generic parameters for a JSON mode (`IS_JSON`, `ALLOW_COMMENTS`, ...) that no caller ever set. The only instantiation is the default one, so every `if IS_JSON` body in `src/js_parser/lexer.rs` was unreachable. JSON is parsed by `src/parsers/json.rs`. ### Fix - Delete the items. 83 source files, +221 / -1653. Every candidate was checked with `rg` over `src/`, `build/debug/codegen/` and `src/codegen/`, including `#[cfg(windows)]` and macOS paths. The Notes list each one. - The lexer becomes a plain `struct Lexer<'a>`: the `JsonOptionsT` trait, the `NewLexer` alias, the `lexer_impl_header!` macro and the `generic_const_exprs` feature gate go with the JSON branches. The only JS-visible change is none: the default instantiation was the only one. - `bun_runtime::Error` loses 85 unit variants that are never built (the X509 codes live in `bun_http::CertError`; `InstallFailed` and friends are only ever nested as `Error::Install(..)`). The `AllocatorVTable` keeps only `free`, the one slot `StdAllocator` dispatches. - New source lint `test/internal/source-lints/literal-bool-condition.test.ts`: a statement-level `if true {` / `if false {` outside `#[cfg(test)]` code fails the lint. rustc and clippy accept both, so the dead `if false { break 'outer; }` in `doStep5.rs` and the always-taken `if true {` block in `Watcher.rs` (unwrapped here) had no other guard. The lint fails on `main` with those two lines and passes with this PR. - Verified: `bun bd`, `bun run rust:check-all` (12 targets), `cargo clippy --workspace`, `cargo check --workspace --tests`, `cargo fmt --check`. `bun bd test` on transpiler, bundler edge cases, shell, yaml, zstd, transpiler cache, `Bun.write`, `Bun.file`, sourcemap, resolver cache, WebSocket client, `bun add`/`bun remove`, lockfile sync, archive, `bun:test`, `--watch`, and the source lints (about 2,700 tests, 0 failures attributable to this change; see Notes). ### Background - `dead_code` does not report a `pub` item, a trait impl, an enum variant that a `match` arm names, or a field that a compound assignment (`+=`) touches. Each of those counts as a use to rustc even when nothing reads the result. - A `const bool` that is the same in every build (`const ALLOW_TMPFILE: bool = false`, a trait const no impl overrides, a const generic no caller sets) makes one side of its `if` unreachable, but rustc still type-checks and keeps that side. The removed branches are all of this kind. Flags that vary per build (`IS_WINDOWS`, `IS_DEBUG`, `ENABLE_ASAN`) and the debug toggles (`TRACING`, `VERBOSE_FS`-style logging switches that still have a body) were left alone. - `BunBuiltinNames.h` entries and JS private names can be referenced by string (`$getByIdDirectPrivate(this, "writer")`), so a name with no `$name` hit is not dead. Two such candidates were checked and kept. <details><summary>Notes</summary> Removed, constant conditions: - `src/js_parser/lexer.rs`: the 7 const generic parameters of `LexerType`, the `JsonOptionsT` trait, `DefaultJsonOptions`, the `NewLexer` alias and the `lexer_impl_header!` macro. 30 `if IS_JSON` bodies, `assert_not_json` and its 13 calls, the `is_ascii_only` field (only written in JSON mode), `Error::JSONStringsMustUseDoubleQuotes`, and the `if !FeatureFlags::ALLOW_JSON_SINGLE_QUOTES` block. `src/js_parser/lib.rs` drops `#![feature(adt_const_params, generic_const_exprs)]`, which nothing else in the crate used. - `src/bun_core/feature_flags.rs`: `ENABLE_ENTRY_CACHE` (always true: the "cache disabled" tails of `read_directory_error` and `read_directory_with_iterator` in `src/resolver/lib.rs`), `VERBOSE_FS` (always false: two `prettyln!` blocks in `src/resolver/fs.rs` and the `bstr::BStr` import), `HARDCODE_LOCALHOST_TO_127_0_0_1` (always false: the rewrite in `HTTPContext::connect` and `WebSocketUpgradeClient`), `ALLOW_JSON_SINGLE_QUOTES` (only read by the lexer JSON mode). - `src/sys/tmp.rs`: `ALLOW_TMPFILE = false` with the `O_TMPFILE` open and `linkat` paths and the `using_tmpfile` field. `RuntimeTranspilerCache.rs` always unlinks the tmp name on failure now, which is what the `!using_tmpfile` guard already did. The non-Linux `O::TMPFILE` consts and `linkat_tmpfile` stubs in `src/sys/lib.rs` had no other caller (`src/install/npm.rs` uses them under `cfg(linux)`). - `src/libarchive/lib.rs`: `ArchiveAppender::HAS_APPEND_MUTABLE`, no impl overrides the `false` default. With it: `append_mutable`, the `if A::HAS_APPEND_MUTABLE` block, `Context::all_files`, `EntryMap`, `U64Context` and its two impls, and the `all_files` initializer in `create_command.rs`. - `src/bundler/linker_context/doStep5.rs`: `if false { break 'outer; }` and the label. `src/watcher/Watcher.rs`: an `if true {` block around the "Added to watch list" log, unwrapped. - `src/io/PipeWriter.rs`: `PosixStreamingWriterParent::HAS_ON_READY`, set by both impls (the macro and `Terminal.rs`), read by nothing. Removed, enum variants nothing constructs (each with its `name()` arm and match arms): - `bun_runtime::Error` (`src/runtime/error.rs`): `Panic`, `RequestBodyNotReusable`, `DNSResolveFailed`, `TooManyRedirects`, `ConnectionRefused`, `RedirectURLInvalid`, the 66 X509 verification codes from `UNABLE_TO_GET_ISSUER_CERT` to `UNKNOWN_CERTIFICATE_VERIFICATION_ERROR`, `InstallFailed`, `InvalidPackageJSON`, `PathAlreadyExists`, `InvalidTarget`, `OpenFailed`, `UnableToDecode`, `SocketClosed`, `StackOverflow`, `Test`, `MissingTranspileExtra`, `PluginError`, `Name`, `EscapeCalledTwice`. The or-patterns in `install_command.rs`, `pm_update_package_json.rs` and `jsc_hooks.rs` keep their live alternatives. - `bun_core::strings::BOM::{Utf16Be, Utf32Le, Utf32Be}`: `detect()` only returns `Utf8` and `Utf16Le`. With them: the three byte-pattern consts, the `_ =>` arms in the two `remove_and_convert_*` functions, and the commented-out detection lines. - `bun_shell_parser`: `Token::{Dollar, Eq}` and `TokenTag::{Dollar, Eq}` (the lexer never pushes them), with the `TestToken` mirrors and JSON arms in `src/runtime/shell/shell_body.rs`. - `ShellErr::Todo` (`shell_body.rs`, `Builtin.rs`), `bun_crash_handler::Error::InvalidDebugInfo` (patterns in `crash_handler/lib.rs` and `jsc/btjs.rs`) and the `bun_jsc::Error::InvalidDebugInfo` mirror, `FetchFlags::PrintSourceAndClone` (`ModuleLoader.rs`, arm in `jsc_hooks.rs`), yaml `ParseError::InvalidIndentation` and the `ParseResultError::InvalidIndentation` it alone produced, `bun_sourcemap::Error::Unknown`. Removed, fields nothing reads: - `AllocatorVTable::{alloc, resize, remap}` (`src/bun_alloc/lib.rs`): only `free` is ever dispatched. With them: `NO_ALLOC`/`NO_RESIZE`/`NO_REMAP`, `MimallocAllocator` and its four functions in `basic.rs`, `default_alloc::{malloc_aligned, realloc_aligned}` and `Alignment::to_byte_units`. - `ArgumentsSlice::all` (`src/jsc/CallFrame.rs`), `ParseTask::tree_shaking` (`src/bundler/ParseTask.rs`, 11 writers in `bundle_v2.rs`; the parser reads `topts.tree_shaking`), `JSMeta::entry_point_part_index` (`LinkerGraph.rs`, written in `scanImportsAndExports.rs`), `NetworkSink::high_water_mark` (`streams.rs`, `s3/client.rs`, with the `part_size` locals that fed it), `CopyFile::read_off`, the POSIX `ReadFile::byte_store`, `file_sink::Options::close`, `ZstdReaderArrayList::total_out`, `Cloner::trees_count`. Removed, commented-out code older than six months (blame on the line, or on the Zig line the port copied): - C++: `ImportMetaObject.cpp`, `InspectorHTTPServerAgent.cpp`, `JSDOMExceptionHandling.cpp`, `ncrypto.cpp`, `KeyObject.cpp`, `EventTarget.cpp`, `JSPerformanceEntryCustom.cpp`, `MessageEvent.h` (plus a duplicate `#include "MessagePort.h"`), `Performance.cpp`, `Performance.h`, `PerformanceEntry.cpp`, `PerformanceObserver.cpp`, `PerformanceResourceTiming.cpp`, `WebSocket.cpp`. - Rust: `AstBuilder.rs`, `postProcessCSSChunk.rs`, `postProcessJSChunk.rs`, `crash_handler/lib.rs`, `css/declaration.rs`, `css/selectors/selector.rs`, `css/values/percentage.rs`, `WebSocketUpgradeClient.rs`, `lexer.rs`, `parse_fn.rs`, `visit_expr.rs`, `paths/resolve_path.rs`, `exec_command.rs`, `braces.rs`, `sha_hmac/sha.rs`, `StaticHashMap.rs`, `ffi_body.rs`. - `.classes.ts`: disabled entries in `sql.classes.ts`, `sockets.classes.ts`, `server.classes.ts`, `jest.classes.ts`; a leftover loop in `generate_uv_posix_stubs.ts`. Declaration-only C++: `CryptoKeyOKP::platformExportSpki/platformExportPkcs8`, `JSX509Certificate::getPublicKey`, `KeyPairJobCtx::deinit`, `BunShell`/`ShellError` in `BunObject.h`. Checked and kept: `Terminal::get_slave_fd` (used by `js_bun_spawn_bindings.rs`), `macro(writer)` and `macro(mockedFunction)` in `BunBuiltinNames.h` (`$getByIdDirectPrivate(this, "writer")` in `ConsoleObject.ts`, `BunCommonStrings.h`), css `Segment::Name` and `CssModuleExport::is_referenced` (lightningcss data model), the react_compiler variants and fields that mirror the upstream schema, `Mode::ProductionDynamic` (bake scaffolding), the MySQL protocol fields that mirror the wire format, the debug toggles `LOG_ALLOCATIONS`, `DISABLE_COMPRESSION_IN_HTTP_CLIENT`, crash handler `ENABLE`, `ENABLE_AUTO_CORK`/`ENABLE_ALLOCATOR_POOL`, and the wasm scaffolding behind `IS_WASM`/`IS_BROWSER`. Test runs: `test/js/web/fetch/fetch.test.ts` fails the same 26 tests with the released `bun` in this container (root user, no network). `Bun.write > copyFileRange is not available > on large files` hits its 5 s timeout under the ASAN debug build while filling a 256 MB buffer in JS; the copy itself takes 0.6 s and the hash matches. This PR repeats no deletion of the open dead-code PRs (#39929, #40122, #40172, #40232, #40294, #40367, #40492, #40525, #40557), checked by diffing the removed lines. Three files are shared with them in other regions (`src/install/lockfile/Package.rs`, `src/runtime/cli/create_command.rs`, `src/runtime/jsc_hooks.rs`). </details> <!-- robobun:evidence:begin --> --- **[review]** gate passed · iteration 2 · 84 files touched <details><summary>fails on main (without fix)</summary> ```console ASAN without fix: BUILD FAILED (no junit output) $ BUN_DEBUG_QUIET_LOGS=1 bun scripts/build.ts --profile=debug --quiet test "--reporter=junit" "--reporter-outfile=/tmp/mechgate.xml" test/internal/source-lints/literal-bool-condition.test.ts ninja: Entering directory `/workspace/bun/build/debug' [1/166] gen generated_host_exports.rs generated_host_exports.rs: 122 exports (host=5, lazy=10, generic=107, rust=0); 243 extern-C blocks audited [2/166] gen ZigGeneratedClasses.{cpp,h,rs} Found 2 classes from /workspace/bun/src/jsc/resolve_message.classes.ts - ResolveMessage (15 fields) - BuildMessage (10 fields) Found 1 classes from /workspace/bun/src/runtime/api/Archive.classes.ts - Archive (4 fields, 1 class fields) Found 2 classes from /workspace/bun/src/runtime/api/BunObject.classes.ts - ResourceUsage (8 fields) - Subprocess (20 fields) Found 1 classes from /workspace/bun/src/runtime/api/cron.classes.ts - CronJob (5 fields) Found 3 classes from /workspace/bun/src/runtime/api/filesystem_router.classes.ts - FileSystemRouter (5 fields) - FrameworkFileSystemRouter (2 fields) - MatchedRoute (8 fields) Found 1 classes from /workspace/bun/src/runtime/api/Glob.classes.ts - Glob (5 fields) Found 1 classes fro ... (truncated) release without fix: 1 FAILED bun test v1.4.1-canary.1 (9e0b058) test/internal/source-lints/literal-bool-condition.test.ts: (pass) scans a non-empty set of tracked Rust sources [0.09ms] (pass) withoutTestItems keeps production code and blanks #[cfg(test)] items [0.09ms] 234 | "fn after_strings() {}", 235 | ]); 236 | }); 237 | 238 | test("if true { .. } / if false { .. } outside #[cfg(test)] code", () => { 239 | expect(offenders).toEqual([]); ^ error: expect(received).toEqual(expected) - [] + [ + "src/bundler/linker_context/doStep5.rs:308: if false {", + "src/watcher/Watcher.rs:752: if true {", + ] - Expected - 1 + Received + 4 at <anonymous> (/workspace/bun/test/internal/source-lints/literal-bool-condition.test.ts:239:21) (fail) if true { .. } / if false { .. } outside #[cfg(test)] code [0.19ms] 2 pass 1 fail 3 expect() calls Ran 3 tests across 1 file. [798.00ms] __F:1:S:0 ``` </details> <details><summary>passes on PR (with fix)</summary> ```console ASAN with fix: all passed $ BUN_DEBUG_QUIET_LOGS=1 bun scripts/build.ts --profile=debug --quiet test "--reporter=junit" "--reporter-outfile=/tmp/mechgate.xml" test/internal/source-lints/literal-bool-condition.test.ts bun test v1.4.1 (731aa92) test/internal/source-lints/literal-bool-condition.test.ts: (pass) scans a non-empty set of tracked Rust sources [2.29ms] (pass) withoutTestItems keeps production code and blanks #[cfg(test)] items [4.24ms] (pass) if true { .. } / if false { .. } outside #[cfg(test)] code [1.22ms] 3 pass 0 fail 3 expect() calls Ran 3 tests across 1 file. [62.41s] __F:0:S:0 release with fix: all passed $ bun scripts/build.ts --profile=release [configured] bun-profile → bun (stripped) in 631ms (unchanged) ninja: Entering directory `/workspace/bun/build/release' [1/126] gen generated_host_exports.rs generated_host_exports.rs: 122 exports (host=5, lazy=10, generic=107, rust=0); 243 extern-C blocks audited [2/126] gen ZigGeneratedClasses.{cpp,h,rs} Found 2 classes from /workspace/bun/src/jsc/resolve_message.classes.ts - ResolveMessage (15 fields) - BuildMessage (10 fields) Found 1 classes from /workspace/bun/src/runtime/api/Archive.classes.ts - Archive (4 fields, 1 class fields) Found 2 classes from /workspace/bun/src/runtime/api/BunObject.classes.ts - ResourceUsage (8 fields) - Subprocess (20 fields) Found 1 classes from /workspace/bun/src/runtime/api/cron.classes.ts - CronJob (5 fields) Found 3 classes from /workspace/bun/src/runtime/api/filesystem_router.classes.ts - FileSystemRouter (5 fields) - FrameworkFileSystemRouter (2 fields) - MatchedRoute (8 fields) Found 1 classes from /workspace/bun/src/runtime/api/Glob.classes.ts - Glob (5 fields) Found 1 classes from /workspace/bun/src/runtime/api/h2.classes.ts - H2FrameParser (32 fields) Found ... (truncated) ``` </details> <details><summary>diff hotspot</summary> ``` src/bun_alloc/basic.rs | 73 +-- src/bun_alloc/lib.rs | 105 +--- src/bun_core/feature_flags.rs | 14 - src/bun_core/string/immutable/unicode.rs | 28 - src/bundler/AstBuilder.rs | 4 - src/bundler/LinkerGraph.rs | 3 - src/bundler/ParseTask.rs | 4 - src/bundler/bundle_v2.rs | 9 - src/bundler/linker_context/doStep5.rs | 5 +- src/bundler/linker_context/postProcessCSSChunk.rs | 9 - src/bundler/linker_context/postProcessJSChunk.rs | 5 - .../linker_context/scanImportsAndExports.rs | 2 - src/collections/StaticHashMap.rs | 7 - src/crash_handler/error.rs | 3 - src/crash_handler/lib.rs | 7 +- src/css/declaration.rs | 4 - src/css/selectors/selector.rs | 23 - src/css/values/percentage.rs | 11 - src/http/HTTPContext.rs | 16 +- .../websocket_client/WebSocketUpgradeClient.rs | 19 +- src/install/lockfile.rs | 2 - src/install/lockfile/Package.rs | 4 +- src/io/PipeWriter.rs | 2 - src/js_parser/lexer.rs | 631 ++++----------------- src/js_parser/lib.rs | 6 - src/js_parser/parse/parse_fn.rs | 3 - src/js_parser/visit/visit_expr.rs | 6 - src/jsc/CallFrame.rs | 9 +- src/jsc/ModuleLoader.rs | 1 - src/jsc/RuntimeTranspilerCache.rs | 6 +- src/jsc/bindings/BunObject.h | 3 - src/jsc/bindings/ImportMetaObject.cpp | 4 - src/jsc/bindings/InspectorHTTPSe ... (truncated) ``` </details> **gate history** · 2 passed · 1 rejected · iteration 2 <details><summary>evidence per changed file</summary> ``` file reads edits tests src/bun_alloc/basic.rs 0 0 0 src/bun_alloc/lib.rs 0 0 0 src/bun_core/feature_flags.rs 1 0 0 src/bun_core/string/immutable/unicode.rs 0 0 0 src/bundler/AstBuilder.rs 0 0 0 src/bundler/LinkerGraph.rs 0 0 0 src/bundler/ParseTask.rs 0 0 0 src/bundler/bundle_v2.rs 0 0 0 src/bundler/linker_context/doStep5.rs 0 0 0 src/bundler/linker_context/postProcessCSSChunk.rs 0 0 0 src/bundler/linker_context/postProcessJSChunk.rs 0 0 0 src/bundler/linker_context/scanImportsAndExports.rs 0 0 0 src/collections/StaticHashMap.rs 0 0 0 src/crash_handler/error.rs 0 0 0 src/crash_handler/lib.rs 0 0 0 src/css/declaration.rs 0 0 0 (+ 68 more files) ``` </details> <!-- robobun:evidence:end --> --------- Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
…al-field cells, Http2Response, and the WebView ObjC wrappers (#42816) ### Problem - Four native class members exist only for built-in JS, and nothing calls them: the SQL connection `connected` getter and `onconnect` accessor, `NodeHTTPResponse.ended`, and `crash_handler.getFeaturesAsVLQ`. - Thirteen `JSInternalFieldObjectImpl` subclasses carry a copied `static size_t allocationSize(Checked<size_t>)`. Each `create()` uses `allocateCell<T>(vm)`, which takes `sizeof(T)`. JavaScriptCore calls `allocationSize` only on its own classes. - Other leftovers have no reader: two WebCore members, eight `Http2Response` members and the `socketData` field behind one of them, two `ObjCRuntime` wrappers, `.typos.toml`, and `packages/bun-error/img/*`. ### Fix - Delete each item: 31 files, 154 lines and 4 images removed. The Notes list every symbol. - Correct because every removed name has zero references in `src/`, `packages/`, `scripts/`, `test/` and `build/debug/codegen/` outside its own definition. No removed member is documented or typed API. - Verified: `bun bd` and `bun run rust:check-all` (12 targets) pass. The sql, `node:http`, streams, `serve-http2`, node error-code, performance and crash-handler test files pass. `ObjCRuntime` compiles only on macOS, so CI is the compile check for those 13 lines. ### Background - A `*.classes.ts` file declares the members of a native class. The generator emits the C++ wrapper and the Rust glue. The generated thunk is `#[no_mangle]`, so neither rustc nor the linker reports a member that no JS reads. - `values: ["onconnect", ...]` in `sql.classes.ts` declares a GC-visited slot on the wrapper. Native code uses the slot through `onconnect_get_cached` / `onconnect_set_cached`. The removed accessor was a JS-facing route to the same slot. The slot stays. - 34 other dead-code pull requests are open. This one deletes nothing that they delete. Six files overlap on other lines (listed in the Notes). <details><summary>Notes</summary> No test is added. The change deletes code that has no user, so it has no behavior to cover, and REVIEW.md says not to add tests that check dead code stays dead. Overlap with open pull requests: - No deleted line is a line that one of the 34 open dead-code pull requests deletes (checked line by line against their diffs). - Six files also change in one of them, on other lines: `scripts/glob-sources.ts` (#40232), `src/jsc/bindings/ErrorCode.h` (#39929), `JSOneShotDirectSink.h` (#41385), `JSStreamAlgorithmContexts.h` (#41445), `src/runtime/api/crash_handler_jsc.rs` (#41385), `src/sql_jsc/postgres/PostgresSQLConnection.rs` (#40824). - The diffs of the 227 open pull requests (newest 2,500) that touch the `node:http`, sql, crash-handler, streams-header, webview or uws HTTP/2 files add no user of a removed name. Removed, one line each: - `PostgresSQLConnection.connected` / `MySQLConnection.connected` and both `get_connected`. Every `.connected` in `src/js/internal/sql/` and `src/js/bun/sql.ts` is `PooledConnectionState.connected`. `test/js/sql` mentions it in comments only. - `PostgresSQLConnection.onconnect` / `MySQLConnection.onconnect` accessor and the two `(get_on_connect, set_on_connect => ...)` lines of `cached_prop_hostfns!`. Every JS `onconnect` is on the options object (`connectionInfo.onconnect`, `ret.onconnect`). - `NodeHTTPResponse.ended` / `get_ended`. The `_http_*` modules read `handle.flags & NodeHTTPResponseFlags.ended`. The other `.ended` hits are `queued.ended`, `_readableState.ended`, and the JS handle in `http1_server_fallback.ts`. - `crash_handler.getFeaturesAsVLQ` / `js_get_features_as_vlq`, and the `BoundedArray` import that only it used. `getFeatureData` and the other entries have users in `test/`, `scripts/` or `packages/bun-release`. - `allocationSize` in `InternalModuleRegistry.h`, `ErrorCode.h` (`ErrorCodeCache`), `BunStreamSource.h`, `JSAsyncIteratorSourceOperation.h`, `JSDirectStreamSource.h`, `JSOneShotDirectSink.h`, `JSReadRequest.h` (2), `JSReadStreamIntoSinkOperation.h`, `JSReadableStreamIntoArrayOperation.h`, `JSStreamAlgorithmContexts.h`, `JSStreamTeeState.h`, `JSStreamPipeToOperation.h`. `rg allocationSize src packages build/debug/codegen` found the 14 definitions and no call. The debug objects contain no `allocationSize` symbol for a bun class. The fourteenth copy, in `JSCrossRealmTransformState.h`, stays because #41445 deletes that file. - #41268 lists `InternalModuleRegistry::allocationSize` under "Kept on purpose" because it corrects the base class version, which returns `sizeof(JSInternalFieldObjectImpl)`. That reason does not hold. Nothing calls either version for these classes, `allocateCell<T>(vm)` sizes the cell from `sizeof(T)`, and four other subclasses (`ModuleLoader.h`, `JSSocketHandlers.h`, `JSNextTickQueue.h`, `JSMockFunction.h`) never had the copy. - `JSPerformanceResourceTiming::protectedWrapped`. The callers of `protectedWrapped()` are on `JSDOMURL`, `JSAbortSignal` and the `CookieMap` wrapper. - `ResourceLoadTiming::isolatedCopy`. No caller. - `Http2Response::getWriteOffset`, `overrideWriteOffset`, `getSocketData`, `prepareForSendfile`, `uncork`, `isCorked`, `getNativeHandle`, `isConnectRequest` (`packages/bun-uws/src/Http2Context.h`), and `Http2ResponseData::socketData`, which only `getSocketData` read and nothing wrote. The callers of the last four names in `libuwsockets.cpp` are on `HttpResponse<SSL>` and `AsyncSocket<SSL>`. `libuwsockets_h2.cpp` uses none of the eight. #40294 removes the same-named members of `HttpResponse` and `Http3Response`. - `ObjCRuntime`: `struct NSObject` (only member: `describe()`), `Ref::s_description`, `WKWebView::isLoading()`, `WKWebView::s_isLoading`. Each name has only its declaration, definition and `sel(...)` initializer. - `.typos.toml`. Its runner, `.github/workflows/typos.yml`, was deleted in 126f468 (2025-11-05). - `packages/bun-error/img/{close.png,error.png,powered-by.png,powered-by.webp}`, last touched 2021-09-11. `bun-error.css` uses inline `data:` URIs. The `img/*` glob in `scripts/glob-sources.ts` goes with them. Tests run with the debug build: `test/js/sql/sql-onconnect-onclose-throw.test.ts` (9), `sql-connection-socket-uaf.test.ts` (2), `sql-mysql-clean-reentry.test.ts` (1), `sql-mysql.test.ts`, `sql.test.ts`, `test/js/node/http/node-http.test.ts` (159), `node-http-uaf.test.ts` (9), `test/js/web/streams/streams.test.js` (563), `test/js/bun/http/serve-http2.test.ts` (90), `test/js/web/timers/performance-entries.test.ts`, `test/cli/run/run-crash-handler.test.ts` (28), `test/js/node/errors/` (2 files), `test/js/bun/util/error-code-mirror.test.ts`. How the candidates were found: - A repo-wide identifier index (definitions with zero other mentions, comments stripped). - A compiler pass over a scratch copy of the workspace: every `pub` item that no other crate names becomes `pub(crate)`, then `cargo check --force-warn dead_code` runs for linux (dev and release), windows and macos. A loop restores `pub` at each definition that a privacy error points to. 131 leaf items came out of it. - A second compiler pass marks each of those 131 items `#[deprecated]` in an unmodified copy and checks all four configurations again. 88 had a real user. The first pass misses them because a private inherent method silently loses method resolution to a trait method of the same name. 43 had none. - Manual review dropped all 43: unit-test users (`CowSlice::init_dupe`, `clap::SliceIterator`, `Imports::ALL_SORTED`, the `h2::Connection` send path), names that `generate-classes.ts` emits (`host_fn_setter`, `host_fn_this_value`), a FreeBSD-only user (`O::EVTONLY`), the `__IsFreeze` autoref const, and errno or fault-injection tables that mirror C. - A mark-and-sweep over the relocations of the `-O0 -ffunction-sections` debug objects for C++. Almost every hit is in a function that one of the open pull requests already deletes. - A per-binding comparison of every native object and `*.classes.ts` member that built-in JS consumes against `src/js`, `packages/bun-types` and `test/`. Self-reviewed: three changes requested, all made. The other four `Http2Response` stubs and `socketData` go too, three more `allocationSize` copies go too, and the `sys/Error.rs` entry is back. Found, not deleted here: - `"sys/Error.rs"` in `rustIdentifierPaths` (`src/codegen/generate-js2native.ts`): no `$newRustFunction` call site on main since 2b3f660, but #40854 adds one. - `FrameworkFileSystemRouter.match` (the `bun:internal-for-testing` router binding, 67 lines with `route_to_json_inverse`): no user on main, but #40731 and #33232 add tests that call it. - `bun_core::strings::split_once`: no user, but #40824 deletes the adjacent `rsplit_once`. - The SQL `queries` getter is never read, so `queries_set_cached` never runs and `get_queries_array()` always returns `undefined`. The `if (queries)` branches in `onResolve*`/`onReject*` (`mysql.ts`, `postgres.ts`) and the `queries` argument of about 12 native call sites are dead. That is a refactor of the resolve path, not a deletion. - `NodeHTTPResponse.ref`: no JS caller, but `unref` has one, and a one-sided pair reads like a bug. - `MySQLConnection.ref`/`unref`: no caller, but `sql.classes.ts` generates both drivers from one loop. - 36 of the 48 `X_getter` functions that `WEBCORE_GENERATED_CONSTRUCTOR_GETTER` defines in `ZigGlobalObject.cpp` have no user. The macro also defines the live `XConstructorCallback`, so this needs a macro split. - `IDLByte`, `IDLShort` and `IDLLongLong` converters: never instantiated, but `src/codegen/bindgen.ts` can emit the type names. - `ERR_REDIS_INVALID_DATABASE` in `ErrorCode.ts`: no user, but three open pull requests edit the adjacent lines. - `internalBinding("quic")` constants that `quic.ts` does not read: the object mirrors Node's list and is returned whole. </details> <!-- robobun:evidence:begin --> --- **no test proof** · iteration 2 · platform-specific test(s) that do not run on this machine, deferring to CI, which covers all platforms: test/cli/run/run-crash-handler.test.ts <!-- robobun:evidence:end -->
… and the CI pipeline script (#43976) Behaviour change: none ### Problem - Eleven files hold items that nothing reads or calls: write-only fields, an uncalled method, four unused types, and CI options that are parsed and dropped. - No tool reports them. C and C++ have no dead-code lint. TypeScript counts `x += n` as a read. The Rust types come from a macro. ### Fix - TypeScript: remove `DataViewReader.u16()`, `DataViewWriter.capacity`, the `totalCount` local in `updateBuildErrorOverlay`, and a commented-out block from 2024 in `src/js/node/dgram.ts`. - C and C++: remove `us_udp_socket_t.connected`, `us_quic_stream_s.headers_delivered` and `Http2ResponseData::totalSize` (each is only written), and `#undef FD_BITS` (nothing defines it). - Rust and CI: remove the opaque types `us_loop_t`, `us_socket_context_t`, `us_udp_socket_t`, `us_udp_packet_buffer_t` from `src/uws_sys/lib.rs`. In `.buildkite/ci.ts`, remove `dryRun`, `Platform.features`, four emoji entries, and the union members `"amazonlinux"` and `"eol"`. - Verified: `rg -w` for each symbol over `src`, `packages`, `scripts`, `test` and `build/debug/codegen` finds no other use. `bun bd`, `bun run rust:check-all` (12 targets) and `tsc` pass. Self-reviewed: 1 concern raised, 1 addressed. ### Background - `DataViewReader` and `DataViewWriter` decode and encode the binary messages between the dev server and its browser client. - `us_udp_socket_t` and `us_quic_stream_s` are private C structs of uSockets. Rust holds them as opaque pointers, so no Rust struct mirrors their layout. - `bun_core::opaque_extern!` declares a zero-sized Rust type for a C struct. Rust code names `Loop`, `udp::Socket` and `udp::PacketBuffer`, not the four removed types. ### Downsides - None found. Checked each removed symbol for users in Rust, C, C++, TypeScript, generated code, tests, and open pull requests. <details><summary>Notes</summary> **Evidence per removal** | Item | Evidence | | --- | --- | | `DataViewReader.u16()` | `rg '\.u16\('` over `src/runtime/bake`, `test/bake`, `test/cli/inspect`: no hit. | | `DataViewWriter.capacity` | The only hit of `.capacity` in the bake TypeScript is the assignment in the constructor. `initCapacity` is the only caller of the constructor. | | `totalCount` | Two hits: the declaration and one `+=`. | | `dgram.ts` block | `git blame`: 589f941, 2024-04-26. `replaceHandle` and `startListening` are not defined in the file. | | `us_udp_socket_t.connected` | Two hits, both `udp->connected = 0;`. | | `us_quic_stream_s.headers_delivered` | Two hits in `quic.c`: the field and one `= 1`. The struct is private to `quic.c`. | | `Http2ResponseData::totalSize` | One member access: `data.totalSize = totalSize;`. The other hits of `totalSize` are the function parameter. | | `#undef FD_BITS` | The only hit of `FD_BITS` in `src` and `packages`. | | Four opaque types | Each name has one non-comment hit in all Rust sources and generated Rust: the macro call. | | `dryRun` | Four hits in `ci.ts`: the field, two assignments, one destructure. Nothing reads the binding. | | `Platform.features` | One hit. | | Emoji, `Distro`, `Tier` entries | No platform in `ci.ts` or image in `scripts/build/ci-images/spec.ts` carries them. `Emoji` is `keyof typeof emojiMap`, so a remaining caller would fail `tsc -p scripts/tsconfig.json`. It passes. | **Taken out because an open pull request uses or removes the item** - `DataViewWriter.u8()`: dead on main, but #42075 adds its first caller (`check.u8(IncomingMessageId.check_errors)` in `hmr-runtime-error.ts`). Git merges the two without a conflict, so the method stays. The tree that results from a merge of this branch with #42075 has no type error for `u8`. - `declare module "bun:wrap"` in `bake.private.d.ts`: no importer, but #39488 already has the same hunk. **Tests run with the debug build, all pass** `test/js/bun/udp/udp_socket.test.ts` (218), `test/js/bun/udp/dgram.test.ts` (62), `test/js/bun/http/serve-http2.test.ts` (93), `test/js/bun/http/serve-http3.test.ts` (73), `test/bake/dev/bundle.test.ts` (23), `test/bake/dev/esm.test.ts` (17), `test/bake/hmr-socket-protocol.test.ts` (4), `test/cli/inspect/BunFrontendDevServer.test.ts` (7). `test/js/node/dgram/node-dgram.test.js` passes 3 of 4: the IPv6 multicast test fails with `ENODEV` in the test container, with and without this change. `prettier` and `cargo fmt --check` report no change. **Overlap with open pull requests** Each removed line was compared with the diffs of the 35 open dead-code pull requests. None removes the same lines. Five files are also touched by an open pull request, in hunks more than 6 lines away: `internal.h` and `quic.c` (#40294, #42431), `dgram.ts` (#42431), `overlay.ts` (#43378, #42075, #39488), `src/uws_sys/lib.rs` (#43010). The added lines of the 122 open pull requests that were updated since 2026-09-18 and touch the bake, uSockets, uWS, uws_sys, server, socket or CI sources name none of the removed symbols. **What was scanned** - C and C++: the debug binary was linked a second time with `--gc-sections`, and the two symbol tables were compared. 414 functions in bun's own C and C++ are unreachable on Linux. Open pull requests remove 263 of them. The remainder is in the list below, has a caller on Windows or macOS, or comes from a macro. - Rust: 37 `#[no_mangle]` exports are unreachable in the Linux link. Each has a caller on another platform, or #40824, #40232 or #40557 removes it. A count of references for all 58,055 Rust definitions found no other item without a user. Of the 144 `allow` attributes for the unused and unreachable lints, each covers code that depends on `cfg` or is macro output. - Cargo: five dependency edges are unused on all 12 targets. #40294 removes three. `bun_resolver -> bun_zstd` is used under `cfg(bun_codegen_embed)`. `bun_wyhash -> bstr` is used by unit tests. - Preprocessor: `USE(BIGINT32)` and `ENABLE(MALLOC_BREAKDOWN)` are never true. #43644 and #40557 remove those branches. - Also scanned and clean: `src/js`, `src/node-fallbacks`, `src/codegen`, `scripts/`, `misctools/`, `patches/` (every patch file has a user), `packages/` except `bun-types`. **Probably dead, left alone on purpose** - The `PerformanceResourceTiming` cluster under `src/jsc/bindings/webcore` (about 2,000 lines: `PerformanceResourceTiming`, `PerformanceServerTiming`, `ResourceTiming`, `NetworkLoadMetrics`, `ResourceLoadTiming`, `ServerTiming` and the two JS wrappers). The linker drops every constructor, so no instance can exist. The two globals are public and `test/js/web/web-globals.test.js` checks them. This needs a decision: keep it for a future resource-timing implementation, or reduce it to the two constructors. - `WEBCORE_GENERATED_CONSTRUCTOR_GETTER` (`ZigGlobalObject.cpp`) emits an `X_getter` function for 50 classes. 45 have no user. A removal needs a second macro and saves no source lines. - The WebIDL converters for `byte`, `short` and `long long`, and most `Clamp` and `EnforceRange` specializations in `JSDOMConvertNumbers.cpp`. No binding uses them, but `src/codegen/bindgen.ts` maps `t.i8`, `t.i16` and `t.i64` to them. - `src/js/bun/sql.ts`: the export properties `sql`, `Query`, `postgres` and the four error classes. Native code reads only `default` and `SQL`. It is not certain that no loader path exposes the module object. - `us_nq_settings_set_scid_len` and `us_nq_settings_set_delay_onclose` (`node_quic_shim.c`, declared in `src/lsquic_sys/lib.rs`): no caller. `node:quic` is under active work. - `Event::currentTargetIsInShadowTree()` and its bit: no reader. The lines sit next to a hunk of #39929. - Bake client: `WebSocketWrapper.close()` and `[Symbol.dispose]()`, `streamingStarted`, the `line` and `column` bookkeeping and seven enum members in `JavaScriptSyntaxHighlighter.ts`, and `externals` in `src/node-fallbacks/build-fallbacks.ts`. Each sits next to a hunk of #43378, #40492, #40122 or #41385. - The `internal: true` property option of the class generator. A guard throws on it, so the branches behind it cannot run. Five open pull requests touch `generate-classes.ts`. - `H2App::getNativeHandle` (next to a hunk of #41195) and `uws_app_listen_config_t` (its last user goes with #42431). - `UWS_ALLOW_SHARED_AND_DEDICATED_COMPRESSOR_MIX`, `UWS_ALLOW_8_WINDOW_BITS` and `LIBUS_NO_SSL`: never defined, but they are documented opt-in switches of the upstream libraries. - `scripts/debug-coredump.ts`, `scripts/gamble.ts`, `scripts/github-metrics.ts`, `scripts/lldb-inline.sh` with `scripts/lldb-inline-tool.cpp`, and `packages/h3blast`: nothing references them. They read as tools that a person runs by hand. - #40232 removes `napi_internal_get_version`. #42556 renamed that function to `Bun__napi_get_version` on main, and it still has no caller. </details>
Problem
rgfinds only the definition and the declaration.Setflavour ofJSDOMIterator, andFetchHeadersguard helpers.Fix
toWrapped()static of 17 wrapper classes and the reference takingtoJS(..., T&)overload of 11 types.DeferredPromise::promise()and fourreject()overloads, unusedEvent,ErrorEventandCustomEventconstructors, and a few more. The Notes list every symbol.construct()method thatgenerate-jssink.tsemitted for every sink, and two Rust items that hawk reports (PluginRunner::could_be_plugininbun_jsc,PathSeparators::POSIX).bun bdbuilds,bun bd teston 22 files that use the touched classes passes (1202 pass, 0 fail), and CI built every platform. New tests inarraybuffersink.test.tsandFormData.test.tspin the sink constructor and theFormDataiteration that the edited codegen andJSDOMIterator.hproduce. They pass before and after this change: a deletion of unreachable code has no behaviour a test can fail on, and the repo does not want tests that assert a symbol is absent (test/internal/source-lints/CLAUDE.md). Each deletion removes the declaration too, so a caller on another platform fails to compile, not to link.Background
JS<T>::toWrapped()is the WebKit IDL hook that turns a JS value back into its native object. OnlyIDLInterface<T>conversions call it. No Bun binding declares one for these 17 types.toJS(..., T&)wraps an existing native object. Bun wraps these types throughtoJSNewlyCreatedor hand written code, so these overloads are never instantiated.Notes: removed symbols, verification, what was left for later
Removed, C++ (definition and declaration in each case):
toWrapped()of JSAbortController, JSCookieMap, JSDOMFormData, JSDOMURL, JSEventEmitter, JSFetchHeaders, JSMessageChannel, JSPerformanceEntry, JSPerformanceObserver, JSPerformanceObserverEntryList, JSPerformanceServerTiming, JSPerformanceTiming, JSTextEncoder, JSURLPattern, JSURLSearchParams, JSWasmStreamingCompiler, JSWebSocket. JSCookieMap.cpp and JSWasmStreamingCompiler.cpp also lose the file-localtoWrapped(JSGlobalObject&, ExceptionThrower&&, JSValue)templates that only named the deleted statics.toJS(..., T&)and the inlinetoJS(..., T*)forwarder for AbortController, CloseEvent, CookieMap, CustomEvent, DOMFormData, ErrorEvent, MessageChannel, TextEncoder, URLPattern and JSC::Wasm::StreamingCompiler.DeferredPromise::promise(),DeferredPromise::reject(RejectAsHandled),reject(std::nullptr_t, RejectAsHandled),reject(JSValue, RejectAsHandled),reject(const PrivateName&, RejectAsHandled). All live callers use theExceptionandExceptionCodeoverloads.Event::Event(EventInterface, IsTrusted), the seven argumentEvent::Event(..., MonotonicTime, IsTrusted), the twoErrorEventconstructors that take a message and a file name plus the two inlinecreate()overloads that were their only users (every caller uses theInitoverload),CustomEvent::create(IsTrusted)and the private constructor behind it.HTTPHeaderMap::remove(StringView),JSEventListener::functionName(),URLPattern::create(ScriptExecutionContext&, Compatible&&, const String&)and theCompatiblealias,JSReadableStreamAsyncIterator::prototype(),JSWasmStreamingCompiler::prototype(),JSNodeHTTPServerSocket::create(VM&, Zig::GlobalObject*, us_socket_t*, bool, JSNodeHTTPResponse*),JSBakeResponse::createStructure()(instances usecreateJSBakeResponseStructure),Bun::createError(JSGlobalObject*, ErrorCode, JSValue)and the declaration-onlycreateError(Zig::GlobalObject*, ErrorCode, JSValue)in ErrorCode.h.HTTP_HEADERS_ACCESSOR_DEFINITIONSand theIndextakingidentifierAt/stringAtoverloads in HTTPHeaderIdentifiers.h (none of the 99<name>Identifier()/<name>String()accessors had a caller, callers useidentifierFor/stringFor),MARKDOWN_TAG_STRINGS_ACCESSOR_DEFINITIONin BunMarkdownTagStrings.h (none of the 30 accessors had a caller, Rust goes throughstringAt), the Set flavour of JSDOMIterator.h (all four iterator traits in the tree areMap): the SetasJSandappendForEachArguments, and with them theJSDOMIteratorTypeenum,EnableIfMap/EnableIfSet, thetypemember of the four traits structs and the<type_traits>include; the three includes that only the removedErrorEventconstructors used (Strong.hin ErrorEvent.h,EventNames.handStrongInlines.hin ErrorEvent.cpp);FetchHeaders::setGuard(),FetchHeaders::guard()and theEnumTraits<FetchHeaders::Guard>specialization, bothJSEventListener::wasCreatedFromMarkupoverloads together with them_wasCreatedFromMarkupbit they read, theCreatedFromMarkupenum, the constructor parameter that fed it and the twoCreatedFromMarkup::Nocall sites (JSEventListener.cpp, JSErrorHandler.cpp), and theOperationFailedandOperationTimedOutentries of BunCommonStrings.h.src/codegen/generate-jssink.ts: the per-sink${constructor}::constructdeclaration and definition.Removed, Rust:
PluginRunner::could_be_plugin(src/jsc/PluginRunner.rs, callers use thebun_bundlerone) andPathSeparators::POSIX(src/paths/Path.rs).How the candidates were found: every function and data symbol of the debug objects, grouped by address so that constructor aliases count as one entity, with relocation edges between them. Roots: references from
libbun_rust.a, JavaScriptCore, WTF, bmalloc and ICU (including weak references and the three hooks WebKit defines weakly and Bun overrides), thesymbols.*export lists, and the static initializers. Debug info,.eh_frameand ASAN metadata were excluded, because ASAN makes every function reference itself. Each unreachable entity was then re-checked withrgon the current tree. Header-only items came from a separate read of the headers.Verification:
bun bd. The new tests in arraybuffersink.test.ts (constructorname,length,newand plain call both produce a working sink, prototype linkage) and FormData.test.ts (entries(),keys(),values(), the default iterator, iterator result shape,forEach()argument order,thisArg, and the TypeError for a non callable callback) pass on this branch and on the released bun, as expected for a deletion: they guard the code that stays. They deliberately do not assertinstanceofagainstBun.ArrayBufferSink, because the generated constructor has noprototypeproperty today (a pre-existing bug, reported separately).bun bd teston test/js/web/fetch/headers.test.ts, headers-case.test.ts, abort/abort.test.ts, html/FormData.test.ts, encoding/text-encoder.test.js, urlpattern/urlpattern.test.ts, url/url.test.ts, web-globals.test.js, websocket/error-event.test.ts, fetch/wasm-streaming.test.ts, timers/performance.test.js, timers/performance-entries.test.ts, workers/message-port-pipe.test.ts, streams/streams.test.js, test/js/bun/cookie/cookie-map.test.ts, util/arraybuffersink.test.ts, util/filesink.test.ts, md/md-react.test.ts, test/js/node/perf_hooks/perf_hooks.test.ts, http/node-http-server-socket-end-drain.test.ts, test/js/deno/event/event.test.ts and custom-event.test.ts.cargo check --workspace, plusbun_jscandbun_pathson the windows and darwin targets. clang-format and prettier are clean. After the deletions,rgoversrc,packages,src/codegenand the codegen output finds no reference to any removed name.Files that #39618 also edits, in different places:
src/codegen/generate-jssink.ts,node/JSNodeHTTPServerSocket.cpp,JSAbortController.cpp,JSCloseEvent.cpp,JSCustomEvent.cpp,JSPerformanceObserver.cpp,JSPerformanceServerTiming.cpp,JSPerformanceTiming.cpp,JSWebSocket.cpp. #39618 also deletesJSErrorHandler.cpp, in which this PR changes one constructor argument; whichever lands second keeps the deletion.DOMPromise::whenPromiseIsSettled()(the whole of JSDOMPromise.cpp) is unreachable too, but #39618 removes the rest of that class, so the header and the .cpp are best deleted together once it has landed; it is left out here on purpose.Found unreachable but left alone on purpose:
bindings.cpp,headers.h,CryptoUtil.cpp, llhttp,JSErrorHandlerand ncrypto) was dropped from this PR.PerformanceResourceTiming,PerformanceServerTiming,ResourceTiming,NetworkLoadMetrics) are never constructed, but their JS constructors and prototypes are web visible, so a clean removal has to reshape the wrappers, andResourceTiming.his touched by Remove dead code from C++ bindings, bindgen glue, ast, and orphaned scripts #39581.JSCrossRealmTransformStateandcrossRealmTransformStateStructureare never instantiated, but the streams headers document them as deliberately kept scaffolding and their subspace slots live in files touched by Remove dead code from bun-uws, the native BufferList class, and built-in JS #37659.<Class>_getterfunctions thatWEBCORE_GENERATED_CONSTRUCTOR_GETTERexpands in ZigGlobalObject.cpp, the eight sink constructor accessors andperformanceObject()in ZigGlobalObject.h: dead, but both files are rewritten by open PRs.ScriptExecutionContext::getMainThreadScriptExecutionContext()is used on Windows,JSPerformanceEntry::subspaceForImpl()is used throughsubspaceFor<>behind an assert (release builds reference it), and the int8convertToInteger*instantiations are reached through bindgen'sIDLByte. All live.us_socket_t::write_fd(windows stub insrc/uws_sys/us_socket_t.rs), theReadWithoutLaunchmode of the windows shim, and theuws_app_run/uws_app_listenC++ definitions become removable once Remove dead code from uws_sys, webcore bindings, crash_handler, and scripts #37181 and Remove dead code from the JSC FFI glue, WebCore bindings, usockets, built-in JS, and orphaned scripts #39618 land.hawk.toml). Removing every#[allow(dead_code)]undersrcand checking the linux, darwin and windows targets found no item that is dead on all three.