浏览代码

LibJS: Replace magic nanosecond numbers with constants

This is an editorial change in the Temporal spec.

See: https://github.com/tc39/proposal-temporal/commit/3fdbfda
Linus Groh 3 年之前
父节点
当前提交
c6f7214a60

+ 3 - 0
Userland/Libraries/LibJS/Runtime/Date.h

@@ -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);

+ 3 - 3
Userland/Libraries/LibJS/Runtime/Temporal/Instant.cpp

@@ -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);
     }

+ 7 - 4
Userland/Libraries/LibJS/Runtime/Temporal/Instant.h

@@ -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);

+ 13 - 12
Userland/Libraries/LibJS/Runtime/Temporal/InstantPrototype.cpp

@@ -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).

+ 1 - 1
Userland/Libraries/LibJS/Runtime/Temporal/Now.cpp

@@ -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.
 

+ 6 - 6
Userland/Libraries/LibJS/Runtime/Temporal/PlainDateTime.cpp

@@ -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);

+ 3 - 2
Userland/Libraries/LibJS/Runtime/Temporal/PlainTime.cpp

@@ -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;

+ 6 - 6
Userland/Libraries/LibJS/Runtime/Temporal/TimeZone.cpp

@@ -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));

+ 3 - 2
Userland/Libraries/LibJS/Runtime/Temporal/ZonedDateTime.cpp

@@ -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) {