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:
- Always link `perry-ext-fetch` when any `compilePackages`-resolved code uses `Headers` / `Response` / `Request` constructors.
- Don't strip `http-client` from perry-stdlib when `node:http` is imported (lose some size, gain correctness).
- 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
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
honoend-to-end viaperry.compilePackages#421, Hono acceptance: 30-line program with hono/cors or hono/logger middleware end-to-end #486, Hono acceptance: @hono/perry-server adapter (4th acceptance bullet of #421) #487 closed).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:
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