Commit 133219ad authored by Frank Tang's avatar Frank Tang Committed by Commit Bot

[Intl] Throws exception on grandfather and private locale

Bug: v8:9613
Change-Id: Ie91a5bd39c82b6baf33fd84dee8420d2c4a5f504
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1803783
Commit-Queue: Frank Tang <ftang@chromium.org>
Reviewed-by: 's avatarJakob Kummerow <jkummerow@chromium.org>
Cr-Commit-Position: refs/heads/master@{#63815}
parent 428c2a38
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include "src/objects/js-collator-inl.h" #include "src/objects/js-collator-inl.h"
#include "src/objects/js-date-time-format-inl.h" #include "src/objects/js-date-time-format-inl.h"
#include "src/objects/js-locale-inl.h" #include "src/objects/js-locale-inl.h"
#include "src/objects/js-locale.h"
#include "src/objects/js-number-format-inl.h" #include "src/objects/js-number-format-inl.h"
#include "src/objects/objects-inl.h" #include "src/objects/objects-inl.h"
#include "src/objects/property-descriptor.h" #include "src/objects/property-descriptor.h"
...@@ -784,6 +785,11 @@ Maybe<std::string> Intl::CanonicalizeLanguageTag(Isolate* isolate, ...@@ -784,6 +785,11 @@ Maybe<std::string> Intl::CanonicalizeLanguageTag(Isolate* isolate,
} }
std::string locale(locale_str->ToCString().get()); std::string locale(locale_str->ToCString().get());
if (!IsStructurallyValidLanguageTag(locale)) {
THROW_NEW_ERROR_RETURN_VALUE(
isolate, NewRangeError(MessageTemplate::kLocaleBadParameters),
Nothing<std::string>());
}
return Intl::CanonicalizeLanguageTag(isolate, locale); return Intl::CanonicalizeLanguageTag(isolate, locale);
} }
...@@ -2096,5 +2102,9 @@ MaybeHandle<String> Intl::FormattedToString( ...@@ -2096,5 +2102,9 @@ MaybeHandle<String> Intl::FormattedToString(
return Intl::ToString(isolate, result); return Intl::ToString(isolate, result);
} }
bool Intl::IsStructurallyValidLanguageTag(const std::string& tag) {
return JSLocale::StartsWithUnicodeLanguageId(tag);
}
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
...@@ -337,6 +337,8 @@ class Intl { ...@@ -337,6 +337,8 @@ class Intl {
static const std::set<std::string>& GetAvailableLocalesForLocale(); static const std::set<std::string>& GetAvailableLocalesForLocale();
static const std::set<std::string>& GetAvailableLocalesForDateFormat(); static const std::set<std::string>& GetAvailableLocalesForDateFormat();
static bool IsStructurallyValidLanguageTag(const std::string& tag);
}; };
} // namespace internal } // namespace internal
......
...@@ -168,10 +168,11 @@ bool IsUnicodeVariantSubtag(const std::string& value) { ...@@ -168,10 +168,11 @@ bool IsUnicodeVariantSubtag(const std::string& value) {
bool IsExtensionSingleton(const std::string& value) { bool IsExtensionSingleton(const std::string& value) {
return IsAlphanum(value, 1, 1); return IsAlphanum(value, 1, 1);
} }
} // namespace
// TODO(ftang) Replace the following check w/ icu::LocaleBuilder // TODO(ftang) Replace the following check w/ icu::LocaleBuilder
// once ICU64 land in March 2019. // once ICU64 land in March 2019.
bool StartsWithUnicodeLanguageId(const std::string& value) { bool JSLocale::StartsWithUnicodeLanguageId(const std::string& value) {
// unicode_language_id = // unicode_language_id =
// unicode_language_subtag (sep unicode_script_subtag)? // unicode_language_subtag (sep unicode_script_subtag)?
// (sep unicode_region_subtag)? (sep unicode_variant_subtag)* ; // (sep unicode_region_subtag)? (sep unicode_variant_subtag)* ;
...@@ -207,6 +208,7 @@ bool StartsWithUnicodeLanguageId(const std::string& value) { ...@@ -207,6 +208,7 @@ bool StartsWithUnicodeLanguageId(const std::string& value) {
return true; return true;
} }
namespace {
Maybe<bool> ApplyOptionsToTag(Isolate* isolate, Handle<String> tag, Maybe<bool> ApplyOptionsToTag(Isolate* isolate, Handle<String> tag,
Handle<JSReceiver> options, Handle<JSReceiver> options,
icu::LocaleBuilder* builder) { icu::LocaleBuilder* builder) {
...@@ -223,7 +225,7 @@ Maybe<bool> ApplyOptionsToTag(Isolate* isolate, Handle<String> tag, ...@@ -223,7 +225,7 @@ Maybe<bool> ApplyOptionsToTag(Isolate* isolate, Handle<String> tag,
CHECK_NOT_NULL(*bcp47_tag); CHECK_NOT_NULL(*bcp47_tag);
// 2. If IsStructurallyValidLanguageTag(tag) is false, throw a RangeError // 2. If IsStructurallyValidLanguageTag(tag) is false, throw a RangeError
// exception. // exception.
if (!StartsWithUnicodeLanguageId(*bcp47_tag)) { if (!JSLocale::StartsWithUnicodeLanguageId(*bcp47_tag)) {
return Just(false); return Just(false);
} }
UErrorCode status = U_ZERO_ERROR; UErrorCode status = U_ZERO_ERROR;
......
...@@ -49,6 +49,9 @@ class JSLocale : public JSObject { ...@@ -49,6 +49,9 @@ class JSLocale : public JSObject {
static Handle<String> ToString(Isolate* isolate, Handle<JSLocale> locale); static Handle<String> ToString(Isolate* isolate, Handle<JSLocale> locale);
static std::string ToString(Handle<JSLocale> locale); static std::string ToString(Handle<JSLocale> locale);
// Help function to validate locale by other Intl objects.
static bool StartsWithUnicodeLanguageId(const std::string& value);
DECL_CAST(JSLocale) DECL_CAST(JSLocale)
DECL_ACCESSORS(icu_locale, Managed<icu::Locale>) DECL_ACCESSORS(icu_locale, Managed<icu::Locale>)
......
...@@ -125,9 +125,6 @@ assertEquals("abci\u0307", "aBcI\u0307".toLowerCase()); ...@@ -125,9 +125,6 @@ assertEquals("abci\u0307", "aBcI\u0307".toLowerCase());
// Anything other than 'tr' and 'az' behave like root for U+0307. // Anything other than 'tr' and 'az' behave like root for U+0307.
assertEquals("abci\u0307", "aBcI\u0307".toLocaleLowerCase("fil")); assertEquals("abci\u0307", "aBcI\u0307".toLocaleLowerCase("fil"));
assertEquals("abci\u0307", "aBcI\u0307".toLocaleLowerCase("zh-Hant-TW")); assertEquals("abci\u0307", "aBcI\u0307".toLocaleLowerCase("zh-Hant-TW"));
assertEquals("abci\u0307", "aBcI\u0307".toLocaleLowerCase("i-klingon"));
assertEquals("abci\u0307", "aBcI\u0307".toLocaleLowerCase("i-enochian"));
assertEquals("abci\u0307", "aBcI\u0307".toLocaleLowerCase("x-foobar"));
// Up to 8 chars are allowed for the primary language tag in BCP 47. // Up to 8 chars are allowed for the primary language tag in BCP 47.
assertEquals("abci\u0307", "aBcI\u0307".toLocaleLowerCase("longlang")); assertEquals("abci\u0307", "aBcI\u0307".toLocaleLowerCase("longlang"));
......
...@@ -8,18 +8,8 @@ ...@@ -8,18 +8,8 @@
// v8 works around that ICU issue. // v8 works around that ICU issue.
// See https://www.iana.org/assignments/language-subtag-registry/language-subtag-registry . // See https://www.iana.org/assignments/language-subtag-registry/language-subtag-registry .
["cel-gaulish", "cel-gaulish"], ["cel-gaulish", "cel-gaulish"],
["i-default", "i-default"],
["i-mingo", "i-mingo"],
["i-enochian", "i-enochian"],
["zh-min", "zh-min"],
// Matching should be case-insensitive. // Matching should be case-insensitive.
["I-default", "i-default"],
["i-DEFAULT", "i-default"],
["I-DEFAULT", "i-default"],
["i-DEfauLT", "i-default"],
["zh-Min", "zh-min"],
["Zh-min", "zh-min"],
].forEach(([inputLocale, expectedLocale]) => { ].forEach(([inputLocale, expectedLocale]) => {
const canonicalLocales = Intl.getCanonicalLocales(inputLocale); const canonicalLocales = Intl.getCanonicalLocales(inputLocale);
assertEquals(canonicalLocales.length, 1); assertEquals(canonicalLocales.length, 1);
......
...@@ -9,8 +9,6 @@ ...@@ -9,8 +9,6 @@
// Matching should be case-insensitive. // Matching should be case-insensitive.
["sgn-De", "gsg"], ["sgn-De", "gsg"],
["sgn-BE-FR", "sfb"],
["Sgn-bE-Fr", "sfb"],
// deprecated region tag // deprecated region tag
["und-Latn-dd", "und-Latn-DE"], ["und-Latn-dd", "und-Latn-DE"],
......
...@@ -83,16 +83,15 @@ for (const service of services) { ...@@ -83,16 +83,15 @@ for (const service of services) {
privateuseLocale = service.supportedLocalesOf("en-US-x-twain"); privateuseLocale = service.supportedLocalesOf("en-US-x-twain");
assertEquals("en-US-x-twain", privateuseLocale[0]); assertEquals("en-US-x-twain", privateuseLocale[0]);
privateuseLocale2 = service.supportedLocalesOf("x-twain"); assertThrows(() => service.supportedLocalesOf("x-twain"), RangeError);
assertEquals(undefined, privateuseLocale2[0]);
if (service != Intl.PluralRules) { if (service != Intl.PluralRules) {
grandfatheredLocale = service.supportedLocalesOf("art-lojban"); grandfatheredLocale = service.supportedLocalesOf("art-lojban");
assertEquals(undefined, grandfatheredLocale[0]); assertEquals(undefined, grandfatheredLocale[0]);
} }
grandfatheredLocale2 = service.supportedLocalesOf("i-pwn"); assertThrows(() => service.supportedLocalesOf("x-pwn"), RangeError);
assertEquals(undefined, grandfatheredLocale2[0]);
unicodeInPrivateuseLocale = service.supportedLocalesOf( unicodeInPrivateuseLocale = service.supportedLocalesOf(
"en-US-x-u-co-phonebk" "en-US-x-u-co-phonebk"
......
...@@ -144,7 +144,3 @@ assertEquals( ...@@ -144,7 +144,3 @@ assertEquals(
assertEquals( assertEquals(
'ar', 'ar',
(new Intl.ListFormat(['xyz', 'ar'])).resolvedOptions().locale); (new Intl.ListFormat(['xyz', 'ar'])).resolvedOptions().locale);
assertEquals(
'ar',
(new Intl.ListFormat(['i-default', 'ar'])).resolvedOptions().locale);
...@@ -6,5 +6,5 @@ Object.prototype.__defineGetter__('x', function () { ...@@ -6,5 +6,5 @@ Object.prototype.__defineGetter__('x', function () {
return -2147483648; return -2147483648;
}); });
var f = ["x-u-foo"]; var f = ["en-US"];
Intl.NumberFormat(f); Intl.NumberFormat(f);
...@@ -156,7 +156,3 @@ assertEquals( ...@@ -156,7 +156,3 @@ assertEquals(
assertThrows(() => assertThrows(() =>
Intl.RelativeTimeFormat.prototype.resolvedOptions.call(receiver), TypeError); Intl.RelativeTimeFormat.prototype.resolvedOptions.call(receiver), TypeError);
} }
assertEquals(
'ar',
(new Intl.RelativeTimeFormat(['i-default', 'ar'])).resolvedOptions().locale);
...@@ -530,20 +530,15 @@ ...@@ -530,20 +530,15 @@
# https://bugs.chromium.org/p/v8/issues/detail?id=9613 # https://bugs.chromium.org/p/v8/issues/detail?id=9613
'intl402/Intl/getCanonicalLocales/canonicalized-tags': [FAIL], 'intl402/Intl/getCanonicalLocales/canonicalized-tags': [FAIL],
'intl402/Intl/getCanonicalLocales/grandfathered': [FAIL], 'intl402/Intl/getCanonicalLocales/grandfathered': [FAIL],
'intl402/Intl/getCanonicalLocales/invalid-tags': [FAIL],
'intl402/Intl/getCanonicalLocales/non-iana-canon': [FAIL], 'intl402/Intl/getCanonicalLocales/non-iana-canon': [FAIL],
'intl402/Intl/getCanonicalLocales/preferred-grandfathered': [FAIL], 'intl402/Intl/getCanonicalLocales/preferred-grandfathered': [FAIL],
'intl402/Intl/getCanonicalLocales/preferred-variant': [FAIL], 'intl402/Intl/getCanonicalLocales/preferred-variant': [FAIL],
'intl402/language-tags-invalid': [FAIL],
'intl402/ListFormat/constructor/constructor/locales-valid': [FAIL],
'intl402/Locale/constructor-non-iana-canon': [FAIL], 'intl402/Locale/constructor-non-iana-canon': [FAIL],
'intl402/Locale/constructor-options-region-valid': [FAIL], 'intl402/Locale/constructor-options-region-valid': [FAIL],
'intl402/Locale/constructor-tag': [FAIL], 'intl402/Locale/constructor-tag': [FAIL],
'intl402/Locale/getters': [FAIL], 'intl402/Locale/getters': [FAIL],
'intl402/Locale/likely-subtags-grandfathered': [FAIL], 'intl402/Locale/likely-subtags-grandfathered': [FAIL],
'intl402/PluralRules/prototype/resolvedOptions/order': [FAIL], 'intl402/PluralRules/prototype/resolvedOptions/order': [FAIL],
'intl402/RelativeTimeFormat/constructor/constructor/locales-valid': [FAIL],
'intl402/Segmenter/constructor/constructor/locales-valid': [FAIL],
######################## NEEDS INVESTIGATION ########################### ######################## NEEDS INVESTIGATION ###########################
......
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