Skip to content

[Next.js/dylib] Full production App Route compatibility tracker #8040

Description

@proggeramlug

Goal

Run a real production Next.js 16 App Route as an app-only Perry dylib, with runtime and stdlib supplied once by separate shared provider images, and pass the same black-box verifier as Node without compatibility fallbacks.

This is the correctness gate required before the Perry-vs-Node 1/10/100 deployment RSS, CPU, and startup comparison is meaningful. The current benchmark is promising but lower-bound-only because it calls userland directly and fabricates the final response.

Fixed reproduction — do not design another app

#8034 contains a complete copy/paste fixture generator pinned to Next.js 16.3.0 / React 19.2.4, plus a 21-request verifier. The app already exercises:

  • production next build --webpack output;
  • the generated routeModule.handle / AppRouteRouteModule.handle path;
  • a re-exported imported GET/POST handler;
  • method, pathname, query, headers, and POST body;
  • Next's AsyncLocalStorage-backed headers() before and after async continuations;
  • a request-time dynamic import;
  • a two-chunk streamed NextResponse;
  • status, custom response header, and Set-Cookie; and
  • 20 distinct concurrent request contexts.

Every child issue uses that app. Smaller compiler/runtime fixtures are welcome for localization, but they cannot replace #8034 as acceptance evidence.

Work items

Existing groundwork to retain

These reduce the work but do not replace the composed production test. If current main already fixes a child behavior, close that child with a #8034 regression proving it rather than with a synthetic-only test.

Suggested execution order

  1. Land [Next.js/dylib] Add a pinned production App Route parity fixture and CI gate #8034's Node oracle and a Perry test marked expected-fail, recording the exact current Perry SHA and first failing boundary.
  2. Fix [GC/dylib] Install array-growth forwarding for low-address macOS arena allocations #8035 independently so GC diagnostics and stale growth references cannot contaminate later debugging.
  3. Make the request enter and survive the real route boundary ([Next.js/dylib] Preserve NextRequest and nextUrl.searchParams across App Route imports #8036).
  4. Make cold production modules initialize exactly once ([Next.js/dylib] Make production webpack App Route lazy loading deadlock-free #8039).
  5. Make Next's request/work context survive concurrency and continuations ([Next.js/dylib] Preserve request/work AsyncLocalStorage through concurrent App Routes #8037).
  6. Carry and drain the real returned response ([Next.js/dylib] Preserve returned NextResponse headers, cookies, and stream across module boundaries #8038).
  7. Remove the expected-fail marker and every compatibility branch; run the full stability matrix below.

Items 2–6 may proceed in parallel when their focused fixtures isolate them, but #8034 is the shared final oracle.

Definition of done

  • Runtime and stdlib are separate provider files loaded once per process.
  • The target app dylib excludes embedded runtime/stdlib implementations and resolves the documented provider ABI.
  • Providers load first; the app loads with eager relocation so first-request binding latency is not hidden.
  • The production webpack build enters the actual generated App Route module and private handle pipeline.
  • [Next.js/dylib] Add a pinned production App Route parity fixture and CI gate #8034's verifier passes on Node and Perry with identical observable status, headers/cookie, and JSON.
  • Ten consecutive cold Perry process starts pass; each process passes two verifier runs.
  • A 100-iteration run of the 20-way concurrent request batch has zero context leaks, hangs, truncations, or wrong values.
  • Normal GC and forced/verified GC runs pass.
  • Startup/request stderr contains no skipped-forwarding, unsettled-await, unimplemented, or compatibility-fallback diagnostic.
  • A source/test audit finds no direct userland GET invocation, ignored Response, hard-coded output, lazy-module eager-init workaround, or legacy fallback in the Perry path.

Explicitly out of scope

Once this tracker is green, run the separate performance matrix for 1, 10, and 100 copies of the same real Next deployment, followed by 100 distinct builds, against one Node process per app and a defensible shared-Node topology.

Baseline

The lower-bound observation was recorded with Perry 0.5.1503 at 564c56308d221a51b50308d9165578fbb176e877. Reproduce #8034 on current main before implementing and record that SHA in the test output; do not assume the old baseline identifies the first current failure.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew capability or improvementparityCompatibility gap with Node.js, ECMAScript, or the supported ecosystem

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions