Summary
http.Server is a net handle, not %EventEmitter. off(), listeners(), and on("newListener") therefore have no lowering for HTTP events, even though on("request") / on("upgrade") already do.
T3 Code's src/httpResponseErrorGuard.ts (rejectRequestsUntilServing) is the real-world harness: it registers temporary 503 handlers, then uses newListener + listeners().includes() + off() to drop them when the serving handlers attach. Node emits newListener before the add, so the handoff is synchronous.
Expected
This program should compile and match Node:
import * as http from "node:http";
const server = http.createServer();
const rejectRequest = (_req: http.IncomingMessage, res: http.ServerResponse) => {
res.writeHead(503).end();
};
server.on("request", rejectRequest);
server.on("newListener", function onNewListener(event) {
if (event === "request") server.off("request", rejectRequest);
if (!server.listeners("request").includes(rejectRequest)) {
server.off("newListener", onNewListener);
}
});
server.on("request", (_req, res) => {
res.end("ok");
});newListener fires before the second on("request"), off removes the last matching HTTP listener, and listeners() returns those functions by identity.
Actual (0.4.7)
server.off("request" | "upgrade" | "newListener"), server.listeners(...), and server.on("newListener") are SC1090 / no-lowering. Net-only off("error" | "close" | ...) already works.
Out of scope (fork-side)
res.on("error") on ServerResponse is a different surface. The T3 fork should replace that with abort/writableEnded rather than asking scriptc to lower writable error events in this issue.
Evidence
Plan E3: real src/httpResponseErrorGuard.ts harness failed on newListener, listeners(), off(), res.on("error").
I reported this issue via Cursor Agent. Will attach a PR to fix it today 👍🏼