From 8e55eb960eceb1c4c7af1b72a19f042bcec4d552 Mon Sep 17 00:00:00 2001 From: Idan Horowitz Date: Thu, 30 Jun 2022 09:43:20 +0300 Subject: [PATCH] LibJS: Implement the ToDurationRecord abstract operation --- .../LibJS/Runtime/Intl/DurationFormat.cpp | 55 ++++++++++++++++++- .../LibJS/Runtime/Intl/DurationFormat.h | 24 ++++---- 2 files changed, 68 insertions(+), 11 deletions(-) diff --git a/Userland/Libraries/LibJS/Runtime/Intl/DurationFormat.cpp b/Userland/Libraries/LibJS/Runtime/Intl/DurationFormat.cpp index cc0c318fa4..cbc698c014 100644 --- a/Userland/Libraries/LibJS/Runtime/Intl/DurationFormat.cpp +++ b/Userland/Libraries/LibJS/Runtime/Intl/DurationFormat.cpp @@ -5,8 +5,8 @@ */ #include -#include #include +#include namespace JS::Intl { @@ -123,6 +123,59 @@ StringView DurationFormat::display_to_string(Display display) } } +// 1.1.1 ToDurationRecord ( input ), https://tc39.es/proposal-intl-duration-format/#sec-todurationrecord +ThrowCompletionOr to_duration_record(GlobalObject& global_object, Value input) +{ + auto& vm = global_object.vm(); + + // 1. If Type(input) is not Object, throw a TypeError exception. + if (!input.is_object()) + return vm.throw_completion(global_object, ErrorType::NotAnObject, input); + auto& input_object = input.as_object(); + + // 2. Let result be a new Record. + Temporal::DurationRecord result; + + // 3. Let any be false. + auto any = false; + + // 4. For each row in Table 1, except the header row, in table order, do + for (auto const& duration_instances_component : duration_instances_components) { + // a. Let valueSlot be the Value Slot value. + auto value_slot = duration_instances_component.value_slot; + + // b. Let unit be the Unit value. + auto unit = duration_instances_component.unit; + + // c. Let value be ? Get(input, unit). + auto value = TRY(input_object.get(FlyString(unit))); + + double value_number; + // d. If value is not undefined, then + if (!value.is_undefined()) { + // i. Set any to true. + any = true; + // ii. Set value to ? ToIntegerWithoutRounding(value). + value_number = TRY(Temporal::to_integer_without_rounding(global_object, value, ErrorType::TemporalInvalidDurationPropertyValueNonIntegral, unit, value)); + } + // e. Else, + else { + // i. Set value to 0. + value_number = 0; + } + + // f. Set the field of result whose name is valueSlot to value. + result.*value_slot = value_number; + } + + // 5. If any is false, throw a TypeError exception. + if (!any) + return vm.throw_completion(global_object, ErrorType::TemporalInvalidDurationLikeObject); + + // 6. Return result. + return result; +} + // 1.1.2 GetDurationUnitOptions ( unit, options, baseStyle, stylesList, digitalBase, prevStyle ), https://tc39.es/proposal-intl-duration-format/#sec-getdurationunitoptions ThrowCompletionOr get_duration_unit_options(GlobalObject& global_object, String const& unit, Object const& options, StringView base_style, Span styles_list, StringView digital_base, Optional const& previous_style) { diff --git a/Userland/Libraries/LibJS/Runtime/Intl/DurationFormat.h b/Userland/Libraries/LibJS/Runtime/Intl/DurationFormat.h index 7a63d9c66d..ea59c2b60f 100644 --- a/Userland/Libraries/LibJS/Runtime/Intl/DurationFormat.h +++ b/Userland/Libraries/LibJS/Runtime/Intl/DurationFormat.h @@ -8,7 +8,9 @@ #include #include +#include #include +#include namespace JS::Intl { @@ -160,6 +162,7 @@ private: }; struct DurationInstanceComponent { + double Temporal::DurationRecord::*value_slot; void (DurationFormat::*set_style_slot)(StringView); void (DurationFormat::*set_display_slot)(StringView); StringView unit; @@ -172,16 +175,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 { &DurationFormat::set_years_style, &DurationFormat::set_years_display, "years"sv, date_values, "narrow"sv }, - DurationInstanceComponent { &DurationFormat::set_months_style, &DurationFormat::set_months_display, "months"sv, date_values, "narrow"sv }, - DurationInstanceComponent { &DurationFormat::set_weeks_style, &DurationFormat::set_weeks_display, "weeks"sv, date_values, "narrow"sv }, - DurationInstanceComponent { &DurationFormat::set_days_style, &DurationFormat::set_days_display, "days"sv, date_values, "narrow"sv }, - DurationInstanceComponent { &DurationFormat::set_hours_style, &DurationFormat::set_hours_display, "hours"sv, time_values, "numeric"sv }, - DurationInstanceComponent { &DurationFormat::set_minutes_style, &DurationFormat::set_minutes_display, "minutes"sv, time_values, "numeric"sv }, - DurationInstanceComponent { &DurationFormat::set_seconds_style, &DurationFormat::set_seconds_display, "seconds"sv, time_values, "numeric"sv }, - DurationInstanceComponent { &DurationFormat::set_milliseconds_style, &DurationFormat::set_milliseconds_display, "milliseconds"sv, sub_second_values, "numeric"sv }, - DurationInstanceComponent { &DurationFormat::set_microseconds_style, &DurationFormat::set_microseconds_display, "microseconds"sv, sub_second_values, "numeric"sv }, - DurationInstanceComponent { &DurationFormat::set_nanoseconds_style, &DurationFormat::set_nanoseconds_display, "nanoseconds"sv, sub_second_values, "numeric"sv }, + DurationInstanceComponent { &Temporal::DurationRecord::years, &DurationFormat::set_years_style, &DurationFormat::set_years_display, "years"sv, date_values, "narrow"sv }, + DurationInstanceComponent { &Temporal::DurationRecord::months, &DurationFormat::set_months_style, &DurationFormat::set_months_display, "months"sv, date_values, "narrow"sv }, + DurationInstanceComponent { &Temporal::DurationRecord::weeks, &DurationFormat::set_weeks_style, &DurationFormat::set_weeks_display, "weeks"sv, date_values, "narrow"sv }, + DurationInstanceComponent { &Temporal::DurationRecord::days, &DurationFormat::set_days_style, &DurationFormat::set_days_display, "days"sv, date_values, "narrow"sv }, + DurationInstanceComponent { &Temporal::DurationRecord::hours, &DurationFormat::set_hours_style, &DurationFormat::set_hours_display, "hours"sv, time_values, "numeric"sv }, + DurationInstanceComponent { &Temporal::DurationRecord::minutes, &DurationFormat::set_minutes_style, &DurationFormat::set_minutes_display, "minutes"sv, time_values, "numeric"sv }, + DurationInstanceComponent { &Temporal::DurationRecord::seconds, &DurationFormat::set_seconds_style, &DurationFormat::set_seconds_display, "seconds"sv, time_values, "numeric"sv }, + DurationInstanceComponent { &Temporal::DurationRecord::milliseconds, &DurationFormat::set_milliseconds_style, &DurationFormat::set_milliseconds_display, "milliseconds"sv, sub_second_values, "numeric"sv }, + DurationInstanceComponent { &Temporal::DurationRecord::microseconds, &DurationFormat::set_microseconds_style, &DurationFormat::set_microseconds_display, "microseconds"sv, sub_second_values, "numeric"sv }, + DurationInstanceComponent { &Temporal::DurationRecord::nanoseconds, &DurationFormat::set_nanoseconds_style, &DurationFormat::set_nanoseconds_display, "nanoseconds"sv, sub_second_values, "numeric"sv }, }; struct DurationUnitOptions { @@ -189,6 +192,7 @@ struct DurationUnitOptions { String display; }; +ThrowCompletionOr to_duration_record(GlobalObject& global_object, Value input); ThrowCompletionOr get_duration_unit_options(GlobalObject& global_object, String const& unit, Object const& options, StringView base_style, Span styles_list, StringView digital_base, Optional const& previous_style); }