Skip to content

Commit

Permalink
Editorial: Adjust RangeError condition in ToTemporalInstant
Browse files Browse the repository at this point in the history
We must avoid calling GetUTCEpochNanoseconds with dates that are too large
because it is ill-defined in ECMA-262 what is supposed to happen. (See
tc39/ecma262#1087). We had a condition in
ToTemporalInstant that was supposed to prevent this, but was incorrect
because subtracting the UTC offset could push the date out of range.

Note that this is editorial, because IsValidEpochNanoseconds would throw
anyway in this case even if GetUTCEpochNanoseconds was fully defined for
large inputs.

See: #2985
  • Loading branch information
ptomato committed Sep 30, 2024
1 parent cf046bb commit 43bc062
Show file tree
Hide file tree
Showing 2 changed files with 20 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 @@ -1363,7 +1363,7 @@ export function ToTemporalInstant(item) {

// ParseTemporalInstantString ensures that either `z` is true or or `offset` is non-undefined
const offsetNanoseconds = z ? 0 : ParseDateTimeUTCOffset(offset);
const epochNanoseconds = GetUTCEpochNanoseconds(
const balanced = BalanceISODateTime(
year,
month,
day,
Expand All @@ -1372,8 +1372,22 @@ export function ToTemporalInstant(item) {
second,
millisecond,
microsecond,
nanosecond
).subtract(offsetNanoseconds);
nanosecond - offsetNanoseconds
);
if (MathAbs(ISODateToEpochDays(balanced.year, balanced.month - 1, balanced.day)) > 1e8) {
throw new RangeErrorCtor('date/time value is outside the supported range');
}
const epochNanoseconds = GetUTCEpochNanoseconds(
balanced.year,
balanced.month,
balanced.day,
balanced.hour,
balanced.minute,
balanced.second,
balanced.millisecond,
balanced.microsecond,
balanced.nanosecond
);
ValidateEpochNanoseconds(epochNanoseconds);
return new TemporalInstant(epochNanoseconds);
}
Expand Down
5 changes: 3 additions & 2 deletions spec/instant.html
Original file line number Diff line number Diff line change
Expand Up @@ -412,12 +412,13 @@ <h1>
1. Let _parsed_ be ? ParseISODateTime(_item_, « |TemporalInstantString| »).
1. Assert: Either _parsed_.[[TimeZone]].[[OffsetString]] is not ~empty~ or _parsed_.[[TimeZone]].[[Z]] is *true*, but not both.
1. If _parsed_.[[TimeZone]].[[Z]] is *true*, let _offsetNanoseconds_ be 0; otherwise, let _offsetNanoseconds_ be ! ParseDateTimeUTCOffset(_parsed_.[[TimeZone]].[[OffsetString]]).
1. If abs(ISODateToEpochDays(_parsed_.[[Year]], _parsed_.[[Month]] - 1, _parsed_.[[Day]])) > 10<sup>8</sup>, throw a *RangeError* exception.
1. If _parsed_.[[Time]] is ~start-of-day~, then
1. Let _time_ be Time Record { [[Days]]: 0, [[Hour]]: 0, [[Minute]]: 0, [[Second]]: 0, [[Millisecond]]: 0, [[Microsecond]]: 0, [[Nanosecond]]: 0 }.
1. Else,
1. Let _time_ be _parsed_.[[Time]].
1. Let _epochNanoseconds_ be GetUTCEpochNanoseconds(_parsed_.[[Year]], _parsed_.[[Month]], _parsed_.[[Day]], _time_.[[Hour]], _time_.[[Minute]], _time_.[[Second]], _time_.[[Millisecond]], _time_.[[Microsecond]], _time_.[[Nanosecond]]) - ℤ(_offsetNanoseconds_).
1. Let _balanced_ be BalanceISODateTime(_parsed_.[[Year]], _parsed_.[[Month]], _parsed_.[[Day]], _time_.[[Hour]], _time_.[[Minute]], _time_.[[Second]], _time_.[[Millisecond]], _time_.[[Microsecond]], _time_.[[Nanosecond]] - _offsetNanoseconds_).
1. If abs(ISODateToEpochDays(_balanced_.[[Year]], _balanced_.[[Month]] - 1, _balanced_.[[Day]])) > 10<sup>8</sup>, throw a *RangeError* exception.
1. Let _epochNanoseconds_ be GetUTCEpochNanoseconds(_balanced_.[[Year]], _balanced_.[[Month]], _balanced_.[[Day]], _balanced_.[[Hour]], _balanced_.[[Minute]], _balanced_.[[Second]], _balanced_.[[Millisecond]], _balanced_.[[Microsecond]], _balanced_.[[Nanosecond]]).
1. If IsValidEpochNanoseconds(_epochNanoseconds_) is *false*, throw a *RangeError* exception.
1. Return ! CreateTemporalInstant(_epochNanoseconds_).
</emu-alg>
Expand Down

0 comments on commit 43bc062

Please sign in to comment.