diff --git a/packages/compiler-cli/ngcc/src/sourcemaps/segment_marker.ts b/packages/compiler-cli/ngcc/src/sourcemaps/segment_marker.ts index 229a8d220d..78d71f1053 100644 --- a/packages/compiler-cli/ngcc/src/sourcemaps/segment_marker.ts +++ b/packages/compiler-cli/ngcc/src/sourcemaps/segment_marker.ts @@ -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}; } diff --git a/packages/compiler-cli/ngcc/src/sourcemaps/source_file.ts b/packages/compiler-cli/ngcc/src/sourcemaps/source_file.ts index 7d7805b14d..839eec56f0 100644 --- a/packages/compiler-cli/ngcc/src/sourcemaps/source_file.ts +++ b/packages/compiler-cli/ngcc/src/sourcemaps/source_file.ts @@ -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}); diff --git a/packages/compiler-cli/ngcc/test/sourcemaps/segment_marker_spec.ts b/packages/compiler-cli/ngcc/test/sourcemaps/segment_marker_spec.ts index a7549992bb..8632643c28 100644 --- a/packages/compiler-cli/ngcc/test/sourcemaps/segment_marker_spec.ts +++ b/packages/compiler-cli/ngcc/test/sourcemaps/segment_marker_spec.ts @@ -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}); }); }); }); \ No newline at end of file diff --git a/packages/compiler-cli/ngcc/test/sourcemaps/source_file_spec.ts b/packages/compiler-cli/ngcc/test/sourcemaps/source_file_spec.ts index ef2de6ed68..5c0456bc39 100644 --- a/packages/compiler-cli/ngcc/test/sourcemaps/source_file_spec.ts +++ b/packages/compiler-cli/ngcc/test/sourcemaps/source_file_spec.ts @@ -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])); }); /**