Commit 0f0ead74 authored by Frank Tang's avatar Frank Tang Committed by V8 LUCI CQ

Implement proposal-intl-locale-info

Spec: https://tc39.es/proposal-intl-locale-info/
Design Doc: https://docs.google.com/document/d/1OwEsvs8VQwvR-ug01xLyIwpgcvUfaP24u9owc7aBKJ4/edit#
https://www.chromestatus.com/feature/5566859262820352

Behind flag --harmony_intl_locale_info

Bug: v8:11638

Change-Id: Ie616b3394d047c99d95ae46f112b5f0b367afe74
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2570218
Commit-Queue: Frank Tang <ftang@chromium.org>
Reviewed-by: 's avatarShu-yu Guo <syg@chromium.org>
Reviewed-by: 's avatarJakob Kummerow <jkummerow@chromium.org>
Cr-Commit-Position: refs/heads/master@{#74394}
parent eb648278
......@@ -982,6 +982,7 @@ namespace internal {
CPP(CollatorPrototypeCompare) \
/* ecma402 #sec-intl.collator.supportedlocalesof */ \
CPP(CollatorSupportedLocalesOf) \
/* ecma402 #sec-intl.collator.prototype.resolvedoptions */ \
CPP(CollatorPrototypeResolvedOptions) \
/* ecma402 #sup-date.prototype.tolocaledatestring */ \
CPP(DatePrototypeToLocaleDateString) \
......@@ -1027,21 +1028,46 @@ namespace internal {
CPP(ListFormatSupportedLocalesOf) \
/* ecma402 #sec-intl-locale-constructor */ \
CPP(LocaleConstructor) \
/* ecma402 #sec-Intl.Locale.prototype.baseName */ \
CPP(LocalePrototypeBaseName) \
/* ecma402 #sec-Intl.Locale.prototype.calendar */ \
CPP(LocalePrototypeCalendar) \
/* ecma402 #sec-Intl.Locale.prototype.calendars */ \
CPP(LocalePrototypeCalendars) \
/* ecma402 #sec-Intl.Locale.prototype.caseFirst */ \
CPP(LocalePrototypeCaseFirst) \
/* ecma402 #sec-Intl.Locale.prototype.collation */ \
CPP(LocalePrototypeCollation) \
/* ecma402 #sec-Intl.Locale.prototype.collations */ \
CPP(LocalePrototypeCollations) \
/* ecma402 #sec-Intl.Locale.prototype.hourCycle */ \
CPP(LocalePrototypeHourCycle) \
/* ecma402 #sec-Intl.Locale.prototype.hourCycles */ \
CPP(LocalePrototypeHourCycles) \
/* ecma402 #sec-Intl.Locale.prototype.language */ \
CPP(LocalePrototypeLanguage) \
/* ecma402 #sec-Intl.Locale.prototype.maximize */ \
CPP(LocalePrototypeMaximize) \
/* ecma402 #sec-Intl.Locale.prototype.minimize */ \
CPP(LocalePrototypeMinimize) \
/* ecma402 #sec-Intl.Locale.prototype.numeric */ \
CPP(LocalePrototypeNumeric) \
/* ecma402 #sec-Intl.Locale.prototype.numberingSystem */ \
CPP(LocalePrototypeNumberingSystem) \
/* ecma402 #sec-Intl.Locale.prototype.numberingSystems */ \
CPP(LocalePrototypeNumberingSystems) \
/* ecma402 #sec-Intl.Locale.prototype.region */ \
CPP(LocalePrototypeRegion) \
/* ecma402 #sec-Intl.Locale.prototype.script */ \
CPP(LocalePrototypeScript) \
/* ecma402 #sec-Intl.Locale.prototype.textInfo */ \
CPP(LocalePrototypeTextInfo) \
/* ecma402 #sec-Intl.Locale.prototype.timezones */ \
CPP(LocalePrototypeTimeZones) \
/* ecma402 #sec-Intl.Locale.prototype.toString */ \
CPP(LocalePrototypeToString) \
/* ecma402 #sec-Intl.Locale.prototype.weekInfo */ \
CPP(LocalePrototypeWeekInfo) \
/* ecma402 #sec-intl.numberformat */ \
CPP(NumberFormatConstructor) \
/* ecma402 #sec-number-format-functions */ \
......@@ -1056,6 +1082,7 @@ namespace internal {
CPP(NumberFormatSupportedLocalesOf) \
/* ecma402 #sec-intl.pluralrules */ \
CPP(PluralRulesConstructor) \
/* ecma402 #sec-intl.pluralrules.prototype.resolvedoptions */ \
CPP(PluralRulesPrototypeResolvedOptions) \
/* ecma402 #sec-intl.pluralrules.prototype.select */ \
CPP(PluralRulesPrototypeSelect) \
......
......@@ -668,6 +668,49 @@ BUILTIN(LocalePrototypeMinimize) {
RETURN_RESULT_OR_FAILURE(isolate, JSLocale::Minimize(isolate, locale));
}
BUILTIN(LocalePrototypeCalendars) {
HandleScope scope(isolate);
CHECK_RECEIVER(JSLocale, locale, "Intl.Locale.prototype.calendars");
RETURN_RESULT_OR_FAILURE(isolate, JSLocale::Calendars(isolate, locale));
}
BUILTIN(LocalePrototypeCollations) {
HandleScope scope(isolate);
CHECK_RECEIVER(JSLocale, locale, "Intl.Locale.prototype.collations");
RETURN_RESULT_OR_FAILURE(isolate, JSLocale::Collations(isolate, locale));
}
BUILTIN(LocalePrototypeHourCycles) {
HandleScope scope(isolate);
CHECK_RECEIVER(JSLocale, locale, "Intl.Locale.prototype.hourCycles");
RETURN_RESULT_OR_FAILURE(isolate, JSLocale::HourCycles(isolate, locale));
}
BUILTIN(LocalePrototypeNumberingSystems) {
HandleScope scope(isolate);
CHECK_RECEIVER(JSLocale, locale, "Intl.Locale.prototype.numberingSystems");
RETURN_RESULT_OR_FAILURE(isolate,
JSLocale::NumberingSystems(isolate, locale));
}
BUILTIN(LocalePrototypeTextInfo) {
HandleScope scope(isolate);
CHECK_RECEIVER(JSLocale, locale, "Intl.Locale.prototype.textInfo");
RETURN_RESULT_OR_FAILURE(isolate, JSLocale::TextInfo(isolate, locale));
}
BUILTIN(LocalePrototypeTimeZones) {
HandleScope scope(isolate);
CHECK_RECEIVER(JSLocale, locale, "Intl.Locale.prototype.timeZones");
RETURN_RESULT_OR_FAILURE(isolate, JSLocale::TimeZones(isolate, locale));
}
BUILTIN(LocalePrototypeWeekInfo) {
HandleScope scope(isolate);
CHECK_RECEIVER(JSLocale, locale, "Intl.Locale.prototype.weekInfo");
RETURN_RESULT_OR_FAILURE(isolate, JSLocale::WeekInfo(isolate, locale));
}
BUILTIN(RelativeTimeFormatSupportedLocalesOf) {
HandleScope scope(isolate);
Handle<Object> locales = args.atOrUndefined(isolate, 1);
......
......@@ -276,9 +276,10 @@ DEFINE_BOOL(harmony_shipping, true, "enable all shipped harmony features")
V(harmony_import_assertions, "harmony import assertions")
#ifdef V8_INTL_SUPPORT
#define HARMONY_INPROGRESS(V) \
HARMONY_INPROGRESS_BASE(V) \
V(harmony_intl_displaynames_date_types, "Intl.DisplayNames date types")
#define HARMONY_INPROGRESS(V) \
HARMONY_INPROGRESS_BASE(V) \
V(harmony_intl_displaynames_date_types, "Intl.DisplayNames date types") \
V(harmony_intl_locale_info, "Intl locale info")
#else
#define HARMONY_INPROGRESS(V) HARMONY_INPROGRESS_BASE(V)
#endif
......
......@@ -4525,6 +4525,32 @@ void Genesis::InitializeGlobal_harmony_relative_indexing_methods() {
}
}
#ifdef V8_INTL_SUPPORT
void Genesis::InitializeGlobal_harmony_intl_locale_info() {
if (!FLAG_harmony_intl_locale_info) return;
Handle<JSObject> prototype(
JSObject::cast(native_context()->intl_locale_function().prototype()),
isolate_);
SimpleInstallGetter(isolate(), prototype, factory()->calendars_string(),
Builtins::kLocalePrototypeCalendars, true);
SimpleInstallGetter(isolate(), prototype, factory()->collations_string(),
Builtins::kLocalePrototypeCollations, true);
SimpleInstallGetter(isolate(), prototype, factory()->hourCycles_string(),
Builtins::kLocalePrototypeHourCycles, true);
SimpleInstallGetter(isolate(), prototype,
factory()->numberingSystems_string(),
Builtins::kLocalePrototypeNumberingSystems, true);
SimpleInstallGetter(isolate(), prototype, factory()->textInfo_string(),
Builtins::kLocalePrototypeTextInfo, true);
SimpleInstallGetter(isolate(), prototype, factory()->timeZones_string(),
Builtins::kLocalePrototypeTimeZones, true);
SimpleInstallGetter(isolate(), prototype, factory()->weekInfo_string(),
Builtins::kLocalePrototypeWeekInfo, true);
}
#endif // V8_INTL_SUPPORT
Handle<JSFunction> Genesis::CreateArrayBuffer(
Handle<String> name, ArrayBufferKind array_buffer_kind) {
// Create the %ArrayBufferPrototype%
......
......@@ -12,10 +12,12 @@
V(_, accounting_string, "accounting") \
V(_, breakType_string, "breakType") \
V(_, calendar_string, "calendar") \
V(_, calendars_string, "calendars") \
V(_, cardinal_string, "cardinal") \
V(_, caseFirst_string, "caseFirst") \
V(_, compare_string, "compare") \
V(_, collation_string, "collation") \
V(_, collations_string, "collations") \
V(_, compact_string, "compact") \
V(_, compactDisplay_string, "compactDisplay") \
V(_, currency_string, "currency") \
......@@ -26,6 +28,7 @@
V(_, day_string, "day") \
V(_, dayPeriod_string, "dayPeriod") \
V(_, decimal_string, "decimal") \
V(_, direction_string, "direction") \
V(_, endRange_string, "endRange") \
V(_, engineering_string, "engineering") \
V(_, era_string, "era") \
......@@ -35,6 +38,7 @@
V(_, exponentSeparator_string, "exponentSeparator") \
V(_, fallback_string, "fallback") \
V(_, first_string, "first") \
V(_, firstDay_string, "firstDay") \
V(_, format_string, "format") \
V(_, fraction_string, "fraction") \
V(_, fractionalSecond_string, "fractionalSecond") \
......@@ -50,6 +54,7 @@
V(_, hour_string, "hour") \
V(_, hour12_string, "hour12") \
V(_, hourCycle_string, "hourCycle") \
V(_, hourCycles_string, "hourCycles") \
V(_, ideo_string, "ideo") \
V(_, ignorePunctuation_string, "ignorePunctuation") \
V(_, Invalid_Date_string, "Invalid Date") \
......@@ -63,8 +68,10 @@
V(_, locale_string, "locale") \
V(_, loose_string, "loose") \
V(_, lower_string, "lower") \
V(_, ltr_string, "ltr") \
V(_, maximumFractionDigits_string, "maximumFractionDigits") \
V(_, maximumSignificantDigits_string, "maximumSignificantDigits") \
V(_, minimalDays_string, "minimalDays") \
V(_, minimumFractionDigits_string, "minimumFractionDigits") \
V(_, minimumIntegerDigits_string, "minimumIntegerDigits") \
V(_, minimumSignificantDigits_string, "minimumSignificantDigits") \
......@@ -78,6 +85,7 @@
V(_, notation_string, "notation") \
V(_, normal_string, "normal") \
V(_, numberingSystem_string, "numberingSystem") \
V(_, numberingSystems_string, "numberingSystems") \
V(_, numeric_string, "numeric") \
V(_, ordinal_string, "ordinal") \
V(_, percentSign_string, "percentSign") \
......@@ -85,6 +93,7 @@
V(_, quarter_string, "quarter") \
V(_, region_string, "region") \
V(_, relatedYear_string, "relatedYear") \
V(_, rtl_string, "rtl") \
V(_, scientific_string, "scientific") \
V(_, second_string, "second") \
V(_, segment_string, "segment") \
......@@ -99,8 +108,10 @@
V(_, strict_string, "strict") \
V(_, style_string, "style") \
V(_, term_string, "term") \
V(_, textInfo_string, "textInfo") \
V(_, timeStyle_string, "timeStyle") \
V(_, timeZone_string, "timeZone") \
V(_, timeZones_string, "timeZones") \
V(_, timeZoneName_string, "timeZoneName") \
V(_, type_string, "type") \
V(_, unknown_string, "unknown") \
......@@ -111,6 +122,9 @@
V(_, unit_string, "unit") \
V(_, unitDisplay_string, "unitDisplay") \
V(_, weekday_string, "weekday") \
V(_, weekendEnd_string, "weekendEnd") \
V(_, weekendStart_string, "weekendStart") \
V(_, weekInfo_string, "weekInfo") \
V(_, year_string, "year") \
V(_, yearName_string, "yearName")
#else // V8_INTL_SUPPORT
......
......@@ -20,10 +20,15 @@
#include "src/objects/intl-objects.h"
#include "src/objects/js-locale-inl.h"
#include "src/objects/objects-inl.h"
#include "unicode/calendar.h"
#include "unicode/char16ptr.h"
#include "unicode/coll.h"
#include "unicode/dtptngen.h"
#include "unicode/localebuilder.h"
#include "unicode/locid.h"
#include "unicode/ucal.h"
#include "unicode/uloc.h"
#include "unicode/ulocdata.h"
#include "unicode/unistr.h"
namespace v8 {
......@@ -165,6 +170,11 @@ bool IsUnicodeVariantSubtag(const std::string& value) {
bool IsExtensionSingleton(const std::string& value) {
return IsAlphanum(value, 1, 1);
}
int32_t weekdayFromEDaysOfWeek(icu::Calendar::EDaysOfWeek eDaysOfWeek) {
return (eDaysOfWeek == icu::Calendar::SUNDAY) ? 7 : eDaysOfWeek - 1;
}
} // namespace
bool JSLocale::Is38AlphaNumList(const std::string& value) {
......@@ -450,6 +460,340 @@ MaybeHandle<JSLocale> JSLocale::Minimize(Isolate* isolate,
return Construct(isolate, result);
}
template <typename T>
MaybeHandle<JSArray> GetKeywordValuesFromLocale(
Isolate* isolate, const char* key, const char* unicode_key,
const icu::Locale& locale,
const std::map<std::string, std::string>& substitutions) {
Factory* factory = isolate->factory();
UErrorCode status = U_ZERO_ERROR;
std::string ext =
locale.getUnicodeKeywordValue<std::string>(unicode_key, status);
if (!ext.empty()) {
Handle<FixedArray> fixed_array = factory->NewFixedArray(1);
Handle<String> str = factory->NewStringFromAsciiChecked(ext.c_str());
fixed_array->set(0, *str);
return factory->NewJSArrayWithElements(fixed_array);
}
status = U_ZERO_ERROR;
std::unique_ptr<icu::StringEnumeration> enumeration(
T::getKeywordValuesForLocale(key, locale, true, status));
if (U_FAILURE(status)) {
THROW_NEW_ERROR(isolate, NewRangeError(MessageTemplate::kIcuError),
JSArray);
}
int32_t count = enumeration->count(status);
if (U_FAILURE(status)) {
THROW_NEW_ERROR(isolate, NewRangeError(MessageTemplate::kIcuError),
JSArray);
}
Handle<FixedArray> fixed_array = factory->NewFixedArray(count);
int32_t index = 0;
for (const char* item = enumeration->next(nullptr, status);
U_SUCCESS(status) && item != nullptr;
item = enumeration->next(nullptr, status)) {
auto mapped = substitutions.find(item);
if (mapped != substitutions.end()) {
item = mapped->second.c_str();
if (*item == '\0') {
continue;
}
}
Handle<String> str = factory->NewStringFromAsciiChecked(item);
fixed_array->set(index++, *str);
}
if (U_FAILURE(status)) {
THROW_NEW_ERROR(isolate, NewRangeError(MessageTemplate::kIcuError),
JSArray);
}
return factory->NewJSArrayWithElements(fixed_array);
}
MaybeHandle<JSArray> JSLocale::Calendars(Isolate* isolate,
Handle<JSLocale> locale) {
icu::Locale icu_locale(*(locale->icu_locale().raw()));
const std::map<std::string, std::string> substitutions(
{{"gregorian", "gregory"}, {"ethiopic-amete-alem", "ethioaa"}});
return GetKeywordValuesFromLocale<icu::Calendar>(isolate, "calendar", "ca",
icu_locale, substitutions);
}
MaybeHandle<JSArray> JSLocale::Collations(Isolate* isolate,
Handle<JSLocale> locale) {
icu::Locale icu_locale(*(locale->icu_locale().raw()));
const std::map<std::string, std::string> substitutions(
{{"standard", ""}, {"search", ""}});
return GetKeywordValuesFromLocale<icu::Collator>(isolate, "collations", "co",
icu_locale, substitutions);
}
MaybeHandle<JSArray> JSLocale::HourCycles(Isolate* isolate,
Handle<JSLocale> locale) {
// Let preferred be loc.[[HourCycle]].
// Let locale be loc.[[Locale]].
icu::Locale icu_locale(*(locale->icu_locale().raw()));
Factory* factory = isolate->factory();
// Assert: locale matches the unicode_locale_id production.
// Let list be a List of 1 or more hour cycle identifiers, which must be
// String values indicating either the 12-hour format ("h11", "h12") or the
// 24-hour format ("h23", "h24"), sorted in descending preference of those in
// common use in the locale for date and time formatting.
// Return CreateArrayFromListAndPreferred( list, preferred ).
Handle<FixedArray> fixed_array = factory->NewFixedArray(1);
UErrorCode status = U_ZERO_ERROR;
std::string ext =
icu_locale.getUnicodeKeywordValue<std::string>("hc", status);
if (!ext.empty()) {
Handle<String> str = factory->NewStringFromAsciiChecked(ext.c_str());
fixed_array->set(0, *str);
return factory->NewJSArrayWithElements(fixed_array);
}
status = U_ZERO_ERROR;
std::unique_ptr<icu::DateTimePatternGenerator> generator(
icu::DateTimePatternGenerator::createInstance(icu_locale, status));
if (U_FAILURE(status)) {
THROW_NEW_ERROR(isolate, NewRangeError(MessageTemplate::kIcuError),
JSArray);
}
UDateFormatHourCycle hc = generator->getDefaultHourCycle(status);
if (U_FAILURE(status)) {
THROW_NEW_ERROR(isolate, NewRangeError(MessageTemplate::kIcuError),
JSArray);
}
Handle<String> hour_cycle;
switch (hc) {
case UDAT_HOUR_CYCLE_11:
hour_cycle = factory->h11_string();
break;
case UDAT_HOUR_CYCLE_12:
hour_cycle = factory->h12_string();
break;
case UDAT_HOUR_CYCLE_23:
hour_cycle = factory->h23_string();
break;
case UDAT_HOUR_CYCLE_24:
hour_cycle = factory->h24_string();
break;
default:
break;
}
fixed_array->set(0, *hour_cycle);
return factory->NewJSArrayWithElements(fixed_array);
}
MaybeHandle<JSArray> JSLocale::NumberingSystems(Isolate* isolate,
Handle<JSLocale> locale) {
// Let preferred be loc.[[NumberingSystem]].
// Let locale be loc.[[Locale]].
icu::Locale icu_locale(*(locale->icu_locale().raw()));
Factory* factory = isolate->factory();
// Assert: locale matches the unicode_locale_id production.
// Let list be a List of 1 or more numbering system identifiers, which must be
// String values conforming to the type sequence from UTS 35 Unicode Locale
// Identifier, section 3.2, sorted in descending preference of those in common
// use in the locale for formatting numeric values.
// Return CreateArrayFromListAndPreferred( list, preferred ).
UErrorCode status = U_ZERO_ERROR;
Handle<FixedArray> fixed_array = factory->NewFixedArray(1);
std::string numbering_system =
icu_locale.getUnicodeKeywordValue<std::string>("nu", status);
if (numbering_system.empty()) {
numbering_system = Intl::GetNumberingSystem(icu_locale);
}
Handle<String> str =
factory->NewStringFromAsciiChecked(numbering_system.c_str());
fixed_array->set(0, *str);
return factory->NewJSArrayWithElements(fixed_array);
}
MaybeHandle<Object> JSLocale::TimeZones(Isolate* isolate,
Handle<JSLocale> locale) {
// Let loc be the this value.
// Perform ? RequireInternalSlot(loc, [[InitializedLocale]])
// Let locale be loc.[[Locale]].
icu::Locale icu_locale(*(locale->icu_locale().raw()));
Factory* factory = isolate->factory();
// If the unicode_language_id production of locale does not contain the
// ["-" unicode_region_subtag] sequence, return undefined.
const char* region = icu_locale.getCountry();
if (region == nullptr || strlen(region) == 0) {
return factory->undefined_value();
}
// Return TimeZonesOfLocale(loc).
// Let locale be loc.[[Locale]].
// Assert: locale matches the unicode_locale_id production.
// Let region be the substring of locale corresponding to the
// unicode_region_subtag production of the unicode_language_id.
// Let list be a List of 1 or more time zone identifiers, which must be String
// values indicating a Zone or Link name of the IANA Time Zone Database,
// sorted in descending preference of those in common use in region.
int32_t index = 0;
UErrorCode status = U_ZERO_ERROR;
std::unique_ptr<icu::StringEnumeration> enumeration(
icu::TimeZone::createTimeZoneIDEnumeration(UCAL_ZONE_TYPE_CANONICAL,
region, nullptr, status));
if (U_FAILURE(status)) {
THROW_NEW_ERROR(isolate, NewRangeError(MessageTemplate::kIcuError),
JSArray);
}
int32_t count = enumeration->count(status);
if (U_FAILURE(status)) {
THROW_NEW_ERROR(isolate, NewRangeError(MessageTemplate::kIcuError),
JSArray);
}
// Return CreateArrayFromList( list ).
Handle<FixedArray> fixed_array = factory->NewFixedArray(count);
for (const char* item = enumeration->next(nullptr, status);
U_SUCCESS(status) && item != nullptr;
item = enumeration->next(nullptr, status)) {
Handle<String> str = isolate->factory()->NewStringFromAsciiChecked(item);
fixed_array->set(index++, *str);
}
if (U_FAILURE(status)) {
THROW_NEW_ERROR(isolate, NewRangeError(MessageTemplate::kIcuError),
JSArray);
}
return factory->NewJSArrayWithElements(fixed_array);
}
MaybeHandle<JSObject> JSLocale::TextInfo(Isolate* isolate,
Handle<JSLocale> locale) {
// Let loc be the this value.
// Perform ? RequireInternalSlot(loc, [[InitializedLocale]]).
// Let locale be loc.[[Locale]].
// Assert: locale matches the unicode_locale_id production.
Factory* factory = isolate->factory();
// Let info be ! ObjectCreate(%Object.prototype%).
Handle<JSObject> info = factory->NewJSObject(isolate->object_function());
// Let dir be "ltr".
Handle<String> dir = factory->ltr_string();
// If the default general ordering of characters (characterOrder) within a
// line in the locale is right-to-left, then
UErrorCode status = U_ZERO_ERROR;
ULayoutType orientation = uloc_getCharacterOrientation(
(locale->icu_locale().raw())->getName(), &status);
if (U_FAILURE(status)) {
THROW_NEW_ERROR(isolate, NewRangeError(MessageTemplate::kIcuError),
JSObject);
}
if (orientation == ULOC_LAYOUT_LTR) {
// Let dir be "rtl".
dir = factory->rtl_string();
}
// Perform ! CreateDataPropertyOrThrow(info, "direction", dir).
CHECK(JSReceiver::CreateDataProperty(
isolate, info, factory->direction_string(), dir, Just(kDontThrow))
.FromJust());
// Return info.
return info;
}
MaybeHandle<JSObject> JSLocale::WeekInfo(Isolate* isolate,
Handle<JSLocale> locale) {
// Let loc be the this value.
// Perform ? RequireInternalSlot(loc, [[InitializedLocale]]).
// Let locale be loc.[[Locale]].
// Assert: locale matches the unicode_locale_id production.
Factory* factory = isolate->factory();
// Let info be ! ObjectCreate(%Object.prototype%).
Handle<JSObject> info = factory->NewJSObject(isolate->object_function());
UErrorCode status = U_ZERO_ERROR;
std::unique_ptr<icu::Calendar> calendar(
icu::Calendar::createInstance(*(locale->icu_locale().raw()), status));
if (U_FAILURE(status)) {
THROW_NEW_ERROR(isolate, NewRangeError(MessageTemplate::kIcuError),
JSObject);
}
// Let fd be the weekday value indicating which day of the week is considered
// the 'first' day, for calendar purposes, in the locale.
int32_t fd = weekdayFromEDaysOfWeek(calendar->getFirstDayOfWeek());
bool thursday_is_weekend =
(UCAL_WEEKDAY != calendar->getDayOfWeekType(UCAL_THURSDAY, status));
bool friday_is_weekend =
(UCAL_WEEKDAY != calendar->getDayOfWeekType(UCAL_FRIDAY, status));
bool saturday_is_weekend =
(UCAL_WEEKDAY != calendar->getDayOfWeekType(UCAL_SATURDAY, status));
bool sunday_is_weekend =
(UCAL_WEEKDAY != calendar->getDayOfWeekType(UCAL_SUNDAY, status));
if (U_FAILURE(status)) {
THROW_NEW_ERROR(isolate, NewRangeError(MessageTemplate::kIcuError),
JSObject);
}
// Let ws be the weekday value indicating which day of the week is considered
// the starting day of the 'weekend', for calendar purposes, in the locale.
int32_t ws = thursday_is_weekend ? 4 : (friday_is_weekend ? 5 : 6);
// Let we be the weekday value indicating which day of the week is considered
// the ending day of the 'weekend', for calendar purposes, in the locale.
int32_t we = sunday_is_weekend ? 7 : (saturday_is_weekend ? 6 : 5);
// Let md be the minimal days required in the first week of a month or year,
// for calendar purposes, in the locale.
int32_t md = calendar->getMinimalDaysInFirstWeek();
// Perform ! CreateDataPropertyOrThrow(info, "firstDay", fd).
CHECK(JSReceiver::CreateDataProperty(
isolate, info, factory->firstDay_string(),
factory->NewNumberFromInt(fd), Just(kDontThrow))
.FromJust());
// Perform ! CreateDataPropertyOrThrow(info, "weekendStart", ws).
CHECK(JSReceiver::CreateDataProperty(
isolate, info, factory->weekendStart_string(),
factory->NewNumberFromInt(ws), Just(kDontThrow))
.FromJust());
// Perform ! CreateDataPropertyOrThrow(info, "weekendEnd", we).
CHECK(JSReceiver::CreateDataProperty(
isolate, info, factory->weekendEnd_string(),
factory->NewNumberFromInt(we), Just(kDontThrow))
.FromJust());
// Perform ! CreateDataPropertyOrThrow(info, "minimalDays", md).
CHECK(JSReceiver::CreateDataProperty(
isolate, info, factory->minimalDays_string(),
factory->NewNumberFromInt(md), Just(kDontThrow))
.FromJust());
// Return info.
return info;
}
Handle<Object> JSLocale::Language(Isolate* isolate, Handle<JSLocale> locale) {
Factory* factory = isolate->factory();
const char* language = locale->icu_locale().raw()->getLanguage();
......
......@@ -40,6 +40,21 @@ class JSLocale : public TorqueGeneratedJSLocale<JSLocale, JSObject> {
static MaybeHandle<JSLocale> Minimize(Isolate* isolate,
Handle<JSLocale> locale);
V8_WARN_UNUSED_RESULT static MaybeHandle<JSArray> Calendars(
Isolate* isolate, Handle<JSLocale> locale);
V8_WARN_UNUSED_RESULT static MaybeHandle<JSArray> Collations(
Isolate* isolate, Handle<JSLocale> locale);
V8_WARN_UNUSED_RESULT static MaybeHandle<JSArray> HourCycles(
Isolate* isolate, Handle<JSLocale> locale);
V8_WARN_UNUSED_RESULT static MaybeHandle<JSArray> NumberingSystems(
Isolate* isolate, Handle<JSLocale> locale);
V8_WARN_UNUSED_RESULT static MaybeHandle<JSObject> TextInfo(
Isolate* isolate, Handle<JSLocale> locale);
V8_WARN_UNUSED_RESULT static MaybeHandle<Object> TimeZones(
Isolate* isolate, Handle<JSLocale> locale);
V8_WARN_UNUSED_RESULT static MaybeHandle<JSObject> WeekInfo(
Isolate* isolate, Handle<JSLocale> locale);
static Handle<Object> Language(Isolate* isolate, Handle<JSLocale> locale);
static Handle<Object> Script(Isolate* isolate, Handle<JSLocale> locale);
static Handle<Object> Region(Isolate* isolate, Handle<JSLocale> locale);
......
// Copyright 2021 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --harmony_intl_locale_info
// Check getter properties against the spec.
function checkProperties(property) {
let desc = Object.getOwnPropertyDescriptor(Intl.Locale.prototype, property);
assertEquals(`get ${property}`, desc.get.name);
assertEquals('function', typeof desc.get)
assertEquals(undefined, desc.set);
assertFalse(desc.enumerable);
assertTrue(desc.configurable);
}
checkProperties('calendars');
checkProperties('collations');
checkProperties('hourCycles');
checkProperties('numberingSystems');
checkProperties('textInfo');
checkProperties('timeZones');
checkProperties('weekInfo');
// Copyright 2021 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --harmony_intl_locale_info
function checkLocale(locale) {
let l = new Intl.Locale(locale);
assertTrue(Array.isArray(l.calendars));
assertTrue(Array.isArray(l.collations));
assertTrue(Array.isArray(l.hourCycles));
assertTrue(Array.isArray(l.numberingSystems));
if (l.region == undefined) {
assertEquals(undefined, l.timeZones);
} else {
assertTrue(Array.isArray(l.timeZones));
}
assertEquals("object", typeof(l.textInfo));
assertEquals(1, Object.keys(l.textInfo).length);
assertEquals("string", typeof(l.textInfo.direction));
assertEquals("object", typeof(l.weekInfo));
assertEquals(4, Object.keys(l.weekInfo).length);
assertEquals("number", typeof(l.weekInfo.firstDay));
assertTrue(l.weekInfo.firstDay >= 1);
assertTrue(l.weekInfo.firstDay <= 7);
assertEquals("number", typeof(l.weekInfo.weekendStart));
assertTrue(l.weekInfo.weekendStart >= 1);
assertTrue(l.weekInfo.weekendStart <= 7);
assertEquals("number", typeof(l.weekInfo.weekendEnd));
assertTrue(l.weekInfo.weekendEnd >= 1);
assertTrue(l.weekInfo.weekendEnd <= 7);
assertEquals("number", typeof(l.weekInfo.minimalDays));
assertTrue(l.weekInfo.minimalDays >= 1);
assertTrue(l.weekInfo.minimalDays <= 7);
}
checkLocale("ar");
checkLocale("en");
checkLocale("fr");
checkLocale("en-GB");
// Copyright 2021 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --harmony_intl_locale_info
// Test Unicode extension.
function testExt(base, ukey, uvalue, property) {
let baseLocale = new Intl.Locale(base);
let extLocale = new Intl.Locale(base + "-u-" + ukey + "-" + uvalue);
let baseActual = baseLocale[property];
assertTrue(Array.isArray(baseActual));
assertTrue(baseActual.length > 0);
assertFalse(uvalue == baseActual[0]);
let extActual = extLocale[property];
assertTrue(Array.isArray(extActual));
assertEquals(1, extActual.length);
assertEquals(uvalue, extActual[0]);
}
testExt("ar", "ca", "roc", "calendars");
testExt("fr", "nu", "thai", "numberingSystems");
testExt("th", "co", "pinyin", "collations");
testExt("ko", "hc", "h11", "hourCycles");
......@@ -328,67 +328,67 @@ KNOWN_MAPS = {
("read_only_space", 0x031ed): (67, "BasicBlockCountersMarkerMap"),
("read_only_space", 0x03231): (90, "ArrayBoilerplateDescriptionMap"),
("read_only_space", 0x03331): (103, "InterceptorInfoMap"),
("read_only_space", 0x0549d): (75, "PromiseFulfillReactionJobTaskMap"),
("read_only_space", 0x054c5): (76, "PromiseRejectReactionJobTaskMap"),
("read_only_space", 0x054ed): (77, "CallableTaskMap"),
("read_only_space", 0x05515): (78, "CallbackTaskMap"),
("read_only_space", 0x0553d): (79, "PromiseResolveThenableJobTaskMap"),
("read_only_space", 0x05565): (82, "FunctionTemplateInfoMap"),
("read_only_space", 0x0558d): (83, "ObjectTemplateInfoMap"),
("read_only_space", 0x055b5): (84, "AccessCheckInfoMap"),
("read_only_space", 0x055dd): (85, "AccessorInfoMap"),
("read_only_space", 0x05605): (86, "AccessorPairMap"),
("read_only_space", 0x0562d): (87, "AliasedArgumentsEntryMap"),
("read_only_space", 0x05655): (88, "AllocationMementoMap"),
("read_only_space", 0x0567d): (91, "AsmWasmDataMap"),
("read_only_space", 0x056a5): (92, "AsyncGeneratorRequestMap"),
("read_only_space", 0x056cd): (93, "BaselineDataMap"),
("read_only_space", 0x056f5): (94, "BreakPointMap"),
("read_only_space", 0x0571d): (95, "BreakPointInfoMap"),
("read_only_space", 0x05745): (96, "CachedTemplateObjectMap"),
("read_only_space", 0x0576d): (98, "ClassPositionsMap"),
("read_only_space", 0x05795): (99, "DebugInfoMap"),
("read_only_space", 0x057bd): (102, "FunctionTemplateRareDataMap"),
("read_only_space", 0x057e5): (104, "InterpreterDataMap"),
("read_only_space", 0x0580d): (105, "ModuleRequestMap"),
("read_only_space", 0x05835): (106, "PromiseCapabilityMap"),
("read_only_space", 0x0585d): (107, "PromiseReactionMap"),
("read_only_space", 0x05885): (108, "PropertyDescriptorObjectMap"),
("read_only_space", 0x058ad): (109, "PrototypeInfoMap"),
("read_only_space", 0x058d5): (110, "RegExpBoilerplateDescriptionMap"),
("read_only_space", 0x058fd): (111, "ScriptMap"),
("read_only_space", 0x05925): (112, "SourceTextModuleInfoEntryMap"),
("read_only_space", 0x0594d): (113, "StackFrameInfoMap"),
("read_only_space", 0x05975): (114, "TemplateObjectDescriptionMap"),
("read_only_space", 0x0599d): (115, "Tuple2Map"),
("read_only_space", 0x059c5): (116, "WasmExceptionTagMap"),
("read_only_space", 0x059ed): (117, "WasmIndirectFunctionTableMap"),
("read_only_space", 0x05a15): (135, "SloppyArgumentsElementsMap"),
("read_only_space", 0x05a3d): (152, "DescriptorArrayMap"),
("read_only_space", 0x05a65): (157, "UncompiledDataWithoutPreparseDataMap"),
("read_only_space", 0x05a8d): (156, "UncompiledDataWithPreparseDataMap"),
("read_only_space", 0x05ab5): (173, "OnHeapBasicBlockProfilerDataMap"),
("read_only_space", 0x05add): (169, "InternalClassMap"),
("read_only_space", 0x05b05): (180, "SmiPairMap"),
("read_only_space", 0x05b2d): (179, "SmiBoxMap"),
("read_only_space", 0x05b55): (146, "ExportedSubClassBaseMap"),
("read_only_space", 0x05b7d): (147, "ExportedSubClassMap"),
("read_only_space", 0x05ba5): (68, "AbstractInternalClassSubclass1Map"),
("read_only_space", 0x05bcd): (69, "AbstractInternalClassSubclass2Map"),
("read_only_space", 0x05bf5): (134, "InternalClassWithSmiElementsMap"),
("read_only_space", 0x05c1d): (170, "InternalClassWithStructElementsMap"),
("read_only_space", 0x05c45): (148, "ExportedSubClass2Map"),
("read_only_space", 0x05c6d): (181, "SortStateMap"),
("read_only_space", 0x05c95): (184, "WasmCapiFunctionDataMap"),
("read_only_space", 0x05cbd): (89, "AllocationSiteWithWeakNextMap"),
("read_only_space", 0x05ce5): (89, "AllocationSiteWithoutWeakNextMap"),
("read_only_space", 0x05d0d): (80, "LoadHandler1Map"),
("read_only_space", 0x05d35): (80, "LoadHandler2Map"),
("read_only_space", 0x05d5d): (80, "LoadHandler3Map"),
("read_only_space", 0x05d85): (81, "StoreHandler0Map"),
("read_only_space", 0x05dad): (81, "StoreHandler1Map"),
("read_only_space", 0x05dd5): (81, "StoreHandler2Map"),
("read_only_space", 0x05dfd): (81, "StoreHandler3Map"),
("read_only_space", 0x055d5): (75, "PromiseFulfillReactionJobTaskMap"),
("read_only_space", 0x055fd): (76, "PromiseRejectReactionJobTaskMap"),
("read_only_space", 0x05625): (77, "CallableTaskMap"),
("read_only_space", 0x0564d): (78, "CallbackTaskMap"),
("read_only_space", 0x05675): (79, "PromiseResolveThenableJobTaskMap"),
("read_only_space", 0x0569d): (82, "FunctionTemplateInfoMap"),
("read_only_space", 0x056c5): (83, "ObjectTemplateInfoMap"),
("read_only_space", 0x056ed): (84, "AccessCheckInfoMap"),
("read_only_space", 0x05715): (85, "AccessorInfoMap"),
("read_only_space", 0x0573d): (86, "AccessorPairMap"),
("read_only_space", 0x05765): (87, "AliasedArgumentsEntryMap"),
("read_only_space", 0x0578d): (88, "AllocationMementoMap"),
("read_only_space", 0x057b5): (91, "AsmWasmDataMap"),
("read_only_space", 0x057dd): (92, "AsyncGeneratorRequestMap"),
("read_only_space", 0x05805): (93, "BaselineDataMap"),
("read_only_space", 0x0582d): (94, "BreakPointMap"),
("read_only_space", 0x05855): (95, "BreakPointInfoMap"),
("read_only_space", 0x0587d): (96, "CachedTemplateObjectMap"),
("read_only_space", 0x058a5): (98, "ClassPositionsMap"),
("read_only_space", 0x058cd): (99, "DebugInfoMap"),
("read_only_space", 0x058f5): (102, "FunctionTemplateRareDataMap"),
("read_only_space", 0x0591d): (104, "InterpreterDataMap"),
("read_only_space", 0x05945): (105, "ModuleRequestMap"),
("read_only_space", 0x0596d): (106, "PromiseCapabilityMap"),
("read_only_space", 0x05995): (107, "PromiseReactionMap"),
("read_only_space", 0x059bd): (108, "PropertyDescriptorObjectMap"),
("read_only_space", 0x059e5): (109, "PrototypeInfoMap"),
("read_only_space", 0x05a0d): (110, "RegExpBoilerplateDescriptionMap"),
("read_only_space", 0x05a35): (111, "ScriptMap"),
("read_only_space", 0x05a5d): (112, "SourceTextModuleInfoEntryMap"),
("read_only_space", 0x05a85): (113, "StackFrameInfoMap"),
("read_only_space", 0x05aad): (114, "TemplateObjectDescriptionMap"),
("read_only_space", 0x05ad5): (115, "Tuple2Map"),
("read_only_space", 0x05afd): (116, "WasmExceptionTagMap"),
("read_only_space", 0x05b25): (117, "WasmIndirectFunctionTableMap"),
("read_only_space", 0x05b4d): (135, "SloppyArgumentsElementsMap"),
("read_only_space", 0x05b75): (152, "DescriptorArrayMap"),
("read_only_space", 0x05b9d): (157, "UncompiledDataWithoutPreparseDataMap"),
("read_only_space", 0x05bc5): (156, "UncompiledDataWithPreparseDataMap"),
("read_only_space", 0x05bed): (173, "OnHeapBasicBlockProfilerDataMap"),
("read_only_space", 0x05c15): (169, "InternalClassMap"),
("read_only_space", 0x05c3d): (180, "SmiPairMap"),
("read_only_space", 0x05c65): (179, "SmiBoxMap"),
("read_only_space", 0x05c8d): (146, "ExportedSubClassBaseMap"),
("read_only_space", 0x05cb5): (147, "ExportedSubClassMap"),
("read_only_space", 0x05cdd): (68, "AbstractInternalClassSubclass1Map"),
("read_only_space", 0x05d05): (69, "AbstractInternalClassSubclass2Map"),
("read_only_space", 0x05d2d): (134, "InternalClassWithSmiElementsMap"),
("read_only_space", 0x05d55): (170, "InternalClassWithStructElementsMap"),
("read_only_space", 0x05d7d): (148, "ExportedSubClass2Map"),
("read_only_space", 0x05da5): (181, "SortStateMap"),
("read_only_space", 0x05dcd): (184, "WasmCapiFunctionDataMap"),
("read_only_space", 0x05df5): (89, "AllocationSiteWithWeakNextMap"),
("read_only_space", 0x05e1d): (89, "AllocationSiteWithoutWeakNextMap"),
("read_only_space", 0x05e45): (80, "LoadHandler1Map"),
("read_only_space", 0x05e6d): (80, "LoadHandler2Map"),
("read_only_space", 0x05e95): (80, "LoadHandler3Map"),
("read_only_space", 0x05ebd): (81, "StoreHandler0Map"),
("read_only_space", 0x05ee5): (81, "StoreHandler1Map"),
("read_only_space", 0x05f0d): (81, "StoreHandler2Map"),
("read_only_space", 0x05f35): (81, "StoreHandler3Map"),
("map_space", 0x02119): (1057, "ExternalMap"),
("map_space", 0x02141): (1098, "JSMessageObjectMap"),
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment