next.js
0090db22 - turbo-tasks: add hashed cell mode for hash-based change detection without cell data (#91576)

Commit
40 days ago
turbo-tasks: add hashed cell mode for hash-based change detection without cell data (#91576) ## Summary ### Core: hash-based cell change detection - Adds `cell_data_hash: AutoMap<CellId, [u8; 16]>` to the storage schema (`category = "data"`) so the backend can persist a hash of transient cell data across evictions - Stored as `[u8; 16]` (little-endian bytes of a u128) rather than `u128` to keep the 1-byte alignment out of `AutoMap` and therefore out of the `LazyField` enum — a bare `u128` would grow the enum from 56 to 64 bytes due to its 16-byte alignment requirement - Adds `content_hash: Option<u128>` to `UpdateCellOperation::run` and threads it through the full call chain: `CurrentCellRef` → `TurboTasksCallApi::update_own_task_cell` → `Backend::update_task_cell` → operation - **New invalidation logic** in `UpdateCellOperation::run` for the `assume_unchanged = false` path: - Old content available → real equality compare (unchanged) - Old content evicted, hashes match → write new content but **skip dependent invalidation** - Old content evicted, hashes differ (or missing) → write + invalidate as before - `cell_data_hash` is updated whenever content is written (skipped if hash is unchanged; always updated for non-serializable cells regardless of `assume_unchanged`) - Adds `hashed_compare_and_update` / `hashed_compare_and_update_with_shared_reference` methods to `CurrentCellRef` (require `T: PartialEq + DeterministicHash`); hash is computed lazily (only after equality check fails when old value is available) - Adds `VcCellHashedCompareMode<T>` in `cell_mode.rs` which implements `VcCellMode<T>` for `T: VcValueType + PartialEq + DeterministicHash` ### Macro: `serialization = "hash"` and `hash = "manual"` - **`serialization = "hash"`** — behaves like `serialization = "none"` (no disk serialization, transient) but uses `VcCellHashedCompareMode` so the stored hash prevents spurious downstream invalidation when transient data is evicted and re-executed - Valid only with `cell = "compare"` (the default); combining with `cell = "new"` or `cell = "keyed"` is a compile error - Automatically derives `DeterministicHash` on the annotated type - **`hash = "manual"`** — opt-out of the auto-derive when a custom `DeterministicHash` impl is needed (analogous to `eq = "manual"`); using `hash = "manual"` without `serialization = "hash"` is a compile error ### turbo-tasks-fs: `PersistedFileContent` - Adds `PersistedFileContent` — a mirror of `FileContent` that is returned by `Vc<FileContent>::persist()`, storing the same data but obtained through the persistent cache path - `FileContent` is switched to `serialization = "hash"` so the macro auto-derives `DeterministicHash` - `DiskFileSystem::write()` now calls `.persist().await?` before emitting the write effect, using `PersistedFileContent` for the file comparison and write — this ensures full content is in the persistent cache on restore, avoiding spurious downstream invalidation - `WriteContent::File` in `invalidator_map.rs` is updated to hold `ReadRef<PersistedFileContent>` ### turbopack-core: `Code` with hash-based serialization - Adds `DeterministicHash` impls for `SmallVec<[T; N]>` and `()` in `turbo-tasks-hash` - Switches `Code` to `serialization = "hash"` so module factory code cells use hash-based change detection - Calls `.persist()` on module factory code cells in `turbopack-ecmascript` ### next-core: duplicate asset detection and parallel emit - `emit_assets` now emits node and client assets concurrently via `try_join!` - Detects duplicate assets (same output path, different content) and returns a hard error with a diff summary — previously the last writer silently won ## Macro syntax ```rust #[turbo_tasks::value(serialization = "hash")] struct MyTransientType { ... } // opt out of auto-derived DeterministicHash when you need a custom impl: #[turbo_tasks::value(serialization = "hash", hash = "manual")] struct MyTransientType { ... } ``` ## Test plan - [x] Integration tests in `turbopack/crates/turbo-tasks-backend/tests/hashed_cell_mode.rs`: - `test_hashed_cell_mode_change_triggers_invalidation` — value change triggers consumer re-execution - `test_hashed_cell_mode_equal_value_no_invalidation` — same hash prevents consumer re-execution - [x] `cargo test -p turbo-tasks-macros-tests` passes - [x] `cargo test -p turbo-tasks-backend --test hashed_cell_mode` passes - [x] `cargo check --workspace` passes --------- Co-authored-by: Tobias Koppers <sokra@users.noreply.github.com> Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Vercel <vercel[bot]@users.noreply.github.com>
Author
Parents
Loading