Commit 8fd5fa22 authored by Sathya Gunasekaran's avatar Sathya Gunasekaran Committed by Commit Bot

[Intl] Validate extension keys

- Fix ParseBCP47 to return just the extension. The second argument to
  substr function is actually the length, not the end position of the
  substring :')
- Remove extension keys that aren't part of the relevant extension keys
- Use 'ca' as an relevant extension key for DateTimeFormat
- Use the canonicalized locale tag after create the ICU locale is
  created, rather than the input locale tag.

Bug: chromium:895942, v8:5751
Cq-Include-Trybots: luci.v8.try:v8_linux_noi18n_rel_ng
Change-Id: I189709714d847e684b04409b734a60ff04ed7dd2
Reviewed-on: https://chromium-review.googlesource.com/c/1291076Reviewed-by: 's avatarFrank Tang <ftang@chromium.org>
Commit-Queue: Sathya Gunasekaran <gsathya@chromium.org>
Cr-Commit-Position: refs/heads/master@{#57274}
parent 9681eb5f
......@@ -1445,8 +1445,8 @@ ParsedLocale ParseBCP47Locale(const std::string& locale) {
const std::string end = locale.substr(unicode_extension_end);
parsed_locale.no_extensions_locale = beginning + end;
parsed_locale.extension =
locale.substr(unicode_extension_start, unicode_extension_end);
parsed_locale.extension = locale.substr(
unicode_extension_start, unicode_extension_end - unicode_extension_start);
return parsed_locale;
}
......@@ -1630,13 +1630,13 @@ MaybeHandle<JSObject> Intl::SupportedLocalesOf(
namespace {
std::map<std::string, std::string> LookupUnicodeExtensions(
const icu::Locale& icu_locale, const std::set<std::string>& relevant_keys) {
std::map<std::string, std::string> LookupAndValidateUnicodeExtensions(
icu::Locale* icu_locale, const std::set<std::string>& relevant_keys) {
std::map<std::string, std::string> extensions;
UErrorCode status = U_ZERO_ERROR;
std::unique_ptr<icu::StringEnumeration> keywords(
icu_locale.createKeywords(status));
icu_locale->createKeywords(status));
if (U_FAILURE(status)) return extensions;
if (!keywords) return extensions;
......@@ -1654,7 +1654,7 @@ std::map<std::string, std::string> LookupUnicodeExtensions(
continue;
}
icu_locale.getKeywordValue(keyword, value, ULOC_FULLNAME_CAPACITY, status);
icu_locale->getKeywordValue(keyword, value, ULOC_FULLNAME_CAPACITY, status);
// Ignore failures in ICU and skip to the next keyword.
//
......@@ -1666,11 +1666,14 @@ std::map<std::string, std::string> LookupUnicodeExtensions(
const char* bcp47_key = uloc_toUnicodeLocaleKey(keyword);
// Ignore keywords that we don't recognize - spec allows that.
if (bcp47_key && (relevant_keys.find(bcp47_key) != relevant_keys.end())) {
const char* bcp47_value = uloc_toUnicodeLocaleType(bcp47_key, value);
extensions.insert(
std::pair<std::string, std::string>(bcp47_key, bcp47_value));
} else {
status = U_ZERO_ERROR;
icu_locale->setKeywordValue(keyword, nullptr, status);
CHECK(U_SUCCESS(status));
}
}
......@@ -1751,11 +1754,17 @@ Intl::ResolvedLocale Intl::ResolveLocale(
icu::Locale icu_locale = CreateICULocale(locale);
std::map<std::string, std::string> extensions =
LookupUnicodeExtensions(icu_locale, relevant_extension_keys);
LookupAndValidateUnicodeExtensions(&icu_locale, relevant_extension_keys);
char canonicalized_locale[ULOC_FULLNAME_CAPACITY];
UErrorCode status = U_ZERO_ERROR;
uloc_toLanguageTag(icu_locale.getName(), canonicalized_locale,
ULOC_FULLNAME_CAPACITY, true, &status);
CHECK(U_SUCCESS(status));
// TODO(gsathya): Remove privateuse subtags from extensions.
return Intl::ResolvedLocale{locale, icu_locale, extensions};
return Intl::ResolvedLocale{canonicalized_locale, icu_locale, extensions};
}
Managed<icu::UnicodeString>* Intl::SetTextToBreakIterator(
......
......@@ -798,13 +798,22 @@ MaybeHandle<JSDateTimeFormat> JSDateTimeFormat::Initialize(
// 9. Set opt.[[hc]] to hourCycle.
// TODO(ftang): change behavior based on hour_cycle.
// ecma402/#sec-intl.datetimeformat-internal-slots
// The value of the [[RelevantExtensionKeys]] internal slot is
// « "ca", "nu", "hc" ».
//
// TODO(ftang): Add "hc" to this list of keys:
// https://bugs.chromium.org/p/v8/issues/detail?id=7482
std::set<std::string> relevant_extension_keys = {"nu", "ca"};
// 10. Let localeData be %DateTimeFormat%.[[LocaleData]].
// 11. Let r be ResolveLocale( %DateTimeFormat%.[[AvailableLocales]],
// requestedLocales, opt, %DateTimeFormat%.[[RelevantExtensionKeys]],
// localeData).
Intl::ResolvedLocale r =
Intl::ResolveLocale(isolate, JSDateTimeFormat::GetAvailableLocales(),
requested_locales, locale_matcher, {"nu"});
//
Intl::ResolvedLocale r = Intl::ResolveLocale(
isolate, JSDateTimeFormat::GetAvailableLocales(), requested_locales,
locale_matcher, relevant_extension_keys);
// TODO(ftang): Make sure that "nu" key doesn't have "native",
// "traditio" or "finance" values.
......
// Copyright 2018 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
x = new Intl.DateTimeFormat("en-u-foo-x-u");
assertEquals('en', x.resolvedOptions().locale);
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