Fix sourcemaps for merged files

This commit is contained in:
Rob 2015-11-22 19:21:04 -08:00
Родитель 23e38e0aec
Коммит 6c64a7d131
5 изменённых файлов: 42 добавлений и 25 удалений

Просмотреть файл

@ -126,20 +126,21 @@ export class SourceMapTransformer implements IDebugTransformer {
if (this._sourceMaps) {
this._allRuntimeScriptPaths.add(event.body.scriptUrl);
const mapped = this._sourceMaps.MapToSource(event.body.scriptUrl, 0, 0);
if (mapped) {
event.body.scriptUrl = mapped.path;
}
const sources = this._sourceMaps.AllMappedSources(event.body.scriptUrl);
if (sources) {
utils.Logger.log(`SourceMaps.scriptParsed: ${event.body.scriptUrl} was just loaded and has mapped sources: ${JSON.stringify(sources)}`);
sources.forEach(sourcePath => {
// If there's a setBreakpoints request waiting on this script, go through setBreakpoints again
if (this._pendingBreakpointsByPath.has(event.body.scriptUrl)) {
utils.Logger.log(`SourceMaps.scriptParsed: ${event.body.scriptUrl} was just loaded and has pending breakpoints`);
const pendingBreakpoint = this._pendingBreakpointsByPath.get(event.body.scriptUrl);
this._pendingBreakpointsByPath.delete(event.body.scriptUrl);
if (this._pendingBreakpointsByPath.has(sourcePath)) {
utils.Logger.log(`SourceMaps.scriptParsed: Resolving pending breakpoints for ${sourcePath}`);
const pendingBreakpoint = this._pendingBreakpointsByPath.get(sourcePath);
this._pendingBreakpointsByPath.delete(sourcePath);
this.setBreakpoints(pendingBreakpoint.args, pendingBreakpoint.requestSeq)
.then(pendingBreakpoint.resolve, pendingBreakpoint.reject);
}
});
}
}
}
}

Просмотреть файл

@ -32,6 +32,11 @@ export interface ISourceMaps {
* line and column are 0 based.
*/
MapToSource(path: string, line: number, column: number): MappingResult;
/*
* Get all the sources that map to this generated file
*/
AllMappedSources(path: string): string[];
}
@ -81,6 +86,11 @@ export class SourceMaps implements ISourceMaps {
return null;
}
public AllMappedSources(pathToGenerated: string): string[] {
const map = this._findGeneratedToSourceMapping(pathToGenerated);
return map ? map.sources : null;
}
//---- private -----------------------------------------------------------------------
private _findSourceToGeneratedMapping(pathToSource: string): SourceMap {
@ -227,6 +237,13 @@ class SourceMap {
this._smc = new SourceMapConsumer(sm);
}
/*
* Return all mapped sources as absolute paths
*/
public get sources(): string[] {
return this._sources.map(sourcePath => Path.join(this._sourceRoot, sourcePath));
}
/*
* the generated file of this source map.
*/
@ -250,7 +267,7 @@ class SourceMap {
/*
* finds the nearest source location for the given location in the generated file.
*/
public originalPositionFor(line: number, column: number, bias: Bias = Bias.LEAST_UPPER_BOUND): SourceMap.MappedPosition {
public originalPositionFor(line: number, column: number, bias: Bias = Bias.GREATEST_LOWER_BOUND): SourceMap.MappedPosition {
const mp = this._smc.originalPositionFor(<any>{
line: line,
@ -269,7 +286,7 @@ class SourceMap {
/*
* finds the nearest location in the generated file for the given source location.
*/
public generatedPositionFor(src: string, line: number, column: number, bias = Bias.LEAST_UPPER_BOUND): SourceMap.Position {
public generatedPositionFor(src: string, line: number, column: number, bias = Bias.GREATEST_LOWER_BOUND): SourceMap.Position {
// make input path relative to sourceRoot
if (this._sourceRoot) {

Просмотреть файл

@ -78,21 +78,22 @@ suite('SourceMapTransformer', () => {
const args = createArgs(AUTHORED_PATH, AUTHORED_LINES);
const expected = createArgs(RUNTIME_PATH, RUNTIME_LINES, RUNTIME_COLS);
const mock = testUtils.getRegisteredSinonMock('./sourceMaps', undefined, 'SourceMaps');
const mock = testUtils.createRegisteredSinonMock('./sourceMaps', undefined, 'SourceMaps');
mock.expects('MapPathFromSource')
.once()
.withArgs(AUTHORED_PATH).returns(null);
mock.expects('MapPathFromSource')
.once()
.withArgs(AUTHORED_PATH).returns(RUNTIME_PATH);
mock.expects('AllMappedSources')
.once()
.withArgs(RUNTIME_PATH).returns([AUTHORED_PATH]);
args.lines.forEach((line, i) => {
mock.expects('MapFromSource')
.once()
.withArgs(AUTHORED_PATH, line, 0)
.returns({ path: RUNTIME_PATH, line: RUNTIME_LINES[i], column: RUNTIME_COLS[i] });
});
mock.expects('MapToSource')
.withArgs(RUNTIME_PATH, 0, 0).returns({ path: AUTHORED_PATH });
const transformer = getTransformer(true, true);
const setBreakpointsP = transformer.setBreakpoints(args, 0).then(() => {
@ -175,12 +176,6 @@ suite('SourceMapTransformer', () => {
assert.deepEqual(response, expected);
});
});
suite('scriptParsed()', () => {
test('calls MapToSource', () => {
getTransformer().scriptParsed(new testUtils.MockEvent('scriptParsed', { scriptUrl: RUNTIME_PATH }));
});
});
});
class MockSourceMaps implements ISourceMaps {
@ -216,4 +211,8 @@ class MockSourceMaps implements ISourceMaps {
const mappedLine = AUTHORED_LINES[RUNTIME_LINES.indexOf(line)];
return { path: AUTHORED_PATH, line: mappedLine, column: 0 };
}
public AllMappedSources(pathToGenerated: string): string[] {
return [AUTHORED_PATH];
}
}

Просмотреть файл

@ -55,7 +55,7 @@ export function getSinonMock(mockBase = {}): Sinon.SinonMock {
return m;
}
export function getRegisteredSinonMock(requireName: string, mockInstance = {}, name?: string, asConstructor = true): Sinon.SinonMock {
export function createRegisteredSinonMock(requireName: string, mockInstance = {}, name?: string, asConstructor = true): Sinon.SinonMock {
const mock = getSinonMock(mockInstance);
const mockContainer = {};
if (asConstructor) {

Просмотреть файл

@ -39,7 +39,7 @@ suite('WebKitDebugAdapter', () => {
mockery.registerMock('net', {});
mockery.registerMock('fs', {});
mockWebKitConnection = testUtils.getRegisteredSinonMock('./webKitConnection', new DefaultMockWebKitConnection(), 'WebKitConnection');
mockWebKitConnection = testUtils.createRegisteredSinonMock('./webKitConnection', new DefaultMockWebKitConnection(), 'WebKitConnection');
});
teardown(() => {