From 72674d7905ab1e20254134342712ad893d770efe Mon Sep 17 00:00:00 2001 From: Timothy Flynn Date: Mon, 28 Mar 2022 10:17:39 -0400 Subject: [PATCH] LibJS: Set DateTimeFormat's [[HourCycle]] internal slot only once This is an editorial change in the Intl spec. See: https://github.com/tc39/ecma402/commit/8081868 --- .../LibJS/Runtime/Intl/DateTimeFormat.h | 1 - .../Intl/DateTimeFormatConstructor.cpp | 169 +++++++++--------- 2 files changed, 86 insertions(+), 84 deletions(-) diff --git a/Userland/Libraries/LibJS/Runtime/Intl/DateTimeFormat.h b/Userland/Libraries/LibJS/Runtime/Intl/DateTimeFormat.h index 21af771186..f4ffd3e7fa 100644 --- a/Userland/Libraries/LibJS/Runtime/Intl/DateTimeFormat.h +++ b/Userland/Libraries/LibJS/Runtime/Intl/DateTimeFormat.h @@ -60,7 +60,6 @@ public: bool has_hour_cycle() const { return m_hour_cycle.has_value(); } Unicode::HourCycle hour_cycle() const { return *m_hour_cycle; } StringView hour_cycle_string() const { return Unicode::hour_cycle_to_string(*m_hour_cycle); } - void set_hour_cycle(StringView hour_cycle) { m_hour_cycle = Unicode::hour_cycle_from_string(hour_cycle); } void set_hour_cycle(Unicode::HourCycle hour_cycle) { m_hour_cycle = hour_cycle; } void clear_hour_cycle() { m_hour_cycle.clear(); } diff --git a/Userland/Libraries/LibJS/Runtime/Intl/DateTimeFormatConstructor.cpp b/Userland/Libraries/LibJS/Runtime/Intl/DateTimeFormatConstructor.cpp index 6ef00d730c..9f53c36bcd 100644 --- a/Userland/Libraries/LibJS/Runtime/Intl/DateTimeFormatConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/Intl/DateTimeFormatConstructor.cpp @@ -156,32 +156,90 @@ ThrowCompletionOr initialize_date_time_format(GlobalObject& glo if (result.ca.has_value()) date_time_format.set_calendar(result.ca.release_value()); - // 21. Set dateTimeFormat.[[HourCycle]] to r.[[hc]]. - if (result.hc.has_value()) - date_time_format.set_hour_cycle(result.hc.release_value()); - - // 22. Set dateTimeFormat.[[NumberingSystem]] to r.[[nu]]. + // 21. Set dateTimeFormat.[[NumberingSystem]] to r.[[nu]]. if (result.nu.has_value()) date_time_format.set_numbering_system(result.nu.release_value()); - // 23. Let dataLocale be r.[[dataLocale]]. + // 22. Let dataLocale be r.[[dataLocale]]. auto data_locale = move(result.data_locale); // Non-standard, the data locale is needed for LibUnicode lookups while formatting. date_time_format.set_data_locale(data_locale); - // 24. Let timeZone be ? Get(options, "timeZone"). + // 23. Let dataLocaleData be localeData.[[]]. + // 24. Let hcDefault be dataLocaleData.[[hourCycle]]. + auto default_hour_cycle = Unicode::get_default_regional_hour_cycle(data_locale); + + // Non-standard, default_hour_cycle will be empty if Unicode data generation is disabled. + if (!default_hour_cycle.has_value()) + return &date_time_format; + + Optional hour_cycle_value; + + // 25. If r.[[hc]] is null, then + if (!result.hc.has_value()) { + // a. Let hc be hcDefault. + hour_cycle_value = default_hour_cycle; + } + + // 26. If hour12 is true, then + if (hour12.is_boolean() && hour12.as_bool()) { + // a. If hcDefault is "h11" or "h23", then + if ((default_hour_cycle == Unicode::HourCycle::H11) || (default_hour_cycle == Unicode::HourCycle::H23)) { + // i. Let hc be "h11". + hour_cycle_value = Unicode::HourCycle::H11; + } + // b. Else, + else { + // i. Let hc be "h12". + hour_cycle_value = Unicode::HourCycle::H12; + } + } + // 27. Else if hour12 is false, then + else if (hour12.is_boolean() && !hour12.as_bool()) { + // a. If hcDefault is "h11" or "h23", then + if ((default_hour_cycle == Unicode::HourCycle::H11) || (default_hour_cycle == Unicode::HourCycle::H23)) { + // i. Let hc be "h23". + hour_cycle_value = Unicode::HourCycle::H23; + } + // b. Else, + else { + // i. Let hc be "h24". + hour_cycle_value = Unicode::HourCycle::H24; + } + } + // 28. Else, + else { + // a. Let hc be r.[[hc]]. + if (result.hc.has_value()) + hour_cycle_value = Unicode::hour_cycle_from_string(*result.hc); + + // b. Assert: hour12 is undefined. + VERIFY(hour12.is_undefined()); + } + + // 29. Set dateTimeFormat.[[HourCycle]] to hc. + if (hour_cycle_value.has_value()) + date_time_format.set_hour_cycle(*hour_cycle_value); + + // 30. Let formatOptions be a new Record. + Unicode::CalendarPattern format_options {}; + + // 31. Set formatOptions.[[hourCycle]] to hc. + format_options.hour_cycle = hour_cycle_value; + + // 32. Let timeZone be ? Get(options, "timeZone"). auto time_zone_value = TRY(options->get(vm.names.timeZone)); String time_zone; - // 25. If timeZone is undefined, then + // 33. If timeZone is undefined, then if (time_zone_value.is_undefined()) { - // a. Let timeZone be DefaultTimeZone(). + // a. Set timeZone to DefaultTimeZone(). time_zone = Temporal::default_time_zone(); } - // 26. Else, + // 34. Else, else { - // a. Let timeZone be ? ToString(timeZone). + // a. Set timeZone to ? ToString(timeZone). time_zone = TRY(time_zone_value.to_string(global_object)); // b. If the result of IsValidTimeZoneName(timeZone) is false, then @@ -190,17 +248,14 @@ ThrowCompletionOr initialize_date_time_format(GlobalObject& glo return vm.throw_completion(global_object, ErrorType::OptionIsNotValidValue, time_zone, vm.names.timeZone); } - // c. Let timeZone be CanonicalizeTimeZoneName(timeZone). + // c. Set timeZone to CanonicalizeTimeZoneName(timeZone). time_zone = Temporal::canonicalize_time_zone_name(time_zone); } - // 27. Set dateTimeFormat.[[TimeZone]] to timeZone. + // 35. Set dateTimeFormat.[[TimeZone]] to timeZone. date_time_format.set_time_zone(move(time_zone)); - // 28. Let formatOptions be a new Record. - Unicode::CalendarPattern format_options {}; - - // 29. For each row of Table 6, except the header row, in table order, do + // 36. For each row of Table 6, except the header row, in table order, do TRY(for_each_calendar_field(global_object, format_options, [&](auto& option, auto const& property, auto const& defaults) -> ThrowCompletionOr { using ValueType = typename RemoveReference::ValueType; @@ -228,78 +283,26 @@ ThrowCompletionOr initialize_date_time_format(GlobalObject& glo return {}; })); - // 30. Let dataLocaleData be localeData.[[]]. - - // 31. Let hcDefault be dataLocaleData.[[hourCycle]]. - auto default_hour_cycle = Unicode::get_default_regional_hour_cycle(data_locale); - - // Non-standard, default_hour_cycle will be empty if Unicode data generation is disabled. - if (!default_hour_cycle.has_value()) - return &date_time_format; - - // 32. Let hc be dateTimeFormat.[[HourCycle]]. - // 33. If hc is null, then - // a. Set hc to hcDefault. - auto hour_cycle_value = date_time_format.has_hour_cycle() ? date_time_format.hour_cycle() : *default_hour_cycle; - - // 34. If hour12 is true, then - if (hour12.is_boolean() && hour12.as_bool()) { - // a. If hcDefault is "h11" or "h23", then - if ((default_hour_cycle == Unicode::HourCycle::H11) || (default_hour_cycle == Unicode::HourCycle::H23)) { - // i. Set hc to "h11". - hour_cycle_value = Unicode::HourCycle::H11; - } - // b. Else, - else { - // i. Set hc to "h12". - hour_cycle_value = Unicode::HourCycle::H12; - } - } - // 35. Else if hour12 is false, then - else if (hour12.is_boolean() && !hour12.as_bool()) { - // a. If hcDefault is "h11" or "h23", then - if ((default_hour_cycle == Unicode::HourCycle::H11) || (default_hour_cycle == Unicode::HourCycle::H23)) { - // i. Set hc to "h23". - hour_cycle_value = Unicode::HourCycle::H23; - } - // b. Else, - else { - // i. Set hc to "h24". - hour_cycle_value = Unicode::HourCycle::H24; - } - } - // 36. Else, - else { - // a. Assert: hour12 is undefined. - VERIFY(hour12.is_undefined()); - } - - // 37. Set dateTimeFormat.[[HourCycle]] to hc. - date_time_format.set_hour_cycle(hour_cycle_value); - - // 38. Set formatOptions.[[hourCycle]] to hc. - format_options.hour_cycle = hour_cycle_value; - - // 39. Let matcher be ? GetOption(options, "formatMatcher", "string", « "basic", "best fit" », "best fit"). + // 37. Let matcher be ? GetOption(options, "formatMatcher", "string", « "basic", "best fit" », "best fit"). matcher = TRY(get_option(global_object, *options, vm.names.formatMatcher, Value::Type::String, AK::Array { "basic"sv, "best fit"sv }, "best fit"sv)); - // 40. Let dateStyle be ? GetOption(options, "dateStyle", "string", « "full", "long", "medium", "short" », undefined). + // 38. Let dateStyle be ? GetOption(options, "dateStyle", "string", « "full", "long", "medium", "short" », undefined). auto date_style = TRY(get_option(global_object, *options, vm.names.dateStyle, Value::Type::String, AK::Array { "full"sv, "long"sv, "medium"sv, "short"sv }, Empty {})); - // 41. Set dateTimeFormat.[[DateStyle]] to dateStyle. + // 39. Set dateTimeFormat.[[DateStyle]] to dateStyle. if (!date_style.is_undefined()) date_time_format.set_date_style(date_style.as_string().string()); - // 42. Let timeStyle be ? GetOption(options, "timeStyle", "string", « "full", "long", "medium", "short" », undefined). + // 40. Let timeStyle be ? GetOption(options, "timeStyle", "string", « "full", "long", "medium", "short" », undefined). auto time_style = TRY(get_option(global_object, *options, vm.names.timeStyle, Value::Type::String, AK::Array { "full"sv, "long"sv, "medium"sv, "short"sv }, Empty {})); - // 43. Set dateTimeFormat.[[TimeStyle]] to timeStyle. + // 41. Set dateTimeFormat.[[TimeStyle]] to timeStyle. if (!time_style.is_undefined()) date_time_format.set_time_style(time_style.as_string().string()); Optional best_format {}; - // 44. If dateStyle is not undefined or timeStyle is not undefined, then + // 42. If dateStyle is not undefined or timeStyle is not undefined, then if (date_time_format.has_date_style() || date_time_format.has_time_style()) { // a. For each row in Table 6, except the header row, do TRY(for_each_calendar_field(global_object, format_options, [&](auto const& option, auto const& property, auto const&) -> ThrowCompletionOr { @@ -318,7 +321,7 @@ ThrowCompletionOr initialize_date_time_format(GlobalObject& glo // c. Let bestFormat be DateTimeStyleFormat(dateStyle, timeStyle, styles). best_format = date_time_style_format(data_locale, date_time_format); } - // 45. Else, + // 43. Else, else { // a. Let formats be dataLocaleData.[[formats]].[[]]. auto formats = Unicode::get_calendar_available_formats(data_locale, date_time_format.calendar()); @@ -335,7 +338,7 @@ ThrowCompletionOr initialize_date_time_format(GlobalObject& glo } } - // 46. For each row in Table 6, except the header row, in table order, do + // 44. For each row in Table 6, except the header row, in table order, do date_time_format.for_each_calendar_field_zipped_with(*best_format, [&](auto& date_time_format_field, auto const& best_format_field, auto) { // a. Let prop be the name given in the Property column of the row. // b. If bestFormat has a field [[]], then @@ -349,13 +352,13 @@ ThrowCompletionOr initialize_date_time_format(GlobalObject& glo String pattern; Vector range_patterns; - // 47. If dateTimeFormat.[[Hour]] is undefined, then + // 45. If dateTimeFormat.[[Hour]] is undefined, then if (!date_time_format.has_hour()) { // a. Set dateTimeFormat.[[HourCycle]] to undefined. date_time_format.clear_hour_cycle(); } - // 48. If dateTimeformat.[[HourCycle]] is "h11" or "h12", then + // 46. If dateTimeformat.[[HourCycle]] is "h11" or "h12", then if ((hour_cycle_value == Unicode::HourCycle::H11) || (hour_cycle_value == Unicode::HourCycle::H12)) { // a. Let pattern be bestFormat.[[pattern12]]. if (best_format->pattern12.has_value()) { @@ -369,7 +372,7 @@ ThrowCompletionOr initialize_date_time_format(GlobalObject& glo // b. Let rangePatterns be bestFormat.[[rangePatterns12]]. range_patterns = Unicode::get_calendar_range12_formats(data_locale, date_time_format.calendar(), best_format->skeleton); } - // 49. Else, + // 47. Else, else { // a. Let pattern be bestFormat.[[pattern]]. pattern = move(best_format->pattern); @@ -378,13 +381,13 @@ ThrowCompletionOr initialize_date_time_format(GlobalObject& glo range_patterns = Unicode::get_calendar_range_formats(data_locale, date_time_format.calendar(), best_format->skeleton); } - // 50. Set dateTimeFormat.[[Pattern]] to pattern. + // 48. Set dateTimeFormat.[[Pattern]] to pattern. date_time_format.set_pattern(move(pattern)); - // 51. Set dateTimeFormat.[[RangePatterns]] to rangePatterns. + // 49. Set dateTimeFormat.[[RangePatterns]] to rangePatterns. date_time_format.set_range_patterns(move(range_patterns)); - // 52. Return dateTimeFormat. + // 50. Return dateTimeFormat. return &date_time_format; }