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

[Temporal][intl] Implement real toLocaleString for Temporal

Also change Intl.DateTimeFormat to take temporal objects for format.

Design doc: https://docs.google.com/document/d/1gI_Jd9ztnkqhQnDTR4GaI3JOFdMNJW2kQK_UaBPvMug

Implement the intl enabled
Temporal.Instant.prototype.toLocaleString,  Temporal.PlainDate.prototype.toLocaleString
Temporal.PlainDateTime.prototype.toLocaleString
Temporal.PlainMonthDay.prototype.toLocaleString
Temporal.PlainTime.prototype.toLocaleString
Temporal.PlainYearMonth.prototype.toLocaleString
Temporal.ZonedDateTime.prototype.toLocaleString

Implement AOs:
HandleDateTimeTemporalDate, HandleDateTimeTemporalYearMonth, HandleDateTimeTemporalMonthDay, HandleDateTimeTemporalTime
HandleDateTimeTemporalDateTime, HandleDateTimeTemporalInstant, HandleDateTimeTemporalZonedDateTime, HandleDateTimeOthers, HandleDateTimeValue


Spec Text:
https://tc39.es/proposal-temporal/#sec-temporal-handledatetimevaluetemporaldate
https://tc39.es/proposal-temporal/#sec-temporal-handledatetimevaluetemporalyearmonth
https://tc39.es/proposal-temporal/#sec-temporal-handledatetimevaluetemporalmonthday
https://tc39.es/proposal-temporal/#sec-temporal-handledatetimevaluetemporaltime
https://tc39.es/proposal-temporal/#sec-temporal-handledatetimevaluetemporaldatetime
https://tc39.es/proposal-temporal/#sec-temporal-handledatetimevaluetemporalinstant
https://tc39.es/proposal-temporal/#sec-temporal-handledatetimevaluetemporalzoneddatetime
https://tc39.es/proposal-temporal/#sec-temporal-handledatetimeothers
https://tc39.es/proposal-temporal/#sec-temporal-handledatetimevalue
https://tc39.es/proposal-temporal/#sup-temporal.instant.prototype.tolocalestring
https://tc39.es/proposal-temporal/#sup-temporal.plaindate.prototype.tolocalestring
Temporal.PlainDateTime.prototype.toLocaleString
https://tc39.es/proposal-temporal/#sup-temporal.plainmonthday.prototype.tolocalestring
https://tc39.es/proposal-temporal/#sup-temporal.plaintime.prototype.tolocalestring
https://tc39.es/proposal-temporal/#sup-temporal.plainyearmonth.prototype.tolocalestring
https://tc39.es/proposal-temporal/#sup-temporal.zoneddatetime.prototype.tolocalestring

Remove the output_range parameter and use the is_null() of
MaybeHandle<T> for to check the optional return.

Bug: v8:11544
Change-Id: Ia9ffe7a71c8fb68391581eb5ef7620708e2bd1f0
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3791526
Commit-Queue: Frank Tang <ftang@chromium.org>
Reviewed-by: 's avatarAdam Klein <adamk@chromium.org>
Cr-Commit-Position: refs/heads/main@{#82453}
parent 0b1104fa
......@@ -137,26 +137,14 @@ BUILTIN(DateTimeFormatPrototypeFormatToParts) {
Handle<JSDateTimeFormat>::cast(date_format_holder);
Handle<Object> x = args.atOrUndefined(isolate, 1);
if (x->IsUndefined(isolate)) {
x = factory->NewNumber(JSDate::CurrentTimeValue(isolate));
} else {
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, x,
Object::ToNumber(isolate, args.at(1)));
}
double date_value = DateCache::TimeClip(x->Number());
if (std::isnan(date_value)) {
THROW_NEW_ERROR_RETURN_FAILURE(
isolate, NewRangeError(MessageTemplate::kInvalidTimeValue));
}
RETURN_RESULT_OR_FAILURE(isolate, JSDateTimeFormat::FormatToParts(
isolate, dtf, date_value, false));
isolate, dtf, x, false, method_name));
}
// Common code for DateTimeFormatPrototypeFormtRange(|ToParts)
template <class T, MaybeHandle<T> (*F)(Isolate*, Handle<JSDateTimeFormat>,
double, double)>
Handle<Object>, Handle<Object>,
const char* const)>
V8_WARN_UNUSED_RESULT Object DateTimeFormatRange(
BuiltinArguments args, Isolate* isolate, const char* const method_name) {
// 1. Let dtf be this value.
......@@ -171,20 +159,12 @@ V8_WARN_UNUSED_RESULT Object DateTimeFormatRange(
THROW_NEW_ERROR_RETURN_FAILURE(
isolate, NewTypeError(MessageTemplate::kInvalidTimeValue));
}
// 4. Let x be ? ToNumber(startDate).
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, start_date,
Object::ToNumber(isolate, start_date));
double x = start_date->Number();
// 5. Let y be ? ToNumber(endDate).
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, end_date,
Object::ToNumber(isolate, end_date));
double y = end_date->Number();
// 6. Return ? FormatDateTimeRange(dtf, x, y)
// 4. Return ? FormatDateTimeRange(dtf, startDate, endDate)
// OR
// 6. Return ? FormatDateTimeRangeToParts(dtf, x, y).
RETURN_RESULT_OR_FAILURE(isolate, F(isolate, dtf, x, y));
// 4. Return ? FormatDateTimeRangeToParts(dtf, startDate, endDate).
RETURN_RESULT_OR_FAILURE(isolate,
F(isolate, dtf, start_date, end_date, method_name));
}
BUILTIN(DateTimeFormatPrototypeFormatRange) {
......@@ -584,7 +564,8 @@ BUILTIN(DateTimeFormatInternalFormat) {
Handle<Object> date = args.atOrUndefined(isolate, 1);
RETURN_RESULT_OR_FAILURE(isolate, JSDateTimeFormat::DateTimeFormat(
isolate, date_format_holder, date));
isolate, date_format_holder, date,
"DateTime Format Functions"));
}
BUILTIN(IntlGetCanonicalLocales) {
......
This diff is collapsed.
......@@ -61,22 +61,24 @@ class JSDateTimeFormat
// DateTime Format Functions
V8_WARN_UNUSED_RESULT static MaybeHandle<String> DateTimeFormat(
Isolate* isolate, Handle<JSDateTimeFormat> date_time_format,
Handle<Object> date);
Handle<Object> date, const char* method_name);
// ecma402/#sec-Intl.DateTimeFormat.prototype.formatToParts
V8_WARN_UNUSED_RESULT static MaybeHandle<JSArray> FormatToParts(
Isolate* isolate, Handle<JSDateTimeFormat> date_time_format,
double date_value, bool output_source);
Handle<Object> x, bool output_source, const char* method_name);
// ecma402/#sec-intl.datetimeformat.prototype.formatRange
V8_WARN_UNUSED_RESULT static MaybeHandle<String> FormatRange(
Isolate* isolate, Handle<JSDateTimeFormat> date_time_format,
double x_date_value, double y_date_value);
Handle<Object> x_date_value, Handle<Object> y_date_value,
const char* method_name);
// ecma402/sec-Intl.DateTimeFormat.prototype.formatRangeToParts
V8_WARN_UNUSED_RESULT static MaybeHandle<JSArray> FormatRangeToParts(
Isolate* isolate, Handle<JSDateTimeFormat> date_time_format,
double x_date_value, double y_date_value);
Handle<Object> x_date_value, Handle<Object> y_date_value,
const char* method_name);
// ecma-402/#sec-todatetimeoptions
enum class RequiredOption { kDate, kTime, kAny };
......@@ -90,6 +92,11 @@ class JSDateTimeFormat
Handle<Object> options, RequiredOption required, DefaultsOption defaults,
const char* method_name);
// Function to support Temporal
V8_WARN_UNUSED_RESULT static MaybeHandle<String> TemporalToLocaleString(
Isolate* isolate, Handle<JSReceiver> temporal, Handle<Object> locales,
Handle<Object> options, const char* method_name);
V8_EXPORT_PRIVATE static const std::set<std::string>& GetAvailableLocales();
Handle<Object> static TimeZoneId(Isolate* isolate, const icu::TimeZone& tz);
......
......@@ -59,20 +59,6 @@ enum class Unit {
*/
// Struct
struct DateRecordCommon {
int32_t year;
int32_t month;
int32_t day;
};
struct TimeRecordCommon {
int32_t hour;
int32_t minute;
int32_t second;
int32_t millisecond;
int32_t microsecond;
int32_t nanosecond;
};
// only for BalanceTime
struct UnbalancedTimeRecordCommon {
......@@ -84,10 +70,9 @@ struct UnbalancedTimeRecordCommon {
double nanosecond;
};
struct DateTimeRecordCommon {
DateRecordCommon date;
TimeRecordCommon time;
};
using temporal::DateRecordCommon;
using temporal::DateTimeRecordCommon;
using temporal::TimeRecordCommon;
struct DateRecord {
DateRecordCommon date;
......@@ -11937,8 +11922,13 @@ MaybeHandle<String> JSTemporalPlainDate::ToString(
MaybeHandle<String> JSTemporalPlainDate::ToLocaleString(
Isolate* isolate, Handle<JSTemporalPlainDate> temporal_date,
Handle<Object> locales, Handle<Object> options) {
// TODO(ftang) Implement #sup-temporal.plaindate.prototype.tolocalestring
#ifdef V8_INTL_SUPPORT
return JSDateTimeFormat::TemporalToLocaleString(
isolate, temporal_date, locales, options,
"Temporal.PlainDate.prototype.toLocaleString");
#else // V8_INTL_SUPPORT
return TemporalDateToString(isolate, temporal_date, ShowCalendar::kAuto);
#endif // V8_INTL_SUPPORT
}
// #sec-temporal-createtemporaldatetime
......@@ -12641,7 +12631,11 @@ MaybeHandle<String> JSTemporalPlainDateTime::ToJSON(
MaybeHandle<String> JSTemporalPlainDateTime::ToLocaleString(
Isolate* isolate, Handle<JSTemporalPlainDateTime> date_time,
Handle<Object> locales, Handle<Object> options) {
// TODO(ftang) Implement #sup-temporal.plaindatetime.prototype.tolocalestring
#ifdef V8_INTL_SUPPORT
return JSDateTimeFormat::TemporalToLocaleString(
isolate, date_time, locales, options,
"Temporal.PlainDateTime.prototype.toLocaleString");
#else // V8_INTL_SUPPORT
return TemporalDateTimeToString(
isolate,
{{date_time->iso_year(), date_time->iso_month(), date_time->iso_day()},
......@@ -12650,6 +12644,7 @@ MaybeHandle<String> JSTemporalPlainDateTime::ToLocaleString(
date_time->iso_nanosecond()}},
Handle<JSReceiver>(date_time->calendar(), isolate), Precision::kAuto,
ShowCalendar::kAuto);
#endif // V8_INTL_SUPPORT
}
namespace {
......@@ -13663,8 +13658,13 @@ MaybeHandle<String> JSTemporalPlainMonthDay::ToString(
MaybeHandle<String> JSTemporalPlainMonthDay::ToLocaleString(
Isolate* isolate, Handle<JSTemporalPlainMonthDay> month_day,
Handle<Object> locales, Handle<Object> options) {
// TODO(ftang) Implement #sup-temporal.plainmonthday.prototype.tolocalestring
#ifdef V8_INTL_SUPPORT
return JSDateTimeFormat::TemporalToLocaleString(
isolate, month_day, locales, options,
"Temporal.PlainMonthDay.prototype.toLocaleString");
#else // V8_INTL_SUPPORT
return TemporalMonthDayToString(isolate, month_day, ShowCalendar::kAuto);
#endif // V8_INTL_SUPPORT
}
MaybeHandle<JSTemporalPlainYearMonth> JSTemporalPlainYearMonth::Constructor(
......@@ -14306,8 +14306,13 @@ MaybeHandle<String> JSTemporalPlainYearMonth::ToString(
MaybeHandle<String> JSTemporalPlainYearMonth::ToLocaleString(
Isolate* isolate, Handle<JSTemporalPlainYearMonth> year_month,
Handle<Object> locales, Handle<Object> options) {
// TODO(ftang) Implement #sup-temporal.plainyearmonth.prototype.tolocalestring
#ifdef V8_INTL_SUPPORT
return JSDateTimeFormat::TemporalToLocaleString(
isolate, year_month, locales, options,
"Temporal.PlainYearMonth.prototype.toLocaleString");
#else // V8_INTL_SUPPORT
return TemporalYearMonthToString(isolate, year_month, ShowCalendar::kAuto);
#endif // V8_INTL_SUPPORT
}
// #sec-temporal-plaintime-constructor
......@@ -14999,8 +15004,13 @@ MaybeHandle<String> JSTemporalPlainTime::ToJSON(
MaybeHandle<String> JSTemporalPlainTime::ToLocaleString(
Isolate* isolate, Handle<JSTemporalPlainTime> temporal_time,
Handle<Object> locales, Handle<Object> options) {
// TODO(ftang) Implement #sup-temporal.plaintime.prototype.tolocalestring
#ifdef V8_INTL_SUPPORT
return JSDateTimeFormat::TemporalToLocaleString(
isolate, temporal_time, locales, options,
"Temporal.PlainTime.prototype.toLocaleString");
#else // V8_INTL_SUPPORT
return TemporalTimeToString(isolate, temporal_time, Precision::kAuto);
#endif // V8_INTL_SUPPORT
}
namespace {
......@@ -16709,11 +16719,15 @@ MaybeHandle<String> JSTemporalZonedDateTime::ToJSON(
MaybeHandle<String> JSTemporalZonedDateTime::ToLocaleString(
Isolate* isolate, Handle<JSTemporalZonedDateTime> zoned_date_time,
Handle<Object> locales, Handle<Object> options) {
// TODO(ftang) Implement #sup-temporal.plaindatetime.prototype.tolocalestring
const char* method_name = "Temporal.ZonedDateTime.prototype.toLocaleString";
#ifdef V8_INTL_SUPPORT
return JSDateTimeFormat::TemporalToLocaleString(
isolate, zoned_date_time, locales, options, method_name);
#else // V8_INTL_SUPPORT
return TemporalZonedDateTimeToString(
isolate, zoned_date_time, Precision::kAuto, ShowCalendar::kAuto,
ShowTimeZone::kAuto, ShowOffset::kAuto,
"Temporal.ZonedDateTime.prototype.toLocaleString");
ShowTimeZone::kAuto, ShowOffset::kAuto, method_name);
#endif // V8_INTL_SUPPORT
}
// #sec-temporal.zoneddatetime.prototype.tostring
......@@ -18044,10 +18058,15 @@ MaybeHandle<String> JSTemporalInstant::ToJSON(
MaybeHandle<String> JSTemporalInstant::ToLocaleString(
Isolate* isolate, Handle<JSTemporalInstant> instant, Handle<Object> locales,
Handle<Object> options) {
// TODO(ftang) Implement #sup-temporal.instant.prototype.tolocalestring
return TemporalInstantToString(
isolate, instant, isolate->factory()->undefined_value(), Precision::kAuto,
"Temporal.Instant.prototype.toLocaleString");
const char* method_name = "Temporal.Instant.prototype.toLocaleString";
#ifdef V8_INTL_SUPPORT
return JSDateTimeFormat::TemporalToLocaleString(isolate, instant, locales,
options, method_name);
#else // V8_INTL_SUPPORT
return TemporalInstantToString(isolate, instant,
isolate->factory()->undefined_value(),
Precision::kAuto, method_name);
#endif // V8_INTL_SUPPORT
}
// #sec-temporal.instant.prototype.tostring
......@@ -18454,6 +18473,22 @@ MaybeHandle<Oddball> IsInvalidTemporalCalendarField(
return isolate->factory()->false_value();
}
// #sec-temporal-getbuiltincalendar
MaybeHandle<JSTemporalCalendar> GetBuiltinCalendar(Isolate* isolate,
Handle<String> id) {
return JSTemporalCalendar::Constructor(isolate, CONSTRUCTOR(calendar),
CONSTRUCTOR(calendar), id);
}
// A simple conviention function to avoid the need to unnecessarily exposing
// the definiation of enum Disambiguation.
MaybeHandle<JSTemporalInstant> BuiltinTimeZoneGetInstantForCompatible(
Isolate* isolate, Handle<JSReceiver> time_zone,
Handle<JSTemporalPlainDateTime> date_time, const char* method_name) {
return BuiltinTimeZoneGetInstantFor(isolate, time_zone, date_time,
Disambiguation::kCompatible, method_name);
}
} // namespace temporal
} // namespace internal
} // namespace v8
......@@ -1046,6 +1046,35 @@ class JSTemporalZonedDateTime
namespace temporal {
struct DateRecordCommon {
int32_t year;
int32_t month;
int32_t day;
};
struct TimeRecordCommon {
int32_t hour;
int32_t minute;
int32_t second;
int32_t millisecond;
int32_t microsecond;
int32_t nanosecond;
};
struct DateTimeRecordCommon {
DateRecordCommon date;
TimeRecordCommon time;
};
// #sec-temporal-createtemporaldatetime
V8_WARN_UNUSED_RESULT MaybeHandle<JSTemporalPlainDateTime>
CreateTemporalDateTime(Isolate* isolate, const DateTimeRecordCommon& date_time,
Handle<JSReceiver> calendar);
// #sec-temporal-createtemporaltimezone
MaybeHandle<JSTemporalTimeZone> CreateTemporalTimeZone(
Isolate* isolate, Handle<String> identifier);
// #sec-temporal-createtemporalinstant
V8_WARN_UNUSED_RESULT MaybeHandle<JSTemporalInstant> CreateTemporalInstant(
Isolate* isolate, Handle<JSFunction> target, Handle<HeapObject> new_target,
......@@ -1104,6 +1133,14 @@ V8_WARN_UNUSED_RESULT MaybeHandle<JSReceiver> ToTemporalTimeZone(
V8_WARN_UNUSED_RESULT MaybeHandle<Oddball> IsInvalidTemporalCalendarField(
Isolate* isolate, Handle<String> string, Handle<FixedArray> field_names);
// #sec-temporal-getbuiltincalendar
V8_WARN_UNUSED_RESULT MaybeHandle<JSTemporalCalendar> GetBuiltinCalendar(
Isolate* isolate, Handle<String> id);
MaybeHandle<JSTemporalInstant> BuiltinTimeZoneGetInstantForCompatible(
Isolate* isolate, Handle<JSReceiver> time_zone,
Handle<JSTemporalPlainDateTime> date_time, const char* method_name);
} // namespace temporal
} // namespace internal
} // namespace v8
......
......@@ -541,43 +541,10 @@
'built-ins/Temporal/ZonedDateTime/prototype/until/zoneddatetime-string': [FAIL],
'built-ins/Temporal/ZonedDateTime/prototype/until/zoneddatetime-string-multiple-offsets': [FAIL],
'built-ins/Temporal/ZonedDateTime/prototype/withTimeZone/timezone-string-multiple-offsets': [FAIL],
'intl402/DateTimeFormat/prototype/formatRange/temporal-objects-resolved-time-zone': [FAIL],
'intl402/DateTimeFormat/prototype/formatRangeToParts/temporal-objects-resolved-time-zone': [FAIL],
'intl402/DateTimeFormat/prototype/format/temporal-objects-resolved-time-zone': [FAIL],
'intl402/DateTimeFormat/prototype/formatToParts/temporal-objects-resolved-time-zone': [FAIL],
'intl402/Temporal/Calendar/prototype/dateFromFields/infinity-throws-rangeerror': [FAIL],
'intl402/Temporal/Calendar/prototype/monthDayFromFields/infinity-throws-rangeerror': [FAIL],
'intl402/Temporal/Calendar/prototype/weekOfYear/infinity-throws-rangeerror': [FAIL],
'intl402/Temporal/Calendar/prototype/yearMonthFromFields/infinity-throws-rangeerror': [FAIL],
'intl402/Temporal/Instant/prototype/toLocaleString/locales-undefined': [FAIL],
'intl402/Temporal/Instant/prototype/toLocaleString/options-conflict': [FAIL],
'intl402/Temporal/Instant/prototype/toLocaleString/options-undefined': [FAIL],
'intl402/Temporal/PlainDate/prototype/toLocaleString/locales-undefined': [FAIL],
'intl402/Temporal/PlainDate/prototype/toLocaleString/options-conflict': [FAIL],
'intl402/Temporal/PlainDate/prototype/toLocaleString/options-undefined': [FAIL],
'intl402/Temporal/PlainDate/prototype/toLocaleString/resolved-time-zone': [FAIL],
'intl402/Temporal/PlainDate/prototype/toLocaleString/timezone-getoffsetnanosecondsfor-not-callable': [FAIL],
'intl402/Temporal/PlainDateTime/prototype/toLocaleString/locales-undefined': [FAIL],
'intl402/Temporal/PlainDateTime/prototype/toLocaleString/options-conflict': [FAIL],
'intl402/Temporal/PlainDateTime/prototype/toLocaleString/options-undefined': [FAIL],
'intl402/Temporal/PlainDateTime/prototype/toLocaleString/resolved-time-zone': [FAIL],
'intl402/Temporal/PlainDateTime/prototype/toLocaleString/timezone-getoffsetnanosecondsfor-not-callable': [FAIL],
'intl402/Temporal/PlainMonthDay/prototype/toLocaleString/locales-undefined': [FAIL],
'intl402/Temporal/PlainMonthDay/prototype/toLocaleString/options-undefined': [FAIL],
'intl402/Temporal/PlainMonthDay/prototype/toLocaleString/resolved-time-zone': [FAIL],
'intl402/Temporal/PlainMonthDay/prototype/toLocaleString/timezone-getoffsetnanosecondsfor-not-callable': [FAIL],
'intl402/Temporal/PlainTime/prototype/toLocaleString/locales-undefined': [FAIL],
'intl402/Temporal/PlainTime/prototype/toLocaleString/options-conflict': [FAIL],
'intl402/Temporal/PlainTime/prototype/toLocaleString/options-undefined': [FAIL],
'intl402/Temporal/PlainTime/prototype/toLocaleString/resolved-time-zone': [FAIL],
'intl402/Temporal/PlainTime/prototype/toLocaleString/timezone-getoffsetnanosecondsfor-not-callable': [FAIL],
'intl402/Temporal/PlainYearMonth/prototype/toLocaleString/locales-undefined': [FAIL],
'intl402/Temporal/PlainYearMonth/prototype/toLocaleString/options-undefined': [FAIL],
'intl402/Temporal/PlainYearMonth/prototype/toLocaleString/resolved-time-zone': [FAIL],
'intl402/Temporal/PlainYearMonth/prototype/toLocaleString/timezone-getoffsetnanosecondsfor-not-callable': [FAIL],
'intl402/Temporal/ZonedDateTime/prototype/toLocaleString/locales-undefined': [FAIL],
'intl402/Temporal/ZonedDateTime/prototype/toLocaleString/options-conflict': [FAIL],
'intl402/Temporal/ZonedDateTime/prototype/toLocaleString/options-undefined': [FAIL],
'intl402/Temporal/Duration/prototype/round/relativeto-string-datetime': [FAIL],
'intl402/Temporal/Duration/prototype/total/relativeto-string-datetime': [FAIL],
'intl402/Temporal/PlainYearMonth/from/argument-object': [FAIL],
......
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