Remove dead code from bun-uws, the native BufferList class, and built-in JS
Problem
- No user-visible behavior changes. About 2,058 lines across bun-uws, the native
JSBufferListbinding, the built-in JS modules and two Rustextern "C"exports have no remaining reference onmain. packages/bun-uwshad never been swept: it is header templates, so the linker-based sweep in #37454 could not see members that are never instantiated.- Two bun-uws
layoutAssert()helpers were never called, so theirstatic_asserts never ran. The WebSocket one guards a layout thatWebSocket::getContextData()really depends on.
Fix
- Deletes the unreferenced headers, template members,
JSBufferList, JS declarations and helpers, and the two Rust exports. The property to check: each removed item has zero references insrc/,packages/,scripts/,test/and codegen output, so nothing that runs today can change. - bun-uws members were checked by hand against every file that includes each header. The
extern "C"candidates were also checked againstvendor/and the prebuilt WebKit symbol tables, which is what keptBun__thisThreadHasVMandWTFTimer__*in place. - The WebSocket layout check becomes a
RELEASE_ASSERTinWebSocketContext::create(), so it now runs once per context in every build. The HttpContext one guarded nothing and is dropped. - Verification:
bun bdbuilds, the preprocessedPerMessageDeflate.his byte-identical, the websocket, http, http3, quic, stream and repl tests pass (the few local failures fail the same way onmain), and a new source lint fires onmainfor every removed file and symbol and passes here.
Background
packages/bun-uwsis Bun's fork of uWebSockets, the C++ HTTP and WebSocket server behindBun.serve. It is header templates; Bun reaches it through the C shim insrc/uws_sys/and a few bindings files, so those includers are the complete set of callers.- A member of a class template that is never called is never instantiated, so it is never compiled or linked. Linker-based dead-code tools cannot see it, and a
static_assertinside it never runs. WebSocket::getContextData()finds the context's data by pointer arithmetic from the socket group (groupfirst,dataimmediately after) so thatWebSocket.hneed not includeWebSocketContext.h.offsetofcannot express this because the struct is not standard-layout, hence a runtime assert.JSBufferListwas a native buffer list for Node-style streams; the JS streams implementation replaced it, and the only remaining mention is a comment.test/internal/source-lints/holds tests that read the source tree instead of the built binary. The new one lists every removed file and symbol, so a revert or a fresh upstream import shows up as a failing test.
Original description
Removes 2,050 lines of code that nothing references (plus the 322-line packages/bun-uws/misc/ directory of upstream README assets), with 26 lines added (one assertion, a rewritten import, comment fixes). No behavior change: every removed item is unreferenced today on main, and the build passes without it.
This run deliberately picked areas none of the 18 open dead-code PRs touch. packages/bun-uws had never been swept: it is header templates, so the recent linker-based sweep (#37454) could not see uninstantiated members, and each candidate below was checked by hand against every file that includes the header (the other bun-uws headers, src/uws_sys/libuwsockets*.cpp, and the eight bindings files that include App.h/Http3*.h). JSBufferList was noted as verified-dead but left for its own PR in #37181.
Removed
bun-uws (packages/bun-uws/src, -870)
- Whole headers nothing includes:
ClientApp.h,HttpError.h(superseded byHttpErrors.h),Multipart.handMessageParser.h(its only includer),ProxyParser.h(only reachable underUWS_WITH_PROXY, which no build defines; verified againstcompile_commands.jsonandscripts/build), plus every#ifdef UWS_WITH_PROXYblock and thereserved/proxyParserparameters whose only purpose was to carry the proxy parser intogetHeaders() WebSocketBehavior::subscriptionandsubscriptionHandler: the only place aWebSocketBehavioris built (uws_ws()in the C shim) never sets it, so every dispatch site inWebSocket::end/subscribe/unsubscribeandWebSocketContext::onClosewas unreachable;TopicTree::unsubscribedrops thenewCountthat only those sites readHttpRequest: the per-routestd::mapof parameter offsets (setParameterOffsets,getParameter(name); every caller uses the index overload),getQuery()with no key,isShortRead,notFieldNameWord/hasMore/hasBetween(unused since the v20.62 parser upgrade), and the now unused<map>includesHttpContext::HTTP_IDLE_TIMEOUT_S,HttpFlags::isAuthorized(the live flag is the per-socket one inAsyncSocketData),HttpResponse::getHttpResponseDataS,HttpResponse::endWithoutBody,HttpResponse::overrideWriteOffset(byte-identical tosetWriteOffset, which is what the shim calls)App:publish(unsigned char),listen(host, port, handler),listen(handler, path, options), theUWS_NO_ZLIBblock;H3App: the twolistenoverloads the shim does not use;Http3Request::isAncient/getCaseSensitiveMethod;Http3Response::setWriteOffset/uncork/isCorked/close/getNativeHandle/isConnectRequest/setTimeout/resetTimeout/prepareForSendfile(the matchinguws_h3_res_*shims are stubs that do not call them); the write-onlyHttp3ResponseData::totalSizeLoop::integrate,Loop::setSilentand theLoopData::noMarkflag it wrote, a strayus_timer_tforward declarationPerMessageDeflate.h: theUWS_NO_ZLIB/UWS_MOCK_ZLIBmock streams and theUWS_USE_LIBDEFLATEguards (the macro is defined unconditionally three lines above its first use). The preprocessed output of the header is identical before and after.HttpContext::layoutAssert()andWebSocketContext::layoutAssert()were never called, and as static members of class templates theirstatic_asserts were never instantiated. Instantiating them does not compile either (offsetofon a non-standard-layout type is an error under-Werror). TheHttpContextone guarded nothing (fromSocketround-trips theextpointer), so it is simply removed; theWebSocketContextone guards the layoutWebSocket::getContextData()really depends on, so it becomes aRELEASE_ASSERTincreate()(the layout can differ per ABI and only debug/asan builds enableASSERT; it runs once per context).misc/(READMORE.md, three PNGs, logo.svg, democert.pem/key.pem): referenced by nothing in the repo; also drops the.gitattributesline for afuzzing/directory that no longer exists
Native BufferList (src/jsc/bindings, -641)
JSBufferList.cpp/.hand theirZigGlobalObjectlazy structure, the three accessors, and theDOMIsoSubspaces/DOMClientIsoSubspacesslots. The JS streams implementation replaced it long ago; the only remaining mention of "BufferList" in the tree is a comment ininternal/streams/readable.ts.
Built-in JS (src/js, -520)
internal/util/inspect.d.ts(ambient types fornode-inspect-extracted, which nothing imports; the one JSDoc@typereferring to it innode/util.tsgoes too) andsrc/js/.gitignore(ignoressrc/js/out, which codegen has not written to since the build moved underbuild/)private.d.ts: theBunFS/BunFSWatchertypes (Bun.fs()no longer exists),Bun.TOML,Bun.ttyQuicStream.prototype[kSendHeaders]and its symbol (the public header methods talk to the native handle directly), the unusedget [kVerifyPeer](the setter stays),colors.tsyellow/gray/clear/reset, the runtimeSSLModeexport ininternal/sql/shared.ts(only imported as a type), theREPL_MODE_*re-exports ofinternal/repl/utils.js(repl.jstakes them frominternal/repl/mode),Dequeue#clear(), theOperation/Diffdeclarations inassertion_error.ts, and the write-onlylisteningIdinnet.ts
Rust (-18)
zig__ModuleInfo__destroyandzig_loginanalyze_transpiled_module.rs:extern "C"exports that no C++ declares or calls (BunAnalyzeTranspiledModule.cppfrees throughzig__ModuleInfoDeserialized__deinit), and that do not appear invendor/or in the prebuilt WebKit libraries
Verification
rgfor every symbol acrosssrc/,packages/,scripts/,test/andbuild/debug/codegen/; theextern "C"candidates were additionally checked againstvendor/and against both the undefined and the weak-defined symbols of the prebuiltlibWTF.a/libJavaScriptCore.a. That check is what disqualifiedBun__thisThreadHasVM(WTF ships a weak default that Bun overrides, so it shows up as neither a textual reference nor an undefined symbol; removing it tripsRunLoopBun.cpp's assertion as soon as a Worker starts) andWTFTimer__deinit/__cancel(imported bylibWTF.a). Both stay.- The preprocessed
PerMessageDeflate.his byte-for-byte identical before and after (one blank line aside). bun bdpasses. The only Rust file touched has nocfggates, so the hostcargo checkcovers every target. clang-format, prettier and oxlint are clean.bun bd testpasses ontest/js/bun/websocket/websocket-server.test.ts(pub/sub,end(), close paths; theWebSocketContext::createassertion runs in every server test),test/js/web/websocket/websocket-permessage-deflate.test.ts,test/js/bun/http/bun-serve-routes.test.ts(route parameters),test/js/bun/http/serve-http3.test.ts,test/js/node/http/node-http.test.ts,test/js/node/quic/quic-stream.test.ts,test/js/node/assert/assert.test.cjs,test/js/node/stream/node-stream.test.js,test/js/bun/sqlite/sqlite.test.js,test/internal/fifo.test.ts(the one failure there is the large push/shift test timing out under a debug ASAN build, which it also does onmain), andtest/js/node/test/parallel/test-repl-definecommand.js. The few failures seen locally (a proxy test that needs network, two debug-build perf timeouts, and three Worker lifecycle tests) fail identically on an unmodifiedmaindebug build in the same container.- No open PR adds a caller of anything removed here (checked the diffs of the 60 open PRs that mention bun-uws, including the HTTP/2 server work in #36161, which defines its own
Http2Responseequivalents). TheHttp3ResponseData::totalSizehunk sits next to a hunk in #34385 and theZigGlobalObject/DOMIsoSubspaceshunks next to ones in #37062/#37149/#37332; they delete different lines.
Rebase notes
Rebased onto main twice, on 2026-08-17 and 2026-08-21 (about 430 commits in total). Conflicts were mechanical: #39420 removed the JSMIMEBindings.h include next to the JSBufferList.h include this PR removes, and #39770 restructured the lazy-structure initializers in ZigGlobalObject.cpp and the slot declarations in DOMIsoSubspaces.h / DOMClientIsoSubspaces.h, so the BufferList entries were removed again in their new form (and the modified-on-main JSBufferList.cpp/.h stay deleted). Every removed symbol was re-checked against the new main after each rebase; nothing gained a caller.
The source lint that earlier revisions of this PR added is gone: main has since deleted the existing dead-symbols-* lints and test/internal/source-lints/CLAUDE.md asks for no more of them, so this PR now only deletes code (the source-lints workflow trigger change that existed for that lint is dropped too).
Left for follow-ups
- Once #37181 lands (it removes the
uws_*C wrappers), these bun-uws members lose their last caller and can go too:QueryParser.has a whole withHttpRequest::getQuery(key)andHttp3Request::getQuery/query,App::removeServerName/missingServerName/onMissingServerNameandHttpContextData::missingServerNameHandler,App::getNativeHandle,H3App::constructorFailed/getNativeHandle,WebSocket::send{First,,Last}Fragment,AsyncSocket::getRemoteAddressAsText/addressAsText,HttpResponse::getWriteOffset/setWriteOffset/getSocketData,Http3Response::getWriteOffset/overrideWriteOffset/getSocketDataand the never-writtenHttp3ResponseData::socketData. ChunkedEncoding.h'strailerflag is passed asfalseby all threeChunkIteratorcall sites, so its 4-byte-terminator branch is dead; removing it is a signature change through the parser rather than a deletion.Http3Response::endWithoutBody'sreportedContentLengthis alwaysstd::nullopt(its one caller is in the shim file #37181 edits).uWS::WebSocket/WebSocketContext/WebSocketProtocolare only ever instantiated withisServer = true(the onlyfalseuse was in the deletedClientApp.h), so the client-side masking branches inWebSocketProtocol.hare unreachable; dropping the parameter is a refactor.Bun__Node__CAStore(cli/Arguments.rs) is a#[no_mangle]static that nothing native reads yet; the adjacent comment says native code is meant to migrate to it, so it is left alone.