mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 14:27:35 +00:00
LibJS: Make sure to exactly add nanoseconds in add_duration
If the given nanoseconds values add to something above 2**53 - 1 we are potentially rounding the double to some near integer value.
This commit is contained in:
parent
1b0ca52c54
commit
1be337353b
1 changed files with 18 additions and 8 deletions
|
@ -988,10 +988,15 @@ ThrowCompletionOr<DurationRecord> add_duration(VM& vm, double years1, double mon
|
|||
}
|
||||
|
||||
// b. Let result be ? BalanceDuration(d1 + d2, h1 + h2, min1 + min2, s1 + s2, ms1 + ms2, mus1 + mus2, ns1 + ns2, largestUnit).
|
||||
VERIFY(trunc(nanoseconds1 + nanoseconds2) == nanoseconds1 + nanoseconds2);
|
||||
if (!isfinite(nanoseconds1 + nanoseconds2))
|
||||
return vm.throw_completion<RangeError>(ErrorType::TemporalInvalidDuration);
|
||||
auto result = TRY(balance_duration(vm, days1 + days2, hours1 + hours2, minutes1 + minutes2, seconds1 + seconds2, milliseconds1 + milliseconds2, microseconds1 + microseconds2, Crypto::SignedBigInteger { nanoseconds1 + nanoseconds2 }, largest_unit));
|
||||
// NOTE: Nanoseconds is the only one that can overflow the safe integer range of a double
|
||||
// so we have to check for that case.
|
||||
Crypto::SignedBigInteger sum_of_nano_seconds;
|
||||
if (fabs(nanoseconds1 + nanoseconds2) >= MAX_ARRAY_LIKE_INDEX)
|
||||
sum_of_nano_seconds = Crypto::SignedBigInteger { nanoseconds1 }.plus(Crypto::SignedBigInteger { nanoseconds2 });
|
||||
else
|
||||
sum_of_nano_seconds = Crypto::SignedBigInteger { nanoseconds1 + nanoseconds2 };
|
||||
|
||||
auto result = TRY(balance_duration(vm, days1 + days2, hours1 + hours2, minutes1 + minutes2, seconds1 + seconds2, milliseconds1 + milliseconds2, microseconds1 + microseconds2, sum_of_nano_seconds, largest_unit));
|
||||
|
||||
// c. Return ! CreateDurationRecord(0, 0, 0, result.[[Days]], result.[[Hours]], result.[[Minutes]], result.[[Seconds]], result.[[Milliseconds]], result.[[Microseconds]], result.[[Nanoseconds]]).
|
||||
return MUST(create_duration_record(vm, 0, 0, 0, result.days, result.hours, result.minutes, result.seconds, result.milliseconds, result.microseconds, result.nanoseconds));
|
||||
|
@ -1032,10 +1037,15 @@ ThrowCompletionOr<DurationRecord> add_duration(VM& vm, double years1, double mon
|
|||
auto* date_difference = TRY(calendar_date_until(vm, calendar, &relative_to, end, *difference_options));
|
||||
|
||||
// k. Let result be ? BalanceDuration(dateDifference.[[Days]], h1 + h2, min1 + min2, s1 + s2, ms1 + ms2, mus1 + mus2, ns1 + ns2, largestUnit).
|
||||
VERIFY(trunc(nanoseconds1 + nanoseconds2) == nanoseconds1 + nanoseconds2);
|
||||
if (!isfinite(nanoseconds1 + nanoseconds2))
|
||||
return vm.throw_completion<RangeError>(ErrorType::TemporalInvalidDuration);
|
||||
auto result = TRY(balance_duration(vm, date_difference->days(), hours1 + hours2, minutes1 + minutes2, seconds1 + seconds2, milliseconds1 + milliseconds2, microseconds1 + microseconds2, Crypto::SignedBigInteger { nanoseconds1 + nanoseconds2 }, largest_unit));
|
||||
// NOTE: Nanoseconds is the only one that can overflow the safe integer range of a double
|
||||
// so we have to check for that case.
|
||||
Crypto::SignedBigInteger sum_of_nano_seconds;
|
||||
if (fabs(nanoseconds1 + nanoseconds2) >= MAX_ARRAY_LIKE_INDEX)
|
||||
sum_of_nano_seconds = Crypto::SignedBigInteger { nanoseconds1 }.plus(Crypto::SignedBigInteger { nanoseconds2 });
|
||||
else
|
||||
sum_of_nano_seconds = Crypto::SignedBigInteger { nanoseconds1 + nanoseconds2 };
|
||||
|
||||
auto result = TRY(balance_duration(vm, date_difference->days(), hours1 + hours2, minutes1 + minutes2, seconds1 + seconds2, milliseconds1 + milliseconds2, microseconds1 + microseconds2, sum_of_nano_seconds, largest_unit));
|
||||
|
||||
// l. Return ? CreateDurationRecord(dateDifference.[[Years]], dateDifference.[[Months]], dateDifference.[[Weeks]], result.[[Days]], result.[[Hours]], result.[[Minutes]], result.[[Seconds]], result.[[Milliseconds]], result.[[Microseconds]], result.[[Nanoseconds]]).
|
||||
return MUST(create_duration_record(vm, date_difference->years(), date_difference->months(), date_difference->weeks(), result.days, result.hours, result.minutes, result.seconds, result.milliseconds, result.microseconds, result.nanoseconds));
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue