diff --git a/src/index.js b/src/index.js index fa03809..eac13e3 100644 --- a/src/index.js +++ b/src/index.js @@ -5,7 +5,12 @@ import path from "path"; import schema from "./options.json"; -import { getSourceMappingURL, fetchFromURL, flattenSourceMap } from "./utils"; +import { + getSourceMappingURL, + fetchFromURL, + flattenSourceMap, + isURL, +} from "./utils"; export default async function loader(input, inputMap) { const options = this.getOptions(schema); @@ -122,7 +127,7 @@ export default async function loader(input, inputMap) { if (skipReading) { sourceContent = originalSourceContent; - } else if (!errored && sourceURL) { + } else if (!errored && sourceURL && !isURL(sourceURL)) { this.addDependency(sourceURL); } diff --git a/src/utils.js b/src/utils.js index 824a917..459f7a1 100644 --- a/src/utils.js +++ b/src/utils.js @@ -96,6 +96,10 @@ function getSourceMappingURL(code) { } function getAbsolutePath(context, request, sourceRoot) { + if (isURL(sourceRoot)) { + return new URL(request, sourceRoot).toString(); + } + if (sourceRoot) { if (path.isAbsolute(sourceRoot)) { return path.join(sourceRoot, request); @@ -125,6 +129,10 @@ function fetchFromDataURL(loaderContext, sourceURL) { async function fetchFromFilesystem(loaderContext, sourceURL) { let buffer; + if (isURL(sourceURL)) { + return { path: sourceURL }; + } + try { buffer = await new Promise((resolve, reject) => { loaderContext.fs.readFile(sourceURL, (error, data) => { @@ -179,6 +187,10 @@ async function fetchPathsFromFilesystem( return result; } +function isURL(value) { + return /^[a-z][a-z0-9+.-]*:/i.test(value) && !path.win32.isAbsolute(value); +} + async function fetchFromURL( loaderContext, context, @@ -187,7 +199,7 @@ async function fetchFromURL( skipReading = false ) { // 1. It's an absolute url and it is not `windows` path like `C:\dir\file` - if (/^[a-z][a-z0-9+.-]*:/i.test(url) && !path.win32.isAbsolute(url)) { + if (isURL(url)) { const { protocol } = urlUtils.parse(url); if (protocol === "data:") { @@ -268,4 +280,4 @@ async function fetchFromURL( return { sourceURL, sourceContent }; } -export { getSourceMappingURL, fetchFromURL, flattenSourceMap }; +export { getSourceMappingURL, fetchFromURL, flattenSourceMap, isURL }; diff --git a/test/__snapshots__/loader.test.js.snap b/test/__snapshots__/loader.test.js.snap index a45fad7..1c1462f 100644 --- a/test/__snapshots__/loader.test.js.snap +++ b/test/__snapshots__/loader.test.js.snap @@ -113,6 +113,27 @@ exports[`source-map-loader should leave normal files with fake source-map untouc exports[`source-map-loader should leave normal files with fake source-map untouched: warnings 1`] = `Array []`; +exports[`source-map-loader should process absolute URL in sourceRoot: code 1`] = ` +"const foo = "test"; +" +`; + +exports[`source-map-loader should process absolute URL in sourceRoot: errors 1`] = `[]`; + +exports[`source-map-loader should process absolute URL in sourceRoot: map 1`] = ` +{ + "file": "index.d.ts", + "mappings": "AAAA,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,MAAM,EAAE,KAAK,aAAa,EAAE,CAAC;AAEtC,OAAO,EACH,UAAU,EACV,iBAAiB,EACjB,SAAS,EACT,OAAO,EACP,QAAQ,EACX,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,UAAU,EAAE,KAAK,iBAAiB,EAAE,CAAC;AAE9C,aAAK,OAAO,GAAG,aAAa,GAAG,iBAAiB,CAAC;AAIjD;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,QAAQ,CAIvE;AACD;;;;;;;;;GASG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,EAAE,CAErE;AACD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC3B,EAAE,EAAE,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,SAAS,EAAE,KAAK,IAAI,EACnD,OAAO,CAAC,EAAE,OAAO,EACjB,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,GACvC,MAAM,CAGR;AAED,OAAO,EACH,OAAO,IAAI,SAAS,EACpB,KAAK,SAAS,IAAI,kBAAkB,GACvC,MAAM,gBAAgB,CAAC;AAMxB,OAAO,KAAK,WAAW,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,CAAC;AAEvB,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAEzC,OAAO,EAAE,OAAO,EAAE,CAAC;AAEnB;;;;;GAKG;AACH,wBAAgB,SAAS,CACrB,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,aAAa,GAAG,iBAAqC,GAC/D,IAAI,GAAG,IAAI,CAEb;AAED,OAAO,KAAK,QAAQ,MAAM,UAAU,CAAC;AAGrC,OAAO,EAAE,UAAU,IAAI,cAAc,EAAE,CAAC", + "names": [], + "sources": [ + "https://raw.githubusercontent.com/fb55/htmlparser2/4763205746cd80120b5d2b69041197a394d24ba9/src/index.ts", + ], + "version": 3, +} +`; + +exports[`source-map-loader should process absolute URL in sourceRoot: warnings 1`] = `[]`; + exports[`source-map-loader should process css sourceMap: code 1`] = ` "* { box-sizing: border-box; } diff --git a/test/fixtures/absolute-source-root.js b/test/fixtures/absolute-source-root.js new file mode 100644 index 0000000..c291190 --- /dev/null +++ b/test/fixtures/absolute-source-root.js @@ -0,0 +1,2 @@ +const foo = "test"; +//# sourceMappingURL=absolute-source-root.js.map diff --git a/test/fixtures/absolute-source-root.js.map b/test/fixtures/absolute-source-root.js.map new file mode 100644 index 0000000..4edcea9 --- /dev/null +++ b/test/fixtures/absolute-source-root.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"https://raw.githubusercontent.com/fb55/htmlparser2/4763205746cd80120b5d2b69041197a394d24ba9/src/","sources":["index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,MAAM,EAAE,KAAK,aAAa,EAAE,CAAC;AAEtC,OAAO,EACH,UAAU,EACV,iBAAiB,EACjB,SAAS,EACT,OAAO,EACP,QAAQ,EACX,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,UAAU,EAAE,KAAK,iBAAiB,EAAE,CAAC;AAE9C,aAAK,OAAO,GAAG,aAAa,GAAG,iBAAiB,CAAC;AAIjD;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,QAAQ,CAIvE;AACD;;;;;;;;;GASG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,EAAE,CAErE;AACD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC3B,EAAE,EAAE,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,SAAS,EAAE,KAAK,IAAI,EACnD,OAAO,CAAC,EAAE,OAAO,EACjB,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,GACvC,MAAM,CAGR;AAED,OAAO,EACH,OAAO,IAAI,SAAS,EACpB,KAAK,SAAS,IAAI,kBAAkB,GACvC,MAAM,gBAAgB,CAAC;AAMxB,OAAO,KAAK,WAAW,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,CAAC;AAEvB,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAEzC,OAAO,EAAE,OAAO,EAAE,CAAC;AAEnB;;;;;GAKG;AACH,wBAAgB,SAAS,CACrB,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,aAAa,GAAG,iBAAqC,GAC/D,IAAI,GAAG,IAAI,CAEb;AAED,OAAO,KAAK,QAAQ,MAAM,UAAU,CAAC;AAGrC,OAAO,EAAE,UAAU,IAAI,cAAc,EAAE,CAAC"} \ No newline at end of file diff --git a/test/loader.test.js b/test/loader.test.js index ed4e9df..2816cef 100644 --- a/test/loader.test.js +++ b/test/loader.test.js @@ -752,4 +752,17 @@ describe("source-map-loader", () => { expect(getWarnings(stats)).toMatchSnapshot("warnings"); expect(getErrors(stats)).toMatchSnapshot("errors"); }); + + it("should process absolute URL in sourceRoot", async () => { + const testId = "absolute-source-root.js"; + const compiler = getCompiler(testId); + const stats = await compile(compiler); + const codeFromBundle = getCodeFromBundle(stats, compiler); + + expect(codeFromBundle.map).toBeDefined(); + expect(normalizeMap(codeFromBundle.map)).toMatchSnapshot("map"); + expect(codeFromBundle.code).toMatchSnapshot("code"); + expect(getWarnings(stats)).toMatchSnapshot("warnings"); + expect(getErrors(stats)).toMatchSnapshot("errors"); + }); });