Skip to content

Commit

Permalink
Normative: Throw on conversion from TimeZone to Calendar and vice versa
Browse files Browse the repository at this point in the history
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 <[email protected]>

Closes: #2354
  • Loading branch information
ptomato committed Nov 29, 2022
1 parent c0209c2 commit 2084e77
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 5 deletions.
20 changes: 17 additions & 3 deletions polyfill/lib/ecmascript.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -1683,9 +1683,17 @@ export const ES = ObjectAssign({}, ES2022, {
if (ES.Type(calendarLike) === 'Object') {
if (ES.IsTemporalCalendar(calendarLike)) return calendarLike;
if (HasSlot(calendarLike, CALENDAR)) return GetSlot(calendarLike, CALENDAR);
if (ES.IsTemporalTimeZone(calendarLike)) {
throw new RangeError('Expected a calendar object but received a Temporal.TimeZone');
}
if (!('calendar' in calendarLike)) return calendarLike;
calendarLike = calendarLike.calendar;
if (ES.Type(calendarLike) === 'Object' && !('calendar' in calendarLike)) return calendarLike;
if (ES.Type(calendarLike) === 'Object') {
if (ES.IsTemporalTimeZone(calendarLike)) {
throw new RangeError('Expected a calendar object as the calendar property but received a Temporal.TimeZone');
}
if (!('calendar' in calendarLike)) return calendarLike;
}
}
const identifier = ES.ToString(calendarLike);
const TemporalCalendar = GetIntrinsic('%Temporal.Calendar%');
Expand Down Expand Up @@ -1746,10 +1754,16 @@ export const ES = ObjectAssign({}, ES2022, {
if (ES.Type(temporalTimeZoneLike) === 'Object') {
if (ES.IsTemporalTimeZone(temporalTimeZoneLike)) return temporalTimeZoneLike;
if (ES.IsTemporalZonedDateTime(temporalTimeZoneLike)) return GetSlot(temporalTimeZoneLike, TIME_ZONE);
if (ES.IsTemporalCalendar(temporalTimeZoneLike)) {
throw new RangeError('Expected a time zone object but received a Temporal.Calendar');
}
if (!('timeZone' in temporalTimeZoneLike)) return temporalTimeZoneLike;
temporalTimeZoneLike = temporalTimeZoneLike.timeZone;
if (ES.Type(temporalTimeZoneLike) === 'Object' && !('timeZone' in temporalTimeZoneLike)) {
return temporalTimeZoneLike;
if (ES.Type(temporalTimeZoneLike) === 'Object') {
if (ES.IsTemporalCalendar(temporalTimeZoneLike)) {
throw new RangeError('Expected a time zone object as the timeZone property but received a Temporal.Calendar');
}
if (!('timeZone' in temporalTimeZoneLike)) return temporalTimeZoneLike;
}
}
const identifier = ES.ToString(temporalTimeZoneLike);
Expand Down
5 changes: 4 additions & 1 deletion spec/calendar.html
Original file line number Diff line number Diff line change
Expand Up @@ -367,9 +367,12 @@ <h1>ToTemporalCalendar ( _temporalCalendarLike_ )</h1>
1. Return _temporalCalendarLike_.
1. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalTime]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then
1. Return _temporalCalendarLike_.[[Calendar]].
1. If _temporalCalendarLike_ has an [[InitializedTemporalTimeZone]] internal slot, throw a *RangeError* exception.
1. If ? HasProperty(_temporalCalendarLike_, *"calendar"*) is *false*, return _temporalCalendarLike_.
1. Set _temporalCalendarLike_ to ? Get(_temporalCalendarLike_, *"calendar"*).
1. If Type(_temporalCalendarLike_) is Object and ? HasProperty(_temporalCalendarLike_, *"calendar"*) is *false*, return _temporalCalendarLike_.
1. If Type(_temporalCalendarLike_) is Object, then
1. If _temporalCalendarLike_ has an [[InitializedTemporalTimeZone]] internal slot, throw a *RangeError* exception.
1. If ? HasProperty(_temporalCalendarLike_, *"calendar"*) is *false*, return _temporalCalendarLike_.
1. Let _identifier_ be ? ToString(_temporalCalendarLike_).
1. Set _identifier_ to ? ParseTemporalCalendarString(_identifier_).
1. If IsBuiltinCalendar(_identifier_) is *false*, throw a *RangeError* exception.
Expand Down
5 changes: 4 additions & 1 deletion spec/timezone.html
Original file line number Diff line number Diff line change
Expand Up @@ -539,9 +539,12 @@ <h1>ToTemporalTimeZone ( _temporalTimeZoneLike_ )</h1>
1. Return _temporalTimeZoneLike_.
1. If _temporalTimeZoneLike_ has an [[InitializedTemporalZonedDateTime]] internal slot, then
1. Return _temporalTimeZoneLike_.[[TimeZone]].
1. If _temporalTimeZoneLike_ has an [[InitializedTemporalCalendar]] internal slot, throw a *RangeError* exception.
1. If ? HasProperty(_temporalTimeZoneLike_, *"timeZone"*) is *false*, return _temporalTimeZoneLike_.
1. Set _temporalTimeZoneLike_ to ? Get(_temporalTimeZoneLike_, *"timeZone"*).
1. If Type(_temporalTimeZoneLike_) is Object and ? HasProperty(_temporalTimeZoneLike_, *"timeZone"*) is *false*, return _temporalTimeZoneLike_.
1. If Type(_temporalTimeZoneLike_) is Object, then
1. If _temporalTimeZoneLike_ has an [[InitializedTemporalCalendar]] internal slot, throw a *RangeError* exception.
1. If ? HasProperty(_temporalTimeZoneLike_, *"timeZone"*) is *false*, return _temporalTimeZoneLike_.
1. Let _identifier_ be ? ToString(_temporalTimeZoneLike_).
1. Let _parseResult_ be ? ParseTemporalTimeZoneString(_identifier_).
1. If _parseResult_.[[Name]] is not *undefined*, then
Expand Down

0 comments on commit 2084e77

Please sign in to comment.