perf(ngcc): store the position of SegmentMarkers to avoid unnecessary computation (#36027)
Previously, calculations related to the position of and difference between SegmentMarkers required extensive computation based around the line, line start positions and columns of each segment. PR Close #36027
This commit is contained in:
parent
47025e07ce
commit
772bb5e742
|
@ -16,6 +16,7 @@
|
|||
export interface SegmentMarker {
|
||||
readonly line: number;
|
||||
readonly column: number;
|
||||
readonly position: number;
|
||||
next: SegmentMarker|undefined;
|
||||
}
|
||||
|
||||
|
@ -26,20 +27,7 @@ export interface SegmentMarker {
|
|||
* and zero if they are at the same position.
|
||||
*/
|
||||
export function compareSegments(a: SegmentMarker, b: SegmentMarker): number {
|
||||
return a.line === b.line ? a.column - b.column : a.line - b.line;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the difference between two segment markers in a source file.
|
||||
*
|
||||
* @param startOfLinePositions the position of the start of each line of content of the source file
|
||||
* where we are computing the difference
|
||||
* @param a the start marker
|
||||
* @param b the end marker
|
||||
* @returns the number of characters between the two segments `a` and `b`
|
||||
*/
|
||||
export function segmentDiff(startOfLinePositions: number[], a: SegmentMarker, b: SegmentMarker) {
|
||||
return startOfLinePositions[b.line] - startOfLinePositions[a.line] + b.column - a.column;
|
||||
return a.position - b.position;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -51,19 +39,19 @@ export function segmentDiff(startOfLinePositions: number[], a: SegmentMarker, b:
|
|||
* @param offset the number of character to offset by.
|
||||
*/
|
||||
export function offsetSegment(
|
||||
startOfLinePositions: number[], marker: SegmentMarker, offset: number) {
|
||||
startOfLinePositions: number[], marker: SegmentMarker, offset: number): SegmentMarker {
|
||||
if (offset === 0) {
|
||||
return marker;
|
||||
}
|
||||
|
||||
let line = marker.line;
|
||||
const newPos = startOfLinePositions[line] + marker.column + offset;
|
||||
while (line < startOfLinePositions.length - 1 && startOfLinePositions[line + 1] <= newPos) {
|
||||
const position = marker.position + offset;
|
||||
while (line < startOfLinePositions.length - 1 && startOfLinePositions[line + 1] <= position) {
|
||||
line++;
|
||||
}
|
||||
while (line > 0 && startOfLinePositions[line] > newPos) {
|
||||
while (line > 0 && startOfLinePositions[line] > position) {
|
||||
line--;
|
||||
}
|
||||
const column = newPos - startOfLinePositions[line];
|
||||
return {line, column, next: undefined};
|
||||
const column = position - startOfLinePositions[line];
|
||||
return {line, column, position, next: undefined};
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ import {removeComments, removeMapFileComments} from 'convert-source-map';
|
|||
import {SourceMapMappings, SourceMapSegment, decode, encode} from 'sourcemap-codec';
|
||||
import {AbsoluteFsPath, dirname, relative} from '../../../src/ngtsc/file_system';
|
||||
import {RawSourceMap} from './raw_source_map';
|
||||
import {SegmentMarker, compareSegments, offsetSegment, segmentDiff} from './segment_marker';
|
||||
import {SegmentMarker, compareSegments, offsetSegment} from './segment_marker';
|
||||
|
||||
export function removeSourceMapComments(contents: string): string {
|
||||
return removeMapFileComments(removeComments(contents)).replace(/\n\n$/, '\n');
|
||||
|
@ -89,7 +89,7 @@ export class SourceFile {
|
|||
* source files with no transitive source maps.
|
||||
*/
|
||||
private flattenMappings(): Mapping[] {
|
||||
const mappings = parseMappings(this.rawMap, this.sources);
|
||||
const mappings = parseMappings(this.rawMap, this.sources, this.startOfLinePositions);
|
||||
ensureOriginalSegmentLinks(mappings);
|
||||
const flattenedMappings: Mapping[] = [];
|
||||
for (let mappingIndex = 0; mappingIndex < mappings.length; mappingIndex++) {
|
||||
|
@ -277,8 +277,7 @@ export function mergeMappings(generatedSource: SourceFile, ab: Mapping, bc: Mapp
|
|||
// segment-marker" of B->C (4*): `1 - 4 = -3`.
|
||||
// Since it is negative we must increment the "generated segment-marker" with `3` to give [3,2].
|
||||
|
||||
const diff =
|
||||
segmentDiff(ab.originalSource.startOfLinePositions, ab.originalSegment, bc.generatedSegment);
|
||||
const diff = compareSegments(bc.generatedSegment, ab.originalSegment);
|
||||
if (diff > 0) {
|
||||
return {
|
||||
name,
|
||||
|
@ -303,7 +302,8 @@ export function mergeMappings(generatedSource: SourceFile, ab: Mapping, bc: Mapp
|
|||
* in the `sources` parameter.
|
||||
*/
|
||||
export function parseMappings(
|
||||
rawMap: RawSourceMap | null, sources: (SourceFile | null)[]): Mapping[] {
|
||||
rawMap: RawSourceMap | null, sources: (SourceFile | null)[],
|
||||
generatedSourceStartOfLinePositions: number[]): Mapping[] {
|
||||
if (rawMap === null) {
|
||||
return [];
|
||||
}
|
||||
|
@ -330,11 +330,13 @@ export function parseMappings(
|
|||
const generatedSegment: SegmentMarker = {
|
||||
line: generatedLine,
|
||||
column: generatedColumn,
|
||||
position: generatedSourceStartOfLinePositions[generatedLine] + generatedColumn,
|
||||
next: undefined,
|
||||
};
|
||||
const originalSegment: SegmentMarker = {
|
||||
line,
|
||||
column,
|
||||
position: originalSource.startOfLinePositions[line] + column,
|
||||
next: undefined,
|
||||
};
|
||||
mappings.push({name, generatedSegment, originalSegment, originalSource});
|
||||
|
|
|
@ -5,54 +5,65 @@
|
|||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
import {compareSegments, offsetSegment, segmentDiff} from '../../src/sourcemaps/segment_marker';
|
||||
import {compareSegments, offsetSegment} from '../../src/sourcemaps/segment_marker';
|
||||
import {computeStartOfLinePositions} from '../../src/sourcemaps/source_file';
|
||||
|
||||
describe('SegmentMarker utils', () => {
|
||||
describe('compareSegments()', () => {
|
||||
it('should return 0 if the segments are the same', () => {
|
||||
expect(compareSegments(
|
||||
{line: 0, column: 0, next: undefined}, {line: 0, column: 0, next: undefined}))
|
||||
{line: 0, column: 0, position: 0, next: undefined},
|
||||
{line: 0, column: 0, position: 0, next: undefined}))
|
||||
.toEqual(0);
|
||||
expect(compareSegments(
|
||||
{line: 123, column: 0, next: undefined}, {line: 123, column: 0, next: undefined}))
|
||||
{line: 123, column: 0, position: 200, next: undefined},
|
||||
{line: 123, column: 0, position: 200, next: undefined}))
|
||||
.toEqual(0);
|
||||
expect(compareSegments(
|
||||
{line: 0, column: 45, next: undefined}, {line: 0, column: 45, next: undefined}))
|
||||
{line: 0, column: 45, position: 45, next: undefined},
|
||||
{line: 0, column: 45, position: 45, next: undefined}))
|
||||
.toEqual(0);
|
||||
expect(
|
||||
compareSegments(
|
||||
{line: 123, column: 45, next: undefined}, {line: 123, column: 45, next: undefined}))
|
||||
expect(compareSegments(
|
||||
{line: 123, column: 45, position: 245, next: undefined},
|
||||
{line: 123, column: 45, position: 245, next: undefined}))
|
||||
.toEqual(0);
|
||||
});
|
||||
|
||||
it('should return a negative number if the first segment is before the second segment', () => {
|
||||
expect(compareSegments(
|
||||
{line: 0, column: 0, next: undefined}, {line: 0, column: 45, next: undefined}))
|
||||
{line: 0, column: 0, position: 0, next: undefined},
|
||||
{line: 0, column: 45, position: 45, next: undefined}))
|
||||
.toBeLessThan(0);
|
||||
expect(compareSegments(
|
||||
{line: 123, column: 0, next: undefined}, {line: 123, column: 45, next: undefined}))
|
||||
{line: 123, column: 0, position: 200, next: undefined},
|
||||
{line: 123, column: 45, position: 245, next: undefined}))
|
||||
.toBeLessThan(0);
|
||||
expect(compareSegments(
|
||||
{line: 13, column: 45, next: undefined}, {line: 123, column: 45, next: undefined}))
|
||||
{line: 13, column: 45, position: 75, next: undefined},
|
||||
{line: 123, column: 45, position: 245, next: undefined}))
|
||||
.toBeLessThan(0);
|
||||
expect(compareSegments(
|
||||
{line: 13, column: 45, next: undefined}, {line: 123, column: 9, next: undefined}))
|
||||
{line: 13, column: 45, position: 75, next: undefined},
|
||||
{line: 123, column: 9, position: 209, next: undefined}))
|
||||
.toBeLessThan(0);
|
||||
});
|
||||
|
||||
it('should return a positive number if the first segment is after the second segment', () => {
|
||||
expect(compareSegments(
|
||||
{line: 0, column: 45, next: undefined}, {line: 0, column: 0, next: undefined}))
|
||||
{line: 0, column: 45, position: 45, next: undefined},
|
||||
{line: 0, column: 0, position: 0, next: undefined}))
|
||||
.toBeGreaterThan(0);
|
||||
expect(compareSegments(
|
||||
{line: 123, column: 45, next: undefined}, {line: 123, column: 0, next: undefined}))
|
||||
{line: 123, column: 45, position: 245, next: undefined},
|
||||
{line: 123, column: 0, position: 200, next: undefined}))
|
||||
.toBeGreaterThan(0);
|
||||
expect(compareSegments(
|
||||
{line: 123, column: 45, next: undefined}, {line: 13, column: 45, next: undefined}))
|
||||
{line: 123, column: 45, position: 245, next: undefined},
|
||||
{line: 13, column: 45, position: 75, next: undefined}))
|
||||
.toBeGreaterThan(0);
|
||||
expect(compareSegments(
|
||||
{line: 123, column: 9, next: undefined}, {line: 13, column: 45, next: undefined}))
|
||||
{line: 123, column: 9, position: 209, next: undefined},
|
||||
{line: 13, column: 45, position: 75, next: undefined}))
|
||||
.toBeGreaterThan(0);
|
||||
});
|
||||
});
|
||||
|
@ -61,38 +72,38 @@ describe('SegmentMarker utils', () => {
|
|||
it('should return an identical marker if offset is 0', () => {
|
||||
const startOfLinePositions =
|
||||
computeStartOfLinePositions('012345\n0123456789\r\n012*4567\n0123456');
|
||||
const marker = {line: 2, column: 3, next: undefined};
|
||||
const marker = {line: 2, column: 3, position: 20, next: undefined};
|
||||
expect(offsetSegment(startOfLinePositions, marker, 0)).toBe(marker);
|
||||
});
|
||||
|
||||
it('should return a new marker offset by the given chars', () => {
|
||||
const startOfLinePositions =
|
||||
computeStartOfLinePositions('012345\n0123456789\r\n012*4567\n0123456');
|
||||
const marker = {line: 2, column: 3, next: undefined};
|
||||
const marker = {line: 2, column: 3, position: 21, next: undefined};
|
||||
expect(offsetSegment(startOfLinePositions, marker, 1))
|
||||
.toEqual({line: 2, column: 4, next: undefined});
|
||||
.toEqual({line: 2, column: 4, position: 22, next: undefined});
|
||||
expect(offsetSegment(startOfLinePositions, marker, 2))
|
||||
.toEqual({line: 2, column: 5, next: undefined});
|
||||
.toEqual({line: 2, column: 5, position: 23, next: undefined});
|
||||
expect(offsetSegment(startOfLinePositions, marker, 4))
|
||||
.toEqual({line: 2, column: 7, next: undefined});
|
||||
.toEqual({line: 2, column: 7, position: 25, next: undefined});
|
||||
expect(offsetSegment(startOfLinePositions, marker, 6))
|
||||
.toEqual({line: 3, column: 0, next: undefined});
|
||||
.toEqual({line: 3, column: 0, position: 27, next: undefined});
|
||||
expect(offsetSegment(startOfLinePositions, marker, 8))
|
||||
.toEqual({line: 3, column: 2, next: undefined});
|
||||
.toEqual({line: 3, column: 2, position: 29, next: undefined});
|
||||
expect(offsetSegment(startOfLinePositions, marker, 20))
|
||||
.toEqual({line: 3, column: 14, next: undefined});
|
||||
.toEqual({line: 3, column: 14, position: 41, next: undefined});
|
||||
expect(offsetSegment(startOfLinePositions, marker, -1))
|
||||
.toEqual({line: 2, column: 2, next: undefined});
|
||||
.toEqual({line: 2, column: 2, position: 20, next: undefined});
|
||||
expect(offsetSegment(startOfLinePositions, marker, -2))
|
||||
.toEqual({line: 2, column: 1, next: undefined});
|
||||
.toEqual({line: 2, column: 1, position: 19, next: undefined});
|
||||
expect(offsetSegment(startOfLinePositions, marker, -3))
|
||||
.toEqual({line: 2, column: 0, next: undefined});
|
||||
.toEqual({line: 2, column: 0, position: 18, next: undefined});
|
||||
expect(offsetSegment(startOfLinePositions, marker, -4))
|
||||
.toEqual({line: 1, column: 10, next: undefined});
|
||||
.toEqual({line: 1, column: 10, position: 17, next: undefined});
|
||||
expect(offsetSegment(startOfLinePositions, marker, -6))
|
||||
.toEqual({line: 1, column: 8, next: undefined});
|
||||
.toEqual({line: 1, column: 8, position: 15, next: undefined});
|
||||
expect(offsetSegment(startOfLinePositions, marker, -16))
|
||||
.toEqual({line: 0, column: 5, next: undefined});
|
||||
.toEqual({line: 0, column: 5, position: 5, next: undefined});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -21,13 +21,13 @@ runInEachFileSystem(() => {
|
|||
|
||||
describe('parseMappings()', () => {
|
||||
it('should be an empty array for source files with no source map', () => {
|
||||
const mappings = parseMappings(null, []);
|
||||
const mappings = parseMappings(null, [], []);
|
||||
expect(mappings).toEqual([]);
|
||||
});
|
||||
|
||||
it('should be empty array for source files with no source map mappings', () => {
|
||||
const rawSourceMap: RawSourceMap = {mappings: '', names: [], sources: [], version: 3};
|
||||
const mappings = parseMappings(rawSourceMap, []);
|
||||
const mappings = parseMappings(rawSourceMap, [], []);
|
||||
expect(mappings).toEqual([]);
|
||||
});
|
||||
|
||||
|
@ -39,18 +39,18 @@ runInEachFileSystem(() => {
|
|||
version: 3
|
||||
};
|
||||
const originalSource = new SourceFile(_('/foo/src/a.js'), 'abcdefg', null, false, []);
|
||||
const mappings = parseMappings(rawSourceMap, [originalSource]);
|
||||
const mappings = parseMappings(rawSourceMap, [originalSource], [0, 8]);
|
||||
expect(mappings).toEqual([
|
||||
{
|
||||
generatedSegment: {line: 0, column: 0, next: undefined},
|
||||
generatedSegment: {line: 0, column: 0, position: 0, next: undefined},
|
||||
originalSource,
|
||||
originalSegment: {line: 0, column: 0, next: undefined},
|
||||
originalSegment: {line: 0, column: 0, position: 0, next: undefined},
|
||||
name: undefined
|
||||
},
|
||||
{
|
||||
generatedSegment: {line: 0, column: 6, next: undefined},
|
||||
generatedSegment: {line: 0, column: 6, position: 6, next: undefined},
|
||||
originalSource,
|
||||
originalSegment: {line: 0, column: 3, next: undefined},
|
||||
originalSegment: {line: 0, column: 3, position: 3, next: undefined},
|
||||
name: undefined
|
||||
},
|
||||
]);
|
||||
|
@ -58,12 +58,13 @@ runInEachFileSystem(() => {
|
|||
});
|
||||
|
||||
describe('extractOriginalSegments()', () => {
|
||||
it('should return an empty Map for source files with no source map',
|
||||
() => { expect(extractOriginalSegments(parseMappings(null, []))).toEqual(new Map()); });
|
||||
it('should return an empty Map for source files with no source map', () => {
|
||||
expect(extractOriginalSegments(parseMappings(null, [], []))).toEqual(new Map());
|
||||
});
|
||||
|
||||
it('should be empty Map for source files with no source map mappings', () => {
|
||||
const rawSourceMap: RawSourceMap = {mappings: '', names: [], sources: [], version: 3};
|
||||
expect(extractOriginalSegments(parseMappings(rawSourceMap, []))).toEqual(new Map());
|
||||
expect(extractOriginalSegments(parseMappings(rawSourceMap, [], []))).toEqual(new Map());
|
||||
});
|
||||
|
||||
it('should parse the segments in ascending order of original position from the raw source map',
|
||||
|
@ -76,11 +77,11 @@ runInEachFileSystem(() => {
|
|||
version: 3
|
||||
};
|
||||
const originalSegments =
|
||||
extractOriginalSegments(parseMappings(rawSourceMap, [originalSource]));
|
||||
extractOriginalSegments(parseMappings(rawSourceMap, [originalSource], [0, 8]));
|
||||
expect(originalSegments.get(originalSource)).toEqual([
|
||||
{line: 0, column: 0, next: undefined},
|
||||
{line: 0, column: 2, next: undefined},
|
||||
{line: 0, column: 3, next: undefined},
|
||||
{line: 0, column: 0, position: 0, next: undefined},
|
||||
{line: 0, column: 2, position: 2, next: undefined},
|
||||
{line: 0, column: 3, position: 3, next: undefined},
|
||||
]);
|
||||
});
|
||||
|
||||
|
@ -95,15 +96,15 @@ runInEachFileSystem(() => {
|
|||
version: 3
|
||||
};
|
||||
const originalSegments =
|
||||
extractOriginalSegments(parseMappings(rawSourceMap, [sourceA, sourceB]));
|
||||
extractOriginalSegments(parseMappings(rawSourceMap, [sourceA, sourceB], [0, 8]));
|
||||
expect(originalSegments.get(sourceA)).toEqual([
|
||||
{line: 0, column: 0, next: undefined},
|
||||
{line: 0, column: 2, next: undefined},
|
||||
{line: 0, column: 0, position: 0, next: undefined},
|
||||
{line: 0, column: 2, position: 2, next: undefined},
|
||||
]);
|
||||
expect(originalSegments.get(sourceB)).toEqual([
|
||||
{line: 0, column: 2, next: undefined},
|
||||
{line: 0, column: 3, next: undefined},
|
||||
{line: 0, column: 5, next: undefined},
|
||||
{line: 0, column: 2, position: 2, next: undefined},
|
||||
{line: 0, column: 3, position: 3, next: undefined},
|
||||
{line: 0, column: 5, position: 5, next: undefined},
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
@ -111,59 +112,59 @@ runInEachFileSystem(() => {
|
|||
describe('findLastMappingIndexBefore', () => {
|
||||
it('should find the highest mapping index that has a segment marker below the given one if there is not an exact match',
|
||||
() => {
|
||||
const marker5: SegmentMarker = {line: 0, column: 50, next: undefined};
|
||||
const marker4: SegmentMarker = {line: 0, column: 40, next: marker5};
|
||||
const marker3: SegmentMarker = {line: 0, column: 30, next: marker4};
|
||||
const marker2: SegmentMarker = {line: 0, column: 20, next: marker3};
|
||||
const marker1: SegmentMarker = {line: 0, column: 10, next: marker2};
|
||||
const marker5: SegmentMarker = {line: 0, column: 50, position: 50, next: undefined};
|
||||
const marker4: SegmentMarker = {line: 0, column: 40, position: 40, next: marker5};
|
||||
const marker3: SegmentMarker = {line: 0, column: 30, position: 30, next: marker4};
|
||||
const marker2: SegmentMarker = {line: 0, column: 20, position: 20, next: marker3};
|
||||
const marker1: SegmentMarker = {line: 0, column: 10, position: 10, next: marker2};
|
||||
const mappings: Mapping[] = [marker1, marker2, marker3, marker4, marker5].map(
|
||||
marker => ({ generatedSegment: marker } as Mapping));
|
||||
|
||||
const marker: SegmentMarker = {line: 0, column: 35, next: undefined};
|
||||
const marker: SegmentMarker = {line: 0, column: 35, position: 35, next: undefined};
|
||||
const index = findLastMappingIndexBefore(mappings, marker, /* exclusive */ false, 0);
|
||||
expect(index).toEqual(2);
|
||||
});
|
||||
|
||||
it('should find the highest mapping index that has a segment marker (when there are duplicates) below the given one if there is not an exact match',
|
||||
() => {
|
||||
const marker5: SegmentMarker = {line: 0, column: 50, next: undefined};
|
||||
const marker4: SegmentMarker = {line: 0, column: 30, next: marker5};
|
||||
const marker3: SegmentMarker = {line: 0, column: 30, next: marker4};
|
||||
const marker2: SegmentMarker = {line: 0, column: 20, next: marker3};
|
||||
const marker1: SegmentMarker = {line: 0, column: 10, next: marker2};
|
||||
const marker5: SegmentMarker = {line: 0, column: 50, position: 50, next: undefined};
|
||||
const marker4: SegmentMarker = {line: 0, column: 30, position: 30, next: marker5};
|
||||
const marker3: SegmentMarker = {line: 0, column: 30, position: 30, next: marker4};
|
||||
const marker2: SegmentMarker = {line: 0, column: 20, position: 20, next: marker3};
|
||||
const marker1: SegmentMarker = {line: 0, column: 10, position: 10, next: marker2};
|
||||
const mappings: Mapping[] = [marker1, marker2, marker3, marker4, marker5].map(
|
||||
marker => ({ generatedSegment: marker } as Mapping));
|
||||
|
||||
const marker: SegmentMarker = {line: 0, column: 35, next: undefined};
|
||||
const marker: SegmentMarker = {line: 0, column: 35, position: 35, next: undefined};
|
||||
const index = findLastMappingIndexBefore(mappings, marker, /* exclusive */ false, 0);
|
||||
expect(index).toEqual(3);
|
||||
});
|
||||
|
||||
it('should find the last mapping if the segment marker is higher than all of them', () => {
|
||||
const marker5: SegmentMarker = {line: 0, column: 50, next: undefined};
|
||||
const marker4: SegmentMarker = {line: 0, column: 40, next: marker5};
|
||||
const marker3: SegmentMarker = {line: 0, column: 30, next: marker4};
|
||||
const marker2: SegmentMarker = {line: 0, column: 20, next: marker3};
|
||||
const marker1: SegmentMarker = {line: 0, column: 10, next: marker2};
|
||||
const marker5: SegmentMarker = {line: 0, column: 50, position: 50, next: undefined};
|
||||
const marker4: SegmentMarker = {line: 0, column: 40, position: 40, next: marker5};
|
||||
const marker3: SegmentMarker = {line: 0, column: 30, position: 30, next: marker4};
|
||||
const marker2: SegmentMarker = {line: 0, column: 20, position: 20, next: marker3};
|
||||
const marker1: SegmentMarker = {line: 0, column: 10, position: 10, next: marker2};
|
||||
const mappings: Mapping[] = [marker1, marker2, marker3, marker4, marker5].map(
|
||||
marker => ({ generatedSegment: marker } as Mapping));
|
||||
|
||||
const marker: SegmentMarker = {line: 0, column: 60, next: undefined};
|
||||
const marker: SegmentMarker = {line: 0, column: 60, position: 60, next: undefined};
|
||||
|
||||
const index = findLastMappingIndexBefore(mappings, marker, /* exclusive */ false, 0);
|
||||
expect(index).toEqual(4);
|
||||
});
|
||||
|
||||
it('should return -1 if the segment marker is lower than all of them', () => {
|
||||
const marker5: SegmentMarker = {line: 0, column: 50, next: undefined};
|
||||
const marker4: SegmentMarker = {line: 0, column: 40, next: marker5};
|
||||
const marker3: SegmentMarker = {line: 0, column: 30, next: marker4};
|
||||
const marker2: SegmentMarker = {line: 0, column: 20, next: marker3};
|
||||
const marker1: SegmentMarker = {line: 0, column: 10, next: marker2};
|
||||
const marker5: SegmentMarker = {line: 0, column: 50, position: 50, next: undefined};
|
||||
const marker4: SegmentMarker = {line: 0, column: 40, position: 40, next: marker5};
|
||||
const marker3: SegmentMarker = {line: 0, column: 30, position: 30, next: marker4};
|
||||
const marker2: SegmentMarker = {line: 0, column: 20, position: 20, next: marker3};
|
||||
const marker1: SegmentMarker = {line: 0, column: 10, position: 10, next: marker2};
|
||||
const mappings: Mapping[] = [marker1, marker2, marker3, marker4, marker5].map(
|
||||
marker => ({ generatedSegment: marker } as Mapping));
|
||||
|
||||
const marker: SegmentMarker = {line: 0, column: 5, next: undefined};
|
||||
const marker: SegmentMarker = {line: 0, column: 5, position: 5, next: undefined};
|
||||
|
||||
const index = findLastMappingIndexBefore(mappings, marker, /* exclusive */ false, 0);
|
||||
expect(index).toEqual(-1);
|
||||
|
@ -172,11 +173,11 @@ runInEachFileSystem(() => {
|
|||
describe('[exact match inclusive]', () => {
|
||||
it('should find the matching segment marker mapping index if there is only one of them',
|
||||
() => {
|
||||
const marker5: SegmentMarker = {line: 0, column: 50, next: undefined};
|
||||
const marker4: SegmentMarker = {line: 0, column: 40, next: marker5};
|
||||
const marker3: SegmentMarker = {line: 0, column: 30, next: marker4};
|
||||
const marker2: SegmentMarker = {line: 0, column: 20, next: marker3};
|
||||
const marker1: SegmentMarker = {line: 0, column: 10, next: marker2};
|
||||
const marker5: SegmentMarker = {line: 0, column: 50, position: 50, next: undefined};
|
||||
const marker4: SegmentMarker = {line: 0, column: 40, position: 40, next: marker5};
|
||||
const marker3: SegmentMarker = {line: 0, column: 30, position: 30, next: marker4};
|
||||
const marker2: SegmentMarker = {line: 0, column: 20, position: 20, next: marker3};
|
||||
const marker1: SegmentMarker = {line: 0, column: 10, position: 10, next: marker2};
|
||||
|
||||
const mappings: Mapping[] = [marker1, marker2, marker3, marker4, marker5].map(
|
||||
marker => ({ generatedSegment: marker } as Mapping));
|
||||
|
@ -186,11 +187,11 @@ runInEachFileSystem(() => {
|
|||
|
||||
it('should find the highest matching segment marker mapping index if there is more than one of them',
|
||||
() => {
|
||||
const marker5: SegmentMarker = {line: 0, column: 50, next: undefined};
|
||||
const marker4: SegmentMarker = {line: 0, column: 30, next: marker5};
|
||||
const marker3: SegmentMarker = {line: 0, column: 30, next: marker4};
|
||||
const marker2: SegmentMarker = {line: 0, column: 20, next: marker3};
|
||||
const marker1: SegmentMarker = {line: 0, column: 10, next: marker2};
|
||||
const marker5: SegmentMarker = {line: 0, column: 50, position: 50, next: undefined};
|
||||
const marker4: SegmentMarker = {line: 0, column: 30, position: 30, next: marker5};
|
||||
const marker3: SegmentMarker = {line: 0, column: 30, position: 30, next: marker4};
|
||||
const marker2: SegmentMarker = {line: 0, column: 20, position: 20, next: marker3};
|
||||
const marker1: SegmentMarker = {line: 0, column: 10, position: 10, next: marker2};
|
||||
|
||||
const mappings: Mapping[] = [marker1, marker2, marker3, marker4, marker5].map(
|
||||
marker => ({ generatedSegment: marker } as Mapping));
|
||||
|
@ -201,11 +202,11 @@ runInEachFileSystem(() => {
|
|||
|
||||
describe('[exact match exclusive]', () => {
|
||||
it('should find the preceding mapping index if there is a matching segment marker', () => {
|
||||
const marker5: SegmentMarker = {line: 0, column: 50, next: undefined};
|
||||
const marker4: SegmentMarker = {line: 0, column: 40, next: marker5};
|
||||
const marker3: SegmentMarker = {line: 0, column: 30, next: marker4};
|
||||
const marker2: SegmentMarker = {line: 0, column: 20, next: marker3};
|
||||
const marker1: SegmentMarker = {line: 0, column: 10, next: marker2};
|
||||
const marker5: SegmentMarker = {line: 0, column: 50, position: 50, next: undefined};
|
||||
const marker4: SegmentMarker = {line: 0, column: 40, position: 40, next: marker5};
|
||||
const marker3: SegmentMarker = {line: 0, column: 30, position: 30, next: marker4};
|
||||
const marker2: SegmentMarker = {line: 0, column: 20, position: 20, next: marker3};
|
||||
const marker1: SegmentMarker = {line: 0, column: 10, position: 10, next: marker2};
|
||||
|
||||
const mappings: Mapping[] = [marker1, marker2, marker3, marker4, marker5].map(
|
||||
marker => ({ generatedSegment: marker } as Mapping));
|
||||
|
@ -215,11 +216,11 @@ runInEachFileSystem(() => {
|
|||
|
||||
it('should find the highest preceding mapping index if there is more than one matching segment marker',
|
||||
() => {
|
||||
const marker5: SegmentMarker = {line: 0, column: 50, next: undefined};
|
||||
const marker4: SegmentMarker = {line: 0, column: 30, next: marker5};
|
||||
const marker3: SegmentMarker = {line: 0, column: 30, next: marker4};
|
||||
const marker2: SegmentMarker = {line: 0, column: 20, next: marker3};
|
||||
const marker1: SegmentMarker = {line: 0, column: 10, next: marker2};
|
||||
const marker5: SegmentMarker = {line: 0, column: 50, position: 50, next: undefined};
|
||||
const marker4: SegmentMarker = {line: 0, column: 30, position: 30, next: marker5};
|
||||
const marker3: SegmentMarker = {line: 0, column: 30, position: 30, next: marker4};
|
||||
const marker2: SegmentMarker = {line: 0, column: 20, position: 20, next: marker3};
|
||||
const marker1: SegmentMarker = {line: 0, column: 10, position: 10, next: marker2};
|
||||
|
||||
const mappings: Mapping[] = [marker1, marker2, marker3, marker4, marker5].map(
|
||||
marker => ({ generatedSegment: marker } as Mapping));
|
||||
|
@ -231,59 +232,59 @@ runInEachFileSystem(() => {
|
|||
describe('[with lowerIndex hint', () => {
|
||||
it('should find the highest mapping index above the lowerIndex hint that has a segment marker below the given one if there is not an exact match',
|
||||
() => {
|
||||
const marker5: SegmentMarker = {line: 0, column: 50, next: undefined};
|
||||
const marker4: SegmentMarker = {line: 0, column: 40, next: marker5};
|
||||
const marker3: SegmentMarker = {line: 0, column: 30, next: marker4};
|
||||
const marker2: SegmentMarker = {line: 0, column: 20, next: marker3};
|
||||
const marker1: SegmentMarker = {line: 0, column: 10, next: marker2};
|
||||
const marker5: SegmentMarker = {line: 0, column: 50, position: 50, next: undefined};
|
||||
const marker4: SegmentMarker = {line: 0, column: 40, position: 40, next: marker5};
|
||||
const marker3: SegmentMarker = {line: 0, column: 30, position: 30, next: marker4};
|
||||
const marker2: SegmentMarker = {line: 0, column: 20, position: 20, next: marker3};
|
||||
const marker1: SegmentMarker = {line: 0, column: 10, position: 10, next: marker2};
|
||||
const mappings: Mapping[] = [marker1, marker2, marker3, marker4, marker5].map(
|
||||
marker => ({ generatedSegment: marker } as Mapping));
|
||||
|
||||
const marker: SegmentMarker = {line: 0, column: 35, next: undefined};
|
||||
const marker: SegmentMarker = {line: 0, column: 35, position: 35, next: undefined};
|
||||
const index = findLastMappingIndexBefore(mappings, marker, /* exclusive */ false, 1);
|
||||
expect(index).toEqual(2);
|
||||
});
|
||||
|
||||
it('should return the lowerIndex mapping index if there is a single exact match and we are not exclusive',
|
||||
() => {
|
||||
const marker5: SegmentMarker = {line: 0, column: 50, next: undefined};
|
||||
const marker4: SegmentMarker = {line: 0, column: 40, next: marker5};
|
||||
const marker3: SegmentMarker = {line: 0, column: 30, next: marker4};
|
||||
const marker2: SegmentMarker = {line: 0, column: 20, next: marker3};
|
||||
const marker1: SegmentMarker = {line: 0, column: 10, next: marker2};
|
||||
const marker5: SegmentMarker = {line: 0, column: 50, position: 50, next: undefined};
|
||||
const marker4: SegmentMarker = {line: 0, column: 40, position: 40, next: marker5};
|
||||
const marker3: SegmentMarker = {line: 0, column: 30, position: 30, next: marker4};
|
||||
const marker2: SegmentMarker = {line: 0, column: 20, position: 20, next: marker3};
|
||||
const marker1: SegmentMarker = {line: 0, column: 10, position: 10, next: marker2};
|
||||
const mappings: Mapping[] = [marker1, marker2, marker3, marker4, marker5].map(
|
||||
marker => ({ generatedSegment: marker } as Mapping));
|
||||
|
||||
const marker: SegmentMarker = {line: 0, column: 30, next: undefined};
|
||||
const marker: SegmentMarker = {line: 0, column: 30, position: 30, next: undefined};
|
||||
const index = findLastMappingIndexBefore(mappings, marker, /* exclusive */ false, 2);
|
||||
expect(index).toEqual(2);
|
||||
});
|
||||
|
||||
it('should return the lowerIndex mapping index if there are multiple exact matches and we are not exclusive',
|
||||
() => {
|
||||
const marker5: SegmentMarker = {line: 0, column: 50, next: undefined};
|
||||
const marker4: SegmentMarker = {line: 0, column: 30, next: marker5};
|
||||
const marker3: SegmentMarker = {line: 0, column: 30, next: marker4};
|
||||
const marker2: SegmentMarker = {line: 0, column: 20, next: marker3};
|
||||
const marker1: SegmentMarker = {line: 0, column: 10, next: marker2};
|
||||
const marker5: SegmentMarker = {line: 0, column: 50, position: 50, next: undefined};
|
||||
const marker4: SegmentMarker = {line: 0, column: 30, position: 30, next: marker5};
|
||||
const marker3: SegmentMarker = {line: 0, column: 30, position: 30, next: marker4};
|
||||
const marker2: SegmentMarker = {line: 0, column: 20, position: 20, next: marker3};
|
||||
const marker1: SegmentMarker = {line: 0, column: 10, position: 10, next: marker2};
|
||||
const mappings: Mapping[] = [marker1, marker2, marker3, marker4, marker5].map(
|
||||
marker => ({ generatedSegment: marker } as Mapping));
|
||||
|
||||
const marker: SegmentMarker = {line: 0, column: 30, next: undefined};
|
||||
const marker: SegmentMarker = {line: 0, column: 30, position: 30, next: undefined};
|
||||
const index = findLastMappingIndexBefore(mappings, marker, /* exclusive */ false, 3);
|
||||
expect(index).toEqual(3);
|
||||
});
|
||||
|
||||
it('should return -1 if the segment marker is lower than the lowerIndex hint', () => {
|
||||
const marker5: SegmentMarker = {line: 0, column: 50, next: undefined};
|
||||
const marker4: SegmentMarker = {line: 0, column: 40, next: marker5};
|
||||
const marker3: SegmentMarker = {line: 0, column: 30, next: marker4};
|
||||
const marker2: SegmentMarker = {line: 0, column: 20, next: marker3};
|
||||
const marker1: SegmentMarker = {line: 0, column: 10, next: marker2};
|
||||
const marker5: SegmentMarker = {line: 0, column: 50, position: 50, next: undefined};
|
||||
const marker4: SegmentMarker = {line: 0, column: 40, position: 40, next: marker5};
|
||||
const marker3: SegmentMarker = {line: 0, column: 30, position: 30, next: marker4};
|
||||
const marker2: SegmentMarker = {line: 0, column: 20, position: 20, next: marker3};
|
||||
const marker1: SegmentMarker = {line: 0, column: 10, position: 10, next: marker2};
|
||||
const mappings: Mapping[] = [marker1, marker2, marker3, marker4, marker5].map(
|
||||
marker => ({ generatedSegment: marker } as Mapping));
|
||||
|
||||
const marker: SegmentMarker = {line: 0, column: 25, next: undefined};
|
||||
const marker: SegmentMarker = {line: 0, column: 25, position: 25, next: undefined};
|
||||
|
||||
const index = findLastMappingIndexBefore(mappings, marker, /* exclusive */ false, 2);
|
||||
expect(index).toEqual(-1);
|
||||
|
@ -291,15 +292,15 @@ runInEachFileSystem(() => {
|
|||
|
||||
it('should return -1 if the segment marker is equal to the lowerIndex hint and we are exclusive',
|
||||
() => {
|
||||
const marker5: SegmentMarker = {line: 0, column: 50, next: undefined};
|
||||
const marker4: SegmentMarker = {line: 0, column: 40, next: marker5};
|
||||
const marker3: SegmentMarker = {line: 0, column: 30, next: marker4};
|
||||
const marker2: SegmentMarker = {line: 0, column: 20, next: marker3};
|
||||
const marker1: SegmentMarker = {line: 0, column: 10, next: marker2};
|
||||
const marker5: SegmentMarker = {line: 0, column: 50, position: 50, next: undefined};
|
||||
const marker4: SegmentMarker = {line: 0, column: 40, position: 40, next: marker5};
|
||||
const marker3: SegmentMarker = {line: 0, column: 30, position: 30, next: marker4};
|
||||
const marker2: SegmentMarker = {line: 0, column: 20, position: 20, next: marker3};
|
||||
const marker1: SegmentMarker = {line: 0, column: 10, position: 10, next: marker2};
|
||||
const mappings: Mapping[] = [marker1, marker2, marker3, marker4, marker5].map(
|
||||
marker => ({ generatedSegment: marker } as Mapping));
|
||||
|
||||
const marker: SegmentMarker = {line: 0, column: 30, next: undefined};
|
||||
const marker: SegmentMarker = {line: 0, column: 30, position: 30, next: undefined};
|
||||
|
||||
const index = findLastMappingIndexBefore(mappings, marker, /* exclusive */ true, 2);
|
||||
expect(index).toEqual(-1);
|
||||
|
@ -319,7 +320,7 @@ runInEachFileSystem(() => {
|
|||
sources: ['a.js', 'b.js'],
|
||||
version: 3
|
||||
};
|
||||
const mappings = parseMappings(rawSourceMap, [sourceA, sourceB]);
|
||||
const mappings = parseMappings(rawSourceMap, [sourceA, sourceB], [0, 8]);
|
||||
ensureOriginalSegmentLinks(mappings);
|
||||
expect(mappings[0].originalSegment.next).toBe(mappings[2].originalSegment);
|
||||
expect(mappings[1].originalSegment.next).toBe(mappings[3].originalSegment);
|
||||
|
@ -356,7 +357,7 @@ runInEachFileSystem(() => {
|
|||
const sourceFile = new SourceFile(
|
||||
_('/foo/src/index.js'), 'abc123defg', rawSourceMap, false, [originalSource]);
|
||||
expect(removeOriginalSegmentLinks(sourceFile.flattenedMappings))
|
||||
.toEqual(parseMappings(rawSourceMap, [originalSource]));
|
||||
.toEqual(parseMappings(rawSourceMap, [originalSource], [0, 11]));
|
||||
});
|
||||
|
||||
it('should merge mappings from flattened original source files', () => {
|
||||
|
@ -383,39 +384,39 @@ runInEachFileSystem(() => {
|
|||
|
||||
expect(removeOriginalSegmentLinks(aSource.flattenedMappings)).toEqual([
|
||||
{
|
||||
generatedSegment: {line: 0, column: 0, next: undefined},
|
||||
generatedSegment: {line: 0, column: 0, position: 0, next: undefined},
|
||||
originalSource: dSource,
|
||||
originalSegment: {line: 0, column: 0, next: undefined},
|
||||
originalSegment: {line: 0, column: 0, position: 0, next: undefined},
|
||||
name: undefined
|
||||
},
|
||||
{
|
||||
generatedSegment: {line: 0, column: 1, next: undefined},
|
||||
generatedSegment: {line: 0, column: 1, position: 1, next: undefined},
|
||||
originalSource: cSource,
|
||||
originalSegment: {line: 0, column: 0, next: undefined},
|
||||
originalSegment: {line: 0, column: 0, position: 0, next: undefined},
|
||||
name: undefined
|
||||
},
|
||||
{
|
||||
generatedSegment: {line: 0, column: 2, next: undefined},
|
||||
generatedSegment: {line: 0, column: 2, position: 2, next: undefined},
|
||||
originalSource: cSource,
|
||||
originalSegment: {line: 0, column: 2, next: undefined},
|
||||
originalSegment: {line: 0, column: 2, position: 2, next: undefined},
|
||||
name: undefined
|
||||
},
|
||||
{
|
||||
generatedSegment: {line: 0, column: 3, next: undefined},
|
||||
generatedSegment: {line: 0, column: 3, position: 3, next: undefined},
|
||||
originalSource: dSource,
|
||||
originalSegment: {line: 0, column: 1, next: undefined},
|
||||
originalSegment: {line: 0, column: 1, position: 1, next: undefined},
|
||||
name: undefined
|
||||
},
|
||||
{
|
||||
generatedSegment: {line: 0, column: 4, next: undefined},
|
||||
generatedSegment: {line: 0, column: 4, position: 4, next: undefined},
|
||||
originalSource: cSource,
|
||||
originalSegment: {line: 0, column: 1, next: undefined},
|
||||
originalSegment: {line: 0, column: 1, position: 1, next: undefined},
|
||||
name: undefined
|
||||
},
|
||||
{
|
||||
generatedSegment: {line: 0, column: 5, next: undefined},
|
||||
generatedSegment: {line: 0, column: 5, position: 5, next: undefined},
|
||||
originalSource: dSource,
|
||||
originalSegment: {line: 0, column: 2, next: undefined},
|
||||
originalSegment: {line: 0, column: 2, position: 2, next: undefined},
|
||||
name: undefined
|
||||
},
|
||||
]);
|
||||
|
@ -441,7 +442,7 @@ runInEachFileSystem(() => {
|
|||
// These flattened mappings are just the mappings from a to b.
|
||||
// (The mappings to c are dropped since there is no source file to map to.)
|
||||
expect(removeOriginalSegmentLinks(aSource.flattenedMappings))
|
||||
.toEqual(parseMappings(aSourceMap, [bSource]));
|
||||
.toEqual(parseMappings(aSourceMap, [bSource], [0, 7]));
|
||||
});
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue