bun_ptr: RefPtr releases on Drop; remove ScopedRef/IntrusiveRc/DestructorCtx
What does this PR do?
RefPtr<T> (bun_ptr's owned handle to an intrusively refcounted T) previously had no Drop, so every holder released its ref by hand — .deref() inside Drop impls, take-then-deref at every early return, and a dozen one-off guard newtypes (StoreRef, ScopedRef, StaticRouteRef, FileSinkRef, DerefOnDrop, …) whose only job was to add the missing Drop. Forgetting one leaked; doing it twice was a use-after-free. This makes RefPtr behave like Arc: dropping releases the ref, Clone takes one, into_raw/from_raw move a ref across raw-pointer/FFI boundaries, and it is Send/Sync when T is. No runtime cost change — the same decrement happens at the same points, and RefPtr is now a #[repr(transparent)] NonNull<T> in every profile (the debug-only per-ref tracking it carried was write-only and is deleted; the refcount's use-after-destroy canary stays).
On top of that:
- One owning-ref type with one API (
new/init_ref/from_this/from_raw/into_raw/this_ptr/into_this_ptr/as_ptr/as_non_null).ScopedRef, theIntrusiveRcalias,ThisPtr::ref_guard,dupe_ref,data(), and the hand-rolled newtypes above (StoreRef,StaticRouteRef,FileSinkRef/FileSinkPtr,DerefOnDrop,ResolverRefGuard,Scheduler/WatcherRefGuard,RefDataPtr) are folded into it;HTTPContext.h2_session, h3PendingConnect.session, subprocessWritable::Pipe, and h2SignalRef.parserhold aRefPtrinstead of a raw pointer + manual deref. Types that take a keep-alive ref on&selfall spell itself.ref_guard(). - The unused
DestructorCtxassociated type is removed from the refcount traits. WeakPtrreleases onDrop(its manualderef()is gone).JsCell::setwrites first and drops the old value after (matchingCell::set), so a field whoseDropre-enters or frees the owner is sound.- ~60 manual
.deref()sites,AnyRoute::deref_, and severalDrop/finalizebodies that existed only to release a ref are deleted. - Pre-existing, fixed while here: the install security scanner over-released its JSON pipe writer when
start()failed (use-after-free on that error path), and on Windows its errdefer closed the uv pipe a second time after the writer already owned it. s3.test.ts: fix a racyreceived += await …accumulator that under-counted when two part uploads overlapped.
First step of replacing manual deinit/deref teardown with ownership + Drop across the Rust tree; converting the remaining raw *mut T holders of refcounted types to RefPtr follows separately.
How did you verify your code works?
cargo check --workspace + clippy for linux-gnu/musl, windows, darwin, freebsd, android. Debug build + targeted suites covering every touched holder: blob/Bun.file/Bun.write, serve static/file/html/routes + reload, body-leak, WebSocket client (incl. proxy tunnel), fetch keep-alive/http2/proxy/SSL-ctx eviction, spawn stdin/stdout, shell, FileSink, cron, dns, fs.watchFile, TLS upgrade/duplex, node http2, S3 multipart, archive, security scanner, bake dev server, bun:test done-callback/expect — all pass.