diff --git a/lib/internal/source_map/source_map_cache.js b/lib/internal/source_map/source_map_cache.js index a4a95ad0ae49c3..95b09090c4739c 100644 --- a/lib/internal/source_map/source_map_cache.js +++ b/lib/internal/source_map/source_map_cache.js @@ -247,7 +247,10 @@ function dataFromUrl(sourceURL, sourceMappingURL) { } } - const mapURL = new URL(sourceMappingURL, sourceURL).href; + const mapURL = URLParse(sourceMappingURL, sourceURL); + if (mapURL === null) { + return null; + } return sourceMapFromFile(mapURL); } @@ -276,7 +279,7 @@ function lineLengths(content) { /** * Read source map from file. - * @param {string} mapURL - file url of the source map + * @param {URL} mapURL - file url of the source map * @returns {object} deserialized source map JSON object */ function sourceMapFromFile(mapURL) { diff --git a/test/parallel/test-source-map-invalid-url.js b/test/parallel/test-source-map-invalid-url.js new file mode 100644 index 00000000000000..a968040b4f1e3d --- /dev/null +++ b/test/parallel/test-source-map-invalid-url.js @@ -0,0 +1,56 @@ +// Flags: --enable-source-maps +'use strict'; + +const common = require('../common'); +const assert = require('node:assert'); +const childProcess = require('node:child_process'); + +// TODO(legendecas): c8 will complain if non-file-scheme is used in source maps. +// https://github.com/bcoe/c8/blob/ee2f1cfc5584d41bb2d51b788d0953dab0c798f8/lib/report.js#L517 +if (process.env.NODE_V8_COVERAGE) { + console.log('Spawning with coverage disabled.'); + const { status } = childProcess.spawnSync( + process.execPath, + [__filename], + { + stdio: 'inherit', + env: { + ...process.env, + NODE_V8_COVERAGE: '', + }, + }, + ); + assert.strictEqual(status, 0); + return; +} + +const sources = [ + ` + //# sourceMappingURL=unknown-protocol://invalid/url + //# sourceURL=unknown-protocol://invalid/url + `, + ` + //# sourceMappingURL=file://invalid:/file/url + //# sourceURL=file://invalid:/file/url + `, + ` + //# sourceMappingURL=invalid-url + //# sourceURL=invalid-url + `, +]; + +sources.forEach(test); + +function test(source) { + // Eval should tolerate invalid source map url + eval(source); + + const base64 = Buffer.from(source).toString('base64url'); + + // Dynamic import should tolerate invalid source map url + import(`data:text/javascript;base64,${base64}`) + .then(common.mustCall()); +} + +// eslint-disable-next-line @stylistic/js/spaced-comment +//# sourceMappingURL=invalid-url