Skip to content

Make instant() resilient to a leaked navigation-testing cookie#95375

Open
unstubbable wants to merge 1 commit into
canaryfrom
hl/fix-nested-instant-scope-error
Open

Make instant() resilient to a leaked navigation-testing cookie#95375
unstubbable wants to merge 1 commit into
canaryfrom
hl/fix-nested-instant-scope-error

Conversation

@unstubbable

@unstubbable unstubbable commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

The Instant Navigation Testing helper threw An instant() scope is already active whenever it found the next-instant-navigation-testing cookie set at acquire time. Because Playwright reuses one browser context across every test in a file, a cookie left behind by an earlier scope poisoned the shared jar and made every following instant() call fail fast, cascading through the suite.

The cookie can outlive its scope: under the lock, each MPA page load asynchronously re-writes it via cookieStore, and that write can land right after the scope's release deletes it but before the client observes the deletion, resurrecting a captured-state entry that the change handler then ignores.

Nesting is now tracked in-process, keyed on the browser context, rather than inferred from cookie presence. The context is the right granularity because the instant cookie is context-scoped: concurrent scopes on the same context share one cookie and conflict, while scopes on separate contexts or browsers are independent and must both run. On acquire we clear any stale cookie instead of throwing, and the release re-reads and re-deletes until the cookie stays gone, defeating the resurrection race. New tests cover recovery from a leaked cookie and concurrent scopes across separate contexts.


Stack created with GitHub Stacks CLIGive Feedback 💬

The Instant Navigation Testing helper threw "An instant() scope is
already active" whenever it found the next-instant-navigation-testing
cookie set at acquire time. Because Playwright reuses one browser
context across every test in a file, a cookie left behind by an earlier
scope poisoned the shared jar and made every following instant() call
fail fast, cascading through the suite.

The cookie can outlive its scope: under the lock, each MPA page load
asynchronously re-writes it via cookieStore, and that write can land
right after the scope's release deletes it but before the client
observes the deletion, resurrecting a captured-state entry that the
change handler then ignores.

Nesting is now tracked in-process, keyed on the browser context, rather
than inferred from cookie presence. The context is the right granularity
because the instant cookie is context-scoped: concurrent scopes on the
same context share one cookie and conflict, while scopes on separate
contexts or browsers are independent and must both run. On acquire we
clear any stale cookie instead of throwing, and the release re-reads and
re-deletes until the cookie stays gone, defeating the resurrection race.
New tests cover recovery from a leaked cookie and concurrent scopes
across separate contexts.
@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Stats from current PR

🟢 1 improvement

Metric Canary PR Change Trend
Turbo Build Time (cached) 5.663s 5.364s 🟢 299ms (-5%) ▂▂▁▃▁
📊 All Metrics
📖 Metrics Glossary

Dev Server Metrics:

  • Listen = TCP port starts accepting connections
  • First Request = HTTP server returns successful response
  • Cold = Fresh build (no cache)
  • Warm = With cached build artifacts

Build Metrics:

  • Fresh = Clean build (no .next directory)
  • Cached = With existing .next directory

Change Thresholds:

  • Time: Changes < 50ms AND < 10%, OR < 2% are insignificant
  • Size: Changes < 1KB AND < 1% are insignificant
  • All other changes are flagged to catch regressions

⚡ Dev Server

Metric Canary PR Change Trend
Cold (Listen) 812ms 813ms ▃▃▂▃▂
Cold (Ready in log) 778ms 798ms ▂▂▁▂▂
Cold (First Request) 1.313s 1.362s ▃▃▂▃▂
Warm (Listen) 813ms 813ms ▃▃▂▃▃
Warm (Ready in log) 785ms 777ms ▂▂▁▂▂
Warm (First Request) 599ms 588ms ▁▁▁▂▁
📦 Dev Server (Webpack) (Legacy)

📦 Dev Server (Webpack)

Metric Canary PR Change Trend
Cold (Listen) 763ms 811ms ▇█▆▆▇
Cold (Ready in log) 766ms 771ms ▇█▇▇█
Cold (First Request) 3.367s 3.354s ███▇█
Warm (Listen) 812ms 811ms ██▇▆█
Warm (Ready in log) 769ms 771ms ▇█▇▇█
Warm (First Request) 3.393s 3.409s █▇▇▇█

⚡ Production Builds

Metric Canary PR Change Trend
Fresh Build 5.382s 5.231s ▂▂▁▃▁
Cached Build 5.663s 5.364s 🟢 299ms (-5%) ▂▂▁▃▁
📦 Production Builds (Webpack) (Legacy)

📦 Production Builds (Webpack)

Metric Canary PR Change Trend
Fresh Build 24.647s 24.607s █▇███
Cached Build 24.850s 24.804s █████
node_modules Size 514 MB 514 MB ▄▄▄▄▄
📦 Bundle Sizes

Bundle Sizes

⚡ Turbopack

Client

Main Bundles
Canary PR Change
0-ub5lopl8ixs.js gzip 161 B N/A -
03gmyxr7dukvs.js gzip 10.3 kB N/A -
040t1q17lo593.js gzip 8.77 kB N/A -
0bb0vtp8dwsez.js gzip 450 B N/A -
0cz1d0mv5g_q7.js gzip 39.4 kB 39.4 kB
0gtn-prl2sl2k.js gzip 168 B N/A -
0nxqz3q165m2l.js gzip 220 B N/A -
0qr-1tnb7_hg5.js gzip 5.72 kB N/A -
0uilzvklme4ea.js gzip 8.76 kB N/A -
0yynmvs0ojur8.js gzip 156 B N/A -
0z0y83mfx-l-h.js gzip 10 kB N/A -
0zlhr5nlmygkf.js gzip 71 kB N/A -
15ok8ydf274z0.js gzip 10.6 kB N/A -
16cqqcigykfea.js gzip 13.6 kB N/A -
17h18zxt1915l.js gzip 1.46 kB N/A -
191caw8zzv6x1.js gzip 157 B N/A -
1cbwph_wkdd0e.js gzip 155 B N/A -
1elt1qium-r2m.css gzip 115 B 115 B
1en9l2o01i7h6.js gzip 7.65 kB N/A -
1fq1h7dxad4cv.js gzip 9.44 kB N/A -
1fym-adbk_69_.js gzip 13.1 kB N/A -
1gav7nfh4y8ln.js gzip 8.76 kB N/A -
1in1_vhc_2fqt.js gzip 155 B N/A -
1ligodam0at4l.js gzip 156 B N/A -
1lkqge6cmc1fu.js gzip 155 B N/A -
1oedzj0eoi2cy.js gzip 152 B N/A -
1zhkj-cxywprd.js gzip 65.5 kB N/A -
1zxeepg375efo.js gzip 14.3 kB N/A -
211bcgtt5_u2e.js gzip 156 B N/A -
2qw1wbno0e942.js gzip 156 B N/A -
2rypqffktcxqh.js gzip 8.69 kB N/A -
2uqsizxtehgqf.js gzip 8.79 kB N/A -
2vzktdqwbijqc.js gzip 8.74 kB N/A -
383--ncvhf-af.js gzip 157 B N/A -
38yh8zfm2a7p_.js gzip 159 B N/A -
3c244akvx_-be.js gzip 8.74 kB N/A -
3dmlemitx3ef3.js gzip 2.29 kB N/A -
3umfpv6uzk6cg.js gzip 13.2 kB N/A -
3xaxx2id8j9or.js gzip 53.5 kB N/A -
4237vdj6eyslt.js gzip 8.7 kB N/A -
turbopack-0e..xx_-.js gzip 3.74 kB N/A -
turbopack-0k..q-ho.js gzip 3.74 kB N/A -
turbopack-0k.._aln.js gzip 3.72 kB N/A -
turbopack-12..i6c9.js gzip 3.74 kB N/A -
turbopack-1a..hygh.js gzip 3.74 kB N/A -
turbopack-1b..zy9p.js gzip 3.74 kB N/A -
turbopack-1r..7bag.js gzip 3.74 kB N/A -
turbopack-2v..r4ru.js gzip 3.74 kB N/A -
turbopack-2y..946z.js gzip 3.74 kB N/A -
turbopack-37..yw5d.js gzip 3.74 kB N/A -
turbopack-3c..0lp2.js gzip 3.74 kB N/A -
turbopack-3u.._h4i.js gzip 3.74 kB N/A -
turbopack-3y..ve51.js gzip 3.74 kB N/A -
turbopack-41..j1f_.js gzip 3.75 kB N/A -
00tc16j5-eos9.js gzip N/A 1.46 kB -
0bshwjqm5ousd.js gzip N/A 156 B -
0gaw1gmpwuwkn.js gzip N/A 8.8 kB -
0m9mj4zd62tfi.js gzip N/A 159 B -
0nkkmu465ni6t.js gzip N/A 71 kB -
0qkxrh960j3ss.js gzip N/A 155 B -
0wcjlcc3wem94.js gzip N/A 155 B -
12zyjjmq4oad1.js gzip N/A 5.72 kB -
165b3vw4t79jv.js gzip N/A 156 B -
1go-x_hl1ac3o.js gzip N/A 7.65 kB -
1k9cc4-gpa2cx.js gzip N/A 13.1 kB -
1n59uogejo81s.js gzip N/A 10.3 kB -
1npei3hlexdv3.js gzip N/A 9.99 kB -
1ssuiwj_rnpc5.js gzip N/A 8.77 kB -
2-phc9obd3nyd.js gzip N/A 8.77 kB -
21a4k2w01yb2n.js gzip N/A 155 B -
21xp4i0y5kmfh.js gzip N/A 155 B -
23gji-p3v7u-m.js gzip N/A 14.3 kB -
24utq57r3l1cw.js gzip N/A 8.7 kB -
2f_7ecamj08vk.js gzip N/A 156 B -
2fhjq6ek3srmr.js gzip N/A 8.69 kB -
2ftm10fgi9egn.js gzip N/A 151 B -
2g0t7upz_v-hf.js gzip N/A 10.6 kB -
2ia9qqy99aie9.js gzip N/A 13.6 kB -
2k-surm3vm2dk.js gzip N/A 65.5 kB -
2oza28kdqvoay.js gzip N/A 8.74 kB -
2v5cv-ktrogvl.js gzip N/A 167 B -
2ximoiza7e8to.js gzip N/A 53.5 kB -
2zh8-mmhujy8o.js gzip N/A 2.29 kB -
3-ve5wqlwn7f-.js gzip N/A 154 B -
30h_m0irj-q6p.js gzip N/A 221 B -
37ejbfx1u9lpo.js gzip N/A 8.75 kB -
38c63ct4i1cy7.js gzip N/A 449 B -
3hd1us4ordyc9.js gzip N/A 13.2 kB -
3jimpal3lvz5e.js gzip N/A 9.44 kB -
3wb4pe4z4-aim.js gzip N/A 8.77 kB -
40ma1oy0-fe4_.js gzip N/A 160 B -
43go6fy-5y_jp.js gzip N/A 155 B -
turbopack-0b..npmq.js gzip N/A 3.74 kB -
turbopack-0i..16eb.js gzip N/A 3.74 kB -
turbopack-0r..uvpq.js gzip N/A 3.74 kB -
turbopack-0s..5xx5.js gzip N/A 3.74 kB -
turbopack-11..vft6.js gzip N/A 3.74 kB -
turbopack-14..95r6.js gzip N/A 3.74 kB -
turbopack-1o..osnd.js gzip N/A 3.75 kB -
turbopack-21..a1mx.js gzip N/A 3.74 kB -
turbopack-21..s0y5.js gzip N/A 3.74 kB -
turbopack-23..0vil.js gzip N/A 3.74 kB -
turbopack-26..gsz_.js gzip N/A 3.74 kB -
turbopack-29..t-fc.js gzip N/A 3.74 kB -
turbopack-30..jj7i.js gzip N/A 3.74 kB -
turbopack-3t..9b3q.js gzip N/A 3.72 kB -
Total 466 kB 466 kB ⚠️ +8 B

Server

Middleware
Canary PR Change
middleware-b..fest.js gzip 733 B 725 B 🟢 8 B (-1%)
Total 733 B 725 B ✅ -8 B
Build Details
Build Manifests
Canary PR Change
_buildManifest.js gzip 431 B 433 B
Total 431 B 433 B ⚠️ +2 B

📦 Webpack

Client

Main Bundles
Canary PR Change
2486.HASH.js gzip 169 B N/A -
3146-HASH.js gzip 63.6 kB N/A -
39fcf99b-HASH.js gzip 62.9 kB N/A -
8443-HASH.js gzip 4.68 kB N/A -
9431-HASH.js gzip 5.62 kB N/A -
framework-HASH.js gzip 59.8 kB 59.8 kB
main-app-HASH.js gzip 256 B 255 B
main-HASH.js gzip 39.6 kB 40.1 kB 🔴 +455 B (+1%)
webpack-HASH.js gzip 1.68 kB 1.68 kB
6105-HASH.js gzip N/A 5.63 kB -
764.HASH.js gzip N/A 169 B -
8898-HASH.js gzip N/A 63.1 kB -
9597-HASH.js gzip N/A 4.65 kB -
e1ccab69-HASH.js gzip N/A 62.9 kB -
Total 238 kB 238 kB ✅ -72 B
Polyfills
Canary PR Change
polyfills-HASH.js gzip 39.4 kB 39.4 kB
Total 39.4 kB 39.4 kB
Pages
Canary PR Change
_app-HASH.js gzip 194 B 194 B
_error-HASH.js gzip 183 B 182 B
css-HASH.js gzip 335 B 335 B
dynamic-HASH.js gzip 1.8 kB 1.8 kB
edge-ssr-HASH.js gzip 255 B 254 B
head-HASH.js gzip 351 B 349 B
hooks-HASH.js gzip 384 B 384 B
image-HASH.js gzip 580 B 581 B
index-HASH.js gzip 259 B 259 B
link-HASH.js gzip 2.49 kB 2.49 kB
routerDirect..HASH.js gzip 319 B 319 B
script-HASH.js gzip 386 B 386 B
withRouter-HASH.js gzip 315 B 313 B
1afbb74e6ecf..834.css gzip 106 B 106 B
Total 7.96 kB 7.95 kB ✅ -6 B

Server

Edge SSR
Canary PR Change
edge-ssr.js gzip 127 kB 127 kB
page.js gzip 284 kB 285 kB
Total 411 kB 411 kB ⚠️ +821 B
Middleware
Canary PR Change
middleware-b..fest.js gzip 616 B 615 B
middleware-r..fest.js gzip 156 B 155 B
middleware.js gzip 45.2 kB 44.9 kB
edge-runtime..pack.js gzip 842 B 842 B
Total 46.8 kB 46.5 kB ✅ -319 B
Build Details
Build Manifests
Canary PR Change
_buildManifest.js gzip 719 B 719 B
Total 719 B 719 B
Build Cache
Canary PR Change
0.pack gzip 4.74 MB 4.73 MB 🟢 9.6 kB (0%)
index.pack gzip 117 kB 117 kB
index.pack.old gzip 118 kB 117 kB
Total 4.98 MB 4.96 MB ✅ -11.2 kB

🔄 Shared (bundler-independent)

Runtimes
Canary PR Change
app-page-exp...dev.js gzip 364 kB 364 kB
app-page-exp..prod.js gzip 200 kB 200 kB
app-page-tur...dev.js gzip 363 kB 363 kB
app-page-tur..prod.js gzip 200 kB 200 kB
app-page-tur...dev.js gzip 360 kB 360 kB
app-page-tur..prod.js gzip 198 kB 198 kB
app-page.run...dev.js gzip 360 kB 360 kB
app-page.run..prod.js gzip 198 kB 198 kB
app-route-ex...dev.js gzip 79 kB 79 kB
app-route-ex..prod.js gzip 53.6 kB 53.6 kB
app-route-tu...dev.js gzip 79.1 kB 79.1 kB
app-route-tu..prod.js gzip 53.6 kB 53.6 kB
app-route-tu...dev.js gzip 78.7 kB 78.7 kB
app-route-tu..prod.js gzip 53.3 kB 53.3 kB
app-route.ru...dev.js gzip 78.6 kB 78.6 kB
app-route.ru..prod.js gzip 53.3 kB 53.3 kB
dist_client_...dev.js gzip 324 B 324 B
dist_client_...dev.js gzip 326 B 326 B
dist_client_...dev.js gzip 318 B 318 B
dist_client_...dev.js gzip 317 B 317 B
pages-api-tu...dev.js gzip 45.2 kB 45.2 kB
pages-api-tu..prod.js gzip 33.9 kB 33.9 kB
pages-api.ru...dev.js gzip 45.1 kB 45.1 kB
pages-api.ru..prod.js gzip 33.9 kB 33.9 kB
pages-turbo....dev.js gzip 54.6 kB 54.6 kB
pages-turbo...prod.js gzip 39.5 kB 39.5 kB
pages.runtim...dev.js gzip 54.6 kB 54.6 kB
pages.runtim..prod.js gzip 39.5 kB 39.5 kB
server.runti..prod.js gzip 64.9 kB 64.9 kB
use-cache-pr...dev.js gzip 71.3 kB 71.3 kB
use-cache-pr...dev.js gzip 71.3 kB 71.3 kB
use-cache-pr...dev.js gzip 69.6 kB 69.6 kB
use-cache-pr...dev.js gzip 69.6 kB 69.6 kB
Total 3.47 MB 3.47 MB
📎 Tarball URL
https://vercel-packages.vercel.app/next/commits/f124099305bc3e82e9a480dc1b591ae47d52421b/next

Commit: f124099

@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Tests Passed

Commit: f124099

@unstubbable unstubbable marked this pull request as ready for review July 1, 2026 21:05
@unstubbable unstubbable requested a review from acdlite July 1, 2026 21:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

1 participant