diff --git a/polyfill/lib/calendar.mjs b/polyfill/lib/calendar.mjs index a494a7bf94..cbc93ee33e 100644 --- a/polyfill/lib/calendar.mjs +++ b/polyfill/lib/calendar.mjs @@ -324,9 +324,6 @@ impl['iso8601'] = { monthDayFromFields(fields, options, calendarSlotValue) { fields = ES.PrepareTemporalFields(fields, ['day', 'month', 'monthCode', 'year'], ['day']); const overflow = ES.ToTemporalOverflow(options); - if (fields.month !== undefined && fields.year === undefined && fields.monthCode === undefined) { - throw new TypeError('either year or monthCode required with month'); - } const referenceISOYear = 1972; fields = resolveNonLunisolarMonth(fields); let { month, day, year } = fields; @@ -701,7 +698,7 @@ const nonIsoHelperBase = { } if (this.hasEra) { if ((calendarDate['era'] === undefined) !== (calendarDate['eraYear'] === undefined)) { - throw new RangeError("properties 'era' and 'eraYear' must be provided together"); + throw new TypeError("properties 'era' and 'eraYear' must be provided together"); } } }, diff --git a/polyfill/lib/ecmascript.mjs b/polyfill/lib/ecmascript.mjs index 9fa10ac025..03fa2336b6 100644 --- a/polyfill/lib/ecmascript.mjs +++ b/polyfill/lib/ecmascript.mjs @@ -1345,24 +1345,16 @@ export function ToTemporalMonthDay(item, options) { if (options !== undefined) options = SnapshotOwnProperties(GetOptionsObject(options), null); if (Type(item) === 'Object') { if (IsTemporalMonthDay(item)) return item; - let calendar, calendarAbsent; + let calendar; if (HasSlot(item, CALENDAR)) { calendar = GetSlot(item, CALENDAR); - calendarAbsent = false; } else { calendar = item.calendar; - calendarAbsent = calendar === undefined; if (calendar === undefined) calendar = 'iso8601'; calendar = ToTemporalCalendarSlotValue(calendar); } const fieldNames = CalendarFields(calendar, ['day', 'month', 'monthCode', 'year']); const fields = PrepareTemporalFields(item, fieldNames, []); - // Callers who omit the calendar are not writing calendar-independent - // code. In that case, `monthCode`/`year` can be omitted; `month` and - // `day` are sufficient. Add a `year` to satisfy calendar validation. - if (calendarAbsent && fields.month !== undefined && fields.monthCode === undefined && fields.year === undefined) { - fields.year = 1972; - } return CalendarMonthDayFromFields(calendar, fields, options); } @@ -1373,6 +1365,9 @@ export function ToTemporalMonthDay(item, options) { ToTemporalOverflow(options); // validate and ignore if (referenceISOYear === undefined) { + if (calendar !== 'iso8601') { + throw new Error(`assertion failed: missing year with non-"iso8601" calendar identifier ${calendar}`); + } RejectISODate(1972, month, day); return CreateTemporalMonthDay(month, day, calendar); } diff --git a/polyfill/test262 b/polyfill/test262 index dceb204259..892a5dccd2 160000 --- a/polyfill/test262 +++ b/polyfill/test262 @@ -1 +1 @@ -Subproject commit dceb204259abc800b7a6ec7bccf07f9a7c69297d +Subproject commit 892a5dccd2a59a63f3a363db07f53bf896912699 diff --git a/spec/calendar.html b/spec/calendar.html index 8b153b8f7d..23653f10af 100644 --- a/spec/calendar.html +++ b/spec/calendar.html @@ -917,7 +917,7 @@

ISOMonthDayFromFields ( _fields_, _overflow_ )

1. Let _day_ be ! Get(_fields_, *"day"*). 1. Assert: _month_ and _day_ are Numbers. 1. Let _year_ be ! Get(_fields_, *"year"*). - 1. Let _referenceISOYear_ be 1972 (the first leap year after the epoch). + 1. Let _referenceISOYear_ be 1972 (the first ISO 8601 leap year after the epoch). 1. If _year_ is *undefined*, then 1. Let _result_ be ? RegulateISODate(_referenceISOYear_, ℝ(_month_), ℝ(_day_), _overflow_). 1. Else, diff --git a/spec/intl.html b/spec/intl.html index 1ac51aef19..2b5ed4a7af 100644 --- a/spec/intl.html +++ b/spec/intl.html @@ -1855,6 +1855,7 @@

+ + When _type_ is ~month-day~ and *"month"* is provided without *"monthCode"*, it is recommended that all built-in calendars other than the ISO 8601 calendar require a disambiguating year (e.g., either *"year"* or *"era"* and *"eraYear"*), including those that always use exactly the same months as the ISO 8601 calendar (which receives special handling in this specification as a default calendar that is permanently stable for automated processing). + diff --git a/spec/plainmonthday.html b/spec/plainmonthday.html index 44a2ecf6b4..57d9aa874a 100644 --- a/spec/plainmonthday.html +++ b/spec/plainmonthday.html @@ -32,14 +32,13 @@

Temporal.PlainMonthDay ( _isoMonth_, _isoDay_ [ , _calendarLike_ [ , _refere 1. If NewTarget is *undefined*, then 1. Throw a *TypeError* exception. 1. If _referenceISOYear_ is *undefined*, then - 1. Set _referenceISOYear_ to *1972*𝔽. + 1. Set _referenceISOYear_ to *1972*𝔽 (the first ISO 8601 leap year after the epoch). 1. Let _m_ be ? ToIntegerWithTruncation(_isoMonth_). 1. Let _d_ be ? ToIntegerWithTruncation(_isoDay_). 1. Let _calendar_ be ? ToTemporalCalendarSlotValue(_calendarLike_, *"iso8601"*). - 1. Let _ref_ be ? ToIntegerWithTruncation(_referenceISOYear_). - 1. Return ? CreateTemporalMonthDay(_m_, _d_, _calendar_, _ref_, NewTarget). + 1. Let _y_ be ? ToIntegerWithTruncation(_referenceISOYear_). + 1. Return ? CreateTemporalMonthDay(_m_, _d_, _calendar_, _y_, NewTarget). - 1972 is the first leap year after the epoch. @@ -366,27 +365,16 @@

1. If _options_ is not present, set _options_ to *undefined*. 1. If _options_ is not *undefined*, set _options_ to ? SnapshotOwnProperties(! GetOptionsObject(_options_), *null*). - 1. Let _referenceISOYear_ be 1972 (the first leap year after the epoch). 1. If Type(_item_) is Object, then 1. If _item_ has an [[InitializedTemporalMonthDay]] internal slot, then 1. Return _item_. 1. If _item_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then 1. Let _calendar_ be _item_.[[Calendar]]. - 1. Let _calendarAbsent_ be *false*. 1. Else, 1. Let _calendarLike_ be ? Get(_item_, *"calendar"*). - 1. If _calendarLike_ is *undefined*, then - 1. Let _calendarAbsent_ be *true*. - 1. Else, - 1. Let _calendarAbsent_ be *false*. 1. Let _calendar_ be ? ToTemporalCalendarSlotValue(_calendarLike_, *"iso8601"*). 1. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"month"*, *"monthCode"*, *"year"* »). 1. Let _fields_ be ? PrepareTemporalFields(_item_, _fieldNames_, «»). - 1. Let _month_ be ! Get(_fields_, *"month"*). - 1. Let _monthCode_ be ! Get(_fields_, *"monthCode"*). - 1. Let _year_ be ! Get(_fields_, *"year"*). - 1. If _calendarAbsent_ is *true*, and _month_ is not *undefined*, and _monthCode_ is *undefined* and _year_ is *undefined*, then - 1. Perform ! CreateDataPropertyOrThrow(_fields_, *"year"*, 𝔽(_referenceISOYear_)). 1. Return ? CalendarMonthDayFromFields(_calendar_, _fields_, _options_). 1. If _item_ is not a String, throw a *TypeError* exception. 1. Let _result_ be ? ParseTemporalMonthDayString(_item_). @@ -396,6 +384,8 @@

1. Set _calendar_ to the ASCII-lowercase of _calendar_. 1. Perform ? ToTemporalOverflow(_options_). 1. If _result_.[[Year]] is *undefined*, then + 1. Assert: _calendar_ is *"iso8601"*. + 1. Let _referenceISOYear_ be 1972 (the first ISO 8601 leap year after the epoch). 1. Return ? CreateTemporalMonthDay(_result_.[[Month]], _result_.[[Day]], _calendar_, _referenceISOYear_). 1. Set _result_ to ? CreateTemporalMonthDay(_result_.[[Month]], _result_.[[Day]], _calendar_, _result_.[[Year]]). 1. NOTE: The following operation is called without _options_, in order for the calendar to store a canonical value in the [[ISOYear]] internal slot of the result.