diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 4b64f1299f..3dc2735d00 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -1061,10 +1061,10 @@ namespace ts { /** * Stable sort of an array. Elements equal to each other maintain their relative position in the array. */ - export function stableSort(array: ReadonlyArray, comparer: Comparer) { + export function stableSort(array: ReadonlyArray, comparer: Comparer): SortedReadonlyArray { const indices = array.map((_, i) => i); stableSortIndices(array, indices, comparer); - return indices.map(i => array[i]); + return indices.map(i => array[i]) as SortedArray as SortedReadonlyArray; } export function rangeEquals(array1: ReadonlyArray, array2: ReadonlyArray, pos: number, end: number) { @@ -1156,7 +1156,7 @@ namespace ts { * @param offset An offset into `array` at which to start the search. */ export function binarySearch(array: ReadonlyArray, value: T, keySelector: (v: T) => U, keyComparer: Comparer, offset?: number): number { - return some(array) ? binarySearchKey(array, keySelector(value), keySelector, keyComparer, offset) : -1; + return binarySearchKey(array, keySelector(value), keySelector, keyComparer, offset); } /** @@ -2167,74 +2167,4 @@ namespace ts { export function fill(length: number, cb: (index: number) => T): T[] { return new Array(length).fill(0).map((_, i) => cb(i)); } - - /** - * A list of sorted and unique values. Optimized for best performance when items are added - * in the sort order. - */ - export class SortedUniqueList implements Push { - private relationalComparer: (a: T, b: T) => Comparison; - private equalityComparer: (a: T, b: T) => boolean; - private sortedAndUnique = true; - private copyOnWrite = false; - private unsafeArray: T[] = []; - private unsafeLast: T | undefined = undefined; - - constructor(relationalComparer: Comparer, equalityComparer: EqualityComparer) { - this.relationalComparer = relationalComparer; - this.equalityComparer = equalityComparer; - } - - get size() { - return this.unsafeArray.length; - } - - get last() { - this.ensureSortedAndUnique(); - return this.unsafeLast === undefined - ? this.unsafeLast = lastOrUndefined(this.unsafeArray) - : this.unsafeLast; - } - - push(...values: T[]) { - for (const value of values) { - if (this.sortedAndUnique) { - const last = this.last; - if (last === undefined || this.relationalComparer(value, last) > 0) { - this.unsafeAdd(value, /*sortedAndUnique*/ true); - continue; - } - if (this.equalityComparer(value, last)) { - continue; - } - } - this.unsafeAdd(value, /*sortedAndUnique*/ false); - } - } - - toArray(): ReadonlyArray { - this.ensureSortedAndUnique(); - this.copyOnWrite = true; - return this.unsafeArray; - } - - private unsafeAdd(value: T, sortedAndUnique: boolean) { - if (this.copyOnWrite || this.unsafeArray === emptyArray) { - this.unsafeArray = this.unsafeArray.slice(); - this.copyOnWrite = false; - } - - this.unsafeArray.push(value); - this.unsafeLast = sortedAndUnique ? value : undefined; - this.sortedAndUnique = sortedAndUnique; - } - - private ensureSortedAndUnique() { - if (!this.sortedAndUnique) { - this.unsafeArray = deduplicateSorted(stableSort(this.unsafeArray, this.relationalComparer) as any as SortedReadonlyArray, this.equalityComparer) as any as T[]; - this.unsafeLast = undefined; - this.sortedAndUnique = true; - } - } - } } diff --git a/src/compiler/sourcemap.ts b/src/compiler/sourcemap.ts index 700c6a9100..76cf24e51d 100644 --- a/src/compiler/sourcemap.ts +++ b/src/compiler/sourcemap.ts @@ -566,18 +566,18 @@ namespace ts { && value.sourcePosition !== undefined; } - function sameMappedPosition(left: T, right: T) { + function sameMappedPosition(left: MappedPosition, right: MappedPosition) { return left.generatedPosition === right.generatedPosition && left.sourceIndex === right.sourceIndex && left.sourcePosition === right.sourcePosition; } function compareSourcePositions(left: SourceMappedPosition, right: SourceMappedPosition) { - return left.sourcePosition - right.sourcePosition; + return compareValues(left.sourceIndex, right.sourceIndex); } function compareGeneratedPositions(left: MappedPosition, right: MappedPosition) { - return left.generatedPosition - right.generatedPosition; + return compareValues(left.generatedPosition, right.generatedPosition); } function getSourcePositionOfMapping(value: SourceMappedPosition) { @@ -598,8 +598,8 @@ namespace ts { const sourceFileCanonicalPaths = sourceFileAbsolutePaths.map(source => host.getCanonicalFileName(source) as Path); const sourceToSourceIndexMap = createMapFromEntries(sourceFileCanonicalPaths.map((source, i) => [source, i] as [string, number])); let decodedMappings: ReadonlyArray | undefined; - let generatedMappings: ReadonlyArray | undefined; - let sourceMappings: ReadonlyArray> | undefined; + let generatedMappings: SortedReadonlyArray | undefined; + let sourceMappings: ReadonlyArray> | undefined; return { getSourcePosition, @@ -648,25 +648,25 @@ namespace ts { function getSourceMappings(sourceIndex: number) { if (sourceMappings === undefined) { - const lists: SortedUniqueList[] = []; + const lists: SourceMappedPosition[][] = []; for (const mapping of getDecodedMappings()) { if (!isSourceMappedPosition(mapping)) continue; let list = lists[mapping.sourceIndex]; - if (!list) lists[mapping.sourceIndex] = list = new SortedUniqueList(compareSourcePositions, sameMappedPosition); + if (!list) lists[mapping.sourceIndex] = list = []; list.push(mapping); } - sourceMappings = lists.map(list => list.toArray()); + sourceMappings = lists.map(list => sortAndDeduplicate(list, compareSourcePositions, sameMappedPosition)); } return sourceMappings[sourceIndex]; } function getGeneratedMappings() { if (generatedMappings === undefined) { - const list = new SortedUniqueList(compareGeneratedPositions, sameMappedPosition); + const list: MappedPosition[] = []; for (const mapping of getDecodedMappings()) { list.push(mapping); } - generatedMappings = list.toArray(); + generatedMappings = sortAndDeduplicate(list, compareGeneratedPositions, sameMappedPosition); } return generatedMappings; }