Skip to content

Remove dead code from the WebCore wrapper headers, the node:crypto bindings, NodeVMModule, and the build scripts - #43914

Merged
Jarred-Sumner merged 2 commits into
mainfrom
robobun/a15c1688/dead-code-sweep
Sep 24, 2026
Merged

Jarred-Sumner merged 2 commits into
mainfrom
robobun/a15c1688/dead-code-sweep

Conversation

@robobun

@robobun robobun commented Sep 24, 2026 •

Copy link
Copy Markdown
Collaborator

Behaviour change: none

Problem

  • 38 lines in 23 files have no reader: 14 type aliases, one enum, three locals, three build-script leftovers, nine stale config entries.
  • The sweep found no other free dead code. The 37 open dead-code PRs already delete each larger item. This PR shares no deletion with them.

Fix

  • Remove using DOMWrapped from 14 wrapper headers (JSAbortSignal.h, JSBroadcastChannel.h, JSCloseEvent.h, JSCustomEvent.h, JSErrorEvent.h, JSMessageEvent.h, JSMessagePort.h, JSPerformance.h, JSPerformanceMark.h, JSPerformanceMeasure.h, JSPerformanceResourceTiming.h, JSWebSocket.h, JSWorker.h, JSWebView.h).
  • Remove NodeVMModule::Type and three locals that nothing reads: contents (CryptoPrimes.cpp), dataString and encodingString (JSCipherPrototype.cpp).
  • Remove ToolSpec.versionArg (scripts/build/tools.ts), the sys/Error.rs key of rustIdentifierPaths (generate-js2native.ts), and the internalRegistry field that createInternalModuleRegistry returns. Remove eight entries of .gitattributes, .prettierignore and oxlint.json that name paths that do not exist, and one duplicate pattern.
  • Verified: rg finds no other use of each name in src/, packages/, scripts/, test/ and build/debug/codegen/. bun bd passes. With the debug build: abort.test.ts, broadcast-channel.test.ts, websocket-client.test.ts, perf_hooks.test.ts, vm.test.ts, test-crypto-prime.js, test/internal/source-lints/.

Background

  • DOMWrapped names the C++ class that a JS wrapper class wraps. JSDOMWrapper<T> defines it for each wrapper. Only JSDOMIterator.h reads it, for JSFetchHeaders, JSDOMFormData, JSURLSearchParams and JSCookieMap. None of those four declares its own alias.
  • ToolSpec describes a tool that the build looks for on the PATH. versionArg was for a tool that prints its version with version and not --version. No tool spec sets it.

Downsides

  • None found. Checked each name with rg, the debug build, and the suites above.
Notes

How this sweep searched

  • Rust: a rust-analyzer reference index of the whole workspace (49,127 items), then a mark and sweep from these roots: FFI and test attributes, trait items, macro-generated items, names that the generated code uses, and names with a textual occurrence that the index did not resolve. After the false positives were removed (macro dispatch such as any_dispatch!, comptime_string_map! statics, struct field shorthand, the codegen name r#ref), no unreferenced item was left outside the open PRs.
  • C, C++ and Rust: a relink of the debug build with --gc-sections --print-gc-sections. The debug build has no inlining, so a dropped function section has no caller on linux-x64. The relink dropped 337 C-named functions and 166 plain C++ functions from Bun's own objects. The open PRs already delete them, except the items under "Kept" below.
  • src/js/: every builtin export has a CodeGenerator reference, every internal module has a loader, and no module-local binding is unused.
  • .rs files outside every module tree, headers that nothing includes, .cpp files outside the build, unused Cargo dependencies (cargo reports 9 on linux. Open PRs already remove 4. The other 5 have a use on another target or in tests): nothing to remove.

Kept, with the reason

  • WEBCORE_GENERATED_CONSTRUCTOR_GETTER (ZigGlobalObject.cpp) defines a <Name>_getter for 51 classes. Only 15 have a user. To remove the other 36 needs a second macro, which adds lines.
  • PerformanceResourceTiming, ResourceTiming, NetworkLoadMetrics, ResourceLoadTiming: nothing creates an instance, but PerformanceResourceTiming is a global constructor, so the class is API surface.
  • bun_core::strings::split_once: no caller, but clippy.toml names it as the replacement for str::split_once.
  • StringPrintStream pathOut (BunJSCModule.h): an unread local, but Write the sampling profiler report at exit from Bun, not JSC's atexit hook #41137 already removes that line in its rewrite of startSamplingProfiler.
  • jsFunctionAppendOnLoadPluginNode and three sibling host functions, Process_defaultSetter, Bun__napi_get_version: no caller, already removed by Remove dead code from the JSC bindings, headers.h, the console builtin, and bun_jsc #40232.
  • completions/bun-cli.json and misctools/generate-cli-completions.ts: nothing reads the JSON, but feature PRs keep it up to date by hand.
  • scripts/lldb-inline-tool.cpp, scripts/lldb-inline.sh, scripts/github-metrics.ts, scripts/gamble.ts: nothing references them, but they are manual developer tools.
  • HiveBitSet::_FITS (src/collections/hive_array.rs): a static assertion, so it stays. It has a defect outside the scope of this PR: it is an associated const of a generic impl and nothing references it, so rustc never evaluates it. A reference such as let () = Self::_FITS; in init_empty() makes it run.
  • The defaulted special members in ncrypto.cpp, and the CMAKE_* exports in flake.nix and shell.nix (not testable here).

no test proof · iteration 0 · the description declares no behaviour change, so there is no failing test to prove; the existing suite in CI is the check

…ndings, NodeVMModule, and the build scripts

- Remove the `using DOMWrapped` alias from 14 wrapper headers. Only
  JSDOMIterator reads `DOMWrapped`, and only for the four wrappers that
  have an iterator. Those four take the alias from JSDOMWrapper.
- Remove `NodeVMModule::Type`, which nothing names.
- Remove four locals that are declared and never read (CryptoPrimes.cpp,
  JSCipherPrototype.cpp, BunJSCModule.h).
- Remove `ToolSpec.versionArg`, which no tool spec sets.
- Remove the `sys/Error.rs` entry of `rustIdentifierPaths` and the
  `internalRegistry` field the module registry scanner returns. Nothing
  reads either of them.
- Remove entries in .gitattributes, .prettierignore and oxlint.json that
  name paths that do not exist, and one duplicate ignore pattern.
@robobun

robobun commented Sep 24, 2026

Copy link
Copy Markdown
Collaborator Author

Status: ready for review.

  • Each removed name has no other textual use in src/, packages/, scripts/, test/ and the generated code (rg).
  • bun bd passes with the change. The suites named in the description pass with the debug build.
  • The diff has no Rust edit, and no deletion that an open dead-code PR already makes (checked against the patches of the 37 open PRs).

@coderabbitai

coderabbitai Bot commented Sep 24, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository: oven-sh/bun/.coderabbit.yaml

Review profile: ASSERTIVE

Plan: Essentials

Run ID: 9f52a135-d916-4d4a-9ff9-87281fb25f93

📥 Commits

Reviewing files that changed from the base of the PR and between 73df7bb and da74313.

📒 Files selected for processing (24)
  • .gitattributes
  • .prettierignore
  • oxlint.json
  • scripts/build/tools.ts
  • src/codegen/generate-js2native.ts
  • src/codegen/internal-module-registry-scanner.ts
  • src/jsc/bindings/NodeVMModule.h
  • src/jsc/bindings/node/crypto/CryptoPrimes.cpp
  • src/jsc/bindings/node/crypto/JSCipherPrototype.cpp
  • src/jsc/bindings/webcore/JSAbortSignal.h
  • src/jsc/bindings/webcore/JSBroadcastChannel.h
  • src/jsc/bindings/webcore/JSCloseEvent.h
  • src/jsc/bindings/webcore/JSCustomEvent.h
  • src/jsc/bindings/webcore/JSErrorEvent.h
  • src/jsc/bindings/webcore/JSMessageEvent.h
  • src/jsc/bindings/webcore/JSMessagePort.h
  • src/jsc/bindings/webcore/JSPerformance.h
  • src/jsc/bindings/webcore/JSPerformanceMark.h
  • src/jsc/bindings/webcore/JSPerformanceMeasure.h
  • src/jsc/bindings/webcore/JSPerformanceResourceTiming.h
  • src/jsc/bindings/webcore/JSWebSocket.h
  • src/jsc/bindings/webcore/JSWorker.h
  • src/jsc/modules/BunJSCModule.h
  • src/runtime/webview/JSWebView.h
💤 Files with no reviewable changes (22)
  • src/jsc/bindings/webcore/JSAbortSignal.h
  • src/runtime/webview/JSWebView.h
  • src/jsc/modules/BunJSCModule.h
  • src/jsc/bindings/webcore/JSWebSocket.h
  • src/codegen/generate-js2native.ts
  • .prettierignore
  • src/jsc/bindings/webcore/JSWorker.h
  • src/jsc/bindings/webcore/JSErrorEvent.h
  • src/jsc/bindings/webcore/JSMessagePort.h
  • src/jsc/bindings/node/crypto/JSCipherPrototype.cpp
  • src/jsc/bindings/webcore/JSCustomEvent.h
  • src/jsc/bindings/webcore/JSPerformanceResourceTiming.h
  • src/jsc/bindings/webcore/JSPerformanceMeasure.h
  • src/jsc/bindings/webcore/JSCloseEvent.h
  • src/jsc/bindings/webcore/JSPerformanceMark.h
  • src/jsc/bindings/node/crypto/CryptoPrimes.cpp
  • src/codegen/internal-module-registry-scanner.ts
  • src/jsc/bindings/webcore/JSBroadcastChannel.h
  • src/jsc/bindings/webcore/JSMessageEvent.h
  • src/jsc/bindings/webcore/JSPerformance.h
  • src/jsc/bindings/NodeVMModule.h
  • .gitattributes

Included review availability: Your plan provides up to 10 included reviews per hour; 6 remain after this review.


Walkthrough

The pull request removes repository configuration entries, an alternate build-tool version argument, codegen return and identifier entries, C++ binding declarations, and unused local variables.

Changes

Repository tooling

Layer / File(s) Summary
Repository classification and lint rules
.gitattributes, .prettierignore, oxlint.json
Git attributes and formatting-ignore entries were removed. Oxlint exclusions were reduced, and the first override now matches test files only.

Build tool version checks

Layer / File(s) Summary
Tool version argument
scripts/build/tools.ts
ToolSpec no longer accepts versionArg. findTool always checks candidate versions with --version.

Code generation interfaces

Layer / File(s) Summary
Codegen identifier and registry outputs
src/codegen/generate-js2native.ts, src/codegen/internal-module-registry-scanner.ts
The Rust identifier allowlist no longer includes sys/Error.rs. createInternalModuleRegistry no longer returns internalRegistry.

JSC declarations and implementation cleanup

Layer / File(s) Summary
Binding declarations
src/jsc/bindings/NodeVMModule.h, src/jsc/bindings/webcore/JS*.h, src/runtime/webview/JSWebView.h
The NodeVMModule::Type enum and the listed DOMWrapped aliases were removed.
Unused local variables
src/jsc/bindings/node/crypto/CryptoPrimes.cpp, src/jsc/bindings/node/crypto/JSCipherPrototype.cpp, src/jsc/modules/BunJSCModule.h
Unused locals were removed. The described buffer allocation, argument conversion, and profiler path setup remain.

Suggested reviewers: dylan-conway

Merge Risk: ⚪ Minimal · up to da743

The cleanup does not establish a material behavior or configured-check regression in the inspected paths. The PR is mergeable with normal checks.

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly summarizes the primary change: removal of unused code across WebCore wrapper headers, node:crypto bindings, NodeVMModule, and build scripts.
Description check ✅ Passed The description explains the problem, fix, scope, behavior impact, and verification steps. It does not use the exact template headings, but it provides the required information in equivalent sections.

Comment @coderabbitai help to get the list of available commands.

@robobun

robobun commented Sep 24, 2026

Copy link
Copy Markdown
Collaborator Author

Note on the Biome warning for oxlint.json in the review above: it is not from this change. oxlint.json is JSON with comments, and the comments that Biome rejects (line 20 and after) are the same on main. oxlint loads the edited file: bunx oxlint -c oxlint.json scripts/build/tools.ts reports 0 warnings and 0 errors, and test/internal/oxlint-plugin-bun.test.ts passes.

@claude claude Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nothing blocking. The comments below are optional suggestions. There is no need to push a fix for them before merging.

Beyond the inline finding (which is pre-existing, not introduced here), I checked the deletions themselves: the only reader of DOMWrapped is JSDOMIterator.h, and none of the 14 wrappers losing the alias is instantiated as an iterator Wrapper, so they fall back to the identical base alias in JSDOMWrapper.h:76; no builtin calls $rust("sys/Error.rs", ...); the removed .gitattributes/oxlint.json entries name paths that do not exist in the tree (no scripts/build/deps/*.snapshot, examples/, ZigGeneratedCode.h, or bun-simdutf.h).

Extended reasoning...

Deletion-only sweep (+2/-39) across 14 WebCore wrapper headers, node:crypto locals, NodeVMModule, BunJSCModule.h, two codegen scripts, tools.ts, and three config files; it touches no security-sensitive surface. The one confirmed finding is a pre-existing lifetime bug adjacent to the removed pathOut local, not something this PR introduces. Grepping confirmed each removed C++ alias falls back to the base-class alias and the removed codegen/config entries have no consumers.

Additional findings (outside the current diff — GitHub can't attach inline comments there):

  • 🟣 src/jsc/modules/BunJSCModule.h — pre-existing: a script that calls startSamplingProfiler(dir) from bun:jsc makes the at-exit profile report read freed memory. BunJSCModule.h:476 builds pathCString as a local CString, and BunJSCModule.h:484 stores its raw buffer pointer into Options::samplingProfilerPath(), which JSC's reportDataToOptionFile dereferences from the atexit hook long after the block ended. Fix: give the path storage that outlives the function, for example a function-static or intentionally leaked CString (or fastStrDup) whose data() is what Options::samplingProfilerPath() keeps. This hunk only removed the unused pathOut next to it; the dangling store was already there.

    Why this was flagged

    User JS calls startSamplingProfiler("/some/dir") from bun:jsc (registered at src/jsc/modules/BunJSCModule.h:989). At BunJSCModule.h:476 auto pathCString = toCString(String(path)); creates a WTF::CString whose buffer is refcounted and owned by that local. BunJSCModule.h:484 does Options::samplingProfilerPath() = pathCString.span().data(); and BunJSCModule.h:485 calls samplingProfiler.registerForReportAtExit(). When the if (!path.isEmpty()) block ends at BunJSCModule.h:486 the CString is destroyed and its buffer freed, but the global option still holds the pointer. At process exit JSC's atexit handler runs SamplingProfiler::reportDataToOptionFile(), which reads Options::samplingProfilerPath() to build the output file name, so it reads freed heap memory: under ASan this is a heap-use-after-free abort, otherwise the profile is written to a garbage or wrong path or the process crashes at exit. The base branch has the same defect; this PR removes only the unused StringPrintStream pathOut; from the same block, so it is pre-existing. No safeguard exists: nothing else keeps the…

    Verification: pre-existing (the diff touches this exact block: it deletes the unused StringPrintStream pathOut; that sat at old line 476, but the dangling-pointer store is unchanged from the base). Trigger: any script that calls startSamplingProfiler("<dir>") from bun:jsc (exported at /home/claude/bun/src/jsc/modules/BunJSCModule.h:989, typed in packages/bun-types/jsc.d.ts:766, exercised by…

The open fix for the startSamplingProfiler crash already removes this
line. Leave it to that change.
@robobun

robobun commented Sep 24, 2026

Copy link
Copy Markdown
Collaborator Author

On the review finding about startSamplingProfiler(dir) in BunJSCModule.h: it is real and it is not from this change.

@claude claude Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM — pure dead-code removal with every deleted name confirmed to have no remaining reader.

What was reviewed:

  • DOMWrapped: the only consumer is JSDOMIterator.h, instantiated solely for JSCookieMap/JSURLSearchParams/JSDOMFormData/JSFetchHeaders, none of which are touched; the base JSDOMWrapper<T> alias still exists for the 14 edited wrappers.
  • versionArg, internalRegistry return field, NodeVMModule::Type, and the four C++ locals: repo-wide grep finds no reference outside the deleted lines; sys/Error.rs still exists but no $rust() call names it, and a stale key would fail loudly at codegen anyway.
  • Config removals (.gitattributes, .prettierignore, oxlint.json override globs): every dropped path is absent from the tree; the oxlint duplicate ignore entry was an exact repeat.
Extended reasoning...

The net diff is +2/-38 across 23 files: type-alias and enum removals in WebCore wrapper headers and NodeVMModule.h, unused locals in two node:crypto .cpp files, an unused ToolSpec field and codegen map entry in build scripts, and stale entries in three config files. The crypto files are touched only to drop never-read locals, so no security-sensitive logic changes; no exception-check or ownership paths are altered. None of the changed files fall under .github/CODEOWNERS. The second commit reverted the BunJSCModule.h hunk after the earlier review, and the remaining diff verified clean on independent greps, which decided approve over defer.

@robobun

robobun commented Sep 24, 2026

Copy link
Copy Markdown
Collaborator Author
Updated 12:15 PM PT - Sep 24th, 2026

✅ @robobun, your commit 3cc1293b5f610d1aaf8aff651ea4a27e7d4a8af2 passed in Build #120372! 🎉


🧪   To try this PR locally:

bunx bun-pr 43914

That installs a local version of the PR into your bun-43914 executable, so you can run:

bun-43914 --bun

@Jarred-Sumner
Jarred-Sumner merged commit ce18964 into main Sep 24, 2026
11 checks passed
@Jarred-Sumner
Jarred-Sumner deleted the robobun/a15c1688/dead-code-sweep branch September 24, 2026 23:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants