From e5d97ffe6730751d957946635055cbd64135fcc5 Mon Sep 17 00:00:00 2001 From: Richard Gibson Date: Mon, 21 Aug 2023 15:34:57 -0400 Subject: [PATCH 1/6] Editorial: DRY out ISO 8601 PlainMonthDay reference year defaulting --- spec/plainmonthday.html | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/spec/plainmonthday.html b/spec/plainmonthday.html index 44a2ecf6b4..bf3e9d2eda 100644 --- a/spec/plainmonthday.html +++ b/spec/plainmonthday.html @@ -366,27 +366,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 +385,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 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. From fe8bd6f2033872c8d0e9c40799951d5ce4484059 Mon Sep 17 00:00:00 2001 From: Richard Gibson Date: Mon, 21 Aug 2023 16:11:02 -0400 Subject: [PATCH 2/6] Polyfill: Align MonthDay code with spec --- polyfill/lib/calendar.mjs | 3 --- polyfill/lib/ecmascript.mjs | 10 ++++------ 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/polyfill/lib/calendar.mjs b/polyfill/lib/calendar.mjs index a494a7bf94..1bd9660a4b 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; diff --git a/polyfill/lib/ecmascript.mjs b/polyfill/lib/ecmascript.mjs index 9fa10ac025..756e8686b5 100644 --- a/polyfill/lib/ecmascript.mjs +++ b/polyfill/lib/ecmascript.mjs @@ -1345,13 +1345,11 @@ 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); } @@ -1360,9 +1358,6 @@ export function ToTemporalMonthDay(item, options) { // 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 +1368,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); } From 157ecb595ebb421ceeec96cae685eea630fdba55 Mon Sep 17 00:00:00 2001 From: Richard Gibson Date: Wed, 23 Aug 2023 16:03:19 -0400 Subject: [PATCH 3/6] Editorial: Improve inline explanations of reference ISO year --- polyfill/lib/ecmascript.mjs | 3 --- spec/calendar.html | 2 +- spec/plainmonthday.html | 9 ++++----- 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/polyfill/lib/ecmascript.mjs b/polyfill/lib/ecmascript.mjs index 756e8686b5..03fa2336b6 100644 --- a/polyfill/lib/ecmascript.mjs +++ b/polyfill/lib/ecmascript.mjs @@ -1355,9 +1355,6 @@ export function ToTemporalMonthDay(item, options) { } 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. return CalendarMonthDayFromFields(calendar, fields, options); } 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/plainmonthday.html b/spec/plainmonthday.html index bf3e9d2eda..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. @@ -386,7 +385,7 @@

1. Perform ? ToTemporalOverflow(_options_). 1. If _result_.[[Year]] is *undefined*, then 1. Assert: _calendar_ is *"iso8601"*. - 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. 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. From 7ce6e265c8ebfc26785abfe0393ac17b76153e55 Mon Sep 17 00:00:00 2001 From: Richard Gibson Date: Sat, 16 Sep 2023 12:25:23 -0400 Subject: [PATCH 4/6] Editorial: Note that optional calendars should not infer monthCode from month Fixes #2664 --- spec/intl.html | 4 ++++ 1 file changed, 4 insertions(+) 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 @@

  • If _type_ is ~date~ or ~month-day~ and *"day"* in the calendar has an interpretation analogous to ISO 8601 and its corresponding value is *undefined*.
  • If *"month"* and *"monthCode"* in the calendar have interpretations analogous to ISO 8601 and either the corresponding values for both are *undefined* or neither value is *undefined* but they do not identify the same month.
  • +
  • If _type_ is ~month-day~ and the value for *"monthCode"* is *undefined* and a year cannot be determined from _fields_.
  • If _type_ is ~date~ or ~year-month~ and the calendar supports the usual partitioning of years into eras with their own year counting as represented by *"year"*, *"era"*, and *"eraYear"* (as in the Gregorian or traditional Japanese calendars) and any of the following cases apply:
    • The value for each of *"year"* and *"era"* and *"eraYear"* is *undefined*.
    • The value for *"era"* is *undefined* but the value for *"eraYear"* is not.
    • @@ -1862,6 +1863,9 @@

    • None of the three values are *undefined* but the values for *"era"* and *"eraYear"* do not together identify the same year as the value for *"year"*.
+ + 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). + From a96bec1d02bf153097ba12130c1453118738bdf4 Mon Sep 17 00:00:00 2001 From: Philip Chimento Date: Tue, 19 Sep 2023 11:09:29 -0700 Subject: [PATCH 5/6] Polyfill: Align CalendarResolveFields with spec From CalendarResolveFields: "The operation throws a *TypeError* exception if the properties of _fields_ are internally inconsistent within the calendar or insufficient to identify a unique instance of _type_ in the calendar." --- polyfill/lib/calendar.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/polyfill/lib/calendar.mjs b/polyfill/lib/calendar.mjs index 1bd9660a4b..cbc93ee33e 100644 --- a/polyfill/lib/calendar.mjs +++ b/polyfill/lib/calendar.mjs @@ -698,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"); } } }, From a58a0f4293fc26b937aa86ca703765ee562138d2 Mon Sep 17 00:00:00 2001 From: Philip Chimento Date: Thu, 26 Oct 2023 10:27:35 -0700 Subject: [PATCH 6/6] Update test262 --- polyfill/test262 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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