summaryrefslogtreecommitdiff
path: root/Userland/Libraries
diff options
context:
space:
mode:
authorLinus Groh <mail@linusgroh.de>2021-07-28 18:36:52 +0100
committerLinus Groh <mail@linusgroh.de>2021-07-28 21:57:30 +0100
commitae4bf8fc329bfaf23d112868167418904d97e761 (patch)
tree40658d5cd45b913ea72202156163487499ecd80f /Userland/Libraries
parent321f2c09270c7b7351170fa4884bb00521ad9459 (diff)
downloadserenity-ae4bf8fc329bfaf23d112868167418904d97e761.zip
LibJS: Start implementing Temporal.PlainTime
This commit adds the PlainTime object itself, its constructor and prototype (currently empty), and the CreateTemporalTime abstract operation.
Diffstat (limited to 'Userland/Libraries')
-rw-r--r--Userland/Libraries/LibJS/CMakeLists.txt2
-rw-r--r--Userland/Libraries/LibJS/Forward.h1
-rw-r--r--Userland/Libraries/LibJS/Runtime/ErrorTypes.h1
-rw-r--r--Userland/Libraries/LibJS/Runtime/GlobalObject.cpp2
-rw-r--r--Userland/Libraries/LibJS/Runtime/Temporal/PlainTime.cpp59
-rw-r--r--Userland/Libraries/LibJS/Runtime/Temporal/PlainTime.h33
-rw-r--r--Userland/Libraries/LibJS/Runtime/Temporal/PlainTimeConstructor.cpp126
-rw-r--r--Userland/Libraries/LibJS/Runtime/Temporal/PlainTimeConstructor.h28
-rw-r--r--Userland/Libraries/LibJS/Runtime/Temporal/PlainTimePrototype.cpp23
-rw-r--r--Userland/Libraries/LibJS/Runtime/Temporal/PlainTimePrototype.h22
-rw-r--r--Userland/Libraries/LibJS/Runtime/Temporal/Temporal.cpp2
-rw-r--r--Userland/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.js50
12 files changed, 347 insertions, 2 deletions
diff --git a/Userland/Libraries/LibJS/CMakeLists.txt b/Userland/Libraries/LibJS/CMakeLists.txt
index aa5f064083..008ee31f03 100644
--- a/Userland/Libraries/LibJS/CMakeLists.txt
+++ b/Userland/Libraries/LibJS/CMakeLists.txt
@@ -141,6 +141,8 @@ set(SOURCES
Runtime/Temporal/PlainDateTimeConstructor.cpp
Runtime/Temporal/PlainDateTimePrototype.cpp
Runtime/Temporal/PlainTime.cpp
+ Runtime/Temporal/PlainTimeConstructor.cpp
+ Runtime/Temporal/PlainTimePrototype.cpp
Runtime/Temporal/PlainYearMonth.cpp
Runtime/Temporal/Temporal.cpp
Runtime/Temporal/TimeZone.cpp
diff --git a/Userland/Libraries/LibJS/Forward.h b/Userland/Libraries/LibJS/Forward.h
index 27835581d9..4d73840641 100644
--- a/Userland/Libraries/LibJS/Forward.h
+++ b/Userland/Libraries/LibJS/Forward.h
@@ -82,6 +82,7 @@
__JS_ENUMERATE(Instant, instant, InstantPrototype, InstantConstructor) \
__JS_ENUMERATE(PlainDate, plain_date, PlainDatePrototype, PlainDateConstructor) \
__JS_ENUMERATE(PlainDateTime, plain_date_time, PlainDateTimePrototype, PlainDateTimeConstructor) \
+ __JS_ENUMERATE(PlainTime, plain_time, PlainTimePrototype, PlainTimeConstructor) \
__JS_ENUMERATE(TimeZone, time_zone, TimeZonePrototype, TimeZoneConstructor)
#define JS_ENUMERATE_ITERATOR_PROTOTYPES \
diff --git a/Userland/Libraries/LibJS/Runtime/ErrorTypes.h b/Userland/Libraries/LibJS/Runtime/ErrorTypes.h
index cbc7c0fd22..39f366061d 100644
--- a/Userland/Libraries/LibJS/Runtime/ErrorTypes.h
+++ b/Userland/Libraries/LibJS/Runtime/ErrorTypes.h
@@ -177,6 +177,7 @@
M(TemporalInvalidOffsetNanosecondsValue, "Invalid offset nanoseconds value, must be in range -86400 * 10^9 to 86400 * 10^9") \
M(TemporalInvalidPlainDate, "Invalid plain date") \
M(TemporalInvalidPlainDateTime, "Invalid plain date time") \
+ M(TemporalInvalidPlainTime, "Invalid plain time") \
M(TemporalInvalidTime, "Invalid time") \
M(TemporalInvalidTimeZoneName, "Invalid time zone name") \
M(TemporalMissingRequiredProperty, "Required property {} is missing or undefined") \
diff --git a/Userland/Libraries/LibJS/Runtime/GlobalObject.cpp b/Userland/Libraries/LibJS/Runtime/GlobalObject.cpp
index fc096f4fd7..bdaaa84c07 100644
--- a/Userland/Libraries/LibJS/Runtime/GlobalObject.cpp
+++ b/Userland/Libraries/LibJS/Runtime/GlobalObject.cpp
@@ -79,6 +79,8 @@
#include <LibJS/Runtime/Temporal/PlainDatePrototype.h>
#include <LibJS/Runtime/Temporal/PlainDateTimeConstructor.h>
#include <LibJS/Runtime/Temporal/PlainDateTimePrototype.h>
+#include <LibJS/Runtime/Temporal/PlainTimeConstructor.h>
+#include <LibJS/Runtime/Temporal/PlainTimePrototype.h>
#include <LibJS/Runtime/Temporal/Temporal.h>
#include <LibJS/Runtime/Temporal/TimeZoneConstructor.h>
#include <LibJS/Runtime/Temporal/TimeZonePrototype.h>
diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/PlainTime.cpp b/Userland/Libraries/LibJS/Runtime/Temporal/PlainTime.cpp
index 740256a6e1..e29a72f124 100644
--- a/Userland/Libraries/LibJS/Runtime/Temporal/PlainTime.cpp
+++ b/Userland/Libraries/LibJS/Runtime/Temporal/PlainTime.cpp
@@ -1,14 +1,37 @@
/*
* Copyright (c) 2021, Idan Horowitz <idan.horowitz@serenityos.org>
+ * Copyright (c) 2021, Linus Groh <linusg@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
+#include <LibJS/Runtime/AbstractOperations.h>
+#include <LibJS/Runtime/GlobalObject.h>
+#include <LibJS/Runtime/Object.h>
+#include <LibJS/Runtime/Temporal/Calendar.h>
#include <LibJS/Runtime/Temporal/PlainTime.h>
-#include <LibJS/Runtime/Value.h>
+#include <LibJS/Runtime/Temporal/PlainTimeConstructor.h>
namespace JS::Temporal {
+// 4 Temporal.PlainTime Objects, https://tc39.es/proposal-temporal/#sec-temporal-plaintime-objects
+PlainTime::PlainTime(u8 iso_hour, u8 iso_minute, u8 iso_second, u16 iso_millisecond, u16 iso_microsecond, u16 iso_nanosecond, Calendar& calendar, Object& prototype)
+ : Object(prototype)
+ , m_iso_hour(iso_hour)
+ , m_iso_minute(iso_minute)
+ , m_iso_second(iso_second)
+ , m_iso_millisecond(iso_millisecond)
+ , m_iso_microsecond(iso_microsecond)
+ , m_iso_nanosecond(iso_nanosecond)
+ , m_calendar(calendar)
+{
+}
+
+void PlainTime::visit_edges(Visitor& visitor)
+{
+ visitor.visit(&m_calendar);
+}
+
// 4.5.5 IsValidTime ( hour, minute, second, millisecond, microsecond, nanosecond ), https://tc39.es/proposal-temporal/#sec-temporal-isvalidtime
bool is_valid_time(u8 hour, u8 minute, u8 second, u16 millisecond, u16 microsecond, u16 nanosecond)
{
@@ -107,4 +130,38 @@ DaysAndTime balance_time(i64 hour, i64 minute, i64 second, i64 millisecond, i64
};
}
+// 4.5.8 CreateTemporalTime ( hour, minute, second, millisecond, microsecond, nanosecond [ , newTarget ] ), https://tc39.es/proposal-temporal/#sec-temporal-createtemporaltime
+PlainTime* create_temporal_time(GlobalObject& global_object, u8 hour, u8 minute, u8 second, u16 millisecond, u16 microsecond, u16 nanosecond, FunctionObject* new_target)
+{
+ auto& vm = global_object.vm();
+
+ // 1. Assert: hour, minute, second, millisecond, microsecond and nanosecond are integers.
+
+ // 2. If ! IsValidTime(hour, minute, second, millisecond, microsecond, nanosecond) is false, throw a RangeError exception.
+ if (!is_valid_time(hour, minute, second, millisecond, microsecond, nanosecond)) {
+ vm.throw_exception<RangeError>(global_object, ErrorType::TemporalInvalidPlainTime);
+ return {};
+ }
+
+ // 3. If newTarget is not present, set it to %Temporal.PlainTime%.
+ if (!new_target)
+ new_target = global_object.temporal_plain_time_constructor();
+
+ // 4. Let object be ? OrdinaryCreateFromConstructor(newTarget, "%Temporal.PlainTime.prototype%", ยซ [[InitializedTemporalTime]], [[ISOHour]], [[ISOMinute]], [[ISOSecond]], [[ISOMillisecond]], [[ISOMicrosecond]], [[ISONanosecond]], [[Calendar]] ยป).
+ // 5. Set object.[[ISOHour]] to hour.
+ // 6. Set object.[[ISOMinute]] to minute.
+ // 7. Set object.[[ISOSecond]] to second.
+ // 8. Set object.[[ISOMillisecond]] to millisecond.
+ // 9. Set object.[[ISOMicrosecond]] to microsecond.
+ // 10. Set object.[[ISONanosecond]] to nanosecond.
+ // 11. Set object.[[Calendar]] to ? GetISO8601Calendar().
+ // NOTE: No exception check needed for GetISO8601Calendar, see https://github.com/tc39/proposal-temporal/pull/1643
+ auto* object = ordinary_create_from_constructor<PlainTime>(global_object, *new_target, &GlobalObject::temporal_plain_time_prototype, hour, minute, second, millisecond, microsecond, nanosecond, *get_iso8601_calendar(global_object));
+ if (vm.exception())
+ return {};
+
+ // 12. Return object.
+ return object;
+}
+
}
diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/PlainTime.h b/Userland/Libraries/LibJS/Runtime/Temporal/PlainTime.h
index 1c85fa946f..fabf4c10df 100644
--- a/Userland/Libraries/LibJS/Runtime/Temporal/PlainTime.h
+++ b/Userland/Libraries/LibJS/Runtime/Temporal/PlainTime.h
@@ -1,15 +1,45 @@
/*
* Copyright (c) 2021, Idan Horowitz <idan.horowitz@serenityos.org>
+ * Copyright (c) 2021, Linus Groh <linusg@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
-#include <LibJS/Runtime/Value.h>
+#include <LibJS/Runtime/Object.h>
namespace JS::Temporal {
+class PlainTime final : public Object {
+ JS_OBJECT(PlainDateTime, Object);
+
+public:
+ PlainTime(u8 iso_hour, u8 iso_minute, u8 iso_second, u16 iso_millisecond, u16 iso_microsecond, u16 iso_nanosecond, Calendar& calendar, Object& prototype);
+ virtual ~PlainTime() override = default;
+
+ [[nodiscard]] u8 iso_hour() const { return m_iso_hour; }
+ [[nodiscard]] u8 iso_minute() const { return m_iso_minute; }
+ [[nodiscard]] u8 iso_second() const { return m_iso_second; }
+ [[nodiscard]] u16 iso_millisecond() const { return m_iso_millisecond; }
+ [[nodiscard]] u16 iso_microsecond() const { return m_iso_microsecond; }
+ [[nodiscard]] u16 iso_nanosecond() const { return m_iso_nanosecond; }
+ [[nodiscard]] Calendar const& calendar() const { return m_calendar; }
+ [[nodiscard]] Calendar& calendar() { return m_calendar; }
+
+private:
+ virtual void visit_edges(Visitor&) override;
+
+ // 4.4 Properties of Temporal.PlainTime Instances, https://tc39.es/proposal-temporal/#sec-properties-of-temporal-plaintime-instances
+ u8 m_iso_hour { 0 }; // [[ISOHour]]
+ u8 m_iso_minute { 0 }; // [[ISOMinute]]
+ u8 m_iso_second { 0 }; // [[ISOSecond]]
+ u16 m_iso_millisecond { 0 }; // [[ISOMillisecond]]
+ u16 m_iso_microsecond { 0 }; // [[ISOMicrosecond]]
+ u16 m_iso_nanosecond { 0 }; // [[ISONanosecond]]
+ Calendar& m_calendar; // [[Calendar]] (always the built-in ISO 8601 calendar)
+};
+
struct DaysAndTime {
i32 days;
u8 hour;
@@ -22,5 +52,6 @@ struct DaysAndTime {
bool is_valid_time(u8 hour, u8 minute, u8 second, u16 millisecond, u16 microsecond, u16 nanosecond);
DaysAndTime balance_time(i64 hour, i64 minute, i64 second, i64 millisecond, i64 microsecond, i64 nanosecond);
+PlainTime* create_temporal_time(GlobalObject&, u8 hour, u8 minute, u8 second, u16 millisecond, u16 microsecond, u16 nanosecond, FunctionObject* new_target = nullptr);
}
diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/PlainTimeConstructor.cpp b/Userland/Libraries/LibJS/Runtime/Temporal/PlainTimeConstructor.cpp
new file mode 100644
index 0000000000..ba1c62aa74
--- /dev/null
+++ b/Userland/Libraries/LibJS/Runtime/Temporal/PlainTimeConstructor.cpp
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2021, Linus Groh <linusg@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <LibJS/Runtime/GlobalObject.h>
+#include <LibJS/Runtime/Temporal/PlainTime.h>
+#include <LibJS/Runtime/Temporal/PlainTimeConstructor.h>
+
+namespace JS::Temporal {
+
+// 4.1 The Temporal.PlainTime Constructor, https://tc39.es/proposal-temporal/#sec-temporal-plaintime-constructor
+PlainTimeConstructor::PlainTimeConstructor(GlobalObject& global_object)
+ : NativeFunction(vm().names.PlainTime.as_string(), *global_object.function_prototype())
+{
+}
+
+void PlainTimeConstructor::initialize(GlobalObject& global_object)
+{
+ NativeFunction::initialize(global_object);
+
+ auto& vm = this->vm();
+
+ // 4.2.1 Temporal.PlainTime.prototype, https://tc39.es/proposal-temporal/#sec-temporal-plaintime-prototype
+ define_direct_property(vm.names.prototype, global_object.temporal_plain_time_prototype(), 0);
+
+ define_direct_property(vm.names.length, Value(0), Attribute::Configurable);
+}
+
+// 4.1.1 Temporal.PlainTime ( [ hour [ , minute [ , second [ , millisecond [ , microsecond [ , nanosecond ] ] ] ] ] ] ), https://tc39.es/proposal-temporal/#sec-temporal.plaintime
+Value PlainTimeConstructor::call()
+{
+ auto& vm = this->vm();
+
+ // 1. If NewTarget is undefined, throw a TypeError exception.
+ vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Temporal.PlainTime");
+ return {};
+}
+
+// 4.1.1 Temporal.PlainTime ( [ hour [ , minute [ , second [ , millisecond [ , microsecond [ , nanosecond ] ] ] ] ] ] ), https://tc39.es/proposal-temporal/#sec-temporal.plaintime
+Value PlainTimeConstructor::construct(FunctionObject& new_target)
+{
+ auto& vm = this->vm();
+ auto& global_object = this->global_object();
+
+ // 2. Let hour be ? ToIntegerOrInfinity(hour).
+ auto hour = vm.argument(0).to_integer_or_infinity(global_object);
+ if (vm.exception())
+ return {};
+
+ // 3. If hour is +โˆž or -โˆž, throw a RangeError exception.
+ if (Value(hour).is_infinity()) {
+ vm.throw_exception<RangeError>(global_object, ErrorType::TemporalInvalidPlainTime);
+ return {};
+ }
+
+ // 4. Let minute be ? ToIntegerOrInfinity(hour).
+ auto minute = vm.argument(1).to_integer_or_infinity(global_object);
+ if (vm.exception())
+ return {};
+
+ // 5. If minute is +โˆž or -โˆž, throw a RangeError exception.
+ if (Value(minute).is_infinity()) {
+ vm.throw_exception<RangeError>(global_object, ErrorType::TemporalInvalidPlainTime);
+ return {};
+ }
+
+ // 6. Let second be ? ToIntegerOrInfinity(hour).
+ auto second = vm.argument(2).to_integer_or_infinity(global_object);
+ if (vm.exception())
+ return {};
+
+ // 7. If second is +โˆž or -โˆž, throw a RangeError exception.
+ if (Value(second).is_infinity()) {
+ vm.throw_exception<RangeError>(global_object, ErrorType::TemporalInvalidPlainTime);
+ return {};
+ }
+
+ // 8. Let millisecond be ? ToIntegerOrInfinity(hour).
+ auto millisecond = vm.argument(3).to_integer_or_infinity(global_object);
+ if (vm.exception())
+ return {};
+
+ // 9. If millisecond is +โˆž or -โˆž, throw a RangeError exception.
+ if (Value(millisecond).is_infinity()) {
+ vm.throw_exception<RangeError>(global_object, ErrorType::TemporalInvalidPlainTime);
+ return {};
+ }
+
+ // 10. Let microsecond be ? ToIntegerOrInfinity(hour).
+ auto microsecond = vm.argument(4).to_integer_or_infinity(global_object);
+ if (vm.exception())
+ return {};
+
+ // 11. If microsecond is +โˆž or -โˆž, throw a RangeError exception.
+ if (Value(microsecond).is_infinity()) {
+ vm.throw_exception<RangeError>(global_object, ErrorType::TemporalInvalidPlainTime);
+ return {};
+ }
+
+ // 12. Let nanosecond be ? ToIntegerOrInfinity(hour).
+ auto nanosecond = vm.argument(5).to_integer_or_infinity(global_object);
+ if (vm.exception())
+ return {};
+
+ // 13. If nanosecond is +โˆž or -โˆž, throw a RangeError exception.
+ if (Value(nanosecond).is_infinity()) {
+ vm.throw_exception<RangeError>(global_object, ErrorType::TemporalInvalidPlainTime);
+ return {};
+ }
+
+ // IMPLEMENTATION DEFINED: This is an optimization that allows us to treat these doubles as normal integers from this point onwards.
+ // This does not change the exposed behaviour as the call to CreateTemporalTime will immediately check that these values are valid
+ // ISO values (for hours: 0 - 23, for minutes and seconds: 0 - 59, milliseconds, microseconds, and nanoseconds: 0 - 999) all of which
+ // are subsets of this check.
+ if (!AK::is_within_range<u8>(hour) || !AK::is_within_range<u8>(minute) || !AK::is_within_range<u8>(second) || !AK::is_within_range<u16>(millisecond) || !AK::is_within_range<u16>(microsecond) || !AK::is_within_range<u16>(nanosecond)) {
+ vm.throw_exception<RangeError>(global_object, ErrorType::TemporalInvalidPlainTime);
+ return {};
+ }
+
+ // 14. Return ? CreateTemporalTime(hour, minute, second, millisecond, microsecond, nanosecond, NewTarget).
+ return create_temporal_time(global_object, hour, minute, second, millisecond, microsecond, nanosecond, &new_target);
+}
+
+}
diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/PlainTimeConstructor.h b/Userland/Libraries/LibJS/Runtime/Temporal/PlainTimeConstructor.h
new file mode 100644
index 0000000000..2ecd73e123
--- /dev/null
+++ b/Userland/Libraries/LibJS/Runtime/Temporal/PlainTimeConstructor.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2021, Linus Groh <linusg@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <LibJS/Runtime/NativeFunction.h>
+
+namespace JS::Temporal {
+
+class PlainTimeConstructor final : public NativeFunction {
+ JS_OBJECT(PlainTimeConstructor, NativeFunction);
+
+public:
+ explicit PlainTimeConstructor(GlobalObject&);
+ virtual void initialize(GlobalObject&) override;
+ virtual ~PlainTimeConstructor() override = default;
+
+ virtual Value call() override;
+ virtual Value construct(FunctionObject& new_target) override;
+
+private:
+ virtual bool has_constructor() const override { return true; }
+};
+
+}
diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/PlainTimePrototype.cpp b/Userland/Libraries/LibJS/Runtime/Temporal/PlainTimePrototype.cpp
new file mode 100644
index 0000000000..f12b3a6993
--- /dev/null
+++ b/Userland/Libraries/LibJS/Runtime/Temporal/PlainTimePrototype.cpp
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2021, Linus Groh <linusg@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <LibJS/Runtime/GlobalObject.h>
+#include <LibJS/Runtime/Temporal/PlainTimePrototype.h>
+
+namespace JS::Temporal {
+
+// 4.3 Properties of the Temporal.PlainTime Prototype Object, https://tc39.es/proposal-temporal/#sec-properties-of-the-temporal-plaintime-prototype-object
+PlainTimePrototype::PlainTimePrototype(GlobalObject& global_object)
+ : Object(*global_object.object_prototype())
+{
+}
+
+void PlainTimePrototype::initialize(GlobalObject& global_object)
+{
+ Object::initialize(global_object);
+}
+
+}
diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/PlainTimePrototype.h b/Userland/Libraries/LibJS/Runtime/Temporal/PlainTimePrototype.h
new file mode 100644
index 0000000000..61fc38fc99
--- /dev/null
+++ b/Userland/Libraries/LibJS/Runtime/Temporal/PlainTimePrototype.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2021, Linus Groh <linusg@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <LibJS/Runtime/Object.h>
+
+namespace JS::Temporal {
+
+class PlainTimePrototype final : public Object {
+ JS_OBJECT(PlainTimePrototype, Object);
+
+public:
+ explicit PlainTimePrototype(GlobalObject&);
+ virtual void initialize(GlobalObject&) override;
+ virtual ~PlainTimePrototype() override = default;
+};
+
+}
diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/Temporal.cpp b/Userland/Libraries/LibJS/Runtime/Temporal/Temporal.cpp
index 1a8b5b16db..1cb1e0dcc7 100644
--- a/Userland/Libraries/LibJS/Runtime/Temporal/Temporal.cpp
+++ b/Userland/Libraries/LibJS/Runtime/Temporal/Temporal.cpp
@@ -11,6 +11,7 @@
#include <LibJS/Runtime/Temporal/Now.h>
#include <LibJS/Runtime/Temporal/PlainDateConstructor.h>
#include <LibJS/Runtime/Temporal/PlainDateTimeConstructor.h>
+#include <LibJS/Runtime/Temporal/PlainTimeConstructor.h>
#include <LibJS/Runtime/Temporal/Temporal.h>
#include <LibJS/Runtime/Temporal/TimeZoneConstructor.h>
@@ -38,6 +39,7 @@ void Temporal::initialize(GlobalObject& global_object)
define_direct_property(vm.names.Instant, global_object.temporal_instant_constructor(), attr);
define_direct_property(vm.names.PlainDate, global_object.temporal_plain_date_constructor(), attr);
define_direct_property(vm.names.PlainDateTime, global_object.temporal_plain_date_time_constructor(), attr);
+ define_direct_property(vm.names.PlainTime, global_object.temporal_plain_time_constructor(), attr);
define_direct_property(vm.names.TimeZone, global_object.temporal_time_zone_constructor(), attr);
}
diff --git a/Userland/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.js b/Userland/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.js
new file mode 100644
index 0000000000..bc5ccf9922
--- /dev/null
+++ b/Userland/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.js
@@ -0,0 +1,50 @@
+describe("errors", () => {
+ test("called without new", () => {
+ expect(() => {
+ Temporal.PlainTime();
+ }).toThrowWithMessage(
+ TypeError,
+ "Temporal.PlainTime constructor must be called with 'new'"
+ );
+ });
+
+ test("cannot pass Infinity", () => {
+ for (let i = 0; i < 6; ++i) {
+ const args = Array(6).fill(0);
+
+ args[i] = Infinity;
+ expect(() => {
+ new Temporal.PlainTime(...args);
+ }).toThrowWithMessage(RangeError, "Invalid plain time");
+
+ args[i] = -Infinity;
+ expect(() => {
+ new Temporal.PlainTime(...args);
+ }).toThrowWithMessage(RangeError, "Invalid plain time");
+ }
+ });
+
+ test("cannot pass invalid ISO time", () => {
+ const badValues = [24, 60, 60, 1000, 1000, 1000];
+ for (let i = 0; i < 6; ++i) {
+ const args = [0, 0, 0, 0, 0, 0];
+ args[i] = badValues[i];
+ expect(() => {
+ new Temporal.PlainTime(...args);
+ }).toThrowWithMessage(RangeError, "Invalid plain time");
+ }
+ });
+});
+
+describe("normal behavior", () => {
+ test("length is 0", () => {
+ expect(Temporal.PlainTime).toHaveLength(0);
+ });
+
+ test("basic functionality", () => {
+ const plainTime = new Temporal.PlainTime(19, 46, 32, 123, 456, 789);
+ expect(typeof plainTime).toBe("object");
+ expect(plainTime).toBeInstanceOf(Temporal.PlainTime);
+ expect(Object.getPrototypeOf(plainTime)).toBe(Temporal.PlainTime.prototype);
+ });
+});