diff --git a/lib/internal/source_map/source_map_cache.js b/lib/internal/source_map/source_map_cache.js index 2813da21dfdc63..10db1edd99e15f 100644 --- a/lib/internal/source_map/source_map_cache.js +++ b/lib/internal/source_map/source_map_cache.js @@ -39,6 +39,7 @@ const kLeadingProtocol = /^\w+:\/\//; const kSourceMappingURLMagicComment = /\/[*/]#\s+sourceMappingURL=(?[^\s]+)/g; const kSourceURLMagicComment = /\/[*/]#\s+sourceURL=(?[^\s]+)/g; +const { isAbsolute } = require('path'); const { fileURLToPath, pathToFileURL, URL } = require('internal/url'); let SourceMap; @@ -251,9 +252,13 @@ function sourceMapFromDataUrl(sourceURL, url) { // If the sources are not absolute URLs after prepending of the "sourceRoot", // the sources are resolved relative to the SourceMap (like resolving script // src in a html document). +// If the sources are absolute paths, the sources are converted to absolute file URLs. function sourcesToAbsolute(baseURL, data) { data.sources = data.sources.map((source) => { source = (data.sourceRoot || '') + source; + if (isAbsolute(source)) { + return pathToFileURL(source).href; + } return new URL(source, baseURL).href; }); // The sources array is now resolved to absolute URLs, sourceRoot should diff --git a/test/fixtures/source-map/ts-node-win32.js b/test/fixtures/source-map/ts-node-win32.js new file mode 100644 index 00000000000000..22606906c9a5ba --- /dev/null +++ b/test/fixtures/source-map/ts-node-win32.js @@ -0,0 +1,10 @@ +function foo(str) { + return str; +} +foo('noop'); +// To recreate (Windows only): +// +// const filePath = require.resolve('./test/fixtures/source-map/ts-node.ts'); +// const compiled = require('ts-node').create({ transpileOnly: true }).compile(fs.readFileSync(filePath, 'utf8'), filePath); +// fs.writeFileSync('test/fixtures/source-map/ts-node-win32.js', compiled); +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRDovd29ya3NwYWNlcy9ub2RlL3Rlc3QvZml4dHVyZXMvc291cmNlLW1hcC90cy1ub2RlLnRzIiwic291cmNlcyI6WyJEOi93b3Jrc3BhY2VzL25vZGUvdGVzdC9maXh0dXJlcy9zb3VyY2UtbWFwL3RzLW5vZGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsU0FBUyxHQUFHLENBQUMsR0FBVztJQUN0QixPQUFPLEdBQUcsQ0FBQztBQUNiLENBQUM7QUFFRCxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUM7QUFFWiw4QkFBOEI7QUFDOUIsRUFBRTtBQUNGLDZFQUE2RTtBQUM3RSw0SEFBNEg7QUFDNUgsMkVBQTJFIiwic291cmNlc0NvbnRlbnQiOlsiZnVuY3Rpb24gZm9vKHN0cjogc3RyaW5nKSB7XG4gIHJldHVybiBzdHI7XG59XG5cbmZvbygnbm9vcCcpO1xuXG4vLyBUbyByZWNyZWF0ZSAoV2luZG93cyBvbmx5KTpcbi8vXG4vLyBjb25zdCBmaWxlUGF0aCA9IHJlcXVpcmUucmVzb2x2ZSgnLi90ZXN0L2ZpeHR1cmVzL3NvdXJjZS1tYXAvdHMtbm9kZS50cycpO1xuLy8gY29uc3QgY29tcGlsZWQgPSByZXF1aXJlKCd0cy1ub2RlJykuY3JlYXRlKHsgdHJhbnNwaWxlT25seTogdHJ1ZSB9KS5jb21waWxlKGZzLnJlYWRGaWxlU3luYyhmaWxlUGF0aCwgJ3V0ZjgnKSwgZmlsZVBhdGgpO1xuLy8gZnMud3JpdGVGaWxlU3luYygndGVzdC9maXh0dXJlcy9zb3VyY2UtbWFwL3RzLW5vZGUtd2luMzIuanMnLCBjb21waWxlZCk7XG4iXX0= diff --git a/test/fixtures/source-map/ts-node.ts b/test/fixtures/source-map/ts-node.ts new file mode 100644 index 00000000000000..2ff34e0f942f15 --- /dev/null +++ b/test/fixtures/source-map/ts-node.ts @@ -0,0 +1,11 @@ +function foo(str: string) { + return str; +} + +foo('noop'); + +// To recreate (Windows only): +// +// const filePath = require.resolve('./test/fixtures/source-map/ts-node.ts'); +// const compiled = require('ts-node').create({ transpileOnly: true }).compile(fs.readFileSync(filePath, 'utf8'), filePath); +// fs.writeFileSync('test/fixtures/source-map/ts-node-win32.js', compiled); diff --git a/test/parallel/test-source-map-enable.js b/test/parallel/test-source-map-enable.js index 5038aff360e518..46c25d26cfa8e7 100644 --- a/test/parallel/test-source-map-enable.js +++ b/test/parallel/test-source-map-enable.js @@ -289,6 +289,30 @@ function nextdir() { assert.match(output.stderr.toString(), /at functionC.*10:3/); } +// Properly converts Windows absolute paths to absolute URLs. +// Refs: https://github.com/nodejs/node/issues/50523 +// Refs: https://github.com/TypeStrong/ts-node/issues/1769 +{ + const coverageDirectory = nextdir(); + const output = spawnSync(process.execPath, [ + require.resolve('../fixtures/source-map/ts-node-win32.js'), + ], { env: { ...process.env, NODE_V8_COVERAGE: coverageDirectory } }); + assert.strictEqual(output.status, 0); + assert.strictEqual(output.stderr.toString(), ''); + const sourceMap = getSourceMapFromCache( + 'ts-node-win32.js', + coverageDirectory + ); + // base64 JSON should have been decoded, the D: in the sources field should + // have been taken as the drive letter on Windows, the scheme on POSIX. + assert.strictEqual( + sourceMap.data.sources[0], + common.isWindows ? + 'file:///D:/workspaces/node/test/fixtures/source-map/ts-node.ts' : + 'd:/workspaces/node/test/fixtures/source-map/ts-node.ts' + ); +} + // Stores and applies source map associated with file that throws while // being required. {