Skip to content

Commit e9ce745

Browse files
authoredMar 6, 2019
fix: source map generation when sourceRoot is present (#901)
1 parent a49e904 commit e9ce745

File tree

8 files changed

+362
-192
lines changed

8 files changed

+362
-192
lines changed
 

‎package-lock.json

+27-40
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎package.json

+1
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
"icss-utils": "^4.1.0",
4646
"loader-utils": "^1.2.3",
4747
"camelcase": "^5.2.0",
48+
"normalize-path": "^3.0.0",
4849
"postcss": "^7.0.14",
4950
"postcss-modules-extract-imports": "^2.0.0",
5051
"postcss-modules-local-by-default": "^2.0.6",

‎src/index.js

+25-32
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {
1717
getCurrentRequest,
1818
stringifyRequest,
1919
} from 'loader-utils';
20+
import normalizePath from 'normalize-path';
2021

2122
import schema from './options.json';
2223
import { importParser, icssParser, urlParser } from './plugins';
@@ -42,13 +43,24 @@ export default function loader(content, map, meta) {
4243
/* eslint-disable no-param-reassign */
4344
if (sourceMap) {
4445
if (map) {
46+
// Some loader emit source map as string
4547
if (typeof map === 'string') {
4648
map = JSON.stringify(map);
4749
}
4850

51+
// Source maps should use forward slash because it is URLs (https://github.com/mozilla/source-map/issues/91)
52+
// We should normalize path because previous loaders like `sass-loader` using backslash when generate source map
53+
54+
if (map.file) {
55+
map.file = normalizePath(map.file);
56+
}
57+
58+
if (map.sourceRoot) {
59+
map.sourceRoot = normalizePath(map.sourceRoot);
60+
}
61+
4962
if (map.sources) {
50-
map.sources = map.sources.map((source) => source.replace(/\\/g, '/'));
51-
map.sourceRoot = '';
63+
map.sources = map.sources.map((source) => normalizePath(source));
5264
}
5365
}
5466
} else {
@@ -120,17 +132,15 @@ export default function loader(content, map, meta) {
120132

121133
postcss(plugins)
122134
.process(content, {
123-
// we need a prefix to avoid path rewriting of PostCSS
124-
from: `/css-loader!${getRemainingRequest(this)
135+
from: getRemainingRequest(this)
125136
.split('!')
126-
.pop()}`,
137+
.pop(),
127138
to: getCurrentRequest(this)
128139
.split('!')
129140
.pop(),
130141
map: options.sourceMap
131142
? {
132143
prev: map,
133-
sourcesContent: true,
134144
inline: false,
135145
annotation: false,
136146
}
@@ -141,6 +151,14 @@ export default function loader(content, map, meta) {
141151
.warnings()
142152
.forEach((warning) => this.emitWarning(new Warning(warning)));
143153

154+
if (result.map) {
155+
const newMap = result.map.toJSON();
156+
157+
console.log(newMap.file);
158+
console.log(newMap.sourceRoot);
159+
console.log(newMap.sources);
160+
}
161+
144162
const messages = result.messages || [];
145163

146164
// Run other loader (`postcss-loader`, `sass-loader` and etc) for importing CSS
@@ -301,39 +319,14 @@ export default function loader(content, map, meta) {
301319
);
302320
});
303321

304-
let newMap = result.map;
305-
306-
if (sourceMap && newMap) {
307-
// Add a SourceMap
308-
newMap = newMap.toJSON();
309-
310-
if (newMap.sources) {
311-
newMap.sources = newMap.sources.map(
312-
(source) =>
313-
source
314-
.split('!')
315-
.pop()
316-
.replace(/\\/g, '/'),
317-
this
318-
);
319-
newMap.sourceRoot = '';
320-
}
321-
322-
newMap.file = newMap.file
323-
.split('!')
324-
.pop()
325-
.replace(/\\/g, '/');
326-
newMap = JSON.stringify(newMap);
327-
}
328-
329322
const runtimeCode = `exports = module.exports = require(${stringifyRequest(
330323
this,
331324
require.resolve('./runtime/api')
332325
)})(${!!sourceMap});\n`;
333326
const importCode =
334327
imports.length > 0 ? `// Imports\n${imports.join('\n')}\n\n` : '';
335328
const moduleCode = `// Module\nexports.push([module.id, ${cssAsString}, ""${
336-
newMap ? `,${newMap}` : ''
329+
result.map ? `,${result.map}` : ''
337330
}]);\n\n`;
338331
const exportsCode =
339332
exports.length > 0

‎test/__snapshots__/sourceMap-option.test.js.snap

+174-52
Original file line numberDiff line numberDiff line change
@@ -34,23 +34,6 @@ Array [
3434

3535
exports[`sourceMap option false should not generate source map when source map is \`undefined\` from other loader: warnings 1`] = `Array []`;
3636

37-
exports[`sourceMap option false should not generate source map when source map is valid and it is string from other loader: errors 1`] = `Array []`;
38-
39-
exports[`sourceMap option false should not generate source map when source map is valid and it is string from other loader: module (evaluated) 1`] = `
40-
Array [
41-
Array [
42-
1,
43-
".class {
44-
color: red;
45-
}
46-
",
47-
"",
48-
],
49-
]
50-
`;
51-
52-
exports[`sourceMap option false should not generate source map when source map is valid and it is string from other loader: warnings 1`] = `Array []`;
53-
5437
exports[`sourceMap option false should not generate source map: errors 1`] = `Array []`;
5538

5639
exports[`sourceMap option false should not generate source map: module (evaluated) 1`] = `
@@ -68,22 +51,22 @@ Array [
6851

6952
exports[`sourceMap option false should not generate source map: warnings 1`] = `Array []`;
7053

71-
exports[`sourceMap option false should not generate sourceMap when source map is valid from other loader: errors 1`] = `Array []`;
54+
exports[`sourceMap option should not generate sourceMap when source map is valid from other loader (\`sass-loader\`): errors 1`] = `Array []`;
7255

73-
exports[`sourceMap option false should not generate sourceMap when source map is valid from other loader: module (evaluated) 1`] = `
56+
exports[`sourceMap option should not generate sourceMap when source map is valid from other loader (\`sass-loader\`): module (evaluated) 1`] = `
7457
Array [
7558
Array [
7659
1,
77-
".class {
78-
color: red;
79-
}
80-
",
60+
"body {
61+
font: 100% Helvetica, sans-serif;
62+
color: #333;
63+
}",
8164
"",
8265
],
8366
]
8467
`;
8568

86-
exports[`sourceMap option false should not generate sourceMap when source map is valid from other loader: warnings 1`] = `Array []`;
69+
exports[`sourceMap option should not generate sourceMap when source map is valid from other loader (\`sass-loader\`): warnings 1`] = `Array []`;
8770

8871
exports[`sourceMap option true should generate source map when source map is \`null\` from other loader: errors 1`] = `Array []`;
8972

@@ -97,12 +80,11 @@ Array [
9780
",
9881
"",
9982
Object {
100-
"file": "basic.css",
83+
"file": "../../basic.css",
10184
"mappings": "AAAA;EACE,UAAU;AACZ",
10285
"names": Array [],
103-
"sourceRoot": "",
10486
"sources": Array [
105-
"/replaced/original/path/",
87+
"../../basic.css",
10688
],
10789
"sourcesContent": Array [
10890
".class {
@@ -130,12 +112,11 @@ Array [
130112
",
131113
"",
132114
Object {
133-
"file": "basic.css",
115+
"file": "../../basic.css",
134116
"mappings": "AAAA;EACE,UAAU;AACZ",
135117
"names": Array [],
136-
"sourceRoot": "",
137118
"sources": Array [
138-
"/replaced/original/path/",
119+
"../../basic.css",
139120
],
140121
"sourcesContent": Array [
141122
".class {
@@ -163,16 +144,50 @@ Array [
163144
",
164145
"",
165146
Object {
166-
"file": "basic.css",
167-
"mappings": "AAAA;ECCE,UAAU;AACZ",
147+
"file": "../../basic.css",
148+
"mappings": "AAGA;EACE,UAAA;ACFF",
168149
"names": Array [],
169-
"sourceRoot": "",
170150
"sources": Array [
171-
"/replaced/original/path/",
172-
"/replaced/original/path/",
151+
"source-map/basic.postcss.css",
152+
"../../basic.css",
173153
],
174154
"sourcesContent": Array [
175-
".class { a: b c d; }",
155+
"@custom-media --viewport-medium (width <= 50rem);
156+
@custom-selector :--heading h1, h2, h3, h4, h5, h6;
157+
158+
:root {
159+
--fontSize: 1rem;
160+
--mainColor: #12345678;
161+
--secondaryColor: lab(32.5 38.5 -47.6 / 90%);
162+
}
163+
164+
html {
165+
overflow: hidden auto;
166+
}
167+
168+
@media (--viewport-medium) {
169+
body {
170+
color: var(--mainColor);
171+
font-family: system-ui;
172+
font-size: var(--fontSize);
173+
line-height: calc(var(--fontSize) * 1.5);
174+
overflow-wrap: break-word;
175+
padding-inline: calc(var(--fontSize) / 2 + 1px);
176+
}
177+
}
178+
179+
:--heading {
180+
margin-block: 0;
181+
}
182+
183+
a {
184+
color: rgb(0 0 100% / 90%);
185+
186+
&:hover {
187+
color: rebeccapurple;
188+
}
189+
}
190+
",
176191
".class {
177192
color: red;
178193
}
@@ -186,40 +201,148 @@ Array [
186201

187202
exports[`sourceMap option true should generate source map when source map is valid and it is string from other loader: warnings 1`] = `Array []`;
188203

189-
exports[`sourceMap option true should generate source map when source map is valid from other loader: errors 1`] = `Array []`;
204+
exports[`sourceMap option true should generate source map when source map is valid from other loader (\`postcss-loader\`): errors 1`] = `Array []`;
190205

191-
exports[`sourceMap option true should generate source map when source map is valid from other loader: module (evaluated) 1`] = `
206+
exports[`sourceMap option true should generate source map when source map is valid from other loader (\`postcss-loader\`): module (evaluated) 1`] = `
192207
Array [
193208
Array [
194209
1,
195-
".class {
196-
color: red;
210+
":root {
211+
--fontSize: 1rem;
212+
--mainColor: rgba(18,52,86,0.47059);
213+
--secondaryColor: rgba(102, 51, 153, 0.9);
214+
}
215+
216+
html {
217+
overflow-x: hidden;
218+
overflow-y: auto;
219+
overflow: hidden auto;
220+
}
221+
222+
@media (max-width: 50rem) {
223+
body {
224+
color: rgba(18,52,86,0.47059);
225+
color: var(--mainColor);
226+
font-family: system-ui, -apple-system, Segoe UI, Roboto, Ubuntu, Cantarell, Noto Sans, sans-serif;
227+
font-size: 1rem;
228+
font-size: var(--fontSize);
229+
line-height: calc(1rem * 1.5);
230+
line-height: calc(var(--fontSize) * 1.5);
231+
word-wrap: break-word;
232+
padding-left: calc(1rem / 2 + 1px);
233+
padding-right: calc(1rem / 2 + 1px);
234+
padding-left: calc(var(--fontSize) / 2 + 1px);
235+
padding-right: calc(var(--fontSize) / 2 + 1px);
236+
}
237+
}
238+
239+
h1,h2,h3,h4,h5,h6 {
240+
margin-top: 0;
241+
margin-bottom: 0;
242+
}
243+
244+
a {
245+
color: rgba(0, 0, 255, 0.9)
197246
}
247+
248+
a:hover {
249+
color: #639;
250+
}
198251
",
199252
"",
200253
Object {
201-
"file": "basic.css",
202-
"mappings": "AAAA;ECCE,UAAU;AACZ",
254+
"file": "../../basic.postcss.css",
255+
"mappings": "AAGA;EACE,gBAAgB;EAChB,mCAAsB;EACtB,yCAA4C;AAC9C;;AAEA;EACE,kBAAqB;EAArB,gBAAqB;EAArB,qBAAqB;AACvB;;AAEA;EACE;IACE,6BAAuB;IAAvB,uBAAuB;IACvB,iGAAsB;IACtB,eAA0B;IAA1B,0BAA0B;IAC1B,6BAAwC;IAAxC,wCAAwC;IACxC,qBAAyB;IACzB,kCAA+C;IAA/C,mCAA+C;IAA/C,6CAA+C;IAA/C,8CAA+C;EACjD;AACF;;AAEA;EACE,aAAe;EAAf,gBAAe;AACjB;;AAEA;EACE;AAKF;;AAHA;GACG,WAAoB;CACtB",
203256
"names": Array [],
204-
"sourceRoot": "",
205257
"sources": Array [
206-
"/replaced/original/path/",
207-
"/replaced/original/path/",
258+
"../../basic.postcss.css",
208259
],
209260
"sourcesContent": Array [
210-
".class { a: b c d; }",
211-
".class {
212-
color: red;
261+
"@custom-media --viewport-medium (width <= 50rem);
262+
@custom-selector :--heading h1, h2, h3, h4, h5, h6;
263+
264+
:root {
265+
--fontSize: 1rem;
266+
--mainColor: #12345678;
267+
--secondaryColor: lab(32.5 38.5 -47.6 / 90%);
268+
}
269+
270+
html {
271+
overflow: hidden auto;
272+
}
273+
274+
@media (--viewport-medium) {
275+
body {
276+
color: var(--mainColor);
277+
font-family: system-ui;
278+
font-size: var(--fontSize);
279+
line-height: calc(var(--fontSize) * 1.5);
280+
overflow-wrap: break-word;
281+
padding-inline: calc(var(--fontSize) / 2 + 1px);
282+
}
283+
}
284+
285+
:--heading {
286+
margin-block: 0;
287+
}
288+
289+
a {
290+
color: rgb(0 0 100% / 90%);
291+
292+
&:hover {
293+
color: rebeccapurple;
294+
}
295+
}
296+
",
297+
],
298+
"version": 3,
299+
},
300+
],
301+
]
302+
`;
303+
304+
exports[`sourceMap option true should generate source map when source map is valid from other loader (\`postcss-loader\`): warnings 1`] = `Array []`;
305+
306+
exports[`sourceMap option true should generate source map when source map is valid from other loader (\`sass-loader\`): errors 1`] = `Array []`;
307+
308+
exports[`sourceMap option true should generate source map when source map is valid from other loader (\`sass-loader\`): module (evaluated) 1`] = `
309+
Array [
310+
Array [
311+
1,
312+
"body {
313+
font: 100% Helvetica, sans-serif;
314+
color: #333;
315+
}",
316+
"",
317+
Object {
318+
"file": "../../basic.scss",
319+
"mappings": "AAGA;EACE,gCAAA;EACA,WAJc;ACEhB",
320+
"names": Array [],
321+
"sources": Array [
322+
"source-map/basic.scss",
323+
"../../basic.scss",
324+
],
325+
"sourcesContent": Array [
326+
"$font-stack: Helvetica, sans-serif;
327+
$primary-color: #333;
328+
329+
body {
330+
font: 100% $font-stack;
331+
color: $primary-color;
213332
}
214333
",
334+
"body {
335+
font: 100% Helvetica, sans-serif;
336+
color: #333;
337+
}",
215338
],
216339
"version": 3,
217340
},
218341
],
219342
]
220343
`;
221344

222-
exports[`sourceMap option true should generate source map when source map is valid from other loader: warnings 1`] = `Array []`;
345+
exports[`sourceMap option true should generate source map when source map is valid from other loader (\`sass-loader\`): warnings 1`] = `Array []`;
223346

224347
exports[`sourceMap option true should generate source map: errors 1`] = `Array []`;
225348

@@ -233,12 +356,11 @@ Array [
233356
",
234357
"",
235358
Object {
236-
"file": "basic.css",
359+
"file": "../../basic.css",
237360
"mappings": "AAAA;EACE,UAAU;AACZ",
238361
"names": Array [],
239-
"sourceRoot": "",
240362
"sources": Array [
241-
"/replaced/original/path/",
363+
"../../basic.css",
242364
],
243365
"sourcesContent": Array [
244366
".class {
+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
@custom-media --viewport-medium (width <= 50rem);
2+
@custom-selector :--heading h1, h2, h3, h4, h5, h6;
3+
4+
:root {
5+
--fontSize: 1rem;
6+
--mainColor: #12345678;
7+
--secondaryColor: lab(32.5 38.5 -47.6 / 90%);
8+
}
9+
10+
html {
11+
overflow: hidden auto;
12+
}
13+
14+
@media (--viewport-medium) {
15+
body {
16+
color: var(--mainColor);
17+
font-family: system-ui;
18+
font-size: var(--fontSize);
19+
line-height: calc(var(--fontSize) * 1.5);
20+
overflow-wrap: break-word;
21+
padding-inline: calc(var(--fontSize) / 2 + 1px);
22+
}
23+
}
24+
25+
:--heading {
26+
margin-block: 0;
27+
}
28+
29+
a {
30+
color: rgb(0 0 100% / 90%);
31+
32+
&:hover {
33+
color: rebeccapurple;
34+
}
35+
}

‎test/fixtures/source-map/basic.scss

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
$font-stack: Helvetica, sans-serif;
2+
$primary-color: #333;
3+
4+
body {
5+
font: 100% $font-stack;
6+
color: $primary-color;
7+
}

‎test/helpers.js

+23-2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ const del = require('del');
55
const webpack = require('webpack');
66
const MemoryFS = require('memory-fs');
77
const stripAnsi = require('strip-ansi');
8+
const normalizePath = require('normalize-path');
89

910
function evaluated(output, modules, moduleId = 1) {
1011
let m;
@@ -224,8 +225,28 @@ function normalizeErrors(errors) {
224225
function normalizeSourceMap(module) {
225226
return module.map((m) => {
226227
if (m[3]) {
227-
// eslint-disable-next-line no-param-reassign
228-
m[3].sources = m[3].sources.map(() => '/replaced/original/path/');
228+
if (m[3].file) {
229+
// eslint-disable-next-line no-param-reassign
230+
m[3].file = normalizePath(
231+
path.relative(path.resolve(__dirname, 'fixtures'), m[3].file)
232+
);
233+
}
234+
235+
if (m[3].sourceRoot) {
236+
// eslint-disable-next-line no-param-reassign
237+
m[3].sourceRoot = normalizePath(
238+
path.relative(path.resolve(__dirname, 'fixtures'), m[3].sourceRoot)
239+
);
240+
}
241+
242+
if (m[3].sources) {
243+
// eslint-disable-next-line no-param-reassign
244+
m[3].sources = m[3].sources.map((source) =>
245+
normalizePath(
246+
path.relative(path.resolve(__dirname, 'fixtures'), source)
247+
)
248+
);
249+
}
229250
}
230251

231252
return m;

‎test/sourceMap-option.test.js

+70-66
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
const path = require('path');
2+
3+
const postcssPresetEnv = require('postcss-preset-env');
4+
15
const { webpack, evaluated, normalizeSourceMap } = require('./helpers');
26

37
describe('sourceMap option', () => {
@@ -65,22 +69,26 @@ describe('sourceMap option', () => {
6569
expect(stats.compilation.errors).toMatchSnapshot('errors');
6670
});
6771

68-
it('should generate source map when source map is valid from other loader', async () => {
72+
it('should generate source map when source map is valid and it is string from other loader', async () => {
6973
const config = {
7074
loader: {
7175
options: {
7276
sourceMap: true,
7377
},
7478
},
75-
sourceMap: {
76-
file: 'test.css',
77-
mappings: 'AAAA,SAAS,SAAS,EAAE',
78-
names: [],
79-
sourceRoot: '',
80-
sources: ['/folder/test.css'],
81-
sourcesContent: ['.class { a: b c d; }'],
79+
sourceMap: JSON.stringify({
8280
version: 3,
83-
},
81+
sources: [
82+
path.join(__dirname, 'fixtures/source-map/basic.postcss.css'),
83+
],
84+
names: [],
85+
mappings:
86+
'AAGA;EACE,gBAAgB;EAChB,mCAAsB;EACtB,yCAA4C;AAC9C;;AAEA;EACE,kBAAqB;EAArB,gBAAqB;EAArB,qBAAqB;AACvB;;AAEA;EACE;IACE,6BAAuB;IAAvB,uBAAuB;IACvB,iGAAsB;IACtB,eAA0B;IAA1B,0BAA0B;IAC1B,6BAAwC;IAAxC,wCAAwC;IACxC,qBAAyB;IACzB,kCAA+C;IAA/C,mCAA+C;IAA/C,6CAA+C;IAA/C,8CAA+C;EACjD;AACF;;AAEA;EACE,aAAe;EAAf,gBAAe;AACjB;;AAEA;EACE;AAKF;;AAHA;GACG,WAAoB;CACtB',
87+
file: path.join(__dirname, 'fixtures/source-map/basic.postcss.css'),
88+
sourcesContent: [
89+
'@custom-media --viewport-medium (width <= 50rem);\n@custom-selector :--heading h1, h2, h3, h4, h5, h6;\n\n:root {\n --fontSize: 1rem;\n --mainColor: #12345678;\n --secondaryColor: lab(32.5 38.5 -47.6 / 90%);\n}\n\nhtml {\n overflow: hidden auto;\n}\n\n@media (--viewport-medium) {\n body {\n color: var(--mainColor);\n font-family: system-ui;\n font-size: var(--fontSize);\n line-height: calc(var(--fontSize) * 1.5);\n overflow-wrap: break-word;\n padding-inline: calc(var(--fontSize) / 2 + 1px);\n }\n}\n\n:--heading {\n margin-block: 0;\n}\n\na {\n color: rgb(0 0 100% / 90%);\n\n&:hover {\n color: rebeccapurple;\n }\n}\n',
90+
],
91+
}),
8492
};
8593
const testId = './source-map/basic.css';
8694
const stats = await webpack(testId, config);
@@ -94,24 +102,22 @@ describe('sourceMap option', () => {
94102
expect(stats.compilation.errors).toMatchSnapshot('errors');
95103
});
96104

97-
it('should generate source map when source map is valid and it is string from other loader', async () => {
105+
it('should generate source map when source map is valid from other loader (`sass-loader`)', async () => {
98106
const config = {
99107
loader: {
108+
test: /\.s[ca]ss$/i,
100109
options: {
101110
sourceMap: true,
102111
},
103112
},
104-
sourceMap: JSON.stringify({
105-
file: 'test.css',
106-
mappings: 'AAAA,SAAS,SAAS,EAAE',
107-
names: [],
108-
sourceRoot: '',
109-
sources: ['/folder/test.css'],
110-
sourcesContent: ['.class { a: b c d; }'],
111-
version: 3,
112-
}),
113+
sassLoader: true,
114+
sassLoaderOptions: {
115+
// eslint-disable-next-line global-require
116+
implementation: require('sass'),
117+
sourceMap: true,
118+
},
113119
};
114-
const testId = './source-map/basic.css';
120+
const testId = './source-map/basic.scss';
115121
const stats = await webpack(testId, config);
116122
const { modules } = stats.toJson();
117123
const module = modules.find((m) => m.id === testId);
@@ -122,35 +128,41 @@ describe('sourceMap option', () => {
122128
expect(stats.compilation.warnings).toMatchSnapshot('warnings');
123129
expect(stats.compilation.errors).toMatchSnapshot('errors');
124130
});
125-
});
126131

127-
describe('false', () => {
128-
it('should not generate source map', async () => {
132+
it('should generate source map when source map is valid from other loader (`postcss-loader`)', async () => {
129133
const config = {
130134
loader: {
131135
options: {
132-
sourceMap: false,
136+
sourceMap: true,
133137
},
134138
},
139+
postcssLoader: true,
140+
postcssLoaderOptions: {
141+
sourceMap: true,
142+
plugins: () => [postcssPresetEnv({ stage: 0 })],
143+
},
135144
};
136-
const testId = './source-map/basic.css';
145+
const testId = './source-map/basic.postcss.css';
137146
const stats = await webpack(testId, config);
138147
const { modules } = stats.toJson();
139148
const module = modules.find((m) => m.id === testId);
140149

141-
expect(evaluated(module.source)).toMatchSnapshot('module (evaluated)');
150+
expect(normalizeSourceMap(evaluated(module.source))).toMatchSnapshot(
151+
'module (evaluated)'
152+
);
142153
expect(stats.compilation.warnings).toMatchSnapshot('warnings');
143154
expect(stats.compilation.errors).toMatchSnapshot('errors');
144155
});
156+
});
145157

146-
it('should not generate source map when source map is `null` from other loader', async () => {
158+
describe('false', () => {
159+
it('should not generate source map', async () => {
147160
const config = {
148161
loader: {
149162
options: {
150163
sourceMap: false,
151164
},
152165
},
153-
sourceMap: null,
154166
};
155167
const testId = './source-map/basic.css';
156168
const stats = await webpack(testId, config);
@@ -162,15 +174,14 @@ describe('sourceMap option', () => {
162174
expect(stats.compilation.errors).toMatchSnapshot('errors');
163175
});
164176

165-
it('should not generate source map when source map is `undefined` from other loader', async () => {
177+
it('should not generate source map when source map is `null` from other loader', async () => {
166178
const config = {
167179
loader: {
168180
options: {
169181
sourceMap: false,
170182
},
171183
},
172-
// eslint-disable-next-line no-undefined
173-
sourceMap: undefined,
184+
sourceMap: null,
174185
};
175186
const testId = './source-map/basic.css';
176187
const stats = await webpack(testId, config);
@@ -182,22 +193,15 @@ describe('sourceMap option', () => {
182193
expect(stats.compilation.errors).toMatchSnapshot('errors');
183194
});
184195

185-
it('should not generate sourceMap when source map is valid from other loader', async () => {
196+
it('should not generate source map when source map is `undefined` from other loader', async () => {
186197
const config = {
187198
loader: {
188199
options: {
189200
sourceMap: false,
190201
},
191202
},
192-
sourceMap: {
193-
file: 'test.css',
194-
mappings: 'AAAA,SAAS,SAAS,EAAE',
195-
names: [],
196-
sourceRoot: '',
197-
sources: ['/folder/test.css'],
198-
sourcesContent: ['.class { a: b c d; }'],
199-
version: 3,
200-
},
203+
// eslint-disable-next-line no-undefined
204+
sourceMap: undefined,
201205
};
202206
const testId = './source-map/basic.css';
203207
const stats = await webpack(testId, config);
@@ -208,32 +212,32 @@ describe('sourceMap option', () => {
208212
expect(stats.compilation.warnings).toMatchSnapshot('warnings');
209213
expect(stats.compilation.errors).toMatchSnapshot('errors');
210214
});
215+
});
211216

212-
it('should not generate source map when source map is valid and it is string from other loader', async () => {
213-
const config = {
214-
loader: {
215-
options: {
216-
sourceMap: false,
217-
},
217+
it('should not generate sourceMap when source map is valid from other loader (`sass-loader`)', async () => {
218+
const config = {
219+
loader: {
220+
test: /\.s[ca]ss$/i,
221+
options: {
222+
sourceMap: false,
218223
},
219-
sourceMap: JSON.stringify({
220-
file: 'test.css',
221-
mappings: 'AAAA,SAAS,SAAS,EAAE',
222-
names: [],
223-
sourceRoot: '',
224-
sources: ['/folder/test.css'],
225-
sourcesContent: ['.class { a: b c d; }'],
226-
version: 3,
227-
}),
228-
};
229-
const testId = './source-map/basic.css';
230-
const stats = await webpack(testId, config);
231-
const { modules } = stats.toJson();
232-
const module = modules.find((m) => m.id === testId);
233-
234-
expect(evaluated(module.source)).toMatchSnapshot('module (evaluated)');
235-
expect(stats.compilation.warnings).toMatchSnapshot('warnings');
236-
expect(stats.compilation.errors).toMatchSnapshot('errors');
237-
});
224+
},
225+
sassLoader: true,
226+
sassLoaderOptions: {
227+
// eslint-disable-next-line global-require
228+
implementation: require('sass'),
229+
sourceMap: true,
230+
},
231+
};
232+
const testId = './source-map/basic.scss';
233+
const stats = await webpack(testId, config);
234+
const { modules } = stats.toJson();
235+
const module = modules.find((m) => m.id === testId);
236+
237+
expect(normalizeSourceMap(evaluated(module.source))).toMatchSnapshot(
238+
'module (evaluated)'
239+
);
240+
expect(stats.compilation.warnings).toMatchSnapshot('warnings');
241+
expect(stats.compilation.errors).toMatchSnapshot('errors');
238242
});
239243
});

0 commit comments

Comments
 (0)
Please sign in to comment.