Commit 3059138b authored by littledan's avatar littledan Committed by Commit bot

[intl] Fall back on an invalid default locale to "und"

The default locale can be changed in some environments with environment
variables. These environment variables used to allow the system to get
into an invalid state, where the default locale was unsupported. This
patch detects that case and falls back to "und" as the default locale
if there is an Intl service which does not support the locale that ICU
reports as the default. It also has a slight cleanup of surrounding code.

I haven't gone through the work to set up an automated test, as triggering
the case requires setting environment variables, which our tests don't tend
to do, but I tested interactively as follows:

dehrenberg@dehrenberg:~/v8/v8$ LC_ALL="tlh-FR" rlwrap out/Release/d8
V8 version 5.7.0 (candidate)
d8> new Intl.NumberFormat("foo").resolvedOptions().locale
"und"
d8> new Intl.NumberFormat().resolvedOptions().locale
"und"
d8>

dehrenberg@dehrenberg:~/v8/v8$ LC_ALL="de" rlwrap out/Release/d8
V8 version 5.7.0 (candidate)
d8> new Intl.NumberFormat().resolvedOptions().locale
"de"
d8> new Intl.NumberFormat("foo").resolvedOptions().locale
"de"
d8>

BUG=v8:4216

Review-Url: https://codereview.chromium.org/2646593002
Cr-Commit-Position: refs/heads/master@{#43253}
parent ae8f2820
...@@ -153,6 +153,13 @@ var DEFAULT_ICU_LOCALE = UNDEFINED; ...@@ -153,6 +153,13 @@ var DEFAULT_ICU_LOCALE = UNDEFINED;
function GetDefaultICULocaleJS() { function GetDefaultICULocaleJS() {
if (IS_UNDEFINED(DEFAULT_ICU_LOCALE)) { if (IS_UNDEFINED(DEFAULT_ICU_LOCALE)) {
DEFAULT_ICU_LOCALE = %GetDefaultICULocale(); DEFAULT_ICU_LOCALE = %GetDefaultICULocale();
// Check that this is a valid default, otherwise fall back to "und"
for (let service in AVAILABLE_LOCALES) {
if (IS_UNDEFINED(getAvailableLocalesOf(service)[DEFAULT_ICU_LOCALE])) {
DEFAULT_ICU_LOCALE = "und";
break;
}
}
} }
return DEFAULT_ICU_LOCALE; return DEFAULT_ICU_LOCALE;
} }
...@@ -298,19 +305,16 @@ function supportedLocalesOf(service, locales, options) { ...@@ -298,19 +305,16 @@ function supportedLocalesOf(service, locales, options) {
var requestedLocales = initializeLocaleList(locales); var requestedLocales = initializeLocaleList(locales);
// Cache these, they don't ever change per service. var availableLocales = getAvailableLocalesOf(service);
if (IS_UNDEFINED(AVAILABLE_LOCALES[service])) {
AVAILABLE_LOCALES[service] = getAvailableLocalesOf(service);
}
// Use either best fit or lookup algorithm to match locales. // Use either best fit or lookup algorithm to match locales.
if (matcher === 'best fit') { if (matcher === 'best fit') {
return initializeLocaleList(bestFitSupportedLocalesOf( return initializeLocaleList(bestFitSupportedLocalesOf(
requestedLocales, AVAILABLE_LOCALES[service])); requestedLocales, availableLocales));
} }
return initializeLocaleList(lookupSupportedLocalesOf( return initializeLocaleList(lookupSupportedLocalesOf(
requestedLocales, AVAILABLE_LOCALES[service])); requestedLocales, availableLocales));
} }
...@@ -437,17 +441,14 @@ function lookupMatcher(service, requestedLocales) { ...@@ -437,17 +441,14 @@ function lookupMatcher(service, requestedLocales) {
throw %make_error(kWrongServiceType, service); throw %make_error(kWrongServiceType, service);
} }
// Cache these, they don't ever change per service. var availableLocales = getAvailableLocalesOf(service);
if (IS_UNDEFINED(AVAILABLE_LOCALES[service])) {
AVAILABLE_LOCALES[service] = getAvailableLocalesOf(service);
}
for (var i = 0; i < requestedLocales.length; ++i) { for (var i = 0; i < requestedLocales.length; ++i) {
// Remove all extensions. // Remove all extensions.
var locale = %RegExpInternalReplace( var locale = %RegExpInternalReplace(
GetAnyExtensionRE(), requestedLocales[i], ''); GetAnyExtensionRE(), requestedLocales[i], '');
do { do {
if (!IS_UNDEFINED(AVAILABLE_LOCALES[service][locale])) { if (!IS_UNDEFINED(availableLocales[locale])) {
// Return the resolved locale and extension. // Return the resolved locale and extension.
var extensionMatch = %regexp_internal_match( var extensionMatch = %regexp_internal_match(
GetUnicodeExtensionRE(), requestedLocales[i]); GetUnicodeExtensionRE(), requestedLocales[i]);
...@@ -658,6 +659,11 @@ function getOptimalLanguageTag(original, resolved) { ...@@ -658,6 +659,11 @@ function getOptimalLanguageTag(original, resolved) {
* that is supported. This is required by the spec. * that is supported. This is required by the spec.
*/ */
function getAvailableLocalesOf(service) { function getAvailableLocalesOf(service) {
// Cache these, they don't ever change per service.
if (!IS_UNDEFINED(AVAILABLE_LOCALES[service])) {
return AVAILABLE_LOCALES[service];
}
var available = %AvailableLocalesOf(service); var available = %AvailableLocalesOf(service);
for (var i in available) { for (var i in available) {
...@@ -672,6 +678,8 @@ function getAvailableLocalesOf(service) { ...@@ -672,6 +678,8 @@ function getAvailableLocalesOf(service) {
} }
} }
AVAILABLE_LOCALES[service] = available;
return available; return available;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment