Skip to content

Commit

Permalink
Editorial: Adjust RangeError condition in GetPossibleEpochNanoseconds
Browse files Browse the repository at this point in the history
Similarly to the previous commit, 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). Previously to PR #2925, that
could not happen because GetPossibleInstantsFor took a PlainDateTime
object, but now it takes an ISO Date-Time Record.

Note that this is editorial, because IsValidEpochNanoseconds would throw
anyway in this case even if GetUTCEpochNanoseconds was fully defined for
large inputs.
  • Loading branch information
ptomato committed Oct 1, 2024
1 parent e37c33a commit fb6c830
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 7 deletions.
36 changes: 31 additions & 5 deletions polyfill/lib/ecmascript.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2098,13 +2098,38 @@ export function GetPossibleEpochNanoseconds(timeZone, isoDateTime) {
const { year, month, day, hour, minute, second, millisecond, microsecond, nanosecond } = isoDateTime;
const offsetMinutes = ParseTimeZoneIdentifier(timeZone).offsetMinutes;
if (offsetMinutes !== undefined) {
return [
GetUTCEpochNanoseconds(year, month, day, hour, minute, second, millisecond, microsecond, nanosecond).subtract(
offsetMinutes * 60e9
)
];
const balanced = BalanceISODateTime(
year,
month,
day,
hour,
minute - offsetMinutes,
second,
millisecond,
microsecond,
nanosecond
);
if (MathAbs(ISODateToEpochDays(balanced.year, balanced.month - 1, balanced.day)) > 1e8) {
throw new RangeErrorCtor('date/time value is outside the supported range');
}
const epochNs = GetUTCEpochNanoseconds(
balanced.year,
balanced.month,
balanced.day,
balanced.hour,
balanced.minute,
balanced.second,
balanced.millisecond,
balanced.microsecond,
balanced.nanosecond
);
ValidateEpochNanoseconds(epochNs);
return [epochNs];
}

if (MathAbs(ISODateToEpochDays(year, month - 1, day)) > 1e8) {
throw new RangeErrorCtor('date/time value is outside the supported range');
}
return GetNamedTimeZoneEpochNanoseconds(
timeZone,
year,
Expand Down Expand Up @@ -2693,6 +2718,7 @@ export function GetNamedTimeZoneEpochNanoseconds(
) {
return undefined;
}
ValidateEpochNanoseconds(epochNanoseconds);
return epochNanoseconds;
}
]);
Expand Down
6 changes: 4 additions & 2 deletions spec/timezone.html
Original file line number Diff line number Diff line change
Expand Up @@ -357,10 +357,12 @@ <h1>
<emu-alg>
1. Let _parseResult_ be ! ParseTimeZoneIdentifier(_timeZone_).
1. If _parseResult_.[[OffsetMinutes]] is not ~empty~, then
1. Let _offsetNanoseconds_ be _parseResult_.[[OffsetMinutes]] × (60 × 10<sup>9</sup>).
1. Let _epochNanoseconds_ be GetUTCEpochNanoseconds(_isoDateTime_.[[Year]], _isoDateTime_.[[Month]], _isoDateTime_.[[Day]], _isoDateTime_.[[Hour]], _isoDateTime_.[[Minute]], _isoDateTime_.[[Second]], _isoDateTime_.[[Millisecond]], _isoDateTime_.[[Microsecond]], _isoDateTime_.[[Nanosecond]]) - ℤ(_offsetNanoseconds_).
1. Let _balanced_ be BalanceISODateTime(_isoDateTime_.[[Year]], _isoDateTime_.[[Month]], _isoDateTime_.[[Day]], _isoDateTime_.[[Hour]], _isoDateTime_.[[Minute]] - _parseResult_.[[OffsetMinutes]], _isoDateTime_.[[Second]], _isoDateTime_.[[Millisecond]], _isoDateTime_.[[Microsecond]], _isoDateTime_.[[Nanosecond]]).
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. Let _possibleEpochNanoseconds_ be « _epochNanoseconds_ ».
1. Else,
1. If abs(ISODateToEpochDays(_isoDateTime_.[[Year]], _isoDateTime_.[[Month]] - 1, _isoDateTime_.[[Day]])) > 10<sup>8</sup>, throw a *RangeError* exception.
1. Let _possibleEpochNanoseconds_ be GetNamedTimeZoneEpochNanoseconds(_parseResult_.[[Name]], _isoDateTime_.[[Year]], _isoDateTime_.[[Month]], _isoDateTime_.[[Day]], _isoDateTime_.[[Hour]], _isoDateTime_.[[Minute]], _isoDateTime_.[[Second]], _isoDateTime_.[[Millisecond]], _isoDateTime_.[[Microsecond]], _isoDateTime_.[[Nanosecond]]).
1. For each value _epochNanoseconds_ in _possibleEpochNanoseconds_, do
1. If IsValidEpochNanoseconds(_epochNanoseconds_) is *false*, throw a *RangeError* exception.
Expand Down

0 comments on commit fb6c830

Please sign in to comment.