Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit e6167cf

Browse files
petebacondarwinAndrewKushnir
authored andcommitted
fix(ngcc): handle multiple original sources when flattening source-maps (#36027)
Previously the list of original segments that was searched for incoming mappings did not differentiate between different original source files. Now there is a separate array of segments to search for each of the original source files. PR Close #36027
1 parent 8768fc4 commit e6167cf

File tree

2 files changed

+70
-22
lines changed

2 files changed

+70
-22
lines changed

‎packages/compiler-cli/ngcc/src/sourcemaps/source_file.ts

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ export class SourceFile {
9090
*/
9191
private flattenMappings(): Mapping[] {
9292
const mappings = parseMappings(this.rawMap, this.sources);
93-
const originalSegments = extractOriginalSegments(mappings);
93+
const originalSegmentsBySource = extractOriginalSegments(mappings);
9494
const flattenedMappings: Mapping[] = [];
9595
for (let mappingIndex = 0; mappingIndex < mappings.length; mappingIndex++) {
9696
const aToBmapping = mappings[mappingIndex];
@@ -120,6 +120,8 @@ export class SourceFile {
120120
// For mapping [0,0] the incoming start and end are 0 and 2 (i.e. the range a, b, c)
121121
// For mapping [4,2] the incoming start and end are 2 and 5 (i.e. the range c, d, e, f)
122122
//
123+
124+
const originalSegments = originalSegmentsBySource.get(bSource) !;
123125
const incomingStart = aToBmapping.originalSegment;
124126
const incomingEndIndex = originalSegments.indexOf(incomingStart) + 1;
125127
const incomingEnd = incomingEndIndex < originalSegments.length ?
@@ -337,8 +339,26 @@ export function parseMappings(
337339
return mappings;
338340
}
339341

340-
export function extractOriginalSegments(mappings: Mapping[]): SegmentMarker[] {
341-
return mappings.map(mapping => mapping.originalSegment).sort(compareSegments);
342+
/**
343+
* Extract the segment markers from the original source files in each mapping of an array of
344+
* `mappings`.
345+
*
346+
* @param mappings The mappings whose original segments we want to extract
347+
* @returns Return a map from original source-files (referenced in the `mappings`) to arrays of
348+
* segment-markers sorted by their order in their source file.
349+
*/
350+
export function extractOriginalSegments(mappings: Mapping[]): Map<SourceFile, SegmentMarker[]> {
351+
const originalSegments = new Map<SourceFile, SegmentMarker[]>();
352+
for (const mapping of mappings) {
353+
const originalSource = mapping.originalSource;
354+
if (!originalSegments.has(originalSource)) {
355+
originalSegments.set(originalSource, []);
356+
}
357+
const segments = originalSegments.get(originalSource) !;
358+
segments.push(mapping.originalSegment);
359+
}
360+
originalSegments.forEach(segmentMarkers => segmentMarkers.sort(compareSegments));
361+
return originalSegments;
342362
}
343363

344364
export function computeLineLengths(str: string): number[] {

‎packages/compiler-cli/ngcc/test/sourcemaps/source_file_spec.ts

Lines changed: 47 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -58,12 +58,12 @@ runInEachFileSystem(() => {
5858
});
5959

6060
describe('extractOriginalSegments()', () => {
61-
it('should return an empty array for source files with no source map',
62-
() => { expect(extractOriginalSegments(parseMappings(null, []))).toEqual([]); });
61+
it('should return an empty Map for source files with no source map',
62+
() => { expect(extractOriginalSegments(parseMappings(null, []))).toEqual(new Map()); });
6363

64-
it('should be empty array for source files with no source map mappings', () => {
64+
it('should be empty Map for source files with no source map mappings', () => {
6565
const rawSourceMap: RawSourceMap = {mappings: '', names: [], sources: [], version: 3};
66-
expect(extractOriginalSegments(parseMappings(rawSourceMap, []))).toEqual([]);
66+
expect(extractOriginalSegments(parseMappings(rawSourceMap, []))).toEqual(new Map());
6767
});
6868

6969
it('should parse the segments in ascending order of original position from the raw source map',
@@ -75,12 +75,37 @@ runInEachFileSystem(() => {
7575
sources: ['a.js'],
7676
version: 3
7777
};
78-
expect(extractOriginalSegments(parseMappings(rawSourceMap, [originalSource]))).toEqual([
78+
const originalSegments =
79+
extractOriginalSegments(parseMappings(rawSourceMap, [originalSource]));
80+
expect(originalSegments.get(originalSource)).toEqual([
7981
{line: 0, column: 0},
8082
{line: 0, column: 2},
8183
{line: 0, column: 3},
8284
]);
8385
});
86+
87+
it('should create separate arrays for each original source file', () => {
88+
const sourceA = new SourceFile(_('/foo/src/a.js'), 'abcdefg', null, false, []);
89+
const sourceB = new SourceFile(_('/foo/src/b.js'), '1234567', null, false, []);
90+
const rawSourceMap: RawSourceMap = {
91+
mappings:
92+
encode([[[0, 0, 0, 0], [2, 1, 0, 3], [4, 0, 0, 2], [5, 1, 0, 5], [6, 1, 0, 2]]]),
93+
names: [],
94+
sources: ['a.js', 'b.js'],
95+
version: 3
96+
};
97+
const originalSegments =
98+
extractOriginalSegments(parseMappings(rawSourceMap, [sourceA, sourceB]));
99+
expect(originalSegments.get(sourceA)).toEqual([
100+
{line: 0, column: 0},
101+
{line: 0, column: 2},
102+
]);
103+
expect(originalSegments.get(sourceB)).toEqual([
104+
{line: 0, column: 2},
105+
{line: 0, column: 3},
106+
{line: 0, column: 5},
107+
]);
108+
});
84109
});
85110

86111
describe('findLastMappingIndexBefore', () => {
@@ -313,15 +338,18 @@ runInEachFileSystem(() => {
313338
});
314339

315340
it('should merge mappings from flattened original source files', () => {
316-
const cSource = new SourceFile(_('/foo/src/c.js'), 'bcd123e', null, false, []);
341+
const cSource = new SourceFile(_('/foo/src/c.js'), 'bcd123', null, false, []);
342+
const dSource = new SourceFile(_('/foo/src/d.js'), 'aef', null, false, []);
343+
317344
const bSourceMap: RawSourceMap = {
318-
mappings: encode([[[1, 0, 0, 0], [4, 0, 0, 3], [4, 0, 0, 6], [5, 0, 0, 7]]]),
345+
mappings: encode([[[0, 1, 0, 0], [1, 0, 0, 0], [4, 1, 0, 1]]]),
319346
names: [],
320-
sources: ['c.js'],
347+
sources: ['c.js', 'd.js'],
321348
version: 3
322349
};
323350
const bSource =
324-
new SourceFile(_('/foo/src/b.js'), 'abcdef', bSourceMap, false, [cSource]);
351+
new SourceFile(_('/foo/src/b.js'), 'abcdef', bSourceMap, false, [cSource, dSource]);
352+
325353
const aSourceMap: RawSourceMap = {
326354
mappings: encode([[[0, 0, 0, 0], [2, 0, 0, 3], [4, 0, 0, 2], [5, 0, 0, 5]]]),
327355
names: [],
@@ -333,27 +361,27 @@ runInEachFileSystem(() => {
333361

334362
expect(aSource.flattenedMappings).toEqual([
335363
{
336-
generatedSegment: {line: 0, column: 1},
337-
originalSource: cSource,
364+
generatedSegment: {line: 0, column: 0},
365+
originalSource: dSource,
338366
originalSegment: {line: 0, column: 0},
339367
name: undefined
340368
},
341369
{
342-
generatedSegment: {line: 0, column: 2},
370+
generatedSegment: {line: 0, column: 1},
343371
originalSource: cSource,
344-
originalSegment: {line: 0, column: 2},
372+
originalSegment: {line: 0, column: 0},
345373
name: undefined
346374
},
347375
{
348-
generatedSegment: {line: 0, column: 3},
376+
generatedSegment: {line: 0, column: 2},
349377
originalSource: cSource,
350-
originalSegment: {line: 0, column: 3},
378+
originalSegment: {line: 0, column: 2},
351379
name: undefined
352380
},
353381
{
354382
generatedSegment: {line: 0, column: 3},
355-
originalSource: cSource,
356-
originalSegment: {line: 0, column: 6},
383+
originalSource: dSource,
384+
originalSegment: {line: 0, column: 1},
357385
name: undefined
358386
},
359387
{
@@ -364,8 +392,8 @@ runInEachFileSystem(() => {
364392
},
365393
{
366394
generatedSegment: {line: 0, column: 5},
367-
originalSource: cSource,
368-
originalSegment: {line: 0, column: 7},
395+
originalSource: dSource,
396+
originalSegment: {line: 0, column: 2},
369397
name: undefined
370398
},
371399
]);

0 commit comments

Comments
 (0)