Skip to content

Commit 2084e77

Browse files
committed
Normative: Throw on conversion from TimeZone to Calendar and vice versa
In order to prevent bugs like `new Temporal.ZonedDateTime(0n, cal, tz)` (where the calendar and time zone arguments are switched, silently poisoning the object) ToTemporalCalendar should throw if it encounters a Temporal.TimeZone instance, and ToTemporalTimeZone should throw if it encounters a Temporal.Calendar instance. Includes implementation in the reference code. Co-authored-by: Aditi <aditisingh1400@gmail.com> Closes: #2354
1 parent c0209c2 commit 2084e77

File tree

3 files changed

+25
-5
lines changed

3 files changed

+25
-5
lines changed

polyfill/lib/ecmascript.mjs

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1683,9 +1683,17 @@ export const ES = ObjectAssign({}, ES2022, {
16831683
if (ES.Type(calendarLike) === 'Object') {
16841684
if (ES.IsTemporalCalendar(calendarLike)) return calendarLike;
16851685
if (HasSlot(calendarLike, CALENDAR)) return GetSlot(calendarLike, CALENDAR);
1686+
if (ES.IsTemporalTimeZone(calendarLike)) {
1687+
throw new RangeError('Expected a calendar object but received a Temporal.TimeZone');
1688+
}
16861689
if (!('calendar' in calendarLike)) return calendarLike;
16871690
calendarLike = calendarLike.calendar;
1688-
if (ES.Type(calendarLike) === 'Object' && !('calendar' in calendarLike)) return calendarLike;
1691+
if (ES.Type(calendarLike) === 'Object') {
1692+
if (ES.IsTemporalTimeZone(calendarLike)) {
1693+
throw new RangeError('Expected a calendar object as the calendar property but received a Temporal.TimeZone');
1694+
}
1695+
if (!('calendar' in calendarLike)) return calendarLike;
1696+
}
16891697
}
16901698
const identifier = ES.ToString(calendarLike);
16911699
const TemporalCalendar = GetIntrinsic('%Temporal.Calendar%');
@@ -1746,10 +1754,16 @@ export const ES = ObjectAssign({}, ES2022, {
17461754
if (ES.Type(temporalTimeZoneLike) === 'Object') {
17471755
if (ES.IsTemporalTimeZone(temporalTimeZoneLike)) return temporalTimeZoneLike;
17481756
if (ES.IsTemporalZonedDateTime(temporalTimeZoneLike)) return GetSlot(temporalTimeZoneLike, TIME_ZONE);
1757+
if (ES.IsTemporalCalendar(temporalTimeZoneLike)) {
1758+
throw new RangeError('Expected a time zone object but received a Temporal.Calendar');
1759+
}
17491760
if (!('timeZone' in temporalTimeZoneLike)) return temporalTimeZoneLike;
17501761
temporalTimeZoneLike = temporalTimeZoneLike.timeZone;
1751-
if (ES.Type(temporalTimeZoneLike) === 'Object' && !('timeZone' in temporalTimeZoneLike)) {
1752-
return temporalTimeZoneLike;
1762+
if (ES.Type(temporalTimeZoneLike) === 'Object') {
1763+
if (ES.IsTemporalCalendar(temporalTimeZoneLike)) {
1764+
throw new RangeError('Expected a time zone object as the timeZone property but received a Temporal.Calendar');
1765+
}
1766+
if (!('timeZone' in temporalTimeZoneLike)) return temporalTimeZoneLike;
17531767
}
17541768
}
17551769
const identifier = ES.ToString(temporalTimeZoneLike);

spec/calendar.html

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -367,9 +367,12 @@ <h1>ToTemporalCalendar ( _temporalCalendarLike_ )</h1>
367367
1. Return _temporalCalendarLike_.
368368
1. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalTime]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then
369369
1. Return _temporalCalendarLike_.[[Calendar]].
370+
1. If _temporalCalendarLike_ has an [[InitializedTemporalTimeZone]] internal slot, throw a *RangeError* exception.
370371
1. If ? HasProperty(_temporalCalendarLike_, *"calendar"*) is *false*, return _temporalCalendarLike_.
371372
1. Set _temporalCalendarLike_ to ? Get(_temporalCalendarLike_, *"calendar"*).
372-
1. If Type(_temporalCalendarLike_) is Object and ? HasProperty(_temporalCalendarLike_, *"calendar"*) is *false*, return _temporalCalendarLike_.
373+
1. If Type(_temporalCalendarLike_) is Object, then
374+
1. If _temporalCalendarLike_ has an [[InitializedTemporalTimeZone]] internal slot, throw a *RangeError* exception.
375+
1. If ? HasProperty(_temporalCalendarLike_, *"calendar"*) is *false*, return _temporalCalendarLike_.
373376
1. Let _identifier_ be ? ToString(_temporalCalendarLike_).
374377
1. Set _identifier_ to ? ParseTemporalCalendarString(_identifier_).
375378
1. If IsBuiltinCalendar(_identifier_) is *false*, throw a *RangeError* exception.

spec/timezone.html

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -539,9 +539,12 @@ <h1>ToTemporalTimeZone ( _temporalTimeZoneLike_ )</h1>
539539
1. Return _temporalTimeZoneLike_.
540540
1. If _temporalTimeZoneLike_ has an [[InitializedTemporalZonedDateTime]] internal slot, then
541541
1. Return _temporalTimeZoneLike_.[[TimeZone]].
542+
1. If _temporalTimeZoneLike_ has an [[InitializedTemporalCalendar]] internal slot, throw a *RangeError* exception.
542543
1. If ? HasProperty(_temporalTimeZoneLike_, *"timeZone"*) is *false*, return _temporalTimeZoneLike_.
543544
1. Set _temporalTimeZoneLike_ to ? Get(_temporalTimeZoneLike_, *"timeZone"*).
544-
1. If Type(_temporalTimeZoneLike_) is Object and ? HasProperty(_temporalTimeZoneLike_, *"timeZone"*) is *false*, return _temporalTimeZoneLike_.
545+
1. If Type(_temporalTimeZoneLike_) is Object, then
546+
1. If _temporalTimeZoneLike_ has an [[InitializedTemporalCalendar]] internal slot, throw a *RangeError* exception.
547+
1. If ? HasProperty(_temporalTimeZoneLike_, *"timeZone"*) is *false*, return _temporalTimeZoneLike_.
545548
1. Let _identifier_ be ? ToString(_temporalTimeZoneLike_).
546549
1. Let _parseResult_ be ? ParseTemporalTimeZoneString(_identifier_).
547550
1. If _parseResult_.[[Name]] is not *undefined*, then

0 commit comments

Comments
 (0)