@@ -1613,21 +1613,17 @@ namespace ts {
16131613 * Creates a string comparer for use with string collation in the UI.
16141614 */
16151615 const createStringComparer = ( function ( ) {
1616- // If the host supports Intl, we use it for comparisons using the default locale.
1617- if ( typeof Intl === "object" && typeof Intl . Collator === "function" ) {
1618- return createIntlCollatorStringComparer ;
1619- }
1616+ type CachedLocale = "en-US" | undefined ;
16201617
1621- // If the host does not support Intl, we fall back to localeCompare.
1622- // localeCompare in Node v0.10 is just an ordinal comparison, so don't use it.
1623- if ( typeof String . prototype . localeCompare === "function" &&
1624- typeof String . prototype . toLocaleUpperCase === "function" &&
1625- "a" . localeCompare ( "B" ) < 0 ) {
1626- return createLocaleCompareStringComparer ;
1618+ interface StringComparerCache {
1619+ default ?: Comparer < string > ;
1620+ "en-US" ?: Comparer < string > ;
16271621 }
16281622
1629- // Otherwise, fall back to ordinal comparison:
1630- return createFallbackStringComparer ;
1623+ let caseInsensitiveCache : StringComparerCache | undefined ;
1624+ let caseSensitiveCache : StringComparerCache | undefined ;
1625+ const createStringComparerNoCache = getStringComparerFactory ( ) ;
1626+ return createStringComparer ;
16311627
16321628 function compareWithCallback ( a : string | undefined , b : string | undefined , comparer : ( a : string , b : string ) => number ) {
16331629 if ( a === b ) return Comparison . EqualTo ;
@@ -1688,6 +1684,47 @@ namespace ts {
16881684 return compareCaseInsensitive ( a , b ) || compareCaseSensitive ( a , b ) ;
16891685 }
16901686 }
1687+
1688+ function getStringComparerFactory ( ) {
1689+ // If the host supports Intl, we use it for comparisons using the default locale.
1690+ if ( typeof Intl === "object" && typeof Intl . Collator === "function" ) {
1691+ return createIntlCollatorStringComparer ;
1692+ }
1693+
1694+ // If the host does not support Intl, we fall back to localeCompare.
1695+ // localeCompare in Node v0.10 is just an ordinal comparison, so don't use it.
1696+ if ( typeof String . prototype . localeCompare === "function" &&
1697+ typeof String . prototype . toLocaleUpperCase === "function" &&
1698+ "a" . localeCompare ( "B" ) < 0 ) {
1699+ return createLocaleCompareStringComparer ;
1700+ }
1701+
1702+ // Otherwise, fall back to ordinal comparison:
1703+ return createFallbackStringComparer ;
1704+ }
1705+
1706+ // Hold onto common string comparers. This avoids constantly reallocating comparers during
1707+ // tests.
1708+ function createStringComparerCached ( locale : CachedLocale , caseInsensitive : boolean ) {
1709+ const cacheKey = locale || "default" ;
1710+ const cache = caseInsensitive
1711+ ? caseInsensitiveCache || ( caseInsensitiveCache = { } )
1712+ : caseSensitiveCache || ( caseSensitiveCache = { } ) ;
1713+
1714+ let comparer = cache [ cacheKey ] ;
1715+ if ( ! comparer ) {
1716+ comparer = createStringComparerNoCache ( locale , caseInsensitive ) ;
1717+ cache [ cacheKey ] = comparer ;
1718+ }
1719+
1720+ return comparer ;
1721+ }
1722+
1723+ function createStringComparer ( locale : string | undefined , caseInsensitive : boolean ) {
1724+ return locale === undefined || locale === "en-US"
1725+ ? createStringComparerCached ( locale as CachedLocale , caseInsensitive )
1726+ : createStringComparerNoCache ( locale , caseInsensitive ) ;
1727+ }
16911728 } ) ( ) ;
16921729
16931730 let uiCS : Comparer < string > | undefined ;
0 commit comments