Kaynağa Gözat

LibJS: Implement the ToDurationRecord abstract operation

Idan Horowitz 3 yıl önce
ebeveyn
işleme
8e55eb960e

+ 54 - 1
Userland/Libraries/LibJS/Runtime/Intl/DurationFormat.cpp

@@ -5,8 +5,8 @@
  */
  */
 
 
 #include <LibJS/Runtime/GlobalObject.h>
 #include <LibJS/Runtime/GlobalObject.h>
-#include <LibJS/Runtime/Intl/AbstractOperations.h>
 #include <LibJS/Runtime/Intl/DurationFormat.h>
 #include <LibJS/Runtime/Intl/DurationFormat.h>
+#include <LibJS/Runtime/Temporal/AbstractOperations.h>
 
 
 namespace JS::Intl {
 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<Temporal::DurationRecord> 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<TypeError>(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<TypeError>(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
 // 1.1.2 GetDurationUnitOptions ( unit, options, baseStyle, stylesList, digitalBase, prevStyle ), https://tc39.es/proposal-intl-duration-format/#sec-getdurationunitoptions
 ThrowCompletionOr<DurationUnitOptions> get_duration_unit_options(GlobalObject& global_object, String const& unit, Object const& options, StringView base_style, Span<StringView const> styles_list, StringView digital_base, Optional<String> const& previous_style)
 ThrowCompletionOr<DurationUnitOptions> get_duration_unit_options(GlobalObject& global_object, String const& unit, Object const& options, StringView base_style, Span<StringView const> styles_list, StringView digital_base, Optional<String> const& previous_style)
 {
 {

+ 14 - 10
Userland/Libraries/LibJS/Runtime/Intl/DurationFormat.h

@@ -8,7 +8,9 @@
 
 
 #include <AK/Array.h>
 #include <AK/Array.h>
 #include <AK/String.h>
 #include <AK/String.h>
+#include <LibJS/Runtime/Intl/AbstractOperations.h>
 #include <LibJS/Runtime/Object.h>
 #include <LibJS/Runtime/Object.h>
+#include <LibJS/Runtime/Temporal/Duration.h>
 
 
 namespace JS::Intl {
 namespace JS::Intl {
 
 
@@ -160,6 +162,7 @@ private:
 };
 };
 
 
 struct DurationInstanceComponent {
 struct DurationInstanceComponent {
+    double Temporal::DurationRecord::*value_slot;
     void (DurationFormat::*set_style_slot)(StringView);
     void (DurationFormat::*set_style_slot)(StringView);
     void (DurationFormat::*set_display_slot)(StringView);
     void (DurationFormat::*set_display_slot)(StringView);
     StringView unit;
     StringView unit;
@@ -172,16 +175,16 @@ static constexpr AK::Array<StringView, 3> date_values = { "long"sv, "short"sv, "
 static constexpr AK::Array<StringView, 5> time_values = { "long"sv, "short"sv, "narrow"sv, "numeric"sv, "2-digit"sv };
 static constexpr AK::Array<StringView, 5> time_values = { "long"sv, "short"sv, "narrow"sv, "numeric"sv, "2-digit"sv };
 static constexpr AK::Array<StringView, 4> sub_second_values = { "long"sv, "short"sv, "narrow"sv, "numeric"sv };
 static constexpr AK::Array<StringView, 4> sub_second_values = { "long"sv, "short"sv, "narrow"sv, "numeric"sv };
 static constexpr AK::Array<DurationInstanceComponent, 10> duration_instances_components {
 static constexpr AK::Array<DurationInstanceComponent, 10> 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 {
 struct DurationUnitOptions {
@@ -189,6 +192,7 @@ struct DurationUnitOptions {
     String display;
     String display;
 };
 };
 
 
+ThrowCompletionOr<Temporal::DurationRecord> to_duration_record(GlobalObject& global_object, Value input);
 ThrowCompletionOr<DurationUnitOptions> get_duration_unit_options(GlobalObject& global_object, String const& unit, Object const& options, StringView base_style, Span<StringView const> styles_list, StringView digital_base, Optional<String> const& previous_style);
 ThrowCompletionOr<DurationUnitOptions> get_duration_unit_options(GlobalObject& global_object, String const& unit, Object const& options, StringView base_style, Span<StringView const> styles_list, StringView digital_base, Optional<String> const& previous_style);
 
 
 }
 }