1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 16:37:35 +00:00

LibJS: Replace magic nanosecond numbers with constants

This is an editorial change in the Temporal spec.

See: 3fdbfda
This commit is contained in:
Linus Groh 2022-05-06 19:28:56 +02:00
parent 3729a910f6
commit c6f7214a60
9 changed files with 45 additions and 36 deletions

View file

@ -44,6 +44,9 @@ constexpr double ms_per_minute = 60'000;
constexpr double ms_per_hour = 3'600'000;
// https://tc39.es/ecma262/#eqn-msPerDay
constexpr double ms_per_day = 86'400'000;
// https://tc39.es/proposal-temporal/#eqn-nsPerDay
constexpr double ns_per_day = 86'400'000'000'000;
static auto const ns_per_day_bigint = "86400000000000"_sbigint;
u16 day_within_year(double);
u8 date_from_time(double);

View file

@ -39,8 +39,8 @@ bool is_valid_epoch_nanoseconds(BigInt const& epoch_nanoseconds)
{
// 1. Assert: Type(epochNanoseconds) is BigInt.
// 2. If epochNanoseconds < -86400 × 10^17 or epochNanoseconds > 86400 × 10^17, then
if (epoch_nanoseconds.big_integer() < INSTANT_NANOSECONDS_MIN || epoch_nanoseconds.big_integer() > INSTANT_NANOSECONDS_MAX) {
// 2. If (epochNanoseconds) < nsMinInstant or (epochNanoseconds) > nsMaxInstant, then
if (epoch_nanoseconds.big_integer() < ns_min_instant || epoch_nanoseconds.big_integer() > ns_max_instant) {
// a. Return false.
return false;
}
@ -119,7 +119,7 @@ ThrowCompletionOr<BigInt*> parse_temporal_instant(GlobalObject& global_object, S
auto* utc = get_epoch_from_iso_parts(global_object, result.year, result.month, result.day, result.hour, result.minute, result.second, result.millisecond, result.microsecond, result.nanosecond);
// 6. If (utc) < -8.64 × 10^21 or (utc) > 8.64 × 10^21, then
if (utc->big_integer() < INSTANT_NANOSECONDS_MIN || utc->big_integer() > INSTANT_NANOSECONDS_MAX) {
if (utc->big_integer() < ns_min_instant || utc->big_integer() > ns_max_instant) {
// a. Throw a RangeError exception.
return vm.throw_completion<RangeError>(global_object, ErrorType::TemporalInvalidEpochNanoseconds);
}

View file

@ -32,10 +32,13 @@ private:
BigInt const& m_nanoseconds; // [[Nanoseconds]]
};
// -86400 * 10^17
auto const INSTANT_NANOSECONDS_MIN = "-8640000000000000000000"_sbigint;
// +86400 * 10^17
auto const INSTANT_NANOSECONDS_MAX = "8640000000000000000000"_sbigint;
// https://tc39.es/proposal-temporal/#eqn-nsMaxInstant
// nsMaxInstant = 10^8 × nsPerDay = 8.64 × 10^21
static auto const ns_max_instant = "8640000000000000000000"_sbigint;
// https://tc39.es/proposal-temporal/#eqn-nsMinInstant
// nsMinInstant = -nsMaxInstant = -8.64 × 10^21
static auto const ns_min_instant = "-8640000000000000000000"_sbigint;
bool is_valid_epoch_nanoseconds(BigInt const& epoch_nanoseconds);
ThrowCompletionOr<Instant*> create_temporal_instant(GlobalObject&, BigInt const& nanoseconds, FunctionObject const* new_target = nullptr);

View file

@ -6,6 +6,7 @@
#include <AK/TypeCasts.h>
#include <LibCrypto/BigInt/UnsignedBigInteger.h>
#include <LibJS/Runtime/Date.h>
#include <LibJS/Runtime/GlobalObject.h>
#include <LibJS/Runtime/Temporal/AbstractOperations.h>
#include <LibJS/Runtime/Temporal/Calendar.h>
@ -278,35 +279,35 @@ JS_DEFINE_NATIVE_FUNCTION(InstantPrototype::round)
double maximum;
// 8. If smallestUnit is "hour", then
if (smallest_unit == "hour"sv) {
// a. Let maximum be 24.
maximum = 24;
// a. Let maximum be HoursPerDay.
maximum = hours_per_day;
}
// 9. Else if smallestUnit is "minute", then
else if (smallest_unit == "minute"sv) {
// a. Let maximum be 1440.
maximum = 1440;
// a. Let maximum be MinutesPerHour × HoursPerDay.
maximum = minutes_per_hour * hours_per_day;
}
// 10. Else if smallestUnit is "second", then
else if (smallest_unit == "second"sv) {
// a. Let maximum be 86400.
maximum = 86400;
// a. Let maximum be SecondsPerMinute × MinutesPerHour × HoursPerDay.
maximum = seconds_per_minute * minutes_per_hour * hours_per_day;
}
// 11. Else if smallestUnit is "millisecond", then
else if (smallest_unit == "millisecond"sv) {
// a. Let maximum be 8.64 × 10^7.
maximum = 86400000;
// a. Let maximum be (msPerDay).
maximum = ms_per_day;
}
// 12. Else if smallestUnit is "microsecond", then
else if (smallest_unit == "microsecond"sv) {
// a. Let maximum be 8.64 × 10^10.
maximum = 86400000000;
// a. Let maximum be 10^3 × (msPerDay).
maximum = 1000 * ms_per_day;
}
// 13. Else,
else {
// a. Assert: smallestUnit is "nanosecond".
VERIFY(smallest_unit == "nanosecond"sv);
// b. Let maximum be 8.64 × 10^13.
maximum = 86400000000000;
// b. Let maximum be nsPerDay.
maximum = ns_per_day;
}
// 14. Let roundingIncrement be ? ToTemporalRoundingIncrement(roundTo, maximum, true).

View file

@ -164,7 +164,7 @@ BigInt* system_utc_epoch_nanoseconds(GlobalObject& global_object)
auto now = Time::now_realtime().to_nanoseconds();
auto ns = Crypto::SignedBigInteger::create_from(now);
// 2. Set ns to the result of clamping ns between -8.64 × 10^21 and 8.64 × 10^21.
// 2. Set ns to the result of clamping ns between nsMinInstant and nsMaxInstant.
// NOTE: Time::to_nanoseconds() already clamps between -(2^63) and 2^63 - 1, the range of an i64,
// if an overflow occurs during seconds -> nanoseconds conversion.

View file

@ -68,9 +68,9 @@ BigInt* get_epoch_from_iso_parts(GlobalObject& global_object, i32 year, u8 month
return js_bigint(vm, Crypto::SignedBigInteger::create_from(static_cast<i64>(ms)).multiplied_by(Crypto::UnsignedBigInteger { 1'000'000 }).plus(Crypto::SignedBigInteger::create_from((i64)microsecond * 1000)).plus(Crypto::SignedBigInteger(nanosecond)));
}
// -864 * 10^19 - 864 * 10^11
// nsMinInstant - nsPerDay
auto const DATETIME_NANOSECONDS_MIN = "-8640000086400000000000"_sbigint;
// +864 * 10^19 + 864 * 10^11
// nsMaxInstant + nsPerDay
auto const DATETIME_NANOSECONDS_MAX = "8640000086400000000000"_sbigint;
// 5.5.2 ISODateTimeWithinLimits ( year, month, day, hour, minute, second, millisecond, microsecond, nanosecond ), https://tc39.es/proposal-temporal/#sec-temporal-isodatetimewithinlimits
@ -79,13 +79,13 @@ bool iso_date_time_within_limits(GlobalObject& global_object, i32 year, u8 month
// 1. Let ns be (GetEpochFromISOParts(year, month, day, hour, minute, second, millisecond, microsecond, nanosecond)).
auto ns = get_epoch_from_iso_parts(global_object, year, month, day, hour, minute, second, millisecond, microsecond, nanosecond)->big_integer();
// 2. If ns ≤ -8.64 × 10^21 - 8.64 × 10^13, then
// 2. If ns ≤ nsMinInstant - nsPerDay, then
if (ns <= DATETIME_NANOSECONDS_MIN) {
// a. Return false.
return false;
}
// 3. If ns ≥ 8.64 × 10^21 + 8.64 × 10^13, then
// 3. If ns ≥ nsMaxInstant + nsPerDay, then
if (ns >= DATETIME_NANOSECONDS_MAX) {
// a. Return false.
return false;
@ -328,9 +328,9 @@ ISODateTime round_iso_date_time(i32 year, u8 month, u8 day, u8 hour, u8 minute,
{
// 1. Assert: year, month, day, hour, minute, second, millisecond, microsecond, and nanosecond are integers.
// 2. If dayLength is not present, set dayLength to 8.64 × 10^13.
// 2. If dayLength is not present, set dayLength to nsPerDay.
if (!day_length.has_value())
day_length = 86400000000000;
day_length = ns_per_day;
// 3. Let roundedTime be ! RoundTime(hour, minute, second, millisecond, microsecond, nanosecond, increment, unit, roundingMode, dayLength).
auto rounded_time = round_time(hour, minute, second, millisecond, microsecond, nanosecond, increment, unit, rounding_mode, day_length);

View file

@ -6,6 +6,7 @@
*/
#include <LibJS/Runtime/AbstractOperations.h>
#include <LibJS/Runtime/Date.h>
#include <LibJS/Runtime/GlobalObject.h>
#include <LibJS/Runtime/Object.h>
#include <LibJS/Runtime/Temporal/AbstractOperations.h>
@ -531,9 +532,9 @@ DaysAndTime round_time(u8 hour, u8 minute, u8 second, u16 millisecond, u16 micro
// 3. If unit is "day", then
if (unit == "day"sv) {
// a. If dayLengthNs is not present, set dayLengthNs to 8.64 × 10^13.
// a. If dayLengthNs is not present, set dayLengthNs to nsPerDay.
if (!day_length_ns.has_value())
day_length_ns = 86400000000000;
day_length_ns = ns_per_day;
// b. Let quantity be (((((hour × 60 + minute) × 60 + second) × 1000 + millisecond) × 1000 + microsecond) × 1000 + nanosecond) / dayLengthNs.
quantity = (((((hour * 60 + minute) * 60 + second) * 1000 + millisecond) * 1000 + microsecond) * 1000 + nanosecond) / *day_length_ns;

View file

@ -491,8 +491,8 @@ ThrowCompletionOr<double> get_offset_nanoseconds_for(GlobalObject& global_object
// 5. Set offsetNanoseconds to (offsetNanoseconds).
auto offset_nanoseconds = offset_nanoseconds_value.as_double();
// 6. If abs(offsetNanoseconds) > 86400 × 10^9, throw a RangeError exception.
if (fabs(offset_nanoseconds) > 86400000000000.0)
// 6. If abs(offsetNanoseconds) > nsPerDay, throw a RangeError exception.
if (fabs(offset_nanoseconds) > ns_per_day)
return vm.throw_completion<RangeError>(global_object, ErrorType::TemporalInvalidOffsetNanosecondsValue);
// 7. Return offsetNanoseconds.
@ -588,11 +588,11 @@ ThrowCompletionOr<Instant*> disambiguate_possible_instants(GlobalObject& global_
// 7. Let epochNanoseconds be GetEpochFromISOParts(dateTime.[[ISOYear]], dateTime.[[ISOMonth]], dateTime.[[ISODay]], dateTime.[[ISOHour]], dateTime.[[ISOMinute]], dateTime.[[ISOSecond]], dateTime.[[ISOMillisecond]], dateTime.[[ISOMicrosecond]], dateTime.[[ISONanosecond]]).
auto* epoch_nanoseconds = get_epoch_from_iso_parts(global_object, date_time.iso_year(), date_time.iso_month(), date_time.iso_day(), date_time.iso_hour(), date_time.iso_minute(), date_time.iso_second(), date_time.iso_millisecond(), date_time.iso_microsecond(), date_time.iso_nanosecond());
// 8. Let dayBefore be ! CreateTemporalInstant(epochNanoseconds - 8.64 × 10^13).
auto* day_before = MUST(create_temporal_instant(global_object, *js_bigint(vm, epoch_nanoseconds->big_integer().minus("86400000000000"_sbigint))));
// 8. Let dayBefore be ! CreateTemporalInstant(epochNanoseconds - (nsPerDay)).
auto* day_before = MUST(create_temporal_instant(global_object, *js_bigint(vm, epoch_nanoseconds->big_integer().minus(ns_per_day_bigint))));
// 9. Let dayAfter be ! CreateTemporalInstant(epochNanoseconds + 8.64 × 10^13).
auto* day_after = MUST(create_temporal_instant(global_object, *js_bigint(vm, epoch_nanoseconds->big_integer().plus("86400000000000"_sbigint))));
// 9. Let dayAfter be ! CreateTemporalInstant(epochNanoseconds + (nsPerDay)).
auto* day_after = MUST(create_temporal_instant(global_object, *js_bigint(vm, epoch_nanoseconds->big_integer().plus(ns_per_day_bigint))));
// 10. Let offsetBefore be ? GetOffsetNanosecondsFor(timeZone, dayBefore).
auto offset_before = TRY(get_offset_nanoseconds_for(global_object, time_zone, *day_before));

View file

@ -6,6 +6,7 @@
*/
#include <LibJS/Runtime/AbstractOperations.h>
#include <LibJS/Runtime/Date.h>
#include <LibJS/Runtime/GlobalObject.h>
#include <LibJS/Runtime/Temporal/Calendar.h>
#include <LibJS/Runtime/Temporal/Duration.h>
@ -439,8 +440,8 @@ ThrowCompletionOr<NanosecondsToDaysResult> nanoseconds_to_days(GlobalObject& glo
{
auto& vm = global_object.vm();
// 1. Let dayLengthNs be 8.64 × 10^13.
auto day_length_ns = "86400000000000"_sbigint;
// 1. Let dayLengthNs be nsPerDay.
auto day_length_ns = ns_per_day_bigint;
// 2. If nanoseconds = 0, then
if (nanoseconds == "0"_bigint) {