Skip to content

Commit 0cca6a4

Browse files
authored
feat: apply pathMapping when loading sourcemaps (#1241)
Fixes #1240
1 parent 8e87a53 commit 0cca6a4

File tree

8 files changed

+73
-1
lines changed

8 files changed

+73
-1
lines changed

src/adapter/sources.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -852,6 +852,7 @@ export class SourceContainer {
852852
contentHash?: string,
853853
): Promise<Source> {
854854
const absolutePath = await this.sourcePathResolver.urlToAbsolutePath({ url });
855+
855856
this.logger.verbose(LogTag.RuntimeSourceCreate, 'Creating source from url', {
856857
inputUrl: url,
857858
absolutePath,

src/common/sourceMaps/sourceMapFactory.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { IRootDapApi } from '../../dap/connection';
1010
import { sourceMapParseFailed } from '../../dap/errors';
1111
import { MapUsingProjection } from '../datastructure/mapUsingProjection';
1212
import { IDisposable } from '../disposable';
13+
import { ILogger, LogTag } from '../logging';
1314
import { ISourcePathResolver } from '../sourcePathResolver';
1415
import { fileUrlToAbsolutePath } from '../urlUtils';
1516
import { ISourceMapMetadata, SourceMap } from './sourceMap';
@@ -49,13 +50,16 @@ export class SourceMapFactory implements ISourceMapFactory {
4950
@inject(ISourcePathResolver) private readonly pathResolve: ISourcePathResolver,
5051
@inject(IResourceProvider) private readonly resourceProvider: IResourceProvider,
5152
@inject(IRootDapApi) protected readonly dap: Dap.Api,
53+
@inject(ILogger) private readonly logger: ILogger,
5254
) {}
5355

5456
/**
5557
* @inheritdoc
5658
*/
5759
public async load(metadata: ISourceMapMetadata): Promise<SourceMap> {
58-
const basic = await this.parseSourceMap(metadata.sourceMapUrl);
60+
const basic =
61+
(await this.parsePathMappedSourceMap(metadata.sourceMapUrl)) ||
62+
(await this.parseSourceMap(metadata.sourceMapUrl));
5963

6064
// The source-map library is destructive with its sources parsing. If the
6165
// source root is '/', it'll "helpfully" resolve a source like `../foo.ts`
@@ -80,6 +84,17 @@ export class SourceMapFactory implements ISourceMapFactory {
8084
);
8185
}
8286

87+
public async parsePathMappedSourceMap(url: string) {
88+
const localSourceMapUrl = await this.pathResolve.urlToAbsolutePath({ url });
89+
if (!localSourceMapUrl) return;
90+
91+
try {
92+
return this.parseSourceMap(localSourceMapUrl);
93+
} catch (error) {
94+
this.logger.info(LogTag.SourceMapParsing, 'Parsing path mapped source map failed.', error);
95+
}
96+
}
97+
8398
/**
8499
* @inheritdoc
85100
*/
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
allThreadsStopped : false
3+
description : Paused on breakpoint
4+
reason : breakpoint
5+
threadId : <number>
6+
}
7+
foo @ ${workspaceFolder}/web/tmp/app.ts:2:3
8+
<anonymous> @ ${workspaceFolder}/web/tmp/app.ts:5:1

src/test/breakpoints/breakpointsTest.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,42 @@ describe('breakpoints', () => {
132132
await waitForPause(p);
133133
p.assertLog();
134134
});
135+
136+
itIntegrates("source map that's path mapped", async ({ r }) => {
137+
const cwd = r.workspacePath('web/tmp');
138+
139+
after(() =>
140+
del([`${forceForwardSlashes(cwd)}/**`], {
141+
force: true /* delete outside cwd */,
142+
}),
143+
);
144+
145+
createFileTree(cwd, {
146+
'app.ts': await readfile(r.workspacePath('web/pathMapped/app.ts')),
147+
'app.js': (await readfile(r.workspacePath('web/pathMapped/app.js'))).replace(
148+
'app.js.map',
149+
'mappedPath/app.js.map',
150+
),
151+
'index.html': await readfile(r.workspacePath('web/pathMapped/index.html')),
152+
mappedDir: {
153+
'app.js.map': await readfile(r.workspacePath('web/pathMapped/app.js.map')),
154+
},
155+
});
156+
157+
const p = await r.launchUrl('tmp/index.html', {
158+
pathMapping: {
159+
'/mappedPath/': '${workspaceFolder}/web/tmp/mappedDir/',
160+
},
161+
});
162+
const source: Dap.Source = {
163+
path: p.workspacePath('web/tmp/app.ts'),
164+
};
165+
166+
await p.dap.setBreakpoints({ source, breakpoints: [{ line: 2 }] });
167+
p.load();
168+
await waitForPause(p);
169+
p.assertLog();
170+
});
135171
});
136172

137173
describe('launched', () => {

testWorkspace/web/pathMapped/app.js

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

testWorkspace/web/pathMapped/app.js.map

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

testWorkspace/web/pathMapped/app.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
function foo() {
2+
void(0); // break here
3+
}
4+
5+
foo();
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<script src="app.js"></script>

0 commit comments

Comments
 (0)