Repository navigation
Conversation
|
Updated 3:04 AM PT - Nov 8th, 2026
❌ @robobun, your commit 8731992 has 1 failures in 🧪 To try this PR locally: bunx bun-pr 47813That installs a local version of the PR into your bun-47813 --bun |
|
Status: ready for review. CI is red on one test that this diff does not touch. This pull request has no repro. It deletes three C++ member functions that have no caller: 23 lines in How they were checked:
The branch now contains CI build 138552 is finished: 187 of 188 jobs pass. The one red test is The same test is red with the same message in 19 builds of other branches since 2026-11-07. Two examples are builds 138554 and 138536. The 20 failing jobs ran on 20 different CI machines, and one of those machines also ran a job that passes. So the result follows the content of the build, not the machine. The test can also turn red on |
|
No actionable comments were generated in the recent review. WalkthroughTwo methods, ChangesCrypto helper API removals
Suggested reviewers: Merge Risk:
|
There was a problem hiding this comment.
LGTM — a pure deletion of two member functions with no callers; declarations go with definitions, so any missed caller would fail to compile rather than silently change behavior.
What was reviewed:
- Searched src/ and packages/ for
isWrapModeandpop_back: the onlyisWrapModecall (JSCipherConstructor.cpp:196) is on aCipher, whose method is untouched; remainingpop_backcalls are on std containers. - Checked that neither symbol is a C++ member that Rust could import via
extern "C", and that no generated binding names them. - CODEOWNERS does not cover ncrypto.cpp/.h.
Extended reasoning...
The change removes 17 lines from src/jsc/bindings/ncrypto.cpp and ncrypto.h: the definition and declaration of CryptoErrorList::pop_back and CipherCtxPointer::isWrapMode, with nothing added or modified. It touches the crypto bindings layer, but only by deleting dead code, so no cipher, key, or error-handling behavior changes. Repo-wide search confirms no remaining callers, the identically named Cipher::isWrapMode is a different class and keeps its caller, and a missed call site would be a compile error, not a runtime regression. The bug hunt ran dry, no CODEOWNER covers these files, and there are no open objections, which decided approve.
…ar*, size_t) #47671 replaced the last four callers in node/crypto/CryptoPrimes.cpp with bignumOption(). No other code calls the two-argument overload.
There was a problem hiding this comment.
LGTM — pure deletion of three unreferenced member functions, declarations and definitions removed together, so any missed caller would fail to compile rather than misbehave.
What was reviewed:
- Searched all of
src/andpackages/forisWrapMode,pop_back(),BN_bin2bn, and two-argument.reset(calls: the onlyisWrapMode()caller (src/jsc/bindings/node/crypto/JSCipherConstructor.cpp:196) is onCipher, whose ownisWrapModeis untouched; noCryptoErrorList::pop_backorBignumPointer::reset(data, len)call sites exist, including platform-gated code. - The latest commit (8731992) also removes
BignumPointer::reset(const unsigned char*, size_t), which the PR title and description do not mention — worth adding to the description for the record. - Build/link and tests were not run in this review; the no-caller conclusion rests on reading and repo-wide search.
Extended reasoning...
The diff removes 23 lines from src/jsc/bindings/ncrypto.cpp and ncrypto.h: CryptoErrorList::pop_back, the two-argument BignumPointer::reset overload, and CipherCtxPointer::isWrapMode, with no additions and no changes to any live function. It touches the crypto helper layer but only deletes definitions with no callers, so there is no reachable behavior or security surface change. Repo-wide search confirmed no remaining references in src/ or packages/ and that the still-used Cipher::isWrapMode is a different class's method left intact. The changed files are not covered by CODEOWNERS, and since the prior review the PR gained a merge of main plus one additional equally mechanical deletion. The mechanical nature of the change and compile-time enforcement of the no-caller claim decided approval.
CryptoErrorList::pop_back and CipherCtxPointer::isWrapModeCryptoErrorList::pop_back, CipherCtxPointer::isWrapMode, and a BignumPointer::reset overload
Behaviour change: none
Problem
src/jsc/bindings/ncrypto.cpphave no caller:CryptoErrorList::pop_back(),CipherCtxPointer::isWrapMode()andBignumPointer::reset(const unsigned char*, size_t).errorStack.pop_back()(node/crypto/CryptoUtil.cpp). node:crypto, webcrypto: a third batch of Node compatibility fixes #47591 removedm_ctx.isWrapMode()(node/crypto/JSCipherPrototype.cpp). node:crypto, webcrypto: a fourth batch of Node compatibility fixes #47671 removed four two-argumentresetcalls (node/crypto/CryptoPrimes.cpp).Fix
ncrypto.cppandncrypto.h, no added line.bun bdbuilds and links.BignumPointer::reset(BIGNUM*)andCipher::isWrapMode()(a method of another class) keep their callers.bun bd, then eight crypto test files (1233 tests pass) and 28 Node.jstest-crypto-*files (Notes).Background
ncryptois Bun's copy of the OpenSSL wrapper classes of Node.js.CryptoErrorListcaptures the OpenSSL error queue.CipherCtxPointerowns anEVP_CIPHER_CTX.BignumPointerowns aBIGNUM.Downsides
Notes
What is removed (line numbers on
main2596ac5)src/jsc/bindings/ncrypto.cpp:CryptoErrorList::pop_back()(97-104),BignumPointer::reset(const unsigned char*, size_t)(261-265) andCipherCtxPointer::isWrapMode()(2922-2927), each with the blank line after it.src/jsc/bindings/ncrypto.h: the three declarations (122 with one blank line, 554 and 640).Commits
pop_back()andisWrapMode().main(2596ac5) brings node:crypto, webcrypto: a fourth batch of Node compatibility fixes #47671 into the branch.resetoverload. It cannot come before the merge, because the first base still has the four callers.Checks (on the merged head, unless a line names another commit)
rg -w pop_backoversrc/andpackages/finds three calls. Each is on a standard container:sni_tree.cpp:65,Http2Context.h:887andlint_js.rs:923.rg isWrapModefindsCipher::isWrapMode()(definition, declaration, and its call atnode/crypto/JSCipherConstructor.cpp:196) and nothing else.src/andpackages/for aresetwith two or more arguments findsDataPointer::reset(void*, size_t)(called atncrypto.cpp:165) and the grapheme state classes ofsliceAnsi.cppandstringWidth.cpp. No call is on aBignumPointer.bun bd(debug, ASAN) builds and links.clang-format(LLVM 23) reports nothing on the two files.ncrypto.cpponmain: 503 bytes (pop_back), 124 bytes (isWrapMode) and 88 bytes (reset).-Wl,--gc-sectionsdropped the first two functions (on the first base, 6cdb383). I made no such relink for theresetoverload.-Wl,--gc-sectionson Linux,-dead_stripon macOS and/OPT:REFon Windows (scripts/build/flags.ts).mainbuild 138398. Its 12 numbers equal those of build 138422 (docs: say thatmock.restore()restores spies and leaves other mocks as they are #48153, documentation only) and of build 138485 (test: wait for the warmup stream's descriptor to close in tty.test.ts #48167, one test file).test/js/node/crypto/node-crypto.test.js(326),crypto.test.ts(467),crypto.key-objects.test.ts(112),crypto-rsa.test.js(45),x509.test.ts(62),ecdh.test.ts(16),crypto-random.test.ts(27) andtest/js/web/crypto/web-crypto.test.ts(178).crypto-random.test.ts, directly after the build,randomInt does not call RAND_bytes per iterationreached the 5 s limit. It passes alone in 1.1 s and in the second run of the file.test/js/node/test/parallel/exit with 0. For ciphers and signatures:test-crypto-cipheriv-decipheriv.js,test-crypto-authenticated.js,test-crypto-authenticated-stream.js,test-crypto-padding.js,test-crypto-padding-aes256.js,test-crypto-aes-wrap.js,test-crypto-des3-wrap.js,test-crypto-getcipherinfo.js,test-crypto-key-objects.js,test-crypto-sign-verify.jsandtest-crypto-rsa-dsa.js.test-crypto-prime.js,test-crypto-random.js,test-crypto-ecdh-convert-key.js,test-crypto-keygen-dh-classic.js,test-crypto-dh.jsand the 12 filestest-crypto-dh-*.js(constructor,curves,errors,generate-keys,group-setters,leak,modp2,modp2-views,odd-key,padding,shared,stateless).test-crypto-dh-leak.jsbecause the build has ASAN.main(6cdb383) and on the first commit.bun run rust:check-alldoes not apply.Open pull requests
resetoverload (2026-11-08): I read the diffs of the 49 open pull requests that namencrypto,BignumPointer,CryptoPrimesorBN_bin2bn. None deletes the overload and none adds a call. crypto: accept ArrayBuffer and SharedArrayBuffer for generatePrime options.add/rem #38680 deletes the four old callers, as node:crypto, webcrypto: a fourth batch of Node compatibility fixes #47671 did.pop_back()one day earlier and left it, because Remove dead code from the JSC, WebCore, and node bindings, uWS/uSockets, SecretsLinux, and seven Rust crates #42431 deletes the two lines above its declaration (rbegin(),rend()). This diff does not touch those lines, and a three-way merge with Remove dead code from the JSC, WebCore, and node bindings, uWS/uSockets, SecretsLinux, and seven Rust crates #42431 has no conflict inncrypto.h.ncrypto.cpp,ncrypto.horCryptoPrimes.cpp. For each, a trial merge with this branch conflicts in the same files as a trial merge withmain. Six merge cleanly with both: crypto: port OpenSSL's prime search for generatePrime with add #37963, node:crypto: implement encapsulate() and decapsulate() #40550, crypto: apply a UTCTime timezone offset in the X509Certificate validity strings and Dates #42415, node:crypto: keep the sign/verifycontextbytes on the job and decide support in runTask #45621, Remove dead code from JSDOMWrapper.h and ncrypto.cpp: two preprocessor blocks that never compile #48067 and node:crypto: refuse BLAKE2b for RSA signatures, read detached buffers as empty, name the key argument like Node #48086.Found dead in this run, and left alone
ncrypto, named by code but never true:Cipher::isWrapMode(),CipherCtxPointer::setAllowWrap()and the branch atJSCipherConstructor.cpp:196. BoringSSL never returnsEVP_CIPH_WRAP_MODE(vendor/boringssl/include/openssl/cipher.h:425). The sweep removes what no code names, so these stay.ncrypto, unused but not a plain deletion:CryptoErrorList::empty(), theOptionenum, and theCryptoErrorList*parameter ofClearErrorOnReturnandMarkPopErrorOnReturn(no guard passes one). They are not left over from node:crypto, webcrypto, tls: more Node compatibility fixes #47567, node:crypto, webcrypto: a third batch of Node compatibility fixes #47591 or node:crypto, webcrypto: a fourth batch of Node compatibility fixes #47671, and the removal edits live constructors.rbegin()andrend()are in Remove dead code from the JSC, WebCore, and node bindings, uWS/uSockets, SecretsLinux, and seven Rust crates #42431.ncrypto, special member functions with no caller: the default and move constructors andrelease()ofECDSASigPointer,ECGroupPointerandECPointPointer, and the move constructor ofHMACCtxPointer. The removal makes the classes non-movable. That needs a maintainer's decision.PerformanceResourceTiming::createhas no caller, so its constructor, theResourceTimingconstructor,populateServerTimingandPerformanceServerTiming::createnever run. Remove dead code: 15 trait impls nothing uses and two C++ overloads #47264 held them because Remove dead code from bun_core, the JSC bindings, the debugger, and 24 other crates #41385 deletes a line inside theResourceTimingconstructor. The cut also leavesResourceTiming.cppwith one allocator macro andServerTiming.hwith no user butServerTiming.cpp, which Remove dead code from the build scripts, the vscode and debug-adapter packages, the bake overlay, and two WebCore files #40122 deletes. The unit needs one pull request of its own and a maintainer's answer: keep the classes forperformance.markResourceTiming(), or reduce them to the two globals. (State of 2026-11-02.)IDLByte,IDLShortandIDLLongLong, 14convertToInteger*specializations withtoSmallerInt, and eightJSConverterspecializations that nothing onmaininstantiates (365 lines). bindgen: deleteb.anyand.variadic#46789 maps the bindgeni64toIDLLongLong, and the bun:dom draft bun:dom and the Vitest work in one tree (not for merging) #45415 uses the rest. Remove dead code from ZigGlobalObject, FuzzilliREPRL.cpp, BunBuiltinNames.h and launch.json #47672, Remove dead code from the zsh completions, the SQLite lazy loader, and the C++ bindings #47439 and Remove dead code from headers.h, the REPL shims, builtin-names.ts and the builtins code generator: what #45631 left unused #47324 held them for the same reason. (State of 2026-11-02.)src/jsc/bindingsandpackages/(on 6cdb383). An open pull request deletes at least 169 of them (Remove dead code from the JSC bindings, headers.h, the console builtin, and bun_jsc #40232 has 45, Remove dead code from the WebCore bindings, the JSSink codegen, and two Rust helpers #39929 has 43). Others have a user that the Linux debug link does not see:bsd_socket_export,bsd_socket_import,us_loop_integrateanduws_get_loop_with_native(Windows),Bun__prepareTrimmedExecutableandposix_spawnattr_reset_signals(macOS),Bun__askForAddressSpaceToStart(builds without ASAN),JSPerformanceEntry::subspaceForImpl(builds without assertions),Bun__CallFrame__describeFrame(the lldbbtjscommand) andJSC__ArrayBuffer__ref(a required trait method).bun_sys::windows_impl::umask,UvHandle::data,bun_errno::posix::mode_tandMEMORYSTATUS_PRESSURE_NORMALare 17 lines and stay for a later run.bun_zstd::inflate_embedded*looks unused, but a macro arm undercfg(bun_codegen_embed)calls it. 52 trait impls that the linker drops were not tested. Remove dead code: 15 trait impls nothing uses and two C++ overloads #47264 tested 84 of that kind and the compiler needed 68.The self-review
ncryptofunctions alone, the resource timing constructors held.resetoverload joined after the review. It has the shape the review asked for: one definition and one declaration with no caller, in the same two files.main, or restore files on the branches of Remove dead code from bun_core, the JSC bindings, the debugger, and 24 other crates #41385 and Remove dead code from the build scripts, the vscode and debug-adapter packages, the bake overlay, and two WebCore files #40122 to release their lines. The sweep must not repeat a deletion of an open pull request. That question is with a maintainer.The Rust probe, for the next run
#[deprecated(note = "<id>")]went on 16,839 items: each function with no symbol in the--gc-sectionslink, each module-levelconst,staticand type alias, and each struct, enum and trait with no live method. Thencargo check --workspace --all-targetsran for Linux, Windows and macOS with the lint atwarn. Each warning is one use. An item that no code outside the set reaches has no user. One pass takes about 8 minutes.bun_ptrallowsdeprecatedfor the whole crate. A file can start with#![cfg(...)]. Aconst fnand an#[inline(always)]function have no symbol. A macro arm under acfgthat no check enables hides its uses.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