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
The current Perry/Perch Next.js adapter can execute NextResponse.json(...) inside an imported route, but it cannot consume the returned Response reliably. It therefore discards the real return value and fabricates deterministic response bytes in the caller. That makes the RSS/CPU result a lower bound rather than an apples-to-apples Next.js result.
Closed work such as #237 and #1650 established the Web Streams / Response.body surface. This issue is the remaining composed case: a NextResponse returned through an imported async App Route boundary, then inspected and drained by the app-library entry point.
Reproduction app (provided)
Use the exact pinned app and verifier attached to #8034. Do not replace the streamed response with NextResponse.json() or a hard-coded Buffer.
The supplied route returns:
status 207;
content-type: application/json; charset=utf-8;
x-perry-repro: <request id>;
Set-Cookie: perry_ctx=<request id>; ... via NextResponse.cookies;
a ReadableStream<Uint8Array> that emits the JSON in two chunks, with the second chunk queued in a microtask.
Focused oracle:
BASE_URL=http://127.0.0.1:3100 npm run verify
Required implementation behavior
For both Response and the NextResponse subclass:
preserve the native response identity/brand across a cross-module return and an async Promise<Response> return;
preserve status, status text, headers, and cookie mutations;
preserve body: ReadableStream | null, including the queued second chunk and close signal;
keep the response, Headers backing, stream handle, controller, queued chunks, and reader rooted for the full drain;
make repeated property reads and body reads resolve the same backing record;
surface a thrown/rejected stream error instead of hanging or returning an empty body.
The host ABI can serialize the final response after Perry has exposed these fields; that serialization is not a reason to fabricate a different response inside the test.
Regression coverage
Add a two-module minimal fixture in which module A returns a streamed Response both synchronously and asynchronously and module B validates status/headers/cookies and drains body.getReader(). Then keep #8034 as the production Next subclass/composition test.
Run both tests in executable mode and app-only dylib mode against the shared runtime/stdlib providers; this catches native-handle registries accidentally duplicated or hidden across images.
What happened?
The current Perry/Perch Next.js adapter can execute
NextResponse.json(...)inside an imported route, but it cannot consume the returnedResponsereliably. It therefore discards the real return value and fabricates deterministic response bytes in the caller. That makes the RSS/CPU result a lower bound rather than an apples-to-apples Next.js result.Closed work such as #237 and #1650 established the Web Streams /
Response.bodysurface. This issue is the remaining composed case: aNextResponsereturned through an imported async App Route boundary, then inspected and drained by the app-library entry point.Reproduction app (provided)
Use the exact pinned app and verifier attached to #8034. Do not replace the streamed response with
NextResponse.json()or a hard-coded Buffer.The supplied route returns:
207;content-type: application/json; charset=utf-8;x-perry-repro: <request id>;Set-Cookie: perry_ctx=<request id>; ...viaNextResponse.cookies;ReadableStream<Uint8Array>that emits the JSON in two chunks, with the second chunk queued in a microtask.Focused oracle:
Required implementation behavior
For both
Responseand theNextResponsesubclass:Promise<Response>return;body: ReadableStream | null, including the queued second chunk and close signal;The host ABI can serialize the final response after Perry has exposed these fields; that serialization is not a reason to fabricate a different response inside the test.
Regression coverage
Add a two-module minimal fixture in which module A returns a streamed
Responseboth synchronously and asynchronously and module B validates status/headers/cookies and drainsbody.getReader(). Then keep #8034 as the production Next subclass/composition test.Run both tests in executable mode and app-only dylib mode against the shared runtime/stdlib providers; this catches native-handle registries accidentally duplicated or hidden across images.
Acceptance criteria
GET(...)return value.Baseline / references
0.5.1503at564c56308d221a51b50308d9165578fbb176e877