You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
bench/RESULTS-v2.md (post-#82): chttp-fetch-node runs at 53–73% of chttp-node. The gap is not dispatch — it is per-request undici new Request(...) + new Headers + new Response construction plus resp.text() re-buffering in the Node→fetch bridge (bench/apps/chttp-fetch.ts shows the pattern: IncomingMessage → undici Request → app.fetch → undici Response → ServerResponse).
Direction
WebReqView/ResView are already structural interfaces — the runtime never nominally requires undici objects. c.req.raw on the fetch arm returns the WebReqView, not a real Request. So a Node bridge can:
Build a lightweight LiteRequest straight over IncomingMessage implementing the WebReqView members (method, url, headers-shaped map, buffered text()/arrayBuffer(), lazy body stream) — skipping undici's WHATWG URL/Headers machinery.
Serialize ResView/FetchResponseSink output straight to ServerResponse — skipping new Response + text().
Lazily materialize a real undici Request only when a consumer calls fetch(c.req.raw) or otherwise needs the host object (edge case — document).
Ship as an opt-in Node entry (e.g. app.serveFetch(port) or a documented bridge helper) — app.fetch keeps returning a real Response for WinterCG hosts.
Steps
node --cpu-prof the current chttp-fetch-node cell first to confirm the undici ctor share before writing the lite path.
Expected recovery: most of the 27–47% gap; ELF path (fetchShim primitives) already pays none of this.
Bench chttp-fetch-node re-run is the acceptance gate.
Activity
fix(router): lite sink multi-header writes inside the scriptc subset (#…
feat(router): lite Node fetch bridge for the fetch dispatch arm (#89) (…