fix(ext/node): don't emit 'finish' when a native http response races a client abort
Makes the full unit_node::http_test suite pass on the native node:http
fast path. Five fixes, each unblocking the next previously-masked
failure:
- ServerResponse 'finish' after client abort (#34002): an async
handler's end() can commit a response while the client's FIN is
still unprocessed (tokio's cached readiness misses a FIN that
arrived since the reactor last ran). The serve loop now takes a
raw-socket peek (MSG_PEEK, plain TCP/unix only) at commit time and
resolves the request's cancel watcher; the JS side defers the
'finish'/'close' choice for handler-returned-uncommitted responses
to that verdict, like Node, where 'finish' only follows a completed
socket write. Sync (hot path) responses are untouched.
- diagnostics_channel: publish http.server.request.start before the
native dispatch, and scope each dispatch's async context so a
subscriber's or handler's AsyncLocalStorage.enterWith() reaches the
handler but doesn't leak into later requests on the connection.
- async_hooks: run the handler in the IncomingMessage's async
resource (executionAsyncResource() === req, like parserOnIncoming),
and emulate Node's suspended keep-alive socket Timeout
(keepAliveTimeout + 1000) with an unref'd noop timer so hooks
observe its init/destroy; only allocated while hooks are active.
- Readable.toWeb(req) cancel (#33567): a stream destroyer() detaches
req.socket before destroying, which must not abort the response
through the native external; and a response finishing with a
started-but-incomplete body now force-closes the connection like
Node instead of trying to reuse it.
- graceful close vs unconsumed bodies: the post-response body drain
is now bounded by the server's cancel handle -- on server.close()
it consumes only the already-available tail, then shuts down the
write side so the response and FIN flush ahead of the close (a
close with unread data RSTs and can discard the just-written
response).