aboutsummaryrefslogtreecommitdiff
path: root/deps/v8/src/objects/js-locale.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/objects/js-locale.cc')
-rw-r--r--deps/v8/src/objects/js-locale.cc215
1 files changed, 70 insertions, 145 deletions
diff --git a/deps/v8/src/objects/js-locale.cc b/deps/v8/src/objects/js-locale.cc
index 4e35c16b0f..509f9a3069 100644
--- a/deps/v8/src/objects/js-locale.cc
+++ b/deps/v8/src/objects/js-locale.cc
@@ -13,14 +13,15 @@
#include <string>
#include <vector>
-#include "src/api.h"
-#include "src/global-handles.h"
+#include "src/api/api.h"
+#include "src/execution/isolate.h"
+#include "src/handles/global-handles.h"
#include "src/heap/factory.h"
-#include "src/isolate.h"
-#include "src/objects-inl.h"
#include "src/objects/intl-objects.h"
#include "src/objects/js-locale-inl.h"
+#include "src/objects/objects-inl.h"
#include "unicode/char16ptr.h"
+#include "unicode/localebuilder.h"
#include "unicode/locid.h"
#include "unicode/uloc.h"
#include "unicode/unistr.h"
@@ -30,21 +31,6 @@ namespace internal {
namespace {
-// Helper function to check a locale is valid. It will return false if
-// the length of the extension fields are incorrect. For example, en-u-a or
-// en-u-co-b will return false.
-bool IsValidLocale(const icu::Locale& locale) {
- // icu::Locale::toLanguageTag won't return U_STRING_NOT_TERMINATED_WARNING for
- // incorrect locale yet. So we still need the following uloc_toLanguageTag
- // TODO(ftang): Change to use icu::Locale::toLanguageTag once it indicate
- // error.
- char result[ULOC_FULLNAME_CAPACITY];
- UErrorCode status = U_ZERO_ERROR;
- uloc_toLanguageTag(locale.getName(), result, ULOC_FULLNAME_CAPACITY, true,
- &status);
- return U_SUCCESS(status) && status != U_STRING_NOT_TERMINATED_WARNING;
-}
-
struct OptionData {
const char* name;
const char* key;
@@ -55,9 +41,8 @@ struct OptionData {
// Inserts tags from options into locale string.
Maybe<bool> InsertOptionsIntoLocale(Isolate* isolate,
Handle<JSReceiver> options,
- icu::Locale* icu_locale) {
+ icu::LocaleBuilder* builder) {
CHECK(isolate);
- CHECK(!icu_locale->isBogus());
const std::vector<const char*> hour_cycle_values = {"h11", "h12", "h23",
"h24"};
@@ -75,7 +60,6 @@ Maybe<bool> InsertOptionsIntoLocale(Isolate* isolate,
// TODO(cira): Pass in values as per the spec to make this to be
// spec compliant.
- UErrorCode status = U_ZERO_ERROR;
for (const auto& option_to_bcp47 : kOptionToUnicodeTagMap) {
std::unique_ptr<char[]> value_str = nullptr;
bool value_bool = false;
@@ -99,32 +83,18 @@ Maybe<bool> InsertOptionsIntoLocale(Isolate* isolate,
DCHECK_NOT_NULL(value_str.get());
// Overwrite existing, or insert new key-value to the locale string.
- if (uloc_toLegacyType(uloc_toLegacyKey(option_to_bcp47.key),
- value_str.get())) {
- // Only call setUnicodeKeywordValue if that value is a valid one.
- icu_locale->setUnicodeKeywordValue(option_to_bcp47.key, value_str.get(),
- status);
- if (U_FAILURE(status)) {
- return Just(false);
- }
- } else {
+ if (!uloc_toLegacyType(uloc_toLegacyKey(option_to_bcp47.key),
+ value_str.get())) {
return Just(false);
}
+ builder->setUnicodeLocaleKeyword(option_to_bcp47.key, value_str.get());
}
-
- // Check all the unicode extension fields are in the right length.
- if (!IsValidLocale(*icu_locale)) {
- THROW_NEW_ERROR_RETURN_VALUE(
- isolate, NewRangeError(MessageTemplate::kLocaleBadParameters),
- Nothing<bool>());
- }
-
return Just(true);
}
Handle<Object> UnicodeKeywordValue(Isolate* isolate, Handle<JSLocale> locale,
const char* key) {
- icu::Locale* icu_locale = locale->icu_locale()->raw();
+ icu::Locale* icu_locale = locale->icu_locale().raw();
UErrorCode status = U_ZERO_ERROR;
std::string value =
icu_locale->getUnicodeKeywordValue<std::string>(key, status);
@@ -237,32 +207,29 @@ bool StartsWithUnicodeLanguageId(const std::string& value) {
return true;
}
-Maybe<std::string> ApplyOptionsToTag(Isolate* isolate, Handle<String> tag,
- Handle<JSReceiver> options) {
+Maybe<bool> ApplyOptionsToTag(Isolate* isolate, Handle<String> tag,
+ Handle<JSReceiver> options,
+ icu::LocaleBuilder* builder) {
v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
if (tag->length() == 0) {
THROW_NEW_ERROR_RETURN_VALUE(
isolate, NewRangeError(MessageTemplate::kLocaleNotEmpty),
- Nothing<std::string>());
+ Nothing<bool>());
}
v8::String::Utf8Value bcp47_tag(v8_isolate, v8::Utils::ToLocal(tag));
+ builder->setLanguageTag({*bcp47_tag, bcp47_tag.length()});
CHECK_LT(0, bcp47_tag.length());
CHECK_NOT_NULL(*bcp47_tag);
// 2. If IsStructurallyValidLanguageTag(tag) is false, throw a RangeError
// exception.
if (!StartsWithUnicodeLanguageId(*bcp47_tag)) {
- THROW_NEW_ERROR_RETURN_VALUE(
- isolate, NewRangeError(MessageTemplate::kLocaleBadParameters),
- Nothing<std::string>());
+ return Just(false);
}
UErrorCode status = U_ZERO_ERROR;
- icu::Locale icu_locale =
- icu::Locale::forLanguageTag({*bcp47_tag, bcp47_tag.length()}, status);
+ builder->build(status);
if (U_FAILURE(status)) {
- THROW_NEW_ERROR_RETURN_VALUE(
- isolate, NewRangeError(MessageTemplate::kLocaleBadParameters),
- Nothing<std::string>());
+ return Just(false);
}
// 3. Let language be ? GetOption(options, "language", "string", undefined,
@@ -272,15 +239,16 @@ Maybe<std::string> ApplyOptionsToTag(Isolate* isolate, Handle<String> tag,
Maybe<bool> maybe_language =
Intl::GetStringOption(isolate, options, "language", empty_values,
"ApplyOptionsToTag", &language_str);
- MAYBE_RETURN(maybe_language, Nothing<std::string>());
+ MAYBE_RETURN(maybe_language, Nothing<bool>());
// 4. If language is not undefined, then
if (maybe_language.FromJust()) {
+ builder->setLanguage(language_str.get());
+ builder->build(status);
// a. If language does not match the unicode_language_subtag production,
// throw a RangeError exception.
- if (!IsUnicodeLanguageSubtag(language_str.get())) {
- THROW_NEW_ERROR_RETURN_VALUE(
- isolate, NewRangeError(MessageTemplate::kLocaleBadParameters),
- Nothing<std::string>());
+ if (U_FAILURE(status) || language_str[0] == '\0' ||
+ IsAlpha(language_str.get(), 4, 4)) {
+ return Just(false);
}
}
// 5. Let script be ? GetOption(options, "script", "string", undefined,
@@ -289,15 +257,15 @@ Maybe<std::string> ApplyOptionsToTag(Isolate* isolate, Handle<String> tag,
Maybe<bool> maybe_script =
Intl::GetStringOption(isolate, options, "script", empty_values,
"ApplyOptionsToTag", &script_str);
- MAYBE_RETURN(maybe_script, Nothing<std::string>());
+ MAYBE_RETURN(maybe_script, Nothing<bool>());
// 6. If script is not undefined, then
if (maybe_script.FromJust()) {
+ builder->setScript(script_str.get());
+ builder->build(status);
// a. If script does not match the unicode_script_subtag production, throw
// a RangeError exception.
- if (!IsUnicodeScriptSubtag(script_str.get())) {
- THROW_NEW_ERROR_RETURN_VALUE(
- isolate, NewRangeError(MessageTemplate::kLocaleBadParameters),
- Nothing<std::string>());
+ if (U_FAILURE(status) || script_str[0] == '\0') {
+ return Just(false);
}
}
// 7. Let region be ? GetOption(options, "region", "string", undefined,
@@ -306,85 +274,41 @@ Maybe<std::string> ApplyOptionsToTag(Isolate* isolate, Handle<String> tag,
Maybe<bool> maybe_region =
Intl::GetStringOption(isolate, options, "region", empty_values,
"ApplyOptionsToTag", &region_str);
- MAYBE_RETURN(maybe_region, Nothing<std::string>());
+ MAYBE_RETURN(maybe_region, Nothing<bool>());
// 8. If region is not undefined, then
if (maybe_region.FromJust()) {
// a. If region does not match the region production, throw a RangeError
// exception.
- if (!IsUnicodeRegionSubtag(region_str.get())) {
- THROW_NEW_ERROR_RETURN_VALUE(
- isolate, NewRangeError(MessageTemplate::kLocaleBadParameters),
- Nothing<std::string>());
+ builder->setRegion(region_str.get());
+ builder->build(status);
+ if (U_FAILURE(status) || region_str[0] == '\0') {
+ return Just(false);
}
}
- // 9. Set tag to CanonicalizeLanguageTag(tag).
- Maybe<std::string> maybe_canonicalized =
- Intl::CanonicalizeLanguageTag(isolate, tag);
- MAYBE_RETURN(maybe_canonicalized, Nothing<std::string>());
-
- std::vector<std::string> tokens;
- std::string token;
- std::istringstream token_stream(maybe_canonicalized.FromJust());
- while (std::getline(token_stream, token, '-')) {
- tokens.push_back(token);
- }
+ // 9. Set tag to CanonicalizeLanguageTag(tag).
// 10. If language is not undefined,
- std::string locale_str;
- if (maybe_language.FromJust()) {
- // a. Assert: tag matches the unicode_locale_id production.
- // b. Set tag to tag with the substring corresponding to the
- // unicode_language_subtag production replaced by the string language.
- tokens[0] = language_str.get();
- }
-
+ // a. Assert: tag matches the unicode_locale_id production.
+ // b. Set tag to tag with the substring corresponding to the
+ // unicode_language_subtag production replaced by the string language.
// 11. If script is not undefined, then
- if (maybe_script.FromJust()) {
- // a. If tag does not contain a unicode_script_subtag production, then
- if (tokens.size() < 2 || !IsUnicodeScriptSubtag(tokens[1])) {
- // i. Set tag to the concatenation of the unicode_language_subtag
- // production of tag, "-", script, and the rest of tag.
- tokens.insert(tokens.begin() + 1, script_str.get());
- // b. Else,
- } else {
- // i. Set tag to tag with the substring corresponding to the
- // unicode_script_subtag production replaced by the string script.
- tokens[1] = script_str.get();
- }
- }
+ // a. If tag does not contain a unicode_script_subtag production, then
+ // i. Set tag to the concatenation of the unicode_language_subtag
+ // production of tag, "-", script, and the rest of tag.
+ // b. Else,
+ // i. Set tag to tag with the substring corresponding to the
+ // unicode_script_subtag production replaced by the string script.
// 12. If region is not undefined, then
- if (maybe_region.FromJust()) {
- // a. If tag does not contain a unicode_region_subtag production, then
- // i. Set tag to the concatenation of the unicode_language_subtag
- // production of tag, the substring corresponding to the "-"
- // unicode_script_subtag production if present, "-", region, and
- // the rest of tag.
- // b. Else,
- // i. Set tag to tag with the substring corresponding to the
- // unicode_region_subtag production replaced by the string region.
- if (tokens.size() > 1 && IsUnicodeRegionSubtag(tokens[1])) {
- tokens[1] = region_str.get();
- } else if (tokens.size() > 1 && IsUnicodeScriptSubtag(tokens[1])) {
- if (tokens.size() > 2 && IsUnicodeRegionSubtag(tokens[2])) {
- tokens[2] = region_str.get();
- } else {
- tokens.insert(tokens.begin() + 2, region_str.get());
- }
- } else {
- tokens.insert(tokens.begin() + 1, region_str.get());
- }
- }
-
- std::string replaced;
- for (auto it = tokens.begin(); it != tokens.end(); it++) {
- replaced += *it;
- if (it + 1 != tokens.end()) {
- replaced += '-';
- }
- }
-
+ // a. If tag does not contain a unicode_region_subtag production, then
+ // i. Set tag to the concatenation of the unicode_language_subtag
+ // production of tag, the substring corresponding to the "-"
+ // unicode_script_subtag production if present, "-", region, and
+ // the rest of tag.
+ // b. Else,
+ // i. Set tag to tag with the substring corresponding to the
+ // unicode_region_subtag production replaced by the string region.
// 13. Return CanonicalizeLanguageTag(tag).
- return Intl::CanonicalizeLanguageTag(isolate, replaced);
+ return Just(true);
}
} // namespace
@@ -393,21 +317,22 @@ MaybeHandle<JSLocale> JSLocale::Initialize(Isolate* isolate,
Handle<JSLocale> locale,
Handle<String> locale_str,
Handle<JSReceiver> options) {
- Maybe<std::string> maybe_locale =
- ApplyOptionsToTag(isolate, locale_str, options);
- MAYBE_RETURN(maybe_locale, MaybeHandle<JSLocale>());
- UErrorCode status = U_ZERO_ERROR;
- icu::Locale icu_locale =
- icu::Locale::forLanguageTag(maybe_locale.FromJust().c_str(), status);
- if (U_FAILURE(status)) {
+ icu::LocaleBuilder builder;
+ Maybe<bool> maybe_apply =
+ ApplyOptionsToTag(isolate, locale_str, options, &builder);
+ MAYBE_RETURN(maybe_apply, MaybeHandle<JSLocale>());
+ if (!maybe_apply.FromJust()) {
THROW_NEW_ERROR(isolate,
NewRangeError(MessageTemplate::kLocaleBadParameters),
JSLocale);
}
- Maybe<bool> error = InsertOptionsIntoLocale(isolate, options, &icu_locale);
- MAYBE_RETURN(error, MaybeHandle<JSLocale>());
- if (!error.FromJust()) {
+ Maybe<bool> maybe_insert =
+ InsertOptionsIntoLocale(isolate, options, &builder);
+ MAYBE_RETURN(maybe_insert, MaybeHandle<JSLocale>());
+ UErrorCode status = U_ZERO_ERROR;
+ icu::Locale icu_locale = builder.build(status);
+ if (!maybe_insert.FromJust() || U_FAILURE(status)) {
THROW_NEW_ERROR(isolate,
NewRangeError(MessageTemplate::kLocaleBadParameters),
JSLocale);
@@ -458,28 +383,28 @@ Handle<String> JSLocale::Minimize(Isolate* isolate, String locale) {
Handle<Object> JSLocale::Language(Isolate* isolate, Handle<JSLocale> locale) {
Factory* factory = isolate->factory();
- const char* language = locale->icu_locale()->raw()->getLanguage();
+ const char* language = locale->icu_locale().raw()->getLanguage();
if (strlen(language) == 0) return factory->undefined_value();
return factory->NewStringFromAsciiChecked(language);
}
Handle<Object> JSLocale::Script(Isolate* isolate, Handle<JSLocale> locale) {
Factory* factory = isolate->factory();
- const char* script = locale->icu_locale()->raw()->getScript();
+ const char* script = locale->icu_locale().raw()->getScript();
if (strlen(script) == 0) return factory->undefined_value();
return factory->NewStringFromAsciiChecked(script);
}
Handle<Object> JSLocale::Region(Isolate* isolate, Handle<JSLocale> locale) {
Factory* factory = isolate->factory();
- const char* region = locale->icu_locale()->raw()->getCountry();
+ const char* region = locale->icu_locale().raw()->getCountry();
if (strlen(region) == 0) return factory->undefined_value();
return factory->NewStringFromAsciiChecked(region);
}
Handle<String> JSLocale::BaseName(Isolate* isolate, Handle<JSLocale> locale) {
icu::Locale icu_locale =
- icu::Locale::createFromName(locale->icu_locale()->raw()->getBaseName());
+ icu::Locale::createFromName(locale->icu_locale().raw()->getBaseName());
std::string base_name = Intl::ToLanguageTag(icu_locale).FromJust();
return isolate->factory()->NewStringFromAsciiChecked(base_name.c_str());
}
@@ -502,7 +427,7 @@ Handle<Object> JSLocale::HourCycle(Isolate* isolate, Handle<JSLocale> locale) {
Handle<Object> JSLocale::Numeric(Isolate* isolate, Handle<JSLocale> locale) {
Factory* factory = isolate->factory();
- icu::Locale* icu_locale = locale->icu_locale()->raw();
+ icu::Locale* icu_locale = locale->icu_locale().raw();
UErrorCode status = U_ZERO_ERROR;
std::string numeric =
icu_locale->getUnicodeKeywordValue<std::string>("kn", status);
@@ -515,7 +440,7 @@ Handle<Object> JSLocale::NumberingSystem(Isolate* isolate,
}
std::string JSLocale::ToString(Handle<JSLocale> locale) {
- icu::Locale* icu_locale = locale->icu_locale()->raw();
+ icu::Locale* icu_locale = locale->icu_locale().raw();
return Intl::ToLanguageTag(*icu_locale).FromJust();
}