diff options
Diffstat (limited to 'deps/v8/src/objects/js-locale.cc')
-rw-r--r-- | deps/v8/src/objects/js-locale.cc | 170 |
1 files changed, 118 insertions, 52 deletions
diff --git a/deps/v8/src/objects/js-locale.cc b/deps/v8/src/objects/js-locale.cc index 8968aa58c9..78fb30fa41 100644 --- a/deps/v8/src/objects/js-locale.cc +++ b/deps/v8/src/objects/js-locale.cc @@ -35,6 +35,26 @@ namespace internal { namespace { +JSLocale::CaseFirst GetCaseFirst(const char* str) { + if (strcmp(str, "upper") == 0) return JSLocale::CaseFirst::UPPER; + if (strcmp(str, "lower") == 0) return JSLocale::CaseFirst::LOWER; + if (strcmp(str, "false") == 0) return JSLocale::CaseFirst::FALSE_VALUE; + UNREACHABLE(); +} + +JSLocale::HourCycle GetHourCycle(const char* str) { + if (strcmp(str, "h11") == 0) return JSLocale::HourCycle::H11; + if (strcmp(str, "h12") == 0) return JSLocale::HourCycle::H12; + if (strcmp(str, "h23") == 0) return JSLocale::HourCycle::H23; + if (strcmp(str, "h24") == 0) return JSLocale::HourCycle::H24; + UNREACHABLE(); +} + +JSLocale::Numeric GetNumeric(const char* str) { + return strcmp(str, "true") == 0 ? JSLocale::Numeric::TRUE_VALUE + : JSLocale::Numeric::FALSE_VALUE; +} + struct OptionData { const char* name; const char* key; @@ -49,12 +69,12 @@ Maybe<bool> InsertOptionsIntoLocale(Isolate* isolate, CHECK(isolate); CHECK(icu_locale); - static std::vector<const char*> hour_cycle_values = {"h11", "h12", "h23", - "h24"}; - static std::vector<const char*> case_first_values = {"upper", "lower", - "false"}; - static std::vector<const char*> empty_values = {}; - static const std::array<OptionData, 6> kOptionToUnicodeTagMap = { + const std::vector<const char*> hour_cycle_values = {"h11", "h12", "h23", + "h24"}; + const std::vector<const char*> case_first_values = {"upper", "lower", + "false"}; + const std::vector<const char*> empty_values = {}; + const std::array<OptionData, 6> kOptionToUnicodeTagMap = { {{"calendar", "ca", &empty_values, false}, {"collation", "co", &empty_values, false}, {"hourCycle", "hc", &hour_cycle_values, false}, @@ -75,7 +95,7 @@ Maybe<bool> InsertOptionsIntoLocale(Isolate* isolate, : Intl::GetStringOption(isolate, options, option_to_bcp47.name, *(option_to_bcp47.possible_values), "locale", &value_str); - if (maybe_found.IsNothing()) return maybe_found; + MAYBE_RETURN(maybe_found, Nothing<bool>()); // TODO(cira): Use fallback value if value is not found to make // this spec compliant. @@ -138,19 +158,23 @@ bool PopulateLocaleWithUnicodeTags(Isolate* isolate, const char* icu_locale, if (bcp47_key) { const char* bcp47_value = uloc_toUnicodeLocaleType(bcp47_key, value); if (bcp47_value) { - Handle<String> bcp47_handle = - factory->NewStringFromAsciiChecked(bcp47_value); if (strcmp(bcp47_key, "kn") == 0) { - locale_holder->set_numeric(*bcp47_handle); + locale_holder->set_numeric(GetNumeric(bcp47_value)); } else if (strcmp(bcp47_key, "ca") == 0) { + Handle<String> bcp47_handle = + factory->NewStringFromAsciiChecked(bcp47_value); locale_holder->set_calendar(*bcp47_handle); } else if (strcmp(bcp47_key, "kf") == 0) { - locale_holder->set_case_first(*bcp47_handle); + locale_holder->set_case_first(GetCaseFirst(bcp47_value)); } else if (strcmp(bcp47_key, "co") == 0) { + Handle<String> bcp47_handle = + factory->NewStringFromAsciiChecked(bcp47_value); locale_holder->set_collation(*bcp47_handle); } else if (strcmp(bcp47_key, "hc") == 0) { - locale_holder->set_hour_cycle(*bcp47_handle); + locale_holder->set_hour_cycle(GetHourCycle(bcp47_value)); } else if (strcmp(bcp47_key, "nu") == 0) { + Handle<String> bcp47_handle = + factory->NewStringFromAsciiChecked(bcp47_value); locale_holder->set_numbering_system(*bcp47_handle); } } @@ -163,17 +187,17 @@ bool PopulateLocaleWithUnicodeTags(Isolate* isolate, const char* icu_locale, } } // namespace -MaybeHandle<JSLocale> JSLocale::InitializeLocale(Isolate* isolate, - Handle<JSLocale> locale_holder, - Handle<String> locale, - Handle<JSReceiver> options) { +MaybeHandle<JSLocale> JSLocale::Initialize(Isolate* isolate, + Handle<JSLocale> locale_holder, + Handle<String> locale, + Handle<JSReceiver> options) { + locale_holder->set_flags(0); static const char* const kMethod = "Intl.Locale"; v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate); UErrorCode status = U_ZERO_ERROR; // Get ICU locale format, and canonicalize it. char icu_result[ULOC_FULLNAME_CAPACITY]; - char icu_canonical[ULOC_FULLNAME_CAPACITY]; if (locale->length() == 0) { THROW_NEW_ERROR(isolate, NewRangeError(MessageTemplate::kLocaleNotEmpty), @@ -184,18 +208,20 @@ MaybeHandle<JSLocale> JSLocale::InitializeLocale(Isolate* isolate, CHECK_LT(0, bcp47_locale.length()); CHECK_NOT_NULL(*bcp47_locale); - int icu_length = uloc_forLanguageTag( - *bcp47_locale, icu_result, ULOC_FULLNAME_CAPACITY, nullptr, &status); + int parsed_length = 0; + int icu_length = + uloc_forLanguageTag(*bcp47_locale, icu_result, ULOC_FULLNAME_CAPACITY, + &parsed_length, &status); - if (U_FAILURE(status) || status == U_STRING_NOT_TERMINATED_WARNING || - icu_length == 0) { + if (U_FAILURE(status) || + parsed_length < static_cast<int>(bcp47_locale.length()) || + status == U_STRING_NOT_TERMINATED_WARNING || icu_length == 0) { THROW_NEW_ERROR( isolate, NewRangeError(MessageTemplate::kLocaleBadParameters, isolate->factory()->NewStringFromAsciiChecked(kMethod), locale_holder), JSLocale); - return MaybeHandle<JSLocale>(); } Maybe<bool> error = InsertOptionsIntoLocale(isolate, options, icu_result); @@ -207,40 +233,26 @@ MaybeHandle<JSLocale> JSLocale::InitializeLocale(Isolate* isolate, isolate->factory()->NewStringFromAsciiChecked(kMethod), locale_holder), JSLocale); - return MaybeHandle<JSLocale>(); - } - DCHECK(error.FromJust()); - - uloc_canonicalize(icu_result, icu_canonical, ULOC_FULLNAME_CAPACITY, &status); - if (U_FAILURE(status) || status == U_STRING_NOT_TERMINATED_WARNING) { - THROW_NEW_ERROR( - isolate, - NewRangeError(MessageTemplate::kLocaleBadParameters, - isolate->factory()->NewStringFromAsciiChecked(kMethod), - locale_holder), - JSLocale); - return MaybeHandle<JSLocale>(); } - if (!PopulateLocaleWithUnicodeTags(isolate, icu_canonical, locale_holder)) { + if (!PopulateLocaleWithUnicodeTags(isolate, icu_result, locale_holder)) { THROW_NEW_ERROR( isolate, NewRangeError(MessageTemplate::kLocaleBadParameters, isolate->factory()->NewStringFromAsciiChecked(kMethod), locale_holder), JSLocale); - return MaybeHandle<JSLocale>(); } // Extract language, script and region parts. char icu_language[ULOC_LANG_CAPACITY]; - uloc_getLanguage(icu_canonical, icu_language, ULOC_LANG_CAPACITY, &status); + uloc_getLanguage(icu_result, icu_language, ULOC_LANG_CAPACITY, &status); char icu_script[ULOC_SCRIPT_CAPACITY]; - uloc_getScript(icu_canonical, icu_script, ULOC_SCRIPT_CAPACITY, &status); + uloc_getScript(icu_result, icu_script, ULOC_SCRIPT_CAPACITY, &status); char icu_region[ULOC_COUNTRY_CAPACITY]; - uloc_getCountry(icu_canonical, icu_region, ULOC_COUNTRY_CAPACITY, &status); + uloc_getCountry(icu_result, icu_region, ULOC_COUNTRY_CAPACITY, &status); if (U_FAILURE(status) || status == U_STRING_NOT_TERMINATED_WARNING) { THROW_NEW_ERROR( @@ -249,7 +261,6 @@ MaybeHandle<JSLocale> JSLocale::InitializeLocale(Isolate* isolate, isolate->factory()->NewStringFromAsciiChecked(kMethod), locale_holder), JSLocale); - return MaybeHandle<JSLocale>(); } Factory* factory = isolate->factory(); @@ -271,8 +282,7 @@ MaybeHandle<JSLocale> JSLocale::InitializeLocale(Isolate* isolate, } char icu_base_name[ULOC_FULLNAME_CAPACITY]; - uloc_getBaseName(icu_canonical, icu_base_name, ULOC_FULLNAME_CAPACITY, - &status); + uloc_getBaseName(icu_result, icu_base_name, ULOC_FULLNAME_CAPACITY, &status); // We need to convert it back to BCP47. char bcp47_result[ULOC_FULLNAME_CAPACITY]; uloc_toLanguageTag(icu_base_name, bcp47_result, ULOC_FULLNAME_CAPACITY, true, @@ -284,13 +294,12 @@ MaybeHandle<JSLocale> JSLocale::InitializeLocale(Isolate* isolate, isolate->factory()->NewStringFromAsciiChecked(kMethod), locale_holder), JSLocale); - return MaybeHandle<JSLocale>(); } Handle<String> base_name = factory->NewStringFromAsciiChecked(bcp47_result); locale_holder->set_base_name(*base_name); // Produce final representation of the locale string, for toString(). - uloc_toLanguageTag(icu_canonical, bcp47_result, ULOC_FULLNAME_CAPACITY, true, + uloc_toLanguageTag(icu_result, bcp47_result, ULOC_FULLNAME_CAPACITY, true, &status); if (U_FAILURE(status) || status == U_STRING_NOT_TERMINATED_WARNING) { THROW_NEW_ERROR( @@ -299,7 +308,6 @@ MaybeHandle<JSLocale> JSLocale::InitializeLocale(Isolate* isolate, isolate->factory()->NewStringFromAsciiChecked(kMethod), locale_holder), JSLocale); - return MaybeHandle<JSLocale>(); } Handle<String> locale_handle = factory->NewStringFromAsciiChecked(bcp47_result); @@ -310,20 +318,37 @@ MaybeHandle<JSLocale> JSLocale::InitializeLocale(Isolate* isolate, namespace { -Handle<String> MorphLocale(Isolate* isolate, String* input, +Handle<String> MorphLocale(Isolate* isolate, String* language_tag, int32_t (*morph_func)(const char*, char*, int32_t, UErrorCode*)) { Factory* factory = isolate->factory(); char localeBuffer[ULOC_FULLNAME_CAPACITY]; + char morphBuffer[ULOC_FULLNAME_CAPACITY]; + UErrorCode status = U_ZERO_ERROR; + // Convert from language id to locale. + int32_t parsed_length; + int32_t length = + uloc_forLanguageTag(language_tag->ToCString().get(), localeBuffer, + ULOC_FULLNAME_CAPACITY, &parsed_length, &status); + CHECK(parsed_length == language_tag->length()); + DCHECK(U_SUCCESS(status)); + DCHECK_GT(length, 0); DCHECK_NOT_NULL(morph_func); - int32_t length = (*morph_func)(input->ToCString().get(), localeBuffer, - ULOC_FULLNAME_CAPACITY, &status); + // Add the likely subtags or Minimize the subtags on the locale id + length = + (*morph_func)(localeBuffer, morphBuffer, ULOC_FULLNAME_CAPACITY, &status); + DCHECK(U_SUCCESS(status)); + DCHECK_GT(length, 0); + // Returns a well-formed language tag + length = uloc_toLanguageTag(morphBuffer, localeBuffer, ULOC_FULLNAME_CAPACITY, + false, &status); DCHECK(U_SUCCESS(status)); DCHECK_GT(length, 0); - std::string locale(localeBuffer, length); - std::replace(locale.begin(), locale.end(), '_', '-'); - return factory->NewStringFromAsciiChecked(locale.c_str()); + std::string lang(localeBuffer, length); + std::replace(lang.begin(), lang.end(), '_', '-'); + + return factory->NewStringFromAsciiChecked(lang.c_str()); } } // namespace @@ -336,5 +361,46 @@ Handle<String> JSLocale::Minimize(Isolate* isolate, String* locale) { return MorphLocale(isolate, locale, uloc_minimizeSubtags); } +Handle<String> JSLocale::CaseFirstAsString() const { + switch (case_first()) { + case CaseFirst::UPPER: + return GetReadOnlyRoots().upper_string_handle(); + case CaseFirst::LOWER: + return GetReadOnlyRoots().lower_string_handle(); + case CaseFirst::FALSE_VALUE: + return GetReadOnlyRoots().false_string_handle(); + case CaseFirst::COUNT: + UNREACHABLE(); + } +} + +Handle<String> JSLocale::HourCycleAsString() const { + switch (hour_cycle()) { + case HourCycle::H11: + return GetReadOnlyRoots().h11_string_handle(); + case HourCycle::H12: + return GetReadOnlyRoots().h12_string_handle(); + case HourCycle::H23: + return GetReadOnlyRoots().h23_string_handle(); + case HourCycle::H24: + return GetReadOnlyRoots().h24_string_handle(); + case HourCycle::COUNT: + UNREACHABLE(); + } +} + +Handle<String> JSLocale::NumericAsString() const { + switch (numeric()) { + case Numeric::NOTSET: + return GetReadOnlyRoots().undefined_string_handle(); + case Numeric::TRUE_VALUE: + return GetReadOnlyRoots().true_string_handle(); + case Numeric::FALSE_VALUE: + return GetReadOnlyRoots().false_string_handle(); + case Numeric::COUNT: + UNREACHABLE(); + } +} + } // namespace internal } // namespace v8 |