diff --git a/src/builtins/builtins-temporal.cc b/src/builtins/builtins-temporal.cc index 2979cfb1f8..594e130206 100644 --- a/src/builtins/builtins-temporal.cc +++ b/src/builtins/builtins-temporal.cc @@ -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) diff --git a/src/objects/js-temporal-objects.cc b/src/objects/js-temporal-objects.cc index bfb3213fa6..c8a775acf6 100644 --- a/src/objects/js-temporal-objects.cc +++ b/src/objects/js-temporal-objects.cc @@ -718,6 +718,15 @@ MaybeHandle CreateTemporalMonthDay( return object; } +MaybeHandle CreateTemporalMonthDay( + Isolate* isolate, int32_t iso_month, int32_t iso_day, + Handle 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 CreateTemporalYearMonth( Isolate* isolate, Handle target, Handle new_target, @@ -1766,7 +1775,6 @@ MaybeHandle ToTemporalInstant(Isolate* isolate, } // namespace namespace temporal { - // #sec-temporal-totemporalcalendar MaybeHandle ToTemporalCalendar( Isolate* isolate, Handle temporal_calendar_like, @@ -5129,6 +5137,93 @@ double TotalDurationNanoseconds(Isolate* isolate, return duration.nanoseconds + duration.microseconds * 1000; } +Maybe RegulateISODate(Isolate* isolate, ShowOverflow overflow, + const DateRecordCommon& date); +Maybe ResolveISOMonth(Isolate* isolate, Handle fields); + +// #sec-temporal-isomonthdayfromfields +Maybe ISOMonthDayFromFields(Isolate* isolate, + Handle fields, + Handle 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()); + + // 3. Set fields to ? PrepareTemporalFields(fields, « "day", "month", + // "monthCode", "year" », «»). + Handle 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()); + // 4. Let month be ! Get(fields, "month"). + Handle month_obj = + Object::GetPropertyOrElement(isolate, fields, factory->month_string()) + .ToHandleChecked(); + // 5. Let monthCode be ! Get(fields, "monthCode"). + Handle month_code_obj = + Object::GetPropertyOrElement(isolate, fields, factory->monthCode_string()) + .ToHandleChecked(); + // 6. Let year be ! Get(fields, "year"). + Handle 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()); + } + // 8. Set month to ? ResolveISOMonth(fields). + DateRecordCommon result; + MAYBE_ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, result.month, + ResolveISOMonth(isolate, fields), + Nothing()); + + // 9. Let day be ! Get(fields, "day"). + Handle 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()); + } + 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()); + // 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 RegulateISODate(Isolate* isolate, ShowOverflow overflow, // #sec-temporal-resolveisomonth Maybe ResolveISOMonth(Isolate* isolate, Handle fields) { Factory* factory = isolate->factory(); - // 1. Let month be ? Get(fields, "month"). - Handle month_obj; - ASSIGN_RETURN_ON_EXCEPTION_VALUE( - isolate, month_obj, - Object::GetPropertyOrElement(isolate, fields, factory->month_string()), - Nothing()); - // 2. Let monthCode be ? Get(fields, "monthCode"). - Handle month_code_obj; - ASSIGN_RETURN_ON_EXCEPTION_VALUE( - isolate, month_code_obj, - Object::GetPropertyOrElement(isolate, fields, - factory->monthCode_string()), - Nothing()); + // 1. Let month be ! Get(fields, "month"). + Handle month_obj = + Object::GetPropertyOrElement(isolate, fields, factory->month_string()) + .ToHandleChecked(); + // 2. Let monthCode be ! Get(fields, "monthCode"). + Handle 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 ISODateFromFields(Isolate* isolate, RequiredFields::kNone), Nothing()); - // 4. Let year be ? Get(fields, "year"). - Handle year_obj; - ASSIGN_RETURN_ON_EXCEPTION_VALUE( - isolate, year_obj, - Object::GetPropertyOrElement(isolate, fields, factory->year_string()), - Nothing()); + // 4. Let year be ! Get(fields, "year"). + Handle 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 ISODateFromFields(Isolate* isolate, Maybe maybe_month = ResolveISOMonth(isolate, fields); MAYBE_RETURN(maybe_month, Nothing()); - // 7. Let day be ? Get(fields, "day"). - Handle day_obj; - ASSIGN_RETURN_ON_EXCEPTION_VALUE( - isolate, day_obj, - Object::GetPropertyOrElement(isolate, fields, factory->day_string()), - Nothing()); + // 7. Let day be ! Get(fields, "day"). + Handle 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 JSTemporalCalendar::Month(Isolate* isolate, return handle(Smi::FromInt(month), isolate); } +// #sec-temporal.calendar.prototype.monthdayfromfields +MaybeHandle JSTemporalCalendar::MonthDayFromFields( + Isolate* isolate, Handle calendar, + Handle fields_obj, Handle 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 fields = Handle::cast(fields_obj); + // 5. Set options to ? GetOptionsObject(options). + Handle 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 maybe_result = + ISOMonthDayFromFields(isolate, fields, options, method_name); + MAYBE_RETURN(maybe_result, Handle()); + 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 JSTemporalCalendar::ToString( Isolate* isolate, Handle calendar, diff --git a/src/objects/js-temporal-objects.h b/src/objects/js-temporal-objects.h index 571234a8dd..f6fb38df01 100644 --- a/src/objects/js-temporal-objects.h +++ b/src/objects/js-temporal-objects.h @@ -102,6 +102,11 @@ class JSTemporalCalendar Isolate* isolate, Handle calendar, Handle fields, Handle options); + // #sec-temporal.calendar.prototype.monthdayfromfields + V8_WARN_UNUSED_RESULT static MaybeHandle + MonthDayFromFields(Isolate* isolate, Handle calendar, + Handle fields, Handle options); + // #sec-temporal.calendar.prototype.mergefields V8_WARN_UNUSED_RESULT static MaybeHandle MergeFields( Isolate* isolate, Handle calendar, diff --git a/test/test262/test262.status b/test/test262/test262.status index 5ddff6e8de..fe2df374ea 100644 --- a/test/test262/test262.status +++ b/test/test262/test262.status @@ -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],