فهرست منبع

LibJS: Implement Temporal.Instant.fromEpochNanoseconds()

Linus Groh 4 سال پیش
والد
کامیت
ca71d99c66

+ 1 - 0
Userland/Libraries/LibJS/Runtime/CommonPropertyNames.h

@@ -145,6 +145,7 @@ namespace JS {
     P(fromEntries)                           \
     P(fromEpochMicroseconds)                 \
     P(fromEpochMilliseconds)                 \
+    P(fromEpochNanoseconds)                  \
     P(fromEpochSeconds)                      \
     P(fround)                                \
     P(gc)                                    \

+ 19 - 0
Userland/Libraries/LibJS/Runtime/Temporal/InstantConstructor.cpp

@@ -30,6 +30,7 @@ void InstantConstructor::initialize(GlobalObject& global_object)
     define_native_function(vm.names.fromEpochSeconds, from_epoch_seconds, 1, attr);
     define_native_function(vm.names.fromEpochMilliseconds, from_epoch_milliseconds, 1, attr);
     define_native_function(vm.names.fromEpochMicroseconds, from_epoch_microseconds, 1, attr);
+    define_native_function(vm.names.fromEpochNanoseconds, from_epoch_nanoseconds, 1, attr);
 
     define_direct_property(vm.names.length, Value(1), Attribute::Configurable);
 }
@@ -139,4 +140,22 @@ JS_DEFINE_NATIVE_FUNCTION(InstantConstructor::from_epoch_microseconds)
     return create_temporal_instant(global_object, *epoch_nanoseconds);
 }
 
+// 8.2.6 Temporal.Instant.fromEpochNanoseconds ( epochNanoseconds )
+JS_DEFINE_NATIVE_FUNCTION(InstantConstructor::from_epoch_nanoseconds)
+{
+    // 1. Set epochNanoseconds to ? ToBigInt(epochNanoseconds).
+    auto* epoch_nanoseconds = vm.argument(0).to_bigint(global_object);
+    if (vm.exception())
+        return {};
+
+    // 2. If ! IsValidEpochNanoseconds(epochNanoseconds) is false, throw a RangeError exception.
+    if (!is_valid_epoch_nanoseconds(*epoch_nanoseconds)) {
+        vm.throw_exception<RangeError>(global_object, ErrorType::TemporalInvalidEpochNanoseconds);
+        return {};
+    }
+
+    // 3. Return ? CreateTemporalInstant(epochNanoseconds).
+    return create_temporal_instant(global_object, *epoch_nanoseconds);
+}
+
 }

+ 1 - 0
Userland/Libraries/LibJS/Runtime/Temporal/InstantConstructor.h

@@ -27,6 +27,7 @@ private:
     JS_DECLARE_NATIVE_FUNCTION(from_epoch_seconds);
     JS_DECLARE_NATIVE_FUNCTION(from_epoch_milliseconds);
     JS_DECLARE_NATIVE_FUNCTION(from_epoch_microseconds);
+    JS_DECLARE_NATIVE_FUNCTION(from_epoch_nanoseconds);
 };
 
 }

+ 51 - 0
Userland/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.fromEpochNanoseconds.js

@@ -0,0 +1,51 @@
+describe("correct behavior", () => {
+    test("length is 1", () => {
+        expect(Temporal.Instant.fromEpochNanoseconds).toHaveLength(1);
+    });
+
+    test("basic functionality", () => {
+        expect(Temporal.Instant.fromEpochNanoseconds(0n).epochNanoseconds).toBe(0n);
+        expect(Temporal.Instant.fromEpochNanoseconds(1n).epochNanoseconds).toBe(1n);
+        expect(Temporal.Instant.fromEpochNanoseconds(999_999_999n).epochNanoseconds).toBe(
+            999_999_999n
+        );
+        expect(
+            Temporal.Instant.fromEpochNanoseconds(8_640_000_000_000_000_000_000n).epochNanoseconds
+        ).toBe(8_640_000_000_000_000_000_000n);
+
+        expect(Temporal.Instant.fromEpochNanoseconds(-0n).epochNanoseconds).toBe(0n);
+        expect(Temporal.Instant.fromEpochNanoseconds(-1n).epochNanoseconds).toBe(-1n);
+        expect(Temporal.Instant.fromEpochNanoseconds(-999_999_999n).epochNanoseconds).toBe(
+            -999_999_999n
+        );
+        expect(
+            Temporal.Instant.fromEpochNanoseconds(-8_640_000_000_000_000_000_000n).epochNanoseconds
+        ).toBe(-8_640_000_000_000_000_000_000n);
+    });
+});
+
+test("errors", () => {
+    test("argument must be coercible to BigInt", () => {
+        expect(() => {
+            Temporal.Instant.fromEpochNanoseconds(123);
+        }).toThrowWithMessage(TypeError, "Cannot convert number to BigInt");
+        expect(() => {
+            Temporal.Instant.fromEpochNanoseconds("foo");
+        }).toThrowWithMessage(SyntaxError, "Invalid value for BigInt: foo");
+    });
+
+    test("out-of-range epoch nanoseconds value", () => {
+        expect(() => {
+            Temporal.Instant.fromEpochNanoseconds(8_640_000_000_000_000_000_001n);
+        }).toThrowWithMessage(
+            RangeError,
+            "Invalid epoch nanoseconds value, must be in range -86400 * 10^17 to 86400 * 10^17"
+        );
+        expect(() => {
+            Temporal.Instant.fromEpochNanoseconds(-8_640_000_000_000_000_000_001n);
+        }).toThrowWithMessage(
+            RangeError,
+            "Invalid epoch nanoseconds value, must be in range -86400 * 10^17 to 86400 * 10^17"
+        );
+    });
+});