diff --git a/js/src/builtin/temporal/Calendar.cpp b/js/src/builtin/temporal/Calendar.cpp index cddb1c1151ec..5e3356a8b656 100644 --- a/js/src/builtin/temporal/Calendar.cpp +++ b/js/src/builtin/temporal/Calendar.cpp @@ -591,6 +591,46 @@ CalendarObject* js::temporal::GetISO8601Calendar(JSContext* cx) { return CreateTemporalCalendar(cx, id); } + + + +static bool ObjectImplementsTemporalCalendarProtocol(JSContext* cx, + Handle object, + bool* result) { + + MOZ_ASSERT(!object->canUnwrapAs(), + "Calendar objects handled in the caller"); + + + for (auto key : { + &JSAtomState::dateAdd, &JSAtomState::dateFromFields, + &JSAtomState::dateUntil, &JSAtomState::day, + &JSAtomState::dayOfWeek, &JSAtomState::dayOfYear, + &JSAtomState::daysInMonth, &JSAtomState::daysInWeek, + &JSAtomState::daysInYear, &JSAtomState::fields, + &JSAtomState::id, &JSAtomState::inLeapYear, + &JSAtomState::mergeFields, &JSAtomState::month, + &JSAtomState::monthCode, &JSAtomState::monthDayFromFields, + &JSAtomState::monthsInYear, &JSAtomState::weekOfYear, + &JSAtomState::year, &JSAtomState::yearMonthFromFields, + &JSAtomState::yearOfWeek, + }) { + + bool has; + if (!HasProperty(cx, object, cx->names().*key, &has)) { + return false; + } + if (!has) { + *result = false; + return true; + } + } + + + *result = true; + return true; +} + template static bool ToTemporalCalendar(JSContext* cx, Handle object, MutableHandle result) { @@ -614,6 +654,8 @@ bool js::temporal::ToTemporalCalendar(JSContext* cx, Handle temporalCalendarLike, MutableHandle result) { + + Rooted calendarLike(cx, temporalCalendarLike); if (calendarLike.isObject()) { Rooted obj(cx, &calendarLike.toObject()); @@ -637,55 +679,21 @@ bool js::temporal::ToTemporalCalendar(JSContext* cx, } - if (obj->canUnwrapAs()) { - JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_INVALID_OBJECT, - "Temporal.Calendar", "Temporal.TimeZone"); - return false; - } - - - bool hasCalendar; - if (!HasProperty(cx, obj, cx->names().calendar, &hasCalendar)) { + bool implementsCalendarProtocol; + if (!ObjectImplementsTemporalCalendarProtocol( + cx, obj, &implementsCalendarProtocol)) { return false; } - if (!hasCalendar) { - result.set(obj); - return true; - } - - - if (!GetProperty(cx, obj, obj, cx->names().calendar, &calendarLike)) { + if (!implementsCalendarProtocol) { + JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, + JSMSG_TEMPORAL_INVALID_OBJECT, + "Temporal.Calendar", obj->getClass()->name); return false; } - if (calendarLike.isObject()) { - obj = &calendarLike.toObject(); - - - - - - if (obj->canUnwrapAs()) { - JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, - JSMSG_TEMPORAL_INVALID_OBJECT, - "Temporal.Calendar", "Temporal.TimeZone"); - return false; - } - - - - - - if (!HasProperty(cx, obj, cx->names().calendar, &hasCalendar)) { - return false; - } - if (!hasCalendar) { - result.set(obj); - return true; - } - } + result.set(obj); + return true; } @@ -714,6 +722,8 @@ bool js::temporal::ToTemporalCalendar(JSContext* cx, + + bool js::temporal::ToTemporalCalendarWithISODefault( JSContext* cx, Handle temporalCalendarLike, MutableHandle result) {