[pull] canary from vercel:canary#1082
Merged
Merged
Conversation
The tests in `test/development/app-dir/instant-navs-devtools/instant-navs-devtools.test.ts` seem to be failing a lot. According to [datadog](https://app.datadoghq.com/ci/test/flaky?query=%40test.name%3Ainstant-nav-panel%2A&sort=-pipelines_failed&viewMode=flaky), the worst offender fails 40% of runs. <img width="762" height="458" alt="Screenshot 2026-05-28 at 14 58 46" src="https://github.com/user-attachments/assets/148b8122-e5d4-407c-89cf-12101297f189" /> I'm disabling them to avoid disrupting people's CI runs too much I'm taking a stab at unflaking them here #94171, but no luck so far
In both the use-sites of `prependIsPartialByte` we actually have all the stream chunks available as an array, so we can avoid making a whole TransformStream. This was especially unnecessary in the static prerender codepath, where we'd turn the chunks into a stream, transform the stream, and immediately `streamToBuffer` it right after.
This test has been flaking in weird ways, but i also noticed that it's a
bit broken
- we were running build twice, because `next.start()` does that. this
affected what was in the logs that we assert on
- The assertion on the route was incorrect (it checked for `[page]
/static/route` instead of `[route] /static/route`, which would never be
emitted)
- ...which was hiding the fact that actually the thing *was* getting
logged due to a bug unrelated to after()
The idea in the test was essentially to assert that no after()s run at
runtime if the page/route is statically prerendered (which implicitly
also asserts that `after` itself does not make it dynamic). But it
appears that returning a `new Response()` from a static handler is
unsupported (bug imho) because it logs `Failed to update prerender cache
for /static/route Error: LRUCache: calculateSize returned 0, but size
must be > 0. Items with size 0 would never be evicted, causing unbounded
cache growth.`. As a workaround, i just gave it a non-empty body
I don't know if this will fix the flakes we've been seeing in CI. Those,
bizarrely, fail here
```
Error: can not run export while server is running, use next.stop() first
at NextStartInstance.build (/__w/next.js/next.js/test/lib/next-modes/next-start.ts:255:13)
at Object.build (/__w/next.js/next.js/test/e2e/app-dir/next-after-app-static/build-time/build-time.test.ts:36:36)
```
https://github.com/vercel/next.js/blob/1bc1da711cd0699b620716b204b480485274ff05/test/e2e/app-dir/next-after-app-static/build-time/build-time.test.ts#L36
We do `skipStart` in `nextTestSetup`, and there's no other tests running, so i have no idea what "running server" that error is referring to
### What? Propagate edge runtime preferredRegion metadata into adapter outputs and add adapter-config coverage for an edge app route. ### Why? Adapters need access to preferred region metadata from edge outputs when generating provider-specific deployment output. ### How? Copy edge function regions into output.config.preferredRegion and assert the adapter build-complete output for a fixture route with preferredRegion set to cdg1. ### Verification - `pnpm --filter=next build` - `NEXT_TEST_PREFER_OFFLINE=1 pnpm test-start-webpack test/production/adapter-config/adapter-config.test.ts` <!-- NEXT_JS_LLM_PR -->
Previously we pinned all of these to their current versions at the time. That meant that some of these got pinned to really old versions. This updates all of the "first-party" `actions/*` dependencies. Prompted claude with: ``` For all of these uses of actions/*, make sure we're pulling in the latest stable version (check the gh cli). When upgrading across major versions, fetch the release notes from the GH releases using the gh CLI and make sure that there are no problems that the upgrade will cause. ``` Claude read all the release notes and seems to think these upgrades are safe. 
This consolidates the two Resume Data Caches into a single discriminated union and reverts three non-load-bearing changes from #88556. The result sets up a follow-up that fixes a bug where pages exporting `unstable_instant = false` cause their `'use cache'` reads to be incorrectly treated as dynamic. The cache wrapper short-circuits a `'use cache'` miss to a dynamic hole when prerendering a fallback shell that was seeded with a read-only RDC from an earlier phase. The reasoning is that the seed was filled by a phase-1 prerender of a more-specific sibling route, so a miss in phase-2 means the cache key depends on a fallback param. In PR #79743, we set up an XOR on the work unit store that directly encoded this distinction: a prerender carried either a mutable `PrerenderResumeDataCache` (a phase-1 prerender filling caches as it runs) or an immutable `RenderResumeDataCache` (a phase-2 fallback shell reading from a phase-1-seeded cache), never both. The bail-out didn't use that signal directly, though; it was gated on `workUnitStore.allowEmptyStaticShell`, which at the time happened to coincide with "we have a read-only seed" because the fallback-shell flow was the only thing setting it. #89077 later widened that flag to also cover `unstable_instant = false`, which has no seed, so the bail-out started firing for routes that should be allowed to fill their caches normally. #88556 broke the XOR by carrying both caches at the same time. In a follow-up, the flag check is replaced with a precise `workUnitStore.resumeDataCache?.mutable === false`, which only lands cleanly once the XOR is back. The three reverts: (1) at the start of the Cache Components branch of `prerenderToStream`, phase-2 no longer creates a fresh mutable RDC alongside the prefilled one — it just uses the seed; (2) the swap between the prospective and final prerender passes that replaced the prefilled RDC with a freeze of the (now-gone) mutable one is removed, so the final pass reads from the same seed as the prospective pass; (3) the line in the cache wrapper that mirrored prefilled-RDC hits into the mutable RDC (only useful to feed the swap) is removed. The actual fix from #88556 — selecting the seed RDC by matching known params, `buildRDCCacheByPage` in `export/index.ts` — is kept, and the `ppr-root-param-fallback` test suite that was added in that PR still passes. On top of the revert, the two RDC types now carry a `mutable: true | false` discriminator, the store fields collapse into one `resumeDataCache: ResumeDataCache | null`, and the specialized `getPrerenderResumeDataCache` / `getRenderResumeDataCache` helpers are replaced by a single `getResumeDataCache` returning the union. Call sites narrow via `resumeDataCache?.mutable` directly, and the typing-lie in the old `getRenderResumeDataCache` (coercing a mutable cache to read-only via spread) is gone. Restoring the XOR as two separate fields would have worked, but the discriminated union makes the invariant compiler-enforced and removes a typing-lie that the original design already carried — and the revert touches the same call sites anyway, so bundling the refactor in one pass was cleaner than splitting it.
This fixes a bug where pages exporting `unstable_instant = false` cause their `'use cache'` reads to be incorrectly treated as dynamic, so the build emits an empty static shell where it should contain the cached content. The root cause sits in the cache wrapper's Resume Data Cache (RDC) miss bail-out. When prerendering a fallback shell whose RDC is the prefilled, read-only seed from a phase-1 prerender of a more-specific sibling route, a `'use cache'` miss is short-circuited to a dynamic hole — under that contract a miss means the cache key depends on a fallback param. That bail was gated on `workUnitStore.allowEmptyStaticShell`, which originally coincided with "we have a read-only seed" because the fallback-shell flow was the only thing setting the flag. #89077 widened the flag to also cover `unstable_instant = false`, which has no seed, so the bail started firing for routes that should be allowed to fill their caches normally. To fix this, we're replacing the proxy condition with the structural check `workUnitStore.resumeDataCache?.mutable === false`, which precisely matches the case the bail is for: a prerender whose RDC is the immutable, prefilled seed. This avoids the false positive for when `unstable_instant = false` is set and we're doing a prospective prerender with an empty mutable RDC. The check is type-narrowed via the discriminated union introduced in #94194, which is why that PR landed first. With the cache wrapper no longer the consumer, `workUnitStore.allowEmptyStaticShell` is removed from the prerender store — the flag survives only as `renderOpts.allowEmptyStaticShell` and a local parameter feeding the "shell may be empty for any reason" check in `dynamic-rendering.ts`.
- [x] skip traced edges properly in all graph traversals
- [x] iter_nodes and enumerate_nodes include the traced modules
- [x] Don't propagate is_self_async inside of traced references as a perf optimization
- [x] fix performance
- [x] validate that NFT JSON files are identical
- [x] ~~validate/adjust bundle analyzer output~~ will be in followup
- [x] audit `fn chunking_type()` changes
Benchmark:
```
* ced85b3 - (2 weeks ago) refactor - Niklas Mischkulnig (HEAD -> mischnic/nft-module-graph, origin/mischnic/nft-module-graph)
TURBOPACK_PERSISTENT_CACHE=0 NEXT_TURBOPACK_TRACING= pnpm next build 334.96s user 44.57s system 788% cpu 48.152 total
TURBOPACK_PERSISTENT_CACHE=0 NEXT_TURBOPACK_TRACING= pnpm next build 343.39s user 42.61s system 809% cpu 47.659 total
* 5edf482 - (77 minutes ago) v16.3.0-canary.32 - next-js-bot[bot] (HEAD, tag: v16.3.0-canary.32)
TURBOPACK_PERSISTENT_CACHE=0 NEXT_TURBOPACK_TRACING= pnpm next build 333.42s user 43.57s system 712% cpu 52.877 total
TURBOPACK_PERSISTENT_CACHE=0 NEXT_TURBOPACK_TRACING= pnpm next build 332.95s user 43.15s system 791% cpu 47.515 total
TURBOPACK_PERSISTENT_CACHE=0 NEXT_TURBOPACK_TRACING= pnpm next build 337.59s user 41.28s system 771% cpu 49.117 total
TURBOPACK_PERSISTENT_CACHE=0 NEXT_TURBOPACK_TRACING= pnpm next build 335.25s user 45.53s system 718% cpu 52.975 total
```
<details>
<summary>Previous benchmarks</summary>
```
5221241 mischnic/nft-module-graph
pnpm next build 371.41s user 66.39s system 737% cpu 59.353 total
pnpm next build 380.13s user 59.62s system 751% cpu 58.548 total
pnpm next build 374.25s user 60.55s system 761% cpu 57.102 total
8e4cfc5 canary
pnpm next build 370.77s user 53.89s system 762% cpu 55.725 total
pnpm next build 383.16s user 55.61s system 744% cpu 58.921 total
pnpm next build 382.34s user 53.51s system 757% cpu 57.512 total
pnpm next build 381.15s user 54.50s system 751% cpu 57.943 total
```
```
b0d5411a79 mischnic/nft-module-graph
pnpm next build --experimental-build-mode=compil 368.75s user 62.05s system 749% cpu 57.445 total
pnpm next build --experimental-build-mode=compil 368.95s user 58.42s system 763% cpu 56.004 total
0e3ad27 mischnic/nft-module-graph
pnpm next build --experimental-build-mode=compil 369.48s user 60.62s system 748% cpu 57.494 total
pnpm next build --experimental-build-mode=compil 374.89s user 52.27s system 730% cpu 58.449 total
pnpm next build --experimental-build-mode=compil 375.02s user 52.89s system 747% cpu 57.274 total
f37073e mischnic/speed-next-dynamic-map
pnpm next build --experimental-build-mode=compil 389.58s user 55.98s system 704% cpu 1:03.21 total
e599b11 mischnic/fix-side-effect-edge-removal
pnpm next build --experimental-build-mode=compil 386.60s user 53.34s system 720% cpu 1:01.09 total
f68f70b canary
pnpm next build --experimental-build-mode=compil 387.46s user 53.72s system 738% cpu 59.716 total
pnpm next build --experimental-build-mode=compil 390.33s user 53.54s system 734% cpu 1:00.43 total
pnpm next build --experimental-build-mode=compil 385.33s user 56.55s system 722% cpu 1:01.18 total
pnpm next build --experimental-build-mode=compil 386.49s user 56.44s system 726% cpu 1:00.96 total
```
```
b1ed455 origin/mischnic/nft-module-graph
pnpm next build --experimental-build-mode=compile 467.28s user 75.24s system 791% cpu 1:08.56 total
pnpm next build --experimental-build-mode=compile 465.00s user 76.80s system 831% cpu 1:05.20 total
pnpm next build --experimental-build-mode=compile 473.86s user 70.73s system 790% cpu 1:08.90 total
3cb77c8 canary
pnpm next build --experimental-build-mode=compile 367.91s user 58.06s system 726% cpu 58.672 total
pnpm next build --experimental-build-mode=compile 362.97s user 57.68s system 746% cpu 56.379 total
pnpm next build --experimental-build-mode=compile 364.59s user 57.01s system 724% cpu 58.167 total
```
</details>
#94186) Promises are not included in the list of JavaScript's falsy values, therefore, they are always truthy. See https://developer.mozilla.org/en-US/docs/Glossary/Truthy. Additionally, promises are neither `null` or `undefined` so they are not nullish: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing. This PR updates Turbopack's analyzer to reflect this + adds unit tests for `is_truthy` and `is_nullish`.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
See Commits and Changes for more details.
Created by
pull[bot] (v2.0.0-alpha.4)
Can you help keep this open source service alive? 💖 Please sponsor : )