[Intl] Clean up Intl code.

Move functions into anonymous namespce.
Remove dead code.
Move GetCaseFirst into JSCollator
Move HourCycle, ToHourCycle and GetHourCycle into JSDateTimeFormat

Change-Id: Ie6089e7f33677dd40169c56198b52d87ba490b20
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2067689
Commit-Queue: Frank Tang <ftang@chromium.org>
Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
Cr-Commit-Position: refs/heads/master@{#66395}
This commit is contained in:
Frank Tang 2020-02-21 13:41:18 -08:00 committed by Commit Bot
parent 6f112a0807
commit 96dda2fac2
11 changed files with 179 additions and 247 deletions

View File

@ -213,8 +213,8 @@ icu::UnicodeString Intl::ToICUUnicodeString(Isolate* isolate,
return icu::UnicodeString(uchar_buffer, length);
}
icu::StringPiece Intl::ToICUStringPiece(Isolate* isolate,
Handle<String> string) {
namespace {
icu::StringPiece ToICUStringPiece(Isolate* isolate, Handle<String> string) {
DCHECK(string->IsFlat());
DisallowHeapAllocation no_gc;
@ -231,7 +231,6 @@ icu::StringPiece Intl::ToICUStringPiece(Isolate* isolate,
return icu::StringPiece(char_buffer, length);
}
namespace {
MaybeHandle<String> LocaleConvertCase(Isolate* isolate, Handle<String> s,
bool is_to_upper, const char* lang) {
auto case_converter = is_to_upper ? u_strToUpper : u_strToLower;
@ -432,7 +431,9 @@ std::string Intl::GetNumberingSystem(const icu::Locale& icu_locale) {
return "latn";
}
icu::Locale Intl::CreateICULocale(const std::string& bcp47_locale) {
namespace {
icu::Locale CreateICULocale(const std::string& bcp47_locale) {
DisallowHeapAllocation no_gc;
// Convert BCP47 into ICU locale format.
@ -447,6 +448,8 @@ icu::Locale Intl::CreateICULocale(const std::string& bcp47_locale) {
return icu_locale;
}
} // anonymous namespace
// static
MaybeHandle<String> Intl::ToString(Isolate* isolate,
@ -762,41 +765,15 @@ bool IsGrandfatheredTagWithoutPreferredVaule(const std::string& locale) {
return false;
}
} // anonymous namespace
Maybe<std::string> Intl::CanonicalizeLanguageTag(Isolate* isolate,
Handle<Object> locale_in) {
Handle<String> locale_str;
// This does part of the validity checking spec'ed in CanonicalizeLocaleList:
// 7c ii. If Type(kValue) is not String or Object, throw a TypeError
// exception.
// 7c iii. Let tag be ? ToString(kValue).
// 7c iv. If IsStructurallyValidLanguageTag(tag) is false, throw a
// RangeError exception.
if (locale_in->IsString()) {
locale_str = Handle<String>::cast(locale_in);
} else if (locale_in->IsJSReceiver()) {
ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, locale_str,
Object::ToString(isolate, locale_in),
Nothing<std::string>());
} else {
THROW_NEW_ERROR_RETURN_VALUE(isolate,
NewTypeError(MessageTemplate::kLanguageID),
Nothing<std::string>());
}
std::string locale(locale_str->ToCString().get());
if (!IsStructurallyValidLanguageTag(locale)) {
THROW_NEW_ERROR_RETURN_VALUE(
isolate, NewRangeError(MessageTemplate::kLocaleBadParameters),
Nothing<std::string>());
}
return Intl::CanonicalizeLanguageTag(isolate, locale);
bool IsStructurallyValidLanguageTag(const std::string& tag) {
return JSLocale::StartsWithUnicodeLanguageId(tag);
}
Maybe<std::string> Intl::CanonicalizeLanguageTag(Isolate* isolate,
const std::string& locale_in) {
// Canonicalize the locale.
// https://tc39.github.io/ecma402/#sec-canonicalizelanguagetag,
// including type check and structural validity check.
Maybe<std::string> CanonicalizeLanguageTag(Isolate* isolate,
const std::string& locale_in) {
std::string locale = locale_in;
if (locale.length() == 0 ||
@ -864,6 +841,39 @@ Maybe<std::string> Intl::CanonicalizeLanguageTag(Isolate* isolate,
return maybe_to_language_tag;
}
Maybe<std::string> CanonicalizeLanguageTag(Isolate* isolate,
Handle<Object> locale_in) {
Handle<String> locale_str;
// This does part of the validity checking spec'ed in CanonicalizeLocaleList:
// 7c ii. If Type(kValue) is not String or Object, throw a TypeError
// exception.
// 7c iii. Let tag be ? ToString(kValue).
// 7c iv. If IsStructurallyValidLanguageTag(tag) is false, throw a
// RangeError exception.
if (locale_in->IsString()) {
locale_str = Handle<String>::cast(locale_in);
} else if (locale_in->IsJSReceiver()) {
ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, locale_str,
Object::ToString(isolate, locale_in),
Nothing<std::string>());
} else {
THROW_NEW_ERROR_RETURN_VALUE(isolate,
NewTypeError(MessageTemplate::kLanguageID),
Nothing<std::string>());
}
std::string locale(locale_str->ToCString().get());
if (!IsStructurallyValidLanguageTag(locale)) {
THROW_NEW_ERROR_RETURN_VALUE(
isolate, NewRangeError(MessageTemplate::kLocaleBadParameters),
Nothing<std::string>());
}
return CanonicalizeLanguageTag(isolate, locale);
}
} // anonymous namespace
Maybe<std::vector<std::string>> Intl::CanonicalizeLocaleList(
Isolate* isolate, Handle<Object> locales, bool only_return_one_result) {
// 1. If locales is undefined, then
@ -1069,9 +1079,9 @@ Handle<Object> Intl::CompareStrings(Isolate* isolate,
UCollationResult result;
UErrorCode status = U_ZERO_ERROR;
icu::StringPiece string_piece1 = Intl::ToICUStringPiece(isolate, string1);
icu::StringPiece string_piece1 = ToICUStringPiece(isolate, string1);
if (!string_piece1.empty()) {
icu::StringPiece string_piece2 = Intl::ToICUStringPiece(isolate, string2);
icu::StringPiece string_piece2 = ToICUStringPiece(isolate, string2);
if (!string_piece2.empty()) {
result = icu_collator.compareUTF8(string_piece1, string_piece2, status);
DCHECK(U_SUCCESS(status));
@ -2062,26 +2072,6 @@ base::TimezoneCache* Intl::CreateTimeZoneCache() {
: base::OS::CreateTimezoneCache();
}
Maybe<Intl::CaseFirst> Intl::GetCaseFirst(Isolate* isolate,
Handle<JSReceiver> options,
const char* method) {
return Intl::GetStringOption<Intl::CaseFirst>(
isolate, options, "caseFirst", method, {"upper", "lower", "false"},
{Intl::CaseFirst::kUpper, Intl::CaseFirst::kLower,
Intl::CaseFirst::kFalse},
Intl::CaseFirst::kUndefined);
}
Maybe<Intl::HourCycle> Intl::GetHourCycle(Isolate* isolate,
Handle<JSReceiver> options,
const char* method) {
return Intl::GetStringOption<Intl::HourCycle>(
isolate, options, "hourCycle", method, {"h11", "h12", "h23", "h24"},
{Intl::HourCycle::kH11, Intl::HourCycle::kH12, Intl::HourCycle::kH23,
Intl::HourCycle::kH24},
Intl::HourCycle::kUndefined);
}
Maybe<Intl::MatcherOption> Intl::GetLocaleMatcher(Isolate* isolate,
Handle<JSReceiver> options,
const char* method) {
@ -2114,14 +2104,6 @@ Maybe<bool> Intl::GetNumberingSystem(Isolate* isolate,
return Just(false);
}
Intl::HourCycle Intl::ToHourCycle(const std::string& hc) {
if (hc == "h11") return Intl::HourCycle::kH11;
if (hc == "h12") return Intl::HourCycle::kH12;
if (hc == "h23") return Intl::HourCycle::kH23;
if (hc == "h24") return Intl::HourCycle::kH24;
return Intl::HourCycle::kUndefined;
}
const std::set<std::string>& Intl::GetAvailableLocalesForLocale() {
static base::LazyInstance<Intl::AvailableLocales<icu::Locale>>::type
available_locales = LAZY_INSTANCE_INITIALIZER;
@ -2217,9 +2199,6 @@ MaybeHandle<String> Intl::FormattedToString(
return Intl::ToString(isolate, result);
}
bool Intl::IsStructurallyValidLanguageTag(const std::string& tag) {
return JSLocale::StartsWithUnicodeLanguageId(tag);
}
} // namespace internal
} // namespace v8

View File

@ -27,7 +27,6 @@ namespace U_ICU_NAMESPACE {
class BreakIterator;
class Collator;
class FormattedValue;
class SimpleDateFormat;
class UnicodeString;
} // namespace U_ICU_NAMESPACE
@ -132,15 +131,6 @@ class Intl {
Isolate* isolate, Handle<JSReceiver> options, Handle<String> property,
int min, int max, int fallback);
// Canonicalize the locale.
// https://tc39.github.io/ecma402/#sec-canonicalizelanguagetag,
// including type check and structural validity check.
static Maybe<std::string> CanonicalizeLanguageTag(Isolate* isolate,
Handle<Object> locale_in);
static Maybe<std::string> CanonicalizeLanguageTag(Isolate* isolate,
const std::string& locale);
// https://tc39.github.io/ecma402/#sec-canonicalizelocalelist
// {only_return_one_result} is an optimization for callers that only
// care about the first result.
@ -189,8 +179,6 @@ class Intl {
int mnfd_default, int mxfd_default,
bool notation_is_compact);
static icu::Locale CreateICULocale(const std::string& bcp47_locale);
// Helper funciton to convert a UnicodeString to a Handle<String>
V8_WARN_UNUSED_RESULT static MaybeHandle<String> ToString(
Isolate* isolate, const icu::UnicodeString& string);
@ -239,22 +227,6 @@ class Intl {
Isolate* isolate, Handle<JSReceiver> receiver,
Handle<JSFunction> constructor, bool has_initialized_slot);
// enum for "caseFirst" option: shared by Intl.Locale and Intl.Collator.
enum class CaseFirst { kUndefined, kUpper, kLower, kFalse };
// Shared function to read the "caseFirst" option.
V8_WARN_UNUSED_RESULT static Maybe<CaseFirst> GetCaseFirst(
Isolate* isolate, Handle<JSReceiver> options, const char* method);
// enum for "hourCycle" option: shared by Intl.Locale and Intl.DateTimeFormat.
enum class HourCycle { kUndefined, kH11, kH12, kH23, kH24 };
static HourCycle ToHourCycle(const std::string& str);
// Shared function to read the "hourCycle" option.
V8_WARN_UNUSED_RESULT static Maybe<HourCycle> GetHourCycle(
Isolate* isolate, Handle<JSReceiver> options, const char* method);
// enum for "localeMatcher" option: shared by many Intl objects.
enum class MatcherOption { kBestFit, kLookup };
@ -335,10 +307,6 @@ class Intl {
static icu::UnicodeString ToICUUnicodeString(Isolate* isolate,
Handle<String> string);
// Convert a Handle<String> to icu::StringPiece
static icu::StringPiece ToICUStringPiece(Isolate* isolate,
Handle<String> string);
static const uint8_t* ToLatin1LowerTable();
static String ConvertOneByteToLower(String src, String dst);
@ -346,8 +314,6 @@ class Intl {
static const std::set<std::string>& GetAvailableLocalesForLocale();
static const std::set<std::string>& GetAvailableLocalesForDateFormat();
static bool IsStructurallyValidLanguageTag(const std::string& tag);
};
} // namespace internal

View File

@ -37,6 +37,17 @@ enum class Sensitivity {
kUndefined,
};
// enum for "caseFirst" option.
enum class CaseFirst { kUndefined, kUpper, kLower, kFalse };
Maybe<CaseFirst> GetCaseFirst(Isolate* isolate, Handle<JSReceiver> options,
const char* method) {
return Intl::GetStringOption<CaseFirst>(
isolate, options, "caseFirst", method, {"upper", "lower", "false"},
{CaseFirst::kUpper, CaseFirst::kLower, CaseFirst::kFalse},
CaseFirst::kUndefined);
}
// TODO(gsathya): Consider internalizing the value strings.
void CreateDataPropertyForOptions(Isolate* isolate, Handle<JSObject> options,
Handle<String> key, const char* value) {
@ -202,21 +213,21 @@ Handle<JSObject> JSCollator::ResolvedOptions(Isolate* isolate,
namespace {
Intl::CaseFirst ToCaseFirst(const char* str) {
if (strcmp(str, "upper") == 0) return Intl::CaseFirst::kUpper;
if (strcmp(str, "lower") == 0) return Intl::CaseFirst::kLower;
if (strcmp(str, "false") == 0) return Intl::CaseFirst::kFalse;
return Intl::CaseFirst::kUndefined;
CaseFirst ToCaseFirst(const char* str) {
if (strcmp(str, "upper") == 0) return CaseFirst::kUpper;
if (strcmp(str, "lower") == 0) return CaseFirst::kLower;
if (strcmp(str, "false") == 0) return CaseFirst::kFalse;
return CaseFirst::kUndefined;
}
UColAttributeValue ToUColAttributeValue(Intl::CaseFirst case_first) {
UColAttributeValue ToUColAttributeValue(CaseFirst case_first) {
switch (case_first) {
case Intl::CaseFirst::kUpper:
case CaseFirst::kUpper:
return UCOL_UPPER_FIRST;
case Intl::CaseFirst::kLower:
case CaseFirst::kLower:
return UCOL_LOWER_FIRST;
case Intl::CaseFirst::kFalse:
case Intl::CaseFirst::kUndefined:
case CaseFirst::kFalse:
case CaseFirst::kUndefined:
return UCOL_OFF;
}
}
@ -229,8 +240,7 @@ void SetNumericOption(icu::Collator* icu_collator, bool numeric) {
CHECK(U_SUCCESS(status));
}
void SetCaseFirstOption(icu::Collator* icu_collator,
Intl::CaseFirst case_first) {
void SetCaseFirstOption(icu::Collator* icu_collator, CaseFirst case_first) {
CHECK_NOT_NULL(icu_collator);
UErrorCode status = U_ZERO_ERROR;
icu_collator->setAttribute(UCOL_CASE_FIRST, ToUColAttributeValue(case_first),
@ -300,10 +310,9 @@ MaybeHandle<JSCollator> JSCollator::New(Isolate* isolate, Handle<Map> map,
// 14. Let caseFirst be ? GetOption(options, "caseFirst", "string",
// « "upper", "lower", "false" », undefined).
Maybe<Intl::CaseFirst> maybe_case_first =
Intl::GetCaseFirst(isolate, options, service);
Maybe<CaseFirst> maybe_case_first = GetCaseFirst(isolate, options, service);
MAYBE_RETURN(maybe_case_first, MaybeHandle<JSCollator>());
Intl::CaseFirst case_first = maybe_case_first.FromJust();
CaseFirst case_first = maybe_case_first.FromJust();
// The relevant unicode extensions accepted by Collator as specified here:
// https://tc39.github.io/ecma402/#sec-intl-collator-internal-slots
@ -392,7 +401,7 @@ MaybeHandle<JSCollator> JSCollator::New(Isolate* isolate, Handle<Map> map,
// If the caseFirst value is passed in through the options object,
// then we use it. Otherwise, we check if the caseFirst value is
// passed in through the unicode extensions.
if (case_first != Intl::CaseFirst::kUndefined) {
if (case_first != CaseFirst::kUndefined) {
SetCaseFirstOption(icu_collator.get(), case_first);
} else {
auto kf_extension_it = r.extensions.find("kf");

View File

@ -29,13 +29,13 @@ ACCESSORS(JSDateTimeFormat, icu_date_interval_format,
ACCESSORS(JSDateTimeFormat, bound_format, Object, kBoundFormatOffset)
SMI_ACCESSORS(JSDateTimeFormat, flags, kFlagsOffset)
inline void JSDateTimeFormat::set_hour_cycle(Intl::HourCycle hour_cycle) {
inline void JSDateTimeFormat::set_hour_cycle(HourCycle hour_cycle) {
int hints = flags();
hints = HourCycleBits::update(hints, hour_cycle);
set_flags(hints);
}
inline Intl::HourCycle JSDateTimeFormat::hour_cycle() const {
inline JSDateTimeFormat::HourCycle JSDateTimeFormat::hour_cycle() const {
return HourCycleBits::decode(flags());
}

View File

@ -34,6 +34,24 @@ namespace internal {
namespace {
JSDateTimeFormat::HourCycle ToHourCycle(const std::string& hc) {
if (hc == "h11") return JSDateTimeFormat::HourCycle::kH11;
if (hc == "h12") return JSDateTimeFormat::HourCycle::kH12;
if (hc == "h23") return JSDateTimeFormat::HourCycle::kH23;
if (hc == "h24") return JSDateTimeFormat::HourCycle::kH24;
return JSDateTimeFormat::HourCycle::kUndefined;
}
Maybe<JSDateTimeFormat::HourCycle> GetHourCycle(Isolate* isolate,
Handle<JSReceiver> options,
const char* method) {
return Intl::GetStringOption<JSDateTimeFormat::HourCycle>(
isolate, options, "hourCycle", method, {"h11", "h12", "h23", "h24"},
{JSDateTimeFormat::HourCycle::kH11, JSDateTimeFormat::HourCycle::kH12,
JSDateTimeFormat::HourCycle::kH23, JSDateTimeFormat::HourCycle::kH24},
JSDateTimeFormat::HourCycle::kUndefined);
}
class PatternMap {
public:
PatternMap(std::string pattern, std::string value)
@ -210,29 +228,30 @@ DEFFINE_TRAIT(H24Trait, "kk", "k")
DEFFINE_TRAIT(HDefaultTrait, "jj", "j")
#undef DEFFINE_TRAIT
const std::vector<PatternData>& GetPatternData(Intl::HourCycle hour_cycle) {
const std::vector<PatternData>& GetPatternData(
JSDateTimeFormat::HourCycle hour_cycle) {
switch (hour_cycle) {
case Intl::HourCycle::kH11: {
case JSDateTimeFormat::HourCycle::kH11: {
static base::LazyInstance<Pattern, H11Trait>::type h11 =
LAZY_INSTANCE_INITIALIZER;
return h11.Pointer()->Get();
}
case Intl::HourCycle::kH12: {
case JSDateTimeFormat::HourCycle::kH12: {
static base::LazyInstance<Pattern, H12Trait>::type h12 =
LAZY_INSTANCE_INITIALIZER;
return h12.Pointer()->Get();
}
case Intl::HourCycle::kH23: {
case JSDateTimeFormat::HourCycle::kH23: {
static base::LazyInstance<Pattern, H23Trait>::type h23 =
LAZY_INSTANCE_INITIALIZER;
return h23.Pointer()->Get();
}
case Intl::HourCycle::kH24: {
case JSDateTimeFormat::HourCycle::kH24: {
static base::LazyInstance<Pattern, H24Trait>::type h24 =
LAZY_INSTANCE_INITIALIZER;
return h24.Pointer()->Get();
}
case Intl::HourCycle::kUndefined: {
case JSDateTimeFormat::HourCycle::kUndefined: {
static base::LazyInstance<Pattern, HDefaultTrait>::type hDefault =
LAZY_INSTANCE_INITIALIZER;
return hDefault.Pointer()->Get();
@ -320,10 +339,9 @@ std::string ToTitleCaseTimezoneLocation(Isolate* isolate,
return title_cased;
}
} // namespace
std::string JSDateTimeFormat::CanonicalizeTimeZoneID(Isolate* isolate,
const std::string& input) {
// Return the time zone id which match ICU's expectation of title casing
// return empty string when error.
std::string CanonicalizeTimeZoneID(Isolate* isolate, const std::string& input) {
std::string upper = input;
transform(upper.begin(), upper.end(), upper.begin(),
LocaleIndependentAsciiToUpper);
@ -344,8 +362,6 @@ std::string JSDateTimeFormat::CanonicalizeTimeZoneID(Isolate* isolate,
return ToTitleCaseTimezoneLocation(isolate, input);
}
namespace {
Handle<String> DateTimeStyleAsString(Isolate* isolate,
JSDateTimeFormat::DateTimeStyle style) {
switch (style) {
@ -485,32 +501,32 @@ MaybeHandle<JSObject> JSDateTimeFormat::ResolvedOptions(
.FromJust());
// 5.b.i. Let hc be dtf.[[HourCycle]].
Intl::HourCycle hc = date_time_format->hour_cycle();
HourCycle hc = date_time_format->hour_cycle();
if (hc != Intl::HourCycle::kUndefined) {
if (hc != HourCycle::kUndefined) {
CHECK(JSReceiver::CreateDataProperty(
isolate, options, factory->hourCycle_string(),
date_time_format->HourCycleAsString(), Just(kDontThrow))
.FromJust());
switch (hc) {
// ii. If hc is "h11" or "h12", let v be true.
case Intl::HourCycle::kH11:
case Intl::HourCycle::kH12:
case HourCycle::kH11:
case HourCycle::kH12:
CHECK(JSReceiver::CreateDataProperty(
isolate, options, factory->hour12_string(),
factory->true_value(), Just(kDontThrow))
.FromJust());
break;
// iii. Else if, hc is "h23" or "h24", let v be false.
case Intl::HourCycle::kH23:
case Intl::HourCycle::kH24:
case HourCycle::kH23:
case HourCycle::kH24:
CHECK(JSReceiver::CreateDataProperty(
isolate, options, factory->hour12_string(),
factory->false_value(), Just(kDontThrow))
.FromJust());
break;
// iv. Else, let v be undefined.
case Intl::HourCycle::kUndefined:
case HourCycle::kUndefined:
break;
}
}
@ -860,8 +876,7 @@ std::unique_ptr<icu::TimeZone> CreateTimeZone(Isolate* isolate,
// 19.a. Else / Let timeZone be DefaultTimeZone().
return std::unique_ptr<icu::TimeZone>(icu::TimeZone::createDefault());
}
std::string canonicalized =
JSDateTimeFormat::CanonicalizeTimeZoneID(isolate, timezone);
std::string canonicalized = CanonicalizeTimeZoneID(isolate, timezone);
if (canonicalized.empty()) return std::unique_ptr<icu::TimeZone>();
std::unique_ptr<icu::TimeZone> tz(
icu::TimeZone::createTimeZone(canonicalized.c_str()));
@ -925,21 +940,21 @@ icu::Calendar* CreateCalendar(Isolate* isolate, const icu::Locale& icu_locale,
}
icu::UnicodeString ReplaceHourCycleInPattern(icu::UnicodeString pattern,
Intl::HourCycle hc) {
JSDateTimeFormat::HourCycle hc) {
char16_t replacement;
switch (hc) {
case Intl::HourCycle::kUndefined:
case JSDateTimeFormat::HourCycle::kUndefined:
return pattern;
case Intl::HourCycle::kH11:
case JSDateTimeFormat::HourCycle::kH11:
replacement = 'K';
break;
case Intl::HourCycle::kH12:
case JSDateTimeFormat::HourCycle::kH12:
replacement = 'h';
break;
case Intl::HourCycle::kH23:
case JSDateTimeFormat::HourCycle::kH23:
replacement = 'H';
break;
case Intl::HourCycle::kH24:
case JSDateTimeFormat::HourCycle::kH24:
replacement = 'k';
break;
}
@ -971,7 +986,7 @@ icu::UnicodeString ReplaceHourCycleInPattern(icu::UnicodeString pattern,
std::unique_ptr<icu::SimpleDateFormat> CreateICUDateFormat(
const icu::Locale& icu_locale, const icu::UnicodeString& skeleton,
icu::DateTimePatternGenerator* generator, Intl::HourCycle hc) {
icu::DateTimePatternGenerator* generator, JSDateTimeFormat::HourCycle hc) {
// See https://github.com/tc39/ecma402/issues/225 . The best pattern
// generation needs to be done in the base locale according to the
// current spec however odd it may be. See also crbug.com/826549 .
@ -1005,7 +1020,7 @@ class DateFormatCache {
icu::SimpleDateFormat* Create(const icu::Locale& icu_locale,
const icu::UnicodeString& skeleton,
icu::DateTimePatternGenerator* generator,
Intl::HourCycle hc) {
JSDateTimeFormat::HourCycle hc) {
std::string key;
skeleton.toUTF8String<std::string>(key);
key += ":";
@ -1034,7 +1049,7 @@ class DateFormatCache {
std::unique_ptr<icu::SimpleDateFormat> CreateICUDateFormatFromCache(
const icu::Locale& icu_locale, const icu::UnicodeString& skeleton,
icu::DateTimePatternGenerator* generator, Intl::HourCycle hc) {
icu::DateTimePatternGenerator* generator, JSDateTimeFormat::HourCycle hc) {
static base::LazyInstance<DateFormatCache>::type cache =
LAZY_INSTANCE_INITIALIZER;
return std::unique_ptr<icu::SimpleDateFormat>(
@ -1078,7 +1093,8 @@ icu::DateIntervalFormat* LazyCreateDateIntervalFormat(
return (*managed_interval_format).raw();
}
Intl::HourCycle HourCycleFromPattern(const icu::UnicodeString pattern) {
JSDateTimeFormat::HourCycle HourCycleFromPattern(
const icu::UnicodeString pattern) {
bool in_quote = false;
for (int32_t i = 0; i < pattern.length(); i++) {
char16_t ch = pattern[i];
@ -1087,20 +1103,20 @@ Intl::HourCycle HourCycleFromPattern(const icu::UnicodeString pattern) {
in_quote = !in_quote;
break;
case 'K':
if (!in_quote) return Intl::HourCycle::kH11;
if (!in_quote) return JSDateTimeFormat::HourCycle::kH11;
break;
case 'h':
if (!in_quote) return Intl::HourCycle::kH12;
if (!in_quote) return JSDateTimeFormat::HourCycle::kH12;
break;
case 'H':
if (!in_quote) return Intl::HourCycle::kH23;
if (!in_quote) return JSDateTimeFormat::HourCycle::kH23;
break;
case 'k':
if (!in_quote) return Intl::HourCycle::kH24;
if (!in_quote) return JSDateTimeFormat::HourCycle::kH24;
break;
}
}
return Intl::HourCycle::kUndefined;
return JSDateTimeFormat::HourCycle::kUndefined;
}
icu::DateFormat::EStyle DateTimeStyleToEStyle(
@ -1120,23 +1136,23 @@ icu::DateFormat::EStyle DateTimeStyleToEStyle(
}
icu::UnicodeString ReplaceSkeleton(const icu::UnicodeString input,
Intl::HourCycle hc) {
JSDateTimeFormat::HourCycle hc) {
icu::UnicodeString result;
char16_t to;
switch (hc) {
case Intl::HourCycle::kH11:
case JSDateTimeFormat::HourCycle::kH11:
to = 'K';
break;
case Intl::HourCycle::kH12:
case JSDateTimeFormat::HourCycle::kH12:
to = 'h';
break;
case Intl::HourCycle::kH23:
case JSDateTimeFormat::HourCycle::kH23:
to = 'H';
break;
case Intl::HourCycle::kH24:
case JSDateTimeFormat::HourCycle::kH24:
to = 'k';
break;
case Intl::HourCycle::kUndefined:
case JSDateTimeFormat::HourCycle::kUndefined:
UNREACHABLE();
}
for (int32_t i = 0; i < input.length(); i++) {
@ -1170,7 +1186,7 @@ icu::UnicodeString ReplaceSkeleton(const icu::UnicodeString input,
std::unique_ptr<icu::SimpleDateFormat> DateTimeStylePattern(
JSDateTimeFormat::DateTimeStyle date_style,
JSDateTimeFormat::DateTimeStyle time_style, const icu::Locale& icu_locale,
Intl::HourCycle hc, icu::DateTimePatternGenerator* generator) {
JSDateTimeFormat::HourCycle hc, icu::DateTimePatternGenerator* generator) {
std::unique_ptr<icu::SimpleDateFormat> result;
if (date_style != JSDateTimeFormat::DateTimeStyle::kUndefined) {
if (time_style != JSDateTimeFormat::DateTimeStyle::kUndefined) {
@ -1340,15 +1356,14 @@ MaybeHandle<JSDateTimeFormat> JSDateTimeFormat::New(
// 7. Let hourCycle be ? GetOption(options, "hourCycle", "string", « "h11",
// "h12", "h23", "h24" », undefined).
Maybe<Intl::HourCycle> maybe_hour_cycle =
Intl::GetHourCycle(isolate, options, service);
Maybe<HourCycle> maybe_hour_cycle = GetHourCycle(isolate, options, service);
MAYBE_RETURN(maybe_hour_cycle, MaybeHandle<JSDateTimeFormat>());
Intl::HourCycle hour_cycle = maybe_hour_cycle.FromJust();
HourCycle hour_cycle = maybe_hour_cycle.FromJust();
// 8. If hour12 is not undefined, then
if (maybe_get_hour12.FromJust()) {
// a. Let hourCycle be null.
hour_cycle = Intl::HourCycle::kUndefined;
hour_cycle = HourCycle::kUndefined;
}
// 9. Set opt.[[hc]] to hourCycle.
@ -1441,20 +1456,20 @@ MaybeHandle<JSDateTimeFormat> JSDateTimeFormat::New(
// 15.Let hcDefault be dataLocaleData.[[hourCycle]].
icu::UnicodeString hour_pattern = generator->getBestPattern("jjmm", status);
CHECK(U_SUCCESS(status));
Intl::HourCycle hc_default = HourCycleFromPattern(hour_pattern);
HourCycle hc_default = HourCycleFromPattern(hour_pattern);
// 16.Let hc be r.[[hc]].
Intl::HourCycle hc = Intl::HourCycle::kUndefined;
if (hour_cycle == Intl::HourCycle::kUndefined) {
HourCycle hc = HourCycle::kUndefined;
if (hour_cycle == HourCycle::kUndefined) {
auto hc_extension_it = r.extensions.find("hc");
if (hc_extension_it != r.extensions.end()) {
hc = Intl::ToHourCycle(hc_extension_it->second.c_str());
hc = ToHourCycle(hc_extension_it->second.c_str());
}
} else {
hc = hour_cycle;
}
// 17. If hc is null, then
if (hc == Intl::HourCycle::kUndefined) {
if (hc == HourCycle::kUndefined) {
// a. Set hc to hcDefault.
hc = hc_default;
}
@ -1464,26 +1479,24 @@ MaybeHandle<JSDateTimeFormat> JSDateTimeFormat::New(
// a. If hour12 is true, then
if (hour12) {
// i. If hcDefault is "h11" or "h23", then
if (hc_default == Intl::HourCycle::kH11 ||
hc_default == Intl::HourCycle::kH23) {
if (hc_default == HourCycle::kH11 || hc_default == HourCycle::kH23) {
// 1. Set hc to "h11".
hc = Intl::HourCycle::kH11;
hc = HourCycle::kH11;
// ii. Else,
} else {
// 1. Set hc to "h12".
hc = Intl::HourCycle::kH12;
hc = HourCycle::kH12;
}
// b. Else,
} else {
// ii. If hcDefault is "h11" or "h23", then
if (hc_default == Intl::HourCycle::kH11 ||
hc_default == Intl::HourCycle::kH23) {
if (hc_default == HourCycle::kH11 || hc_default == HourCycle::kH23) {
// 1. Set hc to "h23".
hc = Intl::HourCycle::kH23;
hc = HourCycle::kH23;
// iii. Else,
} else {
// 1. Set hc to "h24".
hc = Intl::HourCycle::kH24;
hc = HourCycle::kH24;
}
}
}
@ -1591,7 +1604,7 @@ MaybeHandle<JSDateTimeFormat> JSDateTimeFormat::New(
// g. If dateTimeFormat.[[Hour]] is not undefined, then
if (!has_hour_option) {
// h. Else, i. Set dateTimeFormat.[[HourCycle]] to undefined.
hc = Intl::HourCycle::kUndefined;
hc = HourCycle::kUndefined;
}
}
@ -1614,10 +1627,10 @@ MaybeHandle<JSDateTimeFormat> JSDateTimeFormat::New(
//
// See details in https://github.com/tc39/test262/pull/2035
if (maybe_get_hour12.FromJust() ||
maybe_hour_cycle.FromJust() != Intl::HourCycle::kUndefined) {
maybe_hour_cycle.FromJust() != HourCycle::kUndefined) {
auto hc_extension_it = r.extensions.find("hc");
if (hc_extension_it != r.extensions.end()) {
if (hc != Intl::ToHourCycle(hc_extension_it->second.c_str())) {
if (hc != ToHourCycle(hc_extension_it->second.c_str())) {
// Remove -hc- if it does not agree with what we used.
UErrorCode status = U_ZERO_ERROR;
resolved_locale.setUnicodeKeywordValue("hc", nullptr, status);
@ -1791,15 +1804,15 @@ const std::set<std::string>& JSDateTimeFormat::GetAvailableLocales() {
Handle<String> JSDateTimeFormat::HourCycleAsString() const {
switch (hour_cycle()) {
case Intl::HourCycle::kUndefined:
case HourCycle::kUndefined:
return GetReadOnlyRoots().undefined_string_handle();
case Intl::HourCycle::kH11:
case HourCycle::kH11:
return GetReadOnlyRoots().h11_string_handle();
case Intl::HourCycle::kH12:
case HourCycle::kH12:
return GetReadOnlyRoots().h12_string_handle();
case Intl::HourCycle::kH23:
case HourCycle::kH23:
return GetReadOnlyRoots().h23_string_handle();
case Intl::HourCycle::kH24:
case HourCycle::kH24:
return GetReadOnlyRoots().h24_string_handle();
default:
UNREACHABLE();

View File

@ -48,11 +48,6 @@ class JSDateTimeFormat : public JSObject {
static Maybe<std::string> OptionsToSkeleton(Isolate* isolate,
Handle<JSReceiver> options);
// Return the time zone id which match ICU's expectation of title casing
// return empty string when error.
static std::string CanonicalizeTimeZoneID(Isolate* isolate,
const std::string& input);
// ecma402/#sec-datetime-format-functions
// DateTime Format Functions
V8_WARN_UNUSED_RESULT static MaybeHandle<String> DateTimeFormat(
@ -98,8 +93,11 @@ class JSDateTimeFormat : public JSObject {
DEFINE_FIELD_OFFSET_CONSTANTS(JSObject::kHeaderSize,
TORQUE_GENERATED_JS_DATE_TIME_FORMAT_FIELDS)
inline void set_hour_cycle(Intl::HourCycle hour_cycle);
inline Intl::HourCycle hour_cycle() const;
// enum for "hourCycle" option.
enum class HourCycle { kUndefined, kH11, kH12, kH23, kH24 };
inline void set_hour_cycle(HourCycle hour_cycle);
inline HourCycle hour_cycle() const;
inline void set_date_style(DateTimeStyle date_style);
inline DateTimeStyle date_style() const;
@ -108,19 +106,19 @@ class JSDateTimeFormat : public JSObject {
inline DateTimeStyle time_style() const;
// Bit positions in |flags|.
#define FLAGS_BIT_FIELDS(V, _) \
V(HourCycleBits, Intl::HourCycle, 3, _) \
V(DateStyleBits, DateTimeStyle, 3, _) \
#define FLAGS_BIT_FIELDS(V, _) \
V(HourCycleBits, HourCycle, 3, _) \
V(DateStyleBits, DateTimeStyle, 3, _) \
V(TimeStyleBits, DateTimeStyle, 3, _)
DEFINE_BIT_FIELDS(FLAGS_BIT_FIELDS)
#undef FLAGS_BIT_FIELDS
STATIC_ASSERT(Intl::HourCycle::kUndefined <= HourCycleBits::kMax);
STATIC_ASSERT(Intl::HourCycle::kH11 <= HourCycleBits::kMax);
STATIC_ASSERT(Intl::HourCycle::kH12 <= HourCycleBits::kMax);
STATIC_ASSERT(Intl::HourCycle::kH23 <= HourCycleBits::kMax);
STATIC_ASSERT(Intl::HourCycle::kH24 <= HourCycleBits::kMax);
STATIC_ASSERT(HourCycle::kUndefined <= HourCycleBits::kMax);
STATIC_ASSERT(HourCycle::kH11 <= HourCycleBits::kMax);
STATIC_ASSERT(HourCycle::kH12 <= HourCycleBits::kMax);
STATIC_ASSERT(HourCycle::kH23 <= HourCycleBits::kMax);
STATIC_ASSERT(HourCycle::kH24 <= HourCycleBits::kMax);
STATIC_ASSERT(DateTimeStyle::kUndefined <= DateStyleBits::kMax);
STATIC_ASSERT(DateTimeStyle::kFull <= DateStyleBits::kMax);

View File

@ -31,6 +31,7 @@
namespace v8 {
namespace internal {
namespace {
// Type: identifying the types of the display names.
//
// ecma402/#sec-properties-of-intl-displaynames-instances
@ -70,6 +71,8 @@ UDisplayContext ToUDisplayContext(JSDisplayNames::Style style) {
}
}
} // anonymous namespace
// Abstract class for all different types.
class DisplayNamesInternal {
public:
@ -82,6 +85,8 @@ class DisplayNamesInternal {
virtual const char* calendar() const { return nullptr; }
};
namespace {
class LocaleDisplayNamesCommon : public DisplayNamesInternal {
public:
LocaleDisplayNamesCommon(const icu::Locale& locale,
@ -474,6 +479,9 @@ DisplayNamesInternal* CreateInternal(const icu::Locale& locale,
UNREACHABLE();
}
}
} // anonymous namespace
// ecma402 #sec-Intl.DisplayNames
MaybeHandle<JSDisplayNames> JSDisplayNames::New(Isolate* isolate,
Handle<Map> map,

View File

@ -75,38 +75,6 @@ const char* GetIcuStyleString(JSListFormat::Style style,
} // namespace
JSListFormat::Style get_style(const char* str) {
switch (str[0]) {
case 'n':
if (strcmp(&str[1], "arrow") == 0) return JSListFormat::Style::NARROW;
break;
case 'l':
if (strcmp(&str[1], "ong") == 0) return JSListFormat::Style::LONG;
break;
case 's':
if (strcmp(&str[1], "hort") == 0) return JSListFormat::Style::SHORT;
break;
}
UNREACHABLE();
}
JSListFormat::Type get_type(const char* str) {
switch (str[0]) {
case 'c':
if (strcmp(&str[1], "onjunction") == 0)
return JSListFormat::Type::CONJUNCTION;
break;
case 'd':
if (strcmp(&str[1], "isjunction") == 0)
return JSListFormat::Type::DISJUNCTION;
break;
case 'u':
if (strcmp(&str[1], "nit") == 0) return JSListFormat::Type::UNIT;
break;
}
UNREACHABLE();
}
MaybeHandle<JSListFormat> JSListFormat::New(Isolate* isolate, Handle<Map> map,
Handle<Object> locales,
Handle<Object> input_options) {

View File

@ -24,6 +24,7 @@
namespace v8 {
namespace internal {
namespace {
// Style: identifying the relative time format style used.
//
// ecma402/#sec-properties-of-intl-relativetimeformat-instances
@ -34,7 +35,6 @@ enum class Style {
NARROW // Use the shortest possible form.
};
namespace {
UDateRelativeDateTimeFormatterStyle toIcuStyle(Style style) {
switch (style) {
case Style::LONG:

View File

@ -23,13 +23,6 @@
namespace v8 {
namespace internal {
JSSegmenter::Granularity JSSegmenter::GetGranularity(const char* str) {
if (strcmp(str, "grapheme") == 0) return JSSegmenter::Granularity::GRAPHEME;
if (strcmp(str, "word") == 0) return JSSegmenter::Granularity::WORD;
if (strcmp(str, "sentence") == 0) return JSSegmenter::Granularity::SENTENCE;
UNREACHABLE();
}
MaybeHandle<JSSegmenter> JSSegmenter::New(Isolate* isolate, Handle<Map> map,
Handle<Object> locales,
Handle<Object> input_options) {

View File

@ -82,8 +82,6 @@ class JSSegmenter : public JSObject {
TORQUE_GENERATED_JS_SEGMENTER_FIELDS)
private:
static Granularity GetGranularity(const char* str);
OBJECT_CONSTRUCTORS(JSSegmenter, JSObject);
};