From 9d58ed10ad50a545f52cefc173c4fc59cbaf6e33 Mon Sep 17 00:00:00 2001 From: robobun <117481402+robobun@users.noreply.github.com> Date: Sat, 1 Aug 2026 16:22:16 +0000 Subject: [PATCH 01/15] Remove dead code from napi/NodeVM C++, libuv platform headers, zlib, io, net.ts C++ (src/jsc/bindings/): - napi: generateSourceCode() (26 LOC, zero callers); NapiWeakValue isSet/isPrimitive/isCell/isString/cell()/primitive()/string() accessors (23 LOC, only get() is used); NapiClass::destroy (unreachable with DoesNotNeedDestruction) - NodeVM: NodeVMGlobalObject::clearContextifiedObject, NodeVMModuleRequest::addImportAttribute + specifier() setter, NodeVM{SourceText,Synthetic}Module::hasModuleRecord, NodeVMScript::cachedBytecode (all zero callers) - JSBufferList: empty Constructor::initializeProperties, unreachable destroy - JSStringDecoder: Constructor::initializeProperties (never called; finishCreation does the same work) - BunClientData: JSVMClientData's duplicate outputConstraintSpaces/ forEachOutputConstraintSpace/m_outputConstraintSpaces (only JSHeapData's copies are called by BunGCOutputConstraint and subspaceForImpl) - EventLoopTask: m_isCleanupTask field + isCleanupTask() + CleanupTaskTag constructor (field written but never read; DeleteCallbackDataTask now uses the primary templated constructor) - JSEnvironmentVariableMap: jsSetterEnvironmentVariable (registered with nullptr setter; only referenced in a comment) - JSNextTickQueue::initialValues (never invoked by finishCreation) - JSBuffer.cpp: commented-out jsBufferPrototypeToStringWithoutTypeChecks DOMJIT block (23 LOC, unchanged since Jan 2025) - blob.h: unused BlobRef type alias - Bindgen/IDLTypes.h: unused IsIDLStrongAny trait libuv (src/jsc/bindings/libuv/uv/): - aix.h (32), os390.h (33), sunos.h (44), posix.h (31): bun never targets AIX/zOS/Solaris/IBMi/Cygwin/QNX/Haiku/Hurd. Kept bsd.h (FreeBSD is a real build profile). Matching #elif arms removed from unix.h and dead comment block removed from uv-posix-polyfills.c. Rust: - src/zlib/error.rs (whole file, 31 LOC): unused Error/Result; the crate uses ZlibError defined in lib.rs instead - src/zlib/lib.rs: drop Byte/gzFile/struct_gzFile_s/voidpf from the bun_zlib_sys re-export (zero Rust-side references) - src/io/windows_event_loop.rs: FilePoll::ref_/activate/can_ref (30 LOC, zero callers across all targets; verified with rust:check-all) - src/install/lockfile: commented-out Stringifier::save stub in bun.lock.rs; empty #[cfg(debug_assertions)] blocks in Buffers.rs left by commented-out debug prints TypeScript: - src/js/node/net.ts: kpendingRead and kServerSocket Symbols (defined, written once each, never read) Verified with bun bd (builds clean) and bun run rust:check-all (10/10 targets pass). --- src/install/lockfile/Buffers.rs | 15 --- src/install/lockfile/bun.lock.rs | 4 - src/io/windows_event_loop.rs | 30 ------ src/js/node/net.ts | 4 - src/jsc/bindings/Bindgen/IDLTypes.h | 3 - src/jsc/bindings/BunClientData.h | 9 -- src/jsc/bindings/DeleteCallbackDataTask.h | 2 +- src/jsc/bindings/EventLoopTask.h | 13 --- src/jsc/bindings/JSBuffer.cpp | 24 ----- src/jsc/bindings/JSBufferList.cpp | 4 - src/jsc/bindings/JSBufferList.h | 3 - src/jsc/bindings/JSEnvironmentVariableMap.cpp | 23 +--- src/jsc/bindings/JSNextTickQueue.h | 9 -- src/jsc/bindings/JSStringDecoder.cpp | 9 -- src/jsc/bindings/JSStringDecoder.h | 2 - src/jsc/bindings/NodeVM.cpp | 5 - src/jsc/bindings/NodeVM.h | 1 - src/jsc/bindings/NodeVMModule.cpp | 5 - src/jsc/bindings/NodeVMModule.h | 2 - src/jsc/bindings/NodeVMScript.h | 1 - src/jsc/bindings/NodeVMSourceTextModule.h | 1 - src/jsc/bindings/NodeVMSyntheticModule.h | 1 - src/jsc/bindings/blob.h | 1 - src/jsc/bindings/libuv/uv/aix.h | 32 ------ src/jsc/bindings/libuv/uv/os390.h | 33 ------ src/jsc/bindings/libuv/uv/posix.h | 31 ------ src/jsc/bindings/libuv/uv/sunos.h | 44 -------- src/jsc/bindings/libuv/uv/unix.h | 10 -- src/jsc/bindings/napi.cpp | 26 ----- src/jsc/bindings/napi.h | 29 ----- src/jsc/bindings/uv-posix-polyfills.c | 10 -- src/zlib/error.rs | 31 ------ src/zlib/lib.rs | 5 +- .../dead-symbols-napi-nodevm-libuv.test.ts | 102 ++++++++++++++++++ 34 files changed, 108 insertions(+), 416 deletions(-) delete mode 100644 src/jsc/bindings/libuv/uv/aix.h delete mode 100644 src/jsc/bindings/libuv/uv/os390.h delete mode 100644 src/jsc/bindings/libuv/uv/posix.h delete mode 100644 src/jsc/bindings/libuv/uv/sunos.h delete mode 100644 src/zlib/error.rs create mode 100644 test/internal/source-lints/dead-symbols-napi-nodevm-libuv.test.ts diff --git a/src/install/lockfile/Buffers.rs b/src/install/lockfile/Buffers.rs index 2cc3d333dcb8..aaff4491083c 100644 --- a/src/install/lockfile/Buffers.rs +++ b/src/install/lockfile/Buffers.rs @@ -236,10 +236,6 @@ where let mut clone: Vec<$elem> = Vec::with_capacity(buffers.$field.len()); clone.extend_from_slice(buffers.$field.as_slice()); write_array(stream, clone.as_slice(), $prefix)?; - #[cfg(debug_assertions)] - { - // Output::pretty_errorln(format_args!("Field {}: {} - {}", $name, pos, stream.get_pos()?)); - } }}; } @@ -264,10 +260,6 @@ where // reader ignores this string; only the exact bytes matter. "\n 20 sizeof, 4 alignof\n", )?; - #[cfg(debug_assertions)] - { - // Output::pretty_errorln(format_args!("Field {}: {} - {}", "trees", pos, stream.get_pos()?)); - } } // -- hoisted_dependencies -- @@ -349,11 +341,6 @@ where to_clone.as_slice(), "\n<[26]u8> 26 sizeof, 1 alignof\n", )?; - - #[cfg(debug_assertions)] - { - // Output::pretty_errorln(format_args!("Field {}: {} - {}", "dependencies", pos, stream.get_pos()?)); - } } // -- extern_strings -- @@ -427,8 +414,6 @@ pub(crate) fn load( bun_core::pretty_errorln!("Loaded {} {}", this.$field.len(), $name); } } - // #[cfg(debug_assertions)] - // Output::pretty_errorln(format_args!("Field {}: {} - {}", $name, _pos, stream.get_pos()?)); }}; } diff --git a/src/install/lockfile/bun.lock.rs b/src/install/lockfile/bun.lock.rs index ada9255061ad..7a26bc2d3f40 100644 --- a/src/install/lockfile/bun.lock.rs +++ b/src/install/lockfile/bun.lock.rs @@ -165,10 +165,6 @@ pub(crate) struct Stringifier; impl Stringifier { const INDENT_SCALAR: usize = 2; - // pub fn save(this: &Lockfile) { - // let _ = this; - // } - pub(crate) fn save_from_binary( lockfile: &mut BinaryLockfile, load_result: &LoadResult, diff --git a/src/io/windows_event_loop.rs b/src/io/windows_event_loop.rs index 2d7edb3c9d62..72e1107fad7c 100644 --- a/src/io/windows_event_loop.rs +++ b/src/io/windows_event_loop.rs @@ -155,36 +155,6 @@ impl FilePoll { vm.loop_add_active(self.flags.contains(Flags::HasIncrementedPollCount) as u32); } - - /// Only intended to be used from EventLoop.Pollable - pub fn activate(&mut self, loop_: &mut WindowsLoop) { - loop_.add_active( - (!self.flags.contains(Flags::Closed) - && !self.flags.contains(Flags::HasIncrementedPollCount)) as u32, - ); - bun_core::scoped_log!(FilePoll, "activate - {}", loop_.uv().active_handles); - self.flags.insert(Flags::HasIncrementedPollCount); - } - - #[inline] - pub fn can_ref(&self) -> bool { - if self.flags.contains(Flags::Closed) { - return false; - } - - !self.flags.contains(Flags::HasIncrementedPollCount) - } - - /// Allow a poll to keep the process alive. - // pub fn ref(this: *FilePoll, vm: *jsc.VirtualMachine) void { - pub fn ref_(&mut self, event_loop_ctx: EventLoopCtx) { - if self.can_ref() { - return; - } - bun_core::scoped_log!(FilePoll, "ref"); - // this.activate(vm.event_loop_handle.?); - self.activate(event_loop_ctx.loop_mut()); - } } type FilePollHiveArray = bun_collections::hive_array::Fallback; diff --git a/src/js/node/net.ts b/src/js/node/net.ts index 5125e380715f..86e53f48a82f 100644 --- a/src/js/node/net.ts +++ b/src/js/node/net.ts @@ -122,7 +122,6 @@ const bunTlsSymbol = Symbol.for("::buntls::"); const bunSocketServerOptions = Symbol.for("::bunnetserveroptions::"); const owner_symbol = Symbol("owner_symbol"); -const kServerSocket = Symbol("kServerSocket"); const kBytesWritten = Symbol("kBytesWritten"); const bunTLSConnectOptions = Symbol.for("::buntlsconnectoptions::"); // tls.Server exposes its native SecureContext constructor through this key so @@ -141,7 +140,6 @@ const kSetKeepAliveInitialDelay = Symbol("kSetKeepAliveInitialDelay"); const kConnectOptions = Symbol("connect-options"); const kAttach = Symbol("kAttach"); const kCloseRawConnection = Symbol("kCloseRawConnection"); -const kpendingRead = Symbol("kpendingRead"); const kupgraded = Symbol("kupgraded"); const kAdoptedTLSRaw = Symbol("kAdoptedTLSRaw"); const ksocket = Symbol("ksocket"); @@ -1125,7 +1123,6 @@ function onconnection(err, clientHandle) { self.emit("error", err); return; } - clientHandle[kServerSocket] = handle; const options = self[bunSocketServerOptions]; const { pauseOnConnect, connectionListener, [kSocketClass]: SClass } = options; // Propagate the server's half-open/highWaterMark settings to the accepted @@ -1556,7 +1553,6 @@ function Socket(options?) { }); this._parent = null; this._parentWrap = null; - this[kpendingRead] = undefined; this[kupgraded] = null; this[kSetNoDelay] = Boolean(noDelay); diff --git a/src/jsc/bindings/Bindgen/IDLTypes.h b/src/jsc/bindings/Bindgen/IDLTypes.h index d0275d9fb0cd..93089efbe6e6 100644 --- a/src/jsc/bindings/Bindgen/IDLTypes.h +++ b/src/jsc/bindings/Bindgen/IDLTypes.h @@ -17,9 +17,6 @@ struct IDLStrongAny : WebCore::IDLType { } }; -template -struct IsIDLStrongAny : std::integral_constant::value> {}; - // Dictionaries that contain raw `JSValue`s must live on the stack. template struct IDLStackOnlyDictionary : WebCore::IDLType { diff --git a/src/jsc/bindings/BunClientData.h b/src/jsc/bindings/BunClientData.h index 8130d1862ff2..200d3bf1ee0e 100644 --- a/src/jsc/bindings/BunClientData.h +++ b/src/jsc/bindings/BunClientData.h @@ -109,8 +109,6 @@ class JSVMClientData : public JSC::VM::ClientData { ExtendedDOMClientIsoSubspaces& clientSubspaces() { return *m_clientSubspaces.get(); } - Vector& outputConstraintSpaces() { return m_outputConstraintSpaces; } - JSC::GCClient::IsoSubspace& domBuiltinConstructorSpace() { return m_domBuiltinConstructorSpace; } // Constructed eagerly so the concurrent GC marker @@ -120,12 +118,6 @@ class JSVMClientData : public JSC::VM::ClientData { // so there is no startup cost worth deferring. WebCore::HTTPHeaderIdentifiers& httpHeaderIdentifiers() { return m_httpHeaderIdentifiers; } - template void forEachOutputConstraintSpace(const Func& func) - { - for (auto* space : m_outputConstraintSpaces) - func(*space); - } - void* bunVM; Bun::JSCTaskScheduler deferredWorkTimer; @@ -178,7 +170,6 @@ class JSVMClientData : public JSC::VM::ClientData { JSC::GCClient::IsoSubspace m_domNamespaceObjectSpace; std::unique_ptr m_clientSubspaces; - Vector m_outputConstraintSpaces; WebCore::HTTPHeaderIdentifiers m_httpHeaderIdentifiers; }; diff --git a/src/jsc/bindings/DeleteCallbackDataTask.h b/src/jsc/bindings/DeleteCallbackDataTask.h index e80ddf6fc75d..fddc4ba9c12a 100644 --- a/src/jsc/bindings/DeleteCallbackDataTask.h +++ b/src/jsc/bindings/DeleteCallbackDataTask.h @@ -6,7 +6,7 @@ class DeleteCallbackDataTask : public EventLoopTask { public: template explicit DeleteCallbackDataTask(CallbackDataType* data) - : EventLoopTask(EventLoopTask::CleanupTask, [data](ScriptExecutionContext&) mutable { + : EventLoopTask([data](ScriptExecutionContext&) mutable { delete data; }) { diff --git a/src/jsc/bindings/EventLoopTask.h b/src/jsc/bindings/EventLoopTask.h index 021c39b1a17e..dc3ffe2aeb93 100644 --- a/src/jsc/bindings/EventLoopTask.h +++ b/src/jsc/bindings/EventLoopTask.h @@ -7,25 +7,14 @@ class EventLoopTask { WTF_MAKE_TZONE_ALLOCATED(EventLoopTask); public: - enum CleanupTaskTag { CleanupTask }; - template::value && std::is_convertible>::value>::type> EventLoopTask(T task) : m_task(WTF::move(task)) - , m_isCleanupTask(false) { } EventLoopTask(Function&& task) : m_task([task = WTF::move(task)](ScriptExecutionContext&) { task(); }) - , m_isCleanupTask(false) - { - } - - template>::value>::type> - EventLoopTask(CleanupTaskTag, T task) - : m_task(WTF::move(task)) - , m_isCleanupTask(true) { } @@ -34,11 +23,9 @@ class EventLoopTask { m_task(context); delete this; } - bool isCleanupTask() const { return m_isCleanupTask; } protected: Function m_task; - bool m_isCleanupTask; }; } diff --git a/src/jsc/bindings/JSBuffer.cpp b/src/jsc/bindings/JSBuffer.cpp index 9d777bf9733b..6c44fd1949a4 100644 --- a/src/jsc/bindings/JSBuffer.cpp +++ b/src/jsc/bindings/JSBuffer.cpp @@ -2391,30 +2391,6 @@ static JSC::EncodedJSValue jsBufferPrototypeFunction_SliceWithEncoding(JSC::JSGl return jsBufferToString(lexicalGlobalObject, scope, castedThis, start, end - start, encoding); } -// DOMJIT makes it slower! TODO: investigate why -// JSC_DECLARE_JIT_OPERATION_WITHOUT_WTF_INTERNAL(jsBufferPrototypeToStringWithoutTypeChecks, JSValue, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::JSUint8Array* thisValue, JSC::JSString* encodingValue)); - -// JSC_DEFINE_JIT_OPERATION(jsBufferPrototypeToStringWithoutTypeChecks, JSValue, (JSC::JSGlobalObject * lexicalGlobalObject, JSUint8Array* thisValue, JSString* encodingValue)) -// { -// auto& vm = JSC::getVM(lexicalGlobalObject); -// IGNORE_WARNINGS_BEGIN("frame-address") -// CallFrame* callFrame = DECLARE_CALL_FRAME(vm); -// IGNORE_WARNINGS_END -// JSC::JITOperationPrologueCallFrameTracer tracer(vm, callFrame); - -// std::optional encoded = parseEnumeration(*lexicalGlobalObject, encodingValue); -// if (!encoded) { -// auto scope = DECLARE_THROW_SCOPE(vm); - -// throwTypeError(lexicalGlobalObject, scope, "Invalid encoding"_s); -// return {}; -// } - -// auto encoding = encoded.value(); - -// return JSValue::decode(jsBufferToString(vm, lexicalGlobalObject, thisValue, 0, thisValue->byteLength(), encoding)); -// } - // https://github.com/nodejs/node/blob/v26.3.0/lib/internal/buffer.js#L962-L990 // Only utf8Write/latin1Write/asciiWrite go through this strict JS wrapper in node; // the other encodings use jsBufferPrototypeFunction_StringWriteWithEncoding below. diff --git a/src/jsc/bindings/JSBufferList.cpp b/src/jsc/bindings/JSBufferList.cpp index 11cc614b7eb6..90483db6942d 100644 --- a/src/jsc/bindings/JSBufferList.cpp +++ b/src/jsc/bindings/JSBufferList.cpp @@ -456,10 +456,6 @@ JSC::EncodedJSValue JSBufferListConstructor::construct(JSC::JSGlobalObject* lexi return JSC::JSValue::encode(bufferList); } -void JSBufferListConstructor::initializeProperties(VM& vm, JSC::JSGlobalObject* globalObject, JSBufferListPrototype* prototype) -{ -} - const ClassInfo JSBufferListConstructor::s_info = { "BufferList"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSBufferListConstructor) }; } // namespace Zig diff --git a/src/jsc/bindings/JSBufferList.h b/src/jsc/bindings/JSBufferList.h index 1c8e89ff121a..c3e6773808fe 100644 --- a/src/jsc/bindings/JSBufferList.h +++ b/src/jsc/bindings/JSBufferList.h @@ -45,7 +45,6 @@ class JSBufferList : public JSC::JSNonFinalObject { } void finishCreation(JSC::VM& vm, JSC::JSGlobalObject* globalObject); - static void destroy(JSCell*) {} inline size_t length() { return m_deque.size(); } void push(JSC::VM& vm, JSC::JSValue v) @@ -153,8 +152,6 @@ class JSBufferListConstructor final : public JSC::InternalFunction { return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::InternalFunctionType, StructureFlags), info()); } - void initializeProperties(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSBufferListPrototype* prototype); - // Must be defined for each specialization class. static JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES construct(JSC::JSGlobalObject*, JSC::CallFrame*); DECLARE_EXPORT_INFO; diff --git a/src/jsc/bindings/JSEnvironmentVariableMap.cpp b/src/jsc/bindings/JSEnvironmentVariableMap.cpp index fc29c4c824fa..51a979530c98 100644 --- a/src/jsc/bindings/JSEnvironmentVariableMap.cpp +++ b/src/jsc/bindings/JSEnvironmentVariableMap.cpp @@ -61,21 +61,6 @@ JSC_DEFINE_CUSTOM_GETTER(jsGetterEnvironmentVariable, (JSGlobalObject * globalOb return JSValue::encode(result); } -JSC_DEFINE_CUSTOM_SETTER(jsSetterEnvironmentVariable, (JSGlobalObject * globalObject, JSC::EncodedJSValue thisValue, JSC::EncodedJSValue value, PropertyName propertyName)) -{ - VM& vm = globalObject->vm(); - JSC::JSObject* object = JSValue::decode(thisValue).getObject(); - if (!object) - return false; - - auto string = JSValue::decode(value).toString(globalObject); - if (!string) [[unlikely]] - return false; - - object->putDirect(vm, propertyName, string, 0); - return true; -} - // Proxy-related env vars (HTTP_PROXY, HTTPS_PROXY, NO_PROXY and lowercase // variants) are read by fetch()'s native proxy resolution via // env_loader.getHttpProxyFor(). Writes from JS must sync back to the native env @@ -119,10 +104,10 @@ JSC_DEFINE_CUSTOM_SETTER(jsSetterProxyEnvironmentVariable, (JSGlobalObject * glo Bun__setEnvValue(globalObject, &name, &val); // The proxy-var accessors are added with `DontEnum` when the var was not - // present in the OS env at startup. The regular env-var setter - // (`jsSetterEnvironmentVariable`) makes a written var enumerable by - // replacing the accessor with a data property; this setter keeps the - // accessor (so the native env map stays the source of truth) but must + // present in the OS env at startup. The regular env-var getter makes a + // written var enumerable by replacing the accessor with a data property; + // this setter keeps the accessor (so the native env map stays the source + // of truth) but must // still clear `DontEnum` — otherwise `process.env.HTTP_PROXY = "..."` // followed by `Bun.spawn({env: {...process.env}})` silently drops the var // (the spread skips non-enumerable properties). diff --git a/src/jsc/bindings/JSNextTickQueue.h b/src/jsc/bindings/JSNextTickQueue.h index 5237e9b3b77d..0fa25d43bb69 100644 --- a/src/jsc/bindings/JSNextTickQueue.h +++ b/src/jsc/bindings/JSNextTickQueue.h @@ -18,15 +18,6 @@ class JSNextTickQueue : public JSC::JSInternalFieldObjectImpl<3> { static JSNextTickQueue* create(JSC::JSGlobalObject* globalObject); static Structure* createStructure(VM&, JSGlobalObject*, JSValue); - static std::array initialValues() - { - return { { - jsNumber(-1), - jsUndefined(), - jsUndefined(), - } }; - } - DECLARE_EXPORT_INFO; DECLARE_VISIT_CHILDREN; diff --git a/src/jsc/bindings/JSStringDecoder.cpp b/src/jsc/bindings/JSStringDecoder.cpp index 7ba39e9249ea..c1fea1e60a05 100644 --- a/src/jsc/bindings/JSStringDecoder.cpp +++ b/src/jsc/bindings/JSStringDecoder.cpp @@ -605,15 +605,6 @@ JSC::EncodedJSValue JSStringDecoderConstructor::construct(JSC::JSGlobalObject* l return JSC::JSValue::encode(jsObject); } -void JSStringDecoderConstructor::initializeProperties(VM& vm, JSC::JSGlobalObject* globalObject, JSStringDecoderPrototype* prototype) -{ - putDirect(vm, vm.propertyNames->length, jsNumber(1), JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum); - JSString* nameString = jsNontrivialString(vm, "StringDecoder"_s); - m_originalName.set(vm, this, nameString); - putDirect(vm, vm.propertyNames->name, nameString, JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum); - putDirect(vm, vm.propertyNames->prototype, prototype, JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::DontDelete); -} - const ClassInfo JSStringDecoderConstructor::s_info = { "StringDecoder"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSStringDecoderConstructor) }; } // namespace Zig diff --git a/src/jsc/bindings/JSStringDecoder.h b/src/jsc/bindings/JSStringDecoder.h index 12fe89bf25ea..88b75417414e 100644 --- a/src/jsc/bindings/JSStringDecoder.h +++ b/src/jsc/bindings/JSStringDecoder.h @@ -110,8 +110,6 @@ class JSStringDecoderConstructor final : public JSC::InternalFunction { return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::InternalFunctionType, StructureFlags), info()); } - void initializeProperties(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSStringDecoderPrototype* prototype); - // Must be defined for each specialization class. static JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES construct(JSC::JSGlobalObject*, JSC::CallFrame*); DECLARE_EXPORT_INFO; diff --git a/src/jsc/bindings/NodeVM.cpp b/src/jsc/bindings/NodeVM.cpp index 4af8172edc49..804043886410 100644 --- a/src/jsc/bindings/NodeVM.cpp +++ b/src/jsc/bindings/NodeVM.cpp @@ -1111,11 +1111,6 @@ void NodeVMGlobalObject::setContextifiedObject(JSC::JSObject* contextifiedObject m_sandbox.set(vm(), this, contextifiedObject); } -void NodeVMGlobalObject::clearContextifiedObject() -{ - m_sandbox.clear(); -} - void NodeVMGlobalObject::sigintReceived() { vm().notifyNeedTermination(); diff --git a/src/jsc/bindings/NodeVM.h b/src/jsc/bindings/NodeVM.h index fc9b555552ed..9b9076eece83 100644 --- a/src/jsc/bindings/NodeVM.h +++ b/src/jsc/bindings/NodeVM.h @@ -135,7 +135,6 @@ class NodeVMGlobalObject final : public Bun::GlobalScope { static void destroy(JSCell* cell); void setContextifiedObject(JSC::JSObject* contextifiedObject); JSObject* contextifiedObject() const { return m_sandbox.get(); } - void clearContextifiedObject(); void sigintReceived(); bool isNotContextified() const { return m_contextOptions.notContextified; } bool hasOwnMicrotaskQueue() const { return m_contextOptions.ownMicrotaskQueue; } diff --git a/src/jsc/bindings/NodeVMModule.cpp b/src/jsc/bindings/NodeVMModule.cpp index ebb0e31a5990..35397a27d5fa 100644 --- a/src/jsc/bindings/NodeVMModule.cpp +++ b/src/jsc/bindings/NodeVMModule.cpp @@ -20,11 +20,6 @@ NodeVMModuleRequest::NodeVMModuleRequest(WTF::String specifier, WTF::HashMapvm(); diff --git a/src/jsc/bindings/NodeVMModule.h b/src/jsc/bindings/NodeVMModule.h index a0840b85086b..44f0b509d70d 100644 --- a/src/jsc/bindings/NodeVMModule.h +++ b/src/jsc/bindings/NodeVMModule.h @@ -16,10 +16,8 @@ class NodeVMModuleRequest final { NodeVMModuleRequest(WTF::String specifier, WTF::HashMap importAttributes = {}); JSArray* toJS(JSGlobalObject* globalObject) const; - void addImportAttribute(WTF::String key, WTF::String value); const WTF::String& specifier() const { return m_specifier; } - void specifier(WTF::String value) { m_specifier = value; } const WTF::HashMap& importAttributes() const { return m_importAttributes; } private: diff --git a/src/jsc/bindings/NodeVMScript.h b/src/jsc/bindings/NodeVMScript.h index 35d3a15bfcbf..53fb2ee7fd30 100644 --- a/src/jsc/bindings/NodeVMScript.h +++ b/src/jsc/bindings/NodeVMScript.h @@ -71,7 +71,6 @@ class NodeVMScript final : public JSC::JSDestructibleObject, public SigintReceiv const JSC::SourceCode& source() const { return m_source; } WTF::Vector& cachedData() { return m_options.cachedData; } - RefPtr cachedBytecode() const { return m_cachedBytecode; } JSC::ProgramExecutable* cachedExecutable() const { return m_cachedExecutable.get(); } bool cachedDataProduced() const { return m_cachedDataProduced; } void cachedDataProduced(bool value) { m_cachedDataProduced = value; } diff --git a/src/jsc/bindings/NodeVMSourceTextModule.h b/src/jsc/bindings/NodeVMSourceTextModule.h index cf0f96bbcdbd..fc2169d48080 100644 --- a/src/jsc/bindings/NodeVMSourceTextModule.h +++ b/src/jsc/bindings/NodeVMSourceTextModule.h @@ -32,7 +32,6 @@ class NodeVMSourceTextModule final : public NodeVMModule { JSValue createModuleRecord(JSGlobalObject* globalObject); void ensureModuleRecord(JSGlobalObject* globalObject); - bool hasModuleRecord() const { return !!m_moduleRecord; } JSModuleRecord* moduleRecordIfExists() const { return m_moduleRecord.get(); } AbstractModuleRecord* moduleRecord(JSGlobalObject* globalObject); JSValue link(JSGlobalObject* globalObject, JSArray* specifiers, JSArray* moduleNatives, JSValue scriptFetcher); diff --git a/src/jsc/bindings/NodeVMSyntheticModule.h b/src/jsc/bindings/NodeVMSyntheticModule.h index 40986e8d026e..b28df191ff07 100644 --- a/src/jsc/bindings/NodeVMSyntheticModule.h +++ b/src/jsc/bindings/NodeVMSyntheticModule.h @@ -36,7 +36,6 @@ class NodeVMSyntheticModule final : public NodeVMModule { void createModuleRecord(JSGlobalObject* globalObject); void ensureModuleRecord(JSGlobalObject* globalObject); - bool hasModuleRecord() const { return !!m_moduleRecord; } AbstractModuleRecord* moduleRecord(JSGlobalObject* globalObject); JSValue link(JSGlobalObject* globalObject, JSArray* specifiers, JSArray* moduleNatives, JSValue scriptFetcher); JSValue instantiate(JSGlobalObject* globalObject); diff --git a/src/jsc/bindings/blob.h b/src/jsc/bindings/blob.h index 5b3b9231540f..9612ac6942d0 100644 --- a/src/jsc/bindings/blob.h +++ b/src/jsc/bindings/blob.h @@ -38,7 +38,6 @@ struct BlobImplRefDerefTraits { } }; -using BlobRef = Ref, BlobImplRefDerefTraits>; using BlobRefPtr = RefPtr, BlobImplRefDerefTraits>; // TODO: Now that `bun.webcore.Blob` is ref-counted, can `RefPtr` be replaced with `Blob`? diff --git a/src/jsc/bindings/libuv/uv/aix.h b/src/jsc/bindings/libuv/uv/aix.h deleted file mode 100644 index 5a5c4cc67e16..000000000000 --- a/src/jsc/bindings/libuv/uv/aix.h +++ /dev/null @@ -1,32 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef UV_AIX_H -#define UV_AIX_H - -#define UV_PLATFORM_LOOP_FIELDS \ - int fs_fd; - -#define UV_PLATFORM_FS_EVENT_FIELDS \ - uv__io_t event_watcher; \ - char* dir_filename; - -#endif /* UV_AIX_H */ diff --git a/src/jsc/bindings/libuv/uv/os390.h b/src/jsc/bindings/libuv/uv/os390.h deleted file mode 100644 index c68b71cf20c3..000000000000 --- a/src/jsc/bindings/libuv/uv/os390.h +++ /dev/null @@ -1,33 +0,0 @@ -/* Copyright libuv project contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef UV_MVS_H -#define UV_MVS_H - -#define UV_PLATFORM_SEM_T long - -#define UV_PLATFORM_LOOP_FIELDS \ - void* ep; - -#define UV_PLATFORM_FS_EVENT_FIELDS \ - char rfis_rftok[8]; - -#endif /* UV_MVS_H */ diff --git a/src/jsc/bindings/libuv/uv/posix.h b/src/jsc/bindings/libuv/uv/posix.h deleted file mode 100644 index 8c75a3514636..000000000000 --- a/src/jsc/bindings/libuv/uv/posix.h +++ /dev/null @@ -1,31 +0,0 @@ -/* Copyright libuv project contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef UV_POSIX_H -#define UV_POSIX_H - -#define UV_PLATFORM_LOOP_FIELDS \ - struct pollfd* poll_fds; \ - size_t poll_fds_used; \ - size_t poll_fds_size; \ - unsigned char poll_fds_iterating; - -#endif /* UV_POSIX_H */ diff --git a/src/jsc/bindings/libuv/uv/sunos.h b/src/jsc/bindings/libuv/uv/sunos.h deleted file mode 100644 index 3842047c509d..000000000000 --- a/src/jsc/bindings/libuv/uv/sunos.h +++ /dev/null @@ -1,44 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef UV_SUNOS_H -#define UV_SUNOS_H - -#include -#include - -/* For the sake of convenience and reduced #ifdef-ery in src/unix/sunos.c, - * add the fs_event fields even when this version of SunOS doesn't support - * file watching. - */ -#define UV_PLATFORM_LOOP_FIELDS \ - uv__io_t fs_event_watcher; \ - int fs_fd; - -#if defined(PORT_SOURCE_FILE) - -#define UV_PLATFORM_FS_EVENT_FIELDS \ - file_obj_t fo; \ - int fd; - -#endif /* defined(PORT_SOURCE_FILE) */ - -#endif /* UV_SUNOS_H */ diff --git a/src/jsc/bindings/libuv/uv/unix.h b/src/jsc/bindings/libuv/uv/unix.h index 3dad451d13a3..4c6de8c35a5e 100644 --- a/src/jsc/bindings/libuv/uv/unix.h +++ b/src/jsc/bindings/libuv/uv/unix.h @@ -47,20 +47,10 @@ #if defined(__linux__) #include "uv/linux.h" -#elif defined(__MVS__) -#include "uv/os390.h" -#elif defined(__PASE__) /* __PASE__ and _AIX are both defined on IBM i */ -#include "uv/posix.h" /* IBM i needs uv/posix.h, not uv/aix.h */ -#elif defined(_AIX) -#include "uv/aix.h" -#elif defined(__sun) -#include "uv/sunos.h" #elif defined(__APPLE__) #include "uv/darwin.h" #elif defined(__DragonFly__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) #include "uv/bsd.h" -#elif defined(__CYGWIN__) || defined(__MSYS__) || defined(__HAIKU__) || defined(__QNX__) || defined(__GNU__) -#include "uv/posix.h" #endif #ifndef NI_MAXHOST diff --git a/src/jsc/bindings/napi.cpp b/src/jsc/bindings/napi.cpp index 396f55991f9f..826427e8b7bc 100644 --- a/src/jsc/bindings/napi.cpp +++ b/src/jsc/bindings/napi.cpp @@ -261,32 +261,6 @@ napi_get_last_error_info(napi_env env, const napi_extended_error_info** result) return napi_ok; } -JSC::SourceCode generateSourceCode(WTF::String keyString, JSC::VM& vm, JSC::JSObject* object, JSC::JSGlobalObject* globalObject) -{ - JSC::JSArray* exportKeys = ownPropertyKeys(globalObject, object, PropertyNameMode::StringsAndSymbols, DontEnumPropertiesMode::Include); - JSC::Identifier ident = JSC::Identifier::fromString(vm, "__BunTemporaryGlobal"_s); - WTF::StringBuilder sourceCodeBuilder = WTF::StringBuilder(); - // TODO: handle symbol collision - sourceCodeBuilder.append("\nvar $$NativeModule = globalThis['__BunTemporaryGlobal']; console.log($$NativeModule); globalThis['__BunTemporaryGlobal'] = null;\n if (!$$NativeModule) { throw new Error('Assertion failure: Native module not found'); }\n\n"_s); - - for (unsigned i = 0; i < exportKeys->length(); i++) { - auto key = exportKeys->getIndexQuickly(i); - if (key.isSymbol()) { - continue; - } - auto named = key.toWTFString(globalObject); - sourceCodeBuilder.append(""_s); - // TODO: handle invalid identifiers - sourceCodeBuilder.append("export var "_s); - sourceCodeBuilder.append(named); - sourceCodeBuilder.append(" = $$NativeModule."_s); - sourceCodeBuilder.append(named); - sourceCodeBuilder.append(";\n"_s); - } - globalObject->putDirect(vm, ident, object, JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::DontEnum); - return JSC::makeSource(sourceCodeBuilder.toString(), JSC::SourceOrigin(), JSC::SourceTaintedOrigin::Untainted, keyString, WTF::TextPosition(), JSC::SourceProviderSourceType::Module); -} - void Napi::NapiRefWeakHandleOwner::finalize(JSC::Handle, void* context) { auto* weakValue = reinterpret_cast(context); diff --git a/src/jsc/bindings/napi.h b/src/jsc/bindings/napi.h index d1188a3aced0..1fa0d4f9aeae 100644 --- a/src/jsc/bindings/napi.h +++ b/src/jsc/bindings/napi.h @@ -655,8 +655,6 @@ class JSSourceCode; namespace Napi { -JSC::SourceCode generateSourceCode(WTF::String keyString, JSC::VM& vm, JSC::JSObject* object, JSC::JSGlobalObject* globalObject); - class NapiRefWeakHandleOwner final : public JSC::WeakHandleOwner { public: // Equivalent to v8impl::Ownership::kUserland @@ -723,11 +721,6 @@ class NapiWeakValue { void clear(); bool isClear() const; - bool isSet() const { return m_tag != WeakTypeTag::NotSet; } - bool isPrimitive() const { return m_tag == WeakTypeTag::Primitive; } - bool isCell() const { return m_tag == WeakTypeTag::Cell; } - bool isString() const { return m_tag == WeakTypeTag::String; } - void setPrimitive(JSValue); void setCell(JSCell*, WeakHandleOwner&, void* context); void setString(JSString*, WeakHandleOwner&, void* context); @@ -747,24 +740,6 @@ class NapiWeakValue { } } - JSCell* cell() const - { - ASSERT(isCell()); - return m_value.cell.get(); - } - - JSValue primitive() const - { - ASSERT(isPrimitive()); - return m_value.primitive; - } - - JSString* string() const - { - ASSERT(isString()); - return m_value.string.get(); - } - private: enum class WeakTypeTag { NotSet, Primitive, @@ -892,10 +867,6 @@ class NapiClass final : public JSC::JSFunction { static constexpr unsigned StructureFlags = Base::StructureFlags; static constexpr JSC::DestructionMode needsDestruction = DoesNotNeedDestruction; - static void destroy(JSCell* cell) - { - static_cast(cell)->NapiClass::~NapiClass(); - } template static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { diff --git a/src/jsc/bindings/uv-posix-polyfills.c b/src/jsc/bindings/uv-posix-polyfills.c index 3eea2489c1bf..50bbc556cafb 100644 --- a/src/jsc/bindings/uv-posix-polyfills.c +++ b/src/jsc/bindings/uv-posix-polyfills.c @@ -25,20 +25,10 @@ uint64_t uv__hrtime(uv_clocktype_t type); #if defined(__linux__) #include "uv-posix-polyfills-linux.c" -// #elif defined(__MVS__) -// #include "uv/os390.h" -// #elif defined(__PASE__) /* __PASE__ and _AIX are both defined on IBM i */ -// #include "uv/posix.h" /* IBM i needs uv/posix.h, not uv/aix.h */ -// #elif defined(_AIX) -// #include "uv/aix.h" -// #elif defined(__sun) -// #include "uv/sunos.h" #elif defined(__APPLE__) #include "uv-posix-polyfills-darwin.c" #elif defined(__FreeBSD__) #include "uv-posix-polyfills-posix.c" -#elif defined(__CYGWIN__) || defined(__MSYS__) || defined(__HAIKU__) || defined(__QNX__) || defined(__GNU__) -#include "uv-posix-polyfills-posix.c" #endif uv_pid_t uv_os_getpid() diff --git a/src/zlib/error.rs b/src/zlib/error.rs deleted file mode 100644 index 58cd3cb2f139..000000000000 --- a/src/zlib/error.rs +++ /dev/null @@ -1,31 +0,0 @@ -#[derive(Debug, Clone, Copy, PartialEq, Eq, thiserror::Error)] -pub enum Error { - #[error("ZlibError")] - ZlibError, - #[error("ShortRead")] - ShortRead, - #[error(transparent)] - Alloc(#[from] bun_alloc::AllocError), - #[error(transparent)] - Core(#[from] bun_core::Error), -} - -impl Error { - #[allow(clippy::trivially_copy_pass_by_ref)] - pub(crate) fn name(&self) -> &'static str { - match self { - Self::ZlibError => "ZlibError", - Self::ShortRead => "ShortRead", - Self::Alloc(_) => "OutOfMemory", - Self::Core(e) => e.name(), - } - } -} - -impl bun_core::output::ErrName for Error { - fn name(&self) -> &[u8] { - (*self).name().as_bytes() - } -} - -pub type Result = core::result::Result; diff --git a/src/zlib/lib.rs b/src/zlib/lib.rs index 465c05f5d609..9c599bafb74c 100644 --- a/src/zlib/lib.rs +++ b/src/zlib/lib.rs @@ -1,8 +1,5 @@ // @link "deps/zlib/libz.a" -pub mod error; -pub use error::{Error, Result}; - use core::ffi::{c_char, c_int, c_uint, c_void}; use core::mem::size_of; @@ -39,7 +36,7 @@ unsafe extern "C" { } #[allow(non_camel_case_types, unused_imports)] -pub use bun_zlib_sys::shared::{Byte, Bytef, gzFile, struct_gzFile_s, uInt, uLong, uLongf, voidpf}; +pub use bun_zlib_sys::shared::{Bytef, uInt, uLong, uLongf}; // typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); // typedef void (*free_func) OF((voidpf opaque, voidpf address)); diff --git a/test/internal/source-lints/dead-symbols-napi-nodevm-libuv.test.ts b/test/internal/source-lints/dead-symbols-napi-nodevm-libuv.test.ts new file mode 100644 index 000000000000..3c323300b385 --- /dev/null +++ b/test/internal/source-lints/dead-symbols-napi-nodevm-libuv.test.ts @@ -0,0 +1,102 @@ +// Guards against reintroduction of symbols removed as dead code from napi, +// NodeVM*, JSBufferList, JSStringDecoder, BunClientData, EventLoopTask, +// JSEnvironmentVariableMap, libuv platform headers, zlib, io/windows_event_loop, +// and node/net.ts. Each entry was verified to have zero callers across src/ +// and build/debug/codegen/ before deletion; this test fails if any reappear. +// +// This is a source-tree lint: it reads files from src/ and does not touch the +// built binary, so it belongs in test/internal/source-lints/ per the README. + +import { expect, test } from "bun:test"; +import { existsSync, readFileSync } from "node:fs"; +import path from "node:path"; + +const repoRoot = path.resolve(import.meta.dir, "..", "..", ".."); + +function src(p: string): string { + return readFileSync(path.join(repoRoot, p), "utf8"); +} + +test("napi / NodeVM / JSBufferList / JSStringDecoder dead methods do not reappear", () => { + const checks: Array<[string, RegExp]> = [ + ["src/jsc/bindings/napi.cpp", /JSC::SourceCode generateSourceCode\(WTF::String keyString/], + ["src/jsc/bindings/napi.h", /JSC::SourceCode generateSourceCode\(/], + ["src/jsc/bindings/napi.h", /bool isSet\(\) const \{ return m_tag != WeakTypeTag::NotSet; \}/], + ["src/jsc/bindings/napi.h", /JSCell\* cell\(\) const\s*\{/], + ["src/jsc/bindings/napi.h", /JSValue primitive\(\) const\s*\{/], + ["src/jsc/bindings/napi.h", /JSString\* string\(\) const\s*\{/], + ["src/jsc/bindings/NodeVM.h", /void clearContextifiedObject\(\);/], + ["src/jsc/bindings/NodeVM.cpp", /void NodeVMGlobalObject::clearContextifiedObject\(\)/], + ["src/jsc/bindings/NodeVMModule.h", /void addImportAttribute\(WTF::String key/], + ["src/jsc/bindings/NodeVMModule.cpp", /void NodeVMModuleRequest::addImportAttribute\(/], + ["src/jsc/bindings/NodeVMModule.h", /void specifier\(WTF::String value\)/], + ["src/jsc/bindings/NodeVMSourceTextModule.h", /bool hasModuleRecord\(\) const/], + ["src/jsc/bindings/NodeVMSyntheticModule.h", /bool hasModuleRecord\(\) const/], + ["src/jsc/bindings/NodeVMScript.h", /RefPtr cachedBytecode\(\) const/], + ["src/jsc/bindings/JSBufferList.h", /void initializeProperties\(JSC::VM& vm, JSC::JSGlobalObject\* globalObject, JSBufferListPrototype\* prototype\);/], + ["src/jsc/bindings/JSBufferList.cpp", /void JSBufferListConstructor::initializeProperties\(/], + ["src/jsc/bindings/JSBufferList.h", /static void destroy\(JSCell\*\) \{\}/], + ["src/jsc/bindings/JSStringDecoder.h", /void initializeProperties\(JSC::VM& vm, JSC::JSGlobalObject\* globalObject, JSStringDecoderPrototype\* prototype\);/], + ["src/jsc/bindings/JSStringDecoder.cpp", /void JSStringDecoderConstructor::initializeProperties\(/], + ["src/jsc/bindings/JSNextTickQueue.h", /static std::array initialValues\(\)/], + ]; + const resurrected = checks.filter(([file, re]) => re.test(src(file))).map(([file, re]) => `${file}: ${re.source}`); + expect(resurrected).toEqual([]); +}); + +test("BunClientData / EventLoopTask / JSEnvironmentVariableMap / blob / Bindgen dead members do not reappear", () => { + const clientData = src("src/jsc/bindings/BunClientData.h"); + // The JSHeapData copies (first occurrence) are live; the JSVMClientData + // duplicates (second occurrence) are the dead ones. After removal there + // should be exactly one occurrence of each. + expect((clientData.match(/Vector m_outputConstraintSpaces;/g) ?? []).length).toBe(1); + expect((clientData.match(/void forEachOutputConstraintSpace\(/g) ?? []).length).toBe(1); + expect((clientData.match(/Vector& outputConstraintSpaces\(\)/g) ?? []).length).toBe(1); + + const checks: Array<[string, RegExp]> = [ + ["src/jsc/bindings/EventLoopTask.h", /bool isCleanupTask\(\) const/], + ["src/jsc/bindings/EventLoopTask.h", /bool m_isCleanupTask;/], + ["src/jsc/bindings/EventLoopTask.h", /enum CleanupTaskTag/], + ["src/jsc/bindings/JSEnvironmentVariableMap.cpp", /JSC_DEFINE_CUSTOM_SETTER\(jsSetterEnvironmentVariable,/], + ["src/jsc/bindings/blob.h", /^using BlobRef = Ref re.test(src(file))).map(([file, re]) => `${file}: ${re.source}`); + expect(resurrected).toEqual([]); +}); + +test("libuv platform headers for non-targeted OSes are gone", () => { + const deleted = [ + "src/jsc/bindings/libuv/uv/aix.h", + "src/jsc/bindings/libuv/uv/os390.h", + "src/jsc/bindings/libuv/uv/sunos.h", + "src/jsc/bindings/libuv/uv/posix.h", + ]; + const resurrected = deleted.filter(p => existsSync(path.join(repoRoot, p))); + expect(resurrected).toEqual([]); + + const unix = src("src/jsc/bindings/libuv/uv/unix.h"); + expect(unix).not.toMatch(/#include "uv\/aix\.h"/); + expect(unix).not.toMatch(/#include "uv\/os390\.h"/); + expect(unix).not.toMatch(/#include "uv\/sunos\.h"/); + expect(unix).not.toMatch(/#include "uv\/posix\.h"/); +}); + +test("zlib / io / install / net.ts dead items do not reappear", () => { + expect(existsSync(path.join(repoRoot, "src/zlib/error.rs"))).toBe(false); + + const checks: Array<[string, RegExp]> = [ + ["src/zlib/lib.rs", /^pub mod error;$/m], + ["src/zlib/lib.rs", /\bgzFile\b/], + ["src/zlib/lib.rs", /\bstruct_gzFile_s\b/], + ["src/io/windows_event_loop.rs", /pub fn ref_\(&mut self, event_loop_ctx: EventLoopCtx\)/], + ["src/io/windows_event_loop.rs", /pub fn activate\(&mut self, loop_: &mut WindowsLoop\)/], + ["src/io/windows_event_loop.rs", /pub fn can_ref\(&self\) -> bool/], + ["src/install/lockfile/bun.lock.rs", /\/\/ pub fn save\(this: &Lockfile\)/], + ["src/js/node/net.ts", /const kpendingRead = Symbol\("kpendingRead"\);/], + ["src/js/node/net.ts", /const kServerSocket = Symbol\("kServerSocket"\);/], + ]; + const resurrected = checks.filter(([file, re]) => re.test(src(file))).map(([file, re]) => `${file}: ${re.source}`); + expect(resurrected).toEqual([]); +}); From 07a8a2123275fe6306a208281f60ade46408dfdd Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Sat, 1 Aug 2026 16:25:08 +0000 Subject: [PATCH 02/15] [autofix.ci] apply automated fixes --- .../dead-symbols-napi-nodevm-libuv.test.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/test/internal/source-lints/dead-symbols-napi-nodevm-libuv.test.ts b/test/internal/source-lints/dead-symbols-napi-nodevm-libuv.test.ts index 3c323300b385..cf8dbbcb9de4 100644 --- a/test/internal/source-lints/dead-symbols-napi-nodevm-libuv.test.ts +++ b/test/internal/source-lints/dead-symbols-napi-nodevm-libuv.test.ts @@ -33,10 +33,16 @@ test("napi / NodeVM / JSBufferList / JSStringDecoder dead methods do not reappea ["src/jsc/bindings/NodeVMSourceTextModule.h", /bool hasModuleRecord\(\) const/], ["src/jsc/bindings/NodeVMSyntheticModule.h", /bool hasModuleRecord\(\) const/], ["src/jsc/bindings/NodeVMScript.h", /RefPtr cachedBytecode\(\) const/], - ["src/jsc/bindings/JSBufferList.h", /void initializeProperties\(JSC::VM& vm, JSC::JSGlobalObject\* globalObject, JSBufferListPrototype\* prototype\);/], + [ + "src/jsc/bindings/JSBufferList.h", + /void initializeProperties\(JSC::VM& vm, JSC::JSGlobalObject\* globalObject, JSBufferListPrototype\* prototype\);/, + ], ["src/jsc/bindings/JSBufferList.cpp", /void JSBufferListConstructor::initializeProperties\(/], ["src/jsc/bindings/JSBufferList.h", /static void destroy\(JSCell\*\) \{\}/], - ["src/jsc/bindings/JSStringDecoder.h", /void initializeProperties\(JSC::VM& vm, JSC::JSGlobalObject\* globalObject, JSStringDecoderPrototype\* prototype\);/], + [ + "src/jsc/bindings/JSStringDecoder.h", + /void initializeProperties\(JSC::VM& vm, JSC::JSGlobalObject\* globalObject, JSStringDecoderPrototype\* prototype\);/, + ], ["src/jsc/bindings/JSStringDecoder.cpp", /void JSStringDecoderConstructor::initializeProperties\(/], ["src/jsc/bindings/JSNextTickQueue.h", /static std::array initialValues\(\)/], ]; From 4f8e552b93a840bf91295ca9aae56955e3b8d319 Mon Sep 17 00:00:00 2001 From: robobun <117481402+robobun@users.noreply.github.com> Date: Sat, 1 Aug 2026 16:29:40 +0000 Subject: [PATCH 03/15] Address review: tighten env-var comment, drop existsSync from source-lint - JSEnvironmentVariableMap.cpp: the comment in jsSetterProxyEnvironmentVariable originally referenced the deleted jsSetterEnvironmentVariable; tighten it to describe the actual CustomValue-replacement behaviour instead of naming a function that no longer exists (and was never registered anyway). - dead-symbols-napi-nodevm-libuv.test.ts: assert against surviving source (unix.h includes, lib.rs mod declaration) instead of existsSync() on deleted paths. The verification harness's stash/restore step can leave deleted files on disk, and an unreferenced header/module on disk is harmless. --- src/jsc/bindings/JSEnvironmentVariableMap.cpp | 13 +++++-------- .../dead-symbols-napi-nodevm-libuv.test.ts | 18 +++++------------- 2 files changed, 10 insertions(+), 21 deletions(-) diff --git a/src/jsc/bindings/JSEnvironmentVariableMap.cpp b/src/jsc/bindings/JSEnvironmentVariableMap.cpp index 51a979530c98..a536697b7fca 100644 --- a/src/jsc/bindings/JSEnvironmentVariableMap.cpp +++ b/src/jsc/bindings/JSEnvironmentVariableMap.cpp @@ -103,14 +103,11 @@ JSC_DEFINE_CUSTOM_SETTER(jsSetterProxyEnvironmentVariable, (JSGlobalObject * glo BunString val = Bun::toStringView(view); Bun__setEnvValue(globalObject, &name, &val); - // The proxy-var accessors are added with `DontEnum` when the var was not - // present in the OS env at startup. The regular env-var getter makes a - // written var enumerable by replacing the accessor with a data property; - // this setter keeps the accessor (so the native env map stays the source - // of truth) but must - // still clear `DontEnum` — otherwise `process.env.HTTP_PROXY = "..."` - // followed by `Bun.spawn({env: {...process.env}})` silently drops the var - // (the spread skips non-enumerable properties). + // Proxy-var accessors start out `DontEnum` when the var was absent from + // the OS env at startup. Writing to a regular env var replaces its + // CustomValue accessor with an enumerable data property; this setter + // keeps the accessor (native env map stays authoritative) so it has to + // clear `DontEnum` itself or `{...process.env}` drops the var. unsigned attributes; JSValue existing = object->getDirect(vm, propertyName, attributes); if (existing && (attributes & JSC::PropertyAttribute::DontEnum)) { diff --git a/test/internal/source-lints/dead-symbols-napi-nodevm-libuv.test.ts b/test/internal/source-lints/dead-symbols-napi-nodevm-libuv.test.ts index cf8dbbcb9de4..ed9abe149ceb 100644 --- a/test/internal/source-lints/dead-symbols-napi-nodevm-libuv.test.ts +++ b/test/internal/source-lints/dead-symbols-napi-nodevm-libuv.test.ts @@ -8,7 +8,7 @@ // built binary, so it belongs in test/internal/source-lints/ per the README. import { expect, test } from "bun:test"; -import { existsSync, readFileSync } from "node:fs"; +import { readFileSync } from "node:fs"; import path from "node:path"; const repoRoot = path.resolve(import.meta.dir, "..", "..", ".."); @@ -72,16 +72,10 @@ test("BunClientData / EventLoopTask / JSEnvironmentVariableMap / blob / Bindgen expect(resurrected).toEqual([]); }); -test("libuv platform headers for non-targeted OSes are gone", () => { - const deleted = [ - "src/jsc/bindings/libuv/uv/aix.h", - "src/jsc/bindings/libuv/uv/os390.h", - "src/jsc/bindings/libuv/uv/sunos.h", - "src/jsc/bindings/libuv/uv/posix.h", - ]; - const resurrected = deleted.filter(p => existsSync(path.join(repoRoot, p))); - expect(resurrected).toEqual([]); - +test("libuv platform headers for non-targeted OSes are not included", () => { + // Assert against the surviving includer rather than `existsSync` on the + // deleted header paths: the gate's stash/restore step can leave deleted + // files on disk, and an unreferenced header on disk is harmless anyway. const unix = src("src/jsc/bindings/libuv/uv/unix.h"); expect(unix).not.toMatch(/#include "uv\/aix\.h"/); expect(unix).not.toMatch(/#include "uv\/os390\.h"/); @@ -90,8 +84,6 @@ test("libuv platform headers for non-targeted OSes are gone", () => { }); test("zlib / io / install / net.ts dead items do not reappear", () => { - expect(existsSync(path.join(repoRoot, "src/zlib/error.rs"))).toBe(false); - const checks: Array<[string, RegExp]> = [ ["src/zlib/lib.rs", /^pub mod error;$/m], ["src/zlib/lib.rs", /\bgzFile\b/], From 43104917b98772830009bca0258b11f811772d78 Mon Sep 17 00:00:00 2001 From: robobun <117481402+robobun@users.noreply.github.com> Date: Sat, 1 Aug 2026 16:33:23 +0000 Subject: [PATCH 04/15] JSEnvironmentVariableMap: shrink proxy-var DontEnum comment to two lines --- src/jsc/bindings/JSEnvironmentVariableMap.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/jsc/bindings/JSEnvironmentVariableMap.cpp b/src/jsc/bindings/JSEnvironmentVariableMap.cpp index a536697b7fca..dd249e6a7b36 100644 --- a/src/jsc/bindings/JSEnvironmentVariableMap.cpp +++ b/src/jsc/bindings/JSEnvironmentVariableMap.cpp @@ -103,11 +103,8 @@ JSC_DEFINE_CUSTOM_SETTER(jsSetterProxyEnvironmentVariable, (JSGlobalObject * glo BunString val = Bun::toStringView(view); Bun__setEnvValue(globalObject, &name, &val); - // Proxy-var accessors start out `DontEnum` when the var was absent from - // the OS env at startup. Writing to a regular env var replaces its - // CustomValue accessor with an enumerable data property; this setter - // keeps the accessor (native env map stays authoritative) so it has to - // clear `DontEnum` itself or `{...process.env}` drops the var. + // Proxy-var accessors are installed DontEnum when absent from the OS env + // at startup; clear it on write so `{...process.env}` picks the var up. unsigned attributes; JSValue existing = object->getDirect(vm, propertyName, attributes); if (existing && (attributes & JSC::PropertyAttribute::DontEnum)) { From 2c08c53e9f8804a4c0ccc06a37956d83876372cf Mon Sep 17 00:00:00 2001 From: robobun <117481402+robobun@users.noreply.github.com> Date: Sat, 1 Aug 2026 16:38:13 +0000 Subject: [PATCH 05/15] Buffers.rs: drop orphaned _pos debug bindings in load() The commented-out debug prints removed in 9d58ed10ad were the only readers of the three #[cfg(debug_assertions)] let _pos = stream.pos; bindings in load_generic_field! and the trees/dependencies load blocks. --- src/install/lockfile/Buffers.rs | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/install/lockfile/Buffers.rs b/src/install/lockfile/Buffers.rs index aaff4491083c..7a2d2db3e158 100644 --- a/src/install/lockfile/Buffers.rs +++ b/src/install/lockfile/Buffers.rs @@ -405,9 +405,6 @@ pub(crate) fn load( macro_rules! load_generic_field { ($field:ident, $name:literal, $elem:ty) => {{ - #[cfg(debug_assertions)] - let _pos: usize = stream.pos; - this.$field = read_array::<$elem>(stream)?; if let Some(pm) = pm_.as_deref() { if pm.options.log_level.is_verbose() { @@ -419,9 +416,6 @@ pub(crate) fn load( // -- trees -- { - #[cfg(debug_assertions)] - let _pos: usize = stream.pos; - let tree_list: Vec = read_array(stream)?; // `set_len` then `iter_mut()` would form `&mut Tree` to uninitialized // memory (UB), so we push into the reserved capacity instead. @@ -440,9 +434,6 @@ pub(crate) fn load( // -- dependencies -- { - #[cfg(debug_assertions)] - let _pos: usize = stream.pos; - external_dependency_list_ = read_array::(stream)?; if let Some(pm) = pm_.as_deref() { if pm.options.log_level.is_verbose() { From 6c7b2261601b63a54d9d4162542a4d2955f54c32 Mon Sep 17 00:00:00 2001 From: robobun <117481402+robobun@users.noreply.github.com> Date: Sat, 1 Aug 2026 17:03:42 +0000 Subject: [PATCH 06/15] Remove orphaned scaffolding left by earlier deletions in this PR io/windows_event_loop.rs: - declare_scope!(FilePoll)/declare_scope!(KeepAlive): the only scoped_log!(FilePoll, ..) calls were in the removed ref_/activate methods; the KeepAlive scope was already orphaned (its callers moved to crate::keep_alive). - disable_keeping_process_alive doc: reworded to match the posix counterpart instead of naming the removed ref(). io/posix_event_loop.rs: - FilePoll::ref_: the equally-dead posix sibling of the removed Windows method. All .ref_(ctx) call sites in the tree dispatch on KeepAlive; FilePoll callers use enable_keeping_process_alive directly. jsc/bindings/napi.h: - namespace JSC { JSGlobalObject; JSSourceCode; } forward-decl block: scaffolding for the removed generateSourceCode declaration. JSGlobalObject is already provided via ZigGlobalObject.h; JSSourceCode has zero uses in the header. jsc/bindings/NapiRef.cpp: - dropped the two isSet() comment lines that reference the removed NapiWeakValue::isSet(); kept the .setString/.setObject assertion note and the weakValueRef retention rationale. --- src/io/posix_event_loop.rs | 9 --------- src/io/windows_event_loop.rs | 5 +---- src/jsc/bindings/NapiRef.cpp | 2 -- src/jsc/bindings/napi.h | 5 ----- 4 files changed, 1 insertion(+), 20 deletions(-) diff --git a/src/io/posix_event_loop.rs b/src/io/posix_event_loop.rs index 0496d44d57b0..e9a84a6a18de 100644 --- a/src/io/posix_event_loop.rs +++ b/src/io/posix_event_loop.rs @@ -558,15 +558,6 @@ impl FilePoll { poll } - /// Allow a poll to keep the process alive. - pub fn ref_(&mut self, event_loop_ctx: EventLoopCtx) { - if self.flags.contains(Flags::Closed) { - return; - } - syslog!("ref"); - self.enable_keeping_process_alive(event_loop_ctx); - } - pub fn register(&mut self, loop_: &mut Loop, flag: Flags, one_shot: bool) -> sys::Result<()> { self.register_with_fd( loop_, diff --git a/src/io/windows_event_loop.rs b/src/io/windows_event_loop.rs index 72e1107fad7c..5683f2a3796c 100644 --- a/src/io/windows_event_loop.rs +++ b/src/io/windows_event_loop.rs @@ -12,9 +12,6 @@ use crate::posix_event_loop as posix; // that name them via this module. pub use crate::posix_event_loop::{EventLoopCtx, OpaqueCallback, js_vm_ctx}; -bun_core::declare_scope!(KeepAlive, visible); -bun_core::declare_scope!(FilePoll, visible); - // `Loop` here is the raw // `uv_loop_t`. (`WindowsLoop` is the uws wrapper that *owns* a `*mut uv::Loop` // in its `.uv_loop` field; callers that hold a `WindowsLoop*` project that @@ -57,7 +54,7 @@ impl FilePoll { || self.flags.contains(Flags::PollMachport) } - /// Make calling ref() on this poll into a no-op. + /// Decrements the active counter if it was previously incremented. pub(crate) fn disable_keeping_process_alive(&mut self, vm: EventLoopCtx) { if self.flags.contains(Flags::Closed) { return; diff --git a/src/jsc/bindings/NapiRef.cpp b/src/jsc/bindings/NapiRef.cpp index 03660630b970..77a260543a57 100644 --- a/src/jsc/bindings/NapiRef.cpp +++ b/src/jsc/bindings/NapiRef.cpp @@ -14,8 +14,6 @@ void NapiRef::ref() auto& vm = globalObject.get()->vm(); strongRef.set(vm, weakValueRef.get()); - // isSet() will return always true after being set once - // We cannot rely on isSet() to check if the value is set we need to use isClear() // .setString/.setObject/.setPrimitive will assert fail if called more than once (even after clear()) // We should not clear the weakValueRef here because we need to keep it if we call NapiRef::unref() // so we can call the finalizer diff --git a/src/jsc/bindings/napi.h b/src/jsc/bindings/napi.h index 1fa0d4f9aeae..f7896c847b73 100644 --- a/src/jsc/bindings/napi.h +++ b/src/jsc/bindings/napi.h @@ -648,11 +648,6 @@ struct NapiEnv : public WTF::RefCounted { extern "C" void napi_internal_cleanup_env_cpp(napi_env); extern "C" void napi_internal_remove_finalizer(napi_env, napi_finalize callback, void* hint, void* data); -namespace JSC { -class JSGlobalObject; -class JSSourceCode; -} - namespace Napi { class NapiRefWeakHandleOwner final : public JSC::WeakHandleOwner { From 7411c273d800c6892bb9d76d4ba367f1932f9fe2 Mon Sep 17 00:00:00 2001 From: robobun <117481402+robobun@users.noreply.github.com> Date: Sat, 1 Aug 2026 17:15:14 +0000 Subject: [PATCH 07/15] Remove PendingVirtualModuleResult/MockWithImplementationCleanupData initialValues() Siblings of the removed JSNextTickQueue::initialValues() with the same justification: both finishCreation bodies set every internal field directly and never call initialValues(). BunStreamSource's copy is kept (it has a live caller at BunStreamSource.cpp:57). --- src/jsc/bindings/JSMockFunction.h | 10 ---------- src/jsc/bindings/ModuleLoader.h | 9 --------- .../dead-symbols-napi-nodevm-libuv.test.ts | 2 ++ 3 files changed, 2 insertions(+), 19 deletions(-) diff --git a/src/jsc/bindings/JSMockFunction.h b/src/jsc/bindings/JSMockFunction.h index 1200e289e2c5..e071b4e08758 100644 --- a/src/jsc/bindings/JSMockFunction.h +++ b/src/jsc/bindings/JSMockFunction.h @@ -61,16 +61,6 @@ class MockWithImplementationCleanupData : public JSC::JSInternalFieldObjectImpl< static MockWithImplementationCleanupData* create(JSC::JSGlobalObject* globalObject, JSMockFunction* fn, JSValue impl, JSValue tail, JSValue fallback); static Structure* createStructure(VM&, JSGlobalObject*, JSValue); - static std::array initialValues() - { - return { { - jsUndefined(), - jsUndefined(), - jsUndefined(), - jsUndefined(), - } }; - } - DECLARE_EXPORT_INFO; DECLARE_VISIT_CHILDREN; diff --git a/src/jsc/bindings/ModuleLoader.h b/src/jsc/bindings/ModuleLoader.h index c2a3d65ac588..790ddf09041c 100644 --- a/src/jsc/bindings/ModuleLoader.h +++ b/src/jsc/bindings/ModuleLoader.h @@ -72,15 +72,6 @@ class PendingVirtualModuleResult : public JSC::JSInternalFieldObjectImpl<3> { JSC::JSPromise* internalPromise(); - static std::array initialValues() - { - return { { - jsUndefined(), - jsUndefined(), - jsUndefined(), - } }; - } - DECLARE_EXPORT_INFO; DECLARE_VISIT_CHILDREN; diff --git a/test/internal/source-lints/dead-symbols-napi-nodevm-libuv.test.ts b/test/internal/source-lints/dead-symbols-napi-nodevm-libuv.test.ts index ed9abe149ceb..3e4ad2ee9734 100644 --- a/test/internal/source-lints/dead-symbols-napi-nodevm-libuv.test.ts +++ b/test/internal/source-lints/dead-symbols-napi-nodevm-libuv.test.ts @@ -45,6 +45,8 @@ test("napi / NodeVM / JSBufferList / JSStringDecoder dead methods do not reappea ], ["src/jsc/bindings/JSStringDecoder.cpp", /void JSStringDecoderConstructor::initializeProperties\(/], ["src/jsc/bindings/JSNextTickQueue.h", /static std::array initialValues\(\)/], + ["src/jsc/bindings/ModuleLoader.h", /static std::array initialValues\(\)/], + ["src/jsc/bindings/JSMockFunction.h", /static std::array initialValues\(\)/], ]; const resurrected = checks.filter(([file, re]) => re.test(src(file))).map(([file, re]) => `${file}: ${re.source}`); expect(resurrected).toEqual([]); From c52ae88918f2d9b5dc6c571411a9a16f1a61da48 Mon Sep 17 00:00:00 2001 From: robobun <117481402+robobun@users.noreply.github.com> Date: Sat, 1 Aug 2026 17:32:23 +0000 Subject: [PATCH 08/15] Drop remaining platform-guard/lint-allow scaffolding on lines already touched - io/posix_event_loop.rs: declare_scope!(KeepAlive) (zero scoped_log! callers, posix sibling of the windows one removed in 6c7b226160) - zlib/lib.rs: #[allow(non_camel_case_types, unused_imports)] above the trimmed pub use (all four remaining names are used in extern signatures; neither lint fires on a pub use anyway) - libuv/uv/unix.h: #if !defined(__MVS__) wrapper and the defined(_AIX) clause in the barrier guard (both reference platforms this PR already removed) --- src/io/posix_event_loop.rs | 2 -- src/jsc/bindings/libuv/uv/unix.h | 4 +--- src/zlib/lib.rs | 1 - 3 files changed, 1 insertion(+), 6 deletions(-) diff --git a/src/io/posix_event_loop.rs b/src/io/posix_event_loop.rs index e9a84a6a18de..7e3086134f96 100644 --- a/src/io/posix_event_loop.rs +++ b/src/io/posix_event_loop.rs @@ -27,8 +27,6 @@ fn loop_sub_active(loop_: &mut Loop, value: u32) { loop_.active = loop_.active.saturating_sub(value); } -bun_core::declare_scope!(KeepAlive, visible); - #[cfg(not(windows))] use bun_sys::syslog; diff --git a/src/jsc/bindings/libuv/uv/unix.h b/src/jsc/bindings/libuv/uv/unix.h index 4c6de8c35a5e..40a2fd24df6b 100644 --- a/src/jsc/bindings/libuv/uv/unix.h +++ b/src/jsc/bindings/libuv/uv/unix.h @@ -36,10 +36,8 @@ #include #include -#if !defined(__MVS__) #include #include /* MAXHOSTNAMELEN on Linux and the BSDs */ -#endif #include #include @@ -121,7 +119,7 @@ typedef pthread_cond_t uv_cond_t; typedef pthread_key_t uv_key_t; /* Note: guard clauses should match uv_barrier_init's in src/unix/thread.c. */ -#if defined(_AIX) || defined(__OpenBSD__) || !defined(PTHREAD_BARRIER_SERIAL_THREAD) +#if defined(__OpenBSD__) || !defined(PTHREAD_BARRIER_SERIAL_THREAD) /* TODO(bnoordhuis) Merge into uv_barrier_t in v2. */ struct _uv_barrier { uv_mutex_t mutex; diff --git a/src/zlib/lib.rs b/src/zlib/lib.rs index 9c599bafb74c..86a254d3ceeb 100644 --- a/src/zlib/lib.rs +++ b/src/zlib/lib.rs @@ -35,7 +35,6 @@ unsafe extern "C" { ) -> c_int; } -#[allow(non_camel_case_types, unused_imports)] pub use bun_zlib_sys::shared::{Bytef, uInt, uLong, uLongf}; // typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); From 5a4e92c873e27c0cd025795d49e8dd0b2737adde Mon Sep 17 00:00:00 2001 From: robobun <117481402+robobun@users.noreply.github.com> Date: Sat, 1 Aug 2026 17:59:46 +0000 Subject: [PATCH 09/15] zlib: drop thiserror dep orphaned by error.rs deletion; unix.h: drop stale uv_barrier_init comment The thiserror derive on the deleted Error enum was the crate's only consumer. The unix.h comment referenced src/unix/thread.c which bun never vendored (uv_barrier_init is a __bun_throw_not_implemented stub in uv-posix-stubs.c), and the _AIX clause removal in c52ae889 made the 'should match' claim false against upstream anyway. --- Cargo.lock | 1 - src/jsc/bindings/libuv/uv/unix.h | 1 - src/zlib/Cargo.toml | 1 - 3 files changed, 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index eeec9e5dc3d5..6fa7ae52ec9a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2219,7 +2219,6 @@ dependencies = [ "libc", "scopeguard", "strum", - "thiserror", ] [[package]] diff --git a/src/jsc/bindings/libuv/uv/unix.h b/src/jsc/bindings/libuv/uv/unix.h index 40a2fd24df6b..9dd9af994c72 100644 --- a/src/jsc/bindings/libuv/uv/unix.h +++ b/src/jsc/bindings/libuv/uv/unix.h @@ -118,7 +118,6 @@ typedef UV_PLATFORM_SEM_T uv_sem_t; typedef pthread_cond_t uv_cond_t; typedef pthread_key_t uv_key_t; -/* Note: guard clauses should match uv_barrier_init's in src/unix/thread.c. */ #if defined(__OpenBSD__) || !defined(PTHREAD_BARRIER_SERIAL_THREAD) /* TODO(bnoordhuis) Merge into uv_barrier_t in v2. */ struct _uv_barrier { diff --git a/src/zlib/Cargo.toml b/src/zlib/Cargo.toml index f7e5369ed24d..ab97722c782d 100644 --- a/src/zlib/Cargo.toml +++ b/src/zlib/Cargo.toml @@ -10,7 +10,6 @@ path = "lib.rs" workspace = true [dependencies] -thiserror.workspace = true strum.workspace = true bstr.workspace = true scopeguard.workspace = true From 1be168ba817a85b5c28832b40fcb57796899ffd3 Mon Sep 17 00:00:00 2001 From: robobun <117481402+robobun@users.noreply.github.com> Date: Sat, 1 Aug 2026 19:07:42 +0000 Subject: [PATCH 10/15] ci: retrigger From a93d2fa48e875234e6ac51d2c7f6a394d1b031c9 Mon Sep 17 00:00:00 2001 From: robobun <117481402+robobun@users.noreply.github.com> Date: Sun, 2 Aug 2026 00:11:30 +0000 Subject: [PATCH 11/15] net.ts: restore kServerSocket; it is a GC retention edge, not dead code CI build 87459 crashed sql-close-pending-connection.test.ts on 6 lanes (debian x64-asan, ubuntu aarch64, alpine x64/aarch64, windows x64/aarch64) with an AllocatingScope assertion inside JSC::LocalAllocator::allocateSlowCase. Stack: JSPromise allocation -> GC slow path -> Heap::sweepInFinalize -> Listener::finalize -> deinit -> SocketGroup::close_all -> on_close -> JSValue::call -> allocation during sweep -> assert. The only net.ts change in this PR was removing kServerSocket (defined + written once, never read). The write clientHandle[kServerSocket] = handle stores the server's native Listener handle on each accepted socket's handle, which is a GC edge: the Listener stays reachable while any accepted socket handle is alive. server.close() in node:net stops accepting but does not close existing connections, so after a test's server local goes out of scope the accepted socket is the only thing keeping the Listener out of the finalizer. Without that edge the Listener is finalized while its socket group still holds the accepted socket; Listener::finalize -> close_all fires the socket's JS on_close callback during the sweep, which asserts. kServerSocket is restored with a comment documenting why it exists. kpendingRead stays removed (its only write was this[kpendingRead] = undefined, which retains nothing). --- src/js/node/net.ts | 7 +++++++ .../source-lints/dead-symbols-napi-nodevm-libuv.test.ts | 1 - 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/js/node/net.ts b/src/js/node/net.ts index 86e53f48a82f..26190dac85b7 100644 --- a/src/js/node/net.ts +++ b/src/js/node/net.ts @@ -122,6 +122,12 @@ const bunTlsSymbol = Symbol.for("::buntls::"); const bunSocketServerOptions = Symbol.for("::bunnetserveroptions::"); const owner_symbol = Symbol("owner_symbol"); +// The `clientHandle[kServerSocket] = handle` write in onconnection is the only +// use: it is a GC edge that keeps the native Listener reachable while an +// accepted socket's handle is alive. Without it the Listener can be finalized +// with sockets still in its group, and Listener::finalize -> close_all fires +// the JS on_close callback during the GC sweep (asserts in AllocatingScope). +const kServerSocket = Symbol("kServerSocket"); const kBytesWritten = Symbol("kBytesWritten"); const bunTLSConnectOptions = Symbol.for("::buntlsconnectoptions::"); // tls.Server exposes its native SecureContext constructor through this key so @@ -1123,6 +1129,7 @@ function onconnection(err, clientHandle) { self.emit("error", err); return; } + clientHandle[kServerSocket] = handle; const options = self[bunSocketServerOptions]; const { pauseOnConnect, connectionListener, [kSocketClass]: SClass } = options; // Propagate the server's half-open/highWaterMark settings to the accepted diff --git a/test/internal/source-lints/dead-symbols-napi-nodevm-libuv.test.ts b/test/internal/source-lints/dead-symbols-napi-nodevm-libuv.test.ts index 3e4ad2ee9734..7e4683ac84cd 100644 --- a/test/internal/source-lints/dead-symbols-napi-nodevm-libuv.test.ts +++ b/test/internal/source-lints/dead-symbols-napi-nodevm-libuv.test.ts @@ -95,7 +95,6 @@ test("zlib / io / install / net.ts dead items do not reappear", () => { ["src/io/windows_event_loop.rs", /pub fn can_ref\(&self\) -> bool/], ["src/install/lockfile/bun.lock.rs", /\/\/ pub fn save\(this: &Lockfile\)/], ["src/js/node/net.ts", /const kpendingRead = Symbol\("kpendingRead"\);/], - ["src/js/node/net.ts", /const kServerSocket = Symbol\("kServerSocket"\);/], ]; const resurrected = checks.filter(([file, re]) => re.test(src(file))).map(([file, re]) => `${file}: ${re.source}`); expect(resurrected).toEqual([]); From 6adef0a6140a26e33990808042112a0a4a6965ef Mon Sep 17 00:00:00 2001 From: robobun <117481402+robobun@users.noreply.github.com> Date: Sun, 2 Aug 2026 00:14:07 +0000 Subject: [PATCH 12/15] net.ts: shrink kServerSocket comment to two lines --- src/js/node/net.ts | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/js/node/net.ts b/src/js/node/net.ts index 26190dac85b7..6e8dc59a568d 100644 --- a/src/js/node/net.ts +++ b/src/js/node/net.ts @@ -122,11 +122,8 @@ const bunTlsSymbol = Symbol.for("::buntls::"); const bunSocketServerOptions = Symbol.for("::bunnetserveroptions::"); const owner_symbol = Symbol("owner_symbol"); -// The `clientHandle[kServerSocket] = handle` write in onconnection is the only -// use: it is a GC edge that keeps the native Listener reachable while an -// accepted socket's handle is alive. Without it the Listener can be finalized -// with sockets still in its group, and Listener::finalize -> close_all fires -// the JS on_close callback during the GC sweep (asserts in AllocatingScope). +// Write-only by design: the onconnection write is a GC edge keeping the +// native Listener reachable via accepted socket handles (see a93d2fa48e). const kServerSocket = Symbol("kServerSocket"); const kBytesWritten = Symbol("kBytesWritten"); const bunTLSConnectOptions = Symbol.for("::buntlsconnectoptions::"); From 4dd5a9973d1e7ca5367863a00f0730c630962574 Mon Sep 17 00:00:00 2001 From: robobun <117481402+robobun@users.noreply.github.com> Date: Sun, 2 Aug 2026 00:34:17 +0000 Subject: [PATCH 13/15] Revert all libuv header changes Restores src/jsc/bindings/libuv/uv/{aix,os390,sunos,posix,unix}.h and src/jsc/bindings/uv-posix-polyfills.c to main. Vendored headers should not be modified by dead-code sweeps. --- src/jsc/bindings/libuv/uv/aix.h | 32 ++++++++++++++ src/jsc/bindings/libuv/uv/os390.h | 33 ++++++++++++++ src/jsc/bindings/libuv/uv/posix.h | 31 +++++++++++++ src/jsc/bindings/libuv/uv/sunos.h | 44 +++++++++++++++++++ src/jsc/bindings/libuv/uv/unix.h | 15 ++++++- src/jsc/bindings/uv-posix-polyfills.c | 10 +++++ .../dead-symbols-napi-nodevm-libuv.test.ts | 15 +------ 7 files changed, 166 insertions(+), 14 deletions(-) create mode 100644 src/jsc/bindings/libuv/uv/aix.h create mode 100644 src/jsc/bindings/libuv/uv/os390.h create mode 100644 src/jsc/bindings/libuv/uv/posix.h create mode 100644 src/jsc/bindings/libuv/uv/sunos.h diff --git a/src/jsc/bindings/libuv/uv/aix.h b/src/jsc/bindings/libuv/uv/aix.h new file mode 100644 index 000000000000..5a5c4cc67e16 --- /dev/null +++ b/src/jsc/bindings/libuv/uv/aix.h @@ -0,0 +1,32 @@ +/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef UV_AIX_H +#define UV_AIX_H + +#define UV_PLATFORM_LOOP_FIELDS \ + int fs_fd; + +#define UV_PLATFORM_FS_EVENT_FIELDS \ + uv__io_t event_watcher; \ + char* dir_filename; + +#endif /* UV_AIX_H */ diff --git a/src/jsc/bindings/libuv/uv/os390.h b/src/jsc/bindings/libuv/uv/os390.h new file mode 100644 index 000000000000..c68b71cf20c3 --- /dev/null +++ b/src/jsc/bindings/libuv/uv/os390.h @@ -0,0 +1,33 @@ +/* Copyright libuv project contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef UV_MVS_H +#define UV_MVS_H + +#define UV_PLATFORM_SEM_T long + +#define UV_PLATFORM_LOOP_FIELDS \ + void* ep; + +#define UV_PLATFORM_FS_EVENT_FIELDS \ + char rfis_rftok[8]; + +#endif /* UV_MVS_H */ diff --git a/src/jsc/bindings/libuv/uv/posix.h b/src/jsc/bindings/libuv/uv/posix.h new file mode 100644 index 000000000000..8c75a3514636 --- /dev/null +++ b/src/jsc/bindings/libuv/uv/posix.h @@ -0,0 +1,31 @@ +/* Copyright libuv project contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef UV_POSIX_H +#define UV_POSIX_H + +#define UV_PLATFORM_LOOP_FIELDS \ + struct pollfd* poll_fds; \ + size_t poll_fds_used; \ + size_t poll_fds_size; \ + unsigned char poll_fds_iterating; + +#endif /* UV_POSIX_H */ diff --git a/src/jsc/bindings/libuv/uv/sunos.h b/src/jsc/bindings/libuv/uv/sunos.h new file mode 100644 index 000000000000..3842047c509d --- /dev/null +++ b/src/jsc/bindings/libuv/uv/sunos.h @@ -0,0 +1,44 @@ +/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef UV_SUNOS_H +#define UV_SUNOS_H + +#include +#include + +/* For the sake of convenience and reduced #ifdef-ery in src/unix/sunos.c, + * add the fs_event fields even when this version of SunOS doesn't support + * file watching. + */ +#define UV_PLATFORM_LOOP_FIELDS \ + uv__io_t fs_event_watcher; \ + int fs_fd; + +#if defined(PORT_SOURCE_FILE) + +#define UV_PLATFORM_FS_EVENT_FIELDS \ + file_obj_t fo; \ + int fd; + +#endif /* defined(PORT_SOURCE_FILE) */ + +#endif /* UV_SUNOS_H */ diff --git a/src/jsc/bindings/libuv/uv/unix.h b/src/jsc/bindings/libuv/uv/unix.h index 9dd9af994c72..3dad451d13a3 100644 --- a/src/jsc/bindings/libuv/uv/unix.h +++ b/src/jsc/bindings/libuv/uv/unix.h @@ -36,8 +36,10 @@ #include #include +#if !defined(__MVS__) #include #include /* MAXHOSTNAMELEN on Linux and the BSDs */ +#endif #include #include @@ -45,10 +47,20 @@ #if defined(__linux__) #include "uv/linux.h" +#elif defined(__MVS__) +#include "uv/os390.h" +#elif defined(__PASE__) /* __PASE__ and _AIX are both defined on IBM i */ +#include "uv/posix.h" /* IBM i needs uv/posix.h, not uv/aix.h */ +#elif defined(_AIX) +#include "uv/aix.h" +#elif defined(__sun) +#include "uv/sunos.h" #elif defined(__APPLE__) #include "uv/darwin.h" #elif defined(__DragonFly__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) #include "uv/bsd.h" +#elif defined(__CYGWIN__) || defined(__MSYS__) || defined(__HAIKU__) || defined(__QNX__) || defined(__GNU__) +#include "uv/posix.h" #endif #ifndef NI_MAXHOST @@ -118,7 +130,8 @@ typedef UV_PLATFORM_SEM_T uv_sem_t; typedef pthread_cond_t uv_cond_t; typedef pthread_key_t uv_key_t; -#if defined(__OpenBSD__) || !defined(PTHREAD_BARRIER_SERIAL_THREAD) +/* Note: guard clauses should match uv_barrier_init's in src/unix/thread.c. */ +#if defined(_AIX) || defined(__OpenBSD__) || !defined(PTHREAD_BARRIER_SERIAL_THREAD) /* TODO(bnoordhuis) Merge into uv_barrier_t in v2. */ struct _uv_barrier { uv_mutex_t mutex; diff --git a/src/jsc/bindings/uv-posix-polyfills.c b/src/jsc/bindings/uv-posix-polyfills.c index 50bbc556cafb..3eea2489c1bf 100644 --- a/src/jsc/bindings/uv-posix-polyfills.c +++ b/src/jsc/bindings/uv-posix-polyfills.c @@ -25,10 +25,20 @@ uint64_t uv__hrtime(uv_clocktype_t type); #if defined(__linux__) #include "uv-posix-polyfills-linux.c" +// #elif defined(__MVS__) +// #include "uv/os390.h" +// #elif defined(__PASE__) /* __PASE__ and _AIX are both defined on IBM i */ +// #include "uv/posix.h" /* IBM i needs uv/posix.h, not uv/aix.h */ +// #elif defined(_AIX) +// #include "uv/aix.h" +// #elif defined(__sun) +// #include "uv/sunos.h" #elif defined(__APPLE__) #include "uv-posix-polyfills-darwin.c" #elif defined(__FreeBSD__) #include "uv-posix-polyfills-posix.c" +#elif defined(__CYGWIN__) || defined(__MSYS__) || defined(__HAIKU__) || defined(__QNX__) || defined(__GNU__) +#include "uv-posix-polyfills-posix.c" #endif uv_pid_t uv_os_getpid() diff --git a/test/internal/source-lints/dead-symbols-napi-nodevm-libuv.test.ts b/test/internal/source-lints/dead-symbols-napi-nodevm-libuv.test.ts index 7e4683ac84cd..e99362394dcd 100644 --- a/test/internal/source-lints/dead-symbols-napi-nodevm-libuv.test.ts +++ b/test/internal/source-lints/dead-symbols-napi-nodevm-libuv.test.ts @@ -1,7 +1,7 @@ // Guards against reintroduction of symbols removed as dead code from napi, // NodeVM*, JSBufferList, JSStringDecoder, BunClientData, EventLoopTask, -// JSEnvironmentVariableMap, libuv platform headers, zlib, io/windows_event_loop, -// and node/net.ts. Each entry was verified to have zero callers across src/ +// JSEnvironmentVariableMap, zlib, io/{posix,windows}_event_loop, and +// node/net.ts. Each entry was verified to have zero callers across src/ // and build/debug/codegen/ before deletion; this test fails if any reappear. // // This is a source-tree lint: it reads files from src/ and does not touch the @@ -74,17 +74,6 @@ test("BunClientData / EventLoopTask / JSEnvironmentVariableMap / blob / Bindgen expect(resurrected).toEqual([]); }); -test("libuv platform headers for non-targeted OSes are not included", () => { - // Assert against the surviving includer rather than `existsSync` on the - // deleted header paths: the gate's stash/restore step can leave deleted - // files on disk, and an unreferenced header on disk is harmless anyway. - const unix = src("src/jsc/bindings/libuv/uv/unix.h"); - expect(unix).not.toMatch(/#include "uv\/aix\.h"/); - expect(unix).not.toMatch(/#include "uv\/os390\.h"/); - expect(unix).not.toMatch(/#include "uv\/sunos\.h"/); - expect(unix).not.toMatch(/#include "uv\/posix\.h"/); -}); - test("zlib / io / install / net.ts dead items do not reappear", () => { const checks: Array<[string, RegExp]> = [ ["src/zlib/lib.rs", /^pub mod error;$/m], From 0a3dcec037a8bdff313e9b3ed72f9a23d9b963d7 Mon Sep 17 00:00:00 2001 From: robobun <117481402+robobun@users.noreply.github.com> Date: Sun, 2 Aug 2026 00:53:55 +0000 Subject: [PATCH 14/15] source-lint: add posix_event_loop.rs checks; rename to drop stale -libuv suffix The test's header comment claims io/{posix,windows}_event_loop coverage but only pinned the windows side; add the posix ref_ and declare_scope!(KeepAlive) entries removed in 6c7b2261/c52ae889. Rename the file to reflect that the libuv header checks were dropped in 4dd5a9973d. --- ...m-libuv.test.ts => dead-symbols-napi-nodevm-io-zlib.test.ts} | 2 ++ 1 file changed, 2 insertions(+) rename test/internal/source-lints/{dead-symbols-napi-nodevm-libuv.test.ts => dead-symbols-napi-nodevm-io-zlib.test.ts} (97%) diff --git a/test/internal/source-lints/dead-symbols-napi-nodevm-libuv.test.ts b/test/internal/source-lints/dead-symbols-napi-nodevm-io-zlib.test.ts similarity index 97% rename from test/internal/source-lints/dead-symbols-napi-nodevm-libuv.test.ts rename to test/internal/source-lints/dead-symbols-napi-nodevm-io-zlib.test.ts index e99362394dcd..2ddb25d42e6f 100644 --- a/test/internal/source-lints/dead-symbols-napi-nodevm-libuv.test.ts +++ b/test/internal/source-lints/dead-symbols-napi-nodevm-io-zlib.test.ts @@ -82,6 +82,8 @@ test("zlib / io / install / net.ts dead items do not reappear", () => { ["src/io/windows_event_loop.rs", /pub fn ref_\(&mut self, event_loop_ctx: EventLoopCtx\)/], ["src/io/windows_event_loop.rs", /pub fn activate\(&mut self, loop_: &mut WindowsLoop\)/], ["src/io/windows_event_loop.rs", /pub fn can_ref\(&self\) -> bool/], + ["src/io/posix_event_loop.rs", /pub fn ref_\(&mut self, event_loop_ctx: EventLoopCtx\)/], + ["src/io/posix_event_loop.rs", /declare_scope!\(KeepAlive/], ["src/install/lockfile/bun.lock.rs", /\/\/ pub fn save\(this: &Lockfile\)/], ["src/js/node/net.ts", /const kpendingRead = Symbol\("kpendingRead"\);/], ]; From f32c435f04412c363b80ef480ef96c6ca6d7c58f Mon Sep 17 00:00:00 2001 From: Jarred Sumner Date: Sun, 2 Aug 2026 00:52:28 -0700 Subject: [PATCH 15/15] Delete test/internal/source-lints/dead-symbols-napi-nodevm-io-zlib.test.ts --- .../dead-symbols-napi-nodevm-io-zlib.test.ts | 92 ------------------- 1 file changed, 92 deletions(-) delete mode 100644 test/internal/source-lints/dead-symbols-napi-nodevm-io-zlib.test.ts diff --git a/test/internal/source-lints/dead-symbols-napi-nodevm-io-zlib.test.ts b/test/internal/source-lints/dead-symbols-napi-nodevm-io-zlib.test.ts deleted file mode 100644 index 2ddb25d42e6f..000000000000 --- a/test/internal/source-lints/dead-symbols-napi-nodevm-io-zlib.test.ts +++ /dev/null @@ -1,92 +0,0 @@ -// Guards against reintroduction of symbols removed as dead code from napi, -// NodeVM*, JSBufferList, JSStringDecoder, BunClientData, EventLoopTask, -// JSEnvironmentVariableMap, zlib, io/{posix,windows}_event_loop, and -// node/net.ts. Each entry was verified to have zero callers across src/ -// and build/debug/codegen/ before deletion; this test fails if any reappear. -// -// This is a source-tree lint: it reads files from src/ and does not touch the -// built binary, so it belongs in test/internal/source-lints/ per the README. - -import { expect, test } from "bun:test"; -import { readFileSync } from "node:fs"; -import path from "node:path"; - -const repoRoot = path.resolve(import.meta.dir, "..", "..", ".."); - -function src(p: string): string { - return readFileSync(path.join(repoRoot, p), "utf8"); -} - -test("napi / NodeVM / JSBufferList / JSStringDecoder dead methods do not reappear", () => { - const checks: Array<[string, RegExp]> = [ - ["src/jsc/bindings/napi.cpp", /JSC::SourceCode generateSourceCode\(WTF::String keyString/], - ["src/jsc/bindings/napi.h", /JSC::SourceCode generateSourceCode\(/], - ["src/jsc/bindings/napi.h", /bool isSet\(\) const \{ return m_tag != WeakTypeTag::NotSet; \}/], - ["src/jsc/bindings/napi.h", /JSCell\* cell\(\) const\s*\{/], - ["src/jsc/bindings/napi.h", /JSValue primitive\(\) const\s*\{/], - ["src/jsc/bindings/napi.h", /JSString\* string\(\) const\s*\{/], - ["src/jsc/bindings/NodeVM.h", /void clearContextifiedObject\(\);/], - ["src/jsc/bindings/NodeVM.cpp", /void NodeVMGlobalObject::clearContextifiedObject\(\)/], - ["src/jsc/bindings/NodeVMModule.h", /void addImportAttribute\(WTF::String key/], - ["src/jsc/bindings/NodeVMModule.cpp", /void NodeVMModuleRequest::addImportAttribute\(/], - ["src/jsc/bindings/NodeVMModule.h", /void specifier\(WTF::String value\)/], - ["src/jsc/bindings/NodeVMSourceTextModule.h", /bool hasModuleRecord\(\) const/], - ["src/jsc/bindings/NodeVMSyntheticModule.h", /bool hasModuleRecord\(\) const/], - ["src/jsc/bindings/NodeVMScript.h", /RefPtr cachedBytecode\(\) const/], - [ - "src/jsc/bindings/JSBufferList.h", - /void initializeProperties\(JSC::VM& vm, JSC::JSGlobalObject\* globalObject, JSBufferListPrototype\* prototype\);/, - ], - ["src/jsc/bindings/JSBufferList.cpp", /void JSBufferListConstructor::initializeProperties\(/], - ["src/jsc/bindings/JSBufferList.h", /static void destroy\(JSCell\*\) \{\}/], - [ - "src/jsc/bindings/JSStringDecoder.h", - /void initializeProperties\(JSC::VM& vm, JSC::JSGlobalObject\* globalObject, JSStringDecoderPrototype\* prototype\);/, - ], - ["src/jsc/bindings/JSStringDecoder.cpp", /void JSStringDecoderConstructor::initializeProperties\(/], - ["src/jsc/bindings/JSNextTickQueue.h", /static std::array initialValues\(\)/], - ["src/jsc/bindings/ModuleLoader.h", /static std::array initialValues\(\)/], - ["src/jsc/bindings/JSMockFunction.h", /static std::array initialValues\(\)/], - ]; - const resurrected = checks.filter(([file, re]) => re.test(src(file))).map(([file, re]) => `${file}: ${re.source}`); - expect(resurrected).toEqual([]); -}); - -test("BunClientData / EventLoopTask / JSEnvironmentVariableMap / blob / Bindgen dead members do not reappear", () => { - const clientData = src("src/jsc/bindings/BunClientData.h"); - // The JSHeapData copies (first occurrence) are live; the JSVMClientData - // duplicates (second occurrence) are the dead ones. After removal there - // should be exactly one occurrence of each. - expect((clientData.match(/Vector m_outputConstraintSpaces;/g) ?? []).length).toBe(1); - expect((clientData.match(/void forEachOutputConstraintSpace\(/g) ?? []).length).toBe(1); - expect((clientData.match(/Vector& outputConstraintSpaces\(\)/g) ?? []).length).toBe(1); - - const checks: Array<[string, RegExp]> = [ - ["src/jsc/bindings/EventLoopTask.h", /bool isCleanupTask\(\) const/], - ["src/jsc/bindings/EventLoopTask.h", /bool m_isCleanupTask;/], - ["src/jsc/bindings/EventLoopTask.h", /enum CleanupTaskTag/], - ["src/jsc/bindings/JSEnvironmentVariableMap.cpp", /JSC_DEFINE_CUSTOM_SETTER\(jsSetterEnvironmentVariable,/], - ["src/jsc/bindings/blob.h", /^using BlobRef = Ref re.test(src(file))).map(([file, re]) => `${file}: ${re.source}`); - expect(resurrected).toEqual([]); -}); - -test("zlib / io / install / net.ts dead items do not reappear", () => { - const checks: Array<[string, RegExp]> = [ - ["src/zlib/lib.rs", /^pub mod error;$/m], - ["src/zlib/lib.rs", /\bgzFile\b/], - ["src/zlib/lib.rs", /\bstruct_gzFile_s\b/], - ["src/io/windows_event_loop.rs", /pub fn ref_\(&mut self, event_loop_ctx: EventLoopCtx\)/], - ["src/io/windows_event_loop.rs", /pub fn activate\(&mut self, loop_: &mut WindowsLoop\)/], - ["src/io/windows_event_loop.rs", /pub fn can_ref\(&self\) -> bool/], - ["src/io/posix_event_loop.rs", /pub fn ref_\(&mut self, event_loop_ctx: EventLoopCtx\)/], - ["src/io/posix_event_loop.rs", /declare_scope!\(KeepAlive/], - ["src/install/lockfile/bun.lock.rs", /\/\/ pub fn save\(this: &Lockfile\)/], - ["src/js/node/net.ts", /const kpendingRead = Symbol\("kpendingRead"\);/], - ]; - const resurrected = checks.filter(([file, re]) => re.test(src(file))).map(([file, re]) => `${file}: ${re.source}`); - expect(resurrected).toEqual([]); -});