Turbopack: use keyed cell access for AsyncModulesInfo (#91305)
### What?
Switch `AsyncModulesInfo` to use `cell = "keyed"` and per-key access
(`is_async()`) instead of reading the full `FxHashSet` via `.await?`.
### Why?
`AsyncModulesInfo` is a large set that gets read from many call sites.
With the default cell, any change to any module's async status
invalidates all readers. The `cell = "keyed"` annotation enables
turbo-tasks to track reads at the key level, so a change to one module's
async status only invalidates tasks that queried that specific module.
This reduces unnecessary recomputation during incremental rebuilds where
only a small subset of modules change their async status.
### How?
**Core change** (`async_module_info.rs`):
- Added `cell = "keyed"` to the `#[turbo_tasks::value]` annotation on
`AsyncModulesInfo`
- Added `is_async()` method that uses `contains_key()` for keyed reads
instead of full-set reads
**Call site migration** (5 files):
- All call sites changed from `.async_module_info().await?` (reads full
set) → `.async_module_info()` (returns `Vc`, defers reads)
- `attach_async_info_to_chunkable_module` and
`from_chunkable_module_or_batch` now take `Vc<AsyncModulesInfo>` instead
of `&ReadRef<AsyncModulesInfo>`
- Each call site uses `async_module_info.is_async(module).await?` for
per-key reads
**`referenced_async_modules`** (`mod.rs`):
- Collects neighbor candidates first, then filters via `is_async()` with
`try_flat_join` for concurrent keyed reads
- Simplified: uses in-place `.reverse()` instead of `.rev().collect()`
double allocation
**`compute_merged_modules`** (`merged_modules.rs`):
- Pre-fetches async status for all mergeable modules into a local
`FxHashSet` before the synchronous fixed-point traversal (which cannot
do async reads)
- Added tracing span `"pre-fetch async module status"` for observability
**Cleanup:**
- Consistent variable naming (`async_module_info`) across all call sites
- Doc comment on `attach_async_info_to_chunkable_module` explaining the
keyed access pattern
---------
Co-authored-by: Tobias Koppers <sokra@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>