diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/Calendar.cpp b/Userland/Libraries/LibJS/Runtime/Temporal/Calendar.cpp index c1a0ba0066..09f4dbe38f 100644 --- a/Userland/Libraries/LibJS/Runtime/Temporal/Calendar.cpp +++ b/Userland/Libraries/LibJS/Runtime/Temporal/Calendar.cpp @@ -721,7 +721,7 @@ ThrowCompletionOr resolve_iso_month(GlobalObject& global_object, Object } // 12.2.33 ISODateFromFields ( fields, options ), https://tc39.es/proposal-temporal/#sec-temporal-isodatefromfields -ThrowCompletionOr iso_date_from_fields(GlobalObject& global_object, Object const& fields, Object const& options) +ThrowCompletionOr iso_date_from_fields(GlobalObject& global_object, Object const& fields, Object const& options) { auto& vm = global_object.vm(); @@ -825,7 +825,7 @@ ThrowCompletionOr iso_month_day_from_fields(GlobalObject& global_ob // 11. Let referenceISOYear be 1972 (the first leap year after the Unix epoch). i32 reference_iso_year = 1972; - Optional result; + Optional result; // 12. If monthCode is undefined, then if (month_code.is_undefined()) { diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/Calendar.h b/Userland/Libraries/LibJS/Runtime/Temporal/Calendar.h index 96516e350f..d5e40139fc 100644 --- a/Userland/Libraries/LibJS/Runtime/Temporal/Calendar.h +++ b/Userland/Libraries/LibJS/Runtime/Temporal/Calendar.h @@ -66,7 +66,7 @@ u8 iso_days_in_month(i32 year, u8 month); u8 to_iso_week_of_year(i32 year, u8 month, u8 day); String build_iso_month_code(u8 month); ThrowCompletionOr resolve_iso_month(GlobalObject&, Object const& fields); -ThrowCompletionOr iso_date_from_fields(GlobalObject&, Object const& fields, Object const& options); +ThrowCompletionOr iso_date_from_fields(GlobalObject&, Object const& fields, Object const& options); ThrowCompletionOr iso_year_month_from_fields(GlobalObject&, Object const& fields, Object const& options); ThrowCompletionOr iso_month_day_from_fields(GlobalObject&, Object const& fields, Object const& options); i32 iso_year(Object& temporal_object); diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/PlainDate.cpp b/Userland/Libraries/LibJS/Runtime/Temporal/PlainDate.cpp index 2f2ccbb55d..297e91a115 100644 --- a/Userland/Libraries/LibJS/Runtime/Temporal/PlainDate.cpp +++ b/Userland/Libraries/LibJS/Runtime/Temporal/PlainDate.cpp @@ -37,6 +37,16 @@ void PlainDate::visit_edges(Visitor& 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(GlobalObject& global_object, i32 iso_year, u8 iso_month, u8 iso_day, Object& calendar, FunctionObject const* new_target) { @@ -154,10 +164,10 @@ DateDurationRecord difference_iso_date(GlobalObject& global_object, i32 year1, u return create_date_duration_record(0, 0, 0, 0); // c. Let start be the Record { [[Year]]: y1, [[Month]]: m1, [[Day]]: d1 }. - auto start = ISODate { .year = year1, .month = month1, .day = day1 }; + auto start = ISODateRecord { .year = year1, .month = month1, .day = day1 }; // d. Let end be the Record { [[Year]]: y2, [[Month]]: m2, [[Day]]: d2 }. - auto end = ISODate { .year = year2, .month = month2, .day = day2 }; + auto end = ISODateRecord { .year = year2, .month = month2, .day = day2 }; // e. Let years be end.[[Year]] - start.[[Year]]. double years = end.year - start.year; @@ -292,15 +302,13 @@ DateDurationRecord difference_iso_date(GlobalObject& global_object, i32 year1, u } // 3.5.4 RegulateISODate ( year, month, day, overflow ), https://tc39.es/proposal-temporal/#sec-temporal-regulateisodate -ThrowCompletionOr regulate_iso_date(GlobalObject& global_object, double year, double month, double day, StringView overflow) +ThrowCompletionOr regulate_iso_date(GlobalObject& global_object, double year, double month, double day, StringView overflow) { auto& vm = global_object.vm(); - // 1. Assert: year, month, and day are integers. - VERIFY(year == trunc(year) && month == trunc(month) && day == trunc(day)); - // 2. Assert: overflow is either "constrain" or "reject". - // NOTE: Asserted by the VERIFY_NOT_REACHED at the end - // 3. If overflow is "reject", then + VERIFY(year == trunc(year) && month == trunc(month) && day == trunc(day)); + + // 1. If overflow is "reject", then if (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 @@ -316,9 +324,9 @@ ThrowCompletionOr regulate_iso_date(GlobalObject& global_object, double return vm.throw_completion(global_object, ErrorType::TemporalInvalidPlainDate); // b. Return the Record { [[Year]]: year, [[Month]]: month, [[Day]]: day }. - return ISODate { .year = y, .month = m, .day = d }; + return ISODateRecord { .year = y, .month = m, .day = d }; } - // 4. If overflow is "constrain", then + // 2. If overflow is "constrain", then else 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 @@ -326,19 +334,17 @@ ThrowCompletionOr regulate_iso_date(GlobalObject& global_object, double if (!AK::is_within_range(year)) return vm.throw_completion(global_object, ErrorType::TemporalInvalidPlainDate); - auto y = static_cast(year); - // 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(y, (u8)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 the Record { [[Year]]: year, [[Month]]: month, [[Day]]: day }. - return ISODate { .year = y, .month = static_cast(month), .day = static_cast(day) }; + // d. Return CreateISODateRecord(year, month, day). + return create_iso_date_record(static_cast(year), static_cast(month), static_cast(day)); } VERIFY_NOT_REACHED(); } @@ -366,7 +372,7 @@ bool is_valid_iso_date(i32 year, u8 month, u8 day) } // 3.5.6 BalanceISODate ( year, month, day ), https://tc39.es/proposal-temporal/#sec-temporal-balanceisodate -ISODate balance_iso_date(double year, double month, double day) +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); @@ -377,8 +383,8 @@ ISODate balance_iso_date(double year, double month, double day) // 3. Let ms be MakeDate(epochDays, +0𝔽). auto ms = make_date(epoch_days, 0); - // 4. Return the Record { [[Year]]: ℝ(YearFromTime(ms)), [[Month]]: ℝ(MonthFromTime(ms)) + 1, [[Day]]: ℝ(DateFromTime(ms)) }. - return { .year = year_from_time(ms), .month = static_cast(month_from_time(ms) + 1), .day = date_from_time(ms) }; + // 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 @@ -426,7 +432,7 @@ ThrowCompletionOr temporal_date_to_string(GlobalObject& global_object, P } // 3.5.9 AddISODate ( year, month, day, years, months, weeks, days, overflow ), https://tc39.es/proposal-temporal/#sec-temporal-addisodate -ThrowCompletionOr add_iso_date(GlobalObject& global_object, i32 year, u8 month, u8 day, double years, double months, double weeks, double days, StringView overflow) +ThrowCompletionOr add_iso_date(GlobalObject& global_object, 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)); diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/PlainDate.h b/Userland/Libraries/LibJS/Runtime/Temporal/PlainDate.h index 12c6e2c7ea..d8418cecea 100644 --- a/Userland/Libraries/LibJS/Runtime/Temporal/PlainDate.h +++ b/Userland/Libraries/LibJS/Runtime/Temporal/PlainDate.h @@ -37,21 +37,23 @@ private: Object& m_calendar; // [[Calendar]] }; -struct ISODate { +// 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(GlobalObject&, i32 iso_year, u8 iso_month, u8 iso_day, Object& calendar, FunctionObject const* new_target = nullptr); ThrowCompletionOr to_temporal_date(GlobalObject&, Value item, Object const* options = nullptr); DateDurationRecord difference_iso_date(GlobalObject&, i32 year1, u8 month1, u8 day1, i32 year2, u8 month2, u8 day2, StringView largest_unit); -ThrowCompletionOr regulate_iso_date(GlobalObject&, double year, double month, double day, StringView overflow); +ThrowCompletionOr regulate_iso_date(GlobalObject&, double year, double month, double day, StringView overflow); bool is_valid_iso_date(i32 year, u8 month, u8 day); -ISODate balance_iso_date(double year, double month, double day); +ISODateRecord balance_iso_date(double year, double month, double day); String pad_iso_year(i32 y); ThrowCompletionOr temporal_date_to_string(GlobalObject&, PlainDate&, StringView show_calendar); -ThrowCompletionOr add_iso_date(GlobalObject&, i32 year, u8 month, u8 day, double years, double months, double weeks, double days, StringView overflow); +ThrowCompletionOr add_iso_date(GlobalObject&, 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(GlobalObject&, DifferenceOperation, PlainDate&, Value other, Value options);