From f88826691cefb62070c5eda1d38505686e944bb3 Mon Sep 17 00:00:00 2001 From: Timothy Flynn Date: Mon, 18 Nov 2024 09:24:53 -0500 Subject: [PATCH] LibJS: Remove usage of obsolete Duration record from Intl.DurationFormat The Duration record no longer exists in Temporal. Implement it according to the DurationFormat spec to prepare for its removal from our Temporal implementation. We also implement the DurationSign AO here as well, as the Temporal implementation will now require a Temporal.Duration JS object. --- .../LibJS/Runtime/Intl/DurationFormat.cpp | 41 ++++++++++++----- Libraries/LibJS/Runtime/Intl/DurationFormat.h | 46 ++++++++++++------- 2 files changed, 60 insertions(+), 27 deletions(-) diff --git a/Libraries/LibJS/Runtime/Intl/DurationFormat.cpp b/Libraries/LibJS/Runtime/Intl/DurationFormat.cpp index 6b9884de230..185edf2d42e 100644 --- a/Libraries/LibJS/Runtime/Intl/DurationFormat.cpp +++ b/Libraries/LibJS/Runtime/Intl/DurationFormat.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include namespace JS::Intl { @@ -157,7 +158,7 @@ static GC::Ref construct_list_format(VM& vm, DurationFormat const& d } // 1.1.3 ToDurationRecord ( input ), https://tc39.es/proposal-intl-duration-format/#sec-todurationrecord -ThrowCompletionOr to_duration_record(VM& vm, Value input) +ThrowCompletionOr to_duration_record(VM& vm, Value input) { // 1. If Type(input) is not Object, then if (!input.is_object()) { @@ -172,7 +173,7 @@ ThrowCompletionOr to_duration_record(VM& vm, Value inp auto& input_object = input.as_object(); // 2. Let result be a new Duration Record with each field set to 0. - Temporal::DurationRecord result = {}; + DurationRecord result = {}; bool any_defined = false; auto set_duration_record_value = [&](auto const& name, auto& value_slot) -> ThrowCompletionOr { @@ -240,6 +241,24 @@ ThrowCompletionOr to_duration_record(VM& vm, Value inp return result; } +// 1.1.4 DurationSign ( duration ), https://tc39.es/proposal-intl-duration-format/#sec-durationsign +i8 duration_sign(DurationRecord const& duration) +{ + // 1. For each value v of « duration.[[Years]], duration.[[Months]], duration.[[Weeks]], duration.[[Days]], duration.[[Hours]], duration.[[Minutes]], duration.[[Seconds]], duration.[[Milliseconds]], duration.[[Microseconds]], duration.[[Nanoseconds]] », do + for (auto value : { duration.years, duration.months, duration.weeks, duration.days, duration.hours, duration.minutes, duration.seconds, duration.milliseconds, duration.microseconds, duration.nanoseconds }) { + // a. If v < 0, return -1. + if (value < 0) + return -1; + + // b. If v > 0, return 1. + if (value > 0) + return 1; + } + + // 2. Return 0. + return 0; +} + // 1.1.6 GetDurationUnitOptions ( unit, options, baseStyle, stylesList, digitalBase, prevStyle, twoDigitHours ), https://tc39.es/proposal-intl-duration-format/#sec-getdurationunitoptions ThrowCompletionOr get_duration_unit_options(VM& vm, String const& unit, Object const& options, StringView base_style, ReadonlySpan styles_list, StringView digital_base, StringView previous_style, bool two_digit_hours) { @@ -349,7 +368,7 @@ ThrowCompletionOr get_duration_unit_options(VM& vm, String } // 1.1.7 AddFractionalDigits ( durationFormat, duration ), https://tc39.es/proposal-intl-duration-format/#sec-addfractionaldigits -double add_fractional_digits(DurationFormat const& duration_format, Temporal::DurationRecord const& duration) +double add_fractional_digits(DurationFormat const& duration_format, DurationRecord const& duration) { // 1. Let result be 0. double result = 0; @@ -625,7 +644,7 @@ Vector format_numeric_seconds(VM& vm, DurationFormat const& } // 1.1.12 FormatNumericUnits ( durationFormat, duration, firstNumericUnit, signDisplayed ), https://tc39.es/proposal-intl-duration-format/#sec-formatnumericunits -Vector format_numeric_units(VM& vm, DurationFormat const& duration_format, Temporal::DurationRecord const& duration, StringView first_numeric_unit, bool sign_displayed) +Vector format_numeric_units(VM& vm, DurationFormat const& duration_format, DurationRecord const& duration, StringView first_numeric_unit, bool sign_displayed) { // 1. Assert: firstNumericUnit is "hours", "minutes", or "seconds". VERIFY(first_numeric_unit.is_one_of("hours"sv, "minutes"sv, "seconds"sv)); @@ -696,8 +715,8 @@ Vector format_numeric_units(VM& vm, DurationFormat const& du if (hours_formatted) { // a. If signDisplayed is true, then if (sign_displayed) { - // i. If hoursValue is 0 and DurationSign(duration.[[Years]], duration.[[Months]], duration.[[Weeks]], duration.[[Days]], duration.[[Hours]], duration.[[Minutes]], duration.[[Seconds]], duration.[[Milliseconds]], duration.[[Microseconds]], duration.[[Nanoseconds]]) is -1, then - if (hours_value == 0 && Temporal::duration_sign(duration.years, duration.months, duration.weeks, duration.days, duration.hours, duration.minutes, duration.seconds, duration.milliseconds, duration.microseconds, duration.nanoseconds) == -1) { + // i. If hoursValue is 0 and DurationSign(duration) is -1, then + if (hours_value == 0 && duration_sign(duration) == -1) { // 1. Set hoursValue to negative-zero. hours_value = -0.0; } @@ -714,8 +733,8 @@ Vector format_numeric_units(VM& vm, DurationFormat const& du if (minutes_formatted) { // a. If signDisplayed is true, then if (sign_displayed) { - // i. If minutesValue is 0 and DurationSign(duration.[[Years]], duration.[[Months]], duration.[[Weeks]], duration.[[Days]], duration.[[Hours]], duration.[[Minutes]], duration.[[Seconds]], duration.[[Milliseconds]], duration.[[Microseconds]], duration.[[Nanoseconds]]) is -1, then - if (minutes_value == 0 && Temporal::duration_sign(duration.years, duration.months, duration.weeks, duration.days, duration.hours, duration.minutes, duration.seconds, duration.milliseconds, duration.microseconds, duration.nanoseconds) == -1) { + // i. If minutesValue is 0 and DurationSign(duration) is -1, then + if (minutes_value == 0 && duration_sign(duration) == -1) { // 1. Set minutesValue to negative-zero. minutes_value = -0.0; } @@ -833,7 +852,7 @@ Vector list_format_parts(VM& vm, DurationFormat const& durat } // 1.1.7 PartitionDurationFormatPattern ( durationFormat, duration ), https://tc39.es/proposal-intl-duration-format/#sec-partitiondurationformatpattern -Vector partition_duration_format_pattern(VM& vm, DurationFormat const& duration_format, Temporal::DurationRecord const& duration) +Vector partition_duration_format_pattern(VM& vm, DurationFormat const& duration_format, DurationRecord const& duration) { auto& realm = *vm.current_realm(); @@ -930,8 +949,8 @@ Vector partition_duration_format_pattern(VM& vm, DurationFor // a. Set signDisplayed to false. sign_displayed = false; - // b. If value is 0 and DurationSign(duration.[[Years]], duration.[[Months]], duration.[[Weeks]], duration.[[Days]], duration.[[Hours]], duration.[[Minutes]], duration.[[Seconds]], duration.[[Milliseconds]], duration.[[Microseconds]], duration.[[Nanoseconds]]) is -1, then - if (value == 0 && Temporal::duration_sign(duration.years, duration.months, duration.weeks, duration.days, duration.hours, duration.minutes, duration.seconds, duration.milliseconds, duration.microseconds, duration.nanoseconds) == -1) { + // b. If value is 0 and DurationSign(duration) is -1, then + if (value == 0 && duration_sign(duration) == -1) { // i. Set value to negative-zero. value = -0.0; } diff --git a/Libraries/LibJS/Runtime/Intl/DurationFormat.h b/Libraries/LibJS/Runtime/Intl/DurationFormat.h index cbaaae1db44..8dbfe4f47a9 100644 --- a/Libraries/LibJS/Runtime/Intl/DurationFormat.h +++ b/Libraries/LibJS/Runtime/Intl/DurationFormat.h @@ -11,7 +11,6 @@ #include #include #include -#include #include namespace JS::Intl { @@ -199,8 +198,22 @@ private: Optional m_fractional_digits; // [[FractionalDigits]] }; +// 1.1.1 Duration Records, https://tc39.es/proposal-intl-duration-format/#sec-duration-records +struct DurationRecord { + double years { 0 }; + double months { 0 }; + double weeks { 0 }; + double days { 0 }; + double hours { 0 }; + double minutes { 0 }; + double seconds { 0 }; + double milliseconds { 0 }; + double microseconds { 0 }; + double nanoseconds { 0 }; +}; + struct DurationInstanceComponent { - double Temporal::DurationRecord::*value_slot; + double DurationRecord::*value_slot; DurationFormat::ValueStyle (DurationFormat::*get_style_slot)() const; void (DurationFormat::*set_style_slot)(StringView); DurationFormat::Display (DurationFormat::*get_display_slot)() const; @@ -216,16 +229,16 @@ static constexpr AK::Array date_values = { "long"sv, "short"sv, " static constexpr AK::Array time_values = { "long"sv, "short"sv, "narrow"sv, "numeric"sv, "2-digit"sv }; static constexpr AK::Array sub_second_values = { "long"sv, "short"sv, "narrow"sv, "numeric"sv }; static constexpr AK::Array duration_instances_components { - DurationInstanceComponent { &Temporal::DurationRecord::years, &DurationFormat::years_style, &DurationFormat::set_years_style, &DurationFormat::years_display, &DurationFormat::set_years_display, "years"sv, "year"sv, date_values, "short"sv }, - DurationInstanceComponent { &Temporal::DurationRecord::months, &DurationFormat::months_style, &DurationFormat::set_months_style, &DurationFormat::months_display, &DurationFormat::set_months_display, "months"sv, "month"sv, date_values, "short"sv }, - DurationInstanceComponent { &Temporal::DurationRecord::weeks, &DurationFormat::weeks_style, &DurationFormat::set_weeks_style, &DurationFormat::weeks_display, &DurationFormat::set_weeks_display, "weeks"sv, "week"sv, date_values, "short"sv }, - DurationInstanceComponent { &Temporal::DurationRecord::days, &DurationFormat::days_style, &DurationFormat::set_days_style, &DurationFormat::days_display, &DurationFormat::set_days_display, "days"sv, "day"sv, date_values, "short"sv }, - DurationInstanceComponent { &Temporal::DurationRecord::hours, &DurationFormat::hours_style, &DurationFormat::set_hours_style, &DurationFormat::hours_display, &DurationFormat::set_hours_display, "hours"sv, "hour"sv, time_values, "numeric"sv }, - DurationInstanceComponent { &Temporal::DurationRecord::minutes, &DurationFormat::minutes_style, &DurationFormat::set_minutes_style, &DurationFormat::minutes_display, &DurationFormat::set_minutes_display, "minutes"sv, "minute"sv, time_values, "numeric"sv }, - DurationInstanceComponent { &Temporal::DurationRecord::seconds, &DurationFormat::seconds_style, &DurationFormat::set_seconds_style, &DurationFormat::seconds_display, &DurationFormat::set_seconds_display, "seconds"sv, "second"sv, time_values, "numeric"sv }, - DurationInstanceComponent { &Temporal::DurationRecord::milliseconds, &DurationFormat::milliseconds_style, &DurationFormat::set_milliseconds_style, &DurationFormat::milliseconds_display, &DurationFormat::set_milliseconds_display, "milliseconds"sv, "millisecond"sv, sub_second_values, "numeric"sv }, - DurationInstanceComponent { &Temporal::DurationRecord::microseconds, &DurationFormat::microseconds_style, &DurationFormat::set_microseconds_style, &DurationFormat::microseconds_display, &DurationFormat::set_microseconds_display, "microseconds"sv, "microsecond"sv, sub_second_values, "numeric"sv }, - DurationInstanceComponent { &Temporal::DurationRecord::nanoseconds, &DurationFormat::nanoseconds_style, &DurationFormat::set_nanoseconds_style, &DurationFormat::nanoseconds_display, &DurationFormat::set_nanoseconds_display, "nanoseconds"sv, "nanosecond"sv, sub_second_values, "numeric"sv }, + DurationInstanceComponent { &DurationRecord::years, &DurationFormat::years_style, &DurationFormat::set_years_style, &DurationFormat::years_display, &DurationFormat::set_years_display, "years"sv, "year"sv, date_values, "short"sv }, + DurationInstanceComponent { &DurationRecord::months, &DurationFormat::months_style, &DurationFormat::set_months_style, &DurationFormat::months_display, &DurationFormat::set_months_display, "months"sv, "month"sv, date_values, "short"sv }, + DurationInstanceComponent { &DurationRecord::weeks, &DurationFormat::weeks_style, &DurationFormat::set_weeks_style, &DurationFormat::weeks_display, &DurationFormat::set_weeks_display, "weeks"sv, "week"sv, date_values, "short"sv }, + DurationInstanceComponent { &DurationRecord::days, &DurationFormat::days_style, &DurationFormat::set_days_style, &DurationFormat::days_display, &DurationFormat::set_days_display, "days"sv, "day"sv, date_values, "short"sv }, + DurationInstanceComponent { &DurationRecord::hours, &DurationFormat::hours_style, &DurationFormat::set_hours_style, &DurationFormat::hours_display, &DurationFormat::set_hours_display, "hours"sv, "hour"sv, time_values, "numeric"sv }, + DurationInstanceComponent { &DurationRecord::minutes, &DurationFormat::minutes_style, &DurationFormat::set_minutes_style, &DurationFormat::minutes_display, &DurationFormat::set_minutes_display, "minutes"sv, "minute"sv, time_values, "numeric"sv }, + DurationInstanceComponent { &DurationRecord::seconds, &DurationFormat::seconds_style, &DurationFormat::set_seconds_style, &DurationFormat::seconds_display, &DurationFormat::set_seconds_display, "seconds"sv, "second"sv, time_values, "numeric"sv }, + DurationInstanceComponent { &DurationRecord::milliseconds, &DurationFormat::milliseconds_style, &DurationFormat::set_milliseconds_style, &DurationFormat::milliseconds_display, &DurationFormat::set_milliseconds_display, "milliseconds"sv, "millisecond"sv, sub_second_values, "numeric"sv }, + DurationInstanceComponent { &DurationRecord::microseconds, &DurationFormat::microseconds_style, &DurationFormat::set_microseconds_style, &DurationFormat::microseconds_display, &DurationFormat::set_microseconds_display, "microseconds"sv, "microsecond"sv, sub_second_values, "numeric"sv }, + DurationInstanceComponent { &DurationRecord::nanoseconds, &DurationFormat::nanoseconds_style, &DurationFormat::set_nanoseconds_style, &DurationFormat::nanoseconds_display, &DurationFormat::set_nanoseconds_display, "nanoseconds"sv, "nanosecond"sv, sub_second_values, "numeric"sv }, }; struct DurationUnitOptions { @@ -239,15 +252,16 @@ struct DurationFormatPart { StringView unit; }; -ThrowCompletionOr to_duration_record(VM&, Value input); +ThrowCompletionOr to_duration_record(VM&, Value input); +i8 duration_sign(DurationRecord const&); ThrowCompletionOr get_duration_unit_options(VM&, String const& unit, Object const& options, StringView base_style, ReadonlySpan styles_list, StringView digital_base, StringView previous_style, bool two_digit_hours); -double add_fractional_digits(DurationFormat const&, Temporal::DurationRecord const&); +double add_fractional_digits(DurationFormat const&, DurationRecord const&); bool next_unit_fractional(DurationFormat const&, StringView unit); Vector format_numeric_hours(VM&, DurationFormat const&, double hours_value, bool sign_displayed); Vector format_numeric_minutes(VM&, DurationFormat const&, double minutes_value, bool hours_displayed, bool sign_displayed); Vector format_numeric_seconds(VM&, DurationFormat const&, double seconds_value, bool minutes_displayed, bool sign_displayed); -Vector format_numeric_units(VM&, DurationFormat const&, Temporal::DurationRecord const&, StringView first_numeric_unit, bool sign_displayed); +Vector format_numeric_units(VM&, DurationFormat const&, DurationRecord const&, StringView first_numeric_unit, bool sign_displayed); Vector list_format_parts(VM&, DurationFormat const&, Vector>& partitioned_parts_list); -Vector partition_duration_format_pattern(VM&, DurationFormat const&, Temporal::DurationRecord const&); +Vector partition_duration_format_pattern(VM&, DurationFormat const&, DurationRecord const&); }