summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Userland/Libraries/LibJS/Runtime/CommonPropertyNames.h1
-rw-r--r--Userland/Libraries/LibJS/Runtime/Temporal/InstantConstructor.cpp19
-rw-r--r--Userland/Libraries/LibJS/Runtime/Temporal/InstantConstructor.h1
-rw-r--r--Userland/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.fromEpochNanoseconds.js51
4 files changed, 72 insertions, 0 deletions
diff --git a/Userland/Libraries/LibJS/Runtime/CommonPropertyNames.h b/Userland/Libraries/LibJS/Runtime/CommonPropertyNames.h
index aaf297bf12..8b7a96a906 100644
--- a/Userland/Libraries/LibJS/Runtime/CommonPropertyNames.h
+++ b/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) \
diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/InstantConstructor.cpp b/Userland/Libraries/LibJS/Runtime/Temporal/InstantConstructor.cpp
index c708fe876b..9472bdc00c 100644
--- a/Userland/Libraries/LibJS/Runtime/Temporal/InstantConstructor.cpp
+++ b/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);
+}
+
}
diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/InstantConstructor.h b/Userland/Libraries/LibJS/Runtime/Temporal/InstantConstructor.h
index 1e9ce0e61f..44f502d90b 100644
--- a/Userland/Libraries/LibJS/Runtime/Temporal/InstantConstructor.h
+++ b/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);
};
}
diff --git a/Userland/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.fromEpochNanoseconds.js b/Userland/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.fromEpochNanoseconds.js
new file mode 100644
index 0000000000..f2107caae8
--- /dev/null
+++ b/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"
+ );
+ });
+});