Repository navigation
[Next.js/dylib] Preserve NextRequest and nextUrl.searchParams across App Route imports #8036
Description
Activity
- addedbugConfirmed defect or regressionConfirmed defect or regressionparityCompatibility gap with Node.js, ECMAScript, or the supported ecosystemCompatibility gap with Node.js, ECMAScript, or the supported ecosystem
on Aug 13, 2026 - added 10 commits that reference this issue
on Aug 15, 2026 Closing: everything this issue asked for has landed on
mainexcept the forced-evacuation arm, which was split out as #8163 and stays open there.PR #8082's body says "Closes #8034 and #8036", but GitHub only links the first reference in that phrasing (each issue needs its own keyword), so #8034 auto-closed on merge and this one did not. Closing manually per that intent.
What landed, and where it is gated
- Small compiler fixture with forced/verified evacuation — fix(gc): preserve request graphs across route imports #8044 (
fe0d49792):test-files/test_gap_gc_next_request_import.ts+test-files/fixtures/gc_next_request_import/(request-shaped class through a re-exported imported handler; allocation, dynamic import, promise + timer continuation, body read; 20 concurrent handlers started before the first await; explicitgc()while all 20 are suspended). Registered intest-parity/gc_repsel_corpus.txt, soscripts/gc_repsel_matrix.shruns it under theforce_verify/verify_evac/cons_scan_offarms ingc-moving-witnesses— green onmain(latest scheduled run 31932625278, 2026-08-16 06:56 UTC,3be2016c1). - Production integration test from [Next.js/dylib] Add a pinned production App Route parity fixture and CI gate #8034 — test(next): land the pinned production App Route fixture and its dylib gate #8161 (
e75191b93):tests/fixtures/next-app-route/with therouteModule.handlebypass guard armed,tests/test_next_app_route_dylib.shgrepping the host log for the guard (its signal cannot reachverify.mjs's exit code), wired asnext-app-route.yml(workflow_dispatch+ nightly17 3 * * *UTC; merged after today's slot, so its first scheduled run is 2026-08-17). - Runtime/codegen fixes and the release-tier fixture — fix(next): pass production App Route dylib gate #8082 (
53e8a21e3):tests/release/packages/next-app-route/fixture.sh(Node production oracle, separate runtime/stdlib provider images, untouched webpack output compiled as an app-only dylib, 10 cold processes × 2 verifier passes) — normal arm PASS on that head; plus the stacked defects it took to get there: Scope split unknown-function fallback wrappers by module #8078, fix(codegen): unbreak in-process RS4GC on inline asm and relocation-grown functions #8128, fix(gc): root heap values held across JS-running calls in runtime and ext-http #8131, fix(next): make computed relative chunk requires resolve in a compiled App Route #8146, fix(hir): a nested class's own name beats an enclosing binding innew#8153, fix(gc): prune FUNCTION_CLASS_IDS keys whose closure died (#8040) #8168.
What is NOT closed here — acceptance bullet 4, "passes with forced/verified GC": the production route under
PERRY_GC_FORCE_EVACUATE=1 … PERRY_GC_SCHEDULE_SEED=8036still dies withTypeError: value is not a functionfrom a holder outside the GC heap. That is #8163, opt-in in the fixture behindPERRY_NEXT_ROUTE_FORCED_GC=1(off, fails loudly when set — not a SKIP, notcontinue-on-error).One reconciliation note for whoever touches the fixtures next: the release-tier copy's
perry-host.jsdoes not carry the bypass guard thattests/fixtures/next-app-route/perry-host.jshas; it relies on the forbidden-diagnostic grep instead. Both copies should converge on the armed host.- Small compiler fixture with forced/verified evacuation — fix(gc): preserve request graphs across route imports #8044 (
- added a commit that references this issue
on Sep 15, 2026
What happened?
The Perch Next.js lower-bound fixture on Perry
0.5.1503could construct aNextRequestin one module and call an imported route function, but could not rely on the callee receiving a usable request argument.NextRequest.nextUrl.searchParamswas also not reliable through that path, so the benchmark had to ignore the request and hard-code its workload.This remains a distinct end-to-end gap even though important lower-level fixes have landed: #7252 roots cross-module call arguments and #6738 backs
URLSearchParamssubclasses. The missing regression is the actual production Next request shape across the generated App Route/import boundary.Reproduction app (provided)
Use the exact pinned app and verifier attached to #8034. Do not create a new app. Its route is deliberately re-exported across a module boundary:
Build with:
bash make-next-app-route-fixture.sh cd perry-next-app-route-fixture npm install --package-lock-only npm ci npm run buildThe focused request is:
The returned JSON must contain:
{ "method": "GET", "pathname": "/api/benchmark", "id": "request-7", "iterations": 7, "beforeAwait": "request-7", "afterAwait": "request-7", "requestBody": "" }The attached verifier also sends a POST and requires
requestBody === "perry-request-body".Required implementation behavior
NextRequestobject passed by the generated App Route module into the re-exported user handler.nextUrl,ReadonlyURLSearchParams, headers, and body state across the imported call.NextRequestto a partial plain object.Regression coverage
Add a small compiler fixture for a request-shaped class passed through a re-exported imported function, plus the production integration test from #8034. Run the small fixture with forced evacuation / GC verification so a stale-but-lucky pointer cannot pass.
Acceptance criteria
verify.mjspass through the productionrouteModule.handlepath.GET, hard-coded query value, response fabrication, or other compatibility fallback exists in the Perry test path.Baseline / references
0.5.1503at564c56308d221a51b50308d9165578fbb176e877