Visitar URL original
feat(turbopack): support `false` values for `resolveAlias` config by sokra · Pull Request #93331 · vercel/next.js · GitHub
Skip to content

feat(turbopack): support false values for resolveAlias config - #93331

Merged
sokra merged 14 commits into
canaryfrom
sokra/resolve-alias-false
Sep 22, 2026
Merged

sokra merged 14 commits into
canaryfrom
sokra/resolve-alias-false

Conversation

@sokra

@sokra sokra commented Apr 28, 2026

Copy link
Copy Markdown
Member

What?

Adds support for false as a value in experimental.turbopack.resolveAlias, which resolves the aliased module to an empty stub — matching webpack's long-standing behavior.

// next.config.js
module.exports = {
  experimental: {
    turbopack: {
      resolveAlias: {
        'some-server-only-module': false,
      },
    },
  },
}

With this alias in place:

  • import * as ns from 'some-server-only-module' → ns is {}
  • import { foo } from 'some-server-only-module' → foo is undefined
  • import def from 'some-server-only-module' → def is undefined
  • await import('some-server-only-module') → resolves to {}
  • require('some-server-only-module') → returns {}

Why?

Webpack supports false as an alias target to stub out modules (e.g. to exclude Node-only packages from client/edge bundles). Turbopack did not, causing migration friction for projects that rely on this pattern.

How?

Threads the false sentinel through the full resolution pipeline as a new Empty variant:

false (config)
  → SubpathValue::Empty      (next-core import map)
  → ImportMapping::Empty     (turbopack-core remap)
  → ReplacedImportMapping::Empty
  → ResolveResultItem::Empty
  → ModuleResolveResultItem::Empty
  → ReferencedAsset::Empty   (ESM static imports)
  → SinglePatternMapping::Ignored  (CJS require / dynamic import)

For static ESM imports, ReferencedAsset::Empty is kept as a distinct variant so that binding.rs can distinguish a namespace import (yields {}) from a named/default import (yields undefined).

For CJS require() and dynamic import(), ModuleResolveResultItem::Empty maps to the existing SinglePatternMapping::Ignored, which already generates the correct {} / Promise.resolve({}) stubs — so no new code-generation path was needed there (the redundant Empty variant introduced during development was removed in a follow-up cleanup commit).

Files changed:

  • packages/next/src/server/config-shared.ts — add false to resolveAlias type
  • packages/next/src/server/config-schema.ts — add z.literal(false) to schema
  • crates/next-core/src/next_import_map.rs — map false → SubpathValue::Empty
  • turbopack/crates/turbopack-core/src/resolve/remap.rs — handle ImportMapping::Empty
  • turbopack/crates/turbopack-core/src/resolve/mod.rs — propagate ModuleResolveResultItem::Empty
  • turbopack/crates/turbopack-ecmascript/src/references/esm/base.rs — ReferencedAsset::Empty
  • turbopack/crates/turbopack-ecmascript/src/references/esm/binding.rs — empty-module binding code-gen
  • turbopack/crates/turbopack-ecmascript/src/references/esm/url.rs — handle Empty in URL refs
  • turbopack/crates/turbopack-ecmascript/src/references/async_module.rs — skip Empty in async module analysis
  • turbopack/crates/turbopack-ecmascript/src/references/pattern_mapping.rs — map Empty → Ignored

Tests: test/e2e/turbopack-resolve-alias-false/ covers all five import styles (namespace, named, default, dynamic, CJS).

@github-actions github-actions Bot added created-by: Turbopack team PRs by the Turbopack team. tests Turbopack Related to Turbopack with Next.js. type: next labels Apr 28, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Stats from current PR

✅ No significant changes detected

📊 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) 811ms 811ms ✓ █▁███
Cold (Ready in log) 773ms 774ms ✓ █▁██▇
Cold (First Request) 1.191s 1.187s ✓ ▇▁█▇▄
Warm (Listen) 811ms 811ms ✓ █▁███
Warm (Ready in log) 772ms 775ms ✓ █▁██▇
Warm (First Request) 566ms 573ms ✓ ▇▁█▇▃
📦 Dev Server (Webpack) (Legacy)

📦 Dev Server (Webpack)

Metric Canary PR Change Trend
Cold (Listen) 811ms 811ms ✓ ▃▃▁▆▃
Cold (Ready in log) 787ms 786ms ✓ █▄▇▅▅
Cold (First Request) 3.262s 3.246s ✓ █▇█▆█
Warm (Listen) 811ms 811ms ✓ ▃▆▆▆▁
Warm (Ready in log) 787ms 788ms ✓ █▃▆▄▆
Warm (First Request) 3.254s 3.263s ✓ ▄▅█▂▆

⚡ Production Builds

Metric Canary PR Change Trend
Fresh Build 4.914s 4.927s ✓ ▆▁█▇▆
Cached Build 4.915s 4.894s ✓ █▁█▇▇
📦 Production Builds (Webpack) (Legacy)

📦 Production Builds (Webpack)

Metric Canary PR Change Trend
Fresh Build 23.998s 24.076s ✓ █▁▂▄▄
Cached Build 24.028s 24.020s ✓ █▁▂▆▂
node_modules Size 495 MB 495 MB ✓ ████▃
📦 Bundle Sizes

Bundle Sizes

⚡ Turbopack

Client

Main Bundles
Canary PR Change
0_09canb0ezn8.js gzip 153 B N/A -
02k5onwb4z3s6.js gzip 167 B N/A -
03t9nzq88k1pe.js gzip 155 B N/A -
04tqxk-qcsi2f.js gzip 156 B N/A -
0cz1d0mv5g_q7.js gzip 39.4 kB 39.4 kB ✓
0fli3_wppnim5.js gzip 12.9 kB N/A -
0kb7_ep3r1z0_.js gzip 10.1 kB N/A -
0kw8xgqdrilf6.js gzip 8.56 kB N/A -
0nnx767ck3zz4.js gzip 157 B N/A -
0ojkk2e654xsc.js gzip 8.59 kB N/A -
0wxpyd8r-vipl.js gzip 1.47 kB N/A -
0xrh8l7b4d3s2.js gzip 156 B N/A -
0xy2fhla48_rd.js gzip 9.24 kB N/A -
10wqsvi2mgfmi.js gzip 9.82 kB N/A -
16lhqjoqbznyg.js gzip 220 B 220 B ✓
16vepdkipri3r.js gzip 8.51 kB N/A -
17n96uu6y1pxq.js gzip 8.6 kB N/A -
18y4_8-9or0mn.js gzip 8.51 kB N/A -
1elt1qium-r2m.css gzip 115 B 115 B ✓
1gq145j3kps-h.js gzip 8.62 kB N/A -
1k3mvlb4-0ngf.js gzip 155 B N/A -
1ke_4s9soy654.js gzip 156 B N/A -
1nsh-mbn0e-se.js gzip 8.56 kB N/A -
1qngoc418rk6i.js gzip 65.6 kB N/A -
1r3s1n8vyb7h6.js gzip 161 B N/A -
1tsrrp1tdngti.js gzip 13.3 kB N/A -
1v-qecyz63-0b.js gzip 154 B N/A -
2__-e_ym8n788.js gzip 450 B N/A -
22o6xd9_ywdu6.js gzip 233 B N/A -
25n272-g99oa1.js gzip 7.61 kB N/A -
2c9mvd-i9rxxl.js gzip 160 B N/A -
2d4njk_907vw4.js gzip 157 B N/A -
2faj3acmavn9n.js gzip 13.1 kB N/A -
2kvj8yrfznmwx.js gzip 5.69 kB N/A -
2qv7m7xjnokgr.js gzip 8.58 kB N/A -
2ue5g3yr_f1ds.js gzip 70.9 kB N/A -
342ijzvrpe53h.js gzip 2.29 kB N/A -
3afk9e9-iuwwd.js gzip 157 B N/A -
3k1k5gtofm6eq.js gzip 10.4 kB N/A -
3xq6of2nocani.js gzip 49.5 kB N/A -
42_02jza_7yny.js gzip 13.8 kB N/A -
turbopack-04..w00-.js gzip 4.19 kB N/A -
turbopack-0g..9a3o.js gzip 4.19 kB N/A -
turbopack-0l..g-ev.js gzip 4.19 kB N/A -
turbopack-0m..2-2t.js gzip 4.18 kB N/A -
turbopack-0t..xwt-.js gzip 4.19 kB N/A -
turbopack-0u..t26z.js gzip 4.2 kB N/A -
turbopack-1k..1uu6.js gzip 4.19 kB N/A -
turbopack-1m..q5n1.js gzip 4.19 kB N/A -
turbopack-2j..87q5.js gzip 4.19 kB N/A -
turbopack-2q..y41_.js gzip 4.19 kB N/A -
turbopack-2y..xjoo.js gzip 4.19 kB N/A -
turbopack-3l..z3of.js gzip 4.17 kB N/A -
turbopack-3s..s0yf.js gzip 4.19 kB N/A -
turbopack-3u..-zq7.js gzip 4.19 kB N/A -
03kysncgx5l7w.js gzip N/A 155 B -
0arkbdqpxc37i.js gzip N/A 8.6 kB -
0bz-xifewa17d.js gzip N/A 8.63 kB -
0efh6erg1kc4c.js gzip N/A 158 B -
0tvekitj587fh.js gzip N/A 8.51 kB -
0yvk6-wi8e9wh.js gzip N/A 13.3 kB -
1-jqyfc89tixo.js gzip N/A 1.46 kB -
10y3h86mnhs_2.js gzip N/A 10.4 kB -
12hxdatac0fxj.js gzip N/A 49.5 kB -
139jydanoq6-d.js gzip N/A 154 B -
14t1kneseb8th.js gzip N/A 2.3 kB -
15sb1-dsqfk_j.js gzip N/A 8.59 kB -
1ab2xruymo-oj.js gzip N/A 449 B -
1b3xo3p2pa8_a.js gzip N/A 70.9 kB -
1dt49_v4y8lxb.js gzip N/A 13.8 kB -
1tu25qtsmfhar.js gzip N/A 9.82 kB -
1v3ftpmn8m_ud.js gzip N/A 161 B -
1vein_gnv3mwr.js gzip N/A 8.56 kB -
1vmibvuhp1gey.js gzip N/A 13.1 kB -
1wzrm0xjjbzn5.js gzip N/A 10.1 kB -
1z1geo4e53wn1.js gzip N/A 156 B -
1z3g0uaqtv9_3.js gzip N/A 8.56 kB -
2-2ld71a0y6d5.js gzip N/A 157 B -
213wdc0nef-no.js gzip N/A 168 B -
248gz0gduuney.js gzip N/A 157 B -
2bi5hx402juv-.js gzip N/A 8.58 kB -
2hy56297fog9u.js gzip N/A 8.52 kB -
2k0exemzm1ral.js gzip N/A 157 B -
2pch5duiz7pl1.js gzip N/A 155 B -
2u_rpxq3tzytl.js gzip N/A 233 B -
2zg0rr542d7qb.js gzip N/A 156 B -
314cbinszt68n.js gzip N/A 155 B -
35nh2lh_i5pyh.js gzip N/A 7.61 kB -
368lim5wq0o0r.js gzip N/A 12.9 kB -
3drqjohogojbw.js gzip N/A 5.69 kB -
3inn3g12k7ggr.js gzip N/A 153 B -
3lx6lyx6jwnsa.js gzip N/A 65.5 kB -
3wpp8nvyoj121.js gzip N/A 9.24 kB -
turbopack-02..h8bk.js gzip N/A 4.19 kB -
turbopack-03..d822.js gzip N/A 4.19 kB -
turbopack-04..-sj1.js gzip N/A 4.19 kB -
turbopack-0d..etty.js gzip N/A 4.19 kB -
turbopack-0e..h9db.js gzip N/A 4.19 kB -
turbopack-0h..um4t.js gzip N/A 4.18 kB -
turbopack-0m.._t4k.js gzip N/A 4.19 kB -
turbopack-0o..jeg1.js gzip N/A 4.19 kB -
turbopack-15..3bjj.js gzip N/A 4.2 kB -
turbopack-18..r3ht.js gzip N/A 4.19 kB -
turbopack-1b..dtt2.js gzip N/A 4.19 kB -
turbopack-3b..mz6c.js gzip N/A 4.19 kB -
turbopack-3n..av5a.js gzip N/A 4.17 kB -
turbopack-3y..9apy.js gzip N/A 4.19 kB -
Total 465 kB 465 kB ⚠️ +48 B

Server

Middleware
Canary PR Change
middleware-b..fest.js gzip 718 B 719 B ✓
Total 718 B 719 B ⚠️ +1 B
Build Details
Build Manifests
Canary PR Change
_buildManifest.js gzip 435 B 433 B ✓
Total 435 B 433 B ✅ -2 B

📦 Webpack

Client

Main Bundles
Canary PR Change
2637-HASH.js gzip 4.63 kB N/A -
7724.HASH.js gzip 169 B N/A -
8274-HASH.js gzip 61.4 kB N/A -
8817-HASH.js gzip 5.59 kB N/A -
c3500254-HASH.js gzip 62.8 kB N/A -
framework-HASH.js gzip 59.7 kB 59.7 kB ✓
main-app-HASH.js gzip 254 B 255 B ✓
main-HASH.js gzip 39.4 kB 39.4 kB ✓
webpack-HASH.js gzip 1.68 kB 1.68 kB ✓
5887-HASH.js gzip N/A 5.61 kB -
6522-HASH.js gzip N/A 60.7 kB -
6779-HASH.js gzip N/A 4.63 kB -
8854.HASH.js gzip N/A 169 B -
eab920f9-HASH.js gzip N/A 62.8 kB -
Total 236 kB 235 kB ✅ -652 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 193 B 193 B ✓
_error-HASH.js gzip 182 B 182 B ✓
css-HASH.js gzip 333 B 334 B ✓
dynamic-HASH.js gzip 1.81 kB 1.8 kB ✓
edge-ssr-HASH.js gzip 255 B 255 B ✓
head-HASH.js gzip 353 B 349 B 🟢 4 B (-1%)
hooks-HASH.js gzip 384 B 382 B ✓
image-HASH.js gzip 581 B 581 B ✓
index-HASH.js gzip 260 B 259 B ✓
link-HASH.js gzip 2.52 kB 2.52 kB ✓
routerDirect..HASH.js gzip 316 B 318 B ✓
script-HASH.js gzip 386 B 386 B ✓
withRouter-HASH.js gzip 313 B 314 B ✓
1afbb74e6ecf..834.css gzip 106 B 106 B ✓
Total 7.99 kB 7.98 kB ✅ -10 B

Server

Edge SSR
Canary PR Change
edge-ssr.js gzip 126 kB 126 kB ✓
page.js gzip 274 kB 274 kB ✓
Total 400 kB 399 kB ✅ -525 B
Middleware
Canary PR Change
middleware-b..fest.js gzip 616 B 614 B ✓
middleware-r..fest.js gzip 156 B 156 B ✓
middleware.js gzip 44 kB 44.4 kB ✓
edge-runtime..pack.js gzip 842 B 842 B ✓
Total 45.6 kB 46 kB ⚠️ +343 B
Build Details
Build Manifests
Canary PR Change
_buildManifest.js gzip 722 B 719 B ✓
Total 722 B 719 B ✅ -3 B
Build Cache
Canary PR Change
0.pack gzip 4.4 MB 4.4 MB 🟢 5.43 kB (0%)
index.pack gzip 112 kB 113 kB ✓
index.pack.old gzip 114 kB 115 kB ✓
Total 4.63 MB 4.62 MB ✅ -4.22 kB

🔄 Shared (bundler-independent)

Runtimes
Canary PR Change
app-page-exp...dev.js gzip 348 kB 348 kB ✓
app-page-exp..prod.js gzip 193 kB 193 kB ✓
app-page-tur...dev.js gzip 348 kB 348 kB ✓
app-page-tur..prod.js gzip 193 kB 193 kB ✓
app-page-tur...dev.js gzip 344 kB 344 kB ✓
app-page-tur..prod.js gzip 191 kB 191 kB ✓
app-page.run...dev.js gzip 345 kB 345 kB ✓
app-page.run..prod.js gzip 191 kB 191 kB ✓
app-route-ex...dev.js gzip 77.3 kB 77.3 kB ✓
app-route-ex..prod.js gzip 52.8 kB 52.8 kB ✓
app-route-tu...dev.js gzip 77.4 kB 77.4 kB ✓
app-route-tu..prod.js gzip 52.8 kB 52.8 kB ✓
app-route-tu...dev.js gzip 77 kB 77 kB ✓
app-route-tu..prod.js gzip 52.5 kB 52.5 kB ✓
app-route.ru...dev.js gzip 76.9 kB 76.9 kB ✓
app-route.ru..prod.js gzip 52.5 kB 52.5 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 44.2 kB 44.2 kB ✓
pages-api-tu..prod.js gzip 33.7 kB 33.7 kB ✓
pages-api.ru...dev.js gzip 44.2 kB 44.2 kB ✓
pages-api.ru..prod.js gzip 33.7 kB 33.7 kB ✓
pages-turbo....dev.js gzip 53.7 kB 53.7 kB ✓
pages-turbo...prod.js gzip 39.4 kB 39.4 kB ✓
pages.runtim...dev.js gzip 53.6 kB 53.6 kB ✓
pages.runtim..prod.js gzip 39.4 kB 39.4 kB ✓
server.runti..prod.js gzip 63.1 kB 63.1 kB ✓
Total 3.08 MB 3.08 MB ✓
📎 Tarball URL
https://vercel-packages.vercel.app/next/commits/82c59c71762c88f6f7cb917dd020991b90c820ee/next

Commit: 82c59c7

@github-actions

github-actions Bot commented Apr 28, 2026 •

Copy link
Copy Markdown
Contributor

Tests Passed

Commit: a2b27db

@sokra
sokra requested a review from mischnic April 29, 2026 09:08
@sokra
sokra marked this pull request as ready for review April 29, 2026 09:12
@sokra
sokra force-pushed the sokra/resolve-alias-false branch 2 times, most recently from ef35095 to 9058552 Compare April 30, 2026 09:03
@sokra
sokra force-pushed the sokra/resolve-alias-false branch 2 times, most recently from 775419f to e8664cc Compare May 11, 2026 15:08
Comment thread turbopack/crates/turbopack-core/src/resolve/remap.rs
jet-pang added a commit to wontlost-ltd/aster-cloud that referenced this pull request May 18, 2026
Two Vercel/next.js PRs gate our ability to drop --webpack from the
build script. Both are open as of this commit; tracking explicitly so
we don't lose context between status checks.

  PR #90300 — Turbopack: cross-module constants
              = DefinePlugin equivalent for IS_SAAS / CAN_BILLING
              constant folding (the core DCE we need).
              vercel/next.js#90300

  PR #93331 — feat(turbopack): support 'false' values for resolveAlias
              = belt-and-suspenders module stub-out
              (webpack's resolve.alias = { stripe: false, ... }).
              vercel/next.js#93331

Adds
  - docs/workstreams/turbopack-migration/README.md: full migration
    contract — why webpack stays, what to wait for, switch checklist,
    things explicitly not to do.
  - scripts/check-turbopack-readiness.sh: polls both PRs via gh CLI;
    exit 0 = ready to migrate, exit 1 = keep waiting.
  - package.json: `pnpm check:turbopack-readiness` alias.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
vercel-fleet-prod Bot and others added 13 commits September 21, 2026 13:09
Adds support for passing `false` as a value in `resolveAlias`, which
resolves the aliased import to an empty module (`{}` for CJS/namespace
imports, `undefined` for named bindings).

Chain: `false` → `SubpathValue::Empty` → `ImportMapping::Empty` →
`ReplacedImportMapping::Empty` → `ResolveResultItem::Empty` →
`ModuleResolveResultItem::Empty` → `SinglePatternMapping::Empty` /
`ReferencedAsset::Empty`.

Co-Authored-By: Claude <noreply@anthropic.com>

Co-authored-by: Tobias Koppers <sokra@users.noreply.github.com>
Co-authored-by: Tobias Koppers <1365881+sokra@users.noreply.github.com>
Tests ESM namespace/named/default imports, dynamic import(), and
CommonJS require() all resolve to an empty module when aliased to false.

Co-Authored-By: Claude <noreply@anthropic.com>

Co-authored-by: Tobias Koppers <sokra@users.noreply.github.com>
Co-authored-by: Tobias Koppers <1365881+sokra@users.noreply.github.com>
`SinglePatternMapping::Empty` had identical code generation to `Ignored`
in all three paths (create_id/create_require/create_import), so the
variant was redundant. Map `ModuleResolveResultItem::Empty` directly to
`Ignored` and remove the unreachable explicit arm in `as_module`.

Co-Authored-By: Claude <noreply@anthropic.com>

Co-authored-by: Tobias Koppers <sokra@users.noreply.github.com>
Co-authored-by: Tobias Koppers <1365881+sokra@users.noreply.github.com>
SubpathValue::add_results duplicated the tree-walk logic already
present in ReplacedSubpathValue::add_results. Replace the one call
site (export_value_to_import_mapping) with value.convert().add_results()
and make AliasKey, ReplacedSubpathValue, and ReplacedSubpathValueResult
part of turbopack-core's public resolve API so callers can use them.

Co-Authored-By: Claude <noreply@anthropic.com>

Co-authored-by: Tobias Koppers <sokra@users.noreply.github.com>
Co-authored-by: Tobias Koppers <1365881+sokra@users.noreply.github.com>
Introduce ReplacedSubpathValueResultType::{Path, Empty, Excluded} so
that add_results callers no longer need a boolean return value to detect
terminal cases. Excluded and Empty are now represented as explicit result
entries rather than implicit termination signals, which fixes silent
omission of Empty in the previous add_results logic.

Remove the bool return value from ReplacedSubpathValue::add_results;
callers detect whether a match was found by comparing the target length
before and after the call.

Co-Authored-By: Claude <noreply@anthropic.com>

Co-authored-by: Tobias Koppers <sokra@users.noreply.github.com>
Co-authored-by: Tobias Koppers <1365881+sokra@users.noreply.github.com>
Returns true when a definitive result covering all possible unknown
condition values was found (Excluded, Empty, or a concrete path), so
callers (Alternatives arms and the outer lookup loop) know to stop
trying further alternatives.

Co-Authored-By: Claude <noreply@anthropic.com>

Co-authored-by: Tobias Koppers <sokra@users.noreply.github.com>
Co-authored-by: Tobias Koppers <1365881+sokra@users.noreply.github.com>
…rminal

A Result path might not resolve successfully (the file may not exist),
so Alternatives should continue to the next entry rather than stopping.
Only Excluded and Empty are definitively terminal for all possible
unknown condition values.

Co-Authored-By: Claude <noreply@anthropic.com>

Co-authored-by: Tobias Koppers <sokra@users.noreply.github.com>
Co-authored-by: Tobias Koppers <1365881+sokra@users.noreply.github.com>
…for null

The Excluded arm already returns true to signal termination, so there is
no need to push a result item. Callers simply produce no output for that
case, which naturally leads to an unresolvable outcome.

Co-Authored-By: Claude <noreply@anthropic.com>

Co-authored-by: Tobias Koppers <sokra@users.noreply.github.com>
Co-authored-by: Tobias Koppers <1365881+sokra@users.noreply.github.com>
Alternatives: keep collecting on Result, stop only on Stop.
Conditional/Set: break on both Result and Stop.
Conditional/Unknown: continue regardless (explore all branches).
Excluded -> Stop; Result/Empty -> Result.

Co-Authored-By: Claude <noreply@anthropic.com>

Co-authored-by: Tobias Koppers <sokra@users.noreply.github.com>
Co-authored-by: Tobias Koppers <1365881+sokra@users.noreply.github.com>
An Alternatives node always represents a terminal match — even if all
inner values produce no concrete results (all Unset), the outer loop
should stop rather than fall through to the next alias entry.

Co-Authored-By: Claude <noreply@anthropic.com>

Co-authored-by: Tobias Koppers <sokra@users.noreply.github.com>
Co-authored-by: Tobias Koppers <1365881+sokra@users.noreply.github.com>
- Alternatives arm: drop the no-op state variable; check Stop inline
  and return Result unconditionally at the end.
- ResultsIterMut: merge the identical Excluded/Empty no-op arms.
- Extract push_result() helper shared by the Result and Empty leaf arms.
- Extract apply_conditions() async helper shared by both result types
  in handle_exports_imports_field.
- next_import_map: use Iterator::next() directly instead of
  Some(…next().unwrap()) in the single-mapping arm.

Co-Authored-By: Claude <noreply@anthropic.com>

Co-authored-by: Tobias Koppers <sokra@users.noreply.github.com>
Co-authored-by: Tobias Koppers <1365881+sokra@users.noreply.github.com>
…result

- Fix Unset doc: "No definitive result" (thread 2)
- Empty now returns TerminalState::Stop so no fallback alternatives are
  collected (it already resolves); it still pushes its result to target
  (thread 3)
- Inline push_result and collect_active_conditions helpers; the helpers
  became overkill once Empty no longer shared the same return value as
  Result (thread 4)

Co-Authored-By: Claude <noreply@anthropic.com>

Co-authored-by: Tobias Koppers <sokra@users.noreply.github.com>
Co-authored-by: Tobias Koppers <1365881+sokra@users.noreply.github.com>
The two leaf arms (Result and Empty) share identical condition-collecting
logic; extracting it into a named helper improves readability.

Co-Authored-By: Claude <noreply@anthropic.com>

Co-authored-by: Tobias Koppers <sokra@users.noreply.github.com>
Co-authored-by: Tobias Koppers <1365881+sokra@users.noreply.github.com>
@sokra
sokra force-pushed the sokra/resolve-alias-false branch from e8664cc to 660f21f Compare September 21, 2026 13:10
Co-authored-by: Tobias Koppers <1365881+sokra@users.noreply.github.com>
@sokra
sokra merged commit 95c5e39 into canary Sep 22, 2026
204 of 220 checks passed
@sokra
sokra deleted the sokra/resolve-alias-false branch September 22, 2026 08:10
@github-actions github-actions Bot added the locked label Oct 6, 2026
@github-actions github-actions Bot locked as resolved and limited conversation to collaborators Oct 6, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

created-by: Turbopack team PRs by the Turbopack team. locked tests Turbopack Related to Turbopack with Next.js. type: next

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants