diff --git a/src/build/generate-contributions.ts b/src/build/generate-contributions.ts index 67b040fcc..0c10ce78d 100644 --- a/src/build/generate-contributions.ts +++ b/src/build/generate-contributions.ts @@ -357,6 +357,14 @@ const nodeBaseConfigurationAttributes: ConfigurationAttributes { + private hasPathMapping: boolean; + public static shouldWarnAboutSymlinks(config: AnyLaunchConfiguration) { return 'runtimeArgs' in config && !config.runtimeArgs?.includes('--preserve-symlinks'); } @@ -37,6 +41,7 @@ export class NodeSourcePathResolver extends SourcePathResolverBase { sourceMapOverrides: c.sourceMapPathOverrides, remoteRoot: c.remoteRoot, localRoot: c.localRoot, + pathMapping: c.pathMapping, }; } @@ -47,6 +52,7 @@ export class NodeSourcePathResolver extends SourcePathResolverBase { protected readonly logger: ILogger, ) { super(options, logger); + this.hasPathMapping = Object.keys(this.options.pathMapping).length > 0; } /** @@ -65,6 +71,30 @@ export class NodeSourcePathResolver extends SourcePathResolverBase { return this.options; } + /** + * map remote path to local path and apply the pathMapping option + * + * @param scriptPath remote path + * @returns mapped path + */ + private async rebaseRemoteWithPathMapping(scriptPath: string): Promise { + const mapped = this.rebaseRemoteToLocal(scriptPath); + + if (this.hasPathMapping) { + const mapped2 = await defaultPathMappingResolver( + mapped, + this.options.pathMapping, + this.logger, + ); + + if (mapped2 && (await this.fsUtils.exists(mapped2))) { + return mapped2; + } + } + + return mapped; + } + /** * @override */ @@ -89,7 +119,7 @@ export class NodeSourcePathResolver extends SourcePathResolverBase { const absolutePath = urlUtils.fileUrlToAbsolutePath(url); if (absolutePath) { - return this.rebaseRemoteToLocal(absolutePath); + return await this.rebaseRemoteWithPathMapping(absolutePath); } // It's possible the source might be an HTTP if using the `sourceURL` @@ -111,7 +141,7 @@ export class NodeSourcePathResolver extends SourcePathResolverBase { } const withBase = properResolve(this.options.basePath ?? '', url); - return this.rebaseRemoteToLocal(withBase); + return await this.rebaseRemoteWithPathMapping(withBase); } /** @@ -175,6 +205,6 @@ export class NodeSourcePathResolver extends SourcePathResolverBase { ); } - return this.rebaseRemoteToLocal(url) || url; + return await this.rebaseRemoteWithPathMapping(url); } } diff --git a/src/test/node/node-source-path-resolver.test.ts b/src/test/node/node-source-path-resolver.test.ts index 79782f243..7f9007ef7 100644 --- a/src/test/node/node-source-path-resolver.test.ts +++ b/src/test/node/node-source-path-resolver.test.ts @@ -20,6 +20,7 @@ describe('node source path resolver', () => { remoteRoot: null, localRoot: null, sourceMapOverrides: { 'webpack:///*': `${__dirname}/*` }, + pathMapping: {}, }; it('resolves absolute', async () => { @@ -95,6 +96,35 @@ describe('node source path resolver', () => { ); }); + it('applies pathMapping option', async () => { + const r = new NodeSourcePathResolver( + { + realPath: fsUtils.realPath, + readFile: fsUtils.readFile, + exists: async p => p === '/lib/index.js', + }, + undefined, + { + ...defaultOptions, + pathMapping: { + '/src': '/lib', + }, + }, + Logger.null, + ); + + expect(await r.urlToAbsolutePath({ url: 'file:///src/index.js' })).to.equal('/lib/index.js'); + expect(await r.urlToAbsolutePath({ url: 'file:///src/not-exist.js' })).to.equal( + '/src/not-exist.js', + ); + expect(await r.urlToAbsolutePath({ url: 'file:///src2/index.js' })).to.equal( + '/src2/index.js', + ); + expect(await r.urlToAbsolutePath({ url: 'file:///test/src/index.js' })).to.equal( + '/test/src/index.js', + ); + }); + describe('source map filtering', () => { const testTable = { 'matches paths': {