summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibJS
diff options
context:
space:
mode:
authorLuke Wilde <lukew@serenityos.org>2021-09-08 18:59:09 +0100
committerLinus Groh <mail@linusgroh.de>2021-09-08 19:57:29 +0100
commitd943b8f1005e4446ffe9bfd84dbd1014025f35d2 (patch)
treea3e262d580f5afd1a4ede7a0527eaa5c7e4d1012 /Userland/Libraries/LibJS
parentb8d683c5fb57fac120405d31792a363b6f4e0d85 (diff)
downloadserenity-d943b8f1005e4446ffe9bfd84dbd1014025f35d2.zip
LibJS: Implement Temporal.PlainTime.prototype.with
Ticks off one box in #8982 and fixes one test262 case.
Diffstat (limited to 'Userland/Libraries/LibJS')
-rw-r--r--Userland/Libraries/LibJS/Runtime/ErrorTypes.h2
-rw-r--r--Userland/Libraries/LibJS/Runtime/Temporal/AbstractOperations.cpp17
-rw-r--r--Userland/Libraries/LibJS/Runtime/Temporal/AbstractOperations.h1
-rw-r--r--Userland/Libraries/LibJS/Runtime/Temporal/PlainTime.cpp48
-rw-r--r--Userland/Libraries/LibJS/Runtime/Temporal/PlainTime.h10
-rw-r--r--Userland/Libraries/LibJS/Runtime/Temporal/PlainTimePrototype.cpp110
-rw-r--r--Userland/Libraries/LibJS/Runtime/Temporal/PlainTimePrototype.h1
-rw-r--r--Userland/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.prototype.with.js210
8 files changed, 399 insertions, 0 deletions
diff --git a/Userland/Libraries/LibJS/Runtime/ErrorTypes.h b/Userland/Libraries/LibJS/Runtime/ErrorTypes.h
index dbd64f2660..2a7a2a37eb 100644
--- a/Userland/Libraries/LibJS/Runtime/ErrorTypes.h
+++ b/Userland/Libraries/LibJS/Runtime/ErrorTypes.h
@@ -191,12 +191,14 @@
M(TemporalInvalidPlainDateTime, "Invalid plain date time") \
M(TemporalInvalidPlainMonthDay, "Invalid plain month day") \
M(TemporalInvalidPlainTime, "Invalid plain time") \
+ M(TemporalInvalidPlainTimeLikeObject, "Invalid plain time-like object") \
M(TemporalInvalidPlainYearMonth, "Invalid plain year month") \
M(TemporalInvalidTime, "Invalid time") \
M(TemporalInvalidTimeZoneName, "Invalid time zone name") \
M(TemporalInvalidUnitRange, "Invalid unit range, {} is larger than {}") \
M(TemporalMissingOptionsObject, "Required options object is missing or undefined") \
M(TemporalMissingRequiredProperty, "Required property {} is missing or undefined") \
+ M(TemporalPlainTimeWithArgumentMustNotHave, "Argument must not have a defined {} property") \
M(TemporalPropertyMustBeFinite, "Property must not be Infinity") \
M(TemporalPropertyMustBePositiveInteger, "Property must be a positive integer") \
M(ThisHasNotBeenInitialized, "|this| has not been initialized") \
diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/AbstractOperations.cpp b/Userland/Libraries/LibJS/Runtime/Temporal/AbstractOperations.cpp
index 045fa75282..f314bf0a21 100644
--- a/Userland/Libraries/LibJS/Runtime/Temporal/AbstractOperations.cpp
+++ b/Userland/Libraries/LibJS/Runtime/Temporal/AbstractOperations.cpp
@@ -7,6 +7,7 @@
#include <AK/CharacterTypes.h>
#include <AK/DateTimeLexer.h>
+#include <AK/TypeCasts.h>
#include <AK/Variant.h>
#include <LibJS/Runtime/IteratorOperations.h>
#include <LibJS/Runtime/PropertyName.h>
@@ -14,8 +15,10 @@
#include <LibJS/Runtime/Temporal/Calendar.h>
#include <LibJS/Runtime/Temporal/Duration.h>
#include <LibJS/Runtime/Temporal/PlainDate.h>
+#include <LibJS/Runtime/Temporal/PlainDateTime.h>
#include <LibJS/Runtime/Temporal/PlainTime.h>
#include <LibJS/Runtime/Temporal/TimeZone.h>
+#include <LibJS/Runtime/Temporal/ZonedDateTime.h>
namespace JS::Temporal {
@@ -597,6 +600,20 @@ Optional<u16> maximum_temporal_duration_rounding_increment(StringView unit)
return 1000;
}
+// 13.26 RejectTemporalCalendarType ( object ), https://tc39.es/proposal-temporal/#sec-temporal-rejecttemporalcalendartype
+void reject_temporal_calendar_type(GlobalObject& global_object, Object& object)
+{
+ auto& vm = global_object.vm();
+
+ // 1. Assert: Type(object) is Object.
+
+ // 2. If object has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalTime]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then
+ if (is<PlainDate>(object) || is<PlainDateTime>(object) || is<PlainMonthDay>(object) || is<PlainTime>(object) || is<PlainYearMonth>(object) || is<ZonedDateTime>(object)) {
+ // a. Throw a TypeError exception.
+ vm.throw_exception<TypeError>(global_object, ErrorType::TemporalPlainTimeWithArgumentMustNotHave, "calendar or timeZone");
+ }
+}
+
// 13.27 FormatSecondsStringPart ( second, millisecond, microsecond, nanosecond, precision ), https://tc39.es/proposal-temporal/#sec-temporal-formatsecondsstringpart
String format_seconds_string_part(u8 second, u16 millisecond, u16 microsecond, u16 nanosecond, Variant<String, u8> const& precision)
{
diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/AbstractOperations.h b/Userland/Libraries/LibJS/Runtime/Temporal/AbstractOperations.h
index 0245accce7..9581c96394 100644
--- a/Userland/Libraries/LibJS/Runtime/Temporal/AbstractOperations.h
+++ b/Userland/Libraries/LibJS/Runtime/Temporal/AbstractOperations.h
@@ -91,6 +91,7 @@ Optional<String> to_smallest_temporal_unit(GlobalObject&, Object& normalized_opt
void validate_temporal_unit_range(GlobalObject&, String const& largest_unit, String const& smallest_unit);
String larger_of_two_temporal_units(StringView, StringView);
Optional<u16> maximum_temporal_duration_rounding_increment(StringView unit);
+void reject_temporal_calendar_type(GlobalObject&, Object&);
String format_seconds_string_part(u8 second, u16 millisecond, u16 microsecond, u16 nanosecond, Variant<String, u8> const& precision);
double constrain_to_range(double x, double minimum, double maximum);
BigInt* round_number_to_increment(GlobalObject&, BigInt const&, u64 increment, StringView rounding_mode);
diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/PlainTime.cpp b/Userland/Libraries/LibJS/Runtime/Temporal/PlainTime.cpp
index e11e714d3a..866b96c185 100644
--- a/Userland/Libraries/LibJS/Runtime/Temporal/PlainTime.cpp
+++ b/Userland/Libraries/LibJS/Runtime/Temporal/PlainTime.cpp
@@ -134,6 +134,54 @@ PlainTime* to_temporal_time(GlobalObject& global_object, Value item, Optional<St
return create_temporal_time(global_object, result->hour, result->minute, result->second, result->millisecond, result->microsecond, result->nanosecond);
}
+// 4.5.3 ToPartialTime ( temporalTimeLike ), https://tc39.es/proposal-temporal/#sec-temporal-topartialtime
+Optional<PartialUnregulatedTemporalTime> to_partial_time(GlobalObject& global_object, Object& temporal_time_like)
+{
+ auto& vm = global_object.vm();
+
+ // 1. Assert: Type(temporalTimeLike) is Object.
+
+ // 2. Let result be the Record { [[Hour]]: undefined, [[Minute]]: undefined, [[Second]]: undefined, [[Millisecond]]: undefined, [[Microsecond]]: undefined, [[Nanosecond]]: undefined }.
+ auto result = PartialUnregulatedTemporalTime {};
+
+ // 3. Let any be false.
+ bool any = false;
+
+ // 4. For each row of Table 3, except the header row, in table order, do
+ for (auto& [internal_slot, property] : temporal_time_like_properties<PartialUnregulatedTemporalTime, Optional<double>>(vm)) {
+ // a. Let property be the Property value of the current row.
+
+ // b. Let value be ? Get(temporalTimeLike, property).
+ auto value = temporal_time_like.get(property);
+ if (vm.exception())
+ return {};
+
+ // c. If value is not undefined, then
+ if (!value.is_undefined()) {
+ // i. Set any to true.
+ any = true;
+
+ // ii. Set value to ? ToIntegerThrowOnInfinity(value).
+ auto value_number = to_integer_throw_on_infinity(global_object, value, ErrorType::TemporalPropertyMustBeFinite);
+ if (vm.exception())
+ return {};
+
+ // iii. Set result's internal slot whose name is the Internal Slot value of the current row to value.
+ result.*internal_slot = value_number;
+ }
+ }
+
+ // 5. If any is false, then
+ if (!any) {
+ // a. Throw a TypeError exception.
+ vm.throw_exception<TypeError>(global_object, ErrorType::TemporalInvalidPlainTimeLikeObject);
+ return {};
+ }
+
+ // 6. Return result.
+ return result;
+}
+
// 4.5.4 RegulateTime ( hour, minute, second, millisecond, microsecond, nanosecond, overflow ), https://tc39.es/proposal-temporal/#sec-temporal-regulatetime
Optional<TemporalTime> regulate_time(GlobalObject& global_object, double hour, double minute, double second, double millisecond, double microsecond, double nanosecond, StringView overflow)
{
diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/PlainTime.h b/Userland/Libraries/LibJS/Runtime/Temporal/PlainTime.h
index 80992540f0..aa7b78ff6b 100644
--- a/Userland/Libraries/LibJS/Runtime/Temporal/PlainTime.h
+++ b/Userland/Libraries/LibJS/Runtime/Temporal/PlainTime.h
@@ -60,6 +60,15 @@ struct UnregulatedTemporalTime {
double nanosecond;
};
+struct PartialUnregulatedTemporalTime {
+ Optional<double> hour;
+ Optional<double> minute;
+ Optional<double> second;
+ Optional<double> millisecond;
+ Optional<double> microsecond;
+ Optional<double> nanosecond;
+};
+
// Table 3: Properties of a TemporalTimeLike, https://tc39.es/proposal-temporal/#table-temporal-temporaltimelike-properties
template<typename StructT, typename ValueT>
@@ -82,6 +91,7 @@ auto temporal_time_like_properties = [](VM& vm) {
};
PlainTime* to_temporal_time(GlobalObject&, Value item, Optional<StringView> overflow = {});
+Optional<PartialUnregulatedTemporalTime> to_partial_time(GlobalObject&, Object& temporal_time_like);
Optional<TemporalTime> regulate_time(GlobalObject&, double hour, double minute, double second, double millisecond, double microsecond, double nanosecond, StringView overflow);
bool is_valid_time(double hour, double minute, double second, double millisecond, double microsecond, double nanosecond);
DaysAndTime balance_time(i64 hour, i64 minute, i64 second, i64 millisecond, i64 microsecond, i64 nanosecond);
diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/PlainTimePrototype.cpp b/Userland/Libraries/LibJS/Runtime/Temporal/PlainTimePrototype.cpp
index 1eb60b0275..c45711b311 100644
--- a/Userland/Libraries/LibJS/Runtime/Temporal/PlainTimePrototype.cpp
+++ b/Userland/Libraries/LibJS/Runtime/Temporal/PlainTimePrototype.cpp
@@ -38,6 +38,7 @@ void PlainTimePrototype::initialize(GlobalObject& global_object)
define_native_accessor(vm.names.nanosecond, nanosecond_getter, {}, Attribute::Configurable);
u8 attr = Attribute::Writable | Attribute::Configurable;
+ define_native_function(vm.names.with, with, 1, attr);
define_native_function(vm.names.equals, equals, 1, attr);
define_native_function(vm.names.toPlainDateTime, to_plain_date_time, 1, attr);
define_native_function(vm.names.getISOFields, get_iso_fields, 0, attr);
@@ -148,6 +149,115 @@ JS_DEFINE_NATIVE_FUNCTION(PlainTimePrototype::nanosecond_getter)
return Value(temporal_time->iso_nanosecond());
}
+// 4.3.12 Temporal.PlainTime.prototype.with ( temporalTimeLike [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal.plaintime.prototype.with
+JS_DEFINE_NATIVE_FUNCTION(PlainTimePrototype::with)
+{
+ // 1. Let temporalTime be the this value.
+ // 2. Perform ? RequireInternalSlot(temporalTime, [[InitializedTemporalTime]]).
+ auto* temporal_time = typed_this(global_object);
+ if (vm.exception())
+ return {};
+
+ auto temporal_time_like_argument = vm.argument(0);
+
+ // 3. If Type(temporalTimeLike) is not Object, then
+ if (!temporal_time_like_argument.is_object()) {
+ // a. Throw a TypeError exception.
+ vm.throw_exception<TypeError>(global_object, ErrorType::NotAnObject, temporal_time_like_argument.to_string_without_side_effects());
+ return {};
+ }
+
+ auto& temporal_time_like = temporal_time_like_argument.as_object();
+
+ // 4. Perform ? RejectTemporalCalendarType(temporalTimeLike).
+ reject_temporal_calendar_type(global_object, temporal_time_like);
+ if (vm.exception())
+ return {};
+
+ // 5. Let calendarProperty be ? Get(temporalTimeLike, "calendar").
+ auto calendar_property = temporal_time_like.get(vm.names.calendar);
+ if (vm.exception())
+ return {};
+
+ // 6. If calendarProperty is not undefined, then
+ if (!calendar_property.is_undefined()) {
+ // a. Throw a TypeError exception.
+ vm.throw_exception<TypeError>(global_object, ErrorType::TemporalPlainTimeWithArgumentMustNotHave, "calendar");
+ return {};
+ }
+
+ // 7. Let timeZoneProperty be ? Get(temporalTimeLike, "timeZone").
+ auto time_zone_property = temporal_time_like.get(vm.names.timeZone);
+ if (vm.exception())
+ return {};
+
+ // 8. If timeZoneProperty is not undefined, then
+ if (!time_zone_property.is_undefined()) {
+ // a. Throw a TypeError exception.
+ vm.throw_exception<TypeError>(global_object, ErrorType::TemporalPlainTimeWithArgumentMustNotHave, "timeZone");
+ return {};
+ }
+
+ // 9. Let partialTime be ? ToPartialTime(temporalTimeLike).
+ auto partial_time = to_partial_time(global_object, temporal_time_like);
+ if (vm.exception())
+ return {};
+
+ // 10. Set options to ? GetOptionsObject(options).
+ auto* options = get_options_object(global_object, vm.argument(1));
+ if (vm.exception())
+ return {};
+
+ // 11. Let overflow be ? ToTemporalOverflow(options).
+ auto overflow = to_temporal_overflow(global_object, *options);
+ if (vm.exception())
+ return {};
+
+ // 12. If partialTime.[[Hour]] is not undefined, then
+ // a. Let hour be partialTime.[[Hour]].
+ // 13. Else,
+ // a. Let hour be temporalTime.[[ISOHour]].
+ auto hour = partial_time->hour.value_or(temporal_time->iso_hour());
+
+ // 14. If partialTime.[[Minute]] is not undefined, then
+ // a. Let minute be partialTime.[[Minute]].
+ // 15. Else,
+ // a. Let minute be temporalTime.[[ISOMinute]].
+ auto minute = partial_time->minute.value_or(temporal_time->iso_minute());
+
+ // 16. If partialTime.[[Second]] is not undefined, then
+ // a. Let second be partialTime.[[Second]].
+ // 17. Else,
+ // a. Let second be temporalTime.[[ISOSecond]].
+ auto second = partial_time->second.value_or(temporal_time->iso_second());
+
+ // 18. If partialTime.[[Millisecond]] is not undefined, then
+ // a. Let millisecond be partialTime.[[Millisecond]].
+ // 19. Else,
+ // a. Let millisecond be temporalTime.[[ISOMillisecond]].
+ auto millisecond = partial_time->millisecond.value_or(temporal_time->iso_millisecond());
+
+ // 20. If partialTime.[[Microsecond]] is not undefined, then
+ // a. Let microsecond be partialTime.[[Microsecond]].
+ // 21. Else,
+ // a. Let microsecond be temporalTime.[[ISOMicrosecond]].
+ auto microsecond = partial_time->microsecond.value_or(temporal_time->iso_microsecond());
+
+ // 22. If partialTime.[[Nanosecond]] is not undefined, then
+ // a. Let nanosecond be partialTime.[[Nanosecond]].
+ // 23. Else,
+ // a. Let nanosecond be temporalTime.[[ISONanosecond]].
+ auto nanosecond = partial_time->nanosecond.value_or(temporal_time->iso_nanosecond());
+
+ // 24. Let result be ? RegulateTime(hour, minute, second, millisecond, microsecond, nanosecond, overflow).
+ auto result = regulate_time(global_object, hour, minute, second, millisecond, microsecond, nanosecond, *overflow);
+ if (vm.exception())
+ return {};
+
+ // 25. Return ? CreateTemporalTime(result.[[Hour]], result.[[Minute]], result.[[Second]], result.[[Millisecond]], result.[[Microsecond]], result.[[Nanosecond]]).
+ return create_temporal_time(global_object, result->hour, result->minute, result->second, result->millisecond, result->microsecond, result->nanosecond);
+}
+
// 4.3.16 Temporal.PlainTime.prototype.equals ( other ), https://tc39.es/proposal-temporal/#sec-temporal.plaintime.prototype.equals
JS_DEFINE_NATIVE_FUNCTION(PlainTimePrototype::equals)
{
diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/PlainTimePrototype.h b/Userland/Libraries/LibJS/Runtime/Temporal/PlainTimePrototype.h
index d590872bca..9296b4e4c6 100644
--- a/Userland/Libraries/LibJS/Runtime/Temporal/PlainTimePrototype.h
+++ b/Userland/Libraries/LibJS/Runtime/Temporal/PlainTimePrototype.h
@@ -26,6 +26,7 @@ private:
JS_DECLARE_NATIVE_FUNCTION(millisecond_getter);
JS_DECLARE_NATIVE_FUNCTION(microsecond_getter);
JS_DECLARE_NATIVE_FUNCTION(nanosecond_getter);
+ JS_DECLARE_NATIVE_FUNCTION(with);
JS_DECLARE_NATIVE_FUNCTION(equals);
JS_DECLARE_NATIVE_FUNCTION(to_plain_date_time);
JS_DECLARE_NATIVE_FUNCTION(get_iso_fields);
diff --git a/Userland/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.prototype.with.js b/Userland/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.prototype.with.js
new file mode 100644
index 0000000000..a0ffa7fb99
--- /dev/null
+++ b/Userland/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.prototype.with.js
@@ -0,0 +1,210 @@
+const PLAIN_TIME_PROPERTIES = [
+ "hour",
+ "minute",
+ "second",
+ "millisecond",
+ "microsecond",
+ "nanosecond",
+];
+
+const REJECTED_CALENDAR_TYPES_THREE_ARGUMENTS = [
+ Temporal.PlainDate,
+ Temporal.PlainDateTime,
+ Temporal.PlainTime,
+];
+
+const REJECTED_CALENDAR_TYPES_TWO_ARGUMENTS = [Temporal.PlainMonthDay, Temporal.PlainYearMonth];
+
+describe("correct behaviour", () => {
+ test("length is 1", () => {
+ expect(Temporal.PlainTime.prototype.with).toHaveLength(1);
+ });
+
+ test("basic functionality", () => {
+ const plainTime = new Temporal.PlainTime(1, 2, 3).with({ hour: 4, foo: 5, second: 6 });
+ expect(plainTime.hour).toBe(4);
+ expect(plainTime.minute).toBe(2);
+ expect(plainTime.second).toBe(6);
+ });
+
+ test("each property is looked up from the object", () => {
+ for (const property of PLAIN_TIME_PROPERTIES) {
+ const plainTime = new Temporal.PlainTime().with({ [property]: 1 });
+ expect(plainTime[property]).toBe(1);
+ }
+ });
+
+ test("each property is coerced to number", () => {
+ for (const property of PLAIN_TIME_PROPERTIES) {
+ const plainTime = new Temporal.PlainTime().with({ [property]: "1" });
+ expect(plainTime[property]).toBe(1);
+ }
+ });
+
+ test("argument can have a calendar property as long as it's undefined", () => {
+ expect(() => {
+ new Temporal.PlainTime().with({
+ calendar: undefined,
+ });
+ }).not.toThrowWithMessage(TypeError, "Argument must not have a defined calendar property");
+ });
+
+ test("argument can have a timeZone property as long as it's undefined", () => {
+ expect(() => {
+ new Temporal.PlainTime().with({
+ timeZone: undefined,
+ });
+ }).not.toThrowWithMessage(TypeError, "Argument must not have a defined timeZone property");
+ });
+});
+
+describe("errors", () => {
+ test("this value must be a Temporal.PlainTime object", () => {
+ expect(() => {
+ Temporal.PlainTime.prototype.with.call("foo");
+ }).toThrowWithMessage(TypeError, "Not a Temporal.PlainTime object");
+ });
+
+ test("argument is not an object", () => {
+ expect(() => {
+ new Temporal.PlainTime().with("foo");
+ }).toThrowWithMessage(TypeError, "foo is not an object");
+ expect(() => {
+ new Temporal.PlainTime().with(42);
+ }).toThrowWithMessage(TypeError, "42 is not an object");
+ });
+
+ test("options is not an object", () => {
+ expect(() => {
+ new Temporal.PlainTime().with({ hour: 1 }, "foo");
+ }).toThrowWithMessage(TypeError, "Options is not an object");
+ expect(() => {
+ new Temporal.PlainTime().with({ hour: 1 }, 42);
+ }).toThrowWithMessage(TypeError, "Options is not an object");
+ });
+
+ test("invalid overflow option", () => {
+ expect(() => {
+ new Temporal.PlainTime().with({ hour: 1 }, { overflow: "a" });
+ }).toThrowWithMessage(RangeError, "a is not a valid value for option overflow");
+ });
+
+ test("argument is an invalid plain time-like object", () => {
+ expect(() => {
+ new Temporal.PlainTime().with({});
+ }).toThrowWithMessage(TypeError, "Invalid plain time-like object");
+ expect(() => {
+ new Temporal.PlainTime().with({ foo: 1, bar: 2 });
+ }).toThrowWithMessage(TypeError, "Invalid plain time-like object");
+ });
+
+ test("error when coercing property to number", () => {
+ for (const property of PLAIN_TIME_PROPERTIES) {
+ expect(() => {
+ new Temporal.PlainTime().with({
+ [property]: {
+ valueOf() {
+ throw new Error("error occurred");
+ },
+ },
+ });
+ }).toThrowWithMessage(Error, "error occurred");
+ }
+ });
+
+ test("property must be finite", () => {
+ for (const property of PLAIN_TIME_PROPERTIES) {
+ expect(() => {
+ new Temporal.PlainTime().with({ [property]: Infinity });
+ }).toThrowWithMessage(RangeError, "Property must not be Infinity");
+ expect(() => {
+ new Temporal.PlainTime().with({ [property]: -Infinity });
+ }).toThrowWithMessage(RangeError, "Property must not be Infinity");
+ }
+ });
+
+ test("error when getting property", () => {
+ for (const property of PLAIN_TIME_PROPERTIES) {
+ expect(() => {
+ new Temporal.PlainTime().with({
+ get [property]() {
+ throw new Error("error occurred");
+ },
+ });
+ }).toThrowWithMessage(Error, "error occurred");
+ }
+ });
+
+ test("argument must not have a defined calendar property", () => {
+ expect(() => {
+ new Temporal.PlainTime().with({
+ calendar: null,
+ });
+ }).toThrowWithMessage(TypeError, "Argument must not have a defined calendar property");
+ expect(() => {
+ new Temporal.PlainTime().with({
+ calendar: 1,
+ });
+ }).toThrowWithMessage(TypeError, "Argument must not have a defined calendar property");
+ });
+
+ test("argument must not have a defined timeZone property", () => {
+ expect(() => {
+ new Temporal.PlainTime().with({
+ timeZone: null,
+ });
+ }).toThrowWithMessage(TypeError, "Argument must not have a defined timeZone property");
+ expect(() => {
+ new Temporal.PlainTime().with({
+ timeZone: 1,
+ });
+ }).toThrowWithMessage(TypeError, "Argument must not have a defined timeZone property");
+ });
+
+ test("error when getting calendar", () => {
+ expect(() => {
+ new Temporal.PlainTime().with({
+ get calendar() {
+ throw new Error("error occurred");
+ },
+ });
+ }).toThrowWithMessage(Error, "error occurred");
+ });
+
+ test("error when getting timeZone", () => {
+ expect(() => {
+ new Temporal.PlainTime().with({
+ get timeZone() {
+ throw new Error("error occurred");
+ },
+ });
+ }).toThrowWithMessage(Error, "error occurred");
+ });
+
+ test("rejects calendar types", () => {
+ for (const typeWithCalendar of REJECTED_CALENDAR_TYPES_THREE_ARGUMENTS) {
+ expect(() => {
+ new Temporal.PlainTime().with(new typeWithCalendar(1, 1, 1));
+ }).toThrowWithMessage(
+ TypeError,
+ "Argument must not have a defined calendar or timeZone property"
+ );
+ }
+
+ for (const typeWithCalendar of REJECTED_CALENDAR_TYPES_TWO_ARGUMENTS) {
+ expect(() => {
+ new Temporal.PlainTime().with(new typeWithCalendar(1, 1));
+ }).toThrowWithMessage(
+ TypeError,
+ "Argument must not have a defined calendar or timeZone property"
+ );
+ }
+
+ expect(() => {
+ new Temporal.PlainTime().with(new Temporal.ZonedDateTime(1n, {}));
+ }).toThrowWithMessage(
+ TypeError,
+ "Argument must not have a defined calendar or timeZone property"
+ );
+ });
+});