#include "src/objects/intl-objects.h"
#include <algorithm>
#include <limits>
#include <memory>
#include <optional>
#include <string>
#include <vector>
#include "src/api/api-inl.h"
#include "src/base/logging.h"
#include "src/base/strings.h"
#include "src/common/globals.h"
#include "src/date/date.h"
#include "src/execution/isolate.h"
#include "src/execution/local-isolate.h"
#include "src/handles/global-handles.h"
#include "src/heap/factory.h"
#include "src/objects/js-collator-inl.h"
#include "src/objects/js-date-time-format-inl.h"
#include "src/objects/js-locale-inl.h"
#include "src/objects/js-locale.h"
#include "src/objects/js-number-format-inl.h"
#include "src/objects/js-temporal-objects.h"
#include "src/objects/managed-inl.h"
#include "src/objects/objects-inl.h"
#include "src/objects/option-utils.h"
#include "src/objects/property-descriptor.h"
#include "src/objects/smi.h"
#include "src/objects/string.h"
#include "src/strings/string-case.h"
#include "unicode/basictz.h"
#include "unicode/brkiter.h"
#include "unicode/calendar.h"
#include "unicode/coll.h"
#include "unicode/datefmt.h"
#include "unicode/decimfmt.h"
#include "unicode/formattedvalue.h"
#include "unicode/localebuilder.h"
#include "unicode/localematcher.h"
#include "unicode/locid.h"
#include "unicode/normalizer2.h"
#include "unicode/numberformatter.h"
#include "unicode/numfmt.h"
#include "unicode/numsys.h"
#include "unicode/timezone.h"
#include "unicode/ures.h"
#include "unicode/ustring.h"
#include "unicode/uvernum.h"
#ifndef V8_INTL_SUPPORT
#error Internationalization is expected to be enabled.
#endif
#define XSTR …
#define STR …
static_assert …;
#undef STR
#undef XSTR
namespace v8::internal {
namespace {
inline constexpr uint8_t AsOneByte(uint16_t ch) { … }
constexpr uint8_t kToLower[256] = …;
inline constexpr uint8_t ToLatin1Lower(uint8_t ch) { … }
inline constexpr uint8_t ToLatin1Lower(uint16_t ch) = delete;
inline constexpr uint8_t ToLatin1Upper(uint8_t ch) { … }
inline constexpr uint8_t ToLatin1Upper(uint16_t ch) = delete;
bool ToUpperFastASCII(base::Vector<const uint16_t> src,
DirectHandle<SeqOneByteString> result) { … }
const uint16_t sharp_s = …;
template <typename Char>
bool ToUpperOneByte(base::Vector<const Char> src, uint8_t* dest,
int* sharp_s_count) { … }
template <typename Char>
void ToUpperWithSharpS(base::Vector<const Char> src,
DirectHandle<SeqOneByteString> result) { … }
inline int FindFirstUpperOrNonAscii(Tagged<String> s, int length) { … }
const UChar* GetUCharBufferFromFlat(const String::FlatContent& flat,
std::unique_ptr<base::uc16[]>* dest,
int32_t length) { … }
template <typename T>
MaybeHandle<T> New(Isolate* isolate, Handle<JSFunction> constructor,
Handle<Object> locales, Handle<Object> options,
const char* method_name) { … }
}
const uint8_t* Intl::ToLatin1LowerTable() { … }
icu::UnicodeString Intl::ToICUUnicodeString(Isolate* isolate,
DirectHandle<String> string,
int offset) { … }
namespace {
icu::StringPiece ToICUStringPiece(Isolate* isolate, DirectHandle<String> string,
int offset = 0) { … }
MaybeHandle<String> LocaleConvertCase(Isolate* isolate, DirectHandle<String> s,
bool is_to_upper, const char* lang) { … }
}
Tagged<String> Intl::ConvertOneByteToLower(Tagged<String> src,
Tagged<String> dst) { … }
MaybeHandle<String> Intl::ConvertToLower(Isolate* isolate, Handle<String> s) { … }
MaybeHandle<String> Intl::ConvertToUpper(Isolate* isolate, Handle<String> s) { … }
std::string Intl::GetNumberingSystem(const icu::Locale& icu_locale) { … }
namespace {
Maybe<icu::Locale> CreateICULocale(const std::string& bcp47_locale) { … }
}
MaybeHandle<String> Intl::ToString(Isolate* isolate,
const icu::UnicodeString& string) { … }
MaybeHandle<String> Intl::ToString(Isolate* isolate,
const icu::UnicodeString& string,
int32_t begin, int32_t end) { … }
namespace {
Handle<JSObject> InnerAddElement(Isolate* isolate, Handle<JSArray> array,
int index,
DirectHandle<String> field_type_string,
DirectHandle<String> value) { … }
}
void Intl::AddElement(Isolate* isolate, Handle<JSArray> array, int index,
DirectHandle<String> field_type_string,
DirectHandle<String> value) { … }
void Intl::AddElement(Isolate* isolate, Handle<JSArray> array, int index,
DirectHandle<String> field_type_string,
DirectHandle<String> value,
Handle<String> additional_property_name,
DirectHandle<String> additional_property_value) { … }
namespace {
bool RemoveLocaleScriptTag(const std::string& icu_locale,
std::string* locale_less_script) { … }
bool ValidateResource(const icu::Locale locale, const char* path,
const char* key) { … }
}
std::set<std::string> Intl::BuildLocaleSet(
const std::vector<std::string>& icu_available_locales, const char* path,
const char* validate_key) { … }
Maybe<std::string> Intl::ToLanguageTag(const icu::Locale& locale) { … }
MaybeHandle<Object> Intl::LegacyUnwrapReceiver(Isolate* isolate,
Handle<JSReceiver> receiver,
Handle<JSFunction> constructor,
bool has_initialized_slot) { … }
namespace {
bool IsTwoLetterLanguage(const std::string& locale) { … }
bool IsDeprecatedOrLegacyLanguage(const std::string& locale) { … }
bool IsStructurallyValidLanguageTag(const std::string& tag) { … }
Maybe<std::string> CanonicalizeLanguageTag(Isolate* isolate,
const std::string& locale_in) { … }
Maybe<std::string> CanonicalizeLanguageTag(Isolate* isolate,
Handle<Object> locale_in) { … }
}
Maybe<std::vector<std::string>> Intl::CanonicalizeLocaleList(
Isolate* isolate, Handle<Object> locales, bool only_return_one_result) { … }
MaybeHandle<String> Intl::StringLocaleConvertCase(Isolate* isolate,
Handle<String> s,
bool to_upper,
Handle<Object> locales) { … }
template <class IsolateT>
Intl::CompareStringsOptions Intl::CompareStringsOptionsFor(
IsolateT* isolate, DirectHandle<Object> locales,
DirectHandle<Object> options) { … }
template Intl::CompareStringsOptions Intl::CompareStringsOptionsFor(
Isolate*, DirectHandle<Object>, DirectHandle<Object>);
template Intl::CompareStringsOptions Intl::CompareStringsOptionsFor(
LocalIsolate*, DirectHandle<Object>, DirectHandle<Object>);
std::optional<int> Intl::StringLocaleCompare(
Isolate* isolate, Handle<String> string1, Handle<String> string2,
Handle<Object> locales, Handle<Object> options, const char* method_name) { … }
namespace …
const uint8_t* Intl::AsciiCollationWeightsL1() { … }
const uint8_t* Intl::AsciiCollationWeightsL3() { … }
const int Intl::kAsciiCollationWeightsLength = …;
int Intl::CompareStrings(Isolate* isolate, const icu::Collator& icu_collator,
Handle<String> string1, Handle<String> string2,
CompareStringsOptions compare_strings_options) { … }
MaybeHandle<String> Intl::NumberToLocaleString(Isolate* isolate,
Handle<Object> num,
Handle<Object> locales,
Handle<Object> options,
const char* method_name) { … }
namespace {
bool IsValidRoundingIncrement(int value) { … }
}
Maybe<Intl::NumberFormatDigitOptions> Intl::SetNumberFormatDigitOptions(
Isolate* isolate, Handle<JSReceiver> options, int mnfd_default,
int mxfd_default, bool notation_is_compact, const char* service) { … }
namespace {
std::string BestAvailableLocale(const std::set<std::string>& available_locales,
const std::string& locale) { … }
struct ParsedLocale { … };
ParsedLocale ParseBCP47Locale(const std::string& locale) { … }
std::vector<std::string> LookupSupportedLocales(
const std::set<std::string>& available_locales,
const std::vector<std::string>& requested_locales) { … }
icu::LocaleMatcher BuildLocaleMatcher(
Isolate* isolate, const std::set<std::string>& available_locales,
UErrorCode* status) { … }
class Iterator : public icu::Locale::Iterator { … };
std::string BestFitMatcher(Isolate* isolate,
const std::set<std::string>& available_locales,
const std::vector<std::string>& requested_locales) { … }
std::vector<std::string> BestFitSupportedLocales(
Isolate* isolate, const std::set<std::string>& available_locales,
const std::vector<std::string>& requested_locales) { … }
MaybeHandle<JSArray> CreateArrayFromList(Isolate* isolate,
std::vector<std::string> elements,
PropertyAttributes attr) { … }
MaybeHandle<JSObject> SupportedLocales(
Isolate* isolate, const char* method_name,
const std::set<std::string>& available_locales,
const std::vector<std::string>& requested_locales, Handle<Object> options) { … }
}
MaybeHandle<JSArray> Intl::GetCanonicalLocales(Isolate* isolate,
Handle<Object> locales) { … }
namespace {
MaybeHandle<JSArray> AvailableCollations(Isolate* isolate) { … }
MaybeHandle<JSArray> VectorToJSArray(Isolate* isolate,
const std::vector<std::string>& array) { … }
namespace {
class ResourceAvailableCurrencies { … };
const std::vector<std::string>& GetAvailableCurrencies() { … }
}
MaybeHandle<JSArray> AvailableCurrencies(Isolate* isolate) { … }
MaybeHandle<JSArray> AvailableNumberingSystems(Isolate* isolate) { … }
MaybeHandle<JSArray> AvailableTimeZones(Isolate* isolate) { … }
MaybeHandle<JSArray> AvailableUnits(Isolate* isolate) { … }
}
MaybeHandle<JSArray> Intl::SupportedValuesOf(Isolate* isolate,
Handle<Object> key_obj) { … }
MaybeHandle<JSObject> Intl::SupportedLocalesOf(
Isolate* isolate, const char* method_name,
const std::set<std::string>& available_locales, Handle<Object> locales,
Handle<Object> options) { … }
namespace {
template <typename T>
bool IsValidExtension(const icu::Locale& locale, const char* key,
const std::string& value) { … }
}
bool Intl::IsValidCollation(const icu::Locale& locale,
const std::string& value) { … }
bool Intl::IsWellFormedCalendar(const std::string& value) { … }
bool Intl::IsWellFormedCurrency(const std::string& currency) { … }
bool Intl::IsValidCalendar(const icu::Locale& locale,
const std::string& value) { … }
bool Intl::IsValidNumberingSystem(const std::string& value) { … }
namespace {
bool IsWellFormedNumberingSystem(const std::string& value) { … }
std::map<std::string, std::string> LookupAndValidateUnicodeExtensions(
icu::Locale* icu_locale, const std::set<std::string>& relevant_keys) { … }
std::string LookupMatcher(Isolate* isolate,
const std::set<std::string>& available_locales,
const std::vector<std::string>& requested_locales) { … }
}
Maybe<Intl::ResolvedLocale> Intl::ResolveLocale(
Isolate* isolate, const std::set<std::string>& available_locales,
const std::vector<std::string>& requested_locales, MatcherOption matcher,
const std::set<std::string>& relevant_extension_keys) { … }
Handle<Managed<icu::UnicodeString>> Intl::SetTextToBreakIterator(
Isolate* isolate, Handle<String> text, icu::BreakIterator* break_iterator) { … }
MaybeHandle<String> Intl::Normalize(Isolate* isolate, Handle<String> string,
Handle<Object> form_input) { … }
class ICUTimezoneCache : public base::TimezoneCache { … };
const char* ICUTimezoneCache::LocalTimezone(double time_ms) { … }
icu::TimeZone* ICUTimezoneCache::GetTimeZone() { … }
bool ICUTimezoneCache::GetOffsets(double time_ms, bool is_utc,
int32_t* raw_offset, int32_t* dst_offset) { … }
double ICUTimezoneCache::DaylightSavingsOffset(double time_ms) { … }
double ICUTimezoneCache::LocalTimeOffset(double time_ms, bool is_utc) { … }
void ICUTimezoneCache::Clear(TimeZoneDetection time_zone_detection) { … }
base::TimezoneCache* Intl::CreateTimeZoneCache() { … }
Maybe<Intl::MatcherOption> Intl::GetLocaleMatcher(Isolate* isolate,
Handle<JSReceiver> options,
const char* method_name) { … }
Maybe<bool> Intl::GetNumberingSystem(Isolate* isolate,
Handle<JSReceiver> options,
const char* method_name,
std::unique_ptr<char[]>* result) { … }
const std::set<std::string>& Intl::GetAvailableLocales() { … }
namespace {
struct CheckCalendar { … };
}
const std::set<std::string>& Intl::GetAvailableLocalesForDateFormat() { … }
constexpr uint16_t kInfinityChar = …;
Handle<String> Intl::NumberFieldToType(Isolate* isolate,
const NumberFormatSpan& part,
const icu::UnicodeString& text,
bool is_nan) { … }
MaybeHandle<String> Intl::FormattedToString(
Isolate* isolate, const icu::FormattedValue& formatted) { … }
MaybeHandle<JSArray> Intl::ToJSArray(
Isolate* isolate, const char* unicode_key,
icu::StringEnumeration* enumeration,
const std::function<bool(const char*)>& removes, bool sort) { … }
bool Intl::RemoveCollation(const char* collation) { … }
std::set<std::string> Intl::SanctionedSimpleUnits() { … }
namespace {
bool IsUnicodeStringValidTimeZoneName(const icu::UnicodeString& id) { … }
}
MaybeHandle<String> Intl::CanonicalizeTimeZoneName(
Isolate* isolate, DirectHandle<String> identifier) { … }
bool Intl::IsValidTimeZoneName(Isolate* isolate, DirectHandle<String> id) { … }
bool Intl::IsValidTimeZoneName(const icu::TimeZone& tz) { … }
std::string Intl::TimeZoneIdFromIndex(int32_t index) { … }
int32_t Intl::GetTimeZoneIndex(Isolate* isolate,
DirectHandle<String> identifier) { … }
Intl::FormatRangeSourceTracker::FormatRangeSourceTracker() { … }
void Intl::FormatRangeSourceTracker::Add(int32_t field, int32_t start,
int32_t limit) { … }
Intl::FormatRangeSource Intl::FormatRangeSourceTracker::GetSource(
int32_t start, int32_t limit) const { … }
bool Intl::FormatRangeSourceTracker::FieldContains(int32_t field, int32_t start,
int32_t limit) const { … }
Handle<String> Intl::SourceString(Isolate* isolate, FormatRangeSource source) { … }
Handle<String> Intl::DefaultTimeZone(Isolate* isolate) { … }
namespace {
const icu::BasicTimeZone* CreateBasicTimeZoneFromIndex(
int32_t time_zone_index) { … }
enum class Direction { … };
int64_t ApproximateMillisecondEpoch(Isolate* isolate,
Handle<BigInt> nanosecond_epoch,
Direction direction = Direction::kPast) { … }
Handle<BigInt> MillisecondToNanosecond(Isolate* isolate, int64_t ms) { … }
}
Handle<Object> Intl::GetTimeZoneOffsetTransitionNanoseconds(
Isolate* isolate, int32_t time_zone_index, Handle<BigInt> nanosecond_epoch,
Intl::Transition transition) { … }
std::vector<Handle<BigInt>> Intl::GetTimeZonePossibleOffsetNanoseconds(
Isolate* isolate, int32_t time_zone_index,
Handle<BigInt> nanosecond_epoch) { … }
int64_t Intl::GetTimeZoneOffsetNanoseconds(Isolate* isolate,
int32_t time_zone_index,
Handle<BigInt> nanosecond_epoch) { … }
}