From d9775cd8229ffcecff7cfb194bbcc98945f7554f Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Thu, 26 Oct 2017 14:29:03 -0700 Subject: [PATCH] Ensure explicit default locale before each test --- src/compiler/core.ts | 63 +++++++++++++++++++++++++++++++--------- src/harness/fourslash.ts | 5 ---- src/harness/runner.ts | 5 ++++ 3 files changed, 55 insertions(+), 18 deletions(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 9c52a4481f9..bb0aca3e700 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -1613,21 +1613,17 @@ namespace ts { * Creates a string comparer for use with string collation in the UI. */ const createStringComparer = (function () { - // If the host supports Intl, we use it for comparisons using the default locale. - if (typeof Intl === "object" && typeof Intl.Collator === "function") { - return createIntlCollatorStringComparer; + type CachedLocale = "en-US" | undefined; + + interface StringComparerCache { + default?: Comparer; + "en-US"?: Comparer; } - // If the host does not support Intl, we fall back to localeCompare. - // localeCompare in Node v0.10 is just an ordinal comparison, so don't use it. - if (typeof String.prototype.localeCompare === "function" && - typeof String.prototype.toLocaleUpperCase === "function" && - "a".localeCompare("B") < 0) { - return createLocaleCompareStringComparer; - } - - // Otherwise, fall back to ordinal comparison: - return createFallbackStringComparer; + let caseInsensitiveCache: StringComparerCache | undefined; + let caseSensitiveCache: StringComparerCache | undefined; + const createStringComparerNoCache = getStringComparerFactory(); + return createStringComparer; function compareWithCallback(a: string | undefined, b: string | undefined, comparer: (a: string, b: string) => number) { if (a === b) return Comparison.EqualTo; @@ -1688,6 +1684,47 @@ namespace ts { return compareCaseInsensitive(a, b) || compareCaseSensitive(a, b); } } + + function getStringComparerFactory() { + // If the host supports Intl, we use it for comparisons using the default locale. + if (typeof Intl === "object" && typeof Intl.Collator === "function") { + return createIntlCollatorStringComparer; + } + + // If the host does not support Intl, we fall back to localeCompare. + // localeCompare in Node v0.10 is just an ordinal comparison, so don't use it. + if (typeof String.prototype.localeCompare === "function" && + typeof String.prototype.toLocaleUpperCase === "function" && + "a".localeCompare("B") < 0) { + return createLocaleCompareStringComparer; + } + + // Otherwise, fall back to ordinal comparison: + return createFallbackStringComparer; + } + + // Hold onto common string comparers. This avoids constantly reallocating comparers during + // tests. + function createStringComparerCached(locale: CachedLocale, caseInsensitive: boolean) { + const cacheKey = locale || "default"; + const cache = caseInsensitive + ? caseInsensitiveCache || (caseInsensitiveCache = {}) + : caseSensitiveCache || (caseSensitiveCache = {}); + + let comparer = cache[cacheKey]; + if (!comparer) { + comparer = createStringComparerNoCache(locale, caseInsensitive); + cache[cacheKey] = comparer; + } + + return comparer; + } + + function createStringComparer(locale: string | undefined, caseInsensitive: boolean) { + return locale === undefined || locale === "en-US" + ? createStringComparerCached(locale as CachedLocale, caseInsensitive) + : createStringComparerNoCache(locale, caseInsensitive); + } })(); let uiCS: Comparer | undefined; diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index 105501196b0..b52dbd6932a 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -3128,8 +3128,6 @@ Actual: ${stringify(fullActual)}`); `(function(test, goTo, verify, edit, debug, format, cancellation, classification, verifyOperationIsCancelled) { ${code} })`; - const savedUILocale = ts.getUILocale(); - ts.setUILocale("en-US"); // run tests in en-US by default. try { const test = new FourSlashInterface.Test(state); @@ -3145,9 +3143,6 @@ ${code} catch (err) { throw err; } - finally { - ts.setUILocale(savedUILocale); - } } function chompLeadingSpace(content: string) { diff --git a/src/harness/runner.ts b/src/harness/runner.ts index db807b976bb..57955c9ab43 100644 --- a/src/harness/runner.ts +++ b/src/harness/runner.ts @@ -207,6 +207,11 @@ function beginTests() { ts.Debug.enableDebugInfo(); } + // run tests in en-US by default. + const savedUILocale = ts.getUILocale(); + beforeEach(() => ts.setUILocale("en-US")); + afterEach(() => ts.setUILocale(savedUILocale)); + runTests(runners); if (!runUnitTests) {