Skip to content

Commit

Permalink
Editorial: Abstract days range check into CheckISODaysRange
Browse files Browse the repository at this point in the history
This pattern is there because of #2729 and #2985. Abstract it into its own
operation, for documentation purposes and because it can disappear after
tc39/ecma262#1087 is fixed.

See: #3005
  • Loading branch information
ptomato committed Oct 9, 2024
1 parent e6660f2 commit 14e85b6
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 22 deletions.
32 changes: 15 additions & 17 deletions polyfill/lib/ecmascript.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -1301,9 +1301,7 @@ export function ToTemporalInstant(item) {
microsecond,
nanosecond - offsetNanoseconds
);
if (MathAbs(ISODateToEpochDays(balanced.isoDate.year, balanced.isoDate.month - 1, balanced.isoDate.day)) > 1e8) {
throw new RangeErrorCtor('date/time value is outside the supported range');
}
CheckISODaysRange(balanced.isoDate);
const epochNanoseconds = GetUTCEpochNanoseconds(balanced);
ValidateEpochNanoseconds(epochNanoseconds);
return new TemporalInstant(epochNanoseconds);
Expand Down Expand Up @@ -1441,17 +1439,13 @@ export function InterpretISODateTimeOffset(
time.microsecond,
time.nanosecond - offsetNs
);
if (MathAbs(ISODateToEpochDays(balanced.year, balanced.month - 1, balanced.day)) > 1e8) {
throw new RangeErrorCtor('date/time outside of supported range');
}
CheckISODaysRange(balanced.isoDate);
const epochNs = GetUTCEpochNanoseconds(balanced);
ValidateEpochNanoseconds(epochNs);
return epochNs;
}

if (MathAbs(ISODateToEpochDays(isoDate.year, isoDate.month - 1, isoDate.day)) > 1e8) {
throw new RangeErrorCtor('date/time outside of supported range');
}
CheckISODaysRange(isoDate);
const utcEpochNs = GetUTCEpochNanoseconds(dt);

// "prefer" or "reject"
Expand Down Expand Up @@ -1936,19 +1930,13 @@ export function GetPossibleEpochNanoseconds(timeZone, isoDateTime) {
isoDateTime.time.microsecond,
isoDateTime.time.nanosecond
);
if (MathAbs(ISODateToEpochDays(balanced.isoDate.year, balanced.isoDate.month - 1, balanced.isoDate.day)) > 1e8) {
throw new RangeErrorCtor('date/time value is outside the supported range');
}
CheckISODaysRange(balanced.isoDate);
const epochNs = GetUTCEpochNanoseconds(balanced);
ValidateEpochNanoseconds(epochNs);
return [epochNs];
}

if (
MathAbs(ISODateToEpochDays(isoDateTime.isoDate.year, isoDateTime.isoDate.month - 1, isoDateTime.isoDate.day)) > 1e8
) {
throw new RangeErrorCtor('date/time value is outside the supported range');
}
CheckISODaysRange(isoDateTime.isoDate);
return GetNamedTimeZoneEpochNanoseconds(timeZone, isoDateTime);
}

Expand Down Expand Up @@ -2978,6 +2966,16 @@ export function ISODateToEpochDays(y, m, d) {
return GetUTCEpochMilliseconds(y, m + 1, d, 0, 0, 0, 0) / DAY_MS;
}

// This is needed before calling GetUTCEpochNanoseconds, because it uses MakeDay
// which is ill-defined in how it handles large year numbers. If the issue
// https://github.com/tc39/ecma262/issues/1087 is fixed, this can be removed
// with no observable changes.
function CheckISODaysRange({ year, month, day }) {
if (MathAbs(ISODateToEpochDays(year, month - 1, day)) > 1e8) {
throw new RangeErrorCtor('date/time value is outside the supported range');
}
}

function DifferenceTime(time1, time2) {
const hours = time2.hour - time1.hour;
const minutes = time2.minute - time1.minute;
Expand Down
22 changes: 22 additions & 0 deletions spec/abstractops.html
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,28 @@ <h1>Date Equations</h1>
<emu-note type="editor"> Note that the operation EpochTimeToMonthInYear(_t_) uses 0-based months unlike rest of Temporal since it's intended to be unified with MonthFromTime(_t_) when the above mentioned issue is fixed.</emu-note>
</emu-clause>

<emu-clause id="sec-checkisodaysrange" type="abstract operation">
<h1>
CheckISODaysRange (
_isoDate_: an ISO Date Record,
): either a normal completion containing ~unused~ or a throw completion
</h1>
<dl class="header">
<dt>description</dt>
<dd>It checks that the given date is within the range of 10<sup>8</sup> days from the epoch.</dd>
</dl>
<emu-alg>
1. If abs(ISODateToEpochDays(_isoDate_.[[Year]], _isoDate_.[[Month]] - 1, _isoDate_.[[Day]])) > 10<sup>8</sup>, then
1. Throw a *RangeError* exception.
1. Return ~unused~.
</emu-alg>
<emu-note type="editor">
This operation is solely present to ensure that GetUTCEpochNanoseconds is not called with numbers that are too large.
It is distinct from ISODateWithinLimits, which uses GetUTCEpochNanoseconds.
This operation can be removed with no observable effect when https://github.com/tc39/ecma262/issues/1087 is fixed.
</emu-note>
</emu-clause>

<emu-clause id="sec-temporal-units">
<h1>Units</h1>
<p>
Expand Down
2 changes: 1 addition & 1 deletion spec/instant.html
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,7 @@ <h1>
1. If _parsed_.[[TimeZone]].[[Z]] is *true*, let _offsetNanoseconds_ be 0; otherwise, let _offsetNanoseconds_ be ! ParseDateTimeUTCOffset(_parsed_.[[TimeZone]].[[OffsetString]]).
1. If _parsed_.[[Time]] is ~start-of-day~, let _time_ be MidnightTimeRecord(); else let _time_ be _parsed_.[[Time]].
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_.[[ISODate]].[[Year]], _balanced_.[[ISODate]].[[Month]] - 1, _balanced_.[[ISODate]].[[Day]])) > 10<sup>8</sup>, throw a *RangeError* exception.
1. Perform ? CheckISODaysRange(_balanced_.[[ISODate]]).
1. Let _epochNanoseconds_ be GetUTCEpochNanoseconds(_balanced_).
1. If IsValidEpochNanoseconds(_epochNanoseconds_) is *false*, throw a *RangeError* exception.
1. Return ! CreateTemporalInstant(_epochNanoseconds_).
Expand Down
4 changes: 2 additions & 2 deletions spec/timezone.html
Original file line number Diff line number Diff line change
Expand Up @@ -350,11 +350,11 @@ <h1>
1. Let _parseResult_ be ! ParseTimeZoneIdentifier(_timeZone_).
1. If _parseResult_.[[OffsetMinutes]] is not ~empty~, then
1. Let _balanced_ be BalanceISODateTime(_isoDateTime_.[[ISODate]].[[Year]], _isoDateTime_.[[ISODate]].[[Month]], _isoDateTime_.[[ISODate]].[[Day]], _isoDateTime_.[[Time]].[[Hour]], _isoDateTime_.[[Time]].[[Minute]] - _parseResult_.[[OffsetMinutes]], _isoDateTime_.[[Time]].[[Second]], _isoDateTime_.[[Time]].[[Millisecond]], _isoDateTime_.[[Time]].[[Microsecond]], _isoDateTime_.[[Time]].[[Nanosecond]]).
1. If abs(ISODateToEpochDays(_balanced_.[[ISODate]].[[Year]], _balanced_.[[ISODate]].[[Month]] - 1, _balanced_.[[ISODate]].[[Day]])) > 10<sup>8</sup>, throw a *RangeError* exception.
1. Perform ? CheckISODaysRange(_balanced_.[[ISODate]]).
1. Let _epochNanoseconds_ be GetUTCEpochNanoseconds(_balanced_).
1. Let _possibleEpochNanoseconds_ be « _epochNanoseconds_ ».
1. Else,
1. If abs(ISODateToEpochDays(_isoDateTime_.[[ISODate]].[[Year]], _isoDateTime_.[[ISODate]].[[Month]] - 1, _isoDateTime_.[[ISODate]].[[Day]])) > 10<sup>8</sup>, throw a *RangeError* exception.
1. Perform ? CheckISODaysRange(_isoDateTime_.[[ISODate]]).
1. Let _possibleEpochNanoseconds_ be GetNamedTimeZoneEpochNanoseconds(_parseResult_.[[Name]], _isoDateTime_).
1. For each value _epochNanoseconds_ in _possibleEpochNanoseconds_, do
1. If IsValidEpochNanoseconds(_epochNanoseconds_) is *false*, throw a *RangeError* exception.
Expand Down
4 changes: 2 additions & 2 deletions spec/zoneddatetime.html
Original file line number Diff line number Diff line change
Expand Up @@ -916,13 +916,13 @@ <h1>
1. Return ? GetEpochNanosecondsFor(_timeZone_, _isoDateTime_, _disambiguation_).
1. If _offsetBehaviour_ is ~exact~, or _offsetBehaviour_ is ~option~ and _offsetOption_ is ~use~, then
1. Let _balanced_ be BalanceISODateTime(_isoDate_.[[Year]], _isoDate_.[[Month]], _isoDate_.[[Day]], _time_.[[Hour]], _time_.[[Minute]], _time_.[[Second]], _time_.[[Millisecond]], _time_.[[Microsecond]], _time_.[[Nanosecond]] - _offsetNanoseconds_).
1. If abs(ISODateToEpochDays(_balanced_.[[ISODate]].[[Year]], _balanced_.[[ISODate]].[[Month]] - 1, _balanced_.[[ISODate]].[[Day]])) > 10<sup>8</sup>, throw a *RangeError* exception.
1. Perform ? CheckISODaysRange(_balanced_.[[ISODate]]).
1. Let _epochNanoseconds_ be GetUTCEpochNanoseconds(_balanced_).
1. If IsValidEpochNanoseconds(_epochNanoseconds_) is *false*, throw a *RangeError* exception.
1. Return _epochNanoseconds_.
1. Assert: _offsetBehaviour_ is ~option~.
1. Assert: _offsetOption_ is ~prefer~ or ~reject~.
1. If abs(ISODateToEpochDays(_isoDate_.[[Year]], _isoDate_.[[Month]] - 1, _isoDate_.[[Day]])) > 10<sup>8</sup>, throw a *RangeError* exception.
1. Perform ? CheckISODaysRange(_isoDate_).
1. Let _utcEpochNanoseconds_ be GetUTCEpochNanoseconds(_isoDateTime_).
1. Let _possibleEpochNs_ be ? GetPossibleEpochNanoseconds(_timeZone_, _isoDateTime_).
1. For each element _candidate_ of _possibleEpochNs_, do
Expand Down

0 comments on commit 14e85b6

Please sign in to comment.