next.js
4b3e4e8a - turbopack: move CSS module composes validation from code generation to resolving (#92582)

Commit
9 days ago
turbopack: move CSS module composes validation from code generation to resolving (#92582) ### What? Move the validation that can produce `CssModuleComposesIssue` from code generation (`chunk_item_content`) to the reference's own `resolve_reference()` method, so these errors are surfaced during resolving rather than only during bundling. Two validation checks are moved into `CssModuleComposeReference::resolve_reference()`: 1. A `composes: ... from "...";` target module can't be resolved (unresolvable reference) 2. A `composes: ... from "...";` target module is not a CSS module (e.g. composing from a `.js` or `.txt` file) The `IssueStage` is updated from `CodeGen` to `Resolve` to reflect the new phase. Code generation still handles the error cases gracefully (skipping broken references with `continue`) — it just no longer re-emits the issue since it is already emitted by `resolve_reference()`. ### Why? `get_compilation_issues` (used by the MCP server and other tooling) only builds the module graph — it does not run code generation. Previously, both `CssModuleComposesIssue` variants were only emitted during `chunk_item_content()`, which meant they were invisible to `get_compilation_issues`. Developers using the MCP `get_compilation_issues` tool would not see errors from broken `composes` references until an actual build/bundle was triggered. Since `resolve_reference()` is called as part of module graph traversal, emitting the issue there means it is captured by `get_compilation_issues` alongside other resolve-phase errors. ### How? **`turbopack-css/src/references/compose.rs`** - `CssModuleComposeReference::resolve_reference()` is changed from `fn` to `async fn`. It calls `css_resolve` as before, then awaits `first_module()` on the result and validates: - Resolved to nothing → emit "can't be resolved" issue - Resolved to a module that doesn't implement `CssModuleComposable` → emit "not a CSS module" issue - `CssModuleComposesIssue` and its `Issue` impl are moved here from `module_asset.rs`, now using `ResolvedVc<FileSystemPath>` (from `origin_path()`) as the issue location rather than the `IssueSource` of the composing file. - A new `CssModuleComposable` marker trait (`#[turbo_tasks::value_trait]`) is defined here. `resolve_reference()` uses a `try_sidecast` to this trait to check whether the resolved module is a valid compose target — avoiding a hard dependency on `EcmascriptCssModule` from within `compose.rs`. **`turbopack-css/src/module_asset.rs`** - `EcmascriptCssModule` implements `CssModuleComposable`, marking it as a valid `composes:` target. - `module_references()` is reverted to its original simple form — it only collects references without any validation. - All issue-related imports (`Issue`, `IssueExt`, `IssueSource`, etc.) are removed. **Test fixtures** (`test/development/mcp-server/fixtures/compilation-errors-app/app/css-composes-error/`) - `styles.module.css` — CSS module with `composes: something from './not-a-css-module.txt'` - `not-a-css-module.txt` — a plain text file (resolves but is not a CSS module) - `page.tsx` — page importing the broken CSS module **`test/development/mcp-server/mcp-server-get-compilation-issues.test.ts`** - New test case `should detect CSS module composes errors` verifies the issue is surfaced via `get_compilation_issues`. <!-- NEXT_JS_LLM_PR --> --------- Co-authored-by: Tobias Koppers <sokra@users.noreply.github.com> Co-authored-by: Claude <noreply@anthropic.com>
Author
Parents
Loading