test: cover CSS source map generation across all exportType values#20886
Conversation
Adds two configCases test directories that compile a CSS module under each parser.exportType (link, text, style, css-style-sheet) with devtool: "source-map" and assert that the emitted .css.map (link) or .js.map (text/style/css-style-sheet) is a well-formed v3 source map containing the original source content. The companion -less directory runs the same matrix through less-loader so the source map produced by less-loader is verified to propagate end-to-end into the bundle's source map.
Folds the two source-map config cases into a single multi-config that exercises every parser.exportType (link, text, style, css-style-sheet) with and without less-loader (8 configurations total). Each config aliases STYLE_UNDER_TEST to either style.css or style.less so the shared index.js handles all combinations. Validation now matches what Chrome DevTools requires to actually load a map: the //# sourceMappingURL annotation in the bundle, the V3 schema (version, sources, mappings, sourcesContent length), every segment decoded through a base64-VLQ parser with bounds checking on source/name indices, and an additional pass through Node's built-in node:module SourceMap consumer to confirm at least one entry resolves. For the less-loader path the test asserts the original .less text (@brand-color and friends) is what lands in sourcesContent, not the post-less compiled CSS.
🦋 Changeset detectedLatest commit: 3dba70c The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
This PR is packaged and the instant preview is available (74e2235). Install it locally:
npm i -D webpack@https://pkg.pr.new/webpack@74e2235
yarn add -D webpack@https://pkg.pr.new/webpack@74e2235
pnpm add -D webpack@https://pkg.pr.new/webpack@74e2235 |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #20886 +/- ##
===========================================
- Coverage 90.40% 80.24% -10.17%
===========================================
Files 557 526 -31
Lines 55102 53786 -1316
Branches 14484 14226 -258
===========================================
- Hits 49816 43158 -6658
- Misses 5286 10628 +5342
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
…caping or encoding' Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
One or more co-authors of this pull request were not found. You must specify co-authors in commit message trailer via: Supported
Alternatively, if the co-author should not be included, remove the Please update your commit message(s) by doing |
There was a problem hiding this comment.
Pull request overview
Adds a new configCases matrix test to validate CSS source map generation for all CSS parser.exportType values, including propagation of loader-generated source maps (via less-loader) into emitted .map files.
Changes:
- Add a multi-compiler config that builds the same CSS module under
exportType:link,text,style, andcss-style-sheet(with and withoutless-loader). - Add a runtime test that reads the emitted
.mapfiles and validates v3 source map structure plus presence of original source content. - Add CSS/LESS fixture sources used to assert
sourcesContentcorrectness.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| test/configCases/css/source-map-export-types/webpack.config.js | Defines the multi-compiler matrix across exportType values and optional less-loader preprocessing. |
| test/configCases/css/source-map-export-types/test.config.js | Injects Node utilities into the web-targeted runtime sandbox for map file inspection. |
| test/configCases/css/source-map-export-types/index.js | Implements source map validation (structure, mappings decode, and source content marker assertions). |
| test/configCases/css/source-map-export-types/style.css | CSS fixture source for source-content assertions. |
| test/configCases/css/source-map-export-types/style.less | LESS fixture source for end-to-end loader source map propagation assertions. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
When the CSS parser exportType is text, style, or css-style-sheet, the CSS body is embedded as a JS string literal. The previous code attached the original CSS source map to the surrounding JS source map, but JSON.stringify collapses the CSS onto a single line and the existing line/column information no longer matches the emitted generated text — DevTools could not resolve mappings for CSS modules consumed via these export types. Append a /*# sourceMappingURL=data:application/json;charset=utf-8;base64,... */ comment to the CSS content, matching the behavior of css-loader and style-loader. The comment travels with the CSS into whatever consumer applies it (a <style> tag injected by the cssInjectStyle runtime, a CSSStyleSheet.replaceSync() call, or a caller of the text default export), so DevTools shows the original CSS / preprocessor source. Tests: extend test/configCases/css/source-map-export-types to read the inline data URI from the JS bundle, base64-decode it, validate the V3 schema, decode every VLQ segment with bounds checks against sources/names, run it through Node's built-in node:module SourceMap consumer, and assert the original .css/.less source name and content are present. Update test/configCases/css/export-type-source-map for the new shape.
Coverage for the text exportType + inline data URI source map is fully subsumed by test/configCases/css/source-map-export-types, which now runs all four exportType values both with and without less-loader.
`findEntry(0, 0)` returns `{}` for empty or structurally invalid
maps too, so the assertion was passing trivially without catching
anything the hand-written VLQ decoder and structural checks weren't
already catching. Removing the dependency also avoids coupling the
config case to the `node:module` `SourceMap` API.
For text/style/css-style-sheet exportTypes the CSS module is emitted as a JS string literal. After replacing SourceMapSource with RawSource for the inline data URI fix, the bundle's JS source map no longer included that wrapper module at all — DevTools showed only ./index.js, the runtime, and the bootstrap. Wrap the JS literal in OriginalSource keyed by module.identifier() so the wrapper appears as a source alongside other JS modules. Tests assert the CSS module identifier is in jsMap.sources for every non-link config.
Previously only the inner JS string literal was wrapped, so the
bundle's JS source map sourcesContent for the CSS module entry was
the bare JSON-stringified CSS, not the actual emitted JS. Now the
entire generated module body — `__webpack_require__.r(module.exports
= { "default": "…" })` for text, the `cssInjectStyle(<id>, "…")`
runtime call for style, and the `new CSSStyleSheet()` IIFE for
css-style-sheet — is the source under the CSS module identifier,
matching what css-loader produces.
Tests assert the wrapper text (webpack runtime calls, `module.exports`
for text, `new CSSStyleSheet()` / `replaceSync` for css-style-sheet)
shows up in sourcesContent and that it does not start with a quote
character (which would indicate the old bare-literal regression).
A CSS module's raw `module.identifier()` embeds the absolute filesystem path (e.g. `css/auto|/home/user/.../style.css|text`) when no loader is in front of it, so passing it directly to OriginalSource leaked absolute paths into the bundle's JS source map `sources` for plain `.css` builds. Regular JS sources go through `requestShortener` and end up as `webpack:///./module.js` — switch the CSS module emit to `module.readableIdentifier(requestShortener)` so its sources match (`webpack:///css ./style.css (exportType: text)`, `webpack:///css ./style.less (exportType: style)`, etc.). Add a regression assertion that strips the `webpack:///` scheme from each source and rejects anything starting with `/` or a Windows drive prefix.
`SourceMapDevToolPlugin` strips `sourcesContent` from the external maps when devtool is `nosources-*-source-map`, but the inline data URI map we embed in the CSS string for text/style/css-style-sheet exportTypes was generated by the CSS generator on its own and was still carrying the original CSS body. Read `compilation.options.devtool` and drop `sourcesContent` from the inline map when the devtool string includes `nosources`, matching the external behavior. Adds test/configCases/css/nosources-source-map-export-types covering all four exportTypes: asserts the .css.map (link), the JS .map, and the embedded data URI map all have null/empty sourcesContent and that no original CSS rule text leaks through any of them.
Types CoverageCoverage after merging claude/add-css-sourcemap-tests-5R8Ee into main will be
Coverage Report
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Adds two configCases test directories that compile a CSS module under
each parser.exportType (link, text, style, css-style-sheet) with
devtool: "source-map" and assert that the emitted .css.map (link) or
.js.map (text/style/css-style-sheet) is a well-formed v3 source map
containing the original source content. The companion -less directory
runs the same matrix through less-loader so the source map produced
by less-loader is verified to propagate end-to-end into the bundle's
source map.