@@ -1653,17 +1653,11 @@ namespace ts {
16531653 /**
16541654 * Creates a string comparer for use with string collation in the UI.
16551655 */
1656- const createStringComparer = ( function ( ) {
1657- type CachedLocale = "en-US" | undefined ;
1656+ const createUIStringComparer = ( function ( ) {
1657+ let defaultComparer : Comparer < string > | undefined ;
1658+ let enUSComparer : Comparer < string > | undefined ;
16581659
1659- interface StringComparerCache {
1660- default ?: Comparer < string > ;
1661- "en-US" ?: Comparer < string > ;
1662- }
1663-
1664- let caseInsensitiveCache : StringComparerCache | undefined ;
1665- let caseSensitiveCache : StringComparerCache | undefined ;
1666- const createStringComparerNoCache = getStringComparerFactory ( ) ;
1660+ const stringComparerFactory = getStringComparerFactory ( ) ;
16671661 return createStringComparer ;
16681662
16691663 function compareWithCallback ( a : string | undefined , b : string | undefined , comparer : ( a : string , b : string ) => number ) {
@@ -1674,56 +1668,41 @@ namespace ts {
16741668 return value < 0 ? Comparison . LessThan : value > 0 ? Comparison . GreaterThan : Comparison . EqualTo ;
16751669 }
16761670
1677- function createIntlCollatorStringComparer ( locale : string | undefined , caseInsensitive : boolean ) : Comparer < string > {
1678- // Initialize the sort collator on first use
1679- let comparer : Comparer < string > = ( a , b ) => {
1680- // Intl.Collator.prototype.compare is bound to the collator. See NOTE in
1681- // http://www.ecma-international.org/ecma-402/2.0/#sec-Intl.Collator.prototype.compare
1682- comparer = new Intl . Collator ( locale , { usage : "sort" , sensitivity : caseInsensitive ? "accent" : "variant" } ) . compare ;
1683- return comparer ( a , b ) ;
1684- } ;
1671+ function createIntlCollatorStringComparer ( locale : string | undefined ) : Comparer < string > {
1672+ // Intl.Collator.prototype.compare is bound to the collator. See NOTE in
1673+ // http://www.ecma-international.org/ecma-402/2.0/#sec-Intl.Collator.prototype.compare
1674+ const comparer = new Intl . Collator ( locale , { usage : "sort" , sensitivity : "variant" } ) . compare ;
16851675 return ( a , b ) => compareWithCallback ( a , b , comparer ) ;
16861676 }
16871677
1688- function createLocaleCompareStringComparer ( locale : string | undefined , caseInsensitive : boolean ) : Comparer < string > {
1678+ function createLocaleCompareStringComparer ( locale : string | undefined ) : Comparer < string > {
16891679 // if the locale is not the default locale (`undefined`), use the fallback comparer.
1690- return locale !== undefined ? createFallbackStringComparer ( locale , caseInsensitive ) :
1691- caseInsensitive ? ( a , b ) => compareWithCallback ( a , b , compareCaseInsensitive ) :
1692- ( a , b ) => compareWithCallback ( a , b , compareCaseSensitive ) ;
1680+ if ( locale !== undefined ) return createFallbackStringComparer ( ) ;
16931681
1694- function compareCaseInsensitive ( a : string , b : string ) {
1695- // for case-insensitive comparisons we always map both strings to their
1696- // upper-case form as some unicode characters do not properly round-trip to
1697- // lowercase (such as `ẞ` (German sharp capital s)).
1698- return compareCaseSensitive ( a . toLocaleUpperCase ( ) , b . toLocaleUpperCase ( ) ) ;
1699- }
1682+ return ( a , b ) => compareWithCallback ( a , b , compareStrings ) ;
17001683
1701- function compareCaseSensitive ( a : string , b : string ) {
1684+ function compareStrings ( a : string , b : string ) {
17021685 return a . localeCompare ( b ) ;
17031686 }
17041687 }
17051688
1706- function createFallbackStringComparer ( _locale : string | undefined , caseInsensitive : boolean ) : Comparer < string > {
1707- return caseInsensitive ? ( a , b ) => compareWithCallback ( a , b , compareCaseInsensitive ) :
1708- ( a , b ) => compareWithCallback ( a , b , compareCaseSensitiveDictionaryOrder ) ;
1689+ function createFallbackStringComparer ( ) : Comparer < string > {
1690+ // An ordinal comparison puts "A" after "b", but for the UI we want "A" before "b".
1691+ // We first sort case insensitively. So "Aaa" will come before "baa".
1692+ // Then we sort case sensitively, so "aaa" will come before "Aaa".
1693+ //
1694+ // For case insensitive comparisons we always map both strings to their
1695+ // upper-case form as some unicode characters do not properly round-trip to
1696+ // lowercase (such as `ẞ` (German sharp capital s)).
1697+ return ( a , b ) => compareWithCallback ( a , b , compareDictionaryOrder ) ;
17091698
1710- function compareCaseInsensitive ( a : string , b : string ) {
1711- // for case-insensitive comparisons we always map both strings to their
1712- // upper-case form as some unicode characters do not properly round-trip to
1713- // lowercase (such as `ẞ` (German sharp capital s)).
1714- return compareCaseSensitive ( a . toUpperCase ( ) , b . toUpperCase ( ) ) ;
1699+ function compareDictionaryOrder ( a : string , b : string ) {
1700+ return compareStrings ( a . toUpperCase ( ) , b . toUpperCase ( ) ) || compareStrings ( a , b ) ;
17151701 }
17161702
1717- function compareCaseSensitive ( a : string , b : string ) {
1703+ function compareStrings ( a : string , b : string ) {
17181704 return a < b ? Comparison . LessThan : a > b ? Comparison . GreaterThan : Comparison . EqualTo ;
17191705 }
1720-
1721- function compareCaseSensitiveDictionaryOrder ( a : string , b : string ) {
1722- // An ordinal comparison puts "A" after "b", but for the UI we want "A" before "b".
1723- // We first sort case insensitively. So "Aaa" will come before "baa".
1724- // Then we sort case sensitively, so "aaa" will come before "Aaa".
1725- return compareCaseInsensitive ( a , b ) || compareCaseSensitive ( a , b ) ;
1726- }
17271706 }
17281707
17291708 function getStringComparerFactory ( ) {
@@ -1744,32 +1723,22 @@ namespace ts {
17441723 return createFallbackStringComparer ;
17451724 }
17461725
1747- // Hold onto common string comparers. This avoids constantly reallocating comparers during
1748- // tests.
1749- function createStringComparerCached ( locale : CachedLocale , caseInsensitive : boolean ) {
1750- const cacheKey = locale || "default" ;
1751- const cache = caseInsensitive
1752- ? caseInsensitiveCache || ( caseInsensitiveCache = { } )
1753- : caseSensitiveCache || ( caseSensitiveCache = { } ) ;
1754-
1755- let comparer = cache [ cacheKey ] ;
1756- if ( ! comparer ) {
1757- comparer = createStringComparerNoCache ( locale , caseInsensitive ) ;
1758- cache [ cacheKey ] = comparer ;
1726+ function createStringComparer ( locale : string | undefined ) {
1727+ // Hold onto common string comparers. This avoids constantly reallocating comparers during
1728+ // tests.
1729+ if ( locale === undefined ) {
1730+ return defaultComparer || ( defaultComparer = stringComparerFactory ( locale ) ) ;
1731+ }
1732+ else if ( locale === "en-US" ) {
1733+ return enUSComparer || ( enUSComparer = stringComparerFactory ( locale ) ) ;
1734+ }
1735+ else {
1736+ return stringComparerFactory ( locale ) ;
17591737 }
1760-
1761- return comparer ;
1762- }
1763-
1764- function createStringComparer ( locale : string | undefined , caseInsensitive : boolean ) {
1765- return locale === undefined || locale === "en-US"
1766- ? createStringComparerCached ( locale as CachedLocale , caseInsensitive )
1767- : createStringComparerNoCache ( locale , caseInsensitive ) ;
17681738 }
17691739 } ) ( ) ;
17701740
17711741 let uiComparerCaseSensitive : Comparer < string > | undefined ;
1772- let uiComparerCaseInsensitive : Comparer < string > | undefined ;
17731742 let uiLocale : string | undefined ;
17741743
17751744 export function getUILocale ( ) {
@@ -1780,25 +1749,9 @@ namespace ts {
17801749 if ( uiLocale !== value ) {
17811750 uiLocale = value ;
17821751 uiComparerCaseSensitive = undefined ;
1783- uiComparerCaseInsensitive = undefined ;
17841752 }
17851753 }
17861754
1787- /**
1788- * Compare two strings using the case-insensitive sort behavior of the UI locale.
1789- *
1790- * Ordering is not predictable between different host locales, but is best for displaying
1791- * ordered data for UI presentation. Characters with multiple unicode representations may
1792- * be considered equal.
1793- *
1794- * Case-insensitive comparisons compare strings that differ in only base characters or
1795- * accents/diacritic marks as unequal.
1796- */
1797- export function compareStringsCaseInsensitiveUI ( a : string , b : string ) {
1798- const comparer = uiComparerCaseInsensitive || ( uiComparerCaseInsensitive = createStringComparer ( uiLocale , /*caseInsensitive*/ true ) ) ;
1799- return comparer ( a , b ) ;
1800- }
1801-
18021755 /**
18031756 * Compare two strings in a using the case-sensitive sort behavior of the UI locale.
18041757 *
@@ -1810,7 +1763,7 @@ namespace ts {
18101763 * accents/diacritic marks, or case as unequal.
18111764 */
18121765 export function compareStringsCaseSensitiveUI ( a : string , b : string ) {
1813- const comparer = uiComparerCaseSensitive || ( uiComparerCaseSensitive = createStringComparer ( uiLocale , /*caseInsensitive*/ false ) ) ;
1766+ const comparer = uiComparerCaseSensitive || ( uiComparerCaseSensitive = createUIStringComparer ( uiLocale ) ) ;
18141767 return comparer ( a , b ) ;
18151768 }
18161769
0 commit comments