diff --git a/Libraries/LibJS/CMakeLists.txt b/Libraries/LibJS/CMakeLists.txt index 0f640e14663..9e05a465231 100644 --- a/Libraries/LibJS/CMakeLists.txt +++ b/Libraries/LibJS/CMakeLists.txt @@ -205,40 +205,8 @@ set(SOURCES Runtime/SymbolObject.cpp Runtime/SymbolPrototype.cpp Runtime/Temporal/AbstractOperations.cpp - Runtime/Temporal/Calendar.cpp - Runtime/Temporal/CalendarConstructor.cpp - Runtime/Temporal/CalendarPrototype.cpp Runtime/Temporal/Duration.cpp - Runtime/Temporal/DurationConstructor.cpp - Runtime/Temporal/DurationPrototype.cpp - Runtime/Temporal/Instant.cpp - Runtime/Temporal/InstantConstructor.cpp - Runtime/Temporal/InstantPrototype.cpp - Runtime/Temporal/ISO8601.cpp - Runtime/Temporal/Now.cpp - Runtime/Temporal/PlainDate.cpp - Runtime/Temporal/PlainDateConstructor.cpp - Runtime/Temporal/PlainDatePrototype.cpp - Runtime/Temporal/PlainDateTime.cpp - Runtime/Temporal/PlainDateTimeConstructor.cpp - Runtime/Temporal/PlainDateTimePrototype.cpp - Runtime/Temporal/PlainMonthDay.cpp - Runtime/Temporal/PlainMonthDayConstructor.cpp - Runtime/Temporal/PlainMonthDayPrototype.cpp - Runtime/Temporal/PlainTime.cpp - Runtime/Temporal/PlainTimeConstructor.cpp - Runtime/Temporal/PlainTimePrototype.cpp - Runtime/Temporal/PlainYearMonth.cpp - Runtime/Temporal/PlainYearMonthConstructor.cpp - Runtime/Temporal/PlainYearMonthPrototype.cpp Runtime/Temporal/Temporal.cpp - Runtime/Temporal/TimeZone.cpp - Runtime/Temporal/TimeZoneConstructor.cpp - Runtime/Temporal/TimeZoneMethods.cpp - Runtime/Temporal/TimeZonePrototype.cpp - Runtime/Temporal/ZonedDateTime.cpp - Runtime/Temporal/ZonedDateTimeConstructor.cpp - Runtime/Temporal/ZonedDateTimePrototype.cpp Runtime/TypedArray.cpp Runtime/TypedArrayConstructor.cpp Runtime/TypedArrayPrototype.cpp diff --git a/Libraries/LibJS/Forward.h b/Libraries/LibJS/Forward.h index 01f9721c9e8..606604121f7 100644 --- a/Libraries/LibJS/Forward.h +++ b/Libraries/LibJS/Forward.h @@ -87,17 +87,7 @@ __JS_ENUMERATE(RelativeTimeFormat, relative_time_format, RelativeTimeFormatPrototype, RelativeTimeFormatConstructor) \ __JS_ENUMERATE(Segmenter, segmenter, SegmenterPrototype, SegmenterConstructor) -#define JS_ENUMERATE_TEMPORAL_OBJECTS \ - __JS_ENUMERATE(Calendar, calendar, CalendarPrototype, CalendarConstructor) \ - __JS_ENUMERATE(Duration, duration, DurationPrototype, DurationConstructor) \ - __JS_ENUMERATE(Instant, instant, InstantPrototype, InstantConstructor) \ - __JS_ENUMERATE(PlainDate, plain_date, PlainDatePrototype, PlainDateConstructor) \ - __JS_ENUMERATE(PlainDateTime, plain_date_time, PlainDateTimePrototype, PlainDateTimeConstructor) \ - __JS_ENUMERATE(PlainMonthDay, plain_month_day, PlainMonthDayPrototype, PlainMonthDayConstructor) \ - __JS_ENUMERATE(PlainTime, plain_time, PlainTimePrototype, PlainTimeConstructor) \ - __JS_ENUMERATE(PlainYearMonth, plain_year_month, PlainYearMonthPrototype, PlainYearMonthConstructor) \ - __JS_ENUMERATE(TimeZone, time_zone, TimeZonePrototype, TimeZoneConstructor) \ - __JS_ENUMERATE(ZonedDateTime, zoned_date_time, ZonedDateTimePrototype, ZonedDateTimeConstructor) +#define JS_ENUMERATE_TEMPORAL_OBJECTS #define JS_ENUMERATE_BUILTIN_NAMESPACE_OBJECTS \ __JS_ENUMERATE(AtomicsObject, atomics) \ @@ -284,13 +274,8 @@ namespace Temporal { class PrototypeName; JS_ENUMERATE_TEMPORAL_OBJECTS #undef __JS_ENUMERATE + class Temporal; -struct CalendarMethods; -struct DurationRecord; -struct DateDurationRecord; -struct TimeDurationRecord; -struct TimeZoneMethods; -struct PartialDurationRecord; }; template diff --git a/Libraries/LibJS/Print.cpp b/Libraries/LibJS/Print.cpp index 8a4c8e26c60..97e0611adb4 100644 --- a/Libraries/LibJS/Print.cpp +++ b/Libraries/LibJS/Print.cpp @@ -47,16 +47,6 @@ #include #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include #include #include @@ -516,101 +506,6 @@ ErrorOr print_data_view(JS::PrintContext& print_context, JS::DataView cons return {}; } -ErrorOr print_temporal_calendar(JS::PrintContext& print_context, JS::Temporal::Calendar const& calendar, HashTable& seen_objects) -{ - TRY(print_type(print_context, "Temporal.Calendar"sv)); - TRY(js_out(print_context, " ")); - TRY(print_value(print_context, JS::PrimitiveString::create(calendar.vm(), calendar.identifier()), seen_objects)); - return {}; -} - -ErrorOr print_temporal_duration(JS::PrintContext& print_context, JS::Temporal::Duration const& duration, HashTable&) -{ - TRY(print_type(print_context, "Temporal.Duration"sv)); - TRY(js_out(print_context, " \033[34;1m{} y, {} M, {} w, {} d, {} h, {} m, {} s, {} ms, {} us, {} ns\033[0m", duration.years(), duration.months(), duration.weeks(), duration.days(), duration.hours(), duration.minutes(), duration.seconds(), duration.milliseconds(), duration.microseconds(), duration.nanoseconds())); - return {}; -} - -ErrorOr print_temporal_instant(JS::PrintContext& print_context, JS::Temporal::Instant const& instant, HashTable& seen_objects) -{ - TRY(print_type(print_context, "Temporal.Instant"sv)); - TRY(js_out(print_context, " ")); - // FIXME: Print human readable date and time, like in print_date(print_context, ) - ideally handling arbitrarily large values since we get a bigint. - TRY(print_value(print_context, &instant.nanoseconds(), seen_objects)); - return {}; -} - -ErrorOr print_temporal_plain_date(JS::PrintContext& print_context, JS::Temporal::PlainDate const& plain_date, HashTable& seen_objects) -{ - TRY(print_type(print_context, "Temporal.PlainDate"sv)); - TRY(js_out(print_context, " \033[34;1m{:04}-{:02}-{:02}\033[0m", plain_date.iso_year(), plain_date.iso_month(), plain_date.iso_day())); - TRY(js_out(print_context, "\n calendar: ")); - TRY(print_value(print_context, &plain_date.calendar(), seen_objects)); - return {}; -} - -ErrorOr print_temporal_plain_date_time(JS::PrintContext& print_context, JS::Temporal::PlainDateTime const& plain_date_time, HashTable& seen_objects) -{ - TRY(print_type(print_context, "Temporal.PlainDateTime"sv)); - TRY(js_out(print_context, " \033[34;1m{:04}-{:02}-{:02} {:02}:{:02}:{:02}.{:03}{:03}{:03}\033[0m", plain_date_time.iso_year(), plain_date_time.iso_month(), plain_date_time.iso_day(), plain_date_time.iso_hour(), plain_date_time.iso_minute(), plain_date_time.iso_second(), plain_date_time.iso_millisecond(), plain_date_time.iso_microsecond(), plain_date_time.iso_nanosecond())); - TRY(js_out(print_context, "\n calendar: ")); - TRY(print_value(print_context, &plain_date_time.calendar(), seen_objects)); - return {}; -} - -ErrorOr print_temporal_plain_month_day(JS::PrintContext& print_context, JS::Temporal::PlainMonthDay const& plain_month_day, HashTable& seen_objects) -{ - TRY(print_type(print_context, "Temporal.PlainMonthDay"sv)); - // Also has an [[ISOYear]] internal slot, but showing that here seems rather unexpected. - TRY(js_out(print_context, " \033[34;1m{:02}-{:02}\033[0m", plain_month_day.iso_month(), plain_month_day.iso_day())); - TRY(js_out(print_context, "\n calendar: ")); - TRY(print_value(print_context, &plain_month_day.calendar(), seen_objects)); - return {}; -} - -ErrorOr print_temporal_plain_time(JS::PrintContext& print_context, JS::Temporal::PlainTime const& plain_time, HashTable& seen_objects) -{ - TRY(print_type(print_context, "Temporal.PlainTime"sv)); - TRY(js_out(print_context, " \033[34;1m{:02}:{:02}:{:02}.{:03}{:03}{:03}\033[0m", plain_time.iso_hour(), plain_time.iso_minute(), plain_time.iso_second(), plain_time.iso_millisecond(), plain_time.iso_microsecond(), plain_time.iso_nanosecond())); - TRY(js_out(print_context, "\n calendar: ")); - TRY(print_value(print_context, &plain_time.calendar(), seen_objects)); - return {}; -} - -ErrorOr print_temporal_plain_year_month(JS::PrintContext& print_context, JS::Temporal::PlainYearMonth const& plain_year_month, HashTable& seen_objects) -{ - TRY(print_type(print_context, "Temporal.PlainYearMonth"sv)); - // Also has an [[ISODay]] internal slot, but showing that here seems rather unexpected. - TRY(js_out(print_context, " \033[34;1m{:04}-{:02}\033[0m", plain_year_month.iso_year(), plain_year_month.iso_month())); - TRY(js_out(print_context, "\n calendar: ")); - TRY(print_value(print_context, &plain_year_month.calendar(), seen_objects)); - return {}; -} - -ErrorOr print_temporal_time_zone(JS::PrintContext& print_context, JS::Temporal::TimeZone const& time_zone, HashTable& seen_objects) -{ - TRY(print_type(print_context, "Temporal.TimeZone"sv)); - TRY(js_out(print_context, " ")); - TRY(print_value(print_context, JS::PrimitiveString::create(time_zone.vm(), time_zone.identifier()), seen_objects)); - if (time_zone.offset_nanoseconds().has_value()) { - TRY(js_out(print_context, "\n offset (ns): ")); - TRY(print_value(print_context, JS::Value(*time_zone.offset_nanoseconds()), seen_objects)); - } - return {}; -} - -ErrorOr print_temporal_zoned_date_time(JS::PrintContext& print_context, JS::Temporal::ZonedDateTime const& zoned_date_time, HashTable& seen_objects) -{ - TRY(print_type(print_context, "Temporal.ZonedDateTime"sv)); - TRY(js_out(print_context, "\n epochNanoseconds: ")); - TRY(print_value(print_context, &zoned_date_time.nanoseconds(), seen_objects)); - TRY(js_out(print_context, "\n timeZone: ")); - TRY(print_value(print_context, &zoned_date_time.time_zone(), seen_objects)); - TRY(js_out(print_context, "\n calendar: ")); - TRY(print_value(print_context, &zoned_date_time.calendar(), seen_objects)); - return {}; -} - ErrorOr print_intl_display_names(JS::PrintContext& print_context, JS::Intl::DisplayNames const& display_names, HashTable& seen_objects) { TRY(print_type(print_context, "Intl.DisplayNames"sv)); @@ -1025,26 +920,6 @@ ErrorOr print_value(JS::PrintContext& print_context, JS::Value value, Hash return print_number_object(print_context, static_cast(object), seen_objects); if (is(object)) return print_string_object(print_context, static_cast(object), seen_objects); - if (is(object)) - return print_temporal_calendar(print_context, static_cast(object), seen_objects); - if (is(object)) - return print_temporal_duration(print_context, static_cast(object), seen_objects); - if (is(object)) - return print_temporal_instant(print_context, static_cast(object), seen_objects); - if (is(object)) - return print_temporal_plain_date(print_context, static_cast(object), seen_objects); - if (is(object)) - return print_temporal_plain_date_time(print_context, static_cast(object), seen_objects); - if (is(object)) - return print_temporal_plain_month_day(print_context, static_cast(object), seen_objects); - if (is(object)) - return print_temporal_plain_time(print_context, static_cast(object), seen_objects); - if (is(object)) - return print_temporal_plain_year_month(print_context, static_cast(object), seen_objects); - if (is(object)) - return print_temporal_time_zone(print_context, static_cast(object), seen_objects); - if (is(object)) - return print_temporal_zoned_date_time(print_context, static_cast(object), seen_objects); if (is(object)) return print_intl_display_names(print_context, static_cast(object), seen_objects); if (is(object)) diff --git a/Libraries/LibJS/Runtime/DatePrototype.cpp b/Libraries/LibJS/Runtime/DatePrototype.cpp index 980d5d16c94..9f12a403535 100644 --- a/Libraries/LibJS/Runtime/DatePrototype.cpp +++ b/Libraries/LibJS/Runtime/DatePrototype.cpp @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include @@ -82,7 +81,6 @@ void DatePrototype::initialize(Realm& realm) define_native_function(realm, vm.names.toLocaleString, to_locale_string, 0, attr); define_native_function(realm, vm.names.toLocaleTimeString, to_locale_time_string, 0, attr); define_native_function(realm, vm.names.toString, to_string, 0, attr); - define_native_function(realm, vm.names.toTemporalInstant, to_temporal_instant, 0, attr); define_native_function(realm, vm.names.toTimeString, to_time_string, 0, attr); define_native_function(realm, vm.names.toUTCString, to_utc_string, 0, attr); @@ -1179,20 +1177,6 @@ ByteString to_date_string(double time) return ByteString::formatted("{} {}{}", date_string(time), time_string(time), time_zone_string(time)); } -// 14.1.1 Date.prototype.toTemporalInstant ( ), https://tc39.es/proposal-temporal/#sec-date.prototype.totemporalinstant -JS_DEFINE_NATIVE_FUNCTION(DatePrototype::to_temporal_instant) -{ - // 1. Let t be ? thisTimeValue(this value). - auto t = TRY(this_time_value(vm, vm.this_value())); - - // 2. Let ns be ? NumberToBigInt(t) × ℤ(10^6). - auto* ns = TRY(number_to_bigint(vm, Value(t))); - ns = BigInt::create(vm, ns->big_integer().multiplied_by(Crypto::UnsignedBigInteger { 1'000'000 })); - - // 3. Return ! CreateTemporalInstant(ns). - return MUST(Temporal::create_temporal_instant(vm, *ns)); -} - // 21.4.4.42 Date.prototype.toTimeString ( ), https://tc39.es/ecma262/#sec-date.prototype.totimestring JS_DEFINE_NATIVE_FUNCTION(DatePrototype::to_time_string) { diff --git a/Libraries/LibJS/Runtime/DatePrototype.h b/Libraries/LibJS/Runtime/DatePrototype.h index 8160ff2911a..c55f5dd4536 100644 --- a/Libraries/LibJS/Runtime/DatePrototype.h +++ b/Libraries/LibJS/Runtime/DatePrototype.h @@ -62,7 +62,6 @@ private: JS_DECLARE_NATIVE_FUNCTION(to_locale_string); JS_DECLARE_NATIVE_FUNCTION(to_locale_time_string); JS_DECLARE_NATIVE_FUNCTION(to_string); - JS_DECLARE_NATIVE_FUNCTION(to_temporal_instant); JS_DECLARE_NATIVE_FUNCTION(to_time_string); JS_DECLARE_NATIVE_FUNCTION(to_utc_string); diff --git a/Libraries/LibJS/Runtime/GlobalObject.cpp b/Libraries/LibJS/Runtime/GlobalObject.cpp index 2f742f3274c..8d0426eaf8b 100644 --- a/Libraries/LibJS/Runtime/GlobalObject.cpp +++ b/Libraries/LibJS/Runtime/GlobalObject.cpp @@ -67,17 +67,7 @@ #include #include #include -#include -#include -#include -#include -#include -#include -#include -#include #include -#include -#include #include #include #include diff --git a/Libraries/LibJS/Runtime/Intrinsics.cpp b/Libraries/LibJS/Runtime/Intrinsics.cpp index 92e6b6d9b1e..53b44fdc6ba 100644 --- a/Libraries/LibJS/Runtime/Intrinsics.cpp +++ b/Libraries/LibJS/Runtime/Intrinsics.cpp @@ -99,27 +99,7 @@ #include #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include -#include -#include -#include -#include #include #include #include diff --git a/Libraries/LibJS/Runtime/Temporal/AbstractOperations.cpp b/Libraries/LibJS/Runtime/Temporal/AbstractOperations.cpp index 5072e266ab0..d808b31893d 100644 --- a/Libraries/LibJS/Runtime/Temporal/AbstractOperations.cpp +++ b/Libraries/LibJS/Runtime/Temporal/AbstractOperations.cpp @@ -6,76 +6,11 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include -#include -#include -#include -#include -#include -#include -#include #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include namespace JS::Temporal { -static Optional to_option_type(Value value) -{ - if (value.is_boolean()) - return OptionType::Boolean; - if (value.is_string()) - return OptionType::String; - if (value.is_number()) - return OptionType::Number; - return {}; -} - -// 13.1 IterableToListOfType ( items, elementTypes ), https://tc39.es/proposal-temporal/#sec-iterabletolistoftype -ThrowCompletionOr> iterable_to_list_of_type(VM& vm, Value items, Vector const& element_types) -{ - // 1. Let iteratorRecord be ? GetIterator(items, sync). - auto iterator_record = TRY(get_iterator(vm, items, IteratorHint::Sync)); - - // 2. Let values be a new empty List. - GC::MarkedVector values(vm.heap()); - - // 3. Let next be true. - auto next = true; - // 4. Repeat, while next is not false, - while (next) { - // a. Set next to ? IteratorStep(iteratorRecord). - auto iterator_result = TRY(iterator_step(vm, iterator_record)); - next = iterator_result; - - // b. If next is not false, then - if (next) { - // i. Let nextValue be ? IteratorValue(next). - auto next_value = TRY(iterator_value(vm, *iterator_result)); - // ii. If Type(nextValue) is not an element of elementTypes, then - if (auto type = to_option_type(next_value); !type.has_value() || !element_types.contains_slow(*type)) { - // 1. Let completion be ThrowCompletion(a newly created TypeError object). - auto completion = vm.throw_completion(ErrorType::IterableToListOfTypeInvalidValue, next_value.to_string_without_side_effects()); - // 2. Return ? IteratorClose(iteratorRecord, completion). - return iterator_close(vm, iterator_record, move(completion)); - } - // iii. Append nextValue to the end of the List values. - values.append(next_value); - } - } - - // 5. Return values. - return { move(values) }; -} - // 13.2 GetOptionsObject ( options ), https://tc39.es/proposal-temporal/#sec-getoptionsobject ThrowCompletionOr get_options_object(VM& vm, Value options) { @@ -155,1801 +90,4 @@ ThrowCompletionOr get_option(VM& vm, Object const& options, PropertyKey c return value; } -// 13.4 ToTemporalOverflow ( options ), https://tc39.es/proposal-temporal/#sec-temporal-totemporaloverflow -ThrowCompletionOr to_temporal_overflow(VM& vm, Object const* options) -{ - // 1. If options is undefined, return "constrain". - if (options == nullptr) - return "constrain"_string; - - // 2. Return ? GetOption(options, "overflow", "string", « "constrain", "reject" », "constrain"). - auto option = TRY(get_option(vm, *options, vm.names.overflow, OptionType::String, { "constrain"sv, "reject"sv }, "constrain"sv)); - - VERIFY(option.is_string()); - return option.as_string().utf8_string(); -} - -// 13.5 ToTemporalDisambiguation ( options ), https://tc39.es/proposal-temporal/#sec-temporal-totemporaldisambiguation -ThrowCompletionOr to_temporal_disambiguation(VM& vm, Object const* options) -{ - // 1. If options is undefined, return "compatible". - if (options == nullptr) - return "compatible"_string; - - // 2. Return ? GetOption(options, "disambiguation", "string", « "compatible", "earlier", "later", "reject" », "compatible"). - auto option = TRY(get_option(vm, *options, vm.names.disambiguation, OptionType::String, { "compatible"sv, "earlier"sv, "later"sv, "reject"sv }, "compatible"sv)); - - VERIFY(option.is_string()); - return option.as_string().utf8_string(); -} - -// 13.6 ToTemporalRoundingMode ( normalizedOptions, fallback ), https://tc39.es/proposal-temporal/#sec-temporal-totemporalroundingmode -ThrowCompletionOr to_temporal_rounding_mode(VM& vm, Object const& normalized_options, StringView fallback) -{ - // 1. Return ? GetOption(normalizedOptions, "roundingMode", "string", « "ceil", "floor", "expand", "trunc", "halfCeil", "halfFloor", "halfExpand", "halfTrunc", "halfEven" », fallback). - auto option = TRY(get_option( - vm, normalized_options, vm.names.roundingMode, OptionType::String, - { - "ceil"sv, - "floor"sv, - "expand"sv, - "trunc"sv, - "halfCeil"sv, - "halfFloor"sv, - "halfExpand"sv, - "halfTrunc"sv, - "halfEven"sv, - }, - fallback)); - - VERIFY(option.is_string()); - return option.as_string().utf8_string(); -} - -// 13.7 NegateTemporalRoundingMode ( roundingMode ), https://tc39.es/proposal-temporal/#sec-temporal-negatetemporalroundingmode -StringView negate_temporal_rounding_mode(StringView rounding_mode) -{ - // 1. If roundingMode is "ceil", return "floor". - if (rounding_mode == "ceil"sv) - return "floor"sv; - - // 2. If roundingMode is "floor", return "ceil". - if (rounding_mode == "floor"sv) - return "ceil"sv; - - // 3. If roundingMode is "halfCeil", return "halfFloor". - if (rounding_mode == "halfCeil"sv) - return "halfFloor"sv; - - // 4. If roundingMode is "halfFloor", return "halfCeil". - if (rounding_mode == "halfFloor"sv) - return "halfCeil"sv; - - // 5. Return roundingMode. - return rounding_mode; -} - -// 13.8 ToTemporalOffset ( options, fallback ), https://tc39.es/proposal-temporal/#sec-temporal-totemporaloffset -ThrowCompletionOr to_temporal_offset(VM& vm, Object const* options, StringView fallback) -{ - // 1. If options is undefined, return fallback. - if (options == nullptr) - return TRY_OR_THROW_OOM(vm, String::from_utf8(fallback)); - - // 2. Return ? GetOption(options, "offset", "string", « "prefer", "use", "ignore", "reject" », fallback). - auto option = TRY(get_option(vm, *options, vm.names.offset, OptionType::String, { "prefer"sv, "use"sv, "ignore"sv, "reject"sv }, fallback)); - - VERIFY(option.is_string()); - return option.as_string().utf8_string(); -} - -// 13.9 ToCalendarNameOption ( normalizedOptions ), https://tc39.es/proposal-temporal/#sec-temporal-tocalendarnameoption -ThrowCompletionOr to_calendar_name_option(VM& vm, Object const& normalized_options) -{ - // 1. Return ? GetOption(normalizedOptions, "calendarName", "string", « "auto", "always", "never", "critical" », "auto"). - auto option = TRY(get_option(vm, normalized_options, vm.names.calendarName, OptionType::String, { "auto"sv, "always"sv, "never"sv, "critical"sv }, "auto"sv)); - - VERIFY(option.is_string()); - return option.as_string().utf8_string(); -} - -// 13.10 ToTimeZoneNameOption ( normalizedOptions ), https://tc39.es/proposal-temporal/#sec-temporal-totimezonenameoption -ThrowCompletionOr to_time_zone_name_option(VM& vm, Object const& normalized_options) -{ - // 1. Return ? GetOption(normalizedOptions, "timeZoneName", "string", « "auto", "never", "critical" », "auto"). - auto option = TRY(get_option(vm, normalized_options, vm.names.timeZoneName, OptionType::String, { "auto"sv, "never"sv, "critical"sv }, "auto"sv)); - - VERIFY(option.is_string()); - return option.as_string().utf8_string(); -} - -// 13.11 ToShowOffsetOption ( normalizedOptions ), https://tc39.es/proposal-temporal/#sec-temporal-toshowoffsetoption -ThrowCompletionOr to_show_offset_option(VM& vm, Object const& normalized_options) -{ - // 1. Return ? GetOption(normalizedOptions, "offset", "string", « "auto", "never" », "auto"). - auto option = TRY(get_option(vm, normalized_options, vm.names.offset, OptionType::String, { "auto"sv, "never"sv }, "auto"sv)); - - VERIFY(option.is_string()); - return option.as_string().utf8_string(); -} - -// 13.12 ToTemporalRoundingIncrement ( normalizedOptions, dividend, inclusive ), https://tc39.es/proposal-temporal/#sec-temporal-totemporalroundingincrement -ThrowCompletionOr to_temporal_rounding_increment(VM& vm, Object const& normalized_options) -{ - // 1. Let increment be ? GetOption(normalizedOptions, "roundingIncrement", "number", undefined, 1𝔽) - auto increment_value = TRY(get_option(vm, normalized_options, vm.names.roundingIncrement, OptionType::Number, {}, 1.0)); - VERIFY(increment_value.is_number()); - auto increment = increment_value.as_double(); - - // 2. If increment is not finite, throw a RangeError exception - if (!increment_value.is_finite_number()) - return vm.throw_completion(ErrorType::OptionIsNotValidValue, increment, "roundingIncrement"); - - // 3. If increment < 1𝔽, throw a RangeError exception. - if (increment < 1) { - return vm.throw_completion(ErrorType::OptionIsNotValidValue, increment, "roundingIncrement"); - } - - // 4. Return truncate(ℝ(increment)) - return static_cast(trunc(increment)); -} - -// 13.13 ValidateTemporalRoundingIncrement ( increment, dividend, inclusive ), https://tc39.es/proposal-temporal/#sec-validatetemporalroundingincrement -ThrowCompletionOr validate_temporal_rounding_increment(VM& vm, u64 increment, u64 dividend, bool inclusive) -{ - u64 maximum; - // 1. If inclusive is true, then - if (inclusive) { - // a. Let maximum be dividend. - maximum = dividend; - } - // 2. Else if dividend is more than 1, then - else if (dividend > 1) { - // a. Let maximum be dividend - 1. - maximum = dividend - 1; - } - // 3. Else - else { - // a. Let maximum be 1. - maximum = 1; - } - // 4. If increment > maximum, throw a RangeError exception. - if (increment > maximum) { - return vm.throw_completion(ErrorType::OptionIsNotValidValue, increment, "roundingIncrement"); - } - - // 5. If dividend modulo increment is not zero, then - if (modulo(dividend, increment) != 0) { - // a. Throw a RangeError exception. - return vm.throw_completion(ErrorType::OptionIsNotValidValue, increment, "roundingIncrement"); - } - - // 6. Return UNUSED. - return {}; -} - -// 13.14 ToSecondsStringPrecisionRecord ( normalizedOptions ), https://tc39.es/proposal-temporal/#sec-temporal-tosecondsstringprecisionrecord -ThrowCompletionOr to_seconds_string_precision_record(VM& vm, Object const& normalized_options) -{ - // 1. Let smallestUnit be ? GetTemporalUnit(normalizedOptions, "smallestUnit", time, undefined). - auto smallest_unit = TRY(get_temporal_unit(vm, normalized_options, vm.names.smallestUnit, UnitGroup::Time, Optional {})); - - // 2. If smallestUnit is "hour", throw a RangeError exception. - if (smallest_unit == "hour"sv) - return vm.throw_completion(ErrorType::OptionIsNotValidValue, *smallest_unit, "smallestUnit"sv); - - // 3. If smallestUnit is "minute", then - if (smallest_unit == "minute"sv) { - // a. Return the Record { [[Precision]]: "minute", [[Unit]]: "minute", [[Increment]]: 1 }. - return SecondsStringPrecision { .precision = "minute"sv, .unit = "minute"sv, .increment = 1 }; - } - - // 4. If smallestUnit is "second", then - if (smallest_unit == "second"sv) { - // a. Return the Record { [[Precision]]: 0, [[Unit]]: "second", [[Increment]]: 1 }. - return SecondsStringPrecision { .precision = 0, .unit = "second"sv, .increment = 1 }; - } - - // 5. If smallestUnit is "millisecond", then - if (smallest_unit == "millisecond"sv) { - // a. Return the Record { [[Precision]]: 3, [[Unit]]: "millisecond", [[Increment]]: 1 }. - return SecondsStringPrecision { .precision = 3, .unit = "millisecond"sv, .increment = 1 }; - } - - // 6. If smallestUnit is "microsecond", then - if (smallest_unit == "microsecond"sv) { - // a. Return the Record { [[Precision]]: 6, [[Unit]]: "microsecond", [[Increment]]: 1 }. - return SecondsStringPrecision { .precision = 6, .unit = "microsecond"sv, .increment = 1 }; - } - - // 7. If smallestUnit is "nanosecond", then - if (smallest_unit == "nanosecond"sv) { - // a. Return the Record { [[Precision]]: 9, [[Unit]]: "nanosecond", [[Increment]]: 1 }. - return SecondsStringPrecision { .precision = 9, .unit = "nanosecond"sv, .increment = 1 }; - } - - // 8. Assert: smallestUnit is undefined. - VERIFY(!smallest_unit.has_value()); - - // 9. Let fractionalDigitsVal be ? Get(normalizedOptions, "fractionalSecondDigits"). - auto fractional_digits_value = TRY(normalized_options.get(vm.names.fractionalSecondDigits)); - - // 10. If Type(fractionalDigitsVal) is not Number, then - if (!fractional_digits_value.is_number()) { - // a. If fractionalDigitsVal is not undefined, then - if (!fractional_digits_value.is_undefined()) { - // i. If ? ToString(fractionalDigitsVal) is not "auto", throw a RangeError exception. - if (TRY(fractional_digits_value.to_string(vm)) != "auto"sv) - return vm.template throw_completion(ErrorType::OptionIsNotValidValue, fractional_digits_value, "fractionalSecondDigits"sv); - } - - // b. Return the Record { [[Precision]]: "auto", [[Unit]]: "nanosecond", [[Increment]]: 1 }. - return SecondsStringPrecision { .precision = "auto"sv, .unit = "nanosecond"sv, .increment = 1 }; - } - - // 11. If fractionalDigitsVal is NaN, +∞𝔽, or -∞𝔽, throw a RangeError exception. - if (fractional_digits_value.is_nan() || fractional_digits_value.is_infinity()) - return vm.template throw_completion(ErrorType::OptionIsNotValidValue, fractional_digits_value, "fractionalSecondDigits"sv); - - // 12. Let fractionalDigitCount be truncate(ℝ(fractionalDigitsVal)). - auto fractional_digit_count_unchecked = trunc(fractional_digits_value.as_double()); - - // 13. If fractionalDigitCount < 0 or fractionalDigitCount > 9, throw a RangeError exception. - if (fractional_digit_count_unchecked < 0 || fractional_digit_count_unchecked > 9) - return vm.template throw_completion(ErrorType::OptionIsNotValidValue, fractional_digits_value, "fractionalSecondDigits"sv); - - auto fractional_digit_count = static_cast(fractional_digit_count_unchecked); - - // 14. If fractionalDigitCount is 0, then - if (fractional_digit_count == 0) { - // a. Return the Record { [[Precision]]: 0, [[Unit]]: "second", [[Increment]]: 1 }. - return SecondsStringPrecision { .precision = 0, .unit = "second"sv, .increment = 1 }; - } - - // 15. If fractionalDigitCount is 1, 2, or 3, then - if (fractional_digit_count == 1 || fractional_digit_count == 2 || fractional_digit_count == 3) { - // a. Return the Record { [[Precision]]: fractionalDigitCount, [[Unit]]: "millisecond", [[Increment]]: 10^(3 - fractionalDigitCount) }. - return SecondsStringPrecision { .precision = fractional_digit_count, .unit = "millisecond"sv, .increment = (u32)pow(10, 3 - fractional_digit_count) }; - } - - // 16. If fractionalDigitCount is 4, 5, or 6, then - if (fractional_digit_count == 4 || fractional_digit_count == 5 || fractional_digit_count == 6) { - // a. Return the Record { [[Precision]]: fractionalDigitCount, [[Unit]]: "microsecond", [[Increment]]: 10^(6 - fractionalDigitCount) }. - return SecondsStringPrecision { .precision = fractional_digit_count, .unit = "microsecond"sv, .increment = (u32)pow(10, 6 - fractional_digit_count) }; - } - - // 17. Assert: fractionalDigitCount is 7, 8, or 9. - VERIFY(fractional_digit_count == 7 || fractional_digit_count == 8 || fractional_digit_count == 9); - - // 18. Return the Record { [[Precision]]: fractionalDigitCount, [[Unit]]: "nanosecond", [[Increment]]: 10^(9 - fractionalDigitCount) }. - return SecondsStringPrecision { .precision = fractional_digit_count, .unit = "nanosecond"sv, .increment = (u32)pow(10, 9 - fractional_digit_count) }; -} - -struct TemporalUnit { - StringView singular; - StringView plural; - UnitGroup category; -}; - -// https://tc39.es/proposal-temporal/#table-temporal-units -static Vector temporal_units = { - { "year"sv, "years"sv, UnitGroup::Date }, - { "month"sv, "months"sv, UnitGroup::Date }, - { "week"sv, "weeks"sv, UnitGroup::Date }, - { "day"sv, "days"sv, UnitGroup::Date }, - { "hour"sv, "hours"sv, UnitGroup::Time }, - { "minute"sv, "minutes"sv, UnitGroup::Time }, - { "second"sv, "seconds"sv, UnitGroup::Time }, - { "millisecond"sv, "milliseconds"sv, UnitGroup::Time }, - { "microsecond"sv, "microseconds"sv, UnitGroup::Time }, - { "nanosecond"sv, "nanoseconds"sv, UnitGroup::Time } -}; - -// 13.15 GetTemporalUnit ( normalizedOptions, key, unitGroup, default [ , extraValues ] ), https://tc39.es/proposal-temporal/#sec-temporal-gettemporalunit -ThrowCompletionOr> get_temporal_unit(VM& vm, Object const& normalized_options, PropertyKey const& key, UnitGroup unit_group, TemporalUnitDefault const& default_, Vector const& extra_values) -{ - // 1. Let singularNames be a new empty List. - Vector singular_names; - - // 2. For each row of Table 13, except the header row, in table order, do - for (auto const& row : temporal_units) { - // a. Let unit be the value in the Singular column of the row. - auto unit = row.singular; - - // b. If the Category column of the row is date and unitGroup is date or datetime, append unit to singularNames. - if (row.category == UnitGroup::Date && (unit_group == UnitGroup::Date || unit_group == UnitGroup::DateTime)) - singular_names.append(unit); - // c. Else if the Category column of the row is time and unitGroup is time or datetime, append unit to singularNames. - else if (row.category == UnitGroup::Time && (unit_group == UnitGroup::Time || unit_group == UnitGroup::DateTime)) - singular_names.append(unit); - } - - // 3. If extraValues is present, then - if (!extra_values.is_empty()) { - // a. Set singularNames to the list-concatenation of singularNames and extraValues. - singular_names.extend(extra_values); - } - - OptionDefault default_value; - - // 4. If default is required, then - if (default_.has()) { - // a. Let defaultValue be undefined. - default_value = {}; - } - // 5. Else, - else { - auto default_string = default_.get>(); - - // a. Let defaultValue be default. - default_value = default_string.has_value() ? OptionDefault { *default_string } : OptionDefault {}; - - // b. If defaultValue is not undefined and singularNames does not contain defaultValue, then - if (default_string.has_value() && !singular_names.contains_slow(*default_string)) { - // i. Append defaultValue to singularNames. - singular_names.append(*default_string); - } - } - - // 6. Let allowedValues be a copy of singularNames. - auto allowed_values = singular_names; - - // 7. For each element singularName of singularNames, do - for (auto const& singular_name : singular_names) { - for (auto const& row : temporal_units) { - // a. If singularName is listed in the Singular column of Table 13, then - if (singular_name == row.singular) { - // i. Let pluralName be the value in the Plural column of the corresponding row. - auto plural_name = row.plural; - - // ii. Append pluralName to allowedValues. - allowed_values.append(plural_name); - } - } - } - - // 8. NOTE: For each singular Temporal unit name that is contained within allowedValues, the corresponding plural name is also contained within it. - - // 9. Let value be ? GetOption(normalizedOptions, key, "string", allowedValues, defaultValue). - auto option_value = TRY(get_option(vm, normalized_options, key, OptionType::String, allowed_values.span(), default_value)); - - // 10. If value is undefined and default is required, throw a RangeError exception. - if (option_value.is_undefined() && default_.has()) - return vm.throw_completion(ErrorType::IsUndefined, ByteString::formatted("{} option value", key.as_string())); - - auto value = option_value.is_undefined() - ? Optional {} - : option_value.as_string().utf8_string(); - - // 11. If value is listed in the Plural column of Table 13, then - for (auto const& row : temporal_units) { - if (row.plural == value) { - // a. Set value to the value in the Singular column of the corresponding row. - value = TRY_OR_THROW_OOM(vm, String::from_utf8(row.singular)); - } - } - - // 12. Return value. - return value; -} - -// FIXME: This function is a hack to undo a RelativeTo back to the old API, which was just a Value. -// We should get rid of this once all callers have been converted to the new API. -Value relative_to_converted_to_value(RelativeTo const& relative_to) -{ - if (relative_to.plain_relative_to) - return relative_to.plain_relative_to; - - if (relative_to.zoned_relative_to) - return relative_to.zoned_relative_to; - - return js_undefined(); -} - -// 13.16 ToRelativeTemporalObject ( options ), https://tc39.es/proposal-temporal/#sec-temporal-torelativetemporalobject -ThrowCompletionOr to_relative_temporal_object(VM& vm, Object const& options) -{ - auto& realm = *vm.current_realm(); - - // 1. Assert: Type(options) is Object. - - // 2. Let value be ? Get(options, "relativeTo"). - auto value = TRY(options.get(vm.names.relativeTo)); - - // 3. If value is undefined, then - if (value.is_undefined()) { - // a. Return value. - return RelativeTo {}; - } - - // 4. Let offsetBehaviour be option. - auto offset_behavior = OffsetBehavior::Option; - - // 5. Let matchBehaviour be match exactly. - auto match_behavior = MatchBehavior::MatchExactly; - - ISODateTime result; - Value offset_string; - Value time_zone; - Object* calendar = nullptr; - - // 6. If Type(value) is Object, then - if (value.is_object()) { - auto& value_object = value.as_object(); - // a. If value has an [[InitializedTemporalZonedDateTime]] internal slot, then - if (is(value_object)) { - auto& zoned_relative_to = static_cast(value_object); - - // i. Let timeZoneRec be ? CreateTimeZoneMethodsRecord(value.[[TimeZone]], « GET-OFFSET-NANOSECONDS-FOR, GET-POSSIBLE-INSTANTS-FOR »). - auto time_zone_record = TRY(create_time_zone_methods_record(vm, GC::Ref { zoned_relative_to.time_zone() }, { { TimeZoneMethod::GetOffsetNanosecondsFor, TimeZoneMethod::GetPossibleInstantsFor } })); - - // ii. Return the Record { [[PlainRelativeTo]]: undefined, [[ZonedRelativeTo]]: value, [[TimeZoneRec]]: timeZoneRec }. - return RelativeTo { - .plain_relative_to = {}, - .zoned_relative_to = zoned_relative_to, - .time_zone_record = time_zone_record, - }; - } - - // b. If value has an [[InitializedTemporalDate]] internal slot, then - if (is(value_object)) { - // i. Return the Record { [[PlainRelativeTo]]: value, [[ZonedRelativeTo]]: undefined, [[TimeZoneRec]]: undefined }. - return RelativeTo { - .plain_relative_to = static_cast(value_object), - .zoned_relative_to = {}, - .time_zone_record = {}, - }; - } - - // c. If value has an [[InitializedTemporalDateTime]] internal slot, then - if (is(value_object)) { - auto& plain_date_time = static_cast(value_object); - - // i. Let plainDate be ! CreateTemporalDate(value.[[ISOYear]], value.[[ISOMonth]], value.[[ISODay]], value.[[Calendar]]). - auto* plain_date = TRY(create_temporal_date(vm, plain_date_time.iso_year(), plain_date_time.iso_month(), plain_date_time.iso_day(), plain_date_time.calendar())); - - // ii. Return the Record { [[PlainRelativeTo]]: plainDate, [[ZonedRelativeTo]]: undefined, [[TimeZoneRec]]: undefined }. - return RelativeTo { - .plain_relative_to = plain_date, - .zoned_relative_to = {}, - .time_zone_record = {}, - }; - } - - // d. Let calendar be ? GetTemporalCalendarWithISODefault(value). - calendar = TRY(get_temporal_calendar_with_iso_default(vm, value_object)); - - // e. Let fieldNames be ? CalendarFields(calendar, « "day", "hour", "microsecond", "millisecond", "minute", "month", "monthCode", "nanosecond", "second", "year" »). - auto field_names = TRY(calendar_fields(vm, *calendar, { "day"sv, "hour"sv, "microsecond"sv, "millisecond"sv, "minute"sv, "month"sv, "monthCode"sv, "nanosecond"sv, "second"sv, "year"sv })); - - // f. Let fields be ? PrepareTemporalFields(value, fieldNames, «»). - auto* fields = TRY(prepare_temporal_fields(vm, value_object, field_names, Vector {})); - - // g. Let dateOptions be OrdinaryObjectCreate(null). - auto date_options = Object::create(realm, nullptr); - - // h. Perform ! CreateDataPropertyOrThrow(dateOptions, "overflow", "constrain"). - MUST(date_options->create_data_property_or_throw(vm.names.overflow, PrimitiveString::create(vm, "constrain"_string))); - - // i. Let result be ? InterpretTemporalDateTimeFields(calendar, fields, dateOptions). - result = TRY(interpret_temporal_date_time_fields(vm, *calendar, *fields, date_options)); - - // j. Let offsetString be ? Get(value, "offset"). - offset_string = TRY(value_object.get(vm.names.offset)); - - // k. Let timeZone be ? Get(value, "timeZone"). - time_zone = TRY(value_object.get(vm.names.timeZone)); - - // l. If timeZone is not undefined, then - if (!time_zone.is_undefined()) { - // i. Set timeZone to ? ToTemporalTimeZone(timeZone). - time_zone = TRY(to_temporal_time_zone(vm, time_zone)); - } - - // m. If offsetString is undefined, then - if (offset_string.is_undefined()) { - // i. Set offsetBehaviour to wall. - offset_behavior = OffsetBehavior::Wall; - } - } - // 7. Else, - else { - // a. Let string be ? ToString(value). - auto string = TRY(value.to_string(vm)); - - // b. Let result be ? ParseTemporalRelativeToString(string). - result = TRY(parse_temporal_relative_to_string(vm, string)); - - // c. Let calendar be ? ToTemporalCalendarWithISODefault(result.[[Calendar]]). - calendar = TRY(to_temporal_calendar_with_iso_default(vm, result.calendar.has_value() ? PrimitiveString::create(vm, *result.calendar) : js_undefined())); - - // d. Let offsetString be result.[[TimeZone]].[[OffsetString]]. - offset_string = result.time_zone.offset_string.has_value() ? PrimitiveString::create(vm, *result.time_zone.offset_string) : js_undefined(); - - // e. Let timeZoneName be result.[[TimeZone]].[[Name]]. - auto time_zone_name = result.time_zone.name; - - // f. If timeZoneName is undefined, then - if (!time_zone_name.has_value()) { - // i. Let timeZone be undefined. - time_zone = js_undefined(); - } - // g. Else, - else { - // i. If IsTimeZoneOffsetString(timeZoneName) is false, then - if (!is_time_zone_offset_string(*time_zone_name)) { - // 1. If IsAvailableTimeZoneName(timeZoneName) is false, throw a RangeError exception. - if (!is_available_time_zone_name(*time_zone_name)) - return vm.throw_completion(ErrorType::TemporalInvalidTimeZoneName, *time_zone_name); - - // 2. Set timeZoneName to ! CanonicalizeTimeZoneName(timeZoneName). - time_zone_name = MUST_OR_THROW_OOM(canonicalize_time_zone_name(vm, *time_zone_name)); - } - - // ii. Let timeZone be ! CreateTemporalTimeZone(timeZoneName). - time_zone = MUST_OR_THROW_OOM(create_temporal_time_zone(vm, time_zone_name.release_value())); - - // iii. If result.[[TimeZone]].[[Z]] is true, then - if (result.time_zone.z) { - // 1. Set offsetBehaviour to exact. - offset_behavior = OffsetBehavior::Exact; - } - // iv. Else if offsetString is undefined, then - else if (offset_string.is_undefined()) { - // 1. Set offsetBehaviour to wall. - offset_behavior = OffsetBehavior::Wall; - } - - // v. Set matchBehaviour to match minutes. - match_behavior = MatchBehavior::MatchMinutes; - } - } - - // 8. If timeZone is undefined, then - if (time_zone.is_undefined()) { - // a. Return ? CreateTemporalDate(result.[[Year]], result.[[Month]], result.[[Day]], calendar). - auto* plain_date = TRY(create_temporal_date(vm, result.year, result.month, result.day, *calendar)); - return RelativeTo { - .plain_relative_to = plain_date, - .zoned_relative_to = {}, - .time_zone_record = {}, - }; - } - - double offset_ns; - - // 9. If offsetBehaviour is option, then - if (offset_behavior == OffsetBehavior::Option) { - // a. Set offsetString to ? ToString(offsetString). - // NOTE: offsetString is not used after this path, so we don't need to put this into the original offset_string which is of type JS::Value. - auto actual_offset_string = TRY(offset_string.to_string(vm)); - - // b. If IsTimeZoneOffsetString(offsetString) is false, throw a RangeError exception. - if (!is_time_zone_offset_string(actual_offset_string)) - return vm.throw_completion(ErrorType::TemporalInvalidTimeZoneName, actual_offset_string); - - // c. Let offsetNs be ParseTimeZoneOffsetString(offsetString). - offset_ns = parse_time_zone_offset_string(actual_offset_string); - } - // 10. Else, - else { - // a. Let offsetNs be 0. - offset_ns = 0; - } - - // 11. Let epochNanoseconds be ? InterpretISODateTimeOffset(result.[[Year]], result.[[Month]], result.[[Day]], result.[[Hour]], result.[[Minute]], result.[[Second]], result.[[Millisecond]], result.[[Microsecond]], result.[[Nanosecond]], offsetBehaviour, offsetNs, timeZone, "compatible", "reject", matchBehaviour). - auto const* epoch_nanoseconds = TRY(interpret_iso_date_time_offset(vm, result.year, result.month, result.day, result.hour, result.minute, result.second, result.millisecond, result.microsecond, result.nanosecond, offset_behavior, offset_ns, time_zone, "compatible"sv, "reject"sv, match_behavior)); - - // 12. Return ! CreateTemporalZonedDateTime(epochNanoseconds, timeZone, calendar). - auto time_zone_record = TRY(create_time_zone_methods_record(vm, GC::Ref { time_zone.as_object() }, { { TimeZoneMethod::GetOffsetNanosecondsFor, TimeZoneMethod::GetPossibleInstantsFor } })); - auto* zoned_relative_to = MUST(create_temporal_zoned_date_time(vm, *epoch_nanoseconds, time_zone.as_object(), *calendar)); - return RelativeTo { - .plain_relative_to = {}, - .zoned_relative_to = zoned_relative_to, - .time_zone_record = time_zone_record, - }; -} - -// 13.17 LargerOfTwoTemporalUnits ( u1, u2 ), https://tc39.es/proposal-temporal/#sec-temporal-largeroftwotemporalunits -StringView larger_of_two_temporal_units(StringView unit1, StringView unit2) -{ - // 1. Assert: Both u1 and u2 are listed in the Singular column of Table 13. - - // 2. For each row of Table 13, except the header row, in table order, do - for (auto const& row : temporal_units) { - // a. Let unit be the value in the Singular column of the row. - auto unit = row.singular; - - // b. If SameValue(u1, unit) is true, return unit. - if (unit1 == unit) - return unit; - - // c. If SameValue(u2, unit) is true, return unit. - if (unit2 == unit) - return unit; - } - VERIFY_NOT_REACHED(); -} - -// 13.18 MergeLargestUnitOption ( options, largestUnit ), https://tc39.es/proposal-temporal/#sec-temporal-mergelargestunitoption -ThrowCompletionOr merge_largest_unit_option(VM& vm, Object const& options, String largest_unit) -{ - auto& realm = *vm.current_realm(); - - // 1. Let merged be OrdinaryObjectCreate(null). - auto merged = Object::create(realm, nullptr); - - // 2. Let keys be ? EnumerableOwnPropertyNames(options, key). - auto keys = TRY(options.enumerable_own_property_names(Object::PropertyKind::Key)); - - // 3. For each element nextKey of keys, do - for (auto& key : keys) { - auto next_key = MUST(PropertyKey::from_value(vm, key)); - - // a. Let propValue be ? Get(options, nextKey). - auto prop_value = TRY(options.get(next_key)); - - // b. Perform ! CreateDataPropertyOrThrow(merged, nextKey, propValue). - MUST(merged->create_data_property_or_throw(next_key, prop_value)); - } - - // 4. Perform ! CreateDataPropertyOrThrow(merged, "largestUnit", largestUnit). - MUST(merged->create_data_property_or_throw(vm.names.largestUnit, PrimitiveString::create(vm, move(largest_unit)))); - - // 5. Return merged. - return merged.ptr(); -} - -// 13.19 MaximumTemporalDurationRoundingIncrement ( unit ), https://tc39.es/proposal-temporal/#sec-temporal-maximumtemporaldurationroundingincrement -Optional maximum_temporal_duration_rounding_increment(StringView unit) -{ - // 1. If unit is "year", "month", "week", or "day", then - if (unit.is_one_of("year"sv, "month"sv, "week"sv, "day"sv)) { - // a. Return undefined. - return {}; - } - - // 2. If unit is "hour", then - if (unit == "hour"sv) { - // a. Return 24. - return 24; - } - - // 3. If unit is "minute" or "second", then - if (unit.is_one_of("minute"sv, "second"sv)) { - // a. Return 60. - return 60; - } - - // 4. Assert: unit is one of "millisecond", "microsecond", or "nanosecond". - VERIFY(unit.is_one_of("millisecond"sv, "microsecond"sv, "nanosecond"sv)); - - // 5. Return 1000. - return 1000; -} - -// 13.20 RejectObjectWithCalendarOrTimeZone ( object ), https://tc39.es/proposal-temporal/#sec-temporal-rejectobjectwithcalendarortimezone -ThrowCompletionOr reject_object_with_calendar_or_time_zone(VM& vm, Object& object) -{ - // 1. Assert: Type(object) is Object. - - // 2. If object has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalTime]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then - if (is(object) || is(object) || is(object) || is(object) || is(object) || is(object)) { - // a. Throw a TypeError exception. - return vm.throw_completion(ErrorType::TemporalObjectMustNotHave, "calendar or timeZone"); - } - - // 3. Let calendarProperty be ? Get(object, "calendar"). - auto calendar_property = TRY(object.get(vm.names.calendar)); - - // 4. If calendarProperty is not undefined, then - if (!calendar_property.is_undefined()) { - // a. Throw a TypeError exception. - return vm.throw_completion(ErrorType::TemporalObjectMustNotHave, "calendar"); - } - - // 5. Let timeZoneProperty be ? Get(object, "timeZone"). - auto time_zone_property = TRY(object.get(vm.names.timeZone)); - - // 6. If timeZoneProperty is not undefined, then - if (!time_zone_property.is_undefined()) { - // a. Throw a TypeError exception. - return vm.throw_completion(ErrorType::TemporalObjectMustNotHave, "timeZone"); - } - - return {}; -} - -// 13.21 FormatSecondsStringPart ( second, millisecond, microsecond, nanosecond, precision ), https://tc39.es/proposal-temporal/#sec-temporal-formatsecondsstringpart -ThrowCompletionOr format_seconds_string_part(VM& vm, u8 second, u16 millisecond, u16 microsecond, u16 nanosecond, Variant const& precision) -{ - // 1. Assert: second, millisecond, microsecond, and nanosecond are integers. - - // Non-standard sanity check - if (precision.has()) - VERIFY(precision.get().is_one_of("minute"sv, "auto"sv)); - - // 2. If precision is "minute", return "". - if (precision.has() && precision.get() == "minute"sv) - return String {}; - - // 3. Let secondsString be the string-concatenation of the code unit 0x003A (COLON) and ToZeroPaddedDecimalString(second, 2). - auto seconds_string = TRY_OR_THROW_OOM(vm, String::formatted(":{:02}", second)); - - // 4. Let fraction be millisecond × 10^6 + microsecond × 10^3 + nanosecond. - u32 fraction = millisecond * 1'000'000 + microsecond * 1'000 + nanosecond; - - String fraction_string; - - // 5. If precision is "auto", then - if (precision.has() && precision.get() == "auto"sv) { - // a. If fraction is 0, return secondsString. - if (fraction == 0) - return seconds_string; - - // b. Set fraction to ToZeroPaddedDecimalString(fraction, 9). - fraction_string = TRY_OR_THROW_OOM(vm, String::formatted("{:09}", fraction)); - - // c. Set fraction to the longest possible substring of fraction starting at position 0 and not ending with the code unit 0x0030 (DIGIT ZERO). - fraction_string = TRY_OR_THROW_OOM(vm, fraction_string.trim("0"sv, TrimMode::Right)); - } - // 6. Else, - else { - // a. If precision is 0, return secondsString. - if (precision.get() == 0) - return seconds_string; - - // b. Set fraction to ToZeroPaddedDecimalString(fraction, 9) - fraction_string = TRY_OR_THROW_OOM(vm, String::formatted("{:09}", fraction)); - - // c. Set fraction to the substring of fraction from 0 to precision. - fraction_string = TRY_OR_THROW_OOM(vm, fraction_string.substring_from_byte_offset(0, precision.get())); - } - - // 7. Return the string-concatenation of secondsString, the code unit 0x002E (FULL STOP), and fraction. - return TRY_OR_THROW_OOM(vm, String::formatted("{}.{}", seconds_string, fraction_string)); -} - -// 13.23 GetUnsignedRoundingMode ( roundingMode, isNegative ), https://tc39.es/proposal-temporal/#sec-temporal-getunsignedroundingmode -UnsignedRoundingMode get_unsigned_rounding_mode(StringView rounding_mode, bool is_negative) -{ - // 1. If isNegative is true, return the specification type in the third column of Table 14 where the first column is roundingMode and the second column is "negative". - if (is_negative) { - if (rounding_mode == "ceil"sv) - return UnsignedRoundingMode::Zero; - if (rounding_mode == "floor"sv) - return UnsignedRoundingMode::Infinity; - if (rounding_mode == "expand"sv) - return UnsignedRoundingMode::Infinity; - if (rounding_mode == "trunc"sv) - return UnsignedRoundingMode::Zero; - if (rounding_mode == "halfCeil"sv) - return UnsignedRoundingMode::HalfZero; - if (rounding_mode == "halfFloor"sv) - return UnsignedRoundingMode::HalfInfinity; - if (rounding_mode == "halfExpand"sv) - return UnsignedRoundingMode::HalfInfinity; - if (rounding_mode == "halfTrunc"sv) - return UnsignedRoundingMode::HalfZero; - if (rounding_mode == "halfEven"sv) - return UnsignedRoundingMode::HalfEven; - VERIFY_NOT_REACHED(); - } - // 2. Else, return the specification type in the third column of Table 14 where the first column is roundingMode and the second column is "positive". - else { - if (rounding_mode == "ceil"sv) - return UnsignedRoundingMode::Infinity; - if (rounding_mode == "floor"sv) - return UnsignedRoundingMode::Zero; - if (rounding_mode == "expand"sv) - return UnsignedRoundingMode::Infinity; - if (rounding_mode == "trunc"sv) - return UnsignedRoundingMode::Zero; - if (rounding_mode == "halfCeil"sv) - return UnsignedRoundingMode::HalfInfinity; - if (rounding_mode == "halfFloor"sv) - return UnsignedRoundingMode::HalfZero; - if (rounding_mode == "halfExpand"sv) - return UnsignedRoundingMode::HalfInfinity; - if (rounding_mode == "halfTrunc"sv) - return UnsignedRoundingMode::HalfZero; - if (rounding_mode == "halfEven"sv) - return UnsignedRoundingMode::HalfEven; - VERIFY_NOT_REACHED(); - } -} - -// NOTE: We have two variants of these functions, one using doubles and one using BigInts - most of the time -// doubles will be fine, but take care to choose the right one. The spec is not very clear about this, as -// it uses mathematical values which can be arbitrarily (but not infinitely) large. -// Incidentally V8's Temporal implementation does the same :^) - -// 13.24 ApplyUnsignedRoundingMode ( x, r1, r2, unsignedRoundingMode ), https://tc39.es/proposal-temporal/#sec-temporal-applyunsignedroundingmode -double apply_unsigned_rounding_mode(double x, double r1, double r2, Optional const& unsigned_rounding_mode) -{ - // 1. If x is equal to r1, return r1. - if (x == r1) - return r1; - - // 2. Assert: r1 < x < r2. - VERIFY(r1 < x && x < r2); - - // 3. Assert: unsignedRoundingMode is not undefined. - VERIFY(unsigned_rounding_mode.has_value()); - - // 4. If unsignedRoundingMode is zero, return r1. - if (unsigned_rounding_mode == UnsignedRoundingMode::Zero) - return r1; - - // 5. If unsignedRoundingMode is infinity, return r2. - if (unsigned_rounding_mode == UnsignedRoundingMode::Infinity) - return r2; - - // 6. Let d1 be x – r1. - auto d1 = x - r1; - - // 7. Let d2 be r2 – x. - auto d2 = r2 - x; - - // 8. If d1 < d2, return r1. - if (d1 < d2) - return r1; - - // 9. If d2 < d1, return r2. - if (d2 < d1) - return r2; - - // 10. Assert: d1 is equal to d2. - VERIFY(d1 == d2); - - // 11. If unsignedRoundingMode is half-zero, return r1. - if (unsigned_rounding_mode == UnsignedRoundingMode::HalfZero) - return r1; - - // 12. If unsignedRoundingMode is half-infinity, return r2. - if (unsigned_rounding_mode == UnsignedRoundingMode::HalfInfinity) - return r2; - - // 13. Assert: unsignedRoundingMode is half-even. - VERIFY(unsigned_rounding_mode == UnsignedRoundingMode::HalfEven); - - // 14. Let cardinality be (r1 / (r2 – r1)) modulo 2. - auto cardinality = modulo((r1 / (r2 - r1)), 2); - - // 15. If cardinality is 0, return r1. - if (cardinality == 0) - return r1; - - // 16. Return r2. - return r2; -} - -// 13.24 ApplyUnsignedRoundingMode ( x, r1, r2, unsignedRoundingMode ), https://tc39.es/proposal-temporal/#sec-temporal-applyunsignedroundingmode -Crypto::SignedBigInteger apply_unsigned_rounding_mode(Crypto::SignedDivisionResult const& x, Crypto::SignedBigInteger const& r1, Crypto::SignedBigInteger const& r2, Optional const& unsigned_rounding_mode, Crypto::UnsignedBigInteger const& increment) -{ - // 1. If x is equal to r1, return r1. - if (x.quotient == r1 && x.remainder.unsigned_value().is_zero()) - return r1; - - // 2. Assert: r1 < x < r2. - // NOTE: Skipped for the sake of performance - - // 3. Assert: unsignedRoundingMode is not undefined. - VERIFY(unsigned_rounding_mode.has_value()); - - // 4. If unsignedRoundingMode is zero, return r1. - if (unsigned_rounding_mode == UnsignedRoundingMode::Zero) - return r1; - - // 5. If unsignedRoundingMode is infinity, return r2. - if (unsigned_rounding_mode == UnsignedRoundingMode::Infinity) - return r2; - - // 6. Let d1 be x – r1. - auto d1 = x.remainder.unsigned_value(); - - // 7. Let d2 be r2 – x. - auto d2 = increment.minus(x.remainder.unsigned_value()); - - // 8. If d1 < d2, return r1. - if (d1 < d2) - return r1; - - // 9. If d2 < d1, return r2. - if (d2 < d1) - return r2; - - // 10. Assert: d1 is equal to d2. - // NOTE: Skipped for the sake of performance - - // 11. If unsignedRoundingMode is half-zero, return r1. - if (unsigned_rounding_mode == UnsignedRoundingMode::HalfZero) - return r1; - - // 12. If unsignedRoundingMode is half-infinity, return r2. - if (unsigned_rounding_mode == UnsignedRoundingMode::HalfInfinity) - return r2; - - // 13. Assert: unsignedRoundingMode is half-even. - VERIFY(unsigned_rounding_mode == UnsignedRoundingMode::HalfEven); - - // 14. Let cardinality be (r1 / (r2 – r1)) modulo 2. - auto cardinality = modulo(r1.divided_by(r2.minus(r1)).quotient, "2"_bigint); - - // 15. If cardinality is 0, return r1. - if (cardinality.unsigned_value().is_zero()) - return r1; - - // 16. Return r2. - return r2; -} - -// 13.25 RoundNumberToIncrement ( x, increment, roundingMode ), https://tc39.es/proposal-temporal/#sec-temporal-roundnumbertoincrement -double round_number_to_increment(double x, u64 increment, StringView rounding_mode) -{ - VERIFY(rounding_mode.is_one_of("ceil"sv, "floor"sv, "expand"sv, "trunc"sv, "halfCeil"sv, "halfFloor"sv, "halfExpand"sv, "halfTrunc"sv, "halfEven"sv)); - - // 1. Let quotient be x / increment. - auto quotient = x / static_cast(increment); - - bool is_negative; - - // 2. If quotient < 0, then - if (quotient < 0) { - // a. Let isNegative be true. - is_negative = true; - - // b. Set quotient to -quotient. - quotient = -quotient; - } - // 3. Else, - else { - // a. Let isNegative be false. - is_negative = false; - } - - // 4. Let unsignedRoundingMode be GetUnsignedRoundingMode(roundingMode, isNegative). - auto unsigned_rounding_mode = get_unsigned_rounding_mode(rounding_mode, is_negative); - - // 5. Let r1 be the largest integer such that r1 ≤ quotient. - auto r1 = floor(quotient); - - // 6. Let r2 be the smallest integer such that r2 > quotient. - auto r2 = ceil(quotient); - if (quotient == r2) - r2++; - - // 7. Let rounded be ApplyUnsignedRoundingMode(quotient, r1, r2, unsignedRoundingMode). - auto rounded = apply_unsigned_rounding_mode(quotient, r1, r2, unsigned_rounding_mode); - - // 8. If isNegative is true, set rounded to -rounded. - if (is_negative) - rounded = -rounded; - - // 9. Return rounded × increment. - return rounded * static_cast(increment); -} - -// 13.25 RoundNumberToIncrement ( x, increment, roundingMode ), https://tc39.es/proposal-temporal/#sec-temporal-roundnumbertoincrement -Crypto::SignedBigInteger round_number_to_increment(Crypto::SignedBigInteger const& x, u64 increment, StringView rounding_mode) -{ - VERIFY(rounding_mode.is_one_of("ceil"sv, "floor"sv, "expand"sv, "trunc"sv, "halfCeil"sv, "halfFloor"sv, "halfExpand"sv, "halfTrunc"sv, "halfEven"sv)); - - // OPTIMIZATION: If the increment is 1 the number is always rounded - if (increment == 1) - return x; - - auto increment_big_int = Crypto::UnsignedBigInteger { increment }; - - // 1. Let quotient be x / increment. - auto division_result = x.divided_by(increment_big_int); - - // OPTIMIZATION: If there's no remainder the number is already rounded - if (division_result.remainder.unsigned_value().is_zero()) - return x; - - bool is_negative; - - // 2. If quotient < 0, then - if (division_result.quotient.is_negative()) { - // a. Let isNegative be true. - is_negative = true; - - // b. Set quotient to -quotient. - division_result.quotient.negate(); - division_result.remainder.negate(); - } - // 3. Else, - else { - // a. Let isNegative be false. - is_negative = false; - } - - // 4. Let unsignedRoundingMode be GetUnsignedRoundingMode(roundingMode, isNegative). - auto unsigned_rounding_mode = get_unsigned_rounding_mode(rounding_mode, is_negative); - - // 5. Let r1 be the largest integer such that r1 ≤ quotient. - auto r1 = division_result.quotient; - - // 6. Let r2 be the smallest integer such that r2 > quotient. - auto r2 = division_result.quotient.plus("1"_bigint); - - // 7. Let rounded be ApplyUnsignedRoundingMode(quotient, r1, r2, unsignedRoundingMode). - auto rounded = apply_unsigned_rounding_mode(division_result, r1, r2, unsigned_rounding_mode, increment_big_int); - - // 8. If isNegative is true, set rounded to -rounded. - if (is_negative) - rounded.negate(); - - // 9. Return rounded × increment. - return rounded.multiplied_by(increment_big_int); -} - -// 13.26 RoundNumberToIncrementAsIfPositive ( x, increment, roundingMode ), https://tc39.es/proposal-temporal/#sec-temporal-roundnumbertoincrementasifpositive -Crypto::SignedBigInteger round_number_to_increment_as_if_positive(Crypto::SignedBigInteger const& x, u64 increment, StringView rounding_mode) -{ - VERIFY(rounding_mode.is_one_of("ceil"sv, "floor"sv, "expand"sv, "trunc"sv, "halfCeil"sv, "halfFloor"sv, "halfExpand"sv, "halfTrunc"sv, "halfEven"sv)); - - // OPTIMIZATION: If the increment is 1 the number is always rounded - if (increment == 1) - return x; - - auto increment_big_int = Crypto::UnsignedBigInteger { increment }; - - // 1. Let quotient be x / increment. - auto division_result = x.divided_by(increment_big_int); - - // OPTIMIZATION: If there's no remainder the number is already rounded - if (division_result.remainder.unsigned_value().is_zero()) - return x; - - // 2. Let unsignedRoundingMode be GetUnsignedRoundingMode(roundingMode, false). - auto unsigned_rounding_mode = get_unsigned_rounding_mode(rounding_mode, false); - - // 3. Let r1 be the largest integer such that r1 ≤ quotient. - auto r1 = division_result.quotient; - - // 4. Let r2 be the smallest integer such that r2 > quotient. - auto r2 = division_result.quotient.plus("1"_bigint); - - // 5. Let rounded be ApplyUnsignedRoundingMode(quotient, r1, r2, unsignedRoundingMode). - auto rounded = apply_unsigned_rounding_mode(division_result, r1, r2, unsigned_rounding_mode, increment_big_int); - - // 6. Return rounded × increment. - return rounded.multiplied_by(increment_big_int); -} - -// 13.28 ParseISODateTime ( isoString ), https://tc39.es/proposal-temporal/#sec-temporal-parseisodatetime -ThrowCompletionOr parse_iso_date_time(VM& vm, StringView iso_string) -{ - // 1. Let parseResult be empty. - Optional parse_result; - - static constexpr auto productions_valid_with_any_calendar = AK::Array { - Production::TemporalDateTimeString, - Production::TemporalInstantString, - Production::TemporalTimeString, - Production::TemporalZonedDateTimeString, - }; - - // 2. For each nonterminal goal of « TemporalDateTimeString, TemporalInstantString, TemporalTimeString, TemporalZonedDateTimeString », do - for (auto goal : productions_valid_with_any_calendar) { - // a. If parseResult is not a Parse Node, set parseResult to ParseText(StringToCodePoints(isoString), goal). - parse_result = parse_iso8601(goal, iso_string); - if (parse_result.has_value()) - break; - } - - static constexpr auto productions_valid_only_with_iso8601_calendar = AK::Array { - Production::TemporalMonthDayString, - Production::TemporalYearMonthString, - }; - - // 3. For each nonterminal goal of « TemporalMonthDayString, TemporalYearMonthString », do - for (auto goal : productions_valid_only_with_iso8601_calendar) { - // a. If parseResult is not a Parse Node, then - if (!parse_result.has_value()) { - // i. Set parseResult to ParseText(StringToCodePoints(isoString), goal). - parse_result = parse_iso8601(goal, iso_string); - - // NOTE: This is not done in parse_iso_date_time(VM, ParseResult) below because MonthDay and YearMonth must re-parse their strings, - // as the string could actually be a superset string above in `productions_valid_with_any_calendar` and thus not hit this code path at all. - // All other users of parse_iso_date_time(VM, ParseResult) pass in a ParseResult resulting from a production in `productions_valid_with_any_calendar`, - // and thus cannot hit this code path as they would first parse in step 2 and not step 3. - // ii. If parseResult is a Parse Node, then - if (parse_result.has_value()) { - // 1. For each Annotation Parse Node annotation contained within parseResult, do - for (auto const& annotation : parse_result->annotations) { - // a. Let key be the source text matched by the AnnotationKey Parse Node contained within annotation. - auto const& key = annotation.key; - - // b. Let value be the source text matched by the AnnotationValue Parse Node contained within annotation. - auto const& value = annotation.value; - - // c. If CodePointsToString(key) is "u-ca" and the ASCII-lowercase of CodePointsToString(value) is not "iso8601", throw a RangeError exception. - if (key == "u-ca"sv && value.to_lowercase_string() != "iso8601"sv) { - if (goal == Production::TemporalMonthDayString) - return vm.throw_completion(ErrorType::TemporalOnlyISO8601WithMonthDayString); - else - return vm.throw_completion(ErrorType::TemporalOnlyISO8601WithYearMonthString); - } - } - } - } - } - - // 4. If parseResult is not a Parse Node, throw a RangeError exception. - if (!parse_result.has_value()) - return vm.throw_completion(ErrorType::TemporalInvalidISODateTime); - - return parse_iso_date_time(vm, *parse_result); -} - -// 13.28 ParseISODateTime ( isoString ), https://tc39.es/proposal-temporal/#sec-temporal-parseisodatetime -ThrowCompletionOr parse_iso_date_time(VM& vm, ParseResult const& parse_result) -{ - // NOTE: Steps 1-4 is handled in parse_iso_date_time(VM, StringView) above. - // 5. Let each of year, month, day, hour, minute, second, and fSeconds be the source text matched by the respective DateYear, DateMonth, DateDay, TimeHour, TimeMinute, TimeSecond, and TimeFraction Parse Node contained within parseResult, or an empty sequence of code points if not present. - auto year = parse_result.date_year; - auto month = parse_result.date_month; - auto day = parse_result.date_day; - auto hour = parse_result.time_hour; - auto minute = parse_result.time_minute; - auto second = parse_result.time_second; - auto f_seconds = parse_result.time_fraction; - - // 6. If the first code point of year is U+2212 (MINUS SIGN), replace the first code point with U+002D (HYPHEN-MINUS). - Optional normalized_year; - if (year.has_value()) { - normalized_year = year->starts_with("\xE2\x88\x92"sv) - ? TRY_OR_THROW_OOM(vm, String::formatted("-{}", year->substring_view(3))) - : TRY_OR_THROW_OOM(vm, String::from_utf8(*year)); - } - - // 7. Let yearMV be ! ToIntegerOrInfinity(CodePointsToString(year)). - auto year_mv = *normalized_year.value_or("0"_string).to_number(); - - // 8. If month is empty, then - // a. Let monthMV be 1. - // 9. Else, - // a. Let monthMV be ! ToIntegerOrInfinity(CodePointsToString(month)). - auto month_mv = *month.value_or("1"sv).to_number(); - - // 10. If day is empty, then - // a. Let dayMV be 1. - // 11. Else, - // a. Let dayMV be ! ToIntegerOrInfinity(CodePointsToString(day)). - auto day_mv = *day.value_or("1"sv).to_number(); - - // 12. Let hourMV be ! ToIntegerOrInfinity(CodePointsToString(hour)). - auto hour_mv = *hour.value_or("0"sv).to_number(); - - // 13. Let minuteMV be ! ToIntegerOrInfinity(CodePointsToString(minute)). - auto minute_mv = *minute.value_or("0"sv).to_number(); - - // 14. Let secondMV be ! ToIntegerOrInfinity(CodePointsToString(second)). - auto second_mv = *second.value_or("0"sv).to_number(); - - // 15. If secondMV is 60, then - if (second_mv == 60) { - // a. Set secondMV to 59. - second_mv = 59; - } - - u16 millisecond_mv; - u16 microsecond_mv; - u16 nanosecond_mv; - - // 16. If fSeconds is not empty, then - if (f_seconds.has_value()) { - // a. Let fSecondsDigits be the substring of CodePointsToString(fSeconds) from 1. - auto f_seconds_digits = f_seconds->substring_view(1); - - // b. Let fSecondsDigitsExtended be the string-concatenation of fSecondsDigits and "000000000". - auto f_seconds_digits_extended = TRY_OR_THROW_OOM(vm, String::formatted("{}000000000", f_seconds_digits)); - - // c. Let millisecond be the substring of fSecondsDigitsExtended from 0 to 3. - auto millisecond = TRY_OR_THROW_OOM(vm, f_seconds_digits_extended.substring_from_byte_offset_with_shared_superstring(0, 3)); - - // d. Let microsecond be the substring of fSecondsDigitsExtended from 3 to 6. - auto microsecond = TRY_OR_THROW_OOM(vm, f_seconds_digits_extended.substring_from_byte_offset_with_shared_superstring(3, 3)); - - // e. Let nanosecond be the substring of fSecondsDigitsExtended from 6 to 9. - auto nanosecond = TRY_OR_THROW_OOM(vm, f_seconds_digits_extended.substring_from_byte_offset_with_shared_superstring(6, 3)); - - // f. Let millisecondMV be ! ToIntegerOrInfinity(millisecond). - millisecond_mv = *millisecond.to_number(); - - // g. Let microsecondMV be ! ToIntegerOrInfinity(microsecond). - microsecond_mv = *microsecond.to_number(); - - // h. Let nanosecondMV be ! ToIntegerOrInfinity(nanosecond). - nanosecond_mv = *nanosecond.to_number(); - } - // 17. Else, - else { - // a. Let millisecondMV be 0. - millisecond_mv = 0; - - // b. Let microsecondMV be 0. - microsecond_mv = 0; - - // c. Let nanosecondMV be 0. - nanosecond_mv = 0; - } - - // 18. If IsValidISODate(yearMV, monthMV, dayMV) is false, throw a RangeError exception. - if (!is_valid_iso_date(year_mv, month_mv, day_mv)) - return vm.throw_completion(ErrorType::TemporalInvalidISODate); - - // 19. If IsValidTime(hourMV, minuteMV, secondMV, millisecondMV, microsecondMV, nanosecondMV) is false, throw a RangeError exception. - if (!is_valid_time(hour_mv, minute_mv, second_mv, millisecond_mv, microsecond_mv, nanosecond_mv)) - return vm.throw_completion(ErrorType::TemporalInvalidTime); - - // 20. Let timeZoneResult be the Record { [[Z]]: false, [[OffsetString]]: undefined, [[Name]]: undefined }. - auto time_zone_result = TemporalTimeZone { .z = false, .offset_string = {}, .name = {} }; - - // 21. If parseResult contains a TimeZoneIdentifier Parse Node, then - if (parse_result.time_zone_identifier.has_value()) { - // a. Let name be the source text matched by the TimeZoneIdentifier Parse Node contained within parseResult. - auto name = parse_result.time_zone_identifier; - - // b. Set timeZoneResult.[[Name]] to CodePointsToString(name). - time_zone_result.name = TRY_OR_THROW_OOM(vm, String::from_utf8(*name)); - } - - // 22. If parseResult contains a UTCDesignator Parse Node, then - if (parse_result.utc_designator.has_value()) { - // a. Set timeZoneResult.[[Z]] to true. - time_zone_result.z = true; - } - // 23. Else, - else { - // a. If parseResult contains a TimeZoneNumericUTCOffset Parse Node, then - if (parse_result.time_zone_numeric_utc_offset.has_value()) { - // i. Let offset be the source text matched by the TimeZoneNumericUTCOffset Parse Node contained within parseResult. - auto offset = parse_result.time_zone_numeric_utc_offset; - - // ii. Set timeZoneResult.[[OffsetString]] to CodePointsToString(offset). - time_zone_result.offset_string = TRY_OR_THROW_OOM(vm, String::from_utf8(*offset)); - } - } - - // 23. Let calendar be undefined. - Optional calendar; - - // 25. For each Annotation Parse Node annotation contained within parseResult, do - for (auto const& annotation : parse_result.annotations) { - // a. Let key be the source text matched by the AnnotationKey Parse Node contained within annotation. - auto const& key = annotation.key; - - // b. If CodePointsToString(key) is "u-ca", then - if (key == "u-ca"sv) { - // i. If calendar is undefined, then - if (!calendar.has_value()) { - // 1. Let value be the source text matched by the AnnotationValue Parse Node contained within annotation. - auto const& value = annotation.value; - - // 2. Let calendar be CodePointsToString(value). - calendar = TRY_OR_THROW_OOM(vm, String::from_utf8(value)); - } - } - // c. Else, - else { - // i. If annotation contains an AnnotationCriticalFlag Parse Node, throw a RangeError exception. - if (annotation.critical) - return vm.throw_completion(ErrorType::TemporalUnknownCriticalAnnotation, key); - } - } - - // 26. Return the Record { [[Year]]: yearMV, [[Month]]: monthMV, [[Day]]: dayMV, [[Hour]]: hourMV, [[Minute]]: minuteMV, [[Second]]: secondMV, [[Millisecond]]: millisecondMV, [[Microsecond]]: microsecondMV, [[Nanosecond]]: nanosecondMV, [[TimeZone]]: timeZoneResult, [[Calendar]]: calendar }. - return ISODateTime { .year = year_mv, .month = month_mv, .day = day_mv, .hour = hour_mv, .minute = minute_mv, .second = second_mv, .millisecond = millisecond_mv, .microsecond = microsecond_mv, .nanosecond = nanosecond_mv, .time_zone = move(time_zone_result), .calendar = move(calendar) }; -} - -// 13.29 ParseTemporalInstantString ( isoString ), https://tc39.es/proposal-temporal/#sec-temporal-parsetemporalinstantstring -ThrowCompletionOr parse_temporal_instant_string(VM& vm, StringView iso_string) -{ - // 1. If ParseText(StringToCodePoints(isoString), TemporalInstantString) is a List of errors, throw a RangeError exception. - auto parse_result = parse_iso8601(Production::TemporalInstantString, iso_string); - if (!parse_result.has_value()) - return vm.throw_completion(ErrorType::TemporalInvalidInstantString, iso_string); - - // 2. Let result be ? ParseISODateTime(isoString). - auto result = TRY(parse_iso_date_time(vm, *parse_result)); - - // 3. Let offsetString be result.[[TimeZone]].[[OffsetString]]. - auto offset_string = result.time_zone.offset_string; - - // 4. If result.[[TimeZone]].[[Z]] is true, then - if (result.time_zone.z) { - // a. Set offsetString to "+00:00". - offset_string = "+00:00"_string; - } - - // 6. Assert: offsetString is not undefined. - VERIFY(offset_string.has_value()); - - // 7. Return the Record { [[Year]]: result.[[Year]], [[Month]]: result.[[Month]], [[Day]]: result.[[Day]], [[Hour]]: result.[[Hour]], [[Minute]]: result.[[Minute]], [[Second]]: result.[[Second]], [[Millisecond]]: result.[[Millisecond]], [[Microsecond]]: result.[[Microsecond]], [[Nanosecond]]: result.[[Nanosecond]], [[TimeZoneOffsetString]]: offsetString }. - return TemporalInstant { .year = result.year, .month = result.month, .day = result.day, .hour = result.hour, .minute = result.minute, .second = result.second, .millisecond = result.millisecond, .microsecond = result.microsecond, .nanosecond = result.nanosecond, .time_zone_offset = move(offset_string) }; -} - -// 13.30 ParseTemporalZonedDateTimeString ( isoString ), https://tc39.es/proposal-temporal/#sec-temporal-parsetemporalzoneddatetimestring -ThrowCompletionOr parse_temporal_zoned_date_time_string(VM& vm, StringView iso_string) -{ - // 1. If ParseText(StringToCodePoints(isoString), TemporalZonedDateTimeString) is a List of errors, throw a RangeError exception. - auto parse_result = parse_iso8601(Production::TemporalZonedDateTimeString, iso_string); - if (!parse_result.has_value()) - return vm.throw_completion(ErrorType::TemporalInvalidZonedDateTimeString, iso_string); - - // 2. Return ? ParseISODateTime(isoString). - return parse_iso_date_time(vm, *parse_result); -} - -// 13.31 ParseTemporalCalendarString ( isoString ), https://tc39.es/proposal-temporal/#sec-temporal-parsetemporalcalendarstring -ThrowCompletionOr parse_temporal_calendar_string(VM& vm, StringView iso_string) -{ - // 1. Let parseResult be Completion(ParseISODateTime(isoString)). - auto parse_result_completion = parse_iso_date_time(vm, iso_string); - - // 2. If parseResult is a normal completion, then - if (!parse_result_completion.is_error()) { - // a. Let calendar be parseResult.[[Value]].[[Calendar]]. - auto calendar = parse_result_completion.value().calendar; - - // b. If calendar is undefined, return "iso8601". - if (!calendar.has_value()) - return "iso8601"_string; - // c. Else, return calendar. - else - return calendar.release_value(); - } - // 3. Else, - else { - // a. Set parseResult to ParseText(StringToCodePoints(isoString), AnnotationValue). - auto parse_result = parse_iso8601(Production::AnnotationValue, iso_string); - - // b. If parseResult is a List of errors, throw a RangeError exception. - if (!parse_result.has_value()) - return vm.throw_completion(ErrorType::TemporalInvalidCalendarString, iso_string); - // c. Else, return isoString. - else - return TRY_OR_THROW_OOM(vm, String::from_utf8(iso_string)); - } -} - -// 13.32 ParseTemporalDateString ( isoString ), https://tc39.es/proposal-temporal/#sec-temporal-parsetemporaldatestring -ThrowCompletionOr parse_temporal_date_string(VM& vm, StringView iso_string) -{ - // 1. Let parts be ? ParseTemporalDateTimeString(isoString). - auto parts = TRY(parse_temporal_date_time_string(vm, iso_string)); - - // 2. Return the Record { [[Year]]: parts.[[Year]], [[Month]]: parts.[[Month]], [[Day]]: parts.[[Day]], [[Calendar]]: parts.[[Calendar]] }. - return TemporalDate { .year = parts.year, .month = parts.month, .day = parts.day, .calendar = move(parts.calendar) }; -} - -// 13.33 ParseTemporalDateTimeString ( isoString ), https://tc39.es/proposal-temporal/#sec-temporal-parsetemporaldatetimestring -ThrowCompletionOr parse_temporal_date_time_string(VM& vm, StringView iso_string) -{ - // 1. Let parseResult be ParseText(StringToCodePoints(isoString), TemporalDateTimeString). - auto parse_result = parse_iso8601(Production::TemporalDateTimeString, iso_string); - - // 2. If parseResult is a List of errors, throw a RangeError exception. - if (!parse_result.has_value()) - return vm.throw_completion(ErrorType::TemporalInvalidDateTimeString, iso_string); - - // 3. If parseResult contains a UTCDesignator Parse Node, throw a RangeError exception. - if (parse_result->utc_designator.has_value()) - return vm.throw_completion(ErrorType::TemporalInvalidDateTimeStringUTCDesignator, iso_string); - - // 4. Return ? ParseISODateTime(isoString). - return parse_iso_date_time(vm, *parse_result); -} - -// 13.34 ParseTemporalDurationString ( isoString ), https://tc39.es/proposal-temporal/#sec-temporal-parsetemporaldurationstring -ThrowCompletionOr parse_temporal_duration_string(VM& vm, StringView iso_string) -{ - // 1. Let duration be ParseText(StringToCodePoints(isoString), TemporalDurationString). - auto parse_result = parse_iso8601(Production::TemporalDurationString, iso_string); - - // 2. If duration is a List of errors, throw a RangeError exception. - if (!parse_result.has_value()) - return vm.throw_completion(ErrorType::TemporalInvalidDurationString, iso_string); - - // 3. Let each of sign, years, months, weeks, days, hours, fHours, minutes, fMinutes, seconds, and fSeconds be the source text matched by the respective Sign, DurationYears, DurationMonths, DurationWeeks, DurationDays, DurationWholeHours, DurationHoursFraction, DurationWholeMinutes, DurationMinutesFraction, DurationWholeSeconds, and DurationSecondsFraction Parse Node contained within duration, or an empty sequence of code points if not present. - auto sign_part = parse_result->sign; - auto years_part = parse_result->duration_years; - auto months_part = parse_result->duration_months; - auto weeks_part = parse_result->duration_weeks; - auto days_part = parse_result->duration_days; - auto hours_part = parse_result->duration_whole_hours; - auto f_hours_part = parse_result->duration_hours_fraction; - auto minutes_part = parse_result->duration_whole_minutes; - auto f_minutes_part = parse_result->duration_minutes_fraction; - auto seconds_part = parse_result->duration_whole_seconds; - auto f_seconds_part = parse_result->duration_seconds_fraction; - - // 4. Let yearsMV be ! ToIntegerOrInfinity(CodePointsToString(years)). - auto years = years_part.value_or("0"sv).to_number().release_value(); - - // 5. Let monthsMV be ! ToIntegerOrInfinity(CodePointsToString(months)). - auto months = months_part.value_or("0"sv).to_number().release_value(); - - // 6. Let weeksMV be ! ToIntegerOrInfinity(CodePointsToString(weeks)). - auto weeks = weeks_part.value_or("0"sv).to_number().release_value(); - - // 7. Let daysMV be ! ToIntegerOrInfinity(CodePointsToString(days)). - auto days = days_part.value_or("0"sv).to_number().release_value(); - - // 8. Let hoursMV be ! ToIntegerOrInfinity(CodePointsToString(hours)). - auto hours = hours_part.value_or("0"sv).to_number().release_value(); - - double minutes; - - // 9. If fHours is not empty, then - if (f_hours_part.has_value()) { - // a. If any of minutes, fMinutes, seconds, fSeconds is not empty, throw a RangeError exception. - if (minutes_part.has_value() || f_minutes_part.has_value() || seconds_part.has_value() || f_seconds_part.has_value()) - return vm.throw_completion(ErrorType::TemporalInvalidDurationStringFractionNotLast, iso_string, "hours"sv, "minutes or seconds"sv); - - // b. Let fHoursDigits be the substring of CodePointsToString(fHours) from 1. - auto f_hours_digits = f_hours_part->substring_view(1); - - // c. Let fHoursScale be the length of fHoursDigits. - auto f_hours_scale = (double)f_hours_digits.length(); - - // d. Let minutesMV be ! ToIntegerOrInfinity(fHoursDigits) / 10^fHoursScale × 60. - minutes = f_hours_digits.to_number().release_value() / pow(10., f_hours_scale) * 60; - } - // 10. Else, - else { - // a. Let minutesMV be ! ToIntegerOrInfinity(CodePointsToString(minutes)). - minutes = minutes_part.value_or("0"sv).to_number().release_value(); - } - - double seconds; - - // 11. If fMinutes is not empty, then - if (f_minutes_part.has_value()) { - // a. If any of seconds, fSeconds is not empty, throw a RangeError exception. - if (seconds_part.has_value() || f_seconds_part.has_value()) - return vm.throw_completion(ErrorType::TemporalInvalidDurationStringFractionNotLast, iso_string, "minutes"sv, "seconds"sv); - - // b. Let fMinutesDigits be the substring of CodePointsToString(fMinutes) from 1. - auto f_minutes_digits = f_minutes_part->substring_view(1); - - // c. Let fMinutesScale be the length of fMinutesDigits. - auto f_minutes_scale = (double)f_minutes_digits.length(); - - // d. Let secondsMV be ! ToIntegerOrInfinity(fMinutesDigits) / 10^fMinutesScale × 60. - seconds = f_minutes_digits.to_number().release_value() / pow(10, f_minutes_scale) * 60; - } - // 12. Else if seconds is not empty, then - else if (seconds_part.has_value()) { - // a. Let secondsMV be ! ToIntegerOrInfinity(CodePointsToString(seconds)). - seconds = seconds_part.value_or("0"sv).to_number().release_value(); - } - // 13. Else, - else { - // a. Let secondsMV be remainder(minutesMV, 1) × 60. - seconds = fmod(minutes, 1) * 60; - } - - double milliseconds; - - // 14. If fSeconds is not empty, then - if (f_seconds_part.has_value()) { - // a. Let fSecondsDigits be the substring of CodePointsToString(fSeconds) from 1. - auto f_seconds_digits = f_seconds_part->substring_view(1); - - // b. Let fSecondsScale be the length of fSecondsDigits. - auto f_seconds_scale = (double)f_seconds_digits.length(); - - // c. Let millisecondsMV be ! ToIntegerOrInfinity(fSecondsDigits) / 10^fSecondsScale × 1000. - milliseconds = f_seconds_digits.to_number().release_value() / pow(10, f_seconds_scale) * 1000; - } - // 15. Else, - else { - // a. Let millisecondsMV be remainder(secondsMV, 1) × 1000. - milliseconds = fmod(seconds, 1) * 1000; - } - - // FIXME: This suffers from floating point (im)precision issues - e.g. "PT0.0000001S" ends up - // getting parsed as 99.999999 nanoseconds, which is floor()'d to 99 instead of the - // expected 100. Oof. This is the reason all of these are suffixed with "MV" in the spec: - // mathematical values are not supposed to have this issue. - - // 16. Let microsecondsMV be remainder(millisecondsMV, 1) × 1000. - auto microseconds = fmod(milliseconds, 1) * 1000; - - // 17. Let nanosecondsMV be remainder(microsecondsMV, 1) × 1000. - auto nanoseconds = fmod(microseconds, 1) * 1000; - - i8 factor; - - // 18. If sign contains the code point U+002D (HYPHEN-MINUS) or U+2212 (MINUS SIGN), then - if (sign_part.has_value() && sign_part->is_one_of("-", "\u2212")) { - // a. Let factor be -1. - factor = -1; - } - // 19. Else, - else { - // a. Let factor be 1. - factor = 1; - } - - // 20. Return ? CreateDurationRecord(yearsMV × factor, monthsMV × factor, weeksMV × factor, daysMV × factor, hoursMV × factor, floor(minutesMV) × factor, floor(secondsMV) × factor, floor(millisecondsMV) × factor, floor(microsecondsMV) × factor, floor(nanosecondsMV) × factor). - return create_duration_record(vm, years * factor, months * factor, weeks * factor, days * factor, hours * factor, floor(minutes) * factor, floor(seconds) * factor, floor(milliseconds) * factor, floor(microseconds) * factor, floor(nanoseconds) * factor); -} - -// 13.35 ParseTemporalMonthDayString ( isoString ), https://tc39.es/proposal-temporal/#sec-temporal-parsetemporalmonthdaystring -ThrowCompletionOr parse_temporal_month_day_string(VM& vm, StringView iso_string) -{ - // 1. Let parseResult be ParseText(StringToCodePoints(isoString), TemporalMonthDayString). - auto parse_result = parse_iso8601(Production::TemporalMonthDayString, iso_string); - - // 2. If parseResult is a List of errors, throw a RangeError exception. - if (!parse_result.has_value()) - return vm.throw_completion(ErrorType::TemporalInvalidMonthDayString, iso_string); - - // 3. If parseResult contains a UTCDesignator Parse Node, throw a RangeError exception. - if (parse_result->utc_designator.has_value()) - return vm.throw_completion(ErrorType::TemporalInvalidMonthDayStringUTCDesignator, iso_string); - - // 4. Let result be ? ParseISODateTime(isoString). - // NOTE: We must re-parse the string, as MonthDay strings with non-iso8601 calendars are invalid and will cause parse_iso_date_time to throw. - // However, the string could be "2022-12-29[u-ca=gregorian]" for example, which is not a MonthDay string but instead a DateTime string and thus should not throw. - auto result = TRY(parse_iso_date_time(vm, iso_string)); - - // 5. Let year be result.[[Year]]. - Optional year = result.year; - - // 6. If parseResult does not contain a DateYear Parse Node, then - if (!parse_result->date_year.has_value()) { - // a. Set year to undefined. - year = {}; - } - - // 7. Return the Record { [[Year]]: year, [[Month]]: result.[[Month]], [[Day]]: result.[[Day]], [[Calendar]]: result.[[Calendar]] }. - return TemporalMonthDay { .year = year, .month = result.month, .day = result.day, .calendar = move(result.calendar) }; -} - -// 13.36 ParseTemporalRelativeToString ( isoString ), https://tc39.es/proposal-temporal/#sec-temporal-parsetemporalrelativetostring -ThrowCompletionOr parse_temporal_relative_to_string(VM& vm, StringView iso_string) -{ - // 1. Let parseResult be ParseText(StringToCodePoints(isoString), TemporalDateTimeString). - auto parse_result = parse_iso8601(Production::TemporalDateTimeString, iso_string); - - // 2. If parseResult is a List of errors, throw a RangeError exception. - if (!parse_result.has_value()) - return vm.throw_completion(ErrorType::TemporalInvalidDateTimeString, iso_string); - - // 3. If parseResult contains a UTCDesignator ParseNode but no TimeZoneAnnotation Parse Node, throw a RangeError exception. - if (parse_result->utc_designator.has_value() && !parse_result->time_zone_annotation.has_value()) - return vm.throw_completion(ErrorType::TemporalInvalidRelativeToStringUTCDesignatorWithoutBracketedTimeZone, iso_string); - - // 4. Return ? ParseISODateTime(isoString). - return parse_iso_date_time(vm, *parse_result); -} - -// 13.37 ParseTemporalTimeString ( isoString ), https://tc39.es/proposal-temporal/#sec-temporal-parsetemporaltimestring -ThrowCompletionOr parse_temporal_time_string(VM& vm, StringView iso_string) -{ - // 1. Let parseResult be ParseText(StringToCodePoints(isoString), TemporalTimeString). - auto parse_result = parse_iso8601(Production::TemporalTimeString, iso_string); - - // 2. If parseResult is a List of errors, throw a RangeError exception. - if (!parse_result.has_value()) - return vm.throw_completion(ErrorType::TemporalInvalidTimeString, iso_string); - - // 3. If parseResult contains a UTCDesignator Parse Node, throw a RangeError exception. - if (parse_result->utc_designator.has_value()) - return vm.throw_completion(ErrorType::TemporalInvalidTimeStringUTCDesignator, iso_string); - - // 4. Let result be ? ParseISODateTime(isoString). - auto result = TRY(parse_iso_date_time(vm, *parse_result)); - - // 5. Return the Record { [[Hour]]: result.[[Hour]], [[Minute]]: result.[[Minute]], [[Second]]: result.[[Second]], [[Millisecond]]: result.[[Millisecond]], [[Microsecond]]: result.[[Microsecond]], [[Nanosecond]]: result.[[Nanosecond]], [[Calendar]]: result.[[Calendar]] }. - return TemporalTime { .hour = result.hour, .minute = result.minute, .second = result.second, .millisecond = result.millisecond, .microsecond = result.microsecond, .nanosecond = result.nanosecond, .calendar = move(result.calendar) }; -} - -// 13.38 ParseTemporalTimeZoneString ( timeZoneString ), https://tc39.es/proposal-temporal/#sec-temporal-parsetemporaltimezonestring -ThrowCompletionOr parse_temporal_time_zone_string(VM& vm, StringView time_zone_string) -{ - // 1. Let parseResult be ParseText(StringToCodePoints(timeZoneString), TimeZoneIdentifier). - auto parse_result = parse_iso8601(Production::TimeZoneIdentifier, time_zone_string); - - // 2. If parseResult is a Parse Node, then - if (parse_result.has_value()) { - // a. Return the Record { [[Z]]: false, [[OffsetString]]: undefined, [[Name]]: timeZoneString }. - return TemporalTimeZone { .z = false, .offset_string = {}, .name = TRY_OR_THROW_OOM(vm, String::from_utf8(time_zone_string)) }; - } - - // 3. Let result be ? ParseISODateTime(timeZoneString). - auto result = TRY(parse_iso_date_time(vm, time_zone_string)); - - // 4. Let timeZoneResult be result.[[TimeZone]]. - auto const& time_zone_result = result.time_zone; - - // 5. If timeZoneResult.[[Z]] is false, timeZoneResult.[[OffsetString]] is undefined, and timeZoneResult.[[Name]] is undefined, throw a RangeError exception. - if (!time_zone_result.z && !time_zone_result.offset_string.has_value() && !time_zone_result.name.has_value()) - return vm.throw_completion(ErrorType::TemporalInvalidTimeZoneString, time_zone_string); - - // 6. Return timeZoneResult. - return time_zone_result; -} - -// 13.39 ParseTemporalYearMonthString ( isoString ), https://tc39.es/proposal-temporal/#sec-temporal-parsetemporalyearmonthstring -ThrowCompletionOr parse_temporal_year_month_string(VM& vm, StringView iso_string) -{ - // 1. Let parseResult be ParseText(StringToCodePoints(isoString), TemporalYearMonthString). - auto parse_result = parse_iso8601(Production::TemporalYearMonthString, iso_string); - - // 2. If parseResult is a List of errors, throw a RangeError exception. - if (!parse_result.has_value()) - return vm.throw_completion(ErrorType::TemporalInvalidYearMonthString, iso_string); - - // 3. If parseResult contains a UTCDesignator Parse Node, throw a RangeError exception. - if (parse_result->utc_designator.has_value()) - return vm.throw_completion(ErrorType::TemporalInvalidYearMonthStringUTCDesignator, iso_string); - - // 4. Let result be ? ParseISODateTime(isoString). - // NOTE: We must re-parse the string, as YearMonth strings with non-iso8601 calendars are invalid and will cause parse_iso_date_time to throw. - // However, the string could be "2022-12-29[u-ca=invalid]" for example, which is not a YearMonth string but instead a DateTime string and thus should not throw. - auto result = TRY(parse_iso_date_time(vm, iso_string)); - - // 5. Return the Record { [[Year]]: result.[[Year]], [[Month]]: result.[[Month]], [[Day]]: result.[[Day]], [[Calendar]]: result.[[Calendar]] }. - return TemporalYearMonth { .year = result.year, .month = result.month, .day = result.day, .calendar = move(result.calendar) }; -} - -// 13.40 ToPositiveIntegerWithTruncation ( argument ), https://tc39.es/proposal-temporal/#sec-temporal-topositiveintegerwithtruncation -ThrowCompletionOr to_positive_integer_with_truncation(VM& vm, Value argument) -{ - // 1. Let integer be ? ToIntegerWithTruncation(argument). - auto integer = TRY(to_integer_with_truncation(vm, argument, ErrorType::TemporalPropertyMustBePositiveInteger)); - - // 2. If integer ≤ 0, throw a RangeError exception. - if (integer <= 0) { - return vm.throw_completion(ErrorType::TemporalPropertyMustBePositiveInteger); - } - - // 3. Return integer. - return integer; -} - -// 13.43 PrepareTemporalFields ( fields, fieldNames, requiredFields ), https://tc39.es/proposal-temporal/#sec-temporal-preparetemporalfields -ThrowCompletionOr prepare_temporal_fields(VM& vm, Object const& fields, Vector const& field_names, Variant> const& required_fields) -{ - auto& realm = *vm.current_realm(); - - // 1. Let result be OrdinaryObjectCreate(null). - auto result = Object::create(realm, nullptr); - VERIFY(result); - - // 2. Let any be false. - auto any = false; - - // 3. For each value property of fieldNames, do - for (auto& property : field_names) { - // a. Let value be ? Get(fields, property). - auto value = TRY(fields.get(property.to_byte_string())); - - // b. If value is not undefined, then - if (!value.is_undefined()) { - // i. Set any to true. - any = true; - - // ii. If property is in the Property column of Table 15 and there is a Conversion value in the same row, then - // 1. Let Conversion be the Conversion value of the same row. - // 2. If Conversion is ToIntegerWithTruncation, then - if (property.is_one_of("year"sv, "hour"sv, "minute"sv, "second"sv, "millisecond"sv, "microsecond"sv, "nanosecond"sv, "eraYear"sv)) { - // a. Set value to ? ToIntegerWithTruncation(value). - // b. Set value to 𝔽(value). - value = Value(TRY(to_integer_with_truncation(vm, value, ErrorType::TemporalPropertyMustBeFinite))); - } - // 3. Else if Conversion is ToPositiveIntegerWithTruncation, then - else if (property.is_one_of("month"sv, "day"sv)) { - // a. Set value to ? ToPositiveIntegerWithTruncation(value). - // b. Set value to 𝔽(value). - value = Value(TRY(to_positive_integer_with_truncation(vm, value))); - } - // 4. Else, - else if (property.is_one_of("monthCode"sv, "offset"sv, "era"sv)) { - // a. Assert: Conversion is ToString. - // b. Set value to ? ToString(value). - value = TRY(value.to_primitive_string(vm)); - } - - // iii. Perform ! CreateDataPropertyOrThrow(result, property, value). - MUST(result->create_data_property_or_throw(property.to_byte_string(), value)); - } - // c. Else if requiredFields is a List, then - else if (required_fields.has>()) { - // i. If requiredFields contains property, then - if (required_fields.get>().contains_slow(property)) { - // 1. Throw a TypeError exception. - return vm.throw_completion(ErrorType::MissingRequiredProperty, property); - } - // ii. If property is in the Property column of Table 13, then - // NOTE: The other properties in the table are automatically handled as their default value is undefined - if (property.is_one_of("hour"sv, "minute"sv, "second"sv, "millisecond"sv, "microsecond"sv, "nanosecond"sv)) { - // 1. Set value to the corresponding Default value of the same row. - value = Value(0); - } - - // iii. Perform ! CreateDataPropertyOrThrow(result, property, value). - MUST(result->create_data_property_or_throw(property.to_byte_string(), value)); - } - } - - // 4. If requiredFields is partial and any is false, then - if (required_fields.has() && !any) { - // a. Throw a TypeError exception. - return vm.throw_completion(ErrorType::TemporalObjectMustHaveOneOf, TRY_OR_THROW_OOM(vm, String::join(", "sv, field_names))); - } - - // 5. Return result. - return result.ptr(); -} - -// 13.44 GetDifferenceSettings ( operation, options, unitGroup, disallowedUnits, fallbackSmallestUnit, smallestLargestDefaultUnit ), https://tc39.es/proposal-temporal/#sec-temporal-getdifferencesettings -ThrowCompletionOr get_difference_settings(VM& vm, DifferenceOperation operation, Value options_value, UnitGroup unit_group, Vector const& disallowed_units, TemporalUnitDefault const& fallback_smallest_unit, StringView smallest_largest_default_unit) -{ - // 1. Set options to ? GetOptionsObject(options). - auto* options = TRY(get_options_object(vm, options_value)); - - // 2. Let smallestUnit be ? GetTemporalUnit(options, "smallestUnit", unitGroup, fallbackSmallestUnit). - auto smallest_unit = TRY(get_temporal_unit(vm, *options, vm.names.smallestUnit, unit_group, fallback_smallest_unit)); - - // 3. If disallowedUnits contains smallestUnit, throw a RangeError exception. - if (disallowed_units.contains_slow(*smallest_unit)) - return vm.throw_completion(ErrorType::OptionIsNotValidValue, *smallest_unit, "smallestUnit"sv); - - // 4. Let defaultLargestUnit be ! LargerOfTwoTemporalUnits(smallestLargestDefaultUnit, smallestUnit). - auto default_largest_unit = larger_of_two_temporal_units(smallest_largest_default_unit, *smallest_unit); - - // 5. Let largestUnit be ? GetTemporalUnit(options, "largestUnit", unitGroup, "auto"). - auto largest_unit = TRY(get_temporal_unit(vm, *options, vm.names.largestUnit, unit_group, { "auto"sv })); - - // 6. If disallowedUnits contains largestUnit, throw a RangeError exception. - if (disallowed_units.contains_slow(*largest_unit)) - return vm.throw_completion(ErrorType::OptionIsNotValidValue, *largest_unit, "largestUnit"sv); - - // 7. If largestUnit is "auto", set largestUnit to defaultLargestUnit. - if (largest_unit == "auto"sv) - largest_unit = TRY_OR_THROW_OOM(vm, String::from_utf8(default_largest_unit)); - - // 8. If LargerOfTwoTemporalUnits(largestUnit, smallestUnit) is not largestUnit, throw a RangeError exception. - if (larger_of_two_temporal_units(*largest_unit, *smallest_unit) != largest_unit) - return vm.throw_completion(ErrorType::TemporalInvalidUnitRange, *smallest_unit, *largest_unit); - - // 9. Let roundingMode be ? ToTemporalRoundingMode(options, "trunc"). - auto rounding_mode = TRY(to_temporal_rounding_mode(vm, *options, "trunc"sv)); - - // 10. If operation is since, then - if (operation == DifferenceOperation::Since) { - // a. Set roundingMode to ! NegateTemporalRoundingMode(roundingMode). - rounding_mode = TRY_OR_THROW_OOM(vm, String::from_utf8(negate_temporal_rounding_mode(rounding_mode))); - } - - // 11. Let maximum be ! MaximumTemporalDurationRoundingIncrement(smallestUnit). - auto maximum = maximum_temporal_duration_rounding_increment(*smallest_unit); - - // 12. Let roundingIncrement be ? ToTemporalRoundingIncrement(options). - auto rounding_increment = TRY(to_temporal_rounding_increment(vm, *options)); - - // 13. If maximum is not undefined, perform ? ValidateTemporalRoundingIncrement(roundingIncrement, maximum, false). - if (maximum.has_value()) { - TRY(validate_temporal_rounding_increment(vm, rounding_increment, *maximum, false)); - } - - // 14. Return the Record { [[SmallestUnit]]: smallestUnit, [[LargestUnit]]: largestUnit, [[RoundingMode]]: roundingMode, [[RoundingIncrement]]: roundingIncrement, [[Options]]: options }. - return DifferenceSettings { - .smallest_unit = smallest_unit.release_value(), - .largest_unit = largest_unit.release_value(), - .rounding_mode = move(rounding_mode), - .rounding_increment = rounding_increment, - .options = *options, - }; -} - } diff --git a/Libraries/LibJS/Runtime/Temporal/AbstractOperations.h b/Libraries/LibJS/Runtime/Temporal/AbstractOperations.h index 3007a33bf87..9a9834e29ea 100644 --- a/Libraries/LibJS/Runtime/Temporal/AbstractOperations.h +++ b/Libraries/LibJS/Runtime/Temporal/AbstractOperations.h @@ -7,187 +7,25 @@ #pragma once -#include #include -#include #include #include -#include -#include -#include +#include #include namespace JS::Temporal { -enum class ArithmeticOperation { - Add, - Subtract, -}; - -enum class DifferenceOperation { - Since, - Until, -}; - -enum class UnsignedRoundingMode { - HalfEven, - HalfInfinity, - HalfZero, - Infinity, - Zero, -}; - enum class OptionType { Boolean, String, Number }; -enum class UnitGroup { - Date, - Time, - DateTime, -}; - -struct TemporalInstant { - i32 year; - u8 month; - u8 day; - u8 hour; - u8 minute; - u8 second; - u16 millisecond; - u16 microsecond; - u16 nanosecond; - Optional time_zone_offset; -}; - -struct TemporalDate { - i32 year; - u8 month; - u8 day; - Optional calendar; -}; - -struct TemporalTime { - u8 hour; - u8 minute; - u8 second; - u16 millisecond; - u16 microsecond; - u16 nanosecond; - Optional calendar = {}; -}; - -struct TemporalTimeZone { - bool z; - Optional offset_string; - Optional name; -}; - -struct TemporalYearMonth { - i32 year; - u8 month; - u8 day; - Optional calendar = {}; -}; - -struct TemporalMonthDay { - Optional year; - u8 month; - u8 day; - Optional calendar = {}; -}; - -struct ISODateTime { - i32 year; - u8 month; - u8 day; - u8 hour; - u8 minute; - u8 second; - u16 millisecond; - u16 microsecond; - u16 nanosecond; - TemporalTimeZone time_zone { .z = false, .offset_string = {}, .name = {} }; - Optional calendar = {}; -}; - -struct SecondsStringPrecision { - Variant precision; - StringView unit; - u32 increment; -}; - -struct DifferenceSettings { - String smallest_unit; - String largest_unit; - String rounding_mode; - u64 rounding_increment; - GC::Ref options; -}; - -struct TemporalUnitRequired { }; -struct PrepareTemporalFieldsPartial { }; struct GetOptionRequired { }; - using OptionDefault = Variant; -using TemporalUnitDefault = Variant>; -ThrowCompletionOr> iterable_to_list_of_type(VM&, Value items, Vector const& element_types); ThrowCompletionOr get_options_object(VM&, Value options); ThrowCompletionOr get_option(VM&, Object const& options, PropertyKey const& property, OptionType type, ReadonlySpan values, OptionDefault const&); -ThrowCompletionOr to_temporal_overflow(VM&, Object const* options); -ThrowCompletionOr to_temporal_disambiguation(VM&, Object const* options); -ThrowCompletionOr to_temporal_rounding_mode(VM&, Object const& normalized_options, StringView fallback); -StringView negate_temporal_rounding_mode(StringView rounding_mode); -ThrowCompletionOr to_temporal_offset(VM&, Object const* options, StringView fallback); -ThrowCompletionOr to_calendar_name_option(VM&, Object const& normalized_options); -ThrowCompletionOr to_time_zone_name_option(VM&, Object const& normalized_options); -ThrowCompletionOr to_show_offset_option(VM&, Object const& normalized_options); -ThrowCompletionOr to_temporal_rounding_increment(VM& vm, Object const& normalized_options); -ThrowCompletionOr validate_temporal_rounding_increment(VM& vm, u64 increment, u64 dividend, bool inclusive); -ThrowCompletionOr to_seconds_string_precision_record(VM&, Object const& normalized_options); -ThrowCompletionOr> get_temporal_unit(VM&, Object const& normalized_options, PropertyKey const&, UnitGroup, TemporalUnitDefault const& default_, Vector const& extra_values = {}); - -struct RelativeTo { - GC::Ptr plain_relative_to; // [[PlainRelativeTo]] - GC::Ptr zoned_relative_to; // [[ZonedRelativeTo]] - Optional time_zone_record; // [[TimeZoneRec]] -}; -ThrowCompletionOr to_relative_temporal_object(VM&, Object const& options); - -Value relative_to_converted_to_value(RelativeTo const&); - -StringView larger_of_two_temporal_units(StringView, StringView); -ThrowCompletionOr merge_largest_unit_option(VM&, Object const& options, String largest_unit); -Optional maximum_temporal_duration_rounding_increment(StringView unit); -ThrowCompletionOr reject_object_with_calendar_or_time_zone(VM&, Object&); -ThrowCompletionOr format_seconds_string_part(VM&, u8 second, u16 millisecond, u16 microsecond, u16 nanosecond, Variant const& precision); -double sign(double); -double sign(Crypto::SignedBigInteger const&); -UnsignedRoundingMode get_unsigned_rounding_mode(StringView rounding_mode, bool is_negative); -double apply_unsigned_rounding_mode(double x, double r1, double r2, Optional const&); -Crypto::SignedBigInteger apply_unsigned_rounding_mode(Crypto::SignedDivisionResult const&, Crypto::SignedBigInteger const& r1, Crypto::SignedBigInteger const& r2, Optional const&, Crypto::UnsignedBigInteger const& increment); -double round_number_to_increment(double, u64 increment, StringView rounding_mode); -Crypto::SignedBigInteger round_number_to_increment(Crypto::SignedBigInteger const&, u64 increment, StringView rounding_mode); -Crypto::SignedBigInteger round_number_to_increment_as_if_positive(Crypto::SignedBigInteger const&, u64 increment, StringView rounding_mode); -ThrowCompletionOr parse_iso_date_time(VM&, StringView iso_string); -ThrowCompletionOr parse_iso_date_time(VM&, ParseResult const& parse_result); -ThrowCompletionOr parse_temporal_instant_string(VM&, StringView iso_string); -ThrowCompletionOr parse_temporal_zoned_date_time_string(VM&, StringView iso_string); -ThrowCompletionOr parse_temporal_calendar_string(VM&, StringView iso_string); -ThrowCompletionOr parse_temporal_date_string(VM&, StringView iso_string); -ThrowCompletionOr parse_temporal_date_time_string(VM&, StringView iso_string); -ThrowCompletionOr parse_temporal_duration_string(VM&, StringView iso_string); -ThrowCompletionOr parse_temporal_month_day_string(VM&, StringView iso_string); -ThrowCompletionOr parse_temporal_relative_to_string(VM&, StringView iso_string); -ThrowCompletionOr parse_temporal_time_string(VM&, StringView iso_string); -ThrowCompletionOr parse_temporal_time_zone_string(VM&, StringView iso_string); -ThrowCompletionOr parse_temporal_year_month_string(VM&, StringView iso_string); -ThrowCompletionOr to_positive_integer_with_truncation(VM&, Value argument); -ThrowCompletionOr prepare_temporal_fields(VM&, Object const& fields, Vector const& field_names, Variant> const& required_fields); -ThrowCompletionOr get_difference_settings(VM&, DifferenceOperation, Value options_value, UnitGroup unit_group, Vector const& disallowed_units, TemporalUnitDefault const& fallback_smallest_unit, StringView smallest_largest_default_unit); template ThrowCompletionOr get_option(VM& vm, Object const& options, PropertyKey const& property, OptionType type, StringView const (&values)[Size], OptionDefault const& default_) @@ -195,26 +33,6 @@ ThrowCompletionOr get_option(VM& vm, Object const& options, PropertyKey c return get_option(vm, options, property, type, ReadonlySpan { values }, default_); } -// 13.40 ToIntegerWithTruncation ( argument ), https://tc39.es/proposal-temporal/#sec-tointegerwithtruncation -template -ThrowCompletionOr to_integer_with_truncation(VM& vm, Value argument, ErrorType error_type, Args... args) -{ - // 1. Let number be ? ToIntegerOrInfinity(argument). - auto number = TRY(argument.to_number(vm)); - - // 2. If number is NaN, return 0. - if (number.is_nan()) - return 0; - - // 3. If number is +∞𝔽 or -∞𝔽, throw a RangeError exception. - if (Value(number).is_infinity()) { - return vm.template throw_completion(error_type, args...); - } - - // 4. Return truncate(ℝ(number)). - return trunc(number.as_double()); -} - // 13.41 ToIntegerIfIntegral ( argument ), https://tc39.es/proposal-temporal/#sec-tointegerifintegral template ThrowCompletionOr to_integer_if_integral(VM& vm, Value argument, ErrorType error_type, Args... args) diff --git a/Libraries/LibJS/Runtime/Temporal/Calendar.cpp b/Libraries/LibJS/Runtime/Temporal/Calendar.cpp deleted file mode 100644 index d9e6bc198cd..00000000000 --- a/Libraries/LibJS/Runtime/Temporal/Calendar.cpp +++ /dev/null @@ -1,1270 +0,0 @@ -/* - * Copyright (c) 2021, Idan Horowitz - * Copyright (c) 2021-2023, Linus Groh - * Copyright (c) 2023-2024, Shannon Booth - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace JS::Temporal { - -GC_DEFINE_ALLOCATOR(Calendar); - -// 12 Temporal.Calendar Objects, https://tc39.es/proposal-temporal/#sec-temporal-calendar-objects -Calendar::Calendar(String identifier, Object& prototype) - : Object(ConstructWithPrototypeTag::Tag, prototype) - , m_identifier(move(identifier)) -{ -} - -// 12.1.1 IsBuiltinCalendar ( id ), https://tc39.es/proposal-temporal/#sec-temporal-isbuiltincalendar -bool is_builtin_calendar(StringView identifier) -{ - // 1. Let calendars be AvailableCalendars(). - auto calendars = available_calendars(); - - // 2. If calendars contains the ASCII-lowercase of id, return true. - for (auto calendar : calendars) { - if (calendar.equals_ignoring_ascii_case(identifier)) - return true; - } - - // 3. Return false. - return false; -} - -// 12.1.2 AvailableCalendars ( ), https://tc39.es/proposal-temporal/#sec-temporal-availablecalendars -ReadonlySpan available_calendars() -{ - // 1. Let calendars be the List of String values representing calendar types supported by the implementation. - // NOTE: This can be removed in favor of using `Unicode::get_available_calendars()` once everything is updated to handle non-iso8601 calendars. - static constexpr AK::Array calendars { "iso8601"sv }; - - // 2. Assert: calendars contains "iso8601". - // 3. Assert: calendars does not contain any element that does not identify a calendar type in the Unicode Common Locale Data Repository (CLDR). - // 4. Sort calendars in order as if an Array of the same values had been sorted using %Array.prototype.sort% with undefined as comparefn. - - // 5. Return calendars. - return calendars.span(); -} - -// 12.2.2 CreateCalendarMethodsRecord ( calendar, methods ), https://tc39.es/proposal-temporal/#sec-temporal-createcalendarmethodsrecord -ThrowCompletionOr create_calendar_methods_record(VM& vm, Variant> calendar, ReadonlySpan methods) -{ - // 1. Let record be the Calendar Methods Record { [[Receiver]]: calendar, [[DateAdd]]: undefined, [[DateFromFields]]: undefined, [[DateUntil]]: undefined, [[Day]]: undefined, [[Fields]]: undefined, [[MergeFields]]: undefined, [[MonthDayFromFields]]: undefined, [[YearMonthFromFields]]: undefined }. - CalendarMethods record { - .receiver = move(calendar), - .date_add = nullptr, - .date_from_fields = nullptr, - .date_until = nullptr, - .day = nullptr, - .fields = nullptr, - .merge_fields = nullptr, - .month_day_from_fields = nullptr, - .year_month_from_fields = nullptr, - }; - - // 2. For each element methodName in methods, do - for (auto const& method_name : methods) { - // a. Perform ? CalendarMethodsRecordLookup(record, methodName). - TRY(calendar_methods_record_lookup(vm, record, method_name)); - } - - // 3. Return record. - return record; -} - -ThrowCompletionOr> create_calendar_methods_record_from_relative_to(VM& vm, GC::Ptr plain_relative_to, GC::Ptr zoned_relative_to, ReadonlySpan methods) -{ - // FIXME: The casts to GC::Ref should not be here, and can be fixed once PlainDate & ZonedDateTime have the updated type in the [[Calendar]] slot. - - // 1. If zonedRelativeTo is not undefined, return ? CreateCalendarMethodsRecord(zonedRelativeTo.[[Calendar]], methods). - if (zoned_relative_to) - return TRY(create_calendar_methods_record(vm, GC::Ref { zoned_relative_to->calendar() }, methods)); - - // 2. If plainRelativeTo is not undefined, return ? CreateCalendarMethodsRecord(plainRelativeTo.[[Calendar]], methods). - if (plain_relative_to) - return TRY(create_calendar_methods_record(vm, GC::Ref { plain_relative_to->calendar() }, methods)); - - // 3. Return undefined. - return OptionalNone {}; -} - -// 12.2.4 CalendarMethodsRecordLookup ( calendarRec, methodName ), https://tc39.es/proposal-temporal/#sec-temporal-calendarmethodsrecordlookup -ThrowCompletionOr calendar_methods_record_lookup(VM& vm, CalendarMethods& calendar_record, CalendarMethod method_name) -{ - auto& realm = *vm.current_realm(); - - // 1. Assert: CalendarMethodsRecordHasLookedUp(calendarRec, methodName) is false. - // 2. If methodName is DATE-ADD, then - // a. If calendarRec.[[Receiver]] is a String, then - // i. Set calendarRec.[[DateAdd]] to %Temporal.Calendar.prototype.dateAdd%. - // b. Else, - // i. Set calendarRec.[[DateAdd]] to ? GetMethod(calendarRec.[[Receiver]], "dateAdd"). - // ii. If calendarRec.[[DateAdd]] is undefined, throw a TypeError exception. - // 3. Else if methodName is DATE-FROM-FIELDS, then - // a. If calendarRec.[[Receiver]] is a String, then - // i. Set calendarRec.[[DateFromFields]] to %Temporal.Calendar.prototype.dateFromFields%. - // b. Else, - // i. Set calendarRec.[[DateFromFields]] to ? GetMethod(calendarRec.[[Receiver]], "dateFromFields"). - // ii. If calendarRec.[[DateFromFields]] is undefined, throw a TypeError exception. - // 4. Else if methodName is DATE-UNTIL, then - // a. If calendarRec.[[Receiver]] is a String, then - // i. Set calendarRec.[[DateUntil]] to %Temporal.Calendar.prototype.dateUntil%. - // b. Else, - // i. Set calendarRec.[[DateUntil]] to ? GetMethod(calendarRec.[[Receiver]], "dateUntil"). - // ii. If calendarRec.[[DateUntil]] is undefined, throw a TypeError exception. - // 5. Else if methodName is DAY, then - // a. If calendarRec.[[Receiver]] is a String, then - // i. Set calendarRec.[[Day]] to %Temporal.Calendar.prototype.day%. - // b. Else, - // i. Set calendarRec.[[Day]] to ? GetMethod(calendarRec.[[Receiver]], "day"). - // ii. If calendarRec.[[Day]] is undefined, throw a TypeError exception. - // 6. Else if methodName is FIELDS, then - // a. If calendarRec.[[Receiver]] is a String, then - // i. Set calendarRec.[[Fields]] to %Temporal.Calendar.prototype.fields%. - // b. Else, - // i. Set calendarRec.[[Fields]] to ? GetMethod(calendarRec.[[Receiver]], "fields"). - // ii. If calendarRec.[[Fields]] is undefined, throw a TypeError exception. - // 7. Else if methodName is MERGE-FIELDS, then - // a. If calendarRec.[[Receiver]] is a String, then - // i. Set calendarRec.[[MergeFields]] to %Temporal.Calendar.prototype.mergeFields%. - // b. Else, - // i. Set calendarRec.[[MergeFields]] to ? GetMethod(calendarRec.[[Receiver]], "mergeFields"). - // ii. If calendarRec.[[MergeFields]] is undefined, throw a TypeError exception. - // 8. Else if methodName is MONTH-DAY-FROM-FIELDS, then - // a. If calendarRec.[[Receiver]] is a String, then - // i. Set calendarRec.[[MonthDayFromFields]] to %Temporal.Calendar.prototype.monthDayFromFields%. - // b. Else, - // i. Set calendarRec.[[MonthDayFromFields]] to ? GetMethod(calendarRec.[[Receiver]], "monthDayFromFields"). - // ii. If calendarRec.[[MonthDayFromFields]] is undefined, throw a TypeError exception. - // 9. Else if methodName is YEAR-MONTH-FROM-FIELDS, then - // a. If calendarRec.[[Receiver]] is a String, then - // i. Set calendarRec.[[YearMonthFromFields]] to %Temporal.Calendar.prototype.yearMonthFromFields%. - // b. Else, - // i. Set calendarRec.[[YearMonthFromFields]] to ? GetMethod(calendarRec.[[Receiver]], "yearMonthFromFields"). - // ii. If calendarRec.[[YearMonthFromFields]] is undefined, throw a TypeError exception. - switch (method_name) { -#define __JS_ENUMERATE(PascalName, camelName, snake_name) \ - case CalendarMethod::PascalName: { \ - VERIFY(!calendar_record.snake_name); \ - if (calendar_record.receiver.has()) { \ - const auto& calendar_prototype = *realm.intrinsics().temporal_calendar_prototype(); \ - calendar_record.snake_name = calendar_prototype.get_without_side_effects(vm.names.camelName).as_function(); \ - } else { \ - Value calendar { calendar_record.receiver.get>() }; \ - calendar_record.snake_name = TRY(calendar.get_method(vm, vm.names.camelName)); \ - if (!calendar_record.snake_name) \ - return vm.throw_completion(ErrorType::IsUndefined, #camelName##sv); \ - } \ - break; \ - } - JS_ENUMERATE_CALENDAR_METHODS -#undef __JS_ENUMERATE - } - - // 10. Return unused. - return {}; -} - -// 12.2.5 CalendarMethodsRecordHasLookedUp ( calendarRec, methodName ), https://tc39.es/proposal-temporal/#sec-temporal-calendarmethodsrecordhaslookedup -bool calendar_methods_record_has_looked_up(CalendarMethods const& calendar_record, CalendarMethod method_name) -{ - // 1. If methodName is DATE-ADD, then - // a. Let method be calendarRec.[[DateAdd]]. - // 2. Else if methodName is DATE-FROM-FIELDS, then - // a. Let method be calendarRec.[[DateFromFields]]. - // 3. Else if methodName is DATE-UNTIL, then - // a. Let method be calendarRec.[[DateUntil]]. - // 4. Else if methodName is DAY, then - // a. Let method be calendarRec.[[Day]]. - // 5. Else if methodName is FIELDS, then - // a. Let method be calendarRec.[[Fields]]. - // 6. Else if methodName is MERGE-FIELDS, then - // a. Let method be calendarRec.[[MergeFields]]. - // 7. Else if methodName is MONTH-DAY-FROM-FIELDS, then - // a. Let method be calendarRec.[[MonthDayFromFields]]. - // 8. Else if methodName is YEAR-MONTH-FROM-FIELDS, then - // a. Let method be calendarRec.[[YearMonthFromFields]]. - // 9. If method is undefined, return false. - // 10. Return true. - switch (method_name) { -#define __JS_ENUMERATE(PascalName, camelName, snake_name) \ - case CalendarMethod::PascalName: { \ - return calendar_record.snake_name != nullptr; \ - } - JS_ENUMERATE_CALENDAR_METHODS -#undef __JS_ENUMERATE - } - VERIFY_NOT_REACHED(); -} - -// 12.2.6 CalendarMethodsRecordIsBuiltin ( calendarRec ), https://tc39.es/proposal-temporal/#sec-temporal-calendarmethodsrecordisbuiltin -bool calendar_methods_record_is_builtin(CalendarMethods const& calendar_record) -{ - // 1. If calendarRec.[[Receiver]] is a String, return true. - if (calendar_record.receiver.has()) - return true; - - // 2. Return false. - return false; -} - -// 12.2.7 CalendarMethodsRecordCall ( calendarRec, methodName, arguments ), https://tc39.es/proposal-temporal/#sec-temporal-calendarmethodsrecordcall -ThrowCompletionOr calendar_methods_record_call(VM& vm, CalendarMethods const& calendar_record, CalendarMethod method_name, ReadonlySpan arguments) -{ - // 1. Assert: CalendarMethodsRecordHasLookedUp(calendarRec, methodName) is true. - VERIFY(calendar_methods_record_has_looked_up(calendar_record, method_name)); - - // 2. Let receiver be calendarRec.[[Receiver]]. - // 3. If CalendarMethodsRecordIsBuiltin(calendarRec) is true, then - // a. Set receiver to ! CreateTemporalCalendar(calendarRec.[[Receiver]]). - GC::Ptr receiver; - if (calendar_methods_record_is_builtin(calendar_record)) - receiver = MUST(create_temporal_calendar(vm, calendar_record.receiver.get())); - else - receiver = calendar_record.receiver.get>(); - - // 4. If methodName is DATE-ADD, then - // a. Return ? Call(calendarRec.[[DateAdd]], receiver, arguments). - // 5. If methodName is DATE-FROM-FIELDS, then - // a. Return ? Call(calendarRec.[[DateFromFields]], receiver, arguments). - // 6. If methodName is DATE-UNTIL, then - // a. Return ? Call(calendarRec.[[DateUntil]], receiver, arguments). - // 7. If methodName is DAY, then - // a. Return ? Call(calendarRec.[[Day]], receiver, arguments). - // 8. If methodName is FIELDS, then - // a. Return ? Call(calendarRec.[[Fields]], receiver, arguments). - // 9. If methodName is MERGE-FIELDS, then - // a. Return ? Call(calendarRec.[[MergeFields]], receiver, arguments). - // 10. If methodName is MONTH-DAY-FROM-FIELDS, then - // a. Return ? Call(calendarRec.[[MonthDayFromFields]], receiver, arguments). - // 11. If methodName is YEAR-MONTH-FROM-FIELDS, then - // a. Return ? Call(calendarRec.[[YearMonthFromFields]], receiver, arguments). - switch (method_name) { -#define __JS_ENUMERATE(PascalName, camelName, snake_name) \ - case CalendarMethod::PascalName: { \ - return TRY(call(vm, calendar_record.snake_name, receiver, arguments)); \ - } - JS_ENUMERATE_CALENDAR_METHODS -#undef __JS_ENUMERATE - } - VERIFY_NOT_REACHED(); -} - -// 12.2.1 CreateTemporalCalendar ( identifier [ , newTarget ] ), https://tc39.es/proposal-temporal/#sec-temporal-createtemporalcalendar -ThrowCompletionOr create_temporal_calendar(VM& vm, String const& identifier, FunctionObject const* new_target) -{ - auto& realm = *vm.current_realm(); - - // 1. Assert: IsBuiltinCalendar(identifier) is true. - VERIFY(is_builtin_calendar(identifier)); - - // 2. If newTarget is not provided, set newTarget to %Temporal.Calendar%. - if (!new_target) - new_target = realm.intrinsics().temporal_calendar_constructor(); - - // 3. Let object be ? OrdinaryCreateFromConstructor(newTarget, "%Temporal.Calendar.prototype%", « [[InitializedTemporalCalendar]], [[Identifier]] »). - // 4. Set object.[[Identifier]] to the ASCII-lowercase of identifier. - auto object = TRY(ordinary_create_from_constructor(vm, *new_target, &Intrinsics::temporal_calendar_prototype, TRY_OR_THROW_OOM(vm, identifier.to_lowercase()))); - - // 5. Return object. - return object.ptr(); -} - -// 12.2.2 GetBuiltinCalendar ( id ), https://tc39.es/proposal-temporal/#sec-temporal-getbuiltincalendar -ThrowCompletionOr get_builtin_calendar(VM& vm, String const& identifier) -{ - // 1. If IsBuiltinCalendar(id) is false, throw a RangeError exception. - if (!is_builtin_calendar(identifier)) - return vm.throw_completion(ErrorType::TemporalInvalidCalendarIdentifier, identifier); - - // 2. Return ! CreateTemporalCalendar(id). - return MUST_OR_THROW_OOM(create_temporal_calendar(vm, identifier)); -} - -// 12.2.3 GetISO8601Calendar ( ), https://tc39.es/proposal-temporal/#sec-temporal-getiso8601calendar -Calendar* get_iso8601_calendar(VM& vm) -{ - // 1. Return ! GetBuiltinCalendar("iso8601"). - return MUST(get_builtin_calendar(vm, "iso8601"_string)); -} - -// 12.2.4 CalendarFields ( calendar, fieldNames ), https://tc39.es/proposal-temporal/#sec-temporal-calendarfields -ThrowCompletionOr> calendar_fields(VM& vm, Object& calendar, Vector const& field_names) -{ - auto& realm = *vm.current_realm(); - - // 1. Let fields be ? GetMethod(calendar, "fields"). - auto fields = TRY(Value(&calendar).get_method(vm, vm.names.fields)); - - // 2. If fields is undefined, return fieldNames. - if (!fields) { - Vector result; - TRY_OR_THROW_OOM(vm, result.try_ensure_capacity(field_names.size())); - for (auto& value : field_names) - result.unchecked_append(TRY_OR_THROW_OOM(vm, String::from_utf8(value))); - return result; - } - - // 3. Let fieldsArray be ? Call(fields, calendar, « CreateArrayFromList(fieldNames) »). - auto field_names_array = Array::create_from(realm, field_names, [&](auto value) { - return PrimitiveString::create(vm, value); - }); - auto fields_array = TRY(call(vm, *fields, &calendar, field_names_array)); - - // 4. Return ? IterableToListOfType(fieldsArray, « String »). - auto list = TRY(iterable_to_list_of_type(vm, fields_array, { OptionType::String })); - - Vector result; - TRY_OR_THROW_OOM(vm, result.try_ensure_capacity(list.size())); - for (auto& value : list) - result.unchecked_append(value.as_string().utf8_string()); - return result; -} - -// 12.2.5 CalendarMergeFields ( calendar, fields, additionalFields ), https://tc39.es/proposal-temporal/#sec-temporal-calendarmergefields -ThrowCompletionOr calendar_merge_fields(VM& vm, Object& calendar, Object& fields, Object& additional_fields) -{ - // 1. Let mergeFields be ? GetMethod(calendar, "mergeFields"). - auto merge_fields = TRY(Value(&calendar).get_method(vm, vm.names.mergeFields)); - - // 2. If mergeFields is undefined, then - if (!merge_fields) { - // a. Return ? DefaultMergeCalendarFields(fields, additionalFields). - return TRY(default_merge_calendar_fields(vm, fields, additional_fields)); - } - - // 3. Let result be ? Call(mergeFields, calendar, « fields, additionalFields »). - auto result = TRY(call(vm, merge_fields, &calendar, &fields, &additional_fields)); - - // 4. If Type(result) is not Object, throw a TypeError exception. - if (!result.is_object()) - return vm.throw_completion(ErrorType::NotAnObject, result.to_string_without_side_effects()); - - // 5. Return result. - return &result.as_object(); -} - -// 12.2.6 CalendarDateAdd ( calendar, date, duration [ , options [ , dateAdd ] ] ), https://tc39.es/proposal-temporal/#sec-temporal-calendardateadd -ThrowCompletionOr calendar_date_add(VM& vm, Object& calendar, Value date, Duration& duration, Object* options, FunctionObject* date_add) -{ - // NOTE: `date` is a `Value` because we sometimes need to pass a PlainDate, sometimes a PlainDateTime, and sometimes undefined. - - // 1. Assert: Type(calendar) is Object. - // 2. If options is not present, set options to undefined. - // 3. Assert: Type(options) is Object or Undefined. - - // 4. If dateAdd is not present, set dateAdd to ? GetMethod(calendar, "dateAdd"). - if (!date_add) - date_add = TRY(Value(&calendar).get_method(vm, vm.names.dateAdd)); - - // 5. Let addedDate be ? Call(dateAdd, calendar, « date, duration, options »). - auto added_date = TRY(call(vm, date_add ?: js_undefined(), &calendar, date, &duration, options ?: js_undefined())); - - // 6. Perform ? RequireInternalSlot(addedDate, [[InitializedTemporalDate]]). - auto added_date_object = TRY(added_date.to_object(vm)); - if (!is(*added_date_object)) - return vm.throw_completion(ErrorType::NotAnObjectOfType, "Temporal.PlainDate"); - - // 7. Return addedDate. - return static_cast(added_date_object.ptr()); -} - -// 12.2.7 CalendarDateUntil ( calendar, one, two, options [ , dateUntil ] ), https://tc39.es/proposal-temporal/#sec-temporal-calendardateuntil -ThrowCompletionOr> calendar_date_until(VM& vm, CalendarMethods const& calendar_record, Value one, Value two, Object const& options) -{ - // 1. Let duration be ? CalendarMethodsRecordCall(calendarRec, DATE-UNTIL, « one, two, options »). - auto duration = TRY(calendar_methods_record_call(vm, calendar_record, CalendarMethod::DateUntil, Vector { one, two, &options })); - - // 2. If CalendarMethodsRecordIsBuiltin(calendarRec) is true, return duration. - if (calendar_methods_record_is_builtin(calendar_record)) - return verify_cast(duration.as_object()); - - // 3. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]). - auto duration_object = TRY(duration.to_object(vm)); - if (!is(*duration_object)) - return vm.throw_completion(ErrorType::NotAnObjectOfType, "Temporal.Duration"); - - // 4. Return duration. - return static_cast(duration.as_object()); -} - -// 12.2.8 CalendarYear ( calendar, dateLike ), https://tc39.es/proposal-temporal/#sec-temporal-calendaryear -ThrowCompletionOr calendar_year(VM& vm, Object& calendar, Object& date_like) -{ - // 1. Let result be ? Invoke(calendar, "year", « dateLike »). - auto result = TRY(Value(&calendar).invoke(vm, vm.names.year, &date_like)); - - // 2. If result is undefined, throw a RangeError exception. - if (result.is_undefined()) - return vm.throw_completion(ErrorType::TemporalInvalidCalendarFunctionResult, vm.names.year.as_string(), vm.names.undefined.as_string()); - - // 3. Return ? ToIntegerWithTruncation(result). - return TRY(to_integer_with_truncation(vm, result, ErrorType::TemporalInvalidCalendarFunctionResult, vm.names.year.as_string(), vm.names.Infinity.as_string())); -} - -// 12.2.9 CalendarMonth ( calendar, dateLike ), https://tc39.es/proposal-temporal/#sec-temporal-calendarmonth -ThrowCompletionOr calendar_month(VM& vm, Object& calendar, Object& date_like) -{ - // 1. Let result be ? Invoke(calendar, "month", « dateLike »). - auto result = TRY(Value(&calendar).invoke(vm, vm.names.month, &date_like)); - - // NOTE: Explicitly handled for a better error message similar to the other calendar property AOs - if (result.is_undefined()) - return vm.throw_completion(ErrorType::TemporalInvalidCalendarFunctionResult, vm.names.month.as_string(), vm.names.undefined.as_string()); - - // 2. Return ? ToPositiveIntegerWithTruncation(result). - return TRY(to_positive_integer_with_truncation(vm, result)); -} - -// 12.2.10 CalendarMonthCode ( calendar, dateLike ), https://tc39.es/proposal-temporal/#sec-temporal-calendarmonthcode -ThrowCompletionOr calendar_month_code(VM& vm, Object& calendar, Object& date_like) -{ - // 1. Let result be ? Invoke(calendar, "monthCode", « dateLike »). - auto result = TRY(Value(&calendar).invoke(vm, vm.names.monthCode, &date_like)); - - // 2. If result is undefined, throw a RangeError exception. - if (result.is_undefined()) - return vm.throw_completion(ErrorType::TemporalInvalidCalendarFunctionResult, vm.names.monthCode.as_string(), vm.names.undefined.as_string()); - - // 3. Return ? ToString(result). - return result.to_string(vm); -} - -// 12.2.11 CalendarDay ( calendar, dateLike ), https://tc39.es/proposal-temporal/#sec-temporal-calendarday -ThrowCompletionOr calendar_day(VM& vm, Object& calendar, Object& date_like) -{ - // 1. Let result be ? Invoke(calendar, "day", « dateLike »). - auto result = TRY(Value(&calendar).invoke(vm, vm.names.day, &date_like)); - - // NOTE: Explicitly handled for a better error message similar to the other calendar property AOs - if (result.is_undefined()) - return vm.throw_completion(ErrorType::TemporalInvalidCalendarFunctionResult, vm.names.day.as_string(), vm.names.undefined.as_string()); - - // 2. Return ? ToPositiveIntegerWithTruncation(result). - return TRY(to_positive_integer_with_truncation(vm, result)); -} - -// 12.2.12 CalendarDayOfWeek ( calendar, dateLike ), https://tc39.es/proposal-temporal/#sec-temporal-calendardayofweek -ThrowCompletionOr calendar_day_of_week(VM& vm, Object& calendar, Object& date_like) -{ - // 1. Let result be ? Invoke(calendar, "dayOfWeek", « dateLike »). - auto result = TRY(Value(&calendar).invoke(vm, vm.names.dayOfWeek, &date_like)); - - // NOTE: Explicitly handled for a better error message similar to the other calendar property AOs - if (result.is_undefined()) - return vm.throw_completion(ErrorType::TemporalInvalidCalendarFunctionResult, vm.names.dayOfWeek.as_string(), vm.names.undefined.as_string()); - - // 2. Return ? ToPositiveIntegerWithTruncation(result). - return TRY(to_positive_integer_with_truncation(vm, result)); -} - -// 12.2.13 CalendarDayOfYear ( calendar, dateLike ), https://tc39.es/proposal-temporal/#sec-temporal-calendardayofyear -ThrowCompletionOr calendar_day_of_year(VM& vm, Object& calendar, Object& date_like) -{ - // 1. Let result be ? Invoke(calendar, "dayOfYear", « dateLike »). - auto result = TRY(Value(&calendar).invoke(vm, vm.names.dayOfYear, &date_like)); - - // NOTE: Explicitly handled for a better error message similar to the other calendar property AOs - if (result.is_undefined()) - return vm.throw_completion(ErrorType::TemporalInvalidCalendarFunctionResult, vm.names.dayOfYear.as_string(), vm.names.undefined.as_string()); - - // 2. Return ? ToPositiveIntegerWithTruncation(result). - return TRY(to_positive_integer_with_truncation(vm, result)); -} - -// 12.2.14 CalendarWeekOfYear ( calendar, dateLike ), https://tc39.es/proposal-temporal/#sec-temporal-calendarweekofyear -ThrowCompletionOr calendar_week_of_year(VM& vm, Object& calendar, Object& date_like) -{ - // 1. Let result be ? Invoke(calendar, "weekOfYear", « dateLike »). - auto result = TRY(Value(&calendar).invoke(vm, vm.names.weekOfYear, &date_like)); - - // NOTE: Explicitly handled for a better error message similar to the other calendar property AOs - if (result.is_undefined()) - return vm.throw_completion(ErrorType::TemporalInvalidCalendarFunctionResult, vm.names.weekOfYear.as_string(), vm.names.undefined.as_string()); - - // 2. Return ? ToPositiveIntegerWithTruncation(result). - return TRY(to_positive_integer_with_truncation(vm, result)); -} - -// 12.2.15 CalendarYearOfWeek ( calendar, dateLike ), https://tc39.es/proposal-temporal/#sec-temporal-calendaryearofweek -ThrowCompletionOr calendar_year_of_week(VM& vm, Object& calendar, Object& date_like) -{ - // 1. Let result be ? Invoke(calendar, "yearOfWeek", « dateLike »). - auto result = TRY(Value(&calendar).invoke(vm, vm.names.yearOfWeek, &date_like)); - - // 2. If result is undefined, throw a RangeError exception. - if (result.is_undefined()) - return vm.throw_completion(ErrorType::TemporalInvalidCalendarFunctionResult, vm.names.yearOfWeek.as_string(), vm.names.undefined.as_string()); - - // 3. Return ? ToIntegerWithTruncation(result). - return TRY(to_integer_with_truncation(vm, result, ErrorType::TemporalInvalidCalendarFunctionResult, vm.names.yearOfWeek.as_string(), vm.names.Infinity.to_string())); -} - -// 12.2.16 CalendarDaysInWeek ( calendar, dateLike ), https://tc39.es/proposal-temporal/#sec-temporal-calendardaysinweek -ThrowCompletionOr calendar_days_in_week(VM& vm, Object& calendar, Object& date_like) -{ - // 1. Let result be ? Invoke(calendar, "daysInWeek", « dateLike »). - auto result = TRY(Value(&calendar).invoke(vm, vm.names.daysInWeek, &date_like)); - - // NOTE: Explicitly handled for a better error message similar to the other calendar property AOs - if (result.is_undefined()) - return vm.throw_completion(ErrorType::TemporalInvalidCalendarFunctionResult, vm.names.daysInWeek.as_string(), vm.names.undefined.as_string()); - - // 2. Return ? ToPositiveIntegerWithTruncation(result). - return TRY(to_positive_integer_with_truncation(vm, result)); -} - -// 12.2.17 CalendarDaysInMonth ( calendar, dateLike ), https://tc39.es/proposal-temporal/#sec-temporal-calendardaysinmonth -ThrowCompletionOr calendar_days_in_month(VM& vm, Object& calendar, Object& date_like) -{ - // 1. Let result be ? Invoke(calendar, "daysInMonth", « dateLike »). - auto result = TRY(Value(&calendar).invoke(vm, vm.names.daysInMonth, &date_like)); - - // NOTE: Explicitly handled for a better error message similar to the other calendar property AOs - if (result.is_undefined()) - return vm.throw_completion(ErrorType::TemporalInvalidCalendarFunctionResult, vm.names.daysInMonth.as_string(), vm.names.undefined.as_string()); - - // 2. Return ? ToPositiveIntegerWithTruncation(result). - return TRY(to_positive_integer_with_truncation(vm, result)); -} - -// 12.2.18 CalendarDaysInYear ( calendar, dateLike ), https://tc39.es/proposal-temporal/#sec-temporal-calendardaysinyear -ThrowCompletionOr calendar_days_in_year(VM& vm, Object& calendar, Object& date_like) -{ - // 1. Let result be ? Invoke(calendar, "daysInYear", « dateLike »). - auto result = TRY(Value(&calendar).invoke(vm, vm.names.daysInYear, &date_like)); - - // NOTE: Explicitly handled for a better error message similar to the other calendar property AOs - if (result.is_undefined()) - return vm.throw_completion(ErrorType::TemporalInvalidCalendarFunctionResult, vm.names.daysInYear.as_string(), vm.names.undefined.as_string()); - - // 2. Return ? ToPositiveIntegerWithTruncation(result). - return TRY(to_positive_integer_with_truncation(vm, result)); -} - -// 12.2.19 CalendarMonthsInYear ( calendar, dateLike ), https://tc39.es/proposal-temporal/#sec-temporal-calendarmonthsinyear -ThrowCompletionOr calendar_months_in_year(VM& vm, Object& calendar, Object& date_like) -{ - // 1. Let result be ? Invoke(calendar, "monthsInYear", « dateLike »). - auto result = TRY(Value(&calendar).invoke(vm, vm.names.monthsInYear, &date_like)); - - // NOTE: Explicitly handled for a better error message similar to the other calendar property AOs - if (result.is_undefined()) - return vm.throw_completion(ErrorType::TemporalInvalidCalendarFunctionResult, vm.names.monthsInYear.as_string(), vm.names.undefined.as_string()); - - // 2. Return ? ToPositiveIntegerWithTruncation(result). - return TRY(to_positive_integer_with_truncation(vm, result)); -} - -// 12.2.20 CalendarInLeapYear ( calendar, dateLike ), https://tc39.es/proposal-temporal/#sec-temporal-calendarinleapyear -ThrowCompletionOr calendar_in_leap_year(VM& vm, Object& calendar, Object& date_like) -{ - // 1. Let result be ? Invoke(calendar, "inLeapYear", « dateLike »). - auto result = TRY(Value(&calendar).invoke(vm, vm.names.inLeapYear, &date_like)); - - // 2. Return ToBoolean(result). - return result.to_boolean(); -} - -// 15.6.1.1 CalendarEra ( calendar, dateLike ), https://tc39.es/proposal-temporal/#sec-temporal-calendarera -ThrowCompletionOr calendar_era(VM& vm, Object& calendar, Object& date_like) -{ - // 1. Assert: Type(calendar) is Object. - - // 2. Let result be ? Invoke(calendar, "era", « dateLike »). - auto result = TRY(Value(&calendar).invoke(vm, vm.names.era, &date_like)); - - // 3. If result is not undefined, set result to ? ToString(result). - if (!result.is_undefined()) - result = PrimitiveString::create(vm, TRY(result.to_string(vm))); - - // 4. Return result. - return result; -} - -// 15.6.1.2 CalendarEraYear ( calendar, dateLike ), https://tc39.es/proposal-temporal/#sec-temporal-calendarerayear -ThrowCompletionOr calendar_era_year(VM& vm, Object& calendar, Object& date_like) -{ - // 1. Assert: Type(calendar) is Object. - - // 2. Let result be ? Invoke(calendar, "eraYear", « dateLike »). - auto result = TRY(Value(&calendar).invoke(vm, vm.names.eraYear, &date_like)); - - // 3. If result is not undefined, set result to ? ToIntegerWithTruncation(result). - if (!result.is_undefined()) - result = Value(TRY(to_integer_with_truncation(vm, result, ErrorType::TemporalInvalidCalendarFunctionResult, vm.names.eraYear.as_string(), "Infinity"sv))); - - // 4. Return result. - return result; -} - -// 12.2.21 ToTemporalCalendar ( temporalCalendarLike ), https://tc39.es/proposal-temporal/#sec-temporal-totemporalcalendar -ThrowCompletionOr to_temporal_calendar(VM& vm, Value temporal_calendar_like) -{ - // 1. If Type(temporalCalendarLike) is Object, then - if (temporal_calendar_like.is_object()) { - auto& temporal_calendar_like_object = temporal_calendar_like.as_object(); - - // a. If temporalCalendarLike has an [[InitializedTemporalCalendar]] internal slot, then - if (is(temporal_calendar_like_object)) { - // i. Return temporalCalendarLike. - return &temporal_calendar_like_object; - } - - // b. If temporalCalendarLike has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalTime]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then - // i. Return temporalCalendarLike.[[Calendar]]. - if (is(temporal_calendar_like_object)) - return &static_cast(temporal_calendar_like_object).calendar(); - if (is(temporal_calendar_like_object)) - return &static_cast(temporal_calendar_like_object).calendar(); - if (is(temporal_calendar_like_object)) - return &static_cast(temporal_calendar_like_object).calendar(); - if (is(temporal_calendar_like_object)) - return &static_cast(temporal_calendar_like_object).calendar(); - if (is(temporal_calendar_like_object)) - return &static_cast(temporal_calendar_like_object).calendar(); - if (is(temporal_calendar_like_object)) - return &static_cast(temporal_calendar_like_object).calendar(); - - // c. If temporalCalendarLike has an [[InitializedTemporalTimeZone]] internal slot, throw a RangeError exception. - if (is(temporal_calendar_like_object)) - return vm.throw_completion(ErrorType::TemporalUnexpectedTimeZoneObject); - - // d. If ? HasProperty(temporalCalendarLike, "calendar") is false, return temporalCalendarLike. - if (!TRY(temporal_calendar_like_object.has_property(vm.names.calendar))) - return &temporal_calendar_like_object; - - // e. Set temporalCalendarLike to ? Get(temporalCalendarLike, "calendar"). - temporal_calendar_like = TRY(temporal_calendar_like_object.get(vm.names.calendar)); - - // f. If Type(temporalCalendarLike) is Object, then - if (temporal_calendar_like.is_object()) { - // i. If temporalCalendarLike has an [[InitializedTemporalTimeZone]] internal slot, throw a RangeError exception. - if (is(temporal_calendar_like.as_object())) - return vm.throw_completion(ErrorType::TemporalUnexpectedTimeZoneObject); - - // ii. If ? HasProperty(temporalCalendarLike, "calendar") is false, return temporalCalendarLike. - if (!TRY(temporal_calendar_like.as_object().has_property(vm.names.calendar))) - return &temporal_calendar_like.as_object(); - } - } - - // 2. Let identifier be ? ToString(temporalCalendarLike). - auto identifier = TRY(temporal_calendar_like.to_string(vm)); - - // 3. Set identifier to ? ParseTemporalCalendarString(identifier). - identifier = TRY(parse_temporal_calendar_string(vm, identifier)); - - // 4. If IsBuiltinCalendar(identifier) is false, throw a RangeError exception. - if (!is_builtin_calendar(identifier)) - return vm.throw_completion(ErrorType::TemporalInvalidCalendarIdentifier, identifier); - - // 5. Return ! CreateTemporalCalendar(identifier). - return MUST_OR_THROW_OOM(create_temporal_calendar(vm, identifier)); -} - -// 12.2.22 ToTemporalCalendarWithISODefault ( temporalCalendarLike ), https://tc39.es/proposal-temporal/#sec-temporal-totemporalcalendarwithisodefault -ThrowCompletionOr to_temporal_calendar_with_iso_default(VM& vm, Value temporal_calendar_like) -{ - // 1. If temporalCalendarLike is undefined, then - if (temporal_calendar_like.is_undefined()) { - // a. Return ! GetISO8601Calendar(). - return get_iso8601_calendar(vm); - } - // 2. Return ? ToTemporalCalendar(temporalCalendarLike). - return to_temporal_calendar(vm, temporal_calendar_like); -} - -// 12.2.23 GetTemporalCalendarWithISODefault ( item ), https://tc39.es/proposal-temporal/#sec-temporal-gettemporalcalendarwithisodefault -ThrowCompletionOr get_temporal_calendar_with_iso_default(VM& vm, Object& item) -{ - // 1. If item has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalTime]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then - // a. Return item.[[Calendar]]. - if (is(item)) - return &static_cast(item).calendar(); - if (is(item)) - return &static_cast(item).calendar(); - if (is(item)) - return &static_cast(item).calendar(); - if (is(item)) - return &static_cast(item).calendar(); - if (is(item)) - return &static_cast(item).calendar(); - if (is(item)) - return &static_cast(item).calendar(); - - // 2. Let calendarLike be ? Get(item, "calendar"). - auto calendar_like = TRY(item.get(vm.names.calendar)); - - // 3. Return ? ToTemporalCalendarWithISODefault(calendarLike). - return to_temporal_calendar_with_iso_default(vm, calendar_like); -} - -// 12.2.24 CalendarDateFromFields ( calendar, fields [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal-calendardatefromfields -ThrowCompletionOr calendar_date_from_fields(VM& vm, Object& calendar, Object const& fields, Object const* options) -{ - // 1. If options is not present, set options to undefined. - - // 2. Let date be ? Invoke(calendar, "dateFromFields", « fields, options »). - auto date = TRY(Value(&calendar).invoke(vm, vm.names.dateFromFields, &fields, options ?: js_undefined())); - - // 3. Perform ? RequireInternalSlot(date, [[InitializedTemporalDate]]). - auto date_object = TRY(date.to_object(vm)); - if (!is(*date_object)) - return vm.throw_completion(ErrorType::NotAnObjectOfType, "Temporal.PlainDate"); - - // 4. Return date. - return static_cast(date_object.ptr()); -} - -// 12.2.25 CalendarYearMonthFromFields ( calendar, fields [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal-calendaryearmonthfromfields -ThrowCompletionOr calendar_year_month_from_fields(VM& vm, Object& calendar, Object const& fields, Object const* options) -{ - // 1. If options is not present, set options to undefined. - - // 2. Let yearMonth be ? Invoke(calendar, "yearMonthFromFields", « fields, options »). - auto year_month = TRY(Value(&calendar).invoke(vm, vm.names.yearMonthFromFields, &fields, options ?: js_undefined())); - - // 3. Perform ? RequireInternalSlot(yearMonth, [[InitializedTemporalYearMonth]]). - auto year_month_object = TRY(year_month.to_object(vm)); - if (!is(*year_month_object)) - return vm.throw_completion(ErrorType::NotAnObjectOfType, "Temporal.PlainYearMonth"); - - // 4. Return yearMonth. - return static_cast(year_month_object.ptr()); -} - -// 12.2.26 CalendarMonthDayFromFields ( calendar, fields [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal-calendarmonthdayfromfields -ThrowCompletionOr calendar_month_day_from_fields(VM& vm, Object& calendar, Object const& fields, Object const* options) -{ - // 1. If options is not present, set options to undefined. - - // 2. Let monthDay be ? Invoke(calendar, "monthDayFromFields", « fields, options »). - auto month_day = TRY(Value(&calendar).invoke(vm, vm.names.monthDayFromFields, &fields, options ?: js_undefined())); - - // 3. Perform ? RequireInternalSlot(monthDay, [[InitializedTemporalMonthDay]]). - auto month_day_object = TRY(month_day.to_object(vm)); - if (!is(*month_day_object)) - return vm.throw_completion(ErrorType::NotAnObjectOfType, "Temporal.PlainMonthDay"); - - // 4. Return monthDay. - return static_cast(month_day_object.ptr()); -} - -// 12.2.27 MaybeFormatCalendarAnnotation ( calendarObject, showCalendar ), https://tc39.es/proposal-temporal/#sec-temporal-maybeformatcalendarannotation -ThrowCompletionOr maybe_format_calendar_annotation(VM& vm, Object const* calendar_object, StringView show_calendar) -{ - // 1. If showCalendar is "never", return the empty String. - if (show_calendar == "never"sv) - return String {}; - - // 2. Assert: Type(calendarObject) is Object. - VERIFY(calendar_object); - - // 3. Let calendarID be ? ToString(calendarObject). - auto calendar_id = TRY(Value(calendar_object).to_string(vm)); - - // 4. Return FormatCalendarAnnotation(calendarID, showCalendar). - return format_calendar_annotation(vm, calendar_id, show_calendar); -} - -// 12.2.28 FormatCalendarAnnotation ( id, showCalendar ), https://tc39.es/proposal-temporal/#sec-temporal-formatcalendarannotation -ThrowCompletionOr format_calendar_annotation(VM& vm, StringView id, StringView show_calendar) -{ - VERIFY(show_calendar == "auto"sv || show_calendar == "always"sv || show_calendar == "never"sv || show_calendar == "critical"sv); - - // 1. If showCalendar is "never", return the empty String. - if (show_calendar == "never"sv) - return String {}; - - // 2. If showCalendar is "auto" and id is "iso8601", return the empty String. - if (show_calendar == "auto"sv && id == "iso8601"sv) - return String {}; - - // 3. If showCalendar is "critical", let flag be "!"; else, let flag be the empty String. - auto flag = show_calendar == "critical"sv ? "!"sv : ""sv; - - // 4. Return the string-concatenation of "[", flag, "u-ca=", id, and "]". - return TRY_OR_THROW_OOM(vm, String::formatted("[{}u-ca={}]", flag, id)); -} - -// 12.2.29 CalendarEquals ( one, two ), https://tc39.es/proposal-temporal/#sec-temporal-calendarequals -ThrowCompletionOr calendar_equals(VM& vm, Object& one, Object& two) -{ - // 1. If one and two are the same Object value, return true. - if (&one == &two) - return true; - - // 2. Let calendarOne be ? ToString(one). - auto calendar_one = TRY(Value(&one).to_string(vm)); - - // 3. Let calendarTwo be ? ToString(two). - auto calendar_two = TRY(Value(&two).to_string(vm)); - - // 4. If calendarOne is calendarTwo, return true. - if (calendar_one == calendar_two) - return true; - - // 5. Return false. - return false; -} - -// 12.2.30 ConsolidateCalendars ( one, two ), https://tc39.es/proposal-temporal/#sec-temporal-consolidatecalendars -ThrowCompletionOr consolidate_calendars(VM& vm, Object& one, Object& two) -{ - // 1. If one and two are the same Object value, return two. - if (&one == &two) - return &two; - - // 2. Let calendarOne be ? ToString(one). - auto calendar_one = TRY(Value(&one).to_string(vm)); - - // 3. Let calendarTwo be ? ToString(two). - auto calendar_two = TRY(Value(&two).to_string(vm)); - - // 4. If calendarOne is calendarTwo, return two. - if (calendar_one == calendar_two) - return &two; - - // 5. If calendarOne is "iso8601", return two. - if (calendar_one == "iso8601"sv) - return &two; - - // 6. If calendarTwo is "iso8601", return one. - if (calendar_two == "iso8601"sv) - return &one; - - // 7. Throw a RangeError exception. - return vm.throw_completion(ErrorType::TemporalInvalidCalendar); -} - -// 12.2.31 ISODaysInMonth ( year, month ), https://tc39.es/proposal-temporal/#sec-temporal-isodaysinmonth -u8 iso_days_in_month(i32 year, u8 month) -{ - // 1. If month is 1, 3, 5, 7, 8, 10, or 12, return 31. - if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) - return 31; - - // 2. If month is 4, 6, 9, or 11, return 30. - if (month == 4 || month == 6 || month == 9 || month == 11) - return 30; - - // 3. Assert: month is 2. - VERIFY(month == 2); - - // 4. Return 28 + ℝ(InLeapYear(TimeFromYear(𝔽(year)))). - return 28 + JS::in_leap_year(time_from_year(year)); -} - -// 12.2.32 ToISOWeekOfYear ( year, month, day ), https://tc39.es/proposal-temporal/#sec-temporal-toisoweekofyear -YearWeekRecord to_iso_week_of_year(i32 year, u8 month, u8 day) -{ - // 1. Assert: IsValidISODate(year, month, day) is true. - VERIFY(is_valid_iso_date(year, month, day)); - - // 2. Let wednesday be 3. - constexpr auto wednesday = 3; - - // 3. Let thursday be 4. - constexpr auto thursday = 4; - - // 4. Let friday be 5. - constexpr auto friday = 5; - - // 5. Let saturday be 6. - constexpr auto saturday = 6; - - // 6. Let daysInWeek be 7. - constexpr auto days_in_week = 7; - - // 7. Let maxWeekNumber be 53. - constexpr auto max_week_number = 53; - - // 8. Let dayOfYear be ToISODayOfYear(year, month, day). - auto day_of_year = to_iso_day_of_year(year, month, day); - - // 9. Let dayOfWeek be ToISODayOfWeek(year, month, day). - auto day_of_week = to_iso_day_of_week(year, month, day); - - // 10. Let week be floor((dayOfYear + daysInWeek - dayOfWeek + wednesday ) / daysInWeek). - auto week = static_cast(floor(static_cast(day_of_year + days_in_week - day_of_week + wednesday) / days_in_week)); - - // 11. If week < 1, then - if (week < 1) { - // a. NOTE: This is the last week of the previous year. - - // b. Let dayOfJan1st be ToISODayOfWeek(year, 1, 1). - auto day_of_jan_1st = to_iso_day_of_week(year, 1, 1); - - // c. If dayOfJan1st is friday, then - if (day_of_jan_1st == friday) { - // i. Return the Year-Week Record { [[Week]]: maxWeekNumber, [[Year]]: year - 1 }. - return YearWeekRecord { .week = max_week_number, .year = year - 1 }; - } - - // d. If dayOfJan1st is saturday, and InLeapYear(TimeFromYear(𝔽(year - 1))) is 1𝔽, then - if (day_of_jan_1st == saturday && in_leap_year(time_from_year(year - 1))) { - // i. Return the Year-Week Record { [[Week]]: maxWeekNumber. [[Year]]: year - 1 }. - return YearWeekRecord { .week = max_week_number, .year = year - 1 }; - } - - // e. Return the Year-Week Record { [[Week]]: maxWeekNumber - 1, [[Year]]: year - 1 }. - return YearWeekRecord { .week = max_week_number - 1, .year = year - 1 }; - } - - // 12. If week is maxWeekNumber, then - if (week == max_week_number) { - // a. Let daysInYear be DaysInYear(𝔽(year)). - auto days_in_year = JS::days_in_year(year); - - // b. Let daysLaterInYear be daysInYear - dayOfYear. - auto days_later_in_year = days_in_year - day_of_year; - - // c. Let daysAfterThursday be thursday - dayOfWeek. - auto days_after_thursday = thursday - day_of_week; - - // d. If daysLaterInYear < daysAfterThursday, then - if (days_later_in_year < days_after_thursday) { - // i. Return the Year-Week Record { [[Week]]: 1, [[Year]]: year + 1 }. - return YearWeekRecord { .week = 1, .year = year + 1 }; - } - } - - // 13. Return the Year-Week Record { [[Week]]: week, [[Year]]: year }. - return YearWeekRecord { .week = static_cast(week), .year = year }; -} - -// 12.2.33 ISOMonthCode ( month ), https://tc39.es/proposal-temporal/#sec-temporal-isomonthcode -ThrowCompletionOr iso_month_code(VM& vm, u8 month) -{ - // 1. Let numberPart be ToZeroPaddedDecimalString(month, 2). - // 2. Return the string-concatenation of "M" and numberPart. - return TRY_OR_THROW_OOM(vm, String::formatted("M{:02}", month)); -} - -// 12.2.34 ResolveISOMonth ( fields ), https://tc39.es/proposal-temporal/#sec-temporal-resolveisomonth -ThrowCompletionOr resolve_iso_month(VM& vm, Object const& fields) -{ - // 1. Assert: fields is an ordinary object with no more and no less than the own data properties listed in Table 13. - - // 2. Let month be ! Get(fields, "month"). - auto month = MUST(fields.get(vm.names.month)); - - // 3. Assert: month is undefined or month is a Number. - VERIFY(month.is_undefined() || month.is_number()); - - // 4. Let monthCode be ! Get(fields, "monthCode"). - auto month_code = MUST(fields.get(vm.names.monthCode)); - - // 5. If monthCode is undefined, then - if (month_code.is_undefined()) { - // a. If month is undefined, throw a TypeError exception. - if (month.is_undefined()) - return vm.throw_completion(ErrorType::MissingRequiredProperty, vm.names.month.as_string()); - - // b. Return ℝ(month). - return month.as_double(); - } - - // 6. Assert: Type(monthCode) is String. - VERIFY(month_code.is_string()); - auto month_code_string = month_code.as_string().byte_string(); - - // 7. If the length of monthCode is not 3, throw a RangeError exception. - auto month_length = month_code_string.length(); - if (month_length != 3) - return vm.throw_completion(ErrorType::TemporalInvalidMonthCode); - - // 8. If the first code unit of monthCode is not 0x004D (LATIN CAPITAL LETTER M), throw a RangeError exception. - if (month_code_string[0] != 0x4D) - return vm.throw_completion(ErrorType::TemporalInvalidMonthCode); - - // 9. Let monthCodeDigits be the substring of monthCode from 1. - auto month_code_digits = month_code_string.substring(1); - - // 10. If ParseText(StringToCodePoints(monthCodeDigits), DateMonth) is a List of errors, throw a RangeError exception. - auto parse_result = parse_iso8601(Production::DateMonth, month_code_digits); - if (!parse_result.has_value()) - return vm.throw_completion(ErrorType::TemporalInvalidMonthCode); - - // 11. Let monthCodeNumber be ! ToIntegerOrInfinity(monthCodeDigits). - auto month_code_number = MUST(Value(PrimitiveString::create(vm, move(month_code_digits))).to_integer_or_infinity(vm)); - - // 12. Assert: SameValue(monthCode, ISOMonthCode(monthCodeNumber)) is true. - VERIFY(month_code_string.view() == TRY(iso_month_code(vm, month_code_number))); - - // 13. If month is not undefined and SameValue(month, monthCodeNumber) is false, throw a RangeError exception. - if (!month.is_undefined() && month.as_double() != month_code_number) - return vm.throw_completion(ErrorType::TemporalInvalidMonthCode); - - // 14. Return monthCodeNumber. - return month_code_number; -} - -// 12.2.35 ISODateFromFields ( fields, options ), https://tc39.es/proposal-temporal/#sec-temporal-isodatefromfields -ThrowCompletionOr iso_date_from_fields(VM& vm, Object const& fields, Object const& options) -{ - // 1. Assert: Type(fields) is Object. - - // 2. Set fields to ? PrepareTemporalFields(fields, « "day", "month", "monthCode", "year" », « "year", "day" »). - auto* prepared_fields = TRY(prepare_temporal_fields(vm, fields, - { "day"_string, - "month"_string, - "monthCode"_string, - "year"_string }, - Vector { "year"sv, "day"sv })); - - // 3. Let overflow be ? ToTemporalOverflow(options). - auto overflow = TRY(to_temporal_overflow(vm, &options)); - - // 4. Let year be ! Get(fields, "year"). - auto year = MUST(prepared_fields->get(vm.names.year)); - - // 5. Assert: Type(year) is Number. - VERIFY(year.is_number()); - - // 6. Let month be ? ResolveISOMonth(fields). - auto month = TRY(resolve_iso_month(vm, *prepared_fields)); - - // 7. Let day be ! Get(fields, "day"). - auto day = MUST(prepared_fields->get(vm.names.day)); - - // 8. Assert: Type(day) is Number. - VERIFY(day.is_number()); - - // 9. Return ? RegulateISODate(ℝ(year), month, ℝ(day), overflow). - return regulate_iso_date(vm, year.as_double(), month, day.as_double(), overflow); -} - -// 12.2.36 ISOYearMonthFromFields ( fields, options ), https://tc39.es/proposal-temporal/#sec-temporal-isoyearmonthfromfields -ThrowCompletionOr iso_year_month_from_fields(VM& vm, Object const& fields, Object const& options) -{ - // 1. Assert: Type(fields) is Object. - - // 2. Set fields to ? PrepareTemporalFields(fields, « "month", "monthCode", "year" », « "year" »). - auto* prepared_fields = TRY(prepare_temporal_fields(vm, fields, - { "month"_string, - "monthCode"_string, - "year"_string }, - Vector { "year"sv })); - - // 3. Let overflow be ? ToTemporalOverflow(options). - auto overflow = TRY(to_temporal_overflow(vm, &options)); - - // 4. Let year be ! Get(fields, "year"). - auto year = MUST(prepared_fields->get(vm.names.year)); - - // 5. Assert: Type(year) is Number. - VERIFY(year.is_number()); - - // 6. Let month be ? ResolveISOMonth(fields). - auto month = TRY(resolve_iso_month(vm, *prepared_fields)); - - // 7. Let result be ? RegulateISOYearMonth(ℝ(year), month, overflow). - auto result = TRY(regulate_iso_year_month(vm, year.as_double(), month, overflow)); - - // 8. Return the Record { [[Year]]: result.[[Year]], [[Month]]: result.[[Month]], [[ReferenceISODay]]: 1 }. - return ISOYearMonth { .year = result.year, .month = result.month, .reference_iso_day = 1 }; -} - -// 12.2.37 ISOMonthDayFromFields ( fields, options ), https://tc39.es/proposal-temporal/#sec-temporal-isomonthdayfromfields -ThrowCompletionOr iso_month_day_from_fields(VM& vm, Object const& fields, Object const& options) -{ - // 1. Assert: Type(fields) is Object. - - // 2. Set fields to ? PrepareTemporalFields(fields, « "day", "month", "monthCode", "year" », « "day" »). - auto* prepared_fields = TRY(prepare_temporal_fields(vm, fields, - { "day"_string, - "month"_string, - "monthCode"_string, - "year"_string }, - Vector { "day"sv })); - - // 3. Let overflow be ? ToTemporalOverflow(options). - auto overflow = TRY(to_temporal_overflow(vm, &options)); - - // 4. Let month be ! Get(fields, "month"). - auto month_value = MUST(prepared_fields->get(vm.names.month)); - - // 5. Let monthCode be ! Get(fields, "monthCode"). - auto month_code = MUST(prepared_fields->get(vm.names.monthCode)); - - // 6. Let year be ! Get(fields, "year"). - auto year = MUST(prepared_fields->get(vm.names.year)); - - // 7. If month is not undefined, and monthCode and year are both undefined, then - if (!month_value.is_undefined() && month_code.is_undefined() && year.is_undefined()) { - // a. Throw a TypeError exception. - return vm.throw_completion(ErrorType::MissingRequiredProperty, "monthCode or year"); - } - - // 8. Set month to ? ResolveISOMonth(fields). - auto month = TRY(resolve_iso_month(vm, *prepared_fields)); - - // 9. Let day be ! Get(fields, "day"). - auto day = MUST(prepared_fields->get(vm.names.day)); - - // 10. Assert: Type(day) is Number. - VERIFY(day.is_number()); - - // 11. Let referenceISOYear be 1972 (the first leap year after the Unix epoch). - i32 reference_iso_year = 1972; - - Optional result; - - // 12. If monthCode is undefined, then - if (month_code.is_undefined()) { - // a. Assert: Type(year) is Number. - VERIFY(year.is_number()); - - // b. Let result be ? RegulateISODate(ℝ(year), month, ℝ(day), overflow). - result = TRY(regulate_iso_date(vm, year.as_double(), month, day.as_double(), overflow)); - } - // 13. Else, - else { - // a. Let result be ? RegulateISODate(referenceISOYear, month, ℝ(day), overflow). - result = TRY(regulate_iso_date(vm, reference_iso_year, month, day.as_double(), overflow)); - } - - // 14. Return the Record { [[Month]]: result.[[Month]], [[Day]]: result.[[Day]], [[ReferenceISOYear]]: referenceISOYear }. - return ISOMonthDay { .month = result->month, .day = result->day, .reference_iso_year = reference_iso_year }; -} - -// 12.2.38 DefaultMergeCalendarFields ( fields, additionalFields ), https://tc39.es/proposal-temporal/#sec-temporal-defaultmergecalendarfields -ThrowCompletionOr default_merge_calendar_fields(VM& vm, Object const& fields, Object const& additional_fields) -{ - auto& realm = *vm.current_realm(); - - // 1. Let merged be OrdinaryObjectCreate(%Object.prototype%). - auto merged = Object::create(realm, realm.intrinsics().object_prototype()); - - // 2. Let fieldsKeys be ? EnumerableOwnPropertyNames(fields, key). - auto fields_keys = TRY(fields.enumerable_own_property_names(Object::PropertyKind::Key)); - - // 3. For each element key of fieldsKeys, do - for (auto& key : fields_keys) { - // a. If key is not "month" or "monthCode", then - if (!key.as_string().byte_string().is_one_of(vm.names.month.as_string(), vm.names.monthCode.as_string())) { - auto property_key = MUST(PropertyKey::from_value(vm, key)); - - // i. Let propValue be ? Get(fields, key). - auto prop_value = TRY(fields.get(property_key)); - - // ii. If propValue is not undefined, then - if (!prop_value.is_undefined()) { - // 1. Perform ! CreateDataPropertyOrThrow(merged, key, propValue). - MUST(merged->create_data_property_or_throw(property_key, prop_value)); - } - } - } - - // 4. Let additionalFieldsKeys be ? EnumerableOwnPropertyNames(additionalFields, key). - auto additional_fields_keys = TRY(additional_fields.enumerable_own_property_names(Object::PropertyKind::Key)); - - // IMPLEMENTATION DEFINED: This is an optimization, so we don't have to iterate new_keys three times (worst case), but only once. - bool additional_fields_keys_contains_month_or_month_code_property = false; - - // 5. For each element key of additionalFieldsKeys, do - for (auto& key : additional_fields_keys) { - auto property_key = MUST(PropertyKey::from_value(vm, key)); - - // a. Let propValue be ? Get(additionalFields, key). - auto prop_value = TRY(additional_fields.get(property_key)); - - // b. If propValue is not undefined, then - if (!prop_value.is_undefined()) { - // i. Perform ! CreateDataPropertyOrThrow(merged, key, propValue). - MUST(merged->create_data_property_or_throw(property_key, prop_value)); - } - - // See comment above. - additional_fields_keys_contains_month_or_month_code_property |= key.as_string().byte_string() == vm.names.month.as_string() || key.as_string().byte_string() == vm.names.monthCode.as_string(); - } - - // 6. If additionalFieldsKeys does not contain either "month" or "monthCode", then - if (!additional_fields_keys_contains_month_or_month_code_property) { - // a. Let month be ? Get(fields, "month"). - auto month = TRY(fields.get(vm.names.month)); - - // b. If month is not undefined, then - if (!month.is_undefined()) { - // i. Perform ! CreateDataPropertyOrThrow(merged, "month", month). - MUST(merged->create_data_property_or_throw(vm.names.month, month)); - } - - // c. Let monthCode be ? Get(fields, "monthCode"). - auto month_code = TRY(fields.get(vm.names.monthCode)); - - // d. If monthCode is not undefined, then - if (!month_code.is_undefined()) { - // i. Perform ! CreateDataPropertyOrThrow(merged, "monthCode", monthCode). - MUST(merged->create_data_property_or_throw(vm.names.monthCode, month_code)); - } - } - - // 7. Return merged. - return merged.ptr(); -} - -// 12.2.39 ToISODayOfYear ( year, month, day ), https://tc39.es/proposal-temporal/#sec-temporal-toisodayofyear -u16 to_iso_day_of_year(i32 year, u8 month, u8 day) -{ - // 1. Assert: IsValidISODate(year, month, day) is true. - VERIFY(is_valid_iso_date(year, month, day)); - - // 2. Let epochDays be MakeDay(𝔽(year), 𝔽(month - 1), 𝔽(day)). - auto epoch_days = make_day(year, month - 1, day); - - // 3. Assert: epochDays is finite. - VERIFY(isfinite(epoch_days)); - - // 4. Return ℝ(DayWithinYear(MakeDate(epochDays, +0𝔽))) + 1. - return day_within_year(make_date(epoch_days, 0)) + 1; -} - -// 12.2.40 ToISODayOfWeek ( year, month, day ), https://tc39.es/proposal-temporal/#sec-temporal-toisodayofweek -u8 to_iso_day_of_week(i32 year, u8 month, u8 day) -{ - // 1. Assert: IsValidISODate(year, month, day) is true. - VERIFY(is_valid_iso_date(year, month, day)); - - // 2. Let epochDays be MakeDay(𝔽(year), 𝔽(month - 1), 𝔽(day)). - auto epoch_days = make_day(year, month - 1, day); - - // 3. Assert: epochDays is finite. - VERIFY(isfinite(epoch_days)); - - // 4. Let dayOfWeek be WeekDay(MakeDate(epochDays, +0𝔽)). - auto day_of_week = week_day(make_date(epoch_days, 0)); - - // 5. If dayOfWeek = +0𝔽, return 7. - if (day_of_week == 0) - return 7; - - // 6. Return ℝ(dayOfWeek). - return day_of_week; -} - -} diff --git a/Libraries/LibJS/Runtime/Temporal/Calendar.h b/Libraries/LibJS/Runtime/Temporal/Calendar.h deleted file mode 100644 index 2052186dc80..00000000000 --- a/Libraries/LibJS/Runtime/Temporal/Calendar.h +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (c) 2021, Idan Horowitz - * Copyright (c) 2021-2023, Linus Groh - * Copyright (c) 2023-2024, Shannon Booth - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include -#include -#include -#include -#include -#include - -namespace JS::Temporal { - -class Calendar final : public Object { - JS_OBJECT(Calendar, Object); - GC_DECLARE_ALLOCATOR(Calendar); - -public: - virtual ~Calendar() override = default; - - [[nodiscard]] String const& identifier() const { return m_identifier; } - -private: - Calendar(String identifier, Object& prototype); - - // 12.5 Properties of Temporal.Calendar Instances, https://tc39.es/proposal-temporal/#sec-properties-of-temporal-calendar-instances - String m_identifier; // [[Identifier]] -}; - -// 14.2 The Year-Week Record Specification Type, https://tc39.es/proposal-temporal/#sec-year-week-record-specification-type -struct YearWeekRecord { - u8 week { 0 }; - i32 year { 0 }; -}; - -bool is_builtin_calendar(StringView identifier); -ReadonlySpan available_calendars(); -ThrowCompletionOr create_temporal_calendar(VM&, String const& identifier, FunctionObject const* new_target = nullptr); -ThrowCompletionOr get_builtin_calendar(VM&, String const& identifier); -Calendar* get_iso8601_calendar(VM&); -ThrowCompletionOr> calendar_fields(VM&, Object& calendar, Vector const& field_names); -ThrowCompletionOr calendar_merge_fields(VM&, Object& calendar, Object& fields, Object& additional_fields); -ThrowCompletionOr calendar_date_add(VM&, Object& calendar, Value date, Duration&, Object* options = nullptr, FunctionObject* date_add = nullptr); -ThrowCompletionOr> calendar_date_until(VM&, CalendarMethods const&, Value one, Value two, Object const& options); -ThrowCompletionOr calendar_year(VM&, Object& calendar, Object& date_like); -ThrowCompletionOr calendar_month(VM&, Object& calendar, Object& date_like); -ThrowCompletionOr calendar_month_code(VM&, Object& calendar, Object& date_like); -ThrowCompletionOr calendar_day(VM&, Object& calendar, Object& date_like); -ThrowCompletionOr calendar_day_of_week(VM&, Object& calendar, Object& date_like); -ThrowCompletionOr calendar_day_of_year(VM&, Object& calendar, Object& date_like); -ThrowCompletionOr calendar_week_of_year(VM&, Object& calendar, Object& date_like); -ThrowCompletionOr calendar_year_of_week(VM&, Object& calendar, Object& date_like); -ThrowCompletionOr calendar_days_in_week(VM&, Object& calendar, Object& date_like); -ThrowCompletionOr calendar_days_in_month(VM&, Object& calendar, Object& date_like); -ThrowCompletionOr calendar_days_in_year(VM&, Object& calendar, Object& date_like); -ThrowCompletionOr calendar_months_in_year(VM&, Object& calendar, Object& date_like); -ThrowCompletionOr calendar_in_leap_year(VM&, Object& calendar, Object& date_like); -ThrowCompletionOr calendar_era(VM&, Object& calendar, Object& date_like); -ThrowCompletionOr calendar_era_year(VM&, Object& calendar, Object& date_like); -ThrowCompletionOr to_temporal_calendar(VM&, Value); -ThrowCompletionOr to_temporal_calendar_with_iso_default(VM&, Value); -ThrowCompletionOr get_temporal_calendar_with_iso_default(VM&, Object&); -ThrowCompletionOr calendar_date_from_fields(VM&, Object& calendar, Object const& fields, Object const* options = nullptr); -ThrowCompletionOr calendar_year_month_from_fields(VM&, Object& calendar, Object const& fields, Object const* options = nullptr); -ThrowCompletionOr calendar_month_day_from_fields(VM&, Object& calendar, Object const& fields, Object const* options = nullptr); -ThrowCompletionOr maybe_format_calendar_annotation(VM&, Object const* calendar_object, StringView show_calendar); -ThrowCompletionOr format_calendar_annotation(VM&, StringView id, StringView show_calendar); -ThrowCompletionOr calendar_equals(VM&, Object& one, Object& two); -ThrowCompletionOr consolidate_calendars(VM&, Object& one, Object& two); -u8 iso_days_in_month(i32 year, u8 month); -YearWeekRecord to_iso_week_of_year(i32 year, u8 month, u8 day); -ThrowCompletionOr iso_month_code(VM&, u8 month); -ThrowCompletionOr resolve_iso_month(VM&, Object const& fields); -ThrowCompletionOr iso_date_from_fields(VM&, Object const& fields, Object const& options); -ThrowCompletionOr iso_year_month_from_fields(VM&, Object const& fields, Object const& options); -ThrowCompletionOr iso_month_day_from_fields(VM&, Object const& fields, Object const& options); -ThrowCompletionOr default_merge_calendar_fields(VM&, Object const& fields, Object const& additional_fields); -u16 to_iso_day_of_year(i32 year, u8 month, u8 day); -u8 to_iso_day_of_week(i32 year, u8 month, u8 day); - -// https://tc39.es/proposal-temporal/#table-temporal-calendar-methods-record-fields -struct CalendarMethods { - // The calendar object, or a string indicating a built-in time zone. - Variant> receiver; // [[Reciever]] - - // The calendar's dateAdd method. For a built-in calendar this is always %Temporal.Calendar.prototype.dateAdd%. - GC::Ptr date_add; // [[DateAdd]] - - // The calendar's dateFromFields method. For a built-in calendar this is always %Temporal.Calendar.prototype.dateFromFields%. - GC::Ptr date_from_fields; // [[DateFromFields]] - - // The calendar's dateUntil method. For a built-in calendar this is always %Temporal.Calendar.prototype.dateUntil%. - GC::Ptr date_until; // [[DateUntil]] - - // The calendar's day method. For a built-in calendar this is always %Temporal.Calendar.prototype.day%. - GC::Ptr day; // [[Day]] - - // The calendar's fields method. For a built-in calendar this is always %Temporal.Calendar.prototype.fields%. - GC::Ptr fields; // [[Fields]] - - // The calendar's mergeFields method. For a built-in calendar this is always %Temporal.Calendar.prototype.mergeFields%. - GC::Ptr merge_fields; // [[MergeFields]] - - // The calendar's monthDayFromFields method. For a built-in calendar this is always %Temporal.Calendar.prototype.monthDayFromFields%. - GC::Ptr month_day_from_fields; // [[MonthDayFromFields]] - - // The calendar's yearMonthFromFields method. For a built-in calendar this is always %Temporal.Calendar.prototype.yearMonthFromFields%. - GC::Ptr year_month_from_fields; // [[YearMonthFromFields]] -}; - -#define JS_ENUMERATE_CALENDAR_METHODS \ - __JS_ENUMERATE(DateAdd, dateAdd, date_add) \ - __JS_ENUMERATE(DateFromFields, dateFromFields, date_from_fields) \ - __JS_ENUMERATE(DateUntil, dateUntil, date_until) \ - __JS_ENUMERATE(Day, day, day) \ - __JS_ENUMERATE(Fields, fields, fields) \ - __JS_ENUMERATE(MergeFields, mergeFields, merge_fields) \ - __JS_ENUMERATE(MonthDayFromFields, monthDayFromFields, month_day_from_fields) \ - __JS_ENUMERATE(YearMonthFromFields, yearMonthFromFields, year_month_from_fields) - -enum class CalendarMethod { -#define __JS_ENUMERATE(PascalName, camelName, snake_name) \ - PascalName, - JS_ENUMERATE_CALENDAR_METHODS -#undef __JS_ENUMERATE -}; - -ThrowCompletionOr calendar_methods_record_lookup(VM&, CalendarMethods&, CalendarMethod); -ThrowCompletionOr create_calendar_methods_record(VM&, Variant> calendar, ReadonlySpan); -ThrowCompletionOr> create_calendar_methods_record_from_relative_to(VM&, GC::Ptr, GC::Ptr, ReadonlySpan); -bool calendar_methods_record_has_looked_up(CalendarMethods const&, CalendarMethod); -bool calendar_methods_record_is_builtin(CalendarMethods const&); -ThrowCompletionOr calendar_methods_record_call(VM&, CalendarMethods const&, CalendarMethod, ReadonlySpan arguments); - -} diff --git a/Libraries/LibJS/Runtime/Temporal/CalendarConstructor.cpp b/Libraries/LibJS/Runtime/Temporal/CalendarConstructor.cpp deleted file mode 100644 index 9013d450d0e..00000000000 --- a/Libraries/LibJS/Runtime/Temporal/CalendarConstructor.cpp +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2021-2023, Linus Groh - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include -#include -#include - -namespace JS::Temporal { - -GC_DEFINE_ALLOCATOR(CalendarConstructor); - -// 12.2 The Temporal.Calendar Constructor, https://tc39.es/proposal-temporal/#sec-temporal-calendar-constructor -CalendarConstructor::CalendarConstructor(Realm& realm) - : NativeFunction(realm.vm().names.Calendar.as_string(), realm.intrinsics().function_prototype()) -{ -} - -void CalendarConstructor::initialize(Realm& realm) -{ - Base::initialize(realm); - - auto& vm = this->vm(); - - // 12.3.1 Temporal.Calendar.prototype, https://tc39.es/proposal-temporal/#sec-temporal.calendar.prototype - define_direct_property(vm.names.prototype, realm.intrinsics().temporal_calendar_prototype(), 0); - - u8 attr = Attribute::Writable | Attribute::Configurable; - define_native_function(realm, vm.names.from, from, 1, attr); - - define_direct_property(vm.names.length, Value(1), Attribute::Configurable); -} - -// 12.2.1 Temporal.Calendar ( id ), https://tc39.es/proposal-temporal/#sec-temporal.calendar -ThrowCompletionOr CalendarConstructor::call() -{ - auto& vm = this->vm(); - - // 1. If NewTarget is undefined, then - // a. Throw a TypeError exception. - return vm.throw_completion(ErrorType::ConstructorWithoutNew, "Temporal.Calendar"); -} - -// 12.2.1 Temporal.Calendar ( id ), https://tc39.es/proposal-temporal/#sec-temporal.calendar -ThrowCompletionOr> CalendarConstructor::construct(FunctionObject& new_target) -{ - auto& vm = this->vm(); - - // 2. Set id to ? ToString(id). - auto identifier = TRY(vm.argument(0).to_string(vm)); - - // 3. If IsBuiltinCalendar(id) is false, then - if (!is_builtin_calendar(identifier)) { - // a. Throw a RangeError exception. - return vm.throw_completion(ErrorType::TemporalInvalidCalendarIdentifier, identifier); - } - - // 4. Return ? CreateTemporalCalendar(id, NewTarget). - return *TRY(create_temporal_calendar(vm, identifier, &new_target)); -} - -// 12.3.2 Temporal.Calendar.from ( calendarLike ), https://tc39.es/proposal-temporal/#sec-temporal.calendar.from -JS_DEFINE_NATIVE_FUNCTION(CalendarConstructor::from) -{ - auto calendar_like = vm.argument(0); - - // 1. Return ? ToTemporalCalendar(calendarLike). - return TRY(to_temporal_calendar(vm, calendar_like)); -} - -} diff --git a/Libraries/LibJS/Runtime/Temporal/CalendarConstructor.h b/Libraries/LibJS/Runtime/Temporal/CalendarConstructor.h deleted file mode 100644 index 7222f8d51ea..00000000000 --- a/Libraries/LibJS/Runtime/Temporal/CalendarConstructor.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2021-2022, Linus Groh - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include - -namespace JS::Temporal { - -class CalendarConstructor final : public NativeFunction { - JS_OBJECT(CalendarConstructor, NativeFunction); - GC_DECLARE_ALLOCATOR(CalendarConstructor); - -public: - virtual void initialize(Realm&) override; - virtual ~CalendarConstructor() override = default; - - virtual ThrowCompletionOr call() override; - virtual ThrowCompletionOr> construct(FunctionObject& new_target) override; - -private: - explicit CalendarConstructor(Realm&); - - virtual bool has_constructor() const override { return true; } - - JS_DECLARE_NATIVE_FUNCTION(from); -}; - -} diff --git a/Libraries/LibJS/Runtime/Temporal/CalendarPrototype.cpp b/Libraries/LibJS/Runtime/Temporal/CalendarPrototype.cpp deleted file mode 100644 index deb9343c260..00000000000 --- a/Libraries/LibJS/Runtime/Temporal/CalendarPrototype.cpp +++ /dev/null @@ -1,730 +0,0 @@ -/* - * Copyright (c) 2021-2023, Linus Groh - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace JS::Temporal { - -GC_DEFINE_ALLOCATOR(CalendarPrototype); - -[[nodiscard]] static i32 iso_year(Object& temporal_object); -[[nodiscard]] static u8 iso_month(Object& temporal_object); -[[nodiscard]] static u8 iso_day(Object& temporal_object); - -// 12.4 Properties of the Temporal.Calendar Prototype Object, https://tc39.es/proposal-temporal/#sec-properties-of-the-temporal-calendar-prototype-object -CalendarPrototype::CalendarPrototype(Realm& realm) - : PrototypeObject(realm.intrinsics().object_prototype()) -{ -} - -void CalendarPrototype::initialize(Realm& realm) -{ - Base::initialize(realm); - - auto& vm = this->vm(); - - // 12.4.2 Temporal.Calendar.prototype[ @@toStringTag ], https://tc39.es/proposal-temporal/#sec-temporal.calendar.prototype-@@tostringtag - define_direct_property(vm.well_known_symbol_to_string_tag(), PrimitiveString::create(vm, "Temporal.Calendar"_string), Attribute::Configurable); - - define_native_accessor(realm, vm.names.id, id_getter, {}, Attribute::Configurable); - - u8 attr = Attribute::Writable | Attribute::Configurable; - define_native_function(realm, vm.names.dateFromFields, date_from_fields, 1, attr); - define_native_function(realm, vm.names.yearMonthFromFields, year_month_from_fields, 1, attr); - define_native_function(realm, vm.names.monthDayFromFields, month_day_from_fields, 1, attr); - define_native_function(realm, vm.names.dateAdd, date_add, 2, attr); - define_native_function(realm, vm.names.dateUntil, date_until, 2, attr); - define_native_function(realm, vm.names.year, year, 1, attr); - define_native_function(realm, vm.names.month, month, 1, attr); - define_native_function(realm, vm.names.monthCode, month_code, 1, attr); - define_native_function(realm, vm.names.day, day, 1, attr); - define_native_function(realm, vm.names.dayOfWeek, day_of_week, 1, attr); - define_native_function(realm, vm.names.dayOfYear, day_of_year, 1, attr); - define_native_function(realm, vm.names.weekOfYear, week_of_year, 1, attr); - define_native_function(realm, vm.names.yearOfWeek, year_of_week, 1, attr); - define_native_function(realm, vm.names.daysInWeek, days_in_week, 1, attr); - define_native_function(realm, vm.names.daysInMonth, days_in_month, 1, attr); - define_native_function(realm, vm.names.daysInYear, days_in_year, 1, attr); - define_native_function(realm, vm.names.monthsInYear, months_in_year, 1, attr); - define_native_function(realm, vm.names.inLeapYear, in_leap_year, 1, attr); - define_native_function(realm, vm.names.fields, fields, 1, attr); - define_native_function(realm, vm.names.mergeFields, merge_fields, 2, attr); - define_native_function(realm, vm.names.toString, to_string, 0, attr); - define_native_function(realm, vm.names.toJSON, to_json, 0, attr); - define_native_function(realm, vm.names.era, era, 1, attr); - define_native_function(realm, vm.names.eraYear, era_year, 1, attr); -} - -// 12.4.3 get Temporal.Calendar.prototype.id, https://tc39.es/proposal-temporal/#sec-get-temporal.calendar.prototype.id -JS_DEFINE_NATIVE_FUNCTION(CalendarPrototype::id_getter) -{ - // 1. Let calendar be the this value. - // 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). - auto calendar = TRY(typed_this_object(vm)); - - // 3. Return calendar.[[Identifier]]. - return { PrimitiveString::create(vm, calendar->identifier()) }; -} - -// 12.4.4 Temporal.Calendar.prototype.dateFromFields ( fields [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal.calendar.prototype.datefromfields -// NOTE: This is the minimum dateFromFields implementation for engines without ECMA-402. -JS_DEFINE_NATIVE_FUNCTION(CalendarPrototype::date_from_fields) -{ - // 1. Let calendar be the this value. - // 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). - auto calendar = TRY(typed_this_object(vm)); - - // 3. Assert: calendar.[[Identifier]] is "iso8601". - VERIFY(calendar->identifier() == "iso8601"sv); - - // 4. If Type(fields) is not Object, throw a TypeError exception. - auto fields = vm.argument(0); - if (!fields.is_object()) - return vm.throw_completion(ErrorType::NotAnObject, fields.to_string_without_side_effects()); - - // 5. Set options to ? GetOptionsObject(options). - auto const* options = TRY(get_options_object(vm, vm.argument(1))); - - // 6. Let result be ? ISODateFromFields(fields, options). - auto result = TRY(iso_date_from_fields(vm, fields.as_object(), *options)); - - // 7. Return ? CreateTemporalDate(result.[[Year]], result.[[Month]], result.[[Day]], calendar). - return TRY(create_temporal_date(vm, result.year, result.month, result.day, calendar)); -} - -// 12.4.5 Temporal.Calendar.prototype.yearMonthFromFields ( fields [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal.calendar.prototype.yearmonthfromfields -// NOTE: This is the minimum yearMonthFromFields implementation for engines without ECMA-402. -JS_DEFINE_NATIVE_FUNCTION(CalendarPrototype::year_month_from_fields) -{ - // 1. Let calendar be the this value. - // 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). - auto calendar = TRY(typed_this_object(vm)); - - // 3. Assert: calendar.[[Identifier]] is "iso8601". - VERIFY(calendar->identifier() == "iso8601"sv); - - // 4. If Type(fields) is not Object, throw a TypeError exception. - auto fields = vm.argument(0); - if (!fields.is_object()) - return vm.throw_completion(ErrorType::NotAnObject, fields.to_string_without_side_effects()); - - // 5. Set options to ? GetOptionsObject(options). - auto const* options = TRY(get_options_object(vm, vm.argument(1))); - - // 6. Let result be ? ISOYearMonthFromFields(fields, options). - auto result = TRY(iso_year_month_from_fields(vm, fields.as_object(), *options)); - - // 7. Return ? CreateTemporalYearMonth(result.[[Year]], result.[[Month]], calendar, result.[[ReferenceISODay]]). - return TRY(create_temporal_year_month(vm, result.year, result.month, calendar, result.reference_iso_day)); -} - -// 12.4.6 Temporal.Calendar.prototype.monthDayFromFields ( fields [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal.calendar.prototype.monthdayfromfields -// NOTE: This is the minimum monthDayFromFields implementation for engines without ECMA-402. -JS_DEFINE_NATIVE_FUNCTION(CalendarPrototype::month_day_from_fields) -{ - // 1. Let calendar be the this value. - // 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). - auto calendar = TRY(typed_this_object(vm)); - - // 3. Assert: calendar.[[Identifier]] is "iso8601". - VERIFY(calendar->identifier() == "iso8601"sv); - - // 4. If Type(fields) is not Object, throw a TypeError exception. - auto fields = vm.argument(0); - if (!fields.is_object()) - return vm.throw_completion(ErrorType::NotAnObject, fields.to_string_without_side_effects()); - - // 5. Set options to ? GetOptionsObject(options). - auto const* options = TRY(get_options_object(vm, vm.argument(1))); - - // 6. Let result be ? ISOMonthDayFromFields(fields, options). - auto result = TRY(iso_month_day_from_fields(vm, fields.as_object(), *options)); - - // 7. Return ? CreateTemporalMonthDay(result.[[Month]], result.[[Day]], calendar, result.[[ReferenceISOYear]]). - return TRY(create_temporal_month_day(vm, result.month, result.day, calendar, result.reference_iso_year)); -} - -// 12.4.7 Temporal.Calendar.prototype.dateAdd ( date, duration [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal.calendar.prototype.dateadd -// NOTE: This is the minimum dateAdd implementation for engines without ECMA-402. -JS_DEFINE_NATIVE_FUNCTION(CalendarPrototype::date_add) -{ - // 1. Let calendar be the this value. - // 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). - auto calendar = TRY(typed_this_object(vm)); - - // 3. Assert: calendar.[[Identifier]] is "iso8601". - VERIFY(calendar->identifier() == "iso8601"sv); - - // 4. Set date to ? ToTemporalDate(date). - auto* date = TRY(to_temporal_date(vm, vm.argument(0))); - - // 5. Set duration to ? ToTemporalDuration(duration). - auto duration = TRY(to_temporal_duration(vm, vm.argument(1))); - - // 6. Set options to ? GetOptionsObject(options). - auto const* options = TRY(get_options_object(vm, vm.argument(2))); - - // 7. Let overflow be ? ToTemporalOverflow(options). - auto overflow = TRY(to_temporal_overflow(vm, options)); - - // 8. Let balanceResult be ? BalanceDuration(duration.[[Days]], duration.[[Hours]], duration.[[Minutes]], duration.[[Seconds]], duration.[[Milliseconds]], duration.[[Microseconds]], duration.[[Nanoseconds]], "day"). - auto balance_result = TRY(balance_duration(vm, duration->days(), duration->hours(), duration->minutes(), duration->seconds(), duration->milliseconds(), duration->microseconds(), Crypto::SignedBigInteger { duration->nanoseconds() }, "day"sv)); - - // 9. Let result be ? AddISODate(date.[[ISOYear]], date.[[ISOMonth]], date.[[ISODay]], duration.[[Years]], duration.[[Months]], duration.[[Weeks]], balanceResult.[[Days]], overflow). - auto result = TRY(add_iso_date(vm, date->iso_year(), date->iso_month(), date->iso_day(), duration->years(), duration->months(), duration->weeks(), balance_result.days, overflow)); - - // 10. Return ? CreateTemporalDate(result.[[Year]], result.[[Month]], result.[[Day]], calendar). - return TRY(create_temporal_date(vm, result.year, result.month, result.day, calendar)); -} - -// 12.4.8 Temporal.Calendar.prototype.dateUntil ( one, two [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal.calendar.prototype.dateuntil -// NOTE: This is the minimum dateUntil implementation for engines without ECMA-402. -JS_DEFINE_NATIVE_FUNCTION(CalendarPrototype::date_until) -{ - // 1. Let calendar be the this value. - // 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). - auto calendar = TRY(typed_this_object(vm)); - - // 3. Assert: calendar.[[Identifier]] is "iso8601". - VERIFY(calendar->identifier() == "iso8601"sv); - - // 4. Set one to ? ToTemporalDate(one). - auto* one = TRY(to_temporal_date(vm, vm.argument(0))); - - // 5. Set two to ? ToTemporalDate(two). - auto* two = TRY(to_temporal_date(vm, vm.argument(1))); - - // 6. Set options to ? GetOptionsObject(options). - auto const* options = TRY(get_options_object(vm, vm.argument(2))); - - // 7. Let largestUnit be ? GetTemporalUnit(options, "largestUnit", date, "auto"). - auto largest_unit = TRY(get_temporal_unit(vm, *options, vm.names.largestUnit, UnitGroup::Date, { "auto"sv })); - - // 8. If largestUnit is "auto", set largestUnit to "day". - if (largest_unit == "auto") - largest_unit = "day"_string; - - // 9. Let result be DifferenceISODate(one.[[ISOYear]], one.[[ISOMonth]], one.[[ISODay]], two.[[ISOYear]], two.[[ISOMonth]], two.[[ISODay]], largestUnit). - auto result = difference_iso_date(vm, one->iso_year(), one->iso_month(), one->iso_day(), two->iso_year(), two->iso_month(), two->iso_day(), *largest_unit); - - // 10. Return ! CreateTemporalDuration(result.[[Years]], result.[[Months]], result.[[Weeks]], result.[[Days]], 0, 0, 0, 0, 0, 0). - return MUST(create_temporal_duration(vm, result.years, result.months, result.weeks, result.days, 0, 0, 0, 0, 0, 0)); -} - -// 12.4.9 Temporal.Calendar.prototype.year ( temporalDateLike ), https://tc39.es/proposal-temporal/#sec-temporal.calendar.prototype.year -// NOTE: This is the minimum year implementation for engines without ECMA-402. -JS_DEFINE_NATIVE_FUNCTION(CalendarPrototype::year) -{ - // 1. Let calendar be the this value. - // 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). - auto calendar = TRY(typed_this_object(vm)); - - // 3. Assert: calendar.[[Identifier]] is "iso8601". - VERIFY(calendar->identifier() == "iso8601"sv); - - auto temporal_date_like = vm.argument(0); - // 4. If Type(temporalDateLike) is not Object or temporalDateLike does not have an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], or [[InitializedTemporalYearMonth]] internal slot, then - if (!temporal_date_like.is_object() || !(is(temporal_date_like.as_object()) || is(temporal_date_like.as_object()) || is(temporal_date_like.as_object()))) { - // a. Set temporalDateLike to ? ToTemporalDate(temporalDateLike). - temporal_date_like = TRY(to_temporal_date(vm, temporal_date_like)); - } - - // 5. Assert: temporalDateLike has an [[ISOYear]] internal slot. - // NOTE: The assertion happens in iso_year() call. - - // 6. Return 𝔽(temporalDateLike.[[ISOYear]]). - return Value(iso_year(temporal_date_like.as_object())); -} - -// 12.4.10 Temporal.Calendar.prototype.month ( temporalDateLike ), https://tc39.es/proposal-temporal/#sec-temporal.calendar.prototype.month -// NOTE: This is the minimum month implementation for engines without ECMA-402. -JS_DEFINE_NATIVE_FUNCTION(CalendarPrototype::month) -{ - // 1. Let calendar be the this value. - // 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). - auto calendar = TRY(typed_this_object(vm)); - - // 3. Assert: calendar.[[Identifier]] is "iso8601". - VERIFY(calendar->identifier() == "iso8601"sv); - - auto temporal_date_like = vm.argument(0); - - // 4. If Type(temporalDateLike) is Object and temporalDateLike has an [[InitializedTemporalMonthDay]] internal slot, then - if (temporal_date_like.is_object() && is(temporal_date_like.as_object())) { - // a. Throw a TypeError exception. - return vm.throw_completion(ErrorType::TemporalAmbiguousMonthOfPlainMonthDay); - } - - // 5. If Type(temporalDateLike) is not Object or temporalDateLike does not have an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], or [[InitializedTemporalYearMonth]] internal slot, then - if (!temporal_date_like.is_object() || !(is(temporal_date_like.as_object()) || is(temporal_date_like.as_object()) || is(temporal_date_like.as_object()))) { - // a. Set temporalDateLike to ? ToTemporalDate(temporalDateLike). - temporal_date_like = TRY(to_temporal_date(vm, temporal_date_like)); - } - // 6. Assert: temporalDateLike has an [[ISOMonth]] internal slot. - // NOTE: The assertion happens in iso_month() call. - - // 7. Return 𝔽(temporalDateLike.[[ISOMonth]]). - return Value(iso_month(temporal_date_like.as_object())); -} - -// 12.4.11 Temporal.Calendar.prototype.monthCode ( temporalDateLike ), https://tc39.es/proposal-temporal/#sec-temporal.calendar.prototype.monthcode -// NOTE: This is the minimum monthCode implementation for engines without ECMA-402. -JS_DEFINE_NATIVE_FUNCTION(CalendarPrototype::month_code) -{ - // 1. Let calendar be the this value. - // 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). - auto calendar = TRY(typed_this_object(vm)); - - // 3. Assert: calendar.[[Identifier]] is "iso8601". - VERIFY(calendar->identifier() == "iso8601"sv); - - auto temporal_date_like = vm.argument(0); - // 4. If Type(temporalDateLike) is not Object or temporalDateLike does not have an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], or [[InitializedTemporalYearMonth]] internal slot, then - if (!temporal_date_like.is_object() || !(is(temporal_date_like.as_object()) || is(temporal_date_like.as_object()) || is(temporal_date_like.as_object()) || is(temporal_date_like.as_object()))) { - // a. Set temporalDateLike to ? ToTemporalDate(temporalDateLike). - temporal_date_like = TRY(to_temporal_date(vm, temporal_date_like)); - } - - // 5. Assert: temporalDateLike has an [[ISOMonth]] internal slot. - // NOTE: The assertion happens in iso_month() call. - - // 6. Return ISOMonthCode(temporalDateLike.[[ISOMonth]]). - return PrimitiveString::create(vm, TRY(iso_month_code(vm, iso_month(temporal_date_like.as_object())))); -} - -// 12.4.12 Temporal.Calendar.prototype.day ( temporalDateLike ), https://tc39.es/proposal-temporal/#sec-temporal.calendar.prototype.day -// NOTE: This is the minimum day implementation for engines without ECMA-402. -JS_DEFINE_NATIVE_FUNCTION(CalendarPrototype::day) -{ - // 1. Let calendar be the this value. - // 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). - auto calendar = TRY(typed_this_object(vm)); - - // 3. Assert: calendar.[[Identifier]] is "iso8601". - VERIFY(calendar->identifier() == "iso8601"sv); - - auto temporal_date_like = vm.argument(0); - // 4. If Type(temporalDateLike) is not Object or temporalDateLike does not have an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]] or [[InitializedTemporalMonthDay]] internal slot, then - if (!temporal_date_like.is_object() || !(is(temporal_date_like.as_object()) || is(temporal_date_like.as_object()) || is(temporal_date_like.as_object()))) { - // a. Set temporalDateLike to ? ToTemporalDate(temporalDateLike). - temporal_date_like = TRY(to_temporal_date(vm, temporal_date_like)); - } - // 5. Assert: temporalDateLike has an [[ISODay]] internal slot. - // NOTE: The assertion happens in iso_day() call. - - // 6. Return 𝔽(temporalDateLike.[[ISODay]]). - return Value(iso_day(temporal_date_like.as_object())); -} - -// 12.4.13 Temporal.Calendar.prototype.dayOfWeek ( temporalDateLike ), https://tc39.es/proposal-temporal/#sec-temporal.calendar.prototype.dayofweek -// NOTE: This is the minimum dayOfWeek implementation for engines without ECMA-402. -JS_DEFINE_NATIVE_FUNCTION(CalendarPrototype::day_of_week) -{ - // 1. Let calendar be the this value. - // 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). - auto calendar = TRY(typed_this_object(vm)); - - // 3. Assert: calendar.[[Identifier]] is "iso8601". - VERIFY(calendar->identifier() == "iso8601"sv); - - // 4. Let temporalDate be ? ToTemporalDate(temporalDateLike). - auto* temporal_date = TRY(to_temporal_date(vm, vm.argument(0))); - - // 5. Return 𝔽(ToISODayOfWeek(temporalDate.[[ISOYear]], temporalDate.[[ISOMonth]], temporalDate.[[ISODay]])). - return Value(to_iso_day_of_week(temporal_date->iso_year(), temporal_date->iso_month(), temporal_date->iso_day())); -} - -// 12.4.14 Temporal.Calendar.prototype.dayOfYear ( temporalDateLike ), https://tc39.es/proposal-temporal/#sec-temporal.calendar.prototype.dayofyear -// NOTE: This is the minimum dayOfYear implementation for engines without ECMA-402. -JS_DEFINE_NATIVE_FUNCTION(CalendarPrototype::day_of_year) -{ - // 1. Let calendar be the this value. - // 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). - auto calendar = TRY(typed_this_object(vm)); - - // 3. Assert: calendar.[[Identifier]] is "iso8601". - VERIFY(calendar->identifier() == "iso8601"sv); - - // 4. Let temporalDate be ? ToTemporalDate(temporalDateLike). - auto* temporal_date = TRY(to_temporal_date(vm, vm.argument(0))); - - // 5. Return 𝔽(ToISODayOfYear(temporalDate.[[ISOYear]], temporalDate.[[ISOMonth]], temporalDate.[[ISODay]])). - return Value(to_iso_day_of_year(temporal_date->iso_year(), temporal_date->iso_month(), temporal_date->iso_day())); -} - -// 12.4.15 Temporal.Calendar.prototype.weekOfYear ( temporalDateLike ), https://tc39.es/proposal-temporal/#sec-temporal.calendar.prototype.weekofyear -// NOTE: This is the minimum weekOfYear implementation for engines without ECMA-402. -JS_DEFINE_NATIVE_FUNCTION(CalendarPrototype::week_of_year) -{ - // 1. Let calendar be the this value. - // 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). - auto calendar = TRY(typed_this_object(vm)); - - // 3. Assert: calendar.[[Identifier]] is "iso8601". - VERIFY(calendar->identifier() == "iso8601"sv); - - // 4. Let temporalDate be ? ToTemporalDate(temporalDateLike). - auto* temporal_date = TRY(to_temporal_date(vm, vm.argument(0))); - - // 5. Let isoYearWeek be ToISOWeekOfYear(temporalDate.[[ISOYear]], temporalDate.[[ISOMonth]], temporalDate.[[ISODay]]). - auto iso_year_week = to_iso_week_of_year(temporal_date->iso_year(), temporal_date->iso_month(), temporal_date->iso_day()); - - // 6. Return 𝔽(isoYearWeek.[[Week]]). - return Value(iso_year_week.week); -} - -// 12.5.16 Temporal.Calendar.prototype.yearOfWeek ( temporalDateLike ), https://tc39.es/proposal-temporal/#sec-temporal.calendar.prototype.yearofweek -// NOTE: This is the minimum yearOfWeek implementation for engines without ECMA-402. -JS_DEFINE_NATIVE_FUNCTION(CalendarPrototype::year_of_week) -{ - // 1. Let calendar be the this value. - // 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). - auto calendar = TRY(typed_this_object(vm)); - - // 3. Assert: calendar.[[Identifier]] is "iso8601". - VERIFY(calendar->identifier() == "iso8601"sv); - - // 4. Let temporalDate be ? ToTemporalDate(temporalDateLike). - auto* temporal_date = TRY(to_temporal_date(vm, vm.argument(0))); - - // 5. Let isoYearWeek be ToISOWeekOfYear(temporalDate.[[ISOYear]], temporalDate.[[ISOMonth]], temporalDate.[[ISODay]]). - auto iso_year_week = to_iso_week_of_year(temporal_date->iso_year(), temporal_date->iso_month(), temporal_date->iso_day()); - - // 6. Return 𝔽(isoYearWeek.[[Year]]). - return Value(iso_year_week.year); -} - -// 12.4.17 Temporal.Calendar.prototype.daysInWeek ( temporalDateLike ), https://tc39.es/proposal-temporal/#sec-temporal.calendar.prototype.daysinweek -// NOTE: This is the minimum daysInWeek implementation for engines without ECMA-402. -JS_DEFINE_NATIVE_FUNCTION(CalendarPrototype::days_in_week) -{ - // 1. Let calendar be the this value. - // 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). - auto calendar = TRY(typed_this_object(vm)); - - // 3. Assert: calendar.[[Identifier]] is "iso8601". - VERIFY(calendar->identifier() == "iso8601"sv); - - // 4. Let temporalDate be ? ToTemporalDate(temporalDateLike). - [[maybe_unused]] auto* temporal_date = TRY(to_temporal_date(vm, vm.argument(0))); - - // 5. Return 7𝔽. - return Value(7); -} - -// 12.4.18 Temporal.Calendar.prototype.daysInMonth ( temporalDateLike ), https://tc39.es/proposal-temporal/#sec-temporal.calendar.prototype.daysinweek -// NOTE: This is the minimum daysInMonth implementation for engines without ECMA-402. -JS_DEFINE_NATIVE_FUNCTION(CalendarPrototype::days_in_month) -{ - // 1. Let calendar be the this value. - // 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). - auto calendar = TRY(typed_this_object(vm)); - - // 3. Assert: calendar.[[Identifier]] is "iso8601". - VERIFY(calendar->identifier() == "iso8601"sv); - - auto temporal_date_like = vm.argument(0); - // 4. If Type(temporalDateLike) is not Object or temporalDateLike does not have an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], or [[InitializedTemporalYearMonth]] internal slots, then - if (!temporal_date_like.is_object() || !(is(temporal_date_like.as_object()) || is(temporal_date_like.as_object()) || is(temporal_date_like.as_object()))) { - // a. Set temporalDateLike to ? ToTemporalDate(temporalDateLike). - temporal_date_like = TRY(to_temporal_date(vm, temporal_date_like)); - } - - // 5. Return 𝔽(! ISODaysInMonth(temporalDateLike.[[ISOYear]], temporalDateLike.[[ISOMonth]])). - return Value(iso_days_in_month(iso_year(temporal_date_like.as_object()), iso_month(temporal_date_like.as_object()))); -} - -// 12.4.19 Temporal.Calendar.prototype.daysInYear ( temporalDateLike ), https://tc39.es/proposal-temporal/#sec-temporal.calendar.prototype.daysinyear -// NOTE: This is the minimum daysInYear implementation for engines without ECMA-402. -JS_DEFINE_NATIVE_FUNCTION(CalendarPrototype::days_in_year) -{ - // 1. Let calendar be the this value. - // 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). - auto calendar = TRY(typed_this_object(vm)); - - // 3. Assert: calendar.[[Identifier]] is "iso8601". - VERIFY(calendar->identifier() == "iso8601"sv); - - auto temporal_date_like = vm.argument(0); - // 4. If Type(temporalDateLike) is not Object or temporalDateLike does not have an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], or [[InitializedTemporalYearMonth]] internal slot, then - if (!temporal_date_like.is_object() || !(is(temporal_date_like.as_object()) || is(temporal_date_like.as_object()) || is(temporal_date_like.as_object()))) { - // a. Set temporalDateLike to ? ToTemporalDate(temporalDateLike). - temporal_date_like = TRY(to_temporal_date(vm, temporal_date_like)); - } - - // 5. Return DaysInYear(𝔽(temporalDateLike.[[ISOYear]])). - return Value(JS::days_in_year(iso_year(temporal_date_like.as_object()))); -} - -// 12.4.20 Temporal.Calendar.prototype.monthsInYear ( temporalDateLike ), https://tc39.es/proposal-temporal/#sec-temporal.calendar.prototype.monthsinyear -// NOTE: This is the minimum monthsInYear implementation for engines without ECMA-402. -JS_DEFINE_NATIVE_FUNCTION(CalendarPrototype::months_in_year) -{ - // 1. Let calendar be the this value. - // 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). - auto calendar = TRY(typed_this_object(vm)); - - // 3. Assert: calendar.[[Identifier]] is "iso8601". - VERIFY(calendar->identifier() == "iso8601"sv); - - auto temporal_date_like = vm.argument(0); - // 4. If Type(temporalDateLike) is not Object or temporalDateLike does not have an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], or [[InitializedTemporalYearMonth]] internal slot, then - if (!temporal_date_like.is_object() || !(is(temporal_date_like.as_object()) || is(temporal_date_like.as_object()) || is(temporal_date_like.as_object()))) { - // a. Perform ? ToTemporalDate(temporalDateLike). - (void)TRY(to_temporal_date(vm, temporal_date_like)); - } - - // 5. Return 12𝔽. - return Value(12); -} - -// 12.4.21 Temporal.Calendar.prototype.inLeapYear ( temporalDateLike ), https://tc39.es/proposal-temporal/#sec-temporal.calendar.prototype.inleapyear -// NOTE: This is the minimum inLeapYear implementation for engines without ECMA-402. -JS_DEFINE_NATIVE_FUNCTION(CalendarPrototype::in_leap_year) -{ - // 1. Let calendar be the this value. - // 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). - auto calendar = TRY(typed_this_object(vm)); - - // 3. Assert: calendar.[[Identifier]] is "iso8601". - VERIFY(calendar->identifier() == "iso8601"sv); - - auto temporal_date_like = vm.argument(0); - // 4. If Type(temporalDateLike) is not Object or temporalDateLike does not have an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], or [[InitializedTemporalYearMonth]] internal slot, then - if (!temporal_date_like.is_object() || !(is(temporal_date_like.as_object()) || is(temporal_date_like.as_object()) || is(temporal_date_like.as_object()))) { - // a. Set temporalDateLike to ? ToTemporalDate(temporalDateLike). - temporal_date_like = TRY(to_temporal_date(vm, temporal_date_like)); - } - - // 5. If InLeapYear(TimeFromYear(𝔽(temporalDateLike.[[ISOYear]]))) is 1𝔽, return true. - if (JS::in_leap_year(time_from_year(iso_year(temporal_date_like.as_object())))) - return Value(true); - - // 6. Return false. - return Value(false); -} - -// 12.4.22 Temporal.Calendar.prototype.fields ( fields ), https://tc39.es/proposal-temporal/#sec-temporal.calendar.prototype.fields -// NOTE: This is the minimum fields implementation for engines without ECMA-402. -JS_DEFINE_NATIVE_FUNCTION(CalendarPrototype::fields) -{ - auto& realm = *vm.current_realm(); - - auto fields = vm.argument(0); - - // 1. Let calendar be the this value. - // 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). - auto calendar = TRY(typed_this_object(vm)); - - // 3. Assert: calendar.[[Identifier]] is "iso8601". - VERIFY(calendar->identifier() == "iso8601"sv); - - // 4. Let iteratorRecord be ? GetIterator(fields, sync). - auto iterator_record = TRY(get_iterator(vm, fields, IteratorHint::Sync)); - - // 5. Let fieldNames be a new empty List. - auto field_names = GC::MarkedVector { vm.heap() }; - - // 6. Let next be true. - // 7. Repeat, while next is not false, - while (true) { - // a. Set next to ? IteratorStep(iteratorRecord). - auto next = TRY(iterator_step(vm, iterator_record)); - - // b. If next is not false, then - if (!next) - break; - - // i. Let nextValue be ? IteratorValue(next). - auto next_value = TRY(iterator_value(vm, *next)); - - // ii. If Type(nextValue) is not String, then - if (!next_value.is_string()) { - // 1. Let completion be ThrowCompletion(a newly created TypeError object). - auto completion = vm.throw_completion(ErrorType::TemporalInvalidCalendarFieldValue, next_value.to_string_without_side_effects()); - - // 2. Return ? IteratorClose(iteratorRecord, completion). - return *TRY(iterator_close(vm, iterator_record, move(completion))); - } - - auto next_value_string = next_value.as_string().utf8_string(); - - // iii. If fieldNames contains nextValue, then - if (field_names.contains_slow(next_value)) { - // 1. Let completion be ThrowCompletion(a newly created RangeError object). - auto completion = vm.throw_completion(ErrorType::TemporalDuplicateCalendarField, next_value_string); - - // 2. Return ? IteratorClose(iteratorRecord, completion). - return *TRY(iterator_close(vm, iterator_record, move(completion))); - } - - // iv. If nextValue is not one of "year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond", then - if (!next_value_string.is_one_of("year"sv, "month"sv, "monthCode"sv, "day"sv, "hour"sv, "minute"sv, "second"sv, "millisecond"sv, "microsecond"sv, "nanosecond"sv)) { - // 1. Let completion be ThrowCompletion(a newly created RangeError object). - auto completion = vm.throw_completion(ErrorType::TemporalInvalidCalendarFieldName, next_value_string); - - // 2. Return ? IteratorClose(iteratorRecord, completion). - return *TRY(iterator_close(vm, iterator_record, move(completion))); - } - - // v. Append nextValue to the end of the List fieldNames. - field_names.append(next_value); - } - - // 8. Return CreateArrayFromList(fieldNames). - return Array::create_from(realm, field_names); -} - -// 12.4.23 Temporal.Calendar.prototype.mergeFields ( fields, additionalFields ), https://tc39.es/proposal-temporal/#sec-temporal.calendar.prototype.mergefields -// NOTE: This is the minimum mergeFields implementation for engines without ECMA-402. -JS_DEFINE_NATIVE_FUNCTION(CalendarPrototype::merge_fields) -{ - // 1. Let calendar be the this value. - // 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). - auto calendar = TRY(typed_this_object(vm)); - - // 3. Set fields to ? ToObject(fields). - auto fields = TRY(vm.argument(0).to_object(vm)); - - // 4. Set additionalFields to ? ToObject(additionalFields). - auto additional_fields = TRY(vm.argument(1).to_object(vm)); - - // 5. Assert: calendar.[[Identifier]] is "iso8601". - VERIFY(calendar->identifier() == "iso8601"sv); - - // 6. Return ? DefaultMergeCalendarFields(fields, additionalFields). - return TRY(default_merge_calendar_fields(vm, fields, additional_fields)); -} - -// 12.4.24 Temporal.Calendar.prototype.toString ( ), https://tc39.es/proposal-temporal/#sec-temporal.calendar.prototype.tostring -JS_DEFINE_NATIVE_FUNCTION(CalendarPrototype::to_string) -{ - // 1. Let calendar be the this value. - // 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). - auto calendar = TRY(typed_this_object(vm)); - - // 3. Return calendar.[[Identifier]]. - return PrimitiveString::create(vm, calendar->identifier()); -} - -// 12.4.25 Temporal.Calendar.prototype.toJSON ( ), https://tc39.es/proposal-temporal/#sec-temporal.calendar.prototype.tojson -JS_DEFINE_NATIVE_FUNCTION(CalendarPrototype::to_json) -{ - // 1. Let calendar be the this value. - // 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). - auto calendar = TRY(typed_this_object(vm)); - - // 3. Return ? ToString(calendar). - return PrimitiveString::create(vm, TRY(Value(calendar).to_string(vm))); -} - -// 15.6.2.6 Temporal.Calendar.prototype.era ( temporalDateLike ), https://tc39.es/proposal-temporal/#sec-temporal.calendar.prototype.era -JS_DEFINE_NATIVE_FUNCTION(CalendarPrototype::era) -{ - auto temporal_date_like = vm.argument(0); - - // 1. Let calendar be the this value. - // 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). - auto calendar = TRY(typed_this_object(vm)); - - // 3. If Type(temporalDateLike) is not Object or temporalDateLike does not have an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], or [[InitializedTemporalYearMonth]] internal slot, then - if (!temporal_date_like.is_object() || !(is(temporal_date_like.as_object()) || is(temporal_date_like.as_object()) || is(temporal_date_like.as_object()))) { - // a. Set temporalDateLike to ? ToTemporalDate(temporalDateLike). - temporal_date_like = TRY(to_temporal_date(vm, temporal_date_like)); - } - - // 4. If calendar.[[Identifier]] is "iso8601", then - if (calendar->identifier() == "iso8601"sv) { - // a. Return undefined. - return js_undefined(); - } - - // 5. Let era be the result of implementation-defined processing of temporalDateLike and calendar.[[Identifier]]. - // 6. Return era. - - // NOTE: No support for non-iso8601 calendars yet. - VERIFY_NOT_REACHED(); -} - -// 15.6.2.7 Temporal.Calendar.prototype.eraYear ( temporalDateLike ), https://tc39.es/proposal-temporal/#sec-temporal.calendar.prototype.erayear -JS_DEFINE_NATIVE_FUNCTION(CalendarPrototype::era_year) -{ - auto temporal_date_like = vm.argument(0); - - // 1. Let calendar be the this value. - // 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). - auto calendar = TRY(typed_this_object(vm)); - - // 3. If Type(temporalDateLike) is not Object or temporalDateLike does not have an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], or [[InitializedTemporalYearMonth]] internal slot, then - if (!temporal_date_like.is_object() || !(is(temporal_date_like.as_object()) || is(temporal_date_like.as_object()) || is(temporal_date_like.as_object()))) { - // a. Set temporalDateLike to ? ToTemporalDate(temporalDateLike). - temporal_date_like = TRY(to_temporal_date(vm, temporal_date_like)); - } - - // 4. If calendar.[[Identifier]] is "iso8601", then - if (calendar->identifier() == "iso8601"sv) { - // a. Return undefined. - return js_undefined(); - } - - // 5. Let eraYear be the result of implementation-defined processing of temporalDateLike and calendar.[[Identifier]]. - // 6. Return 𝔽(eraYear). - - // NOTE: No support for non-iso8601 calendars yet. - VERIFY_NOT_REACHED(); -} - -static i32 iso_year(Object& temporal_object) -{ - if (is(temporal_object)) - return static_cast(temporal_object).iso_year(); - if (is(temporal_object)) - return static_cast(temporal_object).iso_year(); - if (is(temporal_object)) - return static_cast(temporal_object).iso_year(); - if (is(temporal_object)) - return static_cast(temporal_object).iso_year(); - VERIFY_NOT_REACHED(); -} - -static u8 iso_month(Object& temporal_object) -{ - if (is(temporal_object)) - return static_cast(temporal_object).iso_month(); - if (is(temporal_object)) - return static_cast(temporal_object).iso_month(); - if (is(temporal_object)) - return static_cast(temporal_object).iso_month(); - if (is(temporal_object)) - return static_cast(temporal_object).iso_month(); - VERIFY_NOT_REACHED(); -} - -static u8 iso_day(Object& temporal_object) -{ - if (is(temporal_object)) - return static_cast(temporal_object).iso_day(); - if (is(temporal_object)) - return static_cast(temporal_object).iso_day(); - if (is(temporal_object)) - return static_cast(temporal_object).iso_day(); - if (is(temporal_object)) - return static_cast(temporal_object).iso_day(); - VERIFY_NOT_REACHED(); -} - -} diff --git a/Libraries/LibJS/Runtime/Temporal/CalendarPrototype.h b/Libraries/LibJS/Runtime/Temporal/CalendarPrototype.h deleted file mode 100644 index 0bfeeb868b2..00000000000 --- a/Libraries/LibJS/Runtime/Temporal/CalendarPrototype.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2021, Linus Groh - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include -#include - -namespace JS::Temporal { - -class CalendarPrototype final : public PrototypeObject { - JS_PROTOTYPE_OBJECT(CalendarPrototype, Calendar, Temporal.Calendar); - GC_DECLARE_ALLOCATOR(CalendarPrototype); - -public: - virtual void initialize(Realm&) override; - virtual ~CalendarPrototype() override = default; - -private: - explicit CalendarPrototype(Realm&); - - JS_DECLARE_NATIVE_FUNCTION(id_getter); - JS_DECLARE_NATIVE_FUNCTION(date_from_fields); - JS_DECLARE_NATIVE_FUNCTION(year_month_from_fields); - JS_DECLARE_NATIVE_FUNCTION(month_day_from_fields); - JS_DECLARE_NATIVE_FUNCTION(date_add); - JS_DECLARE_NATIVE_FUNCTION(date_until); - JS_DECLARE_NATIVE_FUNCTION(year); - JS_DECLARE_NATIVE_FUNCTION(month); - JS_DECLARE_NATIVE_FUNCTION(month_code); - JS_DECLARE_NATIVE_FUNCTION(day); - JS_DECLARE_NATIVE_FUNCTION(day_of_week); - JS_DECLARE_NATIVE_FUNCTION(day_of_year); - JS_DECLARE_NATIVE_FUNCTION(week_of_year); - JS_DECLARE_NATIVE_FUNCTION(year_of_week); - JS_DECLARE_NATIVE_FUNCTION(days_in_week); - JS_DECLARE_NATIVE_FUNCTION(days_in_month); - JS_DECLARE_NATIVE_FUNCTION(days_in_year); - JS_DECLARE_NATIVE_FUNCTION(months_in_year); - JS_DECLARE_NATIVE_FUNCTION(in_leap_year); - JS_DECLARE_NATIVE_FUNCTION(fields); - JS_DECLARE_NATIVE_FUNCTION(merge_fields); - JS_DECLARE_NATIVE_FUNCTION(to_string); - JS_DECLARE_NATIVE_FUNCTION(to_json); - JS_DECLARE_NATIVE_FUNCTION(era); - JS_DECLARE_NATIVE_FUNCTION(era_year); -}; - -} diff --git a/Libraries/LibJS/Runtime/Temporal/Duration.cpp b/Libraries/LibJS/Runtime/Temporal/Duration.cpp index c2e81ee524b..7df784d155c 100644 --- a/Libraries/LibJS/Runtime/Temporal/Duration.cpp +++ b/Libraries/LibJS/Runtime/Temporal/Duration.cpp @@ -7,217 +7,14 @@ */ #include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include #include -#include -#include -#include -#include -#include -#include +#include +#include namespace JS::Temporal { -GC_DEFINE_ALLOCATOR(Duration); - -// 7 Temporal.Duration Objects, https://tc39.es/proposal-temporal/#sec-temporal-duration-objects -Duration::Duration(double years, double months, double weeks, double days, double hours, double minutes, double seconds, double milliseconds, double microseconds, double nanoseconds, Object& prototype) - : Object(ConstructWithPrototypeTag::Tag, prototype) - , m_years(years) - , m_months(months) - , m_weeks(weeks) - , m_days(days) - , m_hours(hours) - , m_minutes(minutes) - , m_seconds(seconds) - , m_milliseconds(milliseconds) - , m_microseconds(microseconds) - , m_nanoseconds(nanoseconds) -{ - auto fields = AK::Array { - &Duration::m_years, - &Duration::m_months, - &Duration::m_weeks, - &Duration::m_days, - &Duration::m_hours, - &Duration::m_minutes, - &Duration::m_seconds, - &Duration::m_milliseconds, - &Duration::m_microseconds, - &Duration::m_nanoseconds, - }; - - // NOTE: The spec stores these fields as mathematical values. VERIFY() that we have finite, - // integral values in them, and normalize any negative zeros caused by floating point math. - // This is usually done using ℝ(𝔽(value)) at the call site. - for (auto const& field : fields) { - auto& value = this->*field; - VERIFY(isfinite(value)); - // FIXME: test-js contains a small number of cases where a Temporal.Duration is constructed - // with a non-integral double. Eliminate these and VERIFY(trunc(value) == value) instead. - if (trunc(value) != value) - value = trunc(value); - else if (bit_cast(value) == NEGATIVE_ZERO_BITS) - value = 0; - } -} - -// NOTE: All of these have two overloads: one that can throw, and one that can't. -// This is so that we don't have to needlessly pass a global object and then unwrap -// the ThrowCompletionOr when we already know that the duration is valid. - -// 7.5.5 CreateDurationRecord ( years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds ), https://tc39.es/proposal-temporal/#sec-temporal-createdurationrecord -DurationRecord create_duration_record(double years, double months, double weeks, double days, double hours, double minutes, double seconds, double milliseconds, double microseconds, double nanoseconds) -{ - // 1. If ! IsValidDuration(years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds) is false, throw a RangeError exception. - VERIFY(is_valid_duration(years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds)); - - // 2. Return the Record { [[Years]]: ℝ(𝔽(years)), [[Months]]: ℝ(𝔽(months)), [[Weeks]]: ℝ(𝔽(weeks)), [[Days]]: ℝ(𝔽(days)), [[Hours]]: ℝ(𝔽(hours)), [[Minutes]]: ℝ(𝔽(minutes)), [[Seconds]]: ℝ(𝔽(seconds)), [[Milliseconds]]: ℝ(𝔽(milliseconds)), [[Microseconds]]: ℝ(𝔽(microseconds)), [[Nanoseconds]]: ℝ(𝔽(nanoseconds)) }. - return DurationRecord { .years = years, .months = months, .weeks = weeks, .days = days, .hours = hours, .minutes = minutes, .seconds = seconds, .milliseconds = milliseconds, .microseconds = microseconds, .nanoseconds = nanoseconds }; -} - -// 7.5.5 CreateDurationRecord ( years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds ), https://tc39.es/proposal-temporal/#sec-temporal-createdurationrecord -ThrowCompletionOr create_duration_record(VM& vm, double years, double months, double weeks, double days, double hours, double minutes, double seconds, double milliseconds, double microseconds, double nanoseconds) -{ - // 1. If ! IsValidDuration(years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds) is false, throw a RangeError exception. - if (!is_valid_duration(years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds)) - return vm.throw_completion(ErrorType::TemporalInvalidDuration); - - // 2. Return the Record { [[Years]]: ℝ(𝔽(years)), [[Months]]: ℝ(𝔽(months)), [[Weeks]]: ℝ(𝔽(weeks)), [[Days]]: ℝ(𝔽(days)), [[Hours]]: ℝ(𝔽(hours)), [[Minutes]]: ℝ(𝔽(minutes)), [[Seconds]]: ℝ(𝔽(seconds)), [[Milliseconds]]: ℝ(𝔽(milliseconds)), [[Microseconds]]: ℝ(𝔽(microseconds)), [[Nanoseconds]]: ℝ(𝔽(nanoseconds)) }. - return DurationRecord { .years = years, .months = months, .weeks = weeks, .days = days, .hours = hours, .minutes = minutes, .seconds = seconds, .milliseconds = milliseconds, .microseconds = microseconds, .nanoseconds = nanoseconds }; -} - -// 7.5.6 CreateDateDurationRecord ( years, months, weeks, days ), https://tc39.es/proposal-temporal/#sec-temporal-createdatedurationrecord -DateDurationRecord create_date_duration_record(double years, double months, double weeks, double days) -{ - // 1. If ! IsValidDuration(years, months, weeks, days, 0, 0, 0, 0, 0, 0) is false, throw a RangeError exception. - VERIFY(is_valid_duration(years, months, weeks, days, 0, 0, 0, 0, 0, 0)); - - // 2. Return the Record { [[Years]]: ℝ(𝔽(years)), [[Months]]: ℝ(𝔽(months)), [[Weeks]]: ℝ(𝔽(weeks)), [[Days]]: ℝ(𝔽(days)) }. - return DateDurationRecord { .years = years, .months = months, .weeks = weeks, .days = days }; -} - -// 7.5.6 CreateDateDurationRecord ( years, months, weeks, days ), https://tc39.es/proposal-temporal/#sec-temporal-createdatedurationrecord -ThrowCompletionOr create_date_duration_record(VM& vm, double years, double months, double weeks, double days) -{ - // 1. If ! IsValidDuration(years, months, weeks, days, 0, 0, 0, 0, 0, 0) is false, throw a RangeError exception. - if (!is_valid_duration(years, months, weeks, days, 0, 0, 0, 0, 0, 0)) - return vm.throw_completion(ErrorType::TemporalInvalidDuration); - - // 2. Return the Record { [[Years]]: ℝ(𝔽(years)), [[Months]]: ℝ(𝔽(months)), [[Weeks]]: ℝ(𝔽(weeks)), [[Days]]: ℝ(𝔽(days)) }. - return DateDurationRecord { .years = years, .months = months, .weeks = weeks, .days = days }; -} - -// 7.5.7 CreateTimeDurationRecord ( days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds ), https://tc39.es/proposal-temporal/#sec-temporal-createtimedurationrecord -ThrowCompletionOr create_time_duration_record(VM& vm, double days, double hours, double minutes, double seconds, double milliseconds, double microseconds, double nanoseconds) -{ - // 1. If ! IsValidDuration(0, 0, 0, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds) is false, throw a RangeError exception. - if (!is_valid_duration(0, 0, 0, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds)) - return vm.throw_completion(ErrorType::TemporalInvalidDuration); - - // 2. Return the Record { [[Days]]: ℝ(𝔽(days)), [[Hours]]: ℝ(𝔽(hours)), [[Minutes]]: ℝ(𝔽(minutes)), [[Seconds]]: ℝ(𝔽(seconds)), [[Milliseconds]]: ℝ(𝔽(milliseconds)), [[Microseconds]]: ℝ(𝔽(microseconds)), [[Nanoseconds]]: ℝ(𝔽(nanoseconds)) }. - return TimeDurationRecord { .days = days, .hours = hours, .minutes = minutes, .seconds = seconds, .milliseconds = milliseconds, .microseconds = microseconds, .nanoseconds = nanoseconds }; -} - -// 7.5.8 ToTemporalDuration ( item ), https://tc39.es/proposal-temporal/#sec-temporal-totemporalduration -ThrowCompletionOr> to_temporal_duration(VM& vm, Value item) -{ - // 1. If Type(item) is Object and item has an [[InitializedTemporalDuration]] internal slot, then - if (item.is_object() && is(item.as_object())) { - // a. Return item. - return static_cast(item.as_object()); - } - - // 2. Let result be ? ToTemporalDurationRecord(item). - auto result = TRY(to_temporal_duration_record(vm, item)); - - // 3. Return ! CreateTemporalDuration(result.[[Years]], result.[[Months]], result.[[Weeks]], result.[[Days]], result.[[Hours]], result.[[Minutes]], result.[[Seconds]], result.[[Milliseconds]], result.[[Microseconds]], result.[[Nanoseconds]]). - return MUST(create_temporal_duration(vm, result.years, result.months, result.weeks, result.days, result.hours, result.minutes, result.seconds, result.milliseconds, result.microseconds, result.nanoseconds)); -} - -// 7.5.9 ToTemporalDurationRecord ( temporalDurationLike ), https://tc39.es/proposal-temporal/#sec-temporal-totemporaldurationrecord -ThrowCompletionOr to_temporal_duration_record(VM& vm, Value temporal_duration_like) -{ - // 1. If Type(temporalDurationLike) is not Object, then - if (!temporal_duration_like.is_object()) { - // a. Let string be ? ToString(temporalDurationLike). - auto string = TRY(temporal_duration_like.to_string(vm)); - - // b. Return ? ParseTemporalDurationString(string). - return parse_temporal_duration_string(vm, string); - } - - // 2. If temporalDurationLike has an [[InitializedTemporalDuration]] internal slot, then - if (is(temporal_duration_like.as_object())) { - auto& duration = static_cast(temporal_duration_like.as_object()); - - // a. Return ! CreateDurationRecord(temporalDurationLike.[[Years]], temporalDurationLike.[[Months]], temporalDurationLike.[[Weeks]], temporalDurationLike.[[Days]], temporalDurationLike.[[Hours]], temporalDurationLike.[[Minutes]], temporalDurationLike.[[Seconds]], temporalDurationLike.[[Milliseconds]], temporalDurationLike.[[Microseconds]], temporalDurationLike.[[Nanoseconds]]). - return create_duration_record(duration.years(), duration.months(), duration.weeks(), duration.days(), duration.hours(), duration.minutes(), duration.seconds(), duration.milliseconds(), duration.microseconds(), duration.nanoseconds()); - } - - // 3. Let result be a new Duration Record with each field set to 0. - auto result = DurationRecord {}; - - // 4. Let partial be ? ToTemporalPartialDurationRecord(temporalDurationLike). - auto partial = TRY(to_temporal_partial_duration_record(vm, temporal_duration_like)); - - // 5. If partial.[[Years]] is not undefined, set result.[[Years]] to partial.[[Years]]. - if (partial.years.has_value()) - result.years = partial.years.value(); - - // 6. If partial.[[Months]] is not undefined, set result.[[Months]] to partial.[[Months]]. - if (partial.months.has_value()) - result.months = partial.months.value(); - - // 7. If partial.[[Weeks]] is not undefined, set result.[[Weeks]] to partial.[[Weeks]]. - if (partial.weeks.has_value()) - result.weeks = partial.weeks.value(); - - // 8. If partial.[[Days]] is not undefined, set result.[[Days]] to partial.[[Days]]. - if (partial.days.has_value()) - result.days = partial.days.value(); - - // 9. If partial.[[Hours]] is not undefined, set result.[[Hours]] to partial.[[Hours]]. - if (partial.hours.has_value()) - result.hours = partial.hours.value(); - - // 10. If partial.[[Minutes]] is not undefined, set result.[[Minutes]] to partial.[[Minutes]]. - if (partial.minutes.has_value()) - result.minutes = partial.minutes.value(); - - // 11. If partial.[[Seconds]] is not undefined, set result.[[Seconds]] to partial.[[Seconds]]. - if (partial.seconds.has_value()) - result.seconds = partial.seconds.value(); - - // 12. If partial.[[Milliseconds]] is not undefined, set result.[[Milliseconds]] to partial.[[Milliseconds]]. - if (partial.milliseconds.has_value()) - result.milliseconds = partial.milliseconds.value(); - - // 13. If partial.[[Microseconds]] is not undefined, set result.[[Microseconds]] to partial.[[Microseconds]]. - if (partial.microseconds.has_value()) - result.microseconds = partial.microseconds.value(); - - // 14. If partial.[[Nanoseconds]] is not undefined, set result.[[Nanoseconds]] to partial.[[Nanoseconds]]. - if (partial.nanoseconds.has_value()) - result.nanoseconds = partial.nanoseconds.value(); - - // 15. If ! IsValidDuration(result.[[Years]], result.[[Months]], result.[[Weeks]], result.[[Days]], result.[[Hours]], result.[[Minutes]], result.[[Seconds]], result.[[Milliseconds]], result.[[Microseconds]], result.[[Nanoseconds]]) is false, then - if (!is_valid_duration(result.years, result.months, result.weeks, result.days, result.hours, result.minutes, result.seconds, result.milliseconds, result.microseconds, result.nanoseconds)) { - // a. Throw a RangeError exception. - return vm.throw_completion(ErrorType::TemporalInvalidDuration); - } - - // 16. Return result. - return result; -} - // 7.5.10 DurationSign ( years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds ), https://tc39.es/proposal-temporal/#sec-temporal-durationsign i8 duration_sign(double years, double months, double weeks, double days, double hours, double minutes, double seconds, double milliseconds, double microseconds, double nanoseconds) { @@ -299,1794 +96,4 @@ bool is_valid_duration(double years, double months, double weeks, double days, d return true; } -// 7.5.12 DefaultTemporalLargestUnit ( years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds ), https://tc39.es/proposal-temporal/#sec-temporal-defaulttemporallargestunit -StringView default_temporal_largest_unit(double years, double months, double weeks, double days, double hours, double minutes, double seconds, double milliseconds, double microseconds) -{ - // 1. If years ≠ 0, return "year". - if (years != 0) - return "year"sv; - - // 2. If months ≠ 0, return "month". - if (months != 0) - return "month"sv; - - // 3. If weeks ≠ 0, return "week". - if (weeks != 0) - return "week"sv; - - // 4. If days ≠ 0, return "day". - if (days != 0) - return "day"sv; - - // 5. If hours ≠ 0, return "hour". - if (hours != 0) - return "hour"sv; - - // 6. If minutes ≠ 0, return "minute". - if (minutes != 0) - return "minute"sv; - - // 7. If seconds ≠ 0, return "second". - if (seconds != 0) - return "second"sv; - - // 8. If milliseconds ≠ 0, return "millisecond". - if (milliseconds != 0) - return "millisecond"sv; - - // 9. If microseconds ≠ 0, return "microsecond". - if (microseconds != 0) - return "microsecond"sv; - - // 10. Return "nanosecond". - return "nanosecond"sv; -} - -// 7.5.13 ToTemporalPartialDurationRecord ( temporalDurationLike ), https://tc39.es/proposal-temporal/#sec-temporal-totemporalpartialdurationrecord -ThrowCompletionOr to_temporal_partial_duration_record(VM& vm, Value temporal_duration_like) -{ - // 1. If Type(temporalDurationLike) is not Object, then - if (!temporal_duration_like.is_object()) { - // a. Throw a TypeError exception. - return vm.throw_completion(ErrorType::NotAnObject, temporal_duration_like.to_string_without_side_effects()); - } - - // 2. Let result be a new partial Duration Record with each field set to undefined. - auto result = PartialDurationRecord {}; - - // 3. Let days be ? Get(temporalDurationLike, "days"). - auto days = TRY(temporal_duration_like.as_object().get(vm.names.days)); - - // 4. If days is not undefined, set result.[[Days]] to ? ToIntegerIfIntegral(days). - if (!days.is_undefined()) - result.days = TRY(to_integer_if_integral(vm, days, ErrorType::TemporalInvalidDurationPropertyValueNonIntegral, "days"sv, days)); - - // 5. Let hours be ? Get(temporalDurationLike, "hours"). - auto hours = TRY(temporal_duration_like.as_object().get(vm.names.hours)); - - // 6. If hours is not undefined, set result.[[Hours]] to ? ToIntegerIfIntegral(hours). - if (!hours.is_undefined()) - result.hours = TRY(to_integer_if_integral(vm, hours, ErrorType::TemporalInvalidDurationPropertyValueNonIntegral, "hours"sv, hours)); - - // 7. Let microseconds be ? Get(temporalDurationLike, "microseconds"). - auto microseconds = TRY(temporal_duration_like.as_object().get(vm.names.microseconds)); - - // 8. If microseconds is not undefined, set result.[[Microseconds]] to ? ToIntegerIfIntegral(microseconds). - if (!microseconds.is_undefined()) - result.microseconds = TRY(to_integer_if_integral(vm, microseconds, ErrorType::TemporalInvalidDurationPropertyValueNonIntegral, "microseconds"sv, microseconds)); - - // 9. Let milliseconds be ? Get(temporalDurationLike, "milliseconds"). - auto milliseconds = TRY(temporal_duration_like.as_object().get(vm.names.milliseconds)); - - // 10. If milliseconds is not undefined, set result.[[Milliseconds]] to ? ToIntegerIfIntegral(milliseconds). - if (!milliseconds.is_undefined()) - result.milliseconds = TRY(to_integer_if_integral(vm, milliseconds, ErrorType::TemporalInvalidDurationPropertyValueNonIntegral, "milliseconds"sv, milliseconds)); - - // 11. Let minutes be ? Get(temporalDurationLike, "minutes"). - auto minutes = TRY(temporal_duration_like.as_object().get(vm.names.minutes)); - - // 12. If minutes is not undefined, set result.[[Minutes]] to ? ToIntegerIfIntegral(minutes). - if (!minutes.is_undefined()) - result.minutes = TRY(to_integer_if_integral(vm, minutes, ErrorType::TemporalInvalidDurationPropertyValueNonIntegral, "minutes"sv, minutes)); - - // 13. Let months be ? Get(temporalDurationLike, "months"). - auto months = TRY(temporal_duration_like.as_object().get(vm.names.months)); - - // 14. If months is not undefined, set result.[[Months]] to ? ToIntegerIfIntegral(months). - if (!months.is_undefined()) - result.months = TRY(to_integer_if_integral(vm, months, ErrorType::TemporalInvalidDurationPropertyValueNonIntegral, "months"sv, months)); - - // 15. Let nanoseconds be ? Get(temporalDurationLike, "nanoseconds"). - auto nanoseconds = TRY(temporal_duration_like.as_object().get(vm.names.nanoseconds)); - - // 16. If nanoseconds is not undefined, set result.[[Nanoseconds]] to ? ToIntegerIfIntegral(nanoseconds). - if (!nanoseconds.is_undefined()) - result.nanoseconds = TRY(to_integer_if_integral(vm, nanoseconds, ErrorType::TemporalInvalidDurationPropertyValueNonIntegral, "nanoseconds"sv, nanoseconds)); - - // 17. Let seconds be ? Get(temporalDurationLike, "seconds"). - auto seconds = TRY(temporal_duration_like.as_object().get(vm.names.seconds)); - - // 18. If seconds is not undefined, set result.[[Seconds]] to ? ToIntegerIfIntegral(seconds). - if (!seconds.is_undefined()) - result.seconds = TRY(to_integer_if_integral(vm, seconds, ErrorType::TemporalInvalidDurationPropertyValueNonIntegral, "seconds"sv, seconds)); - - // 19. Let weeks be ? Get(temporalDurationLike, "weeks"). - auto weeks = TRY(temporal_duration_like.as_object().get(vm.names.weeks)); - - // 20. If weeks is not undefined, set result.[[Weeks]] to ? ToIntegerIfIntegral(weeks). - if (!weeks.is_undefined()) - result.weeks = TRY(to_integer_if_integral(vm, weeks, ErrorType::TemporalInvalidDurationPropertyValueNonIntegral, "weeks"sv, weeks)); - - // 21. Let years be ? Get(temporalDurationLike, "years"). - auto years = TRY(temporal_duration_like.as_object().get(vm.names.years)); - - // 22. If years is not undefined, set result.[[Years]] to ? ToIntegerIfIntegral(years). - if (!years.is_undefined()) - result.years = TRY(to_integer_if_integral(vm, years, ErrorType::TemporalInvalidDurationPropertyValueNonIntegral, "years"sv, years)); - - // 23. If years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, and nanoseconds are all undefined, throw a TypeError exception. - if (years.is_undefined() && months.is_undefined() && weeks.is_undefined() && days.is_undefined() && hours.is_undefined() && minutes.is_undefined() && seconds.is_undefined() && milliseconds.is_undefined() && microseconds.is_undefined() && nanoseconds.is_undefined()) - return vm.throw_completion(ErrorType::TemporalInvalidDurationLikeObject); - - // 24. Return result. - return result; -} - -// 7.5.14 CreateTemporalDuration ( years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds [ , newTarget ] ), https://tc39.es/proposal-temporal/#sec-temporal-createtemporalduration -ThrowCompletionOr> create_temporal_duration(VM& vm, double years, double months, double weeks, double days, double hours, double minutes, double seconds, double milliseconds, double microseconds, double nanoseconds, FunctionObject const* new_target) -{ - auto& realm = *vm.current_realm(); - - // 1. If ! IsValidDuration(years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds) is false, throw a RangeError exception. - if (!is_valid_duration(years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds)) - return vm.throw_completion(ErrorType::TemporalInvalidDuration); - - // 2. If newTarget is not present, set newTarget to %Temporal.Duration%. - if (!new_target) - new_target = realm.intrinsics().temporal_duration_constructor(); - - // 3. Let object be ? OrdinaryCreateFromConstructor(newTarget, "%Temporal.Duration.prototype%", « [[InitializedTemporalDuration]], [[Years]], [[Months]], [[Weeks]], [[Days]], [[Hours]], [[Minutes]], [[Seconds]], [[Milliseconds]], [[Microseconds]], [[Nanoseconds]] »). - // 4. Set object.[[Years]] to ℝ(𝔽(years)). - // 5. Set object.[[Months]] to ℝ(𝔽(months)). - // 6. Set object.[[Weeks]] to ℝ(𝔽(weeks)). - // 7. Set object.[[Days]] to ℝ(𝔽(days)). - // 8. Set object.[[Hours]] to ℝ(𝔽(hours)). - // 9. Set object.[[Minutes]] to ℝ(𝔽(minutes)). - // 10. Set object.[[Seconds]] to ℝ(𝔽(seconds)). - // 11. Set object.[[Milliseconds]] to ℝ(𝔽(milliseconds)). - // 12. Set object.[[Microseconds]] to ℝ(𝔽(microseconds)). - // 13. Set object.[[Nanoseconds]] to ℝ(𝔽(nanoseconds)). - auto object = TRY(ordinary_create_from_constructor(vm, *new_target, &Intrinsics::temporal_duration_prototype, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds)); - - // 14. Return object. - return object; -} - -// 7.5.15 CreateNegatedTemporalDuration ( duration ), https://tc39.es/proposal-temporal/#sec-temporal-createnegatedtemporalduration -GC::Ref create_negated_temporal_duration(VM& vm, Duration const& duration) -{ - // 1. Return ! CreateTemporalDuration(-duration.[[Years]], -duration.[[Months]], -duration.[[Weeks]], -duration.[[Days]], -duration.[[Hours]], -duration.[[Minutes]], -duration.[[Seconds]], -duration.[[Milliseconds]], -duration.[[Microseconds]], -duration.[[Nanoseconds]]). - return MUST(create_temporal_duration(vm, -duration.years(), -duration.months(), -duration.weeks(), -duration.days(), -duration.hours(), -duration.minutes(), -duration.seconds(), -duration.milliseconds(), -duration.microseconds(), -duration.nanoseconds())); -} - -// 7.5.16 CalculateOffsetShift ( relativeTo, y, mon, w, d ), https://tc39.es/proposal-temporal/#sec-temporal-calculateoffsetshift -ThrowCompletionOr calculate_offset_shift(VM& vm, Value relative_to_value, double years, double months, double weeks, double days) -{ - // 1. If Type(relativeTo) is not Object or relativeTo does not have an [[InitializedTemporalZonedDateTime]] internal slot, return 0. - if (!relative_to_value.is_object() || !is(relative_to_value.as_object())) - return 0.0; - - auto& relative_to = static_cast(relative_to_value.as_object()); - auto time_zone_record = TRY(create_time_zone_methods_record(vm, GC::Ref { relative_to.time_zone() }, { { TimeZoneMethod::GetOffsetNanosecondsFor } })); - - // 2. Let instant be ! CreateTemporalInstant(relativeTo.[[Nanoseconds]]). - auto* instant = MUST(create_temporal_instant(vm, relative_to.nanoseconds())); - - // 3. Let offsetBefore be ? GetOffsetNanosecondsFor(relativeTo.[[TimeZone]], instant). - auto offset_before = TRY(get_offset_nanoseconds_for(vm, time_zone_record, *instant)); - - // 4. Let after be ? AddZonedDateTime(relativeTo.[[Nanoseconds]], relativeTo.[[TimeZone]], relativeTo.[[Calendar]], y, mon, w, d, 0, 0, 0, 0, 0, 0). - auto* after = TRY(add_zoned_date_time(vm, relative_to.nanoseconds(), &relative_to.time_zone(), relative_to.calendar(), years, months, weeks, days, 0, 0, 0, 0, 0, 0)); - - // 5. Let instantAfter be ! CreateTemporalInstant(after). - auto* instant_after = MUST(create_temporal_instant(vm, *after)); - - // 6. Let offsetAfter be ? GetOffsetNanosecondsFor(relativeTo.[[TimeZone]], instantAfter). - auto offset_after = TRY(get_offset_nanoseconds_for(vm, time_zone_record, *instant_after)); - - // 7. Return offsetAfter - offsetBefore. - return offset_after - offset_before; -} - -// 7.5.17 BalanceTimeDuration ( days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, largestUnit ), https://tc39.es/proposal-temporal/#sec-temporal-balancetimeduration -ThrowCompletionOr balance_time_duration(VM& vm, double days, double hours, double minutes, double seconds, double milliseconds, double microseconds, Crypto::SignedBigInteger const& nanoseconds, StringView largest_unit) -{ - // 1. Let balanceResult be BalancePossiblyInfiniteTimeDuration(days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, largestUnit). - auto balance_result = balance_possibly_infinite_time_duration(vm, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, largest_unit); - - // 2. If balanceResult is positive overflow or negative overflow, then - if (balance_result.has()) { - // a. Throw a RangeError exception. - return vm.throw_completion(ErrorType::TemporalInvalidDuration); - } - // 3. Else, - else { - // a. Return balanceResult. - return balance_result.get(); - } -} - -// 7.5.17 TotalDurationNanoseconds ( days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, offsetShift ), https://tc39.es/proposal-temporal/#sec-temporal-totaldurationnanoseconds -Crypto::SignedBigInteger total_duration_nanoseconds(double days, double hours, double minutes, double seconds, double milliseconds, double microseconds, Crypto::SignedBigInteger const& nanoseconds, double offset_shift) -{ - VERIFY(offset_shift == trunc(offset_shift)); - - auto result_nanoseconds = nanoseconds; - - // 1. If days ≠ 0, then - if (days != 0) { - // a. Set nanoseconds to nanoseconds - offsetShift. - result_nanoseconds = result_nanoseconds.minus(Crypto::SignedBigInteger { offset_shift }); - } - // 2. Set hours to hours + days × 24. - auto total_hours = Crypto::SignedBigInteger { hours }.plus(Crypto::SignedBigInteger { days }.multiplied_by(Crypto::UnsignedBigInteger(24))); - // 3. Set minutes to minutes + hours × 60. - auto total_minutes = Crypto::SignedBigInteger { minutes }.plus(total_hours.multiplied_by(Crypto::UnsignedBigInteger(60))); - // 4. Set seconds to seconds + minutes × 60. - auto total_seconds = Crypto::SignedBigInteger { seconds }.plus(total_minutes.multiplied_by(Crypto::UnsignedBigInteger(60))); - // 5. Set milliseconds to milliseconds + seconds × 1000. - auto total_milliseconds = Crypto::SignedBigInteger { milliseconds }.plus(total_seconds.multiplied_by(Crypto::UnsignedBigInteger(1000))); - // 6. Set microseconds to microseconds + milliseconds × 1000. - auto total_microseconds = Crypto::SignedBigInteger { microseconds }.plus(total_milliseconds.multiplied_by(Crypto::UnsignedBigInteger(1000))); - // 7. Return nanoseconds + microseconds × 1000. - return result_nanoseconds.plus(total_microseconds.multiplied_by(Crypto::UnsignedBigInteger(1000))); -} - -// FIXME: This function does not exist in newer versions of the spec. It does not properly support as an example a roundingMode of 'ceil' -// Update all callers of this function to spec as required. -// 7.5.18 BalanceDuration ( days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, largestUnit [ , relativeTo ] ), https://tc39.es/proposal-temporal/#sec-temporal-balanceduration -ThrowCompletionOr balance_duration(VM& vm, double days, double hours, double minutes, double seconds, double milliseconds, double microseconds, Crypto::SignedBigInteger const& nanoseconds, StringView largest_unit, Object* relative_to) -{ - // 1. If relativeTo is not present, set relativeTo to undefined. - - // NOTE: If any of the inputs is not finite this will mean that we have infinities, - // so the duration will never be valid. Also - if (!isfinite(days) || !isfinite(hours) || !isfinite(minutes) || !isfinite(seconds) || !isfinite(milliseconds) || !isfinite(microseconds)) - return vm.throw_completion(ErrorType::TemporalInvalidDuration); - - Crypto::SignedBigInteger total_nanoseconds; - // 2. If Type(relativeTo) is Object and relativeTo has an [[InitializedTemporalZonedDateTime]] internal slot, then - if (relative_to && is(*relative_to)) { - auto& relative_to_zoned_date_time = static_cast(*relative_to); - - // a. Let endNs be ? AddZonedDateTime(relativeTo.[[Nanoseconds]], relativeTo.[[TimeZone]], relativeTo.[[Calendar]], 0, 0, 0, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds). - auto* end_ns = TRY(add_zoned_date_time(vm, relative_to_zoned_date_time.nanoseconds(), &relative_to_zoned_date_time.time_zone(), relative_to_zoned_date_time.calendar(), 0, 0, 0, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds.to_double())); - - // b. Set nanoseconds to ℝ(endNs - relativeTo.[[Nanoseconds]]). - total_nanoseconds = end_ns->big_integer().minus(relative_to_zoned_date_time.nanoseconds().big_integer()); - } - // 3. Else, - else { - // a. Set nanoseconds to ! TotalDurationNanoseconds(days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, 0). - total_nanoseconds = total_duration_nanoseconds(days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, 0); - } - - // 4. If largestUnit is one of "year", "month", "week", or "day", then - if (largest_unit.is_one_of("year"sv, "month"sv, "week"sv, "day"sv)) { - // a. Let result be ? NanosecondsToDays(nanoseconds, relativeTo). - auto result = TRY(nanoseconds_to_days(vm, total_nanoseconds, relative_to ?: js_undefined())); - - // b. Set days to result.[[Days]]. - days = result.days; - - // c. Set nanoseconds to result.[[Nanoseconds]]. - total_nanoseconds = move(result.nanoseconds); - } - // 5. Else, - else { - // a. Set days to 0. - days = 0; - } - // 6. Set hours, minutes, seconds, milliseconds, and microseconds to 0. - hours = 0; - minutes = 0; - seconds = 0; - milliseconds = 0; - microseconds = 0; - - // 7. If nanoseconds < 0, let sign be -1; else, let sign be 1. - i8 sign = total_nanoseconds.is_negative() ? -1 : 1; - - // 8. Set nanoseconds to abs(nanoseconds). - total_nanoseconds = Crypto::SignedBigInteger(total_nanoseconds.unsigned_value()); - auto result_nanoseconds = total_nanoseconds.to_double(); - - // 9. If largestUnit is "year", "month", "week", "day", or "hour", then - if (largest_unit.is_one_of("year"sv, "month"sv, "week"sv, "day"sv, "hour"sv)) { - // a. Set microseconds to floor(nanoseconds / 1000). - auto nanoseconds_division_result = total_nanoseconds.divided_by(Crypto::UnsignedBigInteger(1000)); - // b. Set nanoseconds to nanoseconds modulo 1000. - result_nanoseconds = nanoseconds_division_result.remainder.to_double(); - // c. Set milliseconds to floor(microseconds / 1000). - auto microseconds_division_result = nanoseconds_division_result.quotient.divided_by(Crypto::UnsignedBigInteger(1000)); - // d. Set microseconds to microseconds modulo 1000. - microseconds = microseconds_division_result.remainder.to_double(); - // e. Set seconds to floor(milliseconds / 1000). - auto milliseconds_division_result = microseconds_division_result.quotient.divided_by(Crypto::UnsignedBigInteger(1000)); - // f. Set milliseconds to milliseconds modulo 1000. - milliseconds = milliseconds_division_result.remainder.to_double(); - // g. Set minutes to floor(seconds / 60). - auto seconds_division_result = milliseconds_division_result.quotient.divided_by(Crypto::UnsignedBigInteger(60)); - // h. Set seconds to seconds modulo 60. - seconds = seconds_division_result.remainder.to_double(); - // i. Set hours to floor(minutes / 60). - auto minutes_division_result = seconds_division_result.quotient.divided_by(Crypto::UnsignedBigInteger(60)); - hours = minutes_division_result.quotient.to_double(); - // j. Set minutes to minutes modulo 60. - minutes = minutes_division_result.remainder.to_double(); - } - // 10. Else if largestUnit is "minute", then - else if (largest_unit == "minute"sv) { - // a. Set microseconds to floor(nanoseconds / 1000). - auto nanoseconds_division_result = total_nanoseconds.divided_by(Crypto::UnsignedBigInteger(1000)); - // b. Set nanoseconds to nanoseconds modulo 1000. - result_nanoseconds = nanoseconds_division_result.remainder.to_double(); - // c. Set milliseconds to floor(microseconds / 1000). - auto microseconds_division_result = nanoseconds_division_result.quotient.divided_by(Crypto::UnsignedBigInteger(1000)); - // d. Set microseconds to microseconds modulo 1000. - microseconds = microseconds_division_result.remainder.to_double(); - // e. Set seconds to floor(milliseconds / 1000). - auto milliseconds_division_result = microseconds_division_result.quotient.divided_by(Crypto::UnsignedBigInteger(1000)); - // f. Set milliseconds to milliseconds modulo 1000. - milliseconds = milliseconds_division_result.remainder.to_double(); - // g. Set minutes to floor(seconds / 60). - auto seconds_division_result = milliseconds_division_result.quotient.divided_by(Crypto::UnsignedBigInteger(60)); - minutes = seconds_division_result.quotient.to_double(); - // h. Set seconds to seconds modulo 60. - seconds = seconds_division_result.remainder.to_double(); - } - // 11. Else if largestUnit is "second", then - else if (largest_unit == "second"sv) { - // a. Set microseconds to floor(nanoseconds / 1000). - auto nanoseconds_division_result = total_nanoseconds.divided_by(Crypto::UnsignedBigInteger(1000)); - // b. Set nanoseconds to nanoseconds modulo 1000. - result_nanoseconds = nanoseconds_division_result.remainder.to_double(); - // c. Set milliseconds to floor(microseconds / 1000). - auto microseconds_division_result = nanoseconds_division_result.quotient.divided_by(Crypto::UnsignedBigInteger(1000)); - // d. Set microseconds to microseconds modulo 1000. - microseconds = microseconds_division_result.remainder.to_double(); - // e. Set seconds to floor(milliseconds / 1000). - auto milliseconds_division_result = microseconds_division_result.quotient.divided_by(Crypto::UnsignedBigInteger(1000)); - seconds = milliseconds_division_result.quotient.to_double(); - // f. Set milliseconds to milliseconds modulo 1000. - milliseconds = milliseconds_division_result.remainder.to_double(); - } - // 12. Else if largestUnit is "millisecond", then - else if (largest_unit == "millisecond"sv) { - // a. Set microseconds to floor(nanoseconds / 1000). - auto nanoseconds_division_result = total_nanoseconds.divided_by(Crypto::UnsignedBigInteger(1000)); - // b. Set nanoseconds to nanoseconds modulo 1000. - result_nanoseconds = nanoseconds_division_result.remainder.to_double(); - // c. Set milliseconds to floor(microseconds / 1000). - auto microseconds_division_result = nanoseconds_division_result.quotient.divided_by(Crypto::UnsignedBigInteger(1000)); - milliseconds = microseconds_division_result.quotient.to_double(); - // d. Set microseconds to microseconds modulo 1000. - microseconds = microseconds_division_result.remainder.to_double(); - } - // 13. Else if largestUnit is "microsecond", then - else if (largest_unit == "microsecond"sv) { - // a. Set microseconds to floor(nanoseconds / 1000). - auto nanoseconds_division_result = total_nanoseconds.divided_by(Crypto::UnsignedBigInteger(1000)); - microseconds = nanoseconds_division_result.quotient.to_double(); - // b. Set nanoseconds to nanoseconds modulo 1000. - result_nanoseconds = nanoseconds_division_result.remainder.to_double(); - } - // 14. Else, - else { - // a. Assert: largestUnit is "nanosecond". - VERIFY(largest_unit == "nanosecond"sv); - } - // 15. Return ? CreateTimeDurationRecord(days, hours × sign, minutes × sign, seconds × sign, milliseconds × sign, microseconds × sign, nanoseconds × sign). - return create_time_duration_record(vm, days, hours * sign, minutes * sign, seconds * sign, milliseconds * sign, microseconds * sign, result_nanoseconds * sign); -} - -// 7.5.18 BalancePossiblyInfiniteTimeDuration ( days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, largestUnit ), https://tc39.es/proposal-temporal/#sec-temporal-balancepossiblyinfinitetimeduration -Variant balance_possibly_infinite_time_duration(VM& vm, double days, double hours, double minutes, double seconds, double milliseconds, double microseconds, Crypto::SignedBigInteger const& nanoseconds, StringView largest_unit) -{ - // 1. Set hours to hours + days × 24. - hours += days * 24.; - - // 2. Set nanoseconds to TotalDurationNanoseconds(hours, minutes, seconds, milliseconds, microseconds, nanoseconds). - // FIXME: We shouldn't be passing through 0 days and 0 offset digit - auto nanoseconds_bigint = total_duration_nanoseconds(0, hours, minutes, seconds, milliseconds, microseconds, Crypto::SignedBigInteger { nanoseconds }, 0); - double result_nanoseconds = 0; - - // 3. Set days, hours, minutes, seconds, milliseconds, and microseconds to 0. - days = 0; - hours = 0; - minutes = 0; - seconds = 0; - milliseconds = 0; - microseconds = 0; - - // 4. If nanoseconds < 0, let sign be -1; else, let sign be 1. - auto sign = nanoseconds_bigint.is_negative() ? -1 : 1; - - // 5. Set nanoseconds to abs(nanoseconds). - auto total_nanoseconds = Crypto::SignedBigInteger { nanoseconds_bigint.unsigned_value() }; - - // 6. If largestUnit is "year", "month", "week", or "day", then - if (largest_unit.is_one_of("year"sv, "month"sv, "week"sv, "day"sv)) { - // a. Set microseconds to floor(nanoseconds / 1000). - auto nanoseconds_division_result = total_nanoseconds.divided_by(Crypto::UnsignedBigInteger(1000)); - // b. Set nanoseconds to nanoseconds modulo 1000. - result_nanoseconds = nanoseconds_division_result.remainder.to_double(); - // c. Set milliseconds to floor(microseconds / 1000). - auto microseconds_division_result = nanoseconds_division_result.quotient.divided_by(Crypto::UnsignedBigInteger(1000)); - // d. Set microseconds to microseconds modulo 1000. - microseconds = microseconds_division_result.remainder.to_double(); - // e. Set seconds to floor(milliseconds / 1000). - auto milliseconds_division_result = microseconds_division_result.quotient.divided_by(Crypto::UnsignedBigInteger(1000)); - // f. Set milliseconds to milliseconds modulo 1000. - milliseconds = milliseconds_division_result.remainder.to_double(); - // g. Set minutes to floor(seconds / 60). - auto seconds_division_result = milliseconds_division_result.quotient.divided_by(Crypto::UnsignedBigInteger(60)); - // h. Set seconds to seconds modulo 60. - seconds = seconds_division_result.remainder.to_double(); - // i. Set hours to floor(minutes / 60). - auto minutes_division_result = seconds_division_result.quotient.divided_by(Crypto::UnsignedBigInteger(60)); - // j. Set minutes to minutes modulo 60. - minutes = minutes_division_result.remainder.to_double(); - // k. Set days to floor(hours / 24). - auto hours_division_result = minutes_division_result.quotient.divided_by(Crypto::UnsignedBigInteger(24)); - days = hours_division_result.quotient.to_double(); - // l. Set hours to hours modulo 24. - hours = hours_division_result.remainder.to_double(); - } - // 7. Else if largestUnit is "hour", then - else if (largest_unit == "hour"sv) { - // a. Set microseconds to floor(nanoseconds / 1000). - auto nanoseconds_division_result = total_nanoseconds.divided_by(Crypto::UnsignedBigInteger(1000)); - // b. Set nanoseconds to nanoseconds modulo 1000. - result_nanoseconds = nanoseconds_division_result.remainder.to_double(); - // c. Set milliseconds to floor(microseconds / 1000). - auto microseconds_division_result = nanoseconds_division_result.quotient.divided_by(Crypto::UnsignedBigInteger(1000)); - // d. Set microseconds to microseconds modulo 1000. - microseconds = microseconds_division_result.remainder.to_double(); - // e. Set seconds to floor(milliseconds / 1000). - auto milliseconds_division_result = microseconds_division_result.quotient.divided_by(Crypto::UnsignedBigInteger(1000)); - // f. Set milliseconds to milliseconds modulo 1000. - milliseconds = milliseconds_division_result.remainder.to_double(); - // g. Set minutes to floor(seconds / 60). - auto seconds_division_result = milliseconds_division_result.quotient.divided_by(Crypto::UnsignedBigInteger(60)); - // h. Set seconds to seconds modulo 60. - seconds = seconds_division_result.remainder.to_double(); - // i. Set hours to floor(minutes / 60). - auto minutes_division_result = seconds_division_result.quotient.divided_by(Crypto::UnsignedBigInteger(60)); - hours = minutes_division_result.quotient.to_double(); - // j. Set minutes to minutes modulo 60. - minutes = minutes_division_result.remainder.to_double(); - } - // 8. Else if largestUnit is "minute", then - else if (largest_unit == "minute"sv) { - // a. Set microseconds to floor(nanoseconds / 1000). - auto nanoseconds_division_result = total_nanoseconds.divided_by(Crypto::UnsignedBigInteger(1000)); - // b. Set nanoseconds to nanoseconds modulo 1000. - result_nanoseconds = nanoseconds_division_result.remainder.to_double(); - // c. Set milliseconds to floor(microseconds / 1000). - auto microseconds_division_result = nanoseconds_division_result.quotient.divided_by(Crypto::UnsignedBigInteger(1000)); - // d. Set microseconds to microseconds modulo 1000. - microseconds = microseconds_division_result.remainder.to_double(); - // e. Set seconds to floor(milliseconds / 1000). - auto milliseconds_division_result = microseconds_division_result.quotient.divided_by(Crypto::UnsignedBigInteger(1000)); - // f. Set milliseconds to milliseconds modulo 1000. - milliseconds = milliseconds_division_result.remainder.to_double(); - // g. Set minutes to floor(seconds / 60). - auto seconds_division_result = milliseconds_division_result.quotient.divided_by(Crypto::UnsignedBigInteger(60)); - minutes = seconds_division_result.quotient.to_double(); - // h. Set seconds to seconds modulo 60. - seconds = seconds_division_result.remainder.to_double(); - } - // 9. Else if largestUnit is "second", then - else if (largest_unit == "second"sv) { - // a. Set microseconds to floor(nanoseconds / 1000). - auto nanoseconds_division_result = total_nanoseconds.divided_by(Crypto::UnsignedBigInteger(1000)); - // b. Set nanoseconds to nanoseconds modulo 1000. - result_nanoseconds = nanoseconds_division_result.remainder.to_double(); - // c. Set milliseconds to floor(microseconds / 1000). - auto microseconds_division_result = nanoseconds_division_result.quotient.divided_by(Crypto::UnsignedBigInteger(1000)); - // d. Set microseconds to microseconds modulo 1000. - microseconds = microseconds_division_result.remainder.to_double(); - // e. Set seconds to floor(milliseconds / 1000). - auto milliseconds_division_result = microseconds_division_result.quotient.divided_by(Crypto::UnsignedBigInteger(1000)); - seconds = milliseconds_division_result.quotient.to_double(); - // f. Set milliseconds to milliseconds modulo 1000. - milliseconds = milliseconds_division_result.remainder.to_double(); - } - // 10. Else if largestUnit is "millisecond", then - else if (largest_unit == "millisecond"sv) { - // a. Set microseconds to floor(nanoseconds / 1000). - auto nanoseconds_division_result = total_nanoseconds.divided_by(Crypto::UnsignedBigInteger(1000)); - // b. Set nanoseconds to nanoseconds modulo 1000. - result_nanoseconds = nanoseconds_division_result.remainder.to_double(); - // c. Set milliseconds to floor(microseconds / 1000). - auto microseconds_division_result = nanoseconds_division_result.quotient.divided_by(Crypto::UnsignedBigInteger(1000)); - milliseconds = microseconds_division_result.quotient.to_double(); - // d. Set microseconds to microseconds modulo 1000. - microseconds = microseconds_division_result.remainder.to_double(); - } - // 11. Else if largestUnit is "microsecond", then - else if (largest_unit == "microsecond"sv) { - // a. Set microseconds to floor(nanoseconds / 1000). - auto nanoseconds_division_result = total_nanoseconds.divided_by(Crypto::UnsignedBigInteger(1000)); - microseconds = nanoseconds_division_result.quotient.to_double(); - // b. Set nanoseconds to nanoseconds modulo 1000. - result_nanoseconds = nanoseconds_division_result.remainder.to_double(); - } - // 12. Else, - else { - // a. Assert: largestUnit is "nanosecond". - VERIFY(largest_unit == "nanosecond"sv); - result_nanoseconds = total_nanoseconds.to_double(); - } - - // 13. For each value v of « days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds », do - for (double v : { days, hours, minutes, seconds, milliseconds, microseconds, microseconds, result_nanoseconds }) { - // a. If 𝔽(v) is not finite, then - if (!isfinite(v)) { - // i. If sign = 1, then - if (sign == 1) { - // 1. Return positive overflow. - return Overflow::Positive; - } - // ii. Else if sign = -1, then - else { - // 1. Return negative overflow. - return Overflow::Negative; - } - } - } - - // 14. Return ! CreateTimeDurationRecord(days × sign, hours × sign, minutes × sign, seconds × sign, milliseconds × sign, microseconds × sign, nanoseconds × sign). - return MUST(create_time_duration_record(vm, days * sign, hours * sign, minutes * sign, seconds * sign, milliseconds * sign, microseconds * sign, result_nanoseconds * sign)); -} - -// 7.5.19 UnbalanceDurationRelative ( years, months, weeks, days, largestUnit, relativeTo ), https://tc39.es/proposal-temporal/#sec-temporal-unbalancedurationrelative -ThrowCompletionOr unbalance_duration_relative(VM& vm, double years, double months, double weeks, double days, StringView largest_unit, Value relative_to) -{ - auto& realm = *vm.current_realm(); - - // 1. If largestUnit is "year", or years, months, weeks, and days are all 0, then - if (largest_unit == "year"sv || (years == 0 && months == 0 && weeks == 0 && days == 0)) { - // a. Return ! CreateDateDurationRecord(years, months, weeks, days). - return create_date_duration_record(years, months, weeks, days); - } - - // 2. Let sign be ! DurationSign(years, months, weeks, days, 0, 0, 0, 0, 0, 0). - auto sign = duration_sign(years, months, weeks, days, 0, 0, 0, 0, 0, 0); - - // 3. Assert: sign ≠ 0. - VERIFY(sign != 0); - - // 4. Let oneYear be ! CreateTemporalDuration(sign, 0, 0, 0, 0, 0, 0, 0, 0, 0). - auto one_year = MUST(create_temporal_duration(vm, sign, 0, 0, 0, 0, 0, 0, 0, 0, 0)); - - // 5. Let oneMonth be ! CreateTemporalDuration(0, sign, 0, 0, 0, 0, 0, 0, 0, 0). - auto one_month = MUST(create_temporal_duration(vm, 0, sign, 0, 0, 0, 0, 0, 0, 0, 0)); - - // 6. Let oneWeek be ! CreateTemporalDuration(0, 0, sign, 0, 0, 0, 0, 0, 0, 0). - auto one_week = MUST(create_temporal_duration(vm, 0, 0, sign, 0, 0, 0, 0, 0, 0, 0)); - - Object* calendar; - - // 7. If relativeTo is not undefined, then - if (!relative_to.is_undefined()) { - // a. Set relativeTo to ? ToTemporalDate(relativeTo). - auto* relative_to_plain_date = TRY(to_temporal_date(vm, relative_to)); - relative_to = relative_to_plain_date; - - // b. Let calendar be relativeTo.[[Calendar]]. - calendar = &relative_to_plain_date->calendar(); - } - // 8. Else, - else { - // a. Let calendar be undefined. - calendar = nullptr; - } - - // 9. If largestUnit is "month", then - if (largest_unit == "month"sv) { - // a. If calendar is undefined, then - if (!calendar) { - // i. Throw a RangeError exception. - return vm.throw_completion(ErrorType::TemporalMissingStartingPoint, "months"); - } - - // b. Let dateAdd be ? GetMethod(calendar, "dateAdd"). - auto date_add = TRY(Value(calendar).get_method(vm, vm.names.dateAdd)); - - // FIXME: This AO is out of date, this is no longer needed. - // c. Let dateUntil be ? GetMethod(calendar, "dateUntil"). - - // d. Repeat, while years ≠ 0, - while (years != 0) { - // i. Let newRelativeTo be ? CalendarDateAdd(calendar, relativeTo, oneYear, undefined, dateAdd). - auto* new_relative_to = TRY(calendar_date_add(vm, *calendar, relative_to, *one_year, nullptr, date_add)); - - // ii. Let untilOptions be OrdinaryObjectCreate(null). - auto until_options = Object::create(realm, nullptr); - - // iii. Perform ! CreateDataPropertyOrThrow(untilOptions, "largestUnit", "month"). - MUST(until_options->create_data_property_or_throw(vm.names.largestUnit, PrimitiveString::create(vm, "month"_string))); - - // FIXME: AD-HOC calendar records use as this AO is not up to date with latest spec - // iv. Let untilResult be ? CalendarDateUntil(calendar, relativeTo, newRelativeTo, untilOptions, dateUntil). - auto calendar_record = TRY(create_calendar_methods_record(vm, GC::Ref { *calendar }, { { CalendarMethod::DateAdd, CalendarMethod::DateUntil } })); - auto until_result = TRY(calendar_date_until(vm, calendar_record, relative_to, new_relative_to, *until_options)); - - // v. Let oneYearMonths be untilResult.[[Months]]. - auto one_year_months = until_result->months(); - - // vi. Set relativeTo to newRelativeTo. - relative_to = new_relative_to; - - // vii. Set years to years - sign. - years -= sign; - - // viii. Set months to months + oneYearMonths. - months += one_year_months; - } - } - // 10. Else if largestUnit is "week", then - else if (largest_unit == "week"sv) { - // a. If calendar is undefined, then - if (!calendar) { - // i. Throw a RangeError exception. - return vm.throw_completion(ErrorType::TemporalMissingStartingPoint, "weeks"); - } - - // b. Let dateAdd be ? GetMethod(calendar, "dateAdd"). - auto date_add = TRY(Value(calendar).get_method(vm, vm.names.dateAdd)); - - // c. Repeat, while years ≠ 0, - while (years != 0) { - // i. Let moveResult be ? MoveRelativeDate(calendar, relativeTo, oneYear, dateAdd). - auto move_result = TRY(move_relative_date(vm, *calendar, verify_cast(relative_to.as_object()), *one_year, date_add)); - - // ii. Set relativeTo to moveResult.[[RelativeTo]]. - relative_to = move_result.relative_to.cell(); - - // iii. Set days to days + moveResult.[[Days]]. - days += move_result.days; - - // iv. Set years to years - sign. - years -= sign; - } - - // d. Repeat, while months ≠ 0, - while (months != 0) { - // i. Let moveResult be ? MoveRelativeDate(calendar, relativeTo, oneMonth, dateAdd). - auto move_result = TRY(move_relative_date(vm, *calendar, verify_cast(relative_to.as_object()), *one_month, date_add)); - - // ii. Set relativeTo to moveResult.[[RelativeTo]]. - relative_to = move_result.relative_to.cell(); - - // iii. Set days to days + moveResult.[[Days]]. - days += move_result.days; - - // iv. Set months to months - sign. - months -= sign; - } - } - // 11. Else, - else { - // a. If any of years, months, and weeks are not zero, then - if (years != 0 || months != 0 || weeks != 0) { - // i. If calendar is undefined, then - if (!calendar) { - // i. Throw a RangeError exception. - return vm.throw_completion(ErrorType::TemporalMissingStartingPoint, "calendar units"); - } - - // ii. Let dateAdd be ? GetMethod(calendar, "dateAdd"). - auto date_add = TRY(Value(calendar).get_method(vm, vm.names.dateAdd)); - - // iii. Repeat, while years ≠ 0, - while (years != 0) { - // 1. Let moveResult be ? MoveRelativeDate(calendar, relativeTo, oneYear, dateAdd). - auto move_result = TRY(move_relative_date(vm, *calendar, verify_cast(relative_to.as_object()), *one_year, date_add)); - - // 2. Set relativeTo to moveResult.[[RelativeTo]]. - relative_to = move_result.relative_to.cell(); - - // 3. Set days to days + moveResult.[[Days]]. - days += move_result.days; - - // 4. Set years to years - sign. - years -= sign; - } - - // iv. Repeat, while months ≠ 0, - while (months != 0) { - // 1. Let moveResult be ? MoveRelativeDate(calendar, relativeTo, oneMonth, dateAdd). - auto move_result = TRY(move_relative_date(vm, *calendar, verify_cast(relative_to.as_object()), *one_month, date_add)); - - // 2. Set relativeTo to moveResult.[[RelativeTo]]. - relative_to = move_result.relative_to.cell(); - - // 3. Set days to days +moveResult.[[Days]]. - days += move_result.days; - - // 4. Set months to months - sign. - months -= sign; - } - - // v. Repeat, while weeks ≠ 0, - while (weeks != 0) { - // 1. Let moveResult be ? MoveRelativeDate(calendar, relativeTo, oneWeek, dateAdd). - auto move_result = TRY(move_relative_date(vm, *calendar, verify_cast(relative_to.as_object()), *one_week, date_add)); - - // 2. Set relativeTo to moveResult.[[RelativeTo]]. - relative_to = move_result.relative_to.cell(); - - // 3. Set days to days + moveResult.[[Days]]. - days += move_result.days; - - // 4. Set weeks to weeks - sign. - weeks -= sign; - } - } - } - - // 12. Return ? CreateDateDurationRecord(years, months, weeks, days). - return create_date_duration_record(vm, years, months, weeks, days); -} - -// 7.5.20 BalanceDurationRelative ( years, months, weeks, days, largestUnit, relativeTo ), https://tc39.es/proposal-temporal/#sec-temporal-balancedurationrelative -ThrowCompletionOr balance_duration_relative(VM& vm, double years, double months, double weeks, double days, StringView largest_unit, Value relative_to_value) -{ - auto& realm = *vm.current_realm(); - - // 1. If largestUnit is not one of "year", "month", or "week", or years, months, weeks, and days are all 0, then - if (!largest_unit.is_one_of("year"sv, "month"sv, "week"sv) || (years == 0 && months == 0 && weeks == 0 && days == 0)) { - // a. Return ! CreateDateDurationRecord(years, months, weeks, days). - return create_date_duration_record(years, months, weeks, days); - } - - // 2. If relativeTo is undefined, then - if (relative_to_value.is_undefined()) { - // a. Throw a RangeError exception. - return vm.throw_completion(ErrorType::TemporalMissingStartingPoint, "calendar units"); - } - - // 3. Let sign be ! DurationSign(years, months, weeks, days, 0, 0, 0, 0, 0, 0). - auto sign = duration_sign(years, months, weeks, days, 0, 0, 0, 0, 0, 0); - - // 4. Assert: sign ≠ 0. - VERIFY(sign != 0); - - // 5. Let oneYear be ! CreateTemporalDuration(sign, 0, 0, 0, 0, 0, 0, 0, 0, 0). - auto one_year = MUST(create_temporal_duration(vm, sign, 0, 0, 0, 0, 0, 0, 0, 0, 0)); - - // 6. Let oneMonth be ! CreateTemporalDuration(0, sign, 0, 0, 0, 0, 0, 0, 0, 0). - auto one_month = MUST(create_temporal_duration(vm, 0, sign, 0, 0, 0, 0, 0, 0, 0, 0)); - - // 7. Let oneWeek be ! CreateTemporalDuration(0, 0, sign, 0, 0, 0, 0, 0, 0, 0). - auto one_week = MUST(create_temporal_duration(vm, 0, 0, sign, 0, 0, 0, 0, 0, 0, 0)); - - // 8. Set relativeTo to ? ToTemporalDate(relativeTo). - auto* relative_to = TRY(to_temporal_date(vm, relative_to_value)); - - // 9. Let calendar be relativeTo.[[Calendar]]. - auto& calendar = relative_to->calendar(); - - // 10. If largestUnit is "year", then - if (largest_unit == "year"sv) { - // a. Let dateAdd be ? GetMethod(calendar, "dateAdd"). - auto date_add = TRY(Value(&calendar).get_method(vm, vm.names.dateAdd)); - - // b. Let moveResult be ? MoveRelativeDate(calendar, relativeTo, oneYear, dateAdd). - auto move_result = TRY(move_relative_date(vm, calendar, *relative_to, *one_year, date_add)); - - // c. Let newRelativeTo be moveResult.[[RelativeTo]]. - auto* new_relative_to = move_result.relative_to.cell(); - - // d. Let oneYearDays be moveResult.[[Days]]. - auto one_year_days = move_result.days; - - // e. Repeat, while abs(days) ≥ abs(oneYearDays), - while (fabs(days) >= fabs(one_year_days)) { - // i. Set days to days - oneYearDays. - days -= one_year_days; - - // ii. Set years to years + sign. - years += sign; - - // iii. Set relativeTo to newRelativeTo. - relative_to = new_relative_to; - - // iv. Set moveResult to ? MoveRelativeDate(calendar, relativeTo, oneYear, dateAdd). - move_result = TRY(move_relative_date(vm, calendar, *relative_to, *one_year, date_add)); - - // v. Set newRelativeTo to moveResult.[[RelativeTo]]. - new_relative_to = move_result.relative_to.cell(); - - // vi. Set oneYearDays to moveResult.[[Days]]. - one_year_days = move_result.days; - } - - // f. Set moveResult to ? MoveRelativeDate(calendar, relativeTo, oneMonth, dateAdd). - move_result = TRY(move_relative_date(vm, calendar, *relative_to, *one_month, date_add)); - - // g. Set newRelativeTo to moveResult.[[RelativeTo]]. - new_relative_to = move_result.relative_to.cell(); - - // h. Let oneMonthDays be moveResult.[[Days]]. - auto one_month_days = move_result.days; - - // i. Repeat, while abs(days) ≥ abs(oneMonthDays), - while (fabs(days) >= fabs(one_month_days)) { - // i. Set days to days - oneMonthDays. - days -= one_month_days; - - // ii. Set months to months + sign. - months += sign; - - // iii. Set relativeTo to newRelativeTo. - relative_to = new_relative_to; - - // iv. Set moveResult to ? MoveRelativeDate(calendar, relativeTo, oneMonth, dateAdd). - move_result = TRY(move_relative_date(vm, calendar, *relative_to, *one_month, date_add)); - - // v. Set newRelativeTo to moveResult.[[RelativeTo]]. - new_relative_to = move_result.relative_to.cell(); - - // vi. Set oneMonthDays to moveResult.[[Days]]. - one_month_days = move_result.days; - } - - // j. Set newRelativeTo to ? CalendarDateAdd(calendar, relativeTo, oneYear, undefined, dateAdd). - new_relative_to = TRY(calendar_date_add(vm, calendar, relative_to, *one_year, nullptr, date_add)); - - // FIXME: This AO is out of date, this is no longer needed. - // k. Let dateUntil be ? GetMethod(calendar, "dateUntil"). - - // l. Let untilOptions be OrdinaryObjectCreate(null). - auto until_options = Object::create(realm, nullptr); - - // m. Perform ! CreateDataPropertyOrThrow(untilOptions, "largestUnit", "month"). - MUST(until_options->create_data_property_or_throw(vm.names.largestUnit, PrimitiveString::create(vm, "month"_string))); - - // FIXME: AD-HOC calendar records use as this AO is not up to date with latest spec - // n. Let untilResult be ? CalendarDateUntil(calendar, relativeTo, newRelativeTo, untilOptions, dateUntil). - auto calendar_record = TRY(create_calendar_methods_record(vm, GC::Ref { calendar }, { { CalendarMethod::DateAdd, CalendarMethod::DateUntil } })); - auto until_result = TRY(calendar_date_until(vm, calendar_record, relative_to, new_relative_to, *until_options)); - - // o. Let oneYearMonths be untilResult.[[Months]]. - auto one_year_months = until_result->months(); - - // p. Repeat, while abs(months) ≥ abs(oneYearMonths), - while (fabs(months) >= fabs(one_year_months)) { - // i. Set months to months - oneYearMonths. - months -= one_year_months; - - // ii. Set years to years + sign. - years += sign; - - // iii. Set relativeTo to newRelativeTo. - relative_to = new_relative_to; - - // iv. Set newRelativeTo to ? CalendarDateAdd(calendar, relativeTo, oneYear, undefined, dateAdd). - new_relative_to = TRY(calendar_date_add(vm, calendar, relative_to, *one_year, nullptr, date_add)); - - // v. Set untilOptions to OrdinaryObjectCreate(null). - until_options = Object::create(realm, nullptr); - - // vi. Perform ! CreateDataPropertyOrThrow(untilOptions, "largestUnit", "month"). - MUST(until_options->create_data_property_or_throw(vm.names.largestUnit, PrimitiveString::create(vm, "month"_string))); - - // vii. Set untilResult to ? CalendarDateUntil(calendar, relativeTo, newRelativeTo, untilOptions, dateUntil). - until_result = TRY(calendar_date_until(vm, calendar_record, relative_to, new_relative_to, *until_options)); - - // viii. Set oneYearMonths to untilResult.[[Months]]. - one_year_months = until_result->months(); - } - } - // 11. Else if largestUnit is "month", then - else if (largest_unit == "month"sv) { - // a. Let dateAdd be ? GetMethod(calendar, "dateAdd"). - auto date_add = TRY(Value(&calendar).get_method(vm, vm.names.dateAdd)); - - // b. Let moveResult be ? MoveRelativeDate(calendar, relativeTo, oneMonth, dateAdd). - auto move_result = TRY(move_relative_date(vm, calendar, *relative_to, *one_month, date_add)); - - // c. Let newRelativeTo be moveResult.[[RelativeTo]]. - auto* new_relative_to = move_result.relative_to.cell(); - - // d. Let oneMonthDays be moveResult.[[Days]]. - auto one_month_days = move_result.days; - - // e. Repeat, while abs(days) ≥ abs(oneMonthDays), - while (fabs(days) >= fabs(one_month_days)) { - // i. Set days to days - oneMonthDays. - days -= one_month_days; - - // ii. Set months to months + sign. - months += sign; - - // iii. Set relativeTo to newRelativeTo. - relative_to = new_relative_to; - - // iv. Set moveResult to ? MoveRelativeDate(calendar, relativeTo, oneMonth, dateAdd). - move_result = TRY(move_relative_date(vm, calendar, *relative_to, *one_month, date_add)); - - // v. Set newRelativeTo to moveResult.[[RelativeTo]]. - new_relative_to = move_result.relative_to.cell(); - - // vi. Set oneMonthDays to moveResult.[[Days]]. - one_month_days = move_result.days; - } - } - // 12. Else, - else { - // a. Assert: largestUnit is "week". - VERIFY(largest_unit == "week"sv); - - // b. Let dateAdd be ? GetMethod(calendar, "dateAdd"). - auto date_add = TRY(Value(&calendar).get_method(vm, vm.names.dateAdd)); - - // c. Let moveResult be ? MoveRelativeDate(calendar, relativeTo, oneWeek, dateAdd). - auto move_result = TRY(move_relative_date(vm, calendar, *relative_to, *one_week, date_add)); - - // d. Let newRelativeTo be moveResult.[[RelativeTo]]. - auto* new_relative_to = move_result.relative_to.cell(); - - // e. Let oneWeekDays be moveResult.[[Days]]. - auto one_week_days = move_result.days; - - // f. Repeat, while abs(days) ≥ abs(oneWeekDays), - while (fabs(days) >= fabs(one_week_days)) { - // i. Set days to days - oneWeekDays. - days -= one_week_days; - - // ii. Set weeks to weeks + sign. - weeks += sign; - - // iii. Set relativeTo to newRelativeTo. - relative_to = new_relative_to; - - // iv. Set moveResult to ? MoveRelativeDate(calendar, relativeTo, oneWeek, dateAdd). - move_result = TRY(move_relative_date(vm, calendar, *relative_to, *one_week, date_add)); - - // v. Set newRelativeTo to moveResult.[[RelativeTo]]. - new_relative_to = move_result.relative_to.cell(); - - // vi. Set oneWeekDays to moveResult.[[Days]]. - one_week_days = move_result.days; - } - } - - // 13. Return ! CreateDateDurationRecord(years, months, weeks, days). - return create_date_duration_record(years, months, weeks, days); -} - -// 7.5.21 AddDuration ( y1, mon1, w1, d1, h1, min1, s1, ms1, mus1, ns1, y2, mon2, w2, d2, h2, min2, s2, ms2, mus2, ns2, relativeTo ), https://tc39.es/proposal-temporal/#sec-temporal-addduration -ThrowCompletionOr add_duration(VM& vm, double years1, double months1, double weeks1, double days1, double hours1, double minutes1, double seconds1, double milliseconds1, double microseconds1, double nanoseconds1, double years2, double months2, double weeks2, double days2, double hours2, double minutes2, double seconds2, double milliseconds2, double microseconds2, double nanoseconds2, Value relative_to_value) -{ - auto& realm = *vm.current_realm(); - - VERIFY(all_of(AK::Array { years1, months1, weeks1, days1, hours1, minutes1, seconds1, milliseconds1, microseconds1, nanoseconds1, years2, months2, weeks2, days2, hours2, minutes2, seconds2, milliseconds2, microseconds2, nanoseconds2 }, [](auto value) { return value == trunc(value); })); - - // 1. Let largestUnit1 be ! DefaultTemporalLargestUnit(y1, mon1, w1, d1, h1, min1, s1, ms1, mus1). - auto largest_unit1 = default_temporal_largest_unit(years1, months1, weeks1, days1, hours1, minutes1, seconds1, milliseconds1, microseconds1); - - // 2. Let largestUnit2 be ! DefaultTemporalLargestUnit(y2, mon2, w2, d2, h2, min2, s2, ms2, mus2). - auto largest_unit2 = default_temporal_largest_unit(years2, months2, weeks2, days2, hours2, minutes2, seconds2, milliseconds2, microseconds2); - - // 3. Let largestUnit be ! LargerOfTwoTemporalUnits(largestUnit1, largestUnit2). - auto largest_unit = larger_of_two_temporal_units(largest_unit1, largest_unit2); - - // 4. If relativeTo is undefined, then - if (relative_to_value.is_undefined()) { - // a. If largestUnit is one of "year", "month", or "week", then - if (largest_unit.is_one_of("year"sv, "month"sv, "week"sv)) { - // i. Throw a RangeError exception. - return vm.throw_completion(ErrorType::TemporalMissingStartingPoint, "year, month or week"); - } - - // b. Let result be ? BalanceDuration(d1 + d2, h1 + h2, min1 + min2, s1 + s2, ms1 + ms2, mus1 + mus2, ns1 + ns2, largestUnit). - // NOTE: Nanoseconds is the only one that can overflow the safe integer range of a double - // so we have to check for that case. - Crypto::SignedBigInteger sum_of_nano_seconds; - if (fabs(nanoseconds1 + nanoseconds2) >= MAX_ARRAY_LIKE_INDEX) - sum_of_nano_seconds = Crypto::SignedBigInteger { nanoseconds1 }.plus(Crypto::SignedBigInteger { nanoseconds2 }); - else - sum_of_nano_seconds = Crypto::SignedBigInteger { nanoseconds1 + nanoseconds2 }; - - auto result = TRY(balance_duration(vm, days1 + days2, hours1 + hours2, minutes1 + minutes2, seconds1 + seconds2, milliseconds1 + milliseconds2, microseconds1 + microseconds2, sum_of_nano_seconds, largest_unit)); - - // c. Return ! CreateDurationRecord(0, 0, 0, result.[[Days]], result.[[Hours]], result.[[Minutes]], result.[[Seconds]], result.[[Milliseconds]], result.[[Microseconds]], result.[[Nanoseconds]]). - return MUST(create_duration_record(vm, 0, 0, 0, result.days, result.hours, result.minutes, result.seconds, result.milliseconds, result.microseconds, result.nanoseconds)); - } - - // 5. If relativeTo has an [[InitializedTemporalDate]] internal slot, then - if (is(relative_to_value.as_object())) { - auto& relative_to = static_cast(relative_to_value.as_object()); - - // a. Let calendar be relativeTo.[[Calendar]]. - auto& calendar = relative_to.calendar(); - - // b. Let dateDuration1 be ! CreateTemporalDuration(y1, mon1, w1, d1, 0, 0, 0, 0, 0, 0). - auto date_duration1 = MUST(create_temporal_duration(vm, years1, months1, weeks1, days1, 0, 0, 0, 0, 0, 0)); - - // c. Let dateDuration2 be ! CreateTemporalDuration(y2, mon2, w2, d2, 0, 0, 0, 0, 0, 0). - auto date_duration2 = MUST(create_temporal_duration(vm, years2, months2, weeks2, days2, 0, 0, 0, 0, 0, 0)); - - // d. Let dateAdd be ? GetMethod(calendar, "dateAdd"). - auto date_add = TRY(Value(&calendar).get_method(vm, vm.names.dateAdd)); - - // e. Let intermediate be ? CalendarDateAdd(calendar, relativeTo, dateDuration1, undefined, dateAdd). - auto* intermediate = TRY(calendar_date_add(vm, calendar, &relative_to, *date_duration1, nullptr, date_add)); - - // f. Let end be ? CalendarDateAdd(calendar, intermediate, dateDuration2, undefined, dateAdd). - auto* end = TRY(calendar_date_add(vm, calendar, intermediate, *date_duration2, nullptr, date_add)); - - // g. Let dateLargestUnit be ! LargerOfTwoTemporalUnits("day", largestUnit). - auto date_largest_unit = larger_of_two_temporal_units("day"sv, largest_unit); - - // h. Let differenceOptions be OrdinaryObjectCreate(null). - auto difference_options = Object::create(realm, nullptr); - - // i. Perform ! CreateDataPropertyOrThrow(differenceOptions, "largestUnit", dateLargestUnit). - MUST(difference_options->create_data_property_or_throw(vm.names.largestUnit, PrimitiveString::create(vm, date_largest_unit))); - - // j. Let dateDifference be ? CalendarDateUntil(calendar, relativeTo, end, differenceOptions). - // FIXME: AD-HOC calendar records use as this AO is not up to date with latest spec - auto calendar_record = TRY(create_calendar_methods_record(vm, GC::Ref { calendar }, { { CalendarMethod::DateAdd, CalendarMethod::DateUntil } })); - auto date_difference = TRY(calendar_date_until(vm, calendar_record, &relative_to, end, *difference_options)); - - // k. Let result be ? BalanceDuration(dateDifference.[[Days]], h1 + h2, min1 + min2, s1 + s2, ms1 + ms2, mus1 + mus2, ns1 + ns2, largestUnit). - // NOTE: Nanoseconds is the only one that can overflow the safe integer range of a double - // so we have to check for that case. - Crypto::SignedBigInteger sum_of_nano_seconds; - if (fabs(nanoseconds1 + nanoseconds2) >= MAX_ARRAY_LIKE_INDEX) - sum_of_nano_seconds = Crypto::SignedBigInteger { nanoseconds1 }.plus(Crypto::SignedBigInteger { nanoseconds2 }); - else - sum_of_nano_seconds = Crypto::SignedBigInteger { nanoseconds1 + nanoseconds2 }; - - auto result = TRY(balance_duration(vm, date_difference->days(), hours1 + hours2, minutes1 + minutes2, seconds1 + seconds2, milliseconds1 + milliseconds2, microseconds1 + microseconds2, sum_of_nano_seconds, largest_unit)); - - // l. Return ? CreateDurationRecord(dateDifference.[[Years]], dateDifference.[[Months]], dateDifference.[[Weeks]], result.[[Days]], result.[[Hours]], result.[[Minutes]], result.[[Seconds]], result.[[Milliseconds]], result.[[Microseconds]], result.[[Nanoseconds]]). - return MUST(create_duration_record(vm, date_difference->years(), date_difference->months(), date_difference->weeks(), result.days, result.hours, result.minutes, result.seconds, result.milliseconds, result.microseconds, result.nanoseconds)); - } - - // 6. Assert: relativeTo has an [[InitializedTemporalZonedDateTime]] internal slot. - auto& relative_to = verify_cast(relative_to_value.as_object()); - - // 7. Let timeZone be relativeTo.[[TimeZone]]. - auto& time_zone = relative_to.time_zone(); - - // 8. Let calendar be relativeTo.[[Calendar]]. - auto& calendar = relative_to.calendar(); - - // 9. Let intermediateNs be ? AddZonedDateTime(relativeTo.[[Nanoseconds]], timeZone, calendar, y1, mon1, w1, d1, h1, min1, s1, ms1, mus1, ns1). - auto* intermediate_ns = TRY(add_zoned_date_time(vm, relative_to.nanoseconds(), &time_zone, calendar, years1, months1, weeks1, days1, hours1, minutes1, seconds1, milliseconds1, microseconds1, nanoseconds1)); - - // 10. Let endNs be ? AddZonedDateTime(intermediateNs, timeZone, calendar, y2, mon2, w2, d2, h2, min2, s2, ms2, mus2, ns2). - auto* end_ns = TRY(add_zoned_date_time(vm, *intermediate_ns, &time_zone, calendar, years2, months2, weeks2, days2, hours2, minutes2, seconds2, milliseconds2, microseconds2, nanoseconds2)); - - // 11. If largestUnit is not one of "year", "month", "week", or "day", then - if (!largest_unit.is_one_of("year"sv, "month"sv, "week"sv, "day"sv)) { - // a. Let result be DifferenceInstant(zonedRelativeTo.[[Nanoseconds]], endNs, 1, "nanosecond", largestUnit, "halfExpand"). - auto result = difference_instant(vm, relative_to.nanoseconds(), *end_ns, 1, "nanosecond"sv, largest_unit, "halfExpand"sv); - - // b. Return ! CreateDurationRecord(0, 0, 0, 0, result.[[Hours]], result.[[Minutes]], result.[[Seconds]], result.[[Milliseconds]], result.[[Microseconds]], result.[[Nanoseconds]]). - return create_duration_record(0, 0, 0, 0, result.hours, result.minutes, result.seconds, result.milliseconds, result.microseconds, result.nanoseconds); - } - - // 12. Return ? DifferenceZonedDateTime(relativeTo.[[Nanoseconds]], endNs, timeZone, calendar, largestUnit, OrdinaryObjectCreate(null)). - return difference_zoned_date_time(vm, relative_to.nanoseconds(), *end_ns, time_zone, calendar, largest_unit, *Object::create(realm, nullptr)); -} - -// 7.5.23 MoveRelativeDate ( calendar, relativeTo, duration, dateAdd ), https://tc39.es/proposal-temporal/#sec-temporal-moverelativedate -ThrowCompletionOr move_relative_date(VM& vm, Object& calendar, PlainDate& relative_to, Duration& duration, FunctionObject* date_add) -{ - // 1. Let newDate be ? CalendarDateAdd(calendar, relativeTo, duration, undefined, dateAdd) - auto* new_date = TRY(calendar_date_add(vm, calendar, &relative_to, duration, nullptr, date_add)); - - // 2. Let days be DaysUntil(relativeTo, newDate). - auto days = days_until(relative_to, *new_date); - - // 3. Return the Record { [[RelativeTo]]: newDate, [[Days]]: days }. - return MoveRelativeDateResult { .relative_to = make_root(new_date), .days = days }; -} - -// 7.5.24 MoveRelativeZonedDateTime ( zonedDateTime, years, months, weeks, days ), https://tc39.es/proposal-temporal/#sec-temporal-moverelativezoneddatetime -ThrowCompletionOr move_relative_zoned_date_time(VM& vm, ZonedDateTime& zoned_date_time, double years, double months, double weeks, double days) -{ - // 1. Let intermediateNs be ? AddZonedDateTime(zonedDateTime.[[Nanoseconds]], zonedDateTime.[[TimeZone]], zonedDateTime.[[Calendar]], years, months, weeks, days, 0, 0, 0, 0, 0, 0). - auto* intermediate_ns = TRY(add_zoned_date_time(vm, zoned_date_time.nanoseconds(), &zoned_date_time.time_zone(), zoned_date_time.calendar(), years, months, weeks, days, 0, 0, 0, 0, 0, 0)); - - // 2. Return ! CreateTemporalZonedDateTime(intermediateNs, zonedDateTime.[[TimeZone]], zonedDateTime.[[Calendar]]). - return MUST(create_temporal_zoned_date_time(vm, *intermediate_ns, zoned_date_time.time_zone(), zoned_date_time.calendar())); -} - -// 7.5.27 RoundDuration ( years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, increment, unit, roundingMode [ , plainRelativeTo [ , calendarRec [ , zonedRelativeTo [ , timeZoneRec [ , precalculatedPlainDateTime ] ] ] ] ] ), https://tc39.es/proposal-temporal/#sec-temporal-roundduration -// FIXME: Support calendarRec, zonedRelativeTo, timeZoneRec, precalculatedPlainDateTime -ThrowCompletionOr round_duration(VM& vm, double years, double months, double weeks, double days, double hours, double minutes, double seconds, double milliseconds, double microseconds, double nanoseconds, u32 increment, StringView unit, StringView rounding_mode, Object* plain_relative_to_object, Optional const& calendar_record) -{ - auto& realm = *vm.current_realm(); - - Object* calendar = nullptr; // FIXME: Should come from calendarRec - - double fractional_seconds = 0; - double fractional_days = 0; - - // FIXME: 1. Assert: If either of plainRelativeTo or zonedRelativeTo are present and not undefined, calendarRec is not undefined. - if (plain_relative_to_object) - VERIFY(calendar_record.has_value()); - - // FIXME: 2. Assert: If zonedRelativeTo is present and not undefined, timeZoneRec is not undefined. - - // 3. If plainRelativeTo is not present, set plainRelativeTo to undefined. - // NOTE: `plain_relative_to_object` and `plain_relative_to` in the various code paths below are all the same as far as the - // spec is concerned, but the latter is more strictly typed for convenience. - PlainDate* plain_relative_to = nullptr; - - // FIXME: 4. If zonedRelativeTo is not present, set zonedRelativeTo to undefined. - ZonedDateTime* zoned_relative_to = nullptr; - - // FIXME: 5. If precalculatedPlainDateTime is not present, set precalculatedPlainDateTime to undefined. - - // FIXME: assuming "smallestUnit" as the option name here leads to confusing error messages in some cases: - // > new Temporal.Duration().total({ unit: "month" }) - // Uncaught exception: [RangeError] month is not a valid value for option smallestUnit - // 6. If unit is "year", "month", or "week", then - if (unit.is_one_of("year"sv, "month"sv, "week"sv)) { - // a. If plainRelativeTo is undefined, throw a RangeError exception. - if (!plain_relative_to_object) - return vm.throw_completion(ErrorType::OptionIsNotValidValue, unit, "smallestUnit"sv); - - // b. Assert: CalendarMethodsRecordHasLookedUp(calendarRec, dateAdd) is true. - VERIFY(calendar_methods_record_has_looked_up(calendar_record.value(), CalendarMethod::DateAdd)); - - // c. Assert: CalendarMethodsRecordHasLookedUp(calendarRec, dateUntil) is true. - VERIFY(calendar_methods_record_has_looked_up(calendar_record.value(), CalendarMethod::DateAdd)); - } - - // FIXME: AD-HOC, should be coming from arguments given to this function. - if (plain_relative_to_object) { - if (is(plain_relative_to_object)) { - auto* relative_to_zoned_date_time = static_cast(plain_relative_to_object); - zoned_relative_to = relative_to_zoned_date_time; - plain_relative_to = TRY(to_temporal_date(vm, plain_relative_to_object)); - } else { - VERIFY(is(plain_relative_to_object)); - plain_relative_to = verify_cast(plain_relative_to_object); - } - calendar = &plain_relative_to->calendar(); - } - - // 7. If unit is one of "year", "month", "week", or "day", then - if (unit.is_one_of("year"sv, "month"sv, "week"sv, "day"sv)) { - - // a. Let nanoseconds be TotalDurationNanoseconds(hours, minutes, seconds, milliseconds, microseconds, nanoseconds). - // FIXME: We shouldn't be passing through 0 days and 0 offset digit - auto nanoseconds_bigint = total_duration_nanoseconds(0, hours, minutes, seconds, milliseconds, microseconds, Crypto::SignedBigInteger { nanoseconds }, 0); - - // b. If zonedRelativeTo is not undefined, then - if (zoned_relative_to) { - // i. Let intermediate be ? MoveRelativeZonedDateTime(zonedRelativeTo, calendarRec, timeZoneRec, years, months, weeks, days, precalculatedPlainDateTime). - // FIXME: Pass through calendarRecord, timeZoneRec and precalculatedPlainDateTime - auto* intermediate = TRY(move_relative_zoned_date_time(vm, *zoned_relative_to, years, months, weeks, days)); - - // ii. Let result be ? NanosecondsToDays(nanoseconds, intermediate, timeZoneRec). - // FIXME: Pass through timeZoneRec - auto result = TRY(nanoseconds_to_days(vm, nanoseconds_bigint, intermediate)); - - // iii. Let fractionalDays be days + result.[[Days]] + result.[[Nanoseconds]] / result.[[DayLength]]. - auto nanoseconds_division_result = result.nanoseconds.divided_by(Crypto::UnsignedBigInteger { result.day_length }); - fractional_days = days + result.days + nanoseconds_division_result.quotient.to_double() + nanoseconds_division_result.remainder.to_double() / result.day_length; - } - // c. Else, - else { - // i. Let fractionalDays be days + nanoseconds / nsPerDay. - auto nanoseconds_division_result = nanoseconds_bigint.divided_by(ns_per_day_bigint); - fractional_days = days + nanoseconds_division_result.quotient.to_double() + (nanoseconds_division_result.remainder.to_double() / ns_per_day); - } - - // d. Set days, hours, minutes, seconds, milliseconds, microseconds, and nanoseconds to 0. - days = 0; - hours = 0; - minutes = 0; - seconds = 0; - milliseconds = 0; - microseconds = 0; - nanoseconds = 0; - - // e. Assert: fractionalSeconds is not used below. - } - // 8. Else, - else { - // a. Let fractionalSeconds be nanoseconds × 10^-9 + microseconds × 10^-6 + milliseconds × 10^-3 + seconds. - fractional_seconds = nanoseconds * 0.000000001 + microseconds * 0.000001 + milliseconds * 0.001 + seconds; - - // b. Assert: fractionalDays is not used below. - } - - // 9. Let total be unset. - double total = 0; - - // 10. If unit is "year", then - if (unit == "year"sv) { - VERIFY(plain_relative_to); - - // a. Let yearsDuration be ! CreateTemporalDuration(years, 0, 0, 0, 0, 0, 0, 0, 0, 0). - auto years_duration = MUST(create_temporal_duration(vm, years, 0, 0, 0, 0, 0, 0, 0, 0, 0)); - - // FIXME: b. Let yearsLater be ? AddDate(calendarRec, plainRelativeTo, yearsDuration). - auto date_add = TRY(Value(calendar).get_method(vm, vm.names.dateAdd)); - auto* years_later = TRY(calendar_date_add(vm, *calendar, plain_relative_to, *years_duration, nullptr, date_add)); - - // c. Let yearsMonthsWeeks be ! CreateTemporalDuration(years, months, weeks, 0, 0, 0, 0, 0, 0, 0). - auto years_months_weeks = MUST(create_temporal_duration(vm, years, months, weeks, 0, 0, 0, 0, 0, 0, 0)); - - // FIXME: d. Let yearsMonthsWeeksLater be ? AddDate(calendarRec, plainRelativeTo, yearsMonthsWeeks). - auto* years_months_weeks_later = TRY(calendar_date_add(vm, *calendar, plain_relative_to, *years_months_weeks, nullptr, date_add)); - - // e. Let monthsWeeksInDays be DaysUntil(yearsLater, yearsMonthsWeeksLater). - auto months_weeks_in_days = days_until(*years_later, *years_months_weeks_later); - - // f. Set plainRelativeTo to yearsLater. - plain_relative_to = years_later; - - // g. Set fractionalDays to fractionalDays + monthsWeeksInDays. - fractional_days = fractional_days + months_weeks_in_days; - - // h. Let isoResult be ! AddISODate(plainRelativeTo.[[ISOYear]]. plainRelativeTo.[[ISOMonth]], plainRelativeTo.[[ISODay]], 0, 0, 0, truncate(fractionalDays), "constrain"). - auto iso_result = MUST(add_iso_date(vm, plain_relative_to->iso_year(), plain_relative_to->iso_month(), plain_relative_to->iso_day(), 0, 0, 0, trunc(fractional_days), "constrain"sv)); - - // i. Let wholeDaysLater be ? CreateTemporalDate(isoResult.[[Year]], isoResult.[[Month]], isoResult.[[Day]], calendarRec.[[Receiver]]). - // FIXME: Pass through receiver from calendarRec - auto* whole_days_later = TRY(create_temporal_date(vm, iso_result.year, iso_result.month, iso_result.day, *calendar)); - - // j. Let untilOptions be OrdinaryObjectCreate(null). - auto until_options = Object::create(realm, nullptr); - - // k. Perform ! CreateDataPropertyOrThrow(untilOptions, "largestUnit", "year"). - MUST(until_options->create_data_property_or_throw(vm.names.largestUnit, PrimitiveString::create(vm, "year"_string))); - - // l. Let timePassed be ? DifferenceDate(calendarRec, plainRelativeTo, wholeDaysLater, untilOptions). - auto time_passed = TRY(difference_date(vm, calendar_record.value(), *plain_relative_to, *whole_days_later, *until_options)); - - // m. Let yearsPassed be timePassed.[[Years]]. - auto years_passed = time_passed->years(); - - // n. Set years to years + yearsPassed. - years += years_passed; - - // o. Let yearsDuration be ! CreateTemporalDuration(yearsPassed, 0, 0, 0, 0, 0, 0, 0, 0, 0). - years_duration = MUST(create_temporal_duration(vm, years_passed, 0, 0, 0, 0, 0, 0, 0, 0, 0)); - - // p. Let moveResult be ? MoveRelativeDate(calendarRec, plainRelativeTo, yearsDuration). - // FIXME: Pass through calendarRec instead of date_add - auto move_result = TRY(move_relative_date(vm, *calendar, *plain_relative_to, *years_duration, date_add)); - - // q. Set plainRelativeTo to moveResult.[[RelativeTo]]. - auto plain_relative_to = move_result.relative_to; - - // r. Let daysPassed be moveResult.[[Days]]. - auto days_passed = move_result.days; - - // s. Set fractionalDays to fractionalDays - daysPassed. - fractional_days -= days_passed; - - // t. If fractionalDays < 0, let sign be -1; else, let sign be 1. - auto sign = fractional_days < 0 ? -1 : 1; - - // u. Let oneYear be ! CreateTemporalDuration(sign, 0, 0, 0, 0, 0, 0, 0, 0, 0). - auto one_year = MUST(create_temporal_duration(vm, sign, 0, 0, 0, 0, 0, 0, 0, 0, 0)); - - // v. Set moveResult to ? MoveRelativeDate(calendarRec, plainRelativeTo, oneYear). - // FIXME:: pass through calendarRec - move_result = TRY(move_relative_date(vm, *calendar, *plain_relative_to, *one_year, date_add)); - - // w. Let oneYearDays be moveResult.[[Days]]. - auto one_year_days = move_result.days; - - // x. If oneYearDays = 0, throw a RangeError exception. - if (one_year_days == 0) - return vm.throw_completion(ErrorType::TemporalInvalidCalendarFunctionResult, "dateAdd", "result implying a year is zero days long"); - - // y. Let fractionalYears be years + fractionalDays / abs(oneYearDays). - auto fractional_years = years + fractional_days / fabs(one_year_days); - - // z. Set years to RoundNumberToIncrement(fractionalYears, increment, roundingMode). - years = round_number_to_increment(fractional_years, increment, rounding_mode); - - // aa. Set total to fractionalYears. - total = fractional_years; - - // ab. Set months and weeks to 0. - months = 0; - weeks = 0; - } - // 10. Else if unit is "month", then - else if (unit == "month"sv) { - VERIFY(plain_relative_to); - - // a. Let yearsMonths be ! CreateTemporalDuration(years, months, 0, 0, 0, 0, 0, 0, 0, 0). - auto years_months = MUST(create_temporal_duration(vm, years, months, 0, 0, 0, 0, 0, 0, 0, 0)); - - // FIXME: b. Let yearsMonthsLater be ? AddDate(calendarRec, plainRelativeTo, yearsMonths). - auto date_add = TRY(Value(calendar).get_method(vm, vm.names.dateAdd)); - auto* years_months_later = TRY(calendar_date_add(vm, *calendar, plain_relative_to, *years_months, nullptr, date_add)); - - // c. Let yearsMonthsWeeks be ! CreateTemporalDuration(years, months, weeks, 0, 0, 0, 0, 0, 0, 0). - auto years_months_weeks = MUST(create_temporal_duration(vm, years, months, weeks, 0, 0, 0, 0, 0, 0, 0)); - - // FIXME: d. Let yearsMonthsWeeksLater be ? AddDate(calendarRec, plainRelativeTo, yearsMonthsWeeks). - auto* years_months_weeks_later = TRY(calendar_date_add(vm, *calendar, plain_relative_to, *years_months_weeks, nullptr, date_add)); - - // e. Let weeksInDays be DaysUntil(yearsMonthsLater, yearsMonthsWeeksLater). - auto weeks_in_days = days_until(*years_months_later, *years_months_weeks_later); - - // f. Set plainRelativeTo to yearsMonthsLater. - plain_relative_to = years_months_later; - - // g. Set fractionalDays to fractionalDays + weeksInDays. - fractional_days += weeks_in_days; - - // h. Let isoResult be ! AddISODate(plainRelativeTo.[[ISOYear]], plainRelativeTo.[[ISOMonth]], plainRelativeTo.[[ISODay]], 0, 0, 0, truncate(fractionalDays), "constrain"). - auto iso_result = MUST(add_iso_date(vm, plain_relative_to->iso_year(), plain_relative_to->iso_month(), plain_relative_to->iso_day(), 0, 0, 0, trunc(fractional_days), "constrain"sv)); - - // i. Let wholeDaysLater be ? CreateTemporalDate(isoResult.[[Year]], isoResult.[[Month]], isoResult.[[Day]], calendarRec.[[Receiver]]). - // FIXME: Pass through calendarRec - auto* whole_days_later = TRY(create_temporal_date(vm, iso_result.year, iso_result.month, iso_result.day, *calendar)); // FIXME: receiver - - // j. Let untilOptions be OrdinaryObjectCreate(null). - auto until_options = Object::create(realm, nullptr); - - // k. Perform ! CreateDataPropertyOrThrow(untilOptions, "largestUnit", "month"). - MUST(until_options->create_data_property_or_throw(vm.names.largestUnit, PrimitiveString::create(vm, "month"_string))); - - // l. Let timePassed be ? DifferenceDate(calendarRec, plainRelativeTo, wholeDaysLater, untilOptions). - auto time_passed = TRY(difference_date(vm, calendar_record.value(), *plain_relative_to, *whole_days_later, *until_options)); - - // m. Let monthsPassed be timePassed.[[Months]]. - auto months_passed = time_passed->months(); - - // n. Set months to months + monthsPassed. - months += months_passed; - - // o. Let monthsPassedDuration be ! CreateTemporalDuration(0, monthsPassed, 0, 0, 0, 0, 0, 0, 0, 0). - auto months_passed_duration = MUST(create_temporal_duration(vm, 0, months_passed, 0, 0, 0, 0, 0, 0, 0, 0)); - - // p. Let moveResult be ? MoveRelativeDate(calendarRec, plainRelativeTo, monthsPassedDuration). - // FIXME: Pass through calendarRec - auto move_result = TRY(move_relative_date(vm, *calendar, *plain_relative_to, *months_passed_duration, date_add)); - - // q. Set plainRelativeTo to moveResult.[[RelativeTo]]. - plain_relative_to = move_result.relative_to; - - // r. Let daysPassed be moveResult.[[Days]]. - auto days_passed = move_result.days; - - // s. Set fractionalDays to fractionalDays - daysPassed. - fractional_days -= days_passed; - - // t. If fractionalDays < 0, let sign be -1; else, let sign be 1. - auto sign = fractional_days < 0 ? -1 : 1; - - // u. Let oneMonth be ! CreateTemporalDuration(0, sign, 0, 0, 0, 0, 0, 0, 0, 0). - auto one_month = MUST(create_temporal_duration(vm, 0, sign, 0, 0, 0, 0, 0, 0, 0, 0)); - - // v. Let moveResult be ? MoveRelativeDate(calendarRec, plainRelativeTo, oneMonth). - // FIXME: spec bug, this should be set. - move_result = TRY(move_relative_date(vm, *calendar, *plain_relative_to, *one_month, date_add)); - - // w. Let oneMonthDays be moveResult.[[Days]]. - auto one_month_days = move_result.days; - - // x. If oneMonthDays = 0, throw a RangeError exception. - if (one_month_days == 0) - return vm.throw_completion(ErrorType::TemporalInvalidCalendarFunctionResult, "dateAdd", "result implying a month is zero days long"); - - // y. Let fractionalMonths be months + fractionalDays / abs(oneMonthDays). - auto fractional_months = months + fractional_days / fabs(one_month_days); - - // z. Set months to RoundNumberToIncrement(fractionalMonths, increment, roundingMode). - months = round_number_to_increment(fractional_months, increment, rounding_mode); - - // aa. Set total to fractionalMonths. - total = fractional_months; - - // ab. Set weeks to 0. - weeks = 0; - } - // 11. Else if unit is "week", then - else if (unit == "week"sv) { - VERIFY(plain_relative_to); - - // a. Let isoResult be ! AddISODate(plainRelativeTo.[[ISOYear]], plainRelativeTo.[[ISOMonth]], plainRelativeTo.[[ISODay]], 0, 0, 0, truncate(fractionalDays), "constrain"). - auto iso_result = MUST(add_iso_date(vm, plain_relative_to->iso_year(), plain_relative_to->iso_month(), plain_relative_to->iso_day(), 0, 0, 0, trunc(fractional_days), "constrain"sv)); - - // b. Let wholeDaysLater be ? CreateTemporalDate(isoResult.[[Year]], isoResult.[[Month]], isoResult.[[Day]], calendarRec.[[Receiver]]). - // FIXME: Pass through receiver from calendarRec - auto* whole_days_later = TRY(create_temporal_date(vm, iso_result.year, iso_result.month, iso_result.day, *calendar)); - - // c. Let untilOptions be OrdinaryObjectCreate(null). - auto until_options = Object::create(realm, nullptr); - - // d. Perform ! CreateDataPropertyOrThrow(untilOptions, "largestUnit", "week"). - MUST(until_options->create_data_property_or_throw(vm.names.largestUnit, PrimitiveString::create(vm, "month"_string))); - - // e. Let timePassed be ? DifferenceDate(calendarRec, plainRelativeTo, wholeDaysLater, untilOptions). - auto time_passed = TRY(difference_date(vm, calendar_record.value(), *plain_relative_to, *whole_days_later, *until_options)); - - // f. Let weeksPassed be timePassed.[[Weeks]]. - auto weeks_passed = time_passed->weeks(); - - // g. Set weeks to weeks + weeksPassed. - weeks += weeks_passed; - - // h. Let weeksPassedDuration be ! CreateTemporalDuration(0, 0, weeksPassed, 0, 0, 0, 0, 0, 0, 0). - auto weeks_passed_duration = MUST(create_temporal_duration(vm, 0, 0, weeks_passed, 0, 0, 0, 0, 0, 0, 0)); - - // FIXME: i. Let moveResult be ? MoveRelativeDate(calendarRec, plainRelativeTo, weeksPassedDuration). - auto date_add = TRY(Value(calendar).get_method(vm, vm.names.dateAdd)); - auto move_result = TRY(move_relative_date(vm, *calendar, *plain_relative_to, *weeks_passed_duration, date_add)); - - // j. Set plainRelativeTo to moveResult.[[RelativeTo]]. - plain_relative_to = move_result.relative_to; - - // k. Let daysPassed be moveResult.[[Days]]. - auto days_passed = move_result.days; - - // l. Set fractionalDays to fractionalDays - daysPassed. - fractional_days -= days_passed; - - // m. If fractionalDays < 0, let sign be -1; else, let sign be 1. - auto sign = fractional_days < 0 ? -1 : 1; - - // n. Let oneWeek be ! CreateTemporalDuration(0, 0, sign, 0, 0, 0, 0, 0, 0, 0). - auto one_week = MUST(create_temporal_duration(vm, 0, 0, sign, 0, 0, 0, 0, 0, 0, 0)); - - // o. Let moveResult be ? MoveRelativeDate(calendarRec, plainRelativeTo, oneWeek). - // FIXME: spec bug, should be set - move_result = TRY(move_relative_date(vm, *calendar, *plain_relative_to, *one_week, date_add)); - - // p. Let oneWeekDays be moveResult.[[Days]]. - auto one_week_days = move_result.days; - - // q. If oneWeekDays = 0, throw a RangeError exception. - if (one_week_days == 0) - return vm.throw_completion(ErrorType::TemporalInvalidCalendarFunctionResult, "dateAdd", "result implying a month is zero days long"); - - // r. Let fractionalWeeks be weeks + fractionalDays / abs(oneWeekDays). - auto fractional_weeks = weeks + fractional_days / fabs(one_week_days); - - // s. Set weeks to RoundNumberToIncrement(fractionalWeeks, increment, roundingMode). - weeks = round_number_to_increment(fractional_weeks, increment, rounding_mode); - - // t. Set total to fractionalWeeks. - total = fractional_weeks; - } - // 12. Else if unit is "day", then - else if (unit == "day"sv) { - // a. Set days to RoundNumberToIncrement(fractionalDays, increment, roundingMode). - days = round_number_to_increment(fractional_days, increment, rounding_mode); - - // b. Set total to fractionalDays. - total = fractional_days; - } - // 13. Else if unit is "hour", then - else if (unit == "hour"sv) { - // a. Let fractionalHours be (fractionalSeconds / 60 + minutes) / 60 + hours. - auto fractional_hours = (fractional_seconds / 60 + minutes) / 60 + hours; - - // b. Set hours to RoundNumberToIncrement(fractionalHours, increment, roundingMode). - hours = round_number_to_increment(fractional_hours, increment, rounding_mode); - - // c. Set total to fractionalHours. - total = fractional_hours; - - // d. Set minutes, seconds, milliseconds, microseconds, and nanoseconds to 0. - minutes = 0; - seconds = 0; - milliseconds = 0; - microseconds = 0; - nanoseconds = 0; - } - // 14. Else if unit is "minute", then - else if (unit == "minute"sv) { - // a. Let fractionalMinutes be fractionalSeconds / 60 + minutes. - auto fractional_minutes = fractional_seconds / 60 + minutes; - - // b. Set minutes to RoundNumberToIncrement(fractionalMinutes, increment, roundingMode). - minutes = round_number_to_increment(fractional_minutes, increment, rounding_mode); - - // c. Set total to fractionalMinutes. - total = fractional_minutes; - - // d. Set seconds, milliseconds, microseconds, and nanoseconds to 0. - seconds = 0; - milliseconds = 0; - microseconds = 0; - nanoseconds = 0; - } - // 15. Else if unit is "second", then - else if (unit == "second"sv) { - // a. Set seconds to RoundNumberToIncrement(fractionalSeconds, increment, roundingMode). - seconds = round_number_to_increment(fractional_seconds, increment, rounding_mode); - - // b. Set total to fractionalSeconds. - total = fractional_seconds; - - // c. Set milliseconds, microseconds, and nanoseconds to 0. - milliseconds = 0; - microseconds = 0; - nanoseconds = 0; - } - // 16. Else if unit is "millisecond", then - else if (unit == "millisecond"sv) { - // a. Let fractionalMilliseconds be nanoseconds × 10^-6 + microseconds × 10^-3 + milliseconds. - auto fractional_milliseconds = nanoseconds * 0.000001 + microseconds * 0.001 + milliseconds; - - // b. Set milliseconds to RoundNumberToIncrement(fractionalMilliseconds, increment, roundingMode). - milliseconds = round_number_to_increment(fractional_milliseconds, increment, rounding_mode); - - // c. Set total to fractionalMilliseconds. - total = fractional_milliseconds; - - // d. Set microseconds and nanoseconds to 0. - microseconds = 0; - nanoseconds = 0; - } - // 17. Else if unit is "microsecond", then - else if (unit == "microsecond"sv) { - // a. Let fractionalMicroseconds be nanoseconds × 10^-3 + microseconds. - auto fractional_microseconds = nanoseconds * 0.001 + microseconds; - - // b. Set microseconds to RoundNumberToIncrement(fractionalMicroseconds, increment, roundingMode). - microseconds = round_number_to_increment(fractional_microseconds, increment, rounding_mode); - - // c. Set total to fractionalMicroseconds. - total = fractional_microseconds; - - // d. Set nanoseconds to 0. - nanoseconds = 0; - } - // 18. Else, - else { - // a. Assert: unit is "nanosecond". - VERIFY(unit == "nanosecond"sv); - - // b. Set total to nanoseconds. - total = nanoseconds; - - // c. Set nanoseconds to RoundNumberToIncrement(nanoseconds, increment, roundingMode). - nanoseconds = round_number_to_increment(nanoseconds, increment, rounding_mode); - } - - // 20. Let duration be ? CreateDurationRecord(years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds). - auto duration = TRY(create_duration_record(vm, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds)); - - // 21. Return the Record { [[DurationRecord]]: duration, [[Total]]: total }. - return RoundedDuration { .duration_record = duration, .total = total }; -} - -// 7.5.26 AdjustRoundedDurationDays ( years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, increment, unit, roundingMode, relativeTo ), https://tc39.es/proposal-temporal/#sec-temporal-adjustroundeddurationdays -ThrowCompletionOr adjust_rounded_duration_days(VM& vm, double years, double months, double weeks, double days, double hours, double minutes, double seconds, double milliseconds, double microseconds, double nanoseconds, u32 increment, StringView unit, StringView rounding_mode, Object* relative_to_object) -{ - // 1. If Type(relativeTo) is not Object; or relativeTo does not have an [[InitializedTemporalZonedDateTime]] internal slot; or unit is one of "year", "month", "week", or "day"; or unit is "nanosecond" and increment is 1, then - if (relative_to_object == nullptr || !is(relative_to_object) || unit.is_one_of("year"sv, "month"sv, "week"sv, "day"sv) || (unit == "nanosecond"sv && increment == 1)) { - // a. Return ! CreateDurationRecord(years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds). - return create_duration_record(years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds); - } - - auto& relative_to = static_cast(*relative_to_object); - - // 2. Let timeRemainderNs be ! TotalDurationNanoseconds(0, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, 0). - auto time_remainder_ns = total_duration_nanoseconds(0, hours, minutes, seconds, milliseconds, microseconds, Crypto::SignedBigInteger { nanoseconds }, 0); - - i32 direction; - - // 3. If timeRemainderNs = 0, let direction be 0. - if (time_remainder_ns.is_zero()) - direction = 0; - // 4. Else if timeRemainderNs < 0, let direction be -1. - else if (time_remainder_ns.is_negative()) - direction = -1; - // 5. Else, let direction be 1. - else - direction = 1; - - // 6. Let dayStart be ? AddZonedDateTime(relativeTo.[[Nanoseconds]], relativeTo.[[TimeZone]], relativeTo.[[Calendar]], years, months, weeks, days, 0, 0, 0, 0, 0, 0). - auto* day_start = TRY(add_zoned_date_time(vm, relative_to.nanoseconds(), &relative_to.time_zone(), relative_to.calendar(), years, months, weeks, days, 0, 0, 0, 0, 0, 0)); - - // 7. Let dayEnd be ? AddZonedDateTime(dayStart, relativeTo.[[TimeZone]], relativeTo.[[Calendar]], 0, 0, 0, direction, 0, 0, 0, 0, 0, 0). - auto* day_end = TRY(add_zoned_date_time(vm, *day_start, &relative_to.time_zone(), relative_to.calendar(), 0, 0, 0, direction, 0, 0, 0, 0, 0, 0)); - - // 8. Let dayLengthNs be ℝ(dayEnd - dayStart). - auto day_length_ns = day_end->big_integer().minus(day_start->big_integer()); - - // 9. If (timeRemainderNs - dayLengthNs) × direction < 0, then - if (time_remainder_ns.minus(day_length_ns).multiplied_by(Crypto::SignedBigInteger { direction }).is_negative()) { - // a. Return ! CreateDurationRecord(years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds). - return create_duration_record(years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds); - } - - // 10. Set timeRemainderNs to ! RoundTemporalInstant(ℤ(timeRemainderNs - dayLengthNs), increment, unit, roundingMode). - time_remainder_ns = round_temporal_instant(vm, BigInt::create(vm, time_remainder_ns.minus(day_length_ns)), increment, unit, rounding_mode)->big_integer(); - - // 11. Let adjustedDateDuration be ? AddDuration(years, months, weeks, days, 0, 0, 0, 0, 0, 0, 0, 0, 0, direction, 0, 0, 0, 0, 0, 0, relativeTo). - auto adjusted_date_duration = TRY(add_duration(vm, years, months, weeks, days, 0, 0, 0, 0, 0, 0, 0, 0, 0, direction, 0, 0, 0, 0, 0, 0, &relative_to)); - - // 12. Let adjustedTimeDuration be ? BalanceDuration(0, 0, 0, 0, 0, 0, timeRemainderNs, "hour"). - auto adjusted_time_duration = TRY(balance_duration(vm, 0, 0, 0, 0, 0, 0, time_remainder_ns, "hour"sv)); - - // 13. Return ! CreateDurationRecord(adjustedDateDuration.[[Years]], adjustedDateDuration.[[Months]], adjustedDateDuration.[[Weeks]], adjustedDateDuration.[[Days]], adjustedTimeDuration.[[Hours]], adjustedTimeDuration.[[Minutes]], adjustedTimeDuration.[[Seconds]], adjustedTimeDuration.[[Milliseconds]], adjustedTimeDuration.[[Microseconds]], adjustedTimeDuration.[[Nanoseconds]]). - return create_duration_record(adjusted_date_duration.years, adjusted_date_duration.months, adjusted_date_duration.weeks, adjusted_date_duration.days, adjusted_time_duration.hours, adjusted_time_duration.minutes, adjusted_time_duration.seconds, adjusted_time_duration.milliseconds, adjusted_time_duration.microseconds, adjusted_time_duration.nanoseconds); -} - -// 7.5.27 TemporalDurationToString ( years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, precision ), https://tc39.es/proposal-temporal/#sec-temporal-temporaldurationtostring -ThrowCompletionOr temporal_duration_to_string(VM& vm, double years, double months, double weeks, double days, double hours, double minutes, double seconds, double milliseconds, double microseconds, double nanoseconds, Variant const& precision) -{ - if (precision.has()) - VERIFY(precision.get() == "auto"sv); - - // 1. Let sign be ! DurationSign(years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds). - auto sign = duration_sign(years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds); - - // 2. Set microseconds to microseconds + truncate(nanoseconds / 1000). - microseconds += trunc(nanoseconds / 1000); - - // 3. Set nanoseconds to remainder(nanoseconds, 1000). - nanoseconds = fmod(nanoseconds, 1000); - - // 4. Set milliseconds to milliseconds + truncate(microseconds / 1000). - milliseconds += trunc(microseconds / 1000); - - // 5. Set microseconds to remainder(microseconds, 1000). - microseconds = fmod(microseconds, 1000); - - // 6. Set seconds to seconds + truncate(milliseconds / 1000). - seconds += trunc(milliseconds / 1000); - - // 7. Set milliseconds to remainder(milliseconds, 1000). - milliseconds = fmod(milliseconds, 1000); - - // 8. Let datePart be "". - StringBuilder date_part; - - // 9. If years is not 0, then - if (years != 0) { - // a. Set datePart to the string concatenation of abs(years) formatted as a decimal number and the code unit 0x0059 (LATIN CAPITAL LETTER Y). - date_part.appendff("{}", fabs(years)); - date_part.append('Y'); - } - - // 10. If months is not 0, then - if (months != 0) { - // a. Set datePart to the string concatenation of datePart, abs(months) formatted as a decimal number, and the code unit 0x004D (LATIN CAPITAL LETTER M). - date_part.appendff("{}", fabs(months)); - date_part.append('M'); - } - - // 11. If weeks is not 0, then - if (weeks != 0) { - // a. Set datePart to the string concatenation of datePart, abs(weeks) formatted as a decimal number, and the code unit 0x0057 (LATIN CAPITAL LETTER W). - date_part.appendff("{}", fabs(weeks)); - date_part.append('W'); - } - - // 12. If days is not 0, then - if (days != 0) { - // a. Set datePart to the string concatenation of datePart, abs(days) formatted as a decimal number, and the code unit 0x0044 (LATIN CAPITAL LETTER D). - date_part.appendff("{}", fabs(days)); - date_part.append('D'); - } - - // 13. Let timePart be "". - StringBuilder time_part; - - // 14. If hours is not 0, then - if (hours != 0) { - // a. Set timePart to the string concatenation of abs(hours) formatted as a decimal number and the code unit 0x0048 (LATIN CAPITAL LETTER H). - time_part.appendff("{}", fabs(hours)); - time_part.append('H'); - } - - // 15. If minutes is not 0, then - if (minutes != 0) { - // a. Set timePart to the string concatenation of timePart, abs(minutes) formatted as a decimal number, and the code unit 0x004D (LATIN CAPITAL LETTER M). - time_part.appendff("{}", fabs(minutes)); - time_part.append('M'); - } - - // 16. If any of seconds, milliseconds, microseconds, and nanoseconds are not 0; or years, months, weeks, days, hours, and minutes are all 0; or precision is not "auto"; then - if ((seconds != 0 || milliseconds != 0 || microseconds != 0 || nanoseconds != 0) || (years == 0 && months == 0 && weeks == 0 && days == 0 && hours == 0 && minutes == 0) || (!precision.has() || precision.get() != "auto"sv)) { - // a. Let fraction be abs(milliseconds) × 10^6 + abs(microseconds) × 10^3 + abs(nanoseconds). - auto fraction = fabs(milliseconds) * 1'000'000 + fabs(microseconds) * 1'000 + fabs(nanoseconds); - - // b. Let decimalPart be ToZeroPaddedDecimalString(fraction, 9). - // NOTE: padding with zeros leads to weird results when applied to a double. Not sure if that's a bug in AK/Format.h or if I'm doing this wrong. - auto decimal_part_string = TRY_OR_THROW_OOM(vm, String::formatted("{:09}", (u64)fraction)); - StringView decimal_part; - - // c. If precision is "auto", then - if (precision.has() && precision.get() == "auto"sv) { - // i. Set decimalPart to the longest possible substring of decimalPart starting at position 0 and not ending with the code unit 0x0030 (DIGIT ZERO). - decimal_part = decimal_part_string.bytes_as_string_view().trim("0"sv, TrimMode::Right); - } - // d. Else if precision = 0, then - else if (precision.get() == 0) { - // i. Set decimalPart to "". - decimal_part = ""sv; - } - // e. Else, - else { - // i. Set decimalPart to the substring of decimalPart from 0 to precision. - decimal_part = decimal_part_string.bytes_as_string_view().substring_view(0, precision.get()); - } - - // f. Let secondsPart be abs(seconds) formatted as a decimal number. - StringBuilder seconds_part; - seconds_part.appendff("{}", fabs(seconds)); - - // g. If decimalPart is not "", then - if (!decimal_part.is_empty()) { - // i. Set secondsPart to the string-concatenation of secondsPart, the code unit 0x002E (FULL STOP), and decimalPart. - seconds_part.append('.'); - seconds_part.append(decimal_part); - } - - // h. Set timePart to the string concatenation of timePart, secondsPart, and the code unit 0x0053 (LATIN CAPITAL LETTER S). - time_part.append(seconds_part.string_view()); - time_part.append('S'); - } - - // 17. Let signPart be the code unit 0x002D (HYPHEN-MINUS) if sign < 0, and otherwise the empty String. - auto sign_part = sign < 0 ? "-"sv : ""sv; - - // 18. Let result be the string concatenation of signPart, the code unit 0x0050 (LATIN CAPITAL LETTER P) and datePart. - StringBuilder result; - result.append(sign_part); - result.append('P'); - result.append(date_part.string_view()); - - // 19. If timePart is not "", then - if (!time_part.is_empty()) { - // a. Set result to the string concatenation of result, the code unit 0x0054 (LATIN CAPITAL LETTER T), and timePart. - result.append('T'); - result.append(time_part.string_view()); - } - - // 20. Return result. - return TRY_OR_THROW_OOM(vm, result.to_string()); -} - -// 7.5.28 AddDurationToOrSubtractDurationFromDuration ( operation, duration, other, options ), https://tc39.es/proposal-temporal/#sec-temporal-adddurationtoorsubtractdurationfromduration -ThrowCompletionOr> add_duration_to_or_subtract_duration_from_duration(VM& vm, ArithmeticOperation operation, Duration const& duration, Value other_value, Value options_value) -{ - // 1. If operation is subtract, let sign be -1. Otherwise, let sign be 1. - i8 sign = operation == ArithmeticOperation::Subtract ? -1 : 1; - - // 2. Set other to ? ToTemporalDurationRecord(other). - auto other = TRY(to_temporal_duration_record(vm, other_value)); - - // 3. Set options to ? GetOptionsObject(options). - auto const* options = TRY(get_options_object(vm, options_value)); - - // 4. Let relativeToRecord be ? ToRelativeTemporalObject(options). - auto relative_to_record = TRY(to_relative_temporal_object(vm, *options)); - - // 5. Let result be ? AddDuration(duration.[[Years]], duration.[[Months]], duration.[[Weeks]], duration.[[Days]], duration.[[Hours]], duration.[[Minutes]], duration.[[Seconds]], duration.[[Milliseconds]], duration.[[Microseconds]], duration.[[Nanoseconds]], sign × other.[[Years]], sign × other.[[Months]], sign × other.[[Weeks]], sign × other.[[Days]], sign × other.[[Hours]], sign × other.[[Minutes]], sign × other.[[Seconds]], sign × other.[[Milliseconds]], sign × other.[[Microseconds]], sign × other.[[Nanoseconds]], relativeTo). - auto result = TRY(add_duration(vm, duration.years(), duration.months(), duration.weeks(), duration.days(), duration.hours(), duration.minutes(), duration.seconds(), duration.milliseconds(), duration.microseconds(), duration.nanoseconds(), sign * other.years, sign * other.months, sign * other.weeks, sign * other.days, sign * other.hours, sign * other.minutes, sign * other.seconds, sign * other.milliseconds, sign * other.microseconds, sign * other.nanoseconds, relative_to_converted_to_value(relative_to_record))); - - // 6. Return ! CreateTemporalDuration(result.[[Years]], result.[[Months]], result.[[Weeks]], result.[[Days]], result.[[Hours]], result.[[Minutes]], result.[[Seconds]], result.[[Milliseconds]], result.[[Microseconds]], result.[[Nanoseconds]]). - return MUST(create_temporal_duration(vm, result.years, result.months, result.weeks, result.days, result.hours, result.minutes, result.seconds, result.milliseconds, result.microseconds, result.nanoseconds)); -} - } diff --git a/Libraries/LibJS/Runtime/Temporal/Duration.h b/Libraries/LibJS/Runtime/Temporal/Duration.h index 141569a1410..a38c13e75fb 100644 --- a/Libraries/LibJS/Runtime/Temporal/Duration.h +++ b/Libraries/LibJS/Runtime/Temporal/Duration.h @@ -7,172 +7,11 @@ #pragma once -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include namespace JS::Temporal { -class Duration final : public Object { - JS_OBJECT(Duration, Object); - GC_DECLARE_ALLOCATOR(Duration); - -public: - virtual ~Duration() override = default; - - [[nodiscard]] double years() const { return m_years; } - [[nodiscard]] double months() const { return m_months; } - [[nodiscard]] double weeks() const { return m_weeks; } - [[nodiscard]] double days() const { return m_days; } - [[nodiscard]] double hours() const { return m_hours; } - [[nodiscard]] double minutes() const { return m_minutes; } - [[nodiscard]] double seconds() const { return m_seconds; } - [[nodiscard]] double milliseconds() const { return m_milliseconds; } - [[nodiscard]] double microseconds() const { return m_microseconds; } - [[nodiscard]] double nanoseconds() const { return m_nanoseconds; } - -private: - Duration(double years, double months, double weeks, double days, double hours, double minutes, double seconds, double milliseconds, double microseconds, double nanoseconds, Object& prototype); - - // 7.4 Properties of Temporal.Duration Instances, https://tc39.es/proposal-temporal/#sec-properties-of-temporal-duration-instances - double m_years; // [[Years]] - double m_months; // [[Months]] - double m_weeks; // [[Weeks]] - double m_days; // [[Days]] - double m_hours; // [[Hours]] - double m_minutes; // [[Minutes]] - double m_seconds; // [[Seconds]] - double m_milliseconds; // [[Milliseconds]] - double m_microseconds; // [[Microseconds]] - double m_nanoseconds; // [[Nanoseconds]] -}; - -// 7.5.1 Duration Records, https://tc39.es/proposal-temporal/#sec-temporal-duration-records -struct DurationRecord { - double years; - double months; - double weeks; - double days; - double hours; - double minutes; - double seconds; - double milliseconds; - double microseconds; - double nanoseconds; -}; - -// 7.5.2 Date Duration Records, https://tc39.es/proposal-temporal/#sec-temporal-date-duration-records -struct DateDurationRecord { - double years; - double months; - double weeks; - double days; -}; - -// 7.5.3 Time Duration Records, https://tc39.es/proposal-temporal/#sec-temporal-time-duration-records -struct TimeDurationRecord { - double days; - double hours; - double minutes; - double seconds; - double milliseconds; - double microseconds; - double nanoseconds; -}; - -// 7.5.4 Partial Duration Records, https://tc39.es/proposal-temporal/#sec-temporal-partial-duration-records -struct PartialDurationRecord { - Optional years; - Optional months; - Optional weeks; - Optional days; - Optional hours; - Optional minutes; - Optional seconds; - Optional milliseconds; - Optional microseconds; - Optional nanoseconds; -}; - -// Used by MoveRelativeDate to temporarily hold values -struct MoveRelativeDateResult { - GC::Root relative_to; - double days; -}; - -// Used by RoundDuration to temporarily hold values -struct RoundedDuration { - DurationRecord duration_record; - double total; -}; - -// Table 8: Duration Record Fields, https://tc39.es/proposal-temporal/#table-temporal-duration-record-fields - -template -struct TemporalDurationRecordField { - ValueT StructT::*field_name { nullptr }; - PropertyKey property_name; -}; - -DurationRecord create_duration_record(double years, double months, double weeks, double days, double hours, double minutes, double seconds, double milliseconds, double microseconds, double nanoseconds); -ThrowCompletionOr create_duration_record(VM&, double years, double months, double weeks, double days, double hours, double minutes, double seconds, double milliseconds, double microseconds, double nanoseconds); -DateDurationRecord create_date_duration_record(double years, double months, double weeks, double days); -ThrowCompletionOr create_date_duration_record(VM&, double years, double months, double weeks, double days); -ThrowCompletionOr create_time_duration_record(VM&, double days, double hours, double minutes, double seconds, double milliseconds, double microseconds, double nanoseconds); -ThrowCompletionOr> to_temporal_duration(VM&, Value item); -ThrowCompletionOr to_temporal_duration_record(VM&, Value temporal_duration_like); i8 duration_sign(double years, double months, double weeks, double days, double hours, double minutes, double seconds, double milliseconds, double microseconds, double nanoseconds); bool is_valid_duration(double years, double months, double weeks, double days, double hours, double minutes, double seconds, double milliseconds, double microseconds, double nanoseconds); -StringView default_temporal_largest_unit(double years, double months, double weeks, double days, double hours, double minutes, double seconds, double milliseconds, double microseconds); -ThrowCompletionOr to_temporal_partial_duration_record(VM&, Value temporal_duration_like); -ThrowCompletionOr> create_temporal_duration(VM&, double years, double months, double weeks, double days, double hours, double minutes, double seconds, double milliseconds, double microseconds, double nanoseconds, FunctionObject const* new_target = nullptr); -GC::Ref create_negated_temporal_duration(VM&, Duration const& duration); -ThrowCompletionOr calculate_offset_shift(VM&, Value relative_to_value, double years, double months, double weeks, double days); -Crypto::SignedBigInteger total_duration_nanoseconds(double days, double hours, double minutes, double seconds, double milliseconds, double microseconds, Crypto::SignedBigInteger const& nanoseconds, double offset_shift); -ThrowCompletionOr balance_time_duration(VM& vm, double days, double hours, double minutes, double seconds, double milliseconds, double microseconds, Crypto::SignedBigInteger const& nanoseconds, StringView largest_unit); -ThrowCompletionOr balance_duration(VM&, double days, double hours, double minutes, double seconds, double milliseconds, double microseconds, Crypto::SignedBigInteger const& nanoseconds, StringView largest_unit, Object* relative_to = nullptr); - -enum class Overflow { - Positive, - Negative, -}; - -Variant balance_possibly_infinite_time_duration(VM& vm, double days, double hours, double minutes, double seconds, double milliseconds, double microseconds, Crypto::SignedBigInteger const& nanoseconds, StringView largest_unit); - -ThrowCompletionOr unbalance_duration_relative(VM&, double years, double months, double weeks, double days, StringView largest_unit, Value relative_to); -ThrowCompletionOr balance_duration_relative(VM&, double years, double months, double weeks, double days, StringView largest_unit, Value relative_to); -ThrowCompletionOr add_duration(VM&, double years1, double months1, double weeks1, double days1, double hours1, double minutes1, double seconds1, double milliseconds1, double microseconds1, double nanoseconds1, double years2, double months2, double weeks2, double days2, double hours2, double minutes2, double seconds2, double milliseconds2, double microseconds2, double nanoseconds2, Value relative_to_value); -ThrowCompletionOr move_relative_date(VM&, Object& calendar, PlainDate& relative_to, Duration& duration, FunctionObject* date_add); -ThrowCompletionOr move_relative_zoned_date_time(VM&, ZonedDateTime&, double years, double months, double weeks, double days); -ThrowCompletionOr round_duration(VM&, double years, double months, double weeks, double days, double hours, double minutes, double seconds, double milliseconds, double microseconds, double nanoseconds, u32 increment, StringView unit, StringView rounding_mode, Object* relative_to_object = nullptr, Optional const& = {}); -ThrowCompletionOr adjust_rounded_duration_days(VM&, double years, double months, double weeks, double days, double hours, double minutes, double seconds, double milliseconds, double microseconds, double nanoseconds, u32 increment, StringView unit, StringView rounding_mode, Object* relative_to_object); -ThrowCompletionOr temporal_duration_to_string(VM&, double years, double months, double weeks, double days, double hours, double minutes, double seconds, double milliseconds, double microseconds, double nanoseconds, Variant const& precision); -ThrowCompletionOr> add_duration_to_or_subtract_duration_from_duration(VM&, ArithmeticOperation, Duration const&, Value other_value, Value options_value); - -// 7.5.22 DaysUntil ( earlier, later ), https://tc39.es/proposal-temporal/#sec-temporal-daysuntil -template -double days_until(EarlierObjectType& earlier, LaterObjectType& later) -{ - // 1. Let epochDays1 be MakeDay(𝔽(earlier.[[ISOYear]]), 𝔽(earlier.[[ISOMonth]] - 1), 𝔽(earlier.[[ISODay]])). - auto epoch_days_1 = make_day(earlier.iso_year(), earlier.iso_month() - 1, earlier.iso_day()); - - // 2. Assert: epochDays1 is finite. - VERIFY(isfinite(epoch_days_1)); - - // 3. Let epochDays2 be MakeDay(𝔽(later.[[ISOYear]]), 𝔽(later.[[ISOMonth]] - 1), 𝔽(later.[[ISODay]])). - auto epoch_days_2 = make_day(later.iso_year(), later.iso_month() - 1, later.iso_day()); - - // 4. Assert: epochDays2 is finite. - VERIFY(isfinite(epoch_days_2)); - - // 5. Return ℝ(epochDays2) - ℝ(epochDays1). - return epoch_days_2 - epoch_days_1; -} } diff --git a/Libraries/LibJS/Runtime/Temporal/DurationConstructor.cpp b/Libraries/LibJS/Runtime/Temporal/DurationConstructor.cpp deleted file mode 100644 index 1271c919e0f..00000000000 --- a/Libraries/LibJS/Runtime/Temporal/DurationConstructor.cpp +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright (c) 2021-2023, Linus Groh - * Copyright (c) 2021, Luke Wilde - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include -#include -#include -#include -#include -#include - -namespace JS::Temporal { - -GC_DEFINE_ALLOCATOR(DurationConstructor); - -// 7.1 The Temporal.Duration Constructor, https://tc39.es/proposal-temporal/#sec-temporal-duration-constructor -DurationConstructor::DurationConstructor(Realm& realm) - : NativeFunction(realm.vm().names.Duration.as_string(), realm.intrinsics().function_prototype()) -{ -} - -void DurationConstructor::initialize(Realm& realm) -{ - Base::initialize(realm); - - auto& vm = this->vm(); - - // 7.2.1 Temporal.Duration.prototype, https://tc39.es/proposal-temporal/#sec-temporal.duration.prototype - define_direct_property(vm.names.prototype, realm.intrinsics().temporal_duration_prototype(), 0); - - u8 attr = Attribute::Writable | Attribute::Configurable; - define_native_function(realm, vm.names.from, from, 1, attr); - define_native_function(realm, vm.names.compare, compare, 2, attr); - - define_direct_property(vm.names.length, Value(0), Attribute::Configurable); -} - -// 7.1.1 Temporal.Duration ( [ years [ , months [ , weeks [ , days [ , hours [ , minutes [ , seconds [ , milliseconds [ , microseconds [ , nanoseconds ] ] ] ] ] ] ] ] ] ] ), https://tc39.es/proposal-temporal/#sec-temporal.duration -ThrowCompletionOr DurationConstructor::call() -{ - auto& vm = this->vm(); - - // 1. If NewTarget is undefined, then - // a. Throw a TypeError exception. - return vm.throw_completion(ErrorType::ConstructorWithoutNew, "Temporal.Duration"); -} - -// 7.1.1 Temporal.Duration ( [ years [ , months [ , weeks [ , days [ , hours [ , minutes [ , seconds [ , milliseconds [ , microseconds [ , nanoseconds ] ] ] ] ] ] ] ] ] ] ), https://tc39.es/proposal-temporal/#sec-temporal.duration -ThrowCompletionOr> DurationConstructor::construct(FunctionObject& new_target) -{ - auto& vm = this->vm(); - - // 2. Let y be ? ToIntegerIfIntegral(years). - auto y = TRY(to_integer_if_integral(vm, vm.argument(0), ErrorType::TemporalInvalidDuration)); - - // 3. Let mo be ? ToIntegerIfIntegral(months). - auto mo = TRY(to_integer_if_integral(vm, vm.argument(1), ErrorType::TemporalInvalidDuration)); - - // 4. Let w be ? ToIntegerIfIntegral(weeks). - auto w = TRY(to_integer_if_integral(vm, vm.argument(2), ErrorType::TemporalInvalidDuration)); - - // 5. Let d be ? ToIntegerIfIntegral(days). - auto d = TRY(to_integer_if_integral(vm, vm.argument(3), ErrorType::TemporalInvalidDuration)); - - // 6. Let h be ? ToIntegerIfIntegral(hours). - auto h = TRY(to_integer_if_integral(vm, vm.argument(4), ErrorType::TemporalInvalidDuration)); - - // 7. Let m be ? ToIntegerIfIntegral(minutes). - auto m = TRY(to_integer_if_integral(vm, vm.argument(5), ErrorType::TemporalInvalidDuration)); - - // 8. Let s be ? ToIntegerIfIntegral(seconds). - auto s = TRY(to_integer_if_integral(vm, vm.argument(6), ErrorType::TemporalInvalidDuration)); - - // 9. Let ms be ? ToIntegerIfIntegral(milliseconds). - auto ms = TRY(to_integer_if_integral(vm, vm.argument(7), ErrorType::TemporalInvalidDuration)); - - // 10. Let mis be ? ToIntegerIfIntegral(microseconds). - auto mis = TRY(to_integer_if_integral(vm, vm.argument(8), ErrorType::TemporalInvalidDuration)); - - // 11. Let ns be ? ToIntegerIfIntegral(nanoseconds). - auto ns = TRY(to_integer_if_integral(vm, vm.argument(9), ErrorType::TemporalInvalidDuration)); - - // 12. Return ? CreateTemporalDuration(y, mo, w, d, h, m, s, ms, mis, ns, NewTarget). - return TRY(create_temporal_duration(vm, y, mo, w, d, h, m, s, ms, mis, ns, &new_target)); -} - -// 7.2.2 Temporal.Duration.from ( item ), https://tc39.es/proposal-temporal/#sec-temporal.duration.from -JS_DEFINE_NATIVE_FUNCTION(DurationConstructor::from) -{ - auto item = vm.argument(0); - - // 1. If Type(item) is Object and item has an [[InitializedTemporalDuration]] internal slot, then - if (item.is_object() && is(item.as_object())) { - auto& duration = static_cast(item.as_object()); - - // a. Return ! CreateTemporalDuration(item.[[Years]], item.[[Months]], item.[[Weeks]], item.[[Days]], item.[[Hours]], item.[[Minutes]], item.[[Seconds]], item.[[Milliseconds]], item.[[Microseconds]], item.[[Nanoseconds]]). - return MUST(create_temporal_duration(vm, duration.years(), duration.months(), duration.weeks(), duration.days(), duration.hours(), duration.minutes(), duration.seconds(), duration.milliseconds(), duration.microseconds(), duration.nanoseconds())); - } - - // 2. Return ? ToTemporalDuration(item). - return TRY(to_temporal_duration(vm, item)); -} - -// 7.2.3 Temporal.Duration.compare ( one, two [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal.duration.compare -JS_DEFINE_NATIVE_FUNCTION(DurationConstructor::compare) -{ - // 1. Set one to ? ToTemporalDuration(one). - auto one = TRY(to_temporal_duration(vm, vm.argument(0))); - - // 2. Set two to ? ToTemporalDuration(two). - auto two = TRY(to_temporal_duration(vm, vm.argument(1))); - - // 3. Set options to ? GetOptionsObject(options). - auto const* options = TRY(get_options_object(vm, vm.argument(2))); - - // 4. Let relativeTo be ? ToRelativeTemporalObject(options). - auto relative_to = relative_to_converted_to_value(TRY(to_relative_temporal_object(vm, *options))); - - // 5. Let shift1 be ? CalculateOffsetShift(relativeTo, one.[[Years]], one.[[Months]], one.[[Weeks]], one.[[Days]]). - auto shift1 = TRY(calculate_offset_shift(vm, relative_to, one->years(), one->months(), one->weeks(), one->days())); - - // 6. Let shift2 be ? CalculateOffsetShift(relativeTo, two.[[Years]], two.[[Months]], two.[[Weeks]], two.[[Days]]). - auto shift2 = TRY(calculate_offset_shift(vm, relative_to, two->years(), two->months(), two->weeks(), two->days())); - - double days1; - double days2; - - // 7. If any of one.[[Years]], two.[[Years]], one.[[Months]], two.[[Months]], one.[[Weeks]], or two.[[Weeks]] are not 0, then - if (one->years() != 0 || two->years() != 0 || one->months() != 0 || two->months() != 0 || one->weeks() != 0 || two->weeks() != 0) { - // a. Let unbalanceResult1 be ? UnbalanceDurationRelative(one.[[Years]], one.[[Months]], one.[[Weeks]], one.[[Days]], "day", relativeTo). - auto unbalance_result1 = TRY(unbalance_duration_relative(vm, one->years(), one->months(), one->weeks(), one->days(), "day"sv, relative_to)); - - // b. Let unbalanceResult2 be ? UnbalanceDurationRelative(two.[[Years]], two.[[Months]], two.[[Weeks]], two.[[Days]], "day", relativeTo). - auto unbalance_result2 = TRY(unbalance_duration_relative(vm, two->years(), two->months(), two->weeks(), two->days(), "day"sv, relative_to)); - - // c. Let days1 be unbalanceResult1.[[Days]]. - days1 = unbalance_result1.days; - - // d. Let days2 be unbalanceResult2.[[Days]]. - days2 = unbalance_result2.days; - } - // 8. Else, - else { - // a. Let days1 be one.[[Days]]. - days1 = one->days(); - - // b. Let days2 be two.[[Days]]. - days2 = two->days(); - } - - // 9. Let ns1 be ! TotalDurationNanoseconds(days1, one.[[Hours]], one.[[Minutes]], one.[[Seconds]], one.[[Milliseconds]], one.[[Microseconds]], one.[[Nanoseconds]], shift1). - auto ns1 = total_duration_nanoseconds(days1, one->hours(), one->minutes(), one->seconds(), one->milliseconds(), one->microseconds(), Crypto::SignedBigInteger { one->nanoseconds() }, shift1); - - // 10. Let ns2 be ! TotalDurationNanoseconds(days2, two.[[Hours]], two.[[Minutes]], two.[[Seconds]], two.[[Milliseconds]], two.[[Microseconds]], two.[[Nanoseconds]], shift2). - auto ns2 = total_duration_nanoseconds(days2, two->hours(), two->minutes(), two->seconds(), two->milliseconds(), two->microseconds(), Crypto::SignedBigInteger { two->nanoseconds() }, shift2); - - // 11. If ns1 > ns2, return 1𝔽. - if (ns1 > ns2) - return Value(1); - - // 12. If ns1 < ns2, return -1𝔽. - if (ns1 < ns2) - return Value(-1); - - // 13. Return +0𝔽. - return Value(0); -} - -} diff --git a/Libraries/LibJS/Runtime/Temporal/DurationConstructor.h b/Libraries/LibJS/Runtime/Temporal/DurationConstructor.h deleted file mode 100644 index 381dc334944..00000000000 --- a/Libraries/LibJS/Runtime/Temporal/DurationConstructor.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2021-2022, Linus Groh - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include - -namespace JS::Temporal { - -class DurationConstructor final : public NativeFunction { - JS_OBJECT(DurationConstructor, NativeFunction); - GC_DECLARE_ALLOCATOR(DurationConstructor); - -public: - virtual void initialize(Realm&) override; - virtual ~DurationConstructor() override = default; - - virtual ThrowCompletionOr call() override; - virtual ThrowCompletionOr> construct(FunctionObject& new_target) override; - -private: - explicit DurationConstructor(Realm&); - - virtual bool has_constructor() const override { return true; } - - JS_DECLARE_NATIVE_FUNCTION(from); - JS_DECLARE_NATIVE_FUNCTION(compare); -}; - -} diff --git a/Libraries/LibJS/Runtime/Temporal/DurationPrototype.cpp b/Libraries/LibJS/Runtime/Temporal/DurationPrototype.cpp deleted file mode 100644 index 9f0cebd2315..00000000000 --- a/Libraries/LibJS/Runtime/Temporal/DurationPrototype.cpp +++ /dev/null @@ -1,574 +0,0 @@ -/* - * Copyright (c) 2021-2023, Linus Groh - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include -#include -#include -#include -#include -#include -#include - -namespace JS::Temporal { - -GC_DEFINE_ALLOCATOR(DurationPrototype); - -// 7.3 Properties of the Temporal.Duration Prototype Object, https://tc39.es/proposal-temporal/#sec-properties-of-the-temporal-duration-prototype-object -DurationPrototype::DurationPrototype(Realm& realm) - : PrototypeObject(realm.intrinsics().object_prototype()) -{ -} - -void DurationPrototype::initialize(Realm& realm) -{ - Base::initialize(realm); - - auto& vm = this->vm(); - - // 7.3.2 Temporal.Duration.prototype[ @@toStringTag ], https://tc39.es/proposal-temporal/#sec-temporal.duration.prototype-@@tostringtag - define_direct_property(vm.well_known_symbol_to_string_tag(), PrimitiveString::create(vm, "Temporal.Duration"_string), Attribute::Configurable); - - define_native_accessor(realm, vm.names.years, years_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.months, months_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.weeks, weeks_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.days, days_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.hours, hours_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.minutes, minutes_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.seconds, seconds_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.milliseconds, milliseconds_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.microseconds, microseconds_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.nanoseconds, nanoseconds_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.sign, sign_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.blank, blank_getter, {}, Attribute::Configurable); - - u8 attr = Attribute::Writable | Attribute::Configurable; - define_native_function(realm, vm.names.with, with, 1, attr); - define_native_function(realm, vm.names.negated, negated, 0, attr); - define_native_function(realm, vm.names.abs, abs, 0, attr); - define_native_function(realm, vm.names.add, add, 1, attr); - define_native_function(realm, vm.names.subtract, subtract, 1, attr); - define_native_function(realm, vm.names.round, round, 1, attr); - define_native_function(realm, vm.names.total, total, 1, attr); - define_native_function(realm, vm.names.toString, to_string, 0, attr); - define_native_function(realm, vm.names.toJSON, to_json, 0, attr); - define_native_function(realm, vm.names.toLocaleString, to_locale_string, 0, attr); - define_native_function(realm, vm.names.valueOf, value_of, 0, attr); -} - -// 7.3.3 get Temporal.Duration.prototype.years, https://tc39.es/proposal-temporal/#sec-get-temporal.duration.prototype.years -JS_DEFINE_NATIVE_FUNCTION(DurationPrototype::years_getter) -{ - // 1. Let duration be the this value. - // 2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]). - auto duration = TRY(typed_this_object(vm)); - - // 3. Return 𝔽(duration.[[Years]]). - return Value(duration->years()); -} - -// 7.3.4 get Temporal.Duration.prototype.months, https://tc39.es/proposal-temporal/#sec-get-temporal.duration.prototype.months -JS_DEFINE_NATIVE_FUNCTION(DurationPrototype::months_getter) -{ - // 1. Let duration be the this value. - // 2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]). - auto duration = TRY(typed_this_object(vm)); - - // 3. Return 𝔽(duration.[[Months]]). - return Value(duration->months()); -} - -// 7.3.5 get Temporal.Duration.prototype.weeks, https://tc39.es/proposal-temporal/#sec-get-temporal.duration.prototype.weeks -JS_DEFINE_NATIVE_FUNCTION(DurationPrototype::weeks_getter) -{ - // 1. Let duration be the this value. - // 2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]). - auto duration = TRY(typed_this_object(vm)); - - // 3. Return 𝔽(duration.[[Weeks]]). - return Value(duration->weeks()); -} - -// 7.3.6 get Temporal.Duration.prototype.days, https://tc39.es/proposal-temporal/#sec-get-temporal.duration.prototype.days -JS_DEFINE_NATIVE_FUNCTION(DurationPrototype::days_getter) -{ - // 1. Let duration be the this value. - // 2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]). - auto duration = TRY(typed_this_object(vm)); - - // 3. Return 𝔽(duration.[[Days]]). - return Value(duration->days()); -} - -// 7.3.7 get Temporal.Duration.prototype.hours, https://tc39.es/proposal-temporal/#sec-get-temporal.duration.prototype.hours -JS_DEFINE_NATIVE_FUNCTION(DurationPrototype::hours_getter) -{ - // 1. Let duration be the this value. - // 2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]). - auto duration = TRY(typed_this_object(vm)); - - // 3. Return 𝔽(duration.[[Hours]]). - return Value(duration->hours()); -} - -// 7.3.8 get Temporal.Duration.prototype.minutes, https://tc39.es/proposal-temporal/#sec-get-temporal.duration.prototype.minutes -JS_DEFINE_NATIVE_FUNCTION(DurationPrototype::minutes_getter) -{ - // 1. Let duration be the this value. - // 2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]). - auto duration = TRY(typed_this_object(vm)); - - // 3. Return 𝔽(duration.[[Minutes]]). - return Value(duration->minutes()); -} - -// 7.3.9 get Temporal.Duration.prototype.seconds, https://tc39.es/proposal-temporal/#sec-get-temporal.duration.prototype.seconds -JS_DEFINE_NATIVE_FUNCTION(DurationPrototype::seconds_getter) -{ - // 1. Let duration be the this value. - // 2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]). - auto duration = TRY(typed_this_object(vm)); - - // 3. Return 𝔽(duration.[[Seconds]]). - return Value(duration->seconds()); -} - -// 7.3.10 get Temporal.Duration.prototype.milliseconds, https://tc39.es/proposal-temporal/#sec-get-temporal.duration.prototype.milliseconds -JS_DEFINE_NATIVE_FUNCTION(DurationPrototype::milliseconds_getter) -{ - // 1. Let duration be the this value. - // 2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]). - auto duration = TRY(typed_this_object(vm)); - - // 3. Return 𝔽(duration.[[Milliseconds]]). - return Value(duration->milliseconds()); -} - -// 7.3.11 get Temporal.Duration.prototype.microseconds, https://tc39.es/proposal-temporal/#sec-get-temporal.duration.prototype.microseconds -JS_DEFINE_NATIVE_FUNCTION(DurationPrototype::microseconds_getter) -{ - // 1. Let duration be the this value. - // 2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]). - auto duration = TRY(typed_this_object(vm)); - - // 3. Return 𝔽(duration.[[Microseconds]]). - return Value(duration->microseconds()); -} - -// 7.3.12 get Temporal.Duration.prototype.nanoseconds, https://tc39.es/proposal-temporal/#sec-get-temporal.duration.prototype.nanoseconds -JS_DEFINE_NATIVE_FUNCTION(DurationPrototype::nanoseconds_getter) -{ - // 1. Let duration be the this value. - // 2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]). - auto duration = TRY(typed_this_object(vm)); - - // 3. Return 𝔽(duration.[[Nanoseconds]]). - return Value(duration->nanoseconds()); -} - -// 7.3.13 get Temporal.Duration.prototype.sign, https://tc39.es/proposal-temporal/#sec-get-temporal.duration.prototype.sign -JS_DEFINE_NATIVE_FUNCTION(DurationPrototype::sign_getter) -{ - // 1. Let duration be the this value. - // 2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]). - auto duration = TRY(typed_this_object(vm)); - - // 3. Return 𝔽(! DurationSign(duration.[[Years]], duration.[[Months]], duration.[[Weeks]], duration.[[Days]], duration.[[Hours]], duration.[[Minutes]], duration.[[Seconds]], duration.[[Milliseconds]], duration.[[Microseconds]], duration.[[Nanoseconds]])). - return Value(duration_sign(duration->years(), duration->months(), duration->weeks(), duration->days(), duration->hours(), duration->minutes(), duration->seconds(), duration->milliseconds(), duration->microseconds(), duration->nanoseconds())); -} - -// 7.3.14 get Temporal.Duration.prototype.blank, https://tc39.es/proposal-temporal/#sec-get-temporal.duration.prototype.blank -JS_DEFINE_NATIVE_FUNCTION(DurationPrototype::blank_getter) -{ - // 1. Let duration be the this value. - // 2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]). - auto duration = TRY(typed_this_object(vm)); - - // 3. Let sign be ! DurationSign(duration.[[Years]], duration.[[Months]], duration.[[Weeks]], duration.[[Days]], duration.[[Hours]], duration.[[Minutes]], duration.[[Seconds]], duration.[[Milliseconds]], duration.[[Microseconds]], duration.[[Nanoseconds]]). - auto sign = duration_sign(duration->years(), duration->months(), duration->weeks(), duration->days(), duration->hours(), duration->minutes(), duration->seconds(), duration->milliseconds(), duration->microseconds(), duration->nanoseconds()); - - // 4. If sign = 0, return true. - if (sign == 0) - return Value(true); - - // 5. Return false. - return Value(false); -} - -// 7.3.15 Temporal.Duration.prototype.with ( temporalDurationLike ), https://tc39.es/proposal-temporal/#sec-temporal.duration.prototype.with -JS_DEFINE_NATIVE_FUNCTION(DurationPrototype::with) -{ - // 1. Let duration be the this value. - // 2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]). - auto duration = TRY(typed_this_object(vm)); - - // 3. Let temporalDurationLike be ? ToTemporalPartialDurationRecord(temporalDurationLike). - auto temporal_duration_like = TRY(to_temporal_partial_duration_record(vm, vm.argument(0))); - - // 4. If temporalDurationLike.[[Years]] is not undefined, then - // a. Let years be temporalDurationLike.[[Years]]. - // 5. Else, - // a. Let years be duration.[[Years]]. - auto years = temporal_duration_like.years.value_or(duration->years()); - - // 6. If temporalDurationLike.[[Months]] is not undefined, then - // a. Let months be temporalDurationLike.[[Months]]. - // 7. Else, - // a. Let months be duration.[[Months]]. - auto months = temporal_duration_like.months.value_or(duration->months()); - - // 8. If temporalDurationLike.[[Weeks]] is not undefined, then - // a. Let weeks be temporalDurationLike.[[Weeks]]. - // 9. Else, - // a. Let weeks be duration.[[Weeks]]. - auto weeks = temporal_duration_like.weeks.value_or(duration->weeks()); - - // 10. If temporalDurationLike.[[Days]] is not undefined, then - // a. Let days be temporalDurationLike.[[Days]]. - // 11. Else, - // a. Let days be duration.[[Days]]. - auto days = temporal_duration_like.days.value_or(duration->days()); - - // 12. If temporalDurationLike.[[Hours]] is not undefined, then - // a. Let hours be temporalDurationLike.[[Hours]]. - // 13. Else, - // a. Let hours be duration.[[Hours]]. - auto hours = temporal_duration_like.hours.value_or(duration->hours()); - - // 14. If temporalDurationLike.[[Minutes]] is not undefined, then - // a. Let minutes be temporalDurationLike.[[Minutes]]. - // 15. Else, - // a. Let minutes be duration.[[Minutes]]. - auto minutes = temporal_duration_like.minutes.value_or(duration->minutes()); - - // 16. If temporalDurationLike.[[Seconds]] is not undefined, then - // a. Let seconds be temporalDurationLike.[[Seconds]]. - // 17. Else, - // a. Let seconds be duration.[[Seconds]]. - auto seconds = temporal_duration_like.seconds.value_or(duration->seconds()); - - // 18. If temporalDurationLike.[[Milliseconds]] is not undefined, then - // a. Let milliseconds be temporalDurationLike.[[Milliseconds]]. - // 19. Else, - // a. Let milliseconds be duration.[[Milliseconds]]. - auto milliseconds = temporal_duration_like.milliseconds.value_or(duration->milliseconds()); - - // 20. If temporalDurationLike.[[Microseconds]] is not undefined, then - // a. Let microseconds be temporalDurationLike.[[Microseconds]]. - // 21. Else, - // a. Let microseconds be duration.[[Microseconds]]. - auto microseconds = temporal_duration_like.microseconds.value_or(duration->microseconds()); - - // 22. If temporalDurationLike.[[Nanoseconds]] is not undefined, then - // a. Let nanoseconds be temporalDurationLike.[[Nanoseconds]]. - // 23. Else, - // a. Let nanoseconds be duration.[[Nanoseconds]]. - auto nanoseconds = temporal_duration_like.nanoseconds.value_or(duration->nanoseconds()); - - // 24. Return ? CreateTemporalDuration(years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds). - return TRY(create_temporal_duration(vm, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds)); -} - -// 7.3.16 Temporal.Duration.prototype.negated ( ), https://tc39.es/proposal-temporal/#sec-temporal.duration.prototype.negated -JS_DEFINE_NATIVE_FUNCTION(DurationPrototype::negated) -{ - // 1. Let duration be the this value. - // 2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]). - auto duration = TRY(typed_this_object(vm)); - - // 3. Return ! CreateNegatedTemporalDuration(duration). - return create_negated_temporal_duration(vm, duration); -} - -// 7.3.17 Temporal.Duration.prototype.abs ( ), https://tc39.es/proposal-temporal/#sec-temporal.duration.prototype.abs -JS_DEFINE_NATIVE_FUNCTION(DurationPrototype::abs) -{ - // 1. Let duration be the this value. - // 2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]). - auto duration = TRY(typed_this_object(vm)); - - // 3. Return ! CreateTemporalDuration(abs(duration.[[Years]]), abs(duration.[[Months]]), abs(duration.[[Weeks]]), abs(duration.[[Days]]), abs(duration.[[Hours]]), abs(duration.[[Minutes]]), abs(duration.[[Seconds]]), abs(duration.[[Milliseconds]]), abs(duration.[[Microseconds]]), abs(duration.[[Nanoseconds]])). - return TRY(create_temporal_duration(vm, fabs(duration->years()), fabs(duration->months()), fabs(duration->weeks()), fabs(duration->days()), fabs(duration->hours()), fabs(duration->minutes()), fabs(duration->seconds()), fabs(duration->milliseconds()), fabs(duration->microseconds()), fabs(duration->nanoseconds()))); -} - -// 7.3.18 Temporal.Duration.prototype.add ( other [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal.duration.prototype.add -JS_DEFINE_NATIVE_FUNCTION(DurationPrototype::add) -{ - auto other = vm.argument(0); - auto options = vm.argument(1); - - // 1. Let duration be the this value. - // 2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]). - auto duration = TRY(typed_this_object(vm)); - - // 3. Return ? AddDurationToOrSubtractDurationFromDuration(add, duration, other, options). - return TRY(add_duration_to_or_subtract_duration_from_duration(vm, ArithmeticOperation::Add, duration, other, options)); -} - -// 7.3.19 Temporal.Duration.prototype.subtract ( other [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal.duration.prototype.subtract -JS_DEFINE_NATIVE_FUNCTION(DurationPrototype::subtract) -{ - auto other = vm.argument(0); - auto options = vm.argument(1); - - // 1. Let duration be the this value. - // 2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]). - auto duration = TRY(typed_this_object(vm)); - - // 3. Return ? AddDurationToOrSubtractDurationFromDuration(subtract, duration, other, options). - return TRY(add_duration_to_or_subtract_duration_from_duration(vm, ArithmeticOperation::Subtract, duration, other, options)); -} - -// 7.3.20 Temporal.Duration.prototype.round ( roundTo ), https://tc39.es/proposal-temporal/#sec-temporal.duration.prototype.round -JS_DEFINE_NATIVE_FUNCTION(DurationPrototype::round) -{ - auto& realm = *vm.current_realm(); - - auto round_to_value = vm.argument(0); - - // 1. Let duration be the this value. - // 2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]). - auto duration = TRY(typed_this_object(vm)); - - // 3. If roundTo is undefined, then - if (round_to_value.is_undefined()) { - // a. Throw a TypeError exception. - return vm.throw_completion(ErrorType::TemporalMissingOptionsObject); - } - - Object* round_to; - - // 4. If Type(roundTo) is String, then - if (round_to_value.is_string()) { - // a. Let paramString be roundTo. - - // b. Set roundTo to OrdinaryObjectCreate(null). - round_to = Object::create(realm, nullptr); - - // c. Perform ! CreateDataPropertyOrThrow(roundTo, "smallestUnit", paramString). - MUST(round_to->create_data_property_or_throw(vm.names.smallestUnit, vm.argument(0))); - } - // 5. Else, - else { - // a. Set roundTo to ? GetOptionsObject(roundTo). - round_to = TRY(get_options_object(vm, round_to_value)); - } - - // 6. Let smallestUnitPresent be true. - bool smallest_unit_present = true; - - // 7. Let largestUnitPresent be true. - bool largest_unit_present = true; - - // 8. Let smallestUnit be ? GetTemporalUnit(roundTo, "smallestUnit", datetime, undefined). - auto smallest_unit = TRY(get_temporal_unit(vm, *round_to, vm.names.smallestUnit, UnitGroup::DateTime, Optional {})); - - // 9. If smallestUnit is undefined, then - if (!smallest_unit.has_value()) { - // a. Set smallestUnitPresent to false. - smallest_unit_present = false; - - // b. Set smallestUnit to "nanosecond". - smallest_unit = "nanosecond"_string; - } - - // 10. Let defaultLargestUnit be ! DefaultTemporalLargestUnit(duration.[[Years]], duration.[[Months]], duration.[[Weeks]], duration.[[Days]], duration.[[Hours]], duration.[[Minutes]], duration.[[Seconds]], duration.[[Milliseconds]], duration.[[Microseconds]]). - auto default_largest_unit = default_temporal_largest_unit(duration->years(), duration->months(), duration->weeks(), duration->days(), duration->hours(), duration->minutes(), duration->seconds(), duration->milliseconds(), duration->microseconds()); - - // 11. Set defaultLargestUnit to ! LargerOfTwoTemporalUnits(defaultLargestUnit, smallestUnit). - default_largest_unit = larger_of_two_temporal_units(default_largest_unit, *smallest_unit); - - // 12. Let largestUnit be ? GetTemporalUnit(roundTo, "largestUnit", datetime, undefined, « "auto" »). - auto largest_unit = TRY(get_temporal_unit(vm, *round_to, vm.names.largestUnit, UnitGroup::DateTime, Optional {}, { "auto"sv })); - - // 13. If largestUnit is undefined, then - if (!largest_unit.has_value()) { - // a. Set largestUnitPresent to false. - largest_unit_present = false; - - // b. Set largestUnit to defaultLargestUnit. - largest_unit = MUST(String::from_utf8(default_largest_unit)); - } - // 14. Else if largestUnit is "auto", then - else if (*largest_unit == "auto"sv) { - // a. Set largestUnit to defaultLargestUnit. - largest_unit = MUST(String::from_utf8(default_largest_unit)); - } - - // 15. If smallestUnitPresent is false and largestUnitPresent is false, then - if (!smallest_unit_present && !largest_unit_present) { - // a. Throw a RangeError exception. - return vm.throw_completion(ErrorType::TemporalMissingUnits); - } - - // 16. If LargerOfTwoTemporalUnits(largestUnit, smallestUnit) is not largestUnit, throw a RangeError exception. - if (larger_of_two_temporal_units(*largest_unit, *smallest_unit) != largest_unit) - return vm.throw_completion(ErrorType::TemporalInvalidUnitRange, *smallest_unit, *largest_unit); - - // 17. Let roundingMode be ? ToTemporalRoundingMode(roundTo, "halfExpand"). - auto rounding_mode = TRY(to_temporal_rounding_mode(vm, *round_to, "halfExpand"sv)); - - // 18. Let maximum be ! MaximumTemporalDurationRoundingIncrement(smallestUnit). - auto maximum = maximum_temporal_duration_rounding_increment(*smallest_unit); - - // 19. Let roundingIncrement be ? ToTemporalRoundingIncrement(options). - auto rounding_increment = TRY(to_temporal_rounding_increment(vm, *round_to)); - - // 20. If maximum is not undefined, perform ? ValidateTemporalRoundingIncrement(roundingIncrement, maximum, false). - if (maximum.has_value()) { - TRY(validate_temporal_rounding_increment(vm, rounding_increment, *maximum, false)); - } - - // 21. Let relativeTo be ? ToRelativeTemporalObject(roundTo). - auto relative_to = TRY(to_relative_temporal_object(vm, *round_to)); - auto relative_to_value = relative_to_converted_to_value(relative_to); - - // 22. Let unbalanceResult be ? UnbalanceDurationRelative(duration.[[Years]], duration.[[Months]], duration.[[Weeks]], duration.[[Days]], largestUnit, relativeTo). - auto unbalance_result = TRY(unbalance_duration_relative(vm, duration->years(), duration->months(), duration->weeks(), duration->days(), *largest_unit, relative_to_value)); - - auto calendar_record = TRY(create_calendar_methods_record_from_relative_to(vm, relative_to.plain_relative_to, relative_to.zoned_relative_to, { { CalendarMethod::DateAdd, CalendarMethod::DateUntil } })); - // 23. Let roundResult be (? RoundDuration(unbalanceResult.[[Years]], unbalanceResult.[[Months]], unbalanceResult.[[Weeks]], unbalanceResult.[[Days]], duration.[[Hours]], duration.[[Minutes]], duration.[[Seconds]], duration.[[Milliseconds]], duration.[[Microseconds]], duration.[[Nanoseconds]], roundingIncrement, smallestUnit, roundingMode, relativeTo)).[[DurationRecord]]. - auto round_result = TRY(round_duration(vm, unbalance_result.years, unbalance_result.months, unbalance_result.weeks, unbalance_result.days, duration->hours(), duration->minutes(), duration->seconds(), duration->milliseconds(), duration->microseconds(), duration->nanoseconds(), rounding_increment, *smallest_unit, rounding_mode, relative_to_value.is_object() ? &relative_to_value.as_object() : nullptr, calendar_record)).duration_record; - - // 24. Let adjustResult be ? AdjustRoundedDurationDays(roundResult.[[Years]], roundResult.[[Months]], roundResult.[[Weeks]], roundResult.[[Days]], roundResult.[[Hours]], roundResult.[[Minutes]], roundResult.[[Seconds]], roundResult.[[Milliseconds]], roundResult.[[Microseconds]], roundResult.[[Nanoseconds]], roundingIncrement, smallestUnit, roundingMode, relativeTo). - auto adjust_result = TRY(adjust_rounded_duration_days(vm, round_result.years, round_result.months, round_result.weeks, round_result.days, round_result.hours, round_result.minutes, round_result.seconds, round_result.milliseconds, round_result.microseconds, round_result.nanoseconds, rounding_increment, *smallest_unit, rounding_mode, relative_to_value.is_object() ? &relative_to_value.as_object() : nullptr)); - - // 25. Let balanceResult be ? BalanceDurationRelative(adjustResult.[[Years]], adjustResult.[[Months]], adjustResult.[[Weeks]], adjustResult.[[Days]], largestUnit, relativeTo). - auto balance_result = TRY(balance_duration_relative(vm, adjust_result.years, adjust_result.months, adjust_result.weeks, adjust_result.days, *largest_unit, relative_to_value)); - - // 26. If Type(relativeTo) is Object and relativeTo has an [[InitializedTemporalZonedDateTime]] internal slot, then - if (relative_to.zoned_relative_to) { - // a. Set relativeTo to ? MoveRelativeZonedDateTime(relativeTo, balanceResult.[[Years]], balanceResult.[[Months]], balanceResult.[[Weeks]], 0). - relative_to_value = TRY(move_relative_zoned_date_time(vm, *relative_to.zoned_relative_to, balance_result.years, balance_result.months, balance_result.weeks, 0)); - } - - // 27. Let result be ? BalanceDuration(balanceResult.[[Days]], adjustResult.[[Hours]], adjustResult.[[Minutes]], adjustResult.[[Seconds]], adjustResult.[[Milliseconds]], adjustResult.[[Microseconds]], adjustResult.[[Nanoseconds]], largestUnit, relativeTo). - auto result = TRY(balance_duration(vm, balance_result.days, adjust_result.hours, adjust_result.minutes, adjust_result.seconds, adjust_result.milliseconds, adjust_result.microseconds, Crypto::SignedBigInteger { adjust_result.nanoseconds }, *largest_unit, relative_to_value.is_object() ? &relative_to_value.as_object() : nullptr)); - - // 28. Return ! CreateTemporalDuration(balanceResult.[[Years]], balanceResult.[[Months]], balanceResult.[[Weeks]], result.[[Days]], result.[[Hours]], result.[[Minutes]], result.[[Seconds]], result.[[Milliseconds]], result.[[Microseconds]], result.[[Nanoseconds]]). - return MUST(create_temporal_duration(vm, balance_result.years, balance_result.months, balance_result.weeks, result.days, result.hours, result.minutes, result.seconds, result.milliseconds, result.microseconds, result.nanoseconds)); -} - -// 7.3.21 Temporal.Duration.prototype.total ( totalOf ), https://tc39.es/proposal-temporal/#sec-temporal.duration.prototype.total -// FIXME: This is well out of date with the spec. -JS_DEFINE_NATIVE_FUNCTION(DurationPrototype::total) -{ - auto& realm = *vm.current_realm(); - - // 1. Let duration be the this value. - // 2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]). - auto duration = TRY(typed_this_object(vm)); - - // 3. If totalOf is undefined, throw a TypeError exception. - if (vm.argument(0).is_undefined()) - return vm.throw_completion(ErrorType::TemporalMissingOptionsObject); - - Object* total_of; - - // 4. If Type(totalOf) is String, then - if (vm.argument(0).is_string()) { - // a. Let paramString be totalOf. - - // b. Set totalOf to OrdinaryObjectCreate(null). - total_of = Object::create(realm, nullptr); - - // c. Perform ! CreateDataPropertyOrThrow(totalOf, "unit", paramString). - MUST(total_of->create_data_property_or_throw(vm.names.unit, vm.argument(0))); - } - // 5. Else, - else { - // a. Set totalOf to ? GetOptionsObject(totalOf). - total_of = TRY(get_options_object(vm, vm.argument(0))); - } - - // 6. Let relativeTo be ? ToRelativeTemporalObject(totalOf). - auto relative_to = TRY(to_relative_temporal_object(vm, *total_of)); - auto relative_to_value = relative_to_converted_to_value(relative_to); - - // 7. Let unit be ? GetTemporalUnit(totalOf, "unit", datetime, required). - auto unit = TRY(get_temporal_unit(vm, *total_of, vm.names.unit, UnitGroup::DateTime, TemporalUnitRequired {})); - - // 8. Let unbalanceResult be ? UnbalanceDurationRelative(duration.[[Years]], duration.[[Months]], duration.[[Weeks]], duration.[[Days]], unit, relativeTo). - auto unbalance_result = TRY(unbalance_duration_relative(vm, duration->years(), duration->months(), duration->weeks(), duration->days(), *unit, relative_to_value)); - - // 9. Let intermediate be undefined. - ZonedDateTime* intermediate = nullptr; - - // 10. If Type(relativeTo) is Object and relativeTo has an [[InitializedTemporalZonedDateTime]] internal slot, then - if (relative_to.zoned_relative_to) { - // a. Set intermediate to ? MoveRelativeZonedDateTime(relativeTo, unbalanceResult.[[Years]], unbalanceResult.[[Months]], unbalanceResult.[[Weeks]], 0). - intermediate = TRY(move_relative_zoned_date_time(vm, *relative_to.zoned_relative_to, unbalance_result.years, unbalance_result.months, unbalance_result.weeks, 0)); - } - - // 11. Let balanceResult be ? BalanceDuration(unbalanceResult.[[Days]], duration.[[Hours]], duration.[[Minutes]], duration.[[Seconds]], duration.[[Milliseconds]], duration.[[Microseconds]], duration.[[Nanoseconds]], unit, intermediate). - auto balance_result = TRY(balance_duration(vm, unbalance_result.days, duration->hours(), duration->minutes(), duration->seconds(), duration->milliseconds(), duration->microseconds(), Crypto::SignedBigInteger { duration->nanoseconds() }, *unit, intermediate)); - - // 12. Let roundRecord be ? RoundDuration(unbalanceResult.[[Years]], unbalanceResult.[[Months]], unbalanceResult.[[Weeks]], balanceResult.[[Days]], balanceResult.[[Hours]], balanceResult.[[Minutes]], balanceResult.[[Seconds]], balanceResult.[[Milliseconds]], balanceResult.[[Microseconds]], balanceResult.[[Nanoseconds]], 1, unit, "trunc", relativeTo). - auto calendar_record = TRY(create_calendar_methods_record_from_relative_to(vm, relative_to.plain_relative_to, relative_to.zoned_relative_to, { { CalendarMethod::DateAdd, CalendarMethod::DateUntil } })); - - auto round_record = TRY(round_duration(vm, unbalance_result.years, unbalance_result.months, unbalance_result.weeks, balance_result.days, balance_result.hours, balance_result.minutes, balance_result.seconds, balance_result.milliseconds, balance_result.microseconds, balance_result.nanoseconds, 1, *unit, "trunc"sv, relative_to_value.is_object() ? &relative_to_value.as_object() : nullptr, calendar_record)); - - // 13. Return 𝔽(roundRecord.[[Total]]). - return Value(round_record.total); -} - -// 7.3.22 Temporal.Duration.prototype.toString ( [ options ] ), https://tc39.es/proposal-temporal/#sec-temporal.duration.prototype.tostring -JS_DEFINE_NATIVE_FUNCTION(DurationPrototype::to_string) -{ - // 1. Let duration be the this value. - // 2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]). - auto duration = TRY(typed_this_object(vm)); - - // 3. Set options to ? GetOptionsObject(options). - auto const* options = TRY(get_options_object(vm, vm.argument(0))); - - // 4. Let precision be ? ToSecondsStringPrecisionRecord(options). - auto precision = TRY(to_seconds_string_precision_record(vm, *options)); - - // 5. If precision.[[Unit]] is "minute", throw a RangeError exception. - if (precision.unit == "minute"sv) - return vm.throw_completion(ErrorType::OptionIsNotValidValue, "minute"sv, "smallestUnit"sv); - - // 6. Let roundingMode be ? ToTemporalRoundingMode(options, "trunc"). - auto rounding_mode = TRY(to_temporal_rounding_mode(vm, *options, "trunc"sv)); - - // 7. Let result be (? RoundDuration(duration.[[Years]], duration.[[Months]], duration.[[Weeks]], duration.[[Days]], duration.[[Hours]], duration.[[Minutes]], duration.[[Seconds]], duration.[[Milliseconds]], duration.[[Microseconds]], duration.[[Nanoseconds]], precision.[[Increment]], precision.[[Unit]], roundingMode)).[[DurationRecord]]. - auto result = TRY(round_duration(vm, duration->years(), duration->months(), duration->weeks(), duration->days(), duration->hours(), duration->minutes(), duration->seconds(), duration->milliseconds(), duration->microseconds(), duration->nanoseconds(), precision.increment, precision.unit, rounding_mode)).duration_record; - - // 8. Return ! TemporalDurationToString(result.[[Years]], result.[[Months]], result.[[Weeks]], result.[[Days]], result.[[Hours]], result.[[Minutes]], result.[[Seconds]], result.[[Milliseconds]], result.[[Microseconds]], result.[[Nanoseconds]], precision.[[Precision]]). - return PrimitiveString::create(vm, MUST(temporal_duration_to_string(vm, result.years, result.months, result.weeks, result.days, result.hours, result.minutes, result.seconds, result.milliseconds, result.microseconds, result.nanoseconds, precision.precision))); -} - -// 7.3.23 Temporal.Duration.prototype.toJSON ( ), https://tc39.es/proposal-temporal/#sec-temporal.duration.prototype.tojson -JS_DEFINE_NATIVE_FUNCTION(DurationPrototype::to_json) -{ - // 1. Let duration be the this value. - // 2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]). - auto duration = TRY(typed_this_object(vm)); - - // 3. Return ! TemporalDurationToString(duration.[[Years]], duration.[[Months]], duration.[[Weeks]], duration.[[Days]], duration.[[Hours]], duration.[[Minutes]], duration.[[Seconds]], duration.[[Milliseconds]], duration.[[Microseconds]], duration.[[Nanoseconds]], "auto"). - return PrimitiveString::create(vm, MUST(temporal_duration_to_string(vm, duration->years(), duration->months(), duration->weeks(), duration->days(), duration->hours(), duration->minutes(), duration->seconds(), duration->milliseconds(), duration->microseconds(), duration->nanoseconds(), "auto"sv))); -} - -// 7.3.24 Temporal.Duration.prototype.toLocaleString ( [ locales [ , options ] ] ), https://tc39.es/proposal-temporal/#sec-temporal.duration.prototype.tolocalestring -// NOTE: This is the minimum toLocaleString implementation for engines without ECMA-402. -JS_DEFINE_NATIVE_FUNCTION(DurationPrototype::to_locale_string) -{ - // 1. Let duration be the this value. - // 2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]). - auto duration = TRY(typed_this_object(vm)); - - // 3. Return ! TemporalDurationToString(duration.[[Years]], duration.[[Months]], duration.[[Weeks]], duration.[[Days]], duration.[[Hours]], duration.[[Minutes]], duration.[[Seconds]], duration.[[Milliseconds]], duration.[[Microseconds]], duration.[[Nanoseconds]], "auto"). - return PrimitiveString::create(vm, MUST(temporal_duration_to_string(vm, duration->years(), duration->months(), duration->weeks(), duration->days(), duration->hours(), duration->minutes(), duration->seconds(), duration->milliseconds(), duration->microseconds(), duration->nanoseconds(), "auto"sv))); -} - -// 7.3.25 Temporal.Duration.prototype.valueOf ( ), https://tc39.es/proposal-temporal/#sec-temporal.duration.prototype.valueof -JS_DEFINE_NATIVE_FUNCTION(DurationPrototype::value_of) -{ - // 1. Throw a TypeError exception. - return vm.throw_completion(ErrorType::Convert, "Temporal.Duration", "a primitive value"); -} - -} diff --git a/Libraries/LibJS/Runtime/Temporal/DurationPrototype.h b/Libraries/LibJS/Runtime/Temporal/DurationPrototype.h deleted file mode 100644 index 563f243450f..00000000000 --- a/Libraries/LibJS/Runtime/Temporal/DurationPrototype.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2021, Linus Groh - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include -#include - -namespace JS::Temporal { - -class DurationPrototype final : public PrototypeObject { - JS_PROTOTYPE_OBJECT(DurationPrototype, Duration, Temporal.Duration); - GC_DECLARE_ALLOCATOR(DurationPrototype); - -public: - virtual void initialize(Realm&) override; - virtual ~DurationPrototype() override = default; - -private: - explicit DurationPrototype(Realm&); - - JS_DECLARE_NATIVE_FUNCTION(years_getter); - JS_DECLARE_NATIVE_FUNCTION(months_getter); - JS_DECLARE_NATIVE_FUNCTION(weeks_getter); - JS_DECLARE_NATIVE_FUNCTION(days_getter); - JS_DECLARE_NATIVE_FUNCTION(hours_getter); - JS_DECLARE_NATIVE_FUNCTION(minutes_getter); - JS_DECLARE_NATIVE_FUNCTION(seconds_getter); - JS_DECLARE_NATIVE_FUNCTION(milliseconds_getter); - JS_DECLARE_NATIVE_FUNCTION(microseconds_getter); - JS_DECLARE_NATIVE_FUNCTION(nanoseconds_getter); - JS_DECLARE_NATIVE_FUNCTION(sign_getter); - JS_DECLARE_NATIVE_FUNCTION(blank_getter); - JS_DECLARE_NATIVE_FUNCTION(with); - JS_DECLARE_NATIVE_FUNCTION(negated); - JS_DECLARE_NATIVE_FUNCTION(abs); - JS_DECLARE_NATIVE_FUNCTION(add); - JS_DECLARE_NATIVE_FUNCTION(subtract); - JS_DECLARE_NATIVE_FUNCTION(round); - JS_DECLARE_NATIVE_FUNCTION(total); - JS_DECLARE_NATIVE_FUNCTION(to_string); - JS_DECLARE_NATIVE_FUNCTION(to_json); - JS_DECLARE_NATIVE_FUNCTION(to_locale_string); - JS_DECLARE_NATIVE_FUNCTION(value_of); -}; - -} diff --git a/Libraries/LibJS/Runtime/Temporal/ISO8601.cpp b/Libraries/LibJS/Runtime/Temporal/ISO8601.cpp deleted file mode 100644 index b7542bd53c7..00000000000 --- a/Libraries/LibJS/Runtime/Temporal/ISO8601.cpp +++ /dev/null @@ -1,1572 +0,0 @@ -/* - * Copyright (c) 2021-2022, Linus Groh - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include -#include - -namespace JS::Temporal { - -namespace Detail { - -// https://tc39.es/proposal-temporal/#prod-DecimalDigits -bool ISO8601Parser::parse_decimal_digits() -{ - // DecimalDigits[Sep] :: - // DecimalDigit - // DecimalDigits[?Sep] DecimalDigit - // [+Sep] DecimalDigits[+Sep] NumericLiteralSeparator DecimalDigit - // NOTE: Temporal exclusively uses the variant without a separator ([~Sep]) - if (!parse_decimal_digit()) - return false; - while (parse_decimal_digit()) - ; - return true; -} - -// https://tc39.es/proposal-temporal/#prod-DecimalDigit -bool ISO8601Parser::parse_decimal_digit() -{ - // DecimalDigit : one of - // 0 1 2 3 4 5 6 7 8 9 - if (m_state.lexer.next_is(is_ascii_digit)) { - m_state.lexer.consume(); - return true; - } - return false; -} - -// https://tc39.es/proposal-temporal/#prod-NonZeroDigit -bool ISO8601Parser::parse_non_zero_digit() -{ - // NonZeroDigit : one of - // 1 2 3 4 5 6 7 8 9 - if (m_state.lexer.next_is(is_ascii_digit) && !m_state.lexer.next_is('0')) { - m_state.lexer.consume(); - return true; - } - return false; -} - -// https://tc39.es/proposal-temporal/#prod-ASCIISign -bool ISO8601Parser::parse_ascii_sign() -{ - // ASCIISign : one of - // + - - return m_state.lexer.consume_specific('+') - || m_state.lexer.consume_specific('-'); -} - -// https://tc39.es/proposal-temporal/#prod-Sign -bool ISO8601Parser::parse_sign() -{ - // Sign : - // ASCIISign - StateTransaction transaction { *this }; - if (!parse_ascii_sign()) - return false; - m_state.parse_result.sign = transaction.parsed_string_view(); - transaction.commit(); - return true; -} - -// https://tc39.es/proposal-temporal/#prod-UnpaddedHour -bool ISO8601Parser::parse_unpadded_hour() -{ - // UnpaddedHour : - // DecimalDigit - // 1 DecimalDigit - // 20 - // 21 - // 22 - // 23 - StateTransaction transaction { *this }; - auto success = m_state.lexer.consume_specific("20"sv) - || m_state.lexer.consume_specific("21"sv) - || m_state.lexer.consume_specific("22"sv) - || m_state.lexer.consume_specific("23"sv); - if (!success) { - // This could be either of the first two productions. - if (m_state.lexer.consume_specific('1')) - (void)parse_decimal_digit(); - else if (!parse_decimal_digit()) - return false; - } - transaction.commit(); - return true; -} - -// https://tc39.es/proposal-temporal/#prod-Hour -bool ISO8601Parser::parse_hour() -{ - // Hour : - // 0 DecimalDigit - // 1 DecimalDigit - // 20 - // 21 - // 22 - // 23 - StateTransaction transaction { *this }; - if (m_state.lexer.consume_specific('0') || m_state.lexer.consume_specific('1')) { - if (!parse_decimal_digit()) - return false; - } else { - auto success = m_state.lexer.consume_specific("20"sv) - || m_state.lexer.consume_specific("21"sv) - || m_state.lexer.consume_specific("22"sv) - || m_state.lexer.consume_specific("23"sv); - if (!success) - return false; - } - transaction.commit(); - return true; -} - -// https://tc39.es/proposal-temporal/#prod-MinuteSecond -bool ISO8601Parser::parse_minute_second() -{ - // MinuteSecond : - // 0 DecimalDigit - // 1 DecimalDigit - // 2 DecimalDigit - // 3 DecimalDigit - // 4 DecimalDigit - // 5 DecimalDigit - StateTransaction transaction { *this }; - auto success = m_state.lexer.consume_specific('0') - || m_state.lexer.consume_specific('1') - || m_state.lexer.consume_specific('2') - || m_state.lexer.consume_specific('3') - || m_state.lexer.consume_specific('4') - || m_state.lexer.consume_specific('5'); - if (!success) - return false; - if (!parse_decimal_digit()) - return false; - transaction.commit(); - return true; -} - -// https://tc39.es/proposal-temporal/#prod-DecimalSeparator -bool ISO8601Parser::parse_decimal_separator() -{ - // DecimalSeparator : one of - // . , - return m_state.lexer.consume_specific('.') - || m_state.lexer.consume_specific(','); -} - -// https://tc39.es/proposal-temporal/#prod-DaysDesignator -bool ISO8601Parser::parse_days_designator() -{ - // DaysDesignator : one of - // D d - return m_state.lexer.consume_specific('D') - || m_state.lexer.consume_specific('d'); -} - -// https://tc39.es/proposal-temporal/#prod-HoursDesignator -bool ISO8601Parser::parse_hours_designator() -{ - // HoursDesignator : one of - // H h - return m_state.lexer.consume_specific('H') - || m_state.lexer.consume_specific('h'); -} - -// https://tc39.es/proposal-temporal/#prod-MinutesDesignator -bool ISO8601Parser::parse_minutes_designator() -{ - // MinutesDesignator : one of - // M m - return m_state.lexer.consume_specific('M') - || m_state.lexer.consume_specific('m'); -} - -// https://tc39.es/proposal-temporal/#prod-MonthsDesignator -bool ISO8601Parser::parse_months_designator() -{ - // MonthsDesignator : one of - // M m - return m_state.lexer.consume_specific('M') - || m_state.lexer.consume_specific('m'); -} - -// https://tc39.es/proposal-temporal/#prod-DurationDesignator -bool ISO8601Parser::parse_duration_designator() -{ - // DurationDesignator : one of - // P p - return m_state.lexer.consume_specific('P') - || m_state.lexer.consume_specific('p'); -} - -// https://tc39.es/proposal-temporal/#prod-SecondsDesignator -bool ISO8601Parser::parse_seconds_designator() -{ - // SecondsDesignator : one of - // S s - return m_state.lexer.consume_specific('S') - || m_state.lexer.consume_specific('s'); -} - -// https://tc39.es/proposal-temporal/#prod-DateTimeSeparator -bool ISO8601Parser::parse_date_time_separator() -{ - // DateTimeSeparator : - // - // T - // t - return m_state.lexer.consume_specific(' ') - || m_state.lexer.consume_specific('T') - || m_state.lexer.consume_specific('t'); -} - -// https://tc39.es/proposal-temporal/#prod-TimeDesignator -bool ISO8601Parser::parse_time_designator() -{ - // TimeDesignator : one of - // T t - return m_state.lexer.consume_specific('T') - || m_state.lexer.consume_specific('t'); -} - -// https://tc39.es/proposal-temporal/#prod-WeeksDesignator -bool ISO8601Parser::parse_weeks_designator() -{ - // WeeksDesignator : one of - // W w - return m_state.lexer.consume_specific('W') - || m_state.lexer.consume_specific('w'); -} - -// https://tc39.es/proposal-temporal/#prod-YearsDesignator -bool ISO8601Parser::parse_years_designator() -{ - // YearsDesignator : one of - // Y y - return m_state.lexer.consume_specific('Y') - || m_state.lexer.consume_specific('y'); -} - -// https://tc39.es/proposal-temporal/#prod-UTCDesignator -bool ISO8601Parser::parse_utc_designator() -{ - // UTCDesignator : one of - // Z z - StateTransaction transaction { *this }; - auto success = m_state.lexer.consume_specific('Z') - || m_state.lexer.consume_specific('z'); - if (!success) - return false; - m_state.parse_result.utc_designator = transaction.parsed_string_view(); - transaction.commit(); - return true; -} - -// https://tc39.es/proposal-temporal/#prod-AnnotationCriticalFlag -bool ISO8601Parser::parse_annotation_critical_flag() -{ - // AnnotationCriticalFlag : - // ! - return m_state.lexer.consume_specific('!'); -} - -// https://tc39.es/proposal-temporal/#prod-DateYear -bool ISO8601Parser::parse_date_year() -{ - // DateFourDigitYear : - // DecimalDigit DecimalDigit DecimalDigit DecimalDigit - // DateExtendedYear : - // Sign DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit - // DateYear : - // DateFourDigitYear - // DateExtendedYear - StateTransaction transaction { *this }; - if (parse_sign()) { - for (size_t i = 0; i < 6; ++i) { - if (!parse_decimal_digit()) - return false; - } - } else { - for (size_t i = 0; i < 4; ++i) { - if (!parse_decimal_digit()) - return false; - } - } - // It is a Syntax Error if DateExtendedYear is "-000000" or "−000000" (U+2212 MINUS SIGN followed by 000000). - if (transaction.parsed_string_view().is_one_of("-000000"sv, "−000000"sv)) - return false; - m_state.parse_result.date_year = transaction.parsed_string_view(); - transaction.commit(); - return true; -} - -// https://tc39.es/proposal-temporal/#prod-DateMonth -bool ISO8601Parser::parse_date_month() -{ - // DateMonth : - // 0 NonZeroDigit - // 10 - // 11 - // 12 - StateTransaction transaction { *this }; - if (m_state.lexer.consume_specific('0')) { - if (!parse_non_zero_digit()) - return false; - } else { - auto success = m_state.lexer.consume_specific("10"sv) - || m_state.lexer.consume_specific("11"sv) - || m_state.lexer.consume_specific("12"sv); - if (!success) - return false; - } - m_state.parse_result.date_month = transaction.parsed_string_view(); - transaction.commit(); - return true; -} - -// https://tc39.es/proposal-temporal/#prod-DateMonthWithThirtyOneDays -bool ISO8601Parser::parse_date_month_with_thirty_days() -{ - // DateMonthWithThirtyOneDays : one of - // 01 03 05 07 08 10 12 - StateTransaction transaction { *this }; - auto success = m_state.lexer.consume_specific("01"sv) - || m_state.lexer.consume_specific("03"sv) - || m_state.lexer.consume_specific("05"sv) - || m_state.lexer.consume_specific("07"sv) - || m_state.lexer.consume_specific("08"sv) - || m_state.lexer.consume_specific("10"sv) - || m_state.lexer.consume_specific("12"sv); - if (!success) - return false; - transaction.commit(); - return true; -} - -// https://tc39.es/proposal-temporal/#prod-DateDay -bool ISO8601Parser::parse_date_day() -{ - // DateDay : - // 0 NonZeroDigit - // 1 DecimalDigit - // 2 DecimalDigit - // 30 - // 31 - StateTransaction transaction { *this }; - if (m_state.lexer.consume_specific('0')) { - if (!parse_non_zero_digit()) - return false; - } else if (m_state.lexer.consume_specific('1') || m_state.lexer.consume_specific('2')) { - if (!parse_decimal_digit()) - return false; - } else { - auto success = m_state.lexer.consume_specific("30"sv) - || m_state.lexer.consume_specific("31"sv); - if (!success) - return false; - } - m_state.parse_result.date_day = transaction.parsed_string_view(); - transaction.commit(); - return true; -} - -// https://tc39.es/proposal-temporal/#prod-DateSpecYearMonth -bool ISO8601Parser::parse_date_spec_year_month() -{ - // DateSpecYearMonth : - // DateYear -[opt] DateMonth - StateTransaction transaction { *this }; - if (!parse_date_year()) - return false; - m_state.lexer.consume_specific('-'); - if (!parse_date_month()) - return false; - transaction.commit(); - return true; -} - -// https://tc39.es/proposal-temporal/#prod-DateSpecMonthDay -bool ISO8601Parser::parse_date_spec_month_day() -{ - // TwoDashes : - // -- - // DateSpecMonthDay : - // TwoDashes[opt] DateMonth -[opt] DateDay - StateTransaction transaction { *this }; - m_state.lexer.consume_specific("--"sv); - if (!parse_date_month()) - return false; - m_state.lexer.consume_specific('-'); - if (!parse_date_day()) - return false; - transaction.commit(); - return true; -} - -// https://tc39.es/proposal-temporal/#prod-ValidMonthDay -bool ISO8601Parser::parse_valid_month_day() -{ - // ValidMonthDay : - // DateMonth -[opt] 0 NonZeroDigit - // DateMonth -[opt] 1 DecimalDigit - // DateMonth -[opt] 2 DecimalDigit - // DateMonth -[opt] 30 but not one of 0230 or 02-30 - // DateMonthWithThirtyOneDays -[opt] 31 - StateTransaction transaction { *this }; - if (parse_date_month()) { - m_state.lexer.consume_specific('-'); - if (m_state.lexer.consume_specific('0')) { - if (!parse_non_zero_digit()) - return false; - } else if (m_state.lexer.consume_specific('1') || m_state.lexer.consume_specific('2')) { - if (!parse_decimal_digit()) - return false; - } else if (m_state.lexer.consume_specific("30"sv)) { - if (transaction.parsed_string_view().is_one_of("0230"sv, "02-30"sv)) - return false; - } else { - return false; - } - } else if (parse_date_month_with_thirty_days()) { - m_state.lexer.consume_specific('-'); - if (!m_state.lexer.consume_specific("31"sv)) - return false; - } else { - return false; - } - transaction.commit(); - return true; -} - -// https://tc39.es/proposal-temporal/#prod-Date -bool ISO8601Parser::parse_date() -{ - // Date : - // DateYear - DateMonth - DateDay - // DateYear DateMonth DateDay - StateTransaction transaction { *this }; - if (!parse_date_year()) - return false; - auto with_dashes = m_state.lexer.consume_specific('-'); - if (!parse_date_month()) - return false; - if (with_dashes && !m_state.lexer.consume_specific('-')) - return false; - if (!parse_date_day()) - return false; - transaction.commit(); - return true; -} - -// https://tc39.es/proposal-temporal/#prod-TimeHour -bool ISO8601Parser::parse_time_hour() -{ - // TimeHour : - // Hour - StateTransaction transaction { *this }; - if (!parse_hour()) - return false; - m_state.parse_result.time_hour = transaction.parsed_string_view(); - transaction.commit(); - return true; -} - -// https://tc39.es/proposal-temporal/#prod-TimeMinute -bool ISO8601Parser::parse_time_minute() -{ - // TimeMinute : - // MinuteSecond - StateTransaction transaction { *this }; - if (!parse_minute_second()) - return false; - m_state.parse_result.time_minute = transaction.parsed_string_view(); - transaction.commit(); - return true; -} - -// https://tc39.es/proposal-temporal/#prod-TimeSecond -bool ISO8601Parser::parse_time_second() -{ - // TimeSecond : - // MinuteSecond - // 60 - StateTransaction transaction { *this }; - auto success = parse_minute_second() - || m_state.lexer.consume_specific("60"sv); - if (!success) - return false; - m_state.parse_result.time_second = transaction.parsed_string_view(); - transaction.commit(); - return true; -} - -// https://tc39.es/proposal-temporal/#prod-FractionalPart -bool ISO8601Parser::parse_fractional_part() -{ - // FractionalPart : - // DecimalDigit DecimalDigit[opt] DecimalDigit[opt] DecimalDigit[opt] DecimalDigit[opt] DecimalDigit[opt] DecimalDigit[opt] DecimalDigit[opt] DecimalDigit[opt] - if (!parse_decimal_digit()) - return false; - for (size_t i = 0; i < 8; ++i) { - if (!parse_decimal_digit()) - break; - } - return true; -} - -// https://tc39.es/proposal-temporal/#prod-Fraction -bool ISO8601Parser::parse_fraction() -{ - // Fraction : - // DecimalSeparator FractionalPart - StateTransaction transaction { *this }; - if (!parse_decimal_separator()) - return false; - if (!parse_fractional_part()) - return false; - transaction.commit(); - return true; -} - -// https://tc39.es/proposal-temporal/#prod-TimeFraction -bool ISO8601Parser::parse_time_fraction() -{ - // TimeFraction : - // Fraction - StateTransaction transaction { *this }; - if (!parse_fraction()) - return false; - m_state.parse_result.time_fraction = transaction.parsed_string_view(); - transaction.commit(); - return true; -} - -// https://tc39.es/proposal-temporal/#prod-TimeZoneUTCOffsetSign -bool ISO8601Parser::parse_time_zone_utc_offset_sign() -{ - // TimeZoneUTCOffsetSign : - // Sign - StateTransaction transaction { *this }; - if (!parse_sign()) - return false; - m_state.parse_result.time_zone_utc_offset_sign = transaction.parsed_string_view(); - transaction.commit(); - return true; -} - -// https://tc39.es/proposal-temporal/#prod-TimeZoneUTCOffsetHour -bool ISO8601Parser::parse_time_zone_utc_offset_hour() -{ - // TimeZoneUTCOffsetHour : - // Hour - StateTransaction transaction { *this }; - if (!parse_hour()) - return false; - m_state.parse_result.time_zone_utc_offset_hour = transaction.parsed_string_view(); - transaction.commit(); - return true; -} - -// https://tc39.es/proposal-temporal/#prod-TimeZoneUTCOffsetMinute -bool ISO8601Parser::parse_time_zone_utc_offset_minute() -{ - // TimeZoneUTCOffsetMinute : - // MinuteSecond - StateTransaction transaction { *this }; - if (!parse_minute_second()) - return false; - m_state.parse_result.time_zone_utc_offset_minute = transaction.parsed_string_view(); - transaction.commit(); - return true; -} - -// https://tc39.es/proposal-temporal/#prod-TimeZoneUTCOffsetSecond -bool ISO8601Parser::parse_time_zone_utc_offset_second() -{ - // TimeZoneUTCOffsetSecond : - // MinuteSecond - StateTransaction transaction { *this }; - if (!parse_minute_second()) - return false; - m_state.parse_result.time_zone_utc_offset_second = transaction.parsed_string_view(); - transaction.commit(); - return true; -} - -// https://tc39.es/proposal-temporal/#prod-TimeZoneUTCOffsetFractionalPart -bool ISO8601Parser::parse_time_zone_utc_offset_fractional_part() -{ - // TimeZoneUTCOffsetFractionalPart : - // FractionalPart - return parse_fractional_part(); -} - -// https://tc39.es/proposal-temporal/#prod-TimeZoneUTCOffsetFraction -bool ISO8601Parser::parse_time_zone_utc_offset_fraction() -{ - // TimeZoneUTCOffsetFraction : - // DecimalSeparator TimeZoneUTCOffsetFractionalPart - StateTransaction transaction { *this }; - if (!parse_decimal_separator()) - return false; - if (!parse_time_zone_utc_offset_fractional_part()) - return false; - m_state.parse_result.time_zone_utc_offset_fraction = transaction.parsed_string_view(); - transaction.commit(); - return true; -} - -// https://tc39.es/proposal-temporal/#prod-TimeZoneNumericUTCOffset -bool ISO8601Parser::parse_time_zone_numeric_utc_offset() -{ - // TimeZoneNumericUTCOffset : - // TimeZoneUTCOffsetSign TimeZoneUTCOffsetHour - // TimeZoneUTCOffsetSign TimeZoneUTCOffsetHour : TimeZoneUTCOffsetMinute - // TimeZoneUTCOffsetSign TimeZoneUTCOffsetHour TimeZoneUTCOffsetMinute - // TimeZoneUTCOffsetSign TimeZoneUTCOffsetHour : TimeZoneUTCOffsetMinute : TimeZoneUTCOffsetSecond TimeZoneUTCOffsetFraction[opt] - // TimeZoneUTCOffsetSign TimeZoneUTCOffsetHour TimeZoneUTCOffsetMinute TimeZoneUTCOffsetSecond TimeZoneUTCOffsetFraction[opt] - StateTransaction transaction { *this }; - if (!parse_time_zone_utc_offset_sign()) - return false; - if (!parse_time_zone_utc_offset_hour()) - return false; - if (m_state.lexer.consume_specific(':')) { - if (!parse_time_zone_utc_offset_minute()) - return false; - if (m_state.lexer.consume_specific(':')) { - if (!parse_time_zone_utc_offset_second()) - return false; - (void)parse_time_zone_utc_offset_fraction(); - } - } else if (parse_time_zone_utc_offset_minute()) { - if (parse_time_zone_utc_offset_second()) - (void)parse_time_zone_utc_offset_fraction(); - } - m_state.parse_result.time_zone_numeric_utc_offset = transaction.parsed_string_view(); - transaction.commit(); - return true; -} - -// https://tc39.es/proposal-temporal/#prod-TimeZoneUTCOffset -bool ISO8601Parser::parse_time_zone_utc_offset() -{ - // TimeZoneUTCOffset : - // TimeZoneNumericUTCOffset - // UTCDesignator - return parse_time_zone_numeric_utc_offset() - || parse_utc_designator(); -} - -// https://tc39.es/proposal-temporal/#prod-TimeZoneUTCOffsetName -bool ISO8601Parser::parse_time_zone_utc_offset_name() -{ - // TimeZoneUTCOffsetName : - // Sign Hour - // Sign Hour : MinuteSecond - // Sign Hour MinuteSecond - // Sign Hour : MinuteSecond : MinuteSecond Fraction[opt] - // Sign Hour MinuteSecond MinuteSecond Fraction[opt] - StateTransaction transaction { *this }; - if (!parse_sign()) - return false; - if (!parse_hour()) - return false; - if (m_state.lexer.consume_specific(':')) { - if (!parse_minute_second()) - return false; - if (m_state.lexer.consume_specific(':')) { - if (!parse_minute_second()) - return false; - (void)parse_fraction(); - } - } else if (parse_minute_second()) { - if (parse_minute_second()) - (void)parse_fraction(); - } - transaction.commit(); - return true; -} - -// https://tc39.es/proposal-temporal/#prod-TZLeadingChar -bool ISO8601Parser::parse_tz_leading_char() -{ - // TZLeadingChar : - // Alpha - // . - // _ - if (m_state.lexer.next_is(is_ascii_alpha)) { - m_state.lexer.consume(); - return true; - } - return m_state.lexer.consume_specific('.') - || m_state.lexer.consume_specific('_'); -} - -// https://tc39.es/proposal-temporal/#prod-TZChar -bool ISO8601Parser::parse_tz_char() -{ - // TZChar : - // Alpha - // . - // - - // _ - if (m_state.lexer.next_is(is_ascii_alpha)) { - m_state.lexer.consume(); - return true; - } - return m_state.lexer.consume_specific('.') - || m_state.lexer.consume_specific('-') - || m_state.lexer.consume_specific('_'); -} - -// https://tc39.es/proposal-temporal/#prod-TimeZoneIANANameComponent -bool ISO8601Parser::parse_time_zone_iana_component() -{ - // TimeZoneIANANameComponent : - // TZLeadingChar TZChar[opt] TZChar[opt] TZChar[opt] TZChar[opt] TZChar[opt] TZChar[opt] TZChar[opt] TZChar[opt] TZChar[opt] TZChar[opt] TZChar[opt] TZChar[opt] TZChar[opt] but not one of . or .. - StateTransaction transaction { *this }; - if (!parse_tz_leading_char()) - return false; - for (size_t i = 0; i < 13; ++i) { - if (!parse_tz_char()) - break; - } - if (transaction.parsed_string_view().is_one_of("."sv, ".."sv)) - return false; - transaction.commit(); - return true; -} - -// https://tc39.es/proposal-temporal/#prod-TimeZoneIANANameTail -bool ISO8601Parser::parse_time_zone_iana_name_tail() -{ - // TimeZoneIANANameTail : - // TimeZoneIANANameComponent - // TimeZoneIANANameComponent / TimeZoneIANANameTail - StateTransaction transaction { *this }; - if (!parse_time_zone_iana_component()) - return false; - while (m_state.lexer.next_is('/')) { - m_state.lexer.consume(); - if (!parse_time_zone_iana_component()) - return false; - } - transaction.commit(); - return true; -} - -// https://tc39.es/proposal-temporal/#prod-TimeZoneIANALegacyName -bool ISO8601Parser::parse_time_zone_iana_legacy_name() -{ - // TimeZoneIANALegacyName : - // Etc/GMT0 - // GMT0 - // GMT-0 - // GMT+0 - // EST5EDT - // CST6CDT - // MST7MDT - // PST8PDT - return m_state.lexer.consume_specific("Etc/GMT0"sv) - || m_state.lexer.consume_specific("GMT0"sv) - || m_state.lexer.consume_specific("GMT-0"sv) - || m_state.lexer.consume_specific("GMT+0"sv) - || m_state.lexer.consume_specific("EST5EDT"sv) - || m_state.lexer.consume_specific("CST6CDT"sv) - || m_state.lexer.consume_specific("MST7MDT"sv) - || m_state.lexer.consume_specific("PST8PDT"sv); -} - -// https://tc39.es/proposal-temporal/#prod-TimeZoneIANAName -bool ISO8601Parser::parse_time_zone_iana_name() -{ - // TimeZoneIANAName : - // Etc/GMT ASCIISign UnpaddedHour - // TimeZoneIANANameTail - // TimeZoneIANALegacyName - // NOTE: Reverse order here because `TimeZoneIANANameTail` can be a subset of `TimeZoneIANALegacyName`, - // so we'd not attempt to parse that but may not exhaust the input string. - auto parse_etc_gmt_with_offset = [this] { - StateTransaction transaction { *this }; - if (!m_state.lexer.consume_specific("Etc/GMT"sv)) - return false; - if (!parse_ascii_sign()) - return false; - if (!parse_unpadded_hour()) - return false; - transaction.commit(); - return true; - }; - return parse_etc_gmt_with_offset() - || parse_time_zone_iana_legacy_name() - || parse_time_zone_iana_name_tail(); -} - -// https://tc39.es/proposal-temporal/#prod-TimeZoneIdentifier -bool ISO8601Parser::parse_time_zone_identifier() -{ - // TimeZoneIdentifier : - // TimeZoneIANAName - // TimeZoneUTCOffsetName - StateTransaction transaction { *this }; - if (parse_time_zone_iana_name()) { - // no-op. - } else if (!parse_time_zone_utc_offset_name()) { - return false; - } - m_state.parse_result.time_zone_identifier = transaction.parsed_string_view(); - transaction.commit(); - return true; -} - -// https://tc39.es/proposal-temporal/#prod-TimeZoneAnnotation -bool ISO8601Parser::parse_time_zone_annotation() -{ - // TimeZoneAnnotation : - // [ AnnotationCriticalFlag[opt] TimeZoneIdentifier ] - StateTransaction transaction { *this }; - if (!m_state.lexer.consume_specific('[')) - return false; - (void)parse_annotation_critical_flag(); - if (!parse_time_zone_identifier()) - return false; - if (!m_state.lexer.consume_specific(']')) - return false; - m_state.parse_result.time_zone_annotation = transaction.parsed_string_view(); - transaction.commit(); - return true; -} - -// https://tc39.es/proposal-temporal/#prod-AKeyLeadingChar -bool ISO8601Parser::parse_a_key_leading_char() -{ - // AKeyLeadingChar : - // LowercaseAlpha - // _ - if (m_state.lexer.next_is(is_ascii_lower_alpha)) { - m_state.lexer.consume(); - return true; - } - return m_state.lexer.consume_specific('_'); -} - -// https://tc39.es/proposal-temporal/#prod-AKeyChar -bool ISO8601Parser::parse_a_key_char() -{ - // AKeyChar : - // AKeyLeadingChar - // DecimalDigit - // - - if (parse_a_key_leading_char()) - return true; - if (parse_decimal_digit()) - return true; - return m_state.lexer.consume_specific('-'); -} - -// https://tc39.es/proposal-temporal/#prod-AValChar -bool ISO8601Parser::parse_a_val_char() -{ - // AValChar : - // Alpha - // DecimalDigit - if (m_state.lexer.next_is(is_ascii_alpha)) { - m_state.lexer.consume(); - return true; - } - return parse_decimal_digit(); -} - -// https://tc39.es/proposal-temporal/#prod-AnnotationKeyTail -bool ISO8601Parser::parse_annotation_key_tail() -{ - // AnnotationKeyTail : - // AKeyChar AnnotationKeyTail[opt] - if (!parse_a_key_char()) - return false; - // This is implemented without recursion to prevent stack overflow with annotation key tails that have many characters. - while (parse_a_key_char()) - ; - return true; -} - -// https://tc39.es/proposal-temporal/#prod-AnnotationKey -bool ISO8601Parser::parse_annotation_key() -{ - // AnnotationKey : - // AKeyLeadingChar AnnotationKeyTail[opt] - StateTransaction transaction { *this }; - if (!parse_a_key_leading_char()) { - m_state.parse_result.annotation_key = Optional {}; - return false; - } - (void)parse_annotation_key_tail(); - m_state.parse_result.annotation_key = transaction.parsed_string_view(); - transaction.commit(); - return true; -} - -// https://tc39.es/proposal-temporal/#prod-AnnotationValueComponent -bool ISO8601Parser::parse_annotation_value_component() -{ - // AnnotationValueComponent : - // AValChar AnnotationValueComponent[opt] - if (!parse_a_val_char()) - return false; - // This is implemented without recursion to prevent stack overflow with annotation value components that have many characters. - while (parse_a_val_char()) - ; - return true; -} - -// https://tc39.es/proposal-temporal/#prod-AnnotationValueTail -bool ISO8601Parser::parse_annotation_value_tail() -{ - // AnnotationValueTail : - // AnnotationValueComponent - // AnnotationValueComponent - AnnotationValueTail - // This is implemented without recursion to prevent stack overflow with annotation values that have many dashes. - for (;;) { - if (!parse_annotation_value_component()) - return false; - - if (!m_state.lexer.consume_specific('-')) - break; - } - - return true; -} - -// https://tc39.es/proposal-temporal/#prod-AnnotationValue -bool ISO8601Parser::parse_annotation_value() -{ - // AnnotationValue : - // AnnotationValueTail - StateTransaction transaction { *this }; - if (!parse_annotation_value_tail()) { - m_state.parse_result.annotation_value = Optional {}; - return false; - } - m_state.parse_result.annotation_value = transaction.parsed_string_view(); - transaction.commit(); - return true; -} - -// https://tc39.es/proposal-temporal/#prod-Annotation -bool ISO8601Parser::parse_annotation() -{ - // Annotation : - // [ AnnotationCriticalFlag[opt] AnnotationKey = AnnotationValue ] - StateTransaction transaction { *this }; - if (!m_state.lexer.consume_specific('[')) - return false; - - Annotation annotation; - - annotation.critical = parse_annotation_critical_flag(); - - if (!parse_annotation_key()) - return false; - annotation.key = m_state.parse_result.annotation_key.value(); - - if (!m_state.lexer.consume_specific('=')) - return false; - - if (!parse_annotation_value()) - return false; - annotation.value = m_state.parse_result.annotation_value.value(); - - if (!m_state.lexer.consume_specific(']')) - return false; - - m_state.parse_result.annotations.append(annotation); - transaction.commit(); - return true; -} - -// https://tc39.es/proposal-temporal/#prod-Annotations -bool ISO8601Parser::parse_annotations() -{ - // Annotations : - // Annotation Annotations[opt] - if (!parse_annotation()) - return false; - // This is implemented without recursion to prevent stack overflow with ISO strings that have many annotations. - while (parse_annotation()) - ; - return true; -} - -// https://tc39.es/proposal-temporal/#prod-TimeSpec -bool ISO8601Parser::parse_time_spec() -{ - // TimeSpec : - // TimeHour - // TimeHour : TimeMinute - // TimeHour TimeMinute - // TimeHour : TimeMinute : TimeSecond TimeFraction[opt] - // TimeHour TimeMinute TimeSecond TimeFraction[opt] - StateTransaction transaction { *this }; - if (!parse_time_hour()) - return false; - if (m_state.lexer.consume_specific(':')) { - if (!parse_time_minute()) - return false; - if (m_state.lexer.consume_specific(':')) { - if (!parse_time_second()) - return false; - (void)parse_time_fraction(); - } - } else if (parse_time_minute()) { - if (parse_time_second()) - (void)parse_time_fraction(); - } - transaction.commit(); - return true; -} - -// https://tc39.es/proposal-temporal/#prod-TimeSpecWithOptionalOffsetNotAmbiguous -bool ISO8601Parser::parse_time_spec_with_optional_offset_not_ambiguous() -{ - // TimeSpecWithOptionalOffsetNotAmbiguous : - // TimeSpec TimeZoneUTCOffset[opt] but not one of ValidMonthDay or DateSpecYearMonth - { - StateTransaction transaction { *this }; - if (parse_valid_month_day() || parse_date_spec_year_month()) - return false; - } - StateTransaction transaction { *this }; - if (!parse_time_spec()) - return false; - (void)parse_time_zone_utc_offset(); - transaction.commit(); - return true; -} - -// https://tc39.es/proposal-temporal/#prod-DateTime -bool ISO8601Parser::parse_date_time() -{ - // DateTime : - // Date - // Date DateTimeSeparator TimeSpec TimeZoneUTCOffset[opt] - StateTransaction transaction { *this }; - if (!parse_date()) - return false; - if (parse_date_time_separator()) { - if (!parse_time_spec()) - return false; - (void)parse_time_zone_utc_offset(); - } - transaction.commit(); - return true; -} - -// https://tc39.es/proposal-temporal/#prod-AnnotatedTime -bool ISO8601Parser::parse_annotated_time() -{ - // AnnotatedTime : - // TimeDesignator TimeSpec TimeZoneUTCOffset[opt] TimeZoneAnnotation[opt] Annotations[opt] - // TimeSpecWithOptionalOffsetNotAmbiguous TimeZoneAnnotation[opt] Annotations[opt] - { - StateTransaction transaction { *this }; - if (parse_time_designator() && parse_time_spec()) { - (void)parse_time_zone_utc_offset(); - (void)parse_time_zone_annotation(); - (void)parse_annotations(); - transaction.commit(); - return true; - } - } - StateTransaction transaction { *this }; - if (!parse_time_spec_with_optional_offset_not_ambiguous()) - return false; - (void)parse_time_zone_annotation(); - (void)parse_annotations(); - transaction.commit(); - return true; -} - -// https://tc39.es/proposal-temporal/#prod-AnnotatedDateTime -bool ISO8601Parser::parse_annotated_date_time() -{ - // AnnotatedDateTime : - // DateTime TimeZoneAnnotation[opt] Annotations[opt] - if (!parse_date_time()) - return false; - (void)parse_time_zone_annotation(); - (void)parse_annotations(); - return true; -} - -// https://tc39.es/proposal-temporal/#prod-AnnotatedDateTimeTimeRequired -bool ISO8601Parser::parse_annotated_date_time_time_required() -{ - // AnnotatedDateTimeTimeRequired : - // Date DateTimeSeparator TimeSpec TimeZoneUTCOffset[opt] TimeZoneAnnotation[opt] Annotations[opt] - StateTransaction transaction { *this }; - if (!parse_date()) - return false; - if (!parse_date_time_separator()) - return false; - if (!parse_time_spec()) - return false; - (void)parse_time_zone_utc_offset(); - (void)parse_time_zone_annotation(); - (void)parse_annotations(); - transaction.commit(); - return true; -} - -// https://tc39.es/proposal-temporal/#prod-AnnotatedYearMonth -bool ISO8601Parser::parse_annotated_year_month() -{ - // AnnotatedYearMonth : - // DateSpecYearMonth TimeZoneAnnotation[opt] Annotations[opt] - if (!parse_date_spec_year_month()) - return false; - (void)parse_time_zone_annotation(); - (void)parse_annotations(); - return true; -} - -// https://tc39.es/proposal-temporal/#prod-AnnotatedMonthDay -bool ISO8601Parser::parse_annotated_month_day() -{ - // AnnotatedMonthDay : - // DateSpecMonthDay TimeZoneAnnotation[opt] Annotations[opt] - if (!parse_date_spec_month_day()) - return false; - (void)parse_time_zone_annotation(); - (void)parse_annotations(); - return true; -} - -// https://tc39.es/proposal-temporal/#prod-DurationWholeSeconds -bool ISO8601Parser::parse_duration_whole_seconds() -{ - // DurationWholeSeconds : - // DecimalDigits[~Sep] - StateTransaction transaction { *this }; - if (!parse_decimal_digits()) - return false; - m_state.parse_result.duration_whole_seconds = transaction.parsed_string_view(); - transaction.commit(); - return true; -} - -// https://tc39.es/proposal-temporal/#prod-DurationSecondsFraction -bool ISO8601Parser::parse_duration_seconds_fraction() -{ - // DurationSecondsFraction : - // TimeFraction - StateTransaction transaction { *this }; - if (!parse_time_fraction()) - return false; - m_state.parse_result.duration_seconds_fraction = transaction.parsed_string_view(); - transaction.commit(); - return true; -} - -// https://tc39.es/proposal-temporal/#prod-DurationSecondsPart -bool ISO8601Parser::parse_duration_seconds_part() -{ - // DurationSecondsPart : - // DurationWholeSeconds DurationSecondsFraction[opt] SecondsDesignator - StateTransaction transaction { *this }; - if (!parse_duration_whole_seconds()) - return false; - (void)parse_duration_seconds_fraction(); - if (!parse_seconds_designator()) - return false; - transaction.commit(); - return true; -} - -// https://tc39.es/proposal-temporal/#prod-DurationWholeMinutes -bool ISO8601Parser::parse_duration_whole_minutes() -{ - // DurationWholeMinutes : - // DecimalDigits[~Sep] - StateTransaction transaction { *this }; - if (!parse_decimal_digits()) - return false; - m_state.parse_result.duration_whole_minutes = transaction.parsed_string_view(); - transaction.commit(); - return true; -} - -// https://tc39.es/proposal-temporal/#prod-DurationMinutesFraction -bool ISO8601Parser::parse_duration_minutes_fraction() -{ - // DurationMinutesFraction : - // TimeFraction - StateTransaction transaction { *this }; - if (!parse_time_fraction()) - return false; - m_state.parse_result.duration_minutes_fraction = transaction.parsed_string_view(); - transaction.commit(); - return true; -} - -// https://tc39.es/proposal-temporal/#prod-DurationMinutesPart -bool ISO8601Parser::parse_duration_minutes_part() -{ - // DurationMinutesPart : - // DurationWholeMinutes DurationMinutesFraction[opt] MinutesDesignator DurationSecondsPart[opt] - StateTransaction transaction { *this }; - if (!parse_duration_whole_minutes()) - return false; - (void)parse_duration_minutes_fraction(); - if (!parse_minutes_designator()) - return false; - (void)parse_duration_seconds_part(); - transaction.commit(); - return true; -} - -// https://tc39.es/proposal-temporal/#prod-DurationWholeHours -bool ISO8601Parser::parse_duration_whole_hours() -{ - // DurationWholeHours : - // DecimalDigits[~Sep] - StateTransaction transaction { *this }; - if (!parse_decimal_digits()) - return false; - m_state.parse_result.duration_whole_hours = transaction.parsed_string_view(); - transaction.commit(); - return true; -} - -// https://tc39.es/proposal-temporal/#prod-DurationHoursFraction -bool ISO8601Parser::parse_duration_hours_fraction() -{ - // DurationHoursFraction : - // TimeFraction - StateTransaction transaction { *this }; - if (!parse_time_fraction()) - return false; - m_state.parse_result.duration_hours_fraction = transaction.parsed_string_view(); - transaction.commit(); - return true; -} - -// https://tc39.es/proposal-temporal/#prod-DurationHoursPart -bool ISO8601Parser::parse_duration_hours_part() -{ - // DurationHoursPart : - // DurationWholeHours DurationHoursFraction[opt] HoursDesignator DurationMinutesPart - // DurationWholeHours DurationHoursFraction[opt] HoursDesignator DurationSecondsPart[opt] - StateTransaction transaction { *this }; - if (!parse_duration_whole_hours()) - return false; - (void)parse_duration_hours_fraction(); - if (!parse_hours_designator()) - return false; - (void)(parse_duration_minutes_part() - || parse_duration_seconds_part()); - transaction.commit(); - return true; -} - -// https://tc39.es/proposal-temporal/#prod-DurationTime -bool ISO8601Parser::parse_duration_time() -{ - // DurationTime : - // TimeDesignator DurationHoursPart - // TimeDesignator DurationMinutesPart - // TimeDesignator DurationSecondsPart - StateTransaction transaction { *this }; - if (!parse_time_designator()) - return false; - auto success = parse_duration_hours_part() - || parse_duration_minutes_part() - || parse_duration_seconds_part(); - if (!success) - return false; - transaction.commit(); - return true; -} - -// https://tc39.es/proposal-temporal/#prod-DurationDays -bool ISO8601Parser::parse_duration_days() -{ - // DurationDays : - // DecimalDigits[~Sep] - StateTransaction transaction { *this }; - if (!parse_decimal_digits()) - return false; - m_state.parse_result.duration_days = transaction.parsed_string_view(); - transaction.commit(); - return true; -} - -// https://tc39.es/proposal-temporal/#prod-DurationDaysPart -bool ISO8601Parser::parse_duration_days_part() -{ - // DurationDaysPart : - // DurationDays DaysDesignator - StateTransaction transaction { *this }; - if (!parse_duration_days()) - return false; - if (!parse_days_designator()) - return false; - transaction.commit(); - return true; -} - -// https://tc39.es/proposal-temporal/#prod-DurationWeeks -bool ISO8601Parser::parse_duration_weeks() -{ - // DurationWeeks : - // DecimalDigits[~Sep] - StateTransaction transaction { *this }; - if (!parse_decimal_digits()) - return false; - m_state.parse_result.duration_weeks = transaction.parsed_string_view(); - transaction.commit(); - return true; -} - -// https://tc39.es/proposal-temporal/#prod-DurationWeeksPart -bool ISO8601Parser::parse_duration_weeks_part() -{ - // DurationWeeksPart : - // DurationWeeks WeeksDesignator DurationDaysPart[opt] - StateTransaction transaction { *this }; - if (!parse_duration_weeks()) - return false; - if (!parse_weeks_designator()) - return false; - (void)parse_duration_days_part(); - transaction.commit(); - return true; -} - -// https://tc39.es/proposal-temporal/#prod-DurationMonths -bool ISO8601Parser::parse_duration_months() -{ - // DurationMonths : - // DecimalDigits[~Sep] - StateTransaction transaction { *this }; - if (!parse_decimal_digits()) - return false; - m_state.parse_result.duration_months = transaction.parsed_string_view(); - transaction.commit(); - return true; -} - -// https://tc39.es/proposal-temporal/#prod-DurationMonthsPart -bool ISO8601Parser::parse_duration_months_part() -{ - // DurationMonthsPart : - // DurationMonths MonthsDesignator DurationWeeksPart - // DurationMonths MonthsDesignator DurationDaysPart[opt] - StateTransaction transaction { *this }; - if (!parse_duration_months()) - return false; - if (!parse_months_designator()) - return false; - (void)(parse_duration_weeks_part() - || parse_duration_days_part()); - transaction.commit(); - return true; -} - -// https://tc39.es/proposal-temporal/#prod-DurationYears -bool ISO8601Parser::parse_duration_years() -{ - // DurationYears : - // DecimalDigits[~Sep] - StateTransaction transaction { *this }; - if (!parse_decimal_digits()) - return false; - m_state.parse_result.duration_years = transaction.parsed_string_view(); - transaction.commit(); - return true; -} - -// https://tc39.es/proposal-temporal/#prod-DurationYearsPart -bool ISO8601Parser::parse_duration_years_part() -{ - // DurationYearsPart : - // DurationYears YearsDesignator DurationMonthsPart - // DurationYears YearsDesignator DurationWeeksPart - // DurationYears YearsDesignator DurationDaysPart[opt] - StateTransaction transaction { *this }; - if (!parse_duration_years()) - return false; - if (!parse_years_designator()) - return false; - (void)(parse_duration_months_part() - || parse_duration_weeks_part() - || parse_duration_days_part()); - transaction.commit(); - return true; -} - -// https://tc39.es/proposal-temporal/#prod-DurationDate -bool ISO8601Parser::parse_duration_date() -{ - // DurationDate : - // DurationYearsPart DurationTime[opt] - // DurationMonthsPart DurationTime[opt] - // DurationWeeksPart DurationTime[opt] - // DurationDaysPart DurationTime[opt] - auto success = parse_duration_years_part() - || parse_duration_months_part() - || parse_duration_weeks_part() - || parse_duration_days_part(); - if (!success) - return false; - (void)parse_duration_time(); - return true; -} - -// https://tc39.es/proposal-temporal/#prod-Duration -bool ISO8601Parser::parse_duration() -{ - // Duration : - // Sign[opt] DurationDesignator DurationDate - // Sign[opt] DurationDesignator DurationTime - StateTransaction transaction { *this }; - (void)parse_sign(); - if (!parse_duration_designator()) - return false; - auto success = parse_duration_date() - || parse_duration_time(); - if (!success) - return false; - transaction.commit(); - return true; -} - -// https://tc39.es/proposal-temporal/#prod-TemporalInstantString -bool ISO8601Parser::parse_temporal_instant_string() -{ - // TemporalInstantString : - // Date DateTimeSeparator TimeSpec TimeZoneUTCOffset TimeZoneAnnotation[opt] Annotations[opt] - StateTransaction transaction { *this }; - if (!parse_date()) - return false; - if (!parse_date_time_separator()) - return false; - if (!parse_time_spec()) - return false; - if (!parse_time_zone_utc_offset()) - return false; - (void)parse_time_zone_annotation(); - (void)parse_annotations(); - transaction.commit(); - return true; -} - -// https://tc39.es/proposal-temporal/#prod-TemporalDateTimeString -bool ISO8601Parser::parse_temporal_date_time_string() -{ - // TemporalDateTimeString : - // AnnotatedDateTime - return parse_annotated_date_time(); -} - -// https://tc39.es/proposal-temporal/#prod-TemporalDurationString -bool ISO8601Parser::parse_temporal_duration_string() -{ - // TemporalDurationString : - // Duration - return parse_duration(); -} - -// https://tc39.es/proposal-temporal/#prod-TemporalMonthDayString -bool ISO8601Parser::parse_temporal_month_day_string() -{ - // TemporalMonthDayString : - // AnnotatedMonthDay - // AnnotatedDateTime - // NOTE: Reverse order here because `AnnotatedMonthDay` can be a subset of `AnnotatedDateTime`, - // so we'd not attempt to parse that but may not exhaust the input string. - return parse_annotated_date_time() - || parse_annotated_month_day(); -} - -// https://tc39.es/proposal-temporal/#prod-TemporalTimeString -bool ISO8601Parser::parse_temporal_time_string() -{ - // TemporalTimeString : - // AnnotatedTime - // AnnotatedDateTimeTimeRequired - // NOTE: Reverse order here because `AnnotatedTime` can be a subset of `AnnotatedDateTimeTimeRequired`, - // so we'd not attempt to parse that but may not exhaust the input string. - return parse_annotated_date_time_time_required() - || parse_annotated_time(); -} - -// https://tc39.es/proposal-temporal/#prod-TemporalYearMonthString -bool ISO8601Parser::parse_temporal_year_month_string() -{ - // TemporalYearMonthString : - // AnnotatedYearMonth - // AnnotatedDateTime - // NOTE: Reverse order here because `AnnotatedYearMonth` can be a subset of `AnnotatedDateTime`, - // so we'd not attempt to parse that but may not exhaust the input string. - return parse_annotated_date_time() - || parse_annotated_year_month(); -} - -// https://tc39.es/proposal-temporal/#prod-TemporalZonedDateTimeString -bool ISO8601Parser::parse_temporal_zoned_date_time_string() -{ - // TemporalZonedDateTimeString : - // DateTime TimeZoneAnnotation Annotations[opt] - StateTransaction transaction { *this }; - if (!parse_date_time()) - return false; - if (!parse_time_zone_annotation()) - return false; - (void)parse_annotations(); - transaction.commit(); - return true; -} - -} - -#define JS_ENUMERATE_ISO8601_PRODUCTION_PARSERS \ - __JS_ENUMERATE(TemporalInstantString, parse_temporal_instant_string) \ - __JS_ENUMERATE(TemporalDateTimeString, parse_temporal_date_time_string) \ - __JS_ENUMERATE(TemporalDurationString, parse_temporal_duration_string) \ - __JS_ENUMERATE(TemporalMonthDayString, parse_temporal_month_day_string) \ - __JS_ENUMERATE(TemporalTimeString, parse_temporal_time_string) \ - __JS_ENUMERATE(TemporalYearMonthString, parse_temporal_year_month_string) \ - __JS_ENUMERATE(TemporalZonedDateTimeString, parse_temporal_zoned_date_time_string) \ - __JS_ENUMERATE(TimeZoneIdentifier, parse_time_zone_identifier) \ - __JS_ENUMERATE(TimeZoneNumericUTCOffset, parse_time_zone_numeric_utc_offset) \ - __JS_ENUMERATE(AnnotationValue, parse_annotation_value) \ - __JS_ENUMERATE(DateMonth, parse_date_month) - -Optional parse_iso8601(Production production, StringView input) -{ - auto parser = Detail::ISO8601Parser { input }; - - switch (production) { -#define __JS_ENUMERATE(ProductionName, parse_production) \ - case Production::ProductionName: \ - if (!parser.parse_production()) \ - return {}; \ - break; - JS_ENUMERATE_ISO8601_PRODUCTION_PARSERS -#undef __JS_ENUMERATE - default: - VERIFY_NOT_REACHED(); - } - - // If we parsed successfully but didn't reach the end, the string doesn't match the given production. - if (!parser.lexer().is_eof()) - return {}; - - return parser.parse_result(); -} - -} diff --git a/Libraries/LibJS/Runtime/Temporal/ISO8601.h b/Libraries/LibJS/Runtime/Temporal/ISO8601.h deleted file mode 100644 index c9ea96d8115..00000000000 --- a/Libraries/LibJS/Runtime/Temporal/ISO8601.h +++ /dev/null @@ -1,225 +0,0 @@ -/* - * Copyright (c) 2021-2022, Linus Groh - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include -#include -#include -#include - -namespace JS::Temporal { - -struct Annotation { - bool critical { false }; - StringView key; - StringView value; -}; - -struct ParseResult { - Optional sign; - Optional date_year; - Optional date_month; - Optional date_day; - Optional time_hour; - Optional time_minute; - Optional time_second; - Optional time_fraction; - Optional utc_designator; - Optional time_zone_annotation; - Optional time_zone_numeric_utc_offset; - Optional time_zone_utc_offset_sign; - Optional time_zone_utc_offset_hour; - Optional time_zone_utc_offset_minute; - Optional time_zone_utc_offset_second; - Optional time_zone_utc_offset_fraction; - Optional time_zone_identifier; - Optional duration_years; - Optional duration_months; - Optional duration_weeks; - Optional duration_days; - Optional duration_whole_hours; - Optional duration_hours_fraction; - Optional duration_whole_minutes; - Optional duration_minutes_fraction; - Optional duration_whole_seconds; - Optional duration_seconds_fraction; - Optional annotation_key; - Optional annotation_value; - Vector annotations; -}; - -enum class Production { - TemporalInstantString, - TemporalDateTimeString, - TemporalDurationString, - TemporalMonthDayString, - TemporalTimeString, - TemporalYearMonthString, - TemporalZonedDateTimeString, - TimeZoneIdentifier, - TimeZoneNumericUTCOffset, - AnnotationValue, - DateMonth, -}; - -Optional parse_iso8601(Production, StringView); - -namespace Detail { - -// 13.33 ISO 8601 grammar, https://tc39.es/proposal-temporal/#sec-temporal-iso8601grammar -class ISO8601Parser { -public: - explicit ISO8601Parser(StringView input) - : m_input(input) - , m_state({ - .lexer = GenericLexer { input }, - .parse_result = {}, - }) - { - } - - [[nodiscard]] GenericLexer const& lexer() const { return m_state.lexer; } - [[nodiscard]] ParseResult const& parse_result() const { return m_state.parse_result; } - - [[nodiscard]] bool parse_decimal_digits(); - [[nodiscard]] bool parse_decimal_digit(); - [[nodiscard]] bool parse_non_zero_digit(); - [[nodiscard]] bool parse_ascii_sign(); - [[nodiscard]] bool parse_sign(); - [[nodiscard]] bool parse_unpadded_hour(); - [[nodiscard]] bool parse_hour(); - [[nodiscard]] bool parse_minute_second(); - [[nodiscard]] bool parse_decimal_separator(); - [[nodiscard]] bool parse_days_designator(); - [[nodiscard]] bool parse_hours_designator(); - [[nodiscard]] bool parse_minutes_designator(); - [[nodiscard]] bool parse_months_designator(); - [[nodiscard]] bool parse_duration_designator(); - [[nodiscard]] bool parse_seconds_designator(); - [[nodiscard]] bool parse_date_time_separator(); - [[nodiscard]] bool parse_time_designator(); - [[nodiscard]] bool parse_weeks_designator(); - [[nodiscard]] bool parse_years_designator(); - [[nodiscard]] bool parse_utc_designator(); - [[nodiscard]] bool parse_annotation_critical_flag(); - [[nodiscard]] bool parse_date_year(); - [[nodiscard]] bool parse_date_month(); - [[nodiscard]] bool parse_date_month_with_thirty_days(); - [[nodiscard]] bool parse_date_day(); - [[nodiscard]] bool parse_date_spec_year_month(); - [[nodiscard]] bool parse_date_spec_month_day(); - [[nodiscard]] bool parse_valid_month_day(); - [[nodiscard]] bool parse_date(); - [[nodiscard]] bool parse_time_hour(); - [[nodiscard]] bool parse_time_minute(); - [[nodiscard]] bool parse_time_second(); - [[nodiscard]] bool parse_fractional_part(); - [[nodiscard]] bool parse_fraction(); - [[nodiscard]] bool parse_time_fraction(); - [[nodiscard]] bool parse_time_zone_utc_offset_sign(); - [[nodiscard]] bool parse_time_zone_utc_offset_hour(); - [[nodiscard]] bool parse_time_zone_utc_offset_minute(); - [[nodiscard]] bool parse_time_zone_utc_offset_second(); - [[nodiscard]] bool parse_time_zone_utc_offset_fractional_part(); - [[nodiscard]] bool parse_time_zone_utc_offset_fraction(); - [[nodiscard]] bool parse_time_zone_numeric_utc_offset(); - [[nodiscard]] bool parse_time_zone_utc_offset(); - [[nodiscard]] bool parse_time_zone_utc_offset_name(); - [[nodiscard]] bool parse_tz_leading_char(); - [[nodiscard]] bool parse_tz_char(); - [[nodiscard]] bool parse_time_zone_iana_component(); - [[nodiscard]] bool parse_time_zone_iana_name_tail(); - [[nodiscard]] bool parse_time_zone_iana_legacy_name(); - [[nodiscard]] bool parse_time_zone_iana_name(); - [[nodiscard]] bool parse_time_zone_identifier(); - [[nodiscard]] bool parse_time_zone_annotation(); - [[nodiscard]] bool parse_a_key_leading_char(); - [[nodiscard]] bool parse_a_key_char(); - [[nodiscard]] bool parse_a_val_char(); - [[nodiscard]] bool parse_annotation_key_tail(); - [[nodiscard]] bool parse_annotation_key(); - [[nodiscard]] bool parse_annotation_value_component(); - [[nodiscard]] bool parse_annotation_value_tail(); - [[nodiscard]] bool parse_annotation_value(); - [[nodiscard]] bool parse_annotation(); - [[nodiscard]] bool parse_annotations(); - [[nodiscard]] bool parse_time_spec(); - [[nodiscard]] bool parse_time_spec_with_optional_offset_not_ambiguous(); - [[nodiscard]] bool parse_date_time(); - [[nodiscard]] bool parse_annotated_time(); - [[nodiscard]] bool parse_annotated_date_time(); - [[nodiscard]] bool parse_annotated_date_time_time_required(); - [[nodiscard]] bool parse_annotated_year_month(); - [[nodiscard]] bool parse_annotated_month_day(); - [[nodiscard]] bool parse_duration_whole_seconds(); - [[nodiscard]] bool parse_duration_seconds_fraction(); - [[nodiscard]] bool parse_duration_seconds_part(); - [[nodiscard]] bool parse_duration_whole_minutes(); - [[nodiscard]] bool parse_duration_minutes_fraction(); - [[nodiscard]] bool parse_duration_minutes_part(); - [[nodiscard]] bool parse_duration_whole_hours(); - [[nodiscard]] bool parse_duration_hours_fraction(); - [[nodiscard]] bool parse_duration_hours_part(); - [[nodiscard]] bool parse_duration_time(); - [[nodiscard]] bool parse_duration_days(); - [[nodiscard]] bool parse_duration_days_part(); - [[nodiscard]] bool parse_duration_weeks(); - [[nodiscard]] bool parse_duration_weeks_part(); - [[nodiscard]] bool parse_duration_months(); - [[nodiscard]] bool parse_duration_months_part(); - [[nodiscard]] bool parse_duration_years(); - [[nodiscard]] bool parse_duration_years_part(); - [[nodiscard]] bool parse_duration_date(); - [[nodiscard]] bool parse_duration(); - [[nodiscard]] bool parse_temporal_instant_string(); - [[nodiscard]] bool parse_temporal_date_time_string(); - [[nodiscard]] bool parse_temporal_duration_string(); - [[nodiscard]] bool parse_temporal_month_day_string(); - [[nodiscard]] bool parse_temporal_time_string(); - [[nodiscard]] bool parse_temporal_year_month_string(); - [[nodiscard]] bool parse_temporal_zoned_date_time_string(); - -private: - struct State { - GenericLexer lexer; - ParseResult parse_result; - }; - - struct StateTransaction { - explicit StateTransaction(ISO8601Parser& parser) - : m_parser(parser) - , m_saved_state(parser.m_state) - , m_start_index(parser.m_state.lexer.tell()) - { - } - - ~StateTransaction() - { - if (!m_commit) - m_parser.m_state = move(m_saved_state); - } - - void commit() { m_commit = true; } - StringView parsed_string_view() const - { - return m_parser.m_input.substring_view(m_start_index, m_parser.m_state.lexer.tell() - m_start_index); - } - - private: - ISO8601Parser& m_parser; - State m_saved_state; - size_t m_start_index { 0 }; - bool m_commit { false }; - }; - - StringView m_input; - State m_state; -}; - -} - -} diff --git a/Libraries/LibJS/Runtime/Temporal/Instant.cpp b/Libraries/LibJS/Runtime/Temporal/Instant.cpp deleted file mode 100644 index bb87f2e436a..00000000000 --- a/Libraries/LibJS/Runtime/Temporal/Instant.cpp +++ /dev/null @@ -1,370 +0,0 @@ -/* - * Copyright (c) 2021-2023, Linus Groh - * Copyright (c) 2021, Idan Horowitz - * Copyright (c) 2023, Shannon Booth - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace JS::Temporal { - -GC_DEFINE_ALLOCATOR(Instant); - -// 8 Temporal.Instant Objects, https://tc39.es/proposal-temporal/#sec-temporal-instant-objects -Instant::Instant(BigInt const& nanoseconds, Object& prototype) - : Object(ConstructWithPrototypeTag::Tag, prototype) - , m_nanoseconds(nanoseconds) -{ -} - -void Instant::visit_edges(Cell::Visitor& visitor) -{ - Base::visit_edges(visitor); - - visitor.visit(m_nanoseconds); -} - -// 8.5.1 IsValidEpochNanoseconds ( epochNanoseconds ), https://tc39.es/proposal-temporal/#sec-temporal-isvalidepochnanoseconds -bool is_valid_epoch_nanoseconds(BigInt const& epoch_nanoseconds) -{ - return is_valid_epoch_nanoseconds(epoch_nanoseconds.big_integer()); -} - -// 8.5.1 IsValidEpochNanoseconds ( epochNanoseconds ), https://tc39.es/proposal-temporal/#sec-temporal-isvalidepochnanoseconds -bool is_valid_epoch_nanoseconds(Crypto::SignedBigInteger const& epoch_nanoseconds) -{ - // 1. Assert: Type(epochNanoseconds) is BigInt. - - // 2. If ℝ(epochNanoseconds) < nsMinInstant or ℝ(epochNanoseconds) > nsMaxInstant, then - if (epoch_nanoseconds < ns_min_instant || epoch_nanoseconds > ns_max_instant) { - // a. Return false. - return false; - } - - // 3. Return true. - return true; -} - -// 8.5.2 CreateTemporalInstant ( epochNanoseconds [ , newTarget ] ), https://tc39.es/proposal-temporal/#sec-temporal-createtemporalinstant -ThrowCompletionOr create_temporal_instant(VM& vm, BigInt const& epoch_nanoseconds, FunctionObject const* new_target) -{ - auto& realm = *vm.current_realm(); - - // 1. Assert: Type(epochNanoseconds) is BigInt. - - // 2. Assert: ! IsValidEpochNanoseconds(epochNanoseconds) is true. - VERIFY(is_valid_epoch_nanoseconds(epoch_nanoseconds)); - - // 3. If newTarget is not present, set newTarget to %Temporal.Instant%. - if (!new_target) - new_target = realm.intrinsics().temporal_instant_constructor(); - - // 4. Let object be ? OrdinaryCreateFromConstructor(newTarget, "%Temporal.Instant.prototype%", « [[InitializedTemporalInstant]], [[Nanoseconds]] »). - // 5. Set object.[[Nanoseconds]] to epochNanoseconds. - auto object = TRY(ordinary_create_from_constructor(vm, *new_target, &Intrinsics::temporal_instant_prototype, epoch_nanoseconds)); - - // 6. Return object. - return object.ptr(); -} - -// 8.5.3 ToTemporalInstant ( item ), https://tc39.es/proposal-temporal/#sec-temporal-totemporalinstant -ThrowCompletionOr to_temporal_instant(VM& vm, Value item) -{ - // 1. If Type(item) is Object, then - if (item.is_object()) { - // a. If item has an [[InitializedTemporalInstant]] internal slot, then - if (is(item.as_object())) { - // i. Return item. - return &static_cast(item.as_object()); - } - - // b. If item has an [[InitializedTemporalZonedDateTime]] internal slot, then - if (is(item.as_object())) { - auto& zoned_date_time = static_cast(item.as_object()); - - // i. Return ! CreateTemporalInstant(item.[[Nanoseconds]]). - return create_temporal_instant(vm, zoned_date_time.nanoseconds()); - } - } - - // 2. Let string be ? ToString(item). - auto string = TRY(item.to_string(vm)); - - // 3. Let epochNanoseconds be ? ParseTemporalInstant(string). - auto* epoch_nanoseconds = TRY(parse_temporal_instant(vm, string)); - - // 4. Return ! CreateTemporalInstant(ℤ(epochNanoseconds)). - return create_temporal_instant(vm, *epoch_nanoseconds); -} - -// 8.5.4 ParseTemporalInstant ( isoString ), https://tc39.es/proposal-temporal/#sec-temporal-parsetemporalinstant -ThrowCompletionOr parse_temporal_instant(VM& vm, StringView iso_string) -{ - // 1. Assert: Type(isoString) is String. - - // 2. Let result be ? ParseTemporalInstantString(isoString). - auto result = TRY(parse_temporal_instant_string(vm, iso_string)); - - // 3. Let offsetString be result.[[TimeZoneOffsetString]]. - auto& offset_string = result.time_zone_offset; - - // 4. Assert: offsetString is not undefined. - VERIFY(offset_string.has_value()); - - // 5. Let utc be GetUTCEpochNanoseconds(result.[[Year]], result.[[Month]], result.[[Day]], result.[[Hour]], result.[[Minute]], result.[[Second]], result.[[Millisecond]], result.[[Microsecond]], result.[[Nanosecond]]). - auto utc = get_utc_epoch_nanoseconds(result.year, result.month, result.day, result.hour, result.minute, result.second, result.millisecond, result.microsecond, result.nanosecond); - - // 6. If IsTimeZoneOffsetString(offsetString) is false, throw a RangeError exception. - if (!is_time_zone_offset_string(*offset_string)) - return vm.throw_completion(ErrorType::TemporalInvalidTimeZoneName, *offset_string); - - // 7. Let offsetNanoseconds be ParseTimeZoneOffsetString(offsetString). - auto offset_nanoseconds = parse_time_zone_offset_string(*offset_string); - - // 7. Let result be utc - ℤ(offsetNanoseconds). - auto result_ns = utc.minus(Crypto::SignedBigInteger { offset_nanoseconds }); - - // 8. If ! IsValidEpochNanoseconds(result) is false, then - if (!is_valid_epoch_nanoseconds(result_ns)) { - // a. Throw a RangeError exception. - return vm.throw_completion(ErrorType::TemporalInvalidEpochNanoseconds); - } - - // 9. Return result. - return BigInt::create(vm, move(result_ns)).ptr(); -} - -// 8.5.5 CompareEpochNanoseconds ( epochNanosecondsOne, epochNanosecondsTwo ), https://tc39.es/proposal-temporal/#sec-temporal-compareepochnanoseconds -i32 compare_epoch_nanoseconds(BigInt const& epoch_nanoseconds_one, BigInt const& epoch_nanoseconds_two) -{ - // 1. If epochNanosecondsOne > epochNanosecondsTwo, return 1. - if (epoch_nanoseconds_one.big_integer() > epoch_nanoseconds_two.big_integer()) - return 1; - - // 2. If epochNanosecondsOne < epochNanosecondsTwo, return -1. - if (epoch_nanoseconds_one.big_integer() < epoch_nanoseconds_two.big_integer()) - return -1; - - // 3. Return 0. - return 0; -} - -// 8.5.6 AddInstant ( epochNanoseconds, hours, minutes, seconds, milliseconds, microseconds, nanoseconds ), https://tc39.es/proposal-temporal/#sec-temporal-addinstant -ThrowCompletionOr add_instant(VM& vm, BigInt const& epoch_nanoseconds, double hours, double minutes, double seconds, double milliseconds, double microseconds, double nanoseconds) -{ - VERIFY(hours == trunc(hours) && minutes == trunc(minutes) && seconds == trunc(seconds) && milliseconds == trunc(milliseconds) && microseconds == trunc(microseconds) && nanoseconds == trunc(nanoseconds)); - - // 1. Let result be epochNanoseconds + ℤ(nanoseconds) + ℤ(microseconds) × 1000ℤ + ℤ(milliseconds) × 10^6ℤ + ℤ(seconds) × 10^9ℤ + ℤ(minutes) × 60ℤ × 10^9ℤ + ℤ(hours) × 3600ℤ × 10^9ℤ. - auto result = BigInt::create(vm, - epoch_nanoseconds.big_integer() - .plus(Crypto::SignedBigInteger { nanoseconds }) - .plus(Crypto::SignedBigInteger { microseconds }.multiplied_by(Crypto::SignedBigInteger { 1'000 })) - .plus(Crypto::SignedBigInteger { milliseconds }.multiplied_by(Crypto::SignedBigInteger { 1'000'000 })) - .plus(Crypto::SignedBigInteger { seconds }.multiplied_by(Crypto::SignedBigInteger { 1'000'000'000 })) - .plus(Crypto::SignedBigInteger { minutes }.multiplied_by(Crypto::SignedBigInteger { 60 }).multiplied_by(Crypto::SignedBigInteger { 1'000'000'000 })) - .plus(Crypto::SignedBigInteger { hours }.multiplied_by(Crypto::SignedBigInteger { 3600 }).multiplied_by(Crypto::SignedBigInteger { 1'000'000'000 }))); - - // 2. If ! IsValidEpochNanoseconds(result) is false, throw a RangeError exception. - if (!is_valid_epoch_nanoseconds(*result)) - return vm.throw_completion(ErrorType::TemporalInvalidEpochNanoseconds); - - // 3. Return result. - return result.ptr(); -} - -// 8.5.6 DifferenceInstant ( ns1, ns2, roundingIncrement, smallestUnit, largestUnit, roundingMode ), https://tc39.es/proposal-temporal/#sec-temporal-differenceinstant -TimeDurationRecord difference_instant(VM& vm, BigInt const& nanoseconds1, BigInt const& nanoseconds2, u64 rounding_increment, StringView smallest_unit, StringView largest_unit, StringView rounding_mode) -{ - static Crypto::UnsignedBigInteger const BIGINT_ONE_THOUSAND { 1'000 }; - - // 1. Let difference be ℝ(ns2) - ℝ(ns1). - auto difference = nanoseconds2.big_integer().minus(nanoseconds1.big_integer()); - - // 2. Let nanoseconds be remainder(difference, 1000). - auto nanoseconds = remainder(difference, BIGINT_ONE_THOUSAND); - - // 3. Let microseconds be remainder(truncate(difference / 1000), 1000). - auto microseconds = remainder(difference.divided_by(BIGINT_ONE_THOUSAND).quotient, BIGINT_ONE_THOUSAND); - - // 4. Let milliseconds be remainder(truncate(difference / 10^6), 1000). - auto milliseconds = remainder(difference.divided_by(Crypto::UnsignedBigInteger { 1'000'000 }).quotient, BIGINT_ONE_THOUSAND); - - // 5. Let seconds be truncate(difference / 10^9). - auto seconds = difference.divided_by(Crypto::UnsignedBigInteger { 1'000'000'000 }).quotient; - - // 6. If smallestUnit is "nanosecond" and roundingIncrement is 1, then - if (smallest_unit == "nanosecond"sv && rounding_increment == 1) { - // a. Return ! BalanceTimeDuration(0, 0, 0, seconds, milliseconds, microseconds, nanoseconds, largestUnit). - return MUST(balance_time_duration(vm, 0, 0, 0, seconds.to_double(), milliseconds.to_double(), microseconds.to_double(), nanoseconds, largest_unit)); - } - - // 7. Let roundResult be ! RoundDuration(0, 0, 0, 0, 0, 0, seconds, milliseconds, microseconds, nanoseconds, roundingIncrement, smallestUnit, roundingMode). - auto round_result = MUST(round_duration(vm, 0, 0, 0, 0, 0, 0, seconds.to_double(), milliseconds.to_double(), microseconds.to_double(), nanoseconds.to_double(), rounding_increment, smallest_unit, rounding_mode)).duration_record; - - // 8. Assert: roundResult.[[Days]] is 0. - VERIFY(round_result.days == 0); - - // 9. Return ! BalanceTimeDuration(0, roundResult.[[Hours]], roundResult.[[Minutes]], roundResult.[[Seconds]], roundResult.[[Milliseconds]], roundResult.[[Microseconds]], roundResult.[[Nanoseconds]], largestUnit). - return MUST(balance_time_duration(vm, 0, round_result.hours, round_result.minutes, round_result.seconds, round_result.milliseconds, round_result.microseconds, Crypto::SignedBigInteger { round_result.nanoseconds }, largest_unit)); -} - -// 8.5.8 RoundTemporalInstant ( ns, increment, unit, roundingMode ), https://tc39.es/proposal-temporal/#sec-temporal-roundtemporalinstant -BigInt* round_temporal_instant(VM& vm, BigInt const& nanoseconds, u64 increment, StringView unit, StringView rounding_mode) -{ - // 1. Assert: Type(ns) is BigInt. - - u64 increment_nanoseconds; - // 2. If unit is "hour", then - if (unit == "hour"sv) { - // a. Let incrementNs be increment × 3.6 × 10^12. - increment_nanoseconds = increment * 3600000000000; - } - // 3. Else if unit is "minute", then - else if (unit == "minute"sv) { - // a. Let incrementNs be increment × 6 × 10^10. - increment_nanoseconds = increment * 60000000000; - } - // 4. Else if unit is "second", then - else if (unit == "second"sv) { - // a. Let incrementNs be increment × 10^9. - increment_nanoseconds = increment * 1000000000; - } - // 5. Else if unit is "millisecond", then - else if (unit == "millisecond"sv) { - // a. Let incrementNs be increment × 10^6. - increment_nanoseconds = increment * 1000000; - } - // 6. Else if unit is "microsecond", then - else if (unit == "microsecond"sv) { - // a. Let incrementNs be increment × 10^3. - increment_nanoseconds = increment * 1000; - } - // 7. Else, - else { - // a. Assert: unit is "nanosecond". - VERIFY(unit == "nanosecond"sv); - - // b. Let incrementNs be increment. - increment_nanoseconds = increment; - } - - // 8. Return RoundNumberToIncrementAsIfPositive(ℝ(ns), incrementNs, roundingMode). - return BigInt::create(vm, round_number_to_increment_as_if_positive(nanoseconds.big_integer(), increment_nanoseconds, rounding_mode)); -} - -// 8.5.9 TemporalInstantToString ( instant, timeZone, precision ), https://tc39.es/proposal-temporal/#sec-temporal-temporalinstanttostring -ThrowCompletionOr temporal_instant_to_string(VM& vm, Instant& instant, Value time_zone, Variant const& precision) -{ - // 1. Assert: Type(instant) is Object. - // 2. Assert: instant has an [[InitializedTemporalInstant]] internal slot. - - // 3. Let outputTimeZone be timeZone. - auto output_time_zone = time_zone; - - // 4. If outputTimeZone is undefined, then - if (output_time_zone.is_undefined()) { - // a. Set outputTimeZone to ! CreateTemporalTimeZone("UTC"). - output_time_zone = MUST_OR_THROW_OOM(create_temporal_time_zone(vm, "UTC"_string)); - } - - // 5. Let isoCalendar be ! GetISO8601Calendar(). - auto* iso_calendar = get_iso8601_calendar(vm); - - // 6. Let dateTime be ? BuiltinTimeZoneGetPlainDateTimeFor(outputTimeZone, instant, isoCalendar). - auto* date_time = TRY(builtin_time_zone_get_plain_date_time_for(vm, output_time_zone, instant, *iso_calendar)); - - // 7. Let dateTimeString be ! TemporalDateTimeToString(dateTime.[[ISOYear]], dateTime.[[ISOMonth]], dateTime.[[ISODay]], dateTime.[[ISOHour]], dateTime.[[ISOMinute]], dateTime.[[ISOSecond]], dateTime.[[ISOMillisecond]], dateTime.[[ISOMicrosecond]], dateTime.[[ISONanosecond]], undefined, precision, "never"). - auto date_time_string = MUST_OR_THROW_OOM(temporal_date_time_to_string(vm, date_time->iso_year(), date_time->iso_month(), date_time->iso_day(), date_time->iso_hour(), date_time->iso_minute(), date_time->iso_second(), date_time->iso_millisecond(), date_time->iso_microsecond(), date_time->iso_nanosecond(), nullptr, precision, "never"sv)); - - String time_zone_string; - - // 8. If timeZone is undefined, then - if (time_zone.is_undefined()) { - // a. Let timeZoneString be "Z". - time_zone_string = "Z"_string; - } - // 9. Else, - else { - auto time_zone_record = TRY(create_time_zone_methods_record(vm, GC::Ref { time_zone.as_object() }, { { TimeZoneMethod::GetOffsetNanosecondsFor } })); - - // a. Let offsetNs be ? GetOffsetNanosecondsFor(timeZone, instant). - auto offset_ns = TRY(get_offset_nanoseconds_for(vm, time_zone_record, instant)); - - // b. Let timeZoneString be ! FormatISOTimeZoneOffsetString(offsetNs). - time_zone_string = MUST_OR_THROW_OOM(format_iso_time_zone_offset_string(vm, offset_ns)); - } - - // 10. Return the string-concatenation of dateTimeString and timeZoneString. - return TRY_OR_THROW_OOM(vm, String::formatted("{}{}", date_time_string, time_zone_string)); -} - -// 8.5.9 DifferenceTemporalInstant ( operation, instant, other, options ), https://tc39.es/proposal-temporal/#sec-temporal-differencetemporalinstant -ThrowCompletionOr> difference_temporal_instant(VM& vm, DifferenceOperation operation, Instant const& instant, Value other_value, Value options) -{ - // 1. If operation is since, let sign be -1. Otherwise, let sign be 1. - i8 sign = operation == DifferenceOperation::Since ? -1 : 1; - - // 2. Set other to ? ToTemporalInstant(other). - auto* other = TRY(to_temporal_instant(vm, other_value)); - - // 3. Let resolvedOptions be ? SnapshotOwnProperties(? GetOptionsObject(options), null). - auto resolved_options = TRY(TRY(get_options_object(vm, options))->snapshot_own_properties(vm, nullptr)); - - // 4. Let settings be ? GetDifferenceSettings(operation, resolvedOptions, time, « », "nanosecond", "second"). - auto settings = TRY(get_difference_settings(vm, operation, resolved_options, UnitGroup::Time, {}, { "nanosecond"sv }, "second"sv)); - - // 5. Let result be DifferenceInstant(instant.[[Nanoseconds]], other.[[Nanoseconds]], settings.[[RoundingIncrement]], settings.[[SmallestUnit]], settings.[[LargestUnit]], settings.[[RoundingMode]]). - auto result = difference_instant(vm, instant.nanoseconds(), other->nanoseconds(), settings.rounding_increment, settings.smallest_unit, settings.largest_unit, settings.rounding_mode); - - // 6. Return ! CreateTemporalDuration(0, 0, 0, 0, sign × result.[[Hours]], sign × result.[[Minutes]], sign × result.[[Seconds]], sign × result.[[Milliseconds]], sign × result.[[Microseconds]], sign × result.[[Nanoseconds]]). - return MUST(create_temporal_duration(vm, 0, 0, 0, 0, sign * result.hours, sign * result.minutes, sign * result.seconds, sign * result.milliseconds, sign * result.microseconds, sign * result.nanoseconds)); -} - -// 8.5.11 AddDurationToOrSubtractDurationFromInstant ( operation, instant, temporalDurationLike ), https://tc39.es/proposal-temporal/#sec-temporal-adddurationtoorsubtractdurationfrominstant -ThrowCompletionOr add_duration_to_or_subtract_duration_from_instant(VM& vm, ArithmeticOperation operation, Instant const& instant, Value temporal_duration_like) -{ - // 1. If operation is subtract, let sign be -1. Otherwise, let sign be 1. - i8 sign = operation == ArithmeticOperation::Subtract ? -1 : 1; - - // 2. Let duration be ? ToTemporalDurationRecord(temporalDurationLike). - auto duration = TRY(to_temporal_duration_record(vm, temporal_duration_like)); - - // 3. If duration.[[Days]] is not 0, throw a RangeError exception. - if (duration.days != 0) - return vm.throw_completion(ErrorType::TemporalInvalidDurationPropertyValueNonZero, "days", duration.days); - - // 4. If duration.[[Months]] is not 0, throw a RangeError exception. - if (duration.months != 0) - return vm.throw_completion(ErrorType::TemporalInvalidDurationPropertyValueNonZero, "months", duration.months); - - // 5. If duration.[[Weeks]] is not 0, throw a RangeError exception. - if (duration.weeks != 0) - return vm.throw_completion(ErrorType::TemporalInvalidDurationPropertyValueNonZero, "weeks", duration.weeks); - - // 6. If duration.[[Years]] is not 0, throw a RangeError exception. - if (duration.years != 0) - return vm.throw_completion(ErrorType::TemporalInvalidDurationPropertyValueNonZero, "years", duration.years); - - // 7. Let ns be ? AddInstant(instant.[[Nanoseconds]], sign × duration.[[Hours]], sign × duration.[[Minutes]], sign × duration.[[Seconds]], sign × duration.[[Milliseconds]], sign × duration.[[Microseconds]], sign × duration.[[Nanoseconds]]). - auto* ns = TRY(add_instant(vm, instant.nanoseconds(), sign * duration.hours, sign * duration.minutes, sign * duration.seconds, sign * duration.milliseconds, sign * duration.microseconds, sign * duration.nanoseconds)); - - // 8. Return ! CreateTemporalInstant(ns). - return MUST(create_temporal_instant(vm, *ns)); -} - -} diff --git a/Libraries/LibJS/Runtime/Temporal/Instant.h b/Libraries/LibJS/Runtime/Temporal/Instant.h deleted file mode 100644 index ec5c124d3e3..00000000000 --- a/Libraries/LibJS/Runtime/Temporal/Instant.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2021-2023, Linus Groh - * Copyright (c) 2021, Idan Horowitz - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include -#include -#include -#include -#include -#include - -namespace JS::Temporal { - -class Instant final : public Object { - JS_OBJECT(Instant, Object); - GC_DECLARE_ALLOCATOR(Instant); - -public: - virtual ~Instant() override = default; - - [[nodiscard]] BigInt const& nanoseconds() const { return m_nanoseconds; } - -private: - Instant(BigInt const& nanoseconds, Object& prototype); - - virtual void visit_edges(Visitor&) override; - - // 8.4 Properties of Temporal.Instant Instances, https://tc39.es/proposal-temporal/#sec-properties-of-temporal-instant-instances - GC::Ref m_nanoseconds; // [[Nanoseconds]] -}; - -// https://tc39.es/proposal-temporal/#eqn-nsMaxInstant -// nsMaxInstant = 10^8 × nsPerDay = 8.64 × 10^21 -static auto const ns_max_instant = "8640000000000000000000"_sbigint; - -// https://tc39.es/proposal-temporal/#eqn-nsMinInstant -// nsMinInstant = -nsMaxInstant = -8.64 × 10^21 -static auto const ns_min_instant = "-8640000000000000000000"_sbigint; - -bool is_valid_epoch_nanoseconds(BigInt const& epoch_nanoseconds); -bool is_valid_epoch_nanoseconds(Crypto::SignedBigInteger const& epoch_nanoseconds); -ThrowCompletionOr create_temporal_instant(VM&, BigInt const& nanoseconds, FunctionObject const* new_target = nullptr); -ThrowCompletionOr to_temporal_instant(VM&, Value item); -ThrowCompletionOr parse_temporal_instant(VM&, StringView iso_string); -i32 compare_epoch_nanoseconds(BigInt const&, BigInt const&); -ThrowCompletionOr add_instant(VM&, BigInt const& epoch_nanoseconds, double hours, double minutes, double seconds, double milliseconds, double microseconds, double nanoseconds); -TimeDurationRecord difference_instant(VM&, BigInt const& nanoseconds1, BigInt const& nanoseconds2, u64 rounding_increment, StringView smallest_unit, StringView largest_unit, StringView rounding_mode); -BigInt* round_temporal_instant(VM&, BigInt const& nanoseconds, u64 increment, StringView unit, StringView rounding_mode); -ThrowCompletionOr temporal_instant_to_string(VM&, Instant&, Value time_zone, Variant const& precision); -ThrowCompletionOr> difference_temporal_instant(VM&, DifferenceOperation, Instant const&, Value other, Value options); -ThrowCompletionOr add_duration_to_or_subtract_duration_from_instant(VM&, ArithmeticOperation, Instant const&, Value temporal_duration_like); - -} diff --git a/Libraries/LibJS/Runtime/Temporal/InstantConstructor.cpp b/Libraries/LibJS/Runtime/Temporal/InstantConstructor.cpp deleted file mode 100644 index c425581b14f..00000000000 --- a/Libraries/LibJS/Runtime/Temporal/InstantConstructor.cpp +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Copyright (c) 2021-2023, Linus Groh - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include -#include -#include -#include -#include -#include - -namespace JS::Temporal { - -GC_DEFINE_ALLOCATOR(InstantConstructor); - -// 8.1 The Temporal.Instant Constructor, https://tc39.es/proposal-temporal/#sec-temporal-instant-constructor -InstantConstructor::InstantConstructor(Realm& realm) - : NativeFunction(realm.vm().names.Instant.as_string(), realm.intrinsics().function_prototype()) -{ -} - -void InstantConstructor::initialize(Realm& realm) -{ - Base::initialize(realm); - - auto& vm = this->vm(); - - // 8.2.1 Temporal.Instant.prototype, https://tc39.es/proposal-temporal/#sec-temporal.instant.prototype - define_direct_property(vm.names.prototype, realm.intrinsics().temporal_instant_prototype(), 0); - - u8 attr = Attribute::Writable | Attribute::Configurable; - define_native_function(realm, vm.names.from, from, 1, attr); - define_native_function(realm, vm.names.fromEpochSeconds, from_epoch_seconds, 1, attr); - define_native_function(realm, vm.names.fromEpochMilliseconds, from_epoch_milliseconds, 1, attr); - define_native_function(realm, vm.names.fromEpochMicroseconds, from_epoch_microseconds, 1, attr); - define_native_function(realm, vm.names.fromEpochNanoseconds, from_epoch_nanoseconds, 1, attr); - define_native_function(realm, vm.names.compare, compare, 2, attr); - - define_direct_property(vm.names.length, Value(1), Attribute::Configurable); -} - -// 8.1.1 Temporal.Instant ( epochNanoseconds ), https://tc39.es/proposal-temporal/#sec-temporal.instant -ThrowCompletionOr InstantConstructor::call() -{ - auto& vm = this->vm(); - - // 1. If NewTarget is undefined, then - // a. Throw a TypeError exception. - return vm.throw_completion(ErrorType::ConstructorWithoutNew, "Temporal.Instant"); -} - -// 8.1.1 Temporal.Instant ( epochNanoseconds ), https://tc39.es/proposal-temporal/#sec-temporal.instant -ThrowCompletionOr> InstantConstructor::construct(FunctionObject& new_target) -{ - auto& vm = this->vm(); - - // 2. Let epochNanoseconds be ? ToBigInt(epochNanoseconds). - auto epoch_nanoseconds = TRY(vm.argument(0).to_bigint(vm)); - - // 3. If ! IsValidEpochNanoseconds(epochNanoseconds) is false, throw a RangeError exception. - if (!is_valid_epoch_nanoseconds(epoch_nanoseconds)) - return vm.throw_completion(ErrorType::TemporalInvalidEpochNanoseconds); - - // 4. Return ? CreateTemporalInstant(epochNanoseconds, NewTarget). - return *TRY(create_temporal_instant(vm, epoch_nanoseconds, &new_target)); -} - -// 8.2.2 Temporal.Instant.from ( item ), https://tc39.es/proposal-temporal/#sec-temporal.instant.from -JS_DEFINE_NATIVE_FUNCTION(InstantConstructor::from) -{ - auto item = vm.argument(0); - - // 1. If Type(item) is Object and item has an [[InitializedTemporalInstant]] internal slot, then - if (item.is_object() && is(item.as_object())) { - // a. Return ! CreateTemporalInstant(item.[[Nanoseconds]]). - return MUST(create_temporal_instant(vm, BigInt::create(vm, static_cast(item.as_object()).nanoseconds().big_integer()))); - } - - // 2. Return ? ToTemporalInstant(item). - return TRY(to_temporal_instant(vm, item)); -} - -// 8.2.3 Temporal.Instant.fromEpochSeconds ( epochSeconds ), https://tc39.es/proposal-temporal/#sec-temporal.instant.fromepochseconds -JS_DEFINE_NATIVE_FUNCTION(InstantConstructor::from_epoch_seconds) -{ - // 1. Set epochSeconds to ? ToNumber(epochSeconds). - auto epoch_seconds_value = TRY(vm.argument(0).to_number(vm)); - - // 2. Set epochSeconds to ? NumberToBigInt(epochSeconds). - auto* epoch_seconds = TRY(number_to_bigint(vm, epoch_seconds_value)); - - // 3. Let epochNanoseconds be epochSeconds × 10^9ℤ. - auto epoch_nanoseconds = BigInt::create(vm, epoch_seconds->big_integer().multiplied_by(Crypto::UnsignedBigInteger { 1'000'000'000 })); - - // 4. If ! IsValidEpochNanoseconds(epochNanoseconds) is false, throw a RangeError exception. - if (!is_valid_epoch_nanoseconds(epoch_nanoseconds)) - return vm.throw_completion(ErrorType::TemporalInvalidEpochNanoseconds); - - // 5. Return ! CreateTemporalInstant(epochNanoseconds). - return MUST(create_temporal_instant(vm, epoch_nanoseconds)); -} - -// 8.2.4 Temporal.Instant.fromEpochMilliseconds ( epochMilliseconds ), https://tc39.es/proposal-temporal/#sec-temporal.instant.fromepochmilliseconds -JS_DEFINE_NATIVE_FUNCTION(InstantConstructor::from_epoch_milliseconds) -{ - // 1. Set epochMilliseconds to ? ToNumber(epochMilliseconds). - auto epoch_milliseconds_value = TRY(vm.argument(0).to_number(vm)); - - // 2. Set epochMilliseconds to ? NumberToBigInt(epochMilliseconds). - auto* epoch_milliseconds = TRY(number_to_bigint(vm, epoch_milliseconds_value)); - - // 3. Let epochNanoseconds be epochMilliseconds × 10^6ℤ. - auto epoch_nanoseconds = BigInt::create(vm, epoch_milliseconds->big_integer().multiplied_by(Crypto::UnsignedBigInteger { 1'000'000 })); - - // 4. If ! IsValidEpochNanoseconds(epochNanoseconds) is false, throw a RangeError exception. - if (!is_valid_epoch_nanoseconds(epoch_nanoseconds)) - return vm.throw_completion(ErrorType::TemporalInvalidEpochNanoseconds); - - // 5. Return ! CreateTemporalInstant(epochNanoseconds). - return MUST(create_temporal_instant(vm, epoch_nanoseconds)); -} - -// 8.2.5 Temporal.Instant.fromEpochMicroseconds ( epochMicroseconds ), https://tc39.es/proposal-temporal/#sec-temporal.instant.fromepochmicroseconds -JS_DEFINE_NATIVE_FUNCTION(InstantConstructor::from_epoch_microseconds) -{ - // 1. Set epochMicroseconds to ? ToBigInt(epochMicroseconds). - auto epoch_microseconds = TRY(vm.argument(0).to_bigint(vm)); - - // 2. Let epochNanoseconds be epochMicroseconds × 1000ℤ. - auto epoch_nanoseconds = BigInt::create(vm, epoch_microseconds->big_integer().multiplied_by(Crypto::UnsignedBigInteger { 1'000 })); - - // 3. If ! IsValidEpochNanoseconds(epochNanoseconds) is false, throw a RangeError exception. - if (!is_valid_epoch_nanoseconds(epoch_nanoseconds)) - return vm.throw_completion(ErrorType::TemporalInvalidEpochNanoseconds); - - // 4. Return ! CreateTemporalInstant(epochNanoseconds). - return MUST(create_temporal_instant(vm, epoch_nanoseconds)); -} - -// 8.2.6 Temporal.Instant.fromEpochNanoseconds ( epochNanoseconds ), https://tc39.es/proposal-temporal/#sec-temporal.instant.fromepochnanoseconds -JS_DEFINE_NATIVE_FUNCTION(InstantConstructor::from_epoch_nanoseconds) -{ - // 1. Set epochNanoseconds to ? ToBigInt(epochNanoseconds). - auto epoch_nanoseconds = TRY(vm.argument(0).to_bigint(vm)); - - // 2. If ! IsValidEpochNanoseconds(epochNanoseconds) is false, throw a RangeError exception. - if (!is_valid_epoch_nanoseconds(epoch_nanoseconds)) - return vm.throw_completion(ErrorType::TemporalInvalidEpochNanoseconds); - - // 3. Return ! CreateTemporalInstant(epochNanoseconds). - return MUST(create_temporal_instant(vm, epoch_nanoseconds)); -} - -// 8.2.7 Temporal.Instant.compare ( one, two ), https://tc39.es/proposal-temporal/#sec-temporal.instant.compare -JS_DEFINE_NATIVE_FUNCTION(InstantConstructor::compare) -{ - // 1. Set one to ? ToTemporalInstant(one). - auto* one = TRY(to_temporal_instant(vm, vm.argument(0))); - - // 2. Set two to ? ToTemporalInstant(two). - auto* two = TRY(to_temporal_instant(vm, vm.argument(1))); - - // 3. Return 𝔽(! CompareEpochNanoseconds(one.[[Nanoseconds]], two.[[Nanoseconds]])). - return Value(compare_epoch_nanoseconds(one->nanoseconds(), two->nanoseconds())); -} - -} diff --git a/Libraries/LibJS/Runtime/Temporal/InstantConstructor.h b/Libraries/LibJS/Runtime/Temporal/InstantConstructor.h deleted file mode 100644 index b2e9626c48e..00000000000 --- a/Libraries/LibJS/Runtime/Temporal/InstantConstructor.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2021-2022, Linus Groh - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include - -namespace JS::Temporal { - -class InstantConstructor final : public NativeFunction { - JS_OBJECT(InstantConstructor, NativeFunction); - GC_DECLARE_ALLOCATOR(InstantConstructor); - -public: - virtual void initialize(Realm&) override; - virtual ~InstantConstructor() override = default; - - virtual ThrowCompletionOr call() override; - virtual ThrowCompletionOr> construct(FunctionObject& new_target) override; - -private: - explicit InstantConstructor(Realm&); - - virtual bool has_constructor() const override { return true; } - - JS_DECLARE_NATIVE_FUNCTION(from); - 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); - JS_DECLARE_NATIVE_FUNCTION(compare); -}; - -} diff --git a/Libraries/LibJS/Runtime/Temporal/InstantPrototype.cpp b/Libraries/LibJS/Runtime/Temporal/InstantPrototype.cpp deleted file mode 100644 index 98746709ad5..00000000000 --- a/Libraries/LibJS/Runtime/Temporal/InstantPrototype.cpp +++ /dev/null @@ -1,413 +0,0 @@ -/* - * Copyright (c) 2021-2023, Linus Groh - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace JS::Temporal { - -GC_DEFINE_ALLOCATOR(InstantPrototype); - -// 8.3 Properties of the Temporal.Instant Prototype Object, https://tc39.es/proposal-temporal/#sec-properties-of-the-temporal-instant-prototype-object -InstantPrototype::InstantPrototype(Realm& realm) - : PrototypeObject(realm.intrinsics().object_prototype()) -{ -} - -void InstantPrototype::initialize(Realm& realm) -{ - Base::initialize(realm); - - auto& vm = this->vm(); - - // 8.3.2 Temporal.Instant.prototype[ @@toStringTag ], https://tc39.es/proposal-temporal/#sec-temporal.instant.prototype-@@tostringtag - define_direct_property(vm.well_known_symbol_to_string_tag(), PrimitiveString::create(vm, "Temporal.Instant"_string), Attribute::Configurable); - - define_native_accessor(realm, vm.names.epochSeconds, epoch_seconds_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.epochMilliseconds, epoch_milliseconds_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.epochMicroseconds, epoch_microseconds_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.epochNanoseconds, epoch_nanoseconds_getter, {}, Attribute::Configurable); - - u8 attr = Attribute::Writable | Attribute::Configurable; - define_native_function(realm, vm.names.add, add, 1, attr); - define_native_function(realm, vm.names.subtract, subtract, 1, attr); - define_native_function(realm, vm.names.until, until, 1, attr); - define_native_function(realm, vm.names.since, since, 1, attr); - define_native_function(realm, vm.names.round, round, 1, attr); - define_native_function(realm, vm.names.equals, equals, 1, attr); - define_native_function(realm, vm.names.toString, to_string, 0, attr); - define_native_function(realm, vm.names.toLocaleString, to_locale_string, 0, attr); - define_native_function(realm, vm.names.toJSON, to_json, 0, attr); - define_native_function(realm, vm.names.valueOf, value_of, 0, attr); - define_native_function(realm, vm.names.toZonedDateTime, to_zoned_date_time, 1, attr); - define_native_function(realm, vm.names.toZonedDateTimeISO, to_zoned_date_time_iso, 1, attr); -} - -// 8.3.3 get Temporal.Instant.prototype.epochSeconds, https://tc39.es/proposal-temporal/#sec-get-temporal.instant.prototype.epochseconds -JS_DEFINE_NATIVE_FUNCTION(InstantPrototype::epoch_seconds_getter) -{ - // 1. Let instant be the this value. - // 2. Perform ? RequireInternalSlot(instant, [[InitializedTemporalInstant]]). - auto instant = TRY(typed_this_object(vm)); - - // 3. Let ns be instant.[[Nanoseconds]]. - auto& ns = instant->nanoseconds(); - - // 4. Let s be truncate(ℝ(ns) / 10^9). - auto [s, _] = ns.big_integer().divided_by(Crypto::UnsignedBigInteger { 1'000'000'000 }); - - // 5. Return 𝔽(s). - return Value((double)s.to_base_deprecated(10).to_number().value()); -} - -// 8.3.4 get Temporal.Instant.prototype.epochMilliseconds, https://tc39.es/proposal-temporal/#sec-get-temporal.instant.prototype.epochmilliseconds -JS_DEFINE_NATIVE_FUNCTION(InstantPrototype::epoch_milliseconds_getter) -{ - // 1. Let instant be the this value. - // 2. Perform ? RequireInternalSlot(instant, [[InitializedTemporalInstant]]). - auto instant = TRY(typed_this_object(vm)); - - // 3. Let ns be instant.[[Nanoseconds]]. - auto& ns = instant->nanoseconds(); - - // 4. Let ms be truncate(ℝ(ns) / 10^6). - auto [ms, _] = ns.big_integer().divided_by(Crypto::UnsignedBigInteger { 1'000'000 }); - - // 5. Return 𝔽(ms). - return Value((double)ms.to_base_deprecated(10).to_number().value()); -} - -// 8.3.5 get Temporal.Instant.prototype.epochMicroseconds, https://tc39.es/proposal-temporal/#sec-get-temporal.instant.prototype.epochmicroseconds -JS_DEFINE_NATIVE_FUNCTION(InstantPrototype::epoch_microseconds_getter) -{ - // 1. Let instant be the this value. - // 2. Perform ? RequireInternalSlot(instant, [[InitializedTemporalInstant]]). - auto instant = TRY(typed_this_object(vm)); - - // 3. Let ns be instant.[[Nanoseconds]]. - auto& ns = instant->nanoseconds(); - - // 4. Let µs be truncate(ℝ(ns) / 10^3). - auto [us, _] = ns.big_integer().divided_by(Crypto::UnsignedBigInteger { 1'000 }); - - // 5. Return ℤ(µs). - return BigInt::create(vm, move(us)); -} - -// 8.3.6 get Temporal.Instant.prototype.epochNanoseconds, https://tc39.es/proposal-temporal/#sec-get-temporal.instant.prototype.epochnanoseconds -JS_DEFINE_NATIVE_FUNCTION(InstantPrototype::epoch_nanoseconds_getter) -{ - // 1. Let instant be the this value. - // 2. Perform ? RequireInternalSlot(instant, [[InitializedTemporalInstant]]). - auto instant = TRY(typed_this_object(vm)); - - // 3. Let ns be instant.[[Nanoseconds]]. - auto& ns = instant->nanoseconds(); - - // 4. Return ns. - return &ns; -} - -// 8.3.7 Temporal.Instant.prototype.add ( temporalDurationLike ), https://tc39.es/proposal-temporal/#sec-temporal.instant.prototype.add -JS_DEFINE_NATIVE_FUNCTION(InstantPrototype::add) -{ - auto temporal_duration_like = vm.argument(0); - - // 1. Let instant be the this value. - // 2. Perform ? RequireInternalSlot(instant, [[InitializedTemporalInstant]]). - auto instant = TRY(typed_this_object(vm)); - - // 3. Return ? AddDurationToOrSubtractDurationFromInstant(add, instant, temporalDurationLike). - return TRY(add_duration_to_or_subtract_duration_from_instant(vm, ArithmeticOperation::Add, instant, temporal_duration_like)); -} - -// 8.3.8 Temporal.Instant.prototype.subtract ( temporalDurationLike ), https://tc39.es/proposal-temporal/#sec-temporal.instant.prototype.subtract -JS_DEFINE_NATIVE_FUNCTION(InstantPrototype::subtract) -{ - auto temporal_duration_like = vm.argument(0); - - // 1. Let instant be the this value. - // 2. Perform ? RequireInternalSlot(instant, [[InitializedTemporalInstant]]). - auto instant = TRY(typed_this_object(vm)); - - // 3. Return ? AddDurationToOrSubtractDurationFromInstant(subtract, instant, temporalDurationLike). - return TRY(add_duration_to_or_subtract_duration_from_instant(vm, ArithmeticOperation::Subtract, instant, temporal_duration_like)); -} - -// 8.3.9 Temporal.Instant.prototype.until ( other [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal.instant.prototype.until -JS_DEFINE_NATIVE_FUNCTION(InstantPrototype::until) -{ - auto other = vm.argument(0); - auto options = vm.argument(1); - - // 1. Let instant be the this value. - // 2. Perform ? RequireInternalSlot(instant, [[InitializedTemporalInstant]]). - auto instant = TRY(typed_this_object(vm)); - - // 3. Return ? DifferenceTemporalInstant(until, instant, other, options). - return TRY(difference_temporal_instant(vm, DifferenceOperation::Until, instant, other, options)); -} - -// 8.3.10 Temporal.Instant.prototype.since ( other [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal.instant.prototype.since -JS_DEFINE_NATIVE_FUNCTION(InstantPrototype::since) -{ - auto other = vm.argument(0); - auto options = vm.argument(1); - - // 1. Let instant be the this value. - // 2. Perform ? RequireInternalSlot(instant, [[InitializedTemporalInstant]]). - auto instant = TRY(typed_this_object(vm)); - - // 3. Return ? DifferenceTemporalInstant(since, instant, other, options). - return TRY(difference_temporal_instant(vm, DifferenceOperation::Since, instant, other, options)); -} - -// 8.3.11 Temporal.Instant.prototype.round ( roundTo ), https://tc39.es/proposal-temporal/#sec-temporal.instant.prototype.round -JS_DEFINE_NATIVE_FUNCTION(InstantPrototype::round) -{ - auto& realm = *vm.current_realm(); - - // 1. Let instant be the this value. - // 2. Perform ? RequireInternalSlot(instant, [[InitializedTemporalInstant]]). - auto instant = TRY(typed_this_object(vm)); - - // 3. If roundTo is undefined, then - if (vm.argument(0).is_undefined()) { - // a. Throw a TypeError exception. - return vm.throw_completion(ErrorType::TemporalMissingOptionsObject); - } - - Object* round_to; - - // 4. If Type(roundTo) is String, then - if (vm.argument(0).is_string()) { - // a. Let paramString be roundTo. - - // b. Set roundTo to OrdinaryObjectCreate(null). - round_to = Object::create(realm, nullptr); - - // c. Perform ! CreateDataPropertyOrThrow(roundTo, "smallestUnit", paramString). - MUST(round_to->create_data_property_or_throw(vm.names.smallestUnit, vm.argument(0))); - } - // 5. Else, - else { - // a. Set roundTo to ? GetOptionsObject(roundTo). - round_to = TRY(get_options_object(vm, vm.argument(0))); - } - - // 6. Let smallestUnit be ? GetTemporalUnit(roundTo, "smallestUnit", time, required). - auto smallest_unit_value = TRY(get_temporal_unit(vm, *round_to, vm.names.smallestUnit, UnitGroup::Time, TemporalUnitRequired {})); - - // 6. If smallestUnit is undefined, throw a RangeError exception. - if (!smallest_unit_value.has_value()) - return vm.throw_completion(ErrorType::OptionIsNotValidValue, vm.names.undefined.as_string(), "smallestUnit"); - - // At this point smallest_unit_value can only be a string - auto& smallest_unit = *smallest_unit_value; - - // 7. Let roundingMode be ? ToTemporalRoundingMode(roundTo, "halfExpand"). - auto rounding_mode = TRY(to_temporal_rounding_mode(vm, *round_to, "halfExpand"sv)); - - double maximum; - // 8. If smallestUnit is "hour", then - if (smallest_unit == "hour"sv) { - // a. Let maximum be HoursPerDay. - maximum = hours_per_day; - } - // 9. Else if smallestUnit is "minute", then - else if (smallest_unit == "minute"sv) { - // a. Let maximum be MinutesPerHour × HoursPerDay. - maximum = minutes_per_hour * hours_per_day; - } - // 10. Else if smallestUnit is "second", then - else if (smallest_unit == "second"sv) { - // a. Let maximum be SecondsPerMinute × MinutesPerHour × HoursPerDay. - maximum = seconds_per_minute * minutes_per_hour * hours_per_day; - } - // 11. Else if smallestUnit is "millisecond", then - else if (smallest_unit == "millisecond"sv) { - // a. Let maximum be ℝ(msPerDay). - maximum = ms_per_day; - } - // 12. Else if smallestUnit is "microsecond", then - else if (smallest_unit == "microsecond"sv) { - // a. Let maximum be 10^3 × ℝ(msPerDay). - maximum = 1000 * ms_per_day; - } - // 13. Else, - else { - // a. Assert: smallestUnit is "nanosecond". - VERIFY(smallest_unit == "nanosecond"sv); - // b. Let maximum be nsPerDay. - maximum = ns_per_day; - } - - // 14. Let roundingIncrement be ? ToTemporalRoundingIncrement(options). - auto rounding_increment = TRY(to_temporal_rounding_increment(vm, *round_to)); - - // 15. Perform ? ValidateTemporalRoundingIncrement(roundingIncrement, maximum, true). - TRY(validate_temporal_rounding_increment(vm, rounding_increment, maximum, true)); - - // 16. Let roundedNs be ! RoundTemporalInstant(instant.[[Nanoseconds]], roundingIncrement, smallestUnit, roundingMode). - auto* rounded_ns = round_temporal_instant(vm, instant->nanoseconds(), rounding_increment, smallest_unit, rounding_mode); - - // 17. Return ! CreateTemporalInstant(roundedNs). - return MUST(create_temporal_instant(vm, *rounded_ns)); -} - -// 8.3.12 Temporal.Instant.prototype.equals ( other ), https://tc39.es/proposal-temporal/#sec-temporal.instant.prototype.equals -JS_DEFINE_NATIVE_FUNCTION(InstantPrototype::equals) -{ - // 1. Let instant be the this value. - // 2. Perform ? RequireInternalSlot(instant, [[InitializedTemporalInstant]]). - auto instant = TRY(typed_this_object(vm)); - - // 3. Set other to ? ToTemporalInstant(other). - auto other = TRY(to_temporal_instant(vm, vm.argument(0))); - - // 4. If instant.[[Nanoseconds]] ≠ other.[[Nanoseconds]], return false. - if (instant->nanoseconds().big_integer() != other->nanoseconds().big_integer()) - return Value(false); - - // 5. Return true. - return Value(true); -} - -// 8.3.13 Temporal.Instant.prototype.toString ( [ options ] ), https://tc39.es/proposal-temporal/#sec-temporal.instant.prototype.tostring -JS_DEFINE_NATIVE_FUNCTION(InstantPrototype::to_string) -{ - // 1. Let instant be the this value. - // 2. Perform ? RequireInternalSlot(instant, [[InitializedTemporalInstant]]). - auto instant = TRY(typed_this_object(vm)); - - // 3. Set options to ? GetOptionsObject(options). - auto const* options = TRY(get_options_object(vm, vm.argument(0))); - - // 4. Let timeZone be ? Get(options, "timeZone"). - auto time_zone = TRY(options->get(vm.names.timeZone)); - - // 5. If timeZone is not undefined, then - if (!time_zone.is_undefined()) { - // a. Set timeZone to ? ToTemporalTimeZone(timeZone). - time_zone = TRY(to_temporal_time_zone(vm, time_zone)); - } - - // 6. Let precision be ? ToSecondsStringPrecisionRecord(options). - auto precision = TRY(to_seconds_string_precision_record(vm, *options)); - - // 7. Let roundingMode be ? ToTemporalRoundingMode(options, "trunc"). - auto rounding_mode = TRY(to_temporal_rounding_mode(vm, *options, "trunc"sv)); - - // 8. Let roundedNs be ! RoundTemporalInstant(instant.[[Nanoseconds]], precision.[[Increment]], precision.[[Unit]], roundingMode). - auto* rounded_ns = round_temporal_instant(vm, instant->nanoseconds(), precision.increment, precision.unit, rounding_mode); - - // 9. Let roundedInstant be ! CreateTemporalInstant(roundedNs). - auto* rounded_instant = MUST(create_temporal_instant(vm, *rounded_ns)); - - // 10. Return ? TemporalInstantToString(roundedInstant, timeZone, precision.[[Precision]]). - return PrimitiveString::create(vm, TRY(temporal_instant_to_string(vm, *rounded_instant, time_zone, precision.precision))); -} - -// 8.3.14 Temporal.Instant.prototype.toLocaleString ( [ locales [ , options ] ] ), https://tc39.es/proposal-temporal/#sec-temporal.instant.prototype.tolocalestring -// NOTE: This is the minimum toLocaleString implementation for engines without ECMA-402. -JS_DEFINE_NATIVE_FUNCTION(InstantPrototype::to_locale_string) -{ - // 1. Let instant be the this value. - // 2. Perform ? RequireInternalSlot(instant, [[InitializedTemporalInstant]]). - auto instant = TRY(typed_this_object(vm)); - - // 3. Return ? TemporalInstantToString(instant, undefined, "auto"). - return PrimitiveString::create(vm, TRY(temporal_instant_to_string(vm, instant, js_undefined(), "auto"sv))); -} - -// 8.3.15 Temporal.Instant.prototype.toJSON ( ), https://tc39.es/proposal-temporal/#sec-temporal.instant.prototype.tojson -JS_DEFINE_NATIVE_FUNCTION(InstantPrototype::to_json) -{ - // 1. Let instant be the this value. - // 2. Perform ? RequireInternalSlot(instant, [[InitializedTemporalInstant]]). - auto instant = TRY(typed_this_object(vm)); - - // 3. Return ? TemporalInstantToString(instant, undefined, "auto"). - return PrimitiveString::create(vm, TRY(temporal_instant_to_string(vm, instant, js_undefined(), "auto"sv))); -} - -// 8.3.16 Temporal.Instant.prototype.valueOf ( ), https://tc39.es/proposal-temporal/#sec-temporal.instant.prototype.valueof -JS_DEFINE_NATIVE_FUNCTION(InstantPrototype::value_of) -{ - // 1. Throw a TypeError exception. - return vm.throw_completion(ErrorType::Convert, "Temporal.Instant", "a primitive value"); -} - -// 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 = TRY(typed_this_object(vm)); - - // 3. If Type(item) is not Object, then - if (!item.is_object()) { - // a. Throw a TypeError exception. - return vm.throw_completion(ErrorType::NotAnObject, item); - } - - // 4. Let calendarLike be ? Get(item, "calendar"). - auto calendar_like = TRY(item.as_object().get(vm.names.calendar)); - - // 5. If calendarLike is undefined, then - if (calendar_like.is_undefined()) { - // a. Throw a TypeError exception. - return vm.throw_completion(ErrorType::MissingRequiredProperty, vm.names.calendar.as_string()); - } - - // 6. Let calendar be ? ToTemporalCalendar(calendarLike). - auto* calendar = TRY(to_temporal_calendar(vm, calendar_like)); - - // 7. Let temporalTimeZoneLike be ? Get(item, "timeZone"). - auto temporal_time_zone_like = TRY(item.as_object().get(vm.names.timeZone)); - - // 8. If temporalTimeZoneLike is undefined, then - if (temporal_time_zone_like.is_undefined()) { - // a. Throw a TypeError exception. - return vm.throw_completion(ErrorType::MissingRequiredProperty, vm.names.timeZone.as_string()); - } - - // 9. Let timeZone be ? ToTemporalTimeZone(temporalTimeZoneLike). - auto* time_zone = TRY(to_temporal_time_zone(vm, temporal_time_zone_like)); - - // 10. Return ? CreateTemporalZonedDateTime(instant.[[Nanoseconds]], timeZone, calendar). - return TRY(create_temporal_zoned_date_time(vm, instant->nanoseconds(), *time_zone, *calendar)); -} - -// 8.3.18 Temporal.Instant.prototype.toZonedDateTimeISO ( timeZone ), https://tc39.es/proposal-temporal/#sec-temporal.instant.prototype.tozoneddatetimeiso -JS_DEFINE_NATIVE_FUNCTION(InstantPrototype::to_zoned_date_time_iso) -{ - // 1. Let instant be the this value. - // 2. Perform ? RequireInternalSlot(instant, [[InitializedTemporalInstant]]). - auto instant = TRY(typed_this_object(vm)); - - // 3. Set timeZone to ? ToTemporalTimeZone(timeZone). - auto* time_zone = TRY(to_temporal_time_zone(vm, vm.argument(0))); - - // 4. Let calendar be ! GetISO8601Calendar(). - auto* calendar = get_iso8601_calendar(vm); - - // 5. Return ? CreateTemporalZonedDateTime(instant.[[Nanoseconds]], timeZone, calendar). - return TRY(create_temporal_zoned_date_time(vm, instant->nanoseconds(), *time_zone, *calendar)); -} - -} diff --git a/Libraries/LibJS/Runtime/Temporal/InstantPrototype.h b/Libraries/LibJS/Runtime/Temporal/InstantPrototype.h deleted file mode 100644 index 66aea209d49..00000000000 --- a/Libraries/LibJS/Runtime/Temporal/InstantPrototype.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2021, Linus Groh - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include -#include - -namespace JS::Temporal { - -class InstantPrototype final : public PrototypeObject { - JS_PROTOTYPE_OBJECT(InstantPrototype, Instant, Temporal.Instant); - GC_DECLARE_ALLOCATOR(InstantPrototype); - -public: - virtual void initialize(Realm&) override; - virtual ~InstantPrototype() override = default; - -private: - explicit InstantPrototype(Realm&); - - JS_DECLARE_NATIVE_FUNCTION(epoch_seconds_getter); - JS_DECLARE_NATIVE_FUNCTION(epoch_milliseconds_getter); - JS_DECLARE_NATIVE_FUNCTION(epoch_microseconds_getter); - JS_DECLARE_NATIVE_FUNCTION(epoch_nanoseconds_getter); - JS_DECLARE_NATIVE_FUNCTION(add); - JS_DECLARE_NATIVE_FUNCTION(subtract); - JS_DECLARE_NATIVE_FUNCTION(until); - JS_DECLARE_NATIVE_FUNCTION(since); - JS_DECLARE_NATIVE_FUNCTION(round); - JS_DECLARE_NATIVE_FUNCTION(equals); - JS_DECLARE_NATIVE_FUNCTION(to_string); - 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); - JS_DECLARE_NATIVE_FUNCTION(to_zoned_date_time_iso); -}; - -} diff --git a/Libraries/LibJS/Runtime/Temporal/Now.cpp b/Libraries/LibJS/Runtime/Temporal/Now.cpp deleted file mode 100644 index 1723c5aad7c..00000000000 --- a/Libraries/LibJS/Runtime/Temporal/Now.cpp +++ /dev/null @@ -1,241 +0,0 @@ -/* - * Copyright (c) 2021-2023, Linus Groh - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace JS::Temporal { - -GC_DEFINE_ALLOCATOR(Now); - -// 2 The Temporal.Now Object, https://tc39.es/proposal-temporal/#sec-temporal-now-object -Now::Now(Realm& realm) - : Object(ConstructWithPrototypeTag::Tag, realm.intrinsics().object_prototype()) -{ -} - -void Now::initialize(Realm& realm) -{ - Base::initialize(realm); - - auto& vm = this->vm(); - - // 2.1.1 Temporal.Now [ @@toStringTag ], https://tc39.es/proposal-temporal/#sec-temporal-now-@@tostringtag - define_direct_property(vm.well_known_symbol_to_string_tag(), PrimitiveString::create(vm, "Temporal.Now"_string), Attribute::Configurable); - - u8 attr = Attribute::Writable | Attribute::Configurable; - define_native_function(realm, vm.names.timeZone, time_zone, 0, attr); - define_native_function(realm, vm.names.instant, instant, 0, attr); - define_native_function(realm, vm.names.plainDateTime, plain_date_time, 1, attr); - define_native_function(realm, vm.names.plainDateTimeISO, plain_date_time_iso, 0, attr); - define_native_function(realm, vm.names.zonedDateTime, zoned_date_time, 1, attr); - define_native_function(realm, vm.names.zonedDateTimeISO, zoned_date_time_iso, 0, attr); - define_native_function(realm, vm.names.plainDate, plain_date, 1, attr); - define_native_function(realm, vm.names.plainDateISO, plain_date_iso, 0, attr); - define_native_function(realm, vm.names.plainTimeISO, plain_time_iso, 0, attr); -} - -// 2.2.1 Temporal.Now.timeZone ( ), https://tc39.es/proposal-temporal/#sec-temporal.now.timezone -JS_DEFINE_NATIVE_FUNCTION(Now::time_zone) -{ - // 1. Return ! SystemTimeZone(). - return system_time_zone(vm); -} - -// 2.2.2 Temporal.Now.instant ( ), https://tc39.es/proposal-temporal/#sec-temporal.now.instant -JS_DEFINE_NATIVE_FUNCTION(Now::instant) -{ - // 1. Return ! SystemInstant(). - return system_instant(vm); -} - -// 2.2.3 Temporal.Now.plainDateTime ( calendarLike [ , temporalTimeZoneLike ] ), https://tc39.es/proposal-temporal/#sec-temporal.now.plaindatetime -JS_DEFINE_NATIVE_FUNCTION(Now::plain_date_time) -{ - auto calendar_like = vm.argument(0); - auto temporal_time_zone_like = vm.argument(1); - - // 1. Return ? SystemDateTime(temporalTimeZoneLike, calendarLike). - return TRY(system_date_time(vm, temporal_time_zone_like, calendar_like)); -} - -// 2.2.4 Temporal.Now.plainDateTimeISO ( [ temporalTimeZoneLike ] ), https://tc39.es/proposal-temporal/#sec-temporal.now.plaindatetimeiso -JS_DEFINE_NATIVE_FUNCTION(Now::plain_date_time_iso) -{ - auto temporal_time_zone_like = vm.argument(0); - - // 1, Let calendar be ! GetISO8601Calendar(). - auto* calendar = get_iso8601_calendar(vm); - - // 2. Return ? SystemDateTime(temporalTimeZoneLike, calendar). - return TRY(system_date_time(vm, temporal_time_zone_like, calendar)); -} - -// 2.2.5 Temporal.Now.zonedDateTime ( calendarLike [ , temporalTimeZoneLike ] ), https://tc39.es/proposal-temporal/#sec-temporal.now.zoneddatetime -JS_DEFINE_NATIVE_FUNCTION(Now::zoned_date_time) -{ - auto calendar_like = vm.argument(0); - auto temporal_time_zone_like = vm.argument(1); - - // 1. Return ? SystemZonedDateTime(temporalTimeZoneLike, calendarLike). - return TRY(system_zoned_date_time(vm, temporal_time_zone_like, calendar_like)); -} - -// 2.2.6 Temporal.Now.zonedDateTimeISO ( [ temporalTimeZoneLike ] ), https://tc39.es/proposal-temporal/#sec-temporal.now.zoneddatetimeiso -JS_DEFINE_NATIVE_FUNCTION(Now::zoned_date_time_iso) -{ - auto temporal_time_zone_like = vm.argument(0); - - // 1, Let calendar be ! GetISO8601Calendar(). - auto* calendar = get_iso8601_calendar(vm); - - // 2. Return ? SystemZonedDateTime(temporalTimeZoneLike, calendar). - return TRY(system_zoned_date_time(vm, temporal_time_zone_like, calendar)); -} - -// 2.2.7 Temporal.Now.plainDate ( calendarLike [ , temporalTimeZoneLike ] ), https://tc39.es/proposal-temporal/#sec-temporal.now.plaindate -JS_DEFINE_NATIVE_FUNCTION(Now::plain_date) -{ - auto calendar_like = vm.argument(0); - auto temporal_time_zone_like = vm.argument(1); - - // 1. Let dateTime be ? SystemDateTime(temporalTimeZoneLike, calendarLike). - auto* date_time = TRY(system_date_time(vm, temporal_time_zone_like, calendar_like)); - - // 2. Return ! CreateTemporalDate(dateTime.[[ISOYear]], dateTime.[[ISOMonth]], dateTime.[[ISODay]], dateTime.[[Calendar]]). - return MUST(create_temporal_date(vm, date_time->iso_year(), date_time->iso_month(), date_time->iso_day(), date_time->calendar())); -} - -// 2.2.8 Temporal.Now.plainDateISO ( [ temporalTimeZoneLike ] ), https://tc39.es/proposal-temporal/#sec-temporal.now.plaindateiso -JS_DEFINE_NATIVE_FUNCTION(Now::plain_date_iso) -{ - auto temporal_time_zone_like = vm.argument(0); - - // 1. Let calendar be ! GetISO8601Calendar(). - auto* calendar = get_iso8601_calendar(vm); - - // 2. Let dateTime be ? SystemDateTime(temporalTimeZoneLike, calendar). - auto* date_time = TRY(system_date_time(vm, temporal_time_zone_like, calendar)); - - // 3. Return ! CreateTemporalDate(dateTime.[[ISOYear]], dateTime.[[ISOMonth]], dateTime.[[ISODay]], dateTime.[[Calendar]]). - return MUST(create_temporal_date(vm, date_time->iso_year(), date_time->iso_month(), date_time->iso_day(), date_time->calendar())); -} - -// 2.2.9 Temporal.Now.plainTimeISO ( [ temporalTimeZoneLike ] ), https://tc39.es/proposal-temporal/#sec-temporal.now.plaintimeiso -JS_DEFINE_NATIVE_FUNCTION(Now::plain_time_iso) -{ - auto temporal_time_zone_like = vm.argument(0); - - // 1. Let calendar be ! GetISO8601Calendar(). - auto* calendar = get_iso8601_calendar(vm); - - // 2. Let dateTime be ? SystemDateTime(temporalTimeZoneLike, calendar). - auto* date_time = TRY(system_date_time(vm, temporal_time_zone_like, calendar)); - - // 3. Return ! CreateTemporalTime(dateTime.[[ISOHour]], dateTime.[[ISOMinute]], dateTime.[[ISOSecond]], dateTime.[[ISOMillisecond]], dateTime.[[ISOMicrosecond]], dateTime.[[ISONanosecond]]). - return MUST(create_temporal_time(vm, date_time->iso_hour(), date_time->iso_minute(), date_time->iso_second(), date_time->iso_millisecond(), date_time->iso_microsecond(), date_time->iso_nanosecond())); -} - -// 2.3.1 SystemTimeZone ( ), https://tc39.es/proposal-temporal/#sec-temporal-systemtimezone -TimeZone* system_time_zone(VM& vm) -{ - // 1. Let identifier be ! DefaultTimeZone(). - auto identifier = system_time_zone_identifier(); - - // 2. Return ! CreateTemporalTimeZone(identifier). - // FIXME: Propagate possible OOM error - return MUST(create_temporal_time_zone(vm, move(identifier))); -} - -// 2.3.2 SystemUTCEpochNanoseconds ( ), https://tc39.es/proposal-temporal/#sec-temporal-systemutcepochnanoseconds -BigInt* system_utc_epoch_nanoseconds(VM& vm) -{ - // 1. Let ns be the approximate current UTC date and time, in nanoseconds since the epoch. - auto now = AK::UnixDateTime::now().nanoseconds_since_epoch(); - auto ns = Crypto::SignedBigInteger { now }; - - // 2. Set ns to the result of clamping ns between nsMinInstant and nsMaxInstant. - // NOTE: Duration::to_nanoseconds() already clamps between -(2^63) and 2^63 - 1, the range of an i64, - // if an overflow occurs during seconds -> nanoseconds conversion. - - // 3. Return ℤ(ns). - return BigInt::create(vm, move(ns)); -} - -// 2.3.3 SystemInstant ( ), https://tc39.es/proposal-temporal/#sec-temporal-systeminstant -Instant* system_instant(VM& vm) -{ - // 1. Let ns be ! SystemUTCEpochNanoseconds(). - auto* ns = system_utc_epoch_nanoseconds(vm); - - // 2. Return ! CreateTemporalInstant(ns). - return MUST(create_temporal_instant(vm, *ns)); -} - -// 2.3.4 SystemDateTime ( temporalTimeZoneLike, calendarLike ), https://tc39.es/proposal-temporal/#sec-temporal-systemdatetime -ThrowCompletionOr system_date_time(VM& vm, Value temporal_time_zone_like, Value calendar_like) -{ - Object* time_zone; - - // 1. If temporalTimeZoneLike is undefined, then - if (temporal_time_zone_like.is_undefined()) { - // a. Let timeZone be ! SystemTimeZone(). - time_zone = system_time_zone(vm); - } - // 2. Else, - else { - // a. Let timeZone be ? ToTemporalTimeZone(temporalTimeZoneLike). - time_zone = TRY(to_temporal_time_zone(vm, temporal_time_zone_like)); - } - - // 3. Let calendar be ? ToTemporalCalendar(calendarLike). - auto* calendar = TRY(to_temporal_calendar(vm, calendar_like)); - - // 4. Let instant be ! SystemInstant(). - auto* instant = system_instant(vm); - - // 5. Return ? BuiltinTimeZoneGetPlainDateTimeFor(timeZone, instant, calendar). - return builtin_time_zone_get_plain_date_time_for(vm, time_zone, *instant, *calendar); -} - -// 2.3.5 SystemZonedDateTime ( temporalTimeZoneLike, calendarLike ), https://tc39.es/proposal-temporal/#sec-temporal-systemzoneddatetime -ThrowCompletionOr system_zoned_date_time(VM& vm, Value temporal_time_zone_like, Value calendar_like) -{ - Object* time_zone; - - // 1. If temporalTimeZoneLike is undefined, then - if (temporal_time_zone_like.is_undefined()) { - // a. Let timeZone be ! SystemTimeZone(). - time_zone = system_time_zone(vm); - } - // 2. Else, - else { - // a. Let timeZone be ? ToTemporalTimeZone(temporalTimeZoneLike). - time_zone = TRY(to_temporal_time_zone(vm, temporal_time_zone_like)); - } - - // 3. Let calendar be ? ToTemporalCalendar(calendarLike). - auto* calendar = TRY(to_temporal_calendar(vm, calendar_like)); - - // 4. Let ns be ! SystemUTCEpochNanoseconds(). - auto* ns = system_utc_epoch_nanoseconds(vm); - - // 5. Return ? CreateTemporalZonedDateTime(ns, timeZone, calendar). - return create_temporal_zoned_date_time(vm, *ns, *time_zone, *calendar); -} - -} diff --git a/Libraries/LibJS/Runtime/Temporal/Now.h b/Libraries/LibJS/Runtime/Temporal/Now.h deleted file mode 100644 index 8217e49271a..00000000000 --- a/Libraries/LibJS/Runtime/Temporal/Now.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2021-2022, Linus Groh - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include -#include - -namespace JS::Temporal { - -class Now final : public Object { - JS_OBJECT(Now, Object); - GC_DECLARE_ALLOCATOR(Now); - -public: - virtual void initialize(Realm&) override; - virtual ~Now() override = default; - -private: - explicit Now(Realm&); - - JS_DECLARE_NATIVE_FUNCTION(time_zone); - JS_DECLARE_NATIVE_FUNCTION(instant); - JS_DECLARE_NATIVE_FUNCTION(plain_date_time); - JS_DECLARE_NATIVE_FUNCTION(plain_date_time_iso); - JS_DECLARE_NATIVE_FUNCTION(zoned_date_time); - JS_DECLARE_NATIVE_FUNCTION(zoned_date_time_iso); - JS_DECLARE_NATIVE_FUNCTION(plain_date); - JS_DECLARE_NATIVE_FUNCTION(plain_date_iso); - JS_DECLARE_NATIVE_FUNCTION(plain_time_iso); -}; - -TimeZone* system_time_zone(VM&); -BigInt* system_utc_epoch_nanoseconds(VM&); -Instant* system_instant(VM&); -ThrowCompletionOr system_date_time(VM&, Value temporal_time_zone_like, Value calendar_like); -ThrowCompletionOr system_zoned_date_time(VM&, Value temporal_time_zone_like, Value calendar_like); - -} diff --git a/Libraries/LibJS/Runtime/Temporal/PlainDate.cpp b/Libraries/LibJS/Runtime/Temporal/PlainDate.cpp deleted file mode 100644 index d26a7fb3d9a..00000000000 --- a/Libraries/LibJS/Runtime/Temporal/PlainDate.cpp +++ /dev/null @@ -1,583 +0,0 @@ -/* - * Copyright (c) 2021, Idan Horowitz - * Copyright (c) 2021-2023, Linus Groh - * Copyright (c) 2024, Shannon Booth - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace JS::Temporal { - -GC_DEFINE_ALLOCATOR(PlainDate); - -// 3 Temporal.PlainDate Objects, https://tc39.es/proposal-temporal/#sec-temporal-plaindate-objects -PlainDate::PlainDate(i32 year, u8 month, u8 day, Object& calendar, Object& prototype) - : Object(ConstructWithPrototypeTag::Tag, prototype) - , m_iso_year(year) - , m_iso_month(month) - , m_iso_day(day) - , m_calendar(calendar) -{ -} - -void PlainDate::visit_edges(Visitor& visitor) -{ - Base::visit_edges(visitor); - visitor.visit(m_calendar); -} - -// 3.5.2 CreateISODateRecord ( year, month, day ), https://tc39.es/proposal-temporal/#sec-temporal-create-iso-date-record -ISODateRecord create_iso_date_record(i32 year, u8 month, u8 day) -{ - // 1. Assert: IsValidISODate(year, month, day) is true. - VERIFY(is_valid_iso_date(year, month, day)); - - // 2. Return the Record { [[Year]]: year, [[Month]]: month, [[Day]]: day }. - return { .year = year, .month = month, .day = day }; -} - -// 3.5.1 CreateTemporalDate ( isoYear, isoMonth, isoDay, calendar [ , newTarget ] ), https://tc39.es/proposal-temporal/#sec-temporal-createtemporaldate -ThrowCompletionOr create_temporal_date(VM& vm, i32 iso_year, u8 iso_month, u8 iso_day, Object& calendar, FunctionObject const* new_target) -{ - auto& realm = *vm.current_realm(); - - // 1. Assert: isoYear is an integer. - // 2. Assert: isoMonth is an integer. - // 3. Assert: isoDay is an integer. - // 4. Assert: Type(calendar) is Object. - - // 5. If IsValidISODate(isoYear, isoMonth, isoDay) is false, throw a RangeError exception. - if (!is_valid_iso_date(iso_year, iso_month, iso_day)) - return vm.throw_completion(ErrorType::TemporalInvalidPlainDate); - - // 6. If ISODateTimeWithinLimits(isoYear, isoMonth, isoDay, 12, 0, 0, 0, 0, 0) is false, throw a RangeError exception. - if (!iso_date_time_within_limits(iso_year, iso_month, iso_day, 12, 0, 0, 0, 0, 0)) - return vm.throw_completion(ErrorType::TemporalInvalidPlainDate); - - // 7. If newTarget is not present, set newTarget to %Temporal.PlainDate%. - if (!new_target) - new_target = realm.intrinsics().temporal_plain_date_constructor(); - - // 8. Let object be ? OrdinaryCreateFromConstructor(newTarget, "%Temporal.PlainDate.prototype%", « [[InitializedTemporalDate]], [[ISOYear]], [[ISOMonth]], [[ISODay]], [[Calendar]] »). - // 9. Set object.[[ISOYear]] to isoYear. - // 10. Set object.[[ISOMonth]] to isoMonth. - // 11. Set object.[[ISODay]] to isoDay. - // 12. Set object.[[Calendar]] to calendar. - auto object = TRY(ordinary_create_from_constructor(vm, *new_target, &Intrinsics::temporal_plain_date_prototype, iso_year, iso_month, iso_day, calendar)); - - return object.ptr(); -} - -// 3.5.2 ToTemporalDate ( item [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal-totemporaldate -ThrowCompletionOr to_temporal_date(VM& vm, Value item, Object const* options) -{ - // 1. If options is not present, set options to undefined. - // 2. Assert: Type(options) is Object or Undefined. - - // 3. If Type(item) is Object, then - if (item.is_object()) { - auto& item_object = item.as_object(); - // a. If item has an [[InitializedTemporalDate]] internal slot, then - if (is(item_object)) { - // i. Return item. - return static_cast(&item_object); - } - - // b. If item has an [[InitializedTemporalZonedDateTime]] internal slot, then - if (is(item_object)) { - auto& zoned_date_time = static_cast(item_object); - - // i. Perform ? ToTemporalOverflow(options). - (void)TRY(to_temporal_overflow(vm, options)); - - // ii. Let instant be ! CreateTemporalInstant(item.[[Nanoseconds]]). - auto* instant = create_temporal_instant(vm, zoned_date_time.nanoseconds()).release_value(); - - // iii. Let plainDateTime be ? BuiltinTimeZoneGetPlainDateTimeFor(item.[[TimeZone]], instant, item.[[Calendar]]). - auto* plain_date_time = TRY(builtin_time_zone_get_plain_date_time_for(vm, &zoned_date_time.time_zone(), *instant, zoned_date_time.calendar())); - - // iv. Return ! CreateTemporalDate(plainDateTime.[[ISOYear]], plainDateTime.[[ISOMonth]], plainDateTime.[[ISODay]], plainDateTime.[[Calendar]]). - return create_temporal_date(vm, plain_date_time->iso_year(), plain_date_time->iso_month(), plain_date_time->iso_day(), plain_date_time->calendar()); - } - - // c. If item has an [[InitializedTemporalDateTime]] internal slot, then - if (is(item_object)) { - auto& date_time_item = static_cast(item_object); - - // i. Perform ? ToTemporalOverflow(options). - (void)TRY(to_temporal_overflow(vm, options)); - - // ii. Return ! CreateTemporalDate(item.[[ISOYear]], item.[[ISOMonth]], item.[[ISODay]], item.[[Calendar]]). - return create_temporal_date(vm, date_time_item.iso_year(), date_time_item.iso_month(), date_time_item.iso_day(), date_time_item.calendar()); - } - - // d. Let calendar be ? GetTemporalCalendarWithISODefault(item). - auto* calendar = TRY(get_temporal_calendar_with_iso_default(vm, item_object)); - - // e. Let fieldNames be ? CalendarFields(calendar, « "day", "month", "monthCode", "year" »). - auto field_names = TRY(calendar_fields(vm, *calendar, { "day"sv, "month"sv, "monthCode"sv, "year"sv })); - - // f. Let fields be ? PrepareTemporalFields(item, fieldNames, «»). - auto* fields = TRY(prepare_temporal_fields(vm, item_object, field_names, Vector {})); - - // g. Return ? CalendarDateFromFields(calendar, fields, options). - return calendar_date_from_fields(vm, *calendar, *fields, options); - } - - // 4. Perform ? ToTemporalOverflow(options). - (void)TRY(to_temporal_overflow(vm, options)); - - // 5. Let string be ? ToString(item). - auto string = TRY(item.to_string(vm)); - - // 6. Let result be ? ParseTemporalDateString(string). - auto result = TRY(parse_temporal_date_string(vm, string)); - - // 7. Assert: IsValidISODate(result.[[Year]], result.[[Month]], result.[[Day]]) is true. - VERIFY(is_valid_iso_date(result.year, result.month, result.day)); - - // 8. Let calendar be ? ToTemporalCalendarWithISODefault(result.[[Calendar]]). - auto* calendar = TRY(to_temporal_calendar_with_iso_default(vm, result.calendar.has_value() ? PrimitiveString::create(vm, *result.calendar) : js_undefined())); - - // 9. Return ? CreateTemporalDate(result.[[Year]], result.[[Month]], result.[[Day]], calendar). - return create_temporal_date(vm, result.year, result.month, result.day, *calendar); -} - -// 3.5.3 DifferenceISODate ( y1, m1, d1, y2, m2, d2, largestUnit ), https://tc39.es/proposal-temporal/#sec-temporal-differenceisodate -DateDurationRecord difference_iso_date(VM& vm, i32 year1, u8 month1, u8 day1, i32 year2, u8 month2, u8 day2, StringView largest_unit) -{ - VERIFY(largest_unit.is_one_of("year"sv, "month"sv, "week"sv, "day"sv)); - - // 1. If largestUnit is "year" or "month", then - if (largest_unit.is_one_of("year"sv, "month"sv)) { - // a. Let sign be -(! CompareISODate(y1, m1, d1, y2, m2, d2)). - auto sign = -compare_iso_date(year1, month1, day1, year2, month2, day2); - - // b. If sign is 0, return ! CreateDateDurationRecord(0, 0, 0, 0). - if (sign == 0) - return create_date_duration_record(0, 0, 0, 0); - - // c. Let start be the Record { [[Year]]: y1, [[Month]]: m1, [[Day]]: d1 }. - auto start = ISODateRecord { .year = year1, .month = month1, .day = day1 }; - - // d. Let end be the Record { [[Year]]: y2, [[Month]]: m2, [[Day]]: d2 }. - auto end = ISODateRecord { .year = year2, .month = month2, .day = day2 }; - - // e. Let years be end.[[Year]] - start.[[Year]]. - double years = end.year - start.year; - - // f. Let mid be ! AddISODate(y1, m1, d1, years, 0, 0, 0, "constrain"). - auto mid = MUST(add_iso_date(vm, year1, month1, day1, years, 0, 0, 0, "constrain"sv)); - - // g. Let midSign be -(! CompareISODate(mid.[[Year]], mid.[[Month]], mid.[[Day]], y2, m2, d2)). - auto mid_sign = -compare_iso_date(mid.year, mid.month, mid.day, year2, month2, day2); - - // h. If midSign is 0, then - if (mid_sign == 0) { - // i. If largestUnit is "year", return ! CreateDateDurationRecord(years, 0, 0, 0). - if (largest_unit == "year"sv) - return create_date_duration_record(years, 0, 0, 0); - - // ii. Return ! CreateDateDurationRecord(0, years × 12, 0, 0). - return create_date_duration_record(0, years * 12, 0, 0); - } - - // i. Let months be end.[[Month]] - start.[[Month]]. - double months = end.month - start.month; - - // j. If midSign is not equal to sign, then - if (mid_sign != sign) { - // i. Set years to years - sign. - years -= sign; - - // ii. Set months to months + sign × 12. - months += sign * 12; - } - - // k. Set mid to ! AddISODate(y1, m1, d1, years, months, 0, 0, "constrain"). - mid = MUST(add_iso_date(vm, year1, month1, day1, years, months, 0, 0, "constrain"sv)); - - // l. Set midSign to -(! CompareISODate(mid.[[Year]], mid.[[Month]], mid.[[Day]], y2, m2, d2)). - mid_sign = -compare_iso_date(mid.year, mid.month, mid.day, year2, month2, day2); - - // m. If midSign is 0, then - if (mid_sign == 0) { - // i. If largestUnit is "year", return ! CreateDateDurationRecord(years, months, 0, 0). - if (largest_unit == "year"sv) - return create_date_duration_record(years, months, 0, 0); - - // ii. Return ! CreateDateDurationRecord(0, months + years × 12, 0, 0). - return create_date_duration_record(0, months + years * 12, 0, 0); - } - - // n. If midSign is not equal to sign, then - if (mid_sign != sign) { - // i. Set months to months - sign. - months -= sign; - - // ii. If months is equal to -sign, then - if (months == -sign) { - // 1. Set years to years - sign. - years -= sign; - - // 2. Set months to 11 × sign. - months = 11 * sign; - } - - // iii. Set mid to ! AddISODate(y1, m1, d1, years, months, 0, 0, "constrain"). - mid = MUST(add_iso_date(vm, year1, month1, day1, years, months, 0, 0, "constrain"sv)); - } - - double days; - - // o. If mid.[[Month]] = end.[[Month]], then - if (mid.month == end.month) { - // i. Assert: mid.[[Year]] = end.[[Year]]. - VERIFY(mid.year == end.year); - - // ii. Let days be end.[[Day]] - mid.[[Day]]. - days = end.day - mid.day; - } - // p. Else if sign < 0, let days be -mid.[[Day]] - (! ISODaysInMonth(end.[[Year]], end.[[Month]]) - end.[[Day]]). - else if (sign < 0) { - days = -mid.day - (iso_days_in_month(end.year, end.month) - end.day); - } - // q. Else, let days be end.[[Day]] + (! ISODaysInMonth(mid.[[Year]], mid.[[Month]]) - mid.[[Day]]). - else { - days = end.day + (iso_days_in_month(mid.year, mid.month) - mid.day); - } - - // r. If largestUnit is "month", then - if (largest_unit == "month"sv) { - // i. Set months to months + years × 12. - months += years * 12; - - // ii. Set years to 0. - years = 0; - } - - // s. Return ! CreateDateDurationRecord(years, months, 0, days). - return create_date_duration_record(years, months, 0, days); - } - // 2. Else, - else { - // a. Assert: largestUnit is "day" or "week". - VERIFY(largest_unit.is_one_of("day"sv, "week"sv)); - - // b. Let epochDays1 be MakeDay(𝔽(y1), 𝔽(m1 - 1), 𝔽(d1)). - auto epoch_days_1 = make_day(year1, month1 - 1, day1); - - // c. Assert: epochDays1 is finite. - VERIFY(isfinite(epoch_days_1)); - - // d. Let epochDays2 be MakeDay(𝔽(y2), 𝔽(m2 - 1), 𝔽(d2)). - auto epoch_days_2 = make_day(year2, month2 - 1, day2); - - // e. Assert: epochDays2 is finite. - VERIFY(isfinite(epoch_days_2)); - - // f. Let days be ℝ(epochDays2) - ℝ(epochDays1). - auto days = epoch_days_2 - epoch_days_1; - - // g. Let weeks be 0. - double weeks = 0; - - // h. If largestUnit is "week", then - if (largest_unit == "week"sv) { - // i. Set weeks to truncate(days / 7). - weeks = trunc(days / 7); - - // ii. Set days to remainder(days, 7). - days = fmod(days, 7); - } - - // i. Return ! CreateDateDurationRecord(0, 0, weeks, days). - return create_date_duration_record(0, 0, weeks, days); - } -} - -// 3.5.4 RegulateISODate ( year, month, day, overflow ), https://tc39.es/proposal-temporal/#sec-temporal-regulateisodate -ThrowCompletionOr regulate_iso_date(VM& vm, double year, double month, double day, StringView overflow) -{ - VERIFY(year == trunc(year) && month == trunc(month) && day == trunc(day)); - - // 1. If overflow is "constrain", then - if (overflow == "constrain"sv) { - // IMPLEMENTATION DEFINED: This is an optimization that allows us to treat this double as normal integer from this point onwards. This - // does not change the exposed behavior as the parent's call to CreateTemporalDate will immediately check that this value is a valid - // ISO value for years: -273975 - 273975, which is a subset of this check. - if (!AK::is_within_range(year)) - return vm.throw_completion(ErrorType::TemporalInvalidPlainDate); - - // a. Set month to the result of clamping month between 1 and 12. - month = clamp(month, 1, 12); - - // b. Let daysInMonth be ! ISODaysInMonth(year, month). - auto days_in_month = iso_days_in_month(static_cast(year), static_cast(month)); - - // c. Set day to the result of clamping day between 1 and daysInMonth. - day = clamp(day, 1, days_in_month); - - // d. Return CreateISODateRecord(year, month, day). - return create_iso_date_record(static_cast(year), static_cast(month), static_cast(day)); - } - // 2. Else, - else { - // a. Assert: overflow is "reject". - VERIFY(overflow == "reject"sv); - - // 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 behavior as the call to IsValidISODate will immediately check that these values are valid ISO - // values (for years: -273975 - 273975, for months: 1 - 12, for days: 1 - 31) all of which are subsets of this check. - if (!AK::is_within_range(year) || !AK::is_within_range(month) || !AK::is_within_range(day)) - return vm.throw_completion(ErrorType::TemporalInvalidPlainDate); - - auto y = static_cast(year); - auto m = static_cast(month); - auto d = static_cast(day); - // b. If IsValidISODate(year, month, day) is false, throw a RangeError exception. - if (!is_valid_iso_date(y, m, d)) - return vm.throw_completion(ErrorType::TemporalInvalidPlainDate); - - // c. Return the Record { [[Year]]: year, [[Month]]: month, [[Day]]: day }. - return ISODateRecord { .year = y, .month = m, .day = d }; - } -} - -// 3.5.5 IsValidISODate ( year, month, day ), https://tc39.es/proposal-temporal/#sec-temporal-isvalidisodate -bool is_valid_iso_date(i32 year, u8 month, u8 day) -{ - // 1. If month < 1 or month > 12, then - if (month < 1 || month > 12) { - // a. Return false. - return false; - } - - // 2. Let daysInMonth be ! ISODaysInMonth(year, month). - auto days_in_month = iso_days_in_month(year, month); - - // 3. If day < 1 or day > daysInMonth, then - if (day < 1 || day > days_in_month) { - // a. Return false. - return false; - } - - // 4. Return true. - return true; -} - -// 3.5.6 DifferenceDate ( calendarRec, one, two, options ), https://tc39.es/proposal-temporal/#sec-temporal-differencedate -ThrowCompletionOr> difference_date(VM& vm, CalendarMethods const& calendar_record, PlainDate const& one, PlainDate const& two, Object const& options) -{ - // FIXME: 1. Assert: one.[[Calendar]] and two.[[Calendar]] have been determined to be equivalent as with CalendarEquals. - // FIXME: 2. Assert: options is an ordinary Object. - - // 3. Assert: options.[[Prototype]] is null. - VERIFY(!options.prototype()); - - // 4. Assert: options has a "largestUnit" data property. - VERIFY(MUST(options.has_own_property(vm.names.largestUnit))); - - // 5. If one.[[ISOYear]] = two.[[ISOYear]] and one.[[ISOMonth]] = two.[[ISOMonth]] and one.[[ISODay]] = two.[[ISODay]], then - if (one.iso_year() == two.iso_year() && one.iso_month() == two.iso_month() && one.iso_day() == two.iso_day()) { - // a. Return ! CreateTemporalDuration(0, 0, 0, 0, 0, 0, 0, 0, 0, 0). - return MUST(create_temporal_duration(vm, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)); - } - - // 6. If ! Get(options, "largestUnit") is "day", then - auto largest_unit = MUST(options.get(vm.names.largestUnit)); - if (largest_unit.is_string() && largest_unit.as_string().utf8_string_view() == "day"sv) { - // a. Let days be DaysUntil(one, two). - auto days = days_until(one, two); - - // b. Return ! CreateTemporalDuration(0, 0, 0, days, 0, 0, 0, 0, 0, 0). - return MUST(create_temporal_duration(vm, 0, 0, 0, days, 0, 0, 0, 0, 0, 0)); - } - - // 7. Return ? CalendarDateUntil(calendarRec, one, two, options). - return TRY(calendar_date_until(vm, calendar_record, Value { &one }, Value { &two }, options)); -} - -// 3.5.6 BalanceISODate ( year, month, day ), https://tc39.es/proposal-temporal/#sec-temporal-balanceisodate -ISODateRecord balance_iso_date(double year, double month, double day) -{ - // 1. Let epochDays be MakeDay(𝔽(year), 𝔽(month - 1), 𝔽(day)). - auto epoch_days = make_day(year, month - 1, day); - - // 2. Assert: epochDays is finite. - VERIFY(isfinite(epoch_days)); - - // 3. Let ms be MakeDate(epochDays, +0𝔽). - auto ms = make_date(epoch_days, 0); - - // 4. Return CreateISODateRecord(ℝ(YearFromTime(ms)), ℝ(MonthFromTime(ms)) + 1, ℝ(DateFromTime(ms))). - return create_iso_date_record(year_from_time(ms), static_cast(month_from_time(ms) + 1), date_from_time(ms)); -} - -// 3.5.7 PadISOYear ( y ), https://tc39.es/proposal-temporal/#sec-temporal-padisoyear -ThrowCompletionOr pad_iso_year(VM& vm, i32 y) -{ - // 1. Assert: y is an integer. - - // 2. If y ≥ 0 and y ≤ 9999, then - if (y >= 0 && y <= 9999) { - // a. Return ToZeroPaddedDecimalString(y, 4). - return TRY_OR_THROW_OOM(vm, String::formatted("{:04}", y)); - } - - // 3. If y > 0, let yearSign be "+"; otherwise, let yearSign be "-". - auto year_sign = y > 0 ? '+' : '-'; - - // 4. Let year be ToZeroPaddedDecimalString(abs(y), 6). - // 5. Return the string-concatenation of yearSign and year. - return TRY_OR_THROW_OOM(vm, String::formatted("{}{:06}", year_sign, abs(y))); -} - -// 3.5.8 TemporalDateToString ( temporalDate, showCalendar ), https://tc39.es/proposal-temporal/#sec-temporal-temporaldatetostring -ThrowCompletionOr temporal_date_to_string(VM& vm, PlainDate& temporal_date, StringView show_calendar) -{ - // 1. Assert: Type(temporalDate) is Object. - // 2. Assert: temporalDate has an [[InitializedTemporalDate]] internal slot. - - // 3. Let year be ! PadISOYear(temporalDate.[[ISOYear]]). - auto year = MUST_OR_THROW_OOM(pad_iso_year(vm, temporal_date.iso_year())); - - // 4. Let month be ToZeroPaddedDecimalString(monthDay.[[ISOMonth]], 2). - auto month = TRY_OR_THROW_OOM(vm, String::formatted("{:02}", temporal_date.iso_month())); - - // 5. Let day be ToZeroPaddedDecimalString(monthDay.[[ISODay]], 2). - auto day = TRY_OR_THROW_OOM(vm, String::formatted("{:02}", temporal_date.iso_day())); - - // 6. Let calendar be ? MaybeFormatCalendarAnnotation(temporalDate.[[Calendar]], showCalendar). - auto calendar = TRY(maybe_format_calendar_annotation(vm, &temporal_date.calendar(), show_calendar)); - - // 7. Return the string-concatenation of year, the code unit 0x002D (HYPHEN-MINUS), month, the code unit 0x002D (HYPHEN-MINUS), day, and calendar. - return TRY_OR_THROW_OOM(vm, String::formatted("{}-{}-{}{}", year, month, day, calendar)); -} - -// 3.5.9 AddISODate ( year, month, day, years, months, weeks, days, overflow ), https://tc39.es/proposal-temporal/#sec-temporal-addisodate -ThrowCompletionOr add_iso_date(VM& vm, i32 year, u8 month, u8 day, double years, double months, double weeks, double days, StringView overflow) -{ - // 1. Assert: year, month, day, years, months, weeks, and days are integers. - VERIFY(years == trunc(years) && months == trunc(months) && weeks == trunc(weeks) && days == trunc(days)); - - // 2. Assert: overflow is either "constrain" or "reject". - VERIFY(overflow == "constrain"sv || overflow == "reject"sv); - - // 3. Let intermediate be ! BalanceISOYearMonth(year + years, month + months). - auto intermediate_year_month = balance_iso_year_month(year + years, month + months); - - // 4. Let intermediate be ? RegulateISODate(intermediate.[[Year]], intermediate.[[Month]], day, overflow). - auto intermediate = TRY(regulate_iso_date(vm, intermediate_year_month.year, intermediate_year_month.month, day, overflow)); - - // 5. Set days to days + 7 × weeks. - days += 7 * weeks; - - // 6. Let d be intermediate.[[Day]] + days. - auto d = intermediate.day + days; - - // 7. Return BalanceISODate(intermediate.[[Year]], intermediate.[[Month]], d). - return balance_iso_date(intermediate.year, intermediate.month, d); -} - -// 3.5.10 CompareISODate ( y1, m1, d1, y2, m2, d2 ), https://tc39.es/proposal-temporal/#sec-temporal-compareisodate -i8 compare_iso_date(i32 year1, u8 month1, u8 day1, i32 year2, u8 month2, u8 day2) -{ - // 1. Assert: y1, m1, d1, y2, m2, and d2 are integers. - - // 2. If y1 > y2, return 1. - if (year1 > year2) - return 1; - - // 3. If y1 < y2, return -1. - if (year1 < year2) - return -1; - - // 4. If m1 > m2, return 1. - if (month1 > month2) - return 1; - - // 5. If m1 < m2, return -1. - if (month1 < month2) - return -1; - - // 6. If d1 > d2, return 1. - if (day1 > day2) - return 1; - - // 7. If d1 < d2, return -1. - if (day1 < day2) - return -1; - - // 8. Return 0. - return 0; -} - -// 3.5.11 DifferenceTemporalPlainDate ( operation, temporalDate, other, options ), https://tc39.es/proposal-temporal/#sec-temporal-differencetemporalplaindate -ThrowCompletionOr> difference_temporal_plain_date(VM& vm, DifferenceOperation operation, PlainDate& temporal_date, Value other_value, Value options) -{ - // 1. If operation is SINCE, let sign be -1. Otherwise, let sign be 1. - i8 sign = operation == DifferenceOperation::Since ? -1 : 1; - - // 2. Set other to ? ToTemporalDate(other). - auto* other = TRY(to_temporal_date(vm, other_value)); - - // 3. If ? CalendarEquals(temporalDate.[[Calendar]], other.[[Calendar]]) is false, throw a RangeError exception. - if (!TRY(calendar_equals(vm, temporal_date.calendar(), other->calendar()))) - return vm.throw_completion(ErrorType::TemporalDifferentCalendars); - - // 4. Let resolvedOptions be ? SnapshotOwnProperties(? GetOptionsObject(options), null). - auto resolved_options = TRY(TRY(get_options_object(vm, options))->snapshot_own_properties(vm, nullptr)); - - // 5. Let settings be ? GetDifferenceSettings(operation, resolvedOptions, DATE, « », "day", "day"). - auto settings = TRY(get_difference_settings(vm, operation, resolved_options, UnitGroup::Date, {}, { "day"sv }, "day"sv)); - - // 6. If temporalDate.[[ISOYear]] = other.[[ISOYear]], and temporalDate.[[ISOMonth]] = other.[[ISOMonth]], and temporalDate.[[ISODay]] = other.[[ISODay]], then - if (temporal_date.iso_year() == other->iso_year() && temporal_date.iso_month() == other->iso_month() && temporal_date.iso_day() == other->iso_day()) { - // a. Return ! CreateTemporalDuration(0, 0, 0, 0, 0, 0, 0, 0, 0, 0). - return MUST(create_temporal_duration(vm, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)); - } - - // 7. Let calendarRec be ? CreateCalendarMethodsRecord(temporalDate.[[Calendar]], « DATE-ADD, DATE-UNTIL »). - // FIXME: The type of calendar in PlainDate does not align with latest spec - auto calendar_record = TRY(create_calendar_methods_record(vm, GC::Ref { temporal_date.calendar() }, { { CalendarMethod::DateAdd, CalendarMethod::DateUntil } })); - - // 8. Perform ! CreateDataPropertyOrThrow(resolvedOptions, "largestUnit", settings.[[LargestUnit]]). - MUST(resolved_options->create_data_property_or_throw(vm.names.largestUnit, PrimitiveString::create(vm, settings.largest_unit))); - - // 9. Let result be ? DifferenceDate(calendarRec, temporalDate, other, resolvedOptions). - auto result = TRY(difference_date(vm, calendar_record, temporal_date, *other, resolved_options)); - - // 10. If settings.[[SmallestUnit]] is "day" and settings.[[RoundingIncrement]] = 1, let roundingGranularityIsNoop be true; else let roundingGranularityIsNoop be false. - bool rounding_granularity_is_noop = settings.smallest_unit == "day"sv && settings.rounding_increment == 1; - - // 11. If roundingGranularityIsNoop is false, then - if (!rounding_granularity_is_noop) { - // a. Let roundRecord be ? RoundDuration(result.[[Years]], result.[[Months]], result.[[Weeks]], result.[[Days]], ZeroTimeDuration(), settings.[[RoundingIncrement]], settings.[[SmallestUnit]], settings.[[RoundingMode]], temporalDate, calendarRec). - auto round_record = TRY(round_duration(vm, result->years(), result->months(), result->weeks(), result->days(), 0, 0, 0, 0, 0, 0, settings.rounding_increment, settings.smallest_unit, settings.rounding_mode, &temporal_date, calendar_record)).duration_record; - - // FIXME: b. Let roundResult be roundRecord.[[NormalizedDuration]]. - // FIXME: c. Set result to ? BalanceDateDurationRelative(roundResult.[[Years]], roundResult.[[Months]], roundResult.[[Weeks]], roundResult.[[Days]], settings.[[LargestUnit]], settings.[[SmallestUnit]], temporalDate, calendarRec). - result = MUST(create_temporal_duration(vm, round_record.years, round_record.months, round_record.weeks, round_record.days, 0, 0, 0, 0, 0, 0)); - } - - // 16. Return ! CreateTemporalDuration(sign × result.[[Years]], sign × result.[[Months]], sign × result.[[Weeks]], sign × result.[[Days]], 0, 0, 0, 0, 0, 0). - return MUST(create_temporal_duration(vm, sign * result->years(), sign * result->months(), sign * result->weeks(), sign * result->days(), 0, 0, 0, 0, 0, 0)); -} - -} diff --git a/Libraries/LibJS/Runtime/Temporal/PlainDate.h b/Libraries/LibJS/Runtime/Temporal/PlainDate.h deleted file mode 100644 index 3fa52469ef5..00000000000 --- a/Libraries/LibJS/Runtime/Temporal/PlainDate.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2021, Idan Horowitz - * Copyright (c) 2021-2023, Linus Groh - * Copyright (c) 2024, Shannon Booth - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include -#include -#include -#include - -namespace JS::Temporal { - -class PlainDate final : public Object { - JS_OBJECT(PlainDate, Object); - GC_DECLARE_ALLOCATOR(PlainDate); - -public: - virtual ~PlainDate() override = default; - - [[nodiscard]] i32 iso_year() const { return m_iso_year; } - [[nodiscard]] u8 iso_month() const { return m_iso_month; } - [[nodiscard]] u8 iso_day() const { return m_iso_day; } - [[nodiscard]] Object const& calendar() const { return m_calendar; } - [[nodiscard]] Object& calendar() { return m_calendar; } - -private: - PlainDate(i32 iso_year, u8 iso_month, u8 iso_day, Object& calendar, Object& prototype); - - virtual void visit_edges(Visitor&) override; - - // 3.4 Properties of Temporal.PlainDate Instances, https://tc39.es/proposal-temporal/#sec-properties-of-temporal-plaindate-instances - i32 m_iso_year { 0 }; // [[ISOYear]] - u8 m_iso_month { 1 }; // [[ISOMonth]] - u8 m_iso_day { 1 }; // [[ISODay]] - GC::Ref m_calendar; // [[Calendar]] -}; - -// 3.5.1 ISO Date Records, https://tc39.es/proposal-temporal/#sec-temporal-iso-date-records -struct ISODateRecord { - i32 year; - u8 month; - u8 day; -}; - -ISODateRecord create_iso_date_record(i32 year, u8 month, u8 day); -ThrowCompletionOr create_temporal_date(VM&, i32 iso_year, u8 iso_month, u8 iso_day, Object& calendar, FunctionObject const* new_target = nullptr); -ThrowCompletionOr to_temporal_date(VM&, Value item, Object const* options = nullptr); -DateDurationRecord difference_iso_date(VM&, i32 year1, u8 month1, u8 day1, i32 year2, u8 month2, u8 day2, StringView largest_unit); -ThrowCompletionOr regulate_iso_date(VM&, double year, double month, double day, StringView overflow); -bool is_valid_iso_date(i32 year, u8 month, u8 day); -ISODateRecord balance_iso_date(double year, double month, double day); -ThrowCompletionOr pad_iso_year(VM&, i32 y); -ThrowCompletionOr temporal_date_to_string(VM&, PlainDate&, StringView show_calendar); -ThrowCompletionOr add_iso_date(VM&, i32 year, u8 month, u8 day, double years, double months, double weeks, double days, StringView overflow); -i8 compare_iso_date(i32 year1, u8 month1, u8 day1, i32 year2, u8 month2, u8 day2); -ThrowCompletionOr> difference_temporal_plain_date(VM&, DifferenceOperation, PlainDate&, Value other, Value options); -ThrowCompletionOr> difference_date(VM& vm, CalendarMethods const&, PlainDate const& one, PlainDate const& two, Object const& options); - -} diff --git a/Libraries/LibJS/Runtime/Temporal/PlainDateConstructor.cpp b/Libraries/LibJS/Runtime/Temporal/PlainDateConstructor.cpp deleted file mode 100644 index b40bf0aae97..00000000000 --- a/Libraries/LibJS/Runtime/Temporal/PlainDateConstructor.cpp +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (c) 2021, Idan Horowitz - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include -#include -#include -#include -#include -#include -#include - -namespace JS::Temporal { - -GC_DEFINE_ALLOCATOR(PlainDateConstructor); - -// 3.1 The Temporal.PlainDate Constructor, https://tc39.es/proposal-temporal/#sec-temporal-plaindate-constructor -PlainDateConstructor::PlainDateConstructor(Realm& realm) - : NativeFunction(realm.vm().names.PlainDate.as_string(), realm.intrinsics().function_prototype()) -{ -} - -void PlainDateConstructor::initialize(Realm& realm) -{ - Base::initialize(realm); - - auto& vm = this->vm(); - - // 3.2.1 Temporal.PlainDate.prototype, https://tc39.es/proposal-temporal/#sec-temporal.plaindate.prototype - define_direct_property(vm.names.prototype, realm.intrinsics().temporal_plain_date_prototype(), 0); - - u8 attr = Attribute::Writable | Attribute::Configurable; - define_native_function(realm, vm.names.from, from, 1, attr); - define_native_function(realm, vm.names.compare, compare, 2, attr); - - define_direct_property(vm.names.length, Value(3), Attribute::Configurable); -} - -// 3.1.1 Temporal.PlainDate ( isoYear, isoMonth, isoDay [ , calendarLike ] ), https://tc39.es/proposal-temporal/#sec-temporal.plaindate -ThrowCompletionOr PlainDateConstructor::call() -{ - auto& vm = this->vm(); - - // 1. If NewTarget is undefined, throw a TypeError exception. - return vm.throw_completion(ErrorType::ConstructorWithoutNew, "Temporal.PlainDate"); -} - -// 3.1.1 Temporal.PlainDate ( isoYear, isoMonth, isoDay [ , calendarLike ] ), https://tc39.es/proposal-temporal/#sec-temporal.plaindate -ThrowCompletionOr> PlainDateConstructor::construct(FunctionObject& new_target) -{ - auto& vm = this->vm(); - - // 2. Let y be ? ToIntegerWithTruncation(isoYear). - auto y = TRY(to_integer_with_truncation(vm, vm.argument(0), ErrorType::TemporalInvalidPlainDate)); - - // 3. Let m be ? ToIntegerWithTruncation(isoMonth). - auto m = TRY(to_integer_with_truncation(vm, vm.argument(1), ErrorType::TemporalInvalidPlainDate)); - - // 4. Let d be ? ToIntegerWithTruncation(isoDay). - auto d = TRY(to_integer_with_truncation(vm, vm.argument(2), ErrorType::TemporalInvalidPlainDate)); - - // 5. Let calendar be ? ToTemporalCalendarWithISODefault(calendarLike). - auto* calendar = TRY(to_temporal_calendar_with_iso_default(vm, vm.argument(3))); - - // 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 behavior as the call to CreateTemporalDate will immediately check that these values are valid - // ISO values (for years: -273975 - 273975, for months: 1 - 12, for days: 1 - 31) all of which are subsets of this check. - if (!AK::is_within_range(y) || !AK::is_within_range(m) || !AK::is_within_range(d)) - return vm.throw_completion(ErrorType::TemporalInvalidPlainDate); - - // 6. Return ? CreateTemporalDate(y, m, d, calendar, NewTarget). - return *TRY(create_temporal_date(vm, y, m, d, *calendar, &new_target)); -} - -// 3.2.2 Temporal.PlainDate.from ( item [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal.plaindate.from -JS_DEFINE_NATIVE_FUNCTION(PlainDateConstructor::from) -{ - // 1. Set options to ? GetOptionsObject(options). - auto const* options = TRY(get_options_object(vm, vm.argument(1))); - - auto item = vm.argument(0); - // 2. If Type(item) is Object and item has an [[InitializedTemporalDate]] internal slot, then - if (item.is_object() && is(item.as_object())) { - auto& plain_date_item = static_cast(item.as_object()); - // a. Perform ? ToTemporalOverflow(options). - (void)TRY(to_temporal_overflow(vm, options)); - - // b. Return ! CreateTemporalDate(item.[[ISOYear]], item.[[ISOMonth]], item.[[ISODay]], item.[[Calendar]]). - return MUST(create_temporal_date(vm, plain_date_item.iso_year(), plain_date_item.iso_month(), plain_date_item.iso_day(), plain_date_item.calendar())); - } - - // 3. Return ? ToTemporalDate(item, options). - return TRY(to_temporal_date(vm, item, options)); -} - -// 3.2.3 Temporal.PlainDate.compare ( one, two ), https://tc39.es/proposal-temporal/#sec-temporal.plaindate.compare -JS_DEFINE_NATIVE_FUNCTION(PlainDateConstructor::compare) -{ - // 1. Set one to ? ToTemporalDate(one). - auto* one = TRY(to_temporal_date(vm, vm.argument(0))); - - // 2. Set two to ? ToTemporalDate(two). - auto* two = TRY(to_temporal_date(vm, vm.argument(1))); - - // 3. Return 𝔽(! CompareISODate(one.[[ISOYear]], one.[[ISOMonth]], one.[[ISODay]], two.[[ISOYear]], two.[[ISOMonth]], two.[[ISODay]])). - return Value(compare_iso_date(one->iso_year(), one->iso_month(), one->iso_day(), two->iso_year(), two->iso_month(), two->iso_day())); -} - -} diff --git a/Libraries/LibJS/Runtime/Temporal/PlainDateConstructor.h b/Libraries/LibJS/Runtime/Temporal/PlainDateConstructor.h deleted file mode 100644 index e6a7943d137..00000000000 --- a/Libraries/LibJS/Runtime/Temporal/PlainDateConstructor.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2021, Idan Horowitz - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include - -namespace JS::Temporal { - -class PlainDateConstructor final : public NativeFunction { - JS_OBJECT(PlainDateConstructor, NativeFunction); - GC_DECLARE_ALLOCATOR(PlainDateConstructor); - -public: - virtual void initialize(Realm&) override; - virtual ~PlainDateConstructor() override = default; - - virtual ThrowCompletionOr call() override; - virtual ThrowCompletionOr> construct(FunctionObject& new_target) override; - -private: - explicit PlainDateConstructor(Realm&); - - virtual bool has_constructor() const override { return true; } - - JS_DECLARE_NATIVE_FUNCTION(from); - JS_DECLARE_NATIVE_FUNCTION(compare); -}; - -} diff --git a/Libraries/LibJS/Runtime/Temporal/PlainDatePrototype.cpp b/Libraries/LibJS/Runtime/Temporal/PlainDatePrototype.cpp deleted file mode 100644 index 759c77c983d..00000000000 --- a/Libraries/LibJS/Runtime/Temporal/PlainDatePrototype.cpp +++ /dev/null @@ -1,665 +0,0 @@ -/* - * Copyright (c) 2021, Idan Horowitz - * Copyright (c) 2021-2023, Linus Groh - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace JS::Temporal { - -GC_DEFINE_ALLOCATOR(PlainDatePrototype); - -// 3.3 Properties of the Temporal.PlainDate Prototype Object, https://tc39.es/proposal-temporal/#sec-properties-of-the-temporal-plaindate-prototype-object -PlainDatePrototype::PlainDatePrototype(Realm& realm) - : PrototypeObject(realm.intrinsics().object_prototype()) -{ -} - -void PlainDatePrototype::initialize(Realm& realm) -{ - Base::initialize(realm); - - auto& vm = this->vm(); - - // 3.3.2 Temporal.PlainDate.prototype[ @@toStringTag ], https://tc39.es/proposal-temporal/#sec-temporal.plaindate.prototype-@@tostringtag - define_direct_property(vm.well_known_symbol_to_string_tag(), PrimitiveString::create(vm, "Temporal.PlainDate"_string), Attribute::Configurable); - - define_native_accessor(realm, vm.names.calendar, calendar_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.year, year_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.month, month_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.monthCode, month_code_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.day, day_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.dayOfWeek, day_of_week_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.dayOfYear, day_of_year_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.weekOfYear, week_of_year_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.yearOfWeek, year_of_week_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.daysInWeek, days_in_week_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.daysInMonth, days_in_month_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.daysInYear, days_in_year_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.monthsInYear, months_in_year_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.inLeapYear, in_leap_year_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.era, era_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.eraYear, era_year_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.calendarId, calendar_id_getter, {}, Attribute::Configurable); - - u8 attr = Attribute::Writable | Attribute::Configurable; - define_native_function(realm, vm.names.toPlainYearMonth, to_plain_year_month, 0, attr); - define_native_function(realm, vm.names.toPlainMonthDay, to_plain_month_day, 0, attr); - define_native_function(realm, vm.names.getISOFields, get_iso_fields, 0, attr); - define_native_function(realm, vm.names.add, add, 1, attr); - define_native_function(realm, vm.names.subtract, subtract, 1, attr); - define_native_function(realm, vm.names.with, with, 1, attr); - define_native_function(realm, vm.names.withCalendar, with_calendar, 1, attr); - define_native_function(realm, vm.names.until, until, 1, attr); - define_native_function(realm, vm.names.since, since, 1, attr); - define_native_function(realm, vm.names.equals, equals, 1, attr); - define_native_function(realm, vm.names.toPlainDateTime, to_plain_date_time, 0, attr); - define_native_function(realm, vm.names.toZonedDateTime, to_zoned_date_time, 1, attr); - define_native_function(realm, vm.names.toString, to_string, 0, attr); - define_native_function(realm, vm.names.toLocaleString, to_locale_string, 0, attr); - define_native_function(realm, vm.names.toJSON, to_json, 0, attr); - define_native_function(realm, vm.names.valueOf, value_of, 0, attr); -} - -// 3.3.3 get Temporal.PlainDate.prototype.calendar, https://tc39.es/proposal-temporal/#sec-get-temporal.plaindate.prototype.calendar -JS_DEFINE_NATIVE_FUNCTION(PlainDatePrototype::calendar_getter) -{ - // 1. Let temporalDate be the this value. - // 2. Perform ? RequireInternalSlot(temporalDate, [[InitializedTemporalDate]]). - auto temporal_date = TRY(typed_this_object(vm)); - - // 3. Return temporalDate.[[Calendar]]. - return Value(&temporal_date->calendar()); -} - -// 3.3.4 get Temporal.PlainDate.prototype.year, https://tc39.es/proposal-temporal/#sec-get-temporal.plaindate.prototype.year -JS_DEFINE_NATIVE_FUNCTION(PlainDatePrototype::year_getter) -{ - // 1. Let temporalDate be the this value. - // 2. Perform ? RequireInternalSlot(temporalDate, [[InitializedTemporalDate]]). - auto temporal_date = TRY(typed_this_object(vm)); - - // 3. Let calendar be temporalDate.[[Calendar]]. - auto& calendar = temporal_date->calendar(); - - // 4. Return 𝔽(? CalendarYear(calendar, temporalDate)). - return TRY(calendar_year(vm, calendar, temporal_date)); -} - -// 3.3.5 get Temporal.PlainDate.prototype.month, https://tc39.es/proposal-temporal/#sec-get-temporal.plaindate.prototype.month -JS_DEFINE_NATIVE_FUNCTION(PlainDatePrototype::month_getter) -{ - // 1. Let temporalDate be the this value. - // 2. Perform ? RequireInternalSlot(temporalDate, [[InitializedTemporalDate]]). - auto temporal_date = TRY(typed_this_object(vm)); - - // 3. Let calendar be temporalDate.[[Calendar]]. - auto& calendar = temporal_date->calendar(); - - // 4. Return 𝔽(? CalendarMonth(calendar, temporalDate)). - return TRY(calendar_month(vm, calendar, temporal_date)); -} - -// 3.3.6 get Temporal.PlainDate.prototype.monthCode, https://tc39.es/proposal-temporal/#sec-get-temporal.plaindate.prototype.monthCode -JS_DEFINE_NATIVE_FUNCTION(PlainDatePrototype::month_code_getter) -{ - // 1. Let temporalDate be the this value. - // 2. Perform ? RequireInternalSlot(temporalDate, [[InitializedTemporalDate]]). - auto temporal_date = TRY(typed_this_object(vm)); - - // 3. Let calendar be temporalDate.[[Calendar]]. - auto& calendar = temporal_date->calendar(); - - // 4. Return ? CalendarMonthCode(calendar, temporalDate). - return PrimitiveString::create(vm, TRY(calendar_month_code(vm, calendar, temporal_date))); -} - -// 3.3.7 get Temporal.PlainDate.prototype.day, https://tc39.es/proposal-temporal/#sec-get-temporal.plaindate.prototype.day -JS_DEFINE_NATIVE_FUNCTION(PlainDatePrototype::day_getter) -{ - // 1. Let temporalDate be the this value. - // 2. Perform ? RequireInternalSlot(temporalDate, [[InitializedTemporalDate]]). - auto temporal_date = TRY(typed_this_object(vm)); - - // 3. Let calendar be temporalDate.[[Calendar]]. - auto& calendar = temporal_date->calendar(); - - // 4. Return 𝔽(? CalendarDay(calendar, temporalDate)). - return TRY(calendar_day(vm, calendar, temporal_date)); -} - -// 3.3.8 get Temporal.PlainDate.prototype.dayOfWeek, https://tc39.es/proposal-temporal/#sec-get-temporal.plaindate.prototype.dayofweek -JS_DEFINE_NATIVE_FUNCTION(PlainDatePrototype::day_of_week_getter) -{ - // 1. Let temporalDate be the this value. - // 2. Perform ? RequireInternalSlot(temporalDate, [[InitializedTemporalDate]]). - auto temporal_date = TRY(typed_this_object(vm)); - - // 3. Let calendar be temporalDate.[[Calendar]]. - auto& calendar = temporal_date->calendar(); - - // Return 𝔽(? CalendarDayOfWeek(calendar, temporalDate)). - return TRY(calendar_day_of_week(vm, calendar, temporal_date)); -} - -// 3.3.9 get Temporal.PlainDate.prototype.dayOfYear, https://tc39.es/proposal-temporal/#sec-get-temporal.plaindate.prototype.dayofyear -JS_DEFINE_NATIVE_FUNCTION(PlainDatePrototype::day_of_year_getter) -{ - // 1. Let temporalDate be the this value. - // 2. Perform ? RequireInternalSlot(temporalDate, [[InitializedTemporalDate]]). - auto temporal_date = TRY(typed_this_object(vm)); - - // 3. Let calendar be temporalDate.[[Calendar]]. - auto& calendar = temporal_date->calendar(); - - // 4. Return 𝔽(? CalendarDayOfYear(calendar, temporalDate)). - return TRY(calendar_day_of_year(vm, calendar, temporal_date)); -} - -// 3.3.10 get Temporal.PlainDate.prototype.weekOfYear, https://tc39.es/proposal-temporal/#sec-get-temporal.plaindate.prototype.weekofyear -JS_DEFINE_NATIVE_FUNCTION(PlainDatePrototype::week_of_year_getter) -{ - // 1. Let temporalDate be the this value. - // 2. Perform ? RequireInternalSlot(temporalDate, [[InitializedTemporalDate]]). - auto temporal_date = TRY(typed_this_object(vm)); - - // 3. Let calendar be temporalDate.[[Calendar]]. - auto& calendar = temporal_date->calendar(); - - // 4. Return 𝔽(? CalendarWeekOfYear(calendar, temporalDate)). - return TRY(calendar_week_of_year(vm, calendar, temporal_date)); -} - -// 3.3.11 get Temporal.PlainDate.prototype.yearOfWeek, https://tc39.es/proposal-temporal/#sec-get-temporal.plaindate.prototype.yearofweek -JS_DEFINE_NATIVE_FUNCTION(PlainDatePrototype::year_of_week_getter) -{ - // 1. Let temporalDate be the this value. - // 2. Perform ? RequireInternalSlot(temporalDate, [[InitializedTemporalDate]]). - auto temporal_date = TRY(typed_this_object(vm)); - - // 3. Let calendar be temporalDate.[[Calendar]]. - auto& calendar = temporal_date->calendar(); - - // 4. Return 𝔽(? CalendarYearOfWeek(calendar, temporalDate)). - return TRY(calendar_year_of_week(vm, calendar, temporal_date)); -} - -// 3.3.12 get Temporal.PlainDate.prototype.daysInWeek, https://tc39.es/proposal-temporal/#sec-get-temporal.plaindate.prototype.daysinweek -JS_DEFINE_NATIVE_FUNCTION(PlainDatePrototype::days_in_week_getter) -{ - // 1. Let temporalDate be the this value. - // 2. Perform ? RequireInternalSlot(temporalDate, [[InitializedTemporalDate]]). - auto temporal_date = TRY(typed_this_object(vm)); - - // 3. Let calendar be temporalDate.[[Calendar]]. - auto& calendar = temporal_date->calendar(); - - // 4. Return 𝔽(? CalendarDaysInWeek(calendar, temporalDate)). - return TRY(calendar_days_in_week(vm, calendar, temporal_date)); -} - -// 3.3.13 get Temporal.PlainDate.prototype.daysInMonth, https://tc39.es/proposal-temporal/#sec-get-temporal.plaindate.prototype.daysinmonth -JS_DEFINE_NATIVE_FUNCTION(PlainDatePrototype::days_in_month_getter) -{ - // 1. Let temporalDate be the this value. - // 2. Perform ? RequireInternalSlot(temporalDate, [[InitializedTemporalDate]]). - auto temporal_date = TRY(typed_this_object(vm)); - - // 3. Let calendar be temporalDate.[[Calendar]]. - auto& calendar = temporal_date->calendar(); - - // 4. Return 𝔽(? CalendarDaysInMonth(calendar, temporalDate)). - return TRY(calendar_days_in_month(vm, calendar, temporal_date)); -} - -// 3.3.14 get Temporal.PlainDate.prototype.daysInYear, https://tc39.es/proposal-temporal/#sec-get-temporal.plaindate.prototype.daysinyear -JS_DEFINE_NATIVE_FUNCTION(PlainDatePrototype::days_in_year_getter) -{ - // 1. Let temporalDate be the this value. - // 2. Perform ? RequireInternalSlot(temporalDate, [[InitializedTemporalDate]]). - auto temporal_date = TRY(typed_this_object(vm)); - - // 3. Let calendar be temporalDate.[[Calendar]]. - auto& calendar = temporal_date->calendar(); - - // 4. Return 𝔽(? CalendarDaysInYear(calendar, temporalDate)). - return TRY(calendar_days_in_year(vm, calendar, temporal_date)); -} - -// 3.3.15 get Temporal.PlainDate.prototype.monthsInYear, https://tc39.es/proposal-temporal/#sec-get-temporal.plaindate.prototype.monthsinyear -JS_DEFINE_NATIVE_FUNCTION(PlainDatePrototype::months_in_year_getter) -{ - // 1. Let temporalDate be the this value. - // 2. Perform ? RequireInternalSlot(temporalDate, [[InitializedTemporalDate]]). - auto temporal_date = TRY(typed_this_object(vm)); - - // 3. Let calendar be temporalDate.[[Calendar]]. - auto& calendar = temporal_date->calendar(); - - // 4. Return 𝔽(? CalendarMonthsInYear(calendar, temporalDate)). - return TRY(calendar_months_in_year(vm, calendar, temporal_date)); -} - -// 3.3.16 get Temporal.PlainDate.prototype.inLeapYear, https://tc39.es/proposal-temporal/#sec-get-temporal.plaindate.prototype.inleapyear -JS_DEFINE_NATIVE_FUNCTION(PlainDatePrototype::in_leap_year_getter) -{ - // 1. Let temporalDate be the this value. - // 2. Perform ? RequireInternalSlot(temporalDate, [[InitializedTemporalDate]]). - auto temporal_date = TRY(typed_this_object(vm)); - - // 3. Let calendar be temporalDate.[[Calendar]]. - auto& calendar = temporal_date->calendar(); - - // 4. Return ? CalendarInLeapYear(calendar, temporalDate). - return Value(TRY(calendar_in_leap_year(vm, calendar, temporal_date))); -} - -// 15.6.5.2 get Temporal.PlainDate.prototype.era, https://tc39.es/proposal-temporal/#sec-get-temporal.plaindate.prototype.era -JS_DEFINE_NATIVE_FUNCTION(PlainDatePrototype::era_getter) -{ - // 1. Let plainDate be the this value. - // 2. Perform ? RequireInternalSlot(plainDate, [[InitializedTemporalDate]]). - auto plain_date = TRY(typed_this_object(vm)); - - // 3. Let calendar be plainDate.[[Calendar]]. - auto& calendar = plain_date->calendar(); - - // 4. Return ? CalendarEra(calendar, plainDate). - return TRY(calendar_era(vm, calendar, plain_date)); -} - -// 15.6.5.3 get Temporal.PlainDate.prototype.eraYear, https://tc39.es/proposal-temporal/#sec-get-temporal.plaindate.prototype.erayear -JS_DEFINE_NATIVE_FUNCTION(PlainDatePrototype::era_year_getter) -{ - // 1. Let plainDate be the this value. - // 2. Perform ? RequireInternalSlot(plainDate, [[InitializedTemporalDate]]). - auto plain_date = TRY(typed_this_object(vm)); - - // 3. Let calendar be plainDate.[[Calendar]]. - auto& calendar = plain_date->calendar(); - - // 4. Return ? CalendarEraYear(calendar, plainDate). - return TRY(calendar_era_year(vm, calendar, plain_date)); -} - -// 3.3.17 Temporal.PlainDate.prototype.toPlainYearMonth ( ), https://tc39.es/proposal-temporal/#sec-temporal.plaindate.prototype.toplainyearmonth -JS_DEFINE_NATIVE_FUNCTION(PlainDatePrototype::to_plain_year_month) -{ - // 1. Let temporalDate be the this value. - // 2. Perform ? RequireInternalSlot(temporalDate, [[InitializedTemporalDate]]). - auto temporal_date = TRY(typed_this_object(vm)); - - // 3. Let calendar be temporalDate.[[Calendar]]. - auto& calendar = temporal_date->calendar(); - - // 4. Let fieldNames be ? CalendarFields(calendar, « "monthCode", "year" »). - auto field_names = TRY(calendar_fields(vm, calendar, { "monthCode"sv, "year"sv })); - - // 5. Let fields be ? PrepareTemporalFields(temporalDate, fieldNames, «»). - auto* fields = TRY(prepare_temporal_fields(vm, temporal_date, field_names, Vector {})); - - // 6. Return ? CalendarYearMonthFromFields(calendar, fields). - return TRY(calendar_year_month_from_fields(vm, calendar, *fields)); -} - -// 3.3.18 Temporal.PlainDate.prototype.toPlainMonthDay ( ), https://tc39.es/proposal-temporal/#sec-temporal.plaindate.prototype.toplainmonthday -JS_DEFINE_NATIVE_FUNCTION(PlainDatePrototype::to_plain_month_day) -{ - // 1. Let temporalDate be the this value. - // 2. Perform ? RequireInternalSlot(temporalDate, [[InitializedTemporalDate]]). - auto temporal_date = TRY(typed_this_object(vm)); - - // 3. Let calendar be temporalDate.[[Calendar]]. - auto& calendar = temporal_date->calendar(); - - // 4. Let fieldNames be ? CalendarFields(calendar, « "day", "monthCode" »). - auto field_names = TRY(calendar_fields(vm, calendar, { "day"sv, "monthCode"sv })); - - // 5. Let fields be ? PrepareTemporalFields(temporalDate, fieldNames, «»). - auto* fields = TRY(prepare_temporal_fields(vm, temporal_date, field_names, Vector {})); - - // 6. Return ? CalendarMonthDayFromFields(calendar, fields). - return TRY(calendar_month_day_from_fields(vm, calendar, *fields)); -} - -// 3.3.19 Temporal.PlainDate.prototype.getISOFields ( ), https://tc39.es/proposal-temporal/#sec-temporal.plaindate.prototype.getisofields -JS_DEFINE_NATIVE_FUNCTION(PlainDatePrototype::get_iso_fields) -{ - auto& realm = *vm.current_realm(); - - // 1. Let temporalDate be the this value. - // 2. Perform ? RequireInternalSlot(temporalDate, [[InitializedTemporalDate]]). - auto temporal_date = TRY(typed_this_object(vm)); - - // 3. Let fields be OrdinaryObjectCreate(%Object.prototype%). - auto fields = Object::create(realm, realm.intrinsics().object_prototype()); - - // 4. Perform ! CreateDataPropertyOrThrow(fields, "calendar", temporalDate.[[Calendar]]). - MUST(fields->create_data_property_or_throw(vm.names.calendar, Value(&temporal_date->calendar()))); - - // 5. Perform ! CreateDataPropertyOrThrow(fields, "isoDay", 𝔽(temporalDate.[[ISODay]])). - MUST(fields->create_data_property_or_throw(vm.names.isoDay, Value(temporal_date->iso_day()))); - - // 6. Perform ! CreateDataPropertyOrThrow(fields, "isoMonth", 𝔽(temporalDate.[[ISOMonth]])). - MUST(fields->create_data_property_or_throw(vm.names.isoMonth, Value(temporal_date->iso_month()))); - - // 7. Perform ! CreateDataPropertyOrThrow(fields, "isoYear", 𝔽(temporalDate.[[ISOYear]])). - MUST(fields->create_data_property_or_throw(vm.names.isoYear, Value(temporal_date->iso_year()))); - - // 8. Return fields. - return fields; -} - -// 3.3.20 Temporal.PlainDate.prototype.add ( temporalDurationLike [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal.plaindate.prototype.add -JS_DEFINE_NATIVE_FUNCTION(PlainDatePrototype::add) -{ - // 1. Let temporalDate be the this value. - // 2. Perform ? RequireInternalSlot(temporalDate, [[InitializedTemporalDate]]). - auto temporal_date = TRY(typed_this_object(vm)); - - // 3. Let duration be ? ToTemporalDuration(temporalDurationLike). - auto duration = TRY(to_temporal_duration(vm, vm.argument(0))); - - // 4. Set options to ? GetOptionsObject(options). - auto* options = TRY(get_options_object(vm, vm.argument(1))); - - // 5. Return ? CalendarDateAdd(temporalDate.[[Calendar]], temporalDate, duration, options). - return TRY(calendar_date_add(vm, temporal_date->calendar(), temporal_date, *duration, options)); -} - -// 3.3.21 Temporal.PlainDate.prototype.subtract ( temporalDurationLike [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal.plaindate.prototype.subtract -JS_DEFINE_NATIVE_FUNCTION(PlainDatePrototype::subtract) -{ - // 1. Let temporalDate be the this value. - // 2. Perform ? RequireInternalSlot(temporalDate, [[InitializedTemporalDate]]). - auto temporal_date = TRY(typed_this_object(vm)); - - // 3. Let duration be ? ToTemporalDuration(temporalDurationLike). - auto duration = TRY(to_temporal_duration(vm, vm.argument(0))); - - // 4. Set options to ? GetOptionsObject(options). - auto* options = TRY(get_options_object(vm, vm.argument(1))); - - // 5. Let negatedDuration be ! CreateNegatedTemporalDuration(duration). - auto negated_duration = create_negated_temporal_duration(vm, *duration); - - // 6. Return ? CalendarDateAdd(temporalDate.[[Calendar]], temporalDate, negatedDuration, options). - return TRY(calendar_date_add(vm, temporal_date->calendar(), temporal_date, *negated_duration, options)); -} - -// 3.3.22 Temporal.PlainDate.prototype.with ( temporalDateLike [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal.plaindate.prototype.with -JS_DEFINE_NATIVE_FUNCTION(PlainDatePrototype::with) -{ - auto temporal_date_like = vm.argument(0); - - // 1. Let temporalDate be the this value. - // 2. Perform ? RequireInternalSlot(temporalDate, [[InitializedTemporalDate]]). - auto temporal_date = TRY(typed_this_object(vm)); - - // 3. If Type(temporalDateLike) is not Object, then - if (!temporal_date_like.is_object()) { - // a. Throw a TypeError exception. - return vm.throw_completion(ErrorType::NotAnObject, temporal_date_like.to_string_without_side_effects()); - } - - // 4. Perform ? RejectObjectWithCalendarOrTimeZone(temporalDateLike). - TRY(reject_object_with_calendar_or_time_zone(vm, temporal_date_like.as_object())); - - // 5. Let calendar be temporalDate.[[Calendar]]. - auto& calendar = temporal_date->calendar(); - - // 6. Let fieldNames be ? CalendarFields(calendar, « "day", "month", "monthCode", "year" »). - auto field_names = TRY(calendar_fields(vm, calendar, { "day"sv, "month"sv, "monthCode"sv, "year"sv })); - - // 7. Let partialDate be ? PrepareTemporalFields(temporalDateLike, fieldNames, partial). - auto* partial_date = TRY(prepare_temporal_fields(vm, temporal_date_like.as_object(), field_names, PrepareTemporalFieldsPartial {})); - - // 8. Set options to ? GetOptionsObject(options). - auto const* options = TRY(get_options_object(vm, vm.argument(1))); - - // 9. Let fields be ? PrepareTemporalFields(temporalDate, fieldNames, «»). - auto* fields = TRY(prepare_temporal_fields(vm, temporal_date, field_names, Vector {})); - - // 10. Set fields to ? CalendarMergeFields(calendar, fields, partialDate). - fields = TRY(calendar_merge_fields(vm, calendar, *fields, *partial_date)); - - // 11. Set fields to ? PrepareTemporalFields(fields, fieldNames, «»). - fields = TRY(prepare_temporal_fields(vm, *fields, field_names, Vector {})); - - // 12. Return ? CalendarDateFromFields(calendar, fields, options). - return TRY(calendar_date_from_fields(vm, calendar, *fields, options)); -} - -// 3.3.23 Temporal.PlainDate.prototype.withCalendar ( calendarLike ), https://tc39.es/proposal-temporal/#sec-temporal.plaindate.prototype.withcalendar -JS_DEFINE_NATIVE_FUNCTION(PlainDatePrototype::with_calendar) -{ - auto calendar_like = vm.argument(0); - - // 1. Let temporalDate be the this value. - // 2. Perform ? RequireInternalSlot(temporalDate, [[InitializedTemporalDate]]). - auto temporal_date = TRY(typed_this_object(vm)); - - // 3. Let calendar be ? ToTemporalCalendar(calendarLike). - auto* calendar = TRY(to_temporal_calendar(vm, calendar_like)); - - // 4. Return ! CreateTemporalDate(temporalDate.[[ISOYear]], temporalDate.[[ISOMonth]], temporalDate.[[ISODay]], calendar). - return MUST(create_temporal_date(vm, temporal_date->iso_year(), temporal_date->iso_month(), temporal_date->iso_day(), *calendar)); -} - -// 3.3.24 Temporal.PlainDate.prototype.until ( other [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal.plaindate.prototype.until -JS_DEFINE_NATIVE_FUNCTION(PlainDatePrototype::until) -{ - auto other = vm.argument(0); - auto options = vm.argument(1); - - // 1. Let temporalDate be the this value. - // 2. Perform ? RequireInternalSlot(temporalDate, [[InitializedTemporalDate]]). - auto temporal_date = TRY(typed_this_object(vm)); - - // 3. Return ? DifferenceTemporalPlainDate(until, temporalDate, other, options). - return TRY(difference_temporal_plain_date(vm, DifferenceOperation::Until, temporal_date, other, options)); -} - -// 3.3.25 Temporal.PlainDate.prototype.since ( other [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal.plaindate.prototype.since -JS_DEFINE_NATIVE_FUNCTION(PlainDatePrototype::since) -{ - auto other = vm.argument(0); - auto options = vm.argument(1); - - // 1. Let temporalDate be the this value. - // 2. Perform ? RequireInternalSlot(temporalDate, [[InitializedTemporalDate]]). - auto temporal_date = TRY(typed_this_object(vm)); - - // 3. Return ? DifferenceTemporalPlainDate(since, temporalDate, other, options). - return TRY(difference_temporal_plain_date(vm, DifferenceOperation::Since, temporal_date, other, options)); -} - -// 3.3.26 Temporal.PlainDate.prototype.equals ( other ), https://tc39.es/proposal-temporal/#sec-temporal.plaindate.prototype.equals -JS_DEFINE_NATIVE_FUNCTION(PlainDatePrototype::equals) -{ - // 1. Let temporalDate be the this value. - // 2. Perform ? RequireInternalSlot(temporalDate, [[InitializedTemporalDate]]). - auto temporal_date = TRY(typed_this_object(vm)); - - // 3. Set other to ? ToTemporalDate(other). - auto* other = TRY(to_temporal_date(vm, vm.argument(0))); - - // 4. If temporalDate.[[ISOYear]] ≠ other.[[ISOYear]], return false. - if (temporal_date->iso_year() != other->iso_year()) - return Value(false); - // 5. If temporalDate.[[ISOMonth]] ≠ other.[[ISOMonth]], return false. - if (temporal_date->iso_month() != other->iso_month()) - return Value(false); - // 6. If temporalDate.[[ISODay]] ≠ other.[[ISODay]], return false. - if (temporal_date->iso_day() != other->iso_day()) - return Value(false); - // 7. Return ? CalendarEquals(temporalDate.[[Calendar]], other.[[Calendar]]). - return Value(TRY(calendar_equals(vm, temporal_date->calendar(), other->calendar()))); -} - -// 3.3.27 Temporal.PlainDate.prototype.toPlainDateTime ( [ temporalTime ] ), https://tc39.es/proposal-temporal/#sec-temporal.plaindate.prototype.toplaindatetime -JS_DEFINE_NATIVE_FUNCTION(PlainDatePrototype::to_plain_date_time) -{ - // 1. Let temporalDate be the this value. - // 2. Perform ? RequireInternalSlot(temporalDate, [[InitializedTemporalDate]]). - auto temporal_date = TRY(typed_this_object(vm)); - - // 3. If temporalTime is undefined, then - if (vm.argument(0).is_undefined()) { - // a. Return ? CreateTemporalDateTime(temporalDate.[[ISOYear]], temporalDate.[[ISOMonth]], temporalDate.[[ISODay]], 0, 0, 0, 0, 0, 0, temporalDate.[[Calendar]]). - return TRY(create_temporal_date_time(vm, temporal_date->iso_year(), temporal_date->iso_month(), temporal_date->iso_day(), 0, 0, 0, 0, 0, 0, temporal_date->calendar())); - } - - // 4. Set temporalTime to ? ToTemporalTime(temporalTime). - auto* temporal_time = TRY(to_temporal_time(vm, vm.argument(0))); - - // 5. Return ? CreateTemporalDateTime(temporalDate.[[ISOYear]], temporalDate.[[ISOMonth]], temporalDate.[[ISODay]], temporalTime.[[ISOHour]], temporalTime.[[ISOMinute]], temporalTime.[[ISOSecond]], temporalTime.[[ISOMillisecond]], temporalTime.[[ISOMicrosecond]], temporalTime.[[ISONanosecond]], temporalDate.[[Calendar]]). - return TRY(create_temporal_date_time(vm, temporal_date->iso_year(), temporal_date->iso_month(), temporal_date->iso_day(), temporal_time->iso_hour(), temporal_time->iso_minute(), temporal_time->iso_second(), temporal_time->iso_millisecond(), temporal_time->iso_microsecond(), temporal_time->iso_nanosecond(), temporal_date->calendar())); -} - -// 3.3.28 Temporal.PlainDate.prototype.toZonedDateTime ( item ), https://tc39.es/proposal-temporal/#sec-temporal.plaindatetime.prototype.tozoneddatetime -JS_DEFINE_NATIVE_FUNCTION(PlainDatePrototype::to_zoned_date_time) -{ - auto item = vm.argument(0); - - // 1. Let temporalDate be the this value. - // 2. Perform ? RequireInternalSlot(temporalDate, [[InitializedTemporalDate]]). - auto temporal_date = TRY(typed_this_object(vm)); - - auto temporal_time_value = js_undefined(); - Object* time_zone; - - // 3. If Type(item) is Object, then - if (item.is_object()) { - // a. If item has an [[InitializedTemporalTimeZone]] internal slot, then - if (is(item.as_object())) { - // i. Let timeZone be item. - time_zone = &item.as_object(); - - // ii. Let temporalTime be undefined. - } - // b. Else, - else { - // i. Let timeZoneLike be ? Get(item, "timeZone"). - auto time_zone_like = TRY(item.as_object().get(vm.names.timeZone)); - - // ii. If timeZoneLike is undefined, then - if (time_zone_like.is_undefined()) { - // 1. Let timeZone be ? ToTemporalTimeZone(item). - time_zone = TRY(to_temporal_time_zone(vm, item)); - - // 2. Let temporalTime be undefined. - } - // iii. Else, - else { - // 1. Let timeZone be ? ToTemporalTimeZone(timeZoneLike). - time_zone = TRY(to_temporal_time_zone(vm, time_zone_like)); - - // 2. Let temporalTime be ? Get(item, "plainTime"). - temporal_time_value = TRY(item.as_object().get(vm.names.plainTime)); - } - } - } - // 4. Else, - else { - // a. Let timeZone be ? ToTemporalTimeZone(item). - time_zone = TRY(to_temporal_time_zone(vm, item)); - - // b. Let temporalTime be undefined. - } - - PlainDateTime* temporal_date_time; - - // 5. If temporalTime is undefined, then - if (temporal_time_value.is_undefined()) { - // a. Let temporalDateTime be ? CreateTemporalDateTime(temporalDate.[[ISOYear]], temporalDate.[[ISOMonth]], temporalDate.[[ISODay]], 0, 0, 0, 0, 0, 0, temporalDate.[[Calendar]]). - temporal_date_time = TRY(create_temporal_date_time(vm, temporal_date->iso_year(), temporal_date->iso_month(), temporal_date->iso_day(), 0, 0, 0, 0, 0, 0, temporal_date->calendar())); - } - // 6. Else, - else { - // a. Set temporalTime to ? ToTemporalTime(temporalTime). - auto* temporal_time = TRY(to_temporal_time(vm, temporal_time_value)); - - // b. Let temporalDateTime be ? CreateTemporalDateTime(temporalDate.[[ISOYear]], temporalDate.[[ISOMonth]], temporalDate.[[ISODay]], temporalTime.[[ISOHour]], temporalTime.[[ISOMinute]], temporalTime.[[ISOSecond]], temporalTime.[[ISOMillisecond]], temporalTime.[[ISOMicrosecond]], temporalTime.[[ISONanosecond]], temporalDate.[[Calendar]]). - temporal_date_time = TRY(create_temporal_date_time(vm, temporal_date->iso_year(), temporal_date->iso_month(), temporal_date->iso_day(), temporal_time->iso_hour(), temporal_time->iso_minute(), temporal_time->iso_second(), temporal_time->iso_millisecond(), temporal_time->iso_microsecond(), temporal_time->iso_nanosecond(), temporal_time->calendar())); - } - - // 7. Let instant be ? BuiltinTimeZoneGetInstantFor(timeZone, temporalDateTime, "compatible"). - auto instant = TRY(builtin_time_zone_get_instant_for(vm, time_zone, *temporal_date_time, "compatible"sv)); - - // 8. Return ! CreateTemporalZonedDateTime(instant.[[Nanoseconds]], timeZone, temporalDate.[[Calendar]]). - return MUST(create_temporal_zoned_date_time(vm, instant->nanoseconds(), *time_zone, temporal_date->calendar())); -} - -// 3.3.29 Temporal.PlainDate.prototype.toString ( [ options ] ), https://tc39.es/proposal-temporal/#sec-temporal.plaindate.prototype.tostring -JS_DEFINE_NATIVE_FUNCTION(PlainDatePrototype::to_string) -{ - // 1. Let temporalDate be the this value. - // 2. Perform ? RequireInternalSlot(temporalDate, [[InitializedTemporalDate]]). - auto temporal_date = TRY(typed_this_object(vm)); - - // 3. Set options to ? GetOptionsObject(options). - auto* options = TRY(get_options_object(vm, vm.argument(0))); - - // 4. Let showCalendar be ? ToCalendarNameOption(options). - auto show_calendar = TRY(to_calendar_name_option(vm, *options)); - - // 5. Return ? TemporalDateToString(temporalDate, showCalendar). - return PrimitiveString::create(vm, TRY(temporal_date_to_string(vm, temporal_date, show_calendar))); -} - -// 3.3.30 Temporal.PlainDate.prototype.toLocaleString ( [ locales [ , options ] ] ), https://tc39.es/proposal-temporal/#sec-temporal.plaindate.prototype.tolocalestring -// NOTE: This is the minimum toLocaleString implementation for engines without ECMA-402. -JS_DEFINE_NATIVE_FUNCTION(PlainDatePrototype::to_locale_string) -{ - // 1. Let temporalDate be the this value. - // 2. Perform ? RequireInternalSlot(temporalDate, [[InitializedTemporalDate]]). - auto temporal_date = TRY(typed_this_object(vm)); - - // 3. Return ? TemporalDateToString(temporalDate, "auto"). - return PrimitiveString::create(vm, TRY(temporal_date_to_string(vm, temporal_date, "auto"sv))); -} - -// 3.3.31 Temporal.PlainDate.prototype.toJSON ( ), https://tc39.es/proposal-temporal/#sec-temporal.plaindate.prototype.tojson -JS_DEFINE_NATIVE_FUNCTION(PlainDatePrototype::to_json) -{ - // 1. Let temporalDate be the this value. - // 2. Perform ? RequireInternalSlot(temporalDate, [[InitializedTemporalDate]]). - auto temporal_date = TRY(typed_this_object(vm)); - - // 3. Return ? TemporalDateToString(temporalDate, "auto"). - return PrimitiveString::create(vm, TRY(temporal_date_to_string(vm, temporal_date, "auto"sv))); -} - -// 3.3.32 Temporal.PlainDate.prototype.valueOf ( ), https://tc39.es/proposal-temporal/#sec-temporal.plaindate.prototype.valueof -JS_DEFINE_NATIVE_FUNCTION(PlainDatePrototype::value_of) -{ - // 1. Throw a TypeError exception. - return vm.throw_completion(ErrorType::Convert, "Temporal.PlainDate", "a primitive value"); -} - -// 3.3.3 get Temporal.PlainDate.prototype.calendarId, https://tc39.es/proposal-temporal/#sec-get-temporal.plaindate.prototype.calendarid -JS_DEFINE_NATIVE_FUNCTION(PlainDatePrototype::calendar_id_getter) -{ - // 1. Let temporalDate be the this value. - // 2. Perform ? RequireInternalSlot(temporalDate, [[InitializedTemporalDate]]). - auto temporal_date = TRY(typed_this_object(vm)); - - // 3. Return temporalDate.[[Calendar]]. - auto& calendar = static_cast(temporal_date->calendar()); - return PrimitiveString::create(vm, calendar.identifier()); -} - -} diff --git a/Libraries/LibJS/Runtime/Temporal/PlainDatePrototype.h b/Libraries/LibJS/Runtime/Temporal/PlainDatePrototype.h deleted file mode 100644 index 1fd3f199133..00000000000 --- a/Libraries/LibJS/Runtime/Temporal/PlainDatePrototype.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2021, Idan Horowitz - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include -#include - -namespace JS::Temporal { - -class PlainDatePrototype final : public PrototypeObject { - JS_PROTOTYPE_OBJECT(PlainDatePrototype, PlainDate, Temporal.PlainDate); - GC_DECLARE_ALLOCATOR(PlainDatePrototype); - -public: - virtual void initialize(Realm&) override; - virtual ~PlainDatePrototype() override = default; - -private: - explicit PlainDatePrototype(Realm&); - - JS_DECLARE_NATIVE_FUNCTION(calendar_getter); - JS_DECLARE_NATIVE_FUNCTION(calendar_id_getter); - JS_DECLARE_NATIVE_FUNCTION(year_getter); - JS_DECLARE_NATIVE_FUNCTION(month_getter); - JS_DECLARE_NATIVE_FUNCTION(month_code_getter); - JS_DECLARE_NATIVE_FUNCTION(day_getter); - JS_DECLARE_NATIVE_FUNCTION(day_of_week_getter); - JS_DECLARE_NATIVE_FUNCTION(day_of_year_getter); - JS_DECLARE_NATIVE_FUNCTION(week_of_year_getter); - JS_DECLARE_NATIVE_FUNCTION(year_of_week_getter); - JS_DECLARE_NATIVE_FUNCTION(days_in_week_getter); - JS_DECLARE_NATIVE_FUNCTION(days_in_month_getter); - JS_DECLARE_NATIVE_FUNCTION(days_in_year_getter); - JS_DECLARE_NATIVE_FUNCTION(months_in_year_getter); - JS_DECLARE_NATIVE_FUNCTION(in_leap_year_getter); - JS_DECLARE_NATIVE_FUNCTION(era_getter); - JS_DECLARE_NATIVE_FUNCTION(era_year_getter); - JS_DECLARE_NATIVE_FUNCTION(to_plain_year_month); - JS_DECLARE_NATIVE_FUNCTION(to_plain_month_day); - JS_DECLARE_NATIVE_FUNCTION(get_iso_fields); - JS_DECLARE_NATIVE_FUNCTION(add); - JS_DECLARE_NATIVE_FUNCTION(subtract); - JS_DECLARE_NATIVE_FUNCTION(with); - JS_DECLARE_NATIVE_FUNCTION(with_calendar); - JS_DECLARE_NATIVE_FUNCTION(until); - JS_DECLARE_NATIVE_FUNCTION(since); - JS_DECLARE_NATIVE_FUNCTION(equals); - JS_DECLARE_NATIVE_FUNCTION(to_plain_date_time); - JS_DECLARE_NATIVE_FUNCTION(to_zoned_date_time); - JS_DECLARE_NATIVE_FUNCTION(to_string); - JS_DECLARE_NATIVE_FUNCTION(to_locale_string); - JS_DECLARE_NATIVE_FUNCTION(to_json); - JS_DECLARE_NATIVE_FUNCTION(value_of); -}; - -} diff --git a/Libraries/LibJS/Runtime/Temporal/PlainDateTime.cpp b/Libraries/LibJS/Runtime/Temporal/PlainDateTime.cpp deleted file mode 100644 index 9cc9427d8b1..00000000000 --- a/Libraries/LibJS/Runtime/Temporal/PlainDateTime.cpp +++ /dev/null @@ -1,447 +0,0 @@ -/* - * Copyright (c) 2021, Idan Horowitz - * Copyright (c) 2021-2023, Linus Groh - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace JS::Temporal { - -GC_DEFINE_ALLOCATOR(PlainDateTime); - -// 5 Temporal.PlainDateTime Objects, https://tc39.es/proposal-temporal/#sec-temporal-plaindatetime-objects -PlainDateTime::PlainDateTime(i32 iso_year, u8 iso_month, u8 iso_day, u8 iso_hour, u8 iso_minute, u8 iso_second, u16 iso_millisecond, u16 iso_microsecond, u16 iso_nanosecond, Object& calendar, Object& prototype) - : Object(ConstructWithPrototypeTag::Tag, prototype) - , m_iso_year(iso_year) - , m_iso_month(iso_month) - , m_iso_day(iso_day) - , 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 PlainDateTime::visit_edges(Visitor& visitor) -{ - Base::visit_edges(visitor); - visitor.visit(m_calendar); -} - -// nsMinInstant - nsPerDay -auto const DATETIME_NANOSECONDS_MIN = "-8640000086400000000000"_sbigint; -// nsMaxInstant + nsPerDay -auto const DATETIME_NANOSECONDS_MAX = "8640000086400000000000"_sbigint; - -// 5.5.1 ISODateTimeWithinLimits ( year, month, day, hour, minute, second, millisecond, microsecond, nanosecond ), https://tc39.es/proposal-temporal/#sec-temporal-isodatetimewithinlimits -bool iso_date_time_within_limits(i32 year, u8 month, u8 day, u8 hour, u8 minute, u8 second, u16 millisecond, u16 microsecond, u16 nanosecond) -{ - // 1. Assert: IsValidISODate(year, month, day) is true. - VERIFY(is_valid_iso_date(year, month, day)); - - // 2. Let ns be ℝ(GetUTCEpochNanoseconds(year, month, day, hour, minute, second, millisecond, microsecond, nanosecond)). - auto ns = get_utc_epoch_nanoseconds(year, month, day, hour, minute, second, millisecond, microsecond, nanosecond); - - // 3. If ns ≤ nsMinInstant - nsPerDay, then - if (ns <= DATETIME_NANOSECONDS_MIN) { - // a. Return false. - return false; - } - - // 4. If ns ≥ nsMaxInstant + nsPerDay, then - if (ns >= DATETIME_NANOSECONDS_MAX) { - // a. Return false. - return false; - } - // 5. Return true. - return true; -} - -// 5.5.2 InterpretTemporalDateTimeFields ( calendar, fields, options ), https://tc39.es/proposal-temporal/#sec-temporal-interprettemporaldatetimefields -ThrowCompletionOr interpret_temporal_date_time_fields(VM& vm, Object& calendar, Object& fields, Object const* options) -{ - // 1. Let timeResult be ? ToTemporalTimeRecord(fields). - auto unregulated_time_result = TRY(to_temporal_time_record(vm, fields)); - - // 2. Let overflow be ? ToTemporalOverflow(options). - auto overflow = TRY(to_temporal_overflow(vm, options)); - - // 3. Let temporalDate be ? CalendarDateFromFields(calendar, fields, options). - auto* temporal_date = TRY(calendar_date_from_fields(vm, calendar, fields, options)); - - // 4. Let timeResult be ? RegulateTime(timeResult.[[Hour]], timeResult.[[Minute]], timeResult.[[Second]], timeResult.[[Millisecond]], timeResult.[[Microsecond]], timeResult.[[Nanosecond]], overflow). - auto time_result = TRY(regulate_time(vm, *unregulated_time_result.hour, *unregulated_time_result.minute, *unregulated_time_result.second, *unregulated_time_result.millisecond, *unregulated_time_result.microsecond, *unregulated_time_result.nanosecond, overflow)); - - // 5. Return the Record { [[Year]]: temporalDate.[[ISOYear]], [[Month]]: temporalDate.[[ISOMonth]], [[Day]]: temporalDate.[[ISODay]], [[Hour]]: timeResult.[[Hour]], [[Minute]]: timeResult.[[Minute]], [[Second]]: timeResult.[[Second]], [[Millisecond]]: timeResult.[[Millisecond]], [[Microsecond]]: timeResult.[[Microsecond]], [[Nanosecond]]: timeResult.[[Nanosecond]] }. - return ISODateTime { - .year = temporal_date->iso_year(), - .month = temporal_date->iso_month(), - .day = temporal_date->iso_day(), - .hour = time_result.hour, - .minute = time_result.minute, - .second = time_result.second, - .millisecond = time_result.millisecond, - .microsecond = time_result.microsecond, - .nanosecond = time_result.nanosecond, - }; -} - -// 5.5.3 ToTemporalDateTime ( item [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal-totemporaldatetime -ThrowCompletionOr to_temporal_date_time(VM& vm, Value item, Object const* options) -{ - // 1. If options is not present, set options to undefined. - // 2. Assert: Type(options) is Object or Undefined. - - Object* calendar; - ISODateTime result; - - // 3. If Type(item) is Object, then - if (item.is_object()) { - auto& item_object = item.as_object(); - - // a. If item has an [[InitializedTemporalDateTime]] internal slot, then - if (is(item_object)) { - // i. Return item. - return &static_cast(item_object); - } - - // b. If item has an [[InitializedTemporalZonedDateTime]] internal slot, then - if (is(item_object)) { - auto& zoned_date_time = static_cast(item_object); - - // i. Perform ? ToTemporalOverflow(options). - (void)TRY(to_temporal_overflow(vm, options)); - - // ii. Let instant be ! CreateTemporalInstant(item.[[Nanoseconds]]). - auto* instant = create_temporal_instant(vm, zoned_date_time.nanoseconds()).release_value(); - - // iii. Return ? BuiltinTimeZoneGetPlainDateTimeFor(item.[[TimeZone]], instant, item.[[Calendar]]). - return builtin_time_zone_get_plain_date_time_for(vm, &zoned_date_time.time_zone(), *instant, zoned_date_time.calendar()); - } - - // c. If item has an [[InitializedTemporalDate]] internal slot, then - if (is(item_object)) { - auto& plain_date = static_cast(item_object); - - // i. Perform ? ToTemporalOverflow(options). - (void)TRY(to_temporal_overflow(vm, options)); - - // ii. Return ? CreateTemporalDateTime(item.[[ISOYear]], item.[[ISOMonth]], item.[[ISODay]], 0, 0, 0, 0, 0, 0, item.[[Calendar]]). - return create_temporal_date_time(vm, plain_date.iso_year(), plain_date.iso_month(), plain_date.iso_day(), 0, 0, 0, 0, 0, 0, plain_date.calendar()); - } - - // d. Let calendar be ? GetTemporalCalendarWithISODefault(item). - calendar = TRY(get_temporal_calendar_with_iso_default(vm, item_object)); - - // e. Let fieldNames be ? CalendarFields(calendar, « "day", "hour", "microsecond", "millisecond", "minute", "month", "monthCode", "nanosecond", "second", "year" »). - auto field_names = TRY(calendar_fields(vm, *calendar, { "day"sv, "hour"sv, "microsecond"sv, "millisecond"sv, "minute"sv, "month"sv, "monthCode"sv, "nanosecond"sv, "second"sv, "year"sv })); - - // f. Let fields be ? PrepareTemporalFields(item, fieldNames, «»). - auto* fields = TRY(prepare_temporal_fields(vm, item_object, field_names, Vector {})); - - // g. Let result be ? InterpretTemporalDateTimeFields(calendar, fields, options). - result = TRY(interpret_temporal_date_time_fields(vm, *calendar, *fields, options)); - } - // 4. Else, - else { - // a. Perform ? ToTemporalOverflow(options). - (void)TRY(to_temporal_overflow(vm, options)); - - // b. Let string be ? ToString(item). - auto string = TRY(item.to_string(vm)); - - // c. Let result be ? ParseTemporalDateTimeString(string). - result = TRY(parse_temporal_date_time_string(vm, string)); - - // d. Assert: IsValidISODate(result.[[Year]], result.[[Month]], result.[[Day]]) is true. - VERIFY(is_valid_iso_date(result.year, result.month, result.day)); - - // e. Assert: IsValidTime(result.[[Hour]], result.[[Minute]], result.[[Second]], result.[[Millisecond]], result.[[Microsecond]], result.[[Nanosecond]]) is true. - VERIFY(is_valid_time(result.hour, result.minute, result.second, result.millisecond, result.microsecond, result.nanosecond)); - - // f. Let calendar be ? ToTemporalCalendarWithISODefault(result.[[Calendar]]). - calendar = TRY(to_temporal_calendar_with_iso_default(vm, result.calendar.has_value() ? PrimitiveString::create(vm, *result.calendar) : js_undefined())); - } - - // 5. Return ? CreateTemporalDateTime(result.[[Year]], result.[[Month]], result.[[Day]], result.[[Hour]], result.[[Minute]], result.[[Second]], result.[[Millisecond]], result.[[Microsecond]], result.[[Nanosecond]], calendar). - return create_temporal_date_time(vm, result.year, result.month, result.day, result.hour, result.minute, result.second, result.millisecond, result.microsecond, result.nanosecond, *calendar); -} - -// 5.5.4 BalanceISODateTime ( year, month, day, hour, minute, second, millisecond, microsecond, nanosecond ), https://tc39.es/proposal-temporal/#sec-temporal-balanceisodatetime -ISODateTime balance_iso_date_time(i32 year, u8 month, u8 day, u8 hour, u8 minute, u8 second, u16 millisecond, u16 microsecond, i64 nanosecond) -{ - // NOTE: The only use of this AO is in BuiltinTimeZoneGetPlainDateTimeFor, where we know that all values - // but `nanosecond` are in their usual range, hence why that's the only outlier here. The range for that - // is -86400000000000 to 86400000000999, so an i32 is not enough. - - // 1. Assert: year, month, day, hour, minute, second, millisecond, microsecond, and nanosecond are integers. - - // 2. Let balancedTime be ! BalanceTime(hour, minute, second, millisecond, microsecond, nanosecond). - auto balanced_time = balance_time(hour, minute, second, millisecond, microsecond, nanosecond); - - // 3. Let balancedDate be BalanceISODate(year, month, day + balancedTime.[[Days]]). - auto balanced_date = balance_iso_date(year, month, day + balanced_time.days); - - // 4. Return the Record { [[Year]]: balancedDate.[[Year]], [[Month]]: balancedDate.[[Month]], [[Day]]: balancedDate.[[Day]], [[Hour]]: balancedTime.[[Hour]], [[Minute]]: balancedTime.[[Minute]], [[Second]]: balancedTime.[[Second]], [[Millisecond]]: balancedTime.[[Millisecond]], [[Microsecond]]: balancedTime.[[Microsecond]], [[Nanosecond]]: balancedTime.[[Nanosecond]] }. - return ISODateTime { .year = balanced_date.year, .month = balanced_date.month, .day = balanced_date.day, .hour = balanced_time.hour, .minute = balanced_time.minute, .second = balanced_time.second, .millisecond = balanced_time.millisecond, .microsecond = balanced_time.microsecond, .nanosecond = balanced_time.nanosecond }; -} - -// 5.5.5 CreateTemporalDateTime ( isoYear, isoMonth, isoDay, hour, minute, second, millisecond, microsecond, nanosecond, calendar [ , newTarget ] ), https://tc39.es/proposal-temporal/#sec-temporal-createtemporaldatetime -ThrowCompletionOr create_temporal_date_time(VM& vm, i32 iso_year, u8 iso_month, u8 iso_day, u8 hour, u8 minute, u8 second, u16 millisecond, u16 microsecond, u16 nanosecond, Object& calendar, FunctionObject const* new_target) -{ - auto& realm = *vm.current_realm(); - - // 1. Assert: isoYear, isoMonth, isoDay, hour, minute, second, millisecond, microsecond, and nanosecond are integers. - // 2. Assert: Type(calendar) is Object. - - // 3. If IsValidISODate(isoYear, isoMonth, isoDay) is false, throw a RangeError exception. - if (!is_valid_iso_date(iso_year, iso_month, iso_day)) - return vm.throw_completion(ErrorType::TemporalInvalidPlainDateTime); - - // 4. If IsValidTime(hour, minute, second, millisecond, microsecond, nanosecond) is false, throw a RangeError exception. - if (!is_valid_time(hour, minute, second, millisecond, microsecond, nanosecond)) - return vm.throw_completion(ErrorType::TemporalInvalidPlainDateTime); - - // 5. If ISODateTimeWithinLimits(isoYear, isoMonth, isoDay, hour, minute, second, millisecond, microsecond, nanosecond) is false, then - if (!iso_date_time_within_limits(iso_year, iso_month, iso_day, hour, minute, second, millisecond, microsecond, nanosecond)) { - // a. Throw a RangeError exception. - return vm.throw_completion(ErrorType::TemporalInvalidPlainDateTime); - } - - // 6. If newTarget is not present, set newTarget to %Temporal.PlainDateTime%. - if (!new_target) - new_target = realm.intrinsics().temporal_plain_date_time_constructor(); - - // 7. Let object be ? OrdinaryCreateFromConstructor(newTarget, "%Temporal.PlainDateTime.prototype%", « [[InitializedTemporalDateTime]], [[ISOYear]], [[ISOMonth]], [[ISODay]], [[ISOHour]], [[ISOMinute]], [[ISOSecond]], [[ISOMillisecond]], [[ISOMicrosecond]], [[ISONanosecond]], [[Calendar]] »). - // 8. Set object.[[ISOYear]] to isoYear. - // 9. Set object.[[ISOMonth]] to isoMonth. - // 10. Set object.[[ISODay]] to isoDay. - // 11. Set object.[[ISOHour]] to hour. - // 12. Set object.[[ISOMinute]] to minute. - // 13. Set object.[[ISOSecond]] to second. - // 14. Set object.[[ISOMillisecond]] to millisecond. - // 15. Set object.[[ISOMicrosecond]] to microsecond. - // 16. Set object.[[ISONanosecond]] to nanosecond. - // 17. Set object.[[Calendar]] to calendar. - auto object = TRY(ordinary_create_from_constructor(vm, *new_target, &Intrinsics::temporal_plain_date_prototype, iso_year, iso_month, iso_day, hour, minute, second, millisecond, microsecond, nanosecond, calendar)); - - // 18. Return object. - return object.ptr(); -} - -// 5.5.6 TemporalDateTimeToString ( isoYear, isoMonth, isoDay, hour, minute, second, millisecond, microsecond, nanosecond, calendar, precision, showCalendar ), https://tc39.es/proposal-temporal/#sec-temporal-temporaldatetimetostring -ThrowCompletionOr temporal_date_time_to_string(VM& vm, i32 iso_year, u8 iso_month, u8 iso_day, u8 hour, u8 minute, u8 second, u16 millisecond, u16 microsecond, u16 nanosecond, Object const* calendar, Variant const& precision, StringView show_calendar) -{ - // 1. Assert: isoYear, isoMonth, isoDay, hour, minute, second, millisecond, microsecond, and nanosecond are integers. - - // 2. Let year be ! PadISOYear(isoYear). - // 3. Let month be ToZeroPaddedDecimalString(isoMonth, 2). - // 4. Let day be ToZeroPaddedDecimalString(isoDay, 2). - // 5. Let hour be ToZeroPaddedDecimalString(hour, 2). - // 6. Let minute be ToZeroPaddedDecimalString(minute, 2). - - // 7. Let seconds be ! FormatSecondsStringPart(second, millisecond, microsecond, nanosecond, precision). - auto seconds = MUST_OR_THROW_OOM(format_seconds_string_part(vm, second, millisecond, microsecond, nanosecond, precision)); - - // 8. Let calendarString be ? MaybeFormatCalendarAnnotation(calendar, showCalendar). - auto calendar_string = TRY(maybe_format_calendar_annotation(vm, calendar, show_calendar)); - - // 9. Return the string-concatenation of year, the code unit 0x002D (HYPHEN-MINUS), month, the code unit 0x002D (HYPHEN-MINUS), day, 0x0054 (LATIN CAPITAL LETTER T), hour, the code unit 0x003A (COLON), minute, seconds, and calendarString. - return TRY_OR_THROW_OOM(vm, String::formatted("{}-{:02}-{:02}T{:02}:{:02}{}{}", MUST_OR_THROW_OOM(pad_iso_year(vm, iso_year)), iso_month, iso_day, hour, minute, seconds, calendar_string)); -} - -// 5.5.7 CompareISODateTime ( y1, mon1, d1, h1, min1, s1, ms1, mus1, ns1, y2, mon2, d2, h2, min2, s2, ms2, mus2, ns2 ), https://tc39.es/proposal-temporal/#sec-temporal-compareisodatetime -i8 compare_iso_date_time(i32 year1, u8 month1, u8 day1, u8 hour1, u8 minute1, u8 second1, u16 millisecond1, u16 microsecond1, u16 nanosecond1, i32 year2, u8 month2, u8 day2, u8 hour2, u8 minute2, u8 second2, u16 millisecond2, u16 microsecond2, u16 nanosecond2) -{ - // 1. Assert: y1, mon1, d1, h1, min1, s1, ms1, mus1, ns1, y2, mon2, d2, h2, min2, s2, ms2, mus2, and ns2 are integers. - - // 2. Let dateResult be ! CompareISODate(y1, mon1, d1, y2, mon2, d2). - auto date_result = compare_iso_date(year1, month1, day1, year2, month2, day2); - - // 3. If dateResult is not 0, then - if (date_result != 0) { - // a. Return dateResult. - return date_result; - } - - // 4. Return ! CompareTemporalTime(h1, min1, s1, ms1, mus1, ns1, h2, min2, s2, ms2, mus2, ns2). - return compare_temporal_time(hour1, minute1, second1, millisecond1, microsecond1, nanosecond1, hour2, minute2, second2, millisecond2, microsecond2, nanosecond2); -} - -// 5.5.8 AddDateTime ( year, month, day, hour, minute, second, millisecond, microsecond, nanosecond, calendar, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, options ), https://tc39.es/proposal-temporal/#sec-temporal-adddatetime -ThrowCompletionOr add_date_time(VM& vm, i32 year, u8 month, u8 day, u8 hour, u8 minute, u8 second, u16 millisecond, u16 microsecond, u16 nanosecond, Object& calendar, double years, double months, double weeks, double days, double hours, double minutes, double seconds, double milliseconds, double microseconds, double nanoseconds, Object* options) -{ - // 1. Assert: ISODateTimeWithinLimits(year, month, day, hour, minute, second, millisecond, microsecond, nanosecond) is true. - VERIFY(iso_date_time_within_limits(year, month, day, hour, minute, second, millisecond, microsecond, nanosecond)); - - // 2. Let timeResult be ! AddTime(hour, minute, second, millisecond, microsecond, nanosecond, hours, minutes, seconds, milliseconds, microseconds, nanoseconds). - auto time_result = add_time(hour, minute, second, millisecond, microsecond, nanosecond, hours, minutes, seconds, milliseconds, microseconds, nanoseconds); - - // 3. Let datePart be ! CreateTemporalDate(year, month, day, calendar). - auto* date_part = MUST(create_temporal_date(vm, year, month, day, calendar)); - - // 4. Let dateDuration be ? CreateTemporalDuration(years, months, weeks, days + timeResult.[[Days]], 0, 0, 0, 0, 0, 0). - auto date_duration = TRY(create_temporal_duration(vm, years, months, weeks, days + time_result.days, 0, 0, 0, 0, 0, 0)); - - // 5. Let addedDate be ? CalendarDateAdd(calendar, datePart, dateDuration, options). - auto* added_date = TRY(calendar_date_add(vm, calendar, date_part, *date_duration, options)); - - // 6. Return the Record { [[Year]]: addedDate.[[ISOYear]], [[Month]]: addedDate.[[ISOMonth]], [[Day]]: addedDate.[[ISODay]], [[Hour]]: timeResult.[[Hour]], [[Minute]]: timeResult.[[Minute]], [[Second]]: timeResult.[[Second]], [[Millisecond]]: timeResult.[[Millisecond]], [[Microsecond]]: timeResult.[[Microsecond]], [[Nanosecond]]: timeResult.[[Nanosecond]] }. - return TemporalPlainDateTime { .year = added_date->iso_year(), .month = added_date->iso_month(), .day = added_date->iso_day(), .hour = time_result.hour, .minute = time_result.minute, .second = time_result.second, .millisecond = time_result.millisecond, .microsecond = time_result.microsecond, .nanosecond = time_result.nanosecond }; -} - -// 5.5.9 RoundISODateTime ( year, month, day, hour, minute, second, millisecond, microsecond, nanosecond, increment, unit, roundingMode [ , dayLength ] ), https://tc39.es/proposal-temporal/#sec-temporal-roundisodatetime -ISODateTime round_iso_date_time(i32 year, u8 month, u8 day, u8 hour, u8 minute, u8 second, u16 millisecond, u16 microsecond, u16 nanosecond, u64 increment, StringView unit, StringView rounding_mode, Optional day_length) -{ - // 1. Assert: year, month, day, hour, minute, second, millisecond, microsecond, and nanosecond are integers. - - // 2. Assert: ISODateTimeWithinLimits(year, month, day, hour, minute, second, millisecond, microsecond, nanosecond) is true. - VERIFY(iso_date_time_within_limits(year, month, day, hour, minute, second, millisecond, microsecond, nanosecond)); - - // 3. If dayLength is not present, set dayLength to nsPerDay. - if (!day_length.has_value()) - day_length = ns_per_day; - - // 4. Let roundedTime be ! RoundTime(hour, minute, second, millisecond, microsecond, nanosecond, increment, unit, roundingMode, dayLength). - auto rounded_time = round_time(hour, minute, second, millisecond, microsecond, nanosecond, increment, unit, rounding_mode, day_length); - - // 5. Let balanceResult be BalanceISODate(year, month, day + roundedTime.[[Days]]). - auto balance_result = balance_iso_date(year, month, day + rounded_time.days); - - // 6. Return the Record { [[Year]]: balanceResult.[[Year]], [[Month]]: balanceResult.[[Month]], [[Day]]: balanceResult.[[Day]], [[Hour]]: roundedTime.[[Hour]], [[Minute]]: roundedTime.[[Minute]], [[Second]]: roundedTime.[[Second]], [[Millisecond]]: roundedTime.[[Millisecond]], [[Microsecond]]: roundedTime.[[Microsecond]], [[Nanosecond]]: roundedTime.[[Nanosecond]] }. - return ISODateTime { .year = balance_result.year, .month = balance_result.month, .day = balance_result.day, .hour = rounded_time.hour, .minute = rounded_time.minute, .second = rounded_time.second, .millisecond = rounded_time.millisecond, .microsecond = rounded_time.microsecond, .nanosecond = rounded_time.nanosecond }; -} - -// 5.5.10 DifferenceISODateTime ( y1, mon1, d1, h1, min1, s1, ms1, mus1, ns1, y2, mon2, d2, h2, min2, s2, ms2, mus2, ns2, calendar, largestUnit, options ), https://tc39.es/proposal-temporal/#sec-temporal-differenceisodatetime -ThrowCompletionOr difference_iso_date_time(VM& vm, i32 year1, u8 month1, u8 day1, u8 hour1, u8 minute1, u8 second1, u16 millisecond1, u16 microsecond1, u16 nanosecond1, i32 year2, u8 month2, u8 day2, u8 hour2, u8 minute2, u8 second2, u16 millisecond2, u16 microsecond2, u16 nanosecond2, Object& calendar, StringView largest_unit, Object const& options) -{ - // 1. Assert: ISODateTimeWithinLimits(y1, mon1, d1, h1, min1, s1, ms1, mus1, ns1) is true. - VERIFY(iso_date_time_within_limits(year1, month1, day1, hour1, minute1, second1, millisecond1, microsecond1, nanosecond1)); - - // 2. Assert: ISODateTimeWithinLimits(y2, mon2, d2, h2, min2, s2, ms2, mus2, ns2) is true. - VERIFY(iso_date_time_within_limits(year2, month2, day2, hour2, minute2, second2, millisecond2, microsecond2, nanosecond2)); - - // 3. Let timeDifference be ! DifferenceTime(h1, min1, s1, ms1, mus1, ns1, h2, min2, s2, ms2, mus2, ns2). - auto time_difference = difference_time(vm, hour1, minute1, second1, millisecond1, microsecond1, nanosecond1, hour2, minute2, second2, millisecond2, microsecond2, nanosecond2); - - // 4. Let timeSign be ! DurationSign(0, 0, 0, 0, timeDifference.[[Hours]], timeDifference.[[Minutes]], timeDifference.[[Seconds]], timeDifference.[[Milliseconds]], timeDifference.[[Microseconds]], timeDifference.[[Nanoseconds]]). - auto time_sign = duration_sign(0, 0, 0, 0, time_difference.hours, time_difference.minutes, time_difference.seconds, time_difference.milliseconds, time_difference.microseconds, time_difference.nanoseconds); - - // 5. Let dateSign be ! CompareISODate(y2, mon2, d2, y1, mon1, d1). - auto date_sign = compare_iso_date(year2, month2, day2, year1, month1, day1); - - // 6. Let adjustedDate be CreateISODateRecord(y1, mon1, d1). - auto adjusted_date = create_iso_date_record(year1, month1, day1); - - // 7. If timeSign is -dateSign, then - if (time_sign == -date_sign) { - // a. Set adjustedDate to BalanceISODate(adjustedDate.[[Year]], adjustedDate.[[Month]], adjustedDate.[[Day]] - timeSign). - adjusted_date = balance_iso_date(adjusted_date.year, adjusted_date.month, adjusted_date.day - time_sign); - - // b. Set timeDifference to ! BalanceDuration(-timeSign, timeDifference.[[Hours]], timeDifference.[[Minutes]], timeDifference.[[Seconds]], timeDifference.[[Milliseconds]], timeDifference.[[Microseconds]], timeDifference.[[Nanoseconds]], largestUnit). - time_difference = MUST(balance_duration(vm, -time_sign, time_difference.hours, time_difference.minutes, time_difference.seconds, time_difference.milliseconds, time_difference.microseconds, Crypto::SignedBigInteger { time_difference.nanoseconds }, largest_unit)); - } - - // 8. Let date1 be ! CreateTemporalDate(adjustedDate.[[Year]], adjustedDate.[[Month]], adjustedDate.[[Day]], calendar). - auto* date1 = MUST(create_temporal_date(vm, adjusted_date.year, adjusted_date.month, adjusted_date.day, calendar)); - - // 9. Let date2 be ! CreateTemporalDate(y2, mon2, d2, calendar). - auto* date2 = MUST(create_temporal_date(vm, year2, month2, day2, calendar)); - - // 10. Let dateLargestUnit be ! LargerOfTwoTemporalUnits("day", largestUnit). - auto date_largest_unit = larger_of_two_temporal_units("day"sv, largest_unit); - - // 11. Let untilOptions be ? MergeLargestUnitOption(options, dateLargestUnit). - auto* until_options = TRY(merge_largest_unit_option(vm, options, TRY_OR_THROW_OOM(vm, String::from_utf8(date_largest_unit)))); - - // 12. Let dateDifference be ? CalendarDateUntil(calendar, date1, date2, untilOptions). - // FIXME: AD-HOC calendar records use as this AO is not up to date with latest spec - auto calendar_record = TRY(create_calendar_methods_record(vm, GC::Ref { calendar }, { { CalendarMethod::DateAdd, CalendarMethod::DateUntil } })); - auto date_difference = TRY(calendar_date_until(vm, calendar_record, date1, date2, *until_options)); - - // 13. Let balanceResult be ? BalanceDuration(dateDifference.[[Days]], timeDifference.[[Hours]], timeDifference.[[Minutes]], timeDifference.[[Seconds]], timeDifference.[[Milliseconds]], timeDifference.[[Microseconds]], timeDifference.[[Nanoseconds]], largestUnit). - auto balance_result = TRY(balance_duration(vm, date_difference->days(), time_difference.hours, time_difference.minutes, time_difference.seconds, time_difference.milliseconds, time_difference.microseconds, Crypto::SignedBigInteger { time_difference.nanoseconds }, largest_unit)); - - // 14. Return ! CreateDurationRecord(dateDifference.[[Years]], dateDifference.[[Months]], dateDifference.[[Weeks]], balanceResult.[[Days]], balanceResult.[[Hours]], balanceResult.[[Minutes]], balanceResult.[[Seconds]], balanceResult.[[Milliseconds]], balanceResult.[[Microseconds]], balanceResult.[[Nanoseconds]]). - return create_duration_record(date_difference->years(), date_difference->months(), date_difference->weeks(), balance_result.days, balance_result.hours, balance_result.minutes, balance_result.seconds, balance_result.milliseconds, balance_result.microseconds, balance_result.nanoseconds); -} - -// 5.5.11 DifferenceTemporalPlainDateTime ( operation, dateTime, other, options ), https://tc39.es/proposal-temporal/#sec-temporal-differencetemporalplaindatetime -ThrowCompletionOr> difference_temporal_plain_date_time(VM& vm, DifferenceOperation operation, PlainDateTime& date_time, Value other_value, Value options_value) -{ - // 1. If operation is since, let sign be -1. Otherwise, let sign be 1. - i8 sign = operation == DifferenceOperation::Since ? -1 : 1; - - // 2. Set other to ? ToTemporalDateTime(other). - auto* other = TRY(to_temporal_date_time(vm, other_value)); - - // 3. If ? CalendarEquals(dateTime.[[Calendar]], other.[[Calendar]]) is false, throw a RangeError exception. - if (!TRY(calendar_equals(vm, date_time.calendar(), other->calendar()))) - return vm.throw_completion(ErrorType::TemporalDifferentCalendars); - - // 4. Let settings be ? GetDifferenceSettings(operation, options, datetime, « », "nanosecond", "day"). - auto settings = TRY(get_difference_settings(vm, operation, options_value, UnitGroup::DateTime, {}, { "nanosecond"sv }, "day"sv)); - - // 5. Let diff be ? DifferenceISODateTime(dateTime.[[ISOYear]], dateTime.[[ISOMonth]], dateTime.[[ISODay]], dateTime.[[ISOHour]], dateTime.[[ISOMinute]], dateTime.[[ISOSecond]], dateTime.[[ISOMillisecond]], dateTime.[[ISOMicrosecond]], dateTime.[[ISONanosecond]], other.[[ISOYear]], other.[[ISOMonth]], other.[[ISODay]], other.[[ISOHour]], other.[[ISOMinute]], other.[[ISOSecond]], other.[[ISOMillisecond]], other.[[ISOMicrosecond]], other.[[ISONanosecond]], dateTime.[[Calendar]], settings.[[LargestUnit]], settings.[[Options]]). - auto diff = TRY(difference_iso_date_time(vm, date_time.iso_year(), date_time.iso_month(), date_time.iso_day(), date_time.iso_hour(), date_time.iso_minute(), date_time.iso_second(), date_time.iso_millisecond(), date_time.iso_microsecond(), date_time.iso_nanosecond(), other->iso_year(), other->iso_month(), other->iso_day(), other->iso_hour(), other->iso_minute(), other->iso_second(), other->iso_millisecond(), other->iso_microsecond(), other->iso_nanosecond(), date_time.calendar(), settings.largest_unit, settings.options)); - - // 6. Let relativeTo be ! CreateTemporalDate(dateTime.[[ISOYear]], dateTime.[[ISOMonth]], dateTime.[[ISODay]], dateTime.[[Calendar]]). - auto* relative_to = MUST(create_temporal_date(vm, date_time.iso_year(), date_time.iso_month(), date_time.iso_day(), date_time.calendar())); - - // 7. Let roundResult be (? RoundDuration(diff.[[Years]], diff.[[Months]], diff.[[Weeks]], diff.[[Days]], diff.[[Hours]], diff.[[Minutes]], diff.[[Seconds]], diff.[[Milliseconds]], diff.[[Microseconds]], diff.[[Nanoseconds]], settings.[[RoundingIncrement]], settings.[[SmallestUnit]], settings.[[RoundingMode]], relativeTo)).[[DurationRecord]]. - // FIXME: AD-HOC calendar records use as this AO is not up to date with latest spec - auto calendar_record = TRY(create_calendar_methods_record(vm, GC::Ref { date_time.calendar() }, { { CalendarMethod::DateAdd, CalendarMethod::DateUntil } })); - auto round_result = TRY(round_duration(vm, diff.years, diff.months, diff.weeks, diff.days, diff.hours, diff.minutes, diff.seconds, diff.milliseconds, diff.microseconds, diff.nanoseconds, settings.rounding_increment, settings.smallest_unit, settings.rounding_mode, relative_to, calendar_record)).duration_record; - - // 8. Let result be ? BalanceDuration(roundResult.[[Days]], roundResult.[[Hours]], roundResult.[[Minutes]], roundResult.[[Seconds]], roundResult.[[Milliseconds]], roundResult.[[Microseconds]], roundResult.[[Nanoseconds]], settings.[[LargestUnit]]). - auto result = MUST(balance_duration(vm, round_result.days, round_result.hours, round_result.minutes, round_result.seconds, round_result.milliseconds, round_result.microseconds, Crypto::SignedBigInteger { round_result.nanoseconds }, settings.largest_unit)); - - // 9. Return ! CreateTemporalDuration(sign × roundResult.[[Years]], sign × roundResult.[[Months]], sign × roundResult.[[Weeks]], sign × result.[[Days]], sign × result.[[Hours]], sign × result.[[Minutes]], sign × result.[[Seconds]], sign × result.[[Milliseconds]], sign × result.[[Microseconds]], sign × result.[[Nanoseconds]]). - return MUST(create_temporal_duration(vm, sign * round_result.years, sign * round_result.months, sign * round_result.weeks, sign * result.days, sign * result.hours, sign * result.minutes, sign * result.seconds, sign * result.milliseconds, sign * result.microseconds, sign * result.nanoseconds)); -} - -// 5.5.12 AddDurationToOrSubtractDurationFromPlainDateTime ( operation, dateTime, temporalDurationLike, options ), https://tc39.es/proposal-temporal/#sec-temporal-adddurationtoorsubtractdurationfromplaindatetime -ThrowCompletionOr add_duration_to_or_subtract_duration_from_plain_date_time(VM& vm, ArithmeticOperation operation, PlainDateTime& date_time, Value temporal_duration_like, Value options_value) -{ - // 1. If operation is subtract, let sign be -1. Otherwise, let sign be 1. - i8 sign = operation == ArithmeticOperation::Subtract ? -1 : 1; - - // 2. Let duration be ? ToTemporalDurationRecord(temporalDurationLike). - auto duration = TRY(to_temporal_duration_record(vm, temporal_duration_like)); - - // 3. Set options to ? GetOptionsObject(options). - auto* options = TRY(get_options_object(vm, options_value)); - - // 4. Let result be ? AddDateTime(dateTime.[[ISOYear]], dateTime.[[ISOMonth]], dateTime.[[ISODay]], dateTime.[[ISOHour]], dateTime.[[ISOMinute]], dateTime.[[ISOSecond]], dateTime.[[ISOMillisecond]], dateTime.[[ISOMicrosecond]], dateTime.[[ISONanosecond]], dateTime.[[Calendar]], sign × duration.[[Years]], sign × duration.[[Months]], sign × duration.[[Weeks]], sign × duration.[[Days]], sign × duration.[[Hours]], sign × duration.[[Minutes]], sign × duration.[[Seconds]], sign × duration.[[Milliseconds]], sign × duration.[[Microseconds]], sign × duration.[[Nanoseconds]], options). - auto result = TRY(add_date_time(vm, date_time.iso_year(), date_time.iso_month(), date_time.iso_day(), date_time.iso_hour(), date_time.iso_minute(), date_time.iso_second(), date_time.iso_millisecond(), date_time.iso_microsecond(), date_time.iso_nanosecond(), date_time.calendar(), sign * duration.years, sign * duration.months, sign * duration.weeks, sign * duration.days, sign * duration.hours, sign * duration.minutes, sign * duration.seconds, sign * duration.milliseconds, sign * duration.microseconds, sign * duration.nanoseconds, options)); - - // 5. Assert: IsValidISODate(result.[[Year]], result.[[Month]], result.[[Day]]) is true. - VERIFY(is_valid_iso_date(result.year, result.month, result.day)); - - // 6. Assert: IsValidTime(result.[[Hour]], result.[[Minute]], result.[[Second]], result.[[Millisecond]], result.[[Microsecond]], result.[[Nanosecond]]) is true. - VERIFY(is_valid_time(result.hour, result.minute, result.second, result.millisecond, result.microsecond, result.nanosecond)); - - // 7. Return ? CreateTemporalDateTime(result.[[Year]], result.[[Month]], result.[[Day]], result.[[Hour]], result.[[Minute]], result.[[Second]], result.[[Millisecond]], result.[[Microsecond]], result.[[Nanosecond]], dateTime.[[Calendar]]). - return create_temporal_date_time(vm, result.year, result.month, result.day, result.hour, result.minute, result.second, result.millisecond, result.microsecond, result.nanosecond, date_time.calendar()); -} - -} diff --git a/Libraries/LibJS/Runtime/Temporal/PlainDateTime.h b/Libraries/LibJS/Runtime/Temporal/PlainDateTime.h deleted file mode 100644 index 5dd711a93ad..00000000000 --- a/Libraries/LibJS/Runtime/Temporal/PlainDateTime.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) 2021, Idan Horowitz - * Copyright (c) 2021-2023, Linus Groh - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include -#include -#include -#include -#include - -namespace JS::Temporal { - -class PlainDateTime final : public Object { - JS_OBJECT(PlainDateTime, Object); - GC_DECLARE_ALLOCATOR(PlainDateTime); - -public: - virtual ~PlainDateTime() override = default; - - [[nodiscard]] i32 iso_year() const { return m_iso_year; } - [[nodiscard]] u8 iso_month() const { return m_iso_month; } - [[nodiscard]] u8 iso_day() const { return m_iso_day; } - [[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]] Object const& calendar() const { return m_calendar; } - [[nodiscard]] Object& calendar() { return m_calendar; } - -private: - PlainDateTime(i32 iso_year, u8 iso_month, u8 iso_day, u8 iso_hour, u8 iso_minute, u8 iso_second, u16 iso_millisecond, u16 iso_microsecond, u16 iso_nanosecond, Object& calendar, Object& prototype); - - virtual void visit_edges(Visitor&) override; - - // 5.4 Properties of Temporal.PlainDateTime Instances, https://tc39.es/proposal-temporal/#sec-properties-of-temporal-plaindatetime-instances - i32 m_iso_year { 0 }; // [[ISOYear]] - u8 m_iso_month { 0 }; // [[ISOMonth]] - u8 m_iso_day { 0 }; // [[ISODay]] - 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]] - GC::Ref m_calendar; // [[Calendar]] -}; - -// Used by AddDateTime to temporarily hold values -struct TemporalPlainDateTime { - i32 year; - u8 month; - u8 day; - u8 hour; - u8 minute; - u8 second; - u16 millisecond; - u16 microsecond; - u16 nanosecond; -}; - -bool iso_date_time_within_limits(i32 year, u8 month, u8 day, u8 hour, u8 minute, u8 second, u16 millisecond, u16 microsecond, u16 nanosecond); -ThrowCompletionOr interpret_temporal_date_time_fields(VM&, Object& calendar, Object& fields, Object const* options); -ThrowCompletionOr to_temporal_date_time(VM&, Value item, Object const* options = nullptr); -ISODateTime balance_iso_date_time(i32 year, u8 month, u8 day, u8 hour, u8 minute, u8 second, u16 millisecond, u16 microsecond, i64 nanosecond); -ThrowCompletionOr create_temporal_date_time(VM&, i32 iso_year, u8 iso_month, u8 iso_day, u8 hour, u8 minute, u8 second, u16 millisecond, u16 microsecond, u16 nanosecond, Object& calendar, FunctionObject const* new_target = nullptr); -ThrowCompletionOr temporal_date_time_to_string(VM&, i32 iso_year, u8 iso_month, u8 iso_day, u8 hour, u8 minute, u8 second, u16 millisecond, u16 microsecond, u16 nanosecond, Object const* calendar, Variant const& precision, StringView show_calendar); -i8 compare_iso_date_time(i32 year1, u8 month1, u8 day1, u8 hour1, u8 minute1, u8 second1, u16 millisecond1, u16 microsecond1, u16 nanosecond1, i32 year2, u8 month2, u8 day2, u8 hour2, u8 minute2, u8 second2, u16 millisecond2, u16 microsecond2, u16 nanosecond2); -ThrowCompletionOr add_date_time(VM&, i32 year, u8 month, u8 day, u8 hour, u8 minute, u8 second, u16 millisecond, u16 microsecond, u16 nanosecond, Object& calendar, double years, double months, double weeks, double days, double hours, double minutes, double seconds, double milliseconds, double microseconds, double nanoseconds, Object* options); -ISODateTime round_iso_date_time(i32 year, u8 month, u8 day, u8 hour, u8 minute, u8 second, u16 millisecond, u16 microsecond, u16 nanosecond, u64 increment, StringView unit, StringView rounding_mode, Optional day_length = {}); -ThrowCompletionOr difference_iso_date_time(VM&, i32 year1, u8 month1, u8 day1, u8 hour1, u8 minute1, u8 second1, u16 millisecond1, u16 microsecond1, u16 nanosecond1, i32 year2, u8 month2, u8 day2, u8 hour2, u8 minute2, u8 second2, u16 millisecond2, u16 microsecond2, u16 nanosecond2, Object& calendar, StringView largest_unit, Object const& options); -ThrowCompletionOr> difference_temporal_plain_date_time(VM&, DifferenceOperation, PlainDateTime&, Value other, Value options); -ThrowCompletionOr add_duration_to_or_subtract_duration_from_plain_date_time(VM&, ArithmeticOperation, PlainDateTime&, Value temporal_duration_like, Value options_value); - -} diff --git a/Libraries/LibJS/Runtime/Temporal/PlainDateTimeConstructor.cpp b/Libraries/LibJS/Runtime/Temporal/PlainDateTimeConstructor.cpp deleted file mode 100644 index 811b22d3327..00000000000 --- a/Libraries/LibJS/Runtime/Temporal/PlainDateTimeConstructor.cpp +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright (c) 2021-2023, Linus Groh - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include -#include -#include -#include -#include -#include -#include - -namespace JS::Temporal { - -GC_DEFINE_ALLOCATOR(PlainDateTimeConstructor); - -// 5.1 The Temporal.PlainDateTime Constructor, https://tc39.es/proposal-temporal/#sec-temporal-plaindatetime-constructor -PlainDateTimeConstructor::PlainDateTimeConstructor(Realm& realm) - : NativeFunction(realm.vm().names.PlainDateTime.as_string(), realm.intrinsics().function_prototype()) -{ -} - -void PlainDateTimeConstructor::initialize(Realm& realm) -{ - Base::initialize(realm); - - auto& vm = this->vm(); - - // 5.2.1 Temporal.PlainDateTime.prototype, https://tc39.es/proposal-temporal/#sec-temporal.plaindatetime.prototype - define_direct_property(vm.names.prototype, realm.intrinsics().temporal_plain_date_time_prototype(), 0); - - u8 attr = Attribute::Writable | Attribute::Configurable; - define_native_function(realm, vm.names.from, from, 1, attr); - define_native_function(realm, vm.names.compare, compare, 2, attr); - - define_direct_property(vm.names.length, Value(3), Attribute::Configurable); -} - -// 5.1.1 Temporal.PlainDateTime ( isoYear, isoMonth, isoDay [ , hour [ , minute [ , second [ , millisecond [ , microsecond [ , nanosecond [ , calendarLike ] ] ] ] ] ] ] ), https://tc39.es/proposal-temporal/#sec-temporal.plaindatetime -ThrowCompletionOr PlainDateTimeConstructor::call() -{ - auto& vm = this->vm(); - - // 1. If NewTarget is undefined, throw a TypeError exception. - return vm.throw_completion(ErrorType::ConstructorWithoutNew, "Temporal.PlainDateTime"); -} - -// 5.1.1 Temporal.PlainDateTime ( isoYear, isoMonth, isoDay [ , hour [ , minute [ , second [ , millisecond [ , microsecond [ , nanosecond [ , calendarLike ] ] ] ] ] ] ] ), https://tc39.es/proposal-temporal/#sec-temporal.plaindatetime -ThrowCompletionOr> PlainDateTimeConstructor::construct(FunctionObject& new_target) -{ - auto& vm = this->vm(); - - // 2. Let isoYear be ? ToIntegerWithTruncation(isoYear). - auto iso_year = TRY(to_integer_with_truncation(vm, vm.argument(0), ErrorType::TemporalInvalidPlainDateTime)); - - // 3. Let isoMonth be ? ToIntegerWithTruncation(isoMonth). - auto iso_month = TRY(to_integer_with_truncation(vm, vm.argument(1), ErrorType::TemporalInvalidPlainDateTime)); - - // 4. Let isoDay be ? ToIntegerWithTruncation(isoDay). - auto iso_day = TRY(to_integer_with_truncation(vm, vm.argument(2), ErrorType::TemporalInvalidPlainDateTime)); - - // 5. Let hour be ? ToIntegerWithTruncation(hour). - auto hour = TRY(to_integer_with_truncation(vm, vm.argument(3), ErrorType::TemporalInvalidPlainDateTime)); - - // 6. Let minute be ? ToIntegerWithTruncation(minute). - auto minute = TRY(to_integer_with_truncation(vm, vm.argument(4), ErrorType::TemporalInvalidPlainDateTime)); - - // 7. Let second be ? ToIntegerWithTruncation(second). - auto second = TRY(to_integer_with_truncation(vm, vm.argument(5), ErrorType::TemporalInvalidPlainDateTime)); - - // 8. Let millisecond be ? ToIntegerWithTruncation(millisecond). - auto millisecond = TRY(to_integer_with_truncation(vm, vm.argument(6), ErrorType::TemporalInvalidPlainDateTime)); - - // 9. Let microsecond be ? ToIntegerWithTruncation(microsecond). - auto microsecond = TRY(to_integer_with_truncation(vm, vm.argument(7), ErrorType::TemporalInvalidPlainDateTime)); - - // 10. Let nanosecond be ? ToIntegerWithTruncation(nanosecond). - auto nanosecond = TRY(to_integer_with_truncation(vm, vm.argument(8), ErrorType::TemporalInvalidPlainDateTime)); - - // 11. Let calendar be ? ToTemporalCalendarWithISODefault(calendarLike). - auto* calendar = TRY(to_temporal_calendar_with_iso_default(vm, vm.argument(9))); - - // 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 behavior as the call to CreateTemporalDateTime will immediately check that these values are valid - // ISO values (for years: -273975 - 273975, for months: 1 - 12, for days: 1 - 31, 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(iso_year) || !AK::is_within_range(iso_month) || !AK::is_within_range(iso_day) || !AK::is_within_range(hour) || !AK::is_within_range(minute) || !AK::is_within_range(second) || !AK::is_within_range(millisecond) || !AK::is_within_range(microsecond) || !AK::is_within_range(nanosecond)) - return vm.throw_completion(ErrorType::TemporalInvalidPlainDateTime); - - // 12. Return ? CreateTemporalDateTime(isoYear, isoMonth, isoDay, hour, minute, second, millisecond, microsecond, nanosecond, calendar, NewTarget). - return *TRY(create_temporal_date_time(vm, iso_year, iso_month, iso_day, hour, minute, second, millisecond, microsecond, nanosecond, *calendar, &new_target)); -} - -// 5.2.2 Temporal.PlainDateTime.from ( item [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal.plaindatetime.from -JS_DEFINE_NATIVE_FUNCTION(PlainDateTimeConstructor::from) -{ - auto item = vm.argument(0); - - // 1. Set options to ? GetOptionsObject(options). - auto* options = TRY(get_options_object(vm, vm.argument(1))); - - // 2. If Type(item) is Object and item has an [[InitializedTemporalDateTime]] internal slot, then - if (item.is_object() && is(item.as_object())) { - auto& plain_date_time = static_cast(item.as_object()); - - // a. Perform ? ToTemporalOverflow(options). - (void)TRY(to_temporal_overflow(vm, options)); - - // b. Return ! CreateTemporalDateTime(item.[[ISOYear]], item.[[ISOMonth]], item.[[ISODay]], item.[[ISOHour]], item.[[ISOMinute]], item.[[ISOSecond]], item.[[ISOMillisecond]], item.[[ISOMicrosecond]], item.[[ISONanosecond]], item.[[Calendar]]). - return MUST(create_temporal_date_time(vm, plain_date_time.iso_year(), plain_date_time.iso_month(), plain_date_time.iso_day(), plain_date_time.iso_hour(), plain_date_time.iso_minute(), plain_date_time.iso_second(), plain_date_time.iso_millisecond(), plain_date_time.iso_microsecond(), plain_date_time.iso_nanosecond(), plain_date_time.calendar())); - } - - // 3. Return ? ToTemporalDateTime(item, options). - return TRY(to_temporal_date_time(vm, item, options)); -} - -// 5.2.3 Temporal.PlainDateTime.compare ( one, two ), https://tc39.es/proposal-temporal/#sec-temporal.plaindatetime.compare -JS_DEFINE_NATIVE_FUNCTION(PlainDateTimeConstructor::compare) -{ - // 1. Set one to ? ToTemporalDateTime(one). - auto* one = TRY(to_temporal_date_time(vm, vm.argument(0))); - - // 2. Set two to ? ToTemporalDateTime(two). - auto* two = TRY(to_temporal_date_time(vm, vm.argument(1))); - - // 3. Return 𝔽(! CompareISODateTime(one.[[ISOYear]], one.[[ISOMonth]], one.[[ISODay]], one.[[ISOHour]], one.[[ISOMinute]], one.[[ISOSecond]], one.[[ISOMillisecond]], one.[[ISOMicrosecond]], one.[[ISONanosecond]], two.[[ISOYear]], two.[[ISOMonth]], two.[[ISODay]], two.[[ISOHour]], two.[[ISOMinute]], two.[[ISOSecond]], two.[[ISOMillisecond]], two.[[ISOMicrosecond]], two.[[ISONanosecond]])). - return Value(compare_iso_date_time(one->iso_year(), one->iso_month(), one->iso_day(), one->iso_hour(), one->iso_minute(), one->iso_second(), one->iso_millisecond(), one->iso_microsecond(), one->iso_nanosecond(), two->iso_year(), two->iso_month(), two->iso_day(), two->iso_hour(), two->iso_minute(), two->iso_second(), two->iso_millisecond(), two->iso_microsecond(), two->iso_nanosecond())); -} - -} diff --git a/Libraries/LibJS/Runtime/Temporal/PlainDateTimeConstructor.h b/Libraries/LibJS/Runtime/Temporal/PlainDateTimeConstructor.h deleted file mode 100644 index 71e26a7fad4..00000000000 --- a/Libraries/LibJS/Runtime/Temporal/PlainDateTimeConstructor.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2021-2022, Linus Groh - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include - -namespace JS::Temporal { - -class PlainDateTimeConstructor final : public NativeFunction { - JS_OBJECT(PlainDateTimeConstructor, NativeFunction); - GC_DECLARE_ALLOCATOR(PlainDateTimeConstructor); - -public: - virtual void initialize(Realm&) override; - virtual ~PlainDateTimeConstructor() override = default; - - virtual ThrowCompletionOr call() override; - virtual ThrowCompletionOr> construct(FunctionObject& new_target) override; - -private: - explicit PlainDateTimeConstructor(Realm&); - - virtual bool has_constructor() const override { return true; } - - JS_DECLARE_NATIVE_FUNCTION(from); - JS_DECLARE_NATIVE_FUNCTION(compare); -}; - -} diff --git a/Libraries/LibJS/Runtime/Temporal/PlainDateTimePrototype.cpp b/Libraries/LibJS/Runtime/Temporal/PlainDateTimePrototype.cpp deleted file mode 100644 index 0b28b124d7d..00000000000 --- a/Libraries/LibJS/Runtime/Temporal/PlainDateTimePrototype.cpp +++ /dev/null @@ -1,822 +0,0 @@ -/* - * Copyright (c) 2021-2023, Linus Groh - * Copyright (c) 2021, Luke Wilde - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace JS::Temporal { - -GC_DEFINE_ALLOCATOR(PlainDateTimePrototype); - -// 5.3 Properties of the Temporal.PlainDateTime Prototype Object, https://tc39.es/proposal-temporal/#sec-properties-of-the-temporal-plaindatetime-prototype-object -PlainDateTimePrototype::PlainDateTimePrototype(Realm& realm) - : PrototypeObject(realm.intrinsics().object_prototype()) -{ -} - -void PlainDateTimePrototype::initialize(Realm& realm) -{ - Base::initialize(realm); - - auto& vm = this->vm(); - - // 5.3.2 Temporal.PlainDateTime.prototype[ @@toStringTag ], https://tc39.es/proposal-temporal/#sec-temporal.plaindatetime.prototype-@@tostringtag - define_direct_property(vm.well_known_symbol_to_string_tag(), PrimitiveString::create(vm, "Temporal.PlainDateTime"_string), Attribute::Configurable); - - define_native_accessor(realm, vm.names.calendar, calendar_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.calendarId, calendar_id_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.year, year_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.month, month_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.monthCode, month_code_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.day, day_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.hour, hour_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.minute, minute_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.second, second_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.millisecond, millisecond_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.microsecond, microsecond_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.nanosecond, nanosecond_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.dayOfWeek, day_of_week_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.dayOfYear, day_of_year_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.weekOfYear, week_of_year_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.yearOfWeek, year_of_week_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.daysInWeek, days_in_week_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.daysInMonth, days_in_month_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.daysInYear, days_in_year_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.monthsInYear, months_in_year_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.inLeapYear, in_leap_year_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.era, era_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.eraYear, era_year_getter, {}, Attribute::Configurable); - - u8 attr = Attribute::Writable | Attribute::Configurable; - define_native_function(realm, vm.names.with, with, 1, attr); - define_native_function(realm, vm.names.withPlainTime, with_plain_time, 0, attr); - define_native_function(realm, vm.names.withPlainDate, with_plain_date, 1, attr); - define_native_function(realm, vm.names.withCalendar, with_calendar, 1, attr); - define_native_function(realm, vm.names.add, add, 1, attr); - define_native_function(realm, vm.names.subtract, subtract, 1, attr); - define_native_function(realm, vm.names.until, until, 1, attr); - define_native_function(realm, vm.names.since, since, 1, attr); - define_native_function(realm, vm.names.round, round, 1, attr); - define_native_function(realm, vm.names.equals, equals, 1, attr); - define_native_function(realm, vm.names.toString, to_string, 0, attr); - define_native_function(realm, vm.names.toLocaleString, to_locale_string, 0, attr); - define_native_function(realm, vm.names.toJSON, to_json, 0, attr); - define_native_function(realm, vm.names.valueOf, value_of, 0, attr); - define_native_function(realm, vm.names.toZonedDateTime, to_zoned_date_time, 1, attr); - define_native_function(realm, vm.names.toPlainDate, to_plain_date, 0, attr); - define_native_function(realm, vm.names.toPlainYearMonth, to_plain_year_month, 0, attr); - define_native_function(realm, vm.names.toPlainMonthDay, to_plain_month_day, 0, attr); - define_native_function(realm, vm.names.toPlainTime, to_plain_time, 0, attr); - define_native_function(realm, vm.names.getISOFields, get_iso_fields, 0, attr); -} - -// 5.3.3 get Temporal.PlainDateTime.prototype.calendar, https://tc39.es/proposal-temporal/#sec-get-temporal.plaindatetime.prototype.calendar -JS_DEFINE_NATIVE_FUNCTION(PlainDateTimePrototype::calendar_getter) -{ - // 1. Let dateTime be the this value. - // 2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]). - auto date_time = TRY(typed_this_object(vm)); - - // 3. Return dateTime.[[Calendar]]. - return Value(&date_time->calendar()); -} - -// 5.3.4 get Temporal.PlainDateTime.prototype.year, https://tc39.es/proposal-temporal/#sec-get-temporal.plaindatetime.prototype.year -JS_DEFINE_NATIVE_FUNCTION(PlainDateTimePrototype::year_getter) -{ - // 1. Let dateTime be the this value. - // 2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]). - auto date_time = TRY(typed_this_object(vm)); - - // 3. Let calendar be dateTime.[[Calendar]]. - auto& calendar = date_time->calendar(); - - // 4. Return 𝔽(? CalendarYear(calendar, dateTime)). - return TRY(calendar_year(vm, calendar, date_time)); -} - -// 5.3.5 get Temporal.PlainDateTime.prototype.month, https://tc39.es/proposal-temporal/#sec-get-temporal.plaindatetime.prototype.month -JS_DEFINE_NATIVE_FUNCTION(PlainDateTimePrototype::month_getter) -{ - // 1. Let dateTime be the this value. - // 2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]). - auto date_time = TRY(typed_this_object(vm)); - - // 3. Let calendar be dateTime.[[Calendar]]. - auto& calendar = date_time->calendar(); - - // 4. Return 𝔽(? CalendarMonth(calendar, dateTime)). - return TRY(calendar_month(vm, calendar, date_time)); -} - -// 5.3.6 get Temporal.PlainDateTime.prototype.monthCode, https://tc39.es/proposal-temporal/#sec-get-temporal.plaindatetime.prototype.monthcode -JS_DEFINE_NATIVE_FUNCTION(PlainDateTimePrototype::month_code_getter) -{ - // 1. Let dateTime be the this value. - // 2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]). - auto date_time = TRY(typed_this_object(vm)); - - // 3. Let calendar be dateTime.[[Calendar]]. - auto& calendar = date_time->calendar(); - - // 4. Return ? CalendarMonthCode(calendar, dateTime). - return PrimitiveString::create(vm, TRY(calendar_month_code(vm, calendar, date_time))); -} - -// 5.3.7 get Temporal.PlainDateTime.prototype.day, https://tc39.es/proposal-temporal/#sec-get-temporal.plaindatetime.prototype.day -JS_DEFINE_NATIVE_FUNCTION(PlainDateTimePrototype::day_getter) -{ - // 1. Let dateTime be the this value. - // 2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]). - auto date_time = TRY(typed_this_object(vm)); - - // 3. Let calendar be dateTime.[[Calendar]]. - auto& calendar = date_time->calendar(); - - // 4. Return 𝔽(? CalendarDay(calendar, dateTime)). - return TRY(calendar_day(vm, calendar, date_time)); -} - -// 5.3.8 get Temporal.PlainDateTime.prototype.hour, https://tc39.es/proposal-temporal/#sec-get-temporal.plaindatetime.prototype.hour -JS_DEFINE_NATIVE_FUNCTION(PlainDateTimePrototype::hour_getter) -{ - // 1. Let dateTime be the this value. - // 2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]). - auto date_time = TRY(typed_this_object(vm)); - - // 3. Return 𝔽(dateTime.[[ISOHour]]). - return Value(date_time->iso_hour()); -} - -// 5.3.9 get Temporal.PlainDateTime.prototype.minute, https://tc39.es/proposal-temporal/#sec-get-temporal.plaindatetime.prototype.minute -JS_DEFINE_NATIVE_FUNCTION(PlainDateTimePrototype::minute_getter) -{ - // 1. Let dateTime be the this value. - // 2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]). - auto date_time = TRY(typed_this_object(vm)); - - // 3. Return 𝔽(dateTime.[[ISOMinute]]). - return Value(date_time->iso_minute()); -} - -// 5.3.10 get Temporal.PlainDateTime.prototype.second, https://tc39.es/proposal-temporal/#sec-get-temporal.plaindatetime.prototype.second -JS_DEFINE_NATIVE_FUNCTION(PlainDateTimePrototype::second_getter) -{ - // 1. Let dateTime be the this value. - // 2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]). - auto date_time = TRY(typed_this_object(vm)); - - // 3. Return 𝔽(dateTime.[[ISOSecond]]). - return Value(date_time->iso_second()); -} - -// 5.3.11 get Temporal.PlainDateTime.prototype.millisecond, https://tc39.es/proposal-temporal/#sec-get-temporal.plaindatetime.prototype.millisecond -JS_DEFINE_NATIVE_FUNCTION(PlainDateTimePrototype::millisecond_getter) -{ - // 1. Let dateTime be the this value. - // 2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]). - auto date_time = TRY(typed_this_object(vm)); - - // 3. Return 𝔽(dateTime.[[ISOMillisecond]]). - return Value(date_time->iso_millisecond()); -} - -// 5.3.12 get Temporal.PlainDateTime.prototype.microsecond, https://tc39.es/proposal-temporal/#sec-get-temporal.plaindatetime.prototype.microsecond -JS_DEFINE_NATIVE_FUNCTION(PlainDateTimePrototype::microsecond_getter) -{ - // 1. Let dateTime be the this value. - // 2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]). - auto date_time = TRY(typed_this_object(vm)); - - // 3. Return 𝔽(dateTime.[[ISOMicrosecond]]). - return Value(date_time->iso_microsecond()); -} - -// 5.3.13 get Temporal.PlainDateTime.prototype.nanosecond, https://tc39.es/proposal-temporal/#sec-get-temporal.plaindatetime.prototype.nanosecond -JS_DEFINE_NATIVE_FUNCTION(PlainDateTimePrototype::nanosecond_getter) -{ - // 1. Let dateTime be the this value. - // 2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]). - auto date_time = TRY(typed_this_object(vm)); - - // 3. Return 𝔽(dateTime.[[ISONanosecond]]). - return Value(date_time->iso_nanosecond()); -} - -// 5.3.14 get Temporal.PlainDateTime.prototype.dayOfWeek, https://tc39.es/proposal-temporal/#sec-get-temporal.plaindatetime.prototype.dayofweek -JS_DEFINE_NATIVE_FUNCTION(PlainDateTimePrototype::day_of_week_getter) -{ - // 1. Let dateTime be the this value. - // 2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]). - auto date_time = TRY(typed_this_object(vm)); - - // 3. Let calendar be dateTime.[[Calendar]]. - auto& calendar = date_time->calendar(); - - // 4. Return 𝔽(? CalendarDayOfWeek(calendar, dateTime)). - return TRY(calendar_day_of_week(vm, calendar, date_time)); -} - -// 5.3.15 get Temporal.PlainDateTime.prototype.dayOfYear, https://tc39.es/proposal-temporal/#sec-get-temporal.plaindatetime.prototype.dayofyear -JS_DEFINE_NATIVE_FUNCTION(PlainDateTimePrototype::day_of_year_getter) -{ - // 1. Let dateTime be the this value. - // 2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]). - auto date_time = TRY(typed_this_object(vm)); - - // 3. Let calendar be dateTime.[[Calendar]]. - auto& calendar = date_time->calendar(); - - // 4. Return 𝔽(? CalendarDayOfYear(calendar, dateTime)). - return TRY(calendar_day_of_year(vm, calendar, date_time)); -} - -// 5.3.16 get Temporal.PlainDateTime.prototype.weekOfYear, https://tc39.es/proposal-temporal/#sec-get-temporal.plaindatetime.prototype.weekofyear -JS_DEFINE_NATIVE_FUNCTION(PlainDateTimePrototype::week_of_year_getter) -{ - // 1. Let dateTime be the this value. - // 2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]). - auto date_time = TRY(typed_this_object(vm)); - - // 3. Let calendar be dateTime.[[Calendar]]. - auto& calendar = date_time->calendar(); - - // 4. Return 𝔽(? CalendarWeekOfYear(calendar, dateTime)). - return TRY(calendar_week_of_year(vm, calendar, date_time)); -} - -// 5.3.17 get Temporal.PlainDateTime.prototype.yearOfWeek, https://tc39.es/proposal-temporal/#sec-get-temporal.plaindatetime.prototype.yearofweek -JS_DEFINE_NATIVE_FUNCTION(PlainDateTimePrototype::year_of_week_getter) -{ - // 1. Let dateTime be the this value. - // 2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]). - auto date_time = TRY(typed_this_object(vm)); - - // 3. Let calendar be dateTime.[[Calendar]]. - auto& calendar = date_time->calendar(); - - // 4. Return 𝔽(? CalendarYearOfWeek(calendar, dateTime)). - return TRY(calendar_year_of_week(vm, calendar, date_time)); -} - -// 5.3.18 get Temporal.PlainDateTime.prototype.daysInWeek, https://tc39.es/proposal-temporal/#sec-get-temporal.plaindatetime.prototype.daysinweek -JS_DEFINE_NATIVE_FUNCTION(PlainDateTimePrototype::days_in_week_getter) -{ - // 1. Let dateTime be the this value. - // 2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]). - auto date_time = TRY(typed_this_object(vm)); - - // 3. Let calendar be dateTime.[[Calendar]]. - auto& calendar = date_time->calendar(); - - // 4. Return 𝔽(? CalendarDaysInWeek(calendar, dateTime)). - return TRY(calendar_days_in_week(vm, calendar, date_time)); -} - -// 5.3.19 get Temporal.PlainDateTime.prototype.daysInMonth, https://tc39.es/proposal-temporal/#sec-get-temporal.plaindatetime.prototype.daysinmonth -JS_DEFINE_NATIVE_FUNCTION(PlainDateTimePrototype::days_in_month_getter) -{ - // 1. Let dateTime be the this value. - // 2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]). - auto date_time = TRY(typed_this_object(vm)); - - // 3. Let calendar be dateTime.[[Calendar]]. - auto& calendar = date_time->calendar(); - - // 4. Return 𝔽(? CalendarDaysInMonth(calendar, dateTime)). - return TRY(calendar_days_in_month(vm, calendar, date_time)); -} - -// 5.3.20 get Temporal.PlainDateTime.prototype.daysInYear, https://tc39.es/proposal-temporal/#sec-get-temporal.plaindatetime.prototype.daysinyear -JS_DEFINE_NATIVE_FUNCTION(PlainDateTimePrototype::days_in_year_getter) -{ - // 1. Let dateTime be the this value. - // 2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]). - auto date_time = TRY(typed_this_object(vm)); - - // 3. Let calendar be dateTime.[[Calendar]]. - auto& calendar = date_time->calendar(); - - // 4. Return 𝔽(? CalendarDaysInYear(calendar, dateTime)). - return TRY(calendar_days_in_year(vm, calendar, date_time)); -} - -// 5.3.21 get Temporal.PlainDateTime.prototype.monthsInYear, https://tc39.es/proposal-temporal/#sec-get-temporal.plaindatetime.prototype.monthsinyear -JS_DEFINE_NATIVE_FUNCTION(PlainDateTimePrototype::months_in_year_getter) -{ - // 1. Let dateTime be the this value. - // 2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]). - auto date_time = TRY(typed_this_object(vm)); - - // 3. Let calendar be dateTime.[[Calendar]]. - auto& calendar = date_time->calendar(); - - // 4. Return 𝔽(? CalendarMonthsInYear(calendar, dateTime)). - return TRY(calendar_months_in_year(vm, calendar, date_time)); -} - -// 5.3.22 get Temporal.PlainDateTime.prototype.inLeapYear, https://tc39.es/proposal-temporal/#sec-get-temporal.plaindatetime.prototype.inleapyear -JS_DEFINE_NATIVE_FUNCTION(PlainDateTimePrototype::in_leap_year_getter) -{ - // 1. Let dateTime be the this value. - // 2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]). - auto date_time = TRY(typed_this_object(vm)); - - // 3. Let calendar be dateTime.[[Calendar]]. - auto& calendar = date_time->calendar(); - - // 4. Return ? CalendarInLeapYear(calendar, dateTime). - return TRY(calendar_in_leap_year(vm, calendar, date_time)); -} - -// 15.6.6.2 get Temporal.PlainDateTime.prototype.era, https://tc39.es/proposal-temporal/#sec-get-temporal.plaindatetime.prototype.era -JS_DEFINE_NATIVE_FUNCTION(PlainDateTimePrototype::era_getter) -{ - // 1. Let plainDateTime be the this value. - // 2. Perform ? RequireInternalSlot(plainDateTime, [[InitializedTemporalDateTime]]). - auto plain_date_time = TRY(typed_this_object(vm)); - - // 3. Let calendar be plainDateTime.[[Calendar]]. - auto& calendar = plain_date_time->calendar(); - - // 4. Return ? CalendarEra(calendar, plainDateTime). - return TRY(calendar_era(vm, calendar, plain_date_time)); -} - -// 15.6.6.3 get Temporal.PlainDateTime.prototype.eraYear, https://tc39.es/proposal-temporal/#sec-get-temporal.plaindatetime.prototype.erayear -JS_DEFINE_NATIVE_FUNCTION(PlainDateTimePrototype::era_year_getter) -{ - // 1. Let plainDateTime be the this value. - // 2. Perform ? RequireInternalSlot(plainDateTime, [[InitializedTemporalDateTime]]). - auto plain_date_time = TRY(typed_this_object(vm)); - - // 3. Let calendar be plainDateTime.[[Calendar]]. - auto& calendar = plain_date_time->calendar(); - - // 4. Return ? CalendarEraYear(calendar, plainDateTime). - return TRY(calendar_era_year(vm, calendar, plain_date_time)); -} - -// 5.3.23 Temporal.PlainDateTime.prototype.with ( temporalDateTimeLike [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal.plaindatetime.prototype.with -JS_DEFINE_NATIVE_FUNCTION(PlainDateTimePrototype::with) -{ - auto temporal_date_time_like = vm.argument(0); - - // 1. Let dateTime be the this value. - // 2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]). - auto date_time = TRY(typed_this_object(vm)); - - // 3. If Type(temporalDateTimeLike) is not Object, then - if (!temporal_date_time_like.is_object()) { - // a. Throw a TypeError exception. - return vm.throw_completion(ErrorType::NotAnObject, temporal_date_time_like.to_string_without_side_effects()); - } - - // 4. Perform ? RejectObjectWithCalendarOrTimeZone(temporalDateTimeLike). - TRY(reject_object_with_calendar_or_time_zone(vm, temporal_date_time_like.as_object())); - - // 5. Let calendar be dateTime.[[Calendar]]. - auto& calendar = date_time->calendar(); - - // 6. Let fieldNames be ? CalendarFields(calendar, « "day", "hour", "microsecond", "millisecond", "minute", "month", "monthCode", "nanosecond", "second", "year" »). - auto field_names = TRY(calendar_fields(vm, calendar, { "day"sv, "hour"sv, "microsecond"sv, "millisecond"sv, "minute"sv, "month"sv, "monthCode"sv, "nanosecond"sv, "second"sv, "year"sv })); - - // 7. Let partialDateTime be ? PrepareTemporalFields(temporalDateTimeLike, fieldNames, partial). - auto* partial_date_time = TRY(prepare_temporal_fields(vm, temporal_date_time_like.as_object(), field_names, PrepareTemporalFieldsPartial {})); - - // 8. Set options to ? GetOptionsObject(options). - auto* options = TRY(get_options_object(vm, vm.argument(1))); - - // 9. Let fields be ? PrepareTemporalFields(dateTime, fieldNames, «»). - auto* fields = TRY(prepare_temporal_fields(vm, date_time, field_names, Vector {})); - - // 10. Set fields to ? CalendarMergeFields(calendar, fields, partialDateTime). - fields = TRY(calendar_merge_fields(vm, calendar, *fields, *partial_date_time)); - - // 11. Set fields to ? PrepareTemporalFields(fields, fieldNames, «»). - fields = TRY(prepare_temporal_fields(vm, *fields, field_names, Vector {})); - - // 12. Let result be ? InterpretTemporalDateTimeFields(calendar, fields, options). - auto result = TRY(interpret_temporal_date_time_fields(vm, calendar, *fields, options)); - - // 13. Assert: IsValidISODate(result.[[Year]], result.[[Month]], result.[[Day]]) is true. - VERIFY(is_valid_iso_date(result.year, result.month, result.day)); - - // 14. Assert: IsValidTime(result.[[Hour]], result.[[Minute]], result.[[Second]], result.[[Millisecond]], result.[[Microsecond]], result.[[Nanosecond]]) is true. - VERIFY(is_valid_time(result.hour, result.minute, result.second, result.millisecond, result.microsecond, result.nanosecond)); - - // 15. Return ? CreateTemporalDateTime(result.[[Year]], result.[[Month]], result.[[Day]], result.[[Hour]], result.[[Minute]], result.[[Second]], result.[[Millisecond]], result.[[Microsecond]], result.[[Nanosecond]], calendar). - return TRY(create_temporal_date_time(vm, result.year, result.month, result.day, result.hour, result.minute, result.second, result.millisecond, result.microsecond, result.nanosecond, calendar)); -} - -// 5.3.24 Temporal.PlainDateTime.prototype.withPlainTime ( [ plainTimeLike ] ), https://tc39.es/proposal-temporal/#sec-temporal.plaindatetime.prototype.withplaintime -JS_DEFINE_NATIVE_FUNCTION(PlainDateTimePrototype::with_plain_time) -{ - // 1. Let dateTime be the this value. - // 2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]). - auto date_time = TRY(typed_this_object(vm)); - - // 3. If plainTimeLike is undefined, then - if (vm.argument(0).is_undefined()) { - // a. Return ? CreateTemporalDateTime(dateTime.[[ISOYear]], dateTime.[[ISOMonth]], dateTime.[[ISODay]], 0, 0, 0, 0, 0, 0, dateTime.[[Calendar]]). - return TRY(create_temporal_date_time(vm, date_time->iso_year(), date_time->iso_month(), date_time->iso_day(), 0, 0, 0, 0, 0, 0, date_time->calendar())); - } - - // 4. Let plainTime be ? ToTemporalTime(plainTimeLike). - auto* plain_time = TRY(to_temporal_time(vm, vm.argument(0))); - - // 5. Return ? CreateTemporalDateTime(dateTime.[[ISOYear]], dateTime.[[ISOMonth]], dateTime.[[ISODay]], plainTime.[[ISOHour]], plainTime.[[ISOMinute]], plainTime.[[ISOSecond]], plainTime.[[ISOMillisecond]], plainTime.[[ISOMicrosecond]], plainTime.[[ISONanosecond]], dateTime.[[Calendar]]). - return TRY(create_temporal_date_time(vm, date_time->iso_year(), date_time->iso_month(), date_time->iso_day(), plain_time->iso_hour(), plain_time->iso_minute(), plain_time->iso_second(), plain_time->iso_millisecond(), plain_time->iso_microsecond(), plain_time->iso_nanosecond(), date_time->calendar())); -} - -// 5.3.25 Temporal.PlainDateTime.prototype.withPlainDate ( plainDateLike ), https://tc39.es/proposal-temporal/#sec-temporal.plaindatetime.prototype.withplaindate -JS_DEFINE_NATIVE_FUNCTION(PlainDateTimePrototype::with_plain_date) -{ - // 1. Let dateTime be the this value. - // 2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]). - auto date_time = TRY(typed_this_object(vm)); - - // 3. Let plainDate be ? ToTemporalDate(plainDateLike). - auto* plain_date = TRY(to_temporal_date(vm, vm.argument(0))); - - // 4. Let calendar be ? ConsolidateCalendars(dateTime.[[Calendar]], plainDate.[[Calendar]]). - auto* calendar = TRY(consolidate_calendars(vm, date_time->calendar(), plain_date->calendar())); - - // 5. Return ? CreateTemporalDateTime(plainDate.[[ISOYear]], plainDate.[[ISOMonth]], plainDate.[[ISODay]], dateTime.[[ISOHour]], dateTime.[[ISOMinute]], dateTime.[[ISOSecond]], dateTime.[[ISOMillisecond]], dateTime.[[ISOMicrosecond]], dateTime.[[ISONanosecond]], calendar). - return TRY(create_temporal_date_time(vm, plain_date->iso_year(), plain_date->iso_month(), plain_date->iso_day(), date_time->iso_hour(), date_time->iso_minute(), date_time->iso_second(), date_time->iso_millisecond(), date_time->iso_microsecond(), date_time->iso_nanosecond(), *calendar)); -} - -// 5.3.26 Temporal.PlainDateTime.prototype.withCalendar ( calendarLike ), https://tc39.es/proposal-temporal/#sec-temporal.plaindatetime.prototype.withcalendar -JS_DEFINE_NATIVE_FUNCTION(PlainDateTimePrototype::with_calendar) -{ - auto calendar_like = vm.argument(0); - - // 1. Let dateTime be the this value. - // 2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]). - auto date_time = TRY(typed_this_object(vm)); - - // 3. Let calendar be ? ToTemporalCalendar(calendarLike). - auto* calendar = TRY(to_temporal_calendar(vm, calendar_like)); - - // 4. Return ? CreateTemporalDateTime(dateTime.[[ISOYear]], dateTime.[[ISOMonth]], dateTime.[[ISODay]], dateTime.[[ISOHour]], dateTime.[[ISOMinute]], dateTime.[[ISOSecond]], dateTime.[[ISOMillisecond]], dateTime.[[ISOMicrosecond]], dateTime.[[ISONanosecond]], calendar). - return TRY(create_temporal_date_time(vm, date_time->iso_year(), date_time->iso_month(), date_time->iso_day(), date_time->iso_hour(), date_time->iso_minute(), date_time->iso_second(), date_time->iso_millisecond(), date_time->iso_microsecond(), date_time->iso_nanosecond(), *calendar)); -} - -// 5.3.27 Temporal.PlainDateTime.prototype.add ( temporalDurationLike [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal.plaindatetime.prototype.add -JS_DEFINE_NATIVE_FUNCTION(PlainDateTimePrototype::add) -{ - auto temporal_duration_like = vm.argument(0); - auto options = vm.argument(1); - - // 1. Let dateTime be the this value. - // 2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]). - auto date_time = TRY(typed_this_object(vm)); - - // 3. Return ? AddDurationToOrSubtractDurationFromPlainDateTime(add, dateTime, temporalDurationLike, options). - return TRY(add_duration_to_or_subtract_duration_from_plain_date_time(vm, ArithmeticOperation::Add, date_time, temporal_duration_like, options)); -} - -// 5.3.28 Temporal.PlainDateTime.prototype.subtract ( temporalDurationLike [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal.plaindatetime.prototype.subtract -JS_DEFINE_NATIVE_FUNCTION(PlainDateTimePrototype::subtract) -{ - auto temporal_duration_like = vm.argument(0); - auto options = vm.argument(1); - - // 1. Let dateTime be the this value. - // 2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]). - auto date_time = TRY(typed_this_object(vm)); - - // 3. Return ? AddDurationToOrSubtractDurationFromPlainDateTime(subtract, dateTime, temporalDurationLike, options). - return TRY(add_duration_to_or_subtract_duration_from_plain_date_time(vm, ArithmeticOperation::Subtract, date_time, temporal_duration_like, options)); -} - -// 5.3.29 Temporal.PlainDateTime.prototype.until ( other [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal.plaintime.prototype.since -JS_DEFINE_NATIVE_FUNCTION(PlainDateTimePrototype::until) -{ - auto other = vm.argument(0); - auto options = vm.argument(1); - - // 1. Let dateTime be the this value. - // 2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]). - auto date_time = TRY(typed_this_object(vm)); - - // 3. Return ? DifferenceTemporalPlainDateTime(until, dateTime, other, options). - return TRY(difference_temporal_plain_date_time(vm, DifferenceOperation::Until, date_time, other, options)); -} - -// 5.3.30 Temporal.PlainDateTime.prototype.since ( other [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal.plaindatetime.prototype.since -JS_DEFINE_NATIVE_FUNCTION(PlainDateTimePrototype::since) -{ - auto other = vm.argument(0); - auto options = vm.argument(1); - - // 1. Let dateTime be the this value. - // 2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]). - auto date_time = TRY(typed_this_object(vm)); - - // 3. Return ? DifferenceTemporalPlainDateTime(since, dateTime, other, options). - return TRY(difference_temporal_plain_date_time(vm, DifferenceOperation::Since, date_time, other, options)); -} - -// 5.3.31 Temporal.PlainDateTime.prototype.round ( roundTo ), https://tc39.es/proposal-temporal/#sec-temporal.plaindatetime.prototype.round -JS_DEFINE_NATIVE_FUNCTION(PlainDateTimePrototype::round) -{ - auto& realm = *vm.current_realm(); - - // 1. Let dateTime be the this value. - // 2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]). - auto date_time = TRY(typed_this_object(vm)); - - // 3. If roundTo is undefined, then - if (vm.argument(0).is_undefined()) { - // a. Throw a TypeError exception. - return vm.throw_completion(ErrorType::TemporalMissingOptionsObject); - } - - Object* round_to; - - // 4. If Type(roundTo) is String, then - if (vm.argument(0).is_string()) { - // a. Let paramString be roundTo. - - // b. Set roundTo to OrdinaryObjectCreate(null). - round_to = Object::create(realm, nullptr); - - // c. Perform ! CreateDataPropertyOrThrow(roundTo, "smallestUnit", paramString). - MUST(round_to->create_data_property_or_throw(vm.names.smallestUnit, vm.argument(0))); - } - // 5. Else, - else { - // a. Set roundTo to ? GetOptionsObject(roundTo). - round_to = TRY(get_options_object(vm, vm.argument(0))); - } - - // 6. Let smallestUnit be ? GetTemporalUnit(roundTo, "smallestUnit", time, required, « "day" »). - auto smallest_unit = TRY(get_temporal_unit(vm, *round_to, vm.names.smallestUnit, UnitGroup::Time, TemporalUnitRequired {}, { "day"sv })); - - // 7. Let roundingMode be ? ToTemporalRoundingMode(roundTo, "halfExpand"). - auto rounding_mode = TRY(to_temporal_rounding_mode(vm, *round_to, "halfExpand"sv)); - - // 8. If smallestUnit is "day", then - Optional maximum; - if (smallest_unit == "day"sv) { - // a. Let maximum be 1. - maximum = 1; - } - // 9. Else - else { - // a. Let maximum be ! MaximumTemporalDurationRoundingIncrement(smallestUnit) - maximum = maximum_temporal_duration_rounding_increment(*smallest_unit); - - // b. Assert: maximum is not undefined - VERIFY(maximum.has_value()); - } - - // 10. Let roundingIncrement be ? ToTemporalDateTimeRoundingIncrement(roundTo). - auto rounding_increment = TRY(to_temporal_rounding_increment(vm, *round_to)); - - // 11. Perform ? ValidateTemporalRoundingIncrement(roundingIncrement, maximum, false). - TRY(validate_temporal_rounding_increment(vm, rounding_increment, *maximum, false)); - - // 12. Let result be ! RoundISODateTime(dateTime.[[ISOYear]], dateTime.[[ISOMonth]], dateTime.[[ISODay]], dateTime.[[ISOHour]], dateTime.[[ISOMinute]], dateTime.[[ISOSecond]], dateTime.[[ISOMillisecond]], dateTime.[[ISOMicrosecond]], dateTime.[[ISONanosecond]], roundingIncrement, smallestUnit, roundingMode). - auto result = round_iso_date_time(date_time->iso_year(), date_time->iso_month(), date_time->iso_day(), date_time->iso_hour(), date_time->iso_minute(), date_time->iso_second(), date_time->iso_millisecond(), date_time->iso_microsecond(), date_time->iso_nanosecond(), rounding_increment, *smallest_unit, rounding_mode); - - // 13. Return ? CreateTemporalDateTime(result.[[Year]], result.[[Month]], result.[[Day]], result.[[Hour]], result.[[Minute]], result.[[Second]], result.[[Millisecond]], result.[[Microsecond]], result.[[Nanosecond]], dateTime.[[Calendar]]). - return TRY(create_temporal_date_time(vm, result.year, result.month, result.day, result.hour, result.minute, result.second, result.millisecond, result.microsecond, result.nanosecond, date_time->calendar())); -} - -// 5.3.32 Temporal.PlainDateTime.prototype.equals ( other ), https://tc39.es/proposal-temporal/#sec-temporal.plaindatetime.prototype.equals -JS_DEFINE_NATIVE_FUNCTION(PlainDateTimePrototype::equals) -{ - // 1. Let dateTime be the this value. - // 2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]). - auto date_time = TRY(typed_this_object(vm)); - - // 3. Set other to ? ToTemporalDateTime(other). - auto* other = TRY(to_temporal_date_time(vm, vm.argument(0))); - - // 4. Let result be ! CompareISODateTime(dateTime.[[ISOYear]], dateTime.[[ISOMonth]], dateTime.[[ISODay]], dateTime.[[ISOHour]], dateTime.[[ISOMinute]], dateTime.[[ISOSecond]], dateTime.[[ISOMillisecond]], dateTime.[[ISOMicrosecond]], dateTime.[[ISONanosecond]], other.[[ISOYear]], other.[[ISOMonth]], other.[[ISODay]], other.[[ISOHour]], other.[[ISOMinute]], other.[[ISOSecond]], other.[[ISOMillisecond]], other.[[ISOMicrosecond]], other.[[ISONanosecond]]). - auto result = compare_iso_date_time(date_time->iso_year(), date_time->iso_month(), date_time->iso_day(), date_time->iso_hour(), date_time->iso_minute(), date_time->iso_second(), date_time->iso_millisecond(), date_time->iso_microsecond(), date_time->iso_nanosecond(), other->iso_year(), other->iso_month(), other->iso_day(), other->iso_hour(), other->iso_minute(), other->iso_second(), other->iso_millisecond(), other->iso_microsecond(), other->iso_nanosecond()); - - // 5. If result is not 0, return false. - if (result != 0) - return Value(false); - - // 6. Return ? CalendarEquals(dateTime.[[Calendar]], other.[[Calendar]]). - return Value(TRY(calendar_equals(vm, date_time->calendar(), other->calendar()))); -} - -// 5.3.33 Temporal.PlainDateTime.prototype.toString ( [ options ] ), https://tc39.es/proposal-temporal/#sec-temporal.plaindatetime.prototype.tostring -JS_DEFINE_NATIVE_FUNCTION(PlainDateTimePrototype::to_string) -{ - // 1. Let dateTime be the this value. - // 2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]). - auto date_time = TRY(typed_this_object(vm)); - - // 3. Set options to ? GetOptionsObject(options). - auto* options = TRY(get_options_object(vm, vm.argument(0))); - - // 4. Let precision be ? ToSecondsStringPrecisionRecord(options). - auto precision = TRY(to_seconds_string_precision_record(vm, *options)); - - // 5. Let roundingMode be ? ToTemporalRoundingMode(options, "trunc"). - auto rounding_mode = TRY(to_temporal_rounding_mode(vm, *options, "trunc"sv)); - - // 6. Let showCalendar be ? ToCalendarNameOption(options). - auto show_calendar = TRY(to_calendar_name_option(vm, *options)); - - // 7. Let result be ! RoundISODateTime(dateTime.[[ISOYear]], dateTime.[[ISOMonth]], dateTime.[[ISODay]], dateTime.[[ISOHour]], dateTime.[[ISOMinute]], dateTime.[[ISOSecond]], dateTime.[[ISOMillisecond]], dateTime.[[ISOMicrosecond]], dateTime.[[ISONanosecond]], precision.[[Increment]], precision.[[Unit]], roundingMode). - auto result = round_iso_date_time(date_time->iso_year(), date_time->iso_month(), date_time->iso_day(), date_time->iso_hour(), date_time->iso_minute(), date_time->iso_second(), date_time->iso_millisecond(), date_time->iso_microsecond(), date_time->iso_nanosecond(), precision.increment, precision.unit, rounding_mode); - - // 8. Return ? TemporalDateTimeToString(result.[[Year]], result.[[Month]], result.[[Day]], result.[[Hour]], result.[[Minute]], result.[[Second]], result.[[Millisecond]], result.[[Microsecond]], result.[[Nanosecond]], dateTime.[[Calendar]], precision.[[Precision]], showCalendar). - return PrimitiveString::create(vm, TRY(temporal_date_time_to_string(vm, result.year, result.month, result.day, result.hour, result.minute, result.second, result.millisecond, result.microsecond, result.nanosecond, &date_time->calendar(), precision.precision, show_calendar))); -} - -// 5.3.34 Temporal.PlainDateTime.prototype.toLocaleString ( [ locales [ , options ] ] ), https://tc39.es/proposal-temporal/#sec-temporal.plaindatetime.prototype.tolocalestring -// NOTE: This is the minimum toLocaleString implementation for engines without ECMA-402. -JS_DEFINE_NATIVE_FUNCTION(PlainDateTimePrototype::to_locale_string) -{ - // 1. Let dateTime be the this value. - // 2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]). - auto date_time = TRY(typed_this_object(vm)); - - // 3. Return ? TemporalDateTimeToString(dateTime.[[ISOYear]], dateTime.[[ISOMonth]], dateTime.[[ISODay]], dateTime.[[ISOHour]], dateTime.[[ISOMinute]], dateTime.[[ISOSecond]], dateTime.[[ISOMillisecond]], dateTime.[[ISOMicrosecond]], dateTime.[[ISONanosecond]], dateTime.[[Calendar]], "auto", "auto"). - return PrimitiveString::create(vm, TRY(temporal_date_time_to_string(vm, date_time->iso_year(), date_time->iso_month(), date_time->iso_day(), date_time->iso_hour(), date_time->iso_minute(), date_time->iso_second(), date_time->iso_millisecond(), date_time->iso_microsecond(), date_time->iso_nanosecond(), &date_time->calendar(), "auto"sv, "auto"sv))); -} - -// 5.3.35 Temporal.PlainDateTime.prototype.toJSON ( ), https://tc39.es/proposal-temporal/#sec-temporal.plaindatetime.prototype.tojson -JS_DEFINE_NATIVE_FUNCTION(PlainDateTimePrototype::to_json) -{ - // 1. Let dateTime be the this value. - // 2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]). - auto date_time = TRY(typed_this_object(vm)); - - // 3. Return ? TemporalDateTimeToString(dateTime.[[ISOYear]], dateTime.[[ISOMonth]], dateTime.[[ISODay]], dateTime.[[ISOHour]], dateTime.[[ISOMinute]], dateTime.[[ISOSecond]], dateTime.[[ISOMillisecond]], dateTime.[[ISOMicrosecond]], dateTime.[[ISONanosecond]], dateTime.[[Calendar]], "auto", "auto"). - return PrimitiveString::create(vm, TRY(temporal_date_time_to_string(vm, date_time->iso_year(), date_time->iso_month(), date_time->iso_day(), date_time->iso_hour(), date_time->iso_minute(), date_time->iso_second(), date_time->iso_millisecond(), date_time->iso_microsecond(), date_time->iso_nanosecond(), &date_time->calendar(), "auto"sv, "auto"sv))); -} - -// 5.3.36 Temporal.PlainDateTime.prototype.valueOf ( ), https://tc39.es/proposal-temporal/#sec-temporal.plaindatetime.prototype.valueof -JS_DEFINE_NATIVE_FUNCTION(PlainDateTimePrototype::value_of) -{ - // 1. Throw a TypeError exception. - return vm.throw_completion(ErrorType::Convert, "Temporal.PlainDateTime", "a primitive value"); -} - -// 5.3.37 Temporal.PlainDateTime.prototype.toZonedDateTime ( temporalTimeZoneLike [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal.plaindatetime.prototype.tozoneddatetime -JS_DEFINE_NATIVE_FUNCTION(PlainDateTimePrototype::to_zoned_date_time) -{ - // 1. Let dateTime be the this value. - // 2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]). - auto date_time = TRY(typed_this_object(vm)); - - // 3. Let timeZone be ? ToTemporalTimeZone(temporalTimeZoneLike). - auto* time_zone = TRY(to_temporal_time_zone(vm, vm.argument(0))); - - // 4. Set options to ? GetOptionsObject(options). - auto* options = TRY(get_options_object(vm, vm.argument(1))); - - // 5. Let disambiguation be ? ToTemporalDisambiguation(options). - auto disambiguation = TRY(to_temporal_disambiguation(vm, options)); - - // 6. Let instant be ? BuiltinTimeZoneGetInstantFor(timeZone, dateTime, disambiguation). - auto instant = TRY(builtin_time_zone_get_instant_for(vm, time_zone, date_time, disambiguation)); - - // 7. Return ! CreateTemporalZonedDateTime(instant.[[Nanoseconds]], timeZone, dateTime.[[Calendar]]). - return MUST(create_temporal_zoned_date_time(vm, instant->nanoseconds(), *time_zone, date_time->calendar())); -} - -// 5.3.38 Temporal.PlainDateTime.prototype.toPlainDate ( ), https://tc39.es/proposal-temporal/#sec-temporal.plaindatetime.prototype.toplaindate -JS_DEFINE_NATIVE_FUNCTION(PlainDateTimePrototype::to_plain_date) -{ - // 1. Let dateTime be the this value. - // 2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]). - auto date_time = TRY(typed_this_object(vm)); - - // 3. Return ! CreateTemporalDate(dateTime.[[ISOYear]], dateTime.[[ISOMonth]], dateTime.[[ISODay]], dateTime.[[Calendar]]). - return MUST(create_temporal_date(vm, date_time->iso_year(), date_time->iso_month(), date_time->iso_day(), date_time->calendar())); -} - -// 5.3.39 Temporal.PlainDateTime.prototype.toPlainYearMonth ( ), https://tc39.es/proposal-temporal/#sec-temporal.plaindatetime.prototype.toplainyearmonth -JS_DEFINE_NATIVE_FUNCTION(PlainDateTimePrototype::to_plain_year_month) -{ - // 1. Let dateTime be the this value. - // 2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]). - auto date_time = TRY(typed_this_object(vm)); - - // 3. Let calendar be dateTime.[[Calendar]]. - auto& calendar = date_time->calendar(); - - // 4. Let fieldNames be ? CalendarFields(calendar, « "monthCode", "year" »). - auto field_names = TRY(calendar_fields(vm, calendar, { "monthCode"sv, "year"sv })); - - // 5. Let fields be ? PrepareTemporalFields(dateTime, fieldNames, «»). - auto* fields = TRY(prepare_temporal_fields(vm, date_time, field_names, Vector {})); - - // 6. Return ? CalendarYearMonthFromFields(calendar, fields). - return TRY(calendar_year_month_from_fields(vm, calendar, *fields)); -} - -// 5.3.40 Temporal.PlainDateTime.prototype.toPlainMonthDay ( ), https://tc39.es/proposal-temporal/#sec-temporal.plaindatetime.prototype.toplainmonthday -JS_DEFINE_NATIVE_FUNCTION(PlainDateTimePrototype::to_plain_month_day) -{ - // 1. Let dateTime be the this value. - // 2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]). - auto date_time = TRY(typed_this_object(vm)); - - // 3. Let calendar be dateTime.[[Calendar]]. - auto& calendar = date_time->calendar(); - - // 4. Let fieldNames be ? CalendarFields(calendar, « "day", "monthCode" »). - auto field_names = TRY(calendar_fields(vm, calendar, { "day"sv, "monthCode"sv })); - - // 5. Let fields be ? PrepareTemporalFields(dateTime, fieldNames, «»). - auto* fields = TRY(prepare_temporal_fields(vm, date_time, field_names, Vector {})); - - // 6. Return ? CalendarMonthDayFromFields(calendar, fields). - return TRY(calendar_month_day_from_fields(vm, calendar, *fields)); -} - -// 5.3.41 Temporal.PlainDateTime.prototype.toPlainTime ( ), https://tc39.es/proposal-temporal/#sec-temporal.plaindatetime.prototype.toplaintime -JS_DEFINE_NATIVE_FUNCTION(PlainDateTimePrototype::to_plain_time) -{ - // 1. Let dateTime be the this value. - // 2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]). - auto date_time = TRY(typed_this_object(vm)); - - // 3. Return ! CreateTemporalTime(dateTime.[[ISOHour]], dateTime.[[ISOMinute]], dateTime.[[ISOSecond]], dateTime.[[ISOMillisecond]], dateTime.[[ISOMicrosecond]], dateTime.[[ISONanosecond]]). - return MUST(create_temporal_time(vm, date_time->iso_hour(), date_time->iso_minute(), date_time->iso_second(), date_time->iso_millisecond(), date_time->iso_microsecond(), date_time->iso_nanosecond())); -} - -// 5.3.42 Temporal.PlainDateTime.prototype.getISOFields ( ), https://tc39.es/proposal-temporal/#sec-temporal.plaindatetime.prototype.getisofields -JS_DEFINE_NATIVE_FUNCTION(PlainDateTimePrototype::get_iso_fields) -{ - auto& realm = *vm.current_realm(); - - // 1. Let dateTime be the this value. - // 2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]). - auto date_time = TRY(typed_this_object(vm)); - - // 3. Let fields be OrdinaryObjectCreate(%Object.prototype%). - auto fields = Object::create(realm, realm.intrinsics().object_prototype()); - - // 4. Perform ! CreateDataPropertyOrThrow(fields, "calendar", dateTime.[[Calendar]]). - MUST(fields->create_data_property_or_throw(vm.names.calendar, Value(&date_time->calendar()))); - - // 5. Perform ! CreateDataPropertyOrThrow(fields, "isoDay", 𝔽(dateTime.[[ISODay]])). - MUST(fields->create_data_property_or_throw(vm.names.isoDay, Value(date_time->iso_day()))); - - // 6. Perform ! CreateDataPropertyOrThrow(fields, "isoHour", 𝔽(dateTime.[[ISOHour]])). - MUST(fields->create_data_property_or_throw(vm.names.isoHour, Value(date_time->iso_hour()))); - - // 7. Perform ! CreateDataPropertyOrThrow(fields, "isoMicrosecond", 𝔽(dateTime.[[ISOMicrosecond]])). - MUST(fields->create_data_property_or_throw(vm.names.isoMicrosecond, Value(date_time->iso_microsecond()))); - - // 8. Perform ! CreateDataPropertyOrThrow(fields, "isoMillisecond", 𝔽(dateTime.[[ISOMillisecond]])). - MUST(fields->create_data_property_or_throw(vm.names.isoMillisecond, Value(date_time->iso_millisecond()))); - - // 9. Perform ! CreateDataPropertyOrThrow(fields, "isoMinute", 𝔽(dateTime.[[ISOMinute]])). - MUST(fields->create_data_property_or_throw(vm.names.isoMinute, Value(date_time->iso_minute()))); - - // 10. Perform ! CreateDataPropertyOrThrow(fields, "isoMonth", 𝔽(dateTime.[[ISOMonth]])). - MUST(fields->create_data_property_or_throw(vm.names.isoMonth, Value(date_time->iso_month()))); - - // 11. Perform ! CreateDataPropertyOrThrow(fields, "isoNanosecond", 𝔽(dateTime.[[ISONanosecond]])). - MUST(fields->create_data_property_or_throw(vm.names.isoNanosecond, Value(date_time->iso_nanosecond()))); - - // 12. Perform ! CreateDataPropertyOrThrow(fields, "isoSecond", 𝔽(dateTime.[[ISOSecond]])). - MUST(fields->create_data_property_or_throw(vm.names.isoSecond, Value(date_time->iso_second()))); - - // 13. Perform ! CreateDataPropertyOrThrow(fields, "isoYear", 𝔽(dateTime.[[ISOYear]])). - MUST(fields->create_data_property_or_throw(vm.names.isoYear, Value(date_time->iso_year()))); - - // 14. Return fields. - return fields; -} - -// 5.3.3 get Temporal.PlainDateTime.prototype.calendarId, https://tc39.es/proposal-temporal/#sec-get-temporal.plaindatetime.prototype.calendarid -JS_DEFINE_NATIVE_FUNCTION(PlainDateTimePrototype::calendar_id_getter) -{ - // 1. Let dateTime be the this value. - // 2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]). - auto temporal_date = TRY(typed_this_object(vm)); - - // 3. Return dateTime.[[Calendar]]. - auto& calendar = static_cast(temporal_date->calendar()); - return PrimitiveString::create(vm, calendar.identifier()); -} - -} diff --git a/Libraries/LibJS/Runtime/Temporal/PlainDateTimePrototype.h b/Libraries/LibJS/Runtime/Temporal/PlainDateTimePrototype.h deleted file mode 100644 index d9e73b36f66..00000000000 --- a/Libraries/LibJS/Runtime/Temporal/PlainDateTimePrototype.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2021, Linus Groh - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include -#include - -namespace JS::Temporal { - -class PlainDateTimePrototype final : public PrototypeObject { - JS_PROTOTYPE_OBJECT(PlainDateTimePrototype, PlainDateTime, Temporal.PlainDateTime); - GC_DECLARE_ALLOCATOR(PlainDateTimePrototype); - -public: - virtual void initialize(Realm&) override; - virtual ~PlainDateTimePrototype() override = default; - -private: - explicit PlainDateTimePrototype(Realm&); - - JS_DECLARE_NATIVE_FUNCTION(calendar_getter); - JS_DECLARE_NATIVE_FUNCTION(calendar_id_getter); - JS_DECLARE_NATIVE_FUNCTION(year_getter); - JS_DECLARE_NATIVE_FUNCTION(month_getter); - JS_DECLARE_NATIVE_FUNCTION(month_code_getter); - JS_DECLARE_NATIVE_FUNCTION(day_getter); - JS_DECLARE_NATIVE_FUNCTION(hour_getter); - JS_DECLARE_NATIVE_FUNCTION(minute_getter); - JS_DECLARE_NATIVE_FUNCTION(second_getter); - JS_DECLARE_NATIVE_FUNCTION(millisecond_getter); - JS_DECLARE_NATIVE_FUNCTION(microsecond_getter); - JS_DECLARE_NATIVE_FUNCTION(nanosecond_getter); - JS_DECLARE_NATIVE_FUNCTION(day_of_week_getter); - JS_DECLARE_NATIVE_FUNCTION(day_of_year_getter); - JS_DECLARE_NATIVE_FUNCTION(week_of_year_getter); - JS_DECLARE_NATIVE_FUNCTION(year_of_week_getter); - JS_DECLARE_NATIVE_FUNCTION(days_in_week_getter); - JS_DECLARE_NATIVE_FUNCTION(days_in_month_getter); - JS_DECLARE_NATIVE_FUNCTION(days_in_year_getter); - JS_DECLARE_NATIVE_FUNCTION(months_in_year_getter); - JS_DECLARE_NATIVE_FUNCTION(in_leap_year_getter); - JS_DECLARE_NATIVE_FUNCTION(era_getter); - JS_DECLARE_NATIVE_FUNCTION(era_year_getter); - JS_DECLARE_NATIVE_FUNCTION(with); - JS_DECLARE_NATIVE_FUNCTION(with_plain_time); - JS_DECLARE_NATIVE_FUNCTION(with_plain_date); - JS_DECLARE_NATIVE_FUNCTION(with_calendar); - JS_DECLARE_NATIVE_FUNCTION(add); - JS_DECLARE_NATIVE_FUNCTION(subtract); - JS_DECLARE_NATIVE_FUNCTION(until); - JS_DECLARE_NATIVE_FUNCTION(since); - JS_DECLARE_NATIVE_FUNCTION(round); - JS_DECLARE_NATIVE_FUNCTION(equals); - JS_DECLARE_NATIVE_FUNCTION(to_string); - 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); - JS_DECLARE_NATIVE_FUNCTION(to_plain_date); - JS_DECLARE_NATIVE_FUNCTION(to_plain_year_month); - JS_DECLARE_NATIVE_FUNCTION(to_plain_month_day); - JS_DECLARE_NATIVE_FUNCTION(to_plain_time); - JS_DECLARE_NATIVE_FUNCTION(get_iso_fields); -}; - -} diff --git a/Libraries/LibJS/Runtime/Temporal/PlainMonthDay.cpp b/Libraries/LibJS/Runtime/Temporal/PlainMonthDay.cpp deleted file mode 100644 index 7582d0a60e5..00000000000 --- a/Libraries/LibJS/Runtime/Temporal/PlainMonthDay.cpp +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Copyright (c) 2021-2023, Linus Groh - * Copyright (c) 2021, Luke Wilde - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace JS::Temporal { - -GC_DEFINE_ALLOCATOR(PlainMonthDay); - -// 10 Temporal.PlainMonthDay Objects, https://tc39.es/proposal-temporal/#sec-temporal-plainmonthday-objects -PlainMonthDay::PlainMonthDay(u8 iso_month, u8 iso_day, i32 iso_year, Object& calendar, Object& prototype) - : Object(ConstructWithPrototypeTag::Tag, prototype) - , m_iso_year(iso_year) - , m_iso_month(iso_month) - , m_iso_day(iso_day) - , m_calendar(calendar) -{ -} - -void PlainMonthDay::visit_edges(Visitor& visitor) -{ - Base::visit_edges(visitor); - visitor.visit(m_calendar); -} - -// 10.5.1 ToTemporalMonthDay ( item [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal-totemporalmonthday -ThrowCompletionOr to_temporal_month_day(VM& vm, Value item, Object const* options) -{ - // 1. If options is not present, set options to undefined. - // 2. Assert: Type(options) is Object or Undefined. - - // 3. Let referenceISOYear be 1972 (the first leap year after the Unix epoch). - i32 reference_iso_year = 1972; - - // 4. If Type(item) is Object, then - if (item.is_object()) { - auto& item_object = item.as_object(); - - // a. If item has an [[InitializedTemporalMonthDay]] internal slot, then - if (is(item_object)) { - // i. Return item. - return static_cast(&item_object); - } - - Object* calendar = nullptr; - bool calendar_absent; - - // b. If item has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalTime]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then - // i. Let calendar be item.[[Calendar]]. - // ii. Let calendarAbsent be false. - if (is(item_object)) { - calendar = &static_cast(item_object).calendar(); - calendar_absent = false; - } else if (is(item_object)) { - calendar = &static_cast(item_object).calendar(); - calendar_absent = false; - } else if (is(item_object)) { - calendar = &static_cast(item_object).calendar(); - calendar_absent = false; - } else if (is(item_object)) { - calendar = &static_cast(item_object).calendar(); - calendar_absent = false; - } else if (is(item_object)) { - calendar = &static_cast(item_object).calendar(); - calendar_absent = false; - } else if (is(item_object)) { - calendar = &static_cast(item_object).calendar(); - calendar_absent = false; - } else { - // i. Let calendarLike be ? Get(item, "calendar"). - auto calendar_like = TRY(item_object.get(vm.names.calendar)); - - // ii. If calendarLike is undefined, then - // 1. Let calendarAbsent be true. - // iii. Else, - // 1. Let calendarAbsent be false. - calendar_absent = calendar_like.is_undefined(); - - // iv. Let calendar be ? ToTemporalCalendarWithISODefault(calendarLike). - calendar = TRY(to_temporal_calendar_with_iso_default(vm, calendar_like)); - } - - // d. Let fieldNames be ? CalendarFields(calendar, « "day", "month", "monthCode", "year" »). - auto field_names = TRY(calendar_fields(vm, *calendar, { "day"sv, "month"sv, "monthCode"sv, "year"sv })); - - // e. Let fields be ? PrepareTemporalFields(item, fieldNames, «»). - auto* fields = TRY(prepare_temporal_fields(vm, item_object, field_names, Vector {})); - - // f. Let month be ? Get(fields, "month"). - auto month = TRY(fields->get(vm.names.month)); - - // g. Let monthCode be ? Get(fields, "monthCode"). - auto month_code = TRY(fields->get(vm.names.monthCode)); - - // h. Let year be ? Get(fields, "year"). - auto year = TRY(fields->get(vm.names.year)); - - // i. If calendarAbsent is true, and month is not undefined, and monthCode is undefined and year is undefined, then - if (calendar_absent && !month.is_undefined() && month_code.is_undefined() && year.is_undefined()) { - // i. Perform ! CreateDataPropertyOrThrow(fields, "year", 𝔽(referenceISOYear)). - MUST(fields->create_data_property_or_throw(vm.names.year, Value(reference_iso_year))); - } - - // j. Return ? CalendarMonthDayFromFields(calendar, fields, options). - return calendar_month_day_from_fields(vm, *calendar, *fields, options); - } - - // 5. Perform ? ToTemporalOverflow(options). - (void)TRY(to_temporal_overflow(vm, options)); - - // 6. Let string be ? ToString(item). - auto string = TRY(item.to_string(vm)); - - // 7. Let result be ? ParseTemporalMonthDayString(string). - auto result = TRY(parse_temporal_month_day_string(vm, string)); - - // 8. Let calendar be ? ToTemporalCalendarWithISODefault(result.[[Calendar]]). - auto* calendar = TRY(to_temporal_calendar_with_iso_default(vm, result.calendar.has_value() ? PrimitiveString::create(vm, move(*result.calendar)) : js_undefined())); - - // 9. If result.[[Year]] is undefined, then - if (!result.year.has_value()) { - // a. Return ? CreateTemporalMonthDay(result.[[Month]], result.[[Day]], calendar, referenceISOYear). - return TRY(create_temporal_month_day(vm, result.month, result.day, *calendar, reference_iso_year)); - } - - // 10. Set result to ? CreateTemporalMonthDay(result.[[Month]], result.[[Day]], calendar, referenceISOYear). - auto* plain_month_day = TRY(create_temporal_month_day(vm, result.month, result.day, *calendar, reference_iso_year)); - - // 11. NOTE: The following operation is called without options, in order for the calendar to store a canonical value in the [[ISOYear]] internal slot of the result. - // 12. Return ? CalendarMonthDayFromFields(calendar, result). - return TRY(calendar_month_day_from_fields(vm, *calendar, *plain_month_day)); -} - -// 10.5.2 CreateTemporalMonthDay ( isoMonth, isoDay, calendar, referenceISOYear [ , newTarget ] ), https://tc39.es/proposal-temporal/#sec-temporal-createtemporalmonthday -ThrowCompletionOr create_temporal_month_day(VM& vm, u8 iso_month, u8 iso_day, Object& calendar, i32 reference_iso_year, FunctionObject const* new_target) -{ - auto& realm = *vm.current_realm(); - - // 1. Assert: isoMonth, isoDay, and referenceISOYear are integers. - // 2. Assert: Type(calendar) is Object. - - // 3. If IsValidISODate(referenceISOYear, isoMonth, isoDay) is false, throw a RangeError exception. - if (!is_valid_iso_date(reference_iso_year, iso_month, iso_day)) - return vm.throw_completion(ErrorType::TemporalInvalidPlainMonthDay); - - // 4. If ISODateTimeWithinLimits(referenceISOYear, isoMonth, isoDay, 12, 0, 0, 0, 0, 0) is false, throw a RangeError exception. - if (!iso_date_time_within_limits(reference_iso_year, iso_month, iso_day, 12, 0, 0, 0, 0, 0)) - return vm.throw_completion(ErrorType::TemporalInvalidPlainMonthDay); - - // 5. If newTarget is not present, set newTarget to %Temporal.PlainMonthDay%. - if (!new_target) - new_target = realm.intrinsics().temporal_plain_month_day_constructor(); - - // 6. Let object be ? OrdinaryCreateFromConstructor(newTarget, "%Temporal.PlainMonthDay.prototype%", « [[InitializedTemporalMonthDay]], [[ISOMonth]], [[ISODay]], [[ISOYear]], [[Calendar]] »). - // 7. Set object.[[ISOMonth]] to isoMonth. - // 8. Set object.[[ISODay]] to isoDay. - // 9. Set object.[[Calendar]] to calendar. - // 10. Set object.[[ISOYear]] to referenceISOYear. - auto object = TRY(ordinary_create_from_constructor(vm, *new_target, &Intrinsics::temporal_plain_month_day_prototype, iso_month, iso_day, reference_iso_year, calendar)); - - // 11. Return object. - return object.ptr(); -} - -// 10.5.3 TemporalMonthDayToString ( monthDay, showCalendar ), https://tc39.es/proposal-temporal/#sec-temporal-temporalmonthdaytostring -ThrowCompletionOr temporal_month_day_to_string(VM& vm, PlainMonthDay& month_day, StringView show_calendar) -{ - // 1. Assert: Type(monthDay) is Object. - // 2. Assert: monthDay has an [[InitializedTemporalMonthDay]] internal slot. - - // 3. Let month be ToZeroPaddedDecimalString(temporalDate.[[ISOMonth]], 2). - // 4. Let day be ToZeroPaddedDecimalString(temporalDate.[[ISODay]], 2). - // 5. Let result be the string-concatenation of month, the code unit 0x002D (HYPHEN-MINUS), and day. - auto result = TRY_OR_THROW_OOM(vm, String::formatted("{:02}-{:02}", month_day.iso_month(), month_day.iso_day())); - - // 6. Let calendarID be ? ToString(monthDay.[[Calendar]]). - auto calendar_id = TRY(Value(&month_day.calendar()).to_string(vm)); - - // 7. If showCalendar is one of "always" or "critical", or if calendarID is not "iso8601", then - if (show_calendar.is_one_of("always"sv, "critical"sv) || calendar_id != "iso8601"sv) { - // a. Let year be ! PadISOYear(monthDay.[[ISOYear]]). - // b. Set result to the string-concatenation of year, the code unit 0x002D (HYPHEN-MINUS), and result. - result = TRY_OR_THROW_OOM(vm, String::formatted("{}-{}", MUST_OR_THROW_OOM(pad_iso_year(vm, month_day.iso_year())), result)); - } - - // 8. Let calendarString be ! FormatCalendarAnnotation(calendarID, showCalendar). - auto calendar_string = MUST_OR_THROW_OOM(format_calendar_annotation(vm, calendar_id, show_calendar)); - - // 9. Set result to the string-concatenation of result and calendarString. - // 10. Return result. - return TRY_OR_THROW_OOM(vm, String::formatted("{}{}", result, calendar_string)); -} - -} diff --git a/Libraries/LibJS/Runtime/Temporal/PlainMonthDay.h b/Libraries/LibJS/Runtime/Temporal/PlainMonthDay.h deleted file mode 100644 index 07dca500417..00000000000 --- a/Libraries/LibJS/Runtime/Temporal/PlainMonthDay.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2021-2023, Linus Groh - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include - -namespace JS::Temporal { - -class PlainMonthDay final : public Object { - JS_OBJECT(PlainMonthDay, Object); - GC_DECLARE_ALLOCATOR(PlainMonthDay); - -public: - virtual ~PlainMonthDay() override = default; - - [[nodiscard]] i32 iso_year() const { return m_iso_year; } - [[nodiscard]] u8 iso_month() const { return m_iso_month; } - [[nodiscard]] u8 iso_day() const { return m_iso_day; } - [[nodiscard]] Object const& calendar() const { return m_calendar; } - [[nodiscard]] Object& calendar() { return m_calendar; } - -private: - PlainMonthDay(u8 iso_month, u8 iso_day, i32 iso_year, Object& calendar, Object& prototype); - - virtual void visit_edges(Visitor&) override; - - // 10.4 Properties of Temporal.PlainMonthDay Instances, https://tc39.es/proposal-temporal/#sec-properties-of-temporal-plainmonthday-instances - i32 m_iso_year { 0 }; // [[ISOYear]] - u8 m_iso_month { 0 }; // [[ISOMonth]] - u8 m_iso_day { 0 }; // [[ISODay]] - GC::Ref m_calendar; // [[Calendar]] -}; - -struct ISOMonthDay { - u8 month; - u8 day; - i32 reference_iso_year; -}; - -ThrowCompletionOr to_temporal_month_day(VM&, Value item, Object const* options = nullptr); -ThrowCompletionOr create_temporal_month_day(VM&, u8 iso_month, u8 iso_day, Object& calendar, i32 reference_iso_year, FunctionObject const* new_target = nullptr); -ThrowCompletionOr temporal_month_day_to_string(VM&, PlainMonthDay&, StringView show_calendar); - -} diff --git a/Libraries/LibJS/Runtime/Temporal/PlainMonthDayConstructor.cpp b/Libraries/LibJS/Runtime/Temporal/PlainMonthDayConstructor.cpp deleted file mode 100644 index ce6e2afc836..00000000000 --- a/Libraries/LibJS/Runtime/Temporal/PlainMonthDayConstructor.cpp +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (c) 2021-2023, Linus Groh - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include -#include -#include -#include -#include -#include - -namespace JS::Temporal { - -GC_DEFINE_ALLOCATOR(PlainMonthDayConstructor); - -// 10.1 The Temporal.PlainMonthDay Constructor, https://tc39.es/proposal-temporal/#sec-temporal-plainmonthday-constructor -PlainMonthDayConstructor::PlainMonthDayConstructor(Realm& realm) - : NativeFunction(realm.vm().names.PlainMonthDay.as_string(), realm.intrinsics().function_prototype()) -{ -} - -void PlainMonthDayConstructor::initialize(Realm& realm) -{ - Base::initialize(realm); - - auto& vm = this->vm(); - - // 10.2.1 Temporal.PlainMonthDay.prototype, https://tc39.es/proposal-temporal/#sec-temporal.plainmonthday.prototype - define_direct_property(vm.names.prototype, realm.intrinsics().temporal_plain_month_day_prototype(), 0); - - define_direct_property(vm.names.length, Value(2), Attribute::Configurable); - - u8 attr = Attribute::Writable | Attribute::Configurable; - define_native_function(realm, vm.names.from, from, 1, attr); -} - -// 10.1.1 Temporal.PlainMonthDay ( isoMonth, isoDay [ , calendarLike [ , referenceISOYear ] ] ), https://tc39.es/proposal-temporal/#sec-temporal.plainmonthday -ThrowCompletionOr PlainMonthDayConstructor::call() -{ - auto& vm = this->vm(); - - // 1. If NewTarget is undefined, throw a TypeError exception. - return vm.throw_completion(ErrorType::ConstructorWithoutNew, "Temporal.PlainMonthDay"); -} - -// 10.1.1 Temporal.PlainMonthDay ( isoMonth, isoDay [ , calendarLike [ , referenceISOYear ] ] ), https://tc39.es/proposal-temporal/#sec-temporal.plainmonthday -ThrowCompletionOr> PlainMonthDayConstructor::construct(FunctionObject& new_target) -{ - auto& vm = this->vm(); - - auto iso_month = vm.argument(0); - auto iso_day = vm.argument(1); - auto calendar_like = vm.argument(2); - auto reference_iso_year = vm.argument(3); - - // 2. If referenceISOYear is undefined, then - if (reference_iso_year.is_undefined()) { - // a. Set referenceISOYear to 1972𝔽. - reference_iso_year = Value(1972); - } - - // 3. Let m be ? ToIntegerWithTruncation(isoMonth). - auto m = TRY(to_integer_with_truncation(vm, iso_month, ErrorType::TemporalInvalidPlainMonthDay)); - - // 4. Let d be ? ToIntegerWithTruncation(isoDay). - auto d = TRY(to_integer_with_truncation(vm, iso_day, ErrorType::TemporalInvalidPlainMonthDay)); - - // 5. Let calendar be ? ToTemporalCalendarWithISODefault(calendarLike). - auto* calendar = TRY(to_temporal_calendar_with_iso_default(vm, calendar_like)); - - // 6. Let ref be ? ToIntegerWithTruncation(referenceISOYear). - auto ref = TRY(to_integer_with_truncation(vm, reference_iso_year, ErrorType::TemporalInvalidPlainMonthDay)); - - // 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 behavior as the call to CreateTemporalMonthDay will immediately check that these values are valid - // ISO values (for years: -273975 - 273975, for months: 1 - 12, for days: 1 - 31) all of which are subsets of this check. - if (!AK::is_within_range(ref) || !AK::is_within_range(m) || !AK::is_within_range(d)) - return vm.throw_completion(ErrorType::TemporalInvalidPlainMonthDay); - - // 7. Return ? CreateTemporalMonthDay(m, d, calendar, ref, NewTarget). - return *TRY(create_temporal_month_day(vm, m, d, *calendar, ref, &new_target)); -} - -// 10.2.2 Temporal.PlainMonthDay.from ( item [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal.plainmonthday.from -JS_DEFINE_NATIVE_FUNCTION(PlainMonthDayConstructor::from) -{ - auto item = vm.argument(0); - - // 1. Set options to ? GetOptionsObject(options). - auto const* options = TRY(get_options_object(vm, vm.argument(1))); - - // 2. If Type(item) is Object and item has an [[InitializedTemporalMonthDay]] internal slot, then - if (item.is_object() && is(item.as_object())) { - // a. Perform ? ToTemporalOverflow(options). - (void)TRY(to_temporal_overflow(vm, options)); - - auto& plain_month_day_object = static_cast(item.as_object()); - - // b. Return ! CreateTemporalMonthDay(item.[[ISOMonth]], item.[[ISODay]], item.[[Calendar]], item.[[ISOYear]]). - return MUST(create_temporal_month_day(vm, plain_month_day_object.iso_month(), plain_month_day_object.iso_day(), plain_month_day_object.calendar(), plain_month_day_object.iso_year())); - } - - // 3. Return ? ToTemporalMonthDay(item, options). - return TRY(to_temporal_month_day(vm, item, options)); -} - -} diff --git a/Libraries/LibJS/Runtime/Temporal/PlainMonthDayConstructor.h b/Libraries/LibJS/Runtime/Temporal/PlainMonthDayConstructor.h deleted file mode 100644 index 71b85743143..00000000000 --- a/Libraries/LibJS/Runtime/Temporal/PlainMonthDayConstructor.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2021-2022, Linus Groh - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include - -namespace JS::Temporal { - -class PlainMonthDayConstructor final : public NativeFunction { - JS_OBJECT(PlainMonthDayConstructor, NativeFunction); - GC_DECLARE_ALLOCATOR(PlainMonthDayConstructor); - -public: - virtual void initialize(Realm&) override; - virtual ~PlainMonthDayConstructor() override = default; - - virtual ThrowCompletionOr call() override; - virtual ThrowCompletionOr> construct(FunctionObject& new_target) override; - -private: - explicit PlainMonthDayConstructor(Realm&); - - virtual bool has_constructor() const override { return true; } - - JS_DECLARE_NATIVE_FUNCTION(from); -}; - -} diff --git a/Libraries/LibJS/Runtime/Temporal/PlainMonthDayPrototype.cpp b/Libraries/LibJS/Runtime/Temporal/PlainMonthDayPrototype.cpp deleted file mode 100644 index 4e16531580e..00000000000 --- a/Libraries/LibJS/Runtime/Temporal/PlainMonthDayPrototype.cpp +++ /dev/null @@ -1,296 +0,0 @@ -/* - * Copyright (c) 2021-2023, Linus Groh - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include -#include -#include -#include -#include -#include -#include - -namespace JS::Temporal { - -GC_DEFINE_ALLOCATOR(PlainMonthDayPrototype); - -// 10.3 Properties of the Temporal.PlainMonthDay Prototype Object, https://tc39.es/proposal-temporal/#sec-properties-of-the-temporal-plainmonthday-prototype-object -PlainMonthDayPrototype::PlainMonthDayPrototype(Realm& realm) - : PrototypeObject(realm.intrinsics().object_prototype()) -{ -} - -void PlainMonthDayPrototype::initialize(Realm& realm) -{ - Base::initialize(realm); - - auto& vm = this->vm(); - - // 10.3.2 Temporal.PlainMonthDay.prototype[ @@toStringTag ], https://tc39.es/proposal-temporal/#sec-temporal.plainmonthday.prototype-@@tostringtag - define_direct_property(vm.well_known_symbol_to_string_tag(), PrimitiveString::create(vm, "Temporal.PlainMonthDay"_string), Attribute::Configurable); - - define_native_accessor(realm, vm.names.calendar, calendar_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.calendarId, calendar_id_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.monthCode, month_code_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.day, day_getter, {}, Attribute::Configurable); - - u8 attr = Attribute::Writable | Attribute::Configurable; - define_native_function(realm, vm.names.with, with, 1, attr); - define_native_function(realm, vm.names.equals, equals, 1, attr); - define_native_function(realm, vm.names.toString, to_string, 0, attr); - define_native_function(realm, vm.names.toLocaleString, to_locale_string, 0, attr); - define_native_function(realm, vm.names.toJSON, to_json, 0, attr); - define_native_function(realm, vm.names.valueOf, value_of, 0, attr); - define_native_function(realm, vm.names.toPlainDate, to_plain_date, 1, attr); - define_native_function(realm, vm.names.getISOFields, get_iso_fields, 0, attr); -} - -// 10.3.3 get Temporal.PlainMonthDay.prototype.calendar, https://tc39.es/proposal-temporal/#sec-get-temporal.plainmonthday.prototype.calendar -JS_DEFINE_NATIVE_FUNCTION(PlainMonthDayPrototype::calendar_getter) -{ - // 1. Let monthDay be the this value. - // 2. Perform ? RequireInternalSlot(monthDay, [[InitializedTemporalMonthDay]]). - auto month_day = TRY(typed_this_object(vm)); - - // 3. Return monthDay.[[Calendar]]. - return Value(&month_day->calendar()); -} - -// 10.3.4 get Temporal.PlainMonthDay.prototype.monthCode, https://tc39.es/proposal-temporal/#sec-get-temporal.plainmonthday.prototype.monthcode -JS_DEFINE_NATIVE_FUNCTION(PlainMonthDayPrototype::month_code_getter) -{ - // 1. Let monthDay be the this value. - // 2. Perform ? RequireInternalSlot(monthDay, [[InitializedTemporalMonthDay]]). - auto month_day = TRY(typed_this_object(vm)); - - // 3. Let calendar be monthDay.[[Calendar]]. - auto& calendar = month_day->calendar(); - - // 4. Return ? CalendarMonthCode(calendar, monthDay). - return PrimitiveString::create(vm, TRY(calendar_month_code(vm, calendar, month_day))); -} - -// 10.3.5 get Temporal.PlainMonthDay.prototype.day, https://tc39.es/proposal-temporal/#sec-get-temporal.plainmonthday.prototype.day -JS_DEFINE_NATIVE_FUNCTION(PlainMonthDayPrototype::day_getter) -{ - // 1. Let monthDay be the this value. - // 2. Perform ? RequireInternalSlot(monthDay, [[InitializedTemporalMonthDay]]). - auto month_day = TRY(typed_this_object(vm)); - - // 3. Let calendar be monthDay.[[Calendar]]. - auto& calendar = month_day->calendar(); - - // 4. Return 𝔽(? CalendarDay(calendar, monthDay)). - return Value(TRY(calendar_day(vm, calendar, month_day))); -} - -// 10.3.6 Temporal.PlainMonthDay.prototype.with ( temporalMonthDayLike [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal.plainmonthday.prototype.with -JS_DEFINE_NATIVE_FUNCTION(PlainMonthDayPrototype::with) -{ - auto temporal_month_day_like = vm.argument(0); - - // 1. Let monthDay be the this value. - // 2. Perform ? RequireInternalSlot(monthDay, [[InitializedTemporalMonthDay]]). - auto month_day = TRY(typed_this_object(vm)); - - // 3. If Type(temporalMonthDayLike) is not Object, then - if (!temporal_month_day_like.is_object()) { - // a. Throw a TypeError exception. - return vm.throw_completion(ErrorType::NotAnObject, temporal_month_day_like.to_string_without_side_effects()); - } - - // 4. Perform ? RejectObjectWithCalendarOrTimeZone(temporalMonthDayLike). - TRY(reject_object_with_calendar_or_time_zone(vm, temporal_month_day_like.as_object())); - - // 5. Let calendar be monthDay.[[Calendar]]. - auto& calendar = month_day->calendar(); - - // 6. Let fieldNames be ? CalendarFields(calendar, « "day", "month", "monthCode", "year" »). - auto field_names = TRY(calendar_fields(vm, calendar, { "day"sv, "month"sv, "monthCode"sv, "year"sv })); - - // 7. Let partialMonthDay be ? PrepareTemporalFields(temporalMonthDayLike, fieldNames, partial). - auto* partial_month_day = TRY(prepare_temporal_fields(vm, temporal_month_day_like.as_object(), field_names, PrepareTemporalFieldsPartial {})); - - // 8. Set options to ? GetOptionsObject(options). - auto* options = TRY(get_options_object(vm, vm.argument(1))); - - // 9. Let fields be ? PrepareTemporalFields(monthDay, fieldNames, «»). - auto* fields = TRY(prepare_temporal_fields(vm, month_day, field_names, Vector {})); - - // 10. Set fields to ? CalendarMergeFields(calendar, fields, partialMonthDay). - fields = TRY(calendar_merge_fields(vm, calendar, *fields, *partial_month_day)); - - // 11. Set fields to ? PrepareTemporalFields(fields, fieldNames, «»). - fields = TRY(prepare_temporal_fields(vm, *fields, field_names, Vector {})); - - // 12. Return ? CalendarMonthDayFromFields(calendar, fields, options). - return TRY(calendar_month_day_from_fields(vm, calendar, *fields, options)); -} - -// 10.3.7 Temporal.PlainMonthDay.prototype.equals ( other ), https://tc39.es/proposal-temporal/#sec-temporal.plainmonthday.prototype.equals -JS_DEFINE_NATIVE_FUNCTION(PlainMonthDayPrototype::equals) -{ - // 1. Let monthDay be the this value. - // 2. Perform ? RequireInternalSlot(monthDay, [[InitializedTemporalMonthDay]]). - auto month_day = TRY(typed_this_object(vm)); - - // 3. Set other to ? ToTemporalMonthDay(other). - auto* other = TRY(to_temporal_month_day(vm, vm.argument(0))); - - // 4. If monthDay.[[ISOMonth]] ≠ other.[[ISOMonth]], return false. - if (month_day->iso_month() != other->iso_month()) - return Value(false); - - // 5. If monthDay.[[ISODay]] ≠ other.[[ISODay]], return false. - if (month_day->iso_day() != other->iso_day()) - return Value(false); - - // 6. If monthDay.[[ISOYear]] ≠ other.[[ISOYear]], return false. - if (month_day->iso_year() != other->iso_year()) - return Value(false); - - // 7. Return ? CalendarEquals(monthDay.[[Calendar]], other.[[Calendar]]). - return Value(TRY(calendar_equals(vm, month_day->calendar(), other->calendar()))); -} - -// 10.3.8 Temporal.PlainMonthDay.prototype.toString ( [ options ] ), https://tc39.es/proposal-temporal/#sec-temporal.plainmonthday.prototype.tostring -JS_DEFINE_NATIVE_FUNCTION(PlainMonthDayPrototype::to_string) -{ - // 1. Let monthDay be the this value. - // 2. Perform ? RequireInternalSlot(monthDay, [[InitializedTemporalMonthDay]]). - auto month_day = TRY(typed_this_object(vm)); - - // 3. Set options to ? GetOptionsObject(options). - auto* options = TRY(get_options_object(vm, vm.argument(0))); - - // 4. Let showCalendar be ? ToCalendarNameOption(options). - auto show_calendar = TRY(to_calendar_name_option(vm, *options)); - - // 5. Return ? TemporalMonthDayToString(monthDay, showCalendar). - return PrimitiveString::create(vm, TRY(temporal_month_day_to_string(vm, month_day, show_calendar))); -} - -// 10.3.9 Temporal.PlainMonthDay.prototype.toLocaleString ( [ locales [ , options ] ] ), https://tc39.es/proposal-temporal/#sec-temporal.plainmonthday.prototype.tolocalestring -// NOTE: This is the minimum toLocaleString implementation for engines without ECMA-402. -JS_DEFINE_NATIVE_FUNCTION(PlainMonthDayPrototype::to_locale_string) -{ - // 1. Let monthDay be the this value. - // 2. Perform ? RequireInternalSlot(monthDay, [[InitializedTemporalMonthDay]]). - auto month_day = TRY(typed_this_object(vm)); - - // 3. Return ? TemporalMonthDayToString(monthDay, "auto"). - return PrimitiveString::create(vm, TRY(temporal_month_day_to_string(vm, month_day, "auto"sv))); -} - -// 10.3.10 Temporal.PlainMonthDay.prototype.toJSON ( ), https://tc39.es/proposal-temporal/#sec-temporal.plainmonthday.prototype.tojson -JS_DEFINE_NATIVE_FUNCTION(PlainMonthDayPrototype::to_json) -{ - // 1. Let monthDay be the this value. - // 2. Perform ? RequireInternalSlot(monthDay, [[InitializedTemporalMonthDay]]). - auto month_day = TRY(typed_this_object(vm)); - - // 3. Return ? TemporalMonthDayToString(monthDay, "auto"). - return PrimitiveString::create(vm, TRY(temporal_month_day_to_string(vm, month_day, "auto"sv))); -} - -// 10.3.11 Temporal.PlainMonthDay.prototype.valueOf ( ), https://tc39.es/proposal-temporal/#sec-temporal.plainmonthday.prototype.valueof -JS_DEFINE_NATIVE_FUNCTION(PlainMonthDayPrototype::value_of) -{ - // 1. Throw a TypeError exception. - return vm.throw_completion(ErrorType::Convert, "Temporal.PlainMonthDay", "a primitive value"); -} - -// 10.3.12 Temporal.PlainMonthDay.prototype.toPlainDate ( item ), https://tc39.es/proposal-temporal/#sec-temporal.plainmonthday.prototype.toplaindate -JS_DEFINE_NATIVE_FUNCTION(PlainMonthDayPrototype::to_plain_date) -{ - auto& realm = *vm.current_realm(); - - auto item = vm.argument(0); - - // 1. Let monthDay be the this value. - // 2. Perform ? RequireInternalSlot(monthDay, [[InitializedTemporalMonthDay]]). - auto month_day = TRY(typed_this_object(vm)); - - // 3. If Type(item) is not Object, then - if (!item.is_object()) { - // a. Throw a TypeError exception. - return vm.throw_completion(ErrorType::NotAnObject, item); - } - - // 4. Let calendar be monthDay.[[Calendar]]. - auto& calendar = month_day->calendar(); - - // 5. Let receiverFieldNames be ? CalendarFields(calendar, « "day", "monthCode" »). - auto receiver_field_names = TRY(calendar_fields(vm, calendar, { "day"sv, "monthCode"sv })); - - // 6. Let fields be ? PrepareTemporalFields(monthDay, receiverFieldNames, «»). - auto* fields = TRY(prepare_temporal_fields(vm, month_day, receiver_field_names, Vector {})); - - // 7. Let inputFieldNames be ? CalendarFields(calendar, « "year" »). - auto input_field_names = TRY(calendar_fields(vm, calendar, { "year"sv })); - - // 8. Let inputFields be ? PrepareTemporalFields(item, inputFieldNames, «»). - auto* input_fields = TRY(prepare_temporal_fields(vm, item.as_object(), input_field_names, Vector {})); - - // 9. Let mergedFields be ? CalendarMergeFields(calendar, fields, inputFields). - auto* merged_fields = TRY(calendar_merge_fields(vm, calendar, *fields, *input_fields)); - - // 10. Let mergedFieldNames be MergeLists(receiverFieldNames, inputFieldNames). - auto merged_field_names = merge_lists(receiver_field_names, input_field_names); - - // 11. Set mergedFields to ? PrepareTemporalFields(mergedFields, mergedFieldNames, «»). - merged_fields = TRY(prepare_temporal_fields(vm, *merged_fields, merged_field_names, Vector {})); - - // 12. Let options be OrdinaryObjectCreate(null). - auto options = Object::create(realm, nullptr); - - // 13. Perform ! CreateDataPropertyOrThrow(options, "overflow", "reject"). - MUST(options->create_data_property_or_throw(vm.names.overflow, PrimitiveString::create(vm, vm.names.reject.as_string()))); - - // 14. Return ? CalendarDateFromFields(calendar, mergedFields, options). - return TRY(calendar_date_from_fields(vm, calendar, *merged_fields, options)); -} - -// 10.3.13 Temporal.PlainMonthDay.prototype.getISOFields ( ), https://tc39.es/proposal-temporal/#sec-temporal.plainmonthday.prototype.getisofields -JS_DEFINE_NATIVE_FUNCTION(PlainMonthDayPrototype::get_iso_fields) -{ - auto& realm = *vm.current_realm(); - - // 1. Let monthDay be the this value. - // 2. Perform ? RequireInternalSlot(monthDay, [[InitializedTemporalMonthDay]]). - auto month_day = TRY(typed_this_object(vm)); - - // 3. Let fields be OrdinaryObjectCreate(%Object.prototype%). - auto fields = Object::create(realm, realm.intrinsics().object_prototype()); - - // 4. Perform ! CreateDataPropertyOrThrow(fields, "calendar", monthDay.[[Calendar]]). - MUST(fields->create_data_property_or_throw(vm.names.calendar, Value(&month_day->calendar()))); - - // 5. Perform ! CreateDataPropertyOrThrow(fields, "isoDay", 𝔽(monthDay.[[ISODay]])). - MUST(fields->create_data_property_or_throw(vm.names.isoDay, Value(month_day->iso_day()))); - - // 6. Perform ! CreateDataPropertyOrThrow(fields, "isoMonth", 𝔽(monthDay.[[ISOMonth]])). - MUST(fields->create_data_property_or_throw(vm.names.isoMonth, Value(month_day->iso_month()))); - - // 7. Perform ! CreateDataPropertyOrThrow(fields, "isoYear", 𝔽(monthDay.[[ISOYear]])). - MUST(fields->create_data_property_or_throw(vm.names.isoYear, Value(month_day->iso_year()))); - - // 8. Return fields. - return fields; -} - -// 10.3.3 get Temporal.PlainMonthDay.prototype.calendarId -JS_DEFINE_NATIVE_FUNCTION(PlainMonthDayPrototype::calendar_id_getter) -{ - // Step 1: Let monthDay be the this value - // Step 2: Perform ? RequireInternalSlot(monthDay, [[InitializedTemporalMonthDay]]). - auto month_day = TRY(typed_this_object(vm)); - - // Step 3: Return monthDay.[[Calendar]]. - auto& calendar = static_cast(month_day->calendar()); - return PrimitiveString::create(vm, calendar.identifier()); -} - -} diff --git a/Libraries/LibJS/Runtime/Temporal/PlainMonthDayPrototype.h b/Libraries/LibJS/Runtime/Temporal/PlainMonthDayPrototype.h deleted file mode 100644 index 63c46ec2e5f..00000000000 --- a/Libraries/LibJS/Runtime/Temporal/PlainMonthDayPrototype.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2021, Linus Groh - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include -#include - -namespace JS::Temporal { - -class PlainMonthDayPrototype final : public PrototypeObject { - JS_PROTOTYPE_OBJECT(PlainMonthDayPrototype, PlainMonthDay, Temporal.PlainMonthDay); - GC_DECLARE_ALLOCATOR(PlainMonthDayPrototype); - -public: - virtual void initialize(Realm&) override; - virtual ~PlainMonthDayPrototype() override = default; - -private: - explicit PlainMonthDayPrototype(Realm&); - - JS_DECLARE_NATIVE_FUNCTION(calendar_getter); - JS_DECLARE_NATIVE_FUNCTION(calendar_id_getter); - JS_DECLARE_NATIVE_FUNCTION(month_code_getter); - JS_DECLARE_NATIVE_FUNCTION(day_getter); - JS_DECLARE_NATIVE_FUNCTION(with); - JS_DECLARE_NATIVE_FUNCTION(equals); - JS_DECLARE_NATIVE_FUNCTION(to_string); - JS_DECLARE_NATIVE_FUNCTION(to_locale_string); - JS_DECLARE_NATIVE_FUNCTION(to_json); - JS_DECLARE_NATIVE_FUNCTION(value_of); - JS_DECLARE_NATIVE_FUNCTION(to_plain_date); - JS_DECLARE_NATIVE_FUNCTION(get_iso_fields); -}; - -} diff --git a/Libraries/LibJS/Runtime/Temporal/PlainTime.cpp b/Libraries/LibJS/Runtime/Temporal/PlainTime.cpp deleted file mode 100644 index 99e87c963d6..00000000000 --- a/Libraries/LibJS/Runtime/Temporal/PlainTime.cpp +++ /dev/null @@ -1,690 +0,0 @@ -/* - * Copyright (c) 2021, Idan Horowitz - * Copyright (c) 2021-2023, Linus Groh - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace JS::Temporal { - -GC_DEFINE_ALLOCATOR(PlainTime); - -// 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(ConstructWithPrototypeTag::Tag, 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) -{ - Base::visit_edges(visitor); - visitor.visit(m_calendar); -} - -// 4.5.1 DifferenceTime ( h1, min1, s1, ms1, mus1, ns1, h2, min2, s2, ms2, mus2, ns2 ), https://tc39.es/proposal-temporal/#sec-temporal-differencetime -TimeDurationRecord difference_time(VM& vm, u8 hour1, u8 minute1, u8 second1, u16 millisecond1, u16 microsecond1, u16 nanosecond1, u8 hour2, u8 minute2, u8 second2, u16 millisecond2, u16 microsecond2, u16 nanosecond2) -{ - // 1. Let hours be h2 - h1. - auto hours = hour2 - hour1; - - // 2. Let minutes be min2 - min1. - auto minutes = minute2 - minute1; - - // 3. Let seconds be s2 - s1. - auto seconds = second2 - second1; - - // 4. Let milliseconds be ms2 - ms1. - auto milliseconds = millisecond2 - millisecond1; - - // 5. Let microseconds be mus2 - mus1. - auto microseconds = microsecond2 - microsecond1; - - // 6. Let nanoseconds be ns2 - ns1. - auto nanoseconds = nanosecond2 - nanosecond1; - - // 7. Let sign be ! DurationSign(0, 0, 0, 0, hours, minutes, seconds, milliseconds, microseconds, nanoseconds). - auto sign = duration_sign(0, 0, 0, 0, hours, minutes, seconds, milliseconds, microseconds, nanoseconds); - - // 8. Let bt be ! BalanceTime(hours × sign, minutes × sign, seconds × sign, milliseconds × sign, microseconds × sign, nanoseconds × sign). - auto bt = balance_time(hours * sign, minutes * sign, seconds * sign, milliseconds * sign, microseconds * sign, nanoseconds * sign); - - // 9. Assert: bt.[[Days]] is 0. - VERIFY(bt.days == 0); - - // 10. Return ! CreateTimeDurationRecord(0, bt.[[Hour]] × sign, bt.[[Minute]] × sign, bt.[[Second]] × sign, bt.[[Millisecond]] × sign, bt.[[Microsecond]] × sign, bt.[[Nanosecond]] × sign). - return MUST(create_time_duration_record(vm, 0, static_cast(bt.hour * sign), static_cast(bt.minute * sign), static_cast(bt.second * sign), static_cast(bt.millisecond * sign), static_cast(bt.microsecond * sign), static_cast(bt.nanosecond * sign))); -} - -// 4.5.2 ToTemporalTime ( item [ , overflow ] ), https://tc39.es/proposal-temporal/#sec-temporal-totemporaltime -ThrowCompletionOr to_temporal_time(VM& vm, Value item, Optional overflow) -{ - // 1. If overflow is not present, set overflow to "constrain". - if (!overflow.has_value()) - overflow = "constrain"sv; - - // 2. Assert: overflow is either "constrain" or "reject". - VERIFY(overflow == "constrain"sv || overflow == "reject"sv); - - Optional result; - - // 3. If Type(item) is Object, then - if (item.is_object()) { - auto& item_object = item.as_object(); - - // a. If item has an [[InitializedTemporalTime]] internal slot, then - if (is(item_object)) { - // i. Return item. - return &static_cast(item_object); - } - - // b. If item has an [[InitializedTemporalZonedDateTime]] internal slot, then - if (is(item_object)) { - auto& zoned_date_time = static_cast(item_object); - - // i. Let instant be ! CreateTemporalInstant(item.[[Nanoseconds]]). - auto* instant = create_temporal_instant(vm, zoned_date_time.nanoseconds()).release_value(); - - // ii. Set plainDateTime to ? BuiltinTimeZoneGetPlainDateTimeFor(item.[[TimeZone]], instant, item.[[Calendar]]). - auto* plain_date_time = TRY(builtin_time_zone_get_plain_date_time_for(vm, &zoned_date_time.time_zone(), *instant, zoned_date_time.calendar())); - - // iii. Return ! CreateTemporalTime(plainDateTime.[[ISOHour]], plainDateTime.[[ISOMinute]], plainDateTime.[[ISOSecond]], plainDateTime.[[ISOMillisecond]], plainDateTime.[[ISOMicrosecond]], plainDateTime.[[ISONanosecond]]). - return TRY(create_temporal_time(vm, plain_date_time->iso_hour(), plain_date_time->iso_minute(), plain_date_time->iso_second(), plain_date_time->iso_millisecond(), plain_date_time->iso_microsecond(), plain_date_time->iso_nanosecond())); - } - - // c. If item has an [[InitializedTemporalDateTime]] internal slot, then - if (is(item_object)) { - auto& plain_date_time = static_cast(item_object); - // i. Return ! CreateTemporalTime(item.[[ISOHour]], item.[[ISOMinute]], item.[[ISOSecond]], item.[[ISOMillisecond]], item.[[ISOMicrosecond]], item.[[ISONanosecond]]). - return TRY(create_temporal_time(vm, plain_date_time.iso_hour(), plain_date_time.iso_minute(), plain_date_time.iso_second(), plain_date_time.iso_millisecond(), plain_date_time.iso_microsecond(), plain_date_time.iso_nanosecond())); - } - - // d. Let calendar be ? GetTemporalCalendarWithISODefault(item). - auto* calendar = TRY(get_temporal_calendar_with_iso_default(vm, item_object)); - - // e. If ? ToString(calendar) is not "iso8601", then - auto calendar_identifier = TRY(Value(calendar).to_string(vm)); - if (calendar_identifier != "iso8601"sv) { - // i. Throw a RangeError exception. - return vm.throw_completion(ErrorType::TemporalInvalidCalendarIdentifier, calendar_identifier); - } - - // f. Let result be ? ToTemporalTimeRecord(item). - auto unregulated_result = TRY(to_temporal_time_record(vm, item_object)); - - // g. Set result to ? RegulateTime(result.[[Hour]], result.[[Minute]], result.[[Second]], result.[[Millisecond]], result.[[Microsecond]], result.[[Nanosecond]], overflow). - result = TRY(regulate_time(vm, *unregulated_result.hour, *unregulated_result.minute, *unregulated_result.second, *unregulated_result.millisecond, *unregulated_result.microsecond, *unregulated_result.nanosecond, *overflow)); - } - // 4. Else, - else { - // a. Let string be ? ToString(item). - auto string = TRY(item.to_string(vm)); - - // b. Let result be ? ParseTemporalTimeString(string). - result = TRY(parse_temporal_time_string(vm, string)); - - // c. Assert: IsValidTime(result.[[Hour]], result.[[Minute]], result.[[Second]], result.[[Millisecond]], result.[[Microsecond]], result.[[Nanosecond]]) is true. - VERIFY(is_valid_time(result->hour, result->minute, result->second, result->millisecond, result->microsecond, result->nanosecond)); - - // d. If result.[[Calendar]] is not one of undefined or "iso8601", then - if (result->calendar.has_value() && *result->calendar != "iso8601"sv) { - // i. Throw a RangeError exception. - return vm.throw_completion(ErrorType::TemporalInvalidCalendarIdentifier, *result->calendar); - } - } - - // 5. Return ! CreateTemporalTime(result.[[Hour]], result.[[Minute]], result.[[Second]], result.[[Millisecond]], result.[[Microsecond]], result.[[Nanosecond]]). - return MUST(create_temporal_time(vm, result->hour, result->minute, result->second, result->millisecond, result->microsecond, result->nanosecond)); -} - -// 4.5.3 RegulateTime ( hour, minute, second, millisecond, microsecond, nanosecond, overflow ), https://tc39.es/proposal-temporal/#sec-temporal-regulatetime -ThrowCompletionOr regulate_time(VM& vm, double hour, double minute, double second, double millisecond, double microsecond, double nanosecond, StringView overflow) -{ - // 1. Assert: hour, minute, second, millisecond, microsecond and nanosecond are integers. - VERIFY(trunc(hour) == hour && trunc(minute) == minute && trunc(second) == second && trunc(millisecond) == millisecond && trunc(microsecond) == microsecond && trunc(nanosecond) == nanosecond); - - // 2. Assert: overflow is either "constrain" or "reject". - // NOTE: Asserted by the VERIFY_NOT_REACHED at the end - - // 3. If overflow is "constrain", then - if (overflow == "constrain"sv) { - // a. Return ! ConstrainTime(hour, minute, second, millisecond, microsecond, nanosecond). - return constrain_time(hour, minute, second, millisecond, microsecond, nanosecond); - } - // 4. Else, - else { - // a. Assert: overflow is "reject". - VERIFY(overflow == "reject"sv); - - // b. If IsValidTime(hour, minute, second, millisecond, microsecond, nanosecond) is false, throw a RangeError exception. - if (!is_valid_time(hour, minute, second, millisecond, microsecond, nanosecond)) - return vm.throw_completion(ErrorType::TemporalInvalidPlainTime); - - // c. Return the Record { [[Hour]]: hour, [[Minute]]: minute, [[Second]]: second, [[Millisecond]]: millisecond, [[Microsecond]]: microsecond, [[Nanosecond]]: nanosecond }. - return TemporalTime { .hour = static_cast(hour), .minute = static_cast(minute), .second = static_cast(second), .millisecond = static_cast(millisecond), .microsecond = static_cast(microsecond), .nanosecond = static_cast(nanosecond) }; - } -} - -// 4.5.4 IsValidTime ( hour, minute, second, millisecond, microsecond, nanosecond ), https://tc39.es/proposal-temporal/#sec-temporal-isvalidtime -bool is_valid_time(double hour, double minute, double second, double millisecond, double microsecond, double nanosecond) -{ - // 1. If hour < 0 or hour > 23, then - if (hour > 23) { - // a. Return false. - return false; - } - - // 2. If minute < 0 or minute > 59, then - if (minute > 59) { - // a. Return false. - return false; - } - - // 3. If second < 0 or second > 59, then - if (second > 59) { - // a. Return false. - return false; - } - - // 4. If millisecond < 0 or millisecond > 999, then - if (millisecond > 999) { - // a. Return false. - return false; - } - - // 5. If microsecond < 0 or microsecond > 999, then - if (microsecond > 999) { - // a. Return false. - return false; - } - - // 6. If nanosecond < 0 or nanosecond > 999, then - if (nanosecond > 999) { - // a. Return false. - return false; - } - - // 7. Return true. - return true; -} - -// 4.5.5 BalanceTime ( hour, minute, second, millisecond, microsecond, nanosecond ), https://tc39.es/proposal-temporal/#sec-temporal-balancetime -DaysAndTime balance_time(double hour, double minute, double second, double millisecond, double microsecond, double nanosecond) -{ - // 1. Assert: hour, minute, second, millisecond, microsecond, and nanosecond are integers. - VERIFY(hour == trunc(hour) && minute == trunc(minute) && second == trunc(second) && millisecond == trunc(millisecond) && microsecond == trunc(microsecond) && nanosecond == trunc(nanosecond)); - - // 2. Set microsecond to microsecond + floor(nanosecond / 1000). - microsecond += floor(nanosecond / 1000); - - // 3. Set nanosecond to nanosecond modulo 1000. - nanosecond = modulo(nanosecond, 1000); - - // 4. Set millisecond to millisecond + floor(microsecond / 1000). - millisecond += floor(microsecond / 1000); - - // 5. Set microsecond to microsecond modulo 1000. - microsecond = modulo(microsecond, 1000); - - // 6. Set second to second + floor(millisecond / 1000). - second += floor(millisecond / 1000); - - // 7. Set millisecond to millisecond modulo 1000. - millisecond = modulo(millisecond, 1000); - - // 8. Set minute to minute + floor(second / 60). - minute += floor(second / 60); - - // 9. Set second to second modulo 60. - second = modulo(second, 60); - - // 10. Set hour to hour + floor(minute / 60). - hour += floor(minute / 60); - - // 11. Set minute to minute modulo 60. - minute = modulo(minute, 60); - - // 12. Let days be floor(hour / 24). - auto days = floor(hour / 24); - - // 13. Set hour to hour modulo 24. - hour = modulo(hour, 24); - - // 14. Return the Record { [[Days]]: days, [[Hour]]: hour, [[Minute]]: minute, [[Second]]: second, [[Millisecond]]: millisecond, [[Microsecond]]: microsecond, [[Nanosecond]]: nanosecond }. - return DaysAndTime { - .days = static_cast(days), - .hour = static_cast(hour), - .minute = static_cast(minute), - .second = static_cast(second), - .millisecond = static_cast(millisecond), - .microsecond = static_cast(microsecond), - .nanosecond = static_cast(nanosecond), - }; -} - -// 4.5.6 ConstrainTime ( hour, minute, second, millisecond, microsecond, nanosecond ), https://tc39.es/proposal-temporal/#sec-temporal-constraintime -TemporalTime constrain_time(double hour, double minute, double second, double millisecond, double microsecond, double nanosecond) -{ - // 1. Assert: hour, minute, second, millisecond, microsecond, and nanosecond are integers. - - // 2. Set hour to the result of clamping hour between 0 and 23. - hour = clamp(hour, 0, 23); - - // 3. Set minute to the result of clamping minute between 0 and 59. - minute = clamp(minute, 0, 59); - - // 4. Set second to the result of clamping second between 0 and 59. - second = clamp(second, 0, 59); - - // 5. Set millisecond to the result of clamping millisecond between 0 and 999. - millisecond = clamp(millisecond, 0, 999); - - // 6. Set microsecond to the result of clamping microsecond between 0 and 999. - microsecond = clamp(microsecond, 0, 999); - - // 7. Set nanosecond to the result of clamping nanosecond between 0 and 999. - nanosecond = clamp(nanosecond, 0, 999); - - // 8. Return the Record { [[Hour]]: hour, [[Minute]]: minute, [[Second]]: second, [[Millisecond]]: millisecond, [[Microsecond]]: microsecond, [[Nanosecond]]: nanosecond }. - return TemporalTime { .hour = static_cast(hour), .minute = static_cast(minute), .second = static_cast(second), .millisecond = static_cast(millisecond), .microsecond = static_cast(microsecond), .nanosecond = static_cast(nanosecond) }; -} - -// 4.5.7 CreateTemporalTime ( hour, minute, second, millisecond, microsecond, nanosecond [ , newTarget ] ), https://tc39.es/proposal-temporal/#sec-temporal-createtemporaltime -ThrowCompletionOr create_temporal_time(VM& vm, u8 hour, u8 minute, u8 second, u16 millisecond, u16 microsecond, u16 nanosecond, FunctionObject const* new_target) -{ - auto& realm = *vm.current_realm(); - - // 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)) - return vm.throw_completion(ErrorType::TemporalInvalidPlainTime); - - // 3. If newTarget is not present, set newTarget to %Temporal.PlainTime%. - if (!new_target) - new_target = realm.intrinsics().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(). - auto object = TRY(ordinary_create_from_constructor(vm, *new_target, &Intrinsics::temporal_plain_time_prototype, hour, minute, second, millisecond, microsecond, nanosecond, *get_iso8601_calendar(vm))); - - // 12. Return object. - return object.ptr(); -} - -// 4.5.8 ToTemporalTimeRecord ( temporalTimeLike [ , completeness ] ), https://tc39.es/proposal-temporal/#sec-temporal-totemporaltimerecord -ThrowCompletionOr to_temporal_time_record(VM& vm, Object const& temporal_time_like, ToTemporalTimeRecordCompleteness completeness) -{ - // 1. If completeness is not present, set completeness to complete. - - // 2. Let partial be ? PrepareTemporalFields(temporalTimeLike, « "hour", "microsecond", "millisecond", "minute", "nanosecond", "second" », partial). - auto* partial = TRY(prepare_temporal_fields(vm, temporal_time_like, - { "hour"_string, - "microsecond"_string, - "millisecond"_string, - "minute"_string, - "nanosecond"_string, - "second"_string }, - PrepareTemporalFieldsPartial {})); - - TemporalTimeLikeRecord result; - // 3. If completeness is complete, then - if (completeness == ToTemporalTimeRecordCompleteness::Complete) { - // a. Let result be a new TemporalTimeLike Record with each field set to 0. - result = TemporalTimeLikeRecord { 0, 0, 0, 0, 0, 0 }; - } - // 4. Else, - else { - // a. Let result be a new TemporalTimeLike Record with each field set to undefined. - result = TemporalTimeLikeRecord {}; - } - - // 5. Let hourDesc be OrdinaryGetOwnProperty(partial, "hour"). - auto hour_desc = MUST(partial->Object::internal_get_own_property(vm.names.hour)); - - // 6. If hourDesc is not undefined, then - if (hour_desc.has_value()) { - // a. Assert: hourDesc is a data Property Descriptor. - VERIFY(hour_desc->is_data_descriptor()); - - // b. Set result.[[Hour]] to ℝ(hourDesc.[[Value]]). - result.hour = hour_desc->value->as_double(); - } - - // 7. Let minuteDesc be OrdinaryGetOwnProperty(partial, "minute"). - auto minute_desc = MUST(partial->Object::internal_get_own_property(vm.names.minute)); - - // 8. If minuteDesc is not undefined, then - if (minute_desc.has_value()) { - // a. Assert: minuteDesc is a data Property Descriptor. - VERIFY(minute_desc->is_data_descriptor()); - - // b. Set result.[[Minute]] to ℝ(minuteDesc.[[Value]]). - result.minute = minute_desc->value->as_double(); - } - - // 9. Let secondDesc be OrdinaryGetOwnProperty(partial, "second"). - auto second_desc = MUST(partial->Object::internal_get_own_property(vm.names.second)); - - // 10. If secondDesc is not undefined, then - if (second_desc.has_value()) { - // a. Assert: secondDesc is a data Property Descriptor. - VERIFY(second_desc->is_data_descriptor()); - - // b. Set result.[[Second]] to ℝ(secondDesc.[[Value]]). - result.second = second_desc->value->as_double(); - } - - // 11. Let millisecondDesc be OrdinaryGetOwnProperty(partial, "millisecond"). - auto millisecond_desc = MUST(partial->Object::internal_get_own_property(vm.names.millisecond)); - - // 12. If millisecondDesc is not undefined, then - if (millisecond_desc.has_value()) { - // a. Assert: millisecondDesc is a data Property Descriptor. - VERIFY(millisecond_desc->is_data_descriptor()); - - // b. Set result.[[Millisecond]] to ℝ(millisecondDesc.[[Value]]). - result.millisecond = millisecond_desc->value->as_double(); - } - - // 13. Let microsecondDesc be OrdinaryGetOwnProperty(partial, "microsecond"). - auto microsecond_desc = MUST(partial->Object::internal_get_own_property(vm.names.microsecond)); - - // 14. If microsecondDesc is not undefined, then - if (microsecond_desc.has_value()) { - // a. Assert: microsecondDesc is a data Property Descriptor. - VERIFY(microsecond_desc->is_data_descriptor()); - - // b. Set result.[[Microsecond]] to ℝ(microsecondDesc.[[Value]]). - result.microsecond = microsecond_desc->value->as_double(); - } - - // 15. Let nanosecondDesc be OrdinaryGetOwnProperty(partial, "nanosecond"). - auto nanosecond_desc = MUST(partial->Object::internal_get_own_property(vm.names.nanosecond)); - - // 16. If nanosecondDesc is not undefined, then - if (nanosecond_desc.has_value()) { - // a. Assert: nanosecondDesc is a data Property Descriptor. - VERIFY(nanosecond_desc->is_data_descriptor()); - - // b. Set result.[[Nanosecond]] to ℝ(nanosecondDesc.[[Value]]). - result.nanosecond = nanosecond_desc->value->as_double(); - } - - // 17. Return result. - return result; -} - -// 4.5.9 TemporalTimeToString ( hour, minute, second, millisecond, microsecond, nanosecond, precision ), https://tc39.es/proposal-temporal/#sec-temporal-temporaltimetostring -ThrowCompletionOr temporal_time_to_string(VM& vm, u8 hour, u8 minute, u8 second, u16 millisecond, u16 microsecond, u16 nanosecond, Variant const& precision) -{ - // 1. Assert: hour, minute, second, millisecond, microsecond and nanosecond are integers. - - // 2. Let hour be ToZeroPaddedDecimalString(hour, 2). - // 3. Let minute be ToZeroPaddedDecimalString(minute, 2). - - // 4. Let seconds be ! FormatSecondsStringPart(second, millisecond, microsecond, nanosecond, precision). - auto seconds = MUST_OR_THROW_OOM(format_seconds_string_part(vm, second, millisecond, microsecond, nanosecond, precision)); - - // 5. Return the string-concatenation of hour, the code unit 0x003A (COLON), minute, and seconds. - return TRY_OR_THROW_OOM(vm, String::formatted("{:02}:{:02}{}", hour, minute, seconds)); -} - -// 4.5.10 CompareTemporalTime ( h1, min1, s1, ms1, mus1, ns1, h2, min2, s2, ms2, mus2, ns2 ), https://tc39.es/proposal-temporal/#sec-temporal-comparetemporaltime -i8 compare_temporal_time(u8 hour1, u8 minute1, u8 second1, u16 millisecond1, u16 microsecond1, u16 nanosecond1, u8 hour2, u8 minute2, u8 second2, u16 millisecond2, u16 microsecond2, u16 nanosecond2) -{ - // 1. Assert: h1, min1, s1, ms1, mus1, ns1, h2, min2, s2, ms2, mus2, and ns2 are integers. - - // 2. If h1 > h2, return 1. - if (hour1 > hour2) - return 1; - - // 3. If h1 < h2, return -1. - if (hour1 < hour2) - return -1; - - // 4. If min1 > min2, return 1. - if (minute1 > minute2) - return 1; - - // 5. If min1 < min2, return -1. - if (minute1 < minute2) - return -1; - - // 6. If s1 > s2, return 1. - if (second1 > second2) - return 1; - - // 7. If s1 < s2, return -1. - if (second1 < second2) - return -1; - - // 8. If ms1 > ms2, return 1. - if (millisecond1 > millisecond2) - return 1; - - // 9. If ms1 < ms2, return -1. - if (millisecond1 < millisecond2) - return -1; - - // 10. If mus1 > mus2, return 1. - if (microsecond1 > microsecond2) - return 1; - - // 11. If mus1 < mus2, return -1. - if (microsecond1 < microsecond2) - return -1; - - // 12. If ns1 > ns2, return 1. - if (nanosecond1 > nanosecond2) - return 1; - - // 13. If ns1 < ns2, return -1. - if (nanosecond1 < nanosecond2) - return -1; - - // 14. Return 0. - return 0; -} - -// 4.5.11 AddTime ( hour, minute, second, millisecond, microsecond, nanosecond, hours, minutes, seconds, milliseconds, microseconds, nanoseconds ), https://tc39.es/proposal-temporal/#sec-temporal-addtime -DaysAndTime add_time(u8 hour, u8 minute, u8 second, u16 millisecond, u16 microsecond, u16 nanosecond, double hours, double minutes, double seconds, double milliseconds, double microseconds, double nanoseconds) -{ - // 1. Assert: hour, minute, second, millisecond, microsecond, nanosecond, hours, minutes, seconds, milliseconds, microseconds, and nanoseconds are integers. - VERIFY(hours == trunc(hours) && minutes == trunc(minutes) && seconds == trunc(seconds) && milliseconds == trunc(milliseconds) && microseconds == trunc(microseconds) && nanoseconds == trunc(nanoseconds)); - - // 2. Assert: IsValidTime(hour, minute, second, millisecond, microsecond, nanosecond) is true. - VERIFY(is_valid_time(hour, minute, second, millisecond, microsecond, nanosecond)); - - // 3. Let hour be hour + hours. - auto hour_ = hour + hours; - - // 4. Let minute be minute + minutes. - auto minute_ = minute + minutes; - - // 5. Let second be second + seconds. - auto second_ = second + seconds; - - // 6. Let millisecond be millisecond + milliseconds. - auto millisecond_ = millisecond + milliseconds; - - // 7. Let microsecond be microsecond + microseconds. - auto microsecond_ = microsecond + microseconds; - - // 8. Let nanosecond be nanosecond + nanoseconds. - auto nanosecond_ = nanosecond + nanoseconds; - - // 9. Return ! BalanceTime(hour, minute, second, millisecond, microsecond, nanosecond). - return balance_time(hour_, minute_, second_, millisecond_, microsecond_, nanosecond_); -} - -// 4.5.12 RoundTime ( hour, minute, second, millisecond, microsecond, nanosecond, increment, unit, roundingMode [ , dayLengthNs ] ), https://tc39.es/proposal-temporal/#sec-temporal-roundtime -DaysAndTime round_time(u8 hour, u8 minute, u8 second, u16 millisecond, u16 microsecond, u16 nanosecond, u64 increment, StringView unit, StringView rounding_mode, Optional day_length_ns) -{ - // 1. Assert: hour, minute, second, millisecond, microsecond, nanosecond, and increment are integers. - - // 2. Let fractionalSecond be nanosecond × 10-9 + microsecond × 10-6 + millisecond × 10-3 + second. - double fractional_second = nanosecond * 0.000000001 + microsecond * 0.000001 + millisecond * 0.001 + second; - double quantity; - - // 3. If unit is "day", then - if (unit == "day"sv) { - // a. If dayLengthNs is not present, set dayLengthNs to nsPerDay. - if (!day_length_ns.has_value()) - day_length_ns = ns_per_day; - - // b. Let quantity be (((((hour × 60 + minute) × 60 + second) × 1000 + millisecond) × 1000 + microsecond) × 1000 + nanosecond) / dayLengthNs. - quantity = (((((hour * 60.0 + minute) * 60.0 + second) * 1000.0 + millisecond) * 1000.0 + microsecond) * 1000.0 + nanosecond) / *day_length_ns; - } - // 4. Else if unit is "hour", then - else if (unit == "hour"sv) { - // a. Let quantity be (fractionalSecond / 60 + minute) / 60 + hour. - quantity = (fractional_second / 60.0 + minute) / 60.0 + hour; - } - // 5. Else if unit is "minute", then - else if (unit == "minute"sv) { - // a. Let quantity be fractionalSecond / 60 + minute. - quantity = fractional_second / 60.0 + minute; - } - // 6. Else if unit is "second", then - else if (unit == "second"sv) { - // a. Let quantity be fractionalSecond. - quantity = fractional_second; - } - // 7. Else if unit is "millisecond", then - else if (unit == "millisecond"sv) { - // a. Let quantity be nanosecond × 10-6 + microsecond × 10-3 + millisecond. - quantity = nanosecond * 0.000001 + 0.001 * microsecond + millisecond; - } - // 8. Else if unit is "microsecond", then - else if (unit == "microsecond"sv) { - // a. Let quantity be nanosecond × 10-3 + microsecond. - quantity = nanosecond * 0.001 + microsecond; - } - // 9. Else, - else { - // a. Assert: unit is "nanosecond". - VERIFY(unit == "nanosecond"sv); - - // b. Let quantity be nanosecond. - quantity = nanosecond; - } - - // 10. Let result be RoundNumberToIncrement(quantity, increment, roundingMode). - auto result = round_number_to_increment(quantity, increment, rounding_mode); - - // If unit is "day", then - if (unit == "day"sv) { - // a. Return the Record { [[Days]]: result, [[Hour]]: 0, [[Minute]]: 0, [[Second]]: 0, [[Millisecond]]: 0, [[Microsecond]]: 0, [[Nanosecond]]: 0 }. - return DaysAndTime { .days = (i32)result, .hour = 0, .minute = 0, .second = 0, .millisecond = 0, .microsecond = 0, .nanosecond = 0 }; - } - - // 12. If unit is "hour", then - if (unit == "hour"sv) { - // a. Return ! BalanceTime(result, 0, 0, 0, 0, 0). - return balance_time(result, 0, 0, 0, 0, 0); - } - - // 13. If unit is "minute", then - if (unit == "minute"sv) { - // a. Return ! BalanceTime(hour, result, 0, 0, 0, 0). - return balance_time(hour, result, 0, 0, 0, 0); - } - - // 14. If unit is "second", then - if (unit == "second"sv) { - // a. Return ! BalanceTime(hour, minute, result, 0, 0, 0). - return balance_time(hour, minute, result, 0, 0, 0); - } - - // 15. If unit is "millisecond", then - if (unit == "millisecond"sv) { - // a. Return ! BalanceTime(hour, minute, second, result, 0, 0). - return balance_time(hour, minute, second, result, 0, 0); - } - - // 16. If unit is "microsecond", then - if (unit == "microsecond"sv) { - // a. Return ! BalanceTime(hour, minute, second, millisecond, result, 0). - return balance_time(hour, minute, second, millisecond, result, 0); - } - - // 17. Assert: unit is "nanosecond". - VERIFY(unit == "nanosecond"sv); - - // 18. Return ! BalanceTime(hour, minute, second, millisecond, microsecond, result). - return balance_time(hour, minute, second, millisecond, microsecond, result); -} - -// 4.5.13 DifferenceTemporalPlainTime ( operation, temporalTime, other, options ), https://tc39.es/proposal-temporal/#sec-temporal-differencetemporalplaintime -ThrowCompletionOr> difference_temporal_plain_time(VM& vm, DifferenceOperation operation, PlainTime const& temporal_time, Value other_value, Value options_value) -{ - // 1. If operation is since, let sign be -1. Otherwise, let sign be 1. - i8 sign = operation == DifferenceOperation::Since ? -1 : 1; - - // 2. Set other to ? ToTemporalTime(other). - auto* other = TRY(to_temporal_time(vm, other_value)); - - // 3. Let settings be ? GetDifferenceSettings(operation, options, time, « », "nanosecond", "hour"). - auto settings = TRY(get_difference_settings(vm, operation, options_value, UnitGroup::Time, {}, { "nanosecond"sv }, "hour"sv)); - - // 4. Let result be ! DifferenceTime(temporalTime.[[ISOHour]], temporalTime.[[ISOMinute]], temporalTime.[[ISOSecond]], temporalTime.[[ISOMillisecond]], temporalTime.[[ISOMicrosecond]], temporalTime.[[ISONanosecond]], other.[[ISOHour]], other.[[ISOMinute]], other.[[ISOSecond]], other.[[ISOMillisecond]], other.[[ISOMicrosecond]], other.[[ISONanosecond]]). - auto result = difference_time(vm, temporal_time.iso_hour(), temporal_time.iso_minute(), temporal_time.iso_second(), temporal_time.iso_millisecond(), temporal_time.iso_microsecond(), temporal_time.iso_nanosecond(), other->iso_hour(), other->iso_minute(), other->iso_second(), other->iso_millisecond(), other->iso_microsecond(), other->iso_nanosecond()); - - // 5. Set result to (! RoundDuration(0, 0, 0, 0, result.[[Hours]], result.[[Minutes]], result.[[Seconds]], result.[[Milliseconds]], result.[[Microseconds]], result.[[Nanoseconds]], settings.[[RoundingIncrement]], settings.[[SmallestUnit]], settings.[[RoundingMode]])).[[DurationRecord]]. - auto rounded_result = MUST(round_duration(vm, 0, 0, 0, 0, result.hours, result.minutes, result.seconds, result.milliseconds, result.microseconds, result.nanoseconds, settings.rounding_increment, settings.smallest_unit, settings.rounding_mode)).duration_record; - - // 6. Set result to ! BalanceDuration(0, result.[[Hours]], result.[[Minutes]], result.[[Seconds]], result.[[Milliseconds]], result.[[Microseconds]], result.[[Nanoseconds]], settings.[[LargestUnit]]). - result = MUST(balance_duration(vm, 0, rounded_result.hours, rounded_result.minutes, rounded_result.seconds, rounded_result.milliseconds, rounded_result.microseconds, Crypto::SignedBigInteger { rounded_result.nanoseconds }, settings.largest_unit)); - - // 7. Return ! CreateTemporalDuration(0, 0, 0, 0, sign × result.[[Hours]], sign × result.[[Minutes]], sign × result.[[Seconds]], sign × result.[[Milliseconds]], sign × result.[[Microseconds]], sign × result.[[Nanoseconds]]). - return MUST(create_temporal_duration(vm, 0, 0, 0, 0, sign * result.hours, sign * result.minutes, sign * result.seconds, sign * result.milliseconds, sign * result.microseconds, sign * result.nanoseconds)); -} - -// 4.5.14 AddDurationToOrSubtractDurationFromPlainTime ( operation, temporalTime, temporalDurationLike ), https://tc39.es/proposal-temporal/#sec-temporal-adddurationtoorsubtractdurationfromplaintime -ThrowCompletionOr add_duration_to_or_subtract_duration_from_plain_time(VM& vm, ArithmeticOperation operation, PlainTime const& temporal_time, Value temporal_duration_like) -{ - // 1. If operation is subtract, let sign be -1. Otherwise, let sign be 1. - i8 sign = operation == ArithmeticOperation::Subtract ? -1 : 1; - - // 2. Let duration be ? ToTemporalDurationRecord(temporalDurationLike). - auto duration = TRY(to_temporal_duration_record(vm, temporal_duration_like)); - - // 3. Let result be ! AddTime(temporalTime.[[ISOHour]], temporalTime.[[ISOMinute]], temporalTime.[[ISOSecond]], temporalTime.[[ISOMillisecond]], temporalTime.[[ISOMicrosecond]], temporalTime.[[ISONanosecond]], sign × duration.[[Hours]], sign × duration.[[Minutes]], sign × duration.[[Seconds]], sign × duration.[[Milliseconds]], sign × duration.[[Microseconds]], sign × duration.[[Nanoseconds]]). - auto result = add_time(temporal_time.iso_hour(), temporal_time.iso_minute(), temporal_time.iso_second(), temporal_time.iso_millisecond(), temporal_time.iso_microsecond(), temporal_time.iso_nanosecond(), sign * duration.hours, sign * duration.minutes, sign * duration.seconds, sign * duration.milliseconds, sign * duration.microseconds, sign * duration.nanoseconds); - - // 4. Assert: IsValidTime(result.[[Hour]], result.[[Minute]], result.[[Second]], result.[[Millisecond]], result.[[Microsecond]], result.[[Nanosecond]]) is true. - VERIFY(is_valid_time(result.hour, result.minute, result.second, result.millisecond, result.microsecond, result.nanosecond)); - - // 5. Return ! CreateTemporalTime(result.[[Hour]], result.[[Minute]], result.[[Second]], result.[[Millisecond]], result.[[Microsecond]], result.[[Nanosecond]]). - return MUST(create_temporal_time(vm, result.hour, result.minute, result.second, result.millisecond, result.microsecond, result.nanosecond)); -} - -} diff --git a/Libraries/LibJS/Runtime/Temporal/PlainTime.h b/Libraries/LibJS/Runtime/Temporal/PlainTime.h deleted file mode 100644 index e7b9bd37c13..00000000000 --- a/Libraries/LibJS/Runtime/Temporal/PlainTime.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (c) 2021, Idan Horowitz - * Copyright (c) 2021-2023, Linus Groh - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include -#include -#include -#include -#include - -namespace JS::Temporal { - -class PlainTime final : public Object { - JS_OBJECT(PlainTime, Object); - GC_DECLARE_ALLOCATOR(PlainTime); - -public: - 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: - PlainTime(u8 iso_hour, u8 iso_minute, u8 iso_second, u16 iso_millisecond, u16 iso_microsecond, u16 iso_nanosecond, Calendar& calendar, Object& prototype); - - 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]] - GC::Ref m_calendar; // [[Calendar]] (always the built-in ISO 8601 calendar) -}; - -struct DaysAndTime { - i32 days; - u8 hour; - u8 minute; - u8 second; - u16 millisecond; - u16 microsecond; - u16 nanosecond; -}; - -struct TemporalTimeLikeRecord { - Optional hour; - Optional minute; - Optional second; - Optional millisecond; - Optional microsecond; - Optional nanosecond; -}; - -// Table 4: TemporalTimeLike Record Fields, https://tc39.es/proposal-temporal/#table-temporal-temporaltimelike-properties - -template -struct TemporalTimeLikeRecordField { - ValueT StructT::*field_name { nullptr }; - PropertyKey property_name; -}; - -enum class ToTemporalTimeRecordCompleteness { - Partial, - Complete, -}; - -TimeDurationRecord difference_time(VM&, u8 hour1, u8 minute1, u8 second1, u16 millisecond1, u16 microsecond1, u16 nanosecond1, u8 hour2, u8 minute2, u8 second2, u16 millisecond2, u16 microsecond2, u16 nanosecond2); -ThrowCompletionOr to_temporal_time(VM&, Value item, Optional overflow = {}); -ThrowCompletionOr regulate_time(VM&, 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(double hour, double minute, double second, double millisecond, double microsecond, double nanosecond); -TemporalTime constrain_time(double hour, double minute, double second, double millisecond, double microsecond, double nanosecond); -ThrowCompletionOr create_temporal_time(VM&, u8 hour, u8 minute, u8 second, u16 millisecond, u16 microsecond, u16 nanosecond, FunctionObject const* new_target = nullptr); -ThrowCompletionOr to_temporal_time_record(VM&, Object const& temporal_time_like, ToTemporalTimeRecordCompleteness = ToTemporalTimeRecordCompleteness::Complete); -ThrowCompletionOr temporal_time_to_string(VM&, u8 hour, u8 minute, u8 second, u16 millisecond, u16 microsecond, u16 nanosecond, Variant const& precision); -i8 compare_temporal_time(u8 hour1, u8 minute1, u8 second1, u16 millisecond1, u16 microsecond1, u16 nanosecond1, u8 hour2, u8 minute2, u8 second2, u16 millisecond2, u16 microsecond2, u16 nanosecond2); -DaysAndTime add_time(u8 hour, u8 minute, u8 second, u16 millisecond, u16 microsecond, u16 nanosecond, double hours, double minutes, double seconds, double milliseconds, double microseconds, double nanoseconds); -DaysAndTime round_time(u8 hour, u8 minute, u8 second, u16 millisecond, u16 microsecond, u16 nanosecond, u64 increment, StringView unit, StringView rounding_mode, Optional day_length_ns = {}); -ThrowCompletionOr> difference_temporal_plain_time(VM&, DifferenceOperation, PlainTime const&, Value other, Value options); -ThrowCompletionOr add_duration_to_or_subtract_duration_from_plain_time(VM&, ArithmeticOperation, PlainTime const&, Value temporal_duration_like); - -} diff --git a/Libraries/LibJS/Runtime/Temporal/PlainTimeConstructor.cpp b/Libraries/LibJS/Runtime/Temporal/PlainTimeConstructor.cpp deleted file mode 100644 index c505c895128..00000000000 --- a/Libraries/LibJS/Runtime/Temporal/PlainTimeConstructor.cpp +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (c) 2021-2023, Linus Groh - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include -#include -#include -#include -#include - -namespace JS::Temporal { - -GC_DEFINE_ALLOCATOR(PlainTimeConstructor); - -// 4.1 The Temporal.PlainTime Constructor, https://tc39.es/proposal-temporal/#sec-temporal-plaintime-constructor -PlainTimeConstructor::PlainTimeConstructor(Realm& realm) - : NativeFunction(realm.vm().names.PlainTime.as_string(), realm.intrinsics().function_prototype()) -{ -} - -void PlainTimeConstructor::initialize(Realm& realm) -{ - Base::initialize(realm); - - 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, realm.intrinsics().temporal_plain_time_prototype(), 0); - - u8 attr = Attribute::Writable | Attribute::Configurable; - define_native_function(realm, vm.names.from, from, 1, attr); - define_native_function(realm, vm.names.compare, compare, 2, attr); - - 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 -ThrowCompletionOr PlainTimeConstructor::call() -{ - auto& vm = this->vm(); - - // 1. If NewTarget is undefined, throw a TypeError exception. - return vm.throw_completion(ErrorType::ConstructorWithoutNew, "Temporal.PlainTime"); -} - -// 4.1.1 Temporal.PlainTime ( [ hour [ , minute [ , second [ , millisecond [ , microsecond [ , nanosecond ] ] ] ] ] ] ), https://tc39.es/proposal-temporal/#sec-temporal.plaintime -ThrowCompletionOr> PlainTimeConstructor::construct(FunctionObject& new_target) -{ - auto& vm = this->vm(); - - // 2. Let hour be ? ToIntegerWithTruncation(hour). - auto hour = TRY(to_integer_with_truncation(vm, vm.argument(0), ErrorType::TemporalInvalidPlainTime)); - - // 3. Let minute be ? ToIntegerWithTruncation(hour). - auto minute = TRY(to_integer_with_truncation(vm, vm.argument(1), ErrorType::TemporalInvalidPlainTime)); - - // 4. Let second be ? ToIntegerWithTruncation(hour). - auto second = TRY(to_integer_with_truncation(vm, vm.argument(2), ErrorType::TemporalInvalidPlainTime)); - - // 5. Let millisecond be ? ToIntegerWithTruncation(hour). - auto millisecond = TRY(to_integer_with_truncation(vm, vm.argument(3), ErrorType::TemporalInvalidPlainTime)); - - // 6. Let microsecond be ? ToIntegerWithTruncation(hour). - auto microsecond = TRY(to_integer_with_truncation(vm, vm.argument(4), ErrorType::TemporalInvalidPlainTime)); - - // 7. Let nanosecond be ? ToIntegerWithTruncation(hour). - auto nanosecond = TRY(to_integer_with_truncation(vm, vm.argument(5), ErrorType::TemporalInvalidPlainTime)); - - // 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 behavior 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(hour) || !AK::is_within_range(minute) || !AK::is_within_range(second) || !AK::is_within_range(millisecond) || !AK::is_within_range(microsecond) || !AK::is_within_range(nanosecond)) - return vm.throw_completion(ErrorType::TemporalInvalidPlainTime); - - // 8. Return ? CreateTemporalTime(hour, minute, second, millisecond, microsecond, nanosecond, NewTarget). - return *TRY(create_temporal_time(vm, hour, minute, second, millisecond, microsecond, nanosecond, &new_target)); -} - -// 4.2.2 Temporal.PlainTime.from ( item [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal.plaintime.from -JS_DEFINE_NATIVE_FUNCTION(PlainTimeConstructor::from) -{ - // 1. Set options to ? GetOptionsObject(options). - auto* options = TRY(get_options_object(vm, vm.argument(1))); - - // 2. Let overflow be ? ToTemporalOverflow(options). - auto overflow = TRY(to_temporal_overflow(vm, options)); - - auto item = vm.argument(0); - - // 3. If Type(item) is Object and item has an [[InitializedTemporalTime]] internal slot, then - if (item.is_object() && is(item.as_object())) { - auto& plain_time = static_cast(item.as_object()); - // a. Return ! CreateTemporalTime(item.[[ISOHour]], item.[[ISOMinute]], item.[[ISOSecond]], item.[[ISOMillisecond]], item.[[ISOMicrosecond]], item.[[ISONanosecond]]). - return MUST(create_temporal_time(vm, plain_time.iso_hour(), plain_time.iso_minute(), plain_time.iso_second(), plain_time.iso_millisecond(), plain_time.iso_microsecond(), plain_time.iso_nanosecond())); - } - - // 4. Return ? ToTemporalTime(item, overflow). - return TRY(to_temporal_time(vm, item, overflow)); -} - -// 4.2.3 Temporal.PlainTime.compare ( one, two ), https://tc39.es/proposal-temporal/#sec-temporal.plaintime.compare -JS_DEFINE_NATIVE_FUNCTION(PlainTimeConstructor::compare) -{ - // 1. Set one to ? ToTemporalTime(one). - auto* one = TRY(to_temporal_time(vm, vm.argument(0))); - - // 2. Set two to ? ToTemporalTime(two). - auto* two = TRY(to_temporal_time(vm, vm.argument(1))); - - // 3. Return 𝔽(! CompareTemporalTime(one.[[ISOHour]], one.[[ISOMinute]], one.[[ISOSecond]], one.[[ISOMillisecond]], one.[[ISOMicrosecond]], one.[[ISONanosecond]], two.[[ISOHour]], two.[[ISOMinute]], two.[[ISOSecond]], two.[[ISOMillisecond]], two.[[ISOMicrosecond]], two.[[ISONanosecond]])). - return Value(compare_temporal_time(one->iso_hour(), one->iso_minute(), one->iso_second(), one->iso_millisecond(), one->iso_microsecond(), one->iso_nanosecond(), two->iso_hour(), two->iso_minute(), two->iso_second(), two->iso_millisecond(), two->iso_microsecond(), two->iso_nanosecond())); -} - -} diff --git a/Libraries/LibJS/Runtime/Temporal/PlainTimeConstructor.h b/Libraries/LibJS/Runtime/Temporal/PlainTimeConstructor.h deleted file mode 100644 index dc754dbe780..00000000000 --- a/Libraries/LibJS/Runtime/Temporal/PlainTimeConstructor.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2021-2022, Linus Groh - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include - -namespace JS::Temporal { - -class PlainTimeConstructor final : public NativeFunction { - JS_OBJECT(PlainTimeConstructor, NativeFunction); - GC_DECLARE_ALLOCATOR(PlainTimeConstructor); - -public: - virtual void initialize(Realm&) override; - virtual ~PlainTimeConstructor() override = default; - - virtual ThrowCompletionOr call() override; - virtual ThrowCompletionOr> construct(FunctionObject& new_target) override; - -private: - explicit PlainTimeConstructor(Realm&); - - virtual bool has_constructor() const override { return true; } - - JS_DECLARE_NATIVE_FUNCTION(from); - JS_DECLARE_NATIVE_FUNCTION(compare); -}; - -} diff --git a/Libraries/LibJS/Runtime/Temporal/PlainTimePrototype.cpp b/Libraries/LibJS/Runtime/Temporal/PlainTimePrototype.cpp deleted file mode 100644 index 3e9afbb38f4..00000000000 --- a/Libraries/LibJS/Runtime/Temporal/PlainTimePrototype.cpp +++ /dev/null @@ -1,518 +0,0 @@ -/* - * Copyright (c) 2021-2023, Linus Groh - * Copyright (c) 2021, Luke Wilde - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace JS::Temporal { - -GC_DEFINE_ALLOCATOR(PlainTimePrototype); - -// 4.3 Properties of the Temporal.PlainTime Prototype Object, https://tc39.es/proposal-temporal/#sec-properties-of-the-temporal-plaintime-prototype-object -PlainTimePrototype::PlainTimePrototype(Realm& realm) - : PrototypeObject(realm.intrinsics().object_prototype()) -{ -} - -void PlainTimePrototype::initialize(Realm& realm) -{ - Base::initialize(realm); - - auto& vm = this->vm(); - - // 4.3.2 Temporal.PlainTime.prototype[ @@toStringTag ], https://tc39.es/proposal-temporal/#sec-temporal.plaintime.prototype-@@tostringtag - define_direct_property(vm.well_known_symbol_to_string_tag(), PrimitiveString::create(vm, "Temporal.PlainTime"_string), Attribute::Configurable); - - define_native_accessor(realm, vm.names.calendar, calendar_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.hour, hour_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.minute, minute_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.second, second_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.millisecond, millisecond_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.microsecond, microsecond_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.nanosecond, nanosecond_getter, {}, Attribute::Configurable); - - u8 attr = Attribute::Writable | Attribute::Configurable; - define_native_function(realm, vm.names.add, add, 1, attr); - define_native_function(realm, vm.names.subtract, subtract, 1, attr); - define_native_function(realm, vm.names.with, with, 1, attr); - define_native_function(realm, vm.names.until, until, 1, attr); - define_native_function(realm, vm.names.since, since, 1, attr); - define_native_function(realm, vm.names.round, round, 1, attr); - define_native_function(realm, vm.names.equals, equals, 1, attr); - define_native_function(realm, vm.names.toPlainDateTime, to_plain_date_time, 1, attr); - define_native_function(realm, vm.names.toZonedDateTime, to_zoned_date_time, 1, attr); - define_native_function(realm, vm.names.getISOFields, get_iso_fields, 0, attr); - define_native_function(realm, vm.names.toString, to_string, 0, attr); - define_native_function(realm, vm.names.toLocaleString, to_locale_string, 0, attr); - define_native_function(realm, vm.names.toJSON, to_json, 0, attr); - define_native_function(realm, vm.names.valueOf, value_of, 0, attr); -} - -// 4.3.3 get Temporal.PlainTime.prototype.calendar, https://tc39.es/proposal-temporal/#sec-get-temporal.plaintime.prototype.calendar -JS_DEFINE_NATIVE_FUNCTION(PlainTimePrototype::calendar_getter) -{ - // 1. Let temporalTime be the this value. - // 2. Perform ? RequireInternalSlot(temporalTime, [[InitializedTemporalTime]]). - auto temporal_time = TRY(typed_this_object(vm)); - - // 3. Return temporalTime.[[Calendar]]. - return Value(&temporal_time->calendar()); -} - -// 4.3.4 get Temporal.PlainTime.prototype.hour, https://tc39.es/proposal-temporal/#sec-get-temporal.plaintime.prototype.hour -JS_DEFINE_NATIVE_FUNCTION(PlainTimePrototype::hour_getter) -{ - // 1. Let temporalTime be the this value. - // 2. Perform ? RequireInternalSlot(temporalTime, [[InitializedTemporalTime]]). - auto temporal_time = TRY(typed_this_object(vm)); - - // 3. Return 𝔽(temporalTime.[[ISOHour]]). - return Value(temporal_time->iso_hour()); -} - -// 4.3.5 get Temporal.PlainTime.prototype.minute, https://tc39.es/proposal-temporal/#sec-get-temporal.plaintime.prototype.minute -JS_DEFINE_NATIVE_FUNCTION(PlainTimePrototype::minute_getter) -{ - // 1. Let temporalTime be the this value. - // 2. Perform ? RequireInternalSlot(temporalTime, [[InitializedTemporalTime]]). - auto temporal_time = TRY(typed_this_object(vm)); - - // 3. Return 𝔽(temporalTime.[[ISOMinute]]). - return Value(temporal_time->iso_minute()); -} - -// 4.3.6 get Temporal.PlainTime.prototype.second, https://tc39.es/proposal-temporal/#sec-get-temporal.plaintime.prototype.second -JS_DEFINE_NATIVE_FUNCTION(PlainTimePrototype::second_getter) -{ - // 1. Let temporalTime be the this value. - // 2. Perform ? RequireInternalSlot(temporalTime, [[InitializedTemporalTime]]). - auto temporal_time = TRY(typed_this_object(vm)); - - // 3. Return 𝔽(temporalTime.[[ISOSecond]]). - return Value(temporal_time->iso_second()); -} - -// 4.3.7 get Temporal.PlainTime.prototype.millisecond, https://tc39.es/proposal-temporal/#sec-get-temporal.plaintime.prototype.millisecond -JS_DEFINE_NATIVE_FUNCTION(PlainTimePrototype::millisecond_getter) -{ - // 1. Let temporalTime be the this value. - // 2. Perform ? RequireInternalSlot(temporalTime, [[InitializedTemporalTime]]). - auto temporal_time = TRY(typed_this_object(vm)); - - // 3. Return 𝔽(temporalTime.[[ISOMillisecond]]). - return Value(temporal_time->iso_millisecond()); -} - -// 4.3.8 get Temporal.PlainTime.prototype.microsecond, https://tc39.es/proposal-temporal/#sec-get-temporal.plaintime.prototype.microsecond -JS_DEFINE_NATIVE_FUNCTION(PlainTimePrototype::microsecond_getter) -{ - // 1. Let temporalTime be the this value. - // 2. Perform ? RequireInternalSlot(temporalTime, [[InitializedTemporalTime]]). - auto temporal_time = TRY(typed_this_object(vm)); - - // 3. Return 𝔽(temporalTime.[[ISOMicrosecond]]). - return Value(temporal_time->iso_microsecond()); -} - -// 4.3.9 get Temporal.PlainTime.prototype.nanosecond, https://tc39.es/proposal-temporal/#sec-get-temporal.plaintime.prototype.nanosecond -JS_DEFINE_NATIVE_FUNCTION(PlainTimePrototype::nanosecond_getter) -{ - // 1. Let temporalTime be the this value. - // 2. Perform ? RequireInternalSlot(temporalTime, [[InitializedTemporalTime]]). - auto temporal_time = TRY(typed_this_object(vm)); - - // 3. Return 𝔽(temporalTime.[[ISONanosecond]]). - return Value(temporal_time->iso_nanosecond()); -} - -// 4.3.10 Temporal.PlainTime.prototype.add ( temporalDurationLike ), https://tc39.es/proposal-temporal/#sec-temporal.plaintime.prototype.add -JS_DEFINE_NATIVE_FUNCTION(PlainTimePrototype::add) -{ - auto temporal_duration_like = vm.argument(0); - - // 1. Let temporalTime be the this value. - // 2. Perform ? RequireInternalSlot(temporalTime, [[InitializedTemporalTime]]). - auto temporal_time = TRY(typed_this_object(vm)); - - // 3. Return ? AddDurationToOrSubtractDurationFromPlainTime(add, temporalTime, temporalDurationLike). - return TRY(add_duration_to_or_subtract_duration_from_plain_time(vm, ArithmeticOperation::Add, temporal_time, temporal_duration_like)); -} - -// 4.3.11 Temporal.PlainTime.prototype.subtract ( temporalDurationLike ), https://tc39.es/proposal-temporal/#sec-temporal.plaintime.prototype.subtract -JS_DEFINE_NATIVE_FUNCTION(PlainTimePrototype::subtract) -{ - auto temporal_duration_like = vm.argument(0); - - // 1. Let temporalTime be the this value. - // 2. Perform ? RequireInternalSlot(temporalTime, [[InitializedTemporalTime]]). - auto temporal_time = TRY(typed_this_object(vm)); - - // 3. Return ? AddDurationToOrSubtractDurationFromPlainTime(subtract, temporalTime, temporalDurationLike). - return TRY(add_duration_to_or_subtract_duration_from_plain_time(vm, ArithmeticOperation::Subtract, temporal_time, temporal_duration_like)); -} - -// 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 = TRY(typed_this_object(vm)); - - 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. - return vm.throw_completion(ErrorType::NotAnObject, temporal_time_like_argument.to_string_without_side_effects()); - } - - auto& temporal_time_like = temporal_time_like_argument.as_object(); - - // 4. Perform ? RejectObjectWithCalendarOrTimeZone(temporalTimeLike). - TRY(reject_object_with_calendar_or_time_zone(vm, temporal_time_like)); - - // 5. Let partialTime be ? ToTemporalTimeRecord(temporalTimeLike, partial). - auto partial_time = TRY(to_temporal_time_record(vm, temporal_time_like, ToTemporalTimeRecordCompleteness::Partial)); - - // 6. Set options to ? GetOptionsObject(options). - auto* options = TRY(get_options_object(vm, vm.argument(1))); - - // 7. Let overflow be ? ToTemporalOverflow(options). - auto overflow = TRY(to_temporal_overflow(vm, options)); - - // 8. If partialTime.[[Hour]] is not undefined, then - // a. Let hour be partialTime.[[Hour]]. - // 9. Else, - // a. Let hour be temporalTime.[[ISOHour]]. - auto hour = partial_time.hour.value_or(temporal_time->iso_hour()); - - // 10. If partialTime.[[Minute]] is not undefined, then - // a. Let minute be partialTime.[[Minute]]. - // 11. Else, - // a. Let minute be temporalTime.[[ISOMinute]]. - auto minute = partial_time.minute.value_or(temporal_time->iso_minute()); - - // 12. If partialTime.[[Second]] is not undefined, then - // a. Let second be partialTime.[[Second]]. - // 13. Else, - // a. Let second be temporalTime.[[ISOSecond]]. - auto second = partial_time.second.value_or(temporal_time->iso_second()); - - // 14. If partialTime.[[Millisecond]] is not undefined, then - // a. Let millisecond be partialTime.[[Millisecond]]. - // 15. Else, - // a. Let millisecond be temporalTime.[[ISOMillisecond]]. - auto millisecond = partial_time.millisecond.value_or(temporal_time->iso_millisecond()); - - // 16. If partialTime.[[Microsecond]] is not undefined, then - // a. Let microsecond be partialTime.[[Microsecond]]. - // 17. Else, - // a. Let microsecond be temporalTime.[[ISOMicrosecond]]. - auto microsecond = partial_time.microsecond.value_or(temporal_time->iso_microsecond()); - - // 18. If partialTime.[[Nanosecond]] is not undefined, then - // a. Let nanosecond be partialTime.[[Nanosecond]]. - // 19. Else, - // a. Let nanosecond be temporalTime.[[ISONanosecond]]. - auto nanosecond = partial_time.nanosecond.value_or(temporal_time->iso_nanosecond()); - - // 20. Let result be ? RegulateTime(hour, minute, second, millisecond, microsecond, nanosecond, overflow). - auto result = TRY(regulate_time(vm, hour, minute, second, millisecond, microsecond, nanosecond, overflow)); - - // 21. Return ! CreateTemporalTime(result.[[Hour]], result.[[Minute]], result.[[Second]], result.[[Millisecond]], result.[[Microsecond]], result.[[Nanosecond]]). - return MUST(create_temporal_time(vm, result.hour, result.minute, result.second, result.millisecond, result.microsecond, result.nanosecond)); -} - -// 4.3.13 Temporal.PlainTime.prototype.until ( other [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal.plaintime.prototype.until -JS_DEFINE_NATIVE_FUNCTION(PlainTimePrototype::until) -{ - auto other = vm.argument(0); - auto options = vm.argument(1); - - // 1. Let temporalTime be the this value. - // 2. Perform ? RequireInternalSlot(temporalTime, [[InitializedTemporalTime]]). - auto temporal_time = TRY(typed_this_object(vm)); - - // 3. Return ? DifferenceTemporalPlainTime(until, temporalTime, other, options). - return TRY(difference_temporal_plain_time(vm, DifferenceOperation::Until, temporal_time, other, options)); -} - -// 4.3.14 Temporal.PlainTime.prototype.since ( other [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal.plaintime.prototype.since -JS_DEFINE_NATIVE_FUNCTION(PlainTimePrototype::since) -{ - auto other = vm.argument(0); - auto options = vm.argument(1); - - // 1. Let temporalTime be the this value. - // 2. Perform ? RequireInternalSlot(temporalTime, [[InitializedTemporalTime]]). - auto temporal_time = TRY(typed_this_object(vm)); - - // 3. Return ? DifferenceTemporalPlainTime(since, temporalTime, other, options). - return TRY(difference_temporal_plain_time(vm, DifferenceOperation::Since, temporal_time, other, options)); -} - -// 4.3.15 Temporal.PlainTime.prototype.round ( roundTo ), https://tc39.es/proposal-temporal/#sec-temporal.plaintime.prototype.round -JS_DEFINE_NATIVE_FUNCTION(PlainTimePrototype::round) -{ - auto& realm = *vm.current_realm(); - - // 1. Let temporalTime be the this value. - // 2. Perform ? RequireInternalSlot(temporalTime, [[InitializedTemporalTime]]). - auto temporal_time = TRY(typed_this_object(vm)); - - // 3. If roundTo is undefined, then - if (vm.argument(0).is_undefined()) { - // a. Throw a TypeError exception. - return vm.throw_completion(ErrorType::TemporalMissingOptionsObject); - } - - Object* round_to; - - // 4. If Type(roundTo) is String, then - if (vm.argument(0).is_string()) { - // a. Let paramString be roundTo. - - // b. Set roundTo to OrdinaryObjectCreate(null). - round_to = Object::create(realm, nullptr); - - // c. Perform ! CreateDataPropertyOrThrow(roundTo, "smallestUnit", paramString). - MUST(round_to->create_data_property_or_throw(vm.names.smallestUnit, vm.argument(0))); - } - // 5. Else, - else { - // a. Set roundTo to ? GetOptionsObject(roundTo). - round_to = TRY(get_options_object(vm, vm.argument(0))); - } - - // 6. Let smallestUnit be ? GetTemporalUnit(roundTo, "smallestUnit", time, required). - auto smallest_unit = TRY(get_temporal_unit(vm, *round_to, vm.names.smallestUnit, UnitGroup::Time, TemporalUnitRequired {})); - - // 7. Let roundingMode be ? ToTemporalRoundingMode(roundTo, "halfExpand"). - auto rounding_mode = TRY(to_temporal_rounding_mode(vm, *round_to, "halfExpand"sv)); - - // 8. Let maximum be ! MaximumTemporalDurationRoundingIncrement(smallestUnit). - auto maximum = maximum_temporal_duration_rounding_increment(*smallest_unit); - - // 9. Assert maximum is not undefined. - VERIFY(maximum.has_value()); - - // 10. Let roundingIncrement be ? ToTemporalRoundingIncrement(roundTo). - auto rounding_increment = TRY(to_temporal_rounding_increment(vm, *round_to)); - - // 11. Perform ? ValidateTemporalRoundingIncrement(roundingIncrement, maximum, false). - TRY(validate_temporal_rounding_increment(vm, rounding_increment, *maximum, false)); - - // 12. Let result be ! RoundTime(temporalTime.[[ISOHour]], temporalTime.[[ISOMinute]], temporalTime.[[ISOSecond]], temporalTime.[[ISOMillisecond]], temporalTime.[[ISOMicrosecond]], temporalTime.[[ISONanosecond]], roundingIncrement, smallestUnit, roundingMode). - auto result = round_time(temporal_time->iso_hour(), temporal_time->iso_minute(), temporal_time->iso_second(), temporal_time->iso_millisecond(), temporal_time->iso_microsecond(), temporal_time->iso_nanosecond(), rounding_increment, *smallest_unit, rounding_mode); - - // 13. Return ! CreateTemporalTime(result.[[Hour]], result.[[Minute]], result.[[Second]], result.[[Millisecond]], result.[[Microsecond]], result.[[Nanosecond]]). - return MUST(create_temporal_time(vm, 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) -{ - // 1. Let temporalTime be the this value. - // 2. Perform ? RequireInternalSlot(temporalTime, [[InitializedTemporalTime]]). - auto temporal_time = TRY(typed_this_object(vm)); - - // 3. Set other to ? ToTemporalTime(other). - auto* other = TRY(to_temporal_time(vm, vm.argument(0))); - - // 4. If temporalTime.[[ISOHour]] ≠ other.[[ISOHour]], return false. - if (temporal_time->iso_hour() != other->iso_hour()) - return Value(false); - - // 5. If temporalTime.[[ISOMinute]] ≠ other.[[ISOMinute]], return false. - if (temporal_time->iso_minute() != other->iso_minute()) - return Value(false); - - // 6. If temporalTime.[[ISOSecond]] ≠ other.[[ISOSecond]], return false. - if (temporal_time->iso_second() != other->iso_second()) - return Value(false); - - // 7. If temporalTime.[[ISOMillisecond]] ≠ other.[[ISOMillisecond]], return false. - if (temporal_time->iso_millisecond() != other->iso_millisecond()) - return Value(false); - - // 8. If temporalTime.[[ISOMicrosecond]] ≠ other.[[ISOMicrosecond]], return false. - if (temporal_time->iso_microsecond() != other->iso_microsecond()) - return Value(false); - - // 9. If temporalTime.[[ISONanosecond]] ≠ other.[[ISONanosecond]], return false. - if (temporal_time->iso_nanosecond() != other->iso_nanosecond()) - return Value(false); - - // 10. Return true. - return Value(true); -} - -// 4.3.17 Temporal.PlainTime.prototype.toPlainDateTime ( temporalDate ), https://tc39.es/proposal-temporal/#sec-temporal.plaintime.prototype.toplaindatetime -JS_DEFINE_NATIVE_FUNCTION(PlainTimePrototype::to_plain_date_time) -{ - // 1. Let temporalTime be the this value. - // 2. Perform ? RequireInternalSlot(temporalTime, [[InitializedTemporalTime]]). - auto temporal_time = TRY(typed_this_object(vm)); - - // 3. Set temporalDate to ? ToTemporalDate(temporalDate). - auto* temporal_date = TRY(to_temporal_date(vm, vm.argument(0))); - - // 4. Return ? CreateTemporalDateTime(temporalDate.[[ISOYear]], temporalDate.[[ISOMonth]], temporalDate.[[ISODay]], temporalTime.[[ISOHour]], temporalTime.[[ISOMinute]], temporalTime.[[ISOSecond]], temporalTime.[[ISOMillisecond]], temporalTime.[[ISOMicrosecond]], temporalTime.[[ISONanosecond]], temporalDate.[[Calendar]]). - return TRY(create_temporal_date_time(vm, temporal_date->iso_year(), temporal_date->iso_month(), temporal_date->iso_day(), temporal_time->iso_hour(), temporal_time->iso_minute(), temporal_time->iso_second(), temporal_time->iso_millisecond(), temporal_time->iso_microsecond(), temporal_time->iso_nanosecond(), temporal_date->calendar())); -} - -// 4.3.18 Temporal.PlainTime.prototype.toZonedDateTime ( item ), https://tc39.es/proposal-temporal/#sec-temporal.plaintime.prototype.tozoneddatetime -JS_DEFINE_NATIVE_FUNCTION(PlainTimePrototype::to_zoned_date_time) -{ - auto item = vm.argument(0); - - // 1. Let temporalTime be the this value. - // 2. Perform ? RequireInternalSlot(temporalTime, [[InitializedTemporalTime]]). - auto temporal_time = TRY(typed_this_object(vm)); - - // 3. If Type(item) is not Object, then - if (!item.is_object()) { - // a. Throw a TypeError exception. - return vm.throw_completion(ErrorType::NotAnObject, item); - } - - // 4. Let temporalDateLike be ? Get(item, "plainDate"). - auto temporal_date_like = TRY(item.as_object().get(vm.names.plainDate)); - - // 5. If temporalDateLike is undefined, then - if (temporal_date_like.is_undefined()) { - // a. Throw a TypeError exception. - return vm.throw_completion(ErrorType::MissingRequiredProperty, vm.names.plainDate.as_string()); - } - - // 6. Let temporalDate be ? ToTemporalDate(temporalDateLike). - auto* temporal_date = TRY(to_temporal_date(vm, temporal_date_like)); - - // 7. Let temporalTimeZoneLike be ? Get(item, "timeZone"). - auto temporal_time_zone_like = TRY(item.as_object().get(vm.names.timeZone)); - - // 8. If temporalTimeZoneLike is undefined, then - if (temporal_time_zone_like.is_undefined()) { - // a. Throw a TypeError exception. - return vm.throw_completion(ErrorType::MissingRequiredProperty, vm.names.timeZone.as_string()); - } - - // 9. Let timeZone be ? ToTemporalTimeZone(temporalTimeZoneLike). - auto* time_zone = TRY(to_temporal_time_zone(vm, temporal_time_zone_like)); - - // 10. Let temporalDateTime be ? CreateTemporalDateTime(temporalDate.[[ISOYear]], temporalDate.[[ISOMonth]], temporalDate.[[ISODay]], temporalTime.[[ISOHour]], temporalTime.[[ISOMinute]], temporalTime.[[ISOSecond]], temporalTime.[[ISOMillisecond]], temporalTime.[[ISOMicrosecond]], temporalTime.[[ISONanosecond]], temporalDate.[[Calendar]]). - auto* temporal_date_time = TRY(create_temporal_date_time(vm, temporal_date->iso_year(), temporal_date->iso_month(), temporal_date->iso_day(), temporal_time->iso_hour(), temporal_time->iso_minute(), temporal_time->iso_second(), temporal_time->iso_millisecond(), temporal_time->iso_microsecond(), temporal_time->iso_nanosecond(), temporal_date->calendar())); - - // 11. Let instant be ? BuiltinTimeZoneGetInstantFor(timeZone, temporalDateTime, "compatible"). - auto instant = TRY(builtin_time_zone_get_instant_for(vm, time_zone, *temporal_date_time, "compatible"sv)); - - // 12. Return ! CreateTemporalZonedDateTime(instant.[[Nanoseconds]], timeZone, temporalDate.[[Calendar]]). - return MUST(create_temporal_zoned_date_time(vm, instant->nanoseconds(), *time_zone, temporal_date->calendar())); -} - -// 4.3.19 Temporal.PlainTime.prototype.getISOFields ( ), https://tc39.es/proposal-temporal/#sec-temporal.plaintime.prototype.getisofields -JS_DEFINE_NATIVE_FUNCTION(PlainTimePrototype::get_iso_fields) -{ - auto& realm = *vm.current_realm(); - - // 1. Let temporalTime be the this value. - // 2. Perform ? RequireInternalSlot(temporalTime, [[InitializedTemporalTime]]). - auto temporal_time = TRY(typed_this_object(vm)); - - // 3. Let fields be OrdinaryObjectCreate(%Object.prototype%). - auto fields = Object::create(realm, realm.intrinsics().object_prototype()); - - // 4. Perform ! CreateDataPropertyOrThrow(fields, "calendar", temporalTime.[[Calendar]]). - MUST(fields->create_data_property_or_throw(vm.names.calendar, Value(&temporal_time->calendar()))); - - // 5. Perform ! CreateDataPropertyOrThrow(fields, "isoHour", 𝔽(temporalTime.[[ISOHour]])). - MUST(fields->create_data_property_or_throw(vm.names.isoHour, Value(temporal_time->iso_hour()))); - - // 6. Perform ! CreateDataPropertyOrThrow(fields, "isoMicrosecond", 𝔽(temporalTime.[[ISOMicrosecond]])). - MUST(fields->create_data_property_or_throw(vm.names.isoMicrosecond, Value(temporal_time->iso_microsecond()))); - - // 7. Perform ! CreateDataPropertyOrThrow(fields, "isoMillisecond", 𝔽(temporalTime.[[ISOMillisecond]])). - MUST(fields->create_data_property_or_throw(vm.names.isoMillisecond, Value(temporal_time->iso_millisecond()))); - - // 8. Perform ! CreateDataPropertyOrThrow(fields, "isoMinute", 𝔽(temporalTime.[[ISOMinute]])). - MUST(fields->create_data_property_or_throw(vm.names.isoMinute, Value(temporal_time->iso_minute()))); - - // 9. Perform ! CreateDataPropertyOrThrow(fields, "isoNanosecond", 𝔽(temporalTime.[[ISONanosecond]])). - MUST(fields->create_data_property_or_throw(vm.names.isoNanosecond, Value(temporal_time->iso_nanosecond()))); - - // 10. Perform ! CreateDataPropertyOrThrow(fields, "isoSecond", 𝔽(temporalTime.[[ISOSecond]])). - MUST(fields->create_data_property_or_throw(vm.names.isoSecond, Value(temporal_time->iso_second()))); - - // 11. Return fields. - return fields; -} - -// 4.3.20 Temporal.PlainTime.prototype.toString ( [ options ] ), https://tc39.es/proposal-temporal/#sec-temporal.plaintime.prototype.tostring -JS_DEFINE_NATIVE_FUNCTION(PlainTimePrototype::to_string) -{ - // 1. Let temporalTime be the this value. - // 2. Perform ? RequireInternalSlot(temporalTime, [[InitializedTemporalTime]]). - auto temporal_time = TRY(typed_this_object(vm)); - - // 3. Set options to ? GetOptionsObject(options). - auto* options = TRY(get_options_object(vm, vm.argument(0))); - - // 4. Let precision be ? ToSecondsStringPrecisionRecord(options). - auto precision = TRY(to_seconds_string_precision_record(vm, *options)); - - // 5. Let roundingMode be ? ToTemporalRoundingMode(options, "trunc"). - auto rounding_mode = TRY(to_temporal_rounding_mode(vm, *options, "trunc"sv)); - - // 6. Let roundResult be ! RoundTime(temporalTime.[[ISOHour]], temporalTime.[[ISOMinute]], temporalTime.[[ISOSecond]], temporalTime.[[ISOMillisecond]], temporalTime.[[ISOMicrosecond]], temporalTime.[[ISONanosecond]], precision.[[Increment]], precision.[[Unit]], roundingMode). - auto round_result = round_time(temporal_time->iso_hour(), temporal_time->iso_minute(), temporal_time->iso_second(), temporal_time->iso_millisecond(), temporal_time->iso_microsecond(), temporal_time->iso_nanosecond(), precision.increment, precision.unit, rounding_mode); - - // 7. Return ! TemporalTimeToString(roundResult.[[Hour]], roundResult.[[Minute]], roundResult.[[Second]], roundResult.[[Millisecond]], roundResult.[[Microsecond]], roundResult.[[Nanosecond]], precision.[[Precision]]). - auto string = MUST_OR_THROW_OOM(temporal_time_to_string(vm, round_result.hour, round_result.minute, round_result.second, round_result.millisecond, round_result.microsecond, round_result.nanosecond, precision.precision)); - return PrimitiveString::create(vm, move(string)); -} - -// 4.3.21 Temporal.PlainTime.prototype.toLocaleString ( [ locales [ , options ] ] ), https://tc39.es/proposal-temporal/#sec-temporal.plaintime.prototype.tolocalestring -JS_DEFINE_NATIVE_FUNCTION(PlainTimePrototype::to_locale_string) -{ - // 1. Let temporalTime be the this value. - // 2. Perform ? RequireInternalSlot(temporalTime, [[InitializedTemporalTime]]). - auto temporal_time = TRY(typed_this_object(vm)); - - // 3. Return ! TemporalTimeToString(temporalTime.[[ISOHour]], temporalTime.[[ISOMinute]], temporalTime.[[ISOSecond]], temporalTime.[[ISOMillisecond]], temporalTime.[[ISOMicrosecond]], temporalTime.[[ISONanosecond]], "auto"). - auto string = MUST_OR_THROW_OOM(temporal_time_to_string(vm, temporal_time->iso_hour(), temporal_time->iso_minute(), temporal_time->iso_second(), temporal_time->iso_millisecond(), temporal_time->iso_microsecond(), temporal_time->iso_nanosecond(), "auto"sv)); - return PrimitiveString::create(vm, move(string)); -} - -// 4.3.22 Temporal.PlainTime.prototype.toJSON ( ), https://tc39.es/proposal-temporal/#sec-temporal.plaintime.prototype.tojson -JS_DEFINE_NATIVE_FUNCTION(PlainTimePrototype::to_json) -{ - // 1. Let temporalTime be the this value. - // 2. Perform ? RequireInternalSlot(temporalTime, [[InitializedTemporalTime]]). - auto temporal_time = TRY(typed_this_object(vm)); - - // 3. Return ! TemporalTimeToString(temporalTime.[[ISOHour]], temporalTime.[[ISOMinute]], temporalTime.[[ISOSecond]], temporalTime.[[ISOMillisecond]], temporalTime.[[ISOMicrosecond]], temporalTime.[[ISONanosecond]], "auto"). - auto string = MUST_OR_THROW_OOM(temporal_time_to_string(vm, temporal_time->iso_hour(), temporal_time->iso_minute(), temporal_time->iso_second(), temporal_time->iso_millisecond(), temporal_time->iso_microsecond(), temporal_time->iso_nanosecond(), "auto"sv)); - return PrimitiveString::create(vm, move(string)); -} - -// 4.3.23 Temporal.PlainTime.prototype.valueOf ( ), https://tc39.es/proposal-temporal/#sec-temporal.plaintime.prototype.valueof -JS_DEFINE_NATIVE_FUNCTION(PlainTimePrototype::value_of) -{ - // 1. Throw a TypeError exception. - return vm.throw_completion(ErrorType::Convert, "Temporal.PlainTime", "a primitive value"); -} - -} diff --git a/Libraries/LibJS/Runtime/Temporal/PlainTimePrototype.h b/Libraries/LibJS/Runtime/Temporal/PlainTimePrototype.h deleted file mode 100644 index 67b7c21378b..00000000000 --- a/Libraries/LibJS/Runtime/Temporal/PlainTimePrototype.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2021, Linus Groh - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include -#include - -namespace JS::Temporal { - -class PlainTimePrototype final : public PrototypeObject { - JS_PROTOTYPE_OBJECT(PlainTimePrototype, PlainTime, Temporal.PlainTime); - GC_DECLARE_ALLOCATOR(PlainTimePrototype); - -public: - virtual void initialize(Realm&) override; - virtual ~PlainTimePrototype() override = default; - -private: - explicit PlainTimePrototype(Realm&); - - JS_DECLARE_NATIVE_FUNCTION(calendar_getter); - JS_DECLARE_NATIVE_FUNCTION(hour_getter); - JS_DECLARE_NATIVE_FUNCTION(minute_getter); - JS_DECLARE_NATIVE_FUNCTION(second_getter); - JS_DECLARE_NATIVE_FUNCTION(millisecond_getter); - JS_DECLARE_NATIVE_FUNCTION(microsecond_getter); - JS_DECLARE_NATIVE_FUNCTION(nanosecond_getter); - JS_DECLARE_NATIVE_FUNCTION(add); - JS_DECLARE_NATIVE_FUNCTION(subtract); - JS_DECLARE_NATIVE_FUNCTION(with); - JS_DECLARE_NATIVE_FUNCTION(until); - JS_DECLARE_NATIVE_FUNCTION(since); - JS_DECLARE_NATIVE_FUNCTION(round); - JS_DECLARE_NATIVE_FUNCTION(equals); - JS_DECLARE_NATIVE_FUNCTION(to_plain_date_time); - JS_DECLARE_NATIVE_FUNCTION(to_zoned_date_time); - JS_DECLARE_NATIVE_FUNCTION(get_iso_fields); - JS_DECLARE_NATIVE_FUNCTION(to_string); - JS_DECLARE_NATIVE_FUNCTION(to_locale_string); - JS_DECLARE_NATIVE_FUNCTION(to_json); - JS_DECLARE_NATIVE_FUNCTION(value_of); -}; - -} diff --git a/Libraries/LibJS/Runtime/Temporal/PlainYearMonth.cpp b/Libraries/LibJS/Runtime/Temporal/PlainYearMonth.cpp deleted file mode 100644 index 88b5a0deafc..00000000000 --- a/Libraries/LibJS/Runtime/Temporal/PlainYearMonth.cpp +++ /dev/null @@ -1,394 +0,0 @@ -/* - * Copyright (c) 2021-2023, Linus Groh - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace JS::Temporal { - -GC_DEFINE_ALLOCATOR(PlainYearMonth); - -// 9 Temporal.PlainYearMonth Objects, https://tc39.es/proposal-temporal/#sec-temporal-plainyearmonth-objects -PlainYearMonth::PlainYearMonth(i32 iso_year, u8 iso_month, u8 iso_day, Object& calendar, Object& prototype) - : Object(ConstructWithPrototypeTag::Tag, prototype) - , m_iso_year(iso_year) - , m_iso_month(iso_month) - , m_iso_day(iso_day) - , m_calendar(calendar) -{ -} - -void PlainYearMonth::visit_edges(Visitor& visitor) -{ - Base::visit_edges(visitor); - visitor.visit(m_calendar); -} - -// 9.5.1 ToTemporalYearMonth ( item [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal-totemporalyearmonth -ThrowCompletionOr to_temporal_year_month(VM& vm, Value item, Object const* options) -{ - // 1. If options is not present, set options to undefined. - // 2. Assert: Type(options) is Object or Undefined. - - // 3. If Type(item) is Object, then - if (item.is_object()) { - auto& item_object = item.as_object(); - - // a. If item has an [[InitializedTemporalYearMonth]] internal slot, then - if (is(item_object)) { - // i. Return item. - return static_cast(&item_object); - } - - // b. Let calendar be ? GetTemporalCalendarWithISODefault(item). - auto* calendar = TRY(get_temporal_calendar_with_iso_default(vm, item_object)); - - // c. Let fieldNames be ? CalendarFields(calendar, « "month", "monthCode", "year" »). - auto field_names = TRY(calendar_fields(vm, *calendar, { "month"sv, "monthCode"sv, "year"sv })); - - // d. Let fields be ? PrepareTemporalFields(item, fieldNames, «»). - auto* fields = TRY(prepare_temporal_fields(vm, item_object, field_names, Vector {})); - - // e. Return ? CalendarYearMonthFromFields(calendar, fields, options). - return calendar_year_month_from_fields(vm, *calendar, *fields, options); - } - - // 4. Perform ? ToTemporalOverflow(options). - (void)TRY(to_temporal_overflow(vm, options)); - - // 5. Let string be ? ToString(item). - auto string = TRY(item.to_string(vm)); - - // 6. Let result be ? ParseTemporalYearMonthString(string). - auto result = TRY(parse_temporal_year_month_string(vm, string)); - - // 7. Let calendar be ? ToTemporalCalendarWithISODefault(result.[[Calendar]]). - auto* calendar = TRY(to_temporal_calendar_with_iso_default(vm, result.calendar.has_value() ? PrimitiveString::create(vm, *result.calendar) : js_undefined())); - - // 8. Set result to ? CreateTemporalYearMonth(result.[[Year]], result.[[Month]], calendar, result.[[Day]]). - auto* creation_result = TRY(create_temporal_year_month(vm, result.year, result.month, *calendar, result.day)); - - // 9. NOTE: The following operation is called without options, in order for the calendar to store a canonical value in the [[ISODay]] internal slot of the result. - // 10. Return ? CalendarYearMonthFromFields(calendar, result). - return calendar_year_month_from_fields(vm, *calendar, *creation_result); -} - -// 9.5.2 RegulateISOYearMonth ( year, month, overflow ), https://tc39.es/proposal-temporal/#sec-temporal-regulateisoyearmonth -ThrowCompletionOr regulate_iso_year_month(VM& vm, double year, double month, StringView overflow) -{ - // 1. Assert: year and month are integers. - VERIFY(year == trunc(year) && month == trunc(month)); - - // 2. Assert: overflow is either "constrain" or "reject". - // NOTE: Asserted by the VERIFY_NOT_REACHED at the end - - // 3. If overflow is "constrain", then - if (overflow == "constrain"sv) { - // IMPLEMENTATION DEFINED: This is an optimization that allows us to treat `year` (a double) as normal integer from this point onwards. - // This does not change the exposed behavior as the subsequent call to CreateTemporalYearMonth will check that its value is a valid ISO - // values (for years: -273975 - 273975) which is a subset of this check. - // If RegulateISOYearMonth is ever used outside ISOYearMonthFromFields, this may need to be changed. - if (!AK::is_within_range(year)) - return vm.throw_completion(ErrorType::TemporalInvalidPlainYearMonth); - - // a. Set month to the result of clamping month between 1 and 12. - month = clamp(month, 1, 12); - - // b. Return the Record { [[Year]]: year, [[Month]]: month }. - return ISOYearMonth { .year = static_cast(year), .month = static_cast(month), .reference_iso_day = 0 }; - } - // 4. Else, - else { - // a. Assert: overflow is "reject". - VERIFY(overflow == "reject"sv); - - // 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 behavior as the call to IsValidISOMonth and subsequent call to CreateTemporalDateTime will check - // that these values are valid ISO values (for years: -273975 - 273975, for months: 1 - 12) all of which are subsets of this check. - if (!AK::is_within_range(year) || !AK::is_within_range(month)) - return vm.throw_completion(ErrorType::TemporalInvalidPlainYearMonth); - - // b. If month < 1 or month > 12, throw a RangeError exception. - if (month < 1 || month > 12) - return vm.throw_completion(ErrorType::TemporalInvalidPlainYearMonth); - - // c. Return the Record { [[Year]]: year, [[Month]]: month }. - return ISOYearMonth { .year = static_cast(year), .month = static_cast(month), .reference_iso_day = 0 }; - } -} - -// 9.5.3 ISOYearMonthWithinLimits ( year, month ), https://tc39.es/proposal-temporal/#sec-temporal-isoyearmonthwithinlimits -bool iso_year_month_within_limits(i32 year, u8 month) -{ - // 1. Assert: year and month are integers. - - // 2. If year < -271821 or year > 275760, then - if (year < -271821 || year > 275760) { - // a. Return false. - return false; - } - - // 3. If year is -271821 and month < 4, then - if (year == -271821 && month < 4) { - // a. Return false. - return false; - } - - // 4. If year is 275760 and month > 9, then - if (year == 275760 && month > 9) { - // a. Return false. - return false; - } - - // 5. Return true. - return true; -} - -// 9.5.4 BalanceISOYearMonth ( year, month ), https://tc39.es/proposal-temporal/#sec-temporal-balanceisoyearmonth -ISOYearMonth balance_iso_year_month(double year, double month) -{ - // 1. Assert: year and month are integers. - VERIFY(year == trunc(year) && month == trunc(month)); - - // 2. Set year to year + floor((month - 1) / 12). - year += floor((month - 1) / 12); - - // 3. Set month to ((month - 1) modulo 12) + 1. - month = modulo(month - 1, 12) + 1; - - // 4. Return the Record { [[Year]]: year, [[Month]]: month }. - return ISOYearMonth { .year = static_cast(year), .month = static_cast(month), .reference_iso_day = 0 }; -} - -// 9.5.5 CreateTemporalYearMonth ( isoYear, isoMonth, calendar, referenceISODay [ , newTarget ] ), https://tc39.es/proposal-temporal/#sec-temporal-createtemporalyearmonth -ThrowCompletionOr create_temporal_year_month(VM& vm, i32 iso_year, u8 iso_month, Object& calendar, u8 reference_iso_day, FunctionObject const* new_target) -{ - auto& realm = *vm.current_realm(); - - // 1. Assert: isoYear, isoMonth, and referenceISODay are integers. - // 2. Assert: Type(calendar) is Object. - - // 3. If IsValidISODate(isoYear, isoMonth, referenceISODay) is false, throw a RangeError exception. - if (!is_valid_iso_date(iso_year, iso_month, reference_iso_day)) - return vm.throw_completion(ErrorType::TemporalInvalidPlainYearMonth); - - // 4. If ! ISOYearMonthWithinLimits(isoYear, isoMonth) is false, throw a RangeError exception. - if (!iso_year_month_within_limits(iso_year, iso_month)) - return vm.throw_completion(ErrorType::TemporalInvalidPlainYearMonth); - - // 5. If newTarget is not present, set newTarget to %Temporal.PlainYearMonth%. - if (!new_target) - new_target = realm.intrinsics().temporal_plain_year_month_constructor(); - - // 6. Let object be ? OrdinaryCreateFromConstructor(newTarget, "%Temporal.PlainYearMonth.prototype%", « [[InitializedTemporalYearMonth]], [[ISOYear]], [[ISOMonth]], [[ISODay]], [[Calendar]] »). - // 7. Set object.[[ISOYear]] to isoYear. - // 8. Set object.[[ISOMonth]] to isoMonth. - // 9. Set object.[[Calendar]] to calendar. - // 10. Set object.[[ISODay]] to referenceISODay. - auto object = TRY(ordinary_create_from_constructor(vm, *new_target, &Intrinsics::temporal_plain_year_month_prototype, iso_year, iso_month, reference_iso_day, calendar)); - - // 11. Return object. - return object.ptr(); -} - -// 9.5.6 TemporalYearMonthToString ( yearMonth, showCalendar ), https://tc39.es/proposal-temporal/#sec-temporal-temporalyearmonthtostring -ThrowCompletionOr temporal_year_month_to_string(VM& vm, PlainYearMonth& year_month, StringView show_calendar) -{ - // 1. Assert: Type(yearMonth) is Object. - // 2. Assert: yearMonth has an [[InitializedTemporalYearMonth]] internal slot. - - // 3. Let year be ! PadISOYear(yearMonth.[[ISOYear]]). - // 4. Let month be ToZeroPaddedDecimalString(yearMonth.[[ISOMonth]], 2). - // 5. Let result be the string-concatenation of year, the code unit 0x002D (HYPHEN-MINUS), and month. - auto result = TRY_OR_THROW_OOM(vm, String::formatted("{}-{:02}", MUST_OR_THROW_OOM(pad_iso_year(vm, year_month.iso_year())), year_month.iso_month())); - - // 6. Let calendarID be ? ToString(yearMonth.[[Calendar]]). - auto calendar_id = TRY(Value(&year_month.calendar()).to_string(vm)); - - // 7. If showCalendar is one of "always" or "critical", or if calendarID is not "iso8601", then - if (show_calendar.is_one_of("always"sv, "critical"sv) || calendar_id != "iso8601") { - // a. Let day be ToZeroPaddedDecimalString(yearMonth.[[ISODay]], 2). - // b. Set result to the string-concatenation of result, the code unit 0x002D (HYPHEN-MINUS), and day. - result = TRY_OR_THROW_OOM(vm, String::formatted("{}-{:02}", result, year_month.iso_day())); - } - - // 8. Let calendarString be ! FormatCalendarAnnotation(calendarID, showCalendar). - auto calendar_string = MUST_OR_THROW_OOM(format_calendar_annotation(vm, calendar_id, show_calendar)); - - // 9. Set result to the string-concatenation of result and calendarString. - // 10. Return result. - return TRY_OR_THROW_OOM(vm, String::formatted("{}{}", result, calendar_string)); -} - -// 9.5.7 DifferenceTemporalPlainYearMonth ( operation, yearMonth, other, options ), https://tc39.es/proposal-temporal/#sec-temporal-differencetemporalplainyearmonth -ThrowCompletionOr> difference_temporal_plain_year_month(VM& vm, DifferenceOperation operation, PlainYearMonth& year_month, Value other_value, Value options_value) -{ - // 1. If operation is since, let sign be -1. Otherwise, let sign be 1. - i8 sign = operation == DifferenceOperation::Since ? -1 : 1; - - // 2. Set other to ? ToTemporalYearMonth(other). - auto* other = TRY(to_temporal_year_month(vm, other_value)); - - // 3. Let calendar be yearMonth.[[Calendar]]. - auto& calendar = year_month.calendar(); - - // 4. If ? CalendarEquals(calendar, other.[[Calendar]]) is false, throw a RangeError exception. - if (!TRY(calendar_equals(vm, calendar, other->calendar()))) - return vm.throw_completion(ErrorType::TemporalDifferentCalendars); - - // 5. Let resolvedOptions be ? SnapshotOwnProperties(? GetOptionsObject(options), null). - auto resolved_options = TRY(TRY(get_options_object(vm, options_value))->snapshot_own_properties(vm, nullptr)); - - // 6. Let settings be ? GetDifferenceSettings(operation, resolvedOptions, date, « "week", "day" », "month", "year"). - auto settings = TRY(get_difference_settings(vm, operation, resolved_options, UnitGroup::Date, { "week"sv, "day"sv }, { "month"sv }, "year"sv)); - - // 7. If yearMonth.[[ISOYear]] = other.[[ISOYear]] and yearMonth.[[ISOMonth]] = other.[[ISOMonth]] and yearMonth.[[ISODay]] = other.[[ISODay]], then - if (year_month.iso_year() == other->iso_year() && year_month.iso_month() == other->iso_month() && year_month.iso_day() == other->iso_day()) { - // a. Return ! CreateTemporalDuration(0, 0, 0, 0, 0, 0, 0, 0, 0, 0). - return MUST(create_temporal_duration(vm, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)); - } - - // 8. Perform ! CreateDataPropertyOrThrow(resolvedOptions, "largestUnit", settings.[[LargestUnit]]). - MUST(resolved_options->create_data_property_or_throw(vm.names.largestUnit, PrimitiveString::create(vm, settings.largest_unit))); - - // 9. Let calendarRec be ? CreateCalendarMethodsRecord(calendar, « dateAdd, dateFromFields, dateUntil, fields »). - // FIXME: The type of calendar in PlainYearMonth does not align with latest spec - auto calendar_record = TRY(create_calendar_methods_record(vm, GC::Ref { calendar }, { { CalendarMethod::DateAdd, CalendarMethod::DateFromFields, CalendarMethod::DateUntil, CalendarMethod::Fields } })); - - // 10. Let fieldNames be ? CalendarFields(calendarRec, « "monthCode", "year" »). - // FIXME: Pass through calendar record - auto field_names = TRY(calendar_fields(vm, calendar, { "monthCode"sv, "year"sv })); - - // 11. Let thisFields be ? PrepareTemporalFields(yearMonth, fieldNames, «»). - auto* this_fields = TRY(prepare_temporal_fields(vm, year_month, field_names, Vector {})); - - // 12. Perform ! CreateDataPropertyOrThrow(thisFields, "day", 1𝔽). - MUST(this_fields->create_data_property_or_throw(vm.names.day, Value(1))); - - // 13. Let thisDate be ? CalendarDateFromFields(calendarRec, thisFields). - // FIXME: Pass through calendar record - auto* this_date = TRY(calendar_date_from_fields(vm, calendar, *this_fields)); - - // 14. Let otherFields be ? PrepareTemporalFields(other, fieldNames, «»). - auto* other_fields = TRY(prepare_temporal_fields(vm, *other, field_names, Vector {})); - - // 15. Perform ! CreateDataPropertyOrThrow(otherFields, "day", 1𝔽). - MUST(other_fields->create_data_property_or_throw(vm.names.day, Value(1))); - - // 16. Let otherDate be ? CalendarDateFromFields(calendarRec, otherFields). - // FIXME: Pass through calendar record - auto* other_date = TRY(calendar_date_from_fields(vm, calendar, *other_fields)); - - // 17. Perform ! CreateDataPropertyOrThrow(resolvedOptions, "largestUnit", settings.[[LargestUnit]]). - MUST(resolved_options->create_data_property_or_throw(vm.names.largestUnit, PrimitiveString::create(vm, settings.largest_unit))); - - // 18. Let result be ? CalendarDateUntil(calendarRec, thisDate, otherDate, resolvedOptions). - auto result = TRY(calendar_date_until(vm, calendar_record, this_date, other_date, *resolved_options)); - - // 19. If settings.[[SmallestUnit]] is not "month" or settings.[[RoundingIncrement]] ≠ 1, then - if (settings.smallest_unit != "month"sv || settings.rounding_increment != 1) { - // a. Let roundRecord be ? RoundDuration(result.[[Years]], result.[[Months]], 0, 0, 0, 0, 0, 0, 0, 0, settings.[[RoundingIncrement]], settings.[[SmallestUnit]], settings.[[RoundingMode]], thisDate, calendarRec). - auto round_record = TRY(round_duration(vm, result->years(), result->months(), 0, 0, 0, 0, 0, 0, 0, 0, settings.rounding_increment, settings.smallest_unit, settings.rounding_mode, this_date, calendar_record)); - - // b. Let roundResult be roundRecord.[[DurationRecord]]. - auto round_result = round_record.duration_record; - - // FIXME: c. Set result to ? BalanceDateDurationRelative(roundResult.[[Years]], roundResult.[[Months]], 0, 0, settings.[[LargestUnit]], settings.[[SmallestUnit]], thisDate, calendarRec). - result = MUST(create_temporal_duration(vm, round_result.years, round_result.months, 0, 0, 0, 0, 0, 0, 0, 0)); - } - - // 20. Return ! CreateTemporalDuration(sign × result.[[Years]], sign × result.[[Months]], 0, 0, 0, 0, 0, 0, 0, 0). - return MUST(create_temporal_duration(vm, sign * result->years(), sign * result->months(), 0, 0, 0, 0, 0, 0, 0, 0)); -} - -// 9.5.8 AddDurationToOrSubtractDurationFromPlainYearMonth ( operation, yearMonth, temporalDurationLike, options ), https://tc39.es/proposal-temporal/#sec-temporal-adddurationtoorsubtractdurationfromplainyearmonth -ThrowCompletionOr add_duration_to_or_subtract_duration_from_plain_year_month(VM& vm, ArithmeticOperation operation, PlainYearMonth& year_month, Value temporal_duration_like, Value options_value) -{ - auto& realm = *vm.current_realm(); - - // 1. Let duration be ? ToTemporalDuration(temporalDurationLike). - auto duration = TRY(to_temporal_duration(vm, temporal_duration_like)); - - // 2. If operation is subtract, then - if (operation == ArithmeticOperation::Subtract) { - // a. Set duration to ! CreateNegatedTemporalDuration(duration). - duration = create_negated_temporal_duration(vm, *duration); - } - - // 3. Let balanceResult be ? BalanceDuration(duration.[[Days]], duration.[[Hours]], duration.[[Minutes]], duration.[[Seconds]], duration.[[Milliseconds]], duration.[[Microseconds]], duration.[[Nanoseconds]], "day"). - auto balance_result = TRY(balance_duration(vm, duration->days(), duration->hours(), duration->minutes(), duration->seconds(), duration->milliseconds(), duration->microseconds(), Crypto::SignedBigInteger { duration->nanoseconds() }, "day"sv)); - - // 4. Set options to ? GetOptionsObject(options). - auto* options = TRY(get_options_object(vm, options_value)); - - // 5. Let calendar be yearMonth.[[Calendar]]. - auto& calendar = year_month.calendar(); - - // 6. Let fieldNames be ? CalendarFields(calendar, « "monthCode", "year" »). - auto field_names = TRY(calendar_fields(vm, calendar, { "monthCode"sv, "year"sv })); - - // 7. Let fields be ? PrepareTemporalFields(yearMonth, fieldNames, «»). - auto* fields = TRY(prepare_temporal_fields(vm, year_month, field_names, Vector {})); - - // 8. Set sign to ! DurationSign(duration.[[Years]], duration.[[Months]], duration.[[Weeks]], balanceResult.[[Days]], 0, 0, 0, 0, 0, 0). - auto sign = duration_sign(duration->years(), duration->months(), duration->weeks(), balance_result.days, 0, 0, 0, 0, 0, 0); - - double day; - - // 9. If sign < 0, then - if (sign < 0) { - // a. Let day be ? CalendarDaysInMonth(calendar, yearMonth). - day = TRY(calendar_days_in_month(vm, calendar, year_month)); - } - // 10. Else, - else { - // a. Let day be 1. - day = 1; - } - - // 11. Perform ! CreateDataPropertyOrThrow(fields, "day", 𝔽(day)). - MUST(fields->create_data_property_or_throw(vm.names.day, Value(day))); - - // 12. Let date be ? CalendarDateFromFields(calendar, fields). - auto* date = TRY(calendar_date_from_fields(vm, calendar, *fields)); - - // 13. Let durationToAdd be ! CreateTemporalDuration(duration.[[Years]], duration.[[Months]], duration.[[Weeks]], balanceResult.[[Days]], 0, 0, 0, 0, 0, 0). - auto duration_to_add = MUST(create_temporal_duration(vm, duration->years(), duration->months(), duration->weeks(), balance_result.days, 0, 0, 0, 0, 0, 0)); - - // 14. Let optionsCopy be OrdinaryObjectCreate(null). - auto options_copy = Object::create(realm, nullptr); - - // 15. Let entries be ? EnumerableOwnPropertyNames(options, key+value). - auto entries = TRY(options->enumerable_own_property_names(Object::PropertyKind::KeyAndValue)); - - // 16. For each element entry of entries, do - for (auto& entry : entries) { - auto key = MUST(entry.as_array().get_without_side_effects(0).to_property_key(vm)); - auto value = entry.as_array().get_without_side_effects(1); - - // a. Perform ! CreateDataPropertyOrThrow(optionsCopy, entry[0], entry[1]). - MUST(options_copy->create_data_property_or_throw(key, value)); - } - - // 17. Let addedDate be ? CalendarDateAdd(calendar, date, durationToAdd, options). - auto* added_date = TRY(calendar_date_add(vm, calendar, date, *duration_to_add, options)); - - // 18. Let addedDateFields be ? PrepareTemporalFields(addedDate, fieldNames, «»). - auto* added_date_fields = TRY(prepare_temporal_fields(vm, *added_date, field_names, Vector {})); - - // 19. Return ? CalendarYearMonthFromFields(calendar, addedDateFields, optionsCopy). - return calendar_year_month_from_fields(vm, calendar, *added_date_fields, options_copy); -} - -} diff --git a/Libraries/LibJS/Runtime/Temporal/PlainYearMonth.h b/Libraries/LibJS/Runtime/Temporal/PlainYearMonth.h deleted file mode 100644 index 10c070c52d3..00000000000 --- a/Libraries/LibJS/Runtime/Temporal/PlainYearMonth.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2021-2023, Linus Groh - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include -#include - -namespace JS::Temporal { - -class PlainYearMonth final : public Object { - JS_OBJECT(PlainYearMonth, Object); - GC_DECLARE_ALLOCATOR(PlainYearMonth); - -public: - virtual ~PlainYearMonth() override = default; - - [[nodiscard]] i32 iso_year() const { return m_iso_year; } - [[nodiscard]] u8 iso_month() const { return m_iso_month; } - [[nodiscard]] u8 iso_day() const { return m_iso_day; } - [[nodiscard]] Object const& calendar() const { return m_calendar; } - [[nodiscard]] Object& calendar() { return m_calendar; } - -private: - PlainYearMonth(i32 iso_year, u8 iso_month, u8 iso_day, Object& calendar, Object& prototype); - - virtual void visit_edges(Visitor&) override; - - // 9.4 Properties of Temporal.PlainYearMonth Instances, https://tc39.es/proposal-temporal/#sec-properties-of-temporal-plainyearmonth-instances - i32 m_iso_year { 0 }; // [[ISOYear]] - u8 m_iso_month { 0 }; // [[ISOMonth]] - u8 m_iso_day { 0 }; // [[ISODay]] - GC::Ref m_calendar; // [[Calendar]] -}; - -struct ISOYearMonth { - i32 year; - u8 month; - u8 reference_iso_day; -}; - -ThrowCompletionOr to_temporal_year_month(VM&, Value item, Object const* options = nullptr); -ThrowCompletionOr regulate_iso_year_month(VM&, double year, double month, StringView overflow); -bool iso_year_month_within_limits(i32 year, u8 month); -ISOYearMonth balance_iso_year_month(double year, double month); -ThrowCompletionOr create_temporal_year_month(VM&, i32 iso_year, u8 iso_month, Object& calendar, u8 reference_iso_day, FunctionObject const* new_target = nullptr); -ThrowCompletionOr temporal_year_month_to_string(VM&, PlainYearMonth&, StringView show_calendar); -ThrowCompletionOr> difference_temporal_plain_year_month(VM&, DifferenceOperation, PlainYearMonth&, Value other, Value options); -ThrowCompletionOr add_duration_to_or_subtract_duration_from_plain_year_month(VM&, ArithmeticOperation, PlainYearMonth&, Value temporal_duration_like, Value options_value); - -} diff --git a/Libraries/LibJS/Runtime/Temporal/PlainYearMonthConstructor.cpp b/Libraries/LibJS/Runtime/Temporal/PlainYearMonthConstructor.cpp deleted file mode 100644 index 59fff92c92c..00000000000 --- a/Libraries/LibJS/Runtime/Temporal/PlainYearMonthConstructor.cpp +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (c) 2021-2023, Linus Groh - * Copyright (c) 2021, Luke Wilde - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include -#include -#include -#include -#include -#include - -namespace JS::Temporal { - -GC_DEFINE_ALLOCATOR(PlainYearMonthConstructor); - -// 9.1 The Temporal.PlainYearMonth Constructor, https://tc39.es/proposal-temporal/#sec-temporal-plainyearmonth-constructor -PlainYearMonthConstructor::PlainYearMonthConstructor(Realm& realm) - : NativeFunction(realm.vm().names.PlainYearMonth.as_string(), realm.intrinsics().function_prototype()) -{ -} - -void PlainYearMonthConstructor::initialize(Realm& realm) -{ - Base::initialize(realm); - - auto& vm = this->vm(); - - // 9.2.1 Temporal.PlainYearMonth.prototype, https://tc39.es/proposal-temporal/#sec-temporal.plainyearmonth.prototype - define_direct_property(vm.names.prototype, realm.intrinsics().temporal_plain_year_month_prototype(), 0); - - define_direct_property(vm.names.length, Value(2), Attribute::Configurable); - - u8 attr = Attribute::Writable | Attribute::Configurable; - define_native_function(realm, vm.names.from, from, 1, attr); - define_native_function(realm, vm.names.compare, compare, 2, attr); -} - -// 9.1.1 Temporal.PlainYearMonth ( isoYear, isoMonth [ , calendarLike [ , referenceISODay ] ] ), https://tc39.es/proposal-temporal/#sec-temporal.plainyearmonth -ThrowCompletionOr PlainYearMonthConstructor::call() -{ - auto& vm = this->vm(); - - // 1. If NewTarget is undefined, throw a TypeError exception. - return vm.throw_completion(ErrorType::ConstructorWithoutNew, "Temporal.PlainYearMonth"); -} - -// 9.1.1 Temporal.PlainYearMonth ( isoYear, isoMonth [ , calendarLike [ , referenceISODay ] ] ), https://tc39.es/proposal-temporal/#sec-temporal.plainyearmonth -ThrowCompletionOr> PlainYearMonthConstructor::construct(FunctionObject& new_target) -{ - auto& vm = this->vm(); - - auto iso_year = vm.argument(0); - auto iso_month = vm.argument(1); - auto calendar_like = vm.argument(2); - auto reference_iso_day = vm.argument(3); - - // 2. If referenceISODay is undefined, then - if (reference_iso_day.is_undefined()) { - // a. Set referenceISODay to 1𝔽. - reference_iso_day = Value(1); - } - - // 3. Let y be ? ToIntegerWithTruncation(isoYear). - auto y = TRY(to_integer_with_truncation(vm, iso_year, ErrorType::TemporalInvalidPlainYearMonth)); - - // 4. Let m be ? ToIntegerWithTruncation(isoMonth). - auto m = TRY(to_integer_with_truncation(vm, iso_month, ErrorType::TemporalInvalidPlainYearMonth)); - - // 5. Let calendar be ? ToTemporalCalendarWithISODefault(calendarLike). - auto* calendar = TRY(to_temporal_calendar_with_iso_default(vm, calendar_like)); - - // 6. Let ref be ? ToIntegerWithTruncation(referenceISODay). - auto ref = TRY(to_integer_with_truncation(vm, reference_iso_day, ErrorType::TemporalInvalidPlainYearMonth)); - - // 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 behavior as the call to CreateTemporalYearMonth will immediately check that these values are valid - // ISO values (for years: -273975 - 273975, for months: 1 - 12, for days: 1 - 31) all of which are subsets of this check. - if (!AK::is_within_range(y) || !AK::is_within_range(m) || !AK::is_within_range(ref)) - return vm.throw_completion(ErrorType::TemporalInvalidPlainYearMonth); - - // 7. Return ? CreateTemporalYearMonth(y, m, calendar, ref, NewTarget). - return *TRY(create_temporal_year_month(vm, y, m, *calendar, ref, &new_target)); -} - -// 9.2.2 Temporal.PlainYearMonth.from ( item [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal.plainyearmonth.from -JS_DEFINE_NATIVE_FUNCTION(PlainYearMonthConstructor::from) -{ - // 1. Set options to ? GetOptionsObject(options). - auto* options = TRY(get_options_object(vm, vm.argument(1))); - - auto item = vm.argument(0); - - // 2. If Type(item) is Object and item has an [[InitializedTemporalYearMonth]] internal slot, then - if (item.is_object() && is(item.as_object())) { - // a. Perform ? ToTemporalOverflow(options). - (void)TRY(to_temporal_overflow(vm, options)); - - auto& plain_year_month_object = static_cast(item.as_object()); - - // b. Return ! CreateTemporalYearMonth(item.[[ISOYear]], item.[[ISOMonth]], item.[[Calendar]], item.[[ISODay]]). - return MUST(create_temporal_year_month(vm, plain_year_month_object.iso_year(), plain_year_month_object.iso_month(), plain_year_month_object.calendar(), plain_year_month_object.iso_day())); - } - - // 3. Return ? ToTemporalYearMonth(item, options). - return TRY(to_temporal_year_month(vm, item, options)); -} - -// 9.2.3 Temporal.PlainYearMonth.compare ( one, two ), https://tc39.es/proposal-temporal/#sec-temporal.plainyearmonth.compare -JS_DEFINE_NATIVE_FUNCTION(PlainYearMonthConstructor::compare) -{ - // 1. Set one to ? ToTemporalYearMonth(one). - auto* one = TRY(to_temporal_year_month(vm, vm.argument(0))); - - // 2. Set two to ? ToTemporalYearMonth(one). - auto* two = TRY(to_temporal_year_month(vm, vm.argument(1))); - - // 3. Return 𝔽(! CompareISODate(one.[[ISOYear]], one.[[ISOMonth]], one.[[ISODay]], two.[[ISOYear]], two.[[ISOMonth]], two.[[ISODay]])). - return Value(compare_iso_date(one->iso_year(), one->iso_month(), one->iso_day(), two->iso_year(), two->iso_month(), two->iso_day())); -} - -} diff --git a/Libraries/LibJS/Runtime/Temporal/PlainYearMonthConstructor.h b/Libraries/LibJS/Runtime/Temporal/PlainYearMonthConstructor.h deleted file mode 100644 index 7dafaeda508..00000000000 --- a/Libraries/LibJS/Runtime/Temporal/PlainYearMonthConstructor.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2021-2022, Linus Groh - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include - -namespace JS::Temporal { - -class PlainYearMonthConstructor final : public NativeFunction { - JS_OBJECT(PlainYearMonthConstructor, NativeFunction); - GC_DECLARE_ALLOCATOR(PlainYearMonthConstructor); - -public: - virtual void initialize(Realm&) override; - virtual ~PlainYearMonthConstructor() override = default; - - virtual ThrowCompletionOr call() override; - virtual ThrowCompletionOr> construct(FunctionObject& new_target) override; - -private: - explicit PlainYearMonthConstructor(Realm&); - - virtual bool has_constructor() const override { return true; } - - JS_DECLARE_NATIVE_FUNCTION(from); - JS_DECLARE_NATIVE_FUNCTION(compare); -}; - -} diff --git a/Libraries/LibJS/Runtime/Temporal/PlainYearMonthPrototype.cpp b/Libraries/LibJS/Runtime/Temporal/PlainYearMonthPrototype.cpp deleted file mode 100644 index daf93e10a66..00000000000 --- a/Libraries/LibJS/Runtime/Temporal/PlainYearMonthPrototype.cpp +++ /dev/null @@ -1,463 +0,0 @@ -/* - * Copyright (c) 2021-2023, Linus Groh - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace JS::Temporal { - -GC_DEFINE_ALLOCATOR(PlainYearMonthPrototype); - -// 9.3 Properties of the Temporal.PlainYearMonth Prototype Object, https://tc39.es/proposal-temporal/#sec-properties-of-the-temporal-plainyearmonth-prototype-object -PlainYearMonthPrototype::PlainYearMonthPrototype(Realm& realm) - : PrototypeObject(realm.intrinsics().object_prototype()) -{ -} - -void PlainYearMonthPrototype::initialize(Realm& realm) -{ - Base::initialize(realm); - - auto& vm = this->vm(); - - // 9.3.2 Temporal.PlainYearMonth.prototype[ @@toStringTag ], https://tc39.es/proposal-temporal/#sec-temporal.plainyearmonth.prototype-@@tostringtag - define_direct_property(vm.well_known_symbol_to_string_tag(), PrimitiveString::create(vm, "Temporal.PlainYearMonth"_string), Attribute::Configurable); - - define_native_accessor(realm, vm.names.calendar, calendar_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.calendarId, calendar_id_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.year, year_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.month, month_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.monthCode, month_code_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.daysInYear, days_in_year_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.daysInMonth, days_in_month_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.monthsInYear, months_in_year_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.inLeapYear, in_leap_year_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.era, era_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.eraYear, era_year_getter, {}, Attribute::Configurable); - - u8 attr = Attribute::Writable | Attribute::Configurable; - define_native_function(realm, vm.names.with, with, 1, attr); - define_native_function(realm, vm.names.add, add, 1, attr); - define_native_function(realm, vm.names.subtract, subtract, 1, attr); - define_native_function(realm, vm.names.until, until, 1, attr); - define_native_function(realm, vm.names.since, since, 1, attr); - define_native_function(realm, vm.names.equals, equals, 1, attr); - define_native_function(realm, vm.names.toString, to_string, 0, attr); - define_native_function(realm, vm.names.toLocaleString, to_locale_string, 0, attr); - define_native_function(realm, vm.names.toJSON, to_json, 0, attr); - define_native_function(realm, vm.names.valueOf, value_of, 0, attr); - define_native_function(realm, vm.names.toPlainDate, to_plain_date, 1, attr); - define_native_function(realm, vm.names.getISOFields, get_iso_fields, 0, attr); -} - -// 9.3.3 get Temporal.PlainYearMonth.prototype.calendar, https://tc39.es/proposal-temporal/#sec-get-temporal.plainyearmonth.prototype.calendar -JS_DEFINE_NATIVE_FUNCTION(PlainYearMonthPrototype::calendar_getter) -{ - // 1. Let yearMonth be the this value. - // 2. Perform ? RequireInternalSlot(yearMonth, [[InitializedTemporalYearMonth]]). - auto year_month = TRY(typed_this_object(vm)); - - // 3. Return yearMonth.[[Calendar]]. - return Value(&year_month->calendar()); -} - -// 9.3.4 get Temporal.PlainYearMonth.prototype.year, https://tc39.es/proposal-temporal/#sec-get-temporal.plainyearmonth.prototype.year -JS_DEFINE_NATIVE_FUNCTION(PlainYearMonthPrototype::year_getter) -{ - // 1. Let yearMonth be the this value. - // 2. Perform ? RequireInternalSlot(yearMonth, [[InitializedTemporalYearMonth]]). - auto year_month = TRY(typed_this_object(vm)); - - // 3. Let calendar be yearMonth.[[Calendar]]. - auto& calendar = year_month->calendar(); - - // 4. Return 𝔽(? CalendarYear(calendar, yearMonth)). - return Value(TRY(calendar_year(vm, calendar, year_month))); -} - -// 9.3.5 get Temporal.PlainYearMonth.prototype.month, https://tc39.es/proposal-temporal/#sec-get-temporal.plainyearmonth.prototype.month -JS_DEFINE_NATIVE_FUNCTION(PlainYearMonthPrototype::month_getter) -{ - // 1. Let yearMonth be the this value. - // 2. Perform ? RequireInternalSlot(yearMonth, [[InitializedTemporalYearMonth]]). - auto year_month = TRY(typed_this_object(vm)); - - // 3. Let calendar be yearMonth.[[Calendar]]. - auto& calendar = year_month->calendar(); - - // 4. Return 𝔽(? CalendarMonth(calendar, yearMonth)). - return Value(TRY(calendar_month(vm, calendar, year_month))); -} - -// 9.3.6 get Temporal.PlainYearMonth.prototype.monthCode, https://tc39.es/proposal-temporal/#sec-get-temporal.plainyearmonth.prototype.monthCode -JS_DEFINE_NATIVE_FUNCTION(PlainYearMonthPrototype::month_code_getter) -{ - // 1. Let yearMonth be the this value. - // 2. Perform ? RequireInternalSlot(yearMonth, [[InitializedTemporalYearMonth]]). - auto year_month = TRY(typed_this_object(vm)); - - // 3. Let calendar be yearMonth.[[Calendar]]. - auto& calendar = year_month->calendar(); - - // 4. Return ? CalendarMonthCode(calendar, yearMonth). - return PrimitiveString::create(vm, TRY(calendar_month_code(vm, calendar, year_month))); -} - -// 9.3.7 get Temporal.PlainYearMonth.prototype.daysInYear, https://tc39.es/proposal-temporal/#sec-get-temporal.plainyearmonth.prototype.daysinyear -JS_DEFINE_NATIVE_FUNCTION(PlainYearMonthPrototype::days_in_year_getter) -{ - // 1. Let yearMonth be the this value. - // 2. Perform ? RequireInternalSlot(yearMonth, [[InitializedTemporalYearMonth]]). - auto year_month = TRY(typed_this_object(vm)); - - // 3. Let calendar be yearMonth.[[Calendar]]. - auto& calendar = year_month->calendar(); - - // 4. Return 𝔽(? CalendarDaysInYear(calendar, yearMonth)). - return TRY(calendar_days_in_year(vm, calendar, year_month)); -} - -// 9.3.8 get Temporal.PlainYearMonth.prototype.daysInMonth, https://tc39.es/proposal-temporal/#sec-get-temporal.plainyearmonth.prototype.daysinmonth -JS_DEFINE_NATIVE_FUNCTION(PlainYearMonthPrototype::days_in_month_getter) -{ - // 1. Let yearMonth be the this value. - // 2. Perform ? RequireInternalSlot(yearMonth, [[InitializedTemporalYearMonth]]). - auto year_month = TRY(typed_this_object(vm)); - - // 3. Let calendar be yearMonth.[[Calendar]]. - auto& calendar = year_month->calendar(); - - // 4. Return 𝔽(? CalendarDaysInMonth(calendar, yearMonth)). - return TRY(calendar_days_in_month(vm, calendar, year_month)); -} - -// 9.3.9 get Temporal.PlainYearMonth.prototype.monthsInYear, https://tc39.es/proposal-temporal/#sec-get-temporal.plainyearmonth.prototype.monthsinyear -JS_DEFINE_NATIVE_FUNCTION(PlainYearMonthPrototype::months_in_year_getter) -{ - // 1. Let yearMonth be the this value. - // 2. Perform ? RequireInternalSlot(yearMonth, [[InitializedTemporalYearMonth]]). - auto year_month = TRY(typed_this_object(vm)); - - // 3. Let calendar be yearMonth.[[Calendar]]. - auto& calendar = year_month->calendar(); - - // 4. Return 𝔽(? CalendarMonthsInYear(calendar, yearMonth)). - return TRY(calendar_months_in_year(vm, calendar, year_month)); -} - -// 9.3.10 get Temporal.PlainYearMonth.prototype.inLeapYear, https://tc39.es/proposal-temporal/#sec-get-temporal.plainyearmonth.prototype.inleapyear -JS_DEFINE_NATIVE_FUNCTION(PlainYearMonthPrototype::in_leap_year_getter) -{ - // 1. Let yearMonth be the this value. - // 2. Perform ? RequireInternalSlot(yearMonth, [[InitializedTemporalYearMonth]]). - auto year_month = TRY(typed_this_object(vm)); - - // 3. Let calendar be yearMonth.[[Calendar]]. - auto& calendar = year_month->calendar(); - - // 4. Return ? CalendarInLeapYear(calendar, yearMonth). - return Value(TRY(calendar_in_leap_year(vm, calendar, year_month))); -} - -// 15.6.9.2 get Temporal.PlainYearMonth.prototype.era, https://tc39.es/proposal-temporal/#sec-get-temporal.plainyearmonth.prototype.era -JS_DEFINE_NATIVE_FUNCTION(PlainYearMonthPrototype::era_getter) -{ - // 1. Let plainYearMonth be the this value. - // 2. Perform ? RequireInternalSlot(plainYearMonth, [[InitializedTemporalYearMonth]]). - auto plain_year_month = TRY(typed_this_object(vm)); - - // 3. Let calendar be plainYearMonth.[[Calendar]]. - auto& calendar = plain_year_month->calendar(); - - // 4. Return ? CalendarEra(calendar, plainYearMonth). - return TRY(calendar_era(vm, calendar, plain_year_month)); -} - -// 15.6.9.3 get Temporal.PlainYearMonth.prototype.eraYear, https://tc39.es/proposal-temporal/#sec-get-temporal.plainyearmonth.prototype.erayear -JS_DEFINE_NATIVE_FUNCTION(PlainYearMonthPrototype::era_year_getter) -{ - // 1. Let plainYearMonth be the this value. - // 2. Perform ? RequireInternalSlot(plainYearMonth, [[InitializedTemporalYearMonth]]). - auto plain_year_month = TRY(typed_this_object(vm)); - - // 3. Let calendar be plainYearMonth.[[Calendar]]. - auto& calendar = plain_year_month->calendar(); - - // 4. Return ? CalendarEraYear(calendar, plainYearMonth). - return TRY(calendar_era_year(vm, calendar, plain_year_month)); -} - -// 9.3.11 Temporal.PlainYearMonth.prototype.with ( temporalYearMonthLike [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal.plainyearmonth.prototype.with -JS_DEFINE_NATIVE_FUNCTION(PlainYearMonthPrototype::with) -{ - auto temporal_year_month_like = vm.argument(0); - - // 1. Let yearMonth be the this value. - // 2. Perform ? RequireInternalSlot(yearMonth, [[InitializedTemporalYearMonth]]). - auto year_month = TRY(typed_this_object(vm)); - - // 3. If Type(temporalYearMonthLike) is not Object, then - if (!temporal_year_month_like.is_object()) { - // a. Throw a TypeError exception. - return vm.throw_completion(ErrorType::NotAnObject, temporal_year_month_like.to_string_without_side_effects()); - } - - // 4. Perform ? RejectObjectWithCalendarOrTimeZone(temporalYearMonthLike). - TRY(reject_object_with_calendar_or_time_zone(vm, temporal_year_month_like.as_object())); - - // 5. Let calendar be yearMonth.[[Calendar]]. - auto& calendar = year_month->calendar(); - - // 6. Let fieldNames be ? CalendarFields(calendar, « "month", "monthCode", "year" »). - auto field_names = TRY(calendar_fields(vm, calendar, { "month"sv, "monthCode"sv, "year"sv })); - - // 7. Let partialYearMonth be ? PrepareTemporalFields(temporalYearMonthLike, fieldNames, partial). - auto* partial_year_month = TRY(prepare_temporal_fields(vm, temporal_year_month_like.as_object(), field_names, PrepareTemporalFieldsPartial {})); - - // 8. Set options to ? GetOptionsObject(options). - auto* options = TRY(get_options_object(vm, vm.argument(1))); - - // 9. Let fields be ? PrepareTemporalFields(yearMonth, fieldNames, «»). - auto* fields = TRY(prepare_temporal_fields(vm, year_month, field_names, Vector {})); - - // 10. Set fields to ? CalendarMergeFields(calendar, fields, partialYearMonth). - fields = TRY(calendar_merge_fields(vm, calendar, *fields, *partial_year_month)); - - // 11. Set fields to ? PrepareTemporalFields(fields, fieldNames, «»). - fields = TRY(prepare_temporal_fields(vm, *fields, field_names, Vector {})); - - // 12. Return ? CalendarYearMonthFromFields(calendar, fields, options). - return TRY(calendar_year_month_from_fields(vm, calendar, *fields, options)); -} - -// 9.3.12 Temporal.PlainYearMonth.prototype.add ( temporalDurationLike [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal.plainyearmonth.prototype.add -JS_DEFINE_NATIVE_FUNCTION(PlainYearMonthPrototype::add) -{ - auto temporal_duration_like = vm.argument(0); - auto options = vm.argument(1); - - // 1. Let yearMonth be the this value. - // 2. Perform ? RequireInternalSlot(yearMonth, [[InitializedTemporalYearMonth]]). - auto year_month = TRY(typed_this_object(vm)); - - // 3. Return ? AddDurationToOrSubtractDurationFromPlainYearMonth(add, yearMonth, temporalDurationLike, options). - return TRY(add_duration_to_or_subtract_duration_from_plain_year_month(vm, ArithmeticOperation::Add, year_month, temporal_duration_like, options)); -} - -// 9.3.13 Temporal.PlainYearMonth.prototype.subtract ( temporalDurationLike [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal.plainyearmonth.prototype.subtract -JS_DEFINE_NATIVE_FUNCTION(PlainYearMonthPrototype::subtract) -{ - auto temporal_duration_like = vm.argument(0); - auto options = vm.argument(1); - - // 1. Let yearMonth be the this value. - // 2. Perform ? RequireInternalSlot(yearMonth, [[InitializedTemporalYearMonth]]). - auto year_month = TRY(typed_this_object(vm)); - - // 3. Return ? AddDurationToOrSubtractDurationFromPlainYearMonth(add, yearMonth, temporalDurationLike, options). - return TRY(add_duration_to_or_subtract_duration_from_plain_year_month(vm, ArithmeticOperation::Subtract, year_month, temporal_duration_like, options)); -} - -// 9.3.14 Temporal.PlainYearMonth.prototype.until ( other [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal.plainyearmonth.prototype.until -JS_DEFINE_NATIVE_FUNCTION(PlainYearMonthPrototype::until) -{ - auto other = vm.argument(0); - auto options = vm.argument(1); - - // 1. Let yearMonth be the this value. - // 2. Perform ? RequireInternalSlot(yearMonth, [[InitializedTemporalYearMonth]]). - auto year_month = TRY(typed_this_object(vm)); - - // 3. Return ? DifferenceTemporalPlainYearMonth(until, yearMonth, other, options). - return TRY(difference_temporal_plain_year_month(vm, DifferenceOperation::Until, year_month, other, options)); -} - -// 9.3.15 Temporal.PlainYearMonth.prototype.since ( other [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal.plainyearmonth.prototype.since -JS_DEFINE_NATIVE_FUNCTION(PlainYearMonthPrototype::since) -{ - auto other = vm.argument(0); - auto options = vm.argument(1); - - // 1. Let yearMonth be the this value. - // 2. Perform ? RequireInternalSlot(yearMonth, [[InitializedTemporalYearMonth]]). - auto year_month = TRY(typed_this_object(vm)); - - // 3. Return ? DifferenceTemporalPlainYearMonth(since, yearMonth, other, options). - return TRY(difference_temporal_plain_year_month(vm, DifferenceOperation::Since, year_month, other, options)); -} - -// 9.3.16 Temporal.PlainYearMonth.prototype.equals ( other ), https://tc39.es/proposal-temporal/#sec-temporal.plainyearmonth.prototype.equals -JS_DEFINE_NATIVE_FUNCTION(PlainYearMonthPrototype::equals) -{ - // 1. Let yearMonth be the this value. - // 2. Perform ? RequireInternalSlot(yearMonth, [[InitializedTemporalYearMonth]]). - auto year_month = TRY(typed_this_object(vm)); - - // 3. Set other to ? ToTemporalYearMonth(other). - auto* other = TRY(to_temporal_year_month(vm, vm.argument(0))); - - // 4. If yearMonth.[[ISOYear]] ≠ other.[[ISOYear]], return false. - if (year_month->iso_year() != other->iso_year()) - return Value(false); - - // 5. If yearMonth.[[ISOMonth]] ≠ other.[[ISOMonth]], return false. - if (year_month->iso_month() != other->iso_month()) - return Value(false); - - // 6. If yearMonth.[[ISODay]] ≠ other.[[ISODay]], return false. - if (year_month->iso_day() != other->iso_day()) - return Value(false); - - // 7. Return ? CalendarEquals(yearMonth.[[Calendar]], other.[[Calendar]]). - return Value(TRY(calendar_equals(vm, year_month->calendar(), other->calendar()))); -} - -// 9.3.17 Temporal.PlainYearMonth.prototype.toString ( [ options ] ), https://tc39.es/proposal-temporal/#sec-temporal.plainyearmonth.prototype.tostring -JS_DEFINE_NATIVE_FUNCTION(PlainYearMonthPrototype::to_string) -{ - // 1. Let yearMonth be the this value. - // 2. Perform ? RequireInternalSlot(yearMonth, [[InitializedTemporalYearMonth]]). - auto year_month = TRY(typed_this_object(vm)); - - // 3. Set options to ? GetOptionsObject(options). - auto* options = TRY(get_options_object(vm, vm.argument(0))); - - // 4. Let showCalendar be ? ToCalendarNameOption(options). - auto show_calendar = TRY(to_calendar_name_option(vm, *options)); - - // 5. Return ? TemporalYearMonthToString(yearMonth, showCalendar). - return PrimitiveString::create(vm, TRY(temporal_year_month_to_string(vm, year_month, show_calendar))); -} - -// 9.3.18 Temporal.PlainYearMonth.prototype.toLocaleString ( [ locales [ , options ] ] ), https://tc39.es/proposal-temporal/#sec-temporal.plainyearmonth.prototype.tolocalestring -// NOTE: This is the minimum toLocaleString implementation for engines without ECMA-402. -JS_DEFINE_NATIVE_FUNCTION(PlainYearMonthPrototype::to_locale_string) -{ - // 1. Let yearMonth be the this value. - // 2. Perform ? RequireInternalSlot(yearMonth, [[InitializedTemporalYearMonth]]). - auto year_month = TRY(typed_this_object(vm)); - - // 3. Return ? TemporalYearMonthToString(yearMonth, "auto"). - return PrimitiveString::create(vm, TRY(temporal_year_month_to_string(vm, year_month, "auto"sv))); -} - -// 9.3.19 Temporal.PlainYearMonth.prototype.toJSON ( ), https://tc39.es/proposal-temporal/#sec-temporal.plainyearmonth.prototype.tojson -JS_DEFINE_NATIVE_FUNCTION(PlainYearMonthPrototype::to_json) -{ - // 1. Let yearMonth be the this value. - // 2. Perform ? RequireInternalSlot(yearMonth, [[InitializedTemporalYearMonth]]). - auto year_month = TRY(typed_this_object(vm)); - - // 3. Return ? TemporalYearMonthToString(yearMonth, "auto"). - return PrimitiveString::create(vm, TRY(temporal_year_month_to_string(vm, year_month, "auto"sv))); -} - -// 9.3.20 Temporal.PlainYearMonth.prototype.valueOf ( ), https://tc39.es/proposal-temporal/#sec-temporal.plainyearmonth.prototype.valueof -JS_DEFINE_NATIVE_FUNCTION(PlainYearMonthPrototype::value_of) -{ - // 1. Throw a TypeError exception. - return vm.throw_completion(ErrorType::Convert, "Temporal.PlainYearMonth", "a primitive value"); -} - -// 9.3.21 Temporal.PlainYearMonth.prototype.toPlainDate ( item ), https://tc39.es/proposal-temporal/#sec-temporal.plainyearmonth.prototype.toplaindate -JS_DEFINE_NATIVE_FUNCTION(PlainYearMonthPrototype::to_plain_date) -{ - auto& realm = *vm.current_realm(); - - auto item = vm.argument(0); - - // 1. Let yearMonth be the this value. - // 2. Perform ? RequireInternalSlot(yearMonth, [[InitializedTemporalYearMonth]]). - auto year_month = TRY(typed_this_object(vm)); - - // 3. If Type(item) is not Object, then - if (!item.is_object()) { - // a. Throw a TypeError exception. - return vm.throw_completion(ErrorType::NotAnObject, item); - } - - // 4. Let calendar be yearMonth.[[Calendar]]. - auto& calendar = year_month->calendar(); - - // 5. Let receiverFieldNames be ? CalendarFields(calendar, « "monthCode", "year" »). - auto receiver_field_names = TRY(calendar_fields(vm, calendar, { "monthCode"sv, "year"sv })); - - // 6. Let fields be ? PrepareTemporalFields(yearMonth, receiverFieldNames, «»). - auto* fields = TRY(prepare_temporal_fields(vm, year_month, receiver_field_names, Vector {})); - - // 7. Let inputFieldNames be ? CalendarFields(calendar, « "day" »). - auto input_field_names = TRY(calendar_fields(vm, calendar, { "day"sv })); - - // 8. Let inputFields be ? PrepareTemporalFields(item, inputFieldNames, «»). - auto* input_fields = TRY(prepare_temporal_fields(vm, item.as_object(), input_field_names, Vector {})); - - // 9. Let mergedFields be ? CalendarMergeFields(calendar, fields, inputFields). - auto* merged_fields = TRY(calendar_merge_fields(vm, calendar, *fields, *input_fields)); - - // 10. Let mergedFieldNames be MergeLists(receiverFieldNames, inputFieldNames). - auto merged_field_names = merge_lists(receiver_field_names, input_field_names); - - // 11. Set mergedFields to ? PrepareTemporalFields(mergedFields, mergedFieldNames, «»). - merged_fields = TRY(prepare_temporal_fields(vm, *merged_fields, merged_field_names, Vector {})); - - // 12. Let options be OrdinaryObjectCreate(null). - auto options = Object::create(realm, nullptr); - - // 13. Perform ! CreateDataPropertyOrThrow(options, "overflow", "reject"). - MUST(options->create_data_property_or_throw(vm.names.overflow, PrimitiveString::create(vm, vm.names.reject.as_string()))); - - // 14. Return ? CalendarDateFromFields(calendar, mergedFields, options). - return TRY(calendar_date_from_fields(vm, calendar, *merged_fields, options)); -} - -// 9.3.22 Temporal.PlainYearMonth.prototype.getISOFields ( ), https://tc39.es/proposal-temporal/#sec-temporal.plainyearmonth.prototype.getisofields -JS_DEFINE_NATIVE_FUNCTION(PlainYearMonthPrototype::get_iso_fields) -{ - auto& realm = *vm.current_realm(); - - // 1. Let yearMonth be the this value. - // 2. Perform ? RequireInternalSlot(yearMonth, [[InitializedTemporalYearMonth]]). - auto year_month = TRY(typed_this_object(vm)); - - // 3. Let fields be OrdinaryObjectCreate(%Object.prototype%). - auto fields = Object::create(realm, realm.intrinsics().object_prototype()); - - // 4. Perform ! CreateDataPropertyOrThrow(fields, "calendar", yearMonth.[[Calendar]]). - MUST(fields->create_data_property_or_throw(vm.names.calendar, Value(&year_month->calendar()))); - - // 5. Perform ! CreateDataPropertyOrThrow(fields, "isoDay", 𝔽(yearMonth.[[ISODay]])). - MUST(fields->create_data_property_or_throw(vm.names.isoDay, Value(year_month->iso_day()))); - - // 6. Perform ! CreateDataPropertyOrThrow(fields, "isoMonth", 𝔽(yearMonth.[[ISOMonth]])). - MUST(fields->create_data_property_or_throw(vm.names.isoMonth, Value(year_month->iso_month()))); - - // 7. Perform ! CreateDataPropertyOrThrow(fields, "isoYear", 𝔽(yearMonth.[[ISOYear]])). - MUST(fields->create_data_property_or_throw(vm.names.isoYear, Value(year_month->iso_year()))); - - // 8. Return fields. - return fields; -} - -// 9.3.3 get Temporal.PlainYearMonth.prototype.calendarId -JS_DEFINE_NATIVE_FUNCTION(PlainYearMonthPrototype::calendar_id_getter) -{ - // Step 1: Let yearMonth be the this value - // Step 2: Perform ? RequireInternalSlot(yearMonth, [[InitializedTemporalYearMonth]]). - auto year_month = TRY(typed_this_object(vm)); - - // Step 3: Return yearMonth.[[Calendar]].identifier - auto& calendar = static_cast(year_month->calendar()); - return PrimitiveString::create(vm, calendar.identifier()); -} - -} diff --git a/Libraries/LibJS/Runtime/Temporal/PlainYearMonthPrototype.h b/Libraries/LibJS/Runtime/Temporal/PlainYearMonthPrototype.h deleted file mode 100644 index feeb49a94ee..00000000000 --- a/Libraries/LibJS/Runtime/Temporal/PlainYearMonthPrototype.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2021, Linus Groh - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include -#include - -namespace JS::Temporal { - -class PlainYearMonthPrototype final : public PrototypeObject { - JS_PROTOTYPE_OBJECT(PlainYearMonthPrototype, PlainYearMonth, Temporal.PlainYearMonth); - GC_DECLARE_ALLOCATOR(PlainYearMonthPrototype); - -public: - virtual void initialize(Realm&) override; - virtual ~PlainYearMonthPrototype() override = default; - -private: - explicit PlainYearMonthPrototype(Realm&); - - JS_DECLARE_NATIVE_FUNCTION(calendar_getter); - JS_DECLARE_NATIVE_FUNCTION(calendar_id_getter); - JS_DECLARE_NATIVE_FUNCTION(year_getter); - JS_DECLARE_NATIVE_FUNCTION(month_getter); - JS_DECLARE_NATIVE_FUNCTION(month_code_getter); - JS_DECLARE_NATIVE_FUNCTION(days_in_year_getter); - JS_DECLARE_NATIVE_FUNCTION(days_in_month_getter); - JS_DECLARE_NATIVE_FUNCTION(months_in_year_getter); - JS_DECLARE_NATIVE_FUNCTION(in_leap_year_getter); - JS_DECLARE_NATIVE_FUNCTION(era_getter); - JS_DECLARE_NATIVE_FUNCTION(era_year_getter); - JS_DECLARE_NATIVE_FUNCTION(with); - JS_DECLARE_NATIVE_FUNCTION(add); - JS_DECLARE_NATIVE_FUNCTION(subtract); - JS_DECLARE_NATIVE_FUNCTION(until); - JS_DECLARE_NATIVE_FUNCTION(since); - JS_DECLARE_NATIVE_FUNCTION(equals); - JS_DECLARE_NATIVE_FUNCTION(to_string); - JS_DECLARE_NATIVE_FUNCTION(to_locale_string); - JS_DECLARE_NATIVE_FUNCTION(to_json); - JS_DECLARE_NATIVE_FUNCTION(value_of); - JS_DECLARE_NATIVE_FUNCTION(to_plain_date); - JS_DECLARE_NATIVE_FUNCTION(get_iso_fields); -}; - -} diff --git a/Libraries/LibJS/Runtime/Temporal/Temporal.cpp b/Libraries/LibJS/Runtime/Temporal/Temporal.cpp index c898c629c16..ee7a19cf011 100644 --- a/Libraries/LibJS/Runtime/Temporal/Temporal.cpp +++ b/Libraries/LibJS/Runtime/Temporal/Temporal.cpp @@ -5,18 +5,7 @@ */ #include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include -#include -#include namespace JS::Temporal { @@ -36,19 +25,6 @@ void Temporal::initialize(Realm& realm) // 1.1.1 Temporal [ @@toStringTag ], https://tc39.es/proposal-temporal/#sec-temporal-@@tostringtag define_direct_property(vm.well_known_symbol_to_string_tag(), PrimitiveString::create(vm, "Temporal"_string), Attribute::Configurable); - - u8 attr = Attribute::Writable | Attribute::Configurable; - define_direct_property(vm.names.Now, realm.create(realm), attr); - define_intrinsic_accessor(vm.names.Calendar, attr, [](auto& realm) -> Value { return realm.intrinsics().temporal_calendar_constructor(); }); - define_intrinsic_accessor(vm.names.Duration, attr, [](auto& realm) -> Value { return realm.intrinsics().temporal_duration_constructor(); }); - define_intrinsic_accessor(vm.names.Instant, attr, [](auto& realm) -> Value { return realm.intrinsics().temporal_instant_constructor(); }); - define_intrinsic_accessor(vm.names.PlainDate, attr, [](auto& realm) -> Value { return realm.intrinsics().temporal_plain_date_constructor(); }); - define_intrinsic_accessor(vm.names.PlainDateTime, attr, [](auto& realm) -> Value { return realm.intrinsics().temporal_plain_date_time_constructor(); }); - define_intrinsic_accessor(vm.names.PlainMonthDay, attr, [](auto& realm) -> Value { return realm.intrinsics().temporal_plain_month_day_constructor(); }); - define_intrinsic_accessor(vm.names.PlainTime, attr, [](auto& realm) -> Value { return realm.intrinsics().temporal_plain_time_constructor(); }); - define_intrinsic_accessor(vm.names.PlainYearMonth, attr, [](auto& realm) -> Value { return realm.intrinsics().temporal_plain_year_month_constructor(); }); - define_intrinsic_accessor(vm.names.TimeZone, attr, [](auto& realm) -> Value { return realm.intrinsics().temporal_time_zone_constructor(); }); - define_intrinsic_accessor(vm.names.ZonedDateTime, attr, [](auto& realm) -> Value { return realm.intrinsics().temporal_zoned_date_time_constructor(); }); } } diff --git a/Libraries/LibJS/Runtime/Temporal/TimeZone.cpp b/Libraries/LibJS/Runtime/Temporal/TimeZone.cpp deleted file mode 100644 index 96f9fbfadb7..00000000000 --- a/Libraries/LibJS/Runtime/Temporal/TimeZone.cpp +++ /dev/null @@ -1,648 +0,0 @@ -/* - * Copyright (c) 2021-2023, Linus Groh - * Copyright (c) 2024, Shannon Booth - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace JS::Temporal { - -GC_DEFINE_ALLOCATOR(TimeZone); - -// 11 Temporal.TimeZone Objects, https://tc39.es/proposal-temporal/#sec-temporal-timezone-objects -TimeZone::TimeZone(Object& prototype) - : Object(ConstructWithPrototypeTag::Tag, prototype) -{ -} - -// 11.1.1 IsAvailableTimeZoneName ( timeZone ), https://tc39.es/proposal-temporal/#sec-isavailabletimezonename -bool is_available_time_zone_name(StringView time_zone) -{ - // 1. Let timeZones be AvailableTimeZones(). - auto const& time_zones = Unicode::available_time_zones(); - - // 2. For each String candidate in timeZones, do - for (auto const& candidate : time_zones) { - // a. If timeZone is an ASCII-case-insensitive match for candidate, return true. - if (time_zone.equals_ignoring_ascii_case(candidate)) - return true; - } - - // 3. Return false. - return false; -} - -// 6.4.2 CanonicalizeTimeZoneName ( timeZone ), https://tc39.es/ecma402/#sec-canonicalizetimezonename -// 11.1.2 CanonicalizeTimeZoneName ( timeZone ), https://tc39.es/proposal-temporal/#sec-canonicalizetimezonename -// 15.1.2 CanonicalizeTimeZoneName ( timeZone ), https://tc39.es/proposal-temporal/#sup-canonicalizetimezonename -ThrowCompletionOr canonicalize_time_zone_name(VM&, StringView time_zone) -{ - auto const& time_zones = Unicode::available_time_zones(); - - // 1. Let ianaTimeZone be the String value of the Zone or Link name of the IANA Time Zone Database that is an - // ASCII-case-insensitive match of timeZone as described in 6.1. - auto it = time_zones.find_if([&](auto const& candidate) { - return time_zone.equals_ignoring_ascii_case(candidate); - }); - VERIFY(it != time_zones.end()); - - // 2. If ianaTimeZone is a Link name, let ianaTimeZone be the String value of the corresponding Zone name as specified - // in the file backward of the IANA Time Zone Database. - auto iana_time_zone = Unicode::resolve_primary_time_zone(*it).value_or_lazy_evaluated([&]() { - return MUST(String::from_utf8(time_zone)); - }); - - // 3. If ianaTimeZone is one of "Etc/UTC", "Etc/GMT", or "GMT", return "UTC". - if (iana_time_zone.is_one_of("Etc/UTC"sv, "Etc/GMT"sv, "GMT"sv)) - return "UTC"_string; - - // 4. Return ianaTimeZone. - return iana_time_zone; -} - -// 11.6.1 CreateTemporalTimeZone ( identifier [ , newTarget ] ), https://tc39.es/proposal-temporal/#sec-temporal-createtemporaltimezone -ThrowCompletionOr create_temporal_time_zone(VM& vm, String identifier, FunctionObject const* new_target) -{ - auto& realm = *vm.current_realm(); - - // 1. If newTarget is not present, set newTarget to %Temporal.TimeZone%. - if (!new_target) - new_target = realm.intrinsics().temporal_time_zone_constructor(); - - // 2. Let object be ? OrdinaryCreateFromConstructor(newTarget, "%Temporal.TimeZone.prototype%", « [[InitializedTemporalTimeZone]], [[Identifier]], [[OffsetNanoseconds]] »). - auto object = TRY(ordinary_create_from_constructor(vm, *new_target, &Intrinsics::temporal_time_zone_prototype)); - - // 3. If IsTimeZoneOffsetString(identifier) is true, then - if (is_time_zone_offset_string(identifier)) { - // a. Let offsetNanosecondsResult be ParseTimeZoneOffsetString(identifier). - auto offset_nanoseconds_result = parse_time_zone_offset_string(identifier); - - // b. Set object.[[Identifier]] to ! FormatTimeZoneOffsetString(offsetNanosecondsResult). - object->set_identifier(MUST_OR_THROW_OOM(format_time_zone_offset_string(vm, offset_nanoseconds_result))); - - // c. Set object.[[OffsetNanoseconds]] to offsetNanosecondsResult. - object->set_offset_nanoseconds(offset_nanoseconds_result); - } - // 4. Else, - else { - // a. Assert: ! CanonicalizeTimeZoneName(identifier) is identifier. - VERIFY(MUST_OR_THROW_OOM(canonicalize_time_zone_name(vm, identifier)) == identifier); - - // b. Set object.[[Identifier]] to identifier. - object->set_identifier(move(identifier)); - - // c. Set object.[[OffsetNanoseconds]] to undefined. - // NOTE: No-op. - } - - // 5. Return object. - return object.ptr(); -} - -// 11.6.2 GetISOPartsFromEpoch ( epochNanoseconds ), https://tc39.es/proposal-temporal/#sec-temporal-getisopartsfromepoch -ISODateTime get_iso_parts_from_epoch(VM& vm, Crypto::SignedBigInteger const& epoch_nanoseconds) -{ - // 1. Assert: ! IsValidEpochNanoseconds(ℤ(epochNanoseconds)) is true. - VERIFY(is_valid_epoch_nanoseconds(BigInt::create(vm, epoch_nanoseconds))); - - // 2. Let remainderNs be epochNanoseconds modulo 10^6. - auto remainder_ns_bigint = modulo(epoch_nanoseconds, Crypto::UnsignedBigInteger { 1'000'000 }); - auto remainder_ns = remainder_ns_bigint.to_double(); - - // 3. Let epochMilliseconds be 𝔽((epochNanoseconds - remainderNs) / 10^6). - auto epoch_milliseconds_bigint = epoch_nanoseconds.minus(remainder_ns_bigint).divided_by(Crypto::UnsignedBigInteger { 1'000'000 }).quotient; - auto epoch_milliseconds = epoch_milliseconds_bigint.to_double(); - - // 4. Let year be ℝ(! YearFromTime(epochMilliseconds)). - auto year = year_from_time(epoch_milliseconds); - - // 5. Let month be ℝ(! MonthFromTime(epochMilliseconds)) + 1. - auto month = static_cast(month_from_time(epoch_milliseconds) + 1); - - // 6. Let day be ℝ(! DateFromTime(epochMilliseconds)). - auto day = date_from_time(epoch_milliseconds); - - // 7. Let hour be ℝ(! HourFromTime(epochMilliseconds)). - auto hour = hour_from_time(epoch_milliseconds); - - // 8. Let minute be ℝ(! MinFromTime(epochMilliseconds)). - auto minute = min_from_time(epoch_milliseconds); - - // 9. Let second be ℝ(! SecFromTime(epochMilliseconds)). - auto second = sec_from_time(epoch_milliseconds); - - // 10. Let millisecond be ℝ(! msFromTime(epochMilliseconds)). - auto millisecond = ms_from_time(epoch_milliseconds); - - // 11. Let microsecond be floor(remainderNs / 1000). - auto microsecond = floor(remainder_ns / 1000); - - // 12. Assert: microsecond < 1000. - VERIFY(microsecond < 1000); - - // 13. Let nanosecond be remainderNs modulo 1000. - auto nanosecond = modulo(remainder_ns, 1000); - - // 14. Return the Record { [[Year]]: year, [[Month]]: month, [[Day]]: day, [[Hour]]: hour, [[Minute]]: minute, [[Second]]: second, [[Millisecond]]: millisecond, [[Microsecond]]: microsecond, [[Nanosecond]]: nanosecond }. - return { .year = year, .month = month, .day = day, .hour = hour, .minute = minute, .second = second, .millisecond = millisecond, .microsecond = static_cast(microsecond), .nanosecond = static_cast(nanosecond) }; -} - -// 11.6.3 GetNamedTimeZoneNextTransition ( timeZoneIdentifier, epochNanoseconds ), https://tc39.es/proposal-temporal/#sec-temporal-getianatimezonenexttransition -BigInt* get_named_time_zone_next_transition(VM&, [[maybe_unused]] StringView time_zone_identifier, [[maybe_unused]] BigInt const& epoch_nanoseconds) -{ - // The implementation-defined abstract operation GetNamedTimeZoneNextTransition takes arguments timeZoneIdentifier (a String) and epochNanoseconds (a BigInt) and returns a BigInt or null. - // The returned value t represents the number of nanoseconds since the Unix epoch in UTC that corresponds to the first time zone transition after epochNanoseconds in the IANA time zone identified by timeZoneIdentifier. The operation returns null if no such transition exists for which t ≤ ℤ(nsMaxInstant). - // Given the same values of epochNanoseconds and timeZoneIdentifier, the result must be the same for the lifetime of the surrounding agent. - - // TODO: Implement this - return nullptr; -} - -// 11.6.4 GetNamedTimeZonePreviousTransition ( timeZoneIdentifier, epochNanoseconds ), https://tc39.es/proposal-temporal/#sec-temporal-getianatimezoneprevioustransition -BigInt* get_named_time_zone_previous_transition(VM&, [[maybe_unused]] StringView time_zone_identifier, [[maybe_unused]] BigInt const& epoch_nanoseconds) -{ - // The implementation-defined abstract operation GetNamedTimeZonePreviousTransition takes arguments timeZoneIdentifier (a String) and epochNanoseconds (a BigInt) and returns a BigInt or null. - // The returned value t represents the number of nanoseconds since the Unix epoch in UTC that corresponds to the last time zone transition before epochNanoseconds in the IANA time zone identified by timeZoneIdentifier. The operation returns null if no such transition exists for which t ≥ ℤ(nsMinInstant). - // Given the same values of epochNanoseconds and timeZoneIdentifier, the result must be the same for the lifetime of the surrounding agent. - - // TODO: Implement this - return nullptr; -} - -// 11.6.5 FormatTimeZoneOffsetString ( offsetNanoseconds ), https://tc39.es/proposal-temporal/#sec-temporal-formattimezoneoffsetstring -ThrowCompletionOr format_time_zone_offset_string(VM& vm, double offset_nanoseconds) -{ - auto offset = static_cast(offset_nanoseconds); - - // 1. Assert: offsetNanoseconds is an integer. - VERIFY(offset == offset_nanoseconds); - - StringBuilder builder; - // 2. If offsetNanoseconds ≥ 0, let sign be "+"; otherwise, let sign be "-". - if (offset >= 0) - builder.append('+'); - else - builder.append('-'); - - // 3. Let _offsetNanoseconds_ be abs(_offsetNanoseconds_). - offset = AK::abs(offset); - - // 4. Let nanoseconds be offsetNanoseconds modulo 10^9. - auto nanoseconds = offset % 1000000000; - - // 5. Let seconds be floor(offsetNanoseconds / 10^9) modulo 60. - auto seconds = (offset / 1000000000) % 60; - // 6. Let minutes be floor(offsetNanoseconds / (6 × 10^10)) modulo 60. - auto minutes = (offset / 60000000000) % 60; - // 7. Let hours be floor(offsetNanoseconds / (3.6 × 10^12)). - auto hours = offset / 3600000000000; - - // 8. Let h be ToZeroPaddedDecimalString(hours, 2). - builder.appendff("{:02}", hours); - // 9. Let m be ToZeroPaddedDecimalString(minutes, 2). - builder.appendff(":{:02}", minutes); - // 10. Let s be ToZeroPaddedDecimalString(seconds, 2). - // NOTE: Handled by steps 11 & 12 - - // 11. If nanoseconds ≠ 0, then - if (nanoseconds != 0) { - // a. Let fraction be ToZeroPaddedDecimalString(nanoseconds, 9). - auto fraction = TRY_OR_THROW_OOM(vm, String::formatted("{:09}", nanoseconds)); - - // b. Set fraction to the longest possible substring of fraction starting at position 0 and not ending with the code unit 0x0030 (DIGIT ZERO). - fraction = TRY_OR_THROW_OOM(vm, fraction.trim("0"sv, TrimMode::Right)); - - // c. Let post be the string-concatenation of the code unit 0x003A (COLON), s, the code unit 0x002E (FULL STOP), and fraction. - builder.appendff(":{:02}.{}", seconds, fraction); - } - // 12. Else if seconds ≠ 0, then - else if (seconds != 0) { - // a. Let post be the string-concatenation of the code unit 0x003A (COLON) and s. - builder.appendff(":{:02}", seconds); - } - // 13. Else, - // a. Let post be the empty String. - - // 14. Return the string-concatenation of sign, h, the code unit 0x003A (COLON), m, and post. - return TRY_OR_THROW_OOM(vm, builder.to_string()); -} - -// 11.6.6 FormatISOTimeZoneOffsetString ( offsetNanoseconds ), https://tc39.es/proposal-temporal/#sec-temporal-formatisotimezoneoffsetstring -ThrowCompletionOr format_iso_time_zone_offset_string(VM& vm, double offset_nanoseconds) -{ - // 1. Assert: offsetNanoseconds is an integer. - VERIFY(trunc(offset_nanoseconds) == offset_nanoseconds); - - // 2. Set offsetNanoseconds to RoundNumberToIncrement(offsetNanoseconds, 60 × 10^9, "halfExpand"). - offset_nanoseconds = round_number_to_increment(offset_nanoseconds, 60000000000, "halfExpand"sv); - - // 3. If offsetNanoseconds ≥ 0, let sign be "+"; otherwise, let sign be "-". - auto sign = offset_nanoseconds >= 0 ? "+"sv : "-"sv; - - // 4. Set offsetNanoseconds to abs(offsetNanoseconds). - offset_nanoseconds = fabs(offset_nanoseconds); - - // 5. Let minutes be offsetNanoseconds / (60 × 10^9) modulo 60. - auto minutes = fmod(offset_nanoseconds / 60000000000, 60); - - // 6. Let hours be floor(offsetNanoseconds / (3600 × 10^9)). - auto hours = floor(offset_nanoseconds / 3600000000000); - - // 7. Let h be ToZeroPaddedDecimalString(hours, 2). - // 8. Let m be ToZeroPaddedDecimalString(minutes, 2). - // 9. Return the string-concatenation of sign, h, the code unit 0x003A (COLON), and m. - return TRY_OR_THROW_OOM(vm, String::formatted("{}{:02}:{:02}", sign, (u32)hours, (u32)minutes)); -} - -// 11.6.7 ToTemporalTimeZone ( temporalTimeZoneLike ), https://tc39.es/proposal-temporal/#sec-temporal-totemporaltimezone -ThrowCompletionOr to_temporal_time_zone(VM& vm, Value temporal_time_zone_like) -{ - // 1. If Type(temporalTimeZoneLike) is Object, then - if (temporal_time_zone_like.is_object()) { - // a. If temporalTimeZoneLike has an [[InitializedTemporalTimeZone]] internal slot, then - if (is(temporal_time_zone_like.as_object())) { - // i. Return temporalTimeZoneLike. - return &temporal_time_zone_like.as_object(); - } - - // b. If temporalTimeZoneLike has an [[InitializedTemporalZonedDateTime]] internal slot, then - if (is(temporal_time_zone_like.as_object())) { - auto& zoned_date_time = static_cast(temporal_time_zone_like.as_object()); - - // i. Return temporalTimeZoneLike.[[TimeZone]]. - return &zoned_date_time.time_zone(); - } - - // c. If temporalTimeZoneLike has an [[InitializedTemporalCalendar]] internal slot, throw a RangeError exception. - if (is(temporal_time_zone_like.as_object())) - return vm.throw_completion(ErrorType::TemporalUnexpectedCalendarObject); - - // d. If ? HasProperty(temporalTimeZoneLike, "timeZone") is false, return temporalTimeZoneLike. - if (!TRY(temporal_time_zone_like.as_object().has_property(vm.names.timeZone))) - return &temporal_time_zone_like.as_object(); - - // e. Set temporalTimeZoneLike to ? Get(temporalTimeZoneLike, "timeZone"). - temporal_time_zone_like = TRY(temporal_time_zone_like.as_object().get(vm.names.timeZone)); - - // f. If Type(temporalTimeZoneLike) is Object, then - if (temporal_time_zone_like.is_object()) { - // i. If temporalTimeZoneLike has an [[InitializedTemporalCalendar]] internal slot, throw a RangeError exception. - if (is(temporal_time_zone_like.as_object())) - return vm.throw_completion(ErrorType::TemporalUnexpectedCalendarObject); - - // ii. If ? HasProperty(temporalTimeZoneLike, "timeZone") is false, return temporalTimeZoneLike. - if (!TRY(temporal_time_zone_like.as_object().has_property(vm.names.timeZone))) - return &temporal_time_zone_like.as_object(); - } - } - - // 2. Let identifier be ? ToString(temporalTimeZoneLike). - auto identifier = TRY(temporal_time_zone_like.to_string(vm)); - - // 3. Let parseResult be ? ParseTemporalTimeZoneString(identifier). - auto parse_result = TRY(parse_temporal_time_zone_string(vm, identifier)); - - // 4. If parseResult.[[Name]] is not undefined, then - if (parse_result.name.has_value()) { - // a. Let name be parseResult.[[Name]]. - auto name = parse_result.name.release_value(); - - // b. If IsTimeZoneOffsetString(name) is false, then - if (!is_time_zone_offset_string(name)) { - // i. If IsAvailableTimeZoneName(name) is false, throw a RangeError exception. - if (!is_available_time_zone_name(name)) - return vm.throw_completion(ErrorType::TemporalInvalidTimeZoneName, name); - - // ii. Set name to ! CanonicalizeTimeZoneName(name). - name = MUST_OR_THROW_OOM(canonicalize_time_zone_name(vm, name)); - } - - // c. Return ! CreateTemporalTimeZone(name). - return MUST_OR_THROW_OOM(create_temporal_time_zone(vm, move(name))); - } - - // 5. If parseResult.[[Z]] is true, return ! CreateTemporalTimeZone("UTC"). - if (parse_result.z) - return MUST_OR_THROW_OOM(create_temporal_time_zone(vm, "UTC"_string)); - - // 6. Return ! CreateTemporalTimeZone(parseResult.[[OffsetString]]). - return MUST_OR_THROW_OOM(create_temporal_time_zone(vm, parse_result.offset_string.release_value())); -} - -// 11.5.19 GetOffsetNanosecondsFor ( timeZoneRec, instant ), https://tc39.es/proposal-temporal/#sec-temporal-getoffsetnanosecondsfor -ThrowCompletionOr get_offset_nanoseconds_for(VM& vm, TimeZoneMethods const& time_zone_record, Instant const& instant) -{ - // 1. Let offsetNanoseconds be ? TimeZoneMethodsRecordCall(timeZoneRec, GET-OFFSET-NANOSECONDS-FOR, « instant »). - auto offset_nanoseconds_value = TRY(time_zone_methods_record_call(vm, time_zone_record, TimeZoneMethod::GetOffsetNanosecondsFor, { { &instant } })); - - // 2. If TimeZoneMethodsRecordIsBuiltin(timeZoneRec), return ℝ(offsetNanoseconds). - if (time_zone_methods_record_is_builtin(time_zone_record)) - return offset_nanoseconds_value.as_double(); - - // 3. If Type(offsetNanoseconds) is not Number, throw a TypeError exception. - if (!offset_nanoseconds_value.is_number()) - return vm.throw_completion(ErrorType::IsNotA, "Offset nanoseconds value", "number"); - - // 4. If IsIntegralNumber(offsetNanoseconds) is false, throw a RangeError exception. - if (!offset_nanoseconds_value.is_integral_number()) - return vm.throw_completion(ErrorType::IsNotAn, "Offset nanoseconds value", "integral number"); - - // 5. Set offsetNanoseconds to ℝ(offsetNanoseconds). - auto offset_nanoseconds = offset_nanoseconds_value.as_double(); - - // 6. If abs(offsetNanoseconds) ≥ nsPerDay, throw a RangeError exception. - if (fabs(offset_nanoseconds) >= ns_per_day) - return vm.throw_completion(ErrorType::TemporalInvalidOffsetNanosecondsValue); - - // 7. Return offsetNanoseconds. - return offset_nanoseconds; -} - -// 11.6.9 BuiltinTimeZoneGetOffsetStringFor ( timeZone, instant ), https://tc39.es/proposal-temporal/#sec-temporal-builtintimezonegetoffsetstringfor -ThrowCompletionOr builtin_time_zone_get_offset_string_for(VM& vm, Value time_zone, Instant& instant) -{ - auto time_zone_record = TRY(create_time_zone_methods_record(vm, GC::Ref { time_zone.as_object() }, { { TimeZoneMethod::GetOffsetNanosecondsFor } })); - - // 1. Let offsetNanoseconds be ? GetOffsetNanosecondsFor(timeZone, instant). - auto offset_nanoseconds = TRY(get_offset_nanoseconds_for(vm, time_zone_record, instant)); - - // 2. Return ! FormatTimeZoneOffsetString(offsetNanoseconds). - return MUST_OR_THROW_OOM(format_time_zone_offset_string(vm, offset_nanoseconds)); -} - -// 11.6.10 BuiltinTimeZoneGetPlainDateTimeFor ( timeZone, instant, calendar ), https://tc39.es/proposal-temporal/#sec-temporal-builtintimezonegetplaindatetimefor -ThrowCompletionOr builtin_time_zone_get_plain_date_time_for(VM& vm, Value time_zone, Instant& instant, Object& calendar) -{ - auto time_zone_record = TRY(create_time_zone_methods_record(vm, GC::Ref { time_zone.as_object() }, { { TimeZoneMethod::GetOffsetNanosecondsFor } })); - - // 1. Assert: instant has an [[InitializedTemporalInstant]] internal slot. - - // 2. Let offsetNanoseconds be ? GetOffsetNanosecondsFor(timeZone, instant). - auto offset_nanoseconds = TRY(get_offset_nanoseconds_for(vm, time_zone_record, instant)); - - // 3. Let result be ! GetISOPartsFromEpoch(ℝ(instant.[[Nanoseconds]])). - auto result = get_iso_parts_from_epoch(vm, instant.nanoseconds().big_integer()); - - // 4. Set result to BalanceISODateTime(result.[[Year]], result.[[Month]], result.[[Day]], result.[[Hour]], result.[[Minute]], result.[[Second]], result.[[Millisecond]], result.[[Microsecond]], result.[[Nanosecond]] + offsetNanoseconds). - result = balance_iso_date_time(result.year, result.month, result.day, result.hour, result.minute, result.second, result.millisecond, result.microsecond, result.nanosecond + offset_nanoseconds); - - // 5. Return ? CreateTemporalDateTime(result.[[Year]], result.[[Month]], result.[[Day]], result.[[Hour]], result.[[Minute]], result.[[Second]], result.[[Millisecond]], result.[[Microsecond]], result.[[Nanosecond]], calendar). - return create_temporal_date_time(vm, result.year, result.month, result.day, result.hour, result.minute, result.second, result.millisecond, result.microsecond, result.nanosecond, calendar); -} - -// 11.6.11 BuiltinTimeZoneGetInstantFor ( timeZone, dateTime, disambiguation ), https://tc39.es/proposal-temporal/#sec-temporal-builtintimezonegetinstantfor -ThrowCompletionOr> builtin_time_zone_get_instant_for(VM& vm, Value time_zone, PlainDateTime& date_time, StringView disambiguation) -{ - // 1. Assert: dateTime has an [[InitializedTemporalDateTime]] internal slot. - - // 2. Let possibleInstants be ? GetPossibleInstantsFor(timeZone, dateTime). - auto time_zone_record = TRY(create_time_zone_methods_record(vm, GC::Ref { time_zone.as_object() }, { { TimeZoneMethod::GetOffsetNanosecondsFor, TimeZoneMethod::GetPossibleInstantsFor } })); - auto possible_instants = TRY(get_possible_instants_for(vm, time_zone_record, date_time)); - - // 3. Return ? DisambiguatePossibleInstants(possibleInstants, timeZone, dateTime, disambiguation). - return disambiguate_possible_instants(vm, possible_instants, time_zone_record, date_time, disambiguation); -} - -// 11.6.12 DisambiguatePossibleInstants ( possibleInstants, timeZone, dateTime, disambiguation ), https://tc39.es/proposal-temporal/#sec-temporal-disambiguatepossibleinstants -ThrowCompletionOr> disambiguate_possible_instants(VM& vm, GC::MarkedVector> const& possible_instants, TimeZoneMethods const& time_zone_record, PlainDateTime& date_time, StringView disambiguation) -{ - // 1. Assert: TimeZoneMethodsRecordHasLookedUp(timeZoneRec, GET-POSSIBLE-INSTANTS-FOR) is true. - VERIFY(time_zone_methods_record_has_looked_up(time_zone_record, TimeZoneMethod::GetPossibleInstantsFor)); - - // 2. Assert: If possibleInstants is empty, and disambiguation is not "reject", TimeZoneMethodsRecordHasLookedUp(timeZoneRec, GET-OFFSET-NANOSECONDS-FOR) is true. - if (possible_instants.is_empty() && disambiguation != "reject"sv) - VERIFY(time_zone_methods_record_has_looked_up(time_zone_record, TimeZoneMethod::GetOffsetNanosecondsFor)); - - // 3. Let n be possibleInstants's length. - auto n = possible_instants.size(); - - // 4. If n = 1, then - if (n == 1) { - // a. Return possibleInstants[0]. - return possible_instants[0]; - } - - // 5. If n ≠ 0, then - if (n != 0) { - // a. If disambiguation is "earlier" or "compatible", then - if (disambiguation.is_one_of("earlier"sv, "compatible"sv)) { - // i. Return possibleInstants[0]. - return possible_instants[0]; - } - - // b. If disambiguation is "later", then - if (disambiguation == "later"sv) { - // i. Return possibleInstants[n - 1]. - return possible_instants[n - 1]; - } - - // c. Assert: disambiguation is "reject". - VERIFY(disambiguation == "reject"sv); - - // d. Throw a RangeError exception. - return vm.throw_completion(ErrorType::TemporalDisambiguatePossibleInstantsRejectMoreThanOne); - } - - // 6. Assert: n = 0. - VERIFY(n == 0); - - // 7. If disambiguation is "reject", then - if (disambiguation == "reject"sv) { - // a. Throw a RangeError exception. - return vm.throw_completion(ErrorType::TemporalDisambiguatePossibleInstantsRejectZero); - } - - // 8. Let epochNanoseconds be GetUTCEpochNanoseconds(dateTime.[[ISOYear]], dateTime.[[ISOMonth]], dateTime.[[ISODay]], dateTime.[[ISOHour]], dateTime.[[ISOMinute]], dateTime.[[ISOSecond]], dateTime.[[ISOMillisecond]], dateTime.[[ISOMicrosecond]], dateTime.[[ISONanosecond]]). - auto epoch_nanoseconds = get_utc_epoch_nanoseconds(date_time.iso_year(), date_time.iso_month(), date_time.iso_day(), date_time.iso_hour(), date_time.iso_minute(), date_time.iso_second(), date_time.iso_millisecond(), date_time.iso_microsecond(), date_time.iso_nanosecond()); - - // 9. Let dayBeforeNs be epochNanoseconds - ℤ(nsPerDay). - auto day_before_ns = BigInt::create(vm, epoch_nanoseconds.minus(ns_per_day_bigint)); - - // 10. If IsValidEpochNanoseconds(dayBeforeNs) is false, throw a RangeError exception. - if (!is_valid_epoch_nanoseconds(day_before_ns)) - return vm.throw_completion(ErrorType::TemporalInvalidEpochNanoseconds); - - // 11. Let dayBefore be ! CreateTemporalInstant(dayBeforeNs). - auto* day_before = MUST(create_temporal_instant(vm, day_before_ns)); - - // 12. Let dayAfterNs be epochNanoseconds + ℤ(nsPerDay). - auto day_after_ns = BigInt::create(vm, epoch_nanoseconds.plus(ns_per_day_bigint)); - - // 13. If IsValidEpochNanoseconds(dayAfterNs) is false, throw a RangeError exception. - if (!is_valid_epoch_nanoseconds(day_after_ns)) - return vm.throw_completion(ErrorType::TemporalInvalidEpochNanoseconds); - - // 14. Let dayAfter be ! CreateTemporalInstant(dayAfterNs). - auto* day_after = MUST(create_temporal_instant(vm, day_after_ns)); - - // 15. Let offsetBefore be ? GetOffsetNanosecondsFor(timeZoneRec, dayBefore). - auto offset_before = TRY(get_offset_nanoseconds_for(vm, time_zone_record, *day_before)); - - // 16. Let offsetAfter be ? GetOffsetNanosecondsFor(timeZoneRec, dayAfter). - auto offset_after = TRY(get_offset_nanoseconds_for(vm, time_zone_record, *day_after)); - - // 17. Let nanoseconds be offsetAfter - offsetBefore. - auto nanoseconds = offset_after - offset_before; - - // 18. If disambiguation is "earlier", then - if (disambiguation == "earlier"sv) { - // a. Let earlier be ? AddDateTime(dateTime.[[ISOYear]], dateTime.[[ISOMonth]], dateTime.[[ISODay]], dateTime.[[ISOHour]], dateTime.[[ISOMinute]], dateTime.[[ISOSecond]], dateTime.[[ISOMillisecond]], dateTime.[[ISOMicrosecond]], dateTime.[[ISONanosecond]], dateTime.[[Calendar]], 0, 0, 0, 0, 0, 0, 0, 0, 0, -nanoseconds, undefined). - auto earlier = TRY(add_date_time(vm, date_time.iso_year(), date_time.iso_month(), date_time.iso_day(), date_time.iso_hour(), date_time.iso_minute(), date_time.iso_second(), date_time.iso_millisecond(), date_time.iso_microsecond(), date_time.iso_nanosecond(), date_time.calendar(), 0, 0, 0, 0, 0, 0, 0, 0, 0, -nanoseconds, nullptr)); - - // b. Let earlierDateTime be ! CreateTemporalDateTime(earlier.[[Year]], earlier.[[Month]], earlier.[[Day]], earlier.[[Hour]], earlier.[[Minute]], earlier.[[Second]], earlier.[[Millisecond]], earlier.[[Microsecond]], earlier.[[Nanosecond]], dateTime.[[Calendar]]). - auto* earlier_date_time = MUST(create_temporal_date_time(vm, earlier.year, earlier.month, earlier.day, earlier.hour, earlier.minute, earlier.second, earlier.millisecond, earlier.microsecond, earlier.nanosecond, date_time.calendar())); - - // c. Set possibleInstants to ? GetPossibleInstantsFor(timeZone, earlierDateTime). - auto possible_instants_ = TRY(get_possible_instants_for(vm, time_zone_record, *earlier_date_time)); - - // d. If possibleInstants is empty, throw a RangeError exception. - if (possible_instants_.is_empty()) - return vm.throw_completion(ErrorType::TemporalDisambiguatePossibleInstantsEarlierZero); - - // e. Return possibleInstants[0]. - return possible_instants_[0]; - } - - // 19. Assert: disambiguation is "compatible" or "later". - VERIFY(disambiguation.is_one_of("compatible"sv, "later"sv)); - - // 20. Let later be ? AddDateTime(dateTime.[[ISOYear]], dateTime.[[ISOMonth]], dateTime.[[ISODay]], dateTime.[[ISOHour]], dateTime.[[ISOMinute]], dateTime.[[ISOSecond]], dateTime.[[ISOMillisecond]], dateTime.[[ISOMicrosecond]], dateTime.[[ISONanosecond]], dateTime.[[Calendar]], 0, 0, 0, 0, 0, 0, 0, 0, 0, nanoseconds, undefined). - auto later = TRY(add_date_time(vm, date_time.iso_year(), date_time.iso_month(), date_time.iso_day(), date_time.iso_hour(), date_time.iso_minute(), date_time.iso_second(), date_time.iso_millisecond(), date_time.iso_microsecond(), date_time.iso_nanosecond(), date_time.calendar(), 0, 0, 0, 0, 0, 0, 0, 0, 0, nanoseconds, nullptr)); - - // 21. Let laterDateTime be ! CreateTemporalDateTime(later.[[Year]], later.[[Month]], later.[[Day]], later.[[Hour]], later.[[Minute]], later.[[Second]], later.[[Millisecond]], later.[[Microsecond]], later.[[Nanosecond]], dateTime.[[Calendar]]). - auto* later_date_time = MUST(create_temporal_date_time(vm, later.year, later.month, later.day, later.hour, later.minute, later.second, later.millisecond, later.microsecond, later.nanosecond, date_time.calendar())); - - // 22. Set possibleInstants to ? GetPossibleInstantsFor(timeZone, laterDateTime). - auto possible_instants_ = TRY(get_possible_instants_for(vm, time_zone_record, *later_date_time)); - - // 23. Set n to possibleInstants's length. - n = possible_instants_.size(); - - // 24. If n = 0, throw a RangeError exception. - if (n == 0) - return vm.throw_completion(ErrorType::TemporalDisambiguatePossibleInstantsZero); - - // 25. Return possibleInstants[n - 1]. - return possible_instants_[n - 1]; -} - -// 11.5.24 GetPossibleInstantsFor ( timeZoneRec, dateTime ), https://tc39.es/proposal-temporal/#sec-temporal-getpossibleinstantsfor -ThrowCompletionOr>> get_possible_instants_for(VM& vm, TimeZoneMethods const& time_zone_record, PlainDateTime const& date_time) -{ - // 1. Let possibleInstants be ? TimeZoneMethodsRecordCall(timeZoneRec, GET-POSSIBLE-INSTANTS-FOR, « dateTime »). - auto possible_instants = TRY(time_zone_methods_record_call(vm, time_zone_record, TimeZoneMethod::GetPossibleInstantsFor, { { &date_time } })); - - // 2. If TimeZoneMethodsRecordIsBuiltin(timeZoneRec), return ! CreateListFromArrayLike(possibleInstants, « Object »). - if (time_zone_methods_record_is_builtin(time_zone_record)) { - auto list = GC::MarkedVector> { vm.heap() }; - - (void)MUST(create_list_from_array_like(vm, possible_instants, [&list](auto value) -> ThrowCompletionOr { - list.append(verify_cast(value.as_object())); - return {}; - })); - - return list; - } - - // 3. Let iteratorRecord be ? GetIterator(possibleInstants, SYNC). - auto iterator = TRY(get_iterator(vm, possible_instants, IteratorHint::Sync)); - - // 4. Let list be a new empty List. - auto list = GC::MarkedVector> { vm.heap() }; - - // 5. Repeat, - while (true) { - // a. Let value be ? IteratorStepValue(iteratorRecord). - auto value = TRY(iterator_step_value(vm, iterator)); - - // b. If value is DONE, then - if (!value.has_value()) { - // i. Let numResults be list's length. - auto num_results = list.size(); - - // ii. If numResults > 1, then - if (num_results > 1) { - // 1. Let epochNs be a new empty List. - // 2. For each value instant in list, do - // a. Append instant.[[EpochNanoseconds]] to the end of the List epochNs. - // FIXME: spec bug? shouldn't [[EpochNanoseconds]] just be called [[Nanoseconds]]? - // 3. Let min be the least element of the List epochNs. - // 4. Let max be the greatest element of the List epochNs. - - auto const* min = &list.first()->nanoseconds().big_integer(); - auto const* max = &list.first()->nanoseconds().big_integer(); - - for (auto it = list.begin() + 1; it != list.end(); ++it) { - auto const& value = it->ptr()->nanoseconds().big_integer(); - - if (value < *min) - min = &value; - else if (value > *max) - max = &value; - } - - // 5. If abs(ℝ(max - min)) > nsPerDay, throw a RangeError exception. - if (max->minus(*min).unsigned_value() > ns_per_day_bigint.unsigned_value()) - return vm.throw_completion(ErrorType::TemporalInvalidDuration); - } - - // iii. Return list. - return list; - } - - // c. If value is not an Object or value does not have an [[InitializedTemporalInstant]] internal slot, then - if (!value->is_object() || !is(value->as_object())) { - // i. Let completion be ThrowCompletion(a newly created TypeError object). - auto completion = vm.throw_completion(ErrorType::NotAnObjectOfType, "Temporal.Instant"); - - // ii. Return ? IteratorClose(iteratorRecord, completion). - return iterator_close(vm, iterator, move(completion)); - } - - // d. Append value to the end of the List list. - list.append(verify_cast(value->as_object())); - } - - // 7. Return list. - return { move(list) }; -} - -// 11.6.14 TimeZoneEquals ( one, two ), https://tc39.es/proposal-temporal/#sec-temporal-timezoneequals -ThrowCompletionOr time_zone_equals(VM& vm, Object& one, Object& two) -{ - // 1. If one and two are the same Object value, return true. - if (&one == &two) - return true; - - // 2. Let timeZoneOne be ? ToString(one). - auto time_zone_one = TRY(Value(&one).to_string(vm)); - - // 3. Let timeZoneTwo be ? ToString(two). - auto time_zone_two = TRY(Value(&two).to_string(vm)); - - // 4. If timeZoneOne is timeZoneTwo, return true. - if (time_zone_one == time_zone_two) - return true; - - // 5. Return false. - return false; -} - -} diff --git a/Libraries/LibJS/Runtime/Temporal/TimeZone.h b/Libraries/LibJS/Runtime/Temporal/TimeZone.h deleted file mode 100644 index 3d781f70f4d..00000000000 --- a/Libraries/LibJS/Runtime/Temporal/TimeZone.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2021-2023, Linus Groh - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include -#include -#include -#include - -namespace JS::Temporal { - -class TimeZone final : public Object { - JS_OBJECT(TimeZone, Object); - GC_DECLARE_ALLOCATOR(TimeZone); - -public: - // Needs to store values in the range -8.64 * 10^13 to 8.64 * 10^13 - using OffsetType = double; - - virtual ~TimeZone() override = default; - - [[nodiscard]] String const& identifier() const { return m_identifier; } - [[nodiscard]] Optional const& offset_nanoseconds() const { return m_offset_nanoseconds; } - - void set_identifier(String identifier) { m_identifier = move(identifier); } - void set_offset_nanoseconds(OffsetType offset_nanoseconds) { m_offset_nanoseconds = offset_nanoseconds; } - -private: - explicit TimeZone(Object& prototype); - - // 11.5 Properties of Temporal.TimeZone Instances, https://tc39.es/proposal-temporal/#sec-properties-of-temporal-timezone-instances - String m_identifier; // [[Identifier]] - Optional m_offset_nanoseconds; // [[OffsetNanoseconds]] -}; - -bool is_available_time_zone_name(StringView time_zone); -ThrowCompletionOr canonicalize_time_zone_name(VM&, StringView time_zone); -ThrowCompletionOr create_temporal_time_zone(VM&, String identifier, FunctionObject const* new_target = nullptr); -ISODateTime get_iso_parts_from_epoch(VM&, Crypto::SignedBigInteger const& epoch_nanoseconds); -BigInt* get_named_time_zone_next_transition(VM&, StringView time_zone_identifier, BigInt const& epoch_nanoseconds); -BigInt* get_named_time_zone_previous_transition(VM&, StringView time_zone_identifier, BigInt const& epoch_nanoseconds); -ThrowCompletionOr format_time_zone_offset_string(VM&, double offset_nanoseconds); -ThrowCompletionOr format_iso_time_zone_offset_string(VM&, double offset_nanoseconds); -ThrowCompletionOr to_temporal_time_zone(VM&, Value temporal_time_zone_like); -ThrowCompletionOr get_offset_nanoseconds_for(VM& vm, TimeZoneMethods const& time_zone_record, Instant const& instant); -ThrowCompletionOr builtin_time_zone_get_offset_string_for(VM&, Value time_zone, Instant&); -ThrowCompletionOr builtin_time_zone_get_plain_date_time_for(VM&, Value time_zone, Instant&, Object& calendar); -ThrowCompletionOr> builtin_time_zone_get_instant_for(VM&, Value time_zone, PlainDateTime&, StringView disambiguation); -ThrowCompletionOr> disambiguate_possible_instants(VM&, GC::MarkedVector> const& possible_instants, TimeZoneMethods const&, PlainDateTime&, StringView disambiguation); -ThrowCompletionOr>> get_possible_instants_for(VM&, TimeZoneMethods const&, PlainDateTime const&); -ThrowCompletionOr time_zone_equals(VM&, Object& one, Object& two); - -} diff --git a/Libraries/LibJS/Runtime/Temporal/TimeZoneConstructor.cpp b/Libraries/LibJS/Runtime/Temporal/TimeZoneConstructor.cpp deleted file mode 100644 index df12a9a7681..00000000000 --- a/Libraries/LibJS/Runtime/Temporal/TimeZoneConstructor.cpp +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2021-2023, Linus Groh - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include -#include -#include -#include - -namespace JS::Temporal { - -GC_DEFINE_ALLOCATOR(TimeZoneConstructor); - -// 11.2 The Temporal.TimeZone Constructor, https://tc39.es/proposal-temporal/#sec-temporal-timezone-constructor -TimeZoneConstructor::TimeZoneConstructor(Realm& realm) - : NativeFunction(realm.vm().names.TimeZone.as_string(), realm.intrinsics().function_prototype()) -{ -} - -void TimeZoneConstructor::initialize(Realm& realm) -{ - Base::initialize(realm); - - auto& vm = this->vm(); - - // 11.3.1 Temporal.TimeZone.prototype, https://tc39.es/proposal-temporal/#sec-temporal.timezone.prototype - define_direct_property(vm.names.prototype, realm.intrinsics().temporal_time_zone_prototype(), 0); - - u8 attr = Attribute::Writable | Attribute::Configurable; - define_native_function(realm, vm.names.from, from, 1, attr); - - define_direct_property(vm.names.length, Value(1), Attribute::Configurable); -} - -// 11.2.1 Temporal.TimeZone ( identifier ), https://tc39.es/proposal-temporal/#sec-temporal.timezone -ThrowCompletionOr TimeZoneConstructor::call() -{ - auto& vm = this->vm(); - - // 1. If NewTarget is undefined, then - // a. Throw a TypeError exception. - return vm.throw_completion(ErrorType::ConstructorWithoutNew, "Temporal.TimeZone"); -} - -// 11.2.1 Temporal.TimeZone ( identifier ), https://tc39.es/proposal-temporal/#sec-temporal.timezone -ThrowCompletionOr> TimeZoneConstructor::construct(FunctionObject& new_target) -{ - auto& vm = this->vm(); - - // 2. Set identifier to ? ToString(identifier). - auto identifier = TRY(vm.argument(0).to_string(vm)); - - // 3. If IsTimeZoneOffsetString(identifier) is false, then - if (!is_time_zone_offset_string(identifier)) { - // a. If IsAvailableTimeZoneName(identifier) is false, then - if (!is_available_time_zone_name(identifier)) { - // i. Throw a RangeError exception. - return vm.throw_completion(ErrorType::TemporalInvalidTimeZoneName, identifier); - } - - // b. Set identifier to ! CanonicalizeTimeZoneName(identifier). - identifier = MUST_OR_THROW_OOM(canonicalize_time_zone_name(vm, identifier)); - } - - // 4. Return ? CreateTemporalTimeZone(identifier, NewTarget). - return *TRY(create_temporal_time_zone(vm, move(identifier), &new_target)); -} - -// 11.3.2 Temporal.TimeZone.from ( item ), https://tc39.es/proposal-temporal/#sec-temporal.timezone.from -JS_DEFINE_NATIVE_FUNCTION(TimeZoneConstructor::from) -{ - auto item = vm.argument(0); - - // 1. Return ? ToTemporalTimeZone(item). - return TRY(to_temporal_time_zone(vm, item)); -} - -} diff --git a/Libraries/LibJS/Runtime/Temporal/TimeZoneConstructor.h b/Libraries/LibJS/Runtime/Temporal/TimeZoneConstructor.h deleted file mode 100644 index 05305368062..00000000000 --- a/Libraries/LibJS/Runtime/Temporal/TimeZoneConstructor.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2021-2022, Linus Groh - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include - -namespace JS::Temporal { - -class TimeZoneConstructor final : public NativeFunction { - JS_OBJECT(TimeZoneConstructor, NativeFunction); - GC_DECLARE_ALLOCATOR(TimeZoneConstructor); - -public: - virtual void initialize(Realm&) override; - virtual ~TimeZoneConstructor() override = default; - - virtual ThrowCompletionOr call() override; - virtual ThrowCompletionOr> construct(FunctionObject& new_target) override; - -private: - explicit TimeZoneConstructor(Realm&); - - virtual bool has_constructor() const override { return true; } - - JS_DECLARE_NATIVE_FUNCTION(from); -}; - -} diff --git a/Libraries/LibJS/Runtime/Temporal/TimeZoneMethods.cpp b/Libraries/LibJS/Runtime/Temporal/TimeZoneMethods.cpp deleted file mode 100644 index 85e60c15c2e..00000000000 --- a/Libraries/LibJS/Runtime/Temporal/TimeZoneMethods.cpp +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (c) 2024, Shannon Booth - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include -#include -#include - -namespace JS::Temporal { - -// 11.5.2 CreateTimeZoneMethodsRecord ( timeZone, methods ), https://tc39.es/proposal-temporal/#sec-temporal-createtimezonemethodsrecord -ThrowCompletionOr create_time_zone_methods_record(VM& vm, Variant> time_zone, ReadonlySpan methods) -{ - // 1. Let record be the Time Zone Methods Record { [[Receiver]]: timeZone, [[GetOffsetNanosecondsFor]]: undefined, [[GetPossibleInstantsFor]]: undefined }. - TimeZoneMethods record { - .receiver = move(time_zone), - .get_offset_nanoseconds_for = nullptr, - .get_possible_instants_for = nullptr, - }; - - // 2. For each element methodName in methods, do - for (TimeZoneMethod method_name : methods) { - // a. Perform ? TimeZoneMethodsRecordLookup(record, methodName). - TRY(time_zone_methods_record_lookup(vm, record, method_name)); - } - - // 3. Return record. - return record; -} - -// 11.5.3 TimeZoneMethodsRecordLookup ( timeZoneRec, methodName ), https://tc39.es/proposal-temporal/#sec-temporal-timezonemethodsrecordlookup -ThrowCompletionOr time_zone_methods_record_lookup(VM& vm, TimeZoneMethods& time_zone_record, TimeZoneMethod method_name) -{ - auto& realm = *vm.current_realm(); - - // 1. Assert: TimeZoneMethodsRecordHasLookedUp(timeZoneRec, methodName) is false. - // 2. If methodName is GET-OFFSET-NANOSECONDS-FOR, then - // a. If timeZoneRec.[[Receiver]] is a String, then - // i. Set timeZoneRec.[[GetOffsetNanosecondsFor]] to %Temporal.TimeZone.prototype.getOffsetNanosecondsFor%. - // b. Else, - // i. Set timeZoneRec.[[GetOffsetNanosecondsFor]] to ? GetMethod(timeZoneRec.[[Receiver]], "getOffsetNanosecondsFor"). - // ii. If timeZoneRec.[[GetOffsetNanosecondsFor]] is undefined, throw a TypeError exception. - // 3. Else if methodName is GET-POSSIBLE-INSTANTS-FOR, then - // a. If timeZoneRec.[[Receiver]] is a String, then - // i. Set timeZoneRec.[[GetPossibleInstantsFor]] to %Temporal.TimeZone.prototype.getPossibleInstantsFor%. - // b. Else, - // i. Set timeZoneRec.[[GetPossibleInstantsFor]] to ? GetMethod(timeZoneRec.[[Receiver]], "getPossibleInstantsFor"). - // ii. If timeZoneRec.[[GetPossibleInstantsFor]] is undefined, throw a TypeError exception. - switch (method_name) { -#define __JS_ENUMERATE(PascalName, camelName, snake_name) \ - case TimeZoneMethod::PascalName: { \ - VERIFY(!time_zone_record.snake_name); \ - if (time_zone_record.receiver.has()) { \ - const auto& time_zone_prototype = *realm.intrinsics().temporal_time_zone_prototype(); \ - time_zone_record.snake_name = time_zone_prototype.get_without_side_effects(vm.names.camelName).as_function(); \ - } else { \ - Value time_zone { time_zone_record.receiver.get>() }; \ - time_zone_record.snake_name = TRY(time_zone.get_method(vm, vm.names.camelName)); \ - if (!time_zone_record.snake_name) \ - return vm.throw_completion(ErrorType::IsUndefined, #camelName##sv); \ - } \ - break; \ - } - JS_ENUMERATE_TIME_ZONE_METHODS -#undef __JS_ENUMERATE - } - // 4. Return UNUSED. - return {}; -} - -// 11.5.4 TimeZoneMethodsRecordHasLookedUp ( timeZoneRec, methodName ), https://tc39.es/proposal-temporal/#sec-temporal-timezonemethodsrecordhaslookedup -bool time_zone_methods_record_has_looked_up(TimeZoneMethods const& time_zone_record, TimeZoneMethod method_name) -{ - // 1. If methodName is GET-OFFSET-NANOSECONDS-FOR, then - // a. Let method be timeZoneRec.[[GetOffsetNanosecondsFor]]. - // 2. Else if methodName is GET-POSSIBLE-INSTANTS-FOR, then - // a. Let method be timeZoneRec.[[GetPossibleInstantsFor]]. - // 3. If method is undefined, return false. - // 4. Return true. - switch (method_name) { -#define __JS_ENUMERATE(PascalName, camelName, snake_name) \ - case TimeZoneMethod::PascalName: { \ - return time_zone_record.snake_name != nullptr; \ - } - JS_ENUMERATE_TIME_ZONE_METHODS -#undef __JS_ENUMERATE - } - VERIFY_NOT_REACHED(); -} - -// 11.5.5 TimeZoneMethodsRecordIsBuiltin ( timeZoneRec ), https://tc39.es/proposal-temporal/#sec-temporal-timezonemethodsrecordisbuiltin -bool time_zone_methods_record_is_builtin(TimeZoneMethods const& time_zone_record) -{ - // 1. If timeZoneRec.[[Receiver]] is a String, return true. - if (time_zone_record.receiver.has()) - return true; - - // 2. Return false. - return false; -} - -// 11.5.6 TimeZoneMethodsRecordCall ( timeZoneRec, methodName, arguments ), https://tc39.es/proposal-temporal/#sec-temporal-timezonemethodsrecordcall -ThrowCompletionOr time_zone_methods_record_call(VM& vm, TimeZoneMethods const& time_zone_record, TimeZoneMethod method_name, ReadonlySpan arguments) -{ - // 1. Assert: TimeZoneMethodsRecordHasLookedUp(timeZoneRec, methodName) is true. - VERIFY(time_zone_methods_record_has_looked_up(time_zone_record, method_name)); - - // 2. Let receiver be timeZoneRec.[[Receiver]]. - // 3. If TimeZoneMethodsRecordIsBuiltin(timeZoneRec) is true, then - // a. Set receiver to ! CreateTemporalTimeZone(timeZoneRec.[[Receiver]]). - GC::Ptr receiver; - if (time_zone_methods_record_is_builtin(time_zone_record)) - receiver = MUST(create_temporal_time_zone(vm, time_zone_record.receiver.get())); - else - receiver = time_zone_record.receiver.get>(); - - // 4. If methodName is GET-OFFSET-NANOSECONDS-FOR, then - // a. Return ? Call(timeZoneRec.[[GetOffsetNanosecondsFor]], receiver, arguments). - // 5. If methodName is GET-POSSIBLE-INSTANTS-FOR, then - // a. Return ? Call(timeZoneRec.[[GetPossibleInstantsFor]], receiver, arguments). - switch (method_name) { -#define __JS_ENUMERATE(PascalName, camelName, snake_name) \ - case TimeZoneMethod::PascalName: { \ - return TRY(call(vm, time_zone_record.snake_name, receiver, arguments)); \ - } - JS_ENUMERATE_TIME_ZONE_METHODS -#undef __JS_ENUMERATE - } - VERIFY_NOT_REACHED(); -} - -} diff --git a/Libraries/LibJS/Runtime/Temporal/TimeZoneMethods.h b/Libraries/LibJS/Runtime/Temporal/TimeZoneMethods.h deleted file mode 100644 index b0c00487086..00000000000 --- a/Libraries/LibJS/Runtime/Temporal/TimeZoneMethods.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2024, Shannon Booth - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include -#include -#include - -namespace JS::Temporal { - -// 11.5.1 Time Zone Methods Records, https://tc39.es/proposal-temporal/#sec-temporal-time-zone-methods-records -struct TimeZoneMethods { - // The time zone object, or a string indicating a built-in time zone. - Variant> receiver; // [[Reciever]] - - // The time zone's getOffsetNanosecondsFor method. For a built-in time zone this is always %Temporal.TimeZone.prototype.getOffsetNanosecondsFor%. - GC::Ptr get_offset_nanoseconds_for; // [[GetOffsetNanosecondsFor]] - - // The time zone's getPossibleInstantsFor method. For a built-in time zone this is always %Temporal.TimeZone.prototype.getPossibleInstantsFor%. - GC::Ptr get_possible_instants_for; // [[GetPossibleInstantsFor]] -}; - -#define JS_ENUMERATE_TIME_ZONE_METHODS \ - __JS_ENUMERATE(GetOffsetNanosecondsFor, getOffsetNanosecondsFor, get_offset_nanoseconds_for) \ - __JS_ENUMERATE(GetPossibleInstantsFor, getPossibleInstantsFor, get_possible_instants_for) - -enum class TimeZoneMethod { -#define __JS_ENUMERATE(PascalName, camelName, snake_name) \ - PascalName, - JS_ENUMERATE_TIME_ZONE_METHODS -#undef __JS_ENUMERATE -}; - -ThrowCompletionOr time_zone_methods_record_lookup(VM&, TimeZoneMethods&, TimeZoneMethod); -ThrowCompletionOr create_time_zone_methods_record(VM&, Variant> time_zone, ReadonlySpan); -bool time_zone_methods_record_has_looked_up(TimeZoneMethods const&, TimeZoneMethod); -bool time_zone_methods_record_is_builtin(TimeZoneMethods const&); -ThrowCompletionOr time_zone_methods_record_call(VM&, TimeZoneMethods const&, TimeZoneMethod, ReadonlySpan arguments); - -} diff --git a/Libraries/LibJS/Runtime/Temporal/TimeZonePrototype.cpp b/Libraries/LibJS/Runtime/Temporal/TimeZonePrototype.cpp deleted file mode 100644 index 680527eedff..00000000000 --- a/Libraries/LibJS/Runtime/Temporal/TimeZonePrototype.cpp +++ /dev/null @@ -1,253 +0,0 @@ -/* - * Copyright (c) 2021-2023, Linus Groh - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace JS::Temporal { - -GC_DEFINE_ALLOCATOR(TimeZonePrototype); - -// 11.4 Properties of the Temporal.TimeZone Prototype Object, https://tc39.es/proposal-temporal/#sec-properties-of-the-temporal-timezone-prototype-object -TimeZonePrototype::TimeZonePrototype(Realm& realm) - : PrototypeObject(realm.intrinsics().object_prototype()) -{ -} - -void TimeZonePrototype::initialize(Realm& realm) -{ - Base::initialize(realm); - - auto& vm = this->vm(); - - u8 attr = Attribute::Writable | Attribute::Configurable; - define_native_accessor(realm, vm.names.id, id_getter, {}, Attribute::Configurable); - define_native_function(realm, vm.names.getOffsetNanosecondsFor, get_offset_nanoseconds_for, 1, attr); - define_native_function(realm, vm.names.getOffsetStringFor, get_offset_string_for, 1, attr); - define_native_function(realm, vm.names.getPlainDateTimeFor, get_plain_date_time_for, 1, attr); - define_native_function(realm, vm.names.getInstantFor, get_instant_for, 1, attr); - define_native_function(realm, vm.names.getPossibleInstantsFor, get_possible_instants_for, 1, attr); - define_native_function(realm, vm.names.getNextTransition, get_next_transition, 1, attr); - define_native_function(realm, vm.names.getPreviousTransition, get_previous_transition, 1, attr); - define_native_function(realm, vm.names.toString, to_string, 0, attr); - define_native_function(realm, vm.names.toJSON, to_json, 0, attr); - - // 11.4.2 Temporal.TimeZone.prototype[ @@toStringTag ], https://tc39.es/proposal-temporal/#sec-temporal.timezone.prototype-@@tostringtag - define_direct_property(vm.well_known_symbol_to_string_tag(), PrimitiveString::create(vm, "Temporal.TimeZone"_string), Attribute::Configurable); -} - -// 11.4.3 get Temporal.TimeZone.prototype.id, https://tc39.es/proposal-temporal/#sec-get-temporal.timezone.prototype.id -JS_DEFINE_NATIVE_FUNCTION(TimeZonePrototype::id_getter) -{ - // 1. Let timeZone be the this value. - // 2. Perform ? RequireInternalSlot(timeZone, [[InitializedTemporalTimeZone]]). - auto time_zone = TRY(typed_this_object(vm)); - - // 3. Return timeZone.[[Identifier]]. - return PrimitiveString::create(vm, time_zone->identifier()); -} - -// 11.4.4 Temporal.TimeZone.prototype.getOffsetNanosecondsFor ( instant ), https://tc39.es/proposal-temporal/#sec-temporal.timezone.prototype.getoffsetnanosecondsfor -JS_DEFINE_NATIVE_FUNCTION(TimeZonePrototype::get_offset_nanoseconds_for) -{ - // 1. Let timeZone be the this value. - // 2. Perform ? RequireInternalSlot(timeZone, [[InitializedTemporalTimeZone]]). - auto time_zone = TRY(typed_this_object(vm)); - - // 3. Set instant to ? ToTemporalInstant(instant). - auto* instant = TRY(to_temporal_instant(vm, vm.argument(0))); - - // 4. If timeZone.[[OffsetNanoseconds]] is not undefined, return 𝔽(timeZone.[[OffsetNanoseconds]]). - if (time_zone->offset_nanoseconds().has_value()) - return Value(*time_zone->offset_nanoseconds()); - - // 5. Return 𝔽(GetNamedTimeZoneOffsetNanoseconds(timeZone.[[Identifier]], instant.[[Nanoseconds]])). - auto offset = get_named_time_zone_offset_nanoseconds(time_zone->identifier(), instant->nanoseconds().big_integer()); - return Value(static_cast(offset.offset.to_nanoseconds())); -} - -// 11.4.5 Temporal.TimeZone.prototype.getOffsetStringFor ( instant ), https://tc39.es/proposal-temporal/#sec-temporal.timezone.prototype.getoffsetstringfor -JS_DEFINE_NATIVE_FUNCTION(TimeZonePrototype::get_offset_string_for) -{ - // 1. Let timeZone be the this value. - // 2. Perform ? RequireInternalSlot(timeZone, [[InitializedTemporalTimeZone]]). - auto time_zone = TRY(typed_this_object(vm)); - - // 3. Set instant to ? ToTemporalInstant(instant). - auto* instant = TRY(to_temporal_instant(vm, vm.argument(0))); - - // 4. Return ? BuiltinTimeZoneGetOffsetStringFor(timeZone, instant). - auto offset_string = TRY(builtin_time_zone_get_offset_string_for(vm, time_zone, *instant)); - return PrimitiveString::create(vm, move(offset_string)); -} - -// 11.4.6 Temporal.TimeZone.prototype.getPlainDateTimeFor ( instant [ , calendarLike ] ), https://tc39.es/proposal-temporal/#sec-temporal.timezone.prototype.getplaindatetimefor -JS_DEFINE_NATIVE_FUNCTION(TimeZonePrototype::get_plain_date_time_for) -{ - // 1. Let timeZone be the this value. - // 2. Perform ? RequireInternalSlot(timeZone, [[InitializedTemporalTimeZone]]). - auto time_zone = TRY(typed_this_object(vm)); - - // 3. Set instant to ? ToTemporalInstant(instant). - auto* instant = TRY(to_temporal_instant(vm, vm.argument(0))); - - // 4. Let calendar be ? ToTemporalCalendarWithISODefault(calendarLike). - auto* calendar = TRY(to_temporal_calendar_with_iso_default(vm, vm.argument(1))); - - // 5. Return ? BuiltinTimeZoneGetPlainDateTimeFor(timeZone, instant, calendar). - return TRY(builtin_time_zone_get_plain_date_time_for(vm, time_zone, *instant, *calendar)); -} - -// 11.4.7 Temporal.TimeZone.prototype.getInstantFor ( dateTime [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal.timezone.prototype.getinstantfor -JS_DEFINE_NATIVE_FUNCTION(TimeZonePrototype::get_instant_for) -{ - // 1. Let timeZone be the this value. - // 2. Perform ? RequireInternalSlot(timeZone, [[InitializedTemporalTimeZone]]). - auto time_zone = TRY(typed_this_object(vm)); - - // 3. Set dateTime to ? ToTemporalDateTime(dateTime). - auto* date_time = TRY(to_temporal_date_time(vm, vm.argument(0))); - - // 4. Set options to ? GetOptionsObject(options). - auto* options = TRY(get_options_object(vm, vm.argument(1))); - - // 5. Let disambiguation be ? ToTemporalDisambiguation(options). - auto disambiguation = TRY(to_temporal_disambiguation(vm, options)); - - // 6. Return ? BuiltinTimeZoneGetInstantFor(timeZone, dateTime, disambiguation). - return TRY(builtin_time_zone_get_instant_for(vm, time_zone, *date_time, disambiguation)); -} - -// 11.4.8 Temporal.TimeZone.prototype.getPossibleInstantsFor ( dateTime ), https://tc39.es/proposal-temporal/#sec-temporal.timezone.prototype.getpossibleinstantsfor -JS_DEFINE_NATIVE_FUNCTION(TimeZonePrototype::get_possible_instants_for) -{ - auto& realm = *vm.current_realm(); - - // 1. Let timeZone be the this value. - // 2. Perform ? RequireInternalSlot(timeZone, [[InitializedTemporalTimezone]]). - auto time_zone = TRY(typed_this_object(vm)); - - // 3. Set dateTime to ? ToTemporalDateTime(dateTime). - auto* date_time = TRY(to_temporal_date_time(vm, vm.argument(0))); - - Vector possible_epoch_nanoseconds; - - // 4. If timeZone.[[OffsetNanoseconds]] is not undefined, then - if (time_zone->offset_nanoseconds().has_value()) { - // a. Let epochNanoseconds be GetUTCEpochNanoseconds(dateTime.[[ISOYear]], dateTime.[[ISOMonth]], dateTime.[[ISODay]], dateTime.[[ISOHour]], dateTime.[[ISOMinute]], dateTime.[[ISOSecond]], dateTime.[[ISOMillisecond]], dateTime.[[ISOMicrosecond]], dateTime.[[ISONanosecond]]). - auto epoch_nanoseconds = get_utc_epoch_nanoseconds(date_time->iso_year(), date_time->iso_month(), date_time->iso_day(), date_time->iso_hour(), date_time->iso_minute(), date_time->iso_second(), date_time->iso_millisecond(), date_time->iso_microsecond(), date_time->iso_nanosecond()); - - // b. Let possibleEpochNanoseconds be « epochNanoseconds - ℤ(timeZone.[[OffsetNanoseconds]]) ». - possible_epoch_nanoseconds.append(epoch_nanoseconds.minus(Crypto::SignedBigInteger { *time_zone->offset_nanoseconds() })); - } - // 5. Else, - else { - // a. Let possibleEpochNanoseconds be GetNamedTimeZoneEpochNanoseconds(timeZone.[[Identifier]], dateTime.[[ISOYear]], dateTime.[[ISOMonth]], dateTime.[[ISODay]], dateTime.[[ISOHour]], dateTime.[[ISOMinute]], dateTime.[[ISOSecond]], dateTime.[[ISOMillisecond]], dateTime.[[ISOMicrosecond]], dateTime.[[ISONanosecond]]). - possible_epoch_nanoseconds = get_named_time_zone_epoch_nanoseconds(time_zone->identifier(), date_time->iso_year(), date_time->iso_month(), date_time->iso_day(), date_time->iso_hour(), date_time->iso_minute(), date_time->iso_second(), date_time->iso_millisecond(), date_time->iso_microsecond(), date_time->iso_nanosecond()); - } - - // 6. Let possibleInstants be a new empty List. - auto possible_instants = GC::MarkedVector { vm.heap() }; - - // 7. For each value epochNanoseconds in possibleEpochNanoseconds, do - for (auto& epoch_nanoseconds : possible_epoch_nanoseconds) { - // a. If ! IsValidEpochNanoseconds(epochNanoseconds) is false, throw a RangeError exception. - if (!is_valid_epoch_nanoseconds(epoch_nanoseconds)) - return vm.throw_completion(ErrorType::TemporalInvalidEpochNanoseconds); - - // b. Let instant be ! CreateTemporalInstant(epochNanoseconds). - auto epoch_nanoseconds_bigint = BigInt::create(vm, move(epoch_nanoseconds)); - auto* instant = MUST(create_temporal_instant(vm, epoch_nanoseconds_bigint)); - - // c. Append instant to possibleInstants. - possible_instants.append(instant); - } - - // 8. Return CreateArrayFromList(possibleInstants). - return Array::create_from(realm, possible_instants); -} - -// 11.4.9 Temporal.TimeZone.prototype.getNextTransition ( startingPoint ), https://tc39.es/proposal-temporal/#sec-temporal.timezone.prototype.getnexttransition -JS_DEFINE_NATIVE_FUNCTION(TimeZonePrototype::get_next_transition) -{ - // 1. Let timeZone be the this value. - // 2. Perform ? RequireInternalSlot(timeZone, [[InitializedTemporalTimeZone]]). - auto time_zone = TRY(typed_this_object(vm)); - - // 3. Set startingPoint to ? ToTemporalInstant(startingPoint). - auto* starting_point = TRY(to_temporal_instant(vm, vm.argument(0))); - - // 4. If timeZone.[[OffsetNanoseconds]] is not undefined, return null. - if (!time_zone->offset_nanoseconds().has_value()) - return js_null(); - - // 5. Let transition be GetNamedTimeZoneNextTransition(timeZone.[[Identifier]], startingPoint.[[Nanoseconds]]). - auto* transition = get_named_time_zone_next_transition(vm, time_zone->identifier(), starting_point->nanoseconds()); - - // 6. If transition is null, return null. - if (!transition) - return js_null(); - - // 7. Return ! CreateTemporalInstant(transition). - return MUST(create_temporal_instant(vm, *transition)); -} - -// 11.4.10 Temporal.TimeZone.prototype.getPreviousTransition ( startingPoint ), https://tc39.es/proposal-temporal/#sec-temporal.timezone.prototype.getprevioustransition -JS_DEFINE_NATIVE_FUNCTION(TimeZonePrototype::get_previous_transition) -{ - // 1. Let timeZone be the this value. - // 2. Perform ? RequireInternalSlot(timeZone, [[InitializedTemporalTimeZone]]). - auto time_zone = TRY(typed_this_object(vm)); - - // 3. Set startingPoint to ? ToTemporalInstant(startingPoint). - auto* starting_point = TRY(to_temporal_instant(vm, vm.argument(0))); - - // 4. If timeZone.[[OffsetNanoseconds]] is not undefined, return null. - if (!time_zone->offset_nanoseconds().has_value()) - return js_null(); - - // 5. Let transition be GetNamedTimeZonePreviousTransition(timeZone.[[Identifier]], startingPoint.[[Nanoseconds]]). - auto* transition = get_named_time_zone_previous_transition(vm, time_zone->identifier(), starting_point->nanoseconds()); - - // 6. If transition is null, return null. - if (!transition) - return js_null(); - - // 7. Return ! CreateTemporalInstant(transition). - return MUST(create_temporal_instant(vm, *transition)); -} - -// 11.4.11 Temporal.TimeZone.prototype.toString ( ), https://tc39.es/proposal-temporal/#sec-temporal.timezone.prototype.tostring -JS_DEFINE_NATIVE_FUNCTION(TimeZonePrototype::to_string) -{ - // 1. Let timeZone be the this value. - // 2. Perform ? RequireInternalSlot(timeZone, [[InitializedTemporalTimeZone]]). - auto time_zone = TRY(typed_this_object(vm)); - - // 3. Return timeZone.[[Identifier]]. - return PrimitiveString::create(vm, time_zone->identifier()); -} - -// 11.4.12 Temporal.TimeZone.prototype.toJSON ( ), https://tc39.es/proposal-temporal/#sec-temporal.timezone.prototype.tojson -JS_DEFINE_NATIVE_FUNCTION(TimeZonePrototype::to_json) -{ - // 1. Let timeZone be the this value. - // 2. Perform ? RequireInternalSlot(timeZone, [[InitializedTemporalTimeZone]]). - auto time_zone = TRY(typed_this_object(vm)); - - // 3. Return ? ToString(timeZone). - return PrimitiveString::create(vm, TRY(Value(time_zone).to_string(vm))); -} - -} diff --git a/Libraries/LibJS/Runtime/Temporal/TimeZonePrototype.h b/Libraries/LibJS/Runtime/Temporal/TimeZonePrototype.h deleted file mode 100644 index e994a8b986b..00000000000 --- a/Libraries/LibJS/Runtime/Temporal/TimeZonePrototype.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2021, Linus Groh - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include -#include - -namespace JS::Temporal { - -class TimeZonePrototype final : public PrototypeObject { - JS_PROTOTYPE_OBJECT(TimeZonePrototype, TimeZone, Temporal.TimeZone); - GC_DECLARE_ALLOCATOR(TimeZonePrototype); - -public: - virtual void initialize(Realm&) override; - virtual ~TimeZonePrototype() override = default; - -private: - explicit TimeZonePrototype(Realm&); - - JS_DECLARE_NATIVE_FUNCTION(id_getter); - JS_DECLARE_NATIVE_FUNCTION(get_offset_nanoseconds_for); - JS_DECLARE_NATIVE_FUNCTION(get_offset_string_for); - JS_DECLARE_NATIVE_FUNCTION(get_plain_date_time_for); - JS_DECLARE_NATIVE_FUNCTION(get_instant_for); - JS_DECLARE_NATIVE_FUNCTION(get_possible_instants_for); - JS_DECLARE_NATIVE_FUNCTION(get_next_transition); - JS_DECLARE_NATIVE_FUNCTION(get_previous_transition); - JS_DECLARE_NATIVE_FUNCTION(to_string); - JS_DECLARE_NATIVE_FUNCTION(to_json); -}; - -} diff --git a/Libraries/LibJS/Runtime/Temporal/ZonedDateTime.cpp b/Libraries/LibJS/Runtime/Temporal/ZonedDateTime.cpp deleted file mode 100644 index 533cb520035..00000000000 --- a/Libraries/LibJS/Runtime/Temporal/ZonedDateTime.cpp +++ /dev/null @@ -1,652 +0,0 @@ -/* - * Copyright (c) 2021-2023, Linus Groh - * Copyright (c) 2021-2023, Luke Wilde - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace JS::Temporal { - -GC_DEFINE_ALLOCATOR(ZonedDateTime); - -// 6 Temporal.ZonedDateTime Objects, https://tc39.es/proposal-temporal/#sec-temporal-zoneddatetime-objects -ZonedDateTime::ZonedDateTime(BigInt const& nanoseconds, Object& time_zone, Object& calendar, Object& prototype) - : Object(ConstructWithPrototypeTag::Tag, prototype) - , m_nanoseconds(nanoseconds) - , m_time_zone(time_zone) - , m_calendar(calendar) -{ -} - -void ZonedDateTime::visit_edges(Cell::Visitor& visitor) -{ - Base::visit_edges(visitor); - - visitor.visit(m_nanoseconds); - visitor.visit(m_time_zone); - visitor.visit(m_calendar); -} - -// 6.5.1 InterpretISODateTimeOffset ( year, month, day, hour, minute, second, millisecond, microsecond, nanosecond, offsetBehaviour, offsetNanoseconds, timeZone, disambiguation, offsetOption, matchBehaviour ), https://tc39.es/proposal-temporal/#sec-temporal-interpretisodatetimeoffset -ThrowCompletionOr interpret_iso_date_time_offset(VM& vm, i32 year, u8 month, u8 day, u8 hour, u8 minute, u8 second, u16 millisecond, u16 microsecond, u16 nanosecond, OffsetBehavior offset_behavior, double offset_nanoseconds, Value time_zone, StringView disambiguation, StringView offset_option, MatchBehavior match_behavior) -{ - // 1. Let calendar be ! GetISO8601Calendar(). - auto* calendar = get_iso8601_calendar(vm); - - // 2. Let dateTime be ? CreateTemporalDateTime(year, month, day, hour, minute, second, millisecond, microsecond, nanosecond, calendar). - auto* date_time = TRY(create_temporal_date_time(vm, year, month, day, hour, minute, second, millisecond, microsecond, nanosecond, *calendar)); - - // 3. If offsetBehaviour is wall or offsetOption is "ignore", then - if (offset_behavior == OffsetBehavior::Wall || offset_option == "ignore"sv) { - // a. Let instant be ? BuiltinTimeZoneGetInstantFor(timeZone, dateTime, disambiguation). - auto instant = TRY(builtin_time_zone_get_instant_for(vm, time_zone, *date_time, disambiguation)); - - // b. Return instant.[[Nanoseconds]]. - return &instant->nanoseconds(); - } - - // 4. If offsetBehaviour is exact or offsetOption is "use", then - if (offset_behavior == OffsetBehavior::Exact || offset_option == "use"sv) { - // a. Let epochNanoseconds be GetUTCEpochNanoseconds(year, month, day, hour, minute, second, millisecond, microsecond, nanosecond). - auto epoch_nanoseconds = get_utc_epoch_nanoseconds(year, month, day, hour, minute, second, millisecond, microsecond, nanosecond); - - // b. Set epochNanoseconds to epochNanoseconds - ℤ(offsetNanoseconds). - epoch_nanoseconds = epoch_nanoseconds.minus(Crypto::SignedBigInteger { offset_nanoseconds }); - - // c. If ! IsValidEpochNanoseconds(epochNanoseconds) is false, throw a RangeError exception. - if (!is_valid_epoch_nanoseconds(epoch_nanoseconds)) - return vm.throw_completion(ErrorType::TemporalInvalidEpochNanoseconds); - - // d. Return epochNanoseconds. - return BigInt::create(vm, move(epoch_nanoseconds)).ptr(); - } - - // 5. Assert: offsetBehaviour is option. - VERIFY(offset_behavior == OffsetBehavior::Option); - - // 6. Assert: offsetOption is "prefer" or "reject". - VERIFY(offset_option.is_one_of("prefer"sv, "reject"sv)); - - // 7. Let possibleInstants be ? GetPossibleInstantsFor(timeZone, dateTime). - auto time_zone_record = TRY(create_time_zone_methods_record(vm, GC::Ref { time_zone.as_object() }, { { TimeZoneMethod::GetPossibleInstantsFor, TimeZoneMethod::GetOffsetNanosecondsFor } })); - auto possible_instants = TRY(get_possible_instants_for(vm, time_zone_record, *date_time)); - - // 8. For each element candidate of possibleInstants, do - for (auto candidate : possible_instants) { - // a. Let candidateNanoseconds be ? GetOffsetNanosecondsFor(timeZone, candidate). - auto candidate_nanoseconds = TRY(get_offset_nanoseconds_for(vm, time_zone_record, *candidate)); - - // b. If candidateNanoseconds = offsetNanoseconds, then - if (candidate_nanoseconds == offset_nanoseconds) { - // i. Return candidate.[[Nanoseconds]]. - return &candidate->nanoseconds(); - } - - // c. If matchBehaviour is match minutes, then - if (match_behavior == MatchBehavior::MatchMinutes) { - // i. Let roundedCandidateNanoseconds be RoundNumberToIncrement(candidateNanoseconds, 60 × 10^9, "halfExpand"). - auto rounded_candidate_nanoseconds = round_number_to_increment(candidate_nanoseconds, 60000000000, "halfExpand"sv); - - // ii. If roundedCandidateNanoseconds = offsetNanoseconds, then - if (rounded_candidate_nanoseconds == offset_nanoseconds) { - // 1. Return candidate.[[Nanoseconds]]. - return &candidate->nanoseconds(); - } - } - } - - // 9. If offsetOption is "reject", throw a RangeError exception. - if (offset_option == "reject"sv) - return vm.throw_completion(ErrorType::TemporalInvalidZonedDateTimeOffset); - - // 10. Let instant be ? DisambiguatePossibleInstants(possibleInstants, timeZone, dateTime, disambiguation). - auto instant = TRY(disambiguate_possible_instants(vm, possible_instants, time_zone_record, *date_time, disambiguation)); - - // 11. Return instant.[[Nanoseconds]]. - return &instant->nanoseconds(); -} - -// 6.5.2 ToTemporalZonedDateTime ( item [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal-totemporalzoneddatetime -ThrowCompletionOr to_temporal_zoned_date_time(VM& vm, Value item, Object const* options) -{ - // 1. If options is not present, set options to undefined. - // 2. Assert: Type(options) is Object or Undefined. - - // 3. Let offsetBehaviour be option. - auto offset_behavior = OffsetBehavior::Option; - - // 4. Let matchBehaviour be match exactly. - auto match_behavior = MatchBehavior::MatchExactly; - - Object* calendar = nullptr; - Object* time_zone = nullptr; - Optional offset_string; - ISODateTime result; - - // 5. If Type(item) is Object, then - if (item.is_object()) { - auto& item_object = item.as_object(); - - // a. If item has an [[InitializedTemporalZonedDateTime]] internal slot, then - if (is(item_object)) { - // i. Return item. - return &static_cast(item_object); - } - - // b. Let calendar be ? GetTemporalCalendarWithISODefault(item). - calendar = TRY(get_temporal_calendar_with_iso_default(vm, item_object)); - - // c. Let fieldNames be ? CalendarFields(calendar, « "day", "hour", "microsecond", "millisecond", "minute", "month", "monthCode", "nanosecond", "second", "year" »). - auto field_names = TRY(calendar_fields(vm, *calendar, { "day"sv, "hour"sv, "microsecond"sv, "millisecond"sv, "minute"sv, "month"sv, "monthCode"sv, "nanosecond"sv, "second"sv, "year"sv })); - - // d. Append "timeZone" to fieldNames. - field_names.append("timeZone"_string); - - // e. Append "offset" to fieldNames. - field_names.append("offset"_string); - - // f. Let fields be ? PrepareTemporalFields(item, fieldNames, « "timeZone" »). - auto* fields = TRY(prepare_temporal_fields(vm, item_object, field_names, Vector { "timeZone"sv })); - - // g. Let timeZone be ! Get(fields, "timeZone"). - auto time_zone_value = MUST(fields->get(vm.names.timeZone)); - - // h. Set timeZone to ? ToTemporalTimeZone(timeZone). - time_zone = TRY(to_temporal_time_zone(vm, time_zone_value)); - - // i. Let offsetString be ! Get(fields, "offset"). - auto offset_string_value = MUST(fields->get(vm.names.offset)); - - // j. Assert: offsetString is a String or undefined. - VERIFY(offset_string_value.is_string() || offset_string_value.is_undefined()); - - // k. If offsetString is undefined, then - if (offset_string_value.is_undefined()) { - // i. Set offsetBehaviour to wall. - offset_behavior = OffsetBehavior::Wall; - } else { - // NOTE: Not in the spec, since it directly assigns to offsetString in step i, but we can't do it there as it's a type mismatch. - offset_string = offset_string_value.as_string().utf8_string(); - } - - // l. Let result be ? InterpretTemporalDateTimeFields(calendar, fields, options). - result = TRY(interpret_temporal_date_time_fields(vm, *calendar, *fields, options)); - } - // 6. Else, - else { - // a. Perform ? ToTemporalOverflow(options). - (void)TRY(to_temporal_overflow(vm, options)); - - // b. Let string be ? ToString(item). - auto string = TRY(item.to_string(vm)); - - // c. Let result be ? ParseTemporalZonedDateTimeString(string). - result = TRY(parse_temporal_zoned_date_time_string(vm, string)); - - // d. Let timeZoneName be result.[[TimeZone]].[[Name]]. - auto time_zone_name = result.time_zone.name; - - // e. Assert: timeZoneName is not undefined. - VERIFY(time_zone_name.has_value()); - - // f. If IsTimeZoneOffsetString(timeZoneName) is false, then - if (!is_time_zone_offset_string(*time_zone_name)) { - // i. If IsAvailableTimeZoneName(timeZoneName) is false, throw a RangeError exception. - if (!is_available_time_zone_name(*time_zone_name)) - return vm.throw_completion(ErrorType::TemporalInvalidTimeZoneName, *time_zone_name); - - // ii. Set timeZoneName to ! CanonicalizeTimeZoneName(timeZoneName). - time_zone_name = MUST_OR_THROW_OOM(canonicalize_time_zone_name(vm, *time_zone_name)); - } - - // g. Let offsetString be result.[[TimeZone]].[[OffsetString]]. - offset_string = move(result.time_zone.offset_string); - - // h. If result.[[TimeZone]].[[Z]] is true, then - if (result.time_zone.z) { - // i. Set offsetBehaviour to exact. - offset_behavior = OffsetBehavior::Exact; - } - // i. Else if offsetString is undefined, then - else if (!offset_string.has_value()) { - // i. Set offsetBehaviour to wall. - offset_behavior = OffsetBehavior::Wall; - } - - // j. Let timeZone be ! CreateTemporalTimeZone(timeZoneName). - time_zone = MUST_OR_THROW_OOM(create_temporal_time_zone(vm, time_zone_name.release_value())); - - // k. Let calendar be ? ToTemporalCalendarWithISODefault(result.[[Calendar]]). - auto temporal_calendar_like = result.calendar.has_value() - ? PrimitiveString::create(vm, result.calendar.value()) - : js_undefined(); - calendar = TRY(to_temporal_calendar_with_iso_default(vm, temporal_calendar_like)); - - // l. Set matchBehaviour to match minutes. - match_behavior = MatchBehavior::MatchMinutes; - } - - // 7. Let offsetNanoseconds be 0. - double offset_nanoseconds = 0; - - // 8. If offsetBehaviour is option, then - if (offset_behavior == OffsetBehavior::Option) { - // a. If IsTimeZoneOffsetString(offsetString) is false, throw a RangeError exception. - if (!is_time_zone_offset_string(*offset_string)) - return vm.throw_completion(ErrorType::TemporalInvalidTimeZoneName, *offset_string); - - // a. Set offsetNanoseconds to ? ParseTimeZoneOffsetString(offsetString). - offset_nanoseconds = parse_time_zone_offset_string(*offset_string); - } - - // 9. Let disambiguation be ? ToTemporalDisambiguation(options). - auto disambiguation = TRY(to_temporal_disambiguation(vm, options)); - - // 10. Let offsetOption be ? ToTemporalOffset(options, "reject"). - auto offset_option = TRY(to_temporal_offset(vm, options, "reject"sv)); - - // 11. Let epochNanoseconds be ? InterpretISODateTimeOffset(result.[[Year]], result.[[Month]], result.[[Day]], result.[[Hour]], result.[[Minute]], result.[[Second]], result.[[Millisecond]], result.[[Microsecond]], result.[[Nanosecond]], offsetBehaviour, offsetNanoseconds, timeZone, disambiguation, offsetOption, matchBehaviour). - auto* epoch_nanoseconds = TRY(interpret_iso_date_time_offset(vm, result.year, result.month, result.day, result.hour, result.minute, result.second, result.millisecond, result.microsecond, result.nanosecond, offset_behavior, offset_nanoseconds, time_zone, disambiguation, offset_option, match_behavior)); - - // 12. Return ! CreateTemporalZonedDateTime(epochNanoseconds, timeZone, calendar). - return MUST(create_temporal_zoned_date_time(vm, *epoch_nanoseconds, *time_zone, *calendar)); -} - -// 6.5.3 CreateTemporalZonedDateTime ( epochNanoseconds, timeZone, calendar [ , newTarget ] ), https://tc39.es/proposal-temporal/#sec-temporal-createtemporalzoneddatetime -ThrowCompletionOr create_temporal_zoned_date_time(VM& vm, BigInt const& epoch_nanoseconds, Object& time_zone, Object& calendar, FunctionObject const* new_target) -{ - auto& realm = *vm.current_realm(); - - // 1. Assert: ! IsValidEpochNanoseconds(epochNanoseconds) is true. - VERIFY(is_valid_epoch_nanoseconds(epoch_nanoseconds)); - - // 2. If newTarget is not present, set newTarget to %Temporal.ZonedDateTime%. - if (!new_target) - new_target = realm.intrinsics().temporal_zoned_date_time_constructor(); - - // 3. Let object be ? OrdinaryCreateFromConstructor(newTarget, "%Temporal.ZonedDateTime.prototype%", « [[InitializedTemporalZonedDateTime]], [[Nanoseconds]], [[TimeZone]], [[Calendar]] »). - // 4. Set object.[[Nanoseconds]] to epochNanoseconds. - // 5. Set object.[[TimeZone]] to timeZone. - // 6. Set object.[[Calendar]] to calendar. - auto object = TRY(ordinary_create_from_constructor(vm, *new_target, &Intrinsics::temporal_time_zone_prototype, epoch_nanoseconds, time_zone, calendar)); - - // 7. Return object. - return object.ptr(); -} - -// 6.5.4 TemporalZonedDateTimeToString ( zonedDateTime, precision, showCalendar, showTimeZone, showOffset [ , increment, unit, roundingMode ] ), https://tc39.es/proposal-temporal/#sec-temporal-temporalzoneddatetimetostring -ThrowCompletionOr temporal_zoned_date_time_to_string(VM& vm, ZonedDateTime& zoned_date_time, Variant const& precision, StringView show_calendar, StringView show_time_zone, StringView show_offset, Optional increment, Optional unit, Optional rounding_mode) -{ - // 1. If increment is not present, set increment to 1. - if (!increment.has_value()) - increment = 1; - - // 2. If unit is not present, set unit to "nanosecond". - if (!unit.has_value()) - unit = "nanosecond"sv; - - // 3. If roundingMode is not present, set roundingMode to "trunc". - if (!rounding_mode.has_value()) - rounding_mode = "trunc"sv; - - // 4. Let ns be ! RoundTemporalInstant(zonedDateTime.[[Nanoseconds]], increment, unit, roundingMode). - auto* ns = round_temporal_instant(vm, zoned_date_time.nanoseconds(), *increment, *unit, *rounding_mode); - - // 5. Let timeZone be zonedDateTime.[[TimeZone]]. - auto& time_zone = zoned_date_time.time_zone(); - - // 6. Let instant be ! CreateTemporalInstant(ns). - auto* instant = MUST(create_temporal_instant(vm, *ns)); - - // 7. Let isoCalendar be ! GetISO8601Calendar(). - auto* iso_calendar = get_iso8601_calendar(vm); - - // 8. Let temporalDateTime be ? BuiltinTimeZoneGetPlainDateTimeFor(timeZone, instant, isoCalendar). - auto* temporal_date_time = TRY(builtin_time_zone_get_plain_date_time_for(vm, &time_zone, *instant, *iso_calendar)); - - // 9. Let dateTimeString be ! TemporalDateTimeToString(temporalDateTime.[[ISOYear]], temporalDateTime.[[ISOMonth]], temporalDateTime.[[ISODay]], temporalDateTime.[[ISOHour]], temporalDateTime.[[ISOMinute]], temporalDateTime.[[ISOSecond]], temporalDateTime.[[ISOMillisecond]], temporalDateTime.[[ISOMicrosecond]], temporalDateTime.[[ISONanosecond]], isoCalendar, precision, "never"). - auto date_time_string = MUST_OR_THROW_OOM(temporal_date_time_to_string(vm, temporal_date_time->iso_year(), temporal_date_time->iso_month(), temporal_date_time->iso_day(), temporal_date_time->iso_hour(), temporal_date_time->iso_minute(), temporal_date_time->iso_second(), temporal_date_time->iso_millisecond(), temporal_date_time->iso_microsecond(), temporal_date_time->iso_nanosecond(), iso_calendar, precision, "never"sv)); - - String offset_string; - - // 10. If showOffset is "never", then - if (show_offset == "never"sv) { - // a. Let offsetString be the empty String. - offset_string = {}; - } - // 11. Else, - else { - auto time_zone_record = TRY(create_time_zone_methods_record(vm, GC::Ref { time_zone }, { { TimeZoneMethod::GetOffsetNanosecondsFor } })); - - // a. Let offsetNs be ? GetOffsetNanosecondsFor(timeZone, instant). - auto offset_ns = TRY(get_offset_nanoseconds_for(vm, time_zone_record, *instant)); - - // b. Let offsetString be ! FormatISOTimeZoneOffsetString(offsetNs). - offset_string = MUST_OR_THROW_OOM(format_iso_time_zone_offset_string(vm, offset_ns)); - } - - String time_zone_string; - - // 12. If showTimeZone is "never", then - if (show_time_zone == "never"sv) { - // a. Let timeZoneString be the empty String. - time_zone_string = {}; - } - // 13. Else, - else { - // a. Let timeZoneID be ? ToString(timeZone). - auto time_zone_id = TRY(Value(&time_zone).to_string(vm)); - - // b. If showTimeZone is "critical", let flag be "!"; else let flag be the empty String. - auto flag = show_time_zone == "critical"sv ? "!"sv : ""sv; - - // c. Let timeZoneString be the string-concatenation of the code unit 0x005B (LEFT SQUARE BRACKET), flag, timeZoneID, and the code unit 0x005D (RIGHT SQUARE BRACKET). - time_zone_string = TRY_OR_THROW_OOM(vm, String::formatted("[{}{}]", flag, time_zone_id)); - } - - // 14. Let calendarString be ? MaybeFormatCalendarAnnotation(zonedDateTime.[[Calendar]], showCalendar). - auto calendar_string = TRY(maybe_format_calendar_annotation(vm, &zoned_date_time.calendar(), show_calendar)); - - // 15. Return the string-concatenation of dateTimeString, offsetString, timeZoneString, and calendarString. - return TRY_OR_THROW_OOM(vm, String::formatted("{}{}{}{}", date_time_string, offset_string, time_zone_string, calendar_string)); -} - -// 6.5.5 AddZonedDateTime ( epochNanoseconds, timeZone, calendar, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal-addzoneddatetime -ThrowCompletionOr add_zoned_date_time(VM& vm, BigInt const& epoch_nanoseconds, Value time_zone, Object& calendar, double years, double months, double weeks, double days, double hours, double minutes, double seconds, double milliseconds, double microseconds, double nanoseconds, Object* options) -{ - // 1. If options is not present, set options to undefined. - // 2. Assert: Type(options) is Object or Undefined. - - // 3. If all of years, months, weeks, and days are 0, then - if (years == 0 && months == 0 && weeks == 0 && days == 0) { - // a. Return ? AddInstant(epochNanoseconds, hours, minutes, seconds, milliseconds, microseconds, nanoseconds). - return add_instant(vm, epoch_nanoseconds, hours, minutes, seconds, milliseconds, microseconds, nanoseconds); - } - - // 4. Let instant be ! CreateTemporalInstant(epochNanoseconds). - auto* instant = MUST(create_temporal_instant(vm, epoch_nanoseconds)); - - // 5. Let temporalDateTime be ? BuiltinTimeZoneGetPlainDateTimeFor(timeZone, instant, calendar). - auto* temporal_date_time = TRY(builtin_time_zone_get_plain_date_time_for(vm, time_zone, *instant, calendar)); - - // 6. Let datePart be ! CreateTemporalDate(temporalDateTime.[[ISOYear]], temporalDateTime.[[ISOMonth]], temporalDateTime.[[ISODay]], calendar). - auto* date_part = MUST(create_temporal_date(vm, temporal_date_time->iso_year(), temporal_date_time->iso_month(), temporal_date_time->iso_day(), calendar)); - - // 7. Let dateDuration be ! CreateTemporalDuration(years, months, weeks, days, 0, 0, 0, 0, 0, 0). - auto date_duration = MUST(create_temporal_duration(vm, years, months, weeks, days, 0, 0, 0, 0, 0, 0)); - - // 8. Let addedDate be ? CalendarDateAdd(calendar, datePart, dateDuration, options). - auto* added_date = TRY(calendar_date_add(vm, calendar, date_part, *date_duration, options)); - - // 9. Let intermediateDateTime be ? CreateTemporalDateTime(addedDate.[[ISOYear]], addedDate.[[ISOMonth]], addedDate.[[ISODay]], temporalDateTime.[[ISOHour]], temporalDateTime.[[ISOMinute]], temporalDateTime.[[ISOSecond]], temporalDateTime.[[ISOMillisecond]], temporalDateTime.[[ISOMicrosecond]], temporalDateTime.[[ISONanosecond]], calendar). - auto* intermediate_date_time = TRY(create_temporal_date_time(vm, added_date->iso_year(), added_date->iso_month(), added_date->iso_day(), temporal_date_time->iso_hour(), temporal_date_time->iso_minute(), temporal_date_time->iso_second(), temporal_date_time->iso_millisecond(), temporal_date_time->iso_microsecond(), temporal_date_time->iso_nanosecond(), calendar)); - - // 10. Let intermediateInstant be ? BuiltinTimeZoneGetInstantFor(timeZone, intermediateDateTime, "compatible"). - auto intermediate_instant = TRY(builtin_time_zone_get_instant_for(vm, time_zone, *intermediate_date_time, "compatible"sv)); - - // 11. Return ? AddInstant(intermediateInstant.[[Nanoseconds]], hours, minutes, seconds, milliseconds, microseconds, nanoseconds). - return add_instant(vm, intermediate_instant->nanoseconds(), hours, minutes, seconds, milliseconds, microseconds, nanoseconds); -} - -// 6.5.6 DifferenceZonedDateTime ( ns1, ns2, timeZone, calendar, largestUnit, options ), https://tc39.es/proposal-temporal/#sec-temporal-differencezoneddatetime -ThrowCompletionOr difference_zoned_date_time(VM& vm, BigInt const& nanoseconds1, BigInt const& nanoseconds2, Object& time_zone, Object& calendar, StringView largest_unit, Object const& options) -{ - // 1. If ns1 is ns2, then - if (nanoseconds1.big_integer() == nanoseconds2.big_integer()) { - // a. Return ! CreateDurationRecord(0, 0, 0, 0, 0, 0, 0, 0, 0, 0). - return create_duration_record(0, 0, 0, 0, 0, 0, 0, 0, 0, 0); - } - - // 2. Let startInstant be ! CreateTemporalInstant(ns1). - auto* start_instant = MUST(create_temporal_instant(vm, nanoseconds1)); - - // 3. Let startDateTime be ? BuiltinTimeZoneGetPlainDateTimeFor(timeZone, startInstant, calendar). - auto* start_date_time = TRY(builtin_time_zone_get_plain_date_time_for(vm, &time_zone, *start_instant, calendar)); - - // 4. Let endInstant be ! CreateTemporalInstant(ns2). - auto* end_instant = MUST(create_temporal_instant(vm, nanoseconds2)); - - // 5. Let endDateTime be ? BuiltinTimeZoneGetPlainDateTimeFor(timeZone, endInstant, calendar). - auto* end_date_time = TRY(builtin_time_zone_get_plain_date_time_for(vm, &time_zone, *end_instant, calendar)); - - // 6. Let dateDifference be ? DifferenceISODateTime(startDateTime.[[ISOYear]], startDateTime.[[ISOMonth]], startDateTime.[[ISODay]], startDateTime.[[ISOHour]], startDateTime.[[ISOMinute]], startDateTime.[[ISOSecond]], startDateTime.[[ISOMillisecond]], startDateTime.[[ISOMicrosecond]], startDateTime.[[ISONanosecond]], endDateTime.[[ISOYear]], endDateTime.[[ISOMonth]], endDateTime.[[ISODay]], endDateTime.[[ISOHour]], endDateTime.[[ISOMinute]], endDateTime.[[ISOSecond]], endDateTime.[[ISOMillisecond]], endDateTime.[[ISOMicrosecond]], endDateTime.[[ISONanosecond]], calendar, largestUnit, options). - auto date_difference = TRY(difference_iso_date_time(vm, start_date_time->iso_year(), start_date_time->iso_month(), start_date_time->iso_day(), start_date_time->iso_hour(), start_date_time->iso_minute(), start_date_time->iso_second(), start_date_time->iso_millisecond(), start_date_time->iso_microsecond(), start_date_time->iso_nanosecond(), end_date_time->iso_year(), end_date_time->iso_month(), end_date_time->iso_day(), end_date_time->iso_hour(), end_date_time->iso_minute(), end_date_time->iso_second(), end_date_time->iso_millisecond(), end_date_time->iso_microsecond(), end_date_time->iso_nanosecond(), calendar, largest_unit, options)); - - // 7. Let intermediateNs be ? AddZonedDateTime(ns1, timeZone, calendar, dateDifference.[[Years]], dateDifference.[[Months]], dateDifference.[[Weeks]], 0, 0, 0, 0, 0, 0, 0). - auto* intermediate_ns = TRY(add_zoned_date_time(vm, nanoseconds1, &time_zone, calendar, date_difference.years, date_difference.months, date_difference.weeks, 0, 0, 0, 0, 0, 0, 0)); - - // 8. Let timeRemainderNs be ns2 - intermediateNs. - auto time_remainder_ns = nanoseconds2.big_integer().minus(intermediate_ns->big_integer()); - - // 9. Let intermediate be ! CreateTemporalZonedDateTime(intermediateNs, timeZone, calendar). - auto* intermediate = MUST(create_temporal_zoned_date_time(vm, *intermediate_ns, time_zone, calendar)); - - // 10. Let result be ? NanosecondsToDays(timeRemainderNs, intermediate). - auto result = TRY(nanoseconds_to_days(vm, time_remainder_ns, intermediate)); - - // 11. Let timeDifference be ! BalanceDuration(0, 0, 0, 0, 0, 0, result.[[Nanoseconds]], "hour"). - auto time_difference = MUST(balance_duration(vm, 0, 0, 0, 0, 0, 0, result.nanoseconds, "hour"sv)); - - // 12. Return ! CreateDurationRecord(dateDifference.[[Years]], dateDifference.[[Months]], dateDifference.[[Weeks]], result.[[Days]], timeDifference.[[Hours]], timeDifference.[[Minutes]], timeDifference.[[Seconds]], timeDifference.[[Milliseconds]], timeDifference.[[Microseconds]], timeDifference.[[Nanoseconds]]). - return create_duration_record(date_difference.years, date_difference.months, date_difference.weeks, result.days, time_difference.hours, time_difference.minutes, time_difference.seconds, time_difference.milliseconds, time_difference.microseconds, time_difference.nanoseconds); -} - -// 6.5.7 NanosecondsToDays ( nanoseconds, relativeTo ), https://tc39.es/proposal-temporal/#sec-temporal-nanosecondstodays -ThrowCompletionOr nanoseconds_to_days(VM& vm, Crypto::SignedBigInteger nanoseconds, Value relative_to_value) -{ - auto& realm = *vm.current_realm(); - - // 1. Let dayLengthNs be nsPerDay. - auto day_length_ns = ns_per_day_bigint; - - // 2. If nanoseconds = 0, then - if (nanoseconds.is_zero()) { - // a. Return the Record { [[Days]]: 0, [[Nanoseconds]]: 0, [[DayLength]]: dayLengthNs }. - return NanosecondsToDaysResult { .days = 0, .nanoseconds = "0"_sbigint, .day_length = day_length_ns.to_double() }; - } - - // 3. If nanoseconds < 0, let sign be -1; else, let sign be 1. - auto sign = nanoseconds.is_negative() ? -1 : 1; - - // 4. If Type(relativeTo) is not Object or relativeTo does not have an [[InitializedTemporalZonedDateTime]] internal slot, then - if (!relative_to_value.is_object() || !is(relative_to_value.as_object())) { - // a. Return the Record { [[Days]]: truncate(nanoseconds / dayLengthNs), [[Nanoseconds]]: (abs(nanoseconds) modulo dayLengthNs) × sign, [[DayLength]]: dayLengthNs }. - return NanosecondsToDaysResult { - .days = nanoseconds.divided_by(day_length_ns).quotient.to_double(), - .nanoseconds = Crypto::SignedBigInteger { nanoseconds.unsigned_value() }.divided_by(day_length_ns).remainder.multiplied_by(Crypto::SignedBigInteger { sign }), - .day_length = day_length_ns.to_double() - }; - } - - auto& relative_to = static_cast(relative_to_value.as_object()); - - // 5. Let startNs be ℝ(relativeTo.[[Nanoseconds]]). - auto& start_ns = relative_to.nanoseconds().big_integer(); - - // 6. Let startInstant be ! CreateTemporalInstant(ℤ(startNs)). - auto* start_instant = MUST(create_temporal_instant(vm, BigInt::create(vm, start_ns))); - - // 7. Let startDateTime be ? BuiltinTimeZoneGetPlainDateTimeFor(relativeTo.[[TimeZone]], startInstant, relativeTo.[[Calendar]]). - auto* start_date_time = TRY(builtin_time_zone_get_plain_date_time_for(vm, &relative_to.time_zone(), *start_instant, relative_to.calendar())); - - // 8. Let endNs be startNs + nanoseconds. - auto end_ns = start_ns.plus(nanoseconds); - - auto end_ns_bigint = BigInt::create(vm, end_ns); - - // 9. If ! IsValidEpochNanoseconds(ℤ(endNs)) is false, throw a RangeError exception. - if (!is_valid_epoch_nanoseconds(end_ns_bigint)) - return vm.throw_completion(ErrorType::TemporalInvalidEpochNanoseconds); - - // 10. Let endInstant be ! CreateTemporalInstant(ℤ(endNs)). - auto* end_instant = MUST(create_temporal_instant(vm, end_ns_bigint)); - - // 11. Let endDateTime be ? BuiltinTimeZoneGetPlainDateTimeFor(relativeTo.[[TimeZone]], endInstant, relativeTo.[[Calendar]]). - auto* end_date_time = TRY(builtin_time_zone_get_plain_date_time_for(vm, &relative_to.time_zone(), *end_instant, relative_to.calendar())); - - // 12. Let dateDifference be ? DifferenceISODateTime(startDateTime.[[ISOYear]], startDateTime.[[ISOMonth]], startDateTime.[[ISODay]], startDateTime.[[ISOHour]], startDateTime.[[ISOMinute]], startDateTime.[[ISOSecond]], startDateTime.[[ISOMillisecond]], startDateTime.[[ISOMicrosecond]], startDateTime.[[ISONanosecond]], endDateTime.[[ISOYear]], endDateTime.[[ISOMonth]], endDateTime.[[ISODay]], endDateTime.[[ISOHour]], endDateTime.[[ISOMinute]], endDateTime.[[ISOSecond]], endDateTime.[[ISOMillisecond]], endDateTime.[[ISOMicrosecond]], endDateTime.[[ISONanosecond]], relativeTo.[[Calendar]], "day", OrdinaryObjectCreate(null)). - auto date_difference = TRY(difference_iso_date_time(vm, start_date_time->iso_year(), start_date_time->iso_month(), start_date_time->iso_day(), start_date_time->iso_hour(), start_date_time->iso_minute(), start_date_time->iso_second(), start_date_time->iso_millisecond(), start_date_time->iso_microsecond(), start_date_time->iso_nanosecond(), end_date_time->iso_year(), end_date_time->iso_month(), end_date_time->iso_day(), end_date_time->iso_hour(), end_date_time->iso_minute(), end_date_time->iso_second(), end_date_time->iso_millisecond(), end_date_time->iso_microsecond(), end_date_time->iso_nanosecond(), relative_to.calendar(), "day"sv, *Object::create(realm, nullptr))); - - // 13. Let days be dateDifference.[[Days]]. - auto days = date_difference.days; - - // 14. Let intermediateNs be ℝ(? AddZonedDateTime(ℤ(startNs), relativeTo.[[TimeZone]], relativeTo.[[Calendar]], 0, 0, 0, days, 0, 0, 0, 0, 0, 0)). - auto intermediate_ns = TRY(add_zoned_date_time(vm, BigInt::create(vm, start_ns), &relative_to.time_zone(), relative_to.calendar(), 0, 0, 0, days, 0, 0, 0, 0, 0, 0))->big_integer(); - - // 15. If sign is 1, then - if (sign == 1) { - // a. Repeat, while days > 0 and intermediateNs > endNs, - while (days > 0 && intermediate_ns > end_ns) { - // i. Set days to days - 1. - days--; - - // ii. Set intermediateNs to ℝ(? AddZonedDateTime(ℤ(startNs), relativeTo.[[TimeZone]], relativeTo.[[Calendar]], 0, 0, 0, days, 0, 0, 0, 0, 0, 0)). - intermediate_ns = TRY(add_zoned_date_time(vm, BigInt::create(vm, start_ns), &relative_to.time_zone(), relative_to.calendar(), 0, 0, 0, days, 0, 0, 0, 0, 0, 0))->big_integer(); - } - } - - // 16. Set nanoseconds to endNs - intermediateNs. - nanoseconds = end_ns.minus(intermediate_ns); - - // 17. Let done be false. - // 18. Repeat, while done is false, - while (true) { - // a. Let oneDayFartherNs be ℝ(? AddZonedDateTime(ℤ(intermediateNs), relativeTo.[[TimeZone]], relativeTo.[[Calendar]], 0, 0, 0, sign, 0, 0, 0, 0, 0, 0)). - auto one_day_farther_ns = TRY(add_zoned_date_time(vm, BigInt::create(vm, intermediate_ns), &relative_to.time_zone(), relative_to.calendar(), 0, 0, 0, sign, 0, 0, 0, 0, 0, 0))->big_integer(); - - // b. Set dayLengthNs to oneDayFartherNs - intermediateNs. - day_length_ns = one_day_farther_ns.minus(intermediate_ns); - - // c. If (nanoseconds - dayLengthNs) × sign ≥ 0, then - if (nanoseconds.minus(day_length_ns).multiplied_by(Crypto::SignedBigInteger { sign }) >= "0"_sbigint) { - // i. Set nanoseconds to nanoseconds - dayLengthNs. - nanoseconds = nanoseconds.minus(day_length_ns); - - // ii. Set intermediateNs to oneDayFartherNs. - intermediate_ns = move(one_day_farther_ns); - - // iii. Set days to days + sign. - days += sign; - } - // d. Else, - else { - // i. Set done to true. - break; - } - } - - // 19. If days < 0 and sign = 1, throw a RangeError exception. - if (days < 0 && sign == 1) - return vm.throw_completion(ErrorType::TemporalNanosecondsConvertedToDaysWithOppositeSign); - - // 20. If days > 0 and sign = -1, throw a RangeError exception. - if (days > 0 && sign == -1) - return vm.throw_completion(ErrorType::TemporalNanosecondsConvertedToDaysWithOppositeSign); - - // 21. If nanoseconds < 0 and sign = 1, throw a RangeError exception. - if (nanoseconds.is_negative() && sign == 1) - return vm.throw_completion(ErrorType::TemporalNanosecondsConvertedToRemainderOfNanosecondsWithOppositeSign); - - // 22. If nanoseconds > 0 and sign = -1, throw a RangeError exception. - if (nanoseconds.is_positive() && sign == -1) - return vm.throw_completion(ErrorType::TemporalNanosecondsConvertedToRemainderOfNanosecondsWithOppositeSign); - - // 23. If abs(nanoseconds) ≥ abs(dayLengthNs), throw a RangeError exception. - auto compare_result = nanoseconds.unsigned_value().compare_to_double(fabs(day_length_ns.to_double())); - if (compare_result == Crypto::UnsignedBigInteger::CompareResult::DoubleLessThanBigInt || compare_result == Crypto::UnsignedBigInteger::CompareResult::DoubleEqualsBigInt) - return vm.throw_completion(ErrorType::TemporalNanosecondsConvertedToRemainderOfNanosecondsLongerThanDayLength); - - // 24. Return the Record { [[Days]]: days, [[Nanoseconds]]: nanoseconds, [[DayLength]]: abs(dayLengthNs) }. - return NanosecondsToDaysResult { .days = days, .nanoseconds = move(nanoseconds), .day_length = fabs(day_length_ns.to_double()) }; -} - -// 6.5.8 DifferenceTemporalZonedDateTime ( operation, zonedDateTime, other, options ), https://tc39.es/proposal-temporal/#sec-temporal-differencetemporalzoneddatetime -ThrowCompletionOr> difference_temporal_zoned_date_time(VM& vm, DifferenceOperation operation, ZonedDateTime& zoned_date_time, Value other_value, Value options_value) -{ - // 1. If operation is since, let sign be -1. Otherwise, let sign be 1. - i8 sign = operation == DifferenceOperation::Since ? -1 : 1; - - // 2. Set other to ? ToTemporalZonedDateTime(other). - auto* other = TRY(to_temporal_zoned_date_time(vm, other_value)); - - // 3. If ? CalendarEquals(zonedDateTime.[[Calendar]], other.[[Calendar]]) is false, then - if (!TRY(calendar_equals(vm, zoned_date_time.calendar(), other->calendar()))) { - // a. Throw a RangeError exception. - return vm.throw_completion(ErrorType::TemporalDifferentCalendars); - } - - // 4. Let settings be ? GetDifferenceSettings(operation, options, datetime, « », "nanosecond", "hour"). - auto settings = TRY(get_difference_settings(vm, operation, options_value, UnitGroup::DateTime, {}, { "nanosecond"sv }, "hour"sv)); - - // 5. If settings.[[LargestUnit]] is not one of "year", "month", "week", or "day", then - if (!settings.largest_unit.is_one_of("year"sv, "month"sv, "week"sv, "day"sv)) { - // a. Let result be DifferenceInstant(zonedDateTime.[[Nanoseconds]], other.[[Nanoseconds]], settings.[[RoundingIncrement]], settings.[[SmallestUnit]], settings.[[LargestUnit]], settings.[[RoundingMode]]). - auto result = difference_instant(vm, zoned_date_time.nanoseconds(), other->nanoseconds(), settings.rounding_increment, settings.smallest_unit, settings.largest_unit, settings.rounding_mode); - - // b. Return ! CreateTemporalDuration(0, 0, 0, 0, sign × result.[[Hours]], sign × result.[[Minutes]], sign × result.[[Seconds]], sign × result.[[Milliseconds]], sign × result.[[Microseconds]], sign × result.[[Nanoseconds]]). - return create_temporal_duration(vm, 0, 0, 0, 0, sign * result.hours, sign * result.minutes, sign * result.seconds, sign * result.milliseconds, sign * result.microseconds, sign * result.nanoseconds); - } - - // 6. If ? TimeZoneEquals(zonedDateTime.[[TimeZone]], other.[[TimeZone]]) is false, then - if (!TRY(time_zone_equals(vm, zoned_date_time.time_zone(), other->time_zone()))) { - // a. Throw a RangeError exception. - return vm.throw_completion(ErrorType::TemporalDifferentTimeZones); - } - - // 7. Let untilOptions be ? MergeLargestUnitOption(settings.[[Options]], settings.[[LargestUnit]]). - auto* until_options = TRY(merge_largest_unit_option(vm, settings.options, settings.largest_unit)); - - // 8. Let difference be ? DifferenceZonedDateTime(zonedDateTime.[[Nanoseconds]], other.[[Nanoseconds]], zonedDateTime.[[TimeZone]], zonedDateTime.[[Calendar]], settings.[[LargestUnit]], untilOptions). - auto difference = TRY(difference_zoned_date_time(vm, zoned_date_time.nanoseconds(), other->nanoseconds(), zoned_date_time.time_zone(), zoned_date_time.calendar(), settings.largest_unit, *until_options)); - - auto calendar_record = TRY(create_calendar_methods_record(vm, GC::Ref { zoned_date_time.calendar() }, { { CalendarMethod::DateAdd, CalendarMethod::DateFromFields, CalendarMethod::DateUntil, CalendarMethod::Fields } })); - - // 9. Let roundResult be (? RoundDuration(difference.[[Years]], difference.[[Months]], difference.[[Weeks]], difference.[[Days]], difference.[[Hours]], difference.[[Minutes]], difference.[[Seconds]], difference.[[Milliseconds]], difference.[[Microseconds]], difference.[[Nanoseconds]], settings.[[RoundingIncrement]], settings.[[SmallestUnit]], settings.[[RoundingMode]], zonedDateTime)).[[DurationRecord]]. - auto round_result = TRY(round_duration(vm, difference.years, difference.months, difference.weeks, difference.days, difference.hours, difference.minutes, difference.seconds, difference.milliseconds, difference.microseconds, difference.nanoseconds, settings.rounding_increment, settings.smallest_unit, settings.rounding_mode, &zoned_date_time, calendar_record)).duration_record; - - // 10. Let result be ? AdjustRoundedDurationDays(roundResult.[[Years]], roundResult.[[Months]], roundResult.[[Weeks]], roundResult.[[Days]], roundResult.[[Hours]], roundResult.[[Minutes]], roundResult.[[Seconds]], roundResult.[[Milliseconds]], roundResult.[[Microseconds]], roundResult.[[Nanoseconds]], settings.[[RoundingIncrement]], settings.[[SmallestUnit]], settings.[[RoundingMode]], zonedDateTime). - auto result = TRY(adjust_rounded_duration_days(vm, round_result.years, round_result.months, round_result.weeks, round_result.days, round_result.hours, round_result.minutes, round_result.seconds, round_result.milliseconds, round_result.microseconds, round_result.nanoseconds, settings.rounding_increment, settings.smallest_unit, settings.rounding_mode, &zoned_date_time)); - - // 11. Return ! CreateTemporalDuration(sign × result.[[Years]], sign × result.[[Months]], sign × result.[[Weeks]], sign × result.[[Days]], sign × result.[[Hours]], sign × result.[[Minutes]], sign × result.[[Seconds]], sign × result.[[Milliseconds]], sign × result.[[Microseconds]], sign × result.[[Nanoseconds]]). - return MUST(create_temporal_duration(vm, sign * result.years, sign * result.months, sign * result.weeks, sign * result.days, sign * result.hours, sign * result.minutes, sign * result.seconds, sign * result.milliseconds, sign * result.microseconds, sign * result.nanoseconds)); -} - -// 6.5.9 AddDurationToOrSubtractDurationFromZonedDateTime ( operation, zonedDateTime, temporalDurationLike, options ), https://tc39.es/proposal-temporal/#sec-temporal-adddurationtoOrsubtractdurationfromzoneddatetime -ThrowCompletionOr add_duration_to_or_subtract_duration_from_zoned_date_time(VM& vm, ArithmeticOperation operation, ZonedDateTime& zoned_date_time, Value temporal_duration_like, Value options_value) -{ - // 1. If operation is subtract, let sign be -1. Otherwise, let sign be 1. - i8 sign = operation == ArithmeticOperation::Subtract ? -1 : 1; - - // 2. Let duration be ? ToTemporalDurationRecord(temporalDurationLike). - auto duration = TRY(to_temporal_duration_record(vm, temporal_duration_like)); - - // 3. Set options to ? GetOptionsObject(options). - auto* options = TRY(get_options_object(vm, options_value)); - - // 4. Let timeZone be zonedDateTime.[[TimeZone]]. - auto& time_zone = zoned_date_time.time_zone(); - - // 5. Let calendar be zonedDateTime.[[Calendar]]. - auto& calendar = zoned_date_time.calendar(); - - // 6. Let epochNanoseconds be ? AddZonedDateTime(zonedDateTime.[[Nanoseconds]], timeZone, calendar, sign × duration.[[Years]], sign × duration.[[Months]], sign × duration.[[Weeks]], sign × duration.[[Days]], sign × duration.[[Hours]], sign × duration.[[Minutes]], sign × duration.[[Seconds]], sign × duration.[[Milliseconds]], sign × duration.[[Microseconds]], sign × duration.[[Nanoseconds]], options). - auto* epoch_nanoseconds = TRY(add_zoned_date_time(vm, zoned_date_time.nanoseconds(), &time_zone, calendar, sign * duration.years, sign * duration.months, sign * duration.weeks, sign * duration.days, sign * duration.hours, sign * duration.minutes, sign * duration.seconds, sign * duration.milliseconds, sign * duration.microseconds, sign * duration.nanoseconds, options)); - - // 7. Return ! CreateTemporalZonedDateTime(epochNanoseconds, timeZone, calendar). - return MUST(create_temporal_zoned_date_time(vm, *epoch_nanoseconds, time_zone, calendar)); -} - -} diff --git a/Libraries/LibJS/Runtime/Temporal/ZonedDateTime.h b/Libraries/LibJS/Runtime/Temporal/ZonedDateTime.h deleted file mode 100644 index c3fc6a93298..00000000000 --- a/Libraries/LibJS/Runtime/Temporal/ZonedDateTime.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2021-2023, Linus Groh - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include -#include -#include - -namespace JS::Temporal { - -class ZonedDateTime final : public Object { - JS_OBJECT(ZonedDateTime, Object); - GC_DECLARE_ALLOCATOR(ZonedDateTime); - -public: - virtual ~ZonedDateTime() override = default; - - [[nodiscard]] BigInt const& nanoseconds() const { return m_nanoseconds; } - [[nodiscard]] Object const& time_zone() const { return m_time_zone; } - [[nodiscard]] Object& time_zone() { return m_time_zone; } - [[nodiscard]] Object const& calendar() const { return m_calendar; } - [[nodiscard]] Object& calendar() { return m_calendar; } - -private: - ZonedDateTime(BigInt const& nanoseconds, Object& time_zone, Object& calendar, Object& prototype); - - virtual void visit_edges(Visitor&) override; - - // 6.4 Properties of Temporal.ZonedDateTime Instances, https://tc39.es/proposal-temporal/#sec-properties-of-temporal-zoneddatetime-instances - GC::Ref m_nanoseconds; // [[Nanoseconds]] - GC::Ref m_time_zone; // [[TimeZone]] - GC::Ref m_calendar; // [[Calendar]] -}; - -struct NanosecondsToDaysResult { - double days; - Crypto::SignedBigInteger nanoseconds; - double day_length; -}; - -enum class OffsetBehavior { - Option, - Exact, - Wall, -}; - -enum class MatchBehavior { - MatchExactly, - MatchMinutes, -}; - -ThrowCompletionOr interpret_iso_date_time_offset(VM&, i32 year, u8 month, u8 day, u8 hour, u8 minute, u8 second, u16 millisecond, u16 microsecond, u16 nanosecond, OffsetBehavior offset_behavior, double offset_nanoseconds, Value time_zone, StringView disambiguation, StringView offset_option, MatchBehavior match_behavior); -ThrowCompletionOr to_temporal_zoned_date_time(VM&, Value item, Object const* options = nullptr); -ThrowCompletionOr create_temporal_zoned_date_time(VM&, BigInt const& epoch_nanoseconds, Object& time_zone, Object& calendar, FunctionObject const* new_target = nullptr); -ThrowCompletionOr temporal_zoned_date_time_to_string(VM&, ZonedDateTime& zoned_date_time, Variant const& precision, StringView show_calendar, StringView show_time_zone, StringView show_offset, Optional increment = {}, Optional unit = {}, Optional rounding_mode = {}); -ThrowCompletionOr add_zoned_date_time(VM&, BigInt const& epoch_nanoseconds, Value time_zone, Object& calendar, double years, double months, double weeks, double days, double hours, double minutes, double seconds, double milliseconds, double microseconds, double nanoseconds, Object* options = nullptr); -ThrowCompletionOr difference_zoned_date_time(VM&, BigInt const& nanoseconds1, BigInt const& nanoseconds2, Object& time_zone, Object& calendar, StringView largest_unit, Object const& options); -ThrowCompletionOr nanoseconds_to_days(VM&, Crypto::SignedBigInteger nanoseconds, Value relative_to); -ThrowCompletionOr> difference_temporal_zoned_date_time(VM&, DifferenceOperation, ZonedDateTime&, Value other, Value options); -ThrowCompletionOr add_duration_to_or_subtract_duration_from_zoned_date_time(VM&, ArithmeticOperation, ZonedDateTime&, Value temporal_duration_like, Value options_value); - -} diff --git a/Libraries/LibJS/Runtime/Temporal/ZonedDateTimeConstructor.cpp b/Libraries/LibJS/Runtime/Temporal/ZonedDateTimeConstructor.cpp deleted file mode 100644 index dd7b4f14d9e..00000000000 --- a/Libraries/LibJS/Runtime/Temporal/ZonedDateTimeConstructor.cpp +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (c) 2021-2023, Linus Groh - * Copyright (c) 2021, Luke Wilde - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include -#include -#include -#include -#include -#include -#include - -namespace JS::Temporal { - -GC_DEFINE_ALLOCATOR(ZonedDateTimeConstructor); - -// 6.1 The Temporal.ZonedDateTime Constructor, https://tc39.es/proposal-temporal/#sec-temporal-zoneddatetime-constructor -ZonedDateTimeConstructor::ZonedDateTimeConstructor(Realm& realm) - : NativeFunction(realm.vm().names.ZonedDateTime.as_string(), realm.intrinsics().function_prototype()) -{ -} - -void ZonedDateTimeConstructor::initialize(Realm& realm) -{ - Base::initialize(realm); - - auto& vm = this->vm(); - - // 6.2.1 Temporal.ZonedDateTime.prototype, https://tc39.es/proposal-temporal/#sec-temporal.zoneddatetime.prototype - define_direct_property(vm.names.prototype, realm.intrinsics().temporal_zoned_date_time_prototype(), 0); - - u8 attr = Attribute::Writable | Attribute::Configurable; - define_native_function(realm, vm.names.from, from, 1, attr); - define_native_function(realm, vm.names.compare, compare, 2, attr); - - define_direct_property(vm.names.length, Value(2), Attribute::Configurable); -} - -// 6.1.1 Temporal.ZonedDateTime ( epochNanoseconds, timeZoneLike [ , calendarLike ] ), https://tc39.es/proposal-temporal/#sec-temporal.zoneddatetime -ThrowCompletionOr ZonedDateTimeConstructor::call() -{ - auto& vm = this->vm(); - - // 1. If NewTarget is undefined, then - // a. Throw a TypeError exception. - return vm.throw_completion(ErrorType::ConstructorWithoutNew, "Temporal.ZonedDateTime"); -} - -// 6.1.1 Temporal.ZonedDateTime ( epochNanoseconds, timeZoneLike [ , calendarLike ] ), https://tc39.es/proposal-temporal/#sec-temporal.zoneddatetime -ThrowCompletionOr> ZonedDateTimeConstructor::construct(FunctionObject& new_target) -{ - auto& vm = this->vm(); - - // 2. Set epochNanoseconds to ? ToBigInt(epochNanoseconds). - auto epoch_nanoseconds = TRY(vm.argument(0).to_bigint(vm)); - - // 3. If ! IsValidEpochNanoseconds(epochNanoseconds) is false, throw a RangeError exception. - if (!is_valid_epoch_nanoseconds(epoch_nanoseconds)) - return vm.throw_completion(ErrorType::TemporalInvalidEpochNanoseconds); - - // 4. Let timeZone be ? ToTemporalTimeZone(timeZoneLike). - auto* time_zone = TRY(to_temporal_time_zone(vm, vm.argument(1))); - - // 5. Let calendar be ? ToTemporalCalendarWithISODefault(calendarLike). - auto* calendar = TRY(to_temporal_calendar_with_iso_default(vm, vm.argument(2))); - - // 6. Return ? CreateTemporalZonedDateTime(epochNanoseconds, timeZone, calendar, NewTarget). - return *TRY(create_temporal_zoned_date_time(vm, epoch_nanoseconds, *time_zone, *calendar, &new_target)); -} - -// 6.2.2 Temporal.ZonedDateTime.from ( item [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal.zoneddatetime.from -JS_DEFINE_NATIVE_FUNCTION(ZonedDateTimeConstructor::from) -{ - // 1. Set options to ? GetOptionsObject(options). - auto const* options = TRY(get_options_object(vm, vm.argument(1))); - - auto item = vm.argument(0); - - // 2. If Type(item) is Object and item has an [[InitializedTemporalZonedDateTime]] internal slot, then - if (item.is_object() && is(item.as_object())) { - auto& item_object = static_cast(item.as_object()); - - // a. Perform ? ToTemporalOverflow(options). - (void)TRY(to_temporal_overflow(vm, options)); - - // b. Perform ? ToTemporalDisambiguation(options). - (void)TRY(to_temporal_disambiguation(vm, options)); - - // c. Perform ? ToTemporalOffset(options, "reject"). - (void)TRY(to_temporal_offset(vm, options, "reject"sv)); - - // d. Return ! CreateTemporalZonedDateTime(item.[[Nanoseconds]], item.[[TimeZone]], item.[[Calendar]]). - return MUST(create_temporal_zoned_date_time(vm, item_object.nanoseconds(), item_object.time_zone(), item_object.calendar())); - } - - // 3. Return ? ToTemporalZonedDateTime(item, options). - return TRY(to_temporal_zoned_date_time(vm, item, options)); -} - -// 6.2.3 Temporal.ZonedDateTime.compare ( one, two ), https://tc39.es/proposal-temporal/#sec-temporal.zoneddatetime.compare -JS_DEFINE_NATIVE_FUNCTION(ZonedDateTimeConstructor::compare) -{ - // 1. Set one to ? ToTemporalZonedDateTime(one). - auto* one = TRY(to_temporal_zoned_date_time(vm, vm.argument(0))); - - // 2. Set two to ? ToTemporalZonedDateTime(two). - auto* two = TRY(to_temporal_zoned_date_time(vm, vm.argument(1))); - - // 3. Return 𝔽(! CompareEpochNanoseconds(one.[[Nanoseconds]], two.[[Nanoseconds]])). - return Value(compare_epoch_nanoseconds(one->nanoseconds(), two->nanoseconds())); -} - -} diff --git a/Libraries/LibJS/Runtime/Temporal/ZonedDateTimeConstructor.h b/Libraries/LibJS/Runtime/Temporal/ZonedDateTimeConstructor.h deleted file mode 100644 index 2ee8c13a051..00000000000 --- a/Libraries/LibJS/Runtime/Temporal/ZonedDateTimeConstructor.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2021-2022, Linus Groh - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include - -namespace JS::Temporal { - -class ZonedDateTimeConstructor final : public NativeFunction { - JS_OBJECT(ZonedDateTimeConstructor, NativeFunction); - GC_DECLARE_ALLOCATOR(ZonedDateTimeConstructor); - -public: - virtual void initialize(Realm&) override; - virtual ~ZonedDateTimeConstructor() override = default; - - virtual ThrowCompletionOr call() override; - virtual ThrowCompletionOr> construct(FunctionObject& new_target) override; - -private: - explicit ZonedDateTimeConstructor(Realm&); - - virtual bool has_constructor() const override { return true; } - - JS_DECLARE_NATIVE_FUNCTION(from); - JS_DECLARE_NATIVE_FUNCTION(compare); -}; - -} diff --git a/Libraries/LibJS/Runtime/Temporal/ZonedDateTimePrototype.cpp b/Libraries/LibJS/Runtime/Temporal/ZonedDateTimePrototype.cpp deleted file mode 100644 index d78d4ed1ada..00000000000 --- a/Libraries/LibJS/Runtime/Temporal/ZonedDateTimePrototype.cpp +++ /dev/null @@ -1,1418 +0,0 @@ -/* - * Copyright (c) 2021-2023, Linus Groh - * Copyright (c) 2021, Luke Wilde - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace JS::Temporal { - -GC_DEFINE_ALLOCATOR(ZonedDateTimePrototype); - -// 6.3 Properties of the Temporal.ZonedDateTime Prototype Object, https://tc39.es/proposal-temporal/#sec-properties-of-the-temporal-zoneddatetime-prototype-object -ZonedDateTimePrototype::ZonedDateTimePrototype(Realm& realm) - : PrototypeObject(realm.intrinsics().object_prototype()) -{ -} - -void ZonedDateTimePrototype::initialize(Realm& realm) -{ - Base::initialize(realm); - - auto& vm = this->vm(); - - // 6.3.2 Temporal.ZonedDateTime.prototype[ @@toStringTag ], https://tc39.es/proposal-temporal/#sec-temporal.zoneddatetime.prototype-@@tostringtag - define_direct_property(vm.well_known_symbol_to_string_tag(), PrimitiveString::create(vm, "Temporal.ZonedDateTime"_string), Attribute::Configurable); - - define_native_accessor(realm, vm.names.calendar, calendar_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.calendarId, calendar_id_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.timeZone, time_zone_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.year, year_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.month, month_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.monthCode, month_code_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.day, day_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.hour, hour_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.minute, minute_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.second, second_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.millisecond, millisecond_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.microsecond, microsecond_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.nanosecond, nanosecond_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.epochSeconds, epoch_seconds_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.epochMilliseconds, epoch_milliseconds_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.epochMicroseconds, epoch_microseconds_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.epochNanoseconds, epoch_nanoseconds_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.dayOfWeek, day_of_week_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.dayOfYear, day_of_year_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.weekOfYear, week_of_year_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.yearOfWeek, year_of_week_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.hoursInDay, hours_in_day_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.daysInWeek, days_in_week_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.daysInMonth, days_in_month_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.daysInYear, days_in_year_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.monthsInYear, months_in_year_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.inLeapYear, in_leap_year_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.offsetNanoseconds, offset_nanoseconds_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.offset, offset_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.era, era_getter, {}, Attribute::Configurable); - define_native_accessor(realm, vm.names.eraYear, era_year_getter, {}, Attribute::Configurable); - - u8 attr = Attribute::Writable | Attribute::Configurable; - define_native_function(realm, vm.names.with, with, 1, attr); - define_native_function(realm, vm.names.withPlainTime, with_plain_time, 0, attr); - define_native_function(realm, vm.names.withPlainDate, with_plain_date, 1, attr); - define_native_function(realm, vm.names.withTimeZone, with_time_zone, 1, attr); - define_native_function(realm, vm.names.withCalendar, with_calendar, 1, attr); - define_native_function(realm, vm.names.add, add, 1, attr); - define_native_function(realm, vm.names.subtract, subtract, 1, attr); - define_native_function(realm, vm.names.until, until, 1, attr); - define_native_function(realm, vm.names.since, since, 1, attr); - define_native_function(realm, vm.names.round, round, 1, attr); - define_native_function(realm, vm.names.equals, equals, 1, attr); - define_native_function(realm, vm.names.toString, to_string, 0, attr); - define_native_function(realm, vm.names.toLocaleString, to_locale_string, 0, attr); - define_native_function(realm, vm.names.toJSON, to_json, 0, attr); - define_native_function(realm, vm.names.valueOf, value_of, 0, attr); - define_native_function(realm, vm.names.startOfDay, start_of_day, 0, attr); - define_native_function(realm, vm.names.toInstant, to_instant, 0, attr); - define_native_function(realm, vm.names.toPlainDate, to_plain_date, 0, attr); - define_native_function(realm, vm.names.toPlainTime, to_plain_time, 0, attr); - define_native_function(realm, vm.names.toPlainDateTime, to_plain_date_time, 0, attr); - define_native_function(realm, vm.names.toPlainYearMonth, to_plain_year_month, 0, attr); - define_native_function(realm, vm.names.toPlainMonthDay, to_plain_month_day, 0, attr); - define_native_function(realm, vm.names.getISOFields, get_iso_fields, 0, attr); -} - -// 6.3.3 get Temporal.ZonedDateTime.prototype.calendar, https://tc39.es/proposal-temporal/#sec-get-temporal.zoneddatetime.prototype.calendar -JS_DEFINE_NATIVE_FUNCTION(ZonedDateTimePrototype::calendar_getter) -{ - // 1. Let zonedDateTime be the this value. - // 2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]). - auto zoned_date_time = TRY(typed_this_object(vm)); - - // 3. Return zonedDateTime.[[Calendar]]. - return Value(&zoned_date_time->calendar()); -} - -// 6.3.4 get Temporal.ZonedDateTime.prototype.timeZone, https://tc39.es/proposal-temporal/#sec-get-temporal.zoneddatetime.prototype.timezone -JS_DEFINE_NATIVE_FUNCTION(ZonedDateTimePrototype::time_zone_getter) -{ - // 1. Let zonedDateTime be the this value. - // 2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]). - auto zoned_date_time = TRY(typed_this_object(vm)); - - // 3. Return zonedDateTime.[[TimeZone]]. - return Value(&zoned_date_time->time_zone()); -} - -// 6.3.5 get Temporal.ZonedDateTime.prototype.year, https://tc39.es/proposal-temporal/#sec-get-temporal.zoneddatetime.prototype.year -JS_DEFINE_NATIVE_FUNCTION(ZonedDateTimePrototype::year_getter) -{ - // 1. Let zonedDateTime be the this value. - // 2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]). - auto zoned_date_time = TRY(typed_this_object(vm)); - - // 3. Let timeZone be zonedDateTime.[[TimeZone]]. - auto& time_zone = zoned_date_time->time_zone(); - - // 4. Let instant be ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]). - auto* instant = MUST(create_temporal_instant(vm, zoned_date_time->nanoseconds())); - - // 5. Let calendar be zonedDateTime.[[Calendar]]. - auto& calendar = zoned_date_time->calendar(); - - // 6. Let temporalDateTime be ? BuiltinTimeZoneGetPlainDateTimeFor(timeZone, instant, calendar). - auto* temporal_date_time = TRY(builtin_time_zone_get_plain_date_time_for(vm, &time_zone, *instant, calendar)); - - // 7. Return 𝔽(? CalendarYear(calendar, temporalDateTime)). - return TRY(calendar_year(vm, calendar, *temporal_date_time)); -} - -// 6.3.6 get Temporal.ZonedDateTime.prototype.month, https://tc39.es/proposal-temporal/#sec-get-temporal.zoneddatetime.prototype.month -JS_DEFINE_NATIVE_FUNCTION(ZonedDateTimePrototype::month_getter) -{ - // 1. Let zonedDateTime be the this value. - // 2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]). - auto zoned_date_time = TRY(typed_this_object(vm)); - - // 3. Let timeZone be zonedDateTime.[[TimeZone]]. - auto& time_zone = zoned_date_time->time_zone(); - - // 4. Let instant be ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]). - auto* instant = MUST(create_temporal_instant(vm, zoned_date_time->nanoseconds())); - - // 5. Let calendar be zonedDateTime.[[Calendar]]. - auto& calendar = zoned_date_time->calendar(); - - // 6. Let temporalDateTime be ? BuiltinTimeZoneGetPlainDateTimeFor(timeZone, instant, calendar). - auto* temporal_date_time = TRY(builtin_time_zone_get_plain_date_time_for(vm, &time_zone, *instant, calendar)); - - // 7. Return 𝔽(? CalendarMonth(calendar, temporalDateTime)). - return TRY(calendar_month(vm, calendar, *temporal_date_time)); -} - -// 6.3.7 get Temporal.ZonedDateTime.prototype.monthCode, https://tc39.es/proposal-temporal/#sec-get-temporal.zoneddatetime.prototype.monthcode -JS_DEFINE_NATIVE_FUNCTION(ZonedDateTimePrototype::month_code_getter) -{ - // 1. Let zonedDateTime be the this value. - // 2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]). - auto zoned_date_time = TRY(typed_this_object(vm)); - - // 3. Let timeZone be zonedDateTime.[[TimeZone]]. - auto& time_zone = zoned_date_time->time_zone(); - - // 4. Let instant be ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]). - auto* instant = MUST(create_temporal_instant(vm, zoned_date_time->nanoseconds())); - - // 5. Let calendar be zonedDateTime.[[Calendar]]. - auto& calendar = zoned_date_time->calendar(); - - // 6. Let temporalDateTime be ? BuiltinTimeZoneGetPlainDateTimeFor(timeZone, instant, calendar). - auto* temporal_date_time = TRY(builtin_time_zone_get_plain_date_time_for(vm, &time_zone, *instant, calendar)); - - // 7. Return ? CalendarMonthCode(calendar, temporalDateTime). - return PrimitiveString::create(vm, TRY(calendar_month_code(vm, calendar, *temporal_date_time))); -} - -// 6.3.8 get Temporal.ZonedDateTime.prototype.day, https://tc39.es/proposal-temporal/#sec-get-temporal.zoneddatetime.prototype.day -JS_DEFINE_NATIVE_FUNCTION(ZonedDateTimePrototype::day_getter) -{ - // 1. Let zonedDateTime be the this value. - // 2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]). - auto zoned_date_time = TRY(typed_this_object(vm)); - - // 3. Let timeZone be zonedDateTime.[[TimeZone]]. - auto& time_zone = zoned_date_time->time_zone(); - - // 4. Let instant be ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]). - auto* instant = MUST(create_temporal_instant(vm, zoned_date_time->nanoseconds())); - - // 5. Let calendar be zonedDateTime.[[Calendar]]. - auto& calendar = zoned_date_time->calendar(); - - // 6. Let temporalDateTime be ? BuiltinTimeZoneGetPlainDateTimeFor(timeZone, instant, calendar). - auto* temporal_date_time = TRY(builtin_time_zone_get_plain_date_time_for(vm, &time_zone, *instant, calendar)); - - // 7. Return 𝔽(? CalendarDay(calendar, temporalDateTime)). - return TRY(calendar_day(vm, calendar, *temporal_date_time)); -} - -// 6.3.9 get Temporal.ZonedDateTime.prototype.hour, https://tc39.es/proposal-temporal/#sec-get-temporal.zoneddatetime.prototype.hour -JS_DEFINE_NATIVE_FUNCTION(ZonedDateTimePrototype::hour_getter) -{ - // 1. Let zonedDateTime be the this value. - // 2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]). - auto zoned_date_time = TRY(typed_this_object(vm)); - - // 3. Let timeZone be zonedDateTime.[[TimeZone]]. - auto& time_zone = zoned_date_time->time_zone(); - - // 4. Let instant be ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]). - auto* instant = MUST(create_temporal_instant(vm, zoned_date_time->nanoseconds())); - - // 5. Let calendar be zonedDateTime.[[Calendar]]. - auto& calendar = zoned_date_time->calendar(); - - // 6. Let temporalDateTime be ? BuiltinTimeZoneGetPlainDateTimeFor(timeZone, instant, calendar). - auto* temporal_date_time = TRY(builtin_time_zone_get_plain_date_time_for(vm, &time_zone, *instant, calendar)); - - // 7. Return 𝔽(temporalDateTime.[[ISOHour]]). - return Value(temporal_date_time->iso_hour()); -} - -// 6.3.10 get Temporal.ZonedDateTime.prototype.minute, https://tc39.es/proposal-temporal/#sec-get-temporal.zoneddatetime.prototype.minute -JS_DEFINE_NATIVE_FUNCTION(ZonedDateTimePrototype::minute_getter) -{ - // 1. Let zonedDateTime be the this value. - // 2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]). - auto zoned_date_time = TRY(typed_this_object(vm)); - - // 3. Let timeZone be zonedDateTime.[[TimeZone]]. - auto& time_zone = zoned_date_time->time_zone(); - - // 4. Let instant be ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]). - auto* instant = MUST(create_temporal_instant(vm, zoned_date_time->nanoseconds())); - - // 5. Let calendar be zonedDateTime.[[Calendar]]. - auto& calendar = zoned_date_time->calendar(); - - // 6. Let temporalDateTime be ? BuiltinTimeZoneGetPlainDateTimeFor(timeZone, instant, calendar). - auto* temporal_date_time = TRY(builtin_time_zone_get_plain_date_time_for(vm, &time_zone, *instant, calendar)); - - // 7. Return 𝔽(temporalDateTime.[[ISOMinute]]). - return Value(temporal_date_time->iso_minute()); -} - -// 6.3.11 get Temporal.ZonedDateTime.prototype.second, https://tc39.es/proposal-temporal/#sec-get-temporal.zoneddatetime.prototype.second -JS_DEFINE_NATIVE_FUNCTION(ZonedDateTimePrototype::second_getter) -{ - // 1. Let zonedDateTime be the this value. - // 2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]). - auto zoned_date_time = TRY(typed_this_object(vm)); - - // 3. Let timeZone be zonedDateTime.[[TimeZone]]. - auto& time_zone = zoned_date_time->time_zone(); - - // 4. Let instant be ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]). - auto* instant = MUST(create_temporal_instant(vm, zoned_date_time->nanoseconds())); - - // 5. Let calendar be zonedDateTime.[[Calendar]]. - auto& calendar = zoned_date_time->calendar(); - - // 6. Let temporalDateTime be ? BuiltinTimeZoneGetPlainDateTimeFor(timeZone, instant, calendar). - auto* temporal_date_time = TRY(builtin_time_zone_get_plain_date_time_for(vm, &time_zone, *instant, calendar)); - - // 7. Return 𝔽(temporalDateTime.[[ISOSecond]]). - return Value(temporal_date_time->iso_second()); -} - -// 6.3.12 get Temporal.ZonedDateTime.prototype.millisecond, https://tc39.es/proposal-temporal/#sec-get-temporal.zoneddatetime.prototype.millisecond -JS_DEFINE_NATIVE_FUNCTION(ZonedDateTimePrototype::millisecond_getter) -{ - // 1. Let zonedDateTime be the this value. - // 2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]). - auto zoned_date_time = TRY(typed_this_object(vm)); - - // 3. Let timeZone be zonedDateTime.[[TimeZone]]. - auto& time_zone = zoned_date_time->time_zone(); - - // 4. Let instant be ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]). - auto* instant = MUST(create_temporal_instant(vm, zoned_date_time->nanoseconds())); - - // 5. Let calendar be zonedDateTime.[[Calendar]]. - auto& calendar = zoned_date_time->calendar(); - - // 6. Let temporalDateTime be ? BuiltinTimeZoneGetPlainDateTimeFor(timeZone, instant, calendar). - auto* temporal_date_time = TRY(builtin_time_zone_get_plain_date_time_for(vm, &time_zone, *instant, calendar)); - - // 7. Return 𝔽(temporalDateTime.[[ISOMillisecond]]). - return Value(temporal_date_time->iso_millisecond()); -} - -// 6.3.13 get Temporal.ZonedDateTime.prototype.microsecond, https://tc39.es/proposal-temporal/#sec-get-temporal.zoneddatetime.prototype.microsecond -JS_DEFINE_NATIVE_FUNCTION(ZonedDateTimePrototype::microsecond_getter) -{ - // 1. Let zonedDateTime be the this value. - // 2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]). - auto zoned_date_time = TRY(typed_this_object(vm)); - - // 3. Let timeZone be zonedDateTime.[[TimeZone]]. - auto& time_zone = zoned_date_time->time_zone(); - - // 4. Let instant be ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]). - auto* instant = MUST(create_temporal_instant(vm, zoned_date_time->nanoseconds())); - - // 5. Let calendar be zonedDateTime.[[Calendar]]. - auto& calendar = zoned_date_time->calendar(); - - // 6. Let temporalDateTime be ? BuiltinTimeZoneGetPlainDateTimeFor(timeZone, instant, calendar). - auto* temporal_date_time = TRY(builtin_time_zone_get_plain_date_time_for(vm, &time_zone, *instant, calendar)); - - // 7. Return 𝔽(temporalDateTime.[[ISOMicrosecond]]). - return Value(temporal_date_time->iso_microsecond()); -} - -// 6.3.14 get Temporal.ZonedDateTime.prototype.nanosecond, https://tc39.es/proposal-temporal/#sec-get-temporal.zoneddatetime.prototype.nanosecond -JS_DEFINE_NATIVE_FUNCTION(ZonedDateTimePrototype::nanosecond_getter) -{ - // 1. Let zonedDateTime be the this value. - // 2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]). - auto zoned_date_time = TRY(typed_this_object(vm)); - - // 3. Let timeZone be zonedDateTime.[[TimeZone]]. - auto& time_zone = zoned_date_time->time_zone(); - - // 4. Let instant be ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]). - auto* instant = MUST(create_temporal_instant(vm, zoned_date_time->nanoseconds())); - - // 5. Let calendar be zonedDateTime.[[Calendar]]. - auto& calendar = zoned_date_time->calendar(); - - // 6. Let temporalDateTime be ? BuiltinTimeZoneGetPlainDateTimeFor(timeZone, instant, calendar). - auto* temporal_date_time = TRY(builtin_time_zone_get_plain_date_time_for(vm, &time_zone, *instant, calendar)); - - // 7. Return 𝔽(temporalDateTime.[[ISONanosecond]]). - return Value(temporal_date_time->iso_nanosecond()); -} - -// 6.3.15 get Temporal.ZonedDateTime.prototype.epochSeconds, https://tc39.es/proposal-temporal/#sec-get-temporal.zoneddatetime.prototype.epochseconds -JS_DEFINE_NATIVE_FUNCTION(ZonedDateTimePrototype::epoch_seconds_getter) -{ - // 1. Let zonedDateTime be the this value. - // 2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]). - auto zoned_date_time = TRY(typed_this_object(vm)); - - // 3. Let ns be zonedDateTime.[[Nanoseconds]]. - auto& ns = zoned_date_time->nanoseconds(); - - // 4. Let s be truncate(ℝ(ns) / 10^9). - auto s = ns.big_integer().divided_by(Crypto::UnsignedBigInteger { 1'000'000'000 }).quotient; - - // 5. Return 𝔽(s). - return Value((double)s.to_base_deprecated(10).to_number().value()); -} - -// 6.3.16 get Temporal.ZonedDateTime.prototype.epochMilliseconds, https://tc39.es/proposal-temporal/#sec-get-temporal.zoneddatetime.prototype.epochmilliseconds -JS_DEFINE_NATIVE_FUNCTION(ZonedDateTimePrototype::epoch_milliseconds_getter) -{ - // 1. Let zonedDateTime be the this value. - // 2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]). - auto zoned_date_time = TRY(typed_this_object(vm)); - - // 3. Let ns be zonedDateTime.[[Nanoseconds]]. - auto& ns = zoned_date_time->nanoseconds(); - - // 4. Let ms be truncate(ℝ(ns) / 10^6). - auto ms = ns.big_integer().divided_by(Crypto::UnsignedBigInteger { 1'000'000 }).quotient; - - // 5. Return 𝔽(ms). - return Value((double)ms.to_base_deprecated(10).to_number().value()); -} - -// 6.3.17 get Temporal.ZonedDateTime.prototype.epochMicroseconds, https://tc39.es/proposal-temporal/#sec-get-temporal.zoneddatetime.prototype.epochmicroseconds -JS_DEFINE_NATIVE_FUNCTION(ZonedDateTimePrototype::epoch_microseconds_getter) -{ - // 1. Let zonedDateTime be the this value. - // 2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]). - auto zoned_date_time = TRY(typed_this_object(vm)); - - // 3. Let ns be zonedDateTime.[[Nanoseconds]]. - auto& ns = zoned_date_time->nanoseconds(); - - // 4. Let µs be truncate(ℝ(ns) / 10^3). - auto us = ns.big_integer().divided_by(Crypto::UnsignedBigInteger { 1'000 }).quotient; - - // 5. Return ℤ(µs). - return BigInt::create(vm, move(us)); -} - -// 6.3.18 get Temporal.ZonedDateTime.prototype.epochNanoseconds, https://tc39.es/proposal-temporal/#sec-get-temporal.zoneddatetime.prototype.epochnanoseconds -JS_DEFINE_NATIVE_FUNCTION(ZonedDateTimePrototype::epoch_nanoseconds_getter) -{ - // 1. Let zonedDateTime be the this value. - // 2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]). - auto zoned_date_time = TRY(typed_this_object(vm)); - - // 3. Return zonedDateTime.[[Nanoseconds]]. - return &zoned_date_time->nanoseconds(); -} - -// 6.3.19 get Temporal.ZonedDateTime.prototype.dayOfWeek, https://tc39.es/proposal-temporal/#sec-get-temporal.zoneddatetime.prototype.dayofweek -JS_DEFINE_NATIVE_FUNCTION(ZonedDateTimePrototype::day_of_week_getter) -{ - // 1. Let zonedDateTime be the this value. - // 2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]). - auto zoned_date_time = TRY(typed_this_object(vm)); - - // 3. Let timeZone be zonedDateTime.[[TimeZone]]. - auto& time_zone = zoned_date_time->time_zone(); - - // 4. Let instant be ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]). - auto* instant = MUST(create_temporal_instant(vm, zoned_date_time->nanoseconds())); - - // 5. Let calendar be zonedDateTime.[[Calendar]]. - auto& calendar = zoned_date_time->calendar(); - - // 6. Let temporalDateTime be ? BuiltinTimeZoneGetPlainDateTimeFor(timeZone, instant, calendar). - auto* temporal_date_time = TRY(builtin_time_zone_get_plain_date_time_for(vm, &time_zone, *instant, calendar)); - - // 7. Return 𝔽(? CalendarDayOfWeek(calendar, temporalDateTime)). - return TRY(calendar_day_of_week(vm, calendar, *temporal_date_time)); -} - -// 6.3.20 get Temporal.ZonedDateTime.prototype.dayOfYear, https://tc39.es/proposal-temporal/#sec-get-temporal.zoneddatetime.prototype.dayofyear -JS_DEFINE_NATIVE_FUNCTION(ZonedDateTimePrototype::day_of_year_getter) -{ - // 1. Let zonedDateTime be the this value. - // 2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]). - auto zoned_date_time = TRY(typed_this_object(vm)); - - // 3. Let timeZone be zonedDateTime.[[TimeZone]]. - auto& time_zone = zoned_date_time->time_zone(); - - // 4. Let instant be ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]). - auto* instant = MUST(create_temporal_instant(vm, zoned_date_time->nanoseconds())); - - // 5. Let calendar be zonedDateTime.[[Calendar]]. - auto& calendar = zoned_date_time->calendar(); - - // 6. Let temporalDateTime be ? BuiltinTimeZoneGetPlainDateTimeFor(timeZone, instant, calendar). - auto* temporal_date_time = TRY(builtin_time_zone_get_plain_date_time_for(vm, &time_zone, *instant, calendar)); - - // 7. Return 𝔽(? CalendarDayOfYear(calendar, temporalDateTime)). - return TRY(calendar_day_of_year(vm, calendar, *temporal_date_time)); -} - -// 6.3.21 get Temporal.ZonedDateTime.prototype.weekOfYear, https://tc39.es/proposal-temporal/#sec-get-temporal.zoneddatetime.prototype.weekofyear -JS_DEFINE_NATIVE_FUNCTION(ZonedDateTimePrototype::week_of_year_getter) -{ - // 1. Let zonedDateTime be the this value. - // 2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]). - auto zoned_date_time = TRY(typed_this_object(vm)); - - // 3. Let timeZone be zonedDateTime.[[TimeZone]]. - auto& time_zone = zoned_date_time->time_zone(); - - // 4. Let instant be ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]). - auto* instant = MUST(create_temporal_instant(vm, zoned_date_time->nanoseconds())); - - // 5. Let calendar be zonedDateTime.[[Calendar]]. - auto& calendar = zoned_date_time->calendar(); - - // 6. Let temporalDateTime be ? BuiltinTimeZoneGetPlainDateTimeFor(timeZone, instant, calendar). - auto* temporal_date_time = TRY(builtin_time_zone_get_plain_date_time_for(vm, &time_zone, *instant, calendar)); - - // 7. Return 𝔽(? CalendarWeekOfYear(calendar, temporalDateTime)). - return TRY(calendar_week_of_year(vm, calendar, *temporal_date_time)); -} - -// 6.3.22 get Temporal.ZonedDateTime.prototype.yearOfWeek, https://tc39.es/proposal-temporal/#sec-get-temporal.zoneddatetime.prototype.yearofweek -JS_DEFINE_NATIVE_FUNCTION(ZonedDateTimePrototype::year_of_week_getter) -{ - // 1. Let zonedDateTime be the this value. - // 2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]). - auto zoned_date_time = TRY(typed_this_object(vm)); - - // 3. Let timeZone be zonedDateTime.[[TimeZone]]. - auto& time_zone = zoned_date_time->time_zone(); - - // 4. Let instant be ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]). - auto* instant = MUST(create_temporal_instant(vm, zoned_date_time->nanoseconds())); - - // 5. Let calendar be zonedDateTime.[[Calendar]]. - auto& calendar = zoned_date_time->calendar(); - - // 6. Let temporalDateTime be ? BuiltinTimeZoneGetPlainDateTimeFor(timeZone, instant, calendar). - auto* temporal_date_time = TRY(builtin_time_zone_get_plain_date_time_for(vm, &time_zone, *instant, calendar)); - - // 7. Return 𝔽(? CalendarYearOfWeek(calendar, temporalDateTime)). - return TRY(calendar_year_of_week(vm, calendar, *temporal_date_time)); -} - -// 6.3.23 get Temporal.ZonedDateTime.prototype.hoursInDay, https://tc39.es/proposal-temporal/#sec-get-temporal.zoneddatetime.prototype.hoursinday -JS_DEFINE_NATIVE_FUNCTION(ZonedDateTimePrototype::hours_in_day_getter) -{ - // 1. Let zonedDateTime be the this value. - // 2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]). - auto zoned_date_time = TRY(typed_this_object(vm)); - - // 3. Let timeZone be zonedDateTime.[[TimeZone]]. - auto& time_zone = zoned_date_time->time_zone(); - - // 4. Let instant be ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]). - auto* instant = MUST(create_temporal_instant(vm, zoned_date_time->nanoseconds())); - - // 5. Let isoCalendar be ! GetISO8601Calendar(). - auto* iso_calendar = get_iso8601_calendar(vm); - - // 6. Let temporalDateTime be ? BuiltinTimeZoneGetPlainDateTimeFor(timeZone, instant, isoCalendar). - auto* temporal_date_time = TRY(builtin_time_zone_get_plain_date_time_for(vm, &time_zone, *instant, *iso_calendar)); - - // 7. Let year be temporalDateTime.[[ISOYear]]. - auto year = temporal_date_time->iso_year(); - - // 8. Let month be temporalDateTime.[[ISOMonth]]. - auto month = temporal_date_time->iso_month(); - - // 9. Let day be temporalDateTime.[[ISODay]]. - auto day = temporal_date_time->iso_day(); - - // 10. Let today be ? CreateTemporalDateTime(year, month, day, 0, 0, 0, 0, 0, 0, isoCalendar). - auto* today = TRY(create_temporal_date_time(vm, year, month, day, 0, 0, 0, 0, 0, 0, *iso_calendar)); - - // 11. Let tomorrowFields be BalanceISODate(year, month, day + 1). - auto tomorrow_fields = balance_iso_date(year, month, day + 1); - - // 12. Let tomorrow be ? CreateTemporalDateTime(tomorrowFields.[[Year]], tomorrowFields.[[Month]], tomorrowFields.[[Day]], 0, 0, 0, 0, 0, 0, isoCalendar). - auto* tomorrow = TRY(create_temporal_date_time(vm, tomorrow_fields.year, tomorrow_fields.month, tomorrow_fields.day, 0, 0, 0, 0, 0, 0, *iso_calendar)); - - // 13. Let todayInstant be ? BuiltinTimeZoneGetInstantFor(timeZone, today, "compatible"). - auto today_instant = TRY(builtin_time_zone_get_instant_for(vm, &time_zone, *today, "compatible"sv)); - - // 14. Let tomorrowInstant be ? BuiltinTimeZoneGetInstantFor(timeZone, tomorrow, "compatible"). - auto tomorrow_instant = TRY(builtin_time_zone_get_instant_for(vm, &time_zone, *tomorrow, "compatible"sv)); - - // 15. Let diffNs be tomorrowInstant.[[Nanoseconds]] - todayInstant.[[Nanoseconds]]. - auto diff_ns = tomorrow_instant->nanoseconds().big_integer().minus(today_instant->nanoseconds().big_integer()); - - // 16. Return 𝔽(diffNs / (3.6 × 10^12)). - auto hours_diff_ns = diff_ns.divided_by("3600000000000"_bigint).quotient; - return Value(hours_diff_ns.to_double()); -} - -// 6.3.24 get Temporal.ZonedDateTime.prototype.daysInWeek, https://tc39.es/proposal-temporal/#sec-get-temporal.zoneddatetime.prototype.daysinweek -JS_DEFINE_NATIVE_FUNCTION(ZonedDateTimePrototype::days_in_week_getter) -{ - // 1. Let zonedDateTime be the this value. - // 2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]). - auto zoned_date_time = TRY(typed_this_object(vm)); - - // 3. Let timeZone be zonedDateTime.[[TimeZone]]. - auto& time_zone = zoned_date_time->time_zone(); - - // 4. Let instant be ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]). - auto* instant = MUST(create_temporal_instant(vm, zoned_date_time->nanoseconds())); - - // 5. Let calendar be zonedDateTime.[[Calendar]]. - auto& calendar = zoned_date_time->calendar(); - - // 6. Let temporalDateTime be ? BuiltinTimeZoneGetPlainDateTimeFor(timeZone, instant, calendar). - auto* temporal_date_time = TRY(builtin_time_zone_get_plain_date_time_for(vm, &time_zone, *instant, calendar)); - - // 7. Return 𝔽(? CalendarDaysInWeek(calendar, temporalDateTime)). - return TRY(calendar_days_in_week(vm, calendar, *temporal_date_time)); -} - -// 6.3.25 get Temporal.ZonedDateTime.prototype.daysInMonth, https://tc39.es/proposal-temporal/#sec-get-temporal.zoneddatetime.prototype.daysinmonth -JS_DEFINE_NATIVE_FUNCTION(ZonedDateTimePrototype::days_in_month_getter) -{ - // 1. Let zonedDateTime be the this value. - // 2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]). - auto zoned_date_time = TRY(typed_this_object(vm)); - - // 3. Let timeZone be zonedDateTime.[[TimeZone]]. - auto& time_zone = zoned_date_time->time_zone(); - - // 4. Let instant be ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]). - auto* instant = MUST(create_temporal_instant(vm, zoned_date_time->nanoseconds())); - - // 5. Let calendar be zonedDateTime.[[Calendar]]. - auto& calendar = zoned_date_time->calendar(); - - // 6. Let temporalDateTime be ? BuiltinTimeZoneGetPlainDateTimeFor(timeZone, instant, calendar). - auto* temporal_date_time = TRY(builtin_time_zone_get_plain_date_time_for(vm, &time_zone, *instant, calendar)); - - // 7. Return 𝔽(? CalendarDaysInMonth(calendar, temporalDateTime)). - return TRY(calendar_days_in_month(vm, calendar, *temporal_date_time)); -} - -// 6.3.26 get Temporal.ZonedDateTime.prototype.daysInYear, https://tc39.es/proposal-temporal/#sec-get-temporal.zoneddatetime.prototype.daysinyear -JS_DEFINE_NATIVE_FUNCTION(ZonedDateTimePrototype::days_in_year_getter) -{ - // 1. Let zonedDateTime be the this value. - // 2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]). - auto zoned_date_time = TRY(typed_this_object(vm)); - - // 3. Let timeZone be zonedDateTime.[[TimeZone]]. - auto& time_zone = zoned_date_time->time_zone(); - - // 4. Let instant be ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]). - auto* instant = MUST(create_temporal_instant(vm, zoned_date_time->nanoseconds())); - - // 5. Let calendar be zonedDateTime.[[Calendar]]. - auto& calendar = zoned_date_time->calendar(); - - // 6. Let temporalDateTime be ? BuiltinTimeZoneGetPlainDateTimeFor(timeZone, instant, calendar). - auto* temporal_date_time = TRY(builtin_time_zone_get_plain_date_time_for(vm, &time_zone, *instant, calendar)); - - // 7. Return 𝔽(? CalendarDaysInYear(calendar, temporalDateTime)). - return TRY(calendar_days_in_year(vm, calendar, *temporal_date_time)); -} - -// 6.3.27 get Temporal.ZonedDateTime.prototype.monthsInYear, https://tc39.es/proposal-temporal/#sec-get-temporal.zoneddatetime.prototype.monthsinyear -JS_DEFINE_NATIVE_FUNCTION(ZonedDateTimePrototype::months_in_year_getter) -{ - // 1. Let zonedDateTime be the this value. - // 2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]). - auto zoned_date_time = TRY(typed_this_object(vm)); - - // 3. Let timeZone be zonedDateTime.[[TimeZone]]. - auto& time_zone = zoned_date_time->time_zone(); - - // 4. Let instant be ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]). - auto* instant = MUST(create_temporal_instant(vm, zoned_date_time->nanoseconds())); - - // 5. Let calendar be zonedDateTime.[[Calendar]]. - auto& calendar = zoned_date_time->calendar(); - - // 6. Let temporalDateTime be ? BuiltinTimeZoneGetPlainDateTimeFor(timeZone, instant, calendar). - auto* temporal_date_time = TRY(builtin_time_zone_get_plain_date_time_for(vm, &time_zone, *instant, calendar)); - - // 7. Return 𝔽(? CalendarMonthsInYear(calendar, temporalDateTime)). - return TRY(calendar_months_in_year(vm, calendar, *temporal_date_time)); -} - -// 6.3.28 get Temporal.ZonedDateTime.prototype.inLeapYear, https://tc39.es/proposal-temporal/#sec-get-temporal.zoneddatetime.prototype.inleapyear -JS_DEFINE_NATIVE_FUNCTION(ZonedDateTimePrototype::in_leap_year_getter) -{ - // 1. Let zonedDateTime be the this value. - // 2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]). - auto zoned_date_time = TRY(typed_this_object(vm)); - - // 3. Let timeZone be zonedDateTime.[[TimeZone]]. - auto& time_zone = zoned_date_time->time_zone(); - - // 4. Let instant be ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]). - auto* instant = MUST(create_temporal_instant(vm, zoned_date_time->nanoseconds())); - - // 5. Let calendar be zonedDateTime.[[Calendar]]. - auto& calendar = zoned_date_time->calendar(); - - // 6. Let temporalDateTime be ? BuiltinTimeZoneGetPlainDateTimeFor(timeZone, instant, calendar). - auto* temporal_date_time = TRY(builtin_time_zone_get_plain_date_time_for(vm, &time_zone, *instant, calendar)); - - // 7. Return ? CalendarInLeapYear(calendar, temporalDateTime). - return TRY(calendar_in_leap_year(vm, calendar, *temporal_date_time)); -} - -// 6.3.29 get Temporal.ZonedDateTime.prototype.offsetNanoseconds, https://tc39.es/proposal-temporal/#sec-get-temporal.zoneddatetime.prototype.offsetnanoseconds -JS_DEFINE_NATIVE_FUNCTION(ZonedDateTimePrototype::offset_nanoseconds_getter) -{ - // 1. Let zonedDateTime be the this value. - // 2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]). - auto zoned_date_time = TRY(typed_this_object(vm)); - - // 3. Let timeZone be zonedDateTime.[[TimeZone]]. - // 3. Let timeZoneRec be ? CreateTimeZoneMethodsRecord(zonedDateTime.[[TimeZone]], « GET-OFFSET-NANOSECONDS-FOR »). - auto time_zone_record = TRY(create_time_zone_methods_record(vm, GC::Ref { zoned_date_time->time_zone() }, { { TimeZoneMethod::GetOffsetNanosecondsFor } })); - - // 4. Let instant be ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]). - auto* instant = MUST(create_temporal_instant(vm, zoned_date_time->nanoseconds())); - - // 5. Return 𝔽(? GetOffsetNanosecondsFor(timeZoneRec, instant)). - return Value(TRY(get_offset_nanoseconds_for(vm, time_zone_record, *instant))); -} - -// 6.3.30 get Temporal.ZonedDateTime.prototype.offset, https://tc39.es/proposal-temporal/#sec-get-temporal.zoneddatetime.prototype.offset -JS_DEFINE_NATIVE_FUNCTION(ZonedDateTimePrototype::offset_getter) -{ - // 1. Let zonedDateTime be the this value. - // 2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]). - auto zoned_date_time = TRY(typed_this_object(vm)); - - // 3. Let instant be ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]). - auto* instant = MUST(create_temporal_instant(vm, zoned_date_time->nanoseconds())); - - // 4. Return ? BuiltinTimeZoneGetOffsetStringFor(zonedDateTime.[[TimeZone]], instant). - auto offset_string = TRY(builtin_time_zone_get_offset_string_for(vm, &zoned_date_time->time_zone(), *instant)); - return PrimitiveString::create(vm, move(offset_string)); -} - -// 15.6.10.2 get Temporal.ZonedDateTime.prototype.era, https://tc39.es/proposal-temporal/#sec-get-temporal.zoneddatetime.prototype.era -JS_DEFINE_NATIVE_FUNCTION(ZonedDateTimePrototype::era_getter) -{ - // 1. Let zonedDateTime be the this value. - // 2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]). - auto zoned_date_time = TRY(typed_this_object(vm)); - - // 3. Let timeZone be zonedDateTime.[[TimeZone]]. - auto& time_zone = zoned_date_time->time_zone(); - - // 4. Let instant be ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]). - auto* instant = MUST(create_temporal_instant(vm, zoned_date_time->nanoseconds())); - - // 5. Let calendar be zonedDateTime.[[Calendar]]. - auto& calendar = zoned_date_time->calendar(); - - // 6. Let plainDateTime be ? BuiltinTimeZoneGetPlainDateTimeFor(timeZone, instant, calendar). - auto* plain_date_time = TRY(builtin_time_zone_get_plain_date_time_for(vm, &time_zone, *instant, calendar)); - - // 7. Return ? CalendarEra(calendar, plainDateTime). - return TRY(calendar_era(vm, calendar, *plain_date_time)); -} - -// 15.6.10.3 get Temporal.ZonedDateTime.prototype.eraYear, https://tc39.es/proposal-temporal/#sec-get-temporal.zoneddatetime.prototype.erayear -JS_DEFINE_NATIVE_FUNCTION(ZonedDateTimePrototype::era_year_getter) -{ - // 1. Let zonedDateTime be the this value. - // 2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]). - auto zoned_date_time = TRY(typed_this_object(vm)); - - // 3. Let timeZone be zonedDateTime.[[TimeZone]]. - auto& time_zone = zoned_date_time->time_zone(); - - // 4. Let instant be ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]). - auto* instant = MUST(create_temporal_instant(vm, zoned_date_time->nanoseconds())); - - // 5. Let calendar be zonedDateTime.[[Calendar]]. - auto& calendar = zoned_date_time->calendar(); - - // 6. Let plainDateTime be ? BuiltinTimeZoneGetPlainDateTimeFor(timeZone, instant, calendar). - auto* plain_date_time = TRY(builtin_time_zone_get_plain_date_time_for(vm, &time_zone, *instant, calendar)); - - // 7. Return ? CalendarEraYear(calendar, plainDateTime). - return TRY(calendar_era_year(vm, calendar, *plain_date_time)); -} - -// 6.3.31 Temporal.ZonedDateTime.prototype.with ( temporalZonedDateTimeLike [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal.zoneddatetime.prototype.with -JS_DEFINE_NATIVE_FUNCTION(ZonedDateTimePrototype::with) -{ - auto temporal_zoned_date_time_like = vm.argument(0); - - // 1. Let zonedDateTime be the this value. - // 2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]). - auto zoned_date_time = TRY(typed_this_object(vm)); - - // 3. If Type(temporalZonedDateTimeLike) is not Object, then - if (!temporal_zoned_date_time_like.is_object()) { - // a. Throw a TypeError exception. - return vm.throw_completion(ErrorType::NotAnObject, temporal_zoned_date_time_like.to_string_without_side_effects()); - } - - // 4. Perform ? RejectObjectWithCalendarOrTimeZone(temporalZonedDateTimeLike). - TRY(reject_object_with_calendar_or_time_zone(vm, temporal_zoned_date_time_like.as_object())); - - // 5. Let calendar be zonedDateTime.[[Calendar]]. - auto& calendar = zoned_date_time->calendar(); - - // 6. Let fieldNames be ? CalendarFields(calendar, « "day", "hour", "microsecond", "millisecond", "minute", "month", "monthCode", "nanosecond", "second", "year" »). - auto field_names = TRY(calendar_fields(vm, calendar, { "day"sv, "hour"sv, "microsecond"sv, "millisecond"sv, "minute"sv, "month"sv, "monthCode"sv, "nanosecond"sv, "second"sv, "year"sv })); - - // 7. Append "offset" to fieldNames. - field_names.append("offset"_string); - - // 8. Let partialZonedDateTime be ? PrepareTemporalFields(temporalZonedDateTimeLike, fieldNames, partial). - auto* partial_zoned_date_time = TRY(prepare_temporal_fields(vm, temporal_zoned_date_time_like.as_object(), field_names, PrepareTemporalFieldsPartial {})); - - // 9. Set options to ? GetOptionsObject(options). - auto* options = TRY(get_options_object(vm, vm.argument(1))); - - // 10. Let disambiguation be ? ToTemporalDisambiguation(options). - auto disambiguation = TRY(to_temporal_disambiguation(vm, options)); - - // 11. Let offset be ? ToTemporalOffset(options, "prefer"). - auto offset = TRY(to_temporal_offset(vm, options, "prefer"sv)); - - // 12. Let timeZone be zonedDateTime.[[TimeZone]]. - auto& time_zone = zoned_date_time->time_zone(); - - // 13. Append "timeZone" to fieldNames. - field_names.append("timeZone"_string); - - // 14. Let fields be ? PrepareTemporalFields(zonedDateTime, fieldNames, « "timeZone", "offset" »). - auto* fields = TRY(prepare_temporal_fields(vm, zoned_date_time, field_names, Vector { "timeZone"sv, "offset"sv })); - - // 15. Set fields to ? CalendarMergeFields(calendar, fields, partialZonedDateTime). - fields = TRY(calendar_merge_fields(vm, calendar, *fields, *partial_zoned_date_time)); - - // 16. Set fields to ? PrepareTemporalFields(fields, fieldNames, « "timeZone", "offset" »). - fields = TRY(prepare_temporal_fields(vm, *fields, field_names, Vector { "timeZone"sv, "offset"sv })); - - // 17. Let offsetString be ! Get(fields, "offset"). - auto offset_string_value = MUST(fields->get(vm.names.offset)); - - // 18. Assert: Type(offsetString) is String. - VERIFY(offset_string_value.is_string()); - auto offset_string = offset_string_value.as_string().utf8_string(); - - // 19. Let dateTimeResult be ? InterpretTemporalDateTimeFields(calendar, fields, options). - auto date_time_result = TRY(interpret_temporal_date_time_fields(vm, calendar, *fields, options)); - - // 20. If IsTimeZoneOffsetString(offsetString) is false, throw a RangeError exception. - if (!is_time_zone_offset_string(offset_string)) - return vm.throw_completion(ErrorType::TemporalInvalidTimeZoneName, offset_string); - - // 21. Let offsetNanoseconds be ParseTimeZoneOffsetString(offsetString). - auto offset_nanoseconds = parse_time_zone_offset_string(offset_string); - - // 22. Let epochNanoseconds be ? InterpretISODateTimeOffset(dateTimeResult.[[Year]], dateTimeResult.[[Month]], dateTimeResult.[[Day]], dateTimeResult.[[Hour]], dateTimeResult.[[Minute]], dateTimeResult.[[Second]], dateTimeResult.[[Millisecond]], dateTimeResult.[[Microsecond]], dateTimeResult.[[Nanosecond]], option, offsetNanoseconds, timeZone, disambiguation, offset, match exactly). - auto* epoch_nanoseconds = TRY(interpret_iso_date_time_offset(vm, date_time_result.year, date_time_result.month, date_time_result.day, date_time_result.hour, date_time_result.minute, date_time_result.second, date_time_result.millisecond, date_time_result.microsecond, date_time_result.nanosecond, OffsetBehavior::Option, offset_nanoseconds, &time_zone, disambiguation, offset, MatchBehavior::MatchExactly)); - - // 23. Return ! CreateTemporalZonedDateTime(epochNanoseconds, timeZone, calendar). - return MUST(create_temporal_zoned_date_time(vm, *epoch_nanoseconds, time_zone, calendar)); -} - -// 6.3.32 Temporal.ZonedDateTime.prototype.withPlainTime ( [ plainTimeLike ] ), https://tc39.es/proposal-temporal/#sec-temporal.zoneddatetime.prototype.withplaintime -JS_DEFINE_NATIVE_FUNCTION(ZonedDateTimePrototype::with_plain_time) -{ - // 1. Let zonedDateTime be the this value. - // 2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]). - auto zoned_date_time = TRY(typed_this_object(vm)); - - PlainTime* plain_time = nullptr; - - // 3. If plainTimeLike is undefined, then - if (vm.argument(0).is_undefined()) { - // a. Let plainTime be ! CreateTemporalTime(0, 0, 0, 0, 0, 0). - plain_time = MUST(create_temporal_time(vm, 0, 0, 0, 0, 0, 0)); - } - // 4. Else, - else { - // a. Let plainTime be ? ToTemporalTime(plainTimeLike). - plain_time = TRY(to_temporal_time(vm, vm.argument(0))); - } - - // 5. Let timeZone be zonedDateTime.[[TimeZone]]. - auto& time_zone = zoned_date_time->time_zone(); - - // 6. Let instant be ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]). - auto* instant = MUST(create_temporal_instant(vm, zoned_date_time->nanoseconds())); - - // 7. Let calendar be zonedDateTime.[[Calendar]]. - auto& calendar = zoned_date_time->calendar(); - - // 8. Let plainDateTime be ? BuiltinTimeZoneGetPlainDateTimeFor(timeZone, instant, calendar). - auto* plain_date_time = TRY(builtin_time_zone_get_plain_date_time_for(vm, &time_zone, *instant, calendar)); - - // 9. Let resultPlainDateTime be ? CreateTemporalDateTime(plainDateTime.[[ISOYear]], plainDateTime.[[ISOMonth]], plainDateTime.[[ISODay]], plainTime.[[ISOHour]], plainTime.[[ISOMinute]], plainTime.[[ISOSecond]], plainTime.[[ISOMillisecond]], plainTime.[[ISOMicrosecond]], plainTime.[[ISONanosecond]], calendar). - auto* result_plain_date_time = TRY(create_temporal_date_time(vm, plain_date_time->iso_year(), plain_date_time->iso_month(), plain_date_time->iso_day(), plain_time->iso_hour(), plain_time->iso_minute(), plain_time->iso_second(), plain_time->iso_millisecond(), plain_time->iso_microsecond(), plain_time->iso_nanosecond(), calendar)); - - // 10. Set instant to ? BuiltinTimeZoneGetInstantFor(timeZone, resultPlainDateTime, "compatible"). - instant = TRY(builtin_time_zone_get_instant_for(vm, &time_zone, *result_plain_date_time, "compatible"sv)); - - // 11. Return ! CreateTemporalZonedDateTime(instant.[[Nanoseconds]], timeZone, calendar). - return MUST(create_temporal_zoned_date_time(vm, instant->nanoseconds(), time_zone, calendar)); -} - -// 6.3.33 Temporal.ZonedDateTime.prototype.withPlainDate ( plainDateLike ), https://tc39.es/proposal-temporal/#sec-temporal.zoneddatetime.prototype.withplaindate -JS_DEFINE_NATIVE_FUNCTION(ZonedDateTimePrototype::with_plain_date) -{ - // 1. Let zonedDateTime be the this value. - // 2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]). - auto zoned_date_time = TRY(typed_this_object(vm)); - - // 3. Let plainDate be ? ToTemporalDate(plainDateLike). - auto* plain_date = TRY(to_temporal_date(vm, vm.argument(0))); - - // 4. Let timeZone be zonedDateTime.[[TimeZone]]. - auto& time_zone = zoned_date_time->time_zone(); - - // 5. Let instant be ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]). - auto* instant = MUST(create_temporal_instant(vm, zoned_date_time->nanoseconds())); - - // 6. Let plainDateTime be ? BuiltinTimeZoneGetPlainDateTimeFor(timeZone, instant, zonedDateTime.[[Calendar]]). - auto* plain_date_time = TRY(builtin_time_zone_get_plain_date_time_for(vm, &time_zone, *instant, zoned_date_time->calendar())); - - // 7. Let calendar be ? ConsolidateCalendars(zonedDateTime.[[Calendar]], plainDate.[[Calendar]]). - auto* calendar = TRY(consolidate_calendars(vm, zoned_date_time->calendar(), plain_date->calendar())); - - // 8. Let resultPlainDateTime be ? CreateTemporalDateTime(plainDate.[[ISOYear]], plainDate.[[ISOMonth]], plainDate.[[ISODay]], plainDateTime.[[ISOHour]], plainDateTime.[[ISOMinute]], plainDateTime.[[ISOSecond]], plainDateTime.[[ISOMillisecond]], plainDateTime.[[ISOMicrosecond]], plainDateTime.[[ISONanosecond]], calendar). - auto* result_plain_date_time = TRY(create_temporal_date_time(vm, plain_date->iso_year(), plain_date->iso_month(), plain_date->iso_day(), plain_date_time->iso_hour(), plain_date_time->iso_minute(), plain_date_time->iso_second(), plain_date_time->iso_millisecond(), plain_date_time->iso_microsecond(), plain_date_time->iso_nanosecond(), *calendar)); - - // 9. Set instant to ? BuiltinTimeZoneGetInstantFor(timeZone, resultPlainDateTime, "compatible"). - instant = TRY(builtin_time_zone_get_instant_for(vm, &time_zone, *result_plain_date_time, "compatible"sv)); - - // 10. Return ! CreateTemporalZonedDateTime(instant.[[Nanoseconds]], timeZone, calendar). - return MUST(create_temporal_zoned_date_time(vm, instant->nanoseconds(), time_zone, *calendar)); -} - -// 6.3.34 Temporal.ZonedDateTime.prototype.withTimeZone ( timeZoneLike ), https://tc39.es/proposal-temporal/#sec-temporal.zoneddatetime.prototype.withtimezone -JS_DEFINE_NATIVE_FUNCTION(ZonedDateTimePrototype::with_time_zone) -{ - // 1. Let zonedDateTime be the this value. - // 2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]). - auto zoned_date_time = TRY(typed_this_object(vm)); - - // 3. Let timeZone be ? ToTemporalTimeZone(timeZoneLike). - auto* time_zone = TRY(to_temporal_time_zone(vm, vm.argument(0))); - - // 4. Return ! CreateTemporalZonedDateTime(zonedDateTime.[[Nanoseconds]], timeZone, zonedDateTime.[[Calendar]]). - return MUST(create_temporal_zoned_date_time(vm, zoned_date_time->nanoseconds(), *time_zone, zoned_date_time->calendar())); -} - -// 6.3.35 Temporal.ZonedDateTime.prototype.withCalendar ( calendarLike ), https://tc39.es/proposal-temporal/#sec-temporal.zoneddatetime.prototype.withcalendar -JS_DEFINE_NATIVE_FUNCTION(ZonedDateTimePrototype::with_calendar) -{ - // 1. Let zonedDateTime be the this value. - // 2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]). - auto zoned_date_time = TRY(typed_this_object(vm)); - - // 3. Let calendar be ? ToTemporalCalendar(calendarLike). - auto* calendar = TRY(to_temporal_calendar(vm, vm.argument(0))); - - // 4. Return ! CreateTemporalZonedDateTime(zonedDateTime.[[Nanoseconds]], zonedDateTime.[[TimeZone]], calendar). - return MUST(create_temporal_zoned_date_time(vm, zoned_date_time->nanoseconds(), zoned_date_time->time_zone(), *calendar)); -} - -// 6.3.36 Temporal.ZonedDateTime.prototype.add ( temporalDurationLike [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal.zoneddatetime.prototype.add -JS_DEFINE_NATIVE_FUNCTION(ZonedDateTimePrototype::add) -{ - auto temporal_duration_like = vm.argument(0); - auto options = vm.argument(1); - - // 1. Let zonedDateTime be the this value. - // 2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]). - auto zoned_date_time = TRY(typed_this_object(vm)); - - // 3. Return ? AddDurationToOrSubtractDurationFromZonedDateTime(add, zonedDateTime, temporalDurationLike, options). - return TRY(add_duration_to_or_subtract_duration_from_zoned_date_time(vm, ArithmeticOperation::Add, zoned_date_time, temporal_duration_like, options)); -} - -// 6.3.37 Temporal.ZonedDateTime.prototype.subtract ( temporalDurationLike [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal.zoneddatetime.prototype.subtract -JS_DEFINE_NATIVE_FUNCTION(ZonedDateTimePrototype::subtract) -{ - auto temporal_duration_like = vm.argument(0); - auto options = vm.argument(1); - - // 1. Let zonedDateTime be the this value. - // 2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]). - auto zoned_date_time = TRY(typed_this_object(vm)); - - // 3. Return ? AddDurationToOrSubtractDurationFromZonedDateTime(subtract, zonedDateTime, temporalDurationLike, options). - return TRY(add_duration_to_or_subtract_duration_from_zoned_date_time(vm, ArithmeticOperation::Subtract, zoned_date_time, temporal_duration_like, options)); -} - -// 6.3.38 Temporal.ZonedDateTime.prototype.until ( other [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal.zoneddatetime.prototype.until -JS_DEFINE_NATIVE_FUNCTION(ZonedDateTimePrototype::until) -{ - auto other = vm.argument(0); - auto options = vm.argument(1); - - // 1. Let zonedDateTime be the this value. - // 2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]). - auto zoned_date_time = TRY(typed_this_object(vm)); - - // 3. Return ? DifferenceTemporalZonedDateTime(until, zonedDateTime, other, options). - return TRY(difference_temporal_zoned_date_time(vm, DifferenceOperation::Until, zoned_date_time, other, options)); -} - -// 6.3.39 Temporal.ZonedDateTime.prototype.since ( other [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal.zoneddatetime.prototype.since -JS_DEFINE_NATIVE_FUNCTION(ZonedDateTimePrototype::since) -{ - auto other = vm.argument(0); - auto options = vm.argument(1); - - // 1. Let zonedDateTime be the this value. - // 2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]). - auto zoned_date_time = TRY(typed_this_object(vm)); - - // 3. Return ? DifferenceTemporalZonedDateTime(since, zonedDateTime, other, options). - return TRY(difference_temporal_zoned_date_time(vm, DifferenceOperation::Since, zoned_date_time, other, options)); -} - -// 6.3.40 Temporal.ZonedDateTime.prototype.round ( roundTo ), https://tc39.es/proposal-temporal/#sec-temporal.zoneddatetime.prototype.round -JS_DEFINE_NATIVE_FUNCTION(ZonedDateTimePrototype::round) -{ - auto& realm = *vm.current_realm(); - - // 1. Let zonedDateTime be the this value. - // 2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]). - auto zoned_date_time = TRY(typed_this_object(vm)); - - // 3. If roundTo is undefined, then - if (vm.argument(0).is_undefined()) { - // a. Throw a TypeError exception. - return vm.throw_completion(ErrorType::TemporalMissingOptionsObject); - } - - Object* round_to; - - // 4. If Type(roundTo) is String, then - if (vm.argument(0).is_string()) { - // a. Let paramString be roundTo. - - // b. Set roundTo to OrdinaryObjectCreate(null). - round_to = Object::create(realm, nullptr); - - // c. Perform ! CreateDataPropertyOrThrow(roundTo, "smallestUnit", paramString). - MUST(round_to->create_data_property_or_throw(vm.names.smallestUnit, vm.argument(0))); - } - // 5. Else, - else { - // a. Set roundTo to ? GetOptionsObject(roundTo). - round_to = TRY(get_options_object(vm, vm.argument(0))); - } - - // 6. Let smallestUnit be ? GetTemporalUnit(roundTo, "smallestUnit", time, required, « "day" »). - auto smallest_unit = TRY(get_temporal_unit(vm, *round_to, vm.names.smallestUnit, UnitGroup::Time, TemporalUnitRequired {}, { "day"sv })); - - // 7. Let roundingMode be ? ToTemporalRoundingMode(roundTo, "halfExpand"). - auto rounding_mode = TRY(to_temporal_rounding_mode(vm, *round_to, "halfExpand"sv)); - - // 8. If smallestUnit is "day", then - Optional maximum; - if (smallest_unit == "day"sv) { - // a. Let maximum be 1. - maximum = 1; - } - // 9. Else - else { - // a. Let maximum be ! MaximumTemporalDurationRoundingIncrement(smallestUnit) - maximum = maximum_temporal_duration_rounding_increment(*smallest_unit); - - // b. Assert: maximum is not undefined - VERIFY(maximum.has_value()); - } - - // 10. Let roundingIncrement be ? ToTemporalDateTimeRoundingIncrement(roundTo). - auto rounding_increment = TRY(to_temporal_rounding_increment(vm, *round_to)); - - // 11. Perform ? ValidateTemporalDateTimeRoundingIncrement(roundingIncrement, maximum, false). - TRY(validate_temporal_rounding_increment(vm, rounding_increment, *maximum, false)); - - // 12. Let timeZone be zonedDateTime.[[TimeZone]]. - auto& time_zone = zoned_date_time->time_zone(); - - auto time_zone_record = TRY(create_time_zone_methods_record(vm, GC::Ref { time_zone }, { { TimeZoneMethod::GetOffsetNanosecondsFor } })); - - // 13. Let instant be ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]). - auto* instant = MUST(create_temporal_instant(vm, zoned_date_time->nanoseconds())); - - // 14. Let calendar be zonedDateTime.[[Calendar]]. - auto& calendar = zoned_date_time->calendar(); - - // 15. Let temporalDateTime be ? BuiltinTimeZoneGetPlainDateTimeFor(timeZone, instant, calendar). - auto* temporal_date_time = TRY(builtin_time_zone_get_plain_date_time_for(vm, &time_zone, *instant, calendar)); - - // 16. Let isoCalendar be ! GetISO8601Calendar(). - auto* iso_calendar = get_iso8601_calendar(vm); - - // 17. Let dtStart be ? CreateTemporalDateTime(temporalDateTime.[[ISOYear]], temporalDateTime.[[ISOMonth]], temporalDateTime.[[ISODay]], 0, 0, 0, 0, 0, 0, isoCalendar). - auto* dt_start = TRY(create_temporal_date_time(vm, temporal_date_time->iso_year(), temporal_date_time->iso_month(), temporal_date_time->iso_day(), 0, 0, 0, 0, 0, 0, *iso_calendar)); - - // 18. Let instantStart be ? BuiltinTimeZoneGetInstantFor(timeZone, dtStart, "compatible"). - auto instant_start = TRY(builtin_time_zone_get_instant_for(vm, &time_zone, *dt_start, "compatible"sv)); - - // 19. Let startNs be instantStart.[[Nanoseconds]]. - auto& start_ns = instant_start->nanoseconds(); - - // 20. Let endNs be ? AddZonedDateTime(startNs, timeZone, calendar, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0). - auto* end_ns = TRY(add_zoned_date_time(vm, start_ns, &time_zone, calendar, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0)); - - // 21. Let dayLengthNs be ℝ(endNs - startNs). - auto day_length_ns = end_ns->big_integer().minus(start_ns.big_integer()).to_double(); - - // 22. If dayLengthNs ≤ 0, then - if (day_length_ns <= 0) { - // a. Throw a RangeError exception. - return vm.throw_completion(ErrorType::TemporalZonedDateTimeRoundZeroOrNegativeLengthDay); - } - - // 23. Let roundResult be ! RoundISODateTime(temporalDateTime.[[ISOYear]], temporalDateTime.[[ISOMonth]], temporalDateTime.[[ISODay]], temporalDateTime.[[ISOHour]], temporalDateTime.[[ISOMinute]], temporalDateTime.[[ISOSecond]], temporalDateTime.[[ISOMillisecond]], temporalDateTime.[[ISOMicrosecond]], temporalDateTime.[[ISONanosecond]], roundingIncrement, smallestUnit, roundingMode, dayLengthNs). - auto round_result = round_iso_date_time(temporal_date_time->iso_year(), temporal_date_time->iso_month(), temporal_date_time->iso_day(), temporal_date_time->iso_hour(), temporal_date_time->iso_minute(), temporal_date_time->iso_second(), temporal_date_time->iso_millisecond(), temporal_date_time->iso_microsecond(), temporal_date_time->iso_nanosecond(), rounding_increment, *smallest_unit, rounding_mode, day_length_ns); - - // 24. Let offsetNanoseconds be ? GetOffsetNanosecondsFor(timeZone, instant). - auto offset_nanoseconds = TRY(get_offset_nanoseconds_for(vm, time_zone_record, *instant)); - - // 25. Let epochNanoseconds be ? InterpretISODateTimeOffset(roundResult.[[Year]], roundResult.[[Month]], roundResult.[[Day]], roundResult.[[Hour]], roundResult.[[Minute]], roundResult.[[Second]], roundResult.[[Millisecond]], roundResult.[[Microsecond]], roundResult.[[Nanosecond]], option, offsetNanoseconds, timeZone, "compatible", "prefer", match exactly). - auto* epoch_nanoseconds = TRY(interpret_iso_date_time_offset(vm, round_result.year, round_result.month, round_result.day, round_result.hour, round_result.minute, round_result.second, round_result.millisecond, round_result.microsecond, round_result.nanosecond, OffsetBehavior::Option, offset_nanoseconds, &time_zone, "compatible"sv, "prefer"sv, MatchBehavior::MatchExactly)); - - // 26. Return ! CreateTemporalZonedDateTime(epochNanoseconds, timeZone, calendar). - return MUST(create_temporal_zoned_date_time(vm, *epoch_nanoseconds, time_zone, calendar)); -} - -// 6.3.41 Temporal.ZonedDateTime.prototype.equals ( other ), https://tc39.es/proposal-temporal/#sec-temporal.zoneddatetime.prototype.equals -JS_DEFINE_NATIVE_FUNCTION(ZonedDateTimePrototype::equals) -{ - // 1. Let zonedDateTime be the this value. - // 2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]). - auto zoned_date_time = TRY(typed_this_object(vm)); - - // 3. Set other to ? ToTemporalZonedDateTime(other). - auto* other = TRY(to_temporal_zoned_date_time(vm, vm.argument(0))); - - // 4. If zonedDateTime.[[Nanoseconds]] ≠ other.[[Nanoseconds]], return false. - if (zoned_date_time->nanoseconds().big_integer() != other->nanoseconds().big_integer()) - return Value(false); - - // 5. If ? TimeZoneEquals(zonedDateTime.[[TimeZone]], other.[[TimeZone]]) is false, return false. - if (!TRY(time_zone_equals(vm, zoned_date_time->time_zone(), other->time_zone()))) - return Value(false); - - // 6. Return ? CalendarEquals(zonedDateTime.[[Calendar]], other.[[Calendar]]). - return Value(TRY(calendar_equals(vm, zoned_date_time->calendar(), other->calendar()))); -} - -// 6.3.42 Temporal.ZonedDateTime.prototype.toString ( [ options ] ), https://tc39.es/proposal-temporal/#sec-temporal.zoneddatetime.prototype.tostring -JS_DEFINE_NATIVE_FUNCTION(ZonedDateTimePrototype::to_string) -{ - // 1. Let zonedDateTime be the this value. - // 2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]). - auto zoned_date_time = TRY(typed_this_object(vm)); - - // 3. Set options to ? GetOptionsObject(options). - auto* options = TRY(get_options_object(vm, vm.argument(0))); - - // 4. Let precision be ? ToSecondsStringPrecisionRecord(options). - auto precision = TRY(to_seconds_string_precision_record(vm, *options)); - - // 5. Let roundingMode be ? ToTemporalRoundingMode(options, "trunc"). - auto rounding_mode = TRY(to_temporal_rounding_mode(vm, *options, "trunc"sv)); - - // 6. Let showCalendar be ? ToCalendarNameOption(options). - auto show_calendar = TRY(to_calendar_name_option(vm, *options)); - - // 7. Let showTimeZone be ? ToTimeZoneNameOption(options). - auto show_time_zone = TRY(to_time_zone_name_option(vm, *options)); - - // 8. Let showOffset be ? ToShowOffsetOption(options). - auto show_offset = TRY(to_show_offset_option(vm, *options)); - - // 9. Return ? TemporalZonedDateTimeToString(zonedDateTime, precision.[[Precision]], showCalendar, showTimeZone, showOffset, precision.[[Increment]], precision.[[Unit]], roundingMode). - return PrimitiveString::create(vm, TRY(temporal_zoned_date_time_to_string(vm, zoned_date_time, precision.precision, show_calendar, show_time_zone, show_offset, precision.increment, precision.unit, rounding_mode))); -} - -// 6.3.43 Temporal.ZonedDateTime.prototype.toLocaleString ( [ locales [ , options ] ] ), https://tc39.es/proposal-temporal/#sec-temporal.zoneddatetime.prototype.tolocalestring -// NOTE: This is the minimum toLocaleString implementation for engines without ECMA-402. -JS_DEFINE_NATIVE_FUNCTION(ZonedDateTimePrototype::to_locale_string) -{ - // 1. Let zonedDateTime be the this value. - // 2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]). - auto zoned_date_time = TRY(typed_this_object(vm)); - - // 3. Return ? TemporalZonedDateTimeToString(zonedDateTime, "auto", "auto", "auto", "auto"). - return PrimitiveString::create(vm, TRY(temporal_zoned_date_time_to_string(vm, zoned_date_time, "auto"sv, "auto"sv, "auto"sv, "auto"sv))); -} - -// 6.3.44 Temporal.ZonedDateTime.prototype.toJSON ( ), https://tc39.es/proposal-temporal/#sec-temporal.zoneddatetime.prototype.tojson -JS_DEFINE_NATIVE_FUNCTION(ZonedDateTimePrototype::to_json) -{ - // 1. Let zonedDateTime be the this value. - // 2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]). - auto zoned_date_time = TRY(typed_this_object(vm)); - - // 3. Return ? TemporalZonedDateTimeToString(zonedDateTime, "auto", "auto", "auto", "auto"). - return PrimitiveString::create(vm, TRY(temporal_zoned_date_time_to_string(vm, zoned_date_time, "auto"sv, "auto"sv, "auto"sv, "auto"sv))); -} - -// 6.3.45 Temporal.ZonedDateTime.prototype.valueOf ( ), https://tc39.es/proposal-temporal/#sec-temporal.zoneddatetime.prototype.valueof -JS_DEFINE_NATIVE_FUNCTION(ZonedDateTimePrototype::value_of) -{ - // 1. Throw a TypeError exception. - return vm.throw_completion(ErrorType::Convert, "Temporal.ZonedDateTime", "a primitive value"); -} - -// 6.3.46 Temporal.ZonedDateTime.prototype.startOfDay ( ), https://tc39.es/proposal-temporal/#sec-temporal.zoneddatetime.prototype.startofday -JS_DEFINE_NATIVE_FUNCTION(ZonedDateTimePrototype::start_of_day) -{ - // 1. Let zonedDateTime be the this value. - // 2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]). - auto zoned_date_time = TRY(typed_this_object(vm)); - - // 3. Let timeZone be zonedDateTime.[[TimeZone]]. - auto& time_zone = zoned_date_time->time_zone(); - - // 4. Let calendar be zonedDateTime.[[Calendar]]. - auto& calendar = zoned_date_time->calendar(); - - // 5. Let instant be ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]). - auto* instant = MUST(create_temporal_instant(vm, zoned_date_time->nanoseconds())); - - // 6. Let temporalDateTime be ? BuiltinTimeZoneGetPlainDateTimeFor(timeZone, instant, calendar). - auto* temporal_date_time = TRY(builtin_time_zone_get_plain_date_time_for(vm, &time_zone, *instant, calendar)); - - // 7. Let startDateTime be ? CreateTemporalDateTime(temporalDateTime.[[ISOYear]], temporalDateTime.[[ISOMonth]], temporalDateTime.[[ISODay]], 0, 0, 0, 0, 0, 0, calendar). - auto* start_date_time = TRY(create_temporal_date_time(vm, temporal_date_time->iso_year(), temporal_date_time->iso_month(), temporal_date_time->iso_day(), 0, 0, 0, 0, 0, 0, calendar)); - - // 8. Let startInstant be ? BuiltinTimeZoneGetInstantFor(timeZone, startDateTime, "compatible"). - auto start_instant = TRY(builtin_time_zone_get_instant_for(vm, &time_zone, *start_date_time, "compatible"sv)); - - // 9. Return ! CreateTemporalZonedDateTime(startInstant.[[Nanoseconds]], timeZone, calendar). - return MUST(create_temporal_zoned_date_time(vm, start_instant->nanoseconds(), time_zone, calendar)); -} - -// 6.3.47 Temporal.ZonedDateTime.prototype.toInstant ( ), https://tc39.es/proposal-temporal/#sec-temporal.zoneddatetime.prototype.toinstant -JS_DEFINE_NATIVE_FUNCTION(ZonedDateTimePrototype::to_instant) -{ - // 1. Let zonedDateTime be the this value. - // 2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]). - auto zoned_date_time = TRY(typed_this_object(vm)); - - // 3. Return ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]). - return MUST(create_temporal_instant(vm, zoned_date_time->nanoseconds())); -} - -// 6.3.48 Temporal.ZonedDateTime.prototype.toPlainDate ( ), https://tc39.es/proposal-temporal/#sec-temporal.zoneddatetime.prototype.toplaindate -JS_DEFINE_NATIVE_FUNCTION(ZonedDateTimePrototype::to_plain_date) -{ - // 1. Let zonedDateTime be the this value. - // 2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]). - auto zoned_date_time = TRY(typed_this_object(vm)); - - // 3. Let timeZone be zonedDateTime.[[TimeZone]]. - auto& time_zone = zoned_date_time->time_zone(); - - // 4. Let instant be ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]). - auto* instant = MUST(create_temporal_instant(vm, zoned_date_time->nanoseconds())); - - // 5. Let calendar be zonedDateTime.[[Calendar]]. - auto& calendar = zoned_date_time->calendar(); - - // 6. Let temporalDateTime be ? BuiltinTimeZoneGetPlainDateTimeFor(timeZone, instant, calendar). - auto* temporal_date_time = TRY(builtin_time_zone_get_plain_date_time_for(vm, &time_zone, *instant, calendar)); - - // 7. Return ! CreateTemporalDate(temporalDateTime.[[ISOYear]], temporalDateTime.[[ISOMonth]], temporalDateTime.[[ISODay]], calendar). - return MUST(create_temporal_date(vm, temporal_date_time->iso_year(), temporal_date_time->iso_month(), temporal_date_time->iso_day(), calendar)); -} - -// 6.3.49 Temporal.ZonedDateTime.prototype.toPlainTime ( ), https://tc39.es/proposal-temporal/#sec-temporal.zoneddatetime.prototype.toplaintime -JS_DEFINE_NATIVE_FUNCTION(ZonedDateTimePrototype::to_plain_time) -{ - // 1. Let zonedDateTime be the this value. - // 2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]). - auto zoned_date_time = TRY(typed_this_object(vm)); - - // 3. Let timeZone be zonedDateTime.[[TimeZone]]. - auto& time_zone = zoned_date_time->time_zone(); - - // 4. Let instant be ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]). - auto* instant = MUST(create_temporal_instant(vm, zoned_date_time->nanoseconds())); - - // 5. Let calendar be zonedDateTime.[[Calendar]]. - auto& calendar = zoned_date_time->calendar(); - - // 6. Let temporalDateTime be ? BuiltinTimeZoneGetPlainDateTimeFor(timeZone, instant, zonedDateTime.[[Calendar]]). - auto* temporal_date_time = TRY(builtin_time_zone_get_plain_date_time_for(vm, &time_zone, *instant, calendar)); - - // 7. Return ! CreateTemporalTime(temporalDateTime.[[ISOHour]], temporalDateTime.[[ISOMinute]], temporalDateTime.[[ISOSecond]], temporalDateTime.[[ISOMillisecond]], temporalDateTime.[[ISOMicrosecond]], temporalDateTime.[[ISONanosecond]]). - return MUST(create_temporal_time(vm, temporal_date_time->iso_hour(), temporal_date_time->iso_minute(), temporal_date_time->iso_second(), temporal_date_time->iso_millisecond(), temporal_date_time->iso_microsecond(), temporal_date_time->iso_nanosecond())); -} - -// 6.3.50 Temporal.ZonedDateTime.prototype.toPlainDateTime ( ), https://tc39.es/proposal-temporal/#sec-temporal.zoneddatetime.prototype.toplaindatetime -JS_DEFINE_NATIVE_FUNCTION(ZonedDateTimePrototype::to_plain_date_time) -{ - // 1. Let zonedDateTime be the this value. - // 2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]). - auto zoned_date_time = TRY(typed_this_object(vm)); - - // 3. Let timeZone be zonedDateTime.[[TimeZone]]. - auto& time_zone = zoned_date_time->time_zone(); - - // 4. Let instant be ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]). - auto* instant = MUST(create_temporal_instant(vm, zoned_date_time->nanoseconds())); - - // 5. Return ? BuiltinTimeZoneGetPlainDateTimeFor(timeZone, instant, zonedDateTime.[[Calendar]]). - return TRY(builtin_time_zone_get_plain_date_time_for(vm, &time_zone, *instant, zoned_date_time->calendar())); -} - -// 6.3.51 Temporal.ZonedDateTime.prototype.toPlainYearMonth ( ), https://tc39.es/proposal-temporal/#sec-temporal.zoneddatetime.prototype.toplainyearmonth -JS_DEFINE_NATIVE_FUNCTION(ZonedDateTimePrototype::to_plain_year_month) -{ - // 1. Let zonedDateTime be the this value. - // 2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]). - auto zoned_date_time = TRY(typed_this_object(vm)); - - // 3. Let timeZone be zonedDateTime.[[TimeZone]]. - auto& time_zone = zoned_date_time->time_zone(); - - // 4. Let instant be ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]). - auto* instant = MUST(create_temporal_instant(vm, zoned_date_time->nanoseconds())); - - // 5. Let calendar be zonedDateTime.[[Calendar]]. - auto& calendar = zoned_date_time->calendar(); - - // 6. Let temporalDateTime be ? BuiltinTimeZoneGetPlainDateTimeFor(timeZone, instant, calendar). - auto* temporal_date_time = TRY(builtin_time_zone_get_plain_date_time_for(vm, &time_zone, *instant, calendar)); - - // 7. Let fieldNames be ? CalendarFields(calendar, « "monthCode", "year" »). - auto field_names = TRY(calendar_fields(vm, calendar, { "monthCode"sv, "year"sv })); - - // 8. Let fields be ? PrepareTemporalFields(temporalDateTime, fieldNames, «»). - auto* fields = TRY(prepare_temporal_fields(vm, *temporal_date_time, field_names, Vector {})); - - // 9. Return ? CalendarYearMonthFromFields(calendar, fields). - return TRY(calendar_year_month_from_fields(vm, calendar, *fields)); -} - -// 6.3.52 Temporal.ZonedDateTime.prototype.toPlainMonthDay ( ), https://tc39.es/proposal-temporal/#sec-temporal.zoneddatetime.prototype.toplainmonthday -JS_DEFINE_NATIVE_FUNCTION(ZonedDateTimePrototype::to_plain_month_day) -{ - // 1. Let zonedDateTime be the this value. - // 2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]). - auto zoned_date_time = TRY(typed_this_object(vm)); - - // 3. Let timeZone be zonedDateTime.[[TimeZone]]. - auto& time_zone = zoned_date_time->time_zone(); - - // 4. Let instant be ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]). - auto* instant = MUST(create_temporal_instant(vm, zoned_date_time->nanoseconds())); - - // 5. Let calendar be zonedDateTime.[[Calendar]]. - auto& calendar = zoned_date_time->calendar(); - - // 6. Let temporalDateTime be ? BuiltinTimeZoneGetPlainDateTimeFor(timeZone, instant, calendar). - auto* temporal_date_time = TRY(builtin_time_zone_get_plain_date_time_for(vm, &time_zone, *instant, calendar)); - - // 7. Let fieldNames be ? CalendarFields(calendar, « "day", "monthCode" »). - auto field_names = TRY(calendar_fields(vm, calendar, { "day"sv, "monthCode"sv })); - - // 8. Let fields be ? PrepareTemporalFields(temporalDateTime, fieldNames, «»). - auto* fields = TRY(prepare_temporal_fields(vm, *temporal_date_time, field_names, Vector {})); - - // 9. Return ? CalendarMonthDayFromFields(calendar, fields). - return TRY(calendar_month_day_from_fields(vm, calendar, *fields)); -} - -// 6.3.53 Temporal.ZonedDateTime.prototype.getISOFields ( ), https://tc39.es/proposal-temporal/#sec-temporal.zoneddatetime.prototype.getisofields -JS_DEFINE_NATIVE_FUNCTION(ZonedDateTimePrototype::get_iso_fields) -{ - auto& realm = *vm.current_realm(); - - // 1. Let zonedDateTime be the this value. - // 2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]). - auto zoned_date_time = TRY(typed_this_object(vm)); - - // 3. Let fields be OrdinaryObjectCreate(%Object.prototype%). - auto fields = Object::create(realm, realm.intrinsics().object_prototype()); - - // 4. Let timeZone be zonedDateTime.[[TimeZone]]. - auto& time_zone = zoned_date_time->time_zone(); - - // 5. Let instant be ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]). - auto* instant = MUST(create_temporal_instant(vm, zoned_date_time->nanoseconds())); - - // 6. Let calendar be zonedDateTime.[[Calendar]]. - auto& calendar = zoned_date_time->calendar(); - - // 7. Let dateTime be ? BuiltinTimeZoneGetPlainDateTimeFor(timeZone, instant, calendar). - auto* date_time = TRY(builtin_time_zone_get_plain_date_time_for(vm, &time_zone, *instant, calendar)); - - // 8. Let offset be ? BuiltinTimeZoneGetOffsetStringFor(timeZone, instant). - auto offset = TRY(builtin_time_zone_get_offset_string_for(vm, &time_zone, *instant)); - - // 9. Perform ! CreateDataPropertyOrThrow(fields, "calendar", calendar). - MUST(fields->create_data_property_or_throw(vm.names.calendar, Value(&calendar))); - - // 10. Perform ! CreateDataPropertyOrThrow(fields, "isoDay", 𝔽(dateTime.[[ISODay]])). - MUST(fields->create_data_property_or_throw(vm.names.isoDay, Value(date_time->iso_day()))); - - // 11. Perform ! CreateDataPropertyOrThrow(fields, "isoHour", 𝔽(dateTime.[[ISOHour]])). - MUST(fields->create_data_property_or_throw(vm.names.isoHour, Value(date_time->iso_hour()))); - - // 12. Perform ! CreateDataPropertyOrThrow(fields, "isoMicrosecond", 𝔽(dateTime.[[ISOMicrosecond]])). - MUST(fields->create_data_property_or_throw(vm.names.isoMicrosecond, Value(date_time->iso_microsecond()))); - - // 13. Perform ! CreateDataPropertyOrThrow(fields, "isoMillisecond", 𝔽(dateTime.[[ISOMillisecond]])). - MUST(fields->create_data_property_or_throw(vm.names.isoMillisecond, Value(date_time->iso_millisecond()))); - - // 14. Perform ! CreateDataPropertyOrThrow(fields, "isoMinute", 𝔽(dateTime.[[ISOMinute]])). - MUST(fields->create_data_property_or_throw(vm.names.isoMinute, Value(date_time->iso_minute()))); - - // 15. Perform ! CreateDataPropertyOrThrow(fields, "isoMonth", 𝔽(dateTime.[[ISOMonth]])). - MUST(fields->create_data_property_or_throw(vm.names.isoMonth, Value(date_time->iso_month()))); - - // 16. Perform ! CreateDataPropertyOrThrow(fields, "isoNanosecond", 𝔽(dateTime.[[ISONanosecond]])). - MUST(fields->create_data_property_or_throw(vm.names.isoNanosecond, Value(date_time->iso_nanosecond()))); - - // 17. Perform ! CreateDataPropertyOrThrow(fields, "isoSecond", 𝔽(dateTime.[[ISOSecond]])). - MUST(fields->create_data_property_or_throw(vm.names.isoSecond, Value(date_time->iso_second()))); - - // 18. Perform ! CreateDataPropertyOrThrow(fields, "isoYear", 𝔽(dateTime.[[ISOYear]])). - MUST(fields->create_data_property_or_throw(vm.names.isoYear, Value(date_time->iso_year()))); - - // 19. Perform ! CreateDataPropertyOrThrow(fields, "offset", offset). - MUST(fields->create_data_property_or_throw(vm.names.offset, PrimitiveString::create(vm, move(offset)))); - - // 20. Perform ! CreateDataPropertyOrThrow(fields, "timeZone", timeZone). - MUST(fields->create_data_property_or_throw(vm.names.timeZone, Value(&time_zone))); - - // 21. Return fields. - return fields; -} - -// 6.3.3 get Temporal.ZonedDateTime.prototype.calendarId -// https://tc39.es/proposal-temporal/#sec-get-temporal.zoneddatetime.prototype.calendarid -JS_DEFINE_NATIVE_FUNCTION(ZonedDateTimePrototype::calendar_id_getter) -{ - // 1. Let zonedDateTime be the this value. - // 2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]). - auto zoned_date_time = TRY(typed_this_object(vm)); - - // 3. Return zonedDateTime.[[Calendar]].identifier - auto& calendar = static_cast(zoned_date_time->calendar()); - return PrimitiveString::create(vm, calendar.identifier()); -} - -} diff --git a/Libraries/LibJS/Runtime/Temporal/ZonedDateTimePrototype.h b/Libraries/LibJS/Runtime/Temporal/ZonedDateTimePrototype.h deleted file mode 100644 index ff585374352..00000000000 --- a/Libraries/LibJS/Runtime/Temporal/ZonedDateTimePrototype.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) 2021, Linus Groh - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include -#include - -namespace JS::Temporal { - -class ZonedDateTimePrototype final : public PrototypeObject { - JS_PROTOTYPE_OBJECT(ZonedDateTimePrototype, ZonedDateTime, Temporal.ZonedDateTime); - GC_DECLARE_ALLOCATOR(ZonedDateTimePrototype); - -public: - virtual void initialize(Realm&) override; - virtual ~ZonedDateTimePrototype() override = default; - -private: - explicit ZonedDateTimePrototype(Realm&); - - JS_DECLARE_NATIVE_FUNCTION(calendar_getter); - JS_DECLARE_NATIVE_FUNCTION(calendar_id_getter); - JS_DECLARE_NATIVE_FUNCTION(time_zone_getter); - JS_DECLARE_NATIVE_FUNCTION(year_getter); - JS_DECLARE_NATIVE_FUNCTION(month_getter); - JS_DECLARE_NATIVE_FUNCTION(month_code_getter); - JS_DECLARE_NATIVE_FUNCTION(day_getter); - JS_DECLARE_NATIVE_FUNCTION(hour_getter); - JS_DECLARE_NATIVE_FUNCTION(minute_getter); - JS_DECLARE_NATIVE_FUNCTION(second_getter); - JS_DECLARE_NATIVE_FUNCTION(millisecond_getter); - JS_DECLARE_NATIVE_FUNCTION(microsecond_getter); - JS_DECLARE_NATIVE_FUNCTION(nanosecond_getter); - JS_DECLARE_NATIVE_FUNCTION(epoch_seconds_getter); - JS_DECLARE_NATIVE_FUNCTION(epoch_milliseconds_getter); - JS_DECLARE_NATIVE_FUNCTION(epoch_microseconds_getter); - JS_DECLARE_NATIVE_FUNCTION(epoch_nanoseconds_getter); - JS_DECLARE_NATIVE_FUNCTION(day_of_week_getter); - JS_DECLARE_NATIVE_FUNCTION(day_of_year_getter); - JS_DECLARE_NATIVE_FUNCTION(week_of_year_getter); - JS_DECLARE_NATIVE_FUNCTION(year_of_week_getter); - JS_DECLARE_NATIVE_FUNCTION(hours_in_day_getter); - JS_DECLARE_NATIVE_FUNCTION(days_in_week_getter); - JS_DECLARE_NATIVE_FUNCTION(days_in_month_getter); - JS_DECLARE_NATIVE_FUNCTION(days_in_year_getter); - JS_DECLARE_NATIVE_FUNCTION(months_in_year_getter); - JS_DECLARE_NATIVE_FUNCTION(in_leap_year_getter); - JS_DECLARE_NATIVE_FUNCTION(offset_nanoseconds_getter); - JS_DECLARE_NATIVE_FUNCTION(offset_getter); - JS_DECLARE_NATIVE_FUNCTION(era_getter); - JS_DECLARE_NATIVE_FUNCTION(era_year_getter); - JS_DECLARE_NATIVE_FUNCTION(with); - JS_DECLARE_NATIVE_FUNCTION(with_plain_time); - JS_DECLARE_NATIVE_FUNCTION(with_plain_date); - JS_DECLARE_NATIVE_FUNCTION(with_time_zone); - JS_DECLARE_NATIVE_FUNCTION(with_calendar); - JS_DECLARE_NATIVE_FUNCTION(add); - JS_DECLARE_NATIVE_FUNCTION(subtract); - JS_DECLARE_NATIVE_FUNCTION(until); - JS_DECLARE_NATIVE_FUNCTION(since); - JS_DECLARE_NATIVE_FUNCTION(round); - JS_DECLARE_NATIVE_FUNCTION(equals); - JS_DECLARE_NATIVE_FUNCTION(to_string); - JS_DECLARE_NATIVE_FUNCTION(to_locale_string); - JS_DECLARE_NATIVE_FUNCTION(to_json); - JS_DECLARE_NATIVE_FUNCTION(value_of); - JS_DECLARE_NATIVE_FUNCTION(start_of_day); - JS_DECLARE_NATIVE_FUNCTION(to_instant); - JS_DECLARE_NATIVE_FUNCTION(to_plain_date); - JS_DECLARE_NATIVE_FUNCTION(to_plain_time); - JS_DECLARE_NATIVE_FUNCTION(to_plain_date_time); - JS_DECLARE_NATIVE_FUNCTION(to_plain_year_month); - JS_DECLARE_NATIVE_FUNCTION(to_plain_month_day); - JS_DECLARE_NATIVE_FUNCTION(get_iso_fields); -}; - -} diff --git a/Libraries/LibJS/Tests/builtins/Date/Date.prototype.toTemporalInstant.js b/Libraries/LibJS/Tests/builtins/Date/Date.prototype.toTemporalInstant.js deleted file mode 100644 index e1dbf7d6839..00000000000 --- a/Libraries/LibJS/Tests/builtins/Date/Date.prototype.toTemporalInstant.js +++ /dev/null @@ -1,15 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const date = new Date("2021-07-09T01:36:00Z"); - const instant = date.toTemporalInstant(); - expect(instant.epochSeconds).toBe(1625794560); - }); -}); - -describe("errors", () => { - test("this value must be a Date object", () => { - expect(() => { - Date.prototype.toTemporalInstant.call(123); - }).toThrowWithMessage(TypeError, "Not an object of type Date"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.from.js b/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.from.js deleted file mode 100644 index 381aee99691..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.from.js +++ /dev/null @@ -1,73 +0,0 @@ -describe("normal behavior", () => { - test("length is 1", () => { - expect(Temporal.Calendar.from).toHaveLength(1); - }); - - test("basic functionality", () => { - const timeZone = new Temporal.TimeZone("UTC"); - const plainDate = new Temporal.PlainDate(1970, 1, 1); - const plainTime = new Temporal.PlainTime(); - const plainDateTime = new Temporal.PlainDateTime(1970, 1, 1); - const plainMonthDay = new Temporal.PlainMonthDay(1, 1); - const plainYearMonth = new Temporal.PlainYearMonth(1970, 1); - const zonedDateTime = new Temporal.ZonedDateTime(0n, timeZone); - const calendarLike = {}; - const withCalendarLike = { calendar: {} }; - expect(Temporal.Calendar.from(plainDate)).toBe(plainDate.calendar); - expect(Temporal.Calendar.from(plainTime)).toBe(plainTime.calendar); - expect(Temporal.Calendar.from(plainDateTime)).toBe(plainDateTime.calendar); - expect(Temporal.Calendar.from(plainMonthDay)).toBe(plainMonthDay.calendar); - expect(Temporal.Calendar.from(plainYearMonth)).toBe(plainYearMonth.calendar); - expect(Temporal.Calendar.from(zonedDateTime)).toBe(zonedDateTime.calendar); - expect(Temporal.Calendar.from(calendarLike)).toBe(calendarLike); - expect(Temporal.Calendar.from(withCalendarLike)).toBe(withCalendarLike.calendar); - expect(Temporal.Calendar.from("iso8601").id).toBe("iso8601"); - expect(Temporal.Calendar.from("2021-07-06[u-ca=iso8601]").id).toBe("iso8601"); - }); - - test("ToTemporalCalendar fast path returns if it is passed a Temporal.Calendar instance", () => { - // This is obseravble via there being no property lookups (avoiding a "calendar" property lookup in this case) - let madeObservableHasPropertyLookup = false; - class Calendar extends Temporal.Calendar { - constructor() { - super("iso8601"); - } - - get calendar() { - madeObservableHasPropertyLookup = true; - return this; - } - } - const calendar = new Calendar(); - Temporal.Calendar.from(calendar); - expect(madeObservableHasPropertyLookup).toBeFalse(); - }); -}); - -describe("errors", () => { - test("Calendar from TimeZone", () => { - const timeZone = new Temporal.TimeZone("UTC"); - expect(() => { - Temporal.Calendar.from(timeZone); - }).toThrowWithMessage( - RangeError, - "Got unexpected TimeZone object in conversion to Calendar" - ); - }); - - test("yyyy-mm and mm-dd strings can only use the iso8601 calendar", () => { - // FIXME: The error message doesn't really indicate this is the case. - const values = [ - "02-10[u-ca=iso8602]", - "02-10[u-ca=SerenityOS]", - "2023-02[u-ca=iso8602]", - "2023-02[u-ca=SerenityOS]", - ]; - - for (const value of values) { - expect(() => { - Temporal.Calendar.from(value); - }).toThrowWithMessage(RangeError, `Invalid calendar string '${value}'`); - } - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.js b/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.js deleted file mode 100644 index a3e825db46a..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.js +++ /dev/null @@ -1,37 +0,0 @@ -describe("errors", () => { - test("called without new", () => { - expect(() => { - Temporal.Calendar(); - }).toThrowWithMessage(TypeError, "Temporal.Calendar constructor must be called with 'new'"); - }); - - test("argument must be coercible to string", () => { - expect(() => { - new Temporal.Calendar({ - toString() { - throw new Error(); - }, - }); - }).toThrow(Error); - }); - - test("invalid calendar identifier", () => { - expect(() => { - new Temporal.Calendar("foo"); - }).toThrowWithMessage(RangeError, "Invalid calendar identifier 'foo'"); - }); -}); - -describe("normal behavior", () => { - test("length is 1", () => { - expect(Temporal.Calendar).toHaveLength(1); - }); - - test("basic functionality", () => { - const calendar = new Temporal.Calendar("iso8601"); - expect(calendar.id).toBe("iso8601"); - expect(typeof calendar).toBe("object"); - expect(calendar).toBeInstanceOf(Temporal.Calendar); - expect(Object.getPrototypeOf(calendar)).toBe(Temporal.Calendar.prototype); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.@@toStringTag.js b/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.@@toStringTag.js deleted file mode 100644 index 1b2aed043b3..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.@@toStringTag.js +++ /dev/null @@ -1,3 +0,0 @@ -test("basic functionality", () => { - expect(Temporal.Calendar.prototype[Symbol.toStringTag]).toBe("Temporal.Calendar"); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.dateAdd.js b/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.dateAdd.js deleted file mode 100644 index f01775a492a..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.dateAdd.js +++ /dev/null @@ -1,15 +0,0 @@ -describe("correct behavior", () => { - test("length is 2", () => { - expect(Temporal.Calendar.prototype.dateAdd).toHaveLength(2); - }); - - test("basic functionality", () => { - const calendar = new Temporal.Calendar("iso8601"); - const plainDate = new Temporal.PlainDate(1970, 1, 1); - const duration = new Temporal.Duration(1, 2, 3, 4); - const newPlainDate = calendar.dateAdd(plainDate, duration); - expect(newPlainDate.year).toBe(1971); - expect(newPlainDate.month).toBe(3); - expect(newPlainDate.day).toBe(26); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.dateFromFields.js b/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.dateFromFields.js deleted file mode 100644 index ad0121fa2a0..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.dateFromFields.js +++ /dev/null @@ -1,54 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.Calendar.prototype.dateFromFields).toHaveLength(1); - }); - - test("basic functionality", () => { - const calendar = new Temporal.Calendar("iso8601"); - const date = calendar.dateFromFields({ year: 2000, month: 5, day: 2 }); - expect(date.calendar).toBe(calendar); - }); - - test("gets overflow after temporal fields", () => { - const operations = []; - const calendar = new Temporal.Calendar("iso8601"); - - const fields = { - get day() { - operations.push("get day"); - return 3; - }, - - get month() { - operations.push("get month"); - return 10; - }, - - get monthCode() { - operations.push("get monthCode"); - return "M10"; - }, - - get year() { - operations.push("get year"); - return 2022; - }, - }; - - const options = { - get overflow() { - operations.push("get overflow"); - return "constrain"; - }, - }; - - expect(operations).toHaveLength(0); - calendar.dateFromFields(fields, options); - expect(operations).toHaveLength(5); - expect(operations[0]).toBe("get day"); - expect(operations[1]).toBe("get month"); - expect(operations[2]).toBe("get monthCode"); - expect(operations[3]).toBe("get year"); - expect(operations[4]).toBe("get overflow"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.dateUntil.js b/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.dateUntil.js deleted file mode 100644 index 6758371906d..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.dateUntil.js +++ /dev/null @@ -1,79 +0,0 @@ -describe("correct behavior", () => { - test("length is 2", () => { - expect(Temporal.Calendar.prototype.dateUntil).toHaveLength(2); - }); - - test("basic functionality", () => { - const calendar = new Temporal.Calendar("iso8601"); - const one = new Temporal.PlainDate(2021, 7, 6); - const two = new Temporal.PlainDate(2021, 10, 10); - - const oneToTwo = calendar.dateUntil(one, two); - expect(oneToTwo.years).toBe(0); - expect(oneToTwo.months).toBe(0); - expect(oneToTwo.weeks).toBe(0); - expect(oneToTwo.days).toBe(96); - expect(oneToTwo.hours).toBe(0); - expect(oneToTwo.minutes).toBe(0); - expect(oneToTwo.seconds).toBe(0); - expect(oneToTwo.milliseconds).toBe(0); - expect(oneToTwo.microseconds).toBe(0); - expect(oneToTwo.nanoseconds).toBe(0); - - const twoToOne = calendar.dateUntil(two, one); - expect(twoToOne.years).toBe(0); - expect(twoToOne.months).toBe(0); - expect(twoToOne.weeks).toBe(0); - expect(twoToOne.days).toBe(-96); - expect(twoToOne.hours).toBe(0); - expect(twoToOne.minutes).toBe(0); - expect(twoToOne.seconds).toBe(0); - expect(twoToOne.milliseconds).toBe(0); - expect(twoToOne.microseconds).toBe(0); - expect(twoToOne.nanoseconds).toBe(0); - }); - - test("largestUnit option", () => { - const calendar = new Temporal.Calendar("iso8601"); - const one = new Temporal.PlainDate(1970, 1, 1); - const two = new Temporal.PlainDate(2021, 7, 6); - - const values = [ - ["years", 51, 6, 0, 5], - ["months", 0, 618, 0, 5], - ["weeks", 0, 0, 2687, 5], - ["days", 0, 0, 0, 18814], - ]; - for (const [largestUnit, years, months, weeks, days] of values) { - const duration = calendar.dateUntil(one, two, { largestUnit }); - expect(duration.years).toBe(years); - expect(duration.months).toBe(months); - expect(duration.weeks).toBe(weeks); - expect(duration.days).toBe(days); - expect(duration.hours).toBe(0); - expect(duration.minutes).toBe(0); - expect(duration.seconds).toBe(0); - expect(duration.milliseconds).toBe(0); - expect(duration.microseconds).toBe(0); - expect(duration.nanoseconds).toBe(0); - } - }); -}); - -describe("errors", () => { - test("forbidden largestUnit option values", () => { - const calendar = new Temporal.Calendar("iso8601"); - const one = new Temporal.PlainDate(1970, 1, 1); - const two = new Temporal.PlainDate(2021, 7, 6); - - const values = ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"]; - for (const largestUnit of values) { - expect(() => { - calendar.dateUntil(one, two, { largestUnit }); - }).toThrowWithMessage( - RangeError, - `${largestUnit} is not a valid value for option largestUnit` - ); - } - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.day.js b/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.day.js deleted file mode 100644 index 421dd40ceed..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.day.js +++ /dev/null @@ -1,11 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.Calendar.prototype.day).toHaveLength(1); - }); - - test("basic functionality", () => { - const calendar = new Temporal.Calendar("iso8601"); - const date = new Temporal.PlainDate(2021, 7, 23); - expect(calendar.day(date)).toBe(23); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.dayOfWeek.js b/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.dayOfWeek.js deleted file mode 100644 index 129ebd1da05..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.dayOfWeek.js +++ /dev/null @@ -1,11 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.Calendar.prototype.dayOfWeek).toHaveLength(1); - }); - - test("basic functionality", () => { - const calendar = new Temporal.Calendar("iso8601"); - const date = new Temporal.PlainDate(2021, 7, 23); - expect(calendar.dayOfWeek(date)).toBe(5); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.dayOfYear.js b/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.dayOfYear.js deleted file mode 100644 index 2ecb761fd5c..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.dayOfYear.js +++ /dev/null @@ -1,11 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.Calendar.prototype.dayOfYear).toHaveLength(1); - }); - - test("basic functionality", () => { - const calendar = new Temporal.Calendar("iso8601"); - const date = new Temporal.PlainDate(2021, 7, 23); - expect(calendar.dayOfYear(date)).toBe(204); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.daysInMonth.js b/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.daysInMonth.js deleted file mode 100644 index 0cf100ca917..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.daysInMonth.js +++ /dev/null @@ -1,11 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.Calendar.prototype.daysInMonth).toHaveLength(1); - }); - - test("basic functionality", () => { - const calendar = new Temporal.Calendar("iso8601"); - const date = new Temporal.PlainDate(2021, 7, 23); - expect(calendar.daysInMonth(date)).toBe(31); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.daysInWeek.js b/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.daysInWeek.js deleted file mode 100644 index 694e50a9a59..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.daysInWeek.js +++ /dev/null @@ -1,11 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.Calendar.prototype.daysInWeek).toHaveLength(1); - }); - - test("basic functionality", () => { - const calendar = new Temporal.Calendar("iso8601"); - const date = new Temporal.PlainDate(2021, 7, 23); - expect(calendar.daysInWeek(date)).toBe(7); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.daysInYear.js b/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.daysInYear.js deleted file mode 100644 index 3c25b84b459..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.daysInYear.js +++ /dev/null @@ -1,11 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.Calendar.prototype.daysInYear).toHaveLength(1); - }); - - test("basic functionality", () => { - const calendar = new Temporal.Calendar("iso8601"); - const date = new Temporal.PlainDate(2021, 7, 23); - expect(calendar.daysInYear(date)).toBe(365); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.era.js b/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.era.js deleted file mode 100644 index 609da7b177a..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.era.js +++ /dev/null @@ -1,26 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.Calendar.prototype.era).toHaveLength(1); - }); - - test("basic functionality", () => { - const plainDate = new Temporal.PlainDate(2021, 7, 6); - const calendar = new Temporal.Calendar("iso8601"); - expect(calendar.era(plainDate)).toBeUndefined(); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.Calendar object", () => { - expect(() => { - Temporal.Calendar.prototype.era.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.Calendar"); - }); - - test("argument must be date-like", () => { - const calendar = new Temporal.Calendar("iso8601"); - expect(() => { - calendar.era({}); - }).toThrowWithMessage(TypeError, "Required property day is missing or undefined"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.eraYear.js b/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.eraYear.js deleted file mode 100644 index 6ac5e15ce4c..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.eraYear.js +++ /dev/null @@ -1,26 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.Calendar.prototype.eraYear).toHaveLength(1); - }); - - test("basic functionality", () => { - const plainDate = new Temporal.PlainDate(2021, 7, 6); - const calendar = new Temporal.Calendar("iso8601"); - expect(calendar.eraYear(plainDate)).toBeUndefined(); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.Calendar object", () => { - expect(() => { - Temporal.Calendar.prototype.eraYear.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.Calendar"); - }); - - test("argument must be date-like", () => { - const calendar = new Temporal.Calendar("iso8601"); - expect(() => { - calendar.eraYear({}); - }).toThrowWithMessage(TypeError, "Required property day is missing or undefined"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.fields.js b/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.fields.js deleted file mode 100644 index c9e4d704a61..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.fields.js +++ /dev/null @@ -1,55 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.Calendar.prototype.fields).toHaveLength(1); - }); - - test("basic functionality", () => { - const calendar = new Temporal.Calendar("iso8601"); - const array = [ - "year", - "month", - "monthCode", - "day", - "hour", - "minute", - "second", - "millisecond", - "microsecond", - "nanosecond", - ]; - const fields = calendar.fields(array); - expect(fields).toEqual(array); - expect(fields).not.toBe(array); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.Calendar object", () => { - expect(() => { - Temporal.Calendar.prototype.fields.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.Calendar"); - }); - - test("iterator values must be strings", () => { - const calendar = new Temporal.Calendar("iso8601"); - for (const value of [123, null, undefined, true, {}]) { - expect(() => { - calendar.fields([value]); - }).toThrowWithMessage(TypeError, `Invalid calendar field ${value}, expected a string`); - } - }); - - test("iterator values must be valid field names", () => { - const calendar = new Temporal.Calendar("iso8601"); - expect(() => { - calendar.fields(["foo"]); - }).toThrowWithMessage(RangeError, "Invalid calendar field 'foo'"); - }); - - test("iterator values must not contain duplicates", () => { - const calendar = new Temporal.Calendar("iso8601"); - expect(() => { - calendar.fields(["year", "month", "year", "month"]); - }).toThrowWithMessage(RangeError, "Duplicate calendar field 'year'"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.id.js b/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.id.js deleted file mode 100644 index af81f0f3909..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.id.js +++ /dev/null @@ -1,14 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const calendar = new Temporal.Calendar("iso8601"); - expect(calendar.id).toBe("iso8601"); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.Calendar object", () => { - expect(() => { - Reflect.get(Temporal.Calendar.prototype, "id", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.Calendar"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.inLeapYear.js b/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.inLeapYear.js deleted file mode 100644 index 6acd35d6ffb..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.inLeapYear.js +++ /dev/null @@ -1,13 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.Calendar.prototype.inLeapYear).toHaveLength(1); - }); - - test("basic functionality", () => { - const calendar = new Temporal.Calendar("iso8601"); - const date = new Temporal.PlainDate(2021, 7, 23); - expect(calendar.inLeapYear(date)).toBeFalse(); - const leapDate = new Temporal.PlainDate(2020, 7, 23); - expect(calendar.inLeapYear(leapDate)).toBeTrue(); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.mergeFields.js b/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.mergeFields.js deleted file mode 100644 index 596018b14c9..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.mergeFields.js +++ /dev/null @@ -1,54 +0,0 @@ -describe("correct behavior", () => { - test("length is 2", () => { - expect(Temporal.Calendar.prototype.mergeFields).toHaveLength(2); - }); - - test("basic functionality", () => { - const calendar = new Temporal.Calendar("iso8601"); - const fields = {}; - const additionalFields = {}; - const mergedFields = calendar.mergeFields(fields, additionalFields); - expect(mergedFields).not.toBe(fields); - expect(mergedFields).not.toBe(additionalFields); - expect(mergedFields).toEqual({}); - expect(Object.getPrototypeOf(mergedFields)).toBe(Object.prototype); - expect(calendar.mergeFields({ foo: 1, bar: 1 }, { foo: 2 })).toEqual({ foo: 2, bar: 1 }); - expect(calendar.mergeFields({ foo: 1 }, { foo: 2, bar: 2 })).toEqual({ foo: 2, bar: 2 }); - expect(calendar.mergeFields({ foo: 1 }, { foo: 2, bar: 2 })).toEqual({ foo: 2, bar: 2 }); - }); - - test("month and monthCode property handling", () => { - const calendar = new Temporal.Calendar("iso8601"); - expect(calendar.mergeFields({ month: 1 }, { monthCode: 2 })).toEqual({ monthCode: 2 }); - expect(calendar.mergeFields({ monthCode: 1 }, { month: 2 })).toEqual({ month: 2 }); - expect(calendar.mergeFields({ month: 1, monthCode: 1 }, {})).toEqual({ - month: 1, - monthCode: 1, - }); - expect( - calendar.mergeFields({ month: 1, monthCode: 1 }, { month: 2, monthCode: 2 }) - ).toEqual({ month: 2, monthCode: 2 }); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.Calendar object", () => { - expect(() => { - Temporal.Calendar.prototype.mergeFields.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.Calendar"); - }); - - test("fields argument must be coercible to object", () => { - const calendar = new Temporal.Calendar("iso8601"); - expect(() => { - calendar.mergeFields(null, {}); - }).toThrowWithMessage(TypeError, "ToObject on null or undefined"); - }); - - test("additionalFields argument must be coercible to object", () => { - const calendar = new Temporal.Calendar("iso8601"); - expect(() => { - calendar.mergeFields({}, null); - }).toThrowWithMessage(TypeError, "ToObject on null or undefined"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.month.js b/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.month.js deleted file mode 100644 index 92fd7561991..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.month.js +++ /dev/null @@ -1,24 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.Calendar.prototype.month).toHaveLength(1); - }); - - test("basic functionality", () => { - const calendar = new Temporal.Calendar("iso8601"); - const date = new Temporal.PlainDate(2021, 7, 23); - expect(calendar.month(date)).toBe(7); - }); -}); - -describe("errors", () => { - test("argument must not be a Temporal.PlainMonthDay object", () => { - const calendar = new Temporal.Calendar("iso8601"); - const plainMonthDay = new Temporal.PlainMonthDay(7, 6); - expect(() => { - calendar.month(plainMonthDay); - }).toThrowWithMessage( - TypeError, - "Accessing month of PlainMonthDay is ambiguous, use monthCode instead" - ); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.monthCode.js b/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.monthCode.js deleted file mode 100644 index c701cfd668c..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.monthCode.js +++ /dev/null @@ -1,11 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.Calendar.prototype.monthCode).toHaveLength(1); - }); - - test("basic functionality", () => { - const calendar = new Temporal.Calendar("iso8601"); - const date = new Temporal.PlainDate(2021, 7, 23); - expect(calendar.monthCode(date)).toBe("M07"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.monthDayFromFields.js b/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.monthDayFromFields.js deleted file mode 100644 index ff5e9cccf31..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.monthDayFromFields.js +++ /dev/null @@ -1,103 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.Calendar.prototype.monthDayFromFields).toHaveLength(1); - }); - - test("basic functionality", () => { - const calendar = new Temporal.Calendar("iso8601"); - const plainMonthDay = calendar.monthDayFromFields({ year: 2021, month: 7, day: 6 }); - expect(plainMonthDay.calendar).toBe(calendar); - expect(plainMonthDay.monthCode).toBe("M07"); - expect(plainMonthDay.day).toBe(6); - - const fields = plainMonthDay.getISOFields(); - expect(fields.isoYear).toBe(1972); // No, this isn't a mistake - }); - - test("with monthCode", () => { - const calendar = new Temporal.Calendar("iso8601"); - const plainMonthDay = calendar.monthDayFromFields({ monthCode: "M07", day: 6 }); - expect(plainMonthDay.calendar).toBe(calendar); - expect(plainMonthDay.monthCode).toBe("M07"); - expect(plainMonthDay.day).toBe(6); - - const fields = plainMonthDay.getISOFields(); - expect(fields.isoYear).toBe(1972); - }); - - test("gets overflow after temporal fields", () => { - const operations = []; - const calendar = new Temporal.Calendar("iso8601"); - - const fields = { - get day() { - operations.push("get day"); - return 3; - }, - - get month() { - operations.push("get month"); - return 10; - }, - - get monthCode() { - operations.push("get monthCode"); - return "M10"; - }, - - get year() { - operations.push("get year"); - return 2022; - }, - }; - - const options = { - get overflow() { - operations.push("get overflow"); - return "constrain"; - }, - }; - - expect(operations).toHaveLength(0); - calendar.monthDayFromFields(fields, options); - expect(operations).toHaveLength(5); - expect(operations[0]).toBe("get day"); - expect(operations[1]).toBe("get month"); - expect(operations[2]).toBe("get monthCode"); - expect(operations[3]).toBe("get year"); - expect(operations[4]).toBe("get overflow"); - }); -}); - -describe("errors", () => { - test("first argument must be an object", () => { - const calendar = new Temporal.Calendar("iso8601"); - expect(() => { - calendar.monthDayFromFields(42); - }).toThrowWithMessage(TypeError, "42 is not an object"); - }); - - test("month or monthCode field is required", () => { - const calendar = new Temporal.Calendar("iso8601"); - expect(() => { - calendar.monthDayFromFields({ year: 2021, day: 1 }); - }).toThrowWithMessage(TypeError, "Required property month is missing or undefined"); - }); - - test("day field is required", () => { - const calendar = new Temporal.Calendar("iso8601"); - expect(() => { - calendar.monthDayFromFields({ year: 2021, month: 7 }); - }).toThrowWithMessage(TypeError, "Required property day is missing or undefined"); - }); - - test("monthCode or year field is required when month is given", () => { - const calendar = new Temporal.Calendar("iso8601"); - expect(() => { - calendar.monthDayFromFields({ month: 7, day: 6 }); - }).toThrowWithMessage( - TypeError, - "Required property monthCode or year is missing or undefined" - ); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.monthsInYear.js b/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.monthsInYear.js deleted file mode 100644 index 521e8111a4f..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.monthsInYear.js +++ /dev/null @@ -1,11 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.Calendar.prototype.monthsInYear).toHaveLength(1); - }); - - test("basic functionality", () => { - const calendar = new Temporal.Calendar("iso8601"); - const date = new Temporal.PlainDate(2021, 7, 23); - expect(calendar.monthsInYear(date)).toBe(12); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.toJSON.js b/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.toJSON.js deleted file mode 100644 index 6470c47bcfb..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.toJSON.js +++ /dev/null @@ -1,18 +0,0 @@ -describe("correct behavior", () => { - test("length is 0", () => { - expect(Temporal.Calendar.prototype.toJSON).toHaveLength(0); - }); - - test("basic functionality", () => { - const calendar = new Temporal.Calendar("iso8601"); - expect(calendar.toJSON()).toBe("iso8601"); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.Calendar object", () => { - expect(() => { - Temporal.Calendar.prototype.toJSON.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.Calendar"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.toString.js b/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.toString.js deleted file mode 100644 index 49aad08e952..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.toString.js +++ /dev/null @@ -1,18 +0,0 @@ -describe("correct behavior", () => { - test("length is 0", () => { - expect(Temporal.Calendar.prototype.toString).toHaveLength(0); - }); - - test("basic functionality", () => { - const calendar = new Temporal.Calendar("iso8601"); - expect(calendar.toString()).toBe("iso8601"); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.Calendar object", () => { - expect(() => { - Temporal.Calendar.prototype.toString.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.Calendar"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.weekOfYear.js b/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.weekOfYear.js deleted file mode 100644 index f0e8560746f..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.weekOfYear.js +++ /dev/null @@ -1,11 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.Calendar.prototype.weekOfYear).toHaveLength(1); - }); - - test("basic functionality", () => { - const calendar = new Temporal.Calendar("iso8601"); - const date = new Temporal.PlainDate(2021, 7, 23); - expect(calendar.weekOfYear(date)).toBe(29); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.year.js b/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.year.js deleted file mode 100644 index 469a87dec92..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.year.js +++ /dev/null @@ -1,11 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.Calendar.prototype.year).toHaveLength(1); - }); - - test("basic functionality", () => { - const calendar = new Temporal.Calendar("iso8601"); - const date = new Temporal.PlainDate(2021, 7, 23); - expect(calendar.year(date)).toBe(2021); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.yearMonthFromFields.js b/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.yearMonthFromFields.js deleted file mode 100644 index 1a7c36184e7..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.yearMonthFromFields.js +++ /dev/null @@ -1,81 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.Calendar.prototype.yearMonthFromFields).toHaveLength(1); - }); - - test("basic functionality", () => { - const calendar = new Temporal.Calendar("iso8601"); - const plainYearMonth = calendar.yearMonthFromFields({ year: 2021, month: 7 }); - expect(plainYearMonth.calendar).toBe(calendar); - expect(plainYearMonth.year).toBe(2021); - expect(plainYearMonth.month).toBe(7); - }); - - test("with monthCode", () => { - const calendar = new Temporal.Calendar("iso8601"); - const plainYearMonth = calendar.yearMonthFromFields({ year: 2021, monthCode: "M07" }); - expect(plainYearMonth.calendar).toBe(calendar); - expect(plainYearMonth.year).toBe(2021); - expect(plainYearMonth.month).toBe(7); - }); - - test("gets overflow after temporal fields", () => { - const operations = []; - const calendar = new Temporal.Calendar("iso8601"); - - const fields = { - get month() { - operations.push("get month"); - return 10; - }, - - get monthCode() { - operations.push("get monthCode"); - return "M10"; - }, - - get year() { - operations.push("get year"); - return 2022; - }, - }; - - const options = { - get overflow() { - operations.push("get overflow"); - return "constrain"; - }, - }; - - expect(operations).toHaveLength(0); - calendar.yearMonthFromFields(fields, options); - expect(operations).toHaveLength(4); - expect(operations[0]).toBe("get month"); - expect(operations[1]).toBe("get monthCode"); - expect(operations[2]).toBe("get year"); - expect(operations[3]).toBe("get overflow"); - }); -}); - -describe("errors", () => { - test("first argument must be an object", () => { - const calendar = new Temporal.Calendar("iso8601"); - expect(() => { - calendar.yearMonthFromFields(42); - }).toThrowWithMessage(TypeError, "42 is not an object"); - }); - - test("year field is required", () => { - const calendar = new Temporal.Calendar("iso8601"); - expect(() => { - calendar.yearMonthFromFields({ month: 7 }); - }).toThrowWithMessage(TypeError, "Required property year is missing or undefined"); - }); - - test("month or monthCode field is required", () => { - const calendar = new Temporal.Calendar("iso8601"); - expect(() => { - calendar.yearMonthFromFields({ year: 2021 }); - }).toThrowWithMessage(TypeError, "Required property month is missing or undefined"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.yearOfWeek.js b/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.yearOfWeek.js deleted file mode 100644 index e4aae55756a..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Calendar/Calendar.prototype.yearOfWeek.js +++ /dev/null @@ -1,19 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.Calendar.prototype.yearOfWeek).toHaveLength(1); - }); - - test("basic functionality", () => { - const calendar = new Temporal.Calendar("iso8601"); - const date = new Temporal.PlainDate(2023, 1, 1); - expect(calendar.yearOfWeek(date)).toBe(2022); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.Calendar object", () => { - expect(() => { - Temporal.Calendar.prototype.yearOfWeek.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.Calendar"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.compare.js b/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.compare.js deleted file mode 100644 index d533512434e..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.compare.js +++ /dev/null @@ -1,113 +0,0 @@ -describe("correct behavior", () => { - test("length is 2", () => { - expect(Temporal.Duration.compare).toHaveLength(2); - }); - - function checkCommonResults(duration1, duration2) { - expect(Temporal.Duration.compare(duration1, duration1)).toBe(0); - expect(Temporal.Duration.compare(duration2, duration2)).toBe(0); - expect(Temporal.Duration.compare(duration1, duration2)).toBe(-1); - expect(Temporal.Duration.compare(duration2, duration1)).toBe(1); - } - - test("basic functionality", () => { - const duration1 = new Temporal.Duration(0, 0, 0, 1); - const duration2 = new Temporal.Duration(0, 0, 0, 2); - checkCommonResults(duration1, duration2); - }); - - test("duration-like objects", () => { - const duration1 = { years: 0, months: 0, weeks: 0, days: 1 }; - const duration2 = { years: 0, months: 0, weeks: 0, days: 2 }; - checkCommonResults(duration1, duration2); - }); - - test("duration strings", () => { - const duration1 = "P1D"; - const duration2 = "P2D"; - checkCommonResults(duration1, duration2); - }); -}); - -describe("errors", () => { - test("invalid duration-like object", () => { - expect(() => { - Temporal.Duration.compare({}); - }).toThrowWithMessage(TypeError, "Invalid duration-like object"); - - expect(() => { - Temporal.Duration.compare({ years: 0, months: 0, weeks: 0, days: 1 }, {}); - }).toThrowWithMessage(TypeError, "Invalid duration-like object"); - }); - - test("relativeTo is required for comparing calendar units (year, month, week)", () => { - const duration1 = new Temporal.Duration(1); - const duration2 = new Temporal.Duration(2); - - expect(() => { - Temporal.Duration.compare(duration1, duration2); - }).toThrowWithMessage( - RangeError, - "A starting point is required for balancing calendar units" - ); - - const duration3 = new Temporal.Duration(0, 3); - const duration4 = new Temporal.Duration(0, 4); - - expect(() => { - Temporal.Duration.compare(duration3, duration4); - }).toThrowWithMessage( - RangeError, - "A starting point is required for balancing calendar units" - ); - - const duration5 = new Temporal.Duration(0, 0, 5); - const duration6 = new Temporal.Duration(0, 0, 6); - - expect(() => { - Temporal.Duration.compare(duration5, duration6); - }).toThrowWithMessage( - RangeError, - "A starting point is required for balancing calendar units" - ); - - // Still throws if year/month/week of one the duration objects is non-zero. - const duration7 = new Temporal.Duration(0, 0, 0, 7); - const duration8 = new Temporal.Duration(0, 0, 8); - - expect(() => { - Temporal.Duration.compare(duration7, duration8); - }).toThrowWithMessage( - RangeError, - "A starting point is required for balancing calendar units" - ); - - const duration9 = new Temporal.Duration(0, 0, 9); - const duration10 = new Temporal.Duration(0, 0, 0, 10); - - expect(() => { - Temporal.Duration.compare(duration9, duration10); - }).toThrowWithMessage( - RangeError, - "A starting point is required for balancing calendar units" - ); - }); - - test("custom time zone doesn't have a getOffsetNanosecondsFor function", () => { - const zonedDateTime = new Temporal.ZonedDateTime(0n, {}); - const duration = new Temporal.Duration(); - expect(() => { - Temporal.Duration.compare(duration, duration, { relativeTo: zonedDateTime }); - }).toThrowWithMessage(TypeError, "getOffsetNanosecondsFor is undefined"); - }); - - test("UTC designator only allowed with bracketed time zone", () => { - const duration = new Temporal.Duration(); - expect(() => { - Temporal.Duration.compare(duration, duration, { relativeTo: "2022-08-18T17:01Z" }); - }).toThrowWithMessage( - RangeError, - "Invalid relativeTo string '2022-08-18T17:01Z': must not contain a UTC designator without bracketed time zone" - ); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.from.js b/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.from.js deleted file mode 100644 index 3a314e877c8..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.from.js +++ /dev/null @@ -1,133 +0,0 @@ -const expectDurationOneToTen = duration => { - expect(duration.years).toBe(1); - expect(duration.months).toBe(2); - expect(duration.weeks).toBe(3); - expect(duration.days).toBe(4); - expect(duration.hours).toBe(5); - expect(duration.minutes).toBe(6); - expect(duration.seconds).toBe(7); - expect(duration.milliseconds).toBe(8); - expect(duration.microseconds).toBe(9); - expect(duration.nanoseconds).toBe(10); -}; - -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.Duration.from).toHaveLength(1); - }); - - test("Duration instance argument", () => { - const duration = Temporal.Duration.from( - new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) - ); - expectDurationOneToTen(duration); - }); - - test("Duration-like object argument", () => { - const duration = Temporal.Duration.from({ - years: 1, - months: 2, - weeks: 3, - days: 4, - hours: 5, - minutes: 6, - seconds: 7, - milliseconds: 8, - microseconds: 9, - nanoseconds: 10, - }); - expectDurationOneToTen(duration); - }); - - test("NaN value becomes zero", () => { - // NOTE: NaN does *not* throw a RangeError anymore - which is questionable, IMO - as of: - // https://github.com/tc39/proposal-temporal/commit/8c854507a52efbc6e9eb2642f0f928df38e5c021 - const duration = Temporal.Duration.from({ years: "foo" }); - expect(duration.years).toBe(0); - }); - - test("Duration string argument", () => { - // FIXME: yes, this needs 11 instead of 10 for nanoseconds for the test to pass. - // See comment in parse_temporal_duration_string(). - const duration = Temporal.Duration.from("P1Y2M3W4DT5H6M7.008009011S"); - expectDurationOneToTen(duration); - }); -}); - -describe("errors", () => { - test("Invalid duration-like object", () => { - expect(() => { - Temporal.Duration.from({}); - }).toThrowWithMessage(TypeError, "Invalid duration-like object"); - }); - - test("Invalid duration property value", () => { - expect(() => { - Temporal.Duration.from({ years: 1.23 }); - }).toThrowWithMessage( - RangeError, - "Invalid value for duration property 'years': must be an integer, got 1.2" // ...29999999999999 - let's not include that in the test :^) - ); - }); - - test("invalid duration string", () => { - expect(() => { - Temporal.Duration.from("foo"); - }).toThrowWithMessage(RangeError, "Invalid duration string 'foo'"); - }); - - test("invalid duration string: fractional hours proceeded by minutes or seconds", () => { - const values = [ - "PT1.23H1M", - "PT1.23H1.23M", - "PT1.23H1S", - "PT1.23H1.23S", - "PT1.23H1M1S", - "PT1.23H1M1.23S", - "PT1.23H1.23M1S", - "PT1.23H1.23M1.23S", - ]; - for (const value of values) { - expect(() => { - Temporal.Duration.from(value); - }).toThrowWithMessage( - RangeError, - `Invalid duration string '${value}': fractional hours must not be proceeded by minutes or seconds` - ); - } - }); - - test("invalid duration string: fractional minutes proceeded by seconds", () => { - const values = ["PT1.23M1S", "PT1.23M1.23S"]; - for (const value of values) { - expect(() => { - Temporal.Duration.from(value); - }).toThrowWithMessage( - RangeError, - `Invalid duration string '${value}': fractional minutes must not be proceeded by seconds` - ); - } - }); - - test("invalid duration string: exceed duration limits", () => { - const values = [ - "P4294967296Y", // abs(years) >= 2**32 - "P4294967296M", // abs(months) >= 2**32 - "P4294967296W", // abs(weeks) >= 2**32 - "P104249991375D", // days >= 2*53 seconds - "PT2501999792984H", // hours >= 2*53 seconds - "PT150119987579017M", // minutes >= 2*53 seconds - "PT9007199254740992S", // seconds >= 2*53 seconds - ]; - - for (const value of values) { - expect(() => { - Temporal.Duration.from(value); - }).toThrowWithMessage(RangeError, `Invalid duration`); - - expect(() => { - Temporal.Duration.from("-" + value); - }).toThrowWithMessage(RangeError, `Invalid duration`); - } - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.js b/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.js deleted file mode 100644 index df1b3c660a0..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.js +++ /dev/null @@ -1,35 +0,0 @@ -describe("errors", () => { - test("called without new", () => { - expect(() => { - Temporal.Duration(); - }).toThrowWithMessage(TypeError, "Temporal.Duration constructor must be called with 'new'"); - }); - - test("cannot mix arguments with different signs", () => { - expect(() => { - new Temporal.Duration(-1, 1); - }).toThrowWithMessage(RangeError, "Invalid duration"); - expect(() => { - new Temporal.Duration(1, -1); - }).toThrowWithMessage(RangeError, "Invalid duration"); - }); - - test("cannot pass Infinity", () => { - expect(() => { - new Temporal.Duration(Infinity); - }).toThrowWithMessage(RangeError, "Invalid duration"); - }); -}); - -describe("normal behavior", () => { - test("length is 0", () => { - expect(Temporal.Duration).toHaveLength(0); - }); - - test("basic functionality", () => { - const duration = new Temporal.Duration(); - expect(typeof duration).toBe("object"); - expect(duration).toBeInstanceOf(Temporal.Duration); - expect(Object.getPrototypeOf(duration)).toBe(Temporal.Duration.prototype); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.@@toStringTag.js b/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.@@toStringTag.js deleted file mode 100644 index 93c0c32a946..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.@@toStringTag.js +++ /dev/null @@ -1,3 +0,0 @@ -test("basic functionality", () => { - expect(Temporal.Duration.prototype[Symbol.toStringTag]).toBe("Temporal.Duration"); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.abs.js b/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.abs.js deleted file mode 100644 index ba80ce52722..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.abs.js +++ /dev/null @@ -1,53 +0,0 @@ -const DURATION_PROPERTIES = [ - "years", - "months", - "weeks", - "days", - "hours", - "minutes", - "seconds", - "milliseconds", - "microseconds", - "nanoseconds", -]; - -describe("correct behavior", () => { - test("length is 0", () => { - expect(Temporal.Duration.prototype.abs).toHaveLength(0); - }); - - test("basic functionality", () => { - let absoluteDuration; - - absoluteDuration = new Temporal.Duration(123).abs(); - expect(absoluteDuration.years).toBe(123); - - absoluteDuration = new Temporal.Duration(-123).abs(); - expect(absoluteDuration.years).toBe(123); - }); - - test("each property is made absolute", () => { - let values; - let duration; - - values = Array(DURATION_PROPERTIES.length).fill(-1); - duration = new Temporal.Duration(...values).abs(); - for (const property of DURATION_PROPERTIES) { - expect(duration[property]).toBe(1); - } - - values = Array(DURATION_PROPERTIES.length).fill(1); - duration = new Temporal.Duration(...values).abs(); - for (const property of DURATION_PROPERTIES) { - expect(duration[property]).toBe(1); - } - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.Duration object", () => { - expect(() => { - Temporal.Duration.prototype.abs.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.Duration"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.add.js b/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.add.js deleted file mode 100644 index b6a50d14d87..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.add.js +++ /dev/null @@ -1,86 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.Duration.prototype.add).toHaveLength(1); - }); - - function checkCommonResults(durationResult) { - expect(durationResult.years).toBe(0); - expect(durationResult.months).toBe(0); - expect(durationResult.weeks).toBe(0); - expect(durationResult.days).toBe(3); - expect(durationResult.hours).toBe(3); - expect(durationResult.minutes).toBe(3); - expect(durationResult.seconds).toBe(3); - expect(durationResult.milliseconds).toBe(3); - expect(durationResult.microseconds).toBe(3); - expect(durationResult.nanoseconds).toBe(3); - } - - test("basic functionality", () => { - const duration = new Temporal.Duration(0, 0, 0, 2, 2, 2, 2, 2, 2, 2); - const oneDuration = new Temporal.Duration(0, 0, 0, 1, 1, 1, 1, 1, 1, 1); - const durationResult = duration.add(oneDuration); - - checkCommonResults(durationResult); - }); - - test("from duration-like", () => { - const duration = new Temporal.Duration(0, 0, 0, 2, 2, 2, 2, 2, 2, 2); - const oneDuration = { - days: 1, - hours: 1, - minutes: 1, - seconds: 1, - milliseconds: 1, - microseconds: 1, - nanoseconds: 1, - }; - const durationResult = duration.add(oneDuration); - - checkCommonResults(durationResult); - }); - - test("from string", () => { - const duration = new Temporal.Duration(0, 0, 0, 2, 2, 2, 2, 2, 2, 2); - const oneDuration = "P1DT1H1M1.001001001S"; - const durationResult = duration.add(oneDuration); - - checkCommonResults(durationResult); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.Duration object", () => { - expect(() => { - Temporal.Duration.prototype.add.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.Duration"); - }); - - test("relativeTo is required when duration has calendar units", () => { - const yearDuration = new Temporal.Duration(1); - const monthDuration = new Temporal.Duration(0, 1); - const weekDuration = new Temporal.Duration(0, 0, 1); - const durationToAdd = { seconds: 1 }; - - expect(() => { - yearDuration.add(durationToAdd); - }).toThrowWithMessage( - RangeError, - "A starting point is required for balancing year, month or week" - ); - - expect(() => { - monthDuration.add(durationToAdd); - }).toThrowWithMessage( - RangeError, - "A starting point is required for balancing year, month or week" - ); - - expect(() => { - weekDuration.add(durationToAdd); - }).toThrowWithMessage( - RangeError, - "A starting point is required for balancing year, month or week" - ); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.blank.js b/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.blank.js deleted file mode 100644 index 284d2837a34..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.blank.js +++ /dev/null @@ -1,17 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const nonBlankDuration = new Temporal.Duration(123); - expect(nonBlankDuration.blank).toBeFalse(); - - const blankDuration = new Temporal.Duration(0); - expect(blankDuration.blank).toBeTrue(); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.Duration object", () => { - expect(() => { - Reflect.get(Temporal.Duration.prototype, "blank", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.Duration"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.days.js b/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.days.js deleted file mode 100644 index 6f41661e41f..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.days.js +++ /dev/null @@ -1,14 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const duration = new Temporal.Duration(0, 0, 0, 123); - expect(duration.days).toBe(123); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.Duration object", () => { - expect(() => { - Reflect.get(Temporal.Duration.prototype, "days", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.Duration"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.hours.js b/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.hours.js deleted file mode 100644 index e325bf7060d..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.hours.js +++ /dev/null @@ -1,14 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const duration = new Temporal.Duration(0, 0, 0, 0, 123); - expect(duration.hours).toBe(123); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.Duration object", () => { - expect(() => { - Reflect.get(Temporal.Duration.prototype, "hours", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.Duration"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.microseconds.js b/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.microseconds.js deleted file mode 100644 index 5230e2b5591..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.microseconds.js +++ /dev/null @@ -1,14 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const duration = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 123); - expect(duration.microseconds).toBe(123); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.Duration object", () => { - expect(() => { - Reflect.get(Temporal.Duration.prototype, "microseconds", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.Duration"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.milliseconds.js b/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.milliseconds.js deleted file mode 100644 index 31d90bfda67..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.milliseconds.js +++ /dev/null @@ -1,14 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const duration = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 123); - expect(duration.milliseconds).toBe(123); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.Duration object", () => { - expect(() => { - Reflect.get(Temporal.Duration.prototype, "milliseconds", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.Duration"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.minutes.js b/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.minutes.js deleted file mode 100644 index d47b8296b9b..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.minutes.js +++ /dev/null @@ -1,14 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const duration = new Temporal.Duration(0, 0, 0, 0, 0, 123); - expect(duration.minutes).toBe(123); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.Duration object", () => { - expect(() => { - Reflect.get(Temporal.Duration.prototype, "minutes", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.Duration"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.months.js b/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.months.js deleted file mode 100644 index 01424ffe945..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.months.js +++ /dev/null @@ -1,14 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const duration = new Temporal.Duration(0, 123); - expect(duration.months).toBe(123); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.Duration object", () => { - expect(() => { - Reflect.get(Temporal.Duration.prototype, "months", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.Duration"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.nanoseconds.js b/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.nanoseconds.js deleted file mode 100644 index d9b5117a8fa..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.nanoseconds.js +++ /dev/null @@ -1,14 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const duration = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, 123); - expect(duration.nanoseconds).toBe(123); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.Duration object", () => { - expect(() => { - Reflect.get(Temporal.Duration.prototype, "nanoseconds", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.Duration"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.negated.js b/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.negated.js deleted file mode 100644 index d96f5a04d00..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.negated.js +++ /dev/null @@ -1,42 +0,0 @@ -const DURATION_PROPERTIES = [ - "years", - "months", - "weeks", - "days", - "hours", - "minutes", - "seconds", - "milliseconds", - "microseconds", - "nanoseconds", -]; - -describe("correct behavior", () => { - test("length is 0", () => { - expect(Temporal.Duration.prototype.negated).toHaveLength(0); - }); - - test("basic functionality", () => { - const negativeDuration = new Temporal.Duration(123).negated(); - expect(negativeDuration.years).toBe(-123); - - const positiveDuration = new Temporal.Duration(-123).negated(); - expect(positiveDuration.years).toBe(123); - }); - - test("each property is negated", () => { - const values = Array(DURATION_PROPERTIES.length).fill(1); - const duration = new Temporal.Duration(...values).negated(); - for (const property of DURATION_PROPERTIES) { - expect(duration[property]).toBe(-1); - } - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.Duration object", () => { - expect(() => { - Temporal.Duration.prototype.negated.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.Duration"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.round.js b/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.round.js deleted file mode 100644 index 51ea215aab5..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.round.js +++ /dev/null @@ -1,196 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.Duration.prototype.round).toHaveLength(1); - }); - - test("basic functionality", () => { - const duration = new Temporal.Duration(0, 0, 0, 21, 7, 10, 100, 200, 300, 400); - const values = [ - ["nanosecond", "P21DT7H11M40.2003004S"], - ["microsecond", "P21DT7H11M40.2003S"], - ["millisecond", "P21DT7H11M40.2S"], - ["second", "P21DT7H11M40S"], - ["minute", "P21DT7H12M"], - ["hour", "P21DT7H"], - ["day", "P21D"], - ]; - - for (const [smallestUnit, durationString] of values) { - const singularRoundedDuration = duration.round({ smallestUnit }); - const pluralRoundedDuration = duration.round({ smallestUnit: `${smallestUnit}s` }); - - // Passing in a string is treated as though { smallestUnit: "" } was passed in. - const singularRoundedDurationWithString = duration.round(smallestUnit); - const pluralRoundedDurationWithString = duration.round(`${smallestUnit}s`); - - expect(singularRoundedDuration.toString()).toBe(durationString); - expect(singularRoundedDurationWithString.toString()).toBe(durationString); - expect(pluralRoundedDuration.toString()).toBe(durationString); - expect(pluralRoundedDurationWithString.toString()).toBe(durationString); - } - }); - - test("largestUnit option", () => { - const duration = new Temporal.Duration(0, 0, 0, 21, 7, 10, 100, 200, 300, 400); - - // Using strings is not sufficient here, for example, the nanosecond case will produce "PT1840300.2003004S" which is 1840300 s, 200 ms, 300 us, 400 ns - const values = [ - ["nanosecond", { nanoseconds: 1840300200300400 }], - ["microsecond", { microseconds: 1840300200300, nanoseconds: 400 }], - ["millisecond", { milliseconds: 1840300200, microseconds: 300, nanoseconds: 400 }], - [ - "second", - { seconds: 1840300, milliseconds: 200, microseconds: 300, nanoseconds: 400 }, - ], - [ - "minute", - { - minutes: 30671, - seconds: 40, - milliseconds: 200, - microseconds: 300, - nanoseconds: 400, - }, - ], - [ - "hour", - { - hours: 511, - minutes: 11, - seconds: 40, - milliseconds: 200, - microseconds: 300, - nanoseconds: 400, - }, - ], - [ - "day", - { - days: 21, - hours: 7, - minutes: 11, - seconds: 40, - milliseconds: 200, - microseconds: 300, - nanoseconds: 400, - }, - ], - ]; - - for (const [largestUnit, durationLike] of values) { - const singularRoundedDuration = duration.round({ largestUnit }); - const pluralRoundedDuration = duration.round({ largestUnit: `${largestUnit}s` }); - - const propertiesToCheck = Object.keys(durationLike); - - for (const property of propertiesToCheck) { - expect(singularRoundedDuration[property]).toBe(durationLike[property]); - expect(pluralRoundedDuration[property]).toBe(durationLike[property]); - } - } - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.Duration object", () => { - expect(() => { - Temporal.Duration.prototype.round.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.Duration"); - }); - - test("missing options object", () => { - const duration = new Temporal.Duration(1); - expect(() => { - duration.round(); - }).toThrowWithMessage(TypeError, "Required options object is missing or undefined"); - }); - - test("invalid rounding mode", () => { - const duration = new Temporal.Duration(1); - expect(() => { - duration.round({ smallestUnit: "second", roundingMode: "serenityOS" }); - }).toThrowWithMessage( - RangeError, - "serenityOS is not a valid value for option roundingMode" - ); - }); - - test("invalid smallest unit", () => { - const duration = new Temporal.Duration(1); - expect(() => { - duration.round({ smallestUnit: "serenityOS" }); - }).toThrowWithMessage( - RangeError, - "serenityOS is not a valid value for option smallestUnit" - ); - }); - - test("increment may not be NaN", () => { - const duration = new Temporal.Duration(1); - expect(() => { - duration.round({ smallestUnit: "second", roundingIncrement: NaN }); - }).toThrowWithMessage(RangeError, "NaN is not a valid value for option roundingIncrement"); - }); - - test("increment may smaller than 1 or larger than maximum", () => { - const duration = new Temporal.Duration(1); - expect(() => { - duration.round({ smallestUnit: "second", roundingIncrement: -1 }); - }).toThrowWithMessage(RangeError, "-1 is not a valid value for option roundingIncrement"); - expect(() => { - duration.round({ smallestUnit: "second", roundingIncrement: 0 }); - }).toThrowWithMessage(RangeError, "0 is not a valid value for option roundingIncrement"); - expect(() => { - duration.round({ smallestUnit: "second", roundingIncrement: Infinity }); - }).toThrowWithMessage(RangeError, "inf is not a valid value for option roundingIncrement"); - }); - - test("must provide one or both of smallestUnit or largestUnit", () => { - const duration = new Temporal.Duration(1); - expect(() => { - duration.round({}); - }).toThrowWithMessage(RangeError, "One or both of smallestUnit or largestUnit is required"); - }); - - test("relativeTo is required when duration has calendar units", () => { - const duration = new Temporal.Duration(1); - expect(() => { - duration.round({ largestUnit: "second" }); - }).toThrowWithMessage( - RangeError, - "A starting point is required for balancing calendar units" - ); - }); - - // Spec Issue: https://github.com/tc39/proposal-temporal/issues/2124 - // Spec Fix: https://github.com/tc39/proposal-temporal/commit/66f7464aaec64d3cd21fb2ec37f6502743b9a730 - test("balancing calendar units with largestUnit set to 'year' and relativeTo unset throws instead of crashing", () => { - const duration = new Temporal.Duration(1); - expect(() => { - duration.round({ largestUnit: "year" }); - }).toThrowWithMessage( - RangeError, - "A starting point is required for balancing calendar units" - ); - }); - - test("invalid calendar throws range exception when performing round", () => { - const duration = Temporal.Duration.from({ nanoseconds: 0 }); - - const calendar = new (class extends Temporal.Calendar { - dateAdd(date, duration, options) { - return date; - } - })("iso8601"); - - expect(() => { - duration.round({ - relativeTo: new Temporal.PlainDate(1997, 5, 10, calendar), - smallestUnit: "years", - }); - }).toThrowWithMessage( - RangeError, - "Invalid calendar, dateAdd() function returned result implying a year is zero days long" - ); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.seconds.js b/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.seconds.js deleted file mode 100644 index f15a023e960..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.seconds.js +++ /dev/null @@ -1,14 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const duration = new Temporal.Duration(0, 0, 0, 0, 0, 0, 123); - expect(duration.seconds).toBe(123); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.Duration object", () => { - expect(() => { - Reflect.get(Temporal.Duration.prototype, "seconds", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.Duration"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.sign.js b/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.sign.js deleted file mode 100644 index aeabf47d8ef..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.sign.js +++ /dev/null @@ -1,17 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const positiveDuration = new Temporal.Duration(123); - expect(positiveDuration.sign).toBe(1); - - const negativeDuration = new Temporal.Duration(-123); - expect(negativeDuration.sign).toBe(-1); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.Duration object", () => { - expect(() => { - Reflect.get(Temporal.Duration.prototype, "sign", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.Duration"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.subtract.js b/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.subtract.js deleted file mode 100644 index 8b9f473fb41..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.subtract.js +++ /dev/null @@ -1,86 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.Duration.prototype.subtract).toHaveLength(1); - }); - - function checkCommonResults(durationResult) { - expect(durationResult.years).toBe(0); - expect(durationResult.months).toBe(0); - expect(durationResult.weeks).toBe(0); - expect(durationResult.days).toBe(1); - expect(durationResult.hours).toBe(1); - expect(durationResult.minutes).toBe(1); - expect(durationResult.seconds).toBe(1); - expect(durationResult.milliseconds).toBe(1); - expect(durationResult.microseconds).toBe(1); - expect(durationResult.nanoseconds).toBe(1); - } - - test("basic functionality", () => { - const duration = new Temporal.Duration(0, 0, 0, 2, 2, 2, 2, 2, 2, 2); - const oneDuration = new Temporal.Duration(0, 0, 0, 1, 1, 1, 1, 1, 1, 1); - const durationResult = duration.subtract(oneDuration); - - checkCommonResults(durationResult); - }); - - test("from duration-like", () => { - const duration = new Temporal.Duration(0, 0, 0, 2, 2, 2, 2, 2, 2, 2); - const oneDuration = { - days: 1, - hours: 1, - minutes: 1, - seconds: 1, - milliseconds: 1, - microseconds: 1, - nanoseconds: 1, - }; - const durationResult = duration.subtract(oneDuration); - - checkCommonResults(durationResult); - }); - - test("from string", () => { - const duration = new Temporal.Duration(0, 0, 0, 2, 2, 2, 2, 2, 2, 2); - const oneDuration = "P1DT1H1M1.001001001S"; - const durationResult = duration.subtract(oneDuration); - - checkCommonResults(durationResult); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.Duration object", () => { - expect(() => { - Temporal.Duration.prototype.subtract.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.Duration"); - }); - - test("relativeTo is required when duration has calendar units", () => { - const yearDuration = new Temporal.Duration(1); - const monthDuration = new Temporal.Duration(0, 1); - const weekDuration = new Temporal.Duration(0, 0, 1); - const durationToSubtract = { seconds: 1 }; - - expect(() => { - yearDuration.subtract(durationToSubtract); - }).toThrowWithMessage( - RangeError, - "A starting point is required for balancing year, month or week" - ); - - expect(() => { - monthDuration.subtract(durationToSubtract); - }).toThrowWithMessage( - RangeError, - "A starting point is required for balancing year, month or week" - ); - - expect(() => { - weekDuration.subtract(durationToSubtract); - }).toThrowWithMessage( - RangeError, - "A starting point is required for balancing year, month or week" - ); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.toJSON.js b/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.toJSON.js deleted file mode 100644 index d324e957d28..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.toJSON.js +++ /dev/null @@ -1,19 +0,0 @@ -describe("correct behavior", () => { - test("length is 0", () => { - expect(Temporal.Duration.prototype.toJSON).toHaveLength(0); - }); - - test("basic functionality", () => { - expect(new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 8, 9, 10).toJSON()).toBe( - "P1Y2M3W4DT5H6M7.00800901S" - ); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.Duration object", () => { - expect(() => { - Temporal.Duration.prototype.toJSON.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.Duration"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.toLocaleString.js b/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.toLocaleString.js deleted file mode 100644 index 189c3b6846b..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.toLocaleString.js +++ /dev/null @@ -1,19 +0,0 @@ -describe("correct behavior", () => { - test("length is 0", () => { - expect(Temporal.Duration.prototype.toLocaleString).toHaveLength(0); - }); - - test("basic functionality", () => { - expect(new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 8, 9, 10).toLocaleString()).toBe( - "P1Y2M3W4DT5H6M7.00800901S" - ); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.Duration object", () => { - expect(() => { - Temporal.Duration.prototype.toLocaleString.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.Duration"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.toString.js b/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.toString.js deleted file mode 100644 index 1e9ea6a284c..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.toString.js +++ /dev/null @@ -1,94 +0,0 @@ -describe("correct behavior", () => { - test("length is 0", () => { - expect(Temporal.Duration.prototype.toString).toHaveLength(0); - }); - - test("basic functionality", () => { - const values = [ - [[0], "PT0S"], - [[1], "P1Y"], - [[0, 1], "P1M"], - [[0, 0, 1], "P1W"], - [[0, 0, 0, 1], "P1D"], - [[0, 0, 0, 0, 1], "PT1H"], - [[0, 0, 0, 0, 0, 1], "PT1M"], - [[0, 0, 0, 0, 0, 0, 1], "PT1S"], - [[0, 0, 0, 0, 0, 0, 0, 1], "PT0.001S"], - [[0, 0, 0, 0, 0, 0, 0, 0, 1], "PT0.000001S"], - [[0, 0, 0, 0, 0, 0, 0, 0, 0, 1], "PT0.000000001S"], - [[1, 2], "P1Y2M"], - [[1, 2, 3], "P1Y2M3W"], - [[1, 2, 3, 4], "P1Y2M3W4D"], - [[1, 2, 3, 4, 5], "P1Y2M3W4DT5H"], - [[1, 2, 3, 4, 5, 6], "P1Y2M3W4DT5H6M"], - [[1, 2, 3, 4, 5, 6, 7], "P1Y2M3W4DT5H6M7S"], - [[1, 2, 3, 4, 5, 6, 7, 8], "P1Y2M3W4DT5H6M7.008S"], - [[1, 2, 3, 4, 5, 6, 7, 8, 9], "P1Y2M3W4DT5H6M7.008009S"], - [[1, 2, 3, 4, 5, 6, 7, 8, 9, 10], "P1Y2M3W4DT5H6M7.00800901S"], - [ - [100, 200, 300, 400, 500, 600, 700, 800, 900, 1000], - "P100Y200M300W400DT500H600M700.800901S", - ], - [[-1], "-P1Y"], - ]; - for (const [args, expected] of values) { - expect(new Temporal.Duration(...args).toString()).toBe(expected); - } - }); - - test("smallestUnit option", () => { - const values = [ - ["second", "P1Y2M3W4DT5H6M7S"], - ["millisecond", "P1Y2M3W4DT5H6M7.008S"], - ["microsecond", "P1Y2M3W4DT5H6M7.008010S"], - ["nanosecond", "P1Y2M3W4DT5H6M7.008010000S"], - ]; - for (const [smallestUnit, expected] of values) { - expect( - new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 8, 10).toString({ smallestUnit }) - ).toBe(expected); - } - }); - - test("fractionalSecondDigits option", () => { - const values = [ - [0, "P1Y2M3W4DT5H6M7S"], - [1, "P1Y2M3W4DT5H6M7.0S"], - [2, "P1Y2M3W4DT5H6M7.00S"], - [3, "P1Y2M3W4DT5H6M7.008S"], - [4, "P1Y2M3W4DT5H6M7.0080S"], - [5, "P1Y2M3W4DT5H6M7.00801S"], - [6, "P1Y2M3W4DT5H6M7.008010S"], - [7, "P1Y2M3W4DT5H6M7.0080100S"], - [8, "P1Y2M3W4DT5H6M7.00801000S"], - [9, "P1Y2M3W4DT5H6M7.008010000S"], - ]; - for (const [fractionalSecondDigits, expected] of values) { - expect( - new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 8, 10).toString({ - fractionalSecondDigits, - }) - ).toBe(expected); - } - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.Duration object", () => { - expect(() => { - Temporal.Duration.prototype.toString.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.Duration"); - }); - - test("disallowed smallestUnit option values", () => { - const values = ["year", "month", "week", "day", "hour", "minute"]; - for (const smallestUnit of values) { - expect(() => { - new Temporal.Duration(0).toString({ smallestUnit }); - }).toThrowWithMessage( - RangeError, - `${smallestUnit} is not a valid value for option smallestUnit` - ); - } - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.total.js b/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.total.js deleted file mode 100644 index acce649369f..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.total.js +++ /dev/null @@ -1,107 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - { - const duration = new Temporal.Duration(0, 0, 0, 0, 1, 2, 3, 4, 5, 6); - const relativeTo = new Temporal.PlainDate(1970, 1, 1); - const values = [ - [{ unit: "year", relativeTo }, 0.0001180556825534627], - [{ unit: "month", relativeTo }, 0.0013900104558714158], - [{ unit: "week", relativeTo }, 0.006155760590287699], - [{ unit: "day", relativeTo }, 0.04309032413201389], - [{ unit: "hour" }, 1.034167779168333], - [{ unit: "minute" }, 62.0500667501], - [{ unit: "second" }, 3723.00400500600017], - [{ unit: "millisecond" }, 3723004.005005999933928], - [{ unit: "microsecond" }, 3723004005.006000041961669], - [{ unit: "nanosecond" }, 3723004005006], - ]; - for (const [arg, expected] of values) { - const matcher = Number.isInteger(expected) ? "toBe" : "toBeCloseTo"; - expect(duration.total(arg))[matcher](expected); - } - } - - { - const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); - const relativeTo = new Temporal.PlainDate(1970, 1, 1); - const values = [ - [{ unit: "year", relativeTo }, 1.2307194003046997], - [{ unit: "month", relativeTo }, 14.813309068103722], - [{ unit: "week", relativeTo }, 64.17322587303077], - [{ unit: "day", relativeTo }, 449.21258111121534], - [{ unit: "hour", relativeTo }, 10781.101946669169], - [{ unit: "minute", relativeTo }, 646866.1168001501], - [{ unit: "second", relativeTo }, 38811967.00800901], - [{ unit: "millisecond", relativeTo }, 38811967008.00901], - [{ unit: "microsecond", relativeTo }, 38811967008009.01], - [{ unit: "nanosecond", relativeTo }, 38811967008009010], - ]; - for (const [arg, expected] of values) { - const matcher = Number.isInteger(expected) ? "toBe" : "toBeCloseTo"; - expect(duration.total(arg))[matcher](expected); - } - } - - { - const relativeTo = new Temporal.PlainDate(1970, 1, 1); - const units = [ - "year", - "month", - "week", - "day", - "hour", - "minute", - "second", - "millisecond", - "microsecond", - "nanosecond", - ]; - for (let i = 0; i < 10; ++i) { - const args = [0, 0, 0, 0, 0, 0, 0, 0, 0]; - args[i] = 123; - const unit = units[i]; - const duration = new Temporal.Duration(...args); - expect(duration.total({ unit, relativeTo })).toBe(123); - } - } - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.Duration object", () => { - expect(() => { - Temporal.Duration.prototype.total.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.Duration"); - }); - - test("missing options object", () => { - const duration = new Temporal.Duration(); - expect(() => { - duration.total(); - }).toThrowWithMessage(TypeError, "Required options object is missing or undefined"); - }); - - test("missing unit option", () => { - const duration = new Temporal.Duration(); - expect(() => { - duration.total({}); - }).toThrowWithMessage(RangeError, "unit option value is undefined"); - }); - - test("invalid unit option", () => { - const duration = new Temporal.Duration(); - expect(() => { - duration.total({ unit: "foo" }); - }).toThrowWithMessage(RangeError, "foo is not a valid value for option unit"); - }); - - test("relativeTo is required when duration has calendar units", () => { - const duration = new Temporal.Duration(1); - expect(() => { - duration.total({ unit: "second" }); - }).toThrowWithMessage( - RangeError, - "A starting point is required for balancing calendar units" - ); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.valueOf.js b/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.valueOf.js deleted file mode 100644 index fb7a69cb6e4..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.valueOf.js +++ /dev/null @@ -1,7 +0,0 @@ -describe("errors", () => { - test("throws TypeError", () => { - expect(() => { - new Temporal.Duration().valueOf(); - }).toThrowWithMessage(TypeError, "Cannot convert Temporal.Duration to a primitive value"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.weeks.js b/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.weeks.js deleted file mode 100644 index b1c002cf3bd..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.weeks.js +++ /dev/null @@ -1,14 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const duration = new Temporal.Duration(0, 0, 123); - expect(duration.weeks).toBe(123); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.Duration object", () => { - expect(() => { - Reflect.get(Temporal.Duration.prototype, "weeks", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.Duration"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.with.js b/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.with.js deleted file mode 100644 index 4f4a7c28191..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.with.js +++ /dev/null @@ -1,94 +0,0 @@ -const DURATION_PROPERTIES = [ - "years", - "months", - "weeks", - "days", - "hours", - "minutes", - "seconds", - "milliseconds", - "microseconds", - "nanoseconds", -]; - -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.Duration.prototype.with).toHaveLength(1); - }); - - test("basic functionality", () => { - const duration = new Temporal.Duration(1, 2, 3).with({ years: 4, foo: 5, weeks: 6 }); - expect(duration.years).toBe(4); - expect(duration.months).toBe(2); - expect(duration.weeks).toBe(6); - }); - - test("each property is looked up from the object", () => { - for (const property of DURATION_PROPERTIES) { - const duration = new Temporal.Duration().with({ [property]: 1 }); - expect(duration[property]).toBe(1); - } - }); - - test("each property is coerced to number", () => { - for (const property of DURATION_PROPERTIES) { - const duration = new Temporal.Duration().with({ [property]: "1" }); - expect(duration[property]).toBe(1); - } - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.Duration object", () => { - expect(() => { - Temporal.Duration.prototype.with.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.Duration"); - }); - - test("argument is not an object", () => { - expect(() => { - new Temporal.Duration().with("foo"); - }).toThrowWithMessage(TypeError, "foo is not an object"); - expect(() => { - new Temporal.Duration().with(42); - }).toThrowWithMessage(TypeError, "42 is not an object"); - }); - - test("argument is an invalid duration-like object", () => { - expect(() => { - new Temporal.Duration().with({}); - }).toThrowWithMessage(TypeError, "Invalid duration-like object"); - expect(() => { - new Temporal.Duration().with({ foo: 1, bar: 2 }); - }).toThrowWithMessage(TypeError, "Invalid duration-like object"); - }); - - test("error when coercing property to number", () => { - for (const property of DURATION_PROPERTIES) { - expect(() => { - new Temporal.Duration().with({ - [property]: { - valueOf() { - throw new Error(); - }, - }, - }); - }).toThrow(Error); - } - }); - - test("invalid duration value", () => { - for (const property of DURATION_PROPERTIES) { - // NOTE: NaN does *not* throw a RangeError anymore - which is questionable, IMO - as of: - // https://github.com/tc39/proposal-temporal/commit/8c854507a52efbc6e9eb2642f0f928df38e5c021 - for (const value of [1.23, Infinity]) { - expect(() => { - new Temporal.Duration().with({ [property]: value }); - }).toThrowWithMessage( - RangeError, - `Invalid value for duration property '${property}': must be an integer, got ${value}` - ); - } - } - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.years.js b/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.years.js deleted file mode 100644 index 43175e6037d..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Duration/Duration.prototype.years.js +++ /dev/null @@ -1,14 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const duration = new Temporal.Duration(123); - expect(duration.years).toBe(123); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.Duration object", () => { - expect(() => { - Reflect.get(Temporal.Duration.prototype, "years", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.Duration"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.compare.js b/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.compare.js deleted file mode 100644 index 6118888f3f6..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.compare.js +++ /dev/null @@ -1,13 +0,0 @@ -describe("correct behavior", () => { - test("length is 2", () => { - expect(Temporal.Instant.compare).toHaveLength(2); - }); - - test("basic functionality", () => { - const instant1 = new Temporal.Instant(111n); - expect(Temporal.Instant.compare(instant1, instant1)).toBe(0); - const instant2 = new Temporal.Instant(999n); - expect(Temporal.Instant.compare(instant1, instant2)).toBe(-1); - expect(Temporal.Instant.compare(instant2, instant1)).toBe(1); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.from.js b/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.from.js deleted file mode 100644 index d4ed39d3bfd..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.from.js +++ /dev/null @@ -1,76 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.Instant.from).toHaveLength(1); - }); - - test("Instant instance argument", () => { - const instant = new Temporal.Instant(123n); - expect(Temporal.Instant.from(instant).epochNanoseconds).toBe(123n); - }); - - test("ZonedDateTime instance argument", () => { - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = new Temporal.ZonedDateTime(123n, timeZone); - expect(Temporal.Instant.from(zonedDateTime).epochNanoseconds).toBe(123n); - }); - - test("Instant string argument", () => { - expect(Temporal.Instant.from("1975-02-02T14:25:36.123456789Z").epochNanoseconds).toBe( - 160583136123456789n - ); - // Time zone is not validated - expect( - Temporal.Instant.from("1975-02-02T14:25:36.123456789Z[Custom/TimeZone]") - .epochNanoseconds - ).toBe(160583136123456789n); - - // Accepts but ignores the calendar. - let result = null; - expect(() => { - result = Temporal.Instant.from("1970-01-01T00:00Z[u-ca=UTC]"); - }).not.toThrow(); - expect(result).toBeInstanceOf(Temporal.Instant); - expect(result.epochNanoseconds).toBe(0n); - - // Does not validate calendar name, it only checks that the calendar name matches the grammar. - result = null; - expect(() => { - result = Temporal.Instant.from("1970-01-01T00:00Z[u-ca=aAaAaAaA-bBbBbBb]"); - }).not.toThrow(); - expect(result).toBeInstanceOf(Temporal.Instant); - expect(result.epochNanoseconds).toBe(0n); - }); -}); - -describe("errors", () => { - test("invalid instant string", () => { - expect(() => { - Temporal.Instant.from("foo"); - }).toThrowWithMessage(RangeError, "Invalid instant string 'foo'"); - }); - - test("invalid epoch nanoseconds", () => { - // Test cases from https://github.com/tc39/proposal-temporal/commit/baead4d85bc3e9ecab1e9824c3d3fe4fdd77fc3a - expect(() => { - Temporal.Instant.from("-271821-04-20T00:00:00+00:01"); - }).toThrowWithMessage( - RangeError, - "Invalid epoch nanoseconds value, must be in range -86400 * 10^17 to 86400 * 10^17" - ); - expect(() => { - Temporal.Instant.from("+275760-09-13T00:00:00-00:01"); - }).toThrowWithMessage( - RangeError, - "Invalid epoch nanoseconds value, must be in range -86400 * 10^17 to 86400 * 10^17" - ); - }); - - test("annotations must match annotation grammar even though they're ignored", () => { - expect(() => { - Temporal.Instant.from("1970-01-01T00:00Z[SerenityOS=cool]"); - }).toThrowWithMessage( - RangeError, - "Invalid instant string '1970-01-01T00:00Z[SerenityOS=cool]'" - ); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.fromEpochMicroseconds.js b/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.fromEpochMicroseconds.js deleted file mode 100644 index 705f3efac53..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.fromEpochMicroseconds.js +++ /dev/null @@ -1,51 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.Instant.fromEpochMicroseconds).toHaveLength(1); - }); - - test("basic functionality", () => { - expect(Temporal.Instant.fromEpochMicroseconds(0n).epochMicroseconds).toBe(0n); - expect(Temporal.Instant.fromEpochMicroseconds(1n).epochMicroseconds).toBe(1n); - expect(Temporal.Instant.fromEpochMicroseconds(999_999_999n).epochMicroseconds).toBe( - 999_999_999n - ); - expect( - Temporal.Instant.fromEpochMicroseconds(8_640_000_000_000_000_000n).epochMicroseconds - ).toBe(8_640_000_000_000_000_000n); - - expect(Temporal.Instant.fromEpochMicroseconds(-0n).epochMicroseconds).toBe(0n); - expect(Temporal.Instant.fromEpochMicroseconds(-1n).epochMicroseconds).toBe(-1n); - expect(Temporal.Instant.fromEpochMicroseconds(-999_999_999n).epochMicroseconds).toBe( - -999_999_999n - ); - expect( - Temporal.Instant.fromEpochMicroseconds(-8_640_000_000_000_000_000n).epochMicroseconds - ).toBe(-8_640_000_000_000_000_000n); - }); -}); - -describe("errors", () => { - test("argument must be coercible to BigInt", () => { - expect(() => { - Temporal.Instant.fromEpochMicroseconds(123); - }).toThrowWithMessage(TypeError, "Cannot convert number to BigInt"); - expect(() => { - Temporal.Instant.fromEpochMicroseconds("foo"); - }).toThrowWithMessage(SyntaxError, "Invalid value for BigInt: foo"); - }); - - test("out-of-range epoch microseconds value", () => { - expect(() => { - Temporal.Instant.fromEpochMicroseconds(8_640_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.fromEpochMicroseconds(-8_640_000_000_000_000_001n); - }).toThrowWithMessage( - RangeError, - "Invalid epoch nanoseconds value, must be in range -86400 * 10^17 to 86400 * 10^17" - ); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.fromEpochMilliseconds.js b/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.fromEpochMilliseconds.js deleted file mode 100644 index df7f5258c67..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.fromEpochMilliseconds.js +++ /dev/null @@ -1,52 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.Instant.fromEpochMilliseconds).toHaveLength(1); - }); - - test("basic functionality", () => { - expect(Temporal.Instant.fromEpochMilliseconds(0).epochMilliseconds).toBe(0); - expect(Temporal.Instant.fromEpochMilliseconds(1).epochMilliseconds).toBe(1); - expect(Temporal.Instant.fromEpochMilliseconds(999_999_999).epochMilliseconds).toBe( - 999_999_999 - ); - expect( - Temporal.Instant.fromEpochMilliseconds(8_640_000_000_000_000).epochMilliseconds - ).toBe(8_640_000_000_000_000); - - expect(Temporal.Instant.fromEpochMilliseconds(-0).epochMilliseconds).toBe(0); - expect(Temporal.Instant.fromEpochMilliseconds(-1).epochMilliseconds).toBe(-1); - expect(Temporal.Instant.fromEpochMilliseconds(-999_999_999).epochMilliseconds).toBe( - -999_999_999 - ); - expect( - Temporal.Instant.fromEpochMilliseconds(-8_640_000_000_000_000).epochMilliseconds - ).toBe(-8_640_000_000_000_000); - }); -}); - -describe("errors", () => { - test("argument must be coercible to BigInt", () => { - expect(() => { - Temporal.Instant.fromEpochMilliseconds(1.23); - }).toThrowWithMessage(RangeError, "Cannot convert non-integral number to BigInt"); - // NOTE: ToNumber is called on the argument first, so this is effectively NaN. - expect(() => { - Temporal.Instant.fromEpochMilliseconds("foo"); - }).toThrowWithMessage(RangeError, "Cannot convert non-integral number to BigInt"); - }); - - test("out-of-range epoch milliseconds value", () => { - expect(() => { - Temporal.Instant.fromEpochMilliseconds(8_640_000_000_000_001); - }).toThrowWithMessage( - RangeError, - "Invalid epoch nanoseconds value, must be in range -86400 * 10^17 to 86400 * 10^17" - ); - expect(() => { - Temporal.Instant.fromEpochMilliseconds(-8_640_000_000_000_001); - }).toThrowWithMessage( - RangeError, - "Invalid epoch nanoseconds value, must be in range -86400 * 10^17 to 86400 * 10^17" - ); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.fromEpochNanoseconds.js b/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.fromEpochNanoseconds.js deleted file mode 100644 index 08a0c91abad..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.fromEpochNanoseconds.js +++ /dev/null @@ -1,51 +0,0 @@ -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); - }); -}); - -describe("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" - ); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.fromEpochSeconds.js b/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.fromEpochSeconds.js deleted file mode 100644 index 10d1f8686d4..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.fromEpochSeconds.js +++ /dev/null @@ -1,48 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.Instant.fromEpochSeconds).toHaveLength(1); - }); - - test("basic functionality", () => { - expect(Temporal.Instant.fromEpochSeconds(0).epochSeconds).toBe(0); - expect(Temporal.Instant.fromEpochSeconds(1).epochSeconds).toBe(1); - expect(Temporal.Instant.fromEpochSeconds(999_999_999).epochSeconds).toBe(999_999_999); - expect(Temporal.Instant.fromEpochSeconds(8_640_000_000_000).epochSeconds).toBe( - 8_640_000_000_000 - ); - - expect(Temporal.Instant.fromEpochSeconds(-0).epochSeconds).toBe(0); - expect(Temporal.Instant.fromEpochSeconds(-1).epochSeconds).toBe(-1); - expect(Temporal.Instant.fromEpochSeconds(-999_999_999).epochSeconds).toBe(-999_999_999); - expect(Temporal.Instant.fromEpochSeconds(-8_640_000_000_000).epochSeconds).toBe( - -8_640_000_000_000 - ); - }); -}); - -describe("errors", () => { - test("argument must be coercible to BigInt", () => { - expect(() => { - Temporal.Instant.fromEpochSeconds(1.23); - }).toThrowWithMessage(RangeError, "Cannot convert non-integral number to BigInt"); - // NOTE: ToNumber is called on the argument first, so this is effectively NaN. - expect(() => { - Temporal.Instant.fromEpochSeconds("foo"); - }).toThrowWithMessage(RangeError, "Cannot convert non-integral number to BigInt"); - }); - - test("out-of-range epoch seconds value", () => { - expect(() => { - Temporal.Instant.fromEpochSeconds(8_640_000_000_001); - }).toThrowWithMessage( - RangeError, - "Invalid epoch nanoseconds value, must be in range -86400 * 10^17 to 86400 * 10^17" - ); - expect(() => { - Temporal.Instant.fromEpochSeconds(-8_640_000_000_001); - }).toThrowWithMessage( - RangeError, - "Invalid epoch nanoseconds value, must be in range -86400 * 10^17 to 86400 * 10^17" - ); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.js b/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.js deleted file mode 100644 index e4b16359835..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.js +++ /dev/null @@ -1,30 +0,0 @@ -describe("errors", () => { - test("called without new", () => { - expect(() => { - Temporal.Instant(); - }).toThrowWithMessage(TypeError, "Temporal.Instant constructor must be called with 'new'"); - }); - - test("argument must be coercible to bigint", () => { - expect(() => { - new Temporal.Instant(123); - }).toThrowWithMessage(TypeError, "Cannot convert number to BigInt"); - expect(() => { - new Temporal.Instant("foo"); - }).toThrowWithMessage(SyntaxError, "Invalid value for BigInt: foo"); - }); -}); - -describe("normal behavior", () => { - test("length is 1", () => { - expect(Temporal.Instant).toHaveLength(1); - }); - - test("basic functionality", () => { - const instant = new Temporal.Instant(123n); - expect(instant.epochNanoseconds).toBe(123n); - expect(typeof instant).toBe("object"); - expect(instant).toBeInstanceOf(Temporal.Instant); - expect(Object.getPrototypeOf(instant)).toBe(Temporal.Instant.prototype); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.prototype.@@toStringTag.js b/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.prototype.@@toStringTag.js deleted file mode 100644 index a6e1187c845..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.prototype.@@toStringTag.js +++ /dev/null @@ -1,3 +0,0 @@ -test("basic functionality", () => { - expect(Temporal.Instant.prototype[Symbol.toStringTag]).toBe("Temporal.Instant"); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.prototype.add.js b/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.prototype.add.js deleted file mode 100644 index f5a6d9209d1..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.prototype.add.js +++ /dev/null @@ -1,59 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.Instant.prototype.add).toHaveLength(1); - }); - - test("basic functionality", () => { - const instant = new Temporal.Instant(1625614921000000000n); - const duration = new Temporal.Duration(0, 0, 0, 0, 1, 2, 3, 4, 5, 6); - expect(instant.add(duration).epochNanoseconds).toBe(1625618644004005006n); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.Instant object", () => { - expect(() => { - Temporal.Instant.prototype.add.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.Instant"); - }); - - test("invalid nanoseconds value, positive", () => { - const instant = new Temporal.Instant(8_640_000_000_000_000_000_000n); - const duration = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, 1); - expect(() => { - instant.add(duration); - }).toThrowWithMessage( - RangeError, - "Invalid epoch nanoseconds value, must be in range -86400 * 10^17 to 86400 * 10^17" - ); - }); - - test("invalid nanoseconds value, negative", () => { - const instant = new Temporal.Instant(-8_640_000_000_000_000_000_000n); - const duration = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, -1); - expect(() => { - instant.add(duration); - }).toThrowWithMessage( - RangeError, - "Invalid epoch nanoseconds value, must be in range -86400 * 10^17 to 86400 * 10^17" - ); - }); - - test("disallowed fields", () => { - const instant = new Temporal.Instant(1625614921000000000n); - for (const [args, property] of [ - [[123, 0, 0, 0], "years"], - [[0, 123, 0, 0], "months"], - [[0, 0, 123, 0], "weeks"], - [[0, 0, 0, 123], "days"], - ]) { - const duration = new Temporal.Duration(...args); - expect(() => { - instant.add(duration); - }).toThrowWithMessage( - RangeError, - `Invalid value for duration property '${property}': must be zero, got 123` - ); - } - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.prototype.epochMicroseconds.js b/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.prototype.epochMicroseconds.js deleted file mode 100644 index 44b2894ad32..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.prototype.epochMicroseconds.js +++ /dev/null @@ -1,33 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - expect(new Temporal.Instant(0n).epochMicroseconds).toBe(0n); - expect(new Temporal.Instant(1n).epochMicroseconds).toBe(0n); - expect(new Temporal.Instant(999n).epochMicroseconds).toBe(0n); - expect(new Temporal.Instant(1_000n).epochMicroseconds).toBe(1n); - expect(new Temporal.Instant(1_500n).epochMicroseconds).toBe(1n); - expect(new Temporal.Instant(1_999n).epochMicroseconds).toBe(1n); - expect(new Temporal.Instant(2_000n).epochMicroseconds).toBe(2n); - expect(new Temporal.Instant(8_640_000_000_000_000_000_000n).epochMicroseconds).toBe( - 8_640_000_000_000_000_000n - ); - - expect(new Temporal.Instant(-0n).epochMicroseconds).toBe(-0n); - expect(new Temporal.Instant(-1n).epochMicroseconds).toBe(-0n); - expect(new Temporal.Instant(-999n).epochMicroseconds).toBe(-0n); - expect(new Temporal.Instant(-1_000n).epochMicroseconds).toBe(-1n); - expect(new Temporal.Instant(-1_500n).epochMicroseconds).toBe(-1n); - expect(new Temporal.Instant(-1_999n).epochMicroseconds).toBe(-1n); - expect(new Temporal.Instant(-2_000n).epochMicroseconds).toBe(-2n); - expect(new Temporal.Instant(-8_640_000_000_000_000_000_000n).epochMicroseconds).toBe( - -8_640_000_000_000_000_000n - ); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.Instant object", () => { - expect(() => { - Reflect.get(Temporal.Instant.prototype, "epochMicroseconds", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.Instant"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.prototype.epochMilliseconds.js b/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.prototype.epochMilliseconds.js deleted file mode 100644 index 56546f4c738..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.prototype.epochMilliseconds.js +++ /dev/null @@ -1,33 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - expect(new Temporal.Instant(0n).epochMilliseconds).toBe(0); - expect(new Temporal.Instant(1n).epochMilliseconds).toBe(0); - expect(new Temporal.Instant(999_999n).epochMilliseconds).toBe(0); - expect(new Temporal.Instant(1_000_000n).epochMilliseconds).toBe(1); - expect(new Temporal.Instant(1_500_000n).epochMilliseconds).toBe(1); - expect(new Temporal.Instant(1_999_999n).epochMilliseconds).toBe(1); - expect(new Temporal.Instant(2_000_000n).epochMilliseconds).toBe(2); - expect(new Temporal.Instant(8_640_000_000_000_000_000_000n).epochMilliseconds).toBe( - 8_640_000_000_000_000 - ); - - expect(new Temporal.Instant(-0n).epochMilliseconds).toBe(0); - expect(new Temporal.Instant(-1n).epochMilliseconds).toBe(0); - expect(new Temporal.Instant(-999_999n).epochMilliseconds).toBe(0); - expect(new Temporal.Instant(-1_000_000n).epochMilliseconds).toBe(-1); - expect(new Temporal.Instant(-1_500_000n).epochMilliseconds).toBe(-1); - expect(new Temporal.Instant(-1_999_999n).epochMilliseconds).toBe(-1); - expect(new Temporal.Instant(-2_000_000n).epochMilliseconds).toBe(-2); - expect(new Temporal.Instant(-8_640_000_000_000_000_000_000n).epochMilliseconds).toBe( - -8_640_000_000_000_000 - ); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.Instant object", () => { - expect(() => { - Reflect.get(Temporal.Instant.prototype, "epochMilliseconds", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.Instant"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.prototype.epochNanoseconds.js b/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.prototype.epochNanoseconds.js deleted file mode 100644 index 06f66dccb06..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.prototype.epochNanoseconds.js +++ /dev/null @@ -1,25 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - expect(new Temporal.Instant(0n).epochNanoseconds).toBe(0n); - expect(new Temporal.Instant(1n).epochNanoseconds).toBe(1n); - expect(new Temporal.Instant(999n).epochNanoseconds).toBe(999n); - expect(new Temporal.Instant(8_640_000_000_000_000_000_000n).epochNanoseconds).toBe( - 8_640_000_000_000_000_000_000n - ); - - expect(new Temporal.Instant(-0n).epochNanoseconds).toBe(-0n); - expect(new Temporal.Instant(-1n).epochNanoseconds).toBe(-1n); - expect(new Temporal.Instant(-999n).epochNanoseconds).toBe(-999n); - expect(new Temporal.Instant(-8_640_000_000_000_000_000_000n).epochNanoseconds).toBe( - -8_640_000_000_000_000_000_000n - ); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.Instant object", () => { - expect(() => { - Reflect.get(Temporal.Instant.prototype, "epochNanoseconds", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.Instant"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.prototype.epochSeconds.js b/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.prototype.epochSeconds.js deleted file mode 100644 index f01fc435624..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.prototype.epochSeconds.js +++ /dev/null @@ -1,33 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - expect(new Temporal.Instant(0n).epochSeconds).toBe(0); - expect(new Temporal.Instant(1n).epochSeconds).toBe(0); - expect(new Temporal.Instant(999_999_999n).epochSeconds).toBe(0); - expect(new Temporal.Instant(1_000_000_000n).epochSeconds).toBe(1); - expect(new Temporal.Instant(1_500_000_000n).epochSeconds).toBe(1); - expect(new Temporal.Instant(1_999_999_999n).epochSeconds).toBe(1); - expect(new Temporal.Instant(2_000_000_000n).epochSeconds).toBe(2); - expect(new Temporal.Instant(8_640_000_000_000_000_000_000n).epochSeconds).toBe( - 8_640_000_000_000 - ); - - expect(new Temporal.Instant(-0n).epochSeconds).toBe(0); - expect(new Temporal.Instant(-1n).epochSeconds).toBe(0); - expect(new Temporal.Instant(-999_999_999n).epochSeconds).toBe(0); - expect(new Temporal.Instant(-1_000_000_000n).epochSeconds).toBe(-1); - expect(new Temporal.Instant(-1_500_000_000n).epochSeconds).toBe(-1); - expect(new Temporal.Instant(-1_999_999_999n).epochSeconds).toBe(-1); - expect(new Temporal.Instant(-2_000_000_000n).epochSeconds).toBe(-2); - expect(new Temporal.Instant(-8_640_000_000_000_000_000_000n).epochSeconds).toBe( - -8_640_000_000_000 - ); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.Instant object", () => { - expect(() => { - Reflect.get(Temporal.Instant.prototype, "epochSeconds", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.Instant"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.prototype.equals.js b/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.prototype.equals.js deleted file mode 100644 index a1bfc7f4ced..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.prototype.equals.js +++ /dev/null @@ -1,20 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.Instant.prototype.equals).toHaveLength(1); - }); - - test("basic functionality", () => { - const instant1 = new Temporal.Instant(111n); - expect(instant1.equals(instant1)); - const instant2 = new Temporal.Instant(999n); - expect(!instant1.equals(instant2)); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.Instant object", () => { - expect(() => { - Temporal.Instant.prototype.equals.call("foo", 1, 2); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.Instant"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.prototype.round.js b/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.prototype.round.js deleted file mode 100644 index a9251dd2b9b..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.prototype.round.js +++ /dev/null @@ -1,80 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.Instant.prototype.round).toHaveLength(1); - }); - - test("basic functionality", () => { - const instant = new Temporal.Instant(1111111111111n); - expect(instant.round({ smallestUnit: "second" }).epochNanoseconds).toBe(1111000000000n); - expect( - instant.round({ smallestUnit: "second", roundingMode: "ceil" }).epochNanoseconds - ).toBe(1112000000000n); - expect( - instant.round({ smallestUnit: "minute", roundingIncrement: 30, roundingMode: "floor" }) - .epochNanoseconds - ).toBe(0n); - expect( - instant.round({ - smallestUnit: "minute", - roundingIncrement: 30, - roundingMode: "halfExpand", - }).epochNanoseconds - ).toBe(1800000000000n); - }); - - test("string argument is implicitly converted to options object", () => { - const instant = new Temporal.Instant(1111111111111n); - expect( - instant.round("second").equals(instant.round({ smallestUnit: "second" })) - ).toBeTrue(); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.Instant object", () => { - expect(() => { - Temporal.Instant.prototype.round.call("foo", {}); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.Instant"); - }); - - test("missing options object", () => { - expect(() => { - const instant = new Temporal.Instant(1n); - instant.round(); - }).toThrowWithMessage(TypeError, "Required options object is missing or undefined"); - }); - - test("invalid rounding mode", () => { - expect(() => { - const instant = new Temporal.Instant(1n); - instant.round({ smallestUnit: "second", roundingMode: "serenityOS" }); - }).toThrowWithMessage(RangeError, "is not a valid value for option roundingMode"); - }); - - test("invalid smallest unit", () => { - expect(() => { - const instant = new Temporal.Instant(1n); - instant.round({ smallestUnit: "serenityOS" }); - }).toThrowWithMessage(RangeError, "is not a valid value for option smallestUnit"); - }); - - test("increment may not be NaN", () => { - expect(() => { - const instant = new Temporal.Instant(1n); - instant.round({ smallestUnit: "second", roundingIncrement: NaN }); - }).toThrowWithMessage(RangeError, "is not a valid value for option roundingIncrement"); - }); - - test("increment may smaller than 1 or larger than maximum", () => { - const instant = new Temporal.Instant(1n); - expect(() => { - instant.round({ smallestUnit: "second", roundingIncrement: -1 }); - }).toThrowWithMessage(RangeError, "is not a valid value for option roundingIncrement"); - expect(() => { - instant.round({ smallestUnit: "second", roundingIncrement: 0 }); - }).toThrowWithMessage(RangeError, "is not a valid value for option roundingIncrement"); - expect(() => { - instant.round({ smallestUnit: "second", roundingIncrement: Infinity }); - }).toThrowWithMessage(RangeError, "is not a valid value for option roundingIncrement"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.prototype.since.js b/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.prototype.since.js deleted file mode 100644 index 6c1205712ce..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.prototype.since.js +++ /dev/null @@ -1,190 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.Instant.prototype.since).toHaveLength(1); - }); - - test("basic functionality", () => { - const instant1 = new Temporal.Instant(1625614920000000000n); - const instant2 = new Temporal.Instant(0n); - expect(instant1.since(instant2).seconds).toBe(1625614920); - expect(instant1.since(instant2, { largestUnit: "hour" }).hours).toBe(451559); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.Instant object", () => { - expect(() => { - Temporal.Instant.prototype.since.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.Instant"); - }); -}); - -describe("rounding modes", () => { - const earlier = new Temporal.Instant( - 217178610_123_456_789n /* 1976-11-18T15:23:30.123456789Z */ - ); - const later = new Temporal.Instant( - 1572345998_271_986_289n /* 2019-10-29T10:46:38.271986289Z */ - ); - const largestUnit = "hours"; - - test("'ceil' rounding mode", () => { - const expected = [ - ["hours", "PT376436H", "-PT376435H"], - ["minutes", "PT376435H24M", "-PT376435H23M"], - ["seconds", "PT376435H23M9S", "-PT376435H23M8S"], - ["milliseconds", "PT376435H23M8.149S", "-PT376435H23M8.148S"], - ["microseconds", "PT376435H23M8.14853S", "-PT376435H23M8.148529S"], - ["nanoseconds", "PT376435H23M8.1485295S", "-PT376435H23M8.1485295S"], - ]; - - const roundingMode = "ceil"; - expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => { - const sincePositive = later.since(earlier, { largestUnit, smallestUnit, roundingMode }); - expect(sincePositive.toString()).toBe(expectedPositive); - - const sinceNegative = earlier.since(later, { largestUnit, smallestUnit, roundingMode }); - expect(sinceNegative.toString()).toBe(expectedNegative); - }); - }); - - test("'expand' rounding mode", () => { - const expected = [ - ["hours", "PT376436H", "-PT376436H"], - ["minutes", "PT376435H24M", "-PT376435H24M"], - ["seconds", "PT376435H23M9S", "-PT376435H23M9S"], - ["milliseconds", "PT376435H23M8.149S", "-PT376435H23M8.149S"], - ["microseconds", "PT376435H23M8.14853S", "-PT376435H23M8.14853S"], - ["nanoseconds", "PT376435H23M8.1485295S", "-PT376435H23M8.1485295S"], - ]; - - const roundingMode = "expand"; - expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => { - const sincePositive = later.since(earlier, { largestUnit, smallestUnit, roundingMode }); - expect(sincePositive.toString()).toBe(expectedPositive); - - const sinceNegative = earlier.since(later, { largestUnit, smallestUnit, roundingMode }); - expect(sinceNegative.toString()).toBe(expectedNegative); - }); - }); - - test("'floor' rounding mode", () => { - const expected = [ - ["hours", "PT376435H", "-PT376436H"], - ["minutes", "PT376435H23M", "-PT376435H24M"], - ["seconds", "PT376435H23M8S", "-PT376435H23M9S"], - ["milliseconds", "PT376435H23M8.148S", "-PT376435H23M8.149S"], - ["microseconds", "PT376435H23M8.148529S", "-PT376435H23M8.14853S"], - ["nanoseconds", "PT376435H23M8.1485295S", "-PT376435H23M8.1485295S"], - ]; - - const roundingMode = "floor"; - expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => { - const sincePositive = later.since(earlier, { largestUnit, smallestUnit, roundingMode }); - expect(sincePositive.toString()).toBe(expectedPositive); - - const sinceNegative = earlier.since(later, { largestUnit, smallestUnit, roundingMode }); - expect(sinceNegative.toString()).toBe(expectedNegative); - }); - }); - - test("'halfCeil' rounding mode", () => { - const expected = [ - ["hours", "PT376435H", "-PT376435H"], - ["minutes", "PT376435H23M", "-PT376435H23M"], - ["seconds", "PT376435H23M8S", "-PT376435H23M8S"], - ["milliseconds", "PT376435H23M8.149S", "-PT376435H23M8.149S"], - ["microseconds", "PT376435H23M8.14853S", "-PT376435H23M8.148529S"], - ["nanoseconds", "PT376435H23M8.1485295S", "-PT376435H23M8.1485295S"], - ]; - - const roundingMode = "halfCeil"; - expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => { - const sincePositive = later.since(earlier, { largestUnit, smallestUnit, roundingMode }); - expect(sincePositive.toString()).toBe(expectedPositive); - - const sinceNegative = earlier.since(later, { largestUnit, smallestUnit, roundingMode }); - expect(sinceNegative.toString()).toBe(expectedNegative); - }); - }); - - test("'halfEven' rounding mode", () => { - const expected = [ - ["hours", "PT376435H", "-PT376435H"], - ["minutes", "PT376435H23M", "-PT376435H23M"], - ["seconds", "PT376435H23M8S", "-PT376435H23M8S"], - ["milliseconds", "PT376435H23M8.149S", "-PT376435H23M8.149S"], - ["microseconds", "PT376435H23M8.14853S", "-PT376435H23M8.14853S"], - ["nanoseconds", "PT376435H23M8.1485295S", "-PT376435H23M8.1485295S"], - ]; - - const roundingMode = "halfEven"; - expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => { - const sincePositive = later.since(earlier, { largestUnit, smallestUnit, roundingMode }); - expect(sincePositive.toString()).toBe(expectedPositive); - - const sinceNegative = earlier.since(later, { largestUnit, smallestUnit, roundingMode }); - expect(sinceNegative.toString()).toBe(expectedNegative); - }); - }); - - test("'halfExpand' rounding mode", () => { - const expected = [ - ["hours", "PT376435H", "-PT376435H"], - ["minutes", "PT376435H23M", "-PT376435H23M"], - ["seconds", "PT376435H23M8S", "-PT376435H23M8S"], - ["milliseconds", "PT376435H23M8.149S", "-PT376435H23M8.149S"], - ["microseconds", "PT376435H23M8.14853S", "-PT376435H23M8.14853S"], - ["nanoseconds", "PT376435H23M8.1485295S", "-PT376435H23M8.1485295S"], - ]; - - const roundingMode = "halfExpand"; - expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => { - const sincePositive = later.since(earlier, { largestUnit, smallestUnit, roundingMode }); - expect(sincePositive.toString()).toBe(expectedPositive); - - const sinceNegative = earlier.since(later, { largestUnit, smallestUnit, roundingMode }); - expect(sinceNegative.toString()).toBe(expectedNegative); - }); - }); - - test("'halfFloor' rounding mode", () => { - const expected = [ - ["hours", "PT376435H", "-PT376435H"], - ["minutes", "PT376435H23M", "-PT376435H23M"], - ["seconds", "PT376435H23M8S", "-PT376435H23M8S"], - ["milliseconds", "PT376435H23M8.149S", "-PT376435H23M8.149S"], - ["microseconds", "PT376435H23M8.148529S", "-PT376435H23M8.14853S"], - ["nanoseconds", "PT376435H23M8.1485295S", "-PT376435H23M8.1485295S"], - ]; - - const roundingMode = "halfFloor"; - expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => { - const sincePositive = later.since(earlier, { largestUnit, smallestUnit, roundingMode }); - expect(sincePositive.toString()).toBe(expectedPositive); - - const sinceNegative = earlier.since(later, { largestUnit, smallestUnit, roundingMode }); - expect(sinceNegative.toString()).toBe(expectedNegative); - }); - }); - - test("'halfTrunc' rounding mode", () => { - const expected = [ - ["hours", "PT376435H", "-PT376435H"], - ["minutes", "PT376435H23M", "-PT376435H23M"], - ["seconds", "PT376435H23M8S", "-PT376435H23M8S"], - ["milliseconds", "PT376435H23M8.149S", "-PT376435H23M8.149S"], - ["microseconds", "PT376435H23M8.148529S", "-PT376435H23M8.148529S"], - ["nanoseconds", "PT376435H23M8.1485295S", "-PT376435H23M8.1485295S"], - ]; - - const roundingMode = "halfTrunc"; - expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => { - const sincePositive = later.since(earlier, { largestUnit, smallestUnit, roundingMode }); - expect(sincePositive.toString()).toBe(expectedPositive); - - const sinceNegative = earlier.since(later, { largestUnit, smallestUnit, roundingMode }); - expect(sinceNegative.toString()).toBe(expectedNegative); - }); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.prototype.subtract.js b/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.prototype.subtract.js deleted file mode 100644 index 35ae00ce622..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.prototype.subtract.js +++ /dev/null @@ -1,59 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.Instant.prototype.subtract).toHaveLength(1); - }); - - test("basic functionality", () => { - const instant = new Temporal.Instant(1625614921000000000n); - const duration = new Temporal.Duration(0, 0, 0, 0, 1, 2, 3, 4, 5, 6); - expect(instant.subtract(duration).epochNanoseconds).toBe(1625611197995994994n); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.Instant object", () => { - expect(() => { - Temporal.Instant.prototype.subtract.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.Instant"); - }); - - test("invalid nanoseconds value, positive", () => { - const instant = new Temporal.Instant(8_640_000_000_000_000_000_000n); - const duration = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, -1); - expect(() => { - instant.subtract(duration); - }).toThrowWithMessage( - RangeError, - "Invalid epoch nanoseconds value, must be in range -86400 * 10^17 to 86400 * 10^17" - ); - }); - - test("invalid nanoseconds value, negative", () => { - const instant = new Temporal.Instant(-8_640_000_000_000_000_000_000n); - const duration = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, 1); - expect(() => { - instant.subtract(duration); - }).toThrowWithMessage( - RangeError, - "Invalid epoch nanoseconds value, must be in range -86400 * 10^17 to 86400 * 10^17" - ); - }); - - test("disallowed fields", () => { - const instant = new Temporal.Instant(1625614921000000000n); - for (const [args, property] of [ - [[123, 0, 0, 0], "years"], - [[0, 123, 0, 0], "months"], - [[0, 0, 123, 0], "weeks"], - [[0, 0, 0, 123], "days"], - ]) { - const duration = new Temporal.Duration(...args); - expect(() => { - instant.subtract(duration); - }).toThrowWithMessage( - RangeError, - `Invalid value for duration property '${property}': must be zero, got 123` - ); - } - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.prototype.toJSON.js b/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.prototype.toJSON.js deleted file mode 100644 index 074ae092566..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.prototype.toJSON.js +++ /dev/null @@ -1,18 +0,0 @@ -describe("correct behavior", () => { - test("length is 0", () => { - expect(Temporal.Instant.prototype.toJSON).toHaveLength(0); - }); - - test("basic functionality", () => { - const instant = new Temporal.Instant(1625614921123456789n); - expect(instant.toJSON()).toBe("2021-07-06T23:42:01.123456789Z"); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.Instant object", () => { - expect(() => { - Temporal.Instant.prototype.toJSON.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.Instant"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.prototype.toLocaleString.js b/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.prototype.toLocaleString.js deleted file mode 100644 index 2e3ecd1663b..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.prototype.toLocaleString.js +++ /dev/null @@ -1,18 +0,0 @@ -describe("correct behavior", () => { - test("length is 0", () => { - expect(Temporal.Instant.prototype.toLocaleString).toHaveLength(0); - }); - - test("basic functionality", () => { - const instant = new Temporal.Instant(1625614921123456789n); - expect(instant.toLocaleString()).toBe("2021-07-06T23:42:01.123456789Z"); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.Instant object", () => { - expect(() => { - Temporal.Instant.prototype.toLocaleString.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.Instant"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.prototype.toString.js b/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.prototype.toString.js deleted file mode 100644 index d730f6a7960..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.prototype.toString.js +++ /dev/null @@ -1,72 +0,0 @@ -describe("correct behavior", () => { - test("length is 0", () => { - expect(Temporal.Instant.prototype.toString).toHaveLength(0); - }); - - test("basic functionality", () => { - const instant = new Temporal.Instant(1625614921123456789n); - expect(instant.toString()).toBe("2021-07-06T23:42:01.123456789Z"); - }); - - test("timeZone option", () => { - const instant = new Temporal.Instant(1625614921123456789n); - const options = { timeZone: new Temporal.TimeZone("+01:30") }; - expect(instant.toString(options)).toBe("2021-07-07T01:12:01.123456789+01:30"); - }); - - test("fractionalSecondDigits option", () => { - const instant = new Temporal.Instant(1625614921123456000n); - const values = [ - ["auto", "2021-07-06T23:42:01.123456Z"], - [0, "2021-07-06T23:42:01Z"], - [1, "2021-07-06T23:42:01.1Z"], - [2, "2021-07-06T23:42:01.12Z"], - [3, "2021-07-06T23:42:01.123Z"], - [4, "2021-07-06T23:42:01.1234Z"], - [5, "2021-07-06T23:42:01.12345Z"], - [6, "2021-07-06T23:42:01.123456Z"], - [7, "2021-07-06T23:42:01.1234560Z"], - [8, "2021-07-06T23:42:01.12345600Z"], - [9, "2021-07-06T23:42:01.123456000Z"], - ]; - for (const [fractionalSecondDigits, expected] of values) { - const options = { fractionalSecondDigits }; - expect(instant.toString(options)).toBe(expected); - } - - // Ignored when smallestUnit is given - expect(instant.toString({ smallestUnit: "minute", fractionalSecondDigits: 9 })).toBe( - "2021-07-06T23:42Z" - ); - }); - - test("smallestUnit option", () => { - const instant = new Temporal.Instant(1625614921123456789n); - const values = [ - ["minute", "2021-07-06T23:42Z"], - ["second", "2021-07-06T23:42:01Z"], - ["millisecond", "2021-07-06T23:42:01.123Z"], - ["microsecond", "2021-07-06T23:42:01.123456Z"], - ["nanosecond", "2021-07-06T23:42:01.123456789Z"], - ]; - for (const [smallestUnit, expected] of values) { - const options = { smallestUnit }; - expect(instant.toString(options)).toBe(expected); - } - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.Instant object", () => { - expect(() => { - Temporal.Instant.prototype.toString.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.Instant"); - }); - - test("custom time zone doesn't have a getOffsetNanosecondsFor function", () => { - const instant = new Temporal.Instant(0n); - expect(() => { - instant.toString({ timeZone: {} }); - }).toThrowWithMessage(TypeError, "getOffsetNanosecondsFor is undefined"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.prototype.toZonedDateTime.js b/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.prototype.toZonedDateTime.js deleted file mode 100644 index 44188fdca5b..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.prototype.toZonedDateTime.js +++ /dev/null @@ -1,54 +0,0 @@ -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 an object of type Temporal.Instant"); - }); - - test("item 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("item 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("item 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"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.prototype.toZonedDateTimeISO.js b/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.prototype.toZonedDateTimeISO.js deleted file mode 100644 index 956948fcf4f..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.prototype.toZonedDateTimeISO.js +++ /dev/null @@ -1,55 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.Instant.prototype.toZonedDateTimeISO).toHaveLength(1); - }); - - test("basic functionality", () => { - const instant = new Temporal.Instant(1625614921123456789n); - const zonedDateTime = instant.toZonedDateTimeISO("UTC"); - 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.id).toBe("iso8601"); - expect(zonedDateTime.timeZone.id).toBe("UTC"); - }); - - test("custom time zone object", () => { - const instant = new Temporal.Instant(1625614921123456789n); - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = instant.toZonedDateTimeISO({ timeZone }); - expect(zonedDateTime.timeZone).toBe(timeZone); - }); - - test("avoids extra timeZone property lookup", () => { - const instant = new Temporal.Instant(1625614921123456789n); - - let timesGetterCalled = 0; - const timeZoneObject = { - get timeZone() { - timesGetterCalled++; - return "UTC"; - }, - - toString() { - return "UTC"; - }, - }; - - instant.toZonedDateTimeISO({ timeZone: timeZoneObject }); - expect(timesGetterCalled).toBe(0); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.Instant object", () => { - expect(() => { - Temporal.Instant.prototype.toZonedDateTimeISO.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.Instant"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.prototype.until.js b/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.prototype.until.js deleted file mode 100644 index 6c7b824fcd1..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.prototype.until.js +++ /dev/null @@ -1,190 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.Instant.prototype.until).toHaveLength(1); - }); - - test("basic functionality", () => { - const instant1 = new Temporal.Instant(0n); - const instant2 = new Temporal.Instant(1625614920000000000n); - expect(instant1.until(instant2).seconds).toBe(1625614920); - expect(instant1.until(instant2, { largestUnit: "hour" }).hours).toBe(451559); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.Instant object", () => { - expect(() => { - Temporal.Instant.prototype.until.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.Instant"); - }); -}); - -describe("rounding modes", () => { - const earlier = new Temporal.Instant( - 217178610_123_456_789n /* 1976-11-18T15:23:30.123456789Z */ - ); - const later = new Temporal.Instant( - 1572345998_271_986_289n /* 2019-10-29T10:46:38.271986289Z */ - ); - const largestUnit = "hours"; - - test("'ceil' rounding mode", () => { - const expected = [ - ["hours", "PT376436H", "-PT376435H"], - ["minutes", "PT376435H24M", "-PT376435H23M"], - ["seconds", "PT376435H23M9S", "-PT376435H23M8S"], - ["milliseconds", "PT376435H23M8.149S", "-PT376435H23M8.148S"], - ["microseconds", "PT376435H23M8.14853S", "-PT376435H23M8.148529S"], - ["nanoseconds", "PT376435H23M8.1485295S", "-PT376435H23M8.1485295S"], - ]; - - const roundingMode = "ceil"; - expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => { - const untilPositive = earlier.until(later, { largestUnit, smallestUnit, roundingMode }); - expect(untilPositive.toString()).toBe(expectedPositive); - - const untilNegative = later.until(earlier, { largestUnit, smallestUnit, roundingMode }); - expect(untilNegative.toString()).toBe(expectedNegative); - }); - }); - - test("'expand' rounding mode", () => { - const expected = [ - ["hours", "PT376436H", "-PT376436H"], - ["minutes", "PT376435H24M", "-PT376435H24M"], - ["seconds", "PT376435H23M9S", "-PT376435H23M9S"], - ["milliseconds", "PT376435H23M8.149S", "-PT376435H23M8.149S"], - ["microseconds", "PT376435H23M8.14853S", "-PT376435H23M8.14853S"], - ["nanoseconds", "PT376435H23M8.1485295S", "-PT376435H23M8.1485295S"], - ]; - - const roundingMode = "expand"; - expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => { - const untilPositive = earlier.until(later, { largestUnit, smallestUnit, roundingMode }); - expect(untilPositive.toString()).toBe(expectedPositive); - - const untilNegative = later.until(earlier, { largestUnit, smallestUnit, roundingMode }); - expect(untilNegative.toString()).toBe(expectedNegative); - }); - }); - - test("'floor' rounding mode", () => { - const expected = [ - ["hours", "PT376435H", "-PT376436H"], - ["minutes", "PT376435H23M", "-PT376435H24M"], - ["seconds", "PT376435H23M8S", "-PT376435H23M9S"], - ["milliseconds", "PT376435H23M8.148S", "-PT376435H23M8.149S"], - ["microseconds", "PT376435H23M8.148529S", "-PT376435H23M8.14853S"], - ["nanoseconds", "PT376435H23M8.1485295S", "-PT376435H23M8.1485295S"], - ]; - - const roundingMode = "floor"; - expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => { - const untilPositive = earlier.until(later, { largestUnit, smallestUnit, roundingMode }); - expect(untilPositive.toString()).toBe(expectedPositive); - - const untilNegative = later.until(earlier, { largestUnit, smallestUnit, roundingMode }); - expect(untilNegative.toString()).toBe(expectedNegative); - }); - }); - - test("'halfCeil' rounding mode", () => { - const expected = [ - ["hours", "PT376435H", "-PT376435H"], - ["minutes", "PT376435H23M", "-PT376435H23M"], - ["seconds", "PT376435H23M8S", "-PT376435H23M8S"], - ["milliseconds", "PT376435H23M8.149S", "-PT376435H23M8.149S"], - ["microseconds", "PT376435H23M8.14853S", "-PT376435H23M8.148529S"], - ["nanoseconds", "PT376435H23M8.1485295S", "-PT376435H23M8.1485295S"], - ]; - - const roundingMode = "halfCeil"; - expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => { - const untilPositive = earlier.until(later, { largestUnit, smallestUnit, roundingMode }); - expect(untilPositive.toString()).toBe(expectedPositive); - - const untilNegative = later.until(earlier, { largestUnit, smallestUnit, roundingMode }); - expect(untilNegative.toString()).toBe(expectedNegative); - }); - }); - - test("'halfEven' rounding mode", () => { - const expected = [ - ["hours", "PT376435H", "-PT376435H"], - ["minutes", "PT376435H23M", "-PT376435H23M"], - ["seconds", "PT376435H23M8S", "-PT376435H23M8S"], - ["milliseconds", "PT376435H23M8.149S", "-PT376435H23M8.149S"], - ["microseconds", "PT376435H23M8.14853S", "-PT376435H23M8.14853S"], - ["nanoseconds", "PT376435H23M8.1485295S", "-PT376435H23M8.1485295S"], - ]; - - const roundingMode = "halfEven"; - expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => { - const untilPositive = earlier.until(later, { largestUnit, smallestUnit, roundingMode }); - expect(untilPositive.toString()).toBe(expectedPositive); - - const untilNegative = later.until(earlier, { largestUnit, smallestUnit, roundingMode }); - expect(untilNegative.toString()).toBe(expectedNegative); - }); - }); - - test("'halfExpand' rounding mode", () => { - const expected = [ - ["hours", "PT376435H", "-PT376435H"], - ["minutes", "PT376435H23M", "-PT376435H23M"], - ["seconds", "PT376435H23M8S", "-PT376435H23M8S"], - ["milliseconds", "PT376435H23M8.149S", "-PT376435H23M8.149S"], - ["microseconds", "PT376435H23M8.14853S", "-PT376435H23M8.14853S"], - ["nanoseconds", "PT376435H23M8.1485295S", "-PT376435H23M8.1485295S"], - ]; - - const roundingMode = "halfExpand"; - expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => { - const untilPositive = earlier.until(later, { largestUnit, smallestUnit, roundingMode }); - expect(untilPositive.toString()).toBe(expectedPositive); - - const untilNegative = later.until(earlier, { largestUnit, smallestUnit, roundingMode }); - expect(untilNegative.toString()).toBe(expectedNegative); - }); - }); - - test("'halfFloor' rounding mode", () => { - const expected = [ - ["hours", "PT376435H", "-PT376435H"], - ["minutes", "PT376435H23M", "-PT376435H23M"], - ["seconds", "PT376435H23M8S", "-PT376435H23M8S"], - ["milliseconds", "PT376435H23M8.149S", "-PT376435H23M8.149S"], - ["microseconds", "PT376435H23M8.148529S", "-PT376435H23M8.14853S"], - ["nanoseconds", "PT376435H23M8.1485295S", "-PT376435H23M8.1485295S"], - ]; - - const roundingMode = "halfFloor"; - expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => { - const untilPositive = earlier.until(later, { largestUnit, smallestUnit, roundingMode }); - expect(untilPositive.toString()).toBe(expectedPositive); - - const untilNegative = later.until(earlier, { largestUnit, smallestUnit, roundingMode }); - expect(untilNegative.toString()).toBe(expectedNegative); - }); - }); - - test("'halfTrunc' rounding mode", () => { - const expected = [ - ["hours", "PT376435H", "-PT376435H"], - ["minutes", "PT376435H23M", "-PT376435H23M"], - ["seconds", "PT376435H23M8S", "-PT376435H23M8S"], - ["milliseconds", "PT376435H23M8.149S", "-PT376435H23M8.149S"], - ["microseconds", "PT376435H23M8.148529S", "-PT376435H23M8.148529S"], - ["nanoseconds", "PT376435H23M8.1485295S", "-PT376435H23M8.1485295S"], - ]; - - const roundingMode = "halfTrunc"; - expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => { - const untilPositive = earlier.until(later, { largestUnit, smallestUnit, roundingMode }); - expect(untilPositive.toString()).toBe(expectedPositive); - - const untilNegative = later.until(earlier, { largestUnit, smallestUnit, roundingMode }); - expect(untilNegative.toString()).toBe(expectedNegative); - }); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.prototype.valueOf.js b/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.prototype.valueOf.js deleted file mode 100644 index aa4e0ed9fd9..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.prototype.valueOf.js +++ /dev/null @@ -1,7 +0,0 @@ -describe("errors", () => { - test("throws TypeError", () => { - expect(() => { - new Temporal.Instant(0n).valueOf(); - }).toThrowWithMessage(TypeError, "Cannot convert Temporal.Instant to a primitive value"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Now/Now.@@toStringTag.js b/Libraries/LibJS/Tests/builtins/Temporal/Now/Now.@@toStringTag.js deleted file mode 100644 index c9f5e49dc09..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Now/Now.@@toStringTag.js +++ /dev/null @@ -1,3 +0,0 @@ -test("basic functionality", () => { - expect(Temporal.Now[Symbol.toStringTag]).toBe("Temporal.Now"); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Now/Now.plainDate.js b/Libraries/LibJS/Tests/builtins/Temporal/Now/Now.plainDate.js deleted file mode 100644 index dc61a5f05ca..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Now/Now.plainDate.js +++ /dev/null @@ -1,60 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.Now.plainDate).toHaveLength(1); - }); - - test("basic functionality", () => { - const calendar = new Temporal.Calendar("iso8601"); - const plainDate = Temporal.Now.plainDate(calendar); - expect(plainDate).toBeInstanceOf(Temporal.PlainDate); - expect(plainDate.calendar).toBe(calendar); - }); - - test("custom time zone", () => { - const calendar = new Temporal.Calendar("iso8601"); - const timeZone = { - getOffsetNanosecondsFor() { - return 86399999999999; - }, - }; - const plainDate = Temporal.Now.plainDate(calendar, "UTC"); - const plainDateWithOffset = Temporal.Now.plainDate(calendar, timeZone); - if (plainDate.dayOfYear === plainDate.daysInYear) { - expect(plainDateWithOffset.year).toBe(plainDate.year + 1); - expect(plainDateWithOffset.month).toBe(1); - expect(plainDateWithOffset.day).toBe(1); - } else { - expect(plainDateWithOffset.year).toBe(plainDate.year); - if (plainDate.day === plainDate.daysInMonth) { - expect(plainDateWithOffset.month).toBe(plainDate.month + 1); - expect(plainDateWithOffset.day).toBe(1); - } else { - expect(plainDateWithOffset.month).toBe(plainDate.month); - expect(plainDateWithOffset.day).toBe(plainDate.day + 1); - } - } - }); - - test("cannot have a time zone with more than a day", () => { - [86400000000000, -86400000000000, 86400000000001, 86400000000002].forEach(offset => { - const calendar = new Temporal.Calendar("iso8601"); - const timeZone = { - getOffsetNanosecondsFor() { - return offset; - }, - }; - expect(() => Temporal.Now.plainDate(calendar, timeZone)).toThrowWithMessage( - RangeError, - "Invalid offset nanoseconds value, must be in range -86400 * 10^9 + 1 to 86400 * 10^9 - 1" - ); - }); - }); -}); - -describe("errors", () => { - test("custom time zone doesn't have a getOffsetNanosecondsFor function", () => { - expect(() => { - Temporal.Now.plainDate({}, {}); - }).toThrowWithMessage(TypeError, "getOffsetNanosecondsFor is undefined"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Now/Now.plainDateISO.js b/Libraries/LibJS/Tests/builtins/Temporal/Now/Now.plainDateISO.js deleted file mode 100644 index 0505b7d1a25..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Now/Now.plainDateISO.js +++ /dev/null @@ -1,57 +0,0 @@ -describe("correct behavior", () => { - test("length is 0", () => { - expect(Temporal.Now.plainDateISO).toHaveLength(0); - }); - - test("basic functionality", () => { - const plainDate = Temporal.Now.plainDateISO(); - expect(plainDate).toBeInstanceOf(Temporal.PlainDate); - expect(plainDate.calendar.id).toBe("iso8601"); - }); - - test("custom time zone", () => { - const timeZone = { - getOffsetNanosecondsFor() { - return 86399999999999; - }, - }; - const plainDate = Temporal.Now.plainDateISO("UTC"); - const plainDateWithOffset = Temporal.Now.plainDateISO(timeZone); - if (plainDate.dayOfYear === plainDate.daysInYear) { - expect(plainDateWithOffset.year).toBe(plainDate.year + 1); - expect(plainDateWithOffset.month).toBe(1); - expect(plainDateWithOffset.day).toBe(1); - } else { - expect(plainDateWithOffset.year).toBe(plainDate.year); - if (plainDate.day === plainDate.daysInMonth) { - expect(plainDateWithOffset.month).toBe(plainDate.month + 1); - expect(plainDateWithOffset.day).toBe(1); - } else { - expect(plainDateWithOffset.month).toBe(plainDate.month); - expect(plainDateWithOffset.day).toBe(plainDate.day + 1); - } - } - }); - - test("cannot have a time zone with more than a day", () => { - [86400000000000, -86400000000000, 86400000000001, 86400000000002].forEach(offset => { - const timeZone = { - getOffsetNanosecondsFor() { - return offset; - }, - }; - expect(() => Temporal.Now.plainDateISO(timeZone)).toThrowWithMessage( - RangeError, - "Invalid offset nanoseconds value, must be in range -86400 * 10^9 + 1 to 86400 * 10^9 - 1" - ); - }); - }); -}); - -describe("errors", () => { - test("custom time zone doesn't have a getOffsetNanosecondsFor function", () => { - expect(() => { - Temporal.Now.plainDateISO({}); - }).toThrowWithMessage(TypeError, "getOffsetNanosecondsFor is undefined"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Now/Now.plainDateTime.js b/Libraries/LibJS/Tests/builtins/Temporal/Now/Now.plainDateTime.js deleted file mode 100644 index 0aaf7e99c0b..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Now/Now.plainDateTime.js +++ /dev/null @@ -1,109 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.Now.plainDateTime).toHaveLength(1); - }); - - test("basic functionality", () => { - const calendar = new Temporal.Calendar("iso8601"); - const plainDateTime = Temporal.Now.plainDateTime(calendar); - expect(plainDateTime).toBeInstanceOf(Temporal.PlainDateTime); - expect(plainDateTime.calendar).toBe(calendar); - }); - - const plainDateTimeToEpochSeconds = plainDateTime => - (plainDateTime.year - 1970) * 31_556_952 + - plainDateTime.dayOfYear * 86_400 + - plainDateTime.hour * 3_600 + - plainDateTime.minute * 60 + - plainDateTime.second + - plainDateTime.millisecond / 1_000 + - plainDateTime.microsecond / 1_000_000 + - plainDateTime.nanosecond / 1_000_000_000; - - let timeZoneTested = false; - - // Note: We test both positive and negative timezones because one might cross a year boundary. - // Since a year does not have a fixed amount of seconds because it can be a leap year, - // we cannot have a correct constant for seconds per year which is always correct. - // However, by assuming years are at least 2 days long we can simply try the positive - // and negative timezones and skip one if we jump the year. To ensure at least one is - // tested we have the timeZoneTested which is only set to true if one of the tests passed. - - // FIXME: The custom time zone tests are disabled due to being flaky. See: - // https://github.com/SerenityOS/serenity/issues/20806 - - test.skip("custom time zone positive", () => { - const calendar = new Temporal.Calendar("iso8601"); - const timeZone = { - getOffsetNanosecondsFor() { - return 86399999999999; - }, - }; - - const [plainDateTime, plainDateTimeWithOffset] = withinSameSecond(() => { - return [ - Temporal.Now.plainDateTime(calendar, "UTC"), - Temporal.Now.plainDateTime(calendar, timeZone), - ]; - }); - - if (plainDateTime.year !== plainDateTimeWithOffset.year) return; - - const differenceSeconds = - plainDateTimeToEpochSeconds(plainDateTimeWithOffset) - - plainDateTimeToEpochSeconds(plainDateTime); - expect(Math.floor(differenceSeconds)).toBe(86400); - timeZoneTested = true; - }); - - test.skip("custom time zone negative", () => { - const calendar = new Temporal.Calendar("iso8601"); - const timeZone = { - getOffsetNanosecondsFor() { - return -86399999999999; - }, - }; - - const [plainDateTime, plainDateTimeWithOffset] = withinSameSecond(() => { - return [ - Temporal.Now.plainDateTime(calendar, "UTC"), - Temporal.Now.plainDateTime(calendar, timeZone), - ]; - }); - - if (plainDateTime.year !== plainDateTimeWithOffset.year) return; - - const differenceSeconds = - plainDateTimeToEpochSeconds(plainDateTimeWithOffset) - - plainDateTimeToEpochSeconds(plainDateTime); - expect(Math.floor(differenceSeconds)).toBe(-86400); - timeZoneTested = true; - }); - - test.skip("custom time zone test was executed", () => { - expect(timeZoneTested).toBeTrue(); - }); - - test("cannot have a time zone with more than a day", () => { - [86400000000000, -86400000000000, 86400000000001, 86400000000002].forEach(offset => { - const calendar = new Temporal.Calendar("iso8601"); - const timeZone = { - getOffsetNanosecondsFor() { - return offset; - }, - }; - expect(() => Temporal.Now.plainDateTime(calendar, timeZone)).toThrowWithMessage( - RangeError, - "Invalid offset nanoseconds value, must be in range -86400 * 10^9 + 1 to 86400 * 10^9 - 1" - ); - }); - }); -}); - -describe("errors", () => { - test("custom time zone doesn't have a getOffsetNanosecondsFor function", () => { - expect(() => { - Temporal.Now.plainDateTime({}, {}); - }).toThrowWithMessage(TypeError, "getOffsetNanosecondsFor is undefined"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Now/Now.plainDateTimeISO.js b/Libraries/LibJS/Tests/builtins/Temporal/Now/Now.plainDateTimeISO.js deleted file mode 100644 index 14f12749b4d..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Now/Now.plainDateTimeISO.js +++ /dev/null @@ -1,99 +0,0 @@ -describe("correct behavior", () => { - test("length is 0", () => { - expect(Temporal.Now.plainDateTimeISO).toHaveLength(0); - }); - - test("basic functionality", () => { - const plainDateTime = Temporal.Now.plainDateTimeISO(); - expect(plainDateTime).toBeInstanceOf(Temporal.PlainDateTime); - expect(plainDateTime.calendar.id).toBe("iso8601"); - }); - - const plainDateTimeToEpochSeconds = plainDateTime => - (plainDateTime.year - 1970) * 31_556_952 + - plainDateTime.dayOfYear * 86_400 + - plainDateTime.hour * 3_600 + - plainDateTime.minute * 60 + - plainDateTime.second + - plainDateTime.millisecond / 1_000 + - plainDateTime.microsecond / 1_000_000 + - plainDateTime.nanosecond / 1_000_000_000; - - let timeZoneTested = false; - - // Note: We test both positive and negative timezones because one might cross a year boundary. - // Since a year does not have a fixed amount of seconds because it can be a leap year, - // we cannot have a correct constant for seconds per year which is always correct. - // However, by assuming years are at least 2 days long we can simply try the positive - // and negative timezones and skip one if we jump the year. To ensure at least one is - // tested we have the timeZoneTested which is only set to true if one of the tests passed. - - // FIXME: The custom time zone tests are disabled due to being flaky. See: - // https://github.com/SerenityOS/serenity/issues/20806 - - test.skip("custom time zone (positive)", () => { - const timeZone = { - getOffsetNanosecondsFor() { - return 86399999999999; - }, - }; - - const [plainDateTime, plainDateTimeWithOffset] = withinSameSecond(() => { - return [Temporal.Now.plainDateTimeISO("UTC"), Temporal.Now.plainDateTimeISO(timeZone)]; - }); - - if (plainDateTime.year !== plainDateTimeWithOffset.year) return; - - const differenceSeconds = - plainDateTimeToEpochSeconds(plainDateTimeWithOffset) - - plainDateTimeToEpochSeconds(plainDateTime); - expect(Math.floor(differenceSeconds)).toBe(86400); - timeZoneTested = true; - }); - - test.skip("custom time zone (negative)", () => { - const timeZone = { - getOffsetNanosecondsFor() { - return -86399999999999; - }, - }; - - const [plainDateTime, plainDateTimeWithOffset] = withinSameSecond(() => { - return [Temporal.Now.plainDateTimeISO("UTC"), Temporal.Now.plainDateTimeISO(timeZone)]; - }); - - if (plainDateTime.year !== plainDateTimeWithOffset.year) return; - - const differenceSeconds = - plainDateTimeToEpochSeconds(plainDateTimeWithOffset) - - plainDateTimeToEpochSeconds(plainDateTime); - expect(Math.floor(differenceSeconds)).toBe(-86400); - timeZoneTested = true; - }); - - test.skip("custom time zone test was executed", () => { - expect(timeZoneTested).toBeTrue(); - }); - - test("cannot have a time zone with more than a day", () => { - [86400000000000, -86400000000000, 86400000000001, 86400000000002].forEach(offset => { - const timeZone = { - getOffsetNanosecondsFor() { - return offset; - }, - }; - expect(() => Temporal.Now.plainDateTimeISO(timeZone)).toThrowWithMessage( - RangeError, - "Invalid offset nanoseconds value, must be in range -86400 * 10^9 + 1 to 86400 * 10^9 - 1" - ); - }); - }); -}); - -describe("errors", () => { - test("custom time zone doesn't have a getOffsetNanosecondsFor function", () => { - expect(() => { - Temporal.Now.plainDateTimeISO({}); - }).toThrowWithMessage(TypeError, "getOffsetNanosecondsFor is undefined"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Now/Now.plainTimeISO.js b/Libraries/LibJS/Tests/builtins/Temporal/Now/Now.plainTimeISO.js deleted file mode 100644 index d7a27dbbb77..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Now/Now.plainTimeISO.js +++ /dev/null @@ -1,44 +0,0 @@ -describe("correct behavior", () => { - test("length is 0", () => { - expect(Temporal.Now.plainTimeISO).toHaveLength(0); - }); - - test("basic functionality", () => { - const plainTime = Temporal.Now.plainTimeISO(); - expect(plainTime).toBeInstanceOf(Temporal.PlainTime); - expect(plainTime.calendar.id).toBe("iso8601"); - }); - - test("custom time zone", () => { - const timeZone = { - getOffsetNanosecondsFor() { - return 86399999999999; - }, - }; - const plainTime = Temporal.Now.plainTimeISO("UTC"); - const plainTimeWithOffset = Temporal.Now.plainTimeISO(timeZone); - // FIXME: Compare these in a sensible way - }); - - test("cannot have a time zone with more than a day", () => { - [86400000000000, -86400000000000, 86400000000001, 86400000000002].forEach(offset => { - const timeZone = { - getOffsetNanosecondsFor() { - return offset; - }, - }; - expect(() => Temporal.Now.plainTimeISO(timeZone)).toThrowWithMessage( - RangeError, - "Invalid offset nanoseconds value, must be in range -86400 * 10^9 + 1 to 86400 * 10^9 - 1" - ); - }); - }); -}); - -describe("errors", () => { - test("custom time zone doesn't have a getOffsetNanosecondsFor function", () => { - expect(() => { - Temporal.Now.plainTimeISO({}); - }).toThrowWithMessage(TypeError, "getOffsetNanosecondsFor is undefined"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Now/Now.zonedDateTime.js b/Libraries/LibJS/Tests/builtins/Temporal/Now/Now.zonedDateTime.js deleted file mode 100644 index ee09d10ba3b..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Now/Now.zonedDateTime.js +++ /dev/null @@ -1,21 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.Now.zonedDateTime).toHaveLength(1); - }); - - test("basic functionality", () => { - const calendar = new Temporal.Calendar("iso8601"); - const zonedDateTime = Temporal.Now.zonedDateTime(calendar); - expect(zonedDateTime).toBeInstanceOf(Temporal.ZonedDateTime); - expect(zonedDateTime.calendar).toBe(calendar); - }); - - test("with time zone", () => { - const calendar = new Temporal.Calendar("iso8601"); - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = Temporal.Now.zonedDateTime(calendar, timeZone); - expect(zonedDateTime).toBeInstanceOf(Temporal.ZonedDateTime); - expect(zonedDateTime.calendar).toBe(calendar); - expect(zonedDateTime.timeZone).toBe(timeZone); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Now/Now.zonedDateTimeISO.js b/Libraries/LibJS/Tests/builtins/Temporal/Now/Now.zonedDateTimeISO.js deleted file mode 100644 index c5b26d19bce..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/Now/Now.zonedDateTimeISO.js +++ /dev/null @@ -1,19 +0,0 @@ -describe("correct behavior", () => { - test("length is 0", () => { - expect(Temporal.Now.zonedDateTimeISO).toHaveLength(0); - }); - - test("basic functionality", () => { - const zonedDateTime = Temporal.Now.zonedDateTimeISO(); - expect(zonedDateTime).toBeInstanceOf(Temporal.ZonedDateTime); - expect(zonedDateTime.calendar.id).toBe("iso8601"); - }); - - test("with time zone", () => { - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = Temporal.Now.zonedDateTimeISO(timeZone); - expect(zonedDateTime).toBeInstanceOf(Temporal.ZonedDateTime); - expect(zonedDateTime.calendar.id).toBe("iso8601"); - expect(zonedDateTime.timeZone).toBe(timeZone); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.compare.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.compare.js deleted file mode 100644 index a6a92799a3e..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.compare.js +++ /dev/null @@ -1,13 +0,0 @@ -describe("correct behavior", () => { - test("length is 2", () => { - expect(Temporal.PlainDate.compare).toHaveLength(2); - }); - - test("basic functionality", () => { - const plainDate1 = new Temporal.PlainDate(2021, 7, 26); - expect(Temporal.PlainDate.compare(plainDate1, plainDate1)).toBe(0); - const plainDate2 = new Temporal.PlainDate(2021, 7, 27); - expect(Temporal.PlainDate.compare(plainDate1, plainDate2)).toBe(-1); - expect(Temporal.PlainDate.compare(plainDate2, plainDate1)).toBe(1); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.from.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.from.js deleted file mode 100644 index 702b038c47a..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.from.js +++ /dev/null @@ -1,61 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.PlainDate.from).toHaveLength(1); - }); - - test("PlainDate instance argument", () => { - const plainDate = new Temporal.PlainDate(2021, 7, 26); - const createdPlainDate = Temporal.PlainDate.from(plainDate); - expect(createdPlainDate.year).toBe(2021); - expect(createdPlainDate.month).toBe(7); - expect(createdPlainDate.day).toBe(26); - }); - - test("PlainDateTime instance argument", () => { - const plainDateTime = new Temporal.PlainDateTime(2021, 7, 26, 1, 2, 3); - const createdPlainDate = Temporal.PlainDate.from(plainDateTime); - expect(createdPlainDate.year).toBe(2021); - expect(createdPlainDate.month).toBe(7); - expect(createdPlainDate.day).toBe(26); - }); - - test("ZonedDateTime instance argument", () => { - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = new Temporal.ZonedDateTime(1627318123456789000n, timeZone); - const createdPlainDate = Temporal.PlainDate.from(zonedDateTime); - expect(createdPlainDate.year).toBe(2021); - expect(createdPlainDate.month).toBe(7); - expect(createdPlainDate.day).toBe(26); - }); - - test("PlainDate string argument", () => { - const createdPlainDate = Temporal.PlainDate.from("2021-07-26"); - expect(createdPlainDate.year).toBe(2021); - expect(createdPlainDate.month).toBe(7); - expect(createdPlainDate.day).toBe(26); - }); -}); - -describe("errors", () => { - test("custom time zone doesn't have a getOffsetNanosecondsFor function", () => { - const zonedDateTime = new Temporal.ZonedDateTime(0n, {}); - expect(() => { - Temporal.PlainDate.from(zonedDateTime); - }).toThrowWithMessage(TypeError, "getOffsetNanosecondsFor is undefined"); - }); - - test("invalid date time string", () => { - expect(() => { - Temporal.PlainDate.from("foo"); - }).toThrowWithMessage(RangeError, "Invalid date time string 'foo'"); - }); - - test("extended year must not be negative zero", () => { - expect(() => { - Temporal.PlainDate.from("-000000-01-01"); - }).toThrowWithMessage(RangeError, "Invalid date time string '-000000-01-01'"); - expect(() => { - Temporal.PlainDate.from("−000000-01-01"); // U+2212 - }).toThrowWithMessage(RangeError, "Invalid date time string '−000000-01-01'"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.js deleted file mode 100644 index 8273a1bdba5..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.js +++ /dev/null @@ -1,53 +0,0 @@ -describe("errors", () => { - test("called without new", () => { - expect(() => { - Temporal.PlainDate(); - }).toThrowWithMessage( - TypeError, - "Temporal.PlainDate constructor must be called with 'new'" - ); - }); - - test("cannot pass Infinity", () => { - expect(() => { - new Temporal.PlainDate(Infinity); - }).toThrowWithMessage(RangeError, "Invalid plain date"); - expect(() => { - new Temporal.PlainDate(0, Infinity); - }).toThrowWithMessage(RangeError, "Invalid plain date"); - expect(() => { - new Temporal.PlainDate(0, 0, Infinity); - }).toThrowWithMessage(RangeError, "Invalid plain date"); - expect(() => { - new Temporal.PlainDate(-Infinity); - }).toThrowWithMessage(RangeError, "Invalid plain date"); - expect(() => { - new Temporal.PlainDate(0, -Infinity); - }).toThrowWithMessage(RangeError, "Invalid plain date"); - expect(() => { - new Temporal.PlainDate(0, 0, -Infinity); - }).toThrowWithMessage(RangeError, "Invalid plain date"); - }); - - test("cannot pass invalid ISO month/day", () => { - expect(() => { - new Temporal.PlainDate(0, 0, 1); - }).toThrowWithMessage(RangeError, "Invalid plain date"); - expect(() => { - new Temporal.PlainDate(0, 1, 0); - }).toThrowWithMessage(RangeError, "Invalid plain date"); - }); -}); - -describe("normal behavior", () => { - test("length is 3", () => { - expect(Temporal.PlainDate).toHaveLength(3); - }); - - test("basic functionality", () => { - const plainDate = new Temporal.PlainDate(2021, 7, 19); - expect(typeof plainDate).toBe("object"); - expect(plainDate).toBeInstanceOf(Temporal.PlainDate); - expect(Object.getPrototypeOf(plainDate)).toBe(Temporal.PlainDate.prototype); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.@@toStringTag.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.@@toStringTag.js deleted file mode 100644 index 286d2440cbc..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.@@toStringTag.js +++ /dev/null @@ -1,3 +0,0 @@ -test("basic functionality", () => { - expect(Temporal.PlainDate.prototype[Symbol.toStringTag]).toBe("Temporal.PlainDate"); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.add.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.add.js deleted file mode 100644 index eaa8420e42d..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.add.js +++ /dev/null @@ -1,19 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.PlainDate.prototype.add).toHaveLength(1); - }); - - test("basic functionality", () => { - const plainDate = new Temporal.PlainDate(1970, 1, 1); - const result = plainDate.add(new Temporal.Duration(51, 6, 0, 5)); - expect(result.equals(new Temporal.PlainDate(2021, 7, 6))).toBeTrue(); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainDate object", () => { - expect(() => { - Temporal.PlainDate.prototype.add.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainDate"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.calendar.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.calendar.js deleted file mode 100644 index cc8edd98f57..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.calendar.js +++ /dev/null @@ -1,15 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const calendar = { hello: "friends" }; - const plainDate = new Temporal.PlainDate(1, 1, 1, calendar); - expect(plainDate.calendar).toBe(calendar); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainDate object", () => { - expect(() => { - Reflect.get(Temporal.PlainDate.prototype, "calendar", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainDate"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.calendarId.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.calendarId.js deleted file mode 100644 index ae43185fd4f..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.calendarId.js +++ /dev/null @@ -1,15 +0,0 @@ -describe("correct behavior", () => { - test("calendarId basic functionality", () => { - const calendar = "iso8601"; - const plainDate = new Temporal.PlainDate(2000, 5, 1, calendar); - expect(plainDate.calendarId).toBe("iso8601"); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainDate object", () => { - expect(() => { - Reflect.get(Temporal.PlainDate.prototype, "calendarId", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainDate"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.day.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.day.js deleted file mode 100644 index 576e8275cc5..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.day.js +++ /dev/null @@ -1,14 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const date = new Temporal.PlainDate(2021, 7, 23); - expect(date.day).toBe(23); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainDate object", () => { - expect(() => { - Reflect.get(Temporal.PlainDate.prototype, "day", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainDate"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.dayOfWeek.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.dayOfWeek.js deleted file mode 100644 index 436b8b6e850..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.dayOfWeek.js +++ /dev/null @@ -1,14 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const date = new Temporal.PlainDate(2021, 7, 23); - expect(date.dayOfWeek).toBe(5); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainDate object", () => { - expect(() => { - Reflect.get(Temporal.PlainDate.prototype, "dayOfWeek", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainDate"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.dayOfYear.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.dayOfYear.js deleted file mode 100644 index 15d50c8e5c0..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.dayOfYear.js +++ /dev/null @@ -1,14 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const date = new Temporal.PlainDate(2021, 7, 23); - expect(date.dayOfYear).toBe(204); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainDate object", () => { - expect(() => { - Reflect.get(Temporal.PlainDate.prototype, "dayOfYear", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainDate"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.daysInMonth.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.daysInMonth.js deleted file mode 100644 index 9d02718ded0..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.daysInMonth.js +++ /dev/null @@ -1,14 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const date = new Temporal.PlainDate(2021, 7, 23); - expect(date.daysInMonth).toBe(31); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainDate object", () => { - expect(() => { - Reflect.get(Temporal.PlainDate.prototype, "daysInMonth", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainDate"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.daysInWeek.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.daysInWeek.js deleted file mode 100644 index 1e9a8883493..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.daysInWeek.js +++ /dev/null @@ -1,14 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const date = new Temporal.PlainDate(2021, 7, 23); - expect(date.daysInWeek).toBe(7); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainDate object", () => { - expect(() => { - Reflect.get(Temporal.PlainDate.prototype, "daysInWeek", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainDate"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.daysInYear.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.daysInYear.js deleted file mode 100644 index 90eb232fd04..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.daysInYear.js +++ /dev/null @@ -1,14 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const date = new Temporal.PlainDate(2021, 7, 23); - expect(date.daysInYear).toBe(365); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainDate object", () => { - expect(() => { - Reflect.get(Temporal.PlainDate.prototype, "daysInYear", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainDate"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.equals.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.equals.js deleted file mode 100644 index 4fe447e6374..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.equals.js +++ /dev/null @@ -1,13 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.PlainDate.prototype.equals).toHaveLength(1); - }); - - test("basic functionality", () => { - const calendar = { hello: "friends" }; - const firstPlainDate = new Temporal.PlainDate(1, 1, 1, calendar); - const secondPlainDate = new Temporal.PlainDate(0, 1, 1, calendar); - expect(firstPlainDate.equals(firstPlainDate)).toBeTrue(); - expect(firstPlainDate.equals(secondPlainDate)).toBeFalse(); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.era.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.era.js deleted file mode 100644 index f6080cded15..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.era.js +++ /dev/null @@ -1,24 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const plainDate = new Temporal.PlainDate(2021, 7, 6); - expect(plainDate.era).toBeUndefined(); - }); - - test("calendar with custom era function", () => { - const calendar = { - era() { - return "foo"; - }, - }; - const plainDate = new Temporal.PlainDate(2021, 7, 6, calendar); - expect(plainDate.era).toBe("foo"); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainDate object", () => { - expect(() => { - Reflect.get(Temporal.PlainDate.prototype, "era", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainDate"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.eraYear.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.eraYear.js deleted file mode 100644 index aa3452aa466..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.eraYear.js +++ /dev/null @@ -1,24 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const plainDate = new Temporal.PlainDate(2021, 7, 6); - expect(plainDate.eraYear).toBeUndefined(); - }); - - test("calendar with custom eraYear function", () => { - const calendar = { - eraYear() { - return 123; - }, - }; - const plainDate = new Temporal.PlainDate(2021, 7, 6, calendar); - expect(plainDate.eraYear).toBe(123); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainDate object", () => { - expect(() => { - Reflect.get(Temporal.PlainDate.prototype, "eraYear", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainDate"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.getISOFields.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.getISOFields.js deleted file mode 100644 index eaef9723183..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.getISOFields.js +++ /dev/null @@ -1,19 +0,0 @@ -describe("normal behavior", () => { - test("length is 0", () => { - expect(Temporal.PlainDate.prototype.getISOFields).toHaveLength(0); - }); - - test("basic functionality", () => { - const calendar = new Temporal.Calendar("iso8601"); - const plainDate = new Temporal.PlainDate(2021, 7, 29, calendar); - const fields = plainDate.getISOFields(); - expect(fields).toEqual({ calendar, isoDay: 29, isoMonth: 7, isoYear: 2021 }); - // Test field order - expect(Object.getOwnPropertyNames(fields)).toEqual([ - "calendar", - "isoDay", - "isoMonth", - "isoYear", - ]); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.inLeapYear.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.inLeapYear.js deleted file mode 100644 index 94810afc29a..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.inLeapYear.js +++ /dev/null @@ -1,16 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const date = new Temporal.PlainDate(2021, 7, 23); - expect(date.inLeapYear).toBeFalse(); - const leapDate = new Temporal.PlainDate(2020, 7, 23); - expect(leapDate.inLeapYear).toBeTrue(); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainDate object", () => { - expect(() => { - Reflect.get(Temporal.PlainDate.prototype, "inLeapYear", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainDate"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.month.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.month.js deleted file mode 100644 index 4e771f92727..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.month.js +++ /dev/null @@ -1,14 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const date = new Temporal.PlainDate(2021, 7, 23); - expect(date.month).toBe(7); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainDate object", () => { - expect(() => { - Reflect.get(Temporal.PlainDate.prototype, "month", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainDate"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.monthCode.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.monthCode.js deleted file mode 100644 index e5c6a293a82..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.monthCode.js +++ /dev/null @@ -1,14 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const date = new Temporal.PlainDate(2021, 7, 23); - expect(date.monthCode).toBe("M07"); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainDate object", () => { - expect(() => { - Reflect.get(Temporal.PlainDate.prototype, "monthCode", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainDate"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.monthsInYear.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.monthsInYear.js deleted file mode 100644 index 44b3e3566c1..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.monthsInYear.js +++ /dev/null @@ -1,14 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const date = new Temporal.PlainDate(2021, 7, 23); - expect(date.monthsInYear).toBe(12); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainDate object", () => { - expect(() => { - Reflect.get(Temporal.PlainDate.prototype, "monthsInYear", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainDate"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.since.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.since.js deleted file mode 100644 index f97a8ae3845..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.since.js +++ /dev/null @@ -1,286 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.PlainDate.prototype.since).toHaveLength(1); - }); - - test("basic functionality", () => { - const dateOne = new Temporal.PlainDate(2021, 11, 14); - const dateTwo = new Temporal.PlainDate(2022, 12, 25); - const sinceDuration = dateTwo.since(dateOne); - - expect(sinceDuration.years).toBe(0); - expect(sinceDuration.months).toBe(0); - expect(sinceDuration.weeks).toBe(0); - expect(sinceDuration.days).toBe(406); - expect(sinceDuration.hours).toBe(0); - expect(sinceDuration.minutes).toBe(0); - expect(sinceDuration.seconds).toBe(0); - expect(sinceDuration.milliseconds).toBe(0); - expect(sinceDuration.microseconds).toBe(0); - expect(sinceDuration.nanoseconds).toBe(0); - }); - - test("equal dates", () => { - const equalDateOne = new Temporal.PlainDate(1, 1, 1); - const equalDateTwo = new Temporal.PlainDate(1, 1, 1); - - const checkResults = result => { - expect(result.years).toBe(0); - expect(result.months).toBe(0); - expect(result.weeks).toBe(0); - expect(result.days).toBe(0); - expect(result.hours).toBe(0); - expect(result.minutes).toBe(0); - expect(result.seconds).toBe(0); - expect(result.milliseconds).toBe(0); - expect(result.microseconds).toBe(0); - expect(result.nanoseconds).toBe(0); - }; - - checkResults(equalDateOne.since(equalDateOne)); - checkResults(equalDateTwo.since(equalDateTwo)); - checkResults(equalDateOne.since(equalDateTwo)); - checkResults(equalDateTwo.since(equalDateOne)); - }); - - test("negative direction", () => { - const dateOne = new Temporal.PlainDate(2021, 11, 14); - const dateTwo = new Temporal.PlainDate(2022, 12, 25); - const sinceDuration = dateOne.since(dateTwo); - - expect(sinceDuration.years).toBe(0); - expect(sinceDuration.months).toBe(0); - expect(sinceDuration.weeks).toBe(0); - expect(sinceDuration.days).toBe(-406); - expect(sinceDuration.hours).toBe(0); - expect(sinceDuration.minutes).toBe(0); - expect(sinceDuration.seconds).toBe(0); - expect(sinceDuration.milliseconds).toBe(0); - expect(sinceDuration.microseconds).toBe(0); - expect(sinceDuration.nanoseconds).toBe(0); - }); - - test("largestUnit option", () => { - const values = [ - ["year", { years: 1, months: 1, days: 11 }], - ["month", { months: 13, days: 11 }], - ["week", { weeks: 58 }], - ["day", { days: 406 }], - ]; - - const dateOne = new Temporal.PlainDate(2021, 11, 14); - const dateTwo = new Temporal.PlainDate(2022, 12, 25); - - for (const [largestUnit, durationLike] of values) { - const singularOptions = { largestUnit }; - const pluralOptions = { largestUnit: `${largestUnit}s` }; - - const propertiesToCheck = Object.keys(durationLike); - - // Positive direction - const positiveSingularResult = dateTwo.since(dateOne, singularOptions); - for (const property of propertiesToCheck) - expect(positiveSingularResult[property]).toBe(durationLike[property]); - - const positivePluralResult = dateTwo.since(dateOne, pluralOptions); - for (const property of propertiesToCheck) - expect(positivePluralResult[property]).toBe(durationLike[property]); - - // Negative direction - const negativeSingularResult = dateOne.since(dateTwo, singularOptions); - for (const property of propertiesToCheck) - expect(negativeSingularResult[property]).toBe(-durationLike[property]); - - const negativePluralResult = dateOne.since(dateTwo, pluralOptions); - for (const property of propertiesToCheck) - expect(negativePluralResult[property]).toBe(-durationLike[property]); - } - }); - - test("PlainDate string argument", () => { - const dateTwo = new Temporal.PlainDate(2022, 12, 25); - const sinceDuration = dateTwo.since("2021-11-14"); - - expect(sinceDuration.years).toBe(0); - expect(sinceDuration.months).toBe(0); - expect(sinceDuration.weeks).toBe(0); - expect(sinceDuration.days).toBe(406); - expect(sinceDuration.hours).toBe(0); - expect(sinceDuration.minutes).toBe(0); - expect(sinceDuration.seconds).toBe(0); - expect(sinceDuration.milliseconds).toBe(0); - expect(sinceDuration.microseconds).toBe(0); - expect(sinceDuration.nanoseconds).toBe(0); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainDate object", () => { - expect(() => { - Temporal.PlainDate.prototype.since.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainDate"); - }); - - test("cannot compare dates from different calendars", () => { - const calendarOne = { - toString() { - return "calendarOne"; - }, - }; - - const calendarTwo = { - toString() { - return "calendarTwo"; - }, - }; - - const dateOneWithCalendar = new Temporal.PlainDate(2021, 11, 14, calendarOne); - const dateTwoWithCalendar = new Temporal.PlainDate(2022, 12, 25, calendarTwo); - - expect(() => { - dateOneWithCalendar.since(dateTwoWithCalendar); - }).toThrowWithMessage(RangeError, "Cannot compare dates from two different calendars"); - }); - - test("disallowed units", () => { - const dateOne = new Temporal.PlainDate(2021, 11, 14); - const dateTwo = new Temporal.PlainDate(2022, 12, 25); - - const disallowedUnits = [ - "hour", - "minute", - "second", - "millisecond", - "microsecond", - "nanosecond", - ]; - - for (const smallestUnit of disallowedUnits) { - const singularSmallestUnitOptions = { smallestUnit }; - const pluralSmallestUnitOptions = { smallestUnit: `${smallestUnit}s` }; - - expect(() => { - dateOne.since(dateTwo, singularSmallestUnitOptions); - }).toThrowWithMessage( - RangeError, - `${smallestUnit} is not a valid value for option smallestUnit` - ); - - expect(() => { - dateOne.since(dateTwo, pluralSmallestUnitOptions); - }).toThrowWithMessage( - RangeError, - `${smallestUnit}s is not a valid value for option smallestUnit` - ); - } - - for (const largestUnit of disallowedUnits) { - const singularLargestUnitOptions = { largestUnit }; - const pluralLargestUnitOptions = { largestUnit: `${largestUnit}s` }; - - expect(() => { - dateOne.since(dateTwo, singularLargestUnitOptions); - }).toThrowWithMessage( - RangeError, - `${largestUnit} is not a valid value for option largestUnit` - ); - - expect(() => { - dateOne.since(dateTwo, pluralLargestUnitOptions); - }).toThrowWithMessage( - RangeError, - `${largestUnit}s is not a valid value for option largestUnit` - ); - } - }); - - test("invalid unit range", () => { - // smallestUnit -> disallowed largestUnits, see validate_temporal_unit_range - // Note that all the "smallestUnits" are all the allowedUnits. - const invalidRanges = [ - ["year", ["month", "week", "day"]], - ["month", ["week", "day"]], - ["week", ["day"]], - ]; - - const dateOne = new Temporal.PlainDate(2021, 11, 14); - const dateTwo = new Temporal.PlainDate(2022, 12, 25); - - for (const [smallestUnit, disallowedLargestUnits] of invalidRanges) { - for (const disallowedUnit of disallowedLargestUnits) { - const pluralSmallestUnit = `${smallestUnit}s`; - const pluralDisallowedUnit = `${disallowedUnit}s`; - - const singularSmallestSingularDisallowedOptions = { - smallestUnit, - largestUnit: disallowedUnit, - }; - const singularSmallestPluralDisallowedOptions = { - smallestUnit, - largestUnit: pluralDisallowedUnit, - }; - const pluralSmallestSingularDisallowedOptions = { - smallestUnit: pluralSmallestUnit, - largestUnit: disallowedUnit, - }; - const pluralSmallestPluralDisallowedOptions = { - smallestUnit: pluralSmallestUnit, - largestUnit: pluralDisallowedUnit, - }; - - expect(() => { - dateOne.since(dateTwo, singularSmallestSingularDisallowedOptions); - }).toThrowWithMessage( - RangeError, - `Invalid unit range, ${smallestUnit} is larger than ${disallowedUnit}` - ); - - expect(() => { - dateOne.since(dateTwo, singularSmallestPluralDisallowedOptions); - }).toThrowWithMessage( - RangeError, - `Invalid unit range, ${smallestUnit} is larger than ${disallowedUnit}` - ); - - expect(() => { - dateOne.since(dateTwo, pluralSmallestSingularDisallowedOptions); - }).toThrowWithMessage( - RangeError, - `Invalid unit range, ${smallestUnit} is larger than ${disallowedUnit}` - ); - - expect(() => { - dateOne.since(dateTwo, pluralSmallestPluralDisallowedOptions); - }).toThrowWithMessage( - RangeError, - `Invalid unit range, ${smallestUnit} is larger than ${disallowedUnit}` - ); - } - } - }); - - test("dateUntil only called once with rounding mode of days and small enough granularity", () => { - const actual = []; - - class DateUntilOptionsCalendar extends Temporal.Calendar { - constructor() { - super("iso8601"); - } - - dateUntil(earlier, later, options) { - actual.push(options.largestUnit); - return super.dateUntil(earlier, later, options); - } - } - - const calendar = new DateUntilOptionsCalendar(); - - largestUnit = "days"; - expected = []; - - const earlier = new Temporal.PlainDate(2000, 5, 2, calendar); - const later = new Temporal.PlainDate(2001, 6, 3, calendar); - later.since(earlier, { largestUnit }); - expect(actual).toEqual([]); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.subtract.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.subtract.js deleted file mode 100644 index 3df325e73a4..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.subtract.js +++ /dev/null @@ -1,19 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.PlainDate.prototype.subtract).toHaveLength(1); - }); - - test("basic functionality", () => { - const plainDate = new Temporal.PlainDate(2021, 7, 6); - const result = plainDate.subtract(new Temporal.Duration(51, 6, 0, 5)); - expect(result.equals(new Temporal.PlainDate(1970, 1, 1))).toBeTrue(); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainDate object", () => { - expect(() => { - Temporal.PlainDate.prototype.subtract.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainDate"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.toJSON.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.toJSON.js deleted file mode 100644 index 4ce606105ee..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.toJSON.js +++ /dev/null @@ -1,23 +0,0 @@ -describe("correct behavior", () => { - test("length is 0", () => { - expect(Temporal.PlainDate.prototype.toJSON).toHaveLength(0); - }); - - test("basic functionality", () => { - let plainDate; - - plainDate = new Temporal.PlainDate(2021, 7, 6); - expect(plainDate.toJSON()).toBe("2021-07-06"); - - plainDate = new Temporal.PlainDate(2021, 7, 6, { toString: () => "foo" }); - expect(plainDate.toJSON()).toBe("2021-07-06[u-ca=foo]"); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainDate object", () => { - expect(() => { - Temporal.PlainDate.prototype.toJSON.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainDate"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.toLocaleString.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.toLocaleString.js deleted file mode 100644 index bc465a1af20..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.toLocaleString.js +++ /dev/null @@ -1,23 +0,0 @@ -describe("correct behavior", () => { - test("length is 0", () => { - expect(Temporal.PlainDate.prototype.toLocaleString).toHaveLength(0); - }); - - test("basic functionality", () => { - let plainDate; - - plainDate = new Temporal.PlainDate(2021, 7, 6); - expect(plainDate.toLocaleString()).toBe("2021-07-06"); - - plainDate = new Temporal.PlainDate(2021, 7, 6, { toString: () => "foo" }); - expect(plainDate.toLocaleString()).toBe("2021-07-06[u-ca=foo]"); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainDate object", () => { - expect(() => { - Temporal.PlainDate.prototype.toLocaleString.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainDate"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.toPlainDateTime.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.toPlainDateTime.js deleted file mode 100644 index 69fdb1cc48b..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.toPlainDateTime.js +++ /dev/null @@ -1,20 +0,0 @@ -describe("correct behavior", () => { - test("length is 0", () => { - expect(Temporal.PlainDate.prototype.toPlainDateTime).toHaveLength(0); - }); - - test("basic functionality", () => { - const plainDate = new Temporal.PlainDate(2021, 8, 27); - const plainTime = new Temporal.PlainTime(18, 11, 44, 1, 2, 3); - const plainDateTime = plainDate.toPlainDateTime(plainTime); - expect(plainDateTime.year).toBe(2021); - expect(plainDateTime.month).toBe(8); - expect(plainDateTime.day).toBe(27); - expect(plainDateTime.hour).toBe(18); - expect(plainDateTime.minute).toBe(11); - expect(plainDateTime.second).toBe(44); - expect(plainDateTime.millisecond).toBe(1); - expect(plainDateTime.microsecond).toBe(2); - expect(plainDateTime.nanosecond).toBe(3); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.toPlainMonthDay.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.toPlainMonthDay.js deleted file mode 100644 index 4dbbebb24af..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.toPlainMonthDay.js +++ /dev/null @@ -1,15 +0,0 @@ -describe("correct behavior", () => { - test("length is 0", () => { - expect(Temporal.PlainDate.prototype.toPlainMonthDay).toHaveLength(0); - }); - - test("basic functionality", () => { - const plainDate = new Temporal.PlainDate(2021, 7, 6); - const plainMonthDay = plainDate.toPlainMonthDay(); - expect(plainMonthDay.calendar).toBe(plainDate.calendar); - expect(plainMonthDay.monthCode).toBe("M07"); - expect(plainMonthDay.day).toBe(6); - const fields = plainMonthDay.getISOFields(); - expect(fields.isoYear).toBe(1972); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.toPlainYearMonth.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.toPlainYearMonth.js deleted file mode 100644 index c3a100c125e..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.toPlainYearMonth.js +++ /dev/null @@ -1,13 +0,0 @@ -describe("correct behavior", () => { - test("length is 0", () => { - expect(Temporal.PlainDate.prototype.toPlainYearMonth).toHaveLength(0); - }); - - test("basic functionality", () => { - const plainDate = new Temporal.PlainDate(2021, 7, 6); - const plainYearMonth = plainDate.toPlainYearMonth(); - expect(plainYearMonth.calendar).toBe(plainDate.calendar); - expect(plainYearMonth.year).toBe(2021); - expect(plainYearMonth.month).toBe(7); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.toString.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.toString.js deleted file mode 100644 index 87b2f1e5fac..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.toString.js +++ /dev/null @@ -1,73 +0,0 @@ -describe("correct behavior", () => { - test("length is 0", () => { - expect(Temporal.PlainDate.prototype.toString).toHaveLength(0); - }); - - test("basic functionality", () => { - let plainDate; - - plainDate = new Temporal.PlainDate(2021, 7, 6); - expect(plainDate.toString()).toBe("2021-07-06"); - expect(plainDate.toString({ calendarName: "auto" })).toBe("2021-07-06"); - expect(plainDate.toString({ calendarName: "always" })).toBe("2021-07-06[u-ca=iso8601]"); - expect(plainDate.toString({ calendarName: "never" })).toBe("2021-07-06"); - expect(plainDate.toString({ calendarName: "critical" })).toBe("2021-07-06[!u-ca=iso8601]"); - - plainDate = new Temporal.PlainDate(2021, 7, 6, { toString: () => "foo" }); - expect(plainDate.toString()).toBe("2021-07-06[u-ca=foo]"); - expect(plainDate.toString({ calendarName: "auto" })).toBe("2021-07-06[u-ca=foo]"); - expect(plainDate.toString({ calendarName: "always" })).toBe("2021-07-06[u-ca=foo]"); - expect(plainDate.toString({ calendarName: "never" })).toBe("2021-07-06"); - expect(plainDate.toString({ calendarName: "critical" })).toBe("2021-07-06[!u-ca=foo]"); - - plainDate = new Temporal.PlainDate(0, 1, 1); - expect(plainDate.toString()).toBe("0000-01-01"); - - plainDate = new Temporal.PlainDate(999, 1, 1); - expect(plainDate.toString()).toBe("0999-01-01"); - - plainDate = new Temporal.PlainDate(9999, 1, 1); - expect(plainDate.toString()).toBe("9999-01-01"); - - plainDate = new Temporal.PlainDate(12345, 1, 1); - expect(plainDate.toString()).toBe("+012345-01-01"); - - plainDate = new Temporal.PlainDate(123456, 1, 1); - expect(plainDate.toString()).toBe("+123456-01-01"); - - plainDate = new Temporal.PlainDate(-12345, 1, 1); - expect(plainDate.toString()).toBe("-012345-01-01"); - }); - - test("doesn't call ToString on calendar if calenderName option is 'never'", () => { - let calledToString = false; - const calendar = { - toString() { - calledToString = true; - return "nocall"; - }, - }; - - const plainDate = new Temporal.PlainDate(2022, 8, 8, calendar); - const options = { - calendarName: "never", - }; - expect(plainDate.toString(options)).toBe("2022-08-08"); - expect(calledToString).toBeFalse(); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainDate object", () => { - expect(() => { - Temporal.PlainDate.prototype.toString.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainDate"); - }); - - test("calendarName option must be one of 'auto', 'always', 'never', 'critical'", () => { - const plainDate = new Temporal.PlainDate(2021, 7, 6); - expect(() => { - plainDate.toString({ calendarName: "foo" }); - }).toThrowWithMessage(RangeError, "foo is not a valid value for option calendarName"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.toZonedDateTime.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.toZonedDateTime.js deleted file mode 100644 index 1d475faea59..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.toZonedDateTime.js +++ /dev/null @@ -1,105 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.PlainDate.prototype.toZonedDateTime).toHaveLength(1); - }); - - test("basic functionality - time zone", () => { - // 3.b. in the spec - const plainDate = new Temporal.PlainDate(2021, 7, 6); - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = plainDate.toZonedDateTime(timeZone); - expect(zonedDateTime.year).toBe(2021); - expect(zonedDateTime.month).toBe(7); - expect(zonedDateTime.day).toBe(6); - expect(zonedDateTime.hour).toBe(0); - expect(zonedDateTime.minute).toBe(0); - expect(zonedDateTime.second).toBe(0); - expect(zonedDateTime.millisecond).toBe(0); - expect(zonedDateTime.microsecond).toBe(0); - expect(zonedDateTime.nanosecond).toBe(0); - expect(zonedDateTime.calendar).toBe(plainDate.calendar); - expect(zonedDateTime.timeZone).toBe(timeZone); - }); - - test("basic functionality - time zone like object", () => { - // 3.c. in the spec - const plainDate = new Temporal.PlainDate(2021, 7, 6); - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = plainDate.toZonedDateTime({ timeZone }); - expect(zonedDateTime.year).toBe(2021); - expect(zonedDateTime.month).toBe(7); - expect(zonedDateTime.day).toBe(6); - expect(zonedDateTime.hour).toBe(0); - expect(zonedDateTime.minute).toBe(0); - expect(zonedDateTime.second).toBe(0); - expect(zonedDateTime.millisecond).toBe(0); - expect(zonedDateTime.microsecond).toBe(0); - expect(zonedDateTime.nanosecond).toBe(0); - expect(zonedDateTime.calendar).toBe(plainDate.calendar); - expect(zonedDateTime.timeZone).toBe(timeZone); - }); - - test("basic functionality - time zone like object and plain time", () => { - // 3.c. in the spec - const plainDate = new Temporal.PlainDate(2021, 7, 6); - const plainTime = new Temporal.PlainTime(18, 14, 47, 123, 456, 789); - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = plainDate.toZonedDateTime({ timeZone, plainTime }); - expect(zonedDateTime.year).toBe(2021); - expect(zonedDateTime.month).toBe(7); - expect(zonedDateTime.day).toBe(6); - expect(zonedDateTime.hour).toBe(18); - expect(zonedDateTime.minute).toBe(14); - expect(zonedDateTime.second).toBe(47); - expect(zonedDateTime.millisecond).toBe(123); - expect(zonedDateTime.microsecond).toBe(456); - expect(zonedDateTime.nanosecond).toBe(789); - expect(zonedDateTime.calendar).toBe(plainDate.calendar); - expect(zonedDateTime.timeZone).toBe(timeZone); - }); - - test("basic functionality - time zone identifier", () => { - // 4. in the spec - const plainDate = new Temporal.PlainDate(2021, 7, 6); - const zonedDateTime = plainDate.toZonedDateTime("UTC"); - expect(zonedDateTime.year).toBe(2021); - expect(zonedDateTime.month).toBe(7); - expect(zonedDateTime.day).toBe(6); - expect(zonedDateTime.hour).toBe(0); - expect(zonedDateTime.minute).toBe(0); - expect(zonedDateTime.second).toBe(0); - expect(zonedDateTime.millisecond).toBe(0); - expect(zonedDateTime.microsecond).toBe(0); - expect(zonedDateTime.nanosecond).toBe(0); - expect(zonedDateTime.calendar).toBe(plainDate.calendar); - expect(zonedDateTime.timeZone.id).toBe("UTC"); - }); - - test("time zone fast path returns if it is passed a Temporal.TimeZone instance", () => { - const plainDate = new Temporal.PlainDate(2021, 7, 6); - - // This is obseravble via there being no property lookups (avoiding a "timeZone" property lookup in this case) - let madeObservableHasPropertyLookup = false; - class TimeZone extends Temporal.TimeZone { - constructor() { - super("UTC"); - } - - get timeZone() { - madeObservableHasPropertyLookup = true; - return this; - } - } - const timeZone = new TimeZone(); - plainDate.toZonedDateTime(timeZone); - expect(madeObservableHasPropertyLookup).toBeFalse(); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainDate object", () => { - expect(() => { - Temporal.PlainDate.prototype.toZonedDateTime.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainDate"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.until.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.until.js deleted file mode 100644 index 222af0f9263..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.until.js +++ /dev/null @@ -1,262 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.PlainDate.prototype.until).toHaveLength(1); - }); - - test("basic functionality", () => { - const dateOne = new Temporal.PlainDate(2021, 11, 14); - const dateTwo = new Temporal.PlainDate(2022, 12, 25); - const untilDuration = dateOne.until(dateTwo); - - expect(untilDuration.years).toBe(0); - expect(untilDuration.months).toBe(0); - expect(untilDuration.weeks).toBe(0); - expect(untilDuration.days).toBe(406); - expect(untilDuration.hours).toBe(0); - expect(untilDuration.minutes).toBe(0); - expect(untilDuration.seconds).toBe(0); - expect(untilDuration.milliseconds).toBe(0); - expect(untilDuration.microseconds).toBe(0); - expect(untilDuration.nanoseconds).toBe(0); - }); - - test("equal dates", () => { - const equalDateOne = new Temporal.PlainDate(1, 1, 1); - const equalDateTwo = new Temporal.PlainDate(1, 1, 1); - - const checkResults = result => { - expect(result.years).toBe(0); - expect(result.months).toBe(0); - expect(result.weeks).toBe(0); - expect(result.days).toBe(0); - expect(result.hours).toBe(0); - expect(result.minutes).toBe(0); - expect(result.seconds).toBe(0); - expect(result.milliseconds).toBe(0); - expect(result.microseconds).toBe(0); - expect(result.nanoseconds).toBe(0); - }; - - checkResults(equalDateOne.until(equalDateOne)); - checkResults(equalDateTwo.until(equalDateTwo)); - checkResults(equalDateOne.until(equalDateTwo)); - checkResults(equalDateTwo.until(equalDateOne)); - }); - - test("negative direction", () => { - const dateOne = new Temporal.PlainDate(2021, 11, 14); - const dateTwo = new Temporal.PlainDate(2022, 12, 25); - const untilDuration = dateTwo.until(dateOne); - - expect(untilDuration.years).toBe(0); - expect(untilDuration.months).toBe(0); - expect(untilDuration.weeks).toBe(0); - expect(untilDuration.days).toBe(-406); - expect(untilDuration.hours).toBe(0); - expect(untilDuration.minutes).toBe(0); - expect(untilDuration.seconds).toBe(0); - expect(untilDuration.milliseconds).toBe(0); - expect(untilDuration.microseconds).toBe(0); - expect(untilDuration.nanoseconds).toBe(0); - }); - - test("largestUnit option", () => { - const values = [ - ["year", { years: 1, months: 1, days: 11 }], - ["month", { months: 13, days: 11 }], - ["week", { weeks: 58 }], - ["day", { days: 406 }], - ]; - - const dateOne = new Temporal.PlainDate(2021, 11, 14); - const dateTwo = new Temporal.PlainDate(2022, 12, 25); - - for (const [largestUnit, durationLike] of values) { - const singularOptions = { largestUnit }; - const pluralOptions = { largestUnit: `${largestUnit}s` }; - - const propertiesToCheck = Object.keys(durationLike); - - // Positive direction - const positiveSingularResult = dateOne.until(dateTwo, singularOptions); - for (const property of propertiesToCheck) - expect(positiveSingularResult[property]).toBe(durationLike[property]); - - const positivePluralResult = dateOne.until(dateTwo, pluralOptions); - for (const property of propertiesToCheck) - expect(positivePluralResult[property]).toBe(durationLike[property]); - - // Negative direction - const negativeSingularResult = dateTwo.until(dateOne, singularOptions); - for (const property of propertiesToCheck) - expect(negativeSingularResult[property]).toBe(-durationLike[property]); - - const negativePluralResult = dateTwo.until(dateOne, pluralOptions); - for (const property of propertiesToCheck) - expect(negativePluralResult[property]).toBe(-durationLike[property]); - } - }); - - test("PlainDate string argument", () => { - const dateOne = new Temporal.PlainDate(2021, 11, 14); - const untilDuration = dateOne.until("2022-12-25"); - - expect(untilDuration.years).toBe(0); - expect(untilDuration.months).toBe(0); - expect(untilDuration.weeks).toBe(0); - expect(untilDuration.days).toBe(406); - expect(untilDuration.hours).toBe(0); - expect(untilDuration.minutes).toBe(0); - expect(untilDuration.seconds).toBe(0); - expect(untilDuration.milliseconds).toBe(0); - expect(untilDuration.microseconds).toBe(0); - expect(untilDuration.nanoseconds).toBe(0); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainDate object", () => { - expect(() => { - Temporal.PlainDate.prototype.until.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainDate"); - }); - - test("cannot compare dates from different calendars", () => { - const calendarOne = { - toString() { - return "calendarOne"; - }, - }; - - const calendarTwo = { - toString() { - return "calendarTwo"; - }, - }; - - const dateOneWithCalendar = new Temporal.PlainDate(2021, 11, 14, calendarOne); - const dateTwoWithCalendar = new Temporal.PlainDate(2022, 12, 25, calendarTwo); - - expect(() => { - dateOneWithCalendar.until(dateTwoWithCalendar); - }).toThrowWithMessage(RangeError, "Cannot compare dates from two different calendars"); - }); - - test("disallowed units", () => { - const dateOne = new Temporal.PlainDate(2021, 11, 14); - const dateTwo = new Temporal.PlainDate(2022, 12, 25); - - const disallowedUnits = [ - "hour", - "minute", - "second", - "millisecond", - "microsecond", - "nanosecond", - ]; - - for (const smallestUnit of disallowedUnits) { - const singularSmallestUnitOptions = { smallestUnit }; - const pluralSmallestUnitOptions = { smallestUnit: `${smallestUnit}s` }; - - expect(() => { - dateOne.until(dateTwo, singularSmallestUnitOptions); - }).toThrowWithMessage( - RangeError, - `${smallestUnit} is not a valid value for option smallestUnit` - ); - - expect(() => { - dateOne.until(dateTwo, pluralSmallestUnitOptions); - }).toThrowWithMessage( - RangeError, - `${smallestUnit}s is not a valid value for option smallestUnit` - ); - } - - for (const largestUnit of disallowedUnits) { - const singularLargestUnitOptions = { largestUnit }; - const pluralLargestUnitOptions = { largestUnit: `${largestUnit}s` }; - - expect(() => { - dateOne.until(dateTwo, singularLargestUnitOptions); - }).toThrowWithMessage( - RangeError, - `${largestUnit} is not a valid value for option largestUnit` - ); - - expect(() => { - dateOne.until(dateTwo, pluralLargestUnitOptions); - }).toThrowWithMessage( - RangeError, - `${largestUnit}s is not a valid value for option largestUnit` - ); - } - }); - - test("invalid unit range", () => { - // smallestUnit -> disallowed largestUnits, see validate_temporal_unit_range - // Note that all the "smallestUnits" are all the allowedUnits. - const invalidRanges = [ - ["year", ["month", "week", "day"]], - ["month", ["week", "day"]], - ["week", ["day"]], - ]; - - const dateOne = new Temporal.PlainDate(2021, 11, 14); - const dateTwo = new Temporal.PlainDate(2022, 12, 25); - - for (const [smallestUnit, disallowedLargestUnits] of invalidRanges) { - const pluralSmallestUnit = `${smallestUnit}s`; - - for (const disallowedUnit of disallowedLargestUnits) { - const pluralDisallowedUnit = `${disallowedUnit}s`; - - const singularSmallestSingularDisallowedOptions = { - smallestUnit, - largestUnit: disallowedUnit, - }; - const singularSmallestPluralDisallowedOptions = { - smallestUnit, - largestUnit: pluralDisallowedUnit, - }; - const pluralSmallestSingularDisallowedOptions = { - smallestUnit: pluralSmallestUnit, - largestUnit: disallowedUnit, - }; - const pluralSmallestPluralDisallowedOptions = { - smallestUnit: pluralSmallestUnit, - largestUnit: pluralDisallowedUnit, - }; - - expect(() => { - dateOne.until(dateTwo, singularSmallestSingularDisallowedOptions); - }).toThrowWithMessage( - RangeError, - `Invalid unit range, ${smallestUnit} is larger than ${disallowedUnit}` - ); - - expect(() => { - dateOne.until(dateTwo, singularSmallestPluralDisallowedOptions); - }).toThrowWithMessage( - RangeError, - `Invalid unit range, ${smallestUnit} is larger than ${disallowedUnit}` - ); - - expect(() => { - dateOne.until(dateTwo, pluralSmallestSingularDisallowedOptions); - }).toThrowWithMessage( - RangeError, - `Invalid unit range, ${smallestUnit} is larger than ${disallowedUnit}` - ); - - expect(() => { - dateOne.until(dateTwo, pluralSmallestPluralDisallowedOptions); - }).toThrowWithMessage( - RangeError, - `Invalid unit range, ${smallestUnit} is larger than ${disallowedUnit}` - ); - } - } - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.valueOf.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.valueOf.js deleted file mode 100644 index a3c39118ab5..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.valueOf.js +++ /dev/null @@ -1,7 +0,0 @@ -describe("errors", () => { - test("throws TypeError", () => { - expect(() => { - new Temporal.PlainDate(2021, 7, 21).valueOf(); - }).toThrowWithMessage(TypeError, "Cannot convert Temporal.PlainDate to a primitive value"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.weekOfYear.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.weekOfYear.js deleted file mode 100644 index ef9e8552ea9..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.weekOfYear.js +++ /dev/null @@ -1,14 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const date = new Temporal.PlainDate(2021, 7, 23); - expect(date.weekOfYear).toBe(29); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainDate object", () => { - expect(() => { - Reflect.get(Temporal.PlainDate.prototype, "weekOfYear", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainDate"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.with.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.with.js deleted file mode 100644 index d29c33873ce..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.with.js +++ /dev/null @@ -1,58 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.PlainDate.prototype.with).toHaveLength(1); - }); - - test("basic functionality", () => { - const plainDate = new Temporal.PlainDate(1970, 1, 1); - const values = [ - [{ year: 2021 }, new Temporal.PlainDate(2021, 1, 1)], - [{ year: 2021, month: 7 }, new Temporal.PlainDate(2021, 7, 1)], - [{ year: 2021, month: 7, day: 6 }, new Temporal.PlainDate(2021, 7, 6)], - [{ year: 2021, monthCode: "M07", day: 6 }, new Temporal.PlainDate(2021, 7, 6)], - ]; - for (const [arg, expected] of values) { - expect(plainDate.with(arg).equals(expected)).toBeTrue(); - } - - // Supplying the same values doesn't change the date, but still creates a new object - const plainDateLike = { year: plainDate.year, month: plainDate.month, day: plainDate.day }; - expect(plainDate.with(plainDateLike)).not.toBe(plainDate); - expect(plainDate.with(plainDateLike).equals(plainDate)).toBeTrue(); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainDate object", () => { - expect(() => { - Temporal.PlainDate.prototype.with.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainDate"); - }); - - test("argument must be an object", () => { - expect(() => { - new Temporal.PlainDate(1970, 1, 1).with("foo"); - }).toThrowWithMessage(TypeError, "foo is not an object"); - expect(() => { - new Temporal.PlainDate(1970, 1, 1).with(42); - }).toThrowWithMessage(TypeError, "42 is not an object"); - }); - - test("argument must have one of 'day', 'month', 'monthCode', 'year'", () => { - expect(() => { - new Temporal.PlainDate(1970, 1, 1).with({}); - }).toThrowWithMessage( - TypeError, - "Object must have at least one of the following properties: day, month, monthCode, year" - ); - }); - - test("argument must not have 'calendar' or 'timeZone'", () => { - expect(() => { - new Temporal.PlainDate(1970, 1, 1).with({ calendar: {} }); - }).toThrowWithMessage(TypeError, "Object must not have a defined calendar property"); - expect(() => { - new Temporal.PlainDate(1970, 1, 1).with({ timeZone: {} }); - }).toThrowWithMessage(TypeError, "Object must not have a defined timeZone property"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.withCalendar.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.withCalendar.js deleted file mode 100644 index 449e7089eaf..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.withCalendar.js +++ /dev/null @@ -1,13 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.PlainDate.prototype.withCalendar).toHaveLength(1); - }); - - test("basic functionality", () => { - const calendar = { hello: "friends" }; - const firstPlainDate = new Temporal.PlainDate(1, 1, 1); - expect(firstPlainDate.calendar).not.toBe(calendar); - const secondPlainDate = firstPlainDate.withCalendar(calendar); - expect(secondPlainDate.calendar).toBe(calendar); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.year.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.year.js deleted file mode 100644 index 04ed036a3f5..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.year.js +++ /dev/null @@ -1,14 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const date = new Temporal.PlainDate(2021, 7, 23); - expect(date.year).toBe(2021); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainDate object", () => { - expect(() => { - Reflect.get(Temporal.PlainDate.prototype, "year", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainDate"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.yearOfWeek.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.yearOfWeek.js deleted file mode 100644 index ab42d277914..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.yearOfWeek.js +++ /dev/null @@ -1,14 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const date = new Temporal.PlainDate(2023, 1, 1); - expect(date.yearOfWeek).toBe(2022); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainDate object", () => { - expect(() => { - Reflect.get(Temporal.PlainDate.prototype, "yearOfWeek", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainDate"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.compare.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.compare.js deleted file mode 100644 index 7eb4781f28d..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.compare.js +++ /dev/null @@ -1,13 +0,0 @@ -describe("correct behavior", () => { - test("length is 2", () => { - expect(Temporal.PlainDateTime.compare).toHaveLength(2); - }); - - test("basic functionality", () => { - const plainDateTime1 = new Temporal.PlainDateTime(2021, 8, 27, 16, 38, 40, 1, 2, 3); - expect(Temporal.PlainDateTime.compare(plainDateTime1, plainDateTime1)).toBe(0); - const plainDateTime2 = new Temporal.PlainDateTime(2021, 8, 27, 16, 39, 5, 0, 1, 2); - expect(Temporal.PlainDateTime.compare(plainDateTime1, plainDateTime2)).toBe(-1); - expect(Temporal.PlainDateTime.compare(plainDateTime2, plainDateTime1)).toBe(1); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.from.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.from.js deleted file mode 100644 index 0b70105a516..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.from.js +++ /dev/null @@ -1,198 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.PlainDateTime.from).toHaveLength(1); - }); - - test("PlainDate instance argument", () => { - const plainDate = new Temporal.PlainDate(2021, 7, 6); - const plainDateTime = Temporal.PlainDateTime.from(plainDate); - expect(plainDateTime.year).toBe(2021); - expect(plainDateTime.month).toBe(7); - expect(plainDateTime.day).toBe(6); - expect(plainDateTime.hour).toBe(0); - expect(plainDateTime.minute).toBe(0); - expect(plainDateTime.second).toBe(0); - expect(plainDateTime.millisecond).toBe(0); - expect(plainDateTime.microsecond).toBe(0); - expect(plainDateTime.nanosecond).toBe(0); - }); - - test("PlainDateTime instance argument", () => { - const plainDateTime_ = new Temporal.PlainDateTime(2021, 7, 6, 18, 14, 47); - const plainDateTime = Temporal.PlainDateTime.from(plainDateTime_); - expect(plainDateTime).not.toBe(plainDateTime_); - expect(plainDateTime.year).toBe(2021); - expect(plainDateTime.month).toBe(7); - expect(plainDateTime.day).toBe(6); - expect(plainDateTime.hour).toBe(18); - expect(plainDateTime.minute).toBe(14); - expect(plainDateTime.second).toBe(47); - expect(plainDateTime.millisecond).toBe(0); - expect(plainDateTime.microsecond).toBe(0); - expect(plainDateTime.nanosecond).toBe(0); - }); - - test("ZonedDateTime instance argument", () => { - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = new Temporal.ZonedDateTime(1625614921000000000n, timeZone); - const plainDateTime = Temporal.PlainDateTime.from(zonedDateTime); - expect(plainDateTime.year).toBe(2021); - expect(plainDateTime.month).toBe(7); - expect(plainDateTime.day).toBe(6); - expect(plainDateTime.hour).toBe(23); - expect(plainDateTime.minute).toBe(42); - expect(plainDateTime.second).toBe(1); - expect(plainDateTime.millisecond).toBe(0); - expect(plainDateTime.microsecond).toBe(0); - expect(plainDateTime.nanosecond).toBe(0); - }); - - test("fields object argument", () => { - const object = { - year: 2021, - month: 7, - day: 6, - hour: 23, - minute: 42, - second: 1, - millisecond: 0, - microsecond: 0, - nanosecond: 0, - }; - const plainDateTime = Temporal.PlainDateTime.from(object); - expect(plainDateTime.year).toBe(2021); - expect(plainDateTime.month).toBe(7); - expect(plainDateTime.day).toBe(6); - expect(plainDateTime.hour).toBe(23); - expect(plainDateTime.minute).toBe(42); - expect(plainDateTime.second).toBe(1); - expect(plainDateTime.millisecond).toBe(0); - expect(plainDateTime.microsecond).toBe(0); - expect(plainDateTime.nanosecond).toBe(0); - }); - - test("with 'constrain' overflow option", () => { - const object = { - year: 0, - month: 1, - day: 1, - hour: 24, - minute: 60, - second: 60, - millisecond: 1000, - microsecond: 1000, - nanosecond: 1000, - }; - const plainDateTime = Temporal.PlainDateTime.from(object, { overflow: "constrain" }); - expect(plainDateTime.year).toBe(0); - expect(plainDateTime.month).toBe(1); - expect(plainDateTime.day).toBe(1); - expect(plainDateTime.hour).toBe(23); - expect(plainDateTime.minute).toBe(59); - expect(plainDateTime.second).toBe(59); - expect(plainDateTime.millisecond).toBe(999); - expect(plainDateTime.microsecond).toBe(999); - expect(plainDateTime.nanosecond).toBe(999); - }); - - test("PlainDateTime string argument", () => { - const plainDateTime = Temporal.PlainDateTime.from("2021-07-06T23:42:01"); - expect(plainDateTime.year).toBe(2021); - expect(plainDateTime.month).toBe(7); - expect(plainDateTime.day).toBe(6); - expect(plainDateTime.hour).toBe(23); - expect(plainDateTime.minute).toBe(42); - expect(plainDateTime.second).toBe(1); - expect(plainDateTime.millisecond).toBe(0); - expect(plainDateTime.microsecond).toBe(0); - expect(plainDateTime.nanosecond).toBe(0); - }); -}); - -describe("errors", () => { - test("missing fields", () => { - expect(() => { - Temporal.PlainDateTime.from({}); - }).toThrowWithMessage(TypeError, "Required property day is missing or undefined"); - expect(() => { - Temporal.PlainDateTime.from({ year: 0, day: 1 }); - }).toThrowWithMessage(TypeError, "Required property month is missing or undefined"); - expect(() => { - Temporal.PlainDateTime.from({ month: 1, day: 1 }); - }).toThrowWithMessage(TypeError, "Required property year is missing or undefined"); - }); - - test("with 'reject' overflow option", () => { - const values = [ - [{ year: 1234567, month: 1, day: 1 }, "Invalid plain date"], - [{ year: 0, month: 13, day: 1 }, "Invalid plain date"], - [{ year: 0, month: 1, day: 32 }, "Invalid plain date"], - [{ year: 0, month: 1, day: 1, hour: 24 }, "Invalid plain time"], - [{ year: 0, month: 1, day: 1, hour: 0, minute: 60 }, "Invalid plain time"], - [{ year: 0, month: 1, day: 1, hour: 0, minute: 0, second: 60 }, "Invalid plain time"], - [ - { year: 0, month: 1, day: 1, hour: 0, minute: 0, second: 0, millisecond: 1000 }, - "Invalid plain time", - ], - [ - { - year: 0, - month: 1, - day: 1, - hour: 0, - minute: 0, - second: 0, - millisecond: 0, - microsecond: 1000, - }, - "Invalid plain time", - ], - [ - { - year: 0, - month: 1, - day: 1, - hour: 0, - minute: 0, - second: 0, - millisecond: 0, - microsecond: 0, - nanosecond: 1000, - }, - "Invalid plain time", - ], - ]; - for (const [object, error] of values) { - expect(() => { - Temporal.PlainDateTime.from(object, { overflow: "reject" }); - }).toThrowWithMessage(RangeError, error); - } - }); -}); - -describe("errors", () => { - test("custom time zone doesn't have a getOffsetNanosecondsFor function", () => { - const zonedDateTime = new Temporal.ZonedDateTime(0n, {}); - expect(() => { - Temporal.PlainDateTime.from(zonedDateTime); - }).toThrowWithMessage(TypeError, "getOffsetNanosecondsFor is undefined"); - }); - - test("string must not contain a UTC designator", () => { - expect(() => { - Temporal.PlainDateTime.from("2021-07-06T23:42:01Z"); - }).toThrowWithMessage( - RangeError, - "Invalid date time string '2021-07-06T23:42:01Z': must not contain a UTC designator" - ); - }); - - test("extended year must not be negative zero", () => { - expect(() => { - Temporal.PlainDateTime.from("-000000-01-01"); - }).toThrowWithMessage(RangeError, "Invalid date time string '-000000-01-01'"); - expect(() => { - Temporal.PlainDateTime.from("−000000-01-01"); // U+2212 - }).toThrowWithMessage(RangeError, "Invalid date time string '−000000-01-01'"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.js deleted file mode 100644 index 9c20964d442..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.js +++ /dev/null @@ -1,53 +0,0 @@ -describe("errors", () => { - test("called without new", () => { - expect(() => { - Temporal.PlainDateTime(); - }).toThrowWithMessage( - TypeError, - "Temporal.PlainDateTime constructor must be called with 'new'" - ); - }); - - test("cannot pass Infinity", () => { - for (let i = 0; i < 9; ++i) { - const args = Array(9).fill(0); - - args[i] = Infinity; - expect(() => { - new Temporal.PlainDateTime(...args); - }).toThrowWithMessage(RangeError, "Invalid plain date time"); - - args[i] = -Infinity; - expect(() => { - new Temporal.PlainDateTime(...args); - }).toThrowWithMessage(RangeError, "Invalid plain date time"); - } - }); - - test("cannot pass invalid ISO date or time", () => { - // NOTE: The year max value is 3 more than in the polyfill, but they incorrectly seem to - // use ISOYearMonthWithinLimits, which AFAICT isn't used for PlainDate{,Time} in the spec. - // ¯\_(ツ)_/¯ - const badValues = [275764, 0, 0, 24, 60, 60, 1000, 1000, 1000]; - for (let i = 0; i < 9; ++i) { - const args = [0, 1, 1, 0, 0, 0, 0, 0, 0]; - args[i] = badValues[i]; - expect(() => { - new Temporal.PlainDateTime(...args); - }).toThrowWithMessage(RangeError, "Invalid plain date time"); - } - }); -}); - -describe("normal behavior", () => { - test("length is 3", () => { - expect(Temporal.PlainDateTime).toHaveLength(3); - }); - - test("basic functionality", () => { - const plainDateTime = new Temporal.PlainDateTime(2021, 7, 22, 19, 46, 32, 123, 456, 789); - expect(typeof plainDateTime).toBe("object"); - expect(plainDateTime).toBeInstanceOf(Temporal.PlainDateTime); - expect(Object.getPrototypeOf(plainDateTime)).toBe(Temporal.PlainDateTime.prototype); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.@@toStringTag.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.@@toStringTag.js deleted file mode 100644 index fa9d26a5579..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.@@toStringTag.js +++ /dev/null @@ -1,3 +0,0 @@ -test("basic functionality", () => { - expect(Temporal.PlainDateTime.prototype[Symbol.toStringTag]).toBe("Temporal.PlainDateTime"); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.add.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.add.js deleted file mode 100644 index cd3252be196..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.add.js +++ /dev/null @@ -1,19 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.PlainDateTime.prototype.add).toHaveLength(1); - }); - - test("basic functionality", () => { - const plainDateTime = new Temporal.PlainDateTime(1970, 1, 1); - const result = plainDateTime.add(new Temporal.Duration(51, 6, 0, 5, 18, 14, 47)); - expect(result.equals(new Temporal.PlainDateTime(2021, 7, 6, 18, 14, 47))).toBeTrue(); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainDateTime object", () => { - expect(() => { - Temporal.PlainDateTime.prototype.add.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainDateTime"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.calendar.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.calendar.js deleted file mode 100644 index 1da7740b42d..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.calendar.js +++ /dev/null @@ -1,15 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const calendar = { hello: "friends" }; - const plainDateTime = new Temporal.PlainDateTime(0, 1, 1, 0, 0, 0, 0, 0, 0, calendar); - expect(plainDateTime.calendar).toBe(calendar); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainDateTime object", () => { - expect(() => { - Reflect.get(Temporal.PlainDateTime.prototype, "calendar", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainDateTime"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.calendarId.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.calendarId.js deleted file mode 100644 index 25e1c5cfb2a..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.calendarId.js +++ /dev/null @@ -1,15 +0,0 @@ -describe("correct behavior", () => { - test("calendarId basic functionality", () => { - const calendar = "iso8601"; - const plainDateTime = new Temporal.PlainDateTime(2000, 5, 1, 12, 30, 0, calendar); - expect(plainDateTime.calendarId).toBe("iso8601"); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainDateTime object", () => { - expect(() => { - Reflect.get(Temporal.PlainDateTime.prototype, "calendarId", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainDateTime"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.day.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.day.js deleted file mode 100644 index 7431aa0a6ee..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.day.js +++ /dev/null @@ -1,14 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const plainDateTime = new Temporal.PlainDateTime(2021, 7, 29); - expect(plainDateTime.day).toBe(29); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainDateTime object", () => { - expect(() => { - Reflect.get(Temporal.PlainDateTime.prototype, "day", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainDateTime"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.dayOfWeek.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.dayOfWeek.js deleted file mode 100644 index 4b40325b01e..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.dayOfWeek.js +++ /dev/null @@ -1,14 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const plainDateTime = new Temporal.PlainDateTime(2021, 7, 30); - expect(plainDateTime.dayOfWeek).toBe(5); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainDateTime object", () => { - expect(() => { - Reflect.get(Temporal.PlainDateTime.prototype, "dayOfWeek", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainDateTime"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.dayOfYear.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.dayOfYear.js deleted file mode 100644 index 500d2ab4188..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.dayOfYear.js +++ /dev/null @@ -1,14 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const plainDateTime = new Temporal.PlainDateTime(2021, 7, 30); - expect(plainDateTime.dayOfYear).toBe(211); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainDateTime object", () => { - expect(() => { - Reflect.get(Temporal.PlainDateTime.prototype, "dayOfYear", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainDateTime"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.daysInMonth.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.daysInMonth.js deleted file mode 100644 index 174a423ced1..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.daysInMonth.js +++ /dev/null @@ -1,14 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const plainDateTime = new Temporal.PlainDateTime(2021, 7, 30); - expect(plainDateTime.daysInMonth).toBe(31); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainDateTime object", () => { - expect(() => { - Reflect.get(Temporal.PlainDateTime.prototype, "daysInMonth", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainDateTime"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.daysInWeek.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.daysInWeek.js deleted file mode 100644 index 0d83c77587a..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.daysInWeek.js +++ /dev/null @@ -1,14 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const plainDateTime = new Temporal.PlainDateTime(2021, 7, 30); - expect(plainDateTime.daysInWeek).toBe(7); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainDateTime object", () => { - expect(() => { - Reflect.get(Temporal.PlainDateTime.prototype, "daysInWeek", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainDateTime"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.daysInYear.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.daysInYear.js deleted file mode 100644 index 27e76e8caaa..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.daysInYear.js +++ /dev/null @@ -1,14 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const plainDateTime = new Temporal.PlainDateTime(2021, 7, 30); - expect(plainDateTime.daysInYear).toBe(365); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainDateTime object", () => { - expect(() => { - Reflect.get(Temporal.PlainDateTime.prototype, "daysInYear", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainDateTime"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.equals.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.equals.js deleted file mode 100644 index 76badb443d2..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.equals.js +++ /dev/null @@ -1,13 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.PlainDateTime.prototype.equals).toHaveLength(1); - }); - - test("basic functionality", () => { - const calendar = { hello: "friends" }; - const firstPlainDateTime = new Temporal.PlainDateTime(1, 1, 1, 1, 1, 1, 1, 1, 1, calendar); - const secondPlainDateTime = new Temporal.PlainDateTime(0, 1, 1, 1, 1, 1, 1, 1, 1, calendar); - expect(firstPlainDateTime.equals(firstPlainDateTime)); - expect(!firstPlainDateTime.equals(secondPlainDateTime)); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.era.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.era.js deleted file mode 100644 index 61b3019720b..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.era.js +++ /dev/null @@ -1,24 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const plainDateTime = new Temporal.PlainDateTime(2021, 7, 6, 18, 14, 47); - expect(plainDateTime.era).toBeUndefined(); - }); - - test("calendar with custom era function", () => { - const calendar = { - era() { - return "foo"; - }, - }; - const plainDateTime = new Temporal.PlainDateTime(2021, 7, 6, 18, 14, 47, 0, 0, 0, calendar); - expect(plainDateTime.era).toBe("foo"); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainDateTime object", () => { - expect(() => { - Reflect.get(Temporal.PlainDateTime.prototype, "era", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainDateTime"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.eraYear.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.eraYear.js deleted file mode 100644 index 565bd365670..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.eraYear.js +++ /dev/null @@ -1,24 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const plainDateTime = new Temporal.PlainDateTime(2021, 7, 6, 18, 14, 47); - expect(plainDateTime.eraYear).toBeUndefined(); - }); - - test("calendar with custom eraYear function", () => { - const calendar = { - eraYear() { - return 123; - }, - }; - const plainDateTime = new Temporal.PlainDateTime(2021, 7, 6, 18, 14, 47, 0, 0, 0, calendar); - expect(plainDateTime.eraYear).toBe(123); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainDateTime object", () => { - expect(() => { - Reflect.get(Temporal.PlainDateTime.prototype, "eraYear", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainDateTime"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.getISOFields.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.getISOFields.js deleted file mode 100644 index 1204a08eb61..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.getISOFields.js +++ /dev/null @@ -1,47 +0,0 @@ -describe("normal behavior", () => { - test("length is 0", () => { - expect(Temporal.PlainDateTime.prototype.getISOFields).toHaveLength(0); - }); - - test("basic functionality", () => { - const calendar = new Temporal.Calendar("iso8601"); - const plainDateTime = new Temporal.PlainDateTime( - 2021, - 7, - 23, - 0, - 42, - 18, - 123, - 456, - 789, - calendar - ); - const fields = plainDateTime.getISOFields(); - expect(fields).toEqual({ - calendar: calendar, - isoDay: 23, - isoHour: 0, - isoMicrosecond: 456, - isoMillisecond: 123, - isoMinute: 42, - isoMonth: 7, - isoNanosecond: 789, - isoSecond: 18, - isoYear: 2021, - }); - // Test field order - expect(Object.getOwnPropertyNames(fields)).toEqual([ - "calendar", - "isoDay", - "isoHour", - "isoMicrosecond", - "isoMillisecond", - "isoMinute", - "isoMonth", - "isoNanosecond", - "isoSecond", - "isoYear", - ]); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.hour.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.hour.js deleted file mode 100644 index e9e6d52eb09..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.hour.js +++ /dev/null @@ -1,14 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const plainDateTime = new Temporal.PlainDateTime(2021, 7, 30, 1); - expect(plainDateTime.hour).toBe(1); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainDateTime object", () => { - expect(() => { - Reflect.get(Temporal.PlainDateTime.prototype, "hour", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainDateTime"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.inLeapYear.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.inLeapYear.js deleted file mode 100644 index 6e3a3d624f3..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.inLeapYear.js +++ /dev/null @@ -1,14 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const plainDateTime = new Temporal.PlainDateTime(2021, 7, 30); - expect(plainDateTime.inLeapYear).toBeFalse(); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainDateTime object", () => { - expect(() => { - Reflect.get(Temporal.PlainDateTime.prototype, "inLeapYear", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainDateTime"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.microsecond.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.microsecond.js deleted file mode 100644 index 0c117acd7d9..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.microsecond.js +++ /dev/null @@ -1,14 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const plainDateTime = new Temporal.PlainDateTime(2021, 7, 30, 1, 4, 32, 111, 420); - expect(plainDateTime.microsecond).toBe(420); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainDateTime object", () => { - expect(() => { - Reflect.get(Temporal.PlainDateTime.prototype, "microsecond", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainDateTime"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.millisecond.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.millisecond.js deleted file mode 100644 index 66b11e49222..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.millisecond.js +++ /dev/null @@ -1,14 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const plainDateTime = new Temporal.PlainDateTime(2021, 7, 30, 1, 4, 32, 111); - expect(plainDateTime.millisecond).toBe(111); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainDateTime object", () => { - expect(() => { - Reflect.get(Temporal.PlainDateTime.prototype, "millisecond", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainDateTime"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.minute.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.minute.js deleted file mode 100644 index 47bd03f8a93..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.minute.js +++ /dev/null @@ -1,14 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const plainDateTime = new Temporal.PlainDateTime(2021, 7, 30, 1, 4); - expect(plainDateTime.minute).toBe(4); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainDateTime object", () => { - expect(() => { - Reflect.get(Temporal.PlainDateTime.prototype, "minute", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainDateTime"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.month.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.month.js deleted file mode 100644 index 13043506128..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.month.js +++ /dev/null @@ -1,14 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const plainDateTime = new Temporal.PlainDateTime(2021, 7, 29); - expect(plainDateTime.month).toBe(7); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainDateTime object", () => { - expect(() => { - Reflect.get(Temporal.PlainDateTime.prototype, "month", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainDateTime"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.monthCode.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.monthCode.js deleted file mode 100644 index da755b413f7..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.monthCode.js +++ /dev/null @@ -1,14 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const plainDateTime = new Temporal.PlainDateTime(2021, 7, 29); - expect(plainDateTime.monthCode).toBe("M07"); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainDateTime object", () => { - expect(() => { - Reflect.get(Temporal.PlainDateTime.prototype, "monthCode", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainDateTime"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.monthsInYear.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.monthsInYear.js deleted file mode 100644 index 4c7167ef584..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.monthsInYear.js +++ /dev/null @@ -1,14 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const plainDateTime = new Temporal.PlainDateTime(2021, 7, 30); - expect(plainDateTime.monthsInYear).toBe(12); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainDateTime object", () => { - expect(() => { - Reflect.get(Temporal.PlainDateTime.prototype, "monthsInYear", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainDateTime"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.nanosecond.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.nanosecond.js deleted file mode 100644 index ef4cced316b..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.nanosecond.js +++ /dev/null @@ -1,14 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const plainDateTime = new Temporal.PlainDateTime(2021, 7, 30, 1, 4, 32, 111, 420, 963); - expect(plainDateTime.nanosecond).toBe(963); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainDateTime object", () => { - expect(() => { - Reflect.get(Temporal.PlainDateTime.prototype, "nanosecond", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainDateTime"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.round.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.round.js deleted file mode 100644 index 8c83877ae2e..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.round.js +++ /dev/null @@ -1,168 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.PlainDateTime.prototype.round).toHaveLength(1); - }); - - test("basic functionality", () => { - const plainDateTime = new Temporal.PlainDateTime(2021, 11, 3, 18, 8, 10, 100, 200, 300); - - const firstRoundedPlainDateTime = plainDateTime.round({ smallestUnit: "minute" }); - expect(firstRoundedPlainDateTime.year).toBe(2021); - expect(firstRoundedPlainDateTime.month).toBe(11); - expect(firstRoundedPlainDateTime.monthCode).toBe("M11"); - expect(firstRoundedPlainDateTime.day).toBe(3); - expect(firstRoundedPlainDateTime.hour).toBe(18); - expect(firstRoundedPlainDateTime.minute).toBe(8); - expect(firstRoundedPlainDateTime.second).toBe(0); - expect(firstRoundedPlainDateTime.millisecond).toBe(0); - expect(firstRoundedPlainDateTime.microsecond).toBe(0); - expect(firstRoundedPlainDateTime.nanosecond).toBe(0); - - const secondRoundedPlainDateTime = plainDateTime.round({ - smallestUnit: "minute", - roundingMode: "ceil", - }); - expect(secondRoundedPlainDateTime.year).toBe(2021); - expect(secondRoundedPlainDateTime.month).toBe(11); - expect(secondRoundedPlainDateTime.monthCode).toBe("M11"); - expect(secondRoundedPlainDateTime.day).toBe(3); - expect(secondRoundedPlainDateTime.hour).toBe(18); - expect(secondRoundedPlainDateTime.minute).toBe(9); - expect(secondRoundedPlainDateTime.second).toBe(0); - expect(secondRoundedPlainDateTime.millisecond).toBe(0); - expect(secondRoundedPlainDateTime.microsecond).toBe(0); - expect(secondRoundedPlainDateTime.nanosecond).toBe(0); - - const thirdRoundedPlainDateTime = plainDateTime.round({ - smallestUnit: "minute", - roundingMode: "ceil", - roundingIncrement: 30, - }); - expect(thirdRoundedPlainDateTime.year).toBe(2021); - expect(thirdRoundedPlainDateTime.month).toBe(11); - expect(thirdRoundedPlainDateTime.monthCode).toBe("M11"); - expect(thirdRoundedPlainDateTime.day).toBe(3); - expect(thirdRoundedPlainDateTime.hour).toBe(18); - expect(thirdRoundedPlainDateTime.minute).toBe(30); - expect(thirdRoundedPlainDateTime.second).toBe(0); - expect(thirdRoundedPlainDateTime.millisecond).toBe(0); - expect(thirdRoundedPlainDateTime.microsecond).toBe(0); - expect(thirdRoundedPlainDateTime.nanosecond).toBe(0); - - const fourthRoundedPlainDateTime = plainDateTime.round({ - smallestUnit: "minute", - roundingMode: "floor", - roundingIncrement: 30, - }); - expect(fourthRoundedPlainDateTime.year).toBe(2021); - expect(fourthRoundedPlainDateTime.month).toBe(11); - expect(fourthRoundedPlainDateTime.monthCode).toBe("M11"); - expect(fourthRoundedPlainDateTime.day).toBe(3); - expect(fourthRoundedPlainDateTime.hour).toBe(18); - expect(fourthRoundedPlainDateTime.minute).toBe(0); - expect(fourthRoundedPlainDateTime.second).toBe(0); - expect(fourthRoundedPlainDateTime.millisecond).toBe(0); - expect(fourthRoundedPlainDateTime.microsecond).toBe(0); - expect(fourthRoundedPlainDateTime.nanosecond).toBe(0); - - const fifthRoundedPlainDateTime = plainDateTime.round({ - smallestUnit: "hour", - roundingMode: "halfExpand", - roundingIncrement: 4, - }); - expect(fifthRoundedPlainDateTime.year).toBe(2021); - expect(fifthRoundedPlainDateTime.month).toBe(11); - expect(fifthRoundedPlainDateTime.monthCode).toBe("M11"); - expect(fifthRoundedPlainDateTime.day).toBe(3); - expect(fifthRoundedPlainDateTime.hour).toBe(20); - expect(fifthRoundedPlainDateTime.minute).toBe(0); - expect(fifthRoundedPlainDateTime.second).toBe(0); - expect(fifthRoundedPlainDateTime.millisecond).toBe(0); - expect(fifthRoundedPlainDateTime.microsecond).toBe(0); - expect(fifthRoundedPlainDateTime.nanosecond).toBe(0); - }); - - test("string argument is implicitly converted to options object", () => { - const plainDateTime = new Temporal.PlainDateTime(2021, 11, 3, 18, 8, 10, 100, 200, 300); - expect( - plainDateTime.round("minute").equals(plainDateTime.round({ smallestUnit: "minute" })) - ).toBeTrue(); - }); - - test("range boundary conditions", () => { - // PlainDateTime can represent a point of time ±10**8 days from the epoch. - const min = new Temporal.PlainDateTime(-271821, 4, 19, 0, 0, 0, 0, 0, 1); - const max = new Temporal.PlainDateTime(275760, 9, 13, 23, 59, 59, 999, 999, 999); - - ["day", "hour", "minute", "second", "millisecond", "microsecond"].forEach(smallestUnit => { - expect(() => { - min.round({ smallestUnit, roundingMode: "floor" }); - }).toThrow(RangeError); - expect(() => { - min.round({ smallestUnit, roundingMode: "ceil" }); - }).not.toThrow(); - - expect(() => { - max.round({ smallestUnit, roundingMode: "floor" }); - }).not.toThrow(); - expect(() => { - max.round({ smallestUnit, roundingMode: "ceil" }); - }).toThrow(RangeError); - }); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainDateTime object", () => { - expect(() => { - Temporal.PlainDateTime.prototype.round.call("foo", {}); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainDateTime"); - }); - - test("missing options object", () => { - expect(() => { - const plainDateTime = new Temporal.PlainDateTime(2021, 11, 3, 18, 8, 10, 100, 200, 300); - plainDateTime.round(); - }).toThrowWithMessage(TypeError, "Required options object is missing or undefined"); - }); - - test("invalid rounding mode", () => { - expect(() => { - const plainDateTime = new Temporal.PlainDateTime(2021, 11, 3, 18, 8, 10, 100, 200, 300); - plainDateTime.round({ smallestUnit: "second", roundingMode: "serenityOS" }); - }).toThrowWithMessage( - RangeError, - "serenityOS is not a valid value for option roundingMode" - ); - }); - - test("invalid smallest unit", () => { - expect(() => { - const plainDateTime = new Temporal.PlainDateTime(2021, 11, 3, 18, 8, 10, 100, 200, 300); - plainDateTime.round({ smallestUnit: "serenityOS" }); - }).toThrowWithMessage( - RangeError, - "serenityOS is not a valid value for option smallestUnit" - ); - }); - - test("increment may not be NaN", () => { - expect(() => { - const plainDateTime = new Temporal.PlainDateTime(2021, 11, 3, 18, 8, 10, 100, 200, 300); - plainDateTime.round({ smallestUnit: "second", roundingIncrement: NaN }); - }).toThrowWithMessage(RangeError, "NaN is not a valid value for option roundingIncrement"); - }); - - test("increment may not be smaller than 1 or larger than maximum", () => { - const plainDateTime = new Temporal.PlainDateTime(2021, 11, 3, 18, 8, 10, 100, 200, 300); - expect(() => { - plainDateTime.round({ smallestUnit: "second", roundingIncrement: -1 }); - }).toThrowWithMessage(RangeError, "-1 is not a valid value for option roundingIncrement"); - expect(() => { - plainDateTime.round({ smallestUnit: "second", roundingIncrement: 0 }); - }).toThrowWithMessage(RangeError, "0 is not a valid value for option roundingIncrement"); - expect(() => { - plainDateTime.round({ smallestUnit: "second", roundingIncrement: Infinity }); - }).toThrowWithMessage(RangeError, "inf is not a valid value for option roundingIncrement"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.second.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.second.js deleted file mode 100644 index 1becf5cfe59..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.second.js +++ /dev/null @@ -1,14 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const plainDateTime = new Temporal.PlainDateTime(2021, 7, 30, 1, 4, 32); - expect(plainDateTime.second).toBe(32); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainDateTime object", () => { - expect(() => { - Reflect.get(Temporal.PlainDateTime.prototype, "second", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainDateTime"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.since.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.since.js deleted file mode 100644 index 126925b1785..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.since.js +++ /dev/null @@ -1,99 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.PlainDateTime.prototype.since).toHaveLength(1); - }); - - test("basic functionality", () => { - const values = [ - [[0, 1, 1, 0, 0, 0, 0, 0, 0], [0, 1, 1, 0, 0, 0, 0, 0, 0], "PT0S"], - [[2, 3, 4, 5, 6, 7, 8, 9, 10], [1, 2, 3, 4, 5, 6, 7, 8, 9], "P394DT1H1M1.001001001S"], - [[1, 2, 3, 4, 5, 6, 7, 8, 9], [0, 1, 1, 0, 0, 0, 0, 0, 0], "P399DT4H5M6.007008009S"], - [[0, 1, 1, 0, 0, 0, 0, 0, 0], [1, 2, 3, 4, 5, 6, 7, 8, 9], "-P399DT4H5M6.007008009S"], - [ - [0, 12, 31, 23, 59, 59, 999, 999, 999], - [0, 1, 1, 0, 0, 0, 0, 0, 0], - "P365DT23H59M59.999999999S", - ], - [ - [0, 1, 1, 0, 0, 0, 0, 0, 0], - [0, 12, 31, 23, 59, 59, 999, 999, 999], - "-P365DT23H59M59.999999999S", - ], - ]; - for (const [args, argsOther, expected] of values) { - const plainDateTime = new Temporal.PlainDateTime(...args); - const other = new Temporal.PlainDateTime(...argsOther); - expect(plainDateTime.since(other).toString()).toBe(expected); - } - }); - - test("smallestUnit option", () => { - const plainDateTime = new Temporal.PlainDateTime(1, 2, 3, 4, 5, 6, 7, 8, 9); - const other = new Temporal.PlainDateTime(0, 1, 1, 0, 0, 0, 0, 0, 0); - const values = [ - ["year", "P1Y"], - ["month", "P13M"], - ["week", "P57W"], - ["day", "P399D"], - ["hour", "P399DT4H"], - ["minute", "P399DT4H5M"], - ["second", "P399DT4H5M6S"], - ["millisecond", "P399DT4H5M6.007S"], - ["microsecond", "P399DT4H5M6.007008S"], - ["nanosecond", "P399DT4H5M6.007008009S"], - ]; - for (const [smallestUnit, expected] of values) { - expect(plainDateTime.since(other, { smallestUnit }).toString()).toBe(expected); - } - }); - - test("largestUnit option", () => { - const plainDateTime = new Temporal.PlainDateTime(1, 2, 3, 4, 5, 6, 7, 8, 9); - const other = new Temporal.PlainDateTime(0, 1, 1, 0, 0, 0, 0, 0, 0); - const values = [ - ["year", "P1Y1M2DT4H5M6.007008009S"], - ["month", "P13M2DT4H5M6.007008009S"], - ["week", "P57WT4H5M6.007008009S"], - ["day", "P399DT4H5M6.007008009S"], - ["hour", "PT9580H5M6.007008009S"], - ["minute", "PT574805M6.007008009S"], - ["second", "PT34488306.007008009S"], - ["millisecond", "PT34488306.007008009S"], - ["microsecond", "PT34488306.007008009S"], - ["nanosecond", "PT34488306.007008008S"], - ]; - for (const [largestUnit, expected] of values) { - expect(plainDateTime.since(other, { largestUnit }).toString()).toBe(expected); - } - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainDateTime object", () => { - expect(() => { - Temporal.PlainDateTime.prototype.since.call("foo", {}); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainDateTime"); - }); - - test("cannot compare dates from different calendars", () => { - const calendarOne = { - toString() { - return "calendarOne"; - }, - }; - - const calendarTwo = { - toString() { - return "calendarTwo"; - }, - }; - - const args = [1970, 1, 1, 0, 0, 0, 0, 0, 0]; - const plainDateTimeOne = new Temporal.PlainDateTime(...args, calendarOne); - const plainDateTimeTwo = new Temporal.PlainDateTime(...args, calendarTwo); - - expect(() => { - plainDateTimeOne.since(plainDateTimeTwo); - }).toThrowWithMessage(RangeError, "Cannot compare dates from two different calendars"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.subtract.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.subtract.js deleted file mode 100644 index 8282445422c..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.subtract.js +++ /dev/null @@ -1,19 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.PlainDateTime.prototype.subtract).toHaveLength(1); - }); - - test("basic functionality", () => { - const plainDateTime = new Temporal.PlainDateTime(2021, 7, 6, 18, 14, 47); - const result = plainDateTime.subtract(new Temporal.Duration(51, 6, 0, 5, 18, 14, 47)); - expect(result.equals(new Temporal.PlainDateTime(1970, 1, 1))); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainDateTime object", () => { - expect(() => { - Temporal.PlainDateTime.prototype.subtract.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainDateTime"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.toJSON.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.toJSON.js deleted file mode 100644 index b0ce506a78d..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.toJSON.js +++ /dev/null @@ -1,18 +0,0 @@ -describe("correct behavior", () => { - test("length is 0", () => { - expect(Temporal.PlainDateTime.prototype.toJSON).toHaveLength(0); - }); - - test("basic functionality", () => { - const plainDateTime = new Temporal.PlainDateTime(2021, 11, 3, 1, 33, 5, 100, 200, 300); - expect(plainDateTime.toJSON()).toBe("2021-11-03T01:33:05.1002003"); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainDateTime object", () => { - expect(() => { - Temporal.PlainDateTime.prototype.toJSON.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainDateTime"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.toLocaleString.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.toLocaleString.js deleted file mode 100644 index 1f35fa767fe..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.toLocaleString.js +++ /dev/null @@ -1,18 +0,0 @@ -describe("correct behavior", () => { - test("length is 0", () => { - expect(Temporal.PlainDateTime.prototype.toLocaleString).toHaveLength(0); - }); - - test("basic functionality", () => { - const plainDateTime = new Temporal.PlainDateTime(2021, 11, 3, 1, 33, 5, 100, 200, 300); - expect(plainDateTime.toLocaleString()).toBe("2021-11-03T01:33:05.1002003"); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainDateTime object", () => { - expect(() => { - Temporal.PlainDateTime.prototype.toLocaleString.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainDateTime"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.toPlainDate.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.toPlainDate.js deleted file mode 100644 index 7723de2a3b3..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.toPlainDate.js +++ /dev/null @@ -1,11 +0,0 @@ -describe("normal behavior", () => { - test("length is 0", () => { - expect(Temporal.PlainDateTime.prototype.toPlainDate).toHaveLength(0); - }); - - test("basic functionality", () => { - const plainDateTime = new Temporal.PlainDateTime(2021, 7, 23, 0, 32, 18, 123, 456, 789); - const plainDate = plainDateTime.toPlainDate(); - expect(plainDate.equals(new Temporal.PlainDate(2021, 7, 23))).toBeTrue(); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.toPlainMonthDay.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.toPlainMonthDay.js deleted file mode 100644 index 6b52cdbd4f6..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.toPlainMonthDay.js +++ /dev/null @@ -1,13 +0,0 @@ -describe("correct behavior", () => { - test("length is 0", () => { - expect(Temporal.PlainDateTime.prototype.toPlainMonthDay).toHaveLength(0); - }); - - test("basic functionality", () => { - const plainDateTime = new Temporal.PlainDateTime(2021, 7, 6, 18, 14, 47); - const plainMonthDay = plainDateTime.toPlainMonthDay(); - expect(plainMonthDay.calendar).toBe(plainDateTime.calendar); - expect(plainMonthDay.monthCode).toBe("M07"); - expect(plainMonthDay.day).toBe(6); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.toPlainTime.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.toPlainTime.js deleted file mode 100644 index feb4839dc9b..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.toPlainTime.js +++ /dev/null @@ -1,16 +0,0 @@ -describe("normal behavior", () => { - test("length is 0", () => { - expect(Temporal.PlainDateTime.prototype.toPlainTime).toHaveLength(0); - }); - - test("basic functionality", () => { - const plainDateTime = new Temporal.PlainDateTime(2021, 7, 31, 0, 32, 18, 123, 456, 789); - const plainTime = plainDateTime.toPlainTime(); - expect(plainTime.hour).toBe(0); - expect(plainTime.minute).toBe(32); - expect(plainTime.second).toBe(18); - expect(plainTime.millisecond).toBe(123); - expect(plainTime.microsecond).toBe(456); - expect(plainTime.nanosecond).toBe(789); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.toPlainYearMonth.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.toPlainYearMonth.js deleted file mode 100644 index 023470357d6..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.toPlainYearMonth.js +++ /dev/null @@ -1,13 +0,0 @@ -describe("correct behavior", () => { - test("length is 0", () => { - expect(Temporal.PlainDateTime.prototype.toPlainYearMonth).toHaveLength(0); - }); - - test("basic functionality", () => { - const plainDateTime = new Temporal.PlainDateTime(2021, 7, 6, 18, 14, 47); - const plainYearMonth = plainDateTime.toPlainYearMonth(); - expect(plainYearMonth.calendar).toBe(plainDateTime.calendar); - expect(plainYearMonth.year).toBe(2021); - expect(plainYearMonth.month).toBe(7); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.toString.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.toString.js deleted file mode 100644 index c26aa854b97..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.toString.js +++ /dev/null @@ -1,113 +0,0 @@ -describe("correct behavior", () => { - test("length is 0", () => { - expect(Temporal.PlainDateTime.prototype.toString).toHaveLength(0); - }); - - test("basic functionality", () => { - const plainDateTime = new Temporal.PlainDateTime(2021, 11, 3, 1, 33, 5, 100, 200, 300); - expect(plainDateTime.toString()).toBe("2021-11-03T01:33:05.1002003"); - }); - - test("fractionalSecondDigits option", () => { - const plainDateTime = new Temporal.PlainDateTime(2021, 11, 3, 1, 33, 5, 100, 200, 300); - const values = [ - ["auto", "2021-11-03T01:33:05.1002003"], - [0, "2021-11-03T01:33:05"], - [1, "2021-11-03T01:33:05.1"], - [2, "2021-11-03T01:33:05.10"], - [3, "2021-11-03T01:33:05.100"], - [4, "2021-11-03T01:33:05.1002"], - [5, "2021-11-03T01:33:05.10020"], - [6, "2021-11-03T01:33:05.100200"], - [7, "2021-11-03T01:33:05.1002003"], - [8, "2021-11-03T01:33:05.10020030"], - [9, "2021-11-03T01:33:05.100200300"], - ]; - - for (const [fractionalSecondDigits, expected] of values) { - const options = { fractionalSecondDigits }; - expect(plainDateTime.toString(options)).toBe(expected); - } - - // Ignored when smallestUnit is given - expect(plainDateTime.toString({ smallestUnit: "minute", fractionalSecondDigits: 9 })).toBe( - "2021-11-03T01:33" - ); - }); - - test("smallestUnit option", () => { - const plainDateTime = new Temporal.PlainDateTime(2021, 11, 3, 1, 33, 5, 100, 200, 300); - const values = [ - ["minute", "2021-11-03T01:33"], - ["second", "2021-11-03T01:33:05"], - ["millisecond", "2021-11-03T01:33:05.100"], - ["microsecond", "2021-11-03T01:33:05.100200"], - ["nanosecond", "2021-11-03T01:33:05.100200300"], - ]; - - for (const [smallestUnit, expected] of values) { - const singularOptions = { smallestUnit }; - const pluralOptions = { smallestUnit: `${smallestUnit}s` }; - expect(plainDateTime.toString(singularOptions)).toBe(expected); - expect(plainDateTime.toString(pluralOptions)).toBe(expected); - } - }); - - test("doesn't call ToString on calendar if calenderName option is 'never'", () => { - let calledToString = false; - const calendar = { - toString() { - calledToString = true; - return "nocall"; - }, - }; - - const plainDateTime = new Temporal.PlainDateTime( - 2022, - 8, - 8, - 14, - 38, - 40, - 100, - 200, - 300, - calendar - ); - const options = { - calendarName: "never", - }; - expect(plainDateTime.toString(options)).toBe("2022-08-08T14:38:40.1002003"); - expect(calledToString).toBeFalse(); - }); - - test("calendarName option", () => { - const plainDateTime = new Temporal.PlainDateTime(2022, 11, 2, 19, 4, 35, 100, 200, 300); - const values = [ - ["auto", "2022-11-02T19:04:35.1002003"], - ["always", "2022-11-02T19:04:35.1002003[u-ca=iso8601]"], - ["never", "2022-11-02T19:04:35.1002003"], - ["critical", "2022-11-02T19:04:35.1002003[!u-ca=iso8601]"], - ]; - - for (const [calendarName, expected] of values) { - const options = { calendarName }; - expect(plainDateTime.toString(options)).toBe(expected); - } - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainDateTime object", () => { - expect(() => { - Temporal.PlainDateTime.prototype.toString.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainDateTime"); - }); - - test("calendarName option must be one of 'auto', 'always', 'never', 'critical'", () => { - const plainDateTime = new Temporal.PlainDateTime(2022, 11, 2, 19, 5, 40, 100, 200, 300); - expect(() => { - plainDateTime.toString({ calendarName: "foo" }); - }).toThrowWithMessage(RangeError, "foo is not a valid value for option calendarName"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.toZonedDateTime.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.toZonedDateTime.js deleted file mode 100644 index a35ce0fbe74..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.toZonedDateTime.js +++ /dev/null @@ -1,30 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.PlainDateTime.prototype.toZonedDateTime).toHaveLength(1); - }); - - test("basic functionality", () => { - const plainDateTime = new Temporal.PlainDateTime(2021, 7, 6, 18, 14, 47, 123, 456, 789); - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = plainDateTime.toZonedDateTime(timeZone); - expect(zonedDateTime.year).toBe(2021); - expect(zonedDateTime.month).toBe(7); - expect(zonedDateTime.day).toBe(6); - expect(zonedDateTime.hour).toBe(18); - expect(zonedDateTime.minute).toBe(14); - expect(zonedDateTime.second).toBe(47); - expect(zonedDateTime.millisecond).toBe(123); - expect(zonedDateTime.microsecond).toBe(456); - expect(zonedDateTime.nanosecond).toBe(789); - expect(zonedDateTime.calendar).toBe(plainDateTime.calendar); - expect(zonedDateTime.timeZone).toBe(timeZone); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainDateTime object", () => { - expect(() => { - Temporal.PlainDateTime.prototype.toZonedDateTime.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainDateTime"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.until.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.until.js deleted file mode 100644 index 2c78f64cfb6..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.until.js +++ /dev/null @@ -1,99 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.PlainDateTime.prototype.until).toHaveLength(1); - }); - - test("basic functionality", () => { - const values = [ - [[0, 1, 1, 0, 0, 0, 0, 0, 0], [0, 1, 1, 0, 0, 0, 0, 0, 0], "PT0S"], - [[1, 2, 3, 4, 5, 6, 7, 8, 9], [2, 3, 4, 5, 6, 7, 8, 9, 10], "P394DT1H1M1.001001001S"], - [[0, 1, 1, 0, 0, 0, 0, 0, 0], [1, 2, 3, 4, 5, 6, 7, 8, 9], "P399DT4H5M6.007008009S"], - [[1, 2, 3, 4, 5, 6, 7, 8, 9], [0, 1, 1, 0, 0, 0, 0, 0, 0], "-P399DT4H5M6.007008009S"], - [ - [0, 1, 1, 0, 0, 0, 0, 0, 0], - [0, 12, 31, 23, 59, 59, 999, 999, 999], - "P365DT23H59M59.999999999S", - ], - [ - [0, 12, 31, 23, 59, 59, 999, 999, 999], - [0, 1, 1, 0, 0, 0, 0, 0, 0], - "-P365DT23H59M59.999999999S", - ], - ]; - for (const [args, argsOther, expected] of values) { - const plainDateTime = new Temporal.PlainDateTime(...args); - const other = new Temporal.PlainDateTime(...argsOther); - expect(plainDateTime.until(other).toString()).toBe(expected); - } - }); - - test("smallestUnit option", () => { - const plainDateTime = new Temporal.PlainDateTime(0, 1, 1, 0, 0, 0, 0, 0, 0); - const other = new Temporal.PlainDateTime(1, 2, 3, 4, 5, 6, 7, 8, 9); - const values = [ - ["year", "P1Y"], - ["month", "P13M"], - ["week", "P57W"], - ["day", "P399D"], - ["hour", "P399DT4H"], - ["minute", "P399DT4H5M"], - ["second", "P399DT4H5M6S"], - ["millisecond", "P399DT4H5M6.007S"], - ["microsecond", "P399DT4H5M6.007008S"], - ["nanosecond", "P399DT4H5M6.007008009S"], - ]; - for (const [smallestUnit, expected] of values) { - expect(plainDateTime.until(other, { smallestUnit }).toString()).toBe(expected); - } - }); - - test("largestUnit option", () => { - const plainDateTime = new Temporal.PlainDateTime(0, 1, 1, 0, 0, 0, 0, 0, 0); - const other = new Temporal.PlainDateTime(1, 2, 3, 4, 5, 6, 7, 8, 9); - const values = [ - ["year", "P1Y1M2DT4H5M6.007008009S"], - ["month", "P13M2DT4H5M6.007008009S"], - ["week", "P57WT4H5M6.007008009S"], - ["day", "P399DT4H5M6.007008009S"], - ["hour", "PT9580H5M6.007008009S"], - ["minute", "PT574805M6.007008009S"], - ["second", "PT34488306.007008009S"], - ["millisecond", "PT34488306.007008009S"], - ["microsecond", "PT34488306.007008009S"], - ["nanosecond", "PT34488306.007008008S"], - ]; - for (const [largestUnit, expected] of values) { - expect(plainDateTime.until(other, { largestUnit }).toString()).toBe(expected); - } - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainDateTime object", () => { - expect(() => { - Temporal.PlainDateTime.prototype.until.call("foo", {}); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainDateTime"); - }); - - test("cannot compare dates from different calendars", () => { - const calendarOne = { - toString() { - return "calendarOne"; - }, - }; - - const calendarTwo = { - toString() { - return "calendarTwo"; - }, - }; - - const args = [1970, 1, 1, 0, 0, 0, 0, 0, 0]; - const plainDateTimeOne = new Temporal.PlainDateTime(...args, calendarOne); - const plainDateTimeTwo = new Temporal.PlainDateTime(...args, calendarTwo); - - expect(() => { - plainDateTimeOne.until(plainDateTimeTwo); - }).toThrowWithMessage(RangeError, "Cannot compare dates from two different calendars"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.valueOf.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.valueOf.js deleted file mode 100644 index ec9daaee505..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.valueOf.js +++ /dev/null @@ -1,10 +0,0 @@ -describe("errors", () => { - test("throws TypeError", () => { - expect(() => { - new Temporal.PlainDateTime(2021, 7, 22, 19, 54, 38).valueOf(); - }).toThrowWithMessage( - TypeError, - "Cannot convert Temporal.PlainDateTime to a primitive value" - ); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.weekOfYear.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.weekOfYear.js deleted file mode 100644 index 0e801b423be..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.weekOfYear.js +++ /dev/null @@ -1,14 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const plainDateTime = new Temporal.PlainDateTime(2021, 7, 30); - expect(plainDateTime.weekOfYear).toBe(30); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainDateTime object", () => { - expect(() => { - Reflect.get(Temporal.PlainDateTime.prototype, "weekOfYear", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainDateTime"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.with.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.with.js deleted file mode 100644 index 0bf57c6de78..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.with.js +++ /dev/null @@ -1,86 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.PlainDateTime.prototype.with).toHaveLength(1); - }); - - test("basic functionality", () => { - const plainDateTime = new Temporal.PlainDateTime(1970, 1, 1); - const values = [ - [{ year: 2021 }, new Temporal.PlainDateTime(2021, 1, 1)], - [{ year: 2021, month: 7 }, new Temporal.PlainDateTime(2021, 7, 1)], - [{ year: 2021, month: 7, day: 6 }, new Temporal.PlainDateTime(2021, 7, 6)], - [{ year: 2021, monthCode: "M07", day: 6 }, new Temporal.PlainDateTime(2021, 7, 6)], - [ - { hour: 18, minute: 14, second: 47 }, - new Temporal.PlainDateTime(1970, 1, 1, 18, 14, 47), - ], - [ - { - year: 2021, - month: 7, - day: 6, - hour: 18, - minute: 14, - second: 47, - millisecond: 123, - microsecond: 456, - nanosecond: 789, - }, - new Temporal.PlainDateTime(2021, 7, 6, 18, 14, 47, 123, 456, 789), - ], - ]; - for (const [arg, expected] of values) { - expect(plainDateTime.with(arg).equals(expected)).toBeTrue(); - } - - // Supplying the same values doesn't change the date/time, but still creates a new object - const plainDateTimeLike = { - year: plainDateTime.year, - month: plainDateTime.month, - day: plainDateTime.day, - hour: plainDateTime.hour, - minute: plainDateTime.minute, - second: plainDateTime.second, - millisecond: plainDateTime.millisecond, - microsecond: plainDateTime.microsecond, - nanosecond: plainDateTime.nanosecond, - }; - expect(plainDateTime.with(plainDateTimeLike)).not.toBe(plainDateTime); - expect(plainDateTime.with(plainDateTimeLike).equals(plainDateTime)).toBeTrue(); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainDateTime object", () => { - expect(() => { - Temporal.PlainDateTime.prototype.with.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainDateTime"); - }); - - test("argument must be an object", () => { - expect(() => { - new Temporal.PlainDateTime(1970, 1, 1).with("foo"); - }).toThrowWithMessage(TypeError, "foo is not an object"); - expect(() => { - new Temporal.PlainDateTime(1970, 1, 1).with(42); - }).toThrowWithMessage(TypeError, "42 is not an object"); - }); - - test("argument must have one of 'day', 'hour', 'microsecond', 'millisecond', 'minute', 'month', 'monthCode', 'nanosecond', 'second', 'year'", () => { - expect(() => { - new Temporal.PlainDateTime(1970, 1, 1).with({}); - }).toThrowWithMessage( - TypeError, - "Object must have at least one of the following properties: day, hour, microsecond, millisecond, minute, month, monthCode, nanosecond, second, year" - ); - }); - - test("argument must not have 'calendar' or 'timeZone'", () => { - expect(() => { - new Temporal.PlainDateTime(1970, 1, 1).with({ calendar: {} }); - }).toThrowWithMessage(TypeError, "Object must not have a defined calendar property"); - expect(() => { - new Temporal.PlainDateTime(1970, 1, 1).with({ timeZone: {} }); - }).toThrowWithMessage(TypeError, "Object must not have a defined timeZone property"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.withCalendar.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.withCalendar.js deleted file mode 100644 index f05d1de76dd..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.withCalendar.js +++ /dev/null @@ -1,13 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.PlainDateTime.prototype.withCalendar).toHaveLength(1); - }); - - test("basic functionality", () => { - const calendar = { hello: "friends" }; - const firstPlainDateTime = new Temporal.PlainDateTime(1, 2, 3); - expect(firstPlainDateTime.calendar).not.toBe(calendar); - const secondPlainDateTime = firstPlainDateTime.withCalendar(calendar); - expect(secondPlainDateTime.calendar).toBe(calendar); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.withPlainDate.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.withPlainDate.js deleted file mode 100644 index 5219379c2da..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.withPlainDate.js +++ /dev/null @@ -1,17 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.PlainDateTime.prototype.withPlainDate).toHaveLength(1); - }); - - test("basic functionality", () => { - const firstPlainDateTime = new Temporal.PlainDateTime(1, 2, 3, 4, 5, 6); - const plainDate = new Temporal.PlainDate(7, 8, 9); - const secondPlainDateTime = firstPlainDateTime.withPlainDate(plainDate); - expect(secondPlainDateTime.year).toBe(7); - expect(secondPlainDateTime.month).toBe(8); - expect(secondPlainDateTime.day).toBe(9); - expect(secondPlainDateTime.hour).toBe(4); - expect(secondPlainDateTime.minute).toBe(5); - expect(secondPlainDateTime.second).toBe(6); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.withPlainTime.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.withPlainTime.js deleted file mode 100644 index e32f675d296..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.withPlainTime.js +++ /dev/null @@ -1,20 +0,0 @@ -describe("correct behavior", () => { - test("length is 0", () => { - expect(Temporal.PlainDateTime.prototype.withPlainTime).toHaveLength(0); - }); - - test("basic functionality", () => { - const firstPlainDateTime = new Temporal.PlainDateTime(1, 2, 3, 4, 5, 6, 7, 8, 9); - const plainTime = new Temporal.PlainTime(10, 11, 12, 13, 14, 15); - const secondPlainDateTime = firstPlainDateTime.withPlainTime(plainTime); - expect(secondPlainDateTime.year).toBe(1); - expect(secondPlainDateTime.month).toBe(2); - expect(secondPlainDateTime.day).toBe(3); - expect(secondPlainDateTime.hour).toBe(10); - expect(secondPlainDateTime.minute).toBe(11); - expect(secondPlainDateTime.second).toBe(12); - expect(secondPlainDateTime.millisecond).toBe(13); - expect(secondPlainDateTime.microsecond).toBe(14); - expect(secondPlainDateTime.nanosecond).toBe(15); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.year.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.year.js deleted file mode 100644 index ae1c2f16941..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.year.js +++ /dev/null @@ -1,14 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const plainDateTime = new Temporal.PlainDateTime(2021, 7, 29); - expect(plainDateTime.year).toBe(2021); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainDateTime object", () => { - expect(() => { - Reflect.get(Temporal.PlainDateTime.prototype, "year", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainDateTime"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.yearOfWeek.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.yearOfWeek.js deleted file mode 100644 index e733bb6b26e..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.yearOfWeek.js +++ /dev/null @@ -1,14 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const plainDateTime = new Temporal.PlainDateTime(2023, 1, 1); - expect(plainDateTime.yearOfWeek).toBe(2022); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainDateTime object", () => { - expect(() => { - Reflect.get(Temporal.PlainDateTime.prototype, "yearOfWeek", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainDateTime"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainMonthDay/PlainMonthDay.from.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainMonthDay/PlainMonthDay.from.js deleted file mode 100644 index 637ef64be9d..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainMonthDay/PlainMonthDay.from.js +++ /dev/null @@ -1,138 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.PlainMonthDay.from).toHaveLength(1); - }); - - test("PlainDate instance argument", () => { - const plainDate = new Temporal.PlainDate(2021, 7, 6); - const plainMonthDay = Temporal.PlainMonthDay.from(plainDate); - expect(plainMonthDay.monthCode).toBe("M07"); - expect(plainMonthDay.day).toBe(6); - }); - - test("PlainMonthDay instance argument", () => { - const plainMonthDay_ = new Temporal.PlainMonthDay(7, 6); - const plainMonthDay = Temporal.PlainMonthDay.from(plainMonthDay_); - expect(plainMonthDay.monthCode).toBe("M07"); - expect(plainMonthDay.day).toBe(6); - }); - - test("ZonedDateTime instance argument", () => { - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = new Temporal.ZonedDateTime(1625614921000000000n, timeZone); - const plainMonthDay = Temporal.PlainMonthDay.from(zonedDateTime); - expect(plainMonthDay.monthCode).toBe("M07"); - expect(plainMonthDay.day).toBe(6); - }); - - test("fields object argument", () => { - const object = { - month: 7, - day: 6, - }; - const plainMonthDay = Temporal.PlainMonthDay.from(object); - expect(plainMonthDay.monthCode).toBe("M07"); - expect(plainMonthDay.day).toBe(6); - }); - - test("from month day string", () => { - const plainMonthDay = Temporal.PlainMonthDay.from("--07-06"); - expect(plainMonthDay.monthCode).toBe("M07"); - expect(plainMonthDay.day).toBe(6); - }); - - test("from date time string", () => { - const plainMonthDay = Temporal.PlainMonthDay.from("2021-07-06T23:42:01"); - expect(plainMonthDay.monthCode).toBe("M07"); - expect(plainMonthDay.day).toBe(6); - }); - - test("compares calendar name in month day string in lowercase", () => { - const values = [ - "02-10[u-ca=iso8601]", - "02-10[u-ca=isO8601]", - "02-10[u-ca=iSo8601]", - "02-10[u-ca=iSO8601]", - "02-10[u-ca=Iso8601]", - "02-10[u-ca=IsO8601]", - "02-10[u-ca=ISo8601]", - "02-10[u-ca=ISO8601]", - ]; - - for (const value of values) { - expect(() => { - Temporal.PlainMonthDay.from(value); - }).not.toThrowWithMessage( - RangeError, - "MM-DD string format can only be used with the iso8601 calendar" - ); - } - }); -}); - -describe("errors", () => { - test("missing fields", () => { - expect(() => { - Temporal.PlainMonthDay.from({}); - }).toThrowWithMessage(TypeError, "Required property day is missing or undefined"); - expect(() => { - Temporal.PlainMonthDay.from({ month: 1 }); - }).toThrowWithMessage(TypeError, "Required property day is missing or undefined"); - expect(() => { - Temporal.PlainMonthDay.from({ day: 1 }); - }).toThrowWithMessage(TypeError, "Required property month is missing or undefined"); - }); - - test("invalid month day string", () => { - expect(() => { - Temporal.PlainMonthDay.from("foo"); - }).toThrowWithMessage(RangeError, "Invalid month day string 'foo'"); - }); - - test("string must not contain a UTC designator", () => { - expect(() => { - Temporal.PlainMonthDay.from("2021-07-06T23:42:01Z"); - }).toThrowWithMessage( - RangeError, - "Invalid month day string '2021-07-06T23:42:01Z': must not contain a UTC designator" - ); - }); - - test("extended year must not be negative zero", () => { - expect(() => { - Temporal.PlainMonthDay.from("-000000-01-01"); - }).toThrowWithMessage(RangeError, "Invalid month day string '-000000-01-01'"); - expect(() => { - Temporal.PlainMonthDay.from("−000000-01-01"); // U+2212 - }).toThrowWithMessage(RangeError, "Invalid month day string '−000000-01-01'"); - }); - - test("can only use iso8601 calendar with month day strings", () => { - expect(() => { - Temporal.PlainMonthDay.from("02-10[u-ca=iso8602]"); - }).toThrowWithMessage( - RangeError, - "MM-DD string format can only be used with the iso8601 calendar" - ); - - expect(() => { - Temporal.PlainMonthDay.from("02-10[u-ca=SerenityOS]"); - }).toThrowWithMessage( - RangeError, - "MM-DD string format can only be used with the iso8601 calendar" - ); - }); - - test("doesn't throw non-iso8601 calendar error when using a superset format string such as DateTime", () => { - // NOTE: This will still throw, but only because "serenity" is not a recognised calendar, not because of the string format restriction. - try { - Temporal.PlainMonthDay.from("2023-02-10T22:56[u-ca=serenity]"); - } catch (e) { - expect(e).toBeInstanceOf(RangeError); - expect(e.message).not.toBe( - "MM-DD string format can only be used with the iso8601 calendar" - ); - expect(e.message).toBe("Invalid calendar identifier 'serenity'"); - } - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainMonthDay/PlainMonthDay.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainMonthDay/PlainMonthDay.js deleted file mode 100644 index 109d01e28f2..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainMonthDay/PlainMonthDay.js +++ /dev/null @@ -1,65 +0,0 @@ -describe("errors", () => { - test("called without new", () => { - expect(() => { - Temporal.PlainMonthDay(); - }).toThrowWithMessage( - TypeError, - "Temporal.PlainMonthDay constructor must be called with 'new'" - ); - }); - - test("cannot pass Infinity", () => { - expect(() => { - new Temporal.PlainMonthDay(Infinity); - }).toThrowWithMessage(RangeError, "Invalid plain month day"); - expect(() => { - new Temporal.PlainMonthDay(1, Infinity); - }).toThrowWithMessage(RangeError, "Invalid plain month day"); - expect(() => { - new Temporal.PlainMonthDay(1, 1, {}, Infinity); - }).toThrowWithMessage(RangeError, "Invalid plain month day"); - expect(() => { - new Temporal.PlainMonthDay(-Infinity); - }).toThrowWithMessage(RangeError, "Invalid plain month day"); - expect(() => { - new Temporal.PlainMonthDay(1, -Infinity); - }).toThrowWithMessage(RangeError, "Invalid plain month day"); - expect(() => { - new Temporal.PlainMonthDay(1, 1, {}, -Infinity); - }).toThrowWithMessage(RangeError, "Invalid plain month day"); - }); - - test("cannot pass invalid ISO month/day", () => { - expect(() => { - new Temporal.PlainMonthDay(0, 1); - }).toThrowWithMessage(RangeError, "Invalid plain month day"); - expect(() => { - new Temporal.PlainMonthDay(1, 0); - }).toThrowWithMessage(RangeError, "Invalid plain month day"); - }); - - test("not within iso date time limit", () => { - expect(() => { - new Temporal.PlainMonthDay(9, 30, "iso8601", 999_999_999_999_999); - }).toThrowWithMessage(RangeError, "Invalid plain month day"); - }); -}); - -describe("normal behavior", () => { - test("length is 2", () => { - expect(Temporal.PlainMonthDay).toHaveLength(2); - }); - - test("basic functionality", () => { - const plainMonthDay = new Temporal.PlainMonthDay(7, 6); - expect(typeof plainMonthDay).toBe("object"); - expect(plainMonthDay).toBeInstanceOf(Temporal.PlainMonthDay); - expect(Object.getPrototypeOf(plainMonthDay)).toBe(Temporal.PlainMonthDay.prototype); - }); - - test("default reference year is 1972", () => { - const plainMonthDay = new Temporal.PlainMonthDay(7, 6); - const fields = plainMonthDay.getISOFields(); - expect(fields.isoYear).toBe(1972); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainMonthDay/PlainMonthDay.prototype.@@toStringTag.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainMonthDay/PlainMonthDay.prototype.@@toStringTag.js deleted file mode 100644 index cfa06216dc4..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainMonthDay/PlainMonthDay.prototype.@@toStringTag.js +++ /dev/null @@ -1,3 +0,0 @@ -test("basic functionality", () => { - expect(Temporal.PlainMonthDay.prototype[Symbol.toStringTag]).toBe("Temporal.PlainMonthDay"); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainMonthDay/PlainMonthDay.prototype.calendar.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainMonthDay/PlainMonthDay.prototype.calendar.js deleted file mode 100644 index 9ab89accaf6..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainMonthDay/PlainMonthDay.prototype.calendar.js +++ /dev/null @@ -1,15 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const calendar = new Temporal.Calendar("iso8601"); - const plainMonthDay = new Temporal.PlainMonthDay(7, 6, calendar); - expect(plainMonthDay.calendar).toBe(calendar); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainMonthDay object", () => { - expect(() => { - Reflect.get(Temporal.PlainMonthDay.prototype, "calendar", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainMonthDay"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainMonthDay/PlainMonthDay.prototype.calendarId.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainMonthDay/PlainMonthDay.prototype.calendarId.js deleted file mode 100644 index 7ac8fb01c27..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainMonthDay/PlainMonthDay.prototype.calendarId.js +++ /dev/null @@ -1,15 +0,0 @@ -describe("correct behavior", () => { - test("calendarId basic functionality", () => { - const calendar = "iso8601"; - const plainMonthDay = new Temporal.PlainMonthDay(5, 1, calendar); - expect(plainMonthDay.calendarId).toBe("iso8601"); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainMonthDay object", () => { - expect(() => { - Reflect.get(Temporal.PlainMonthDay.prototype, "calendarId", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainMonthDay"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainMonthDay/PlainMonthDay.prototype.day.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainMonthDay/PlainMonthDay.prototype.day.js deleted file mode 100644 index e9807f1286f..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainMonthDay/PlainMonthDay.prototype.day.js +++ /dev/null @@ -1,14 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const plainMonthDay = new Temporal.PlainMonthDay(7, 6); - expect(plainMonthDay.day).toBe(6); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainMonthDay object", () => { - expect(() => { - Reflect.get(Temporal.PlainMonthDay.prototype, "day", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainMonthDay"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainMonthDay/PlainMonthDay.prototype.equals.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainMonthDay/PlainMonthDay.prototype.equals.js deleted file mode 100644 index 5e7d21bcb1d..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainMonthDay/PlainMonthDay.prototype.equals.js +++ /dev/null @@ -1,15 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.PlainMonthDay.prototype.equals).toHaveLength(1); - }); - - test("basic functionality", () => { - const calendar = { hello: "friends" }; - const firstPlainMonthDay = new Temporal.PlainMonthDay(2, 1, calendar); - const secondPlainMonthDay = new Temporal.PlainMonthDay(1, 1, calendar); - expect(firstPlainMonthDay.equals(firstPlainMonthDay)).toBeTrue(); - expect(secondPlainMonthDay.equals(secondPlainMonthDay)).toBeTrue(); - expect(firstPlainMonthDay.equals(secondPlainMonthDay)).toBeFalse(); - expect(secondPlainMonthDay.equals(firstPlainMonthDay)).toBeFalse(); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainMonthDay/PlainMonthDay.prototype.getISOFields.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainMonthDay/PlainMonthDay.prototype.getISOFields.js deleted file mode 100644 index 11475b5a31b..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainMonthDay/PlainMonthDay.prototype.getISOFields.js +++ /dev/null @@ -1,27 +0,0 @@ -describe("normal behavior", () => { - test("length is 0", () => { - expect(Temporal.PlainMonthDay.prototype.getISOFields).toHaveLength(0); - }); - - test("basic functionality", () => { - const calendar = new Temporal.Calendar("iso8601"); - const plainMonthDay = new Temporal.PlainMonthDay(7, 6, calendar, 2021); - const fields = plainMonthDay.getISOFields(); - expect(fields).toEqual({ calendar, isoDay: 6, isoMonth: 7, isoYear: 2021 }); - // Test field order - expect(Object.getOwnPropertyNames(fields)).toEqual([ - "calendar", - "isoDay", - "isoMonth", - "isoYear", - ]); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainMonthDay object", () => { - expect(() => { - Temporal.PlainMonthDay.prototype.getISOFields.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainMonthDay"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainMonthDay/PlainMonthDay.prototype.monthCode.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainMonthDay/PlainMonthDay.prototype.monthCode.js deleted file mode 100644 index 2943794e495..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainMonthDay/PlainMonthDay.prototype.monthCode.js +++ /dev/null @@ -1,14 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const plainMonthDay = new Temporal.PlainMonthDay(7, 6); - expect(plainMonthDay.monthCode).toBe("M07"); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainMonthDay object", () => { - expect(() => { - Reflect.get(Temporal.PlainMonthDay.prototype, "monthCode", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainMonthDay"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainMonthDay/PlainMonthDay.prototype.toJSON.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainMonthDay/PlainMonthDay.prototype.toJSON.js deleted file mode 100644 index 99cb9a93a2c..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainMonthDay/PlainMonthDay.prototype.toJSON.js +++ /dev/null @@ -1,23 +0,0 @@ -describe("correct behavior", () => { - test("length is 0", () => { - expect(Temporal.PlainMonthDay.prototype.toJSON).toHaveLength(0); - }); - - test("basic functionality", () => { - let plainMonthDay; - - plainMonthDay = new Temporal.PlainMonthDay(7, 6); - expect(plainMonthDay.toJSON()).toBe("07-06"); - - plainMonthDay = new Temporal.PlainMonthDay(7, 6, { toString: () => "foo" }, 2021); - expect(plainMonthDay.toJSON()).toBe("2021-07-06[u-ca=foo]"); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainMonthDay object", () => { - expect(() => { - Temporal.PlainMonthDay.prototype.toJSON.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainMonthDay"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainMonthDay/PlainMonthDay.prototype.toLocaleString.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainMonthDay/PlainMonthDay.prototype.toLocaleString.js deleted file mode 100644 index 6d459cc7c12..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainMonthDay/PlainMonthDay.prototype.toLocaleString.js +++ /dev/null @@ -1,23 +0,0 @@ -describe("correct behavior", () => { - test("length is 0", () => { - expect(Temporal.PlainMonthDay.prototype.toLocaleString).toHaveLength(0); - }); - - test("basic functionality", () => { - let plainMonthDay; - - plainMonthDay = new Temporal.PlainMonthDay(7, 6); - expect(plainMonthDay.toLocaleString()).toBe("07-06"); - - plainMonthDay = new Temporal.PlainMonthDay(7, 6, { toString: () => "foo" }, 2021); - expect(plainMonthDay.toLocaleString()).toBe("2021-07-06[u-ca=foo]"); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainMonthDay object", () => { - expect(() => { - Temporal.PlainMonthDay.prototype.toLocaleString.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainMonthDay"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainMonthDay/PlainMonthDay.prototype.toPlainDate.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainMonthDay/PlainMonthDay.prototype.toPlainDate.js deleted file mode 100644 index eb4942a9041..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainMonthDay/PlainMonthDay.prototype.toPlainDate.js +++ /dev/null @@ -1,27 +0,0 @@ -describe("normal behavior", () => { - test("length is 1", () => { - expect(Temporal.PlainMonthDay.prototype.toPlainDate).toHaveLength(1); - }); - - test("basic functionality", () => { - const plainMonthDay = new Temporal.PlainMonthDay(7, 6); - const plainDate = plainMonthDay.toPlainDate({ year: 2021 }); - expect(plainDate.equals(new Temporal.PlainDate(2021, 7, 6))).toBeTrue(); - }); -}); - -describe("errors", () => { - test("argument must be an object", () => { - const plainMonthDay = new Temporal.PlainMonthDay(7, 6); - expect(() => { - plainMonthDay.toPlainDate(42); - }).toThrowWithMessage(TypeError, "42 is not an object"); - }); - - test("year field is required", () => { - const plainMonthDay = new Temporal.PlainMonthDay(7, 6); - expect(() => { - plainMonthDay.toPlainDate({}); - }).toThrowWithMessage(TypeError, "Required property year is missing or undefined"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainMonthDay/PlainMonthDay.prototype.toString.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainMonthDay/PlainMonthDay.prototype.toString.js deleted file mode 100644 index 3b7be044cf0..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainMonthDay/PlainMonthDay.prototype.toString.js +++ /dev/null @@ -1,40 +0,0 @@ -describe("correct behavior", () => { - test("length is 0", () => { - expect(Temporal.PlainMonthDay.prototype.toString).toHaveLength(0); - }); - - test("basic functionality", () => { - let plainMonthDay; - - plainMonthDay = new Temporal.PlainMonthDay(7, 6); - expect(plainMonthDay.toString()).toBe("07-06"); - expect(plainMonthDay.toString({ calendarName: "auto" })).toBe("07-06"); - expect(plainMonthDay.toString({ calendarName: "always" })).toBe("1972-07-06[u-ca=iso8601]"); - expect(plainMonthDay.toString({ calendarName: "never" })).toBe("07-06"); - expect(plainMonthDay.toString({ calendarName: "critical" })).toBe( - "1972-07-06[!u-ca=iso8601]" - ); - - plainMonthDay = new Temporal.PlainMonthDay(7, 6, { toString: () => "foo" }, 2021); - expect(plainMonthDay.toString()).toBe("2021-07-06[u-ca=foo]"); - expect(plainMonthDay.toString({ calendarName: "auto" })).toBe("2021-07-06[u-ca=foo]"); - expect(plainMonthDay.toString({ calendarName: "always" })).toBe("2021-07-06[u-ca=foo]"); - expect(plainMonthDay.toString({ calendarName: "never" })).toBe("2021-07-06"); - expect(plainMonthDay.toString({ calendarName: "critical" })).toBe("2021-07-06[!u-ca=foo]"); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainMonthDay object", () => { - expect(() => { - Temporal.PlainMonthDay.prototype.toString.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainMonthDay"); - }); - - test("calendarName option must be one of 'auto', 'always', 'never', 'critical'", () => { - const plainMonthDay = new Temporal.PlainMonthDay(7, 6); - expect(() => { - plainMonthDay.toString({ calendarName: "foo" }); - }).toThrowWithMessage(RangeError, "foo is not a valid value for option calendarName"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainMonthDay/PlainMonthDay.prototype.valueOf.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainMonthDay/PlainMonthDay.prototype.valueOf.js deleted file mode 100644 index f8f48e07fc3..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainMonthDay/PlainMonthDay.prototype.valueOf.js +++ /dev/null @@ -1,11 +0,0 @@ -describe("errors", () => { - test("throws TypeError", () => { - const plainMonthDay = new Temporal.PlainMonthDay(7, 6); - expect(() => { - plainMonthDay.valueOf(); - }).toThrowWithMessage( - TypeError, - "Cannot convert Temporal.PlainMonthDay to a primitive value" - ); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainMonthDay/PlainMonthDay.prototype.with.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainMonthDay/PlainMonthDay.prototype.with.js deleted file mode 100644 index cd23e685888..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainMonthDay/PlainMonthDay.prototype.with.js +++ /dev/null @@ -1,69 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.PlainMonthDay.prototype.with).toHaveLength(1); - }); - - test("basic functionality", () => { - const plainMonthDay = new Temporal.PlainMonthDay(1, 1); - const values = [ - [{ monthCode: "M07" }, new Temporal.PlainMonthDay(7, 1)], - [{ monthCode: "M07", day: 6 }, new Temporal.PlainMonthDay(7, 6)], - [{ year: 0, month: 7, day: 6 }, new Temporal.PlainMonthDay(7, 6)], - ]; - for (const [arg, expected] of values) { - expect(plainMonthDay.with(arg).equals(expected)).toBeTrue(); - } - - // Supplying the same values doesn't change the month/day, but still creates a new object - const plainMonthDayLike = { - month: plainMonthDay.month, - day: plainMonthDay.day, - }; - expect(plainMonthDay.with(plainMonthDayLike)).not.toBe(plainMonthDay); - expect(plainMonthDay.with(plainMonthDayLike).equals(plainMonthDay)).toBeTrue(); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainMonthDay object", () => { - expect(() => { - Temporal.PlainMonthDay.prototype.with.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainMonthDay"); - }); - - test("argument must be an object", () => { - expect(() => { - new Temporal.PlainMonthDay(1, 1).with("foo"); - }).toThrowWithMessage(TypeError, "foo is not an object"); - expect(() => { - new Temporal.PlainMonthDay(1, 1).with(42); - }).toThrowWithMessage(TypeError, "42 is not an object"); - }); - - test("argument must have one of 'day', 'month', 'monthCode', 'year'", () => { - expect(() => { - new Temporal.PlainMonthDay(1, 1).with({}); - }).toThrowWithMessage( - TypeError, - "Object must have at least one of the following properties: day, month, monthCode, year" - ); - }); - - test("argument must not have 'calendar' or 'timeZone'", () => { - expect(() => { - new Temporal.PlainMonthDay(1, 1).with({ calendar: {} }); - }).toThrowWithMessage(TypeError, "Object must not have a defined calendar property"); - expect(() => { - new Temporal.PlainMonthDay(1, 1).with({ timeZone: {} }); - }).toThrowWithMessage(TypeError, "Object must not have a defined timeZone property"); - }); - - test("month property only works in combination with year", () => { - expect(() => { - new Temporal.PlainMonthDay(1, 1).with({ month: 1 }); - }).toThrowWithMessage( - TypeError, - "Required property monthCode or year is missing or undefined" - ); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.compare.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.compare.js deleted file mode 100644 index 52110cc0bde..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.compare.js +++ /dev/null @@ -1,13 +0,0 @@ -describe("correct behavior", () => { - test("length is 2", () => { - expect(Temporal.PlainTime.compare).toHaveLength(2); - }); - - test("basic functionality", () => { - const plainTime1 = new Temporal.PlainTime(16, 38, 40, 1, 2, 3); - expect(Temporal.PlainTime.compare(plainTime1, plainTime1)).toBe(0); - const plainTime2 = new Temporal.PlainTime(16, 39, 5, 0, 1, 2); - expect(Temporal.PlainTime.compare(plainTime1, plainTime2)).toBe(-1); - expect(Temporal.PlainTime.compare(plainTime2, plainTime1)).toBe(1); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.from.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.from.js deleted file mode 100644 index c88206ebc5b..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.from.js +++ /dev/null @@ -1,98 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.PlainTime.from).toHaveLength(1); - }); - - test("PlainTime instance argument", () => { - const plainTime = new Temporal.PlainTime(18, 45, 37, 1, 2, 3); - const createdPlainTime = Temporal.PlainTime.from(plainTime); - expect(createdPlainTime.hour).toBe(18); - expect(createdPlainTime.minute).toBe(45); - expect(createdPlainTime.second).toBe(37); - expect(createdPlainTime.millisecond).toBe(1); - expect(createdPlainTime.microsecond).toBe(2); - expect(createdPlainTime.nanosecond).toBe(3); - }); - - test("PlainDateTime instance argument", () => { - const plainDateTime = new Temporal.PlainDateTime(2021, 8, 27, 18, 45, 37, 1, 2, 3); - const createdPlainTime = Temporal.PlainTime.from(plainDateTime); - expect(createdPlainTime.hour).toBe(18); - expect(createdPlainTime.minute).toBe(45); - expect(createdPlainTime.second).toBe(37); - expect(createdPlainTime.millisecond).toBe(1); - expect(createdPlainTime.microsecond).toBe(2); - expect(createdPlainTime.nanosecond).toBe(3); - }); - - test("ZonedDateTime instance argument", () => { - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = new Temporal.ZonedDateTime(1627318123456789000n, timeZone); - const createdPlainTime = Temporal.PlainTime.from(zonedDateTime); - expect(createdPlainTime.hour).toBe(16); - expect(createdPlainTime.minute).toBe(48); - expect(createdPlainTime.second).toBe(43); - expect(createdPlainTime.millisecond).toBe(456); - expect(createdPlainTime.microsecond).toBe(789); - expect(createdPlainTime.nanosecond).toBe(0); - }); - - test("PlainTime string argument", () => { - const createdPlainTime = Temporal.PlainTime.from("2021-08-27T18:44:11"); - expect(createdPlainTime.hour).toBe(18); - expect(createdPlainTime.minute).toBe(44); - expect(createdPlainTime.second).toBe(11); - expect(createdPlainTime.millisecond).toBe(0); - expect(createdPlainTime.microsecond).toBe(0); - expect(createdPlainTime.nanosecond).toBe(0); - }); -}); - -describe("errors", () => { - test("custom time zone doesn't have a getOffsetNanosecondsFor function", () => { - const zonedDateTime = new Temporal.ZonedDateTime(0n, {}); - expect(() => { - Temporal.PlainTime.from(zonedDateTime); - }).toThrowWithMessage(TypeError, "getOffsetNanosecondsFor is undefined"); - }); - - test("string must not contain a UTC designator", () => { - expect(() => { - Temporal.PlainTime.from("2021-07-06T23:42:01Z"); - }).toThrowWithMessage( - RangeError, - "Invalid time string '2021-07-06T23:42:01Z': must not contain a UTC designator" - ); - }); - - test("extended year must not be negative zero", () => { - expect(() => { - Temporal.PlainTime.from("-000000-01-01T00:00:00"); - }).toThrowWithMessage(RangeError, "Invalid time string '-000000-01-01T00:00:00'"); - expect(() => { - Temporal.PlainTime.from("−000000-01-01T00:00:00"); // U+2212 - }).toThrowWithMessage(RangeError, "Invalid time string '−000000-01-01T00:00:00'"); - }); - - test("ambiguous string must contain a time designator", () => { - const values = [ - // YYYY-MM or HHMM-UU - "2021-12", - // MMDD or HHMM - "1214", - "0229", - "1130", - // MM-DD or HH-UU - "12-14", - // YYYYMM or HHMMSS - "202112", - ]; - for (const value of values) { - expect(() => { - Temporal.PlainTime.from(value); - }).toThrowWithMessage(RangeError, `Invalid time string '${value}'`); - // Doesn't throw - Temporal.PlainTime.from(`T${value}`); - } - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.js deleted file mode 100644 index bc5ccf99220..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.js +++ /dev/null @@ -1,50 +0,0 @@ -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); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.prototype.@@toStringTag.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.prototype.@@toStringTag.js deleted file mode 100644 index 016b7b14ed4..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.prototype.@@toStringTag.js +++ /dev/null @@ -1,3 +0,0 @@ -test("basic functionality", () => { - expect(Temporal.PlainTime.prototype[Symbol.toStringTag]).toBe("Temporal.PlainTime"); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.prototype.add.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.prototype.add.js deleted file mode 100644 index e5a878edf94..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.prototype.add.js +++ /dev/null @@ -1,27 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.PlainTime.prototype.add).toHaveLength(1); - }); - - test("basic functionality", () => { - const plainTime = new Temporal.PlainTime(1, 1, 1, 1, 1, 1); - const duration = new Temporal.Duration(2021, 10, 1, 1, 0, 1, 2, 3, 4, 5); - const result = plainTime.add(duration); - expect(result.hour).toBe(1); - expect(result.minute).toBe(2); - expect(result.second).toBe(3); - expect(result.millisecond).toBe(4); - expect(result.microsecond).toBe(5); - expect(result.nanosecond).toBe(6); - }); -}); - -describe("errors", () => { - test("invalid duration-like", () => { - const plainTime = new Temporal.PlainTime(1, 1, 1, 1, 1, 1); - const invalidDuration = { foo: 1, bar: 2 }; - expect(() => { - plainTime.add(invalidDuration); - }).toThrowWithMessage(TypeError, "Invalid duration-like object"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.prototype.calendar.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.prototype.calendar.js deleted file mode 100644 index 188ce77a666..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.prototype.calendar.js +++ /dev/null @@ -1,15 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const plainTime = new Temporal.PlainTime(); - expect(plainTime.calendar).toBeInstanceOf(Temporal.Calendar); - expect(plainTime.calendar.id).toBe("iso8601"); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainTime object", () => { - expect(() => { - Reflect.get(Temporal.PlainTime.prototype, "calendar", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainTime"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.prototype.equals.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.prototype.equals.js deleted file mode 100644 index 4d810b3d37f..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.prototype.equals.js +++ /dev/null @@ -1,13 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.PlainTime.prototype.equals).toHaveLength(1); - }); - - test("basic functionality", () => { - const firstPlainTime = new Temporal.PlainTime(1, 1, 1, 1, 1, 1); - const secondPlainTime = new Temporal.PlainTime(0, 1, 1, 1, 1, 1); - expect(firstPlainTime.equals(firstPlainTime)).toBeTrue(); - expect(secondPlainTime.equals(secondPlainTime)).toBeTrue(); - expect(secondPlainTime.equals(firstPlainTime)).toBeFalse(); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.prototype.getISOFields.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.prototype.getISOFields.js deleted file mode 100644 index 3a08b93bdec..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.prototype.getISOFields.js +++ /dev/null @@ -1,29 +0,0 @@ -describe("normal behavior", () => { - test("length is 0", () => { - expect(Temporal.PlainTime.prototype.getISOFields).toHaveLength(0); - }); - - test("basic functionality", () => { - const plainTime = new Temporal.PlainTime(23, 53, 18, 123, 456, 789); - const fields = plainTime.getISOFields(); - expect(fields).toEqual({ - calendar: plainTime.calendar, - isoHour: 23, - isoMicrosecond: 456, - isoMillisecond: 123, - isoMinute: 53, - isoNanosecond: 789, - isoSecond: 18, - }); - // Test field order - expect(Object.getOwnPropertyNames(fields)).toEqual([ - "calendar", - "isoHour", - "isoMicrosecond", - "isoMillisecond", - "isoMinute", - "isoNanosecond", - "isoSecond", - ]); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.prototype.hour.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.prototype.hour.js deleted file mode 100644 index 8a8533ca042..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.prototype.hour.js +++ /dev/null @@ -1,14 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const plainTime = new Temporal.PlainTime(12); - expect(plainTime.hour).toBe(12); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainTime object", () => { - expect(() => { - Reflect.get(Temporal.PlainTime.prototype, "hour", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainTime"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.prototype.microsecond.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.prototype.microsecond.js deleted file mode 100644 index ad550b82ccd..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.prototype.microsecond.js +++ /dev/null @@ -1,14 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const plainTime = new Temporal.PlainTime(0, 0, 0, 0, 12); - expect(plainTime.microsecond).toBe(12); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainTime object", () => { - expect(() => { - Reflect.get(Temporal.PlainTime.prototype, "microsecond", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainTime"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.prototype.millisecond.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.prototype.millisecond.js deleted file mode 100644 index dee6507992a..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.prototype.millisecond.js +++ /dev/null @@ -1,14 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const plainTime = new Temporal.PlainTime(0, 0, 0, 12); - expect(plainTime.millisecond).toBe(12); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainTime object", () => { - expect(() => { - Reflect.get(Temporal.PlainTime.prototype, "millisecond", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainTime"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.prototype.minute.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.prototype.minute.js deleted file mode 100644 index c3f39842d8b..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.prototype.minute.js +++ /dev/null @@ -1,14 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const plainTime = new Temporal.PlainTime(0, 12); - expect(plainTime.minute).toBe(12); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainTime object", () => { - expect(() => { - Reflect.get(Temporal.PlainTime.prototype, "minute", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainTime"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.prototype.nanosecond.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.prototype.nanosecond.js deleted file mode 100644 index ef7c9b9ed91..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.prototype.nanosecond.js +++ /dev/null @@ -1,14 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const plainTime = new Temporal.PlainTime(0, 0, 0, 0, 0, 12); - expect(plainTime.nanosecond).toBe(12); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainTime object", () => { - expect(() => { - Reflect.get(Temporal.PlainTime.prototype, "nanosecond", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainTime"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.prototype.round.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.prototype.round.js deleted file mode 100644 index 6c7e32ffe32..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.prototype.round.js +++ /dev/null @@ -1,144 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.PlainTime.prototype.round).toHaveLength(1); - }); - - test("basic functionality", () => { - const plainTime = new Temporal.PlainTime(18, 15, 9, 100, 200, 300); - - const firstRoundedPlainTime = plainTime.round({ smallestUnit: "minute" }); - expect(firstRoundedPlainTime.hour).toBe(18); - expect(firstRoundedPlainTime.minute).toBe(15); - expect(firstRoundedPlainTime.second).toBe(0); - expect(firstRoundedPlainTime.millisecond).toBe(0); - expect(firstRoundedPlainTime.microsecond).toBe(0); - expect(firstRoundedPlainTime.nanosecond).toBe(0); - - const secondRoundedPlainTime = plainTime.round({ - smallestUnit: "minute", - roundingMode: "ceil", - }); - expect(secondRoundedPlainTime.hour).toBe(18); - expect(secondRoundedPlainTime.minute).toBe(16); - expect(secondRoundedPlainTime.second).toBe(0); - expect(secondRoundedPlainTime.millisecond).toBe(0); - expect(secondRoundedPlainTime.microsecond).toBe(0); - expect(secondRoundedPlainTime.nanosecond).toBe(0); - - const thirdRoundedPlainTime = plainTime.round({ - smallestUnit: "minute", - roundingMode: "ceil", - roundingIncrement: 30, - }); - expect(thirdRoundedPlainTime.hour).toBe(18); - expect(thirdRoundedPlainTime.minute).toBe(30); - expect(thirdRoundedPlainTime.second).toBe(0); - expect(thirdRoundedPlainTime.millisecond).toBe(0); - expect(thirdRoundedPlainTime.microsecond).toBe(0); - expect(thirdRoundedPlainTime.nanosecond).toBe(0); - - const fourthRoundedPlainTime = plainTime.round({ - smallestUnit: "minute", - roundingMode: "floor", - roundingIncrement: 30, - }); - expect(fourthRoundedPlainTime.hour).toBe(18); - expect(fourthRoundedPlainTime.minute).toBe(0); - expect(fourthRoundedPlainTime.second).toBe(0); - expect(fourthRoundedPlainTime.millisecond).toBe(0); - expect(fourthRoundedPlainTime.microsecond).toBe(0); - expect(fourthRoundedPlainTime.nanosecond).toBe(0); - - const fifthRoundedPlainTime = plainTime.round({ - smallestUnit: "hour", - roundingMode: "halfExpand", - roundingIncrement: 4, - }); - expect(fifthRoundedPlainTime.hour).toBe(20); - expect(fifthRoundedPlainTime.minute).toBe(0); - expect(fifthRoundedPlainTime.second).toBe(0); - expect(fifthRoundedPlainTime.millisecond).toBe(0); - expect(fifthRoundedPlainTime.microsecond).toBe(0); - expect(fifthRoundedPlainTime.nanosecond).toBe(0); - }); - - test("string argument is implicitly converted to options object", () => { - const plainTime = new Temporal.PlainTime(18, 15, 9, 100, 200, 300); - expect( - plainTime.round("minute").equals(plainTime.round({ smallestUnit: "minute" })) - ).toBeTrue(); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainTime object", () => { - expect(() => { - Temporal.PlainTime.prototype.round.call("foo", {}); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainTime"); - }); - - test("missing options object", () => { - expect(() => { - const plainTime = new Temporal.PlainTime(18, 15, 9, 100, 200, 300); - plainTime.round(); - }).toThrowWithMessage(TypeError, "Required options object is missing or undefined"); - }); - - test("invalid rounding mode", () => { - expect(() => { - const plainTime = new Temporal.PlainTime(18, 15, 9, 100, 200, 300); - plainTime.round({ smallestUnit: "second", roundingMode: "serenityOS" }); - }).toThrowWithMessage( - RangeError, - "serenityOS is not a valid value for option roundingMode" - ); - }); - - test("invalid smallest unit", () => { - expect(() => { - const plainTime = new Temporal.PlainTime(18, 15, 9, 100, 200, 300); - plainTime.round({ smallestUnit: "serenityOS" }); - }).toThrowWithMessage( - RangeError, - "serenityOS is not a valid value for option smallestUnit" - ); - }); - - test("increment may not be NaN", () => { - expect(() => { - const plainTime = new Temporal.PlainTime(18, 15, 9, 100, 200, 300); - plainTime.round({ smallestUnit: "second", roundingIncrement: NaN }); - }).toThrowWithMessage(RangeError, "NaN is not a valid value for option roundingIncrement"); - }); - - test("increment may not be smaller than 1 or larger than maximum", () => { - const plainTime = new Temporal.PlainTime(18, 15, 9, 100, 200, 300); - expect(() => { - plainTime.round({ smallestUnit: "second", roundingIncrement: -1 }); - }).toThrowWithMessage(RangeError, "-1 is not a valid value for option roundingIncrement"); - expect(() => { - plainTime.round({ smallestUnit: "second", roundingIncrement: 0 }); - }).toThrowWithMessage(RangeError, "0 is not a valid value for option roundingIncrement"); - expect(() => { - plainTime.round({ smallestUnit: "second", roundingIncrement: Infinity }); - }).toThrowWithMessage(RangeError, "inf is not a valid value for option roundingIncrement"); - expect(() => { - plainTime.round({ smallestUnit: "hours", roundingIncrement: 24 }); - }).toThrowWithMessage(RangeError, "24 is not a valid value for option roundingIncrement"); - expect(() => { - plainTime.round({ smallestUnit: "minutes", roundingIncrement: 60 }); - }).toThrowWithMessage(RangeError, "60 is not a valid value for option roundingIncrement"); - expect(() => { - plainTime.round({ smallestUnit: "seconds", roundingIncrement: 60 }); - }).toThrowWithMessage(RangeError, "60 is not a valid value for option roundingIncrement"); - expect(() => { - plainTime.round({ smallestUnit: "milliseconds", roundingIncrement: 1000 }); - }).toThrowWithMessage(RangeError, "1000 is not a valid value for option roundingIncrement"); - expect(() => { - plainTime.round({ smallestUnit: "microseconds", roundingIncrement: 1000 }); - }).toThrowWithMessage(RangeError, "1000 is not a valid value for option roundingIncrement"); - expect(() => { - plainTime.round({ smallestUnit: "nanoseconds", roundingIncrement: 1000 }); - }).toThrowWithMessage(RangeError, "1000 is not a valid value for option roundingIncrement"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.prototype.second.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.prototype.second.js deleted file mode 100644 index b0687ee5719..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.prototype.second.js +++ /dev/null @@ -1,14 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const plainTime = new Temporal.PlainTime(0, 0, 12); - expect(plainTime.second).toBe(12); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainTime object", () => { - expect(() => { - Reflect.get(Temporal.PlainTime.prototype, "second", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainTime"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.prototype.since.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.prototype.since.js deleted file mode 100644 index 134ef2961de..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.prototype.since.js +++ /dev/null @@ -1,89 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.PlainTime.prototype.since).toHaveLength(1); - }); - - test("basic functionality", () => { - const values = [ - [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], "PT0S"], - [[2, 3, 4, 5, 6, 7], [1, 2, 3, 4, 5, 6], "PT1H1M1.001001001S"], - [[1, 2, 3, 4, 5, 6], [0, 0, 0, 0, 0, 0], "PT1H2M3.004005006S"], - [[0, 0, 0, 0, 0, 0], [1, 2, 3, 4, 5, 6], "-PT1H2M3.004005006S"], - [[23, 59, 59, 999, 999, 999], [0, 0, 0, 0, 0, 0], "PT23H59M59.999999999S"], - [[0, 0, 0, 0, 0, 0], [23, 59, 59, 999, 999, 999], "-PT23H59M59.999999999S"], - ]; - for (const [args, argsOther, expected] of values) { - const plainTime = new Temporal.PlainTime(...args); - const other = new Temporal.PlainTime(...argsOther); - expect(plainTime.since(other).toString()).toBe(expected); - } - }); - - test("smallestUnit option", () => { - const plainTime = new Temporal.PlainTime(1, 2, 3, 4, 5, 6); - const other = new Temporal.PlainTime(0, 0, 0, 0, 0, 0); - const values = [ - ["hour", "PT1H"], - ["minute", "PT1H2M"], - ["second", "PT1H2M3S"], - ["millisecond", "PT1H2M3.004S"], - ["microsecond", "PT1H2M3.004005S"], - ["nanosecond", "PT1H2M3.004005006S"], - ]; - for (const [smallestUnit, expected] of values) { - expect(plainTime.since(other, { smallestUnit }).toString()).toBe(expected); - } - }); - - test("largestUnit option", () => { - const plainTime = new Temporal.PlainTime(1, 2, 3, 4, 5, 6); - const other = new Temporal.PlainTime(0, 0, 0, 0, 0, 0); - const values = [ - ["hour", "PT1H2M3.004005006S"], - ["minute", "PT62M3.004005006S"], - ["second", "PT3723.004005006S"], - ["millisecond", "PT3723.004005006S"], - ["microsecond", "PT3723.004005006S"], - ["nanosecond", "PT3723.004005006S"], - ]; - for (const [largestUnit, expected] of values) { - expect(plainTime.since(other, { largestUnit }).toString()).toBe(expected); - } - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainTime object", () => { - expect(() => { - Temporal.PlainTime.prototype.since.call("foo", {}); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainTime"); - }); - - test("disallowed smallestUnit option values", () => { - const values = ["year", "month", "week", "day"]; - for (const smallestUnit of values) { - const plainTime = new Temporal.PlainTime(); - const other = new Temporal.PlainTime(); - expect(() => { - plainTime.since(other, { smallestUnit }); - }).toThrowWithMessage( - RangeError, - `${smallestUnit} is not a valid value for option smallestUnit` - ); - } - }); - - test("disallowed largestUnit option values", () => { - const values = ["year", "month", "week", "day"]; - for (const largestUnit of values) { - const plainTime = new Temporal.PlainTime(); - const other = new Temporal.PlainTime(); - expect(() => { - plainTime.since(other, { largestUnit }); - }).toThrowWithMessage( - RangeError, - `${largestUnit} is not a valid value for option largestUnit` - ); - } - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.prototype.subtract.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.prototype.subtract.js deleted file mode 100644 index 973d0e59ef1..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.prototype.subtract.js +++ /dev/null @@ -1,27 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.PlainTime.prototype.subtract).toHaveLength(1); - }); - - test("basic functionality", () => { - const plainTime = new Temporal.PlainTime(1, 2, 3, 4, 5, 6); - const duration = new Temporal.Duration(2021, 10, 1, 1, 0, 1, 2, 3, 4, 5); - const result = plainTime.subtract(duration); - expect(result.hour).toBe(1); - expect(result.minute).toBe(1); - expect(result.second).toBe(1); - expect(result.millisecond).toBe(1); - expect(result.microsecond).toBe(1); - expect(result.nanosecond).toBe(1); - }); -}); - -describe("errors", () => { - test("invalid duration-like", () => { - const plainTime = new Temporal.PlainTime(1, 1, 1, 1, 1, 1); - const invalidDuration = { foo: 1, bar: 2 }; - expect(() => { - plainTime.subtract(invalidDuration); - }).toThrowWithMessage(TypeError, "Invalid duration-like object"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.prototype.toJSON.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.prototype.toJSON.js deleted file mode 100644 index 2a94c3d2b3a..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.prototype.toJSON.js +++ /dev/null @@ -1,18 +0,0 @@ -describe("correct behavior", () => { - test("length is 0", () => { - expect(Temporal.PlainTime.prototype.toJSON).toHaveLength(0); - }); - - test("basic functionality", () => { - const plainTime = new Temporal.PlainTime(18, 14, 47, 123, 456, 789); - expect(plainTime.toJSON()).toBe("18:14:47.123456789"); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainTime object", () => { - expect(() => { - Temporal.PlainTime.prototype.toJSON.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainTime"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.prototype.toLocaleString.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.prototype.toLocaleString.js deleted file mode 100644 index f0b2ab1a0b0..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.prototype.toLocaleString.js +++ /dev/null @@ -1,18 +0,0 @@ -describe("correct behavior", () => { - test("length is 0", () => { - expect(Temporal.PlainTime.prototype.toLocaleString).toHaveLength(0); - }); - - test("basic functionality", () => { - const plainTime = new Temporal.PlainTime(18, 14, 47, 123, 456, 789); - expect(plainTime.toLocaleString()).toBe("18:14:47.123456789"); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainTime object", () => { - expect(() => { - Temporal.PlainTime.prototype.toLocaleString.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainTime"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.prototype.toPlainDateTime.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.prototype.toPlainDateTime.js deleted file mode 100644 index 3584caa7d94..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.prototype.toPlainDateTime.js +++ /dev/null @@ -1,20 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.PlainTime.prototype.toPlainDateTime).toHaveLength(1); - }); - - test("basic functionality", () => { - const plainDate = new Temporal.PlainDate(2021, 7, 29); - const plainTime = new Temporal.PlainTime(23, 45, 12, 1, 2, 3); - const plainDateTime = plainTime.toPlainDateTime(plainDate); - expect(plainDateTime.year).toBe(2021); - expect(plainDateTime.month).toBe(7); - expect(plainDateTime.day).toBe(29); - expect(plainDateTime.hour).toBe(23); - expect(plainDateTime.minute).toBe(45); - expect(plainDateTime.second).toBe(12); - expect(plainDateTime.millisecond).toBe(1); - expect(plainDateTime.microsecond).toBe(2); - expect(plainDateTime.nanosecond).toBe(3); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.prototype.toString.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.prototype.toString.js deleted file mode 100644 index 3f5ccd9fa8c..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.prototype.toString.js +++ /dev/null @@ -1,59 +0,0 @@ -describe("correct behavior", () => { - test("length is 0", () => { - expect(Temporal.PlainTime.prototype.toString).toHaveLength(0); - }); - - test("basic functionality", () => { - const plainTime = new Temporal.PlainTime(18, 14, 47, 123, 456, 789); - expect(plainTime.toString()).toBe("18:14:47.123456789"); - }); - - test("fractionalSecondDigits option", () => { - const plainTime = new Temporal.PlainTime(18, 14, 47, 123, 456); - const values = [ - ["auto", "18:14:47.123456"], - [0, "18:14:47"], - [1, "18:14:47.1"], - [2, "18:14:47.12"], - [3, "18:14:47.123"], - [4, "18:14:47.1234"], - [5, "18:14:47.12345"], - [6, "18:14:47.123456"], - [7, "18:14:47.1234560"], - [8, "18:14:47.12345600"], - [9, "18:14:47.123456000"], - ]; - for (const [fractionalSecondDigits, expected] of values) { - const options = { fractionalSecondDigits }; - expect(plainTime.toString(options)).toBe(expected); - } - - // Ignored when smallestUnit is given - expect(plainTime.toString({ smallestUnit: "minute", fractionalSecondDigits: 9 })).toBe( - "18:14" - ); - }); - - test("smallestUnit option", () => { - const plainTime = new Temporal.PlainTime(18, 14, 47, 123, 456, 789); - const values = [ - ["minute", "18:14"], - ["second", "18:14:47"], - ["millisecond", "18:14:47.123"], - ["microsecond", "18:14:47.123456"], - ["nanosecond", "18:14:47.123456789"], - ]; - for (const [smallestUnit, expected] of values) { - const options = { smallestUnit }; - expect(plainTime.toString(options)).toBe(expected); - } - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainTime object", () => { - expect(() => { - Temporal.PlainTime.prototype.toString.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainTime"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.prototype.toZonedDateTime.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.prototype.toZonedDateTime.js deleted file mode 100644 index ebbc50937b7..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.prototype.toZonedDateTime.js +++ /dev/null @@ -1,55 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.PlainTime.prototype.toZonedDateTime).toHaveLength(1); - }); - - test("basic functionality", () => { - const plainTime = new Temporal.PlainTime(18, 14, 47, 123, 456, 789); - const plainDate = new Temporal.PlainDate(2021, 7, 6); - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = plainTime.toZonedDateTime({ plainDate, timeZone }); - expect(zonedDateTime.year).toBe(2021); - expect(zonedDateTime.month).toBe(7); - expect(zonedDateTime.day).toBe(6); - expect(zonedDateTime.hour).toBe(18); - expect(zonedDateTime.minute).toBe(14); - expect(zonedDateTime.second).toBe(47); - expect(zonedDateTime.millisecond).toBe(123); - expect(zonedDateTime.microsecond).toBe(456); - expect(zonedDateTime.nanosecond).toBe(789); - expect(zonedDateTime.calendar).toBe(plainDate.calendar); - expect(zonedDateTime.timeZone).toBe(timeZone); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainTime object", () => { - expect(() => { - Temporal.PlainTime.prototype.toZonedDateTime.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainTime"); - }); - - test("item argument must be an object", () => { - const plainTime = new Temporal.PlainTime(); - for (const value of [123, NaN, Infinity, true, false, null, undefined]) { - expect(() => { - plainTime.toZonedDateTime(value); - }).toThrowWithMessage(TypeError, `${value} is not an object`); - } - }); - - test("item argument must have a 'plainDate' property", () => { - const plainTime = new Temporal.PlainTime(); - expect(() => { - plainTime.toZonedDateTime({}); - }).toThrowWithMessage(TypeError, "Required property plainDate is missing or undefined"); - }); - - test("item argument must have a 'timeZone' property", () => { - const plainDate = new Temporal.PlainDate(1970, 1, 1); - const plainTime = new Temporal.PlainTime(); - expect(() => { - plainTime.toZonedDateTime({ plainDate }); - }).toThrowWithMessage(TypeError, "Required property timeZone is missing or undefined"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.prototype.until.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.prototype.until.js deleted file mode 100644 index 57923f76304..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.prototype.until.js +++ /dev/null @@ -1,89 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.PlainTime.prototype.until).toHaveLength(1); - }); - - test("basic functionality", () => { - const values = [ - [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], "PT0S"], - [[1, 2, 3, 4, 5, 6], [2, 3, 4, 5, 6, 7], "PT1H1M1.001001001S"], - [[0, 0, 0, 0, 0, 0], [1, 2, 3, 4, 5, 6], "PT1H2M3.004005006S"], - [[1, 2, 3, 4, 5, 6], [0, 0, 0, 0, 0, 0], "-PT1H2M3.004005006S"], - [[0, 0, 0, 0, 0, 0], [23, 59, 59, 999, 999, 999], "PT23H59M59.999999999S"], - [[23, 59, 59, 999, 999, 999], [0, 0, 0, 0, 0, 0], "-PT23H59M59.999999999S"], - ]; - for (const [args, argsOther, expected] of values) { - const plainTime = new Temporal.PlainTime(...args); - const other = new Temporal.PlainTime(...argsOther); - expect(plainTime.until(other).toString()).toBe(expected); - } - }); - - test("smallestUnit option", () => { - const plainTime = new Temporal.PlainTime(0, 0, 0, 0, 0, 0); - const other = new Temporal.PlainTime(1, 2, 3, 4, 5, 6); - const values = [ - ["hour", "PT1H"], - ["minute", "PT1H2M"], - ["second", "PT1H2M3S"], - ["millisecond", "PT1H2M3.004S"], - ["microsecond", "PT1H2M3.004005S"], - ["nanosecond", "PT1H2M3.004005006S"], - ]; - for (const [smallestUnit, expected] of values) { - expect(plainTime.until(other, { smallestUnit }).toString()).toBe(expected); - } - }); - - test("largestUnit option", () => { - const plainTime = new Temporal.PlainTime(0, 0, 0, 0, 0, 0); - const other = new Temporal.PlainTime(1, 2, 3, 4, 5, 6); - const values = [ - ["hour", "PT1H2M3.004005006S"], - ["minute", "PT62M3.004005006S"], - ["second", "PT3723.004005006S"], - ["millisecond", "PT3723.004005006S"], - ["microsecond", "PT3723.004005006S"], - ["nanosecond", "PT3723.004005006S"], - ]; - for (const [largestUnit, expected] of values) { - expect(plainTime.until(other, { largestUnit }).toString()).toBe(expected); - } - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainTime object", () => { - expect(() => { - Temporal.PlainTime.prototype.until.call("foo", {}); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainTime"); - }); - - test("disallowed smallestUnit option values", () => { - const values = ["year", "month", "week", "day"]; - for (const smallestUnit of values) { - const plainTime = new Temporal.PlainTime(); - const other = new Temporal.PlainTime(); - expect(() => { - plainTime.until(other, { smallestUnit }); - }).toThrowWithMessage( - RangeError, - `${smallestUnit} is not a valid value for option smallestUnit` - ); - } - }); - - test("disallowed largestUnit option values", () => { - const values = ["year", "month", "week", "day"]; - for (const largestUnit of values) { - const plainTime = new Temporal.PlainTime(); - const other = new Temporal.PlainTime(); - expect(() => { - plainTime.until(other, { largestUnit }); - }).toThrowWithMessage( - RangeError, - `${largestUnit} is not a valid value for option largestUnit` - ); - } - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.prototype.valueOf.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.prototype.valueOf.js deleted file mode 100644 index 71a1988d106..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.prototype.valueOf.js +++ /dev/null @@ -1,7 +0,0 @@ -describe("errors", () => { - test("throws TypeError", () => { - expect(() => { - new Temporal.PlainTime(19, 54, 38).valueOf(); - }).toThrowWithMessage(TypeError, "Cannot convert Temporal.PlainTime to a primitive value"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.prototype.with.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.prototype.with.js deleted file mode 100644 index f2c38e57ec6..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.prototype.with.js +++ /dev/null @@ -1,216 +0,0 @@ -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 behavior", () => { - 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, "Object 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, "Object 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 an object of type Temporal.PlainTime"); - }); - - 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, - "Object must have at least one of the following properties: hour, microsecond, millisecond, minute, nanosecond, second" - ); - expect(() => { - new Temporal.PlainTime().with({ foo: 1, bar: 2 }); - }).toThrowWithMessage( - TypeError, - "Object must have at least one of the following properties: hour, microsecond, millisecond, minute, nanosecond, second" - ); - }); - - 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, "Object must not have a defined calendar property"); - expect(() => { - new Temporal.PlainTime().with({ - calendar: 1, - }); - }).toThrowWithMessage(TypeError, "Object 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, "Object must not have a defined timeZone property"); - expect(() => { - new Temporal.PlainTime().with({ - timeZone: 1, - }); - }).toThrowWithMessage(TypeError, "Object 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, - "Object 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, - "Object must not have a defined calendar or timeZone property" - ); - } - - expect(() => { - new Temporal.PlainTime().with(new Temporal.ZonedDateTime(1n, {})); - }).toThrowWithMessage( - TypeError, - "Object must not have a defined calendar or timeZone property" - ); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.compare.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.compare.js deleted file mode 100644 index 789845e8d2e..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.compare.js +++ /dev/null @@ -1,14 +0,0 @@ -describe("correct behavior", () => { - test("length is 2", () => { - expect(Temporal.PlainYearMonth.compare).toHaveLength(2); - }); - - test("basic functionality", () => { - const plainYearMonth1 = new Temporal.PlainYearMonth(2021, 8); - expect(Temporal.PlainYearMonth.compare(plainYearMonth1, plainYearMonth1)).toBe(0); - const plainYearMonth2 = new Temporal.PlainYearMonth(2021, 9); - expect(Temporal.PlainYearMonth.compare(plainYearMonth2, plainYearMonth2)).toBe(0); - expect(Temporal.PlainYearMonth.compare(plainYearMonth1, plainYearMonth2)).toBe(-1); - expect(Temporal.PlainYearMonth.compare(plainYearMonth2, plainYearMonth1)).toBe(1); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.from.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.from.js deleted file mode 100644 index ec4102b0fcb..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.from.js +++ /dev/null @@ -1,164 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.PlainYearMonth.from).toHaveLength(1); - }); - - test("PlainDate instance argument", () => { - const plainDate = new Temporal.PlainDate(2021, 7, 6); - const plainYearMonth = Temporal.PlainYearMonth.from(plainDate); - expect(plainYearMonth.year).toBe(2021); - expect(plainYearMonth.month).toBe(7); - expect(plainYearMonth.monthCode).toBe("M07"); - expect(plainYearMonth.daysInYear).toBe(365); - expect(plainYearMonth.daysInMonth).toBe(31); - expect(plainYearMonth.monthsInYear).toBe(12); - expect(plainYearMonth.inLeapYear).toBeFalse(); - }); - - test("PlainYearMonth instance argument", () => { - const plainYearMonth_ = new Temporal.PlainYearMonth(2021, 7); - const plainYearMonth = Temporal.PlainYearMonth.from(plainYearMonth_); - expect(plainYearMonth.year).toBe(2021); - expect(plainYearMonth.month).toBe(7); - expect(plainYearMonth.monthCode).toBe("M07"); - expect(plainYearMonth.daysInYear).toBe(365); - expect(plainYearMonth.daysInMonth).toBe(31); - expect(plainYearMonth.monthsInYear).toBe(12); - expect(plainYearMonth.inLeapYear).toBeFalse(); - }); - - test("ZonedDateTime instance argument", () => { - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = new Temporal.ZonedDateTime(1625614921000000000n, timeZone); - const plainYearMonth = Temporal.PlainYearMonth.from(zonedDateTime); - expect(plainYearMonth.year).toBe(2021); - expect(plainYearMonth.month).toBe(7); - expect(plainYearMonth.monthCode).toBe("M07"); - expect(plainYearMonth.daysInYear).toBe(365); - expect(plainYearMonth.daysInMonth).toBe(31); - expect(plainYearMonth.monthsInYear).toBe(12); - expect(plainYearMonth.inLeapYear).toBeFalse(); - }); - - test("fields object argument", () => { - const object = { - year: 2021, - month: 7, - }; - const plainYearMonth = Temporal.PlainYearMonth.from(object); - expect(plainYearMonth.year).toBe(2021); - expect(plainYearMonth.month).toBe(7); - expect(plainYearMonth.monthCode).toBe("M07"); - expect(plainYearMonth.daysInYear).toBe(365); - expect(plainYearMonth.daysInMonth).toBe(31); - expect(plainYearMonth.monthsInYear).toBe(12); - expect(plainYearMonth.inLeapYear).toBeFalse(); - }); - - test("from year month string", () => { - const plainYearMonth = Temporal.PlainYearMonth.from("2021-07"); - expect(plainYearMonth.year).toBe(2021); - expect(plainYearMonth.month).toBe(7); - expect(plainYearMonth.monthCode).toBe("M07"); - }); - - test("from date time string", () => { - const plainYearMonth = Temporal.PlainYearMonth.from("2021-07-06T23:42:01"); - expect(plainYearMonth.year).toBe(2021); - expect(plainYearMonth.month).toBe(7); - expect(plainYearMonth.monthCode).toBe("M07"); - expect(plainYearMonth.daysInYear).toBe(365); - expect(plainYearMonth.daysInMonth).toBe(31); - expect(plainYearMonth.monthsInYear).toBe(12); - expect(plainYearMonth.inLeapYear).toBeFalse(); - }); - - test("compares calendar name in year month string in lowercase", () => { - const values = [ - "2023-02[u-ca=iso8601]", - "2023-02[u-ca=isO8601]", - "2023-02[u-ca=iSo8601]", - "2023-02[u-ca=iSO8601]", - "2023-02[u-ca=Iso8601]", - "2023-02[u-ca=IsO8601]", - "2023-02[u-ca=ISo8601]", - "2023-02[u-ca=ISO8601]", - ]; - - for (const value of values) { - expect(() => { - Temporal.PlainYearMonth.from(value); - }).not.toThrowWithMessage( - RangeError, - "YYYY-MM string format can only be used with the iso8601 calendar" - ); - } - }); -}); - -describe("errors", () => { - test("missing fields", () => { - expect(() => { - Temporal.PlainYearMonth.from({}); - }).toThrowWithMessage(TypeError, "Required property year is missing or undefined"); - expect(() => { - Temporal.PlainYearMonth.from({ year: 0 }); - }).toThrowWithMessage(TypeError, "Required property month is missing or undefined"); - expect(() => { - Temporal.PlainYearMonth.from({ month: 1 }); - }).toThrowWithMessage(TypeError, "Required property year is missing or undefined"); - }); - - test("invalid year month string", () => { - expect(() => { - Temporal.PlainYearMonth.from("foo"); - }).toThrowWithMessage(RangeError, "Invalid year month string 'foo'"); - }); - - test("string must not contain a UTC designator", () => { - expect(() => { - Temporal.PlainYearMonth.from("2021-07-06T23:42:01Z"); - }).toThrowWithMessage( - RangeError, - "Invalid year month string '2021-07-06T23:42:01Z': must not contain a UTC designator" - ); - }); - - test("extended year must not be negative zero", () => { - expect(() => { - Temporal.PlainYearMonth.from("-000000-01"); - }).toThrowWithMessage(RangeError, "Invalid year month string '-000000-01'"); - expect(() => { - Temporal.PlainYearMonth.from("−000000-01"); // U+2212 - }).toThrowWithMessage(RangeError, "Invalid year month string '−000000-01'"); - }); - - test("can only use iso8601 calendar with year month strings", () => { - expect(() => { - Temporal.PlainYearMonth.from("2023-02[u-ca=iso8602]"); - }).toThrowWithMessage( - RangeError, - "YYYY-MM string format can only be used with the iso8601 calendar" - ); - - expect(() => { - Temporal.PlainYearMonth.from("2023-02[u-ca=SerenityOS]"); - }).toThrowWithMessage( - RangeError, - "YYYY-MM string format can only be used with the iso8601 calendar" - ); - }); - - test("doesn't throw non-iso8601 calendar error when using a superset format string such as DateTime", () => { - // NOTE: This will still throw, but only because "serenity" is not a recognised calendar, not because of the string format restriction. - try { - Temporal.PlainYearMonth.from("2023-02-10T22:57[u-ca=serenity]"); - } catch (e) { - expect(e).toBeInstanceOf(RangeError); - expect(e.message).not.toBe( - "MM-DD string format can only be used with the iso8601 calendar" - ); - expect(e.message).toBe("Invalid calendar identifier 'serenity'"); - } - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.js deleted file mode 100644 index 2212cebd747..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.js +++ /dev/null @@ -1,59 +0,0 @@ -describe("errors", () => { - test("called without new", () => { - expect(() => { - Temporal.PlainYearMonth(); - }).toThrowWithMessage( - TypeError, - "Temporal.PlainYearMonth constructor must be called with 'new'" - ); - }); - - test("cannot pass Infinity", () => { - expect(() => { - new Temporal.PlainYearMonth(Infinity); - }).toThrowWithMessage(RangeError, "Invalid plain year month"); - expect(() => { - new Temporal.PlainYearMonth(0, Infinity); - }).toThrowWithMessage(RangeError, "Invalid plain year month"); - expect(() => { - new Temporal.PlainYearMonth(0, 1, {}, Infinity); - }).toThrowWithMessage(RangeError, "Invalid plain year month"); - expect(() => { - new Temporal.PlainYearMonth(-Infinity); - }).toThrowWithMessage(RangeError, "Invalid plain year month"); - expect(() => { - new Temporal.PlainYearMonth(0, -Infinity); - }).toThrowWithMessage(RangeError, "Invalid plain year month"); - expect(() => { - new Temporal.PlainYearMonth(0, 1, {}, -Infinity); - }).toThrowWithMessage(RangeError, "Invalid plain year month"); - }); - - test("cannot pass invalid ISO month/day", () => { - expect(() => { - new Temporal.PlainYearMonth(0, 0); - }).toThrowWithMessage(RangeError, "Invalid plain year month"); - expect(() => { - new Temporal.PlainYearMonth(0, 1, {}, 0); - }).toThrowWithMessage(RangeError, "Invalid plain year month"); - }); -}); - -describe("normal behavior", () => { - test("length is 2", () => { - expect(Temporal.PlainYearMonth).toHaveLength(2); - }); - - test("basic functionality", () => { - const plainYearMonth = new Temporal.PlainYearMonth(2021, 7); - expect(typeof plainYearMonth).toBe("object"); - expect(plainYearMonth).toBeInstanceOf(Temporal.PlainYearMonth); - expect(Object.getPrototypeOf(plainYearMonth)).toBe(Temporal.PlainYearMonth.prototype); - }); - - test("default reference day is 1", () => { - const plainYearMonth = new Temporal.PlainYearMonth(2021, 7); - const fields = plainYearMonth.getISOFields(); - expect(fields.isoDay).toBe(1); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.prototype.@@toStringTag.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.prototype.@@toStringTag.js deleted file mode 100644 index 65296d77b21..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.prototype.@@toStringTag.js +++ /dev/null @@ -1,3 +0,0 @@ -test("basic functionality", () => { - expect(Temporal.PlainYearMonth.prototype[Symbol.toStringTag]).toBe("Temporal.PlainYearMonth"); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.prototype.add.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.prototype.add.js deleted file mode 100644 index 27f7396efb0..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.prototype.add.js +++ /dev/null @@ -1,19 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.PlainYearMonth.prototype.add).toHaveLength(1); - }); - - test("basic functionality", () => { - const plainYearMonth = new Temporal.PlainYearMonth(1970, 1); - const result = plainYearMonth.add(new Temporal.Duration(51, 6)); - expect(result.equals(new Temporal.PlainYearMonth(2021, 7))).toBeTrue(); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainYearMonth object", () => { - expect(() => { - Temporal.PlainYearMonth.prototype.add.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainYearMonth"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.prototype.calendar.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.prototype.calendar.js deleted file mode 100644 index a5e31c04cf1..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.prototype.calendar.js +++ /dev/null @@ -1,15 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const calendar = new Temporal.Calendar("iso8601"); - const plainYearMonth = new Temporal.PlainYearMonth(2021, 7, calendar); - expect(plainYearMonth.calendar).toBe(calendar); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainYearMonth object", () => { - expect(() => { - Reflect.get(Temporal.PlainYearMonth.prototype, "calendar", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainYearMonth"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.prototype.calendarId.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.prototype.calendarId.js deleted file mode 100644 index 800f2413e51..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.prototype.calendarId.js +++ /dev/null @@ -1,15 +0,0 @@ -describe("correct behavior", () => { - test("calendarId basic functionality", () => { - const calendar = "iso8601"; - const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar); - expect(plainYearMonth.calendarId).toBe("iso8601"); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainYearMonth object", () => { - expect(() => { - Reflect.get(Temporal.PlainYearMonth.prototype, "calendarId", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainYearMonth"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.prototype.daysInMonth.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.prototype.daysInMonth.js deleted file mode 100644 index 59c07055d41..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.prototype.daysInMonth.js +++ /dev/null @@ -1,14 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const plainYearMonth = new Temporal.PlainYearMonth(2021, 7); - expect(plainYearMonth.daysInMonth).toBe(31); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainYearMonth object", () => { - expect(() => { - Reflect.get(Temporal.PlainYearMonth.prototype, "daysInMonth", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainYearMonth"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.prototype.daysInYear.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.prototype.daysInYear.js deleted file mode 100644 index a0a114902f7..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.prototype.daysInYear.js +++ /dev/null @@ -1,14 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const plainYearMonth = new Temporal.PlainYearMonth(2021, 7); - expect(plainYearMonth.daysInYear).toBe(365); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainYearMonth object", () => { - expect(() => { - Reflect.get(Temporal.PlainYearMonth.prototype, "daysInYear", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainYearMonth"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.prototype.equals.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.prototype.equals.js deleted file mode 100644 index d3b6aa22eca..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.prototype.equals.js +++ /dev/null @@ -1,15 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.PlainYearMonth.prototype.equals).toHaveLength(1); - }); - - test("basic functionality", () => { - const calendar = { hello: "friends" }; - const firstPlainDateTime = new Temporal.PlainYearMonth(1, 1, calendar); - const secondPlainDateTime = new Temporal.PlainYearMonth(0, 1, calendar); - expect(firstPlainDateTime.equals(firstPlainDateTime)).toBeTrue(); - expect(secondPlainDateTime.equals(secondPlainDateTime)).toBeTrue(); - expect(firstPlainDateTime.equals(secondPlainDateTime)).toBeFalse(); - expect(secondPlainDateTime.equals(firstPlainDateTime)).toBeFalse(); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.prototype.era.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.prototype.era.js deleted file mode 100644 index f3ccc9a5a82..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.prototype.era.js +++ /dev/null @@ -1,24 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const plainYearMonth = new Temporal.PlainYearMonth(2021, 7); - expect(plainYearMonth.era).toBeUndefined(); - }); - - test("calendar with custom era function", () => { - const calendar = { - era() { - return "foo"; - }, - }; - const plainYearMonth = new Temporal.PlainYearMonth(2021, 7, calendar); - expect(plainYearMonth.era).toBe("foo"); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainYearMonth object", () => { - expect(() => { - Reflect.get(Temporal.PlainYearMonth.prototype, "era", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainYearMonth"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.prototype.eraYear.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.prototype.eraYear.js deleted file mode 100644 index 88effcb4ccf..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.prototype.eraYear.js +++ /dev/null @@ -1,24 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const plainYearMonth = new Temporal.PlainYearMonth(2021, 7); - expect(plainYearMonth.eraYear).toBeUndefined(); - }); - - test("calendar with custom eraYear function", () => { - const calendar = { - eraYear() { - return 123; - }, - }; - const plainYearMonth = new Temporal.PlainYearMonth(2021, 7, calendar); - expect(plainYearMonth.eraYear).toBe(123); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainYearMonth object", () => { - expect(() => { - Reflect.get(Temporal.PlainYearMonth.prototype, "eraYear", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainYearMonth"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.prototype.getISOFields.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.prototype.getISOFields.js deleted file mode 100644 index be42ba9c894..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.prototype.getISOFields.js +++ /dev/null @@ -1,27 +0,0 @@ -describe("normal behavior", () => { - test("length is 0", () => { - expect(Temporal.PlainYearMonth.prototype.getISOFields).toHaveLength(0); - }); - - test("basic functionality", () => { - const calendar = new Temporal.Calendar("iso8601"); - const plainYearMonth = new Temporal.PlainYearMonth(2021, 7, calendar, 6); - const fields = plainYearMonth.getISOFields(); - expect(fields).toEqual({ calendar, isoDay: 6, isoMonth: 7, isoYear: 2021 }); - // Test field order - expect(Object.getOwnPropertyNames(fields)).toEqual([ - "calendar", - "isoDay", - "isoMonth", - "isoYear", - ]); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainYearMonth object", () => { - expect(() => { - Temporal.PlainYearMonth.prototype.getISOFields.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainYearMonth"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.prototype.inLeapYear.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.prototype.inLeapYear.js deleted file mode 100644 index f79e77e7bda..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.prototype.inLeapYear.js +++ /dev/null @@ -1,14 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const plainYearMonth = new Temporal.PlainYearMonth(2021, 7); - expect(plainYearMonth.inLeapYear).toBe(false); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainYearMonth object", () => { - expect(() => { - Reflect.get(Temporal.PlainYearMonth.prototype, "inLeapYear", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainYearMonth"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.prototype.month.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.prototype.month.js deleted file mode 100644 index 8c09f11cbe8..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.prototype.month.js +++ /dev/null @@ -1,14 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const plainYearMonth = new Temporal.PlainYearMonth(2021, 7); - expect(plainYearMonth.month).toBe(7); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainYearMonth object", () => { - expect(() => { - Reflect.get(Temporal.PlainYearMonth.prototype, "month", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainYearMonth"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.prototype.monthCode.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.prototype.monthCode.js deleted file mode 100644 index 8fdd1852dae..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.prototype.monthCode.js +++ /dev/null @@ -1,14 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const plainYearMonth = new Temporal.PlainYearMonth(2021, 7); - expect(plainYearMonth.monthCode).toBe("M07"); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainYearMonth object", () => { - expect(() => { - Reflect.get(Temporal.PlainYearMonth.prototype, "monthCode", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainYearMonth"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.prototype.monthsInYear.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.prototype.monthsInYear.js deleted file mode 100644 index 6ca5f84084a..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.prototype.monthsInYear.js +++ /dev/null @@ -1,14 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const plainYearMonth = new Temporal.PlainYearMonth(2021, 7); - expect(plainYearMonth.monthsInYear).toBe(12); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainYearMonth object", () => { - expect(() => { - Reflect.get(Temporal.PlainYearMonth.prototype, "monthsInYear", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainYearMonth"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.prototype.since.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.prototype.since.js deleted file mode 100644 index a012dca4dde..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.prototype.since.js +++ /dev/null @@ -1,120 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.PlainYearMonth.prototype.since).toHaveLength(1); - }); - - test("basic functionality", () => { - const values = [ - [[0, 1], [0, 1], "PT0S"], - [[2, 3], [1, 2], "P1Y1M"], - [[1, 2], [0, 1], "P1Y1M"], - [[0, 1], [1, 2], "-P1Y1M"], - [[0, 12], [0, 1], "P11M"], - [[0, 1], [0, 12], "-P11M"], - ]; - for (const [args, argsOther, expected] of values) { - const plainYearMonth = new Temporal.PlainYearMonth(...args); - const other = new Temporal.PlainYearMonth(...argsOther); - expect(plainYearMonth.since(other).toString()).toBe(expected); - } - }); - - test("smallestUnit option", () => { - const plainYearMonth = new Temporal.PlainYearMonth(1, 2); - const other = new Temporal.PlainYearMonth(0, 1); - const values = [ - ["year", "P1Y"], - ["month", "P1Y1M"], - ]; - for (const [smallestUnit, expected] of values) { - expect(plainYearMonth.since(other, { smallestUnit }).toString()).toBe(expected); - } - }); - - test("largestUnit option", () => { - const plainYearMonth = new Temporal.PlainYearMonth(1, 2); - const other = new Temporal.PlainYearMonth(0, 1); - const values = [ - ["year", "P1Y1M"], - ["month", "P13M"], - ]; - for (const [largestUnit, expected] of values) { - expect(plainYearMonth.since(other, { largestUnit }).toString()).toBe(expected); - } - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainYearMonth object", () => { - expect(() => { - Temporal.PlainYearMonth.prototype.since.call("foo", {}); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainYearMonth"); - }); - - test("disallowed smallestUnit option values", () => { - const values = [ - "week", - "day", - "hour", - "minute", - "second", - "millisecond", - "microsecond", - "nanosecond", - ]; - for (const smallestUnit of values) { - const plainYearMonth = new Temporal.PlainYearMonth(1970, 1); - const other = new Temporal.PlainYearMonth(1970, 1); - expect(() => { - plainYearMonth.since(other, { smallestUnit }); - }).toThrowWithMessage( - RangeError, - `${smallestUnit} is not a valid value for option smallestUnit` - ); - } - }); - - test("disallowed largestUnit option values", () => { - const values = [ - "week", - "day", - "hour", - "minute", - "second", - "millisecond", - "microsecond", - "nanosecond", - ]; - for (const largestUnit of values) { - const plainYearMonth = new Temporal.PlainYearMonth(1970, 1); - const other = new Temporal.PlainYearMonth(1970, 1); - expect(() => { - plainYearMonth.since(other, { largestUnit }); - }).toThrowWithMessage( - RangeError, - `${largestUnit} is not a valid value for option largestUnit` - ); - } - }); - - test("cannot compare dates from different calendars", () => { - const calendarOne = { - toString() { - return "calendarOne"; - }, - }; - - const calendarTwo = { - toString() { - return "calendarTwo"; - }, - }; - - const plainYearMonthOne = new Temporal.PlainYearMonth(1970, 1, calendarOne); - const plainYearMonthTwo = new Temporal.PlainYearMonth(1970, 1, calendarTwo); - - expect(() => { - plainYearMonthOne.since(plainYearMonthTwo); - }).toThrowWithMessage(RangeError, "Cannot compare dates from two different calendars"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.prototype.subtract.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.prototype.subtract.js deleted file mode 100644 index 1c04a95cca4..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.prototype.subtract.js +++ /dev/null @@ -1,19 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.PlainYearMonth.prototype.subtract).toHaveLength(1); - }); - - test("basic functionality", () => { - const plainYearMonth = new Temporal.PlainYearMonth(2021, 7); - const result = plainYearMonth.subtract(new Temporal.Duration(51, 6)); - expect(result.equals(new Temporal.PlainYearMonth(1970, 1))).toBeTrue(); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainYearMonth object", () => { - expect(() => { - Temporal.PlainYearMonth.prototype.subtract.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainYearMonth"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.prototype.toJSON.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.prototype.toJSON.js deleted file mode 100644 index 88251a82594..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.prototype.toJSON.js +++ /dev/null @@ -1,23 +0,0 @@ -describe("correct behavior", () => { - test("length is 0", () => { - expect(Temporal.PlainYearMonth.prototype.toJSON).toHaveLength(0); - }); - - test("basic functionality", () => { - let plainYearMonth; - - plainYearMonth = new Temporal.PlainYearMonth(2021, 7); - expect(plainYearMonth.toJSON()).toBe("2021-07"); - - plainYearMonth = new Temporal.PlainYearMonth(2021, 7, { toString: () => "foo" }, 6); - expect(plainYearMonth.toJSON()).toBe("2021-07-06[u-ca=foo]"); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainYearMonth object", () => { - expect(() => { - Temporal.PlainYearMonth.prototype.toJSON.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainYearMonth"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.prototype.toLocaleString.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.prototype.toLocaleString.js deleted file mode 100644 index d3832b2bda7..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.prototype.toLocaleString.js +++ /dev/null @@ -1,23 +0,0 @@ -describe("correct behavior", () => { - test("length is 0", () => { - expect(Temporal.PlainYearMonth.prototype.toLocaleString).toHaveLength(0); - }); - - test("basic functionality", () => { - let plainYearMonth; - - plainYearMonth = new Temporal.PlainYearMonth(2021, 7); - expect(plainYearMonth.toLocaleString()).toBe("2021-07"); - - plainYearMonth = new Temporal.PlainYearMonth(2021, 7, { toString: () => "foo" }, 6); - expect(plainYearMonth.toLocaleString()).toBe("2021-07-06[u-ca=foo]"); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainYearMonth object", () => { - expect(() => { - Temporal.PlainYearMonth.prototype.toLocaleString.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainYearMonth"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.prototype.toPlainDate.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.prototype.toPlainDate.js deleted file mode 100644 index cf0f945da7b..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.prototype.toPlainDate.js +++ /dev/null @@ -1,27 +0,0 @@ -describe("normal behavior", () => { - test("length is 1", () => { - expect(Temporal.PlainYearMonth.prototype.toPlainDate).toHaveLength(1); - }); - - test("basic functionality", () => { - const plainYearMonth = new Temporal.PlainYearMonth(2021, 7); - const plainDate = plainYearMonth.toPlainDate({ day: 6 }); - expect(plainDate.equals(new Temporal.PlainDate(2021, 7, 6))).toBeTrue(); - }); -}); - -describe("errors", () => { - test("argument must be an object", () => { - const plainYearMonth = new Temporal.PlainYearMonth(2021, 7); - expect(() => { - plainYearMonth.toPlainDate(42); - }).toThrowWithMessage(TypeError, "42 is not an object"); - }); - - test("day field is required", () => { - const plainYearMonth = new Temporal.PlainYearMonth(2021, 7); - expect(() => { - plainYearMonth.toPlainDate({}); - }).toThrowWithMessage(TypeError, "Required property day is missing or undefined"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.prototype.toString.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.prototype.toString.js deleted file mode 100644 index 5ad78a4f804..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.prototype.toString.js +++ /dev/null @@ -1,60 +0,0 @@ -describe("correct behavior", () => { - test("length is 0", () => { - expect(Temporal.PlainYearMonth.prototype.toString).toHaveLength(0); - }); - - test("basic functionality", () => { - let plainYearMonth; - - plainYearMonth = new Temporal.PlainYearMonth(2021, 7); - expect(plainYearMonth.toString()).toBe("2021-07"); - expect(plainYearMonth.toString({ calendarName: "auto" })).toBe("2021-07"); - expect(plainYearMonth.toString({ calendarName: "always" })).toBe( - "2021-07-01[u-ca=iso8601]" - ); - expect(plainYearMonth.toString({ calendarName: "never" })).toBe("2021-07"); - expect(plainYearMonth.toString({ calendarName: "critical" })).toBe( - "2021-07-01[!u-ca=iso8601]" - ); - - plainYearMonth = new Temporal.PlainYearMonth(2021, 7, { toString: () => "foo" }, 6); - expect(plainYearMonth.toString()).toBe("2021-07-06[u-ca=foo]"); - expect(plainYearMonth.toString({ calendarName: "auto" })).toBe("2021-07-06[u-ca=foo]"); - expect(plainYearMonth.toString({ calendarName: "always" })).toBe("2021-07-06[u-ca=foo]"); - expect(plainYearMonth.toString({ calendarName: "never" })).toBe("2021-07-06"); - expect(plainYearMonth.toString({ calendarName: "critical" })).toBe("2021-07-06[!u-ca=foo]"); - - plainYearMonth = new Temporal.PlainYearMonth(0, 1); - expect(plainYearMonth.toString()).toBe("0000-01"); - - plainYearMonth = new Temporal.PlainYearMonth(999, 1); - expect(plainYearMonth.toString()).toBe("0999-01"); - - plainYearMonth = new Temporal.PlainYearMonth(9999, 1); - expect(plainYearMonth.toString()).toBe("9999-01"); - - plainYearMonth = new Temporal.PlainYearMonth(12345, 1); - expect(plainYearMonth.toString()).toBe("+012345-01"); - - plainYearMonth = new Temporal.PlainYearMonth(123456, 1); - expect(plainYearMonth.toString()).toBe("+123456-01"); - - plainYearMonth = new Temporal.PlainYearMonth(-12345, 1); - expect(plainYearMonth.toString()).toBe("-012345-01"); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainYearMonth object", () => { - expect(() => { - Temporal.PlainYearMonth.prototype.toString.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainYearMonth"); - }); - - test("calendarName option must be one of 'auto', 'always', 'never', 'critical'", () => { - const plainYearMonth = new Temporal.PlainYearMonth(2021, 7); - expect(() => { - plainYearMonth.toString({ calendarName: "foo" }); - }).toThrowWithMessage(RangeError, "foo is not a valid value for option calendarName"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.prototype.until.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.prototype.until.js deleted file mode 100644 index 1ee71514ced..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.prototype.until.js +++ /dev/null @@ -1,120 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.PlainYearMonth.prototype.until).toHaveLength(1); - }); - - test("basic functionality", () => { - const values = [ - [[0, 1], [0, 1], "PT0S"], - [[1, 2], [2, 3], "P1Y1M"], - [[0, 1], [1, 2], "P1Y1M"], - [[1, 2], [0, 1], "-P1Y1M"], - [[0, 1], [0, 12], "P11M"], - [[0, 12], [0, 1], "-P11M"], - ]; - for (const [args, argsOther, expected] of values) { - const plainYearMonth = new Temporal.PlainYearMonth(...args); - const other = new Temporal.PlainYearMonth(...argsOther); - expect(plainYearMonth.until(other).toString()).toBe(expected); - } - }); - - test("smallestUnit option", () => { - const plainYearMonth = new Temporal.PlainYearMonth(0, 1); - const other = new Temporal.PlainYearMonth(1, 2); - const values = [ - ["year", "P1Y"], - ["month", "P1Y1M"], - ]; - for (const [smallestUnit, expected] of values) { - expect(plainYearMonth.until(other, { smallestUnit }).toString()).toBe(expected); - } - }); - - test("largestUnit option", () => { - const plainYearMonth = new Temporal.PlainYearMonth(0, 1); - const other = new Temporal.PlainYearMonth(1, 2); - const values = [ - ["year", "P1Y1M"], - ["month", "P13M"], - ]; - for (const [largestUnit, expected] of values) { - expect(plainYearMonth.until(other, { largestUnit }).toString()).toBe(expected); - } - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainYearMonth object", () => { - expect(() => { - Temporal.PlainYearMonth.prototype.until.call("foo", {}); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainYearMonth"); - }); - - test("disallowed smallestUnit option values", () => { - const values = [ - "week", - "day", - "hour", - "minute", - "second", - "millisecond", - "microsecond", - "nanosecond", - ]; - for (const smallestUnit of values) { - const plainYearMonth = new Temporal.PlainYearMonth(1970, 1); - const other = new Temporal.PlainYearMonth(1970, 1); - expect(() => { - plainYearMonth.until(other, { smallestUnit }); - }).toThrowWithMessage( - RangeError, - `${smallestUnit} is not a valid value for option smallestUnit` - ); - } - }); - - test("disallowed largestUnit option values", () => { - const values = [ - "week", - "day", - "hour", - "minute", - "second", - "millisecond", - "microsecond", - "nanosecond", - ]; - for (const largestUnit of values) { - const plainYearMonth = new Temporal.PlainYearMonth(1970, 1); - const other = new Temporal.PlainYearMonth(1970, 1); - expect(() => { - plainYearMonth.until(other, { largestUnit }); - }).toThrowWithMessage( - RangeError, - `${largestUnit} is not a valid value for option largestUnit` - ); - } - }); - - test("cannot compare dates from different calendars", () => { - const calendarOne = { - toString() { - return "calendarOne"; - }, - }; - - const calendarTwo = { - toString() { - return "calendarTwo"; - }, - }; - - const plainYearMonthOne = new Temporal.PlainYearMonth(1970, 1, calendarOne); - const plainYearMonthTwo = new Temporal.PlainYearMonth(1970, 1, calendarTwo); - - expect(() => { - plainYearMonthOne.until(plainYearMonthTwo); - }).toThrowWithMessage(RangeError, "Cannot compare dates from two different calendars"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.prototype.valueOf.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.prototype.valueOf.js deleted file mode 100644 index 6c3d2d191f4..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.prototype.valueOf.js +++ /dev/null @@ -1,11 +0,0 @@ -describe("errors", () => { - test("throws TypeError", () => { - const plainYearMonth = new Temporal.PlainYearMonth(2021, 7); - expect(() => { - plainYearMonth.valueOf(); - }).toThrowWithMessage( - TypeError, - "Cannot convert Temporal.PlainYearMonth to a primitive value" - ); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.prototype.with.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.prototype.with.js deleted file mode 100644 index 2953a2baa7e..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.prototype.with.js +++ /dev/null @@ -1,57 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.PlainYearMonth.prototype.with).toHaveLength(1); - }); - - test("basic functionality", () => { - const plainYearMonth = new Temporal.PlainYearMonth(1970, 1); - const values = [ - [{ year: 2021 }, new Temporal.PlainYearMonth(2021, 1)], - [{ year: 2021, month: 7 }, new Temporal.PlainYearMonth(2021, 7)], - [{ year: 2021, monthCode: "M07" }, new Temporal.PlainYearMonth(2021, 7)], - ]; - for (const [arg, expected] of values) { - expect(plainYearMonth.with(arg).equals(expected)).toBeTrue(); - } - - // Supplying the same values doesn't change the year/month, but still creates a new object - const plainYearMonthLike = { year: plainYearMonth.year, month: plainYearMonth.month }; - expect(plainYearMonth.with(plainYearMonthLike)).not.toBe(plainYearMonth); - expect(plainYearMonth.with(plainYearMonthLike).equals(plainYearMonth)).toBeTrue(); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainYearMonth object", () => { - expect(() => { - Temporal.PlainYearMonth.prototype.with.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainYearMonth"); - }); - - test("argument must be an object", () => { - expect(() => { - new Temporal.PlainYearMonth(1970, 1).with("foo"); - }).toThrowWithMessage(TypeError, "foo is not an object"); - expect(() => { - new Temporal.PlainYearMonth(1970, 1).with(42); - }).toThrowWithMessage(TypeError, "42 is not an object"); - }); - - test("argument must have one of 'month', 'monthCode', 'year'", () => { - expect(() => { - new Temporal.PlainYearMonth(1970, 1).with({}); - }).toThrowWithMessage( - TypeError, - "Object must have at least one of the following properties: month, monthCode, year" - ); - }); - - test("argument must not have 'calendar' or 'timeZone'", () => { - expect(() => { - new Temporal.PlainYearMonth(1970, 1).with({ calendar: {} }); - }).toThrowWithMessage(TypeError, "Object must not have a defined calendar property"); - expect(() => { - new Temporal.PlainYearMonth(1970, 1).with({ timeZone: {} }); - }).toThrowWithMessage(TypeError, "Object must not have a defined timeZone property"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.prototype.year.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.prototype.year.js deleted file mode 100644 index 13e0021ab34..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.prototype.year.js +++ /dev/null @@ -1,14 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const plainYearMonth = new Temporal.PlainYearMonth(2021, 7); - expect(plainYearMonth.year).toBe(2021); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.PlainYearMonth object", () => { - expect(() => { - Reflect.get(Temporal.PlainYearMonth.prototype, "year", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainYearMonth"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/TimeZone/TimeZone.from.js b/Libraries/LibJS/Tests/builtins/Temporal/TimeZone/TimeZone.from.js deleted file mode 100644 index 1b96d2fcad6..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/TimeZone/TimeZone.from.js +++ /dev/null @@ -1,89 +0,0 @@ -describe("normal behavior", () => { - test("length is 1", () => { - expect(Temporal.TimeZone.from).toHaveLength(1); - }); - - test("basic functionality", () => { - // From object - const timeZone = new Temporal.TimeZone("UTC"); - const timeZoneLike = {}; - const zonedDateTimeLike = { timeZone: {} }; - expect(Temporal.TimeZone.from(timeZone)).toBe(timeZone); - expect(Temporal.TimeZone.from(timeZoneLike)).toBe(timeZoneLike); - expect(Temporal.TimeZone.from(zonedDateTimeLike)).toBe(zonedDateTimeLike.timeZone); - - // From string - const values = [ - ["UTC", "UTC"], - ["GMT", "UTC"], - ["Etc/UTC", "UTC"], - ["Etc/GMT", "UTC"], - ["Etc/GMT0", "UTC"], // IANA legacy name - ["Etc/GMT+0", "UTC"], // IANA legacy name - ["Etc/GMT-0", "UTC"], // IANA legacy name - ["Etc/GMT+6", "Etc/GMT+6"], - ["Etc/GMT-6", "Etc/GMT-6"], - ["Etc/GMT+12", "Etc/GMT+12"], - ["Etc/GMT-12", "Etc/GMT-12"], - ["Europe/London", "Europe/London"], - ["Australia/Canberra", "Australia/Sydney"], - ["1970-01-01T00:00:00+01", "+01:00"], - ["1970-01-01T00:00:00.000000000+01", "+01:00"], - ["1970-01-01T00:00:00.000000000+01:00:00", "+01:00"], - ]; - for (const [arg, expected] of values) { - expect(Temporal.TimeZone.from(arg).id).toBe(expected); - } - }); - - test("ToTemporalTimeZone fast path returns if it is passed a Temporal.TimeZone instance", () => { - // This is obseravble via there being no property lookups (avoiding a "timeZone" property lookup in this case) - let madeObservableHasPropertyLookup = false; - class TimeZone extends Temporal.TimeZone { - constructor() { - super("UTC"); - } - - get timeZone() { - madeObservableHasPropertyLookup = true; - return this; - } - } - const timeZone = new TimeZone(); - Temporal.TimeZone.from(timeZone); - expect(madeObservableHasPropertyLookup).toBeFalse(); - }); -}); - -describe("errors", () => { - test("TimeZone from Calendar", () => { - const calendar = new Temporal.Calendar("iso8601"); - expect(() => { - Temporal.TimeZone.from(calendar); - }).toThrowWithMessage( - RangeError, - "Got unexpected Calendar object in conversion to TimeZone" - ); - }); - - test("invalid time zone strings", () => { - const values = [ - "1970-01-01+01", - "1970-01-01+01[-12:34]", - "1970-01-01+12:34", - "1970-01-01+12:34:56", - "1970-01-01+12:34:56.789", - "1970-01-01+12:34:56.789[-01:00]", - "1970-01-01-12:34", - "1970-01-01-12:34:56", - "1970-01-01-12:34:56.789", - "1970-01-01-12:34:56.789[+01:00]", - ]; - - for (const value of values) { - expect(() => { - Temporal.TimeZone.from(value); - }).toThrowWithMessage(RangeError, "Invalid ISO date time"); - } - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/TimeZone/TimeZone.js b/Libraries/LibJS/Tests/builtins/Temporal/TimeZone/TimeZone.js deleted file mode 100644 index dd5c594803c..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/TimeZone/TimeZone.js +++ /dev/null @@ -1,95 +0,0 @@ -describe("errors", () => { - test("called without new", () => { - expect(() => { - Temporal.TimeZone(); - }).toThrowWithMessage(TypeError, "Temporal.TimeZone constructor must be called with 'new'"); - }); - - test("Invalid time zone name", () => { - expect(() => { - new Temporal.TimeZone("foo"); - }).toThrowWithMessage(RangeError, "Invalid time zone name 'foo'"); - }); - - test("Invalid numeric UTC offset", () => { - // FIXME: Error message should probably say '...name or UTC offset ...' :^) - expect(() => { - new Temporal.TimeZone("0123456"); - }).toThrowWithMessage(RangeError, "Invalid time zone name '0123456'"); - - expect(() => { - new Temporal.TimeZone("23:59:59.9999999999"); - }).toThrowWithMessage(RangeError, "Invalid time zone name '23:59:59.9999999999'"); - - expect(() => { - new Temporal.TimeZone("\u221201"); - }).toThrowWithMessage(RangeError, "Invalid time zone name '\u221201'"); - }); -}); - -describe("normal behavior", () => { - test("length is 1", () => { - expect(Temporal.TimeZone).toHaveLength(1); - }); - - test("basic functionality", () => { - const timeZone = new Temporal.TimeZone("UTC"); - expect(timeZone.id).toBe("UTC"); - expect(typeof timeZone).toBe("object"); - expect(timeZone).toBeInstanceOf(Temporal.TimeZone); - expect(Object.getPrototypeOf(timeZone)).toBe(Temporal.TimeZone.prototype); - }); - - test("canonicalizes time zone name", () => { - const values = [ - ["UTC", "UTC"], - ["Utc", "UTC"], - ["utc", "UTC"], - ["uTc", "UTC"], - ["GMT", "UTC"], - ["Etc/UTC", "UTC"], - ["Etc/GMT", "UTC"], - ["Etc/GMT+12", "Etc/GMT+12"], - ["Etc/GMT-12", "Etc/GMT-12"], - ["Europe/London", "Europe/London"], - ["Australia/Canberra", "Australia/Sydney"], - ]; - for (const [arg, expected] of values) { - expect(new Temporal.TimeZone(arg).id).toBe(expected); - } - }); - - test("numeric UTC offset", () => { - const signs = [ - ["+", "+"], - ["-", "-"], - ]; - const values = [ - ["01", "01:00"], - ["0123", "01:23"], - ["012345", "01:23:45"], - ["012345.6", "01:23:45.6"], - ["012345.123", "01:23:45.123"], - ["012345.123456789", "01:23:45.123456789"], - ["012345,6", "01:23:45.6"], - ["012345,123", "01:23:45.123"], - ["012345,123456789", "01:23:45.123456789"], - ["01:23", "01:23"], - ["01:23:45", "01:23:45"], - ["01:23:45.6", "01:23:45.6"], - ["01:23:45.123", "01:23:45.123"], - ["01:23:45.123456789", "01:23:45.123456789"], - ["01:23:45,6", "01:23:45.6"], - ["01:23:45,123", "01:23:45.123"], - ["01:23:45,123456789", "01:23:45.123456789"], - ["23:59:59.999999999", "23:59:59.999999999"], - ]; - for (const [sign, expectedSign] of signs) { - for (const [offset, expectedOffset] of values) { - expect(new Temporal.TimeZone(`${sign}${offset}`).id).toBe( - `${expectedSign}${expectedOffset}` - ); - } - } - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/TimeZone/TimeZone.prototype.@@toStringTag.js b/Libraries/LibJS/Tests/builtins/Temporal/TimeZone/TimeZone.prototype.@@toStringTag.js deleted file mode 100644 index 50636ff368d..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/TimeZone/TimeZone.prototype.@@toStringTag.js +++ /dev/null @@ -1,3 +0,0 @@ -test("basic functionality", () => { - expect(Temporal.TimeZone.prototype[Symbol.toStringTag]).toBe("Temporal.TimeZone"); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/TimeZone/TimeZone.prototype.getInstantFor.js b/Libraries/LibJS/Tests/builtins/Temporal/TimeZone/TimeZone.prototype.getInstantFor.js deleted file mode 100644 index 07285475c9b..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/TimeZone/TimeZone.prototype.getInstantFor.js +++ /dev/null @@ -1,29 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.TimeZone.prototype.getInstantFor).toHaveLength(1); - }); - - test("basic functionality", () => { - const timeZone = new Temporal.TimeZone("UTC"); - const plainDateTime = new Temporal.PlainDateTime(2021, 7, 6, 18, 14, 47); - const instant = timeZone.getInstantFor(plainDateTime); - expect(instant).toBeInstanceOf(Temporal.Instant); - expect(instant.epochNanoseconds).toBe(1625595287000000000n); - }); - - test("custom offset", () => { - const timeZone = new Temporal.TimeZone("+01:30"); - const plainDateTime = new Temporal.PlainDateTime(2021, 7, 6, 18, 14, 47); - const instant = timeZone.getInstantFor(plainDateTime); - expect(instant).toBeInstanceOf(Temporal.Instant); - expect(instant.epochNanoseconds).toBe(1625589887000000000n); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.TimeZone object", () => { - expect(() => { - Temporal.TimeZone.prototype.getInstantFor.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.TimeZone"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/TimeZone/TimeZone.prototype.getNextTransition.js b/Libraries/LibJS/Tests/builtins/Temporal/TimeZone/TimeZone.prototype.getNextTransition.js deleted file mode 100644 index d92abb3111d..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/TimeZone/TimeZone.prototype.getNextTransition.js +++ /dev/null @@ -1,25 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.TimeZone.prototype.getNextTransition).toHaveLength(1); - }); - - test("basic functionality", () => { - const timeZone = new Temporal.TimeZone("UTC"); - const instant = new Temporal.Instant(0n); - expect(timeZone.getNextTransition(instant)).toBeNull(); - }); - - test("custom offset", () => { - const timeZone = new Temporal.TimeZone("+01:30"); - const instant = new Temporal.Instant(0n); - expect(timeZone.getNextTransition(instant)).toBeNull(); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.TimeZone object", () => { - expect(() => { - Temporal.TimeZone.prototype.getNextTransition.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.TimeZone"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/TimeZone/TimeZone.prototype.getOffsetNanosecondsFor.js b/Libraries/LibJS/Tests/builtins/Temporal/TimeZone/TimeZone.prototype.getOffsetNanosecondsFor.js deleted file mode 100644 index 6c76ea952db..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/TimeZone/TimeZone.prototype.getOffsetNanosecondsFor.js +++ /dev/null @@ -1,59 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.TimeZone.prototype.getOffsetNanosecondsFor).toHaveLength(1); - }); - - test("basic functionality", () => { - // Adapted from TestTimeZone.cpp's TEST_CASE(time_zone_offset). - - function offset(sign, hours, minutes, seconds) { - return sign * (hours * 3600 + minutes * 60 + seconds) * 1_000_000_000; - } - - function testOffset(timeZone, time, expectedOffset) { - const instant = new Temporal.Instant(BigInt(time) * 1_000_000_000n); - const actualOffset = new Temporal.TimeZone(timeZone).getOffsetNanosecondsFor(instant); - expect(actualOffset).toBe(expectedOffset); - } - - testOffset("America/Chicago", -2717647201, offset(-1, 5, 50, 36)); // November 18, 1883 5:59:59 PM UTC - testOffset("America/Chicago", -2717647200, offset(-1, 6, 0, 0)); // November 18, 1883 6:00:00 PM UTC - testOffset("America/Chicago", -1067788860, offset(-1, 6, 0, 0)); // March 1, 1936 1:59:00 AM Chicago (March 1, 1936 7:59:00 AM UTC) - testOffset("America/Chicago", -1067788800, offset(-1, 5, 0, 0)); // March 1, 1936 3:00:00 AM Chicago (March 1, 1936 8:00:00 AM UTC) - testOffset("America/Chicago", -1045414860, offset(-1, 5, 0, 0)); // November 15, 1936 1:59:00 AM Chicago (November 15, 1936 6:59:00 AM UTC) - testOffset("America/Chicago", -1045411200, offset(-1, 6, 0, 0)); // November 15, 1936 2:00:00 AM Chicago (November 15, 1936 8:00:00 AM UTC) - - testOffset("Europe/London", -3852662326, offset(-1, 0, 1, 15)); // November 30, 1847 11:59:59 PM London (December 1, 1847 12:01:14 AM UTC) - testOffset("Europe/London", -3852662325, offset(+1, 0, 0, 0)); // December 1, 1847 12:01:15 AM London (December 1, 1847 12:01:15 AM UTC) - testOffset("Europe/London", -59004001, offset(+1, 0, 0, 0)); // February 18, 1968 1:59:59 AM London (February 18, 1968 1:59:59 AM UTC) - testOffset("Europe/London", -59004000, offset(+1, 1, 0, 0)); // February 18, 1968 3:00:00 AM London (February 18, 1968 2:00:00 AM UTC) - testOffset("Europe/London", 57722399, offset(+1, 1, 0, 0)); // October 31, 1971 1:59:59 AM UTC - testOffset("Europe/London", 57722400, offset(+1, 0, 0, 0)); // October 31, 1971 2:00:00 AM UTC - - testOffset("UTC", -1641846268, offset(+1, 0, 0, 0)); - testOffset("UTC", 0, offset(+1, 0, 0, 0)); - testOffset("UTC", 1641846268, offset(+1, 0, 0, 0)); - - testOffset("Etc/GMT+4", -1641846268, offset(-1, 4, 0, 0)); - testOffset("Etc/GMT+5", 0, offset(-1, 5, 0, 0)); - testOffset("Etc/GMT+6", 1641846268, offset(-1, 6, 0, 0)); - - testOffset("Etc/GMT-12", -1641846268, offset(+1, 12, 0, 0)); - testOffset("Etc/GMT-13", 0, offset(+1, 13, 0, 0)); - testOffset("Etc/GMT-14", 1641846268, offset(+1, 14, 0, 0)); - }); - - test("custom offset", () => { - const timeZone = new Temporal.TimeZone("+01:30"); - const instant = new Temporal.Instant(0n); - expect(timeZone.getOffsetNanosecondsFor(instant)).toBe(5400000000000); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.TimeZone object", () => { - expect(() => { - Temporal.TimeZone.prototype.getOffsetNanosecondsFor.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.TimeZone"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/TimeZone/TimeZone.prototype.getOffsetStringFor.js b/Libraries/LibJS/Tests/builtins/Temporal/TimeZone/TimeZone.prototype.getOffsetStringFor.js deleted file mode 100644 index 0458c71fccc..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/TimeZone/TimeZone.prototype.getOffsetStringFor.js +++ /dev/null @@ -1,32 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.TimeZone.prototype.getOffsetStringFor).toHaveLength(1); - }); - - test("basic functionality", () => { - const values = [ - ["UTC", "+00:00"], - ["GMT", "+00:00"], - ["Etc/GMT+12", "-12:00"], - ["Etc/GMT-12", "+12:00"], - ["Europe/London", "+01:00"], - ["Europe/Berlin", "+02:00"], - ["America/New_York", "-04:00"], - ["America/Los_Angeles", "-07:00"], - ["+00:00", "+00:00"], - ["+01:30", "+01:30"], - ]; - for (const [arg, expected] of values) { - const instant = new Temporal.Instant(1600000000000000000n); // Sunday, September 13, 2020 12:26:40 PM - expect(new Temporal.TimeZone(arg).getOffsetStringFor(instant)).toBe(expected); - } - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.TimeZone object", () => { - expect(() => { - Temporal.TimeZone.prototype.getOffsetStringFor.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.TimeZone"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/TimeZone/TimeZone.prototype.getPlainDateTimeFor.js b/Libraries/LibJS/Tests/builtins/Temporal/TimeZone/TimeZone.prototype.getPlainDateTimeFor.js deleted file mode 100644 index aaa2c11a0bd..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/TimeZone/TimeZone.prototype.getPlainDateTimeFor.js +++ /dev/null @@ -1,46 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.TimeZone.prototype.getPlainDateTimeFor).toHaveLength(1); - }); - - test("basic functionality", () => { - const timeZone = new Temporal.TimeZone("UTC"); - const instant = Temporal.Instant.fromEpochSeconds(123456789); - const plainDateTime = timeZone.getPlainDateTimeFor(instant); - expect(plainDateTime.year).toBe(1973); - expect(plainDateTime.month).toBe(11); - expect(plainDateTime.day).toBe(29); - expect(plainDateTime.hour).toBe(21); - expect(plainDateTime.minute).toBe(33); - expect(plainDateTime.second).toBe(9); - expect(plainDateTime.millisecond).toBe(0); - expect(plainDateTime.microsecond).toBe(0); - expect(plainDateTime.nanosecond).toBe(0); - expect(plainDateTime.calendar.id).toBe("iso8601"); - }); - - test("custom calendar", () => { - const timeZone = new Temporal.TimeZone("UTC"); - const instant = new Temporal.Instant(0n); - const calendar = new Temporal.Calendar("iso8601"); - const plainDateTime = timeZone.getPlainDateTimeFor(instant, calendar); - expect(plainDateTime.calendar).toBe(calendar); - }); -}); - -describe("errors", () => { - test("time zone doesn't have a getOffsetNanosecondsFor function", () => { - const timeZone = new Temporal.TimeZone("UTC"); - timeZone.getOffsetNanosecondsFor = undefined; - const instant = new Temporal.Instant(1n); - expect(() => { - timeZone.getPlainDateTimeFor(instant); - }).toThrowWithMessage(TypeError, "getOffsetNanosecondsFor is undefined"); - }); - - test("this value must be a Temporal.TimeZone object", () => { - expect(() => { - Temporal.TimeZone.prototype.getPlainDateTimeFor.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.TimeZone"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/TimeZone/TimeZone.prototype.getPossibleInstantsFor.js b/Libraries/LibJS/Tests/builtins/Temporal/TimeZone/TimeZone.prototype.getPossibleInstantsFor.js deleted file mode 100644 index d9587c9d20e..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/TimeZone/TimeZone.prototype.getPossibleInstantsFor.js +++ /dev/null @@ -1,31 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.TimeZone.prototype.getPossibleInstantsFor).toHaveLength(1); - }); - - test("basic functionality", () => { - const timeZone = new Temporal.TimeZone("UTC"); - const plainDateTime = new Temporal.PlainDateTime(2021, 7, 6, 18, 14, 47); - const possibleInstants = timeZone.getPossibleInstantsFor(plainDateTime); - expect(possibleInstants).toBeInstanceOf(Array); - expect(possibleInstants).toHaveLength(1); - expect(possibleInstants[0].epochNanoseconds).toBe(1625595287000000000n); - }); - - test("custom offset", () => { - const timeZone = new Temporal.TimeZone("+01:30"); - const plainDateTime = new Temporal.PlainDateTime(2021, 7, 6, 18, 14, 47); - const possibleInstants = timeZone.getPossibleInstantsFor(plainDateTime); - expect(possibleInstants).toBeInstanceOf(Array); - expect(possibleInstants).toHaveLength(1); - expect(possibleInstants[0].epochNanoseconds).toBe(1625589887000000000n); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.TimeZone object", () => { - expect(() => { - Temporal.TimeZone.prototype.getPossibleInstantsFor.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.TimeZone"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/TimeZone/TimeZone.prototype.getPreviousTransition.js b/Libraries/LibJS/Tests/builtins/Temporal/TimeZone/TimeZone.prototype.getPreviousTransition.js deleted file mode 100644 index ce4b3935912..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/TimeZone/TimeZone.prototype.getPreviousTransition.js +++ /dev/null @@ -1,25 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.TimeZone.prototype.getPreviousTransition).toHaveLength(1); - }); - - test("basic functionality", () => { - const timeZone = new Temporal.TimeZone("UTC"); - const instant = new Temporal.Instant(0n); - expect(timeZone.getPreviousTransition(instant)).toBeNull(); - }); - - test("custom offset", () => { - const timeZone = new Temporal.TimeZone("+01:30"); - const instant = new Temporal.Instant(0n); - expect(timeZone.getPreviousTransition(instant)).toBeNull(); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.TimeZone object", () => { - expect(() => { - Temporal.TimeZone.prototype.getPreviousTransition.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.TimeZone"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/TimeZone/TimeZone.prototype.id.js b/Libraries/LibJS/Tests/builtins/Temporal/TimeZone/TimeZone.prototype.id.js deleted file mode 100644 index 7da702bbca5..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/TimeZone/TimeZone.prototype.id.js +++ /dev/null @@ -1,14 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const timeZone = new Temporal.TimeZone("UTC"); - expect(timeZone.id).toBe("UTC"); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.TimeZone object", () => { - expect(() => { - Reflect.get(Temporal.TimeZone.prototype, "id", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.TimeZone"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/TimeZone/TimeZone.prototype.toJSON.js b/Libraries/LibJS/Tests/builtins/Temporal/TimeZone/TimeZone.prototype.toJSON.js deleted file mode 100644 index 78f803a876e..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/TimeZone/TimeZone.prototype.toJSON.js +++ /dev/null @@ -1,18 +0,0 @@ -describe("correct behavior", () => { - test("length is 0", () => { - expect(Temporal.TimeZone.prototype.toJSON).toHaveLength(0); - }); - - test("basic functionality", () => { - const timeZone = new Temporal.TimeZone("UTC"); - expect(timeZone.toJSON()).toBe("UTC"); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.TimeZone object", () => { - expect(() => { - Temporal.TimeZone.prototype.toJSON.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.TimeZone"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/TimeZone/TimeZone.prototype.toString.js b/Libraries/LibJS/Tests/builtins/Temporal/TimeZone/TimeZone.prototype.toString.js deleted file mode 100644 index 6e452075ff8..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/TimeZone/TimeZone.prototype.toString.js +++ /dev/null @@ -1,35 +0,0 @@ -describe("correct behavior", () => { - test("length is 0", () => { - expect(Temporal.TimeZone.prototype.toString).toHaveLength(0); - }); - - test("basic functionality", () => { - const values = [ - ["utc", "UTC"], - ["Utc", "UTC"], - ["UTC", "UTC"], - ["GMT", "UTC"], - ["Etc/UTC", "UTC"], - ["Etc/GMT", "UTC"], - ["Europe/London", "Europe/London"], - ["Australia/Canberra", "Australia/Sydney"], - ["+00:00", "+00:00"], - ["+00:00:00", "+00:00"], - ["+00:00:00.000", "+00:00"], - ["+12:34:56.789", "+12:34:56.789"], - ["+12:34:56.789000", "+12:34:56.789"], - ["-01:00", "-01:00"], - ]; - for (const [arg, expected] of values) { - expect(new Temporal.TimeZone(arg).toString()).toBe(expected); - } - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.TimeZone object", () => { - expect(() => { - Temporal.TimeZone.prototype.toString.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.TimeZone"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.compare.js b/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.compare.js deleted file mode 100644 index e35fbdfb6e1..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.compare.js +++ /dev/null @@ -1,15 +0,0 @@ -describe("correct behavior", () => { - test("length is 2", () => { - expect(Temporal.ZonedDateTime.compare).toHaveLength(2); - }); - - test("basic functionality", () => { - const zonedDateTimeOne = new Temporal.ZonedDateTime(1n, new Temporal.TimeZone("UTC")); - const zonedDateTimeTwo = new Temporal.ZonedDateTime(2n, new Temporal.TimeZone("UTC")); - - expect(Temporal.ZonedDateTime.compare(zonedDateTimeOne, zonedDateTimeOne)).toBe(0); - expect(Temporal.ZonedDateTime.compare(zonedDateTimeTwo, zonedDateTimeTwo)).toBe(0); - expect(Temporal.ZonedDateTime.compare(zonedDateTimeOne, zonedDateTimeTwo)).toBe(-1); - expect(Temporal.ZonedDateTime.compare(zonedDateTimeTwo, zonedDateTimeOne)).toBe(1); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.from.js b/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.from.js deleted file mode 100644 index 5f77a0c35ab..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.from.js +++ /dev/null @@ -1,160 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.ZonedDateTime.from).toHaveLength(1); - }); - - test("ZonedDateTime instance argument", () => { - const timeZone = new Temporal.TimeZone("UTC"); - const calendar = new Temporal.Calendar("iso8601"); - const zonedDateTime = new Temporal.ZonedDateTime(1627318123456789000n, timeZone, calendar); - const createdZoneDateTime = Temporal.ZonedDateTime.from(zonedDateTime); - - expect(createdZoneDateTime).toBeInstanceOf(Temporal.ZonedDateTime); - expect(createdZoneDateTime).not.toBe(zonedDateTime); - expect(createdZoneDateTime.timeZone).toBe(timeZone); - expect(createdZoneDateTime.calendar).toBe(calendar); - expect(createdZoneDateTime.epochNanoseconds).toBe(1627318123456789000n); - }); - - test("PlainDate instance argument", () => { - const timeZone = new Temporal.TimeZone("UTC"); - const calendar = new Temporal.Calendar("iso8601"); - const plainDate = new Temporal.PlainDate(2021, 11, 7, calendar); - plainDate.timeZone = timeZone; - const createdZoneDateTime = Temporal.ZonedDateTime.from(plainDate); - - expect(createdZoneDateTime).toBeInstanceOf(Temporal.ZonedDateTime); - expect(createdZoneDateTime.timeZone).toBe(timeZone); - expect(createdZoneDateTime.calendar).toBe(calendar); - expect(createdZoneDateTime.year).toBe(2021); - expect(createdZoneDateTime.month).toBe(11); - expect(createdZoneDateTime.day).toBe(7); - }); - - test("PlainDateTime instance argument", () => { - const timeZone = new Temporal.TimeZone("UTC"); - const calendar = new Temporal.Calendar("iso8601"); - const plainDateTime = new Temporal.PlainDateTime( - 2021, - 11, - 7, - 0, - 20, - 5, - 100, - 200, - 300, - calendar - ); - plainDateTime.timeZone = timeZone; - const createdZoneDateTime = Temporal.ZonedDateTime.from(plainDateTime); - - expect(createdZoneDateTime).toBeInstanceOf(Temporal.ZonedDateTime); - expect(createdZoneDateTime.timeZone).toBe(timeZone); - expect(createdZoneDateTime.calendar).toBe(calendar); - expect(createdZoneDateTime.year).toBe(2021); - expect(createdZoneDateTime.month).toBe(11); - expect(createdZoneDateTime.day).toBe(7); - expect(createdZoneDateTime.hour).toBe(0); - expect(createdZoneDateTime.minute).toBe(20); - expect(createdZoneDateTime.second).toBe(5); - expect(createdZoneDateTime.millisecond).toBe(100); - expect(createdZoneDateTime.microsecond).toBe(200); - expect(createdZoneDateTime.nanosecond).toBe(300); - }); - - test("ZonedDateTime-like argument", () => { - const timeZone = new Temporal.TimeZone("UTC"); - const calendar = new Temporal.Calendar("iso8601"); - const zdtLike = { - timeZone, - calendar, - year: 2021, - month: 11, - day: 7, - hour: 0, - minute: 20, - second: 5, - millisecond: 100, - microsecond: 200, - nanosecond: 300, - }; - const createdZoneDateTime = Temporal.ZonedDateTime.from(zdtLike); - - expect(createdZoneDateTime).toBeInstanceOf(Temporal.ZonedDateTime); - expect(createdZoneDateTime.timeZone).toBe(timeZone); - expect(createdZoneDateTime.calendar).toBe(calendar); - expect(createdZoneDateTime.year).toBe(2021); - expect(createdZoneDateTime.month).toBe(11); - expect(createdZoneDateTime.day).toBe(7); - expect(createdZoneDateTime.hour).toBe(0); - expect(createdZoneDateTime.minute).toBe(20); - expect(createdZoneDateTime.second).toBe(5); - expect(createdZoneDateTime.millisecond).toBe(100); - expect(createdZoneDateTime.microsecond).toBe(200); - expect(createdZoneDateTime.nanosecond).toBe(300); - }); - - test("from string", () => { - const zonedDateTime = Temporal.ZonedDateTime.from( - "2021-11-07T00:20:05.100200300+00:00[UTC][u-ca=iso8601]" - ); - - expect(zonedDateTime).toBeInstanceOf(Temporal.ZonedDateTime); - expect(zonedDateTime.timeZone).toBeInstanceOf(Temporal.TimeZone); - expect(zonedDateTime.timeZone.id).toBe("UTC"); - expect(zonedDateTime.calendar).toBeInstanceOf(Temporal.Calendar); - expect(zonedDateTime.calendar.id).toBe("iso8601"); - expect(zonedDateTime.year).toBe(2021); - expect(zonedDateTime.month).toBe(11); - expect(zonedDateTime.day).toBe(7); - expect(zonedDateTime.hour).toBe(0); - expect(zonedDateTime.minute).toBe(20); - expect(zonedDateTime.second).toBe(5); - expect(zonedDateTime.millisecond).toBe(100); - expect(zonedDateTime.microsecond).toBe(200); - expect(zonedDateTime.nanosecond).toBe(300); - expect(zonedDateTime.offset).toBe("+00:00"); - expect(zonedDateTime.offsetNanoseconds).toBe(0); - }); -}); - -describe("errors", () => { - test("requires timeZone property", () => { - expect(() => { - Temporal.ZonedDateTime.from({}); - }).toThrowWithMessage(TypeError, "Required property timeZone is missing or undefined"); - }); - - test("requires year property", () => { - expect(() => { - Temporal.ZonedDateTime.from({ timeZone: new Temporal.TimeZone("UTC") }); - }).toThrowWithMessage(TypeError, "Required property day is missing or undefined"); - }); - - test("requires month property", () => { - expect(() => { - Temporal.ZonedDateTime.from({ - timeZone: new Temporal.TimeZone("UTC"), - day: 1, - year: 2021, - }); - }).toThrowWithMessage(TypeError, "Required property month is missing or undefined"); - }); - - test("requires day property", () => { - expect(() => { - Temporal.ZonedDateTime.from({ - timeZone: new Temporal.TimeZone("UTC"), - year: 2021, - month: 11, - }); - }).toThrowWithMessage(TypeError, "Required property day is missing or undefined"); - }); - - test("invalid zoned date time string", () => { - expect(() => { - Temporal.ZonedDateTime.from("foo"); - }).toThrowWithMessage(RangeError, "Invalid zoned date time string 'foo'"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.js b/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.js deleted file mode 100644 index f65d7247d4e..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.js +++ /dev/null @@ -1,39 +0,0 @@ -describe("errors", () => { - test("called without new", () => { - expect(() => { - Temporal.ZonedDateTime(); - }).toThrowWithMessage( - TypeError, - "Temporal.ZonedDateTime constructor must be called with 'new'" - ); - }); - - test("out-of-range epoch nanoseconds value", () => { - expect(() => { - new Temporal.ZonedDateTime(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(() => { - new Temporal.ZonedDateTime(-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" - ); - }); -}); - -describe("normal behavior", () => { - test("length is 2", () => { - expect(Temporal.ZonedDateTime).toHaveLength(2); - }); - - test("basic functionality", () => { - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = new Temporal.ZonedDateTime(0n, timeZone); - expect(typeof zonedDateTime).toBe("object"); - expect(zonedDateTime).toBeInstanceOf(Temporal.ZonedDateTime); - expect(Object.getPrototypeOf(zonedDateTime)).toBe(Temporal.ZonedDateTime.prototype); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.@@toStringTag.js b/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.@@toStringTag.js deleted file mode 100644 index 33ade578b83..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.@@toStringTag.js +++ /dev/null @@ -1,3 +0,0 @@ -test("basic functionality", () => { - expect(Temporal.ZonedDateTime.prototype[Symbol.toStringTag]).toBe("Temporal.ZonedDateTime"); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.add.js b/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.add.js deleted file mode 100644 index e399e2cfe99..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.add.js +++ /dev/null @@ -1,61 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.ZonedDateTime.prototype.add).toHaveLength(1); - }); - - test("basic functionality", () => { - const plainDateTime = new Temporal.PlainDateTime(2021, 11, 12, 0, 22, 30, 100, 200, 300); - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = plainDateTime.toZonedDateTime(timeZone); - const dayDuration = new Temporal.Duration(0, 0, 0, 1); - const result = zonedDateTime.add(dayDuration); - - expect(zonedDateTime.day).toBe(12); - expect(zonedDateTime.epochNanoseconds).toBe(1636676550100200300n); - - expect(result.day).toBe(13); - expect(result.epochNanoseconds).toBe(1636762950100200300n); - }); - - test("duration-like object", () => { - const plainDateTime = new Temporal.PlainDateTime(2021, 11, 12, 0, 22, 30, 100, 200, 300); - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = plainDateTime.toZonedDateTime(timeZone); - const dayDuration = { days: 1 }; - const result = zonedDateTime.add(dayDuration); - - expect(zonedDateTime.day).toBe(12); - expect(zonedDateTime.epochNanoseconds).toBe(1636676550100200300n); - - expect(result.day).toBe(13); - expect(result.epochNanoseconds).toBe(1636762950100200300n); - }); - - test("duration string", () => { - const plainDateTime = new Temporal.PlainDateTime(2021, 11, 12, 0, 22, 30, 100, 200, 300); - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = plainDateTime.toZonedDateTime(timeZone); - const dayDuration = "P1D"; - const result = zonedDateTime.add(dayDuration); - - expect(zonedDateTime.day).toBe(12); - expect(zonedDateTime.epochNanoseconds).toBe(1636676550100200300n); - - expect(result.day).toBe(13); - expect(result.epochNanoseconds).toBe(1636762950100200300n); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.ZonedDateTime object", () => { - expect(() => { - Temporal.ZonedDateTime.prototype.add.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.ZonedDateTime"); - }); - - test("invalid duration-like object", () => { - expect(() => { - new Temporal.ZonedDateTime(1n, {}).add({}); - }).toThrowWithMessage(TypeError, "Invalid duration-like object"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.calendar.js b/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.calendar.js deleted file mode 100644 index 53d9135c1b4..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.calendar.js +++ /dev/null @@ -1,16 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const timeZone = new Temporal.TimeZone("UTC"); - const calendar = new Temporal.Calendar("iso8601"); - const zonedDateTime = new Temporal.ZonedDateTime(0n, timeZone, calendar); - expect(zonedDateTime.calendar).toBe(calendar); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.ZonedDateTime object", () => { - expect(() => { - Reflect.get(Temporal.ZonedDateTime.prototype, "calendar", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.ZonedDateTime"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.calendarId.js b/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.calendarId.js deleted file mode 100644 index 7fcdf6f3e98..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.calendarId.js +++ /dev/null @@ -1,19 +0,0 @@ -describe("correct behavior", () => { - test("calendarId basic functionality", () => { - const calendar = "iso8601"; - const zonedDateTime = new Temporal.ZonedDateTime( - 0n, - Temporal.TimeZone.from("UTC"), - Temporal.Calendar.from(calendar) - ); - expect(zonedDateTime.calendarId).toBe("iso8601"); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.ZonedDateTime object", () => { - expect(() => { - Reflect.get(Temporal.ZonedDateTime.prototype, "calendarId", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.ZonedDateTime"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.day.js b/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.day.js deleted file mode 100644 index a1a0766045b..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.day.js +++ /dev/null @@ -1,15 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = new Temporal.ZonedDateTime(1625614921000000000n, timeZone); - expect(zonedDateTime.day).toBe(6); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.ZonedDateTime object", () => { - expect(() => { - Reflect.get(Temporal.ZonedDateTime.prototype, "day", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.ZonedDateTime"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.dayOfWeek.js b/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.dayOfWeek.js deleted file mode 100644 index e1fb8e41de0..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.dayOfWeek.js +++ /dev/null @@ -1,15 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = new Temporal.ZonedDateTime(1625614921000000000n, timeZone); - expect(zonedDateTime.dayOfWeek).toBe(2); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.ZonedDateTime object", () => { - expect(() => { - Reflect.get(Temporal.ZonedDateTime.prototype, "dayOfWeek", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.ZonedDateTime"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.dayOfYear.js b/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.dayOfYear.js deleted file mode 100644 index b01db8a25c5..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.dayOfYear.js +++ /dev/null @@ -1,15 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = new Temporal.ZonedDateTime(1625614921000000000n, timeZone); - expect(zonedDateTime.dayOfYear).toBe(187); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.ZonedDateTime object", () => { - expect(() => { - Reflect.get(Temporal.ZonedDateTime.prototype, "dayOfYear", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.ZonedDateTime"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.daysInMonth.js b/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.daysInMonth.js deleted file mode 100644 index 741ae3e480c..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.daysInMonth.js +++ /dev/null @@ -1,15 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = new Temporal.ZonedDateTime(1625614921000000000n, timeZone); - expect(zonedDateTime.daysInMonth).toBe(31); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.ZonedDateTime object", () => { - expect(() => { - Reflect.get(Temporal.ZonedDateTime.prototype, "daysInMonth", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.ZonedDateTime"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.daysInWeek.js b/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.daysInWeek.js deleted file mode 100644 index e0be6b61f96..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.daysInWeek.js +++ /dev/null @@ -1,15 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = new Temporal.ZonedDateTime(1625614921000000000n, timeZone); - expect(zonedDateTime.daysInWeek).toBe(7); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.ZonedDateTime object", () => { - expect(() => { - Reflect.get(Temporal.ZonedDateTime.prototype, "daysInWeek", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.ZonedDateTime"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.daysInYear.js b/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.daysInYear.js deleted file mode 100644 index 3e724ecb519..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.daysInYear.js +++ /dev/null @@ -1,15 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = new Temporal.ZonedDateTime(1625614921000000000n, timeZone); - expect(zonedDateTime.daysInYear).toBe(365); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.ZonedDateTime object", () => { - expect(() => { - Reflect.get(Temporal.ZonedDateTime.prototype, "daysInYear", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.ZonedDateTime"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.epochMicroseconds.js b/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.epochMicroseconds.js deleted file mode 100644 index 7cdbf3c3fec..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.epochMicroseconds.js +++ /dev/null @@ -1,15 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = new Temporal.ZonedDateTime(1625614921000000000n, timeZone); - expect(zonedDateTime.epochMicroseconds).toBe(1625614921000000n); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.ZonedDateTime object", () => { - expect(() => { - Reflect.get(Temporal.ZonedDateTime.prototype, "epochMicroseconds", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.ZonedDateTime"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.epochMilliseconds.js b/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.epochMilliseconds.js deleted file mode 100644 index 381401e70f5..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.epochMilliseconds.js +++ /dev/null @@ -1,15 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = new Temporal.ZonedDateTime(1625614921000000000n, timeZone); - expect(zonedDateTime.epochMilliseconds).toBe(1625614921000); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.ZonedDateTime object", () => { - expect(() => { - Reflect.get(Temporal.ZonedDateTime.prototype, "epochMilliseconds", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.ZonedDateTime"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.epochNanoseconds.js b/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.epochNanoseconds.js deleted file mode 100644 index 9c0e466e766..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.epochNanoseconds.js +++ /dev/null @@ -1,15 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = new Temporal.ZonedDateTime(1625614921000000000n, timeZone); - expect(zonedDateTime.epochNanoseconds).toBe(1625614921000000000n); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.ZonedDateTime object", () => { - expect(() => { - Reflect.get(Temporal.ZonedDateTime.prototype, "epochNanoseconds", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.ZonedDateTime"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.epochSeconds.js b/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.epochSeconds.js deleted file mode 100644 index e764aaf91c0..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.epochSeconds.js +++ /dev/null @@ -1,15 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = new Temporal.ZonedDateTime(1625614921000000000n, timeZone); - expect(zonedDateTime.epochSeconds).toBe(1625614921); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.ZonedDateTime object", () => { - expect(() => { - Reflect.get(Temporal.ZonedDateTime.prototype, "epochSeconds", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.ZonedDateTime"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.equals.js b/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.equals.js deleted file mode 100644 index 6b8ba6f2aff..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.equals.js +++ /dev/null @@ -1,23 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.ZonedDateTime.prototype.equals).toHaveLength(1); - }); - - test("basic functionality", () => { - const zonedDateTimeOne = new Temporal.ZonedDateTime(1n, new Temporal.TimeZone("UTC")); - const zonedDateTimeTwo = new Temporal.ZonedDateTime(2n, new Temporal.TimeZone("UTC")); - - expect(zonedDateTimeOne.equals(zonedDateTimeOne)).toBeTrue(); - expect(zonedDateTimeTwo.equals(zonedDateTimeTwo)).toBeTrue(); - expect(zonedDateTimeOne.equals(zonedDateTimeTwo)).toBeFalse(); - expect(zonedDateTimeTwo.equals(zonedDateTimeOne)).toBeFalse(); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.ZonedDateTime object", () => { - expect(() => { - Temporal.ZonedDateTime.prototype.equals.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.ZonedDateTime"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.era.js b/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.era.js deleted file mode 100644 index dce541c0a80..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.era.js +++ /dev/null @@ -1,26 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = new Temporal.ZonedDateTime(1625614921000000000n, timeZone); - expect(zonedDateTime.era).toBeUndefined(); - }); - - test("calendar with custom era function", () => { - const timeZone = new Temporal.TimeZone("UTC"); - const calendar = { - era() { - return "foo"; - }, - }; - const zonedDateTime = new Temporal.ZonedDateTime(1625614921000000000n, timeZone, calendar); - expect(zonedDateTime.era).toBe("foo"); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.ZonedDateTime object", () => { - expect(() => { - Reflect.get(Temporal.ZonedDateTime.prototype, "era", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.ZonedDateTime"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.eraYear.js b/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.eraYear.js deleted file mode 100644 index 4ec60dc4512..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.eraYear.js +++ /dev/null @@ -1,26 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = new Temporal.ZonedDateTime(1625614921000000000n, timeZone); - expect(zonedDateTime.eraYear).toBeUndefined(); - }); - - test("calendar with custom eraYear function", () => { - const timeZone = new Temporal.TimeZone("UTC"); - const calendar = { - eraYear() { - return 123; - }, - }; - const zonedDateTime = new Temporal.ZonedDateTime(1625614921000000000n, timeZone, calendar); - expect(zonedDateTime.eraYear).toBe(123); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.ZonedDateTime object", () => { - expect(() => { - Reflect.get(Temporal.ZonedDateTime.prototype, "eraYear", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.ZonedDateTime"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.getISOFields.js b/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.getISOFields.js deleted file mode 100644 index 23b74df0d9c..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.getISOFields.js +++ /dev/null @@ -1,56 +0,0 @@ -describe("normal behavior", () => { - test("length is 0", () => { - expect(Temporal.ZonedDateTime.prototype.getISOFields).toHaveLength(0); - }); - - test("basic functionality", () => { - const timeZone = new Temporal.TimeZone("UTC"); - const calendar = new Temporal.Calendar("iso8601"); - const zonedDateTime = new Temporal.ZonedDateTime(1625614921000000000n, timeZone, calendar); - const fields = zonedDateTime.getISOFields(); - expect(fields).toEqual({ - calendar: calendar, - isoDay: 6, - isoHour: 23, - isoMicrosecond: 0, - isoMillisecond: 0, - isoMinute: 42, - isoMonth: 7, - isoNanosecond: 0, - isoSecond: 1, - isoYear: 2021, - offset: "+00:00", - timeZone: timeZone, - }); - // Test field order - expect(Object.getOwnPropertyNames(fields)).toEqual([ - "calendar", - "isoDay", - "isoHour", - "isoMicrosecond", - "isoMillisecond", - "isoMinute", - "isoMonth", - "isoNanosecond", - "isoSecond", - "isoYear", - "offset", - "timeZone", - ]); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.ZonedDateTime object", () => { - expect(() => { - Temporal.ZonedDateTime.prototype.getISOFields.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.ZonedDateTime"); - }); - - test("custom time zone doesn't have a getOffsetNanosecondsFor function", () => { - const zonedDateTime = new Temporal.ZonedDateTime(0n, {}); - expect(() => { - zonedDateTime.getISOFields(); - }).toThrowWithMessage(TypeError, "getOffsetNanosecondsFor is undefined"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.hour.js b/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.hour.js deleted file mode 100644 index 92a423922aa..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.hour.js +++ /dev/null @@ -1,15 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = new Temporal.ZonedDateTime(1625614921000000000n, timeZone); - expect(zonedDateTime.hour).toBe(23); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.ZonedDateTime object", () => { - expect(() => { - Reflect.get(Temporal.ZonedDateTime.prototype, "hour", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.ZonedDateTime"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.hoursInDay.js b/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.hoursInDay.js deleted file mode 100644 index 7466c690a3d..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.hoursInDay.js +++ /dev/null @@ -1,15 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = new Temporal.ZonedDateTime(1625614921000000000n, timeZone); - expect(zonedDateTime.hoursInDay).toBe(24); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.ZonedDateTime object", () => { - expect(() => { - Reflect.get(Temporal.ZonedDateTime.prototype, "hoursInDay", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.ZonedDateTime"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.inLeapYear.js b/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.inLeapYear.js deleted file mode 100644 index 88b546bcac5..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.inLeapYear.js +++ /dev/null @@ -1,15 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = new Temporal.ZonedDateTime(1625614921000000000n, timeZone); - expect(zonedDateTime.inLeapYear).toBeFalse(); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.ZonedDateTime object", () => { - expect(() => { - Reflect.get(Temporal.ZonedDateTime.prototype, "inLeapYear", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.ZonedDateTime"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.microsecond.js b/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.microsecond.js deleted file mode 100644 index 2b49a6c6270..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.microsecond.js +++ /dev/null @@ -1,15 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = new Temporal.ZonedDateTime(123000n, timeZone); - expect(zonedDateTime.microsecond).toBe(123); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.ZonedDateTime object", () => { - expect(() => { - Reflect.get(Temporal.ZonedDateTime.prototype, "microsecond", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.ZonedDateTime"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.millisecond.js b/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.millisecond.js deleted file mode 100644 index eb5aa72113a..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.millisecond.js +++ /dev/null @@ -1,15 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = new Temporal.ZonedDateTime(123000000n, timeZone); - expect(zonedDateTime.millisecond).toBe(123); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.ZonedDateTime object", () => { - expect(() => { - Reflect.get(Temporal.ZonedDateTime.prototype, "millisecond", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.ZonedDateTime"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.minute.js b/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.minute.js deleted file mode 100644 index f8977634734..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.minute.js +++ /dev/null @@ -1,15 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = new Temporal.ZonedDateTime(1625614921000000000n, timeZone); - expect(zonedDateTime.minute).toBe(42); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.ZonedDateTime object", () => { - expect(() => { - Reflect.get(Temporal.ZonedDateTime.prototype, "minute", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.ZonedDateTime"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.month.js b/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.month.js deleted file mode 100644 index 08a57c85036..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.month.js +++ /dev/null @@ -1,15 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = new Temporal.ZonedDateTime(1625614921000000000n, timeZone); - expect(zonedDateTime.month).toBe(7); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.ZonedDateTime object", () => { - expect(() => { - Reflect.get(Temporal.ZonedDateTime.prototype, "month", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.ZonedDateTime"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.monthCode.js b/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.monthCode.js deleted file mode 100644 index 5c41c42b9f1..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.monthCode.js +++ /dev/null @@ -1,15 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = new Temporal.ZonedDateTime(1625614921000000000n, timeZone); - expect(zonedDateTime.monthCode).toBe("M07"); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.ZonedDateTime object", () => { - expect(() => { - Reflect.get(Temporal.ZonedDateTime.prototype, "monthCode", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.ZonedDateTime"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.monthsInYear.js b/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.monthsInYear.js deleted file mode 100644 index e0c3e0c6a1d..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.monthsInYear.js +++ /dev/null @@ -1,15 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = new Temporal.ZonedDateTime(1625614921000000000n, timeZone); - expect(zonedDateTime.monthsInYear).toBe(12); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.ZonedDateTime object", () => { - expect(() => { - Reflect.get(Temporal.ZonedDateTime.prototype, "monthsInYear", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.ZonedDateTime"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.nanosecond.js b/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.nanosecond.js deleted file mode 100644 index 0caf652a858..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.nanosecond.js +++ /dev/null @@ -1,15 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = new Temporal.ZonedDateTime(123n, timeZone); - expect(zonedDateTime.nanosecond).toBe(123); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.ZonedDateTime object", () => { - expect(() => { - Reflect.get(Temporal.ZonedDateTime.prototype, "nanosecond", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.ZonedDateTime"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.offset.js b/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.offset.js deleted file mode 100644 index 9778fb70a01..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.offset.js +++ /dev/null @@ -1,28 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = new Temporal.ZonedDateTime(0n, timeZone); - expect(zonedDateTime.offset).toBe("+00:00"); - }); - - test("custom offset", () => { - const timeZone = new Temporal.TimeZone("+01:30"); - const zonedDateTime = new Temporal.ZonedDateTime(0n, timeZone); - expect(zonedDateTime.offset).toBe("+01:30"); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.ZonedDateTime object", () => { - expect(() => { - Reflect.get(Temporal.ZonedDateTime.prototype, "offset", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.ZonedDateTime"); - }); - - test("custom time zone doesn't have a getOffsetNanosecondsFor function", () => { - const zonedDateTime = new Temporal.ZonedDateTime(0n, {}); - expect(() => { - zonedDateTime.offset; - }).toThrowWithMessage(TypeError, "getOffsetNanosecondsFor is undefined"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.offsetNanoseconds.js b/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.offsetNanoseconds.js deleted file mode 100644 index 814db8b8926..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.offsetNanoseconds.js +++ /dev/null @@ -1,28 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = new Temporal.ZonedDateTime(0n, timeZone); - expect(zonedDateTime.offsetNanoseconds).toBe(0); - }); - - test("custom offset", () => { - const timeZone = new Temporal.TimeZone("+01:30"); - const zonedDateTime = new Temporal.ZonedDateTime(0n, timeZone); - expect(zonedDateTime.offsetNanoseconds).toBe(5400000000000); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.ZonedDateTime object", () => { - expect(() => { - Reflect.get(Temporal.ZonedDateTime.prototype, "offsetNanoseconds", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.ZonedDateTime"); - }); - - test("custom time zone doesn't have a getOffsetNanosecondsFor function", () => { - const zonedDateTime = new Temporal.ZonedDateTime(0n, {}); - expect(() => { - zonedDateTime.offsetNanoseconds; - }).toThrowWithMessage(TypeError, "getOffsetNanosecondsFor is undefined"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.round.js b/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.round.js deleted file mode 100644 index 66397b41208..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.round.js +++ /dev/null @@ -1,146 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.ZonedDateTime.prototype.round).toHaveLength(1); - }); - - test("basic functionality", () => { - const zonedDateTime = new Temporal.ZonedDateTime( - 1111111111111n, - new Temporal.TimeZone("UTC") - ); - expect(zonedDateTime.round({ smallestUnit: "second" }).epochNanoseconds).toBe( - 1111000000000n - ); - expect( - zonedDateTime.round({ smallestUnit: "second", roundingMode: "ceil" }).epochNanoseconds - ).toBe(1112000000000n); - expect( - zonedDateTime.round({ - smallestUnit: "minute", - roundingIncrement: 30, - roundingMode: "floor", - }).epochNanoseconds - ).toBe(0n); - expect( - zonedDateTime.round({ - smallestUnit: "minute", - roundingIncrement: 30, - roundingMode: "halfExpand", - }).epochNanoseconds - ).toBe(1800000000000n); - }); - - test("string argument is implicitly converted to options object", () => { - const zonedDateTime = new Temporal.ZonedDateTime( - 1111111111111n, - new Temporal.TimeZone("UTC") - ); - expect( - zonedDateTime.round("second").equals(zonedDateTime.round({ smallestUnit: "second" })) - ).toBeTrue(); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.ZonedDateTime object", () => { - expect(() => { - Temporal.ZonedDateTime.prototype.round.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.ZonedDateTime"); - }); - - test("missing options object", () => { - const zonedDateTime = new Temporal.ZonedDateTime(1n, new Temporal.TimeZone("UTC")); - expect(() => { - zonedDateTime.round(); - }).toThrowWithMessage(TypeError, "Required options object is missing or undefined"); - }); - - test("invalid rounding mode", () => { - const zonedDateTime = new Temporal.ZonedDateTime(1n, new Temporal.TimeZone("UTC")); - expect(() => { - zonedDateTime.round({ smallestUnit: "second", roundingMode: "serenityOS" }); - }).toThrowWithMessage( - RangeError, - "serenityOS is not a valid value for option roundingMode" - ); - }); - - test("invalid smallest unit", () => { - const zonedDateTime = new Temporal.ZonedDateTime(1n, new Temporal.TimeZone("UTC")); - expect(() => { - zonedDateTime.round({ smallestUnit: "serenityOS" }); - }).toThrowWithMessage( - RangeError, - "serenityOS is not a valid value for option smallestUnit" - ); - }); - - test("increment may not be NaN", () => { - const zonedDateTime = new Temporal.ZonedDateTime(1n, new Temporal.TimeZone("UTC")); - expect(() => { - zonedDateTime.round({ smallestUnit: "second", roundingIncrement: NaN }); - }).toThrowWithMessage(RangeError, "NaN is not a valid value for option roundingIncrement"); - }); - - test("increment may smaller than 1 or larger than maximum", () => { - const zonedDateTime = new Temporal.ZonedDateTime(1n, new Temporal.TimeZone("UTC")); - expect(() => { - zonedDateTime.round({ smallestUnit: "second", roundingIncrement: -1 }); - }).toThrowWithMessage(RangeError, "-1 is not a valid value for option roundingIncrement"); - expect(() => { - zonedDateTime.round({ smallestUnit: "second", roundingIncrement: 0 }); - }).toThrowWithMessage(RangeError, "0 is not a valid value for option roundingIncrement"); - expect(() => { - zonedDateTime.round({ smallestUnit: "second", roundingIncrement: Infinity }); - }).toThrowWithMessage(RangeError, "inf is not a valid value for option roundingIncrement"); - }); - - test("calendar with zero-length days", () => { - const calendar = { - dateAdd(date) { - return date; - }, - }; - - const zonedDateTime = new Temporal.ZonedDateTime( - 1n, - new Temporal.TimeZone("UTC"), - calendar - ); - - expect(() => { - zonedDateTime.round({ smallestUnit: "second" }); - }).toThrowWithMessage( - RangeError, - "Cannot round a ZonedDateTime in a calendar or time zone that has zero or negative length days" - ); - }); - - test("time zone with negative length days", () => { - class CustomTimeZone extends Temporal.TimeZone { - constructor() { - super("UTC"); - this.getPossibleInstantsForCallCount = 0; - } - - getPossibleInstantsFor(temporalDateTime) { - this.getPossibleInstantsForCallCount++; - - if (this.getPossibleInstantsForCallCount === 2) { - return [new Temporal.Instant(-1n)]; - } - - return super.getPossibleInstantsFor(temporalDateTime); - } - } - - const zonedDateTime = new Temporal.ZonedDateTime(1n, new CustomTimeZone()); - - expect(() => { - zonedDateTime.round({ smallestUnit: "second" }); - }).toThrowWithMessage( - RangeError, - "Cannot round a ZonedDateTime in a calendar or time zone that has zero or negative length days" - ); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.second.js b/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.second.js deleted file mode 100644 index c759b0d73b7..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.second.js +++ /dev/null @@ -1,15 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = new Temporal.ZonedDateTime(1625614921000000000n, timeZone); - expect(zonedDateTime.second).toBe(1); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.ZonedDateTime object", () => { - expect(() => { - Reflect.get(Temporal.ZonedDateTime.prototype, "second", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.ZonedDateTime"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.since.js b/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.since.js deleted file mode 100644 index 4f5252e0b1c..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.since.js +++ /dev/null @@ -1,342 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.ZonedDateTime.prototype.since).toHaveLength(1); - }); - - test("basic functionality", () => { - const values = [ - [0n, 0n, "PT0S"], - [2345679011n, 123456789n, "PT2.222222222S"], - [123456789n, 0n, "PT0.123456789S"], - [0n, 123456789n, "-PT0.123456789S"], - [123456789123456789n, 0n, "PT34293H33M9.123456789S"], - [0n, 123456789123456789n, "-PT34293H33M9.123456789S"], - ]; - const utc = new Temporal.TimeZone("UTC"); - for (const [arg, argOther, expected] of values) { - const zonedDateTime = new Temporal.ZonedDateTime(arg, utc); - const other = new Temporal.ZonedDateTime(argOther, utc); - expect(zonedDateTime.since(other).toString()).toBe(expected); - } - }); - - test("smallestUnit option", () => { - const utc = new Temporal.TimeZone("UTC"); - const zonedDateTime = new Temporal.ZonedDateTime(34401906007008009n, utc); - const other = new Temporal.ZonedDateTime(0n, utc); - const values = [ - ["year", "P1Y"], - ["month", "P13M"], - ["week", "P56W"], - ["day", "P398D"], - ["hour", "PT9556H"], - ["minute", "PT9556H5M"], - ["second", "PT9556H5M6S"], - ["millisecond", "PT9556H5M6.007S"], - ["microsecond", "PT9556H5M6.007008S"], - ["nanosecond", "PT9556H5M6.007008009S"], - ]; - for (const [smallestUnit, expected] of values) { - expect(zonedDateTime.since(other, { smallestUnit }).toString()).toBe(expected); - } - }); - - test("largestUnit option", () => { - const utc = new Temporal.TimeZone("UTC"); - const zonedDateTime = new Temporal.ZonedDateTime(34401906007008009n, utc); - const other = new Temporal.ZonedDateTime(0n, utc); - const values = [ - ["year", "P1Y1M2DT4H5M6.007008009S"], - ["month", "P13M2DT4H5M6.007008009S"], - ["week", "P56W6DT4H5M6.007008009S"], - ["day", "P398DT4H5M6.007008009S"], - ["hour", "PT9556H5M6.007008009S"], - ["minute", "PT573365M6.007008009S"], - ["second", "PT34401906.007008009S"], - ["millisecond", "PT34401906.007008009S"], - ["microsecond", "PT34401906.007008009S"], - ["nanosecond", "PT34401906.007008008S"], - ]; - for (const [largestUnit, expected] of values) { - expect(zonedDateTime.since(other, { largestUnit }).toString()).toBe(expected); - } - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.ZonedDateTime object", () => { - expect(() => { - Temporal.ZonedDateTime.prototype.since.call("foo", {}); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.ZonedDateTime"); - }); - - test("cannot compare dates from different calendars", () => { - const calendarOne = { - toString() { - return "calendarOne"; - }, - }; - - const calendarTwo = { - toString() { - return "calendarTwo"; - }, - }; - - const utc = new Temporal.TimeZone("UTC"); - const zonedDateTimeOne = new Temporal.ZonedDateTime(0n, utc, calendarOne); - const zonedDateTimeTwo = new Temporal.ZonedDateTime(0n, utc, calendarTwo); - - expect(() => { - zonedDateTimeOne.since(zonedDateTimeTwo); - }).toThrowWithMessage(RangeError, "Cannot compare dates from two different calendars"); - }); - - test("cannot compare dates from different time zones", () => { - const timeZoneOne = { - toString() { - return "timeZoneOne"; - }, - }; - - const timeZoneTwo = { - toString() { - return "timeZoneTwo"; - }, - }; - - const zonedDateTimeOne = new Temporal.ZonedDateTime(0n, timeZoneOne); - const zonedDateTimeTwo = new Temporal.ZonedDateTime(0n, timeZoneTwo); - - expect(() => { - zonedDateTimeOne.since(zonedDateTimeTwo, { largestUnit: "day" }); - }).toThrowWithMessage(RangeError, "Cannot compare dates from two different time zones"); - }); -}); - -describe("rounding modes", () => { - const earlier = new Temporal.ZonedDateTime( - 1546935756_123_456_789n /* 2019-01-08T08:22:36.123456789+00:00 */, - "UTC" - ); - const later = new Temporal.ZonedDateTime( - 1631018380_987_654_289n /* 2021-09-07T12:39:40.987654289+00:00 */, - "UTC" - ); - - test("'ceil' rounding mode", () => { - const expected = [ - ["years", "P3Y", "-P2Y"], - ["months", "P32M", "-P31M"], - ["weeks", "P140W", "-P139W"], - ["days", "P974D", "-P973D"], - ["hours", "PT23357H", "-PT23356H"], - ["minutes", "PT23356H18M", "-PT23356H17M"], - ["seconds", "PT23356H17M5S", "-PT23356H17M4S"], - ["milliseconds", "PT23356H17M4.865S", "-PT23356H17M4.864S"], - ["microseconds", "PT23356H17M4.864198S", "-PT23356H17M4.864197S"], - ["nanoseconds", "PT23356H17M4.8641975S", "-PT23356H17M4.8641975S"], - ]; - - const roundingMode = "ceil"; - expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => { - const sincePositive = later.since(earlier, { smallestUnit, roundingMode }); - expect(sincePositive.toString()).toBe(expectedPositive); - - const sinceNegative = earlier.since(later, { smallestUnit, roundingMode }); - expect(sinceNegative.toString()).toBe(expectedNegative); - }); - }); - - test("'expand' rounding mode", () => { - const expected = [ - ["years", "P3Y", "-P3Y"], - ["months", "P32M", "-P32M"], - ["weeks", "P140W", "-P140W"], - ["days", "P974D", "-P974D"], - ["hours", "PT23357H", "-PT23357H"], - ["minutes", "PT23356H18M", "-PT23356H18M"], - ["seconds", "PT23356H17M5S", "-PT23356H17M5S"], - ["milliseconds", "PT23356H17M4.865S", "-PT23356H17M4.865S"], - ["microseconds", "PT23356H17M4.864198S", "-PT23356H17M4.864198S"], - ["nanoseconds", "PT23356H17M4.8641975S", "-PT23356H17M4.8641975S"], - ]; - - const roundingMode = "expand"; - expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => { - const sincePositive = later.since(earlier, { smallestUnit, roundingMode }); - expect(sincePositive.toString()).toBe(expectedPositive); - - const sinceNegative = earlier.since(later, { smallestUnit, roundingMode }); - expect(sinceNegative.toString()).toBe(expectedNegative); - }); - }); - - test("'floor' rounding mode", () => { - const expected = [ - ["years", "P2Y", "-P3Y"], - ["months", "P31M", "-P32M"], - ["weeks", "P139W", "-P140W"], - ["days", "P973D", "-P974D"], - ["hours", "PT23356H", "-PT23357H"], - ["minutes", "PT23356H17M", "-PT23356H18M"], - ["seconds", "PT23356H17M4S", "-PT23356H17M5S"], - ["milliseconds", "PT23356H17M4.864S", "-PT23356H17M4.865S"], - ["microseconds", "PT23356H17M4.864197S", "-PT23356H17M4.864198S"], - ["nanoseconds", "PT23356H17M4.8641975S", "-PT23356H17M4.8641975S"], - ]; - - const roundingMode = "floor"; - expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => { - const sincePositive = later.since(earlier, { smallestUnit, roundingMode }); - expect(sincePositive.toString()).toBe(expectedPositive); - - const sinceNegative = earlier.since(later, { smallestUnit, roundingMode }); - expect(sinceNegative.toString()).toBe(expectedNegative); - }); - }); - - test("'trunc' rounding mode", () => { - const expected = [ - ["years", "P2Y", "-P2Y"], - ["months", "P31M", "-P31M"], - ["weeks", "P139W", "-P139W"], - ["days", "P973D", "-P973D"], - ["hours", "PT23356H", "-PT23356H"], - ["minutes", "PT23356H17M", "-PT23356H17M"], - ["seconds", "PT23356H17M4S", "-PT23356H17M4S"], - ["milliseconds", "PT23356H17M4.864S", "-PT23356H17M4.864S"], - ["microseconds", "PT23356H17M4.864197S", "-PT23356H17M4.864197S"], - ["nanoseconds", "PT23356H17M4.8641975S", "-PT23356H17M4.8641975S"], - ]; - - const roundingMode = "trunc"; - expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => { - const sincePositive = later.since(earlier, { smallestUnit, roundingMode }); - expect(sincePositive.toString()).toBe(expectedPositive); - - const sinceNegative = earlier.since(later, { smallestUnit, roundingMode }); - expect(sinceNegative.toString()).toBe(expectedNegative); - }); - }); - - test("'halfCeil' rounding mode", () => { - const expected = [ - ["years", "P3Y", "-P3Y"], - ["months", "P32M", "-P32M"], - ["weeks", "P139W", "-P139W"], - ["days", "P973D", "-P973D"], - ["hours", "PT23356H", "-PT23356H"], - ["minutes", "PT23356H17M", "-PT23356H17M"], - ["seconds", "PT23356H17M5S", "-PT23356H17M5S"], - ["milliseconds", "PT23356H17M4.864S", "-PT23356H17M4.864S"], - ["microseconds", "PT23356H17M4.864198S", "-PT23356H17M4.864197S"], - ["nanoseconds", "PT23356H17M4.8641975S", "-PT23356H17M4.8641975S"], - ]; - - const roundingMode = "halfCeil"; - expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => { - const sincePositive = later.since(earlier, { smallestUnit, roundingMode }); - expect(sincePositive.toString()).toBe(expectedPositive); - - const sinceNegative = earlier.since(later, { smallestUnit, roundingMode }); - expect(sinceNegative.toString()).toBe(expectedNegative); - }); - }); - - test("'halfEven' rounding mode", () => { - const expected = [ - ["years", "P3Y", "-P3Y"], - ["months", "P32M", "-P32M"], - ["weeks", "P139W", "-P139W"], - ["days", "P973D", "-P973D"], - ["hours", "PT23356H", "-PT23356H"], - ["minutes", "PT23356H17M", "-PT23356H17M"], - ["seconds", "PT23356H17M5S", "-PT23356H17M5S"], - ["milliseconds", "PT23356H17M4.864S", "-PT23356H17M4.864S"], - ["microseconds", "PT23356H17M4.864198S", "-PT23356H17M4.864198S"], - ["nanoseconds", "PT23356H17M4.8641975S", "-PT23356H17M4.8641975S"], - ]; - - const roundingMode = "halfEven"; - expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => { - const sincePositive = later.since(earlier, { smallestUnit, roundingMode }); - expect(sincePositive.toString()).toBe(expectedPositive); - - const sinceNegative = earlier.since(later, { smallestUnit, roundingMode }); - expect(sinceNegative.toString()).toBe(expectedNegative); - }); - }); - - test("'halfTrunc' rounding mode", () => { - const expected = [ - ["years", "P3Y", "-P3Y"], - ["months", "P32M", "-P32M"], - ["weeks", "P139W", "-P139W"], - ["days", "P973D", "-P973D"], - ["hours", "PT23356H", "-PT23356H"], - ["minutes", "PT23356H17M", "-PT23356H17M"], - ["seconds", "PT23356H17M5S", "-PT23356H17M5S"], - ["milliseconds", "PT23356H17M4.864S", "-PT23356H17M4.864S"], - ["microseconds", "PT23356H17M4.864197S", "-PT23356H17M4.864197S"], - ["nanoseconds", "PT23356H17M4.8641975S", "-PT23356H17M4.8641975S"], - ]; - - const roundingMode = "halfTrunc"; - expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => { - const sincePositive = later.since(earlier, { smallestUnit, roundingMode }); - expect(sincePositive.toString()).toBe(expectedPositive); - - const sinceNegative = earlier.since(later, { smallestUnit, roundingMode }); - expect(sinceNegative.toString()).toBe(expectedNegative); - }); - }); - - test("'halfExpand' rounding mode", () => { - const expected = [ - ["years", "P3Y", "-P3Y"], - ["months", "P32M", "-P32M"], - ["weeks", "P139W", "-P139W"], - ["days", "P973D", "-P973D"], - ["hours", "PT23356H", "-PT23356H"], - ["minutes", "PT23356H17M", "-PT23356H17M"], - ["seconds", "PT23356H17M5S", "-PT23356H17M5S"], - ["milliseconds", "PT23356H17M4.864S", "-PT23356H17M4.864S"], - ["microseconds", "PT23356H17M4.864198S", "-PT23356H17M4.864198S"], - ["nanoseconds", "PT23356H17M4.8641975S", "-PT23356H17M4.8641975S"], - ]; - - const roundingMode = "halfExpand"; - expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => { - const sincePositive = later.since(earlier, { smallestUnit, roundingMode }); - expect(sincePositive.toString()).toBe(expectedPositive); - - const sinceNegative = earlier.since(later, { smallestUnit, roundingMode }); - expect(sinceNegative.toString()).toBe(expectedNegative); - }); - }); - - test("'halfFloor' rounding mode", () => { - const expected = [ - ["years", "P3Y", "-P3Y"], - ["months", "P32M", "-P32M"], - ["weeks", "P139W", "-P139W"], - ["days", "P973D", "-P973D"], - ["hours", "PT23356H", "-PT23356H"], - ["minutes", "PT23356H17M", "-PT23356H17M"], - ["seconds", "PT23356H17M5S", "-PT23356H17M5S"], - ["milliseconds", "PT23356H17M4.864S", "-PT23356H17M4.864S"], - ["microseconds", "PT23356H17M4.864197S", "-PT23356H17M4.864198S"], - ["nanoseconds", "PT23356H17M4.8641975S", "-PT23356H17M4.8641975S"], - ]; - - const roundingMode = "halfFloor"; - expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => { - const sincePositive = later.since(earlier, { smallestUnit, roundingMode }); - expect(sincePositive.toString()).toBe(expectedPositive); - - const sinceNegative = earlier.since(later, { smallestUnit, roundingMode }); - expect(sinceNegative.toString()).toBe(expectedNegative); - }); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.startOfDay.js b/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.startOfDay.js deleted file mode 100644 index d95402e5e08..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.startOfDay.js +++ /dev/null @@ -1,45 +0,0 @@ -describe("correct behavior", () => { - test("length is 0", () => { - expect(Temporal.ZonedDateTime.prototype.startOfDay).toHaveLength(0); - }); - - test("basic functionality", () => { - const plainDateTime = new Temporal.PlainDateTime(2021, 11, 3, 20, 9, 45, 100, 200, 300); - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = plainDateTime.toZonedDateTime(timeZone); - const startOfDayZonedDateTime = zonedDateTime.startOfDay(); - - expect(startOfDayZonedDateTime.epochNanoseconds).toBe(1635897600000000000n); - expect(startOfDayZonedDateTime.epochMicroseconds).toBe(1635897600000000n); - expect(startOfDayZonedDateTime.epochMilliseconds).toBe(1635897600000); - expect(startOfDayZonedDateTime.epochSeconds).toBe(1635897600); - expect(startOfDayZonedDateTime.year).toBe(2021); - expect(startOfDayZonedDateTime.month).toBe(11); - expect(startOfDayZonedDateTime.monthCode).toBe("M11"); - expect(startOfDayZonedDateTime.day).toBe(3); - expect(startOfDayZonedDateTime.hour).toBe(0); - expect(startOfDayZonedDateTime.minute).toBe(0); - expect(startOfDayZonedDateTime.second).toBe(0); - expect(startOfDayZonedDateTime.millisecond).toBe(0); - expect(startOfDayZonedDateTime.microsecond).toBe(0); - expect(startOfDayZonedDateTime.nanosecond).toBe(0); - expect(startOfDayZonedDateTime.dayOfWeek).toBe(3); - expect(startOfDayZonedDateTime.dayOfYear).toBe(307); - expect(startOfDayZonedDateTime.weekOfYear).toBe(44); - expect(startOfDayZonedDateTime.hoursInDay).toBe(24); - expect(startOfDayZonedDateTime.daysInWeek).toBe(7); - expect(startOfDayZonedDateTime.daysInYear).toBe(365); - expect(startOfDayZonedDateTime.monthsInYear).toBe(12); - expect(startOfDayZonedDateTime.inLeapYear).toBeFalse(); - expect(startOfDayZonedDateTime.offset).toBe("+00:00"); - expect(startOfDayZonedDateTime.offsetNanoseconds).toBe(0); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.ZonedDateTime object", () => { - expect(() => { - Temporal.ZonedDateTime.prototype.startOfDay.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.ZonedDateTime"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.subtract.js b/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.subtract.js deleted file mode 100644 index 6da505976a6..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.subtract.js +++ /dev/null @@ -1,61 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.ZonedDateTime.prototype.subtract).toHaveLength(1); - }); - - test("basic functionality", () => { - const plainDateTime = new Temporal.PlainDateTime(2021, 11, 12, 0, 22, 30, 100, 200, 300); - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = plainDateTime.toZonedDateTime(timeZone); - const dayDuration = new Temporal.Duration(0, 0, 0, 1); - const result = zonedDateTime.subtract(dayDuration); - - expect(zonedDateTime.day).toBe(12); - expect(zonedDateTime.epochNanoseconds).toBe(1636676550100200300n); - - expect(result.day).toBe(11); - expect(result.epochNanoseconds).toBe(1636590150100200300n); - }); - - test("duration-like object", () => { - const plainDateTime = new Temporal.PlainDateTime(2021, 11, 12, 0, 22, 30, 100, 200, 300); - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = plainDateTime.toZonedDateTime(timeZone); - const dayDuration = { days: 1 }; - const result = zonedDateTime.subtract(dayDuration); - - expect(zonedDateTime.day).toBe(12); - expect(zonedDateTime.epochNanoseconds).toBe(1636676550100200300n); - - expect(result.day).toBe(11); - expect(result.epochNanoseconds).toBe(1636590150100200300n); - }); - - test("duration string", () => { - const plainDateTime = new Temporal.PlainDateTime(2021, 11, 12, 0, 22, 30, 100, 200, 300); - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = plainDateTime.toZonedDateTime(timeZone); - const dayDuration = "P1D"; - const result = zonedDateTime.subtract(dayDuration); - - expect(zonedDateTime.day).toBe(12); - expect(zonedDateTime.epochNanoseconds).toBe(1636676550100200300n); - - expect(result.day).toBe(11); - expect(result.epochNanoseconds).toBe(1636590150100200300n); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.ZonedDateTime object", () => { - expect(() => { - Temporal.ZonedDateTime.prototype.subtract.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.ZonedDateTime"); - }); - - test("invalid duration-like object", () => { - expect(() => { - new Temporal.ZonedDateTime(1n, {}).subtract({}); - }).toThrowWithMessage(TypeError, "Invalid duration-like object"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.timeZone.js b/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.timeZone.js deleted file mode 100644 index 21c97b56795..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.timeZone.js +++ /dev/null @@ -1,15 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = new Temporal.ZonedDateTime(0n, timeZone); - expect(zonedDateTime.timeZone).toBe(timeZone); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.ZonedDateTime object", () => { - expect(() => { - Reflect.get(Temporal.ZonedDateTime.prototype, "timeZone", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.ZonedDateTime"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.toInstant.js b/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.toInstant.js deleted file mode 100644 index 453779f603f..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.toInstant.js +++ /dev/null @@ -1,21 +0,0 @@ -describe("correct behavior", () => { - test("length is 0", () => { - expect(Temporal.ZonedDateTime.prototype.toInstant).toHaveLength(0); - }); - - test("basic functionality", () => { - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = new Temporal.ZonedDateTime(1625614921000000000n, timeZone); - const instant = zonedDateTime.toInstant(); - expect(instant).toBeInstanceOf(Temporal.Instant); - expect(instant.epochNanoseconds).toBe(1625614921000000000n); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.ZonedDateTime object", () => { - expect(() => { - Temporal.ZonedDateTime.prototype.toInstant.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.ZonedDateTime"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.toJSON.js b/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.toJSON.js deleted file mode 100644 index 37924955f90..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.toJSON.js +++ /dev/null @@ -1,27 +0,0 @@ -describe("correct behavior", () => { - test("length is 0", () => { - expect(Temporal.ZonedDateTime.prototype.toJSON).toHaveLength(0); - }); - - test("basic functionality", () => { - const plainDateTime = new Temporal.PlainDateTime(2021, 11, 3, 1, 33, 5, 100, 200, 300); - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = plainDateTime.toZonedDateTime(timeZone); - expect(zonedDateTime.toJSON()).toBe("2021-11-03T01:33:05.1002003+00:00[UTC]"); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.ZonedDateTime object", () => { - expect(() => { - Temporal.ZonedDateTime.prototype.toJSON.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.ZonedDateTime"); - }); - - test("custom time zone doesn't have a getOffsetNanosecondsFor function", () => { - const zonedDateTime = new Temporal.ZonedDateTime(0n, {}); - expect(() => { - zonedDateTime.toJSON(); - }).toThrowWithMessage(TypeError, "getOffsetNanosecondsFor is undefined"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.toLocaleString.js b/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.toLocaleString.js deleted file mode 100644 index 7e43fedb300..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.toLocaleString.js +++ /dev/null @@ -1,27 +0,0 @@ -describe("correct behavior", () => { - test("length is 0", () => { - expect(Temporal.ZonedDateTime.prototype.toLocaleString).toHaveLength(0); - }); - - test("basic functionality", () => { - const plainDateTime = new Temporal.PlainDateTime(2021, 11, 3, 1, 33, 5, 100, 200, 300); - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = plainDateTime.toZonedDateTime(timeZone); - expect(zonedDateTime.toLocaleString()).toBe("2021-11-03T01:33:05.1002003+00:00[UTC]"); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.ZonedDateTime object", () => { - expect(() => { - Temporal.ZonedDateTime.prototype.toLocaleString.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.ZonedDateTime"); - }); - - test("custom time zone doesn't have a getOffsetNanosecondsFor function", () => { - const zonedDateTime = new Temporal.ZonedDateTime(0n, {}); - expect(() => { - zonedDateTime.toLocaleString(); - }).toThrowWithMessage(TypeError, "getOffsetNanosecondsFor is undefined"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.toPlainDate.js b/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.toPlainDate.js deleted file mode 100644 index 9cd4ae467a5..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.toPlainDate.js +++ /dev/null @@ -1,23 +0,0 @@ -describe("correct behavior", () => { - test("length is 0", () => { - expect(Temporal.ZonedDateTime.prototype.toPlainDate).toHaveLength(0); - }); - - test("basic functionality", () => { - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = new Temporal.ZonedDateTime(1625614921000000000n, timeZone); - const plainDate = zonedDateTime.toPlainDate(); - expect(plainDate).toBeInstanceOf(Temporal.PlainDate); - expect(plainDate.year).toBe(2021); - expect(plainDate.month).toBe(7); - expect(plainDate.day).toBe(6); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.ZonedDateTime object", () => { - expect(() => { - Temporal.ZonedDateTime.prototype.toPlainDate.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.ZonedDateTime"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.toPlainDateTime.js b/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.toPlainDateTime.js deleted file mode 100644 index cc8013ecaec..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.toPlainDateTime.js +++ /dev/null @@ -1,29 +0,0 @@ -describe("correct behavior", () => { - test("length is 0", () => { - expect(Temporal.ZonedDateTime.prototype.toPlainDateTime).toHaveLength(0); - }); - - test("basic functionality", () => { - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = new Temporal.ZonedDateTime(1625614921000000000n, timeZone); - const plainDateTime = zonedDateTime.toPlainDateTime(); - expect(plainDateTime).toBeInstanceOf(Temporal.PlainDateTime); - expect(plainDateTime.year).toBe(2021); - expect(plainDateTime.month).toBe(7); - expect(plainDateTime.day).toBe(6); - expect(plainDateTime.hour).toBe(23); - expect(plainDateTime.minute).toBe(42); - expect(plainDateTime.second).toBe(1); - expect(plainDateTime.millisecond).toBe(0); - expect(plainDateTime.microsecond).toBe(0); - expect(plainDateTime.nanosecond).toBe(0); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.ZonedDateTime object", () => { - expect(() => { - Temporal.ZonedDateTime.prototype.toPlainDateTime.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.ZonedDateTime"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.toPlainMonthDay.js b/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.toPlainMonthDay.js deleted file mode 100644 index 7189d01b04a..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.toPlainMonthDay.js +++ /dev/null @@ -1,14 +0,0 @@ -describe("correct behavior", () => { - test("length is 0", () => { - expect(Temporal.ZonedDateTime.prototype.toPlainMonthDay).toHaveLength(0); - }); - - test("basic functionality", () => { - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = new Temporal.ZonedDateTime(1625614921000000000n, timeZone); - const plainMonthDay = zonedDateTime.toPlainMonthDay(); - expect(plainMonthDay.calendar).toBe(zonedDateTime.calendar); - expect(plainMonthDay.monthCode).toBe("M07"); - expect(plainMonthDay.day).toBe(6); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.toPlainTime.js b/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.toPlainTime.js deleted file mode 100644 index 6d2586e1d1b..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.toPlainTime.js +++ /dev/null @@ -1,26 +0,0 @@ -describe("correct behavior", () => { - test("length is 0", () => { - expect(Temporal.ZonedDateTime.prototype.toPlainTime).toHaveLength(0); - }); - - test("basic functionality", () => { - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = new Temporal.ZonedDateTime(1625614921000000000n, timeZone); - const plainTime = zonedDateTime.toPlainTime(); - expect(plainTime).toBeInstanceOf(Temporal.PlainTime); - expect(plainTime.hour).toBe(23); - expect(plainTime.minute).toBe(42); - expect(plainTime.second).toBe(1); - expect(plainTime.millisecond).toBe(0); - expect(plainTime.microsecond).toBe(0); - expect(plainTime.nanosecond).toBe(0); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.ZonedDateTime object", () => { - expect(() => { - Temporal.ZonedDateTime.prototype.toPlainTime.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.ZonedDateTime"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.toPlainYearMonth.js b/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.toPlainYearMonth.js deleted file mode 100644 index 254bb0b40c1..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.toPlainYearMonth.js +++ /dev/null @@ -1,14 +0,0 @@ -describe("correct behavior", () => { - test("length is 0", () => { - expect(Temporal.ZonedDateTime.prototype.toPlainYearMonth).toHaveLength(0); - }); - - test("basic functionality", () => { - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = new Temporal.ZonedDateTime(1625614921000000000n, timeZone); - const plainYearMonth = zonedDateTime.toPlainYearMonth(); - expect(plainYearMonth.calendar).toBe(zonedDateTime.calendar); - expect(plainYearMonth.year).toBe(2021); - expect(plainYearMonth.month).toBe(7); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.toString.js b/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.toString.js deleted file mode 100644 index 90bc7eae48b..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.toString.js +++ /dev/null @@ -1,168 +0,0 @@ -describe("correct behavior", () => { - test("length is 0", () => { - expect(Temporal.ZonedDateTime.prototype.toString).toHaveLength(0); - }); - - test("basic functionality", () => { - const plainDateTime = new Temporal.PlainDateTime(2021, 11, 3, 1, 33, 5, 100, 200, 300); - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = plainDateTime.toZonedDateTime(timeZone); - expect(zonedDateTime.toString()).toBe("2021-11-03T01:33:05.1002003+00:00[UTC]"); - }); - - test("negative epoch nanoseconds", () => { - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = new Temporal.ZonedDateTime(-999_999_999n, timeZone); - expect(zonedDateTime.toString()).toBe("1969-12-31T23:59:59.000000001+00:00[UTC]"); - }); - - test("fractionalSecondDigits option", () => { - const plainDateTime = new Temporal.PlainDateTime(2021, 11, 3, 1, 33, 5, 100, 200, 300); - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = plainDateTime.toZonedDateTime(timeZone); - const values = [ - ["auto", "2021-11-03T01:33:05.1002003+00:00[UTC]"], - [0, "2021-11-03T01:33:05+00:00[UTC]"], - [1, "2021-11-03T01:33:05.1+00:00[UTC]"], - [2, "2021-11-03T01:33:05.10+00:00[UTC]"], - [3, "2021-11-03T01:33:05.100+00:00[UTC]"], - [4, "2021-11-03T01:33:05.1002+00:00[UTC]"], - [5, "2021-11-03T01:33:05.10020+00:00[UTC]"], - [6, "2021-11-03T01:33:05.100200+00:00[UTC]"], - [7, "2021-11-03T01:33:05.1002003+00:00[UTC]"], - [8, "2021-11-03T01:33:05.10020030+00:00[UTC]"], - [9, "2021-11-03T01:33:05.100200300+00:00[UTC]"], - ]; - - for (const [fractionalSecondDigits, expected] of values) { - const options = { fractionalSecondDigits }; - expect(zonedDateTime.toString(options)).toBe(expected); - } - - // Ignored when smallestUnit is given - expect(zonedDateTime.toString({ smallestUnit: "minute", fractionalSecondDigits: 9 })).toBe( - "2021-11-03T01:33+00:00[UTC]" - ); - }); - - test("smallestUnit option", () => { - const plainDateTime = new Temporal.PlainDateTime(2021, 11, 3, 1, 33, 5, 100, 200, 300); - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = plainDateTime.toZonedDateTime(timeZone); - const values = [ - ["minute", "2021-11-03T01:33+00:00[UTC]"], - ["second", "2021-11-03T01:33:05+00:00[UTC]"], - ["millisecond", "2021-11-03T01:33:05.100+00:00[UTC]"], - ["microsecond", "2021-11-03T01:33:05.100200+00:00[UTC]"], - ["nanosecond", "2021-11-03T01:33:05.100200300+00:00[UTC]"], - ]; - - for (const [smallestUnit, expected] of values) { - const singularOptions = { smallestUnit }; - const pluralOptions = { smallestUnit: `${smallestUnit}s` }; - expect(zonedDateTime.toString(singularOptions)).toBe(expected); - expect(zonedDateTime.toString(pluralOptions)).toBe(expected); - } - }); - - test("timeZoneName option", () => { - const plainDateTime = new Temporal.PlainDateTime(2021, 11, 3, 1, 33, 5, 100, 200, 300); - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = plainDateTime.toZonedDateTime(timeZone); - const values = [ - ["auto", "2021-11-03T01:33:05.1002003+00:00[UTC]"], - ["never", "2021-11-03T01:33:05.1002003+00:00"], - ["critical", "2021-11-03T01:33:05.1002003+00:00[!UTC]"], - ]; - - for (const [timeZoneName, expected] of values) { - const options = { timeZoneName }; - expect(zonedDateTime.toString(options)).toBe(expected); - } - }); - - test("offset option", () => { - const plainDateTime = new Temporal.PlainDateTime(2021, 11, 3, 1, 33, 5, 100, 200, 300); - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = plainDateTime.toZonedDateTime(timeZone); - const values = [ - ["auto", "2021-11-03T01:33:05.1002003+00:00[UTC]"], - ["never", "2021-11-03T01:33:05.1002003[UTC]"], - ]; - - for (const [offset, expected] of values) { - const options = { offset }; - expect(zonedDateTime.toString(options)).toBe(expected); - } - }); - - test("doesn't call ToString on calendar if calenderName option is 'never'", () => { - let calledToString = false; - const calendar = { - toString() { - calledToString = true; - return "nocall"; - }, - }; - - const plainDateTime = new Temporal.PlainDateTime( - 2022, - 8, - 8, - 14, - 38, - 40, - 100, - 200, - 300, - calendar - ); - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = plainDateTime.toZonedDateTime(timeZone); - - const options = { - calendarName: "never", - }; - expect(zonedDateTime.toString(options)).toBe("2022-08-08T14:38:40.1002003+00:00[UTC]"); - expect(calledToString).toBeFalse(); - }); - - test("calendarName option", () => { - const plainDateTime = new Temporal.PlainDateTime(2022, 11, 2, 19, 4, 35, 100, 200, 300); - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = plainDateTime.toZonedDateTime(timeZone); - const values = [ - ["auto", "2022-11-02T19:04:35.1002003+00:00[UTC]"], - ["always", "2022-11-02T19:04:35.1002003+00:00[UTC][u-ca=iso8601]"], - ["never", "2022-11-02T19:04:35.1002003+00:00[UTC]"], - ["critical", "2022-11-02T19:04:35.1002003+00:00[UTC][!u-ca=iso8601]"], - ]; - - for (const [calendarName, expected] of values) { - const options = { calendarName }; - expect(zonedDateTime.toString(options)).toBe(expected); - } - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.ZonedDateTime object", () => { - expect(() => { - Temporal.ZonedDateTime.prototype.toString.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.ZonedDateTime"); - }); - - test("custom time zone doesn't have a getOffsetNanosecondsFor function", () => { - const zonedDateTime = new Temporal.ZonedDateTime(0n, {}); - expect(() => { - zonedDateTime.toString(); - }).toThrowWithMessage(TypeError, "getOffsetNanosecondsFor is undefined"); - }); - - test("calendarName option must be one of 'auto', 'always', 'never', 'critical'", () => { - const zonedDateTime = new Temporal.ZonedDateTime(0n, "UTC"); - expect(() => { - zonedDateTime.toString({ calendarName: "foo" }); - }).toThrowWithMessage(RangeError, "foo is not a valid value for option calendarName"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.until.js b/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.until.js deleted file mode 100644 index d7c2658fab6..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.until.js +++ /dev/null @@ -1,342 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.ZonedDateTime.prototype.until).toHaveLength(1); - }); - - test("basic functionality", () => { - const values = [ - [0n, 0n, "PT0S"], - [123456789n, 2345679011n, "PT2.222222222S"], - [0n, 123456789n, "PT0.123456789S"], - [123456789n, 0n, "-PT0.123456789S"], - [0n, 123456789123456789n, "PT34293H33M9.123456789S"], - [123456789123456789n, 0n, "-PT34293H33M9.123456789S"], - ]; - const utc = new Temporal.TimeZone("UTC"); - for (const [arg, argOther, expected] of values) { - const zonedDateTime = new Temporal.ZonedDateTime(arg, utc); - const other = new Temporal.ZonedDateTime(argOther, utc); - expect(zonedDateTime.until(other).toString()).toBe(expected); - } - }); - - test("smallestUnit option", () => { - const utc = new Temporal.TimeZone("UTC"); - const zonedDateTime = new Temporal.ZonedDateTime(0n, utc); - const other = new Temporal.ZonedDateTime(34401906007008009n, utc); - const values = [ - ["year", "P1Y"], - ["month", "P13M"], - ["week", "P56W"], - ["day", "P398D"], - ["hour", "PT9556H"], - ["minute", "PT9556H5M"], - ["second", "PT9556H5M6S"], - ["millisecond", "PT9556H5M6.007S"], - ["microsecond", "PT9556H5M6.007008S"], - ["nanosecond", "PT9556H5M6.007008009S"], - ]; - for (const [smallestUnit, expected] of values) { - expect(zonedDateTime.until(other, { smallestUnit }).toString()).toBe(expected); - } - }); - - test("largestUnit option", () => { - const utc = new Temporal.TimeZone("UTC"); - const zonedDateTime = new Temporal.ZonedDateTime(0n, utc); - const other = new Temporal.ZonedDateTime(34401906007008009n, utc); - const values = [ - ["year", "P1Y1M2DT4H5M6.007008009S"], - ["month", "P13M2DT4H5M6.007008009S"], - ["week", "P56W6DT4H5M6.007008009S"], - ["day", "P398DT4H5M6.007008009S"], - ["hour", "PT9556H5M6.007008009S"], - ["minute", "PT573365M6.007008009S"], - ["second", "PT34401906.007008009S"], - ["millisecond", "PT34401906.007008009S"], - ["microsecond", "PT34401906.007008009S"], - ["nanosecond", "PT34401906.007008008S"], - ]; - for (const [largestUnit, expected] of values) { - expect(zonedDateTime.until(other, { largestUnit }).toString()).toBe(expected); - } - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.ZonedDateTime object", () => { - expect(() => { - Temporal.ZonedDateTime.prototype.until.call("foo", {}); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.ZonedDateTime"); - }); - - test("cannot compare dates from different calendars", () => { - const calendarOne = { - toString() { - return "calendarOne"; - }, - }; - - const calendarTwo = { - toString() { - return "calendarTwo"; - }, - }; - - const utc = new Temporal.TimeZone("UTC"); - const zonedDateTimeOne = new Temporal.ZonedDateTime(0n, utc, calendarOne); - const zonedDateTimeTwo = new Temporal.ZonedDateTime(0n, utc, calendarTwo); - - expect(() => { - zonedDateTimeOne.until(zonedDateTimeTwo); - }).toThrowWithMessage(RangeError, "Cannot compare dates from two different calendars"); - }); - - test("cannot compare dates from different time zones", () => { - const timeZoneOne = { - toString() { - return "timeZoneOne"; - }, - }; - - const timeZoneTwo = { - toString() { - return "timeZoneTwo"; - }, - }; - - const zonedDateTimeOne = new Temporal.ZonedDateTime(0n, timeZoneOne); - const zonedDateTimeTwo = new Temporal.ZonedDateTime(0n, timeZoneTwo); - - expect(() => { - zonedDateTimeOne.until(zonedDateTimeTwo, { largestUnit: "day" }); - }).toThrowWithMessage(RangeError, "Cannot compare dates from two different time zones"); - }); -}); - -describe("rounding modes", () => { - const earlier = new Temporal.ZonedDateTime( - 1546935756_123_456_789n /* 2019-01-08T08:22:36.123456789+00:00 */, - "UTC" - ); - const later = new Temporal.ZonedDateTime( - 1631018380_987_654_289n /* 2021-09-07T12:39:40.987654289+00:00 */, - "UTC" - ); - - test("'ceil' rounding mode", () => { - const expected = [ - ["years", "P3Y", "-P2Y"], - ["months", "P32M", "-P31M"], - ["weeks", "P140W", "-P139W"], - ["days", "P974D", "-P973D"], - ["hours", "PT23357H", "-PT23356H"], - ["minutes", "PT23356H18M", "-PT23356H17M"], - ["seconds", "PT23356H17M5S", "-PT23356H17M4S"], - ["milliseconds", "PT23356H17M4.865S", "-PT23356H17M4.864S"], - ["microseconds", "PT23356H17M4.864198S", "-PT23356H17M4.864197S"], - ["nanoseconds", "PT23356H17M4.8641975S", "-PT23356H17M4.8641975S"], - ]; - - const roundingMode = "ceil"; - expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => { - const untilPositive = earlier.until(later, { smallestUnit, roundingMode }); - expect(untilPositive.toString()).toBe(expectedPositive); - - const untilNegative = later.until(earlier, { smallestUnit, roundingMode }); - expect(untilNegative.toString()).toBe(expectedNegative); - }); - }); - - test("'expand' rounding mode", () => { - const expected = [ - ["years", "P3Y", "-P3Y"], - ["months", "P32M", "-P32M"], - ["weeks", "P140W", "-P140W"], - ["days", "P974D", "-P974D"], - ["hours", "PT23357H", "-PT23357H"], - ["minutes", "PT23356H18M", "-PT23356H18M"], - ["seconds", "PT23356H17M5S", "-PT23356H17M5S"], - ["milliseconds", "PT23356H17M4.865S", "-PT23356H17M4.865S"], - ["microseconds", "PT23356H17M4.864198S", "-PT23356H17M4.864198S"], - ["nanoseconds", "PT23356H17M4.8641975S", "-PT23356H17M4.8641975S"], - ]; - - const roundingMode = "expand"; - expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => { - const untilPositive = earlier.until(later, { smallestUnit, roundingMode }); - expect(untilPositive.toString()).toBe(expectedPositive); - - const untilNegative = later.until(earlier, { smallestUnit, roundingMode }); - expect(untilNegative.toString()).toBe(expectedNegative); - }); - }); - - test("'floor' rounding mode", () => { - const expected = [ - ["years", "P2Y", "-P3Y"], - ["months", "P31M", "-P32M"], - ["weeks", "P139W", "-P140W"], - ["days", "P973D", "-P974D"], - ["hours", "PT23356H", "-PT23357H"], - ["minutes", "PT23356H17M", "-PT23356H18M"], - ["seconds", "PT23356H17M4S", "-PT23356H17M5S"], - ["milliseconds", "PT23356H17M4.864S", "-PT23356H17M4.865S"], - ["microseconds", "PT23356H17M4.864197S", "-PT23356H17M4.864198S"], - ["nanoseconds", "PT23356H17M4.8641975S", "-PT23356H17M4.8641975S"], - ]; - - const roundingMode = "floor"; - expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => { - const untilPositive = earlier.until(later, { smallestUnit, roundingMode }); - expect(untilPositive.toString()).toBe(expectedPositive); - - const untilNegative = later.until(earlier, { smallestUnit, roundingMode }); - expect(untilNegative.toString()).toBe(expectedNegative); - }); - }); - - test("'trunc' rounding mode", () => { - const expected = [ - ["years", "P2Y", "-P2Y"], - ["months", "P31M", "-P31M"], - ["weeks", "P139W", "-P139W"], - ["days", "P973D", "-P973D"], - ["hours", "PT23356H", "-PT23356H"], - ["minutes", "PT23356H17M", "-PT23356H17M"], - ["seconds", "PT23356H17M4S", "-PT23356H17M4S"], - ["milliseconds", "PT23356H17M4.864S", "-PT23356H17M4.864S"], - ["microseconds", "PT23356H17M4.864197S", "-PT23356H17M4.864197S"], - ["nanoseconds", "PT23356H17M4.8641975S", "-PT23356H17M4.8641975S"], - ]; - - const roundingMode = "trunc"; - expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => { - const untilPositive = earlier.until(later, { smallestUnit, roundingMode }); - expect(untilPositive.toString()).toBe(expectedPositive); - - const untilNegative = later.until(earlier, { smallestUnit, roundingMode }); - expect(untilNegative.toString()).toBe(expectedNegative); - }); - }); - - test("'halfCeil' rounding mode", () => { - const expected = [ - ["years", "P3Y", "-P3Y"], - ["months", "P32M", "-P32M"], - ["weeks", "P139W", "-P139W"], - ["days", "P973D", "-P973D"], - ["hours", "PT23356H", "-PT23356H"], - ["minutes", "PT23356H17M", "-PT23356H17M"], - ["seconds", "PT23356H17M5S", "-PT23356H17M5S"], - ["milliseconds", "PT23356H17M4.864S", "-PT23356H17M4.864S"], - ["microseconds", "PT23356H17M4.864198S", "-PT23356H17M4.864197S"], - ["nanoseconds", "PT23356H17M4.8641975S", "-PT23356H17M4.8641975S"], - ]; - - const roundingMode = "halfCeil"; - expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => { - const untilPositive = earlier.until(later, { smallestUnit, roundingMode }); - expect(untilPositive.toString()).toBe(expectedPositive); - - const untilNegative = later.until(earlier, { smallestUnit, roundingMode }); - expect(untilNegative.toString()).toBe(expectedNegative); - }); - }); - - test("'halfEven' rounding mode", () => { - const expected = [ - ["years", "P3Y", "-P3Y"], - ["months", "P32M", "-P32M"], - ["weeks", "P139W", "-P139W"], - ["days", "P973D", "-P973D"], - ["hours", "PT23356H", "-PT23356H"], - ["minutes", "PT23356H17M", "-PT23356H17M"], - ["seconds", "PT23356H17M5S", "-PT23356H17M5S"], - ["milliseconds", "PT23356H17M4.864S", "-PT23356H17M4.864S"], - ["microseconds", "PT23356H17M4.864198S", "-PT23356H17M4.864198S"], - ["nanoseconds", "PT23356H17M4.8641975S", "-PT23356H17M4.8641975S"], - ]; - - const roundingMode = "halfEven"; - expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => { - const untilPositive = earlier.until(later, { smallestUnit, roundingMode }); - expect(untilPositive.toString()).toBe(expectedPositive); - - const untilNegative = later.until(earlier, { smallestUnit, roundingMode }); - expect(untilNegative.toString()).toBe(expectedNegative); - }); - }); - - test("'halfTrunc' rounding mode", () => { - const expected = [ - ["years", "P3Y", "-P3Y"], - ["months", "P32M", "-P32M"], - ["weeks", "P139W", "-P139W"], - ["days", "P973D", "-P973D"], - ["hours", "PT23356H", "-PT23356H"], - ["minutes", "PT23356H17M", "-PT23356H17M"], - ["seconds", "PT23356H17M5S", "-PT23356H17M5S"], - ["milliseconds", "PT23356H17M4.864S", "-PT23356H17M4.864S"], - ["microseconds", "PT23356H17M4.864197S", "-PT23356H17M4.864197S"], - ["nanoseconds", "PT23356H17M4.8641975S", "-PT23356H17M4.8641975S"], - ]; - - const roundingMode = "halfTrunc"; - expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => { - const untilPositive = earlier.until(later, { smallestUnit, roundingMode }); - expect(untilPositive.toString()).toBe(expectedPositive); - - const untilNegative = later.until(earlier, { smallestUnit, roundingMode }); - expect(untilNegative.toString()).toBe(expectedNegative); - }); - }); - - test("'halfExpand' rounding mode", () => { - const expected = [ - ["years", "P3Y", "-P3Y"], - ["months", "P32M", "-P32M"], - ["weeks", "P139W", "-P139W"], - ["days", "P973D", "-P973D"], - ["hours", "PT23356H", "-PT23356H"], - ["minutes", "PT23356H17M", "-PT23356H17M"], - ["seconds", "PT23356H17M5S", "-PT23356H17M5S"], - ["milliseconds", "PT23356H17M4.864S", "-PT23356H17M4.864S"], - ["microseconds", "PT23356H17M4.864198S", "-PT23356H17M4.864198S"], - ["nanoseconds", "PT23356H17M4.8641975S", "-PT23356H17M4.8641975S"], - ]; - - const roundingMode = "halfExpand"; - expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => { - const untilPositive = earlier.until(later, { smallestUnit, roundingMode }); - expect(untilPositive.toString()).toBe(expectedPositive); - - const untilNegative = later.until(earlier, { smallestUnit, roundingMode }); - expect(untilNegative.toString()).toBe(expectedNegative); - }); - }); - - test("'halfFloor' rounding mode", () => { - const expected = [ - ["years", "P3Y", "-P3Y"], - ["months", "P32M", "-P32M"], - ["weeks", "P139W", "-P139W"], - ["days", "P973D", "-P973D"], - ["hours", "PT23356H", "-PT23356H"], - ["minutes", "PT23356H17M", "-PT23356H17M"], - ["seconds", "PT23356H17M5S", "-PT23356H17M5S"], - ["milliseconds", "PT23356H17M4.864S", "-PT23356H17M4.864S"], - ["microseconds", "PT23356H17M4.864197S", "-PT23356H17M4.864198S"], - ["nanoseconds", "PT23356H17M4.8641975S", "-PT23356H17M4.8641975S"], - ]; - - const roundingMode = "halfFloor"; - expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => { - const untilPositive = earlier.until(later, { smallestUnit, roundingMode }); - expect(untilPositive.toString()).toBe(expectedPositive); - - const untilNegative = later.until(earlier, { smallestUnit, roundingMode }); - expect(untilNegative.toString()).toBe(expectedNegative); - }); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.valueOf.js b/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.valueOf.js deleted file mode 100644 index c8ecd17de10..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.valueOf.js +++ /dev/null @@ -1,11 +0,0 @@ -describe("errors", () => { - test("throws TypeError", () => { - const timeZone = new Temporal.TimeZone("UTC"); - expect(() => { - new Temporal.ZonedDateTime(0n, timeZone).valueOf(); - }).toThrowWithMessage( - TypeError, - "Cannot convert Temporal.ZonedDateTime to a primitive value" - ); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.weekOfYear.js b/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.weekOfYear.js deleted file mode 100644 index e6dfb9cb575..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.weekOfYear.js +++ /dev/null @@ -1,15 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = new Temporal.ZonedDateTime(1625614921000000000n, timeZone); - expect(zonedDateTime.weekOfYear).toBe(27); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.ZonedDateTime object", () => { - expect(() => { - Reflect.get(Temporal.ZonedDateTime.prototype, "weekOfYear", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.ZonedDateTime"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.with.js b/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.with.js deleted file mode 100644 index 06d0a22ed88..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.with.js +++ /dev/null @@ -1,85 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.ZonedDateTime.prototype.with).toHaveLength(1); - }); - - test("basic functionality", () => { - const utc = new Temporal.TimeZone("UTC"); - const zonedDateTime = new Temporal.ZonedDateTime(0n, utc); - const values = [ - [{ year: 2021 }, 1609459200000000000n], - [{ year: 2021, month: 7 }, 1625097600000000000n], - [{ year: 2021, month: 7, day: 6 }, 1625529600000000000n], - [{ year: 2021, monthCode: "M07", day: 6 }, 1625529600000000000n], - [{ hour: 18, minute: 14, second: 47 }, 65687000000000n], - [ - { - year: 2021, - month: 7, - day: 6, - hour: 18, - minute: 14, - second: 47, - millisecond: 123, - microsecond: 456, - nanosecond: 789, - }, - 1625595287123456789n, - ], - ]; - for (const [arg, epochNanoseconds] of values) { - const expected = new Temporal.ZonedDateTime(epochNanoseconds, utc); - expect(zonedDateTime.with(arg).equals(expected)).toBeTrue(); - } - - // Supplying the same values doesn't change the date/time, but still creates a new object - const zonedDateTimeLike = { - year: zonedDateTime.year, - month: zonedDateTime.month, - day: zonedDateTime.day, - hour: zonedDateTime.hour, - minute: zonedDateTime.minute, - second: zonedDateTime.second, - millisecond: zonedDateTime.millisecond, - microsecond: zonedDateTime.microsecond, - nanosecond: zonedDateTime.nanosecond, - }; - expect(zonedDateTime.with(zonedDateTimeLike)).not.toBe(zonedDateTime); - expect(zonedDateTime.with(zonedDateTimeLike).equals(zonedDateTime)).toBeTrue(); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.ZonedDateTime object", () => { - expect(() => { - Temporal.ZonedDateTime.prototype.with.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.ZonedDateTime"); - }); - - test("argument must be an object", () => { - expect(() => { - new Temporal.ZonedDateTime(0n, {}).with("foo"); - }).toThrowWithMessage(TypeError, "foo is not an object"); - expect(() => { - new Temporal.ZonedDateTime(0n, {}).with(42); - }).toThrowWithMessage(TypeError, "42 is not an object"); - }); - - test("argument must have one of 'day', 'hour', 'microsecond', 'millisecond', 'minute', 'month', 'monthCode', 'nanosecond', 'second', 'year'", () => { - expect(() => { - new Temporal.ZonedDateTime(0n, {}).with({}); - }).toThrowWithMessage( - TypeError, - "Object must have at least one of the following properties: day, hour, microsecond, millisecond, minute, month, monthCode, nanosecond, second, year" - ); - }); - - test("argument must not have 'calendar' or 'timeZone'", () => { - expect(() => { - new Temporal.ZonedDateTime(0n, {}).with({ calendar: {} }); - }).toThrowWithMessage(TypeError, "Object must not have a defined calendar property"); - expect(() => { - new Temporal.ZonedDateTime(0n, {}).with({ timeZone: {} }); - }).toThrowWithMessage(TypeError, "Object must not have a defined timeZone property"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.withCalendar.js b/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.withCalendar.js deleted file mode 100644 index def2acf2999..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.withCalendar.js +++ /dev/null @@ -1,41 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.ZonedDateTime.prototype.withCalendar).toHaveLength(1); - }); - - test("basic functionality", () => { - const object = {}; - const zonedDateTime = new Temporal.ZonedDateTime(1n, {}, object); - expect(zonedDateTime.calendar).toBe(object); - - const calendar = new Temporal.Calendar("iso8601"); - const withCalendarZonedDateTime = zonedDateTime.withCalendar(calendar); - expect(withCalendarZonedDateTime.calendar).toBe(calendar); - }); - - test("from calendar string", () => { - const object = {}; - const zonedDateTime = new Temporal.ZonedDateTime(1n, {}, object); - expect(zonedDateTime.calendar).toBe(object); - - const withCalendarZonedDateTime = zonedDateTime.withCalendar("iso8601"); - expect(withCalendarZonedDateTime.calendar).toBeInstanceOf(Temporal.Calendar); - expect(withCalendarZonedDateTime.calendar.id).toBe("iso8601"); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.ZonedDateTime object", () => { - expect(() => { - Temporal.ZonedDateTime.prototype.withCalendar.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.ZonedDateTime"); - }); - - test("from invalid calendar identifier", () => { - const zonedDateTime = new Temporal.ZonedDateTime(1n, {}, {}); - - expect(() => { - zonedDateTime.withCalendar("iso8602foobar"); - }).toThrowWithMessage(RangeError, "Invalid calendar identifier 'iso8602foobar'"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.withPlainDate.js b/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.withPlainDate.js deleted file mode 100644 index 177466ad014..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.withPlainDate.js +++ /dev/null @@ -1,83 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.ZonedDateTime.prototype.withPlainDate).toHaveLength(1); - }); - - function checkExpectedResults(withPlainDateZonedDateTime) { - expect(withPlainDateZonedDateTime.epochNanoseconds).toBe(1640467016100200300n); - expect(withPlainDateZonedDateTime.epochMicroseconds).toBe(1640467016100200n); - expect(withPlainDateZonedDateTime.epochMilliseconds).toBe(1640467016100); - expect(withPlainDateZonedDateTime.epochSeconds).toBe(1640467016); - expect(withPlainDateZonedDateTime.year).toBe(2021); - expect(withPlainDateZonedDateTime.month).toBe(12); - expect(withPlainDateZonedDateTime.monthCode).toBe("M12"); - expect(withPlainDateZonedDateTime.day).toBe(25); - expect(withPlainDateZonedDateTime.hour).toBe(21); - expect(withPlainDateZonedDateTime.minute).toBe(16); - expect(withPlainDateZonedDateTime.second).toBe(56); - expect(withPlainDateZonedDateTime.millisecond).toBe(100); - expect(withPlainDateZonedDateTime.microsecond).toBe(200); - expect(withPlainDateZonedDateTime.nanosecond).toBe(300); - expect(withPlainDateZonedDateTime.dayOfWeek).toBe(6); - expect(withPlainDateZonedDateTime.dayOfYear).toBe(359); - expect(withPlainDateZonedDateTime.weekOfYear).toBe(51); - expect(withPlainDateZonedDateTime.hoursInDay).toBe(24); - expect(withPlainDateZonedDateTime.daysInWeek).toBe(7); - expect(withPlainDateZonedDateTime.daysInYear).toBe(365); - expect(withPlainDateZonedDateTime.monthsInYear).toBe(12); - expect(withPlainDateZonedDateTime.inLeapYear).toBeFalse(); - expect(withPlainDateZonedDateTime.offset).toBe("+00:00"); - expect(withPlainDateZonedDateTime.offsetNanoseconds).toBe(0); - } - - test("basic functionality", () => { - const plainDateTime = new Temporal.PlainDateTime(2021, 11, 4, 21, 16, 56, 100, 200, 300); - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = plainDateTime.toZonedDateTime(timeZone); - const plainDate = new Temporal.PlainDate(2021, 12, 25); - const withPlainDateZonedDateTime = zonedDateTime.withPlainDate(plainDate); - - checkExpectedResults(withPlainDateZonedDateTime); - }); - - test("plain time-like object", () => { - const plainDateTime = new Temporal.PlainDateTime(2021, 11, 4, 21, 16, 56, 100, 200, 300); - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = plainDateTime.toZonedDateTime(timeZone); - const plainDateLike = { year: 2021, month: 12, day: 25 }; - const withPlainDateZonedDateTime = zonedDateTime.withPlainDate(plainDateLike); - - checkExpectedResults(withPlainDateZonedDateTime); - }); - - test("from plain date string", () => { - const plainDateTime = new Temporal.PlainDateTime(2021, 11, 4, 21, 16, 56, 100, 200, 300); - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = plainDateTime.toZonedDateTime(timeZone); - const withPlainDateZonedDateTime = zonedDateTime.withPlainDate("2021-12-25"); - - checkExpectedResults(withPlainDateZonedDateTime); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.ZonedDateTime object", () => { - expect(() => { - Temporal.ZonedDateTime.prototype.withPlainDate.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.ZonedDateTime"); - }); - - test("missing properties", () => { - expect(() => { - new Temporal.ZonedDateTime(1n, {}).withPlainDate({}); - }).toThrowWithMessage(TypeError, "Required property day is missing or undefined"); - - expect(() => { - new Temporal.ZonedDateTime(1n, {}).withPlainDate({ day: 1, year: 1 }); - }).toThrowWithMessage(TypeError, "Required property month is missing or undefined"); - - expect(() => { - new Temporal.ZonedDateTime(1n, {}).withPlainDate({ day: 1, month: 1 }); - }).toThrowWithMessage(TypeError, "Required property year is missing or undefined"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.withPlainTime.js b/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.withPlainTime.js deleted file mode 100644 index 486e231d725..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.withPlainTime.js +++ /dev/null @@ -1,133 +0,0 @@ -describe("correct behavior", () => { - test("length is 0", () => { - expect(Temporal.ZonedDateTime.prototype.withPlainTime).toHaveLength(0); - }); - - function checkCommonExpectedResults(withPlainTimeZonedDateTime) { - expect(withPlainTimeZonedDateTime.epochNanoseconds).toBe(1636064604200300400n); - expect(withPlainTimeZonedDateTime.epochMicroseconds).toBe(1636064604200300n); - expect(withPlainTimeZonedDateTime.epochMilliseconds).toBe(1636064604200); - expect(withPlainTimeZonedDateTime.epochSeconds).toBe(1636064604); - expect(withPlainTimeZonedDateTime.year).toBe(2021); - expect(withPlainTimeZonedDateTime.month).toBe(11); - expect(withPlainTimeZonedDateTime.monthCode).toBe("M11"); - expect(withPlainTimeZonedDateTime.day).toBe(4); - expect(withPlainTimeZonedDateTime.hour).toBe(22); - expect(withPlainTimeZonedDateTime.minute).toBe(23); - expect(withPlainTimeZonedDateTime.second).toBe(24); - expect(withPlainTimeZonedDateTime.millisecond).toBe(200); - expect(withPlainTimeZonedDateTime.microsecond).toBe(300); - expect(withPlainTimeZonedDateTime.nanosecond).toBe(400); - expect(withPlainTimeZonedDateTime.dayOfWeek).toBe(4); - expect(withPlainTimeZonedDateTime.dayOfYear).toBe(308); - expect(withPlainTimeZonedDateTime.weekOfYear).toBe(44); - expect(withPlainTimeZonedDateTime.hoursInDay).toBe(24); - expect(withPlainTimeZonedDateTime.daysInWeek).toBe(7); - expect(withPlainTimeZonedDateTime.daysInYear).toBe(365); - expect(withPlainTimeZonedDateTime.monthsInYear).toBe(12); - expect(withPlainTimeZonedDateTime.inLeapYear).toBeFalse(); - expect(withPlainTimeZonedDateTime.offset).toBe("+00:00"); - expect(withPlainTimeZonedDateTime.offsetNanoseconds).toBe(0); - } - - test("basic functionality", () => { - const plainDateTime = new Temporal.PlainDateTime(2021, 11, 4, 21, 16, 56, 100, 200, 300); - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = plainDateTime.toZonedDateTime(timeZone); - const plainTime = new Temporal.PlainTime(22, 23, 24, 200, 300, 400); - const withPlainTimeZonedDateTime = zonedDateTime.withPlainTime(plainTime); - - checkCommonExpectedResults(withPlainTimeZonedDateTime); - }); - - test("plain time-like object", () => { - const plainDateTime = new Temporal.PlainDateTime(2021, 11, 4, 21, 16, 56, 100, 200, 300); - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = plainDateTime.toZonedDateTime(timeZone); - const plainTimeLike = { - hour: 22, - minute: 23, - second: 24, - millisecond: 200, - microsecond: 300, - nanosecond: 400, - }; - const withPlainTimeZonedDateTime = zonedDateTime.withPlainTime(plainTimeLike); - - checkCommonExpectedResults(withPlainTimeZonedDateTime); - }); - - test("passing no parameters is the equivalent of using startOfDay", () => { - const plainDateTime = new Temporal.PlainDateTime(2021, 11, 4, 21, 16, 56, 100, 200, 300); - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = plainDateTime.toZonedDateTime(timeZone); - const startOfDayZonedDateTime = zonedDateTime.startOfDay(); - const withPlainTimeZonedDateTime = zonedDateTime.withPlainTime(); - - expect(startOfDayZonedDateTime.epochNanoseconds).toBe( - withPlainTimeZonedDateTime.epochNanoseconds - ); - expect(startOfDayZonedDateTime.epochMicroseconds).toBe( - withPlainTimeZonedDateTime.epochMicroseconds - ); - expect(startOfDayZonedDateTime.epochMilliseconds).toBe( - withPlainTimeZonedDateTime.epochMilliseconds - ); - expect(startOfDayZonedDateTime.epochSeconds).toBe(withPlainTimeZonedDateTime.epochSeconds); - expect(startOfDayZonedDateTime.year).toBe(withPlainTimeZonedDateTime.year); - expect(startOfDayZonedDateTime.month).toBe(withPlainTimeZonedDateTime.month); - expect(startOfDayZonedDateTime.monthCode).toBe(withPlainTimeZonedDateTime.monthCode); - expect(startOfDayZonedDateTime.day).toBe(withPlainTimeZonedDateTime.day); - expect(startOfDayZonedDateTime.hour).toBe(withPlainTimeZonedDateTime.hour); - expect(startOfDayZonedDateTime.minute).toBe(withPlainTimeZonedDateTime.minute); - expect(startOfDayZonedDateTime.second).toBe(withPlainTimeZonedDateTime.second); - expect(startOfDayZonedDateTime.millisecond).toBe(withPlainTimeZonedDateTime.millisecond); - expect(startOfDayZonedDateTime.microsecond).toBe(withPlainTimeZonedDateTime.microsecond); - expect(startOfDayZonedDateTime.nanosecond).toBe(withPlainTimeZonedDateTime.nanosecond); - expect(startOfDayZonedDateTime.dayOfWeek).toBe(withPlainTimeZonedDateTime.dayOfWeek); - expect(startOfDayZonedDateTime.dayOfYear).toBe(withPlainTimeZonedDateTime.dayOfYear); - expect(startOfDayZonedDateTime.weekOfYear).toBe(withPlainTimeZonedDateTime.weekOfYear); - expect(startOfDayZonedDateTime.hoursInDay).toBe(withPlainTimeZonedDateTime.hoursInDay); - expect(startOfDayZonedDateTime.daysInWeek).toBe(withPlainTimeZonedDateTime.daysInWeek); - expect(startOfDayZonedDateTime.daysInYear).toBe(withPlainTimeZonedDateTime.daysInYear); - expect(startOfDayZonedDateTime.monthsInYear).toBe(withPlainTimeZonedDateTime.monthsInYear); - expect(startOfDayZonedDateTime.inLeapYear).toBe(withPlainTimeZonedDateTime.inLeapYear); - expect(startOfDayZonedDateTime.offset).toBe(withPlainTimeZonedDateTime.offset); - expect(startOfDayZonedDateTime.offsetNanoseconds).toBe( - withPlainTimeZonedDateTime.offsetNanoseconds - ); - }); - - test("from plain time string", () => { - const plainDateTime = new Temporal.PlainDateTime(2021, 11, 4, 21, 16, 56, 100, 200, 300); - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = plainDateTime.toZonedDateTime(timeZone); - const withPlainTimeZonedDateTime = zonedDateTime.withPlainTime("22:23:24.200300400"); - - checkCommonExpectedResults(withPlainTimeZonedDateTime); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.ZonedDateTime object", () => { - expect(() => { - Temporal.ZonedDateTime.prototype.withPlainTime.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.ZonedDateTime"); - }); - - test("invalid plain time-like object", () => { - expect(() => { - new Temporal.ZonedDateTime(1n, {}).withPlainTime({}); - }).toThrowWithMessage( - TypeError, - "Object must have at least one of the following properties: hour, microsecond, millisecond, minute, nanosecond, second" - ); - - expect(() => { - new Temporal.ZonedDateTime(1n, {}).withPlainTime({ foo: 1, bar: 2 }); - }).toThrowWithMessage( - TypeError, - "Object must have at least one of the following properties: hour, microsecond, millisecond, minute, nanosecond, second" - ); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.withTimeZone.js b/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.withTimeZone.js deleted file mode 100644 index 00bb9d7647c..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.withTimeZone.js +++ /dev/null @@ -1,41 +0,0 @@ -describe("correct behavior", () => { - test("length is 1", () => { - expect(Temporal.ZonedDateTime.prototype.withTimeZone).toHaveLength(1); - }); - - test("basic functionality", () => { - const object = {}; - const zonedDateTime = new Temporal.ZonedDateTime(1n, object); - expect(zonedDateTime.timeZone).toBe(object); - - const timeZone = new Temporal.TimeZone("UTC"); - const withTimeZoneZonedDateTime = zonedDateTime.withTimeZone(timeZone); - expect(withTimeZoneZonedDateTime.timeZone).toBe(timeZone); - }); - - test("from time zone string", () => { - const object = {}; - const zonedDateTime = new Temporal.ZonedDateTime(1n, object); - expect(zonedDateTime.timeZone).toBe(object); - - const withTimeZoneZonedDateTime = zonedDateTime.withTimeZone("UTC"); - expect(withTimeZoneZonedDateTime.timeZone).toBeInstanceOf(Temporal.TimeZone); - expect(withTimeZoneZonedDateTime.timeZone.id).toBe("UTC"); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.ZonedDateTime object", () => { - expect(() => { - Temporal.ZonedDateTime.prototype.withTimeZone.call("foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.ZonedDateTime"); - }); - - test("from invalid time zone string", () => { - const zonedDateTime = new Temporal.ZonedDateTime(1n, {}); - - expect(() => { - zonedDateTime.withTimeZone("UTCfoobar"); - }).toThrowWithMessage(RangeError, "Invalid time zone name 'UTCfoobar'"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.year.js b/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.year.js deleted file mode 100644 index e268f23ae7c..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.year.js +++ /dev/null @@ -1,15 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = new Temporal.ZonedDateTime(1625614921000000000n, timeZone); - expect(zonedDateTime.year).toBe(2021); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.ZonedDateTime object", () => { - expect(() => { - Reflect.get(Temporal.ZonedDateTime.prototype, "year", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.ZonedDateTime"); - }); -}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.yearOfWeek.js b/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.yearOfWeek.js deleted file mode 100644 index 33379a9e857..00000000000 --- a/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.yearOfWeek.js +++ /dev/null @@ -1,15 +0,0 @@ -describe("correct behavior", () => { - test("basic functionality", () => { - const timeZone = new Temporal.TimeZone("UTC"); - const zonedDateTime = new Temporal.ZonedDateTime(1672531200000000000n, timeZone); - expect(zonedDateTime.yearOfWeek).toBe(2022); - }); -}); - -describe("errors", () => { - test("this value must be a Temporal.ZonedDateTime object", () => { - expect(() => { - Reflect.get(Temporal.ZonedDateTime.prototype, "yearOfWeek", "foo"); - }).toThrowWithMessage(TypeError, "Not an object of type Temporal.ZonedDateTime"); - }); -});