Share Ecmascript HMR chunk versioning, diffing, and merging between browser and node (#96325)
## Summary
`turbopack-nodejs` and `turbopack-browser` each carried their own copy
of the Ecmascript chunk versioning and HMR diffing stack.
`chunk_list/merged_update.rs` already documented the intent to share
this, noting the turbo-tasks value types "cannot be generic and
therefore remain per-runtime". A `value_trait` resolves that: the shared
machinery is written against `EcmascriptHmrChunkContent`, which each
runtime implements in a few lines to expose `entries()` and
`own_version()`.
The shared code now lives in `turbopack-ecmascript/src/hmr/`
(`version.rs`, `update.rs`, `content.rs`, `merger.rs`). Both runtimes'
`ecmascript/version.rs`, `ecmascript/update.rs`, and
`ecmascript/**/merged/` directories are deleted.
No struct fields were widened and no `ChunkingContext` methods changed.
### Behavior changes
- Browser chunk version IDs now hash `minify_type`, matching node. IDs
are opaque and recomputed in-memory on both ends of an HMR connection,
so this cannot desync a client.
- The shared diff uses node's lazy `entries()` materialization, so
chunks with only deletions no longer materialize any `Vc<Code>`. This
now applies to the browser path too.
- Node error text said "chunk path ... is not in client root", a
copy-paste artifact. Now says "output root".
- `#[turbo_tasks(trace_ignore)]` is applied consistently to the merged
chunk version; previously only the browser copy had it.
Browser chunk content keeps the default `VersionedContent::update`.
Overriding it bypasses the `ChunkListUpdate` envelope the client runtime
expects.
### Not included
Unifying the chunk-content structs. That requires widening to `Box<dyn
ChunkingContext>`, and both chunking contexts define `minify_type` twice
— an inherent method and a `ChunkingContext` method whose trait default
is `NoMinify` — so it needs separate verification. The trait added here
lets the two structs coexist at no cost.
The runtime, evaluate, and entry chunk types are also out of scope:
`get_browser_runtime_code` takes eight more parameters than
`get_node_runtime_code`, so those differ behaviorally rather than by
duplication.
<!-- NEXT_JS_LLM -->