[Temporal] Add monthDayFromFields to Calendar
Add AO: ISOMonthDayFromFields Spec Text: https://tc39.es/proposal-temporal/#sec-temporal.calendar.prototype.monthdayfromfields https://tc39.es/proposal-temporal/#sec-temporal-isomonthdayfromfields Bug: v8:11544 Change-Id: I8a04a8e61af8abdb902de33efbf5635b8e8300aa Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3408576 Commit-Queue: Frank Tang <ftang@chromium.org> Reviewed-by: Adam Klein <adamk@chromium.org> Cr-Commit-Position: refs/heads/main@{#80360}
This commit is contained in:
parent
10bbb38fed
commit
bf54cc83a5
@ -294,8 +294,6 @@ TO_BE_IMPLEMENTED(TemporalTimeZonePrototypeToJSON)
|
||||
/* Temporal.Calendar */
|
||||
/* Temporal #sec-temporal.calendar.prototype.yearmonthfromfields */
|
||||
TO_BE_IMPLEMENTED(TemporalCalendarPrototypeYearMonthFromFields)
|
||||
/* Temporal #sec-temporal.calendar.prototype.monthdayfromfields */
|
||||
TO_BE_IMPLEMENTED(TemporalCalendarPrototypeMonthDayFromFields)
|
||||
/* Temporal #sec-temporal.calendar.prototype.dateadd */
|
||||
TO_BE_IMPLEMENTED(TemporalCalendarPrototypeDateAdd)
|
||||
/* Temporal #sec-temporal.calendar.prototype.weekofyear */
|
||||
@ -795,6 +793,7 @@ TEMPORAL_PROTOTYPE_METHOD1(Calendar, InLeapYear, inLeapYear)
|
||||
TEMPORAL_PROTOTYPE_METHOD2(Calendar, MergeFields, mergeFields)
|
||||
TEMPORAL_PROTOTYPE_METHOD1(Calendar, Month, month)
|
||||
TEMPORAL_PROTOTYPE_METHOD1(Calendar, MonthCode, monthCode)
|
||||
TEMPORAL_PROTOTYPE_METHOD2(Calendar, MonthDayFromFields, monthDayFromFields)
|
||||
TEMPORAL_PROTOTYPE_METHOD1(Calendar, MonthsInYear, monthsInYear)
|
||||
TEMPORAL_PROTOTYPE_METHOD1(Calendar, Year, year)
|
||||
TEMPORAL_TO_STRING(Calendar)
|
||||
|
@ -718,6 +718,15 @@ MaybeHandle<JSTemporalPlainMonthDay> CreateTemporalMonthDay(
|
||||
return object;
|
||||
}
|
||||
|
||||
MaybeHandle<JSTemporalPlainMonthDay> CreateTemporalMonthDay(
|
||||
Isolate* isolate, int32_t iso_month, int32_t iso_day,
|
||||
Handle<JSReceiver> calendar, int32_t reference_iso_year) {
|
||||
TEMPORAL_ENTER_FUNC();
|
||||
return CreateTemporalMonthDay(isolate, CONSTRUCTOR(plain_month_day),
|
||||
CONSTRUCTOR(plain_month_day), iso_month,
|
||||
iso_day, calendar, reference_iso_year);
|
||||
}
|
||||
|
||||
// #sec-temporal-createtemporalyearmonth
|
||||
MaybeHandle<JSTemporalPlainYearMonth> CreateTemporalYearMonth(
|
||||
Isolate* isolate, Handle<JSFunction> target, Handle<HeapObject> new_target,
|
||||
@ -1766,7 +1775,6 @@ MaybeHandle<JSTemporalInstant> ToTemporalInstant(Isolate* isolate,
|
||||
} // namespace
|
||||
|
||||
namespace temporal {
|
||||
|
||||
// #sec-temporal-totemporalcalendar
|
||||
MaybeHandle<JSReceiver> ToTemporalCalendar(
|
||||
Isolate* isolate, Handle<Object> temporal_calendar_like,
|
||||
@ -5129,6 +5137,93 @@ double TotalDurationNanoseconds(Isolate* isolate,
|
||||
return duration.nanoseconds + duration.microseconds * 1000;
|
||||
}
|
||||
|
||||
Maybe<DateRecordCommon> RegulateISODate(Isolate* isolate, ShowOverflow overflow,
|
||||
const DateRecordCommon& date);
|
||||
Maybe<int32_t> ResolveISOMonth(Isolate* isolate, Handle<JSReceiver> fields);
|
||||
|
||||
// #sec-temporal-isomonthdayfromfields
|
||||
Maybe<DateRecordCommon> ISOMonthDayFromFields(Isolate* isolate,
|
||||
Handle<JSReceiver> fields,
|
||||
Handle<JSReceiver> options,
|
||||
const char* method_name) {
|
||||
Factory* factory = isolate->factory();
|
||||
// 1. Assert: Type(fields) is Object.
|
||||
// 2. Let overflow be ? ToTemporalOverflow(options).
|
||||
ShowOverflow overflow;
|
||||
MAYBE_ASSIGN_RETURN_ON_EXCEPTION_VALUE(
|
||||
isolate, overflow, ToTemporalOverflow(isolate, options, method_name),
|
||||
Nothing<DateRecordCommon>());
|
||||
|
||||
// 3. Set fields to ? PrepareTemporalFields(fields, « "day", "month",
|
||||
// "monthCode", "year" », «»).
|
||||
Handle<FixedArray> field_names = factory->NewFixedArray(4);
|
||||
field_names->set(0, ReadOnlyRoots(isolate).day_string());
|
||||
field_names->set(1, ReadOnlyRoots(isolate).month_string());
|
||||
field_names->set(2, ReadOnlyRoots(isolate).monthCode_string());
|
||||
field_names->set(3, ReadOnlyRoots(isolate).year_string());
|
||||
ASSIGN_RETURN_ON_EXCEPTION_VALUE(
|
||||
isolate, fields,
|
||||
PrepareTemporalFields(isolate, fields, field_names,
|
||||
RequiredFields::kNone),
|
||||
Nothing<DateRecordCommon>());
|
||||
// 4. Let month be ! Get(fields, "month").
|
||||
Handle<Object> month_obj =
|
||||
Object::GetPropertyOrElement(isolate, fields, factory->month_string())
|
||||
.ToHandleChecked();
|
||||
// 5. Let monthCode be ! Get(fields, "monthCode").
|
||||
Handle<Object> month_code_obj =
|
||||
Object::GetPropertyOrElement(isolate, fields, factory->monthCode_string())
|
||||
.ToHandleChecked();
|
||||
// 6. Let year be ! Get(fields, "year").
|
||||
Handle<Object> year_obj =
|
||||
Object::GetPropertyOrElement(isolate, fields, factory->year_string())
|
||||
.ToHandleChecked();
|
||||
// 7. If month is not undefined, and monthCode and year are both undefined,
|
||||
// then
|
||||
if (!month_obj->IsUndefined(isolate) &&
|
||||
month_code_obj->IsUndefined(isolate) && year_obj->IsUndefined(isolate)) {
|
||||
// a. Throw a TypeError exception.
|
||||
THROW_NEW_ERROR_RETURN_VALUE(isolate, NEW_TEMPORAL_INVALID_ARG_TYPE_ERROR(),
|
||||
Nothing<DateRecordCommon>());
|
||||
}
|
||||
// 8. Set month to ? ResolveISOMonth(fields).
|
||||
DateRecordCommon result;
|
||||
MAYBE_ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, result.month,
|
||||
ResolveISOMonth(isolate, fields),
|
||||
Nothing<DateRecordCommon>());
|
||||
|
||||
// 9. Let day be ! Get(fields, "day").
|
||||
Handle<Object> day_obj =
|
||||
Object::GetPropertyOrElement(isolate, fields, factory->day_string())
|
||||
.ToHandleChecked();
|
||||
// 10. If day is undefined, throw a TypeError exception.
|
||||
if (day_obj->IsUndefined(isolate)) {
|
||||
THROW_NEW_ERROR_RETURN_VALUE(isolate, NEW_TEMPORAL_INVALID_ARG_TYPE_ERROR(),
|
||||
Nothing<DateRecordCommon>());
|
||||
}
|
||||
result.day = FastD2I(floor(day_obj->Number()));
|
||||
// 11. Let referenceISOYear be 1972 (the first leap year after the Unix
|
||||
// epoch).
|
||||
int32_t reference_iso_year = 1972;
|
||||
// 12. If monthCode is undefined, then
|
||||
if (month_code_obj->IsUndefined(isolate)) {
|
||||
result.year = FastD2I(floor(year_obj->Number()));
|
||||
// a. Let result be ? RegulateISODate(year, month, day, overflow).
|
||||
} else {
|
||||
// 13. Else,
|
||||
// a. Let result be ? RegulateISODate(referenceISOYear, month, day,
|
||||
// overflow).
|
||||
result.year = reference_iso_year;
|
||||
}
|
||||
MAYBE_ASSIGN_RETURN_ON_EXCEPTION_VALUE(
|
||||
isolate, result, RegulateISODate(isolate, overflow, result),
|
||||
Nothing<DateRecordCommon>());
|
||||
// 14. Return the new Record { [[Month]]: result.[[Month]], [[Day]]:
|
||||
// result.[[Day]], [[ReferenceISOYear]]: referenceISOYear }.
|
||||
result.year = reference_iso_year;
|
||||
return Just(result);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// #sec-temporal.duration
|
||||
@ -5455,19 +5550,14 @@ Maybe<DateRecordCommon> RegulateISODate(Isolate* isolate, ShowOverflow overflow,
|
||||
// #sec-temporal-resolveisomonth
|
||||
Maybe<int32_t> ResolveISOMonth(Isolate* isolate, Handle<JSReceiver> fields) {
|
||||
Factory* factory = isolate->factory();
|
||||
// 1. Let month be ? Get(fields, "month").
|
||||
Handle<Object> month_obj;
|
||||
ASSIGN_RETURN_ON_EXCEPTION_VALUE(
|
||||
isolate, month_obj,
|
||||
Object::GetPropertyOrElement(isolate, fields, factory->month_string()),
|
||||
Nothing<int32_t>());
|
||||
// 2. Let monthCode be ? Get(fields, "monthCode").
|
||||
Handle<Object> month_code_obj;
|
||||
ASSIGN_RETURN_ON_EXCEPTION_VALUE(
|
||||
isolate, month_code_obj,
|
||||
Object::GetPropertyOrElement(isolate, fields,
|
||||
factory->monthCode_string()),
|
||||
Nothing<int32_t>());
|
||||
// 1. Let month be ! Get(fields, "month").
|
||||
Handle<Object> month_obj =
|
||||
Object::GetPropertyOrElement(isolate, fields, factory->month_string())
|
||||
.ToHandleChecked();
|
||||
// 2. Let monthCode be ! Get(fields, "monthCode").
|
||||
Handle<Object> month_code_obj =
|
||||
Object::GetPropertyOrElement(isolate, fields, factory->monthCode_string())
|
||||
.ToHandleChecked();
|
||||
// 3. If monthCode is undefined, then
|
||||
if (month_code_obj->IsUndefined(isolate)) {
|
||||
// a. If month is undefined, throw a TypeError exception.
|
||||
@ -5558,12 +5648,10 @@ Maybe<DateRecordCommon> ISODateFromFields(Isolate* isolate,
|
||||
RequiredFields::kNone),
|
||||
Nothing<DateRecordCommon>());
|
||||
|
||||
// 4. Let year be ? Get(fields, "year").
|
||||
Handle<Object> year_obj;
|
||||
ASSIGN_RETURN_ON_EXCEPTION_VALUE(
|
||||
isolate, year_obj,
|
||||
Object::GetPropertyOrElement(isolate, fields, factory->year_string()),
|
||||
Nothing<DateRecordCommon>());
|
||||
// 4. Let year be ! Get(fields, "year").
|
||||
Handle<Object> year_obj =
|
||||
Object::GetPropertyOrElement(isolate, fields, factory->year_string())
|
||||
.ToHandleChecked();
|
||||
// 5. If year is undefined, throw a TypeError exception.
|
||||
if (year_obj->IsUndefined(isolate)) {
|
||||
THROW_NEW_ERROR_RETURN_VALUE(isolate, NEW_TEMPORAL_INVALID_ARG_TYPE_ERROR(),
|
||||
@ -5578,12 +5666,10 @@ Maybe<DateRecordCommon> ISODateFromFields(Isolate* isolate,
|
||||
Maybe<int32_t> maybe_month = ResolveISOMonth(isolate, fields);
|
||||
MAYBE_RETURN(maybe_month, Nothing<DateRecordCommon>());
|
||||
|
||||
// 7. Let day be ? Get(fields, "day").
|
||||
Handle<Object> day_obj;
|
||||
ASSIGN_RETURN_ON_EXCEPTION_VALUE(
|
||||
isolate, day_obj,
|
||||
Object::GetPropertyOrElement(isolate, fields, factory->day_string()),
|
||||
Nothing<DateRecordCommon>());
|
||||
// 7. Let day be ! Get(fields, "day").
|
||||
Handle<Object> day_obj =
|
||||
Object::GetPropertyOrElement(isolate, fields, factory->day_string())
|
||||
.ToHandleChecked();
|
||||
// 8. If day is undefined, throw a TypeError exception.
|
||||
if (day_obj->IsUndefined(isolate)) {
|
||||
THROW_NEW_ERROR_RETURN_VALUE(isolate, NEW_TEMPORAL_INVALID_ARG_TYPE_ERROR(),
|
||||
@ -6322,6 +6408,44 @@ MaybeHandle<Smi> JSTemporalCalendar::Month(Isolate* isolate,
|
||||
return handle(Smi::FromInt(month), isolate);
|
||||
}
|
||||
|
||||
// #sec-temporal.calendar.prototype.monthdayfromfields
|
||||
MaybeHandle<JSTemporalPlainMonthDay> JSTemporalCalendar::MonthDayFromFields(
|
||||
Isolate* isolate, Handle<JSTemporalCalendar> calendar,
|
||||
Handle<Object> fields_obj, Handle<Object> options_obj) {
|
||||
// 1. Let calendar be the this value.
|
||||
// 2. Perform ? RequireInternalSlot(calendar,
|
||||
// [[InitializedTemporalCalendar]]).
|
||||
// 3. Assert: calendar.[[Identifier]] is "iso8601".
|
||||
const char* method_name = "Temporal.Calendar.prototype.monthDayFromFields";
|
||||
// 4. If Type(fields) is not Object, throw a TypeError exception.
|
||||
if (!fields_obj->IsJSReceiver()) {
|
||||
THROW_NEW_ERROR(isolate,
|
||||
NewTypeError(MessageTemplate::kCalledOnNonObject,
|
||||
isolate->factory()->NewStringFromAsciiChecked(
|
||||
method_name)),
|
||||
JSTemporalPlainMonthDay);
|
||||
}
|
||||
Handle<JSReceiver> fields = Handle<JSReceiver>::cast(fields_obj);
|
||||
// 5. Set options to ? GetOptionsObject(options).
|
||||
Handle<JSReceiver> options;
|
||||
ASSIGN_RETURN_ON_EXCEPTION(
|
||||
isolate, options, GetOptionsObject(isolate, options_obj, method_name),
|
||||
JSTemporalPlainMonthDay);
|
||||
// 6. Let result be ? ISOMonthDayFromFields(fields, options).
|
||||
if (calendar->calendar_index() == 0) {
|
||||
Maybe<DateRecordCommon> maybe_result =
|
||||
ISOMonthDayFromFields(isolate, fields, options, method_name);
|
||||
MAYBE_RETURN(maybe_result, Handle<JSTemporalPlainMonthDay>());
|
||||
DateRecordCommon result = maybe_result.FromJust();
|
||||
// 7. Return ? CreateTemporalMonthDay(result.[[Month]], result.[[Day]],
|
||||
// calendar, result.[[ReferenceISOYear]]).
|
||||
return CreateTemporalMonthDay(isolate, result.month, result.day, calendar,
|
||||
result.year);
|
||||
}
|
||||
// TODO(ftang) add intl code inside #ifdef V8_INTL_SUPPORT
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
// #sec-temporal.calendar.prototype.tostring
|
||||
MaybeHandle<String> JSTemporalCalendar::ToString(
|
||||
Isolate* isolate, Handle<JSTemporalCalendar> calendar,
|
||||
|
@ -102,6 +102,11 @@ class JSTemporalCalendar
|
||||
Isolate* isolate, Handle<JSTemporalCalendar> calendar,
|
||||
Handle<Object> fields, Handle<Object> options);
|
||||
|
||||
// #sec-temporal.calendar.prototype.monthdayfromfields
|
||||
V8_WARN_UNUSED_RESULT static MaybeHandle<JSTemporalPlainMonthDay>
|
||||
MonthDayFromFields(Isolate* isolate, Handle<JSTemporalCalendar> calendar,
|
||||
Handle<Object> fields, Handle<Object> options);
|
||||
|
||||
// #sec-temporal.calendar.prototype.mergefields
|
||||
V8_WARN_UNUSED_RESULT static MaybeHandle<JSReceiver> MergeFields(
|
||||
Isolate* isolate, Handle<JSTemporalCalendar> calendar,
|
||||
|
@ -400,12 +400,6 @@
|
||||
'built-ins/Temporal/Calendar/prototype/inLeapYear/calendar-datefromfields-called-with-options-undefined': [FAIL],
|
||||
'built-ins/Temporal/Calendar/prototype/month/calendar-datefromfields-called-with-options-undefined': [FAIL],
|
||||
'built-ins/Temporal/Calendar/prototype/monthCode/calendar-datefromfields-called-with-options-undefined': [FAIL],
|
||||
'built-ins/Temporal/Calendar/prototype/monthDayFromFields/basic': [FAIL],
|
||||
'built-ins/Temporal/Calendar/prototype/monthDayFromFields/fields-missing-properties': [FAIL],
|
||||
'built-ins/Temporal/Calendar/prototype/monthDayFromFields/monthcode-invalid': [FAIL],
|
||||
'built-ins/Temporal/Calendar/prototype/monthDayFromFields/overflow-constrain': [FAIL],
|
||||
'built-ins/Temporal/Calendar/prototype/monthDayFromFields/overflow-reject': [FAIL],
|
||||
'built-ins/Temporal/Calendar/prototype/monthDayFromFields/reference-year-1972': [FAIL],
|
||||
'built-ins/Temporal/Calendar/prototype/monthsInYear/calendar-datefromfields-called-with-options-undefined': [FAIL],
|
||||
'built-ins/Temporal/Calendar/prototype/weekOfYear/argument-plaindate': [FAIL],
|
||||
'built-ins/Temporal/Calendar/prototype/weekOfYear/argument-plaindatetime': [FAIL],
|
||||
@ -471,12 +465,6 @@
|
||||
'built-ins/Temporal/Calendar/prototype/daysInYear/basic': [FAIL],
|
||||
'built-ins/Temporal/Calendar/prototype/month/basic': [FAIL],
|
||||
'built-ins/Temporal/Calendar/prototype/monthCode/basic': [FAIL],
|
||||
'built-ins/Temporal/Calendar/prototype/monthDayFromFields/branding': [FAIL],
|
||||
'built-ins/Temporal/Calendar/prototype/monthDayFromFields/fields-not-object': [FAIL],
|
||||
'built-ins/Temporal/Calendar/prototype/monthDayFromFields/infinity-throws-rangeerror': [FAIL],
|
||||
'built-ins/Temporal/Calendar/prototype/monthDayFromFields/overflow-invalid-string': [FAIL],
|
||||
'built-ins/Temporal/Calendar/prototype/monthDayFromFields/overflow-undefined': [FAIL],
|
||||
'built-ins/Temporal/Calendar/prototype/monthDayFromFields/overflow-wrong-type': [FAIL],
|
||||
'built-ins/Temporal/Calendar/prototype/weekOfYear/argument-string-with-utc-designator': [FAIL],
|
||||
'built-ins/Temporal/Calendar/prototype/weekOfYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer': [FAIL],
|
||||
'built-ins/Temporal/Calendar/prototype/weekOfYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable': [FAIL],
|
||||
@ -2579,7 +2567,6 @@
|
||||
'intl402/Temporal/Calendar/prototype/eraYear/argument-string-invalid': [FAIL],
|
||||
|
||||
'built-ins/Temporal/Calendar/prototype/dateAdd/options-wrong-type': [FAIL],
|
||||
'built-ins/Temporal/Calendar/prototype/monthDayFromFields/options-wrong-type': [FAIL],
|
||||
'built-ins/Temporal/Calendar/prototype/yearMonthFromFields/options-wrong-type': [FAIL],
|
||||
'built-ins/Temporal/Duration/compare/options-wrong-type': [FAIL],
|
||||
'built-ins/Temporal/Duration/prototype/add/options-wrong-type': [FAIL],
|
||||
|
Loading…
Reference in New Issue
Block a user