Skip to content

Add Bun runtime support#378

Draft
kriszyp wants to merge 21 commits intosymphony-prepfrom
bun-runtime-support
Draft

Add Bun runtime support#378
kriszyp wants to merge 21 commits intosymphony-prepfrom
bun-runtime-support

Conversation

@kriszyp
Copy link
Copy Markdown
Member

@kriszyp kriszyp commented Apr 18, 2026

  • Replace node-unix-socket native addon with native reusePort (Node v22+)
  • Add BunRequest adapter wrapping Web Fetch API Request
  • Branch http.ts to use Bun.serve() with fetch handler when running on Bun
  • Bridge Operations API (Fastify) to Bun via inject() in bunDelegateToNodeServer
  • Add listenOnPortsBun() using Bun.serve({ reusePort: true }) per worker
  • Support TLS/secure ports on Bun via Bun.serve({ tls: { cert, key } })
  • Create UDS mirror sockets for secure ports via Bun.serve({ unix })
  • Guard Node-specific APIs: v8, inspector, worker.performance, TLS monkey-patches
  • Fix performance.eventLoopUtilization() NotImplementedError on Bun
  • Skip Node version check when running on Bun
  • Parameterize integration tests via HARPER_RUNTIME env var (node|bun)
  • Add CI jobs to run integration tests and API tests on Bun

kriszyp and others added 9 commits April 17, 2026 22:18
- Replace node-unix-socket native addon with native reusePort (Node v22+)
- Add BunRequest adapter wrapping Web Fetch API Request
- Branch http.ts to use Bun.serve() with fetch handler when running on Bun
- Bridge Operations API (Fastify) to Bun via inject() in bunDelegateToNodeServer
- Add listenOnPortsBun() using Bun.serve({ reusePort: true }) per worker
- Support TLS/secure ports on Bun via Bun.serve({ tls: { cert, key } })
- Create UDS mirror sockets for secure ports via Bun.serve({ unix })
- Guard Node-specific APIs: v8, inspector, worker.performance, TLS monkey-patches
- Fix performance.eventLoopUtilization() NotImplementedError on Bun
- Skip Node version check when running on Bun
- Parameterize integration tests via HARPER_RUNTIME env var (node|bun)
- Add CI jobs to run integration tests and API tests on Bun

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Required by repo policy that all actions must be pinned to a full-length commit SHA.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The 4.x-upgrade test returns early from before() when HARPER_LEGACY_VERSION_PATH
is not set, leaving ctx.harper undefined. killHarper/teardownHarper now no-op
gracefully in that case instead of crashing.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
listenOnPortsBun() was using +port directly on keys like "127.0.0.14:9926",
which produces NaN and hits the isNaN guard, skipping every port. Parse
host:port strings the same way listenOnPorts() does for Node — split on the
last colon and pass hostname + numeric port to Bun.serve().

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
On Node, Harper's httpChain auth middleware sets request._nodeRequest.user
for loopback connections in dev mode (AUTHORIZE_LOCAL), which Fastify picks up
via req.raw.user and bypasses its own auth check (fastifyAuth.js:35).

On Bun, bunDelegateToNodeServer calls fastify.inject() with a fresh synthetic
request — no req.raw.user, so Fastify re-runs auth and returns 401.

Fix: strip any incoming x-harper-internal-pre-auth-user header (preventing
forgery), then set it in the inject() call when Harper's auth middleware has
already authenticated the request. fastifyAuth.js trusts this header as an
equivalent to req.raw.user.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The 'send' module (used for static files) calls setHeader/writeHead on the
pipe destination. In the Bun handler, the destination must be a Writable with
a ServerResponse shim so those calls capture headers into the web Response.

The critical bug: 'on-finished' (a send dependency) calls isFinished() which
checks msg.finished. In Bun, Writable.finished is undefined (not a boolean),
so isFinished() returns undefined. Since undefined !== false, on-finished
immediately schedules cleanup() via setImmediate, destroying the ReadStream
before any data flows — causing the response to hang forever.

Fix: add finished: false to the shim object so isFinished() sees a boolean
false and correctly waits for the 'finish' event before calling cleanup().

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@heskew
Copy link
Copy Markdown
Member

heskew commented Apr 18, 2026

👀

kriszyp added 12 commits April 18, 2026 19:35
…rove `process.exit` handling for Bun by force-closing server connections.
…to single HTTP worker

- Remove socket file descriptor passing and proxying logic from http.ts and threadServer.js
- Remove startSocketServer and session affinity implementation from socketRouter.ts
- Remove proxySocket, proxyRequest, and deliverSocket functions
- Simplify lite.js to only start HTTP threads without socket servers
- Add Windows-specific CI workflow for build and integration tests
- Limit Windows to single HTTP worker (no SO_REUSEPORT support)
- Fix package.json test scripts to use double quotes for Windows compatibility
- Disable segfault handler on Bun runtime
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants