diff --git a/src/utils.js b/src/utils.js index 49f37d29..92c23617 100644 --- a/src/utils.js +++ b/src/utils.js @@ -298,6 +298,25 @@ function getModulesPlugins(options, loaderContext) { return plugins; } +const IS_NATIVE_WIN32_PATH = /^[a-z]:[/\\]|^\\\\/i; +const ABSOLUTE_SCHEME = /^[a-z0-9+\-.]+:/i; + +function getURLType(source) { + if (source[0] === '/') { + if (source[1] === '/') { + return 'scheme-relative'; + } + + return 'path-absolute'; + } + + if (IS_NATIVE_WIN32_PATH.test(source)) { + return 'path-absolute'; + } + + return ABSOLUTE_SCHEME.test(source) ? 'absolute' : 'path-relative'; +} + function normalizeSourceMap(map, resourcePath) { let newMap = map; @@ -307,36 +326,34 @@ function normalizeSourceMap(map, resourcePath) { newMap = JSON.parse(newMap); } - // Source maps should use forward slash because it is URLs (https://github.com/mozilla/source-map/issues/91) - // We should normalize path because previous loaders like `sass-loader` using backslash when generate source map - - if (newMap.file) { - delete newMap.file; - } + delete newMap.file; const { sourceRoot } = newMap; - if (newMap.sourceRoot) { - delete newMap.sourceRoot; - } + delete newMap.sourceRoot; if (newMap.sources) { + // Source maps should use forward slash because it is URLs (https://github.com/mozilla/source-map/issues/91) + // We should normalize path because previous loaders like `sass-loader` using backslash when generate source map newMap.sources = newMap.sources.map((source) => { + // Non-standard syntax from `postcss` if (source.indexOf('<') === 0) { return source; } - if (/^\w+:\/\//.test(source)) { - return source; - } + const sourceType = getURLType(source); - const absoluteSource = !sourceRoot - ? source - : path.resolve(sourceRoot, source); + // Do no touch `scheme-relative` and `absolute` URLs + if (sourceType === 'path-relative' || sourceType === 'path-absolute') { + const absoluteSource = + sourceType === 'path-relative' && sourceRoot + ? path.resolve(sourceRoot, normalizePath(source)) + : normalizePath(source); - const resourceDirname = path.dirname(resourcePath); + return path.relative(path.dirname(resourcePath), absoluteSource); + } - return normalizePath(path.relative(resourceDirname, absoluteSource)); + return source; }); } @@ -395,16 +412,19 @@ function normalizeSourceMapForRuntime(map, loaderContext) { const resultMap = map ? map.toJSON() : null; if (resultMap) { - if (typeof resultMap.file !== 'undefined') { - delete resultMap.file; - } + delete resultMap.file; + + resultMap.sourceRoot = ''; resultMap.sources = resultMap.sources.map((source) => { + // Non-standard syntax from `postcss` if (source.indexOf('<') === 0) { return source; } - if (/^\w+:\/\//.test(source)) { + const sourceType = getURLType(source); + + if (sourceType !== 'path-relative') { return source; } diff --git a/test/__snapshots__/sourceMap-option.test.js.snap b/test/__snapshots__/sourceMap-option.test.js.snap index 5b466646..a664b239 100644 --- a/test/__snapshots__/sourceMap-option.test.js.snap +++ b/test/__snapshots__/sourceMap-option.test.js.snap @@ -159,7 +159,7 @@ exports[`"sourceMap" option true should generate source maps #2: module 1`] = ` import ___CSS_LOADER_API_IMPORT___ from \\"../../../src/runtime/api.js\\"; var ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(true); // Module -___CSS_LOADER_EXPORT___.push([module.id, \\".foo {\\\\n color: red;\\\\n}\\\\n\\", \\"\\",{\\"version\\":3,\\"sources\\":[\\"webpack://source-map/with-query.css\\"],\\"names\\":[],\\"mappings\\":\\"AAAA;EACE,UAAU;AACZ\\",\\"sourcesContent\\":[\\".foo {\\\\n color: red;\\\\n}\\\\n\\"]}]); +___CSS_LOADER_EXPORT___.push([module.id, \\".foo {\\\\n color: red;\\\\n}\\\\n\\", \\"\\",{\\"version\\":3,\\"sources\\":[\\"webpack://source-map/with-query.css\\"],\\"names\\":[],\\"mappings\\":\\"AAAA;EACE,UAAU;AACZ\\",\\"sourcesContent\\":[\\".foo {\\\\n color: red;\\\\n}\\\\n\\"],\\"sourceRoot\\":\\"\\"}]); // Exports export default ___CSS_LOADER_EXPORT___; " @@ -177,6 +177,7 @@ Array [ Object { "mappings": "AAAA;EACE,UAAU;AACZ", "names": Array [], + "sourceRoot": "", "sources": Array [ "webpack://source-map/with-query.css", ], @@ -203,7 +204,7 @@ import ___CSS_LOADER_AT_RULE_IMPORT_0___ from \\"-!../../../src/index.js??[ident var ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(true); ___CSS_LOADER_EXPORT___.i(___CSS_LOADER_AT_RULE_IMPORT_0___); // Module -___CSS_LOADER_EXPORT___.push([module.id, \\".class {\\\\n color: red;\\\\n}\\\\n\\", \\"\\",{\\"version\\":3,\\"sources\\":[\\"webpack://test/fixtures/source-map/basic.css\\"],\\"names\\":[],\\"mappings\\":\\"AAEA;EACE,UAAU;AACZ\\",\\"sourcesContent\\":[\\"@import \\\\\\"./nested/nested.css\\\\\\";\\\\n\\\\n.class {\\\\n color: red;\\\\n}\\\\n\\"]}]); +___CSS_LOADER_EXPORT___.push([module.id, \\".class {\\\\n color: red;\\\\n}\\\\n\\", \\"\\",{\\"version\\":3,\\"sources\\":[\\"webpack://test/fixtures/source-map/basic.css\\"],\\"names\\":[],\\"mappings\\":\\"AAEA;EACE,UAAU;AACZ\\",\\"sourcesContent\\":[\\"@import \\\\\\"./nested/nested.css\\\\\\";\\\\n\\\\n.class {\\\\n color: red;\\\\n}\\\\n\\"],\\"sourceRoot\\":\\"\\"}]); // Exports export default ___CSS_LOADER_EXPORT___; " @@ -221,6 +222,7 @@ Array [ Object { "mappings": "AAAA;EACE,WAAW;AACb", "names": Array [], + "sourceRoot": "", "sources": Array [ "webpack://test/fixtures/source-map/nested/nested.css", ], @@ -243,6 +245,7 @@ Array [ Object { "mappings": "AAEA;EACE,UAAU;AACZ", "names": Array [], + "sourceRoot": "", "sources": Array [ "webpack://test/fixtures/source-map/basic.css", ], @@ -357,7 +360,7 @@ import ___CSS_LOADER_AT_RULE_IMPORT_0___ from \\"-!../../../src/index.js??[ident var ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(true); ___CSS_LOADER_EXPORT___.i(___CSS_LOADER_AT_RULE_IMPORT_0___); // Module -___CSS_LOADER_EXPORT___.push([module.id, \\".class {\\\\n color: red;\\\\n}\\\\n\\", \\"\\",{\\"version\\":3,\\"sources\\":[\\"webpack://source-map/basic.css\\"],\\"names\\":[],\\"mappings\\":\\"AAEA;EACE,UAAU;AACZ\\",\\"sourcesContent\\":[\\"@import \\\\\\"./nested/nested.css\\\\\\";\\\\n\\\\n.class {\\\\n color: red;\\\\n}\\\\n\\"]}]); +___CSS_LOADER_EXPORT___.push([module.id, \\".class {\\\\n color: red;\\\\n}\\\\n\\", \\"\\",{\\"version\\":3,\\"sources\\":[\\"webpack://source-map/basic.css\\"],\\"names\\":[],\\"mappings\\":\\"AAEA;EACE,UAAU;AACZ\\",\\"sourcesContent\\":[\\"@import \\\\\\"./nested/nested.css\\\\\\";\\\\n\\\\n.class {\\\\n color: red;\\\\n}\\\\n\\"],\\"sourceRoot\\":\\"\\"}]); // Exports export default ___CSS_LOADER_EXPORT___; " @@ -375,6 +378,7 @@ Array [ Object { "mappings": "AAAA;EACE,WAAW;AACb", "names": Array [], + "sourceRoot": "", "sources": Array [ "webpack://source-map/nested/nested.css", ], @@ -397,6 +401,7 @@ Array [ Object { "mappings": "AAEA;EACE,UAAU;AACZ", "names": Array [], + "sourceRoot": "", "sources": Array [ "webpack://source-map/basic.css", ], @@ -416,6 +421,76 @@ Array [ exports[`"sourceMap" option true should generate source maps when previous loader does not generate source maps: warnings 1`] = `Array []`; +exports[`"sourceMap" option true should generate source maps when previous loader generates different source in source maps: errors 1`] = `Array []`; + +exports[`"sourceMap" option true should generate source maps when previous loader generates different source in source maps: module 1`] = ` +"// Imports +import ___CSS_LOADER_API_IMPORT___ from \\"../../../src/runtime/api.js\\"; +import ___CSS_LOADER_AT_RULE_IMPORT_0___ from \\"-!../../../src/index.js??[ident]!./nested/nested.css\\"; +var ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(true); +___CSS_LOADER_EXPORT___.i(___CSS_LOADER_AT_RULE_IMPORT_0___); +// Module +___CSS_LOADER_EXPORT___.push([module.id, \\".class {\\\\n color: red;\\\\n}\\\\n\\", \\"\\",{\\"version\\":3,\\"sources\\":[\\"webpack://source-map/basic-1.css\\"],\\"names\\":[],\\"mappings\\":\\"AAEA;EACE,UAAU;AACZ\\",\\"sourcesContent\\":[\\"@import \\\\\\"./nested/nested.css\\\\\\";\\\\n\\\\n.class {\\\\n color: red;\\\\n}\\\\n\\"],\\"sourceRoot\\":\\"\\"}]); +// Exports +export default ___CSS_LOADER_EXPORT___; +" +`; + +exports[`"sourceMap" option true should generate source maps when previous loader generates different source in source maps: result 1`] = ` +Array [ + Array [ + "../../src/index.js?[ident]!./source-map/nested/nested.css", + ".nested { + color: blue; +} +", + "", + Object { + "mappings": "AAAA;EACE,WAAW;AACb", + "names": Array [], + "sourceRoot": "", + "sources": Array [ + "webpack://source-map/nested/nested.css", + ], + "sourcesContent": Array [ + ".nested { + color: blue; +} +", + ], + "version": 3, + }, + ], + Array [ + "./source-map/basic.css", + ".class { + color: red; +} +", + "", + Object { + "mappings": "AAEA;EACE,UAAU;AACZ", + "names": Array [], + "sourceRoot": "", + "sources": Array [ + "webpack://source-map/basic-1.css", + ], + "sourcesContent": Array [ + "@import \\"./nested/nested.css\\"; + +.class { + color: red; +} +", + ], + "version": 3, + }, + ], +] +`; + +exports[`"sourceMap" option true should generate source maps when previous loader generates different source in source maps: warnings 1`] = `Array []`; + exports[`"sourceMap" option true should generate source maps when previous loader generates source maps ("less-loader"): errors 1`] = `Array []`; exports[`"sourceMap" option true should generate source maps when previous loader generates source maps ("less-loader"): module 1`] = ` @@ -423,7 +498,7 @@ exports[`"sourceMap" option true should generate source maps when previous loade import ___CSS_LOADER_API_IMPORT___ from \\"../../../src/runtime/api.js\\"; var ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(true); // Module -___CSS_LOADER_EXPORT___.push([module.id, \\"body {\\\\n font: 100% Helvetica, sans-serif;\\\\n color: #333;\\\\n}\\\\n\\", \\"\\",{\\"version\\":3,\\"sources\\":[\\"webpack://source-map/base.less\\"],\\"names\\":[],\\"mappings\\":\\"AAGA;EACE,gCAAA;EACA,WAAA;AAFF\\",\\"sourcesContent\\":[\\"@font-stack: Helvetica, sans-serif;\\\\n@primary-color: #333;\\\\n\\\\nbody {\\\\n font: 100% @font-stack;\\\\n color: @primary-color;\\\\n}\\\\n\\"]}]); +___CSS_LOADER_EXPORT___.push([module.id, \\"body {\\\\n font: 100% Helvetica, sans-serif;\\\\n color: #333;\\\\n}\\\\n\\", \\"\\",{\\"version\\":3,\\"sources\\":[\\"webpack://source-map/base.less\\"],\\"names\\":[],\\"mappings\\":\\"AAGA;EACE,gCAAA;EACA,WAAA;AAFF\\",\\"sourcesContent\\":[\\"@font-stack: Helvetica, sans-serif;\\\\n@primary-color: #333;\\\\n\\\\nbody {\\\\n font: 100% @font-stack;\\\\n color: @primary-color;\\\\n}\\\\n\\"],\\"sourceRoot\\":\\"\\"}]); // Exports export default ___CSS_LOADER_EXPORT___; " @@ -442,6 +517,7 @@ Array [ Object { "mappings": "AAGA;EACE,gCAAA;EACA,WAAA;AAFF", "names": Array [], + "sourceRoot": "", "sources": Array [ "webpack://source-map/base.less", ], @@ -472,7 +548,7 @@ import ___CSS_LOADER_AT_RULE_IMPORT_0___ from \\"-!../../../src/index.js??[ident var ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(true); ___CSS_LOADER_EXPORT___.i(___CSS_LOADER_AT_RULE_IMPORT_0___); // Module -___CSS_LOADER_EXPORT___.push([module.id, \\":root {\\\\n --fontSize: 1rem;\\\\n --mainColor: rgba(18,52,86,0.47059);\\\\n --secondaryColor: rgba(102, 51, 153, 0.9);\\\\n}\\\\n\\\\nhtml {\\\\n overflow-x: hidden;\\\\n overflow-y: auto;\\\\n overflow: hidden auto;\\\\n}\\\\n\\\\n@media (max-width: 50rem) {\\\\n body {\\\\n color: rgba(18,52,86,0.47059);\\\\n color: var(--mainColor);\\\\n font-family: system-ui, -apple-system, Segoe UI, Roboto, Ubuntu, Cantarell, Noto Sans, sans-serif;\\\\n font-size: 1rem;\\\\n font-size: var(--fontSize);\\\\n line-height: calc(1rem * 1.5);\\\\n line-height: calc(var(--fontSize) * 1.5);\\\\n word-wrap: break-word;\\\\n padding-left: calc(1rem / 2 + 1px);\\\\n padding-right: calc(1rem / 2 + 1px);\\\\n padding-left: calc(var(--fontSize) / 2 + 1px);\\\\n padding-right: calc(var(--fontSize) / 2 + 1px);\\\\n }\\\\n}\\\\n\\\\nh1,h2,h3,h4,h5,h6 {\\\\n margin-top: 0;\\\\n margin-bottom: 0;\\\\n}\\\\n\\\\na {\\\\n color: rgba(0, 0, 255, 0.9)\\\\n}\\\\n\\\\na:hover {\\\\n color: #639;\\\\n }\\\\n\\", \\"\\",{\\"version\\":3,\\"sources\\":[\\"webpack://source-map/basic.postcss.css\\"],\\"names\\":[],\\"mappings\\":\\"AAKA;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\\",\\"sourcesContent\\":[\\"@import \\\\\\"./nested/nested.postcss.css\\\\\\";\\\\n\\\\n@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\\"]}]); +___CSS_LOADER_EXPORT___.push([module.id, \\":root {\\\\n --fontSize: 1rem;\\\\n --mainColor: rgba(18,52,86,0.47059);\\\\n --secondaryColor: rgba(102, 51, 153, 0.9);\\\\n}\\\\n\\\\nhtml {\\\\n overflow-x: hidden;\\\\n overflow-y: auto;\\\\n overflow: hidden auto;\\\\n}\\\\n\\\\n@media (max-width: 50rem) {\\\\n body {\\\\n color: rgba(18,52,86,0.47059);\\\\n color: var(--mainColor);\\\\n font-family: system-ui, -apple-system, Segoe UI, Roboto, Ubuntu, Cantarell, Noto Sans, sans-serif;\\\\n font-size: 1rem;\\\\n font-size: var(--fontSize);\\\\n line-height: calc(1rem * 1.5);\\\\n line-height: calc(var(--fontSize) * 1.5);\\\\n word-wrap: break-word;\\\\n padding-left: calc(1rem / 2 + 1px);\\\\n padding-right: calc(1rem / 2 + 1px);\\\\n padding-left: calc(var(--fontSize) / 2 + 1px);\\\\n padding-right: calc(var(--fontSize) / 2 + 1px);\\\\n }\\\\n}\\\\n\\\\nh1,h2,h3,h4,h5,h6 {\\\\n margin-top: 0;\\\\n margin-bottom: 0;\\\\n}\\\\n\\\\na {\\\\n color: rgba(0, 0, 255, 0.9)\\\\n}\\\\n\\\\na:hover {\\\\n color: #639;\\\\n }\\\\n\\", \\"\\",{\\"version\\":3,\\"sources\\":[\\"webpack://source-map/basic.postcss.css\\"],\\"names\\":[],\\"mappings\\":\\"AAKA;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\\",\\"sourcesContent\\":[\\"@import \\\\\\"./nested/nested.postcss.css\\\\\\";\\\\n\\\\n@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\\"],\\"sourceRoot\\":\\"\\"}]); // Exports export default ___CSS_LOADER_EXPORT___; " @@ -490,6 +566,7 @@ Array [ Object { "mappings": "AAAA;EACE,WAAW;AACb", "names": Array [], + "sourceRoot": "", "sources": Array [ "webpack://source-map/nested/nested.postcss.css", ], @@ -550,6 +627,7 @@ a:hover { Object { "mappings": "AAKA;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", "names": Array [], + "sourceRoot": "", "sources": Array [ "webpack://source-map/basic.postcss.css", ], @@ -608,7 +686,7 @@ exports[`"sourceMap" option true should generate source maps when previous loade import ___CSS_LOADER_API_IMPORT___ from \\"../../../src/runtime/api.js\\"; var ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(true); // Module -___CSS_LOADER_EXPORT___.push([module.id, \\"body {\\\\n font: 14px/1.5 Helvetica, arial, sans-serif;\\\\n}\\\\nbody #logo {\\\\n border-radius: 5px;\\\\n}\\\\n/*# sourceMappingURL=test/fixtures/source-map/base.css.map */\\", \\"\\",{\\"version\\":3,\\"sources\\":[\\"webpack://source-map/base.styl\\"],\\"names\\":[],\\"mappings\\":\\"AAAA;EACE,2CAAwB;AAC1B;AAAE;EACE,kBAAe;AAEnB;AACA,4DAA4D\\",\\"sourcesContent\\":[\\"body {\\\\n font: 14px/1.5 Helvetica, arial, sans-serif;\\\\n #logo {\\\\n border-radius: 5px;\\\\n }\\\\n}\\\\n\\"]}]); +___CSS_LOADER_EXPORT___.push([module.id, \\"body {\\\\n font: 14px/1.5 Helvetica, arial, sans-serif;\\\\n}\\\\nbody #logo {\\\\n border-radius: 5px;\\\\n}\\\\n/*# sourceMappingURL=test/fixtures/source-map/base.css.map */\\", \\"\\",{\\"version\\":3,\\"sources\\":[\\"webpack://source-map/base.styl\\"],\\"names\\":[],\\"mappings\\":\\"AAAA;EACE,2CAAwB;AAC1B;AAAE;EACE,kBAAe;AAEnB;AACA,4DAA4D\\",\\"sourcesContent\\":[\\"body {\\\\n font: 14px/1.5 Helvetica, arial, sans-serif;\\\\n #logo {\\\\n border-radius: 5px;\\\\n }\\\\n}\\\\n\\"],\\"sourceRoot\\":\\"\\"}]); // Exports export default ___CSS_LOADER_EXPORT___; " @@ -629,6 +707,7 @@ body #logo { Object { "mappings": "AAAA;EACE,2CAAwB;AAC1B;AAAE;EACE,kBAAe;AAEnB;AACA,4DAA4D", "names": Array [], + "sourceRoot": "", "sources": Array [ "webpack://source-map/base.styl", ], @@ -658,7 +737,7 @@ import ___CSS_LOADER_AT_RULE_IMPORT_0___ from \\"-!../../../src/index.js??[ident var ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(true); ___CSS_LOADER_EXPORT___.i(___CSS_LOADER_AT_RULE_IMPORT_0___); // Module -___CSS_LOADER_EXPORT___.push([module.id, \\".class {\\\\n color: red;\\\\n}\\\\n\\", \\"\\",{\\"version\\":3,\\"sources\\":[\\"webpack://source-map/basic.css\\"],\\"names\\":[],\\"mappings\\":\\"AAEA;EACE,UAAU;AACZ\\",\\"sourcesContent\\":[\\"@import \\\\\\"./nested/nested.css\\\\\\";\\\\n\\\\n.class {\\\\n color: red;\\\\n}\\\\n\\"]}]); +___CSS_LOADER_EXPORT___.push([module.id, \\".class {\\\\n color: red;\\\\n}\\\\n\\", \\"\\",{\\"version\\":3,\\"sources\\":[\\"webpack://source-map/basic.css\\"],\\"names\\":[],\\"mappings\\":\\"AAEA;EACE,UAAU;AACZ\\",\\"sourcesContent\\":[\\"@import \\\\\\"./nested/nested.css\\\\\\";\\\\n\\\\n.class {\\\\n color: red;\\\\n}\\\\n\\"],\\"sourceRoot\\":\\"\\"}]); // Exports export default ___CSS_LOADER_EXPORT___; " @@ -676,6 +755,7 @@ Array [ Object { "mappings": "AAAA;EACE,WAAW;AACb", "names": Array [], + "sourceRoot": "", "sources": Array [ "webpack://source-map/nested/nested.css", ], @@ -698,6 +778,7 @@ Array [ Object { "mappings": "AAEA;EACE,UAAU;AACZ", "names": Array [], + "sourceRoot": "", "sources": Array [ "webpack://source-map/basic.css", ], @@ -726,7 +807,7 @@ import ___CSS_LOADER_AT_RULE_IMPORT_0___ from \\"-!../../../src/index.js??[ident var ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(true); ___CSS_LOADER_EXPORT___.i(___CSS_LOADER_AT_RULE_IMPORT_0___); // Module -___CSS_LOADER_EXPORT___.push([module.id, \\".class {\\\\n color: red;\\\\n}\\\\n\\", \\"\\",{\\"version\\":3,\\"sources\\":[\\"webpack://source-map/basic.css\\"],\\"names\\":[],\\"mappings\\":\\"AAEA;EACE,UAAU;AACZ\\",\\"sourcesContent\\":[\\"@import \\\\\\"./nested/nested.css\\\\\\";\\\\n\\\\n.class {\\\\n color: red;\\\\n}\\\\n\\"]}]); +___CSS_LOADER_EXPORT___.push([module.id, \\".class {\\\\n color: red;\\\\n}\\\\n\\", \\"\\",{\\"version\\":3,\\"sources\\":[\\"webpack://source-map/basic.css\\"],\\"names\\":[],\\"mappings\\":\\"AAEA;EACE,UAAU;AACZ\\",\\"sourcesContent\\":[\\"@import \\\\\\"./nested/nested.css\\\\\\";\\\\n\\\\n.class {\\\\n color: red;\\\\n}\\\\n\\"],\\"sourceRoot\\":\\"\\"}]); // Exports export default ___CSS_LOADER_EXPORT___; " @@ -744,6 +825,7 @@ Array [ Object { "mappings": "AAAA;EACE,WAAW;AACb", "names": Array [], + "sourceRoot": "", "sources": Array [ "webpack://source-map/nested/nested.css", ], @@ -766,6 +848,7 @@ Array [ Object { "mappings": "AAEA;EACE,UAAU;AACZ", "names": Array [], + "sourceRoot": "", "sources": Array [ "webpack://source-map/basic.css", ], @@ -794,7 +877,7 @@ import ___CSS_LOADER_AT_RULE_IMPORT_0___ from \\"-!../../../src/index.js??[ident var ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(true); ___CSS_LOADER_EXPORT___.i(___CSS_LOADER_AT_RULE_IMPORT_0___); // Module -___CSS_LOADER_EXPORT___.push([module.id, \\".class {\\\\n color: red;\\\\n}\\\\n\\", \\"\\",{\\"version\\":3,\\"sources\\":[\\"webpack://source-map/basic.css\\"],\\"names\\":[],\\"mappings\\":\\"AAEA;EACE,UAAU;AACZ\\",\\"sourcesContent\\":[\\"@import \\\\\\"./nested/nested.css\\\\\\";\\\\n\\\\n.class {\\\\n color: red;\\\\n}\\\\n\\"]}]); +___CSS_LOADER_EXPORT___.push([module.id, \\".class {\\\\n color: red;\\\\n}\\\\n\\", \\"\\",{\\"version\\":3,\\"sources\\":[\\"webpack://source-map/basic.css\\"],\\"names\\":[],\\"mappings\\":\\"AAEA;EACE,UAAU;AACZ\\",\\"sourcesContent\\":[\\"@import \\\\\\"./nested/nested.css\\\\\\";\\\\n\\\\n.class {\\\\n color: red;\\\\n}\\\\n\\"],\\"sourceRoot\\":\\"\\"}]); // Exports export default ___CSS_LOADER_EXPORT___; " @@ -812,6 +895,7 @@ Array [ Object { "mappings": "AAAA;EACE,WAAW;AACb", "names": Array [], + "sourceRoot": "", "sources": Array [ "webpack://source-map/nested/nested.css", ], @@ -834,6 +918,7 @@ Array [ Object { "mappings": "AAEA;EACE,UAAU;AACZ", "names": Array [], + "sourceRoot": "", "sources": Array [ "webpack://source-map/basic.css", ], diff --git a/test/sourceMap-option.test.js b/test/sourceMap-option.test.js index d4845340..247ff514 100644 --- a/test/sourceMap-option.test.js +++ b/test/sourceMap-option.test.js @@ -164,6 +164,83 @@ describe('"sourceMap" option', () => { expect(getErrors(stats)).toMatchSnapshot('errors'); }); + it('should generate source maps when previous loader generates different source in source maps', async () => { + const absoluteSourceRoot = path.resolve( + __dirname, + 'fixtures', + 'source-map' + ); + const absolutePath = path.resolve(absoluteSourceRoot, 'basic-1.css'); + const relativePath = path.relative( + absoluteSourceRoot, + path.resolve(__dirname, 'fixtures', 'source-map', 'basic-2.css') + ); + + const compiler = getCompiler( + './source-map/basic.js', + {}, + { + module: { + rules: [ + { + test: /\.css$/i, + use: [ + { + loader: path.resolve(__dirname, '../src'), + options: { sourceMap: true }, + }, + { + loader: path.resolve( + __dirname, + './fixtures/source-map-loader.js' + ), + options: { + sourceMap: JSON.stringify({ + version: 3, + sourceRoot: absoluteSourceRoot, + sources: [ + // Absolute path + absolutePath, + // Relative path + relativePath, + // Absolute URL + 'https://example.com/foo.css', + // Scheme-relative URL, + '//example.com/foo.css', + // Non-standard postcss syntax + ` { const absoluteSourceRoot = path.resolve( __dirname, @@ -422,8 +499,8 @@ describe('"sourceMap" option', () => { expect(chunkName).toBe( webpack.version[0] === '5' - ? 'main.b58b73eca7517a2128fd.bundle.js' - : 'main.1e45307f085c8aadaf4c.bundle.js' + ? 'main.f8a941345941e8190135.bundle.js' + : 'main.bad4e3fa71e9f3e4c073.bundle.js' ); expect( getModuleSource('fixtures/source-map/basic.css', stats) @@ -530,7 +607,7 @@ describe('"sourceMap" option', () => { expect(chunkName).toBe( // TODO still buggy on webpack@4 - webpack.version[0] === '5' ? 'main.8189c1c4f956dd69079a.css' : chunkName + webpack.version[0] === '5' ? 'main.208dafd9be3442f7a927.css' : chunkName ); expect(