diff options
author | Timothy Flynn <trflynn89@pm.me> | 2022-09-02 09:06:55 -0400 |
---|---|---|
committer | Linus Groh <mail@linusgroh.de> | 2022-11-03 18:37:48 +0000 |
commit | 99fc94e138e604d9395d7a76072d5f82b42a0519 (patch) | |
tree | 10a32b3eb640c32cf8490a7dd45c519d0d5da671 /Userland/Libraries/LibJS/Runtime | |
parent | a5bf32018f6e9ea87f9d01c072ca439cb9eed94d (diff) | |
download | serenity-99fc94e138e604d9395d7a76072d5f82b42a0519.zip |
LibJS: Delegate to NumberFormat for DurationFormat unit formatting
This is a normative change in the Intl.DurationFormat proposal. See:
https://github.com/tc39/proposal-intl-duration-format/commit/12ba9df
Diffstat (limited to 'Userland/Libraries/LibJS/Runtime')
-rw-r--r-- | Userland/Libraries/LibJS/Runtime/Intl/DurationFormat.cpp | 78 | ||||
-rw-r--r-- | Userland/Libraries/LibJS/Runtime/Intl/DurationFormat.h | 2 |
2 files changed, 33 insertions, 47 deletions
diff --git a/Userland/Libraries/LibJS/Runtime/Intl/DurationFormat.cpp b/Userland/Libraries/LibJS/Runtime/Intl/DurationFormat.cpp index 310009d4e8..f7e9ee35ab 100644 --- a/Userland/Libraries/LibJS/Runtime/Intl/DurationFormat.cpp +++ b/Userland/Libraries/LibJS/Runtime/Intl/DurationFormat.cpp @@ -299,19 +299,6 @@ ThrowCompletionOr<DurationUnitOptions> get_duration_unit_options(VM& vm, String return DurationUnitOptions { .style = move(style), .display = display.as_string().string() }; } -// FIXME: LibUnicode currently only exposes unit patterns converted to an ECMA402 NumberFormat-specific format, -// since DurationFormat only needs a tiny subset of it, it's much easier to just convert it to the expected format -// here, but at some point we should split the NumberFormat exporter to export both formats of the data. -static String convert_number_format_pattern_to_duration_format_template(::Locale::NumberFormat const& number_format) -{ - auto result = number_format.zero_format.replace("{number}"sv, "{0}"sv, ReplaceMode::FirstOnly); - - for (size_t i = 0; i < number_format.identifiers.size(); ++i) - result = result.replace(String::formatted("{{unitIdentifier:{}}}", i), number_format.identifiers[i], ReplaceMode::FirstOnly); - - return result; -} - // 1.1.7 PartitionDurationFormatPattern ( durationFormat, duration ), https://tc39.es/proposal-intl-duration-format/#sec-partitiondurationformatpattern Vector<PatternPartition> partition_duration_format_pattern(VM& vm, DurationFormat const& duration_format, Temporal::DurationRecord const& duration) { @@ -339,19 +326,22 @@ Vector<PatternPartition> partition_duration_format_pattern(VM& vm, DurationForma // d. Let unit be the Unit value. auto unit = duration_instances_component.unit; - // e. Let style be durationFormat.[[<styleSlot>]]. + // e. Let numberFormatUnit be the NumberFormat Unit value. + auto number_format_unit = duration_instances_component.number_format_unit; + + // f. Let style be durationFormat.[[<styleSlot>]]. auto style = (duration_format.*style_slot)(); - // f. Let display be durationFormat.[[<displaySlot>]]. + // g. Let display be durationFormat.[[<displaySlot>]]. auto display = (duration_format.*display_slot)(); - // g. Let value be duration.[[<valueSlot>]]. + // h. Let value be duration.[[<valueSlot>]]. auto value = duration.*value_slot; - // h. Let nfOpts be ! OrdinaryObjectCreate(null). + // i. Let nfOpts be ! OrdinaryObjectCreate(null). auto* number_format_options = Object::create(realm, nullptr); - // i. If unit is "seconds", "milliseconds", or "microseconds", then + // j. If unit is "seconds", "milliseconds", or "microseconds", then if (unit.is_one_of("seconds"sv, "milliseconds"sv, "microseconds"sv)) { DurationFormat::ValueStyle next_style; @@ -400,31 +390,31 @@ Vector<PatternPartition> partition_duration_format_pattern(VM& vm, DurationForma } } - // j. If style is "2-digit", then + // k. If style is "2-digit", then if (style == DurationFormat::ValueStyle::TwoDigit) { // i. Perform ! CreateDataPropertyOrThrow(nfOpts, "minimumIntegerDigits", 2𝔽). MUST(number_format_options->create_data_property_or_throw(vm.names.minimumIntegerDigits, Value(2))); } - // k. If value is not 0 or display is not "auto", then + // l. If value is not 0 or display is not "auto", then if (value != 0.0 || display != DurationFormat::Display::Auto) { - // i. Let nf be ! Construct(%NumberFormat%, « durationFormat.[[Locale]], nfOpts »). - auto* number_format = static_cast<NumberFormat*>(MUST(construct(vm, *realm.intrinsics().intl_number_format_constructor(), js_string(vm, duration_format.locale()), number_format_options))); + // i. If style is "2-digit" or "numeric", then + if (style == DurationFormat::ValueStyle::TwoDigit || style == DurationFormat::ValueStyle::Numeric) { + // 1. Let nf be ! Construct(%NumberFormat%, « durationFormat.[[Locale]], nfOpts »). + auto* number_format = static_cast<NumberFormat*>(MUST(construct(vm, *realm.intrinsics().intl_number_format_constructor(), js_string(vm, duration_format.locale()), number_format_options))); - // ii. Let dataLocale be durationFormat.[[DataLocale]]. - auto const& data_locale = duration_format.data_locale(); + // 2. Let dataLocale be durationFormat.[[DataLocale]]. + auto const& data_locale = duration_format.data_locale(); - // iii. Let dataLocaleData be %DurationFormat%.[[LocaleData]].[[<dataLocale>]]. + // 3. Let dataLocaleData be %DurationFormat%.[[LocaleData]].[[<dataLocale>]]. - // iv. If style is "2-digit" or "numeric", then - if (style == DurationFormat::ValueStyle::TwoDigit || style == DurationFormat::ValueStyle::Numeric) { - // 1. Let num be ! FormatNumeric(nf, 𝔽(value)). + // 4. Let num be ! FormatNumeric(nf, 𝔽(value)). auto number = format_numeric(vm, *number_format, MathematicalValue(value)); - // 2. Append the new Record { [[Type]]: unit, [[Value]]: num} to the end of result. + // 5. Append the new Record { [[Type]]: unit, [[Value]]: num} to the end of result. result.append({ unit, number }); - // 3. If unit is "hours" or "minutes", then + // 6. If unit is "hours" or "minutes", then if (unit.is_one_of("hours"sv, "minutes"sv)) { double next_value = 0.0; DurationFormat::Display next_display; @@ -462,27 +452,23 @@ Vector<PatternPartition> partition_duration_format_pattern(VM& vm, DurationForma } } } - // v. Else, + // ii. Else, else { - // 1. Let num be ! PartitionNumberPattern(nf, 𝔽(value)). - auto number = partition_number_pattern(vm, *number_format, MathematicalValue(value)); - - // 2. Let pr be ! Construct(%PluralRules%, « durationFormat.[[Locale]] »). - auto* plural_rules = static_cast<PluralRules*>(MUST(construct(vm, *realm.intrinsics().intl_plural_rules_constructor(), js_string(vm, duration_format.locale())))); + // 1. Perform ! CreateDataPropertyOrThrow(nfOpts, "style", "unit"). + MUST(number_format_options->create_data_property_or_throw(vm.names.style, js_string(vm, "unit"sv))); - // 3. Let prv be ! ResolvePlural(pr, 𝔽(value)). - auto plurality = resolve_plural(*plural_rules, Value(value)); + // 2. Perform ! CreateDataPropertyOrThrow(nfOpts, "unit", numberFormatUnit). + MUST(number_format_options->create_data_property_or_throw(vm.names.unit, js_string(vm, number_format_unit))); - auto formats = ::Locale::get_unit_formats(data_locale, duration_instances_component.unit_singular, static_cast<::Locale::Style>(style)); - auto pattern = formats.find_if([&](auto& p) { return p.plurality == plurality; }); - if (pattern == formats.end()) - continue; + // 3. Perform ! CreateDataPropertyOrThrow(nfOpts, "unitDisplay", style). + auto unicode_style = ::Locale::style_to_string(static_cast<::Locale::Style>(style)); + MUST(number_format_options->create_data_property_or_throw(vm.names.unitDisplay, js_string(vm, unicode_style))); - // 4. Let template be dataLocaleData.[[formats]].[[<style>]].[[<unit>]].[[<prv>]]. - auto template_ = convert_number_format_pattern_to_duration_format_template(*pattern); + // 4. Let nf be ! Construct(%NumberFormat%, « durationFormat.[[Locale]], nfOpts »). + auto* number_format = static_cast<NumberFormat*>(MUST(construct(vm, *realm.intrinsics().intl_number_format_constructor(), js_string(vm, duration_format.locale()), number_format_options))); - // 5. Let parts be ! MakePartsList(template, unit, num). - auto parts = make_parts_list(template_, unit, move(number)); + // 5. Let parts be ! PartitionNumberPattern(nf, 𝔽(value)). + auto parts = partition_number_pattern(vm, *number_format, MathematicalValue(value)); // 6. Let concat be an empty String. StringBuilder concat; diff --git a/Userland/Libraries/LibJS/Runtime/Intl/DurationFormat.h b/Userland/Libraries/LibJS/Runtime/Intl/DurationFormat.h index 92f3f52268..ec94d24ebe 100644 --- a/Userland/Libraries/LibJS/Runtime/Intl/DurationFormat.h +++ b/Userland/Libraries/LibJS/Runtime/Intl/DurationFormat.h @@ -194,7 +194,7 @@ struct DurationInstanceComponent { DurationFormat::Display (DurationFormat::*get_display_slot)() const; void (DurationFormat::*set_display_slot)(StringView); StringView unit; - StringView unit_singular; + StringView number_format_unit; Span<StringView const> values; StringView digital_default; }; |