36#pragma GCC diagnostic push
37#pragma GCC diagnostic ignored "-Wshadow"
38#include "unicode/basictz.h"
39#include "unicode/brkiter.h"
40#include "unicode/calendar.h"
41#include "unicode/coll.h"
42#include "unicode/datefmt.h"
43#include "unicode/decimfmt.h"
44#include "unicode/formattedvalue.h"
45#include "unicode/localebuilder.h"
46#include "unicode/localematcher.h"
47#include "unicode/locid.h"
48#include "unicode/normalizer2.h"
49#include "unicode/numberformatter.h"
50#include "unicode/numfmt.h"
51#include "unicode/numsys.h"
52#include "unicode/timezone.h"
53#include "unicode/ures.h"
54#include "unicode/ustring.h"
55#include "unicode/uvernum.h"
56#pragma GCC diagnostic pop
58#ifndef V8_INTL_SUPPORT
59#error Internationalization is expected to be enabled.
74inline constexpr uint8_t AsOneByte(uint16_t ch) {
76 return static_cast<uint8_t
>(ch);
79constexpr uint8_t kToLower[256] = {
80 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
81 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
82 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23,
83 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
84 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B,
85 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
86 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73,
87 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
88 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B,
89 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
90 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, 0x80, 0x81, 0x82, 0x83,
91 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
92 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B,
93 0x9C, 0x9D, 0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7,
94 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3,
95 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,
96 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB,
97 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xD7,
98 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xDF, 0xE0, 0xE1, 0xE2, 0xE3,
99 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
100 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB,
101 0xFC, 0xFD, 0xFE, 0xFF,
104inline constexpr uint8_t ToLatin1Lower(uint8_t ch) {
105 static_assert(std::numeric_limits<
decltype(ch)>::max() <
arraysize(kToLower));
109inline constexpr uint8_t ToLatin1Lower(uint16_t ch) =
delete;
113inline constexpr uint8_t ToLatin1Upper(uint8_t ch) {
114 DCHECK(ch != 0xDF && ch != 0xB5 && ch != 0xFF);
116 ~((
IsAsciiLower(ch) || (((ch & 0xE0) == 0xE0) && ch != 0xF7)) << 5);
119inline constexpr uint8_t ToLatin1Upper(uint16_t ch) =
delete;
121bool ToUpperFastASCII(base::Vector<const uint16_t> src,
122 DirectHandle<SeqOneByteString>
result) {
126 for (
const uint16_t* it = src.begin(); it != src.end(); ++it) {
131 return !(ored & ~0x7F);
134const uint16_t sharp_s = 0xDF;
136template <
typename Char>
137bool ToUpperOneByte(base::Vector<const Char> src, uint8_t* dest,
138 int* sharp_s_count) {
145 for (
auto it = src.begin(); it != src.end(); ++it) {
146 uint8_t ch = AsOneByte(*it);
156 *dest++ = ToLatin1Upper(ch);
162template <
typename Char>
163void ToUpperWithSharpS(base::Vector<const Char> src,
164 DirectHandle<SeqOneByteString>
result) {
165 int32_t dest_index = 0;
166 for (
auto it = src.begin(); it != src.end(); ++it) {
167 uint8_t ch = AsOneByte(*it);
169 result->SeqOneByteStringSet(dest_index++,
'S');
170 result->SeqOneByteStringSet(dest_index++,
'S');
172 result->SeqOneByteStringSet(dest_index++, ToLatin1Upper(ch));
177inline int FindFirstUpperOrNonAscii(
Tagged<String> s,
int length) {
179 uint16_t ch = s->Get(index);
187const UChar* GetUCharBufferFromFlat(
const String::FlatContent& flat,
191 if (flat.IsOneByte()) {
194 CopyChars(dest->get(), flat.ToOneByteVector().begin(), length);
196 return reinterpret_cast<const UChar*
>(dest->get());
198 return reinterpret_cast<const UChar*
>(flat.ToUC16Vector().begin());
203MaybeDirectHandle<T> New(Isolate* isolate, DirectHandle<JSFunction> constructor,
204 DirectHandle<Object> locales,
205 DirectHandle<Object> options,
206 const char* method_name) {
207 DirectHandle<Map>
map;
211 return T::New(isolate, map, locales, options, method_name);
222 std::unique_ptr<base::uc16[]> sap;
225 constexpr unsigned int kShortStringSize = 80;
226 UChar short_string_buffer[kShortStringSize];
227 const UChar* uchar_buffer =
nullptr;
232 uint32_t length =
string->
length();
234 if (flat.
IsOneByte() && length <= kShortStringSize) {
236 uchar_buffer = short_string_buffer;
238 uchar_buffer = GetUCharBufferFromFlat(flat, &sap, length);
240 return icu::UnicodeString(uchar_buffer +
offset, length -
offset);
251 if (!flat.
IsOneByte())
return icu::StringPiece();
253 int32_t length =
string->length();
254 const char* char_buffer =
257 return icu::StringPiece();
260 return icu::StringPiece(char_buffer +
offset, length -
offset);
263MaybeHandle<String> LocaleConvertCase(Isolate* isolate, DirectHandle<String> s,
264 bool is_to_upper,
const char* lang) {
265 auto case_converter = is_to_upper ? u_strToUpper : u_strToLower;
266 uint32_t src_length = s->length();
267 uint32_t dest_length = src_length;
270 std::unique_ptr<base::uc16[]> sap;
272 if (dest_length == 0)
return isolate->factory()->empty_string();
276 for (
int i = 0;
i < 2; ++
i) {
280 isolate,
result, isolate->factory()->NewRawTwoByteString(dest_length));
283 String::FlatContent flat = s->GetFlatContent(no_gc);
284 const UChar* src = GetUCharBufferFromFlat(flat, &sap, src_length);
285 status = U_ZERO_ERROR;
287 case_converter(
reinterpret_cast<UChar*
>(
result->GetChars(no_gc)),
288 dest_length, src, src_length, lang, &status);
289 if (status != U_BUFFER_OVERFLOW_ERROR)
break;
296 DCHECK(U_SUCCESS(status));
297 if (
V8_LIKELY(status == U_STRING_NOT_TERMINATED_WARNING)) {
314 DCHECK(src->IsOneByteRepresentation());
316 DCHECK(IsSeqOneByteString(dst));
320 const int length = src->length();
328 reinterpret_cast<char*
>(dst_data),
329 reinterpret_cast<const char*
>(src_data), length);
331 if (ascii_prefix_length == length)
return dst;
335 for (
int index = ascii_prefix_length; index <
length; ++
index) {
336 dst_data[
index] = ToLatin1Lower(src_data[index]);
340 int index_to_first_unprocessed = FindFirstUpperOrNonAscii(src, length);
341 if (index_to_first_unprocessed == length)
return src;
344 CopyChars(dst_data, src_data, index_to_first_unprocessed);
345 for (
int index = index_to_first_unprocessed; index <
length; ++
index) {
350 dst_data[
index] = ToLatin1Lower(AsOneByte(src_data[index]));
359 if (!s->IsOneByteRepresentation()) {
361 return LocaleConvertCase(isolate, s,
false,
"");
364 int length = s->length();
379 bool is_lower_ascii = FindFirstUpperOrNonAscii(*s, length) ==
length;
384 isolate->factory()->NewRawOneByteString(length).ToHandleChecked();
391 uint32_t length = s->length();
392 if (s->IsOneByteRepresentation() && length > 0) {
400 if (prefix == length) {
405 isolate->factory()->NewRawOneByteString(length).ToHandleChecked();
409 bool is_result_single_byte;
413 uint8_t* dest =
result->GetChars(no_gc);
416 std::memcpy(
result->GetChars(no_gc), src.begin(), prefix);
417 uint32_t ascii_prefix_length =
419 reinterpret_cast<char*
>(
result->GetChars(no_gc)) + prefix,
420 reinterpret_cast<const char*
>(src.begin()) + prefix,
423 if (ascii_prefix_length == length)
return result;
426 is_result_single_byte =
427 ToUpperOneByte(src.SubVector(ascii_prefix_length, length),
428 dest + ascii_prefix_length, &sharp_s_count);
433 is_result_single_byte = ToUpperOneByte(src, dest, &sharp_s_count);
440 return LocaleConvertCase(isolate, s,
true,
"");
443 if (sharp_s_count == 0)
return result;
449 isolate->factory()->NewRawOneByteString(length + sharp_s_count));
461 return LocaleConvertCase(isolate, s,
true,
"");
468 UErrorCode status = U_ZERO_ERROR;
469 std::unique_ptr<icu::NumberingSystem> numbering_system(
470 icu::NumberingSystem::createInstance(icu_locale, status));
471 if (U_SUCCESS(status) && !numbering_system->isAlgorithmic()) {
472 return numbering_system->getName();
483 UErrorCode status = U_ZERO_ERROR;
485 icu::Locale icu_locale = icu::Locale::forLanguageTag(bcp47_locale, status);
486 if (U_FAILURE(status) || icu_locale.isBogus()) {
490 return Just(icu_locale);
498 const icu::UnicodeString&
string) {
500 reinterpret_cast<const uint16_t*
>(
string.getBuffer()),
string.
length()));
504 const icu::UnicodeString&
string,
505 int32_t begin, int32_t
end) {
520 Factory* factory = isolate->factory();
523 field_type_string,
NONE);
529 FATAL(
"Fatal JavaScript invalid size error when adding element");
541 InnerAddElement(isolate, array, index, field_type_string, value);
554 InnerAddElement(isolate, array, index, field_type_string, value);
556 additional_property_value,
NONE);
565bool RemoveLocaleScriptTag(
const std::string& icu_locale,
566 std::string* locale_less_script) {
567 icu::Locale new_locale = icu::Locale::createCanonical(icu_locale.c_str());
568 const char* icu_script = new_locale.getScript();
569 if (icu_script ==
nullptr || strlen(icu_script) == 0) {
570 *locale_less_script = std::string();
574 const char* icu_language = new_locale.getLanguage();
575 const char* icu_country = new_locale.getCountry();
576 icu::Locale short_locale = icu::Locale(icu_language, icu_country);
577 *locale_less_script = short_locale.getName();
581bool ValidateResource(
const icu::Locale locale,
const char* path,
584 UErrorCode status = U_ZERO_ERROR;
585 UResourceBundle* bundle = ures_open(path, locale.getName(), &status);
586 if (bundle !=
nullptr && status == U_ZERO_ERROR) {
587 if (
key ==
nullptr) {
590 UResourceBundle* key_bundle =
591 ures_getByKey(bundle,
key,
nullptr, &status);
592 result = key_bundle !=
nullptr && (status == U_ZERO_ERROR);
593 ures_close(key_bundle);
598 if ((locale.getCountry()[0] !=
'\0') && (locale.getScript()[0] !=
'\0')) {
600 std::string without_country(locale.getLanguage());
601 without_country = without_country.append(
"-").append(locale.getScript());
602 return ValidateResource(without_country.c_str(), path,
key);
603 }
else if ((locale.getCountry()[0] !=
'\0') ||
604 (locale.getScript()[0] !=
'\0')) {
606 std::string language(locale.getLanguage());
607 return ValidateResource(language.c_str(), path,
key);
616 const std::vector<std::string>& icu_available_locales,
const char* path,
617 const char* validate_key) {
618 std::set<std::string> locales;
619 for (
const std::string& locale : icu_available_locales) {
620 if (path !=
nullptr || validate_key !=
nullptr) {
621 if (!ValidateResource(icu::Locale(locale.c_str()), path, validate_key)) {
623 if (locale !=
"nb") {
627 if (!ValidateResource(icu::Locale(
"no"), path, validate_key)) {
632 locales.insert(locale);
633 std::string shortened_locale;
634 if (RemoveLocaleScriptTag(locale, &shortened_locale)) {
635 std::replace(shortened_locale.begin(), shortened_locale.end(),
'_',
'-');
636 locales.insert(shortened_locale);
643 UErrorCode status = U_ZERO_ERROR;
644 std::string res = locale.toLanguageTag<std::string>(
status);
645 if (U_FAILURE(status)) {
648 DCHECK(U_SUCCESS(status));
658 isolate, obj_ordinary_has_instance,
660 bool ordinary_has_instance =
665 if (!has_initialized_slot && ordinary_has_instance) {
669 isolate, new_receiver,
671 isolate->factory()->intl_fallback_symbol()));
680bool IsTwoLetterLanguage(
const std::string& locale) {
682 return locale.length() == 2 &&
IsAsciiLower(locale[0]) &&
686bool IsDeprecatedOrLegacyLanguage(
const std::string& locale) {
688 return locale ==
"in" || locale ==
"iw" || locale ==
"ji" || locale ==
"jw" ||
691 locale ==
"sh" || locale ==
"tl" || locale ==
"no";
694bool IsStructurallyValidLanguageTag(
const std::string& tag) {
701Maybe<std::string> CanonicalizeLanguageTag(Isolate* isolate,
702 const std::string& locale_in) {
703 std::string locale = locale_in;
705 if (locale.empty() ||
710 MessageTemplate::kInvalidLanguageTag,
711 isolate->factory()->NewStringFromAsciiChecked(locale.c_str())),
720 if ((IsTwoLetterLanguage(locale) && !IsDeprecatedOrLegacyLanguage(locale)) ||
727 std::transform(locale.begin(), locale.end(), locale.begin(),
ToAsciiLower);
736 UErrorCode error = U_ZERO_ERROR;
741 icu::Locale icu_locale = icu::Locale::forLanguageTag(locale.c_str(), error);
743 if (U_FAILURE(error) || icu_locale.isBogus()) {
747 MessageTemplate::kInvalidLanguageTag,
748 isolate->factory()->NewStringFromAsciiChecked(locale.c_str())),
753 icu_locale = icu::LocaleBuilder().setLocale(icu_locale).build(error);
754 icu_locale.canonicalize(error);
755 if (U_FAILURE(error) || icu_locale.isBogus()) {
759 MessageTemplate::kInvalidLanguageTag,
760 isolate->factory()->NewStringFromAsciiChecked(locale.c_str())),
764 if (maybe_to_language_tag.IsNothing()) {
768 MessageTemplate::kInvalidLanguageTag,
769 isolate->factory()->NewStringFromAsciiChecked(locale.c_str())),
773 return maybe_to_language_tag;
776Maybe<std::string> CanonicalizeLanguageTag(Isolate* isolate,
777 DirectHandle<Object> locale_in) {
778 DirectHandle<String> locale_str;
786 if (IsString(*locale_in)) {
788 }
else if (IsJSReceiver(*locale_in)) {
794 NewTypeError(MessageTemplate::kLanguageID),
797 std::string locale(locale_str->ToCString().get());
799 if (!IsStructurallyValidLanguageTag(locale)) {
801 isolate, NewRangeError(MessageTemplate::kLocaleBadParameters),
804 return CanonicalizeLanguageTag(isolate, locale);
811 bool only_return_one_result) {
813 if (IsUndefined(*locales, isolate)) {
815 return Just(std::vector<std::string>());
818 std::vector<std::string> seen;
821 if (IsJSLocale(*locales)) {
828 if (IsString(*locales)) {
832 std::string canonicalized_tag;
833 if (!CanonicalizeLanguageTag(isolate, locales).To(&canonicalized_tag)) {
836 seen.push_back(canonicalized_tag);
844 Nothing<std::vector<std::string>>());
849 Nothing<std::vector<std::string>>());
859 for (uint32_t k = 0; k < len; k++) {
866 if (!maybe_found.
FromJust())
continue;
870 Nothing<std::vector<std::string>>());
875 std::string canonicalized_tag;
876 if (IsJSLocale(*k_value)) {
885 if (!CanonicalizeLanguageTag(isolate, k_value).To(&canonicalized_tag)) {
891 if (std::find(seen.begin(), seen.end(), canonicalized_tag) == seen.end()) {
892 seen.push_back(canonicalized_tag);
896 if (only_return_one_result)
return Just(seen);
907 std::vector<std::string> requested_locales;
910 std::string requested_locale = requested_locales.empty()
911 ? isolate->DefaultLocale()
912 : requested_locales[0];
913 size_t dash = requested_locale.find(
'-');
914 if (dash != std::string::npos) {
915 requested_locale = requested_locale.substr(0, dash);
937 if (
V8_UNLIKELY((requested_locale ==
"tr") || (requested_locale ==
"el") ||
938 (requested_locale ==
"lt") || (requested_locale ==
"az"))) {
939 return LocaleConvertCase(isolate, s, to_upper, requested_locale.c_str());
949template <
class IsolateT>
953 if (!IsUndefined(*options, isolate)) {
965 static const char*
const kFastLocales[] = {
966 "en-US",
"en",
"fr",
"es",
"de",
"pt",
"it",
"ca",
967 "de-AT",
"fi",
"id",
"id-ID",
"ms",
"nl",
"pl",
"ro",
968 "sl",
"sv",
"sw",
"vi",
"en-DE",
"en-GB",
971 if (IsUndefined(*locales, isolate)) {
972 const std::string& default_locale = isolate->DefaultLocale();
973 for (
const char* fast_locale : kFastLocales) {
974 if (strcmp(fast_locale, default_locale.c_str()) == 0) {
985 for (
const char* fast_locale : kFastLocales) {
1005 const char* method_name) {
1009 const bool can_cache =
1010 (IsString(*locales) || IsUndefined(*locales, isolate)) &&
1011 IsUndefined(*options, isolate);
1018 icu::Collator* cached_icu_collator =
1019 static_cast<icu::Collator*
>(isolate->get_cached_icu_object(
1020 Isolate::ICUObjectCacheType::kDefaultCollator, locales));
1022 if (cached_icu_collator !=
nullptr) {
1024 string2, compare_strings_options);
1030 isolate->context()->native_context()->intl_collator_function()),
1035 New<JSCollator>(isolate, constructor, locales, options, method_name);
1036 if (!maybe_collator.
ToHandle(&collator))
return {};
1038 isolate->set_icu_object_in_cache(
1039 Isolate::ICUObjectCacheType::kDefaultCollator, locales,
1040 std::static_pointer_cast<icu::UMemory>(
1041 collator->icu_collator()->get()));
1043 icu::Collator* icu_collator = collator->icu_collator()->raw();
1045 compare_strings_options);
1091constexpr uint8_t kCollationWeightsL1[256] = {
1092 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 0, 0,
1093 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1094 6, 12, 16, 28, 38, 29, 27, 15, 17, 18, 24, 32, 9, 8, 14, 25,
1095 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 11, 10, 33, 34, 35, 13,
1096 23, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
1097 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 19, 26, 20, 31, 7,
1098 30, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
1099 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 21, 36, 22, 37, 0,
1101constexpr uint8_t kCollationWeightsL3[256] = {
1102 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0,
1103 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1104 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1105 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1106 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
1107 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1,
1108 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1109 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
1111constexpr int kCollationWeightsLength =
arraysize(kCollationWeightsL1);
1112static_assert(kCollationWeightsLength ==
arraysize(kCollationWeightsL3));
1117constexpr UCollationResult ToUCollationResult(
int delta) {
1118 return delta < 0 ? UCollationResult::UCOL_LESS
1119 : (delta > 0 ? UCollationResult::UCOL_GREATER
1120 : UCollationResult::UCOL_EQUAL);
1123struct FastCompareStringsData {
1130 std::optional<UCollationResult> FastCompareFailed(
1131 int* processed_until_out)
const {
1146template <
class CharT>
1147constexpr bool CanFastCompare(CharT c) {
1148 return c < kCollationWeightsLength && kCollationWeightsL1[c] != 0;
1151template <
class Char1T,
class Char2T>
1152bool FastCompareFlatString(
const Char1T* lhs,
const Char2T* rhs,
int length,
1153 FastCompareStringsData* d) {
1155 const Char1T l = lhs[
i];
1156 const Char2T
r = rhs[
i];
1157 if (!CanFastCompare(l) || !CanFastCompare(
r)) {
1158 d->processed_until =
i;
1162 ToUCollationResult(kCollationWeightsL1[l] - kCollationWeightsL1[
r]);
1163 if (
l1_result != UCollationResult::UCOL_EQUAL) {
1165 d->first_diff_at =
i;
1166 d->processed_until =
i;
1170 if (l !=
r && d->l3_result == UCollationResult::UCOL_EQUAL) {
1175 ToUCollationResult(kCollationWeightsL3[l] - kCollationWeightsL3[
r]);
1179 d->first_diff_at =
i;
1183 d->processed_until =
length;
1187bool FastCompareStringFlatContent(
const String::FlatContent& lhs,
1188 const String::FlatContent& rhs,
int length,
1189 FastCompareStringsData* d) {
1190 if (lhs.IsOneByte()) {
1191 base::Vector<const uint8_t> l = lhs.ToOneByteVector();
1192 if (rhs.IsOneByte()) {
1193 base::Vector<const uint8_t>
r = rhs.ToOneByteVector();
1194 return FastCompareFlatString(l.data(),
r.data(), length, d);
1196 base::Vector<const uint16_t>
r = rhs.ToUC16Vector();
1197 return FastCompareFlatString(l.data(),
r.data(), length, d);
1200 base::Vector<const uint16_t> l = lhs.ToUC16Vector();
1201 if (rhs.IsOneByte()) {
1202 base::Vector<const uint8_t>
r = rhs.ToOneByteVector();
1203 return FastCompareFlatString(l.data(),
r.data(), length, d);
1205 base::Vector<const uint16_t>
r = rhs.ToUC16Vector();
1206 return FastCompareFlatString(l.data(),
r.data(), length, d);
1212bool CharIsAsciiOrOutOfBounds(
const String::FlatContent&
string,
1213 int string_length,
int index) {
1215 return index >= string_length || isascii(
string.
Get(index));
1218bool CharCanFastCompareOrOutOfBounds(
const String::FlatContent&
string,
1219 int string_length,
int index) {
1221 return index >= string_length || CanFastCompare(
string.
Get(index));
1225bool USetContainsAllAsciiItem(USet* set) {
1226 static constexpr int kBufferSize = 64;
1227 UChar buffer[kBufferSize];
1229 const int length = uset_getItemCount(set);
1232 UErrorCode status = U_ZERO_ERROR;
1233 const int item_length =
1234 uset_getItem(set,
i, &
start, &
end, buffer, kBufferSize, &status);
1235 CHECK(U_SUCCESS(status));
1238 if (item_length == 0) {
1240 if (isascii(
start))
return true;
1243 bool all_ascii =
true;
1244 for (
int j = 0; j < item_length; j++) {
1245 if (!isascii(buffer[j])) {
1251 if (all_ascii)
return true;
1258bool CollatorAllowsFastComparison(
const icu::Collator& icu_collator) {
1259 UErrorCode status = U_ZERO_ERROR;
1261 icu::Locale icu_locale(icu_collator.getLocale(ULOC_VALID_LOCALE, status));
1262 DCHECK(U_SUCCESS(status));
1264 static constexpr int kBufferSize = 64;
1265 char buffer[kBufferSize];
1266 const int collation_keyword_length =
1267 icu_locale.getKeywordValue(
"collation", buffer, kBufferSize, status);
1268 DCHECK(U_SUCCESS(status));
1269 if (collation_keyword_length != 0)
return false;
1272 static constexpr struct {
1273 UColAttribute attribute;
1274 UColAttributeValue legal_value;
1275 } kAttributeChecks[] = {
1276 {UCOL_ALTERNATE_HANDLING, UCOL_NON_IGNORABLE},
1277 {UCOL_CASE_FIRST, UCOL_OFF},
1278 {UCOL_CASE_LEVEL, UCOL_OFF},
1279 {UCOL_FRENCH_COLLATION, UCOL_OFF},
1280 {UCOL_NUMERIC_COLLATION, UCOL_OFF},
1281 {UCOL_STRENGTH, UCOL_TERTIARY},
1284 for (
const auto& check : kAttributeChecks) {
1285 if (icu_collator.getAttribute(check.attribute, status) !=
1286 check.legal_value) {
1289 DCHECK(U_SUCCESS(status));
1293 int num_reorder_codes =
1294 ucol_getReorderCodes(icu_collator.toUCollator(),
nullptr, 0, &status);
1295 if (num_reorder_codes != 0)
return false;
1296 DCHECK(U_SUCCESS(status));
1300 ucol_getRules(icu_collator.toUCollator(), &rules_length);
1301 if (rules_length != 0)
return false;
1303 USet* tailored_set = ucol_getTailoredSet(icu_collator.toUCollator(), &status);
1304 DCHECK(U_SUCCESS(status));
1305 if (USetContainsAllAsciiItem(tailored_set))
return false;
1306 uset_close(tailored_set);
1309 USet* contractions = uset_openEmpty();
1310 USet* expansions = uset_openEmpty();
1311 ucol_getContractionsAndExpansions(icu_collator.toUCollator(), contractions,
1312 expansions,
true, &status);
1313 if (USetContainsAllAsciiItem(contractions))
return false;
1314 if (USetContainsAllAsciiItem(expansions))
return false;
1315 DCHECK(U_SUCCESS(status));
1316 uset_close(contractions);
1317 uset_close(expansions);
1372std::optional<UCollationResult> TryFastCompareStrings(
1373 Isolate* isolate,
const icu::Collator& icu_collator,
1374 DirectHandle<String> string1, DirectHandle<String> string2,
1375 int* processed_until_out) {
1380 DCHECK(string1->IsFlat());
1381 DCHECK(string2->IsFlat());
1383 *processed_until_out = 0;
1387 SLOW_DCHECK(CollatorAllowsFastComparison(icu_collator));
1388 USE(CollatorAllowsFastComparison);
1394 const int length1 = string1->length();
1395 const int length2 = string2->length();
1396 int common_length = std::min(length1, length2);
1398 FastCompareStringsData d;
1400 const String::FlatContent& flat1 = string1->GetFlatContent(no_gc);
1401 const String::FlatContent& flat2 = string2->GetFlatContent(no_gc);
1402 if (!FastCompareStringFlatContent(flat1, flat2, common_length, &d)) {
1403 DCHECK_EQ(d.l1_result, UCollationResult::UCOL_EQUAL);
1404 return d.FastCompareFailed(processed_until_out);
1410 if (!CharIsAsciiOrOutOfBounds(flat1, length1, d.processed_until + 1) ||
1411 !CharIsAsciiOrOutOfBounds(flat2, length2, d.processed_until + 1)) {
1412 return d.FastCompareFailed(processed_until_out);
1415 if (d.l1_result != UCollationResult::UCOL_EQUAL) {
1420 UCollationResult length_result = ToUCollationResult(length1 - length2);
1421 if (length_result != UCollationResult::UCOL_EQUAL) {
1424 if (!CharCanFastCompareOrOutOfBounds(flat1, length1, common_length) ||
1425 !CharCanFastCompareOrOutOfBounds(flat2, length2, common_length)) {
1426 return d.FastCompareFailed(processed_until_out);
1428 return length_result;
1439 return &kCollationWeightsL1[0];
1444 return &kCollationWeightsL3[0];
1457 return UCollationResult::UCOL_EQUAL;
1468 std::optional<int> maybe_result = TryFastCompareStrings(
1470 if (maybe_result.has_value())
return maybe_result.value();
1474 UErrorCode status = U_ZERO_ERROR;
1475 icu::StringPiece string_piece1 =
1477 if (!string_piece1.empty()) {
1478 icu::StringPiece string_piece2 =
1480 if (!string_piece2.empty()) {
1481 result = icu_collator.compareUTF8(string_piece1, string_piece2, status);
1482 DCHECK(U_SUCCESS(status));
1487 icu::UnicodeString string_val1 =
1489 icu::UnicodeString string_val2 =
1491 result = icu_collator.compare(string_val1, string_val2, status);
1492 DCHECK(U_SUCCESS(status));
1507 bool can_cache = (IsString(*locales) || IsUndefined(*locales, isolate)) &&
1508 IsUndefined(*options, isolate);
1510 icu::number::LocalizedNumberFormatter* cached_number_format =
1511 static_cast<icu::number::LocalizedNumberFormatter*
>(
1512 isolate->get_cached_icu_object(
1513 Isolate::ICUObjectCacheType::kDefaultNumberFormat, locales));
1515 if (cached_number_format !=
nullptr) {
1523 isolate->context()->native_context()->intl_number_format_function()),
1529 const int kStackSpaceRequiredForNewJSNumberFormat = 16 *
KB;
1530 if (stack_check.
JsHasOverflowed(kStackSpaceRequiredForNewJSNumberFormat)) {
1531 isolate->StackOverflow();
1535 isolate, number_format,
1536 New<JSNumberFormat>(isolate, constructor, locales, options, method_name));
1539 isolate->set_icu_object_in_cache(
1540 Isolate::ICUObjectCacheType::kDefaultNumberFormat, locales,
1541 std::static_pointer_cast<icu::UMemory>(
1542 number_format->icu_number_formatter()->get()));
1546 icu::number::LocalizedNumberFormatter* icu_number_format =
1547 number_format->icu_number_formatter()->raw();
1556bool IsValidRoundingIncrement(
int value) {
1583 int mxfd_default,
bool notation_is_compact,
const char* service) {
1584 Factory* factory = isolate->factory();
1590 if (!
GetNumberOption(isolate, options, factory->minimumIntegerDigits_string(),
1601 factory->minimumFractionDigits_string()),
1609 factory->maximumFractionDigits_string()),
1617 factory->minimumSignificantDigits_string()),
1625 factory->maximumSignificantDigits_string()),
1638 isolate, options, factory->roundingIncrement_string(), 1, 5000, 1);
1647 NewRangeError(MessageTemplate::kPropertyValueOutOfRange,
1648 factory->roundingIncrement_string()),
1656 isolate, options,
"roundingMode", service,
1657 {
"ceil",
"floor",
"expand",
"trunc",
"halfCeil",
"halfFloor",
1658 "halfExpand",
"halfTrunc",
"halfEven"},
1672 isolate, options,
"roundingPriority", service,
1673 {
"auto",
"morePrecision",
"lessPrecision"},
1684 isolate, options,
"trailingZeroDisplay", service,
1685 {
"auto",
"stripIfInteger"},
1701 (!IsUndefined(*mnsd_obj, isolate)) || (!IsUndefined(*mxsd_obj, isolate));
1708 (!IsUndefined(*mnfd_obj, isolate)) || (!IsUndefined(*mxfd_obj, isolate));
1711 bool need_sd =
true;
1713 bool need_fd =
true;
1719 if (need_sd || ((!has_fd) && notation_is_compact)) {
1732 factory->minimumSignificantDigits_string())
1742 factory->maximumSignificantDigits_string())
1775 if (IsUndefined(*mnfd_obj, isolate)) {
1776 mnfd = std::min(mnfd_default, mxfd);
1777 }
else if (IsUndefined(*mxfd_obj, isolate)) {
1780 mxfd = std::max(mxfd_default, mnfd);
1781 }
else if (mnfd > mxfd) {
1786 NewRangeError(MessageTemplate::kPropertyValueOutOfRange, mxfd_str),
1802 if ((!need_sd) && (!need_fd)) {
1824 }
else if (has_sd) {
1838 isolate, NewTypeError(MessageTemplate::kBadRoundingType),
1847 NewRangeError(MessageTemplate::kPropertyValueOutOfRange, mxfd_str),
1851 return Just(digit_options);
1857std::string BestAvailableLocale(
const std::set<std::string>& available_locales,
1858 const std::string& locale) {
1860 std::string candidate = locale;
1866 if (available_locales.find(candidate) != available_locales.end()) {
1873 size_t pos = candidate.rfind(
'-');
1874 if (
pos == std::string::npos) {
1875 return std::string();
1880 if (
pos >= 2 && candidate[
pos - 2] ==
'-') {
1886 candidate = candidate.substr(0,
pos);
1890struct ParsedLocale {
1900ParsedLocale ParseBCP47Locale(
const std::string& locale) {
1901 size_t length = locale.length();
1902 ParsedLocale parsed_locale;
1905 if ((length > 1) && (locale[1] ==
'-')) {
1909 DCHECK(locale[0] ==
'x' || locale[0] ==
'i');
1910 parsed_locale.no_extensions_locale = locale;
1911 return parsed_locale;
1914 size_t unicode_extension_start = locale.find(
"-u-");
1917 if (unicode_extension_start == std::string::npos) {
1918 parsed_locale.no_extensions_locale = locale;
1919 return parsed_locale;
1922 size_t private_extension_start = locale.find(
"-x-");
1925 if (private_extension_start != std::string::npos &&
1926 private_extension_start < unicode_extension_start) {
1927 parsed_locale.no_extensions_locale = locale;
1928 return parsed_locale;
1931 const std::string beginning = locale.substr(0, unicode_extension_start);
1932 size_t unicode_extension_end =
length;
1937 for (
size_t i = unicode_extension_start + 1;
i < length - 2;
i++) {
1938 if (locale[
i] !=
'-')
continue;
1940 if (locale[
i + 2] ==
'-') {
1941 unicode_extension_end =
i;
1948 const std::string
end = locale.substr(unicode_extension_end);
1949 parsed_locale.no_extensions_locale = beginning +
end;
1950 parsed_locale.extension = locale.substr(
1951 unicode_extension_start, unicode_extension_end - unicode_extension_start);
1952 return parsed_locale;
1956std::vector<std::string> LookupSupportedLocales(
1957 const std::set<std::string>& available_locales,
1958 const std::vector<std::string>& requested_locales) {
1960 std::vector<std::string> subset;
1963 for (
const std::string& locale : requested_locales) {
1966 std::string no_extension_locale =
1967 ParseBCP47Locale(locale).no_extensions_locale;
1971 std::string available_locale =
1972 BestAvailableLocale(available_locales, no_extension_locale);
1976 if (!available_locale.empty()) {
1977 subset.push_back(locale);
1985icu::LocaleMatcher BuildLocaleMatcher(
1986 Isolate* isolate,
const std::set<std::string>& available_locales,
1987 UErrorCode* status) {
1988 icu::Locale default_locale =
1989 icu::Locale::forLanguageTag(isolate->DefaultLocale(), *status);
1990 icu::LocaleMatcher::Builder builder;
1991 if (U_FAILURE(*status)) {
1992 return builder.build(*status);
1994 builder.setDefaultLocale(&default_locale);
1995 for (
auto it = available_locales.begin(); it != available_locales.end();
1997 *status = U_ZERO_ERROR;
1998 icu::Locale l = icu::Locale::forLanguageTag(it->c_str(), *status);
2000 if (U_SUCCESS(*status)) {
2001 builder.addSupportedLocale(l);
2004 return builder.build(*status);
2007class Iterator :
public icu::Locale::Iterator {
2009 Iterator(std::vector<std::string>::const_iterator begin,
2010 std::vector<std::string>::const_iterator
end)
2012 ~Iterator()
override =
default;
2014 UBool hasNext()
const override {
return iter_ !=
end_; }
2016 const icu::Locale& next()
override {
2017 UErrorCode status = U_ZERO_ERROR;
2018 locale_ = icu::Locale::forLanguageTag(
iter_->c_str(), status);
2019 DCHECK(U_SUCCESS(status));
2025 std::vector<std::string>::const_iterator
iter_;
2026 std::vector<std::string>::const_iterator
end_;
2046std::string BestFitMatcher(Isolate* isolate,
2047 const std::set<std::string>& available_locales,
2048 const std::vector<std::string>& requested_locales) {
2049 UErrorCode status = U_ZERO_ERROR;
2050 Iterator iter(requested_locales.cbegin(), requested_locales.cend());
2051 std::string bestfit = BuildLocaleMatcher(isolate, available_locales, &status)
2052 .getBestMatchResult(iter, status)
2053 .makeResolvedLocale(status)
2054 .toLanguageTag<std::string>(
status);
2055 DCHECK(U_SUCCESS(status));
2061std::vector<std::string> BestFitSupportedLocales(
2062 Isolate* isolate,
const std::set<std::string>& available_locales,
2063 const std::vector<std::string>& requested_locales) {
2064 UErrorCode status = U_ZERO_ERROR;
2065 icu::LocaleMatcher matcher =
2066 BuildLocaleMatcher(isolate, available_locales, &status);
2067 std::vector<std::string>
result;
2068 if (U_SUCCESS(status)) {
2069 for (
auto it = requested_locales.cbegin(); it != requested_locales.cend();
2071 status = U_ZERO_ERROR;
2072 icu::Locale desired = icu::Locale::forLanguageTag(it->c_str(), status);
2073 icu::LocaleMatcher::Result matched =
2074 matcher.getBestMatchResult(desired, status);
2075 if (U_FAILURE(status))
continue;
2076 if (matched.getSupportedIndex() < 0)
continue;
2083 std::string bestfit = desired.toLanguageTag<std::string>(
status);
2084 if (U_FAILURE(status))
continue;
2092MaybeDirectHandle<JSArray> CreateArrayFromList(
2093 Isolate* isolate, std::vector<std::string> elements,
2095 Factory* factory = isolate->factory();
2097 DirectHandle<JSArray> array = factory->
NewJSArray(0);
2099 uint32_t length =
static_cast<uint32_t
>(elements.size());
2104 const std::string& part = elements[
i];
2105 DirectHandle<String> value =
2116MaybeDirectHandle<JSObject> SupportedLocales(
2117 Isolate* isolate,
const char* method_name,
2118 const std::set<std::string>& available_locales,
2119 const std::vector<std::string>& requested_locales,
2120 DirectHandle<Object> options) {
2121 std::vector<std::string> supported_locales;
2124 DirectHandle<JSReceiver> options_obj;
2126 isolate, options_obj,
2131 Maybe<Intl::MatcherOption> maybe_locale_matcher =
2140 v8_flags.harmony_intl_best_fit_matcher) {
2142 BestFitSupportedLocales(isolate, available_locales, requested_locales);
2148 LookupSupportedLocales(available_locales, requested_locales);
2152 return CreateArrayFromList(isolate, supported_locales,
2167 return CreateArrayFromList(isolate, maybe_ll.
FromJust(),
2174 UErrorCode status = U_ZERO_ERROR;
2175 std::unique_ptr<icu::StringEnumeration> enumeration(
2176 icu::Collator::getKeywordValues(
"collation", status));
2177 if (U_FAILURE(status)) {
2184MaybeDirectHandle<JSArray> VectorToJSArray(
2185 Isolate* isolate,
const std::vector<std::string>& array) {
2186 Factory* factory = isolate->factory();
2187 DirectHandle<FixedArray> fixed_array =
2188 factory->NewFixedArray(
static_cast<int32_t
>(array.size()));
2190 for (
const std::string& item : array) {
2191 DirectHandle<String> str = factory->NewStringFromAsciiChecked(item.c_str());
2192 fixed_array->set(index++, *str);
2194 return factory->NewJSArrayWithElements(fixed_array);
2199class ResourceAvailableCurrencies {
2201 ResourceAvailableCurrencies() {
2202 UErrorCode status = U_ZERO_ERROR;
2203 UEnumeration* uenum =
2204 ucurr_openISOCurrencies(UCURR_COMMON | UCURR_NON_DEPRECATED, &status);
2205 DCHECK(U_SUCCESS(status));
2206 const char* next =
nullptr;
2207 while (U_SUCCESS(status) &&
2208 (next = uenum_next(uenum,
nullptr, &status)) !=
nullptr) {
2211 if (strcmp(next,
"VEF") == 0)
continue;
2212 AddIfAvailable(next);
2216 AddIfAvailable(
"SVC");
2217 AddIfAvailable(
"XDR");
2218 AddIfAvailable(
"XSU");
2219 AddIfAvailable(
"ZWL");
2224 const std::vector<std::string>&
Get()
const {
return list_; }
2226 void AddIfAvailable(
const char* currency) {
2227 icu::UnicodeString
code(currency, -1, US_INV);
2228 UErrorCode status = U_ZERO_ERROR;
2231 ucurr_getName(code.getTerminatedBuffer(),
"en", UCURR_LONG_NAME,
2232 nullptr, &len, &status);
2233 if (U_SUCCESS(status) &&
2234 u_strcmp(
result, code.getTerminatedBuffer()) != 0) {
2235 list_.push_back(currency);
2243const std::vector<std::string>& GetAvailableCurrencies() {
2246 return available_currencies.Pointer()->Get();
2250MaybeDirectHandle<JSArray> AvailableCurrencies(Isolate* isolate) {
2251 return VectorToJSArray(isolate, GetAvailableCurrencies());
2254MaybeDirectHandle<JSArray> AvailableNumberingSystems(Isolate* isolate) {
2255 UErrorCode status = U_ZERO_ERROR;
2256 std::unique_ptr<icu::StringEnumeration> enumeration(
2257 icu::NumberingSystem::getAvailableNames(status));
2258 if (U_FAILURE(status)) {
2263 isolate,
"nu", enumeration.get(),
2264 [](
const char* value) {
2265 UErrorCode status = U_ZERO_ERROR;
2266 std::unique_ptr<icu::NumberingSystem> numbering_system(
2267 icu::NumberingSystem::createInstanceByName(value, status));
2269 return U_FAILURE(status) || numbering_system->isAlgorithmic();
2274MaybeDirectHandle<JSArray> AvailableTimeZones(Isolate* isolate) {
2275 UErrorCode status = U_ZERO_ERROR;
2276 std::unique_ptr<icu::StringEnumeration> enumeration(
2277 icu::TimeZone::createTimeZoneIDEnumeration(
2278 UCAL_ZONE_TYPE_CANONICAL_LOCATION,
nullptr,
nullptr, status));
2279 if (U_FAILURE(status)) {
2282 return Intl::ToJSArray(isolate,
nullptr, enumeration.get(),
nullptr,
true);
2285MaybeDirectHandle<JSArray> AvailableUnits(Isolate* isolate) {
2286 Factory* factory = isolate->factory();
2288 DirectHandle<FixedArray> fixed_array =
2289 factory->NewFixedArray(
static_cast<int32_t>(sanctioned.size()));
2291 for (
const std::string& item : sanctioned) {
2292 DirectHandle<String> str = factory->NewStringFromAsciiChecked(item.c_str());
2293 fixed_array->set(index++, *str);
2295 return factory->NewJSArrayWithElements(fixed_array);
2303 Factory* factory = isolate->factory();
2309 if (factory->calendar_string()->Equals(*key_str)) {
2314 if (factory->collation_string()->Equals(*key_str)) {
2316 return AvailableCollations(isolate);
2319 if (factory->currency_string()->Equals(*key_str)) {
2321 return AvailableCurrencies(isolate);
2324 if (factory->numberingSystem_string()->Equals(*key_str)) {
2326 return AvailableNumberingSystems(isolate);
2329 if (factory->timeZone_string()->Equals(*key_str)) {
2331 return AvailableTimeZones(isolate);
2334 if (factory->unit_string()->Equals(*key_str)) {
2336 return AvailableUnits(isolate);
2344 NewRangeError(MessageTemplate::kInvalid,
2350 Isolate* isolate,
const char* method_name,
2351 const std::set<std::string>& available_locales,
2361 return SupportedLocales(isolate, method_name, available_locales,
2362 requested_locales.
FromJust(), options);
2367template <
typename T>
2368bool IsValidExtension(
const icu::Locale& locale,
const char*
key,
2369 const std::string& value) {
2370 const char* legacy_type = uloc_toLegacyType(
key, value.c_str());
2371 if (legacy_type ==
nullptr) {
2374 UErrorCode status = U_ZERO_ERROR;
2375 std::unique_ptr<icu::StringEnumeration> enumeration(
2376 T::getKeywordValuesForLocale(
key, icu::Locale(locale.getBaseName()),
2378 if (U_FAILURE(status)) {
2382 for (
const char* item = enumeration->next(&length, status);
2383 U_SUCCESS(status) && item !=
nullptr;
2384 item = enumeration->next(&length, status)) {
2385 if (strcmp(legacy_type, item) == 0) {
2395 const std::string& value) {
2396 std::set<std::string> invalid_values = {
"standard",
"search"};
2397 if (invalid_values.find(value) != invalid_values.end())
return false;
2398 return IsValidExtension<icu::Collator>(locale,
"collation", value);
2411 const std::string& value) {
2412 return IsValidExtension<icu::Calendar>(locale,
"calendar", value);
2416 std::set<std::string> invalid_values = {
"native",
"traditio",
"finance"};
2417 if (invalid_values.find(value) != invalid_values.end())
return false;
2418 UErrorCode status = U_ZERO_ERROR;
2419 std::unique_ptr<icu::NumberingSystem> numbering_system(
2420 icu::NumberingSystem::createInstanceByName(value.c_str(), status));
2421 return U_SUCCESS(status) && numbering_system !=
nullptr &&
2422 !numbering_system->isAlgorithmic();
2427bool IsWellFormedNumberingSystem(
const std::string& value) {
2431std::map<std::string, std::string> LookupAndValidateUnicodeExtensions(
2432 icu::Locale* icu_locale,
const std::set<std::string>& relevant_keys) {
2433 std::map<std::string, std::string> extensions;
2435 UErrorCode status = U_ZERO_ERROR;
2436 icu::LocaleBuilder builder;
2437 builder.setLocale(*icu_locale).clearExtensions();
2438 std::unique_ptr<icu::StringEnumeration> keywords(
2439 icu_locale->createKeywords(status));
2440 if (U_FAILURE(status))
return extensions;
2442 if (!keywords)
return extensions;
2443 char value[ULOC_FULLNAME_CAPACITY];
2446 status = U_ZERO_ERROR;
2447 for (
const char* keyword = keywords->next(&length, status);
2448 keyword !=
nullptr; keyword = keywords->next(&length, status)) {
2452 if (U_FAILURE(status)) {
2453 status = U_ZERO_ERROR;
2457 icu_locale->getKeywordValue(keyword, value, ULOC_FULLNAME_CAPACITY, status);
2462 if (U_FAILURE(status)) {
2463 status = U_ZERO_ERROR;
2467 const char* bcp47_key = uloc_toUnicodeLocaleKey(keyword);
2469 if (bcp47_key && (relevant_keys.find(bcp47_key) != relevant_keys.end())) {
2470 const char* bcp47_value = uloc_toUnicodeLocaleType(bcp47_key, value);
2471 bool is_valid_value =
false;
2473 if (strcmp(
"ca", bcp47_key) == 0) {
2475 }
else if (strcmp(
"co", bcp47_key) == 0) {
2477 }
else if (strcmp(
"hc", bcp47_key) == 0) {
2479 std::set<std::string> valid_values = {
"h11",
"h12",
"h23",
"h24"};
2480 is_valid_value = valid_values.find(bcp47_value) != valid_values.end();
2481 }
else if (strcmp(
"lb", bcp47_key) == 0) {
2483 std::set<std::string> valid_values = {
"strict",
"normal",
"loose"};
2484 is_valid_value = valid_values.find(bcp47_value) != valid_values.end();
2485 }
else if (strcmp(
"kn", bcp47_key) == 0) {
2487 std::set<std::string> valid_values = {
"true",
"false"};
2488 is_valid_value = valid_values.find(bcp47_value) != valid_values.end();
2489 }
else if (strcmp(
"kf", bcp47_key) == 0) {
2491 std::set<std::string> valid_values = {
"upper",
"lower",
"false"};
2492 is_valid_value = valid_values.find(bcp47_value) != valid_values.end();
2493 }
else if (strcmp(
"nu", bcp47_key) == 0) {
2496 if (is_valid_value) {
2498 std::pair<std::string, std::string>(bcp47_key, bcp47_value));
2499 builder.setUnicodeLocaleKeyword(bcp47_key, bcp47_value);
2504 status = U_ZERO_ERROR;
2505 *icu_locale = builder.build(status);
2511std::string LookupMatcher(Isolate* isolate,
2512 const std::set<std::string>& available_locales,
2513 const std::vector<std::string>& requested_locales) {
2518 for (
const std::string& locale : requested_locales) {
2521 ParsedLocale parsed_locale = ParseBCP47Locale(locale);
2526 std::string available_locale =
2531 if (!available_locale.empty()) {
2548 return available_locale + parsed_locale.extension;
2555 return isolate->DefaultLocale();
2571 Isolate* isolate,
const std::set<std::string>& available_locales,
2572 const std::vector<std::string>& requested_locales,
MatcherOption matcher,
2573 const std::set<std::string>& relevant_extension_keys) {
2576 v8_flags.harmony_intl_best_fit_matcher) {
2577 locale = BestFitMatcher(isolate, available_locales, requested_locales);
2579 locale = LookupMatcher(isolate, available_locales, requested_locales);
2584 icu::Locale icu_locale = maybe_icu_locale.
FromJust();
2585 std::map<std::string, std::string> extensions =
2586 LookupAndValidateUnicodeExtensions(&icu_locale, relevant_extension_keys);
2598 icu::BreakIterator* break_iterator) {
2600 std::shared_ptr<icu::UnicodeString> u_text{
static_cast<icu::UnicodeString*
>(
2606 break_iterator->setText(*u_text);
2614 const char* form_name;
2615 UNormalization2Mode form_mode;
2616 if (IsUndefined(*form_input, isolate)) {
2619 form_mode = UNORM2_COMPOSE;
2625 if (
String::Equals(isolate, form, isolate->factory()->NFC_string())) {
2627 form_mode = UNORM2_COMPOSE;
2629 isolate->factory()->NFD_string())) {
2631 form_mode = UNORM2_DECOMPOSE;
2633 isolate->factory()->NFKC_string())) {
2635 form_mode = UNORM2_COMPOSE;
2637 isolate->factory()->NFKD_string())) {
2639 form_mode = UNORM2_DECOMPOSE;
2642 isolate->factory()->NewStringFromStaticChars(
"NFC, NFD, NFKC, NFKD");
2645 NewRangeError(MessageTemplate::kNormalizationForm, valid_forms));
2649 uint32_t length =
string->length();
2651 icu::UnicodeString
result;
2652 std::unique_ptr<base::uc16[]> sap;
2653 UErrorCode status = U_ZERO_ERROR;
2656 const icu::Normalizer2* normalizer =
2657 icu::Normalizer2::getInstance(
nullptr, form_name, form_mode, status);
2658 DCHECK(U_SUCCESS(status));
2660 uint32_t normalized_prefix_length =
2661 normalizer->spanQuickCheckYes(input, status);
2663 if (length == normalized_prefix_length)
return string;
2664 icu::UnicodeString unnormalized =
2665 input.tempSubString(normalized_prefix_length);
2667 result.setTo(
false, input.getBuffer(), normalized_prefix_length);
2669 normalizer->normalizeSecondAndAppend(
result, unnormalized, status);
2671 if (U_FAILURE(status)) {
2697 bool GetOffsets(
double time_ms,
bool is_utc, int32_t* raw_offset,
2698 int32_t* dst_offset);
2709 if (name->empty()) {
2710 icu::UnicodeString
result;
2714 icu::StringByteSink<std::string> byte_sink(name);
2715 result.toUTF8(byte_sink);
2718 return name->c_str();
2723 timezone_ = icu::TimeZone::createDefault();
2729 int32_t* raw_offset, int32_t* dst_offset) {
2730 UErrorCode status = U_ZERO_ERROR;
2732 GetTimeZone()->getOffset(time_ms,
false, *raw_offset, *dst_offset, status);
2736 static_cast<const icu::BasicTimeZone*
>(
GetTimeZone())
2737 ->getOffsetFromLocal(time_ms, UCAL_TZ_LOCAL_FORMER,
2738 UCAL_TZ_LOCAL_FORMER, *raw_offset, *dst_offset,
2742 return U_SUCCESS(status);
2746 int32_t raw_offset, dst_offset;
2747 if (!
GetOffsets(time_ms,
true, &raw_offset, &dst_offset))
return 0;
2752 int32_t raw_offset, dst_offset;
2753 if (!
GetOffsets(time_ms, is_utc, &raw_offset, &dst_offset))
return 0;
2754 return raw_offset + dst_offset;
2763 icu::TimeZone::adoptDefault(icu::TimeZone::detectHostTimeZone());
2774 const char* method_name) {
2776 isolate, options,
"localeMatcher", method_name, {
"best fit",
"lookup"},
2783 const char* method_name,
2784 std::unique_ptr<
char[]>*
result) {
2785 const std::vector<const char*> empty_values = {};
2787 empty_values, method_name,
result);
2790 if (!IsWellFormedNumberingSystem(
result->get())) {
2794 MessageTemplate::kInvalid,
2795 isolate->factory()->numberingSystem_string(),
2796 isolate->factory()->NewStringFromAsciiChecked(
result->get())),
2807 return available_locales.Pointer()->Get();
2812struct CheckCalendar {
2813 static const char*
key() {
return "calendar"; }
2814 static const char* path() {
return nullptr; }
2822 return available_locales.Pointer()->Get();
2829 const icu::UnicodeString& text,
2831 switch (
static_cast<UNumberFormatFields
>(part.
field_id)) {
2832 case UNUM_INTEGER_FIELD:
2833 if (is_nan)
return isolate->factory()->nan_string();
2837 text.tempSubString(part.
begin_pos, 3) ==
"INF")) {
2838 return isolate->factory()->infinity_string();
2840 return isolate->factory()->integer_string();
2841 case UNUM_FRACTION_FIELD:
2842 return isolate->factory()->fraction_string();
2843 case UNUM_DECIMAL_SEPARATOR_FIELD:
2844 return isolate->factory()->decimal_string();
2845 case UNUM_GROUPING_SEPARATOR_FIELD:
2846 return isolate->factory()->group_string();
2847 case UNUM_CURRENCY_FIELD:
2848 return isolate->factory()->currency_string();
2849 case UNUM_PERCENT_FIELD:
2850 return isolate->factory()->percentSign_string();
2851 case UNUM_SIGN_FIELD:
2852 return (text.charAt(part.
begin_pos) ==
'+')
2853 ? isolate->factory()->plusSign_string()
2854 : isolate->factory()->minusSign_string();
2855 case UNUM_EXPONENT_SYMBOL_FIELD:
2856 return isolate->factory()->exponentSeparator_string();
2858 case UNUM_EXPONENT_SIGN_FIELD:
2859 return isolate->factory()->exponentMinusSign_string();
2861 case UNUM_EXPONENT_FIELD:
2862 return isolate->factory()->exponentInteger_string();
2864 case UNUM_PERMILL_FIELD:
2869 case UNUM_COMPACT_FIELD:
2870 return isolate->factory()->compact_string();
2871 case UNUM_MEASURE_UNIT_FIELD:
2872 return isolate->factory()->unit_string();
2874 case UNUM_APPROXIMATELY_SIGN_FIELD:
2875 return isolate->factory()->approximatelySign_string();
2885 UErrorCode status = U_ZERO_ERROR;
2887 if (U_FAILURE(status)) {
2894 Isolate* isolate,
const char* unicode_key,
2895 icu::StringEnumeration* enumeration,
2896 const std::function<
bool(
const char*)>& removes,
bool sort) {
2897 UErrorCode status = U_ZERO_ERROR;
2898 std::vector<std::string> array;
2899 for (
const char* item = enumeration->next(
nullptr, status);
2900 U_SUCCESS(status) && item !=
nullptr;
2901 item = enumeration->next(
nullptr, status)) {
2902 if (unicode_key !=
nullptr) {
2903 item = uloc_toUnicodeLocaleType(unicode_key, item);
2905 if (removes ==
nullptr || !(removes)(item)) {
2906 array.push_back(item);
2911 std::sort(array.begin(), array.end());
2913 return VectorToJSArray(isolate, array);
2917 return strcmp(
"standard", collation) == 0 || strcmp(
"search", collation) == 0;
2922 return std::set<std::string>(
2923 {
"acre",
"bit",
"byte",
"celsius",
2924 "centimeter",
"day",
"degree",
"fahrenheit",
2925 "fluid-ounce",
"foot",
"gallon",
"gigabit",
2926 "gigabyte",
"gram",
"hectare",
"hour",
2927 "inch",
"kilobit",
"kilobyte",
"kilogram",
2928 "kilometer",
"liter",
"megabit",
"megabyte",
2929 "meter",
"microsecond",
"mile",
"mile-scandinavian",
2930 "millimeter",
"milliliter",
"millisecond",
"minute",
2931 "month",
"nanosecond",
"ounce",
"percent",
2932 "petabyte",
"pound",
"second",
"stone",
2933 "terabit",
"terabyte",
"week",
"yard",
2940bool IsUnicodeStringValidTimeZoneName(
const icu::UnicodeString&
id) {
2941 UErrorCode status = U_ZERO_ERROR;
2942 icu::UnicodeString canonical;
2943 icu::TimeZone::getCanonicalID(
id, canonical, status);
2944 return U_SUCCESS(status) &&
2945 canonical != icu::UnicodeString(
"Etc/Unknown", -1, US_INV);
2951 UErrorCode status = U_ZERO_ERROR;
2954 icu::UnicodeString time_zone_ustring =
2955 icu::UnicodeString(
time_zone.c_str(), -1, US_INV);
2956 icu::UnicodeString canonical;
2957 icu::TimeZone::getCanonicalID(time_zone_ustring, canonical, status);
2958 CHECK(U_SUCCESS(status));
2966 icu::UnicodeString time_zone_ustring =
2967 icu::UnicodeString(
time_zone.c_str(), -1, US_INV);
2968 return IsUnicodeStringValidTimeZoneName(time_zone_ustring);
2972 icu::UnicodeString id;
2974 return IsUnicodeStringValidTimeZoneName(
id);
2982 std::unique_ptr<icu::StringEnumeration> enumeration(
2983 icu::TimeZone::createEnumeration());
2987 UErrorCode status = U_ZERO_ERROR;
2988 while (U_SUCCESS(status) && curr < index &&
2989 ((
id = enumeration->next(
nullptr, status)) !=
nullptr)) {
2990 CHECK(U_SUCCESS(status));
2993 CHECK(U_SUCCESS(status));
2994 CHECK(
id !=
nullptr);
3000 if (
identifier->Equals(*isolate->factory()->UTC_string())) {
3004 std::string identifier_str(
identifier->ToCString().get());
3005 std::unique_ptr<icu::TimeZone> tz(
3006 icu::TimeZone::createTimeZone(identifier_str.c_str()));
3011 std::unique_ptr<icu::StringEnumeration> enumeration(
3012 icu::TimeZone::createEnumeration());
3016 UErrorCode status = U_ZERO_ERROR;
3017 while (U_SUCCESS(status) &&
3018 (
id = enumeration->next(
nullptr, status)) !=
nullptr) {
3020 if (identifier_str ==
id) {
3024 CHECK(U_SUCCESS(status));
3041 int32_t
start, int32_t limit)
const {
3043 if (FieldContains(0,
start, limit)) {
3045 }
else if (FieldContains(1,
start, limit)) {
3052 int32_t limit)
const {
3062 return isolate->factory()->shared_string();
3064 return isolate->factory()->startRange_string();
3066 return isolate->factory()->endRange_string();
3071 icu::UnicodeString id;
3073 std::unique_ptr<icu::TimeZone> tz(icu::TimeZone::createDefault());
3076 UErrorCode status = U_ZERO_ERROR;
3077 icu::UnicodeString canonical;
3078 icu::TimeZone::getCanonicalID(
id, canonical, status);
3079 DCHECK(U_SUCCESS(status));
3086const icu::BasicTimeZone* CreateBasicTimeZoneFromIndex(
3087 int32_t time_zone_index) {
3089 return static_cast<const icu::BasicTimeZone*
>(
3090 icu::TimeZone::createTimeZone(icu::UnicodeString(
3100enum class Direction { kPast, kFuture };
3101int64_t ApproximateMillisecondEpoch(Isolate* isolate,
3102 DirectHandle<BigInt> nanosecond_epoch,
3103 Direction
direction = Direction::kPast) {
3105 int64_t ms =
BigInt::Divide(isolate, nanosecond_epoch, one_million)
3132DirectHandle<BigInt> MillisecondToNanosecond(Isolate* isolate, int64_t ms) {
3141 Isolate* isolate, int32_t time_zone_index,
3143 std::unique_ptr<const icu::BasicTimeZone> basic_time_zone(
3144 CreateBasicTimeZoneFromIndex(time_zone_index));
3146 icu::TimeZoneTransition icu_transition;
3147 UBool has_transition;
3148 switch (transition) {
3150 has_transition = basic_time_zone->getNextTransition(
3151 ApproximateMillisecondEpoch(isolate, nanosecond_epoch),
false,
3155 has_transition = basic_time_zone->getPreviousTransition(
3156 ApproximateMillisecondEpoch(isolate, nanosecond_epoch,
3157 Direction::kFuture),
3158 false, icu_transition);
3162 if (!has_transition) {
3163 return isolate->factory()->null_value();
3173 constexpr int64_t kMsMinInstant = -8.64e15;
3176 constexpr int64_t kMsMaxInstant = 8.64e15;
3177 int64_t time_ms =
static_cast<int64_t
>(icu_transition.getTime());
3178 if (time_ms < kMsMinInstant || time_ms > kMsMaxInstant) {
3179 return isolate->factory()->null_value();
3181 return MillisecondToNanosecond(isolate, time_ms);
3185 Isolate* isolate, int32_t time_zone_index,
3187 std::unique_ptr<const icu::BasicTimeZone> basic_time_zone(
3188 CreateBasicTimeZoneFromIndex(time_zone_index));
3189 int64_t time_ms = ApproximateMillisecondEpoch(isolate, nanosecond_epoch);
3192 UErrorCode status = U_ZERO_ERROR;
3193 basic_time_zone->getOffsetFromLocal(time_ms, UCAL_TZ_LOCAL_FORMER,
3194 UCAL_TZ_LOCAL_FORMER, raw_offset,
3195 dst_offset, status);
3196 DCHECK(U_SUCCESS(status));
3199 int64_t offset_former = raw_offset + dst_offset;
3201 basic_time_zone->getOffsetFromLocal(time_ms, UCAL_TZ_LOCAL_LATTER,
3202 UCAL_TZ_LOCAL_LATTER, raw_offset,
3203 dst_offset, status);
3204 DCHECK(U_SUCCESS(status));
3207 int64_t offset_latter = raw_offset + dst_offset;
3210 if (offset_former == offset_latter) {
3214 result.push_back(MillisecondToNanosecond(isolate, offset_former));
3215 }
else if (offset_former > offset_latter) {
3219 result.push_back(MillisecondToNanosecond(isolate, offset_former));
3220 result.push_back(MillisecondToNanosecond(isolate, offset_latter));
3231 Isolate* isolate, int32_t time_zone_index,
3233 std::unique_ptr<const icu::BasicTimeZone> basic_time_zone(
3234 CreateBasicTimeZoneFromIndex(time_zone_index));
3235 int64_t time_ms = ApproximateMillisecondEpoch(isolate, nanosecond_epoch);
3238 UErrorCode status = U_ZERO_ERROR;
3239 basic_time_zone->getOffset(time_ms,
false, raw_offset, dst_offset, status);
3240 DCHECK(U_SUCCESS(status));
3242 return static_cast<int64_t
>(raw_offset + dst_offset) * 1000000;
#define SLOW_DCHECK(condition)
V8_WARN_UNUSED_RESULT V8_INLINE bool To(T *out) const
V8_INLINE T FromJust() const &
static TimezoneCache * CreateTimezoneCache()
constexpr T * begin() const
static MaybeHandle< BigInt > Remainder(Isolate *isolate, DirectHandle< BigInt > x, DirectHandle< BigInt > y)
static MaybeHandle< BigInt > Multiply(Isolate *isolate, DirectHandle< BigInt > x, DirectHandle< BigInt > y)
static MaybeHandle< BigInt > Divide(Isolate *isolate, DirectHandle< BigInt > x, DirectHandle< BigInt > y)
static V8_EXPORT_PRIVATE Handle< BigInt > FromUint64(Isolate *isolate, uint64_t n)
static V8_EXPORT_PRIVATE Handle< BigInt > FromInt64(Isolate *isolate, int64_t n)
V8_INLINE bool is_identical_to(Handle< S > other) const
Handle< JSArray > NewJSArray(ElementsKind elements_kind, int length, int capacity, ArrayStorageAllocationMode mode=ArrayStorageAllocationMode::DONT_INITIALIZE_ARRAY_ELEMENTS, AllocationType allocation=AllocationType::kYoung)
Handle< JSObject > NewJSObject(DirectHandle< JSFunction > constructor, AllocationType allocation=AllocationType::kYoung, NewJSObjectType=NewJSObjectType::kNoAPIWrapper)
Handle< String > NewStringFromStaticChars(const char(&str)[N], AllocationType allocation=AllocationType::kYoung)
std::string timezone_name_
std::string dst_timezone_name_
void Clear(TimeZoneDetection time_zone_detection) override
double DaylightSavingsOffset(double time_ms) override
bool GetOffsets(double time_ms, bool is_utc, int32_t *raw_offset, int32_t *dst_offset)
icu::TimeZone * timezone_
icu::TimeZone * GetTimeZone()
const char * LocalTimezone(double time_ms) override
double LocalTimeOffset(double time_ms, bool is_utc) override
~ICUTimezoneCache() override
static void AddElement(Isolate *isolate, DirectHandle< JSArray > array, int index, DirectHandle< String > field_type_string, DirectHandle< String > value)
static V8_WARN_UNUSED_RESULT MaybeDirectHandle< String > NumberToLocaleString(Isolate *isolate, Handle< Object > num, DirectHandle< Object > locales, DirectHandle< Object > options, const char *method_name)
static base::TimezoneCache * CreateTimeZoneCache()
static bool IsValidCalendar(const icu::Locale &locale, const std::string &value)
static bool IsWellFormedCurrency(const std::string &value)
static V8_WARN_UNUSED_RESULT MaybeDirectHandle< String > StringLocaleConvertCase(Isolate *isolate, DirectHandle< String > s, bool is_upper, DirectHandle< Object > locales)
static std::string GetNumberingSystem(const icu::Locale &icu_locale)
static V8_WARN_UNUSED_RESULT MaybeDirectHandle< Object > LegacyUnwrapReceiver(Isolate *isolate, DirectHandle< JSReceiver > receiver, DirectHandle< JSFunction > constructor, bool has_initialized_slot)
static const std::set< std::string > & GetAvailableLocales()
V8_EXPORT_PRIVATE static V8_WARN_UNUSED_RESULT int CompareStrings(Isolate *isolate, const icu::Collator &collator, DirectHandle< String > s1, DirectHandle< String > s2, CompareStringsOptions compare_strings_options=CompareStringsOptions::kNone)
static V8_WARN_UNUSED_RESULT MaybeHandle< String > ToString(Isolate *isolate, const icu::UnicodeString &string)
static V8_WARN_UNUSED_RESULT MaybeHandle< String > ConvertToLower(Isolate *isolate, DirectHandle< String > s)
static V8_WARN_UNUSED_RESULT MaybeDirectHandle< String > Normalize(Isolate *isolate, DirectHandle< String > string, DirectHandle< Object > form_input)
static const int kAsciiCollationWeightsLength
static DirectHandleVector< BigInt > GetTimeZonePossibleOffsetNanoseconds(Isolate *isolate, int32_t time_zone_index, DirectHandle< BigInt > nanosecond_epoch)
static int32_t GetTimeZoneIndex(Isolate *isolate, DirectHandle< String > identifier)
static Tagged< String > ConvertOneByteToLower(Tagged< String > src, Tagged< String > dst)
static bool RemoveCollation(const char *collation)
static Maybe< std::vector< std::string > > CanonicalizeLocaleList(Isolate *isolate, DirectHandle< Object > locales, bool only_return_one_result=false)
static DirectHandle< Object > GetTimeZoneOffsetTransitionNanoseconds(Isolate *isolate, int32_t time_zone_index, DirectHandle< BigInt > nanosecond_epoch, Transition transition)
static bool IsValidCollation(const icu::Locale &locale, const std::string &value)
static const std::set< std::string > & GetAvailableLocalesForDateFormat()
static DirectHandle< String > DefaultTimeZone(Isolate *isolate)
static Maybe< ResolvedLocale > ResolveLocale(Isolate *isolate, const std::set< std::string > &available_locales, const std::vector< std::string > &requested_locales, MatcherOption options, const std::set< std::string > &relevant_extension_keys)
static V8_WARN_UNUSED_RESULT MaybeDirectHandle< JSArray > ToJSArray(Isolate *isolate, const char *unicode_key, icu::StringEnumeration *enumeration, const std::function< bool(const char *)> &removes, bool sort)
static std::set< std::string > SanctionedSimpleUnits()
static const uint8_t * ToLatin1LowerTable()
static V8_WARN_UNUSED_RESULT std::optional< int > StringLocaleCompare(Isolate *isolate, DirectHandle< String > s1, DirectHandle< String > s2, DirectHandle< Object > locales, DirectHandle< Object > options, const char *method_name)
static icu::UnicodeString ToICUUnicodeString(Isolate *isolate, DirectHandle< String > string, int offset=0)
static V8_EXPORT_PRIVATE CompareStringsOptions CompareStringsOptionsFor(IsolateT *isolate, DirectHandle< Object > locales, DirectHandle< Object > options)
static V8_WARN_UNUSED_RESULT bool IsValidTimeZoneName(const icu::TimeZone &tz)
static std::set< std::string > BuildLocaleSet(const std::vector< std::string > &locales, const char *path, const char *validate_key)
static V8_WARN_UNUSED_RESULT std::string TimeZoneIdFromIndex(int32_t index)
static V8_WARN_UNUSED_RESULT MaybeHandle< String > CanonicalizeTimeZoneName(Isolate *isolate, DirectHandle< String > identifier)
static int64_t GetTimeZoneOffsetNanoseconds(Isolate *isolate, int32_t time_zone_index, DirectHandle< BigInt > nanosecond_epoch)
static V8_WARN_UNUSED_RESULT Maybe< MatcherOption > GetLocaleMatcher(Isolate *isolate, DirectHandle< JSReceiver > options, const char *method_name)
static V8_WARN_UNUSED_RESULT MaybeDirectHandle< JSArray > AvailableCalendars(Isolate *isolate)
static bool IsWellFormedCalendar(const std::string &value)
static Maybe< std::string > ToLanguageTag(const icu::Locale &locale)
static V8_WARN_UNUSED_RESULT MaybeDirectHandle< String > FormattedToString(Isolate *isolate, const icu::FormattedValue &formatted)
static V8_WARN_UNUSED_RESULT Maybe< NumberFormatDigitOptions > SetNumberFormatDigitOptions(Isolate *isolate, DirectHandle< JSReceiver > options, int mnfd_default, int mxfd_default, bool notation_is_compact, const char *service)
static const uint8_t * AsciiCollationWeightsL1()
static bool IsValidNumberingSystem(const std::string &value)
static V8_WARN_UNUSED_RESULT MaybeDirectHandle< JSArray > GetCanonicalLocales(Isolate *isolate, DirectHandle< Object > locales)
static V8_WARN_UNUSED_RESULT MaybeDirectHandle< String > ConvertToUpper(Isolate *isolate, DirectHandle< String > s)
static DirectHandle< String > SourceString(Isolate *isolate, FormatRangeSource source)
static V8_WARN_UNUSED_RESULT MaybeDirectHandle< JSArray > SupportedValuesOf(Isolate *isolate, DirectHandle< Object > key)
static DirectHandle< Managed< icu::UnicodeString > > SetTextToBreakIterator(Isolate *isolate, DirectHandle< String > text, icu::BreakIterator *break_iterator)
static const uint8_t * AsciiCollationWeightsL3()
static V8_WARN_UNUSED_RESULT MaybeDirectHandle< JSObject > SupportedLocalesOf(Isolate *isolate, const char *method_name, const std::set< std::string > &available_locales, DirectHandle< Object > locales_in, DirectHandle< Object > options_in)
static DirectHandle< String > NumberFieldToType(Isolate *isolate, const NumberFormatSpan &part, const icu::UnicodeString &text, bool is_nan)
static V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT MaybeHandle< Map > GetDerivedMap(Isolate *isolate, DirectHandle< JSFunction > constructor, DirectHandle< JSReceiver > new_target)
static bool Is38AlphaNumList(const std::string &value)
static bool StartsWithUnicodeLanguageId(const std::string &value)
static DirectHandle< String > ToString(Isolate *isolate, DirectHandle< JSLocale > locale)
static bool Is3Alpha(const std::string &value)
static V8_EXPORT_PRIVATE void AddProperty(Isolate *isolate, DirectHandle< JSObject > object, DirectHandle< Name > name, DirectHandle< Object > value, PropertyAttributes attributes)
static V8_EXPORT_PRIVATE Maybe< bool > AddDataElement(DirectHandle< JSObject > receiver, uint32_t index, DirectHandle< Object > value, PropertyAttributes attributes)
static V8_WARN_UNUSED_RESULT MaybeHandle< Object > GetProperty(Isolate *isolate, DirectHandle< JSReceiver > receiver, const char *key)
V8_EXPORT_PRIVATE static V8_WARN_UNUSED_RESULT Maybe< bool > HasProperty(LookupIterator *it)
static constexpr int32_t kUTCTimeZoneIndex
static DirectHandle< Managed< CppType > > From(Isolate *isolate, size_t estimated_size, std::shared_ptr< CppType > shared_ptr, AllocationType allocation_type=AllocationType::kYoung)
V8_WARN_UNUSED_RESULT V8_INLINE bool ToHandle(DirectHandle< S > *out) const
static V8_WARN_UNUSED_RESULT HandleType< String >::MaybeType ToString(Isolate *isolate, HandleType< T > input)
static V8_WARN_UNUSED_RESULT MaybeHandle< Object > OrdinaryHasInstance(Isolate *isolate, DirectHandle< JSAny > callable, DirectHandle< JSAny > object)
static V8_EXPORT_PRIVATE bool BooleanValue(Tagged< Object > obj, IsolateT *isolate)
static V8_WARN_UNUSED_RESULT HandleType< JSReceiver >::MaybeType ToObject(Isolate *isolate, HandleType< T > object, const char *method_name=nullptr)
static double NumberValue(Tagged< Number > obj)
static V8_WARN_UNUSED_RESULT MaybeDirectHandle< Object > GetLengthFromArrayLike(Isolate *isolate, DirectHandle< JSReceiver > object)
V8_EXPORT_PRIVATE static V8_WARN_UNUSED_RESULT MaybeHandle< Object > GetProperty(LookupIterator *it, bool is_global_reference=false)
static V8_WARN_UNUSED_RESULT HandleType< Object >::MaybeType ToNumeric(Isolate *isolate, HandleType< T > input)
static V8_WARN_UNUSED_RESULT Handle< String > Truncate(Isolate *isolate, Handle< SeqString > string, uint32_t new_length)
static bool IsNeeded(Tagged< String > str, LocalIsolate *local_isolate)
bool JsHasOverflowed(uintptr_t gap=0) const
base::Vector< const uint8_t > ToOneByteVector() const
base::Vector< const base::uc16 > ToUC16Vector() const
static V8_INLINE HandleType< String > Flatten(Isolate *isolate, HandleType< T > string, AllocationType allocation=AllocationType::kYoung)
static bool IsAscii(const char *chars, uint32_t length)
bool Equals(Tagged< String > other) const
void push_back(const T &value)
const v8::base::TimeTicks end_
#define THROW_NEW_ERROR_RETURN_VALUE(isolate, call, value)
#define ASSIGN_RETURN_ON_EXCEPTION(isolate, dst, call)
#define THROW_NEW_ERROR(isolate, call)
#define ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, dst, call, value)
#define MAYBE_RETURN(call, value)
UCollationResult l1_result
std::string no_extensions_locale
std::vector< std::string > list_
UCollationResult l3_result
std::vector< std::string >::const_iterator iter_
#define V8_MINIMUM_ICU_VERSION
ArrayReduceDirection direction
ZoneVector< RpoNumber > & result
#define LAZY_INSTANCE_INITIALIZER
InstructionOperand source
Vector< const char > CStrVector(const char *data)
V8_INLINE const Operation & Get(const Graph &graph, OpIndex index)
Node::Uses::const_iterator begin(const Node::Uses &uses)
V8_INLINE IndirectHandle< T > handle(Tagged< T > object, Isolate *isolate)
template uint32_t FastAsciiConvert< unibrow::ToLowercase >(char *dst, const char *src, uint32_t length)
template uint32_t FastAsciiCasePrefixLength< unibrow::ToUppercase >(const char *src, uint32_t length)
PerThreadAssertScopeDebugOnly< false, SAFEPOINTS_ASSERT, HEAP_ALLOCATION_ASSERT > DisallowGarbageCollection
Tagged(T object) -> Tagged< T >
constexpr bool IsAsciiLower(base::uc32 c)
Maybe< int > DefaultNumberOption(Isolate *isolate, DirectHandle< Object > value, int min, int max, int fallback, DirectHandle< String > property)
V8_INLINE IndirectHandle< T > indirect_handle(DirectHandle< T > handle)
template uint32_t FastAsciiConvert< unibrow::ToUppercase >(char *dst, const char *src, uint32_t length)
refactor address components for immediate indexing make OptimizeMaglevOnNextCall optimize to turbofan instead of maglev filter for tracing turbofan compilation trace turbo cfg trace TurboFan s graph trimmer trace TurboFan s control equivalence trace TurboFan s register allocator trace stack load store counters for optimized code in run fuzzing &&concurrent_recompilation trace_turbo trace_turbo_scheduled trace_turbo_stack_accesses verify TurboFan machine graph of code stubs enable FixedArray bounds checks print TurboFan statistics of wasm compilations maximum cumulative size of bytecode considered for inlining scale factor of bytecode size used to calculate the inlining budget * KB
void CopyChars(DstType *dst, const SrcType *src, size_t count) V8_NONNULL(1
V8_EXPORT_PRIVATE FlagValues v8_flags
constexpr base::uc32 ToAsciiUpper(base::uc32 c)
constexpr bool IsAsciiUpper(base::uc32 c)
Maybe< int > GetNumberOption(Isolate *isolate, DirectHandle< JSReceiver > options, DirectHandle< String > property, int min, int max, int fallback)
MaybeDirectHandle< JSReceiver > CoerceOptionsToObject(Isolate *isolate, DirectHandle< Object > options, const char *method_name)
Maybe< bool > GetStringOption(Isolate *isolate, DirectHandle< JSReceiver > options, const char *property, const std::vector< const char * > &values, const char *method_name, std::unique_ptr< char[]> *result)
constexpr uint32_t kMaxUInt32
T * NewArray(size_t size)
constexpr uint16_t kInfinityChar
template const char * string
constexpr base::uc32 ToAsciiLower(base::uc32 c)
Tagged< To > Cast(Tagged< From > value, const v8::SourceLocation &loc=INIT_SOURCE_LOCATION_IN_DEBUG)
Maybe< T > Just(const T &t)
#define DCHECK_LE(v1, v2)
#define DCHECK_NOT_NULL(val)
#define DCHECK_NE(v1, v2)
#define DCHECK_GE(v1, v2)
#define DCHECK(condition)
#define DCHECK_LT(v1, v2)
#define DCHECK_EQ(v1, v2)
#define DCHECK_GT(v1, v2)
typename LazyStaticInstance< T, CreateTrait, InitOnceTrait, DestroyTrait >::type type
#define V8_LIKELY(condition)
#define V8_UNLIKELY(condition)