SIGN IN SIGN UP
denoland / deno UNCLAIMED

A modern runtime for JavaScript and TypeScript.

0 0 3 Rust

fix(ext/node): enable HTTP parser consume fast path (#33354)

In our llhttp wiring we had a fast path to avoid the JS readable stream
and let the parser read straight from the underlying uv stream.

Several bugs blocked the parser.consume path for anything other than
bare TCPWrap:

- try_unwrap_cppgc_object returns None for any subclass of
LibUvStreamWrap (TCPWrap, TLSWrap, PipeWrap), so the consume fast path
silently no-op'd. Use try_unwrap_cppgc_base_object to match via the base
class.

- The C callback invoked kOnExecute with the raw nread=0 sentinel
(EAGAIN/WouldBlock via libuv's alloc+nread=0 idiom), firing a spurious
v8 scope + function-call round trip per request. Match Node's
node_http_parser.cc:OnStreamRead — skip empty reads.

- Parse errors on the consume fast path invoked kOnExecute with a raw
-1. The JS .execute() wrapper (http_parser.ts) converts negative returns
into an Error object with code/reason/bytesParsed before
onParserExecuteCommon runs its `ret instanceof Error` branch. The
consume path bypassed the wrapper, so protocol errors (chunked-smuggling
etc.) silently wedged the connection. Build the same Error shape in
Rust.

- Casting `&mut ContextScope<HandleScope>` directly to `*mut PinScope`
is UB — ContextScope has a different layout. Coerce via Deref first so
ExecuteContext sees a real PinScope pointer.

- On the consume path the read interceptor borrows buf.base during its
callback but doesn't take ownership, so the caller must free it — we
weren't, leaking 64KB per read once interceptors were actually
exercised.

Increases throughput by about 6% on hello world
N
Nathan Whitaker committed
ea1be680ad5ad2c33deea715cc8554a232557cd5
Parent: b3568ec
Committed by GitHub <noreply@github.com> on 4/22/2026, 8:19:26 AM