Skip to content

Link gap: hono + node:http combination drops Web Fetch FFIs (js_headers_new / js_response_new) #589

Description

@proggeramlug

Repro

```json
{
"perry": {
"compilePackages": ["hono"]
},
"dependencies": { "hono": "^4.6.0" }
}
```

```ts
import { Hono } from "hono"
import { createServer } from "node:http"

const app = new Hono()
app.get("/", (c) => c.json({ ok: true }))

createServer(async (req: any, res: any) => {
const fetchReq = new Request(`http://${req.headers.host}${req.url}`, { method: req.method })
const fetchRes = await app.fetch(fetchReq)
res.statusCode = fetchRes.status
fetchRes.headers.forEach((v: string, k: string) => res.setHeader(k, v))
res.end(await fetchRes.text())
}).listen(3000)
```

`perry compile` link error:

```
Undefined symbols for architecture arm64:
"_js_headers_new", referenced from:
_perry_closure_node_modules_hono_dist_context_js__14
_perry_method_node_modules_hono_dist_context_js__Context___newResponse
"_js_response_new", referenced from:
_perry_closure_node_modules_hono_dist_context_js__23
_perry_closure_node_modules_hono_dist_hono_base_js__29
_perry_method_node_modules_hono_dist_http_exception_js__HTTPException__getResponse
```

What works in isolation

What's broken

Combining the two — using `node:http` to drive hono's `app.fetch` (the canonical "deploy a hono app on a Linux VM" pattern) — fails to link because perry-ext-fetch isn't pulled in alongside perry-ext-http-server.

Root cause

`perry-stdlib`'s `http-client` feature gate (which exports `js_headers_new` / `js_response_new` from `fetch.rs`) is stripped by the well-known module flip when `node:http` is imported. The flip routes the `http` import to `perry-ext-http-server` and assumes that's sufficient — but hono's compiled output uses `new Headers()` / `new Response()` which need the Web Fetch FFIs from a separate staticlib (`perry-ext-fetch`).

The fix is one of:

  1. Always link `perry-ext-fetch` when any `compilePackages`-resolved code uses `Headers` / `Response` / `Request` constructors.
  2. Don't strip `http-client` from perry-stdlib when `node:http` is imported (lose some size, gain correctness).
  3. Re-export `js_headers_new` / `js_response_new` from `perry-ext-http-server` as a compatibility shim.

Likely site: `crates/perry/src/commands/stdlib_features.rs` (the feature-gate decision) or `crates/perry/src/commands/compile/link.rs` (the staticlib-pulling decision).

Acceptance

The repro at the top compiles + links cleanly. `./binary &; curl localhost:3000` returns hono's JSON response.

Refs #421, #486, #487, #577

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions