summaryrefslogtreecommitdiff
path: root/Userland
diff options
context:
space:
mode:
authorLinus Groh <mail@linusgroh.de>2021-09-09 00:27:19 +0100
committerLinus Groh <mail@linusgroh.de>2021-09-09 08:52:48 +0100
commit6607d1dfb1fc19901ee9eb43f67345a8a64136e3 (patch)
treed5ea21d6f073125d62291c008c3d7dba18b444b7 /Userland
parent1c78ff1b9fbecf12d02f9435b6b5b963d7db808f (diff)
downloadserenity-6607d1dfb1fc19901ee9eb43f67345a8a64136e3.zip
LibJS: Implement Temporal.Instant.prototype.toZonedDateTime()
Diffstat (limited to 'Userland')
-rw-r--r--Userland/Libraries/LibJS/Runtime/CommonPropertyNames.h1
-rw-r--r--Userland/Libraries/LibJS/Runtime/Temporal/Instant.h1
-rw-r--r--Userland/Libraries/LibJS/Runtime/Temporal/InstantPrototype.cpp59
-rw-r--r--Userland/Libraries/LibJS/Runtime/Temporal/InstantPrototype.h1
-rw-r--r--Userland/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.prototype.toZonedDateTime.js54
5 files changed, 116 insertions, 0 deletions
diff --git a/Userland/Libraries/LibJS/Runtime/CommonPropertyNames.h b/Userland/Libraries/LibJS/Runtime/CommonPropertyNames.h
index 1220ec25cb..2e33ebc392 100644
--- a/Userland/Libraries/LibJS/Runtime/CommonPropertyNames.h
+++ b/Userland/Libraries/LibJS/Runtime/CommonPropertyNames.h
@@ -435,6 +435,7 @@ namespace JS {
P(toTimeString) \
P(toUpperCase) \
P(toUTCString) \
+ P(toZonedDateTime) \
P(trace) \
P(trim) \
P(trimEnd) \
diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/Instant.h b/Userland/Libraries/LibJS/Runtime/Temporal/Instant.h
index ca370d7a86..e714d6d6d7 100644
--- a/Userland/Libraries/LibJS/Runtime/Temporal/Instant.h
+++ b/Userland/Libraries/LibJS/Runtime/Temporal/Instant.h
@@ -22,6 +22,7 @@ public:
virtual ~Instant() override = default;
[[nodiscard]] BigInt const& nanoseconds() const { return m_nanoseconds; }
+ [[nodiscard]] BigInt& nanoseconds() { return m_nanoseconds; }
private:
virtual void visit_edges(Visitor&) override;
diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/InstantPrototype.cpp b/Userland/Libraries/LibJS/Runtime/Temporal/InstantPrototype.cpp
index 0874738c92..e020790323 100644
--- a/Userland/Libraries/LibJS/Runtime/Temporal/InstantPrototype.cpp
+++ b/Userland/Libraries/LibJS/Runtime/Temporal/InstantPrototype.cpp
@@ -8,10 +8,12 @@
#include <LibCrypto/BigInt/UnsignedBigInteger.h>
#include <LibJS/Runtime/GlobalObject.h>
#include <LibJS/Runtime/Temporal/AbstractOperations.h>
+#include <LibJS/Runtime/Temporal/Calendar.h>
#include <LibJS/Runtime/Temporal/Duration.h>
#include <LibJS/Runtime/Temporal/Instant.h>
#include <LibJS/Runtime/Temporal/InstantPrototype.h>
#include <LibJS/Runtime/Temporal/TimeZone.h>
+#include <LibJS/Runtime/Temporal/ZonedDateTime.h>
namespace JS::Temporal {
@@ -46,6 +48,7 @@ void InstantPrototype::initialize(GlobalObject& global_object)
define_native_function(vm.names.toLocaleString, to_locale_string, 0, attr);
define_native_function(vm.names.toJSON, to_json, 0, attr);
define_native_function(vm.names.valueOf, value_of, 0, attr);
+ define_native_function(vm.names.toZonedDateTime, to_zoned_date_time, 1, attr);
}
static Instant* typed_this(GlobalObject& global_object)
@@ -509,4 +512,60 @@ JS_DEFINE_NATIVE_FUNCTION(InstantPrototype::value_of)
return {};
}
+// 8.3.17 Temporal.Instant.prototype.toZonedDateTime ( item ), https://tc39.es/proposal-temporal/#sec-temporal.instant.prototype.tozoneddatetime
+JS_DEFINE_NATIVE_FUNCTION(InstantPrototype::to_zoned_date_time)
+{
+ auto item = vm.argument(0);
+
+ // 1. Let instant be the this value.
+ // 2. Perform ? RequireInternalSlot(instant, [[InitializedTemporalInstant]]).
+ auto* instant = typed_this(global_object);
+ if (vm.exception())
+ return {};
+
+ // 3. If Type(item) is not Object, then
+ if (!item.is_object()) {
+ // a. Throw a TypeError exception.
+ vm.throw_exception<TypeError>(global_object, ErrorType::NotAnObject, item);
+ return {};
+ }
+
+ // 4. Let calendarLike be ? Get(item, "calendar").
+ auto calendar_like = item.as_object().get(vm.names.calendar);
+ if (vm.exception())
+ return {};
+
+ // 5. If calendarLike is undefined, then
+ if (calendar_like.is_undefined()) {
+ // a. Throw a TypeError exception.
+ vm.throw_exception<TypeError>(global_object, ErrorType::TemporalMissingRequiredProperty, vm.names.calendar.as_string());
+ return {};
+ }
+
+ // 6. Let calendar be ? ToTemporalCalendar(calendarLike).
+ auto* calendar = to_temporal_calendar(global_object, calendar_like);
+ if (vm.exception())
+ return {};
+
+ // 7. Let temporalTimeZoneLike be ? Get(item, "timeZone").
+ auto temporal_time_zone_like = item.as_object().get(vm.names.timeZone);
+ if (vm.exception())
+ return {};
+
+ // 8. If temporalTimeZoneLike is undefined, then
+ if (temporal_time_zone_like.is_undefined()) {
+ // a. Throw a TypeError exception.
+ vm.throw_exception<TypeError>(global_object, ErrorType::TemporalMissingRequiredProperty, vm.names.timeZone.as_string());
+ return {};
+ }
+
+ // 9. Let timeZone be ? ToTemporalTimeZone(temporalTimeZoneLike).
+ auto* time_zone = to_temporal_time_zone(global_object, temporal_time_zone_like);
+ if (vm.exception())
+ return {};
+
+ // 10. Return ? CreateTemporalZonedDateTime(instant.[[Nanoseconds]], timeZone, calendar).
+ return create_temporal_zoned_date_time(global_object, instant->nanoseconds(), *time_zone, *calendar);
+}
+
}
diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/InstantPrototype.h b/Userland/Libraries/LibJS/Runtime/Temporal/InstantPrototype.h
index 013b40dbcf..351d665b78 100644
--- a/Userland/Libraries/LibJS/Runtime/Temporal/InstantPrototype.h
+++ b/Userland/Libraries/LibJS/Runtime/Temporal/InstantPrototype.h
@@ -33,6 +33,7 @@ private:
JS_DECLARE_NATIVE_FUNCTION(to_locale_string);
JS_DECLARE_NATIVE_FUNCTION(to_json);
JS_DECLARE_NATIVE_FUNCTION(value_of);
+ JS_DECLARE_NATIVE_FUNCTION(to_zoned_date_time);
};
}
diff --git a/Userland/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.prototype.toZonedDateTime.js b/Userland/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.prototype.toZonedDateTime.js
new file mode 100644
index 0000000000..d01ec6841a
--- /dev/null
+++ b/Userland/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.prototype.toZonedDateTime.js
@@ -0,0 +1,54 @@
+describe("correct behavior", () => {
+ test("length is 1", () => {
+ expect(Temporal.Instant.prototype.toZonedDateTime).toHaveLength(1);
+ });
+
+ test("basic functionality", () => {
+ const instant = new Temporal.Instant(1625614921123456789n);
+ const calendar = new Temporal.Calendar("iso8601");
+ const timeZone = new Temporal.TimeZone("UTC");
+ const zonedDateTime = instant.toZonedDateTime({ calendar, timeZone });
+ expect(zonedDateTime.year).toBe(2021);
+ expect(zonedDateTime.month).toBe(7);
+ expect(zonedDateTime.day).toBe(6);
+ expect(zonedDateTime.hour).toBe(23);
+ expect(zonedDateTime.minute).toBe(42);
+ expect(zonedDateTime.second).toBe(1);
+ expect(zonedDateTime.millisecond).toBe(123);
+ expect(zonedDateTime.microsecond).toBe(456);
+ expect(zonedDateTime.nanosecond).toBe(789);
+ expect(zonedDateTime.calendar).toBe(calendar);
+ expect(zonedDateTime.timeZone).toBe(timeZone);
+ });
+});
+
+describe("errors", () => {
+ test("this value must be a Temporal.Instant object", () => {
+ expect(() => {
+ Temporal.Instant.prototype.toZonedDateTime.call("foo");
+ }).toThrowWithMessage(TypeError, "Not a Temporal.Instant");
+ });
+
+ test("items argument must be an object", () => {
+ const instant = new Temporal.Instant(0n);
+ for (const value of [123, NaN, Infinity, true, false, null, undefined]) {
+ expect(() => {
+ instant.toZonedDateTime(value);
+ }).toThrowWithMessage(TypeError, `${value} is not an object`);
+ }
+ });
+
+ test("items argument must have a 'calendar' property", () => {
+ const instant = new Temporal.Instant(0n);
+ expect(() => {
+ instant.toZonedDateTime({});
+ }).toThrowWithMessage(TypeError, "Required property calendar is missing or undefined");
+ });
+
+ test("items argument must have a 'timeZone' property", () => {
+ const instant = new Temporal.Instant(0n);
+ expect(() => {
+ instant.toZonedDateTime({ calendar: {} });
+ }).toThrowWithMessage(TypeError, "Required property timeZone is missing or undefined");
+ });
+});