Commit 5c7c6835 authored by Frank Tang's avatar Frank Tang Committed by Commit Bot

Sync DateTimeFormat with latest changes

https://tc39.es/proposal-intl-datetime-style/ (Jun 10, 2020)

fix extra s in message

Bug: v8:10613
Change-Id: I2ef4f4004c1e8f0a58bf4409578876d1553de59b
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2242258
Commit-Queue: Frank Tang <ftang@chromium.org>
Reviewed-by: 's avatarJakob Kummerow <jkummerow@chromium.org>
Cr-Commit-Position: refs/heads/master@{#68329}
parent 9d6f96c1
......@@ -320,7 +320,7 @@ namespace internal {
"a location, got %") \
T(InvalidArrayBufferLength, "Invalid array buffer length") \
T(ArrayBufferAllocationFailed, "Array buffer allocation failed") \
T(Invalid, "Invalid %s : %") \
T(Invalid, "Invalid % : %") \
T(InvalidArrayLength, "Invalid array length") \
T(InvalidAtomicAccessIndex, "Invalid atomic access index") \
T(InvalidCodePoint, "Invalid code point %") \
......
......@@ -907,21 +907,58 @@ MaybeHandle<JSObject> JSDateTimeFormat::ToDateTimeOptions(
needs_default &= maybe_needs_default.FromJust();
}
// 6. If needDefaults is true and defaults is either "date" or "all", then
// 6. Let dateStyle be ? Get(options, "dateStyle").
Maybe<bool> maybe_datestyle_undefined =
IsPropertyUndefined(isolate, options, factory->dateStyle_string());
MAYBE_RETURN(maybe_datestyle_undefined, Handle<JSObject>());
// 7. Let timeStyle be ? Get(options, "timeStyle").
Maybe<bool> maybe_timestyle_undefined =
IsPropertyUndefined(isolate, options, factory->timeStyle_string());
MAYBE_RETURN(maybe_timestyle_undefined, Handle<JSObject>());
// 8. If dateStyle is not undefined or timeStyle is not undefined, let
// needDefaults be false.
if (!maybe_datestyle_undefined.FromJust() ||
!maybe_timestyle_undefined.FromJust()) {
needs_default = false;
}
// 9. If required is "date" and timeStyle is not undefined,
if (required == RequiredOption::kDate &&
!maybe_timestyle_undefined.FromJust()) {
// a. Throw a TypeError exception.
THROW_NEW_ERROR(
isolate,
NewTypeError(MessageTemplate::kInvalid,
factory->NewStringFromStaticChars("option"),
factory->NewStringFromStaticChars("timeStyle")),
JSObject);
}
// 10. If required is "time" and dateStyle is not undefined,
if (required == RequiredOption::kTime &&
!maybe_datestyle_undefined.FromJust()) {
// a. Throw a TypeError exception.
THROW_NEW_ERROR(
isolate,
NewTypeError(MessageTemplate::kInvalid,
factory->NewStringFromStaticChars("option"),
factory->NewStringFromStaticChars("dateStyle")),
JSObject);
}
// 11. If needDefaults is true and defaults is either "date" or "all", then
if (needs_default) {
if (defaults == DefaultsOption::kAll || defaults == DefaultsOption::kDate) {
// a. For each of the property names "year", "month", "day", do)
const std::vector<std::string> list({"year", "month", "day"});
MAYBE_RETURN(CreateDefault(isolate, options, list), Handle<JSObject>());
}
// 7. If needDefaults is true and defaults is either "time" or "all", then
// 12. If needDefaults is true and defaults is either "time" or "all", then
if (defaults == DefaultsOption::kAll || defaults == DefaultsOption::kTime) {
// a. For each of the property names "hour", "minute", "second", do
const std::vector<std::string> list({"hour", "minute", "second"});
MAYBE_RETURN(CreateDefault(isolate, options, list), Handle<JSObject>());
}
}
// 8. Return options.
// 13. Return options.
return options;
}
......@@ -1523,34 +1560,6 @@ MaybeHandle<JSDateTimeFormat> JSDateTimeFormat::New(
CHECK(U_SUCCESS(status));
}
// 17. Let timeZone be ? Get(options, "timeZone").
std::unique_ptr<char[]> timezone = nullptr;
Maybe<bool> maybe_timezone = Intl::GetStringOption(
isolate, options, "timeZone", empty_values, service, &timezone);
MAYBE_RETURN(maybe_timezone, Handle<JSDateTimeFormat>());
std::unique_ptr<icu::TimeZone> tz = CreateTimeZone(timezone.get());
if (tz.get() == nullptr) {
THROW_NEW_ERROR(
isolate,
NewRangeError(MessageTemplate::kInvalidTimeZone,
factory->NewStringFromAsciiChecked(timezone.get())),
JSDateTimeFormat);
}
std::unique_ptr<icu::Calendar> calendar(
CreateCalendar(isolate, icu_locale, tz.release()));
// 18.b If the result of IsValidTimeZoneName(timeZone) is false, then
// i. Throw a RangeError exception.
if (calendar.get() == nullptr) {
THROW_NEW_ERROR(
isolate,
NewRangeError(MessageTemplate::kInvalidTimeZone,
factory->NewStringFromAsciiChecked(timezone.get())),
JSDateTimeFormat);
}
static base::LazyInstance<DateTimePatternGeneratorCache>::type
generator_cache = LAZY_INSTANCE_INITIALIZER;
......@@ -1604,11 +1613,87 @@ MaybeHandle<JSDateTimeFormat> JSDateTimeFormat::New(
}
}
// 17. Let timeZone be ? Get(options, "timeZone").
std::unique_ptr<char[]> timezone = nullptr;
Maybe<bool> maybe_timezone = Intl::GetStringOption(
isolate, options, "timeZone", empty_values, service, &timezone);
MAYBE_RETURN(maybe_timezone, Handle<JSDateTimeFormat>());
std::unique_ptr<icu::TimeZone> tz = CreateTimeZone(timezone.get());
if (tz.get() == nullptr) {
THROW_NEW_ERROR(
isolate,
NewRangeError(MessageTemplate::kInvalidTimeZone,
factory->NewStringFromAsciiChecked(timezone.get())),
JSDateTimeFormat);
}
std::unique_ptr<icu::Calendar> calendar(
CreateCalendar(isolate, icu_locale, tz.release()));
// 18.b If the result of IsValidTimeZoneName(timeZone) is false, then
// i. Throw a RangeError exception.
if (calendar.get() == nullptr) {
THROW_NEW_ERROR(
isolate,
NewRangeError(MessageTemplate::kInvalidTimeZone,
factory->NewStringFromAsciiChecked(timezone.get())),
JSDateTimeFormat);
}
DateTimeStyle date_style = DateTimeStyle::kUndefined;
DateTimeStyle time_style = DateTimeStyle::kUndefined;
std::unique_ptr<icu::SimpleDateFormat> icu_date_format;
// 28. Let dateStyle be ? GetOption(options, "dateStyle", "string", «
// 28. For each row of Table 1, except the header row, do
bool has_hour_option = false;
std::string skeleton;
for (const PatternData& item : GetPatternData(hc)) {
std::unique_ptr<char[]> input;
// i. Let prop be the name given in the Property column of the row.
// ii. Let value be ? GetOption(options, prop, "string", « the strings
// given in the Values column of the row », undefined).
Maybe<bool> maybe_get_option =
Intl::GetStringOption(isolate, options, item.property.c_str(),
item.allowed_values, service, &input);
MAYBE_RETURN(maybe_get_option, Handle<JSDateTimeFormat>());
if (maybe_get_option.FromJust()) {
if (item.property == "hour") {
has_hour_option = true;
}
DCHECK_NOT_NULL(input.get());
// iii. Set opt.[[<prop>]] to value.
skeleton += item.map.find(input.get())->second;
}
}
if (FLAG_harmony_intl_dateformat_fractional_second_digits) {
Maybe<int> maybe_fsd = Intl::GetNumberOption(
isolate, options, factory->fractionalSecondDigits_string(), 0, 3, 0);
MAYBE_RETURN(maybe_fsd, MaybeHandle<JSDateTimeFormat>());
// Convert fractionalSecondDigits to skeleton.
int fsd = maybe_fsd.FromJust();
for (int i = 0; i < fsd; i++) {
skeleton += "S";
}
}
// 29. Let matcher be ? GetOption(options, "formatMatcher", "string", «
// "basic", "best fit" », "best fit").
enum FormatMatcherOption { kBestFit, kBasic };
// We implement only best fit algorithm, but still need to check
// if the formatMatcher values are in range.
// c. Let matcher be ? GetOption(options, "formatMatcher", "string",
// « "basic", "best fit" », "best fit").
Maybe<FormatMatcherOption> maybe_format_matcher =
Intl::GetStringOption<FormatMatcherOption>(
isolate, options, "formatMatcher", service, {"best fit", "basic"},
{FormatMatcherOption::kBestFit, FormatMatcherOption::kBasic},
FormatMatcherOption::kBestFit);
MAYBE_RETURN(maybe_format_matcher, MaybeHandle<JSDateTimeFormat>());
// TODO(ftang): uncomment the following line and handle format_matcher.
// FormatMatcherOption format_matcher = maybe_format_matcher.FromJust();
// 32. Let dateStyle be ? GetOption(options, "dateStyle", "string", «
// "full", "long", "medium", "short" », undefined).
Maybe<DateTimeStyle> maybe_date_style = Intl::GetStringOption<DateTimeStyle>(
isolate, options, "dateStyle", service,
......@@ -1617,11 +1702,10 @@ MaybeHandle<JSDateTimeFormat> JSDateTimeFormat::New(
DateTimeStyle::kShort},
DateTimeStyle::kUndefined);
MAYBE_RETURN(maybe_date_style, MaybeHandle<JSDateTimeFormat>());
// 29. If dateStyle is not undefined, set dateTimeFormat.[[DateStyle]] to
// dateStyle.
// 33. Set dateTimeFormat.[[DateStyle]] to dateStyle.
date_style = maybe_date_style.FromJust();
// 30. Let timeStyle be ? GetOption(options, "timeStyle", "string", «
// 34. Let timeStyle be ? GetOption(options, "timeStyle", "string", «
// "full", "long", "medium", "short" »).
Maybe<DateTimeStyle> maybe_time_style = Intl::GetStringOption<DateTimeStyle>(
isolate, options, "timeStyle", service,
......@@ -1631,88 +1715,64 @@ MaybeHandle<JSDateTimeFormat> JSDateTimeFormat::New(
DateTimeStyle::kUndefined);
MAYBE_RETURN(maybe_time_style, MaybeHandle<JSDateTimeFormat>());
// 31. If timeStyle is not undefined, set dateTimeFormat.[[TimeStyle]] to
// timeStyle.
// 35. Set dateTimeFormat.[[TimeStyle]] to timeStyle.
time_style = maybe_time_style.FromJust();
// 32. If dateStyle or timeStyle are not undefined, then
// 36. If timeStyle is not undefined, then
HourCycle dateTimeFormatHourCycle = HourCycle::kUndefined;
if (time_style != DateTimeStyle::kUndefined) {
// a. Set dateTimeFormat.[[HourCycle]] to hc.
dateTimeFormatHourCycle = hc;
}
// 37. If dateStyle or timeStyle are not undefined, then
if (date_style != DateTimeStyle::kUndefined ||
time_style != DateTimeStyle::kUndefined) {
// Track newer feature dateStyle/timeStyle option.
// a. For each row in Table 1, except the header row, do
// i. Let prop be the name given in the Property column of the row.
// ii. Let p be opt.[[<prop>]].
// iii. If p is not undefined, then
// 1. Throw a TypeError exception.
if (skeleton.length() > 0) {
THROW_NEW_ERROR(isolate,
NewTypeError(MessageTemplate::kInvalid,
factory->NewStringFromStaticChars("option"),
date_style != DateTimeStyle::kUndefined
? factory->dateStyle_string()
: factory->timeStyle_string()),
JSDateTimeFormat);
}
// b. Let pattern be DateTimeStylePattern(dateStyle, timeStyle,
// dataLocaleData, hc).
isolate->CountUsage(
v8::Isolate::UseCounterFeature::kDateTimeFormatDateTimeStyle);
icu_date_format = DateTimeStylePattern(date_style, time_style, icu_locale,
hc, generator.get());
}
// 33. Else,
if (icu_date_format.get() == nullptr) {
bool has_hour_option = false;
// b. For each row of Table 5, except the header row, do
std::string skeleton;
for (const PatternData& item : GetPatternData(hc)) {
std::unique_ptr<char[]> input;
// i. Let prop be the name given in the Property column of the row.
// ii. Let value be ? GetOption(options, prop, "string", « the strings
// given in the Values column of the row », undefined).
Maybe<bool> maybe_get_option =
Intl::GetStringOption(isolate, options, item.property.c_str(),
item.allowed_values, service, &input);
MAYBE_RETURN(maybe_get_option, Handle<JSDateTimeFormat>());
if (maybe_get_option.FromJust()) {
if (item.property == "hour") {
has_hour_option = true;
}
DCHECK_NOT_NULL(input.get());
// iii. Set opt.[[<prop>]] to value.
skeleton += item.map.find(input.get())->second;
}
}
if (FLAG_harmony_intl_dateformat_fractional_second_digits) {
Maybe<int> maybe_fsd = Intl::GetNumberOption(
isolate, options, factory->fractionalSecondDigits_string(), 0, 3, 0);
MAYBE_RETURN(maybe_fsd, MaybeHandle<JSDateTimeFormat>());
// Convert fractionalSecondDigits to skeleton.
int fsd = maybe_fsd.FromJust();
for (int i = 0; i < fsd; i++) {
skeleton += "S";
}
icu_date_format =
DateTimeStylePattern(date_style, time_style, icu_locale,
dateTimeFormatHourCycle, generator.get());
} else {
// e. If dateTimeFormat.[[Hour]] is not undefined, then
if (has_hour_option) {
// v. Set dateTimeFormat.[[HourCycle]] to hc.
dateTimeFormatHourCycle = hc;
} else {
// f. Else,
// Set dateTimeFormat.[[HourCycle]] to undefined.
dateTimeFormatHourCycle = HourCycle::kUndefined;
}
enum FormatMatcherOption { kBestFit, kBasic };
// We implement only best fit algorithm, but still need to check
// if the formatMatcher values are in range.
// c. Let matcher be ? GetOption(options, "formatMatcher", "string",
// « "basic", "best fit" », "best fit").
Maybe<FormatMatcherOption> maybe_format_matcher =
Intl::GetStringOption<FormatMatcherOption>(
isolate, options, "formatMatcher", service, {"best fit", "basic"},
{FormatMatcherOption::kBestFit, FormatMatcherOption::kBasic},
FormatMatcherOption::kBestFit);
MAYBE_RETURN(maybe_format_matcher, MaybeHandle<JSDateTimeFormat>());
// TODO(ftang): uncomment the following line and handle format_matcher.
// FormatMatcherOption format_matcher = maybe_format_matcher.FromJust();
icu::UnicodeString skeleton_ustr(skeleton.c_str());
icu_date_format = CreateICUDateFormatFromCache(icu_locale, skeleton_ustr,
generator.get(), hc);
icu_date_format = CreateICUDateFormatFromCache(
icu_locale, skeleton_ustr, generator.get(), dateTimeFormatHourCycle);
if (icu_date_format.get() == nullptr) {
// Remove extensions and try again.
icu_locale = icu::Locale(icu_locale.getBaseName());
icu_date_format = CreateICUDateFormatFromCache(icu_locale, skeleton_ustr,
generator.get(), hc);
icu_date_format = CreateICUDateFormatFromCache(
icu_locale, skeleton_ustr, generator.get(), dateTimeFormatHourCycle);
if (icu_date_format.get() == nullptr) {
THROW_NEW_ERROR(isolate, NewRangeError(MessageTemplate::kIcuError),
JSDateTimeFormat);
}
}
// g. If dateTimeFormat.[[Hour]] is not undefined, then
if (!has_hour_option) {
// h. Else, i. Set dateTimeFormat.[[HourCycle]] to undefined.
hc = HourCycle::kUndefined;
}
}
// The creation of Calendar depends on timeZone so we have to put 13 after 17.
......@@ -1737,7 +1797,8 @@ MaybeHandle<JSDateTimeFormat> JSDateTimeFormat::New(
maybe_hour_cycle.FromJust() != HourCycle::kUndefined) {
auto hc_extension_it = r.extensions.find("hc");
if (hc_extension_it != r.extensions.end()) {
if (hc != ToHourCycle(hc_extension_it->second.c_str())) {
if (dateTimeFormatHourCycle !=
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);
......@@ -1771,12 +1832,8 @@ MaybeHandle<JSDateTimeFormat> JSDateTimeFormat::New(
}
if (time_style != DateTimeStyle::kUndefined) {
date_time_format->set_time_style(time_style);
date_time_format->set_hour_cycle(hc);
}
if ((date_style == DateTimeStyle::kUndefined) &&
(time_style == DateTimeStyle::kUndefined)) {
date_time_format->set_hour_cycle(hc);
}
date_time_format->set_hour_cycle(dateTimeFormatHourCycle);
date_time_format->set_locale(*locale_str);
date_time_format->set_icu_locale(*managed_locale);
date_time_format->set_icu_simple_date_format(*managed_format);
......
......@@ -75,32 +75,63 @@ new Intl.DateTimeFormat(['en-US'], {
}
});
assertEquals(1, weekday.length);
// Read by ToDateTimeOptions and also in Table 1
// https://tc39.es/proposal-intl-datetime-style/#table-datetimeformat-components
assertEquals(2, weekday.length);
assertEquals(2, year.length);
assertEquals(2, month.length);
assertEquals(2, day.length);
assertEquals(2, hour.length);
assertEquals(2, minute.length);
assertEquals(2, second.length);
// In Table 1
// https://tc39.es/proposal-intl-datetime-style/#table-datetimeformat-components
assertEquals(1, era.length);
assertEquals(1, timeZoneName.length);
// Read by ToDateTimeOptions and InitializeDateTimeFormat
assertEquals(2, dateStyle.length);
assertEquals(2, timeStyle.length);
// Only read by InitializeDateTimeFormat
assertEquals(1, localeMatcher.length);
assertEquals(1, hour12.length);
assertEquals(1, hourCycle.length);
assertEquals(1, timeZone.length);
assertEquals(1, formatMatcher.length);
// ToDateTimeOptions
assertEquals(1, weekday[0]);
assertEquals(1, year.length);
assertEquals(2, year[0]);
assertEquals(1, month.length);
assertEquals(3, month[0]);
assertEquals(1, day.length);
assertEquals(4, day[0]);
assertEquals(1, hour.length);
assertEquals(5, hour[0]);
assertEquals(1, minute.length);
assertEquals(6, minute[0]);
assertEquals(1, second.length);
assertEquals(7, second[0]);
assertEquals(1, localeMatcher.length);
assertEquals(8, localeMatcher[0]);
assertEquals(1, hour12.length);
assertEquals(9, hour12[0]);
assertEquals(1, hourCycle.length);
assertEquals(10, hourCycle[0]);
assertEquals(1, timeZone.length);
assertEquals(11, timeZone[0]);
assertEquals(1, dateStyle.length);
assertEquals(12, dateStyle[0]);
assertEquals(1, timeStyle.length);
assertEquals(13, timeStyle[0]);
assertEquals(0, era.length);
assertEquals(0, timeZoneName.length);
assertEquals(0, formatMatcher.length);
assertEquals(8, dateStyle[0]);
assertEquals(9, timeStyle[0]);
// InitializeDateTimeFormat
assertEquals(10, localeMatcher[0]);
assertEquals(11, hour12[0]);
assertEquals(12, hourCycle[0]);
assertEquals(13, timeZone[0]);
// Table 1 loop in InitializeDateTimeFormat
assertEquals(14, weekday[1]);
assertEquals(15, era[0]);
assertEquals(16, year[1]);
assertEquals(17, month[1]);
assertEquals(18, day[1]);
assertEquals(19, hour[1]);
assertEquals(20, minute[1]);
assertEquals(21, second[1]);
assertEquals(22, timeZoneName[0]);
// After the Table 1 loop in InitializeDateTimeFormat
assertEquals(23, formatMatcher[0]);
assertEquals(24, dateStyle[1]);
assertEquals(25, timeStyle[1]);
assertEquals(25, getCount);
......@@ -76,32 +76,63 @@ new Intl.DateTimeFormat(['en-US'], {
}
});
assertEquals(1, weekday.length);
// Read by ToDateTimeOptions and also in Table 1
// https://tc39.es/proposal-intl-datetime-style/#table-datetimeformat-components
assertEquals(2, weekday.length);
assertEquals(2, year.length);
assertEquals(2, month.length);
assertEquals(2, day.length);
assertEquals(2, hour.length);
assertEquals(2, minute.length);
assertEquals(2, second.length);
// In Table 1
// https://tc39.es/proposal-intl-datetime-style/#table-datetimeformat-components
assertEquals(1, era.length);
assertEquals(1, timeZoneName.length);
// Read by ToDateTimeOptions and InitializeDateTimeFormat
assertEquals(2, dateStyle.length);
assertEquals(2, timeStyle.length);
// Only read by InitializeDateTimeFormat
assertEquals(1, localeMatcher.length);
assertEquals(1, hour12.length);
assertEquals(1, hourCycle.length);
assertEquals(1, timeZone.length);
assertEquals(1, formatMatcher.length);
// ToDateTimeOptions
assertEquals(1, weekday[0]);
assertEquals(1, year.length);
assertEquals(2, year[0]);
assertEquals(1, month.length);
assertEquals(3, month[0]);
assertEquals(1, day.length);
assertEquals(4, day[0]);
assertEquals(1, hour.length);
assertEquals(5, hour[0]);
assertEquals(1, minute.length);
assertEquals(6, minute[0]);
assertEquals(1, second.length);
assertEquals(7, second[0]);
assertEquals(1, localeMatcher.length);
assertEquals(8, localeMatcher[0]);
assertEquals(1, hour12.length);
assertEquals(9, hour12[0]);
assertEquals(1, hourCycle.length);
assertEquals(10, hourCycle[0]);
assertEquals(1, timeZone.length);
assertEquals(11, timeZone[0]);
assertEquals(1, dateStyle.length);
assertEquals(12, dateStyle[0]);
assertEquals(1, timeStyle.length);
assertEquals(13, timeStyle[0]);
assertEquals(0, era.length);
assertEquals(0, timeZoneName.length);
assertEquals(0, formatMatcher.length);
assertEquals(8, dateStyle[0]);
assertEquals(9, timeStyle[0]);
// InitializeDateTimeFormat
assertEquals(10, localeMatcher[0]);
assertEquals(11, hour12[0]);
assertEquals(12, hourCycle[0]);
assertEquals(13, timeZone[0]);
// Table 1 loop in InitializeDateTimeFormat
assertEquals(14, weekday[1]);
assertEquals(15, era[0]);
assertEquals(16, year[1]);
assertEquals(17, month[1]);
assertEquals(18, day[1]);
assertEquals(19, hour[1]);
assertEquals(20, minute[1]);
assertEquals(21, second[1]);
assertEquals(22, timeZoneName[0]);
// After the Table 1 loop in InitializeDateTimeFormat
assertEquals(23, formatMatcher[0]);
assertEquals(24, dateStyle[1]);
assertEquals(25, timeStyle[1]);
assertEquals(25, getCount);
......@@ -74,39 +74,63 @@ new Intl.DateTimeFormat(['en-US'], {
}
});
// Read by ToDateTimeOptions and also in Table 1
// https://tc39.es/proposal-intl-datetime-style/#table-datetimeformat-components
assertEquals(2, weekday.length);
assertEquals(1, weekday[0]);
assertEquals(1, year.length);
assertEquals(2, year[0]);
assertEquals(1, month.length);
assertEquals(3, month[0]);
assertEquals(1, day.length);
assertEquals(4, day[0]);
assertEquals(2, hour.length);
assertEquals(5, hour[0]);
assertEquals(2, minute.length);
assertEquals(6, minute[0]);
assertEquals(2, second.length);
assertEquals(7, second[0]);
// Read by ToDateTimeOptions and also overwrite with a default 'numeric'
// https://tc39.es/proposal-intl-datetime-style/#table-datetimeformat-components
assertEquals(1, year.length);
assertEquals(1, month.length);
assertEquals(1, day.length);
// In Table 1
// https://tc39.es/proposal-intl-datetime-style/#table-datetimeformat-components
assertEquals(1, era.length);
assertEquals(1, timeZoneName.length);
// Read by ToDateTimeOptions and InitializeDateTimeFormat
assertEquals(2, dateStyle.length);
assertEquals(2, timeStyle.length);
// Only read by InitializeDateTimeFormat
assertEquals(1, localeMatcher.length);
assertEquals(8, localeMatcher[0]);
assertEquals(1, hour12.length);
assertEquals(9, hour12[0]);
assertEquals(1, hourCycle.length);
assertEquals(10, hourCycle[0]);
assertEquals(1, timeZone.length);
assertEquals(11, timeZone[0]);
assertEquals(1, dateStyle.length);
assertEquals(12, dateStyle[0]);
assertEquals(1, timeStyle.length);
assertEquals(13, timeStyle[0]);
assertEquals(1, formatMatcher.length);
// ToDateTimeOptions
assertEquals(1, weekday[0]);
assertEquals(2, year[0]);
assertEquals(3, month[0]);
assertEquals(4, day[0]);
assertEquals(5, hour[0]);
assertEquals(6, minute[0]);
assertEquals(7, second[0]);
assertEquals(8, dateStyle[0]);
assertEquals(9, timeStyle[0]);
// InitializeDateTimeFormat
assertEquals(10, localeMatcher[0]);
assertEquals(11, hour12[0]);
assertEquals(12, hourCycle[0]);
assertEquals(13, timeZone[0]);
// Table 1 loop in InitializeDateTimeFormat
assertEquals(14, weekday[1]);
assertEquals(1, era.length);
assertEquals(15, era[0]);
assertEquals(16, hour[1]);
assertEquals(17, minute[1]);
assertEquals(18, second[1]);
assertEquals(1, timeZoneName.length);
assertEquals(19, timeZoneName[0]);
assertEquals(1, formatMatcher.length);
// After the Table 1 loop in InitializeDateTimeFormat
assertEquals(20, formatMatcher[0]);
assertEquals(21, dateStyle[1]);
assertEquals(22, timeStyle[1]);
assertEquals(22, getCount);
......@@ -75,32 +75,63 @@ new Intl.DateTimeFormat(['en-US'], {
}
});
assertEquals(1, weekday.length);
// Read by ToDateTimeOptions and also in Table 1
// https://tc39.es/proposal-intl-datetime-style/#table-datetimeformat-components
assertEquals(2, weekday.length);
assertEquals(2, year.length);
assertEquals(2, month.length);
assertEquals(2, day.length);
assertEquals(2, hour.length);
assertEquals(2, minute.length);
assertEquals(2, second.length);
// In Table 1
// https://tc39.es/proposal-intl-datetime-style/#table-datetimeformat-components
assertEquals(1, era.length);
assertEquals(1, timeZoneName.length);
// Read by ToDateTimeOptions and InitializeDateTimeFormat
assertEquals(2, dateStyle.length);
assertEquals(2, timeStyle.length);
// Only read by InitializeDateTimeFormat
assertEquals(1, localeMatcher.length);
assertEquals(1, hour12.length);
assertEquals(1, hourCycle.length);
assertEquals(1, timeZone.length);
assertEquals(1, formatMatcher.length);
// ToDateTimeOptions
assertEquals(1, weekday[0]);
assertEquals(1, year.length);
assertEquals(2, year[0]);
assertEquals(1, month.length);
assertEquals(3, month[0]);
assertEquals(1, day.length);
assertEquals(4, day[0]);
assertEquals(1, hour.length);
assertEquals(5, hour[0]);
assertEquals(1, minute.length);
assertEquals(6, minute[0]);
assertEquals(1, second.length);
assertEquals(7, second[0]);
assertEquals(1, localeMatcher.length);
assertEquals(8, localeMatcher[0]);
assertEquals(1, hour12.length);
assertEquals(9, hour12[0]);
assertEquals(1, hourCycle.length);
assertEquals(10, hourCycle[0]);
assertEquals(1, timeZone.length);
assertEquals(11, timeZone[0]);
assertEquals(1, dateStyle.length);
assertEquals(12, dateStyle[0]);
assertEquals(1, timeStyle.length);
assertEquals(13, timeStyle[0]);
assertEquals(0, era.length);
assertEquals(0, timeZoneName.length);
assertEquals(0, formatMatcher.length);
assertEquals(8, dateStyle[0]);
assertEquals(9, timeStyle[0]);
// InitializeDateTimeFormat
assertEquals(10, localeMatcher[0]);
assertEquals(11, hour12[0]);
assertEquals(12, hourCycle[0]);
assertEquals(13, timeZone[0]);
// Table 1 loop in InitializeDateTimeFormat
assertEquals(14, weekday[1]);
assertEquals(15, era[0]);
assertEquals(16, year[1]);
assertEquals(17, month[1]);
assertEquals(18, day[1]);
assertEquals(19, hour[1]);
assertEquals(20, minute[1]);
assertEquals(21, second[1]);
assertEquals(22, timeZoneName[0]);
// After the Table 1 loop in InitializeDateTimeFormat
assertEquals(23, formatMatcher[0]);
assertEquals(24, dateStyle[1]);
assertEquals(25, timeStyle[1]);
assertEquals(25, getCount);
......@@ -36,16 +36,15 @@ assertEquals(
(new Intl.DateTimeFormat("en", {fractionalSecondDigits: undefined}))
.resolvedOptions().fractionalSecondDigits);
// When timeStyle or dateStyle is present, the code should not read
// fractionalSecondDigits from the option.
assertEquals(
undefined,
(new Intl.DateTimeFormat(
"en", {timeStyle: "short", fractionalSecondDigits: 3}))
.resolvedOptions().fractionalSecondDigits);
assertEquals(
undefined,
(new Intl.DateTimeFormat(
"en", {dateStyle: "short", fractionalSecondDigits: 3}))
.resolvedOptions().fractionalSecondDigits);
// When timeStyle or dateStyle is present, we should throw TypeError
assertThrows(
() => (new Intl.DateTimeFormat(
"en", {timeStyle: "short", fractionalSecondDigits: 3})),
TypeError,
"Invalid option : timeStyle");
assertThrows(
() => (new Intl.DateTimeFormat(
"en", {dateStyle: "short", fractionalSecondDigits: 3})),
TypeError,
"Invalid option : dateStyle");
// Copyright 2020 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.
// Test
// https://github.com/tc39/proposal-intl-datetime-style/pull/43
// https://github.com/tc39/proposal-intl-datetime-style/pull/47
// https://github.com/tc39/proposal-intl-datetime-style/pull/50
let opt = {
weekday: 'narrow',
era: 'narrow',
year: '2-digit',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
};
let keys = Object.keys(opt);
let testDateStyle = { ...opt };
let testTimeStyle = { ...opt };
testDateStyle.dateStyle = 'long';
testTimeStyle.timeStyle = 'long';
for (key of keys) {
assertThrows(
() => new Intl.DateTimeFormat('en', testDateStyle),
TypeError, "Invalid option : dateStyle");
assertThrows(
() => new Intl.DateTimeFormat('en', testTimeStyle),
TypeError, "Invalid option : timeStyle");
testDateStyle[key] = undefined;
testTimeStyle[key] = undefined;
}
assertThrows(
() => (new Date()).toLocaleDateString("en", {timeStyle: "long"}),
TypeError, "Invalid option : timeStyle");
assertThrows(
() => (new Date()).toLocaleTimeString("en", {dateStyle: "long"}),
TypeError, "Invalid option : dateStyle");
let logs = [];
try {
var dtf = new Intl.DateTimeFormat("en", {
get timeStyle() {
logs.push("get timeStyle");
return "full";
},
get timeZoneName() {
logs.push("get timeZoneName");
return "short";
},
});
logs.push(dtf.resolvedOptions().timeStyle);
logs.push(dtf.resolvedOptions().timeZoneName);
} catch(e) {
logs.push(e.name);
}
assertEquals(
"get timeStyle,get timeZoneName,get timeStyle,TypeError",
logs.join(','));
......@@ -602,6 +602,10 @@
'built-ins/Atomics/waitAsync/true-for-timeout-agent': [SKIP],
'built-ins/Atomics/waitAsync/value-not-equal-agent': [SKIP],
# https://github.com/tc39/test262/pull/2659
'intl402/DateTimeFormat/prototype/resolvedOptions/order-style': [FAIL],
'intl402/DateTimeFormat/constructor-options-order-timedate-style': [FAIL],
######################## NEEDS INVESTIGATION ###########################
# https://bugs.chromium.org/p/v8/issues/detail?id=7833
......
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