From 5b68c1a06c88d578a4424ad183054b8092ac42b0 Mon Sep 17 00:00:00 2001 From: Timothy Flynn Date: Fri, 8 Jul 2022 12:05:09 -0400 Subject: [PATCH] LibJS: Use Intl.PluralRules within Intl.NumberFormat This also allows removing a bit of a BigInt hack to resolve plurality of BigInt numbers (because the AOs used in ResolvePlural support BigInt, wherease the naive Unicode::select_pattern_with_plurality did not). We use cardinal form here; the number format patterns in the CLDR align with the cardinal form of the plural rules. --- .../LibJS/Runtime/Intl/NumberFormat.cpp | 26 ++++++++----------- .../LibJS/Runtime/Intl/NumberFormat.h | 2 +- 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/Userland/Libraries/LibJS/Runtime/Intl/NumberFormat.cpp b/Userland/Libraries/LibJS/Runtime/Intl/NumberFormat.cpp index 79017c6d46..6863ce6b34 100644 --- a/Userland/Libraries/LibJS/Runtime/Intl/NumberFormat.cpp +++ b/Userland/Libraries/LibJS/Runtime/Intl/NumberFormat.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -469,7 +470,7 @@ Vector partition_number_pattern(GlobalObject& global_object, N Unicode::NumberFormat found_pattern {}; // 6. Let pattern be GetNumberFormatPattern(numberFormat, x). - auto pattern = get_number_format_pattern(number_format, number, found_pattern); + auto pattern = get_number_format_pattern(global_object, number_format, number, found_pattern); if (!pattern.has_value()) return {}; @@ -1027,17 +1028,8 @@ RawFormatResult to_raw_fixed(GlobalObject& global_object, Value number, int min_ } // 15.5.11 GetNumberFormatPattern ( numberFormat, x ), https://tc39.es/ecma402/#sec-getnumberformatpattern -Optional> get_number_format_pattern(NumberFormat& number_format, Value number, Unicode::NumberFormat& found_pattern) +Optional> get_number_format_pattern(GlobalObject& global_object, NumberFormat& number_format, Value number, Unicode::NumberFormat& found_pattern) { - auto as_number = [&]() { - if (number.is_number()) - return number.as_double(); - - // FIXME: This should be okay for now as our naive Unicode::select_pattern_with_plurality implementation - // checks against just a few specific small values. But revisit this if precision becomes a concern. - return number.as_bigint().big_integer().to_double(); - }; - // 1. Let localeData be %NumberFormat%.[[LocaleData]]. // 2. Let dataLocale be numberFormat.[[DataLocale]]. // 3. Let dataLocaleData be localeData.[[]]. @@ -1063,7 +1055,11 @@ Optional> get_number_format_pattern(NumberFormat& nu // e. Let patterns be patterns.[[]]. // f. Let patterns be patterns.[[]]. auto formats = Unicode::get_unit_formats(number_format.data_locale(), number_format.unit(), number_format.unit_display()); - patterns = Unicode::select_pattern_with_plurality(formats, as_number()); + auto plurality = resolve_plural(global_object, number_format, Unicode::PluralForm::Cardinal, number); + + if (auto it = formats.find_if([&](auto& p) { return p.plurality == plurality; }); it != formats.end()) + patterns = move(*it); + break; } @@ -1082,10 +1078,10 @@ Optional> get_number_format_pattern(NumberFormat& nu // Handling of other [[CurrencyDisplay]] options will occur after [[SignDisplay]]. if (number_format.currency_display() == NumberFormat::CurrencyDisplay::Name) { auto formats = Unicode::get_compact_number_system_formats(number_format.data_locale(), number_format.numbering_system(), Unicode::CompactNumberFormatType::CurrencyUnit); + auto plurality = resolve_plural(global_object, number_format, Unicode::PluralForm::Cardinal, number); - auto maybe_patterns = Unicode::select_pattern_with_plurality(formats, as_number()); - if (maybe_patterns.has_value()) { - patterns = maybe_patterns.release_value(); + if (auto it = formats.find_if([&](auto& p) { return p.plurality == plurality; }); it != formats.end()) { + patterns = move(*it); break; } } diff --git a/Userland/Libraries/LibJS/Runtime/Intl/NumberFormat.h b/Userland/Libraries/LibJS/Runtime/Intl/NumberFormat.h index ba36285086..1f08fe8ae5 100644 --- a/Userland/Libraries/LibJS/Runtime/Intl/NumberFormat.h +++ b/Userland/Libraries/LibJS/Runtime/Intl/NumberFormat.h @@ -228,7 +228,7 @@ String format_numeric(GlobalObject& global_object, NumberFormat& number_format, Array* format_numeric_to_parts(GlobalObject& global_object, NumberFormat& number_format, Value number); RawFormatResult to_raw_precision(GlobalObject& global_object, Value number, int min_precision, int max_precision); RawFormatResult to_raw_fixed(GlobalObject& global_object, Value number, int min_fraction, int max_fraction); -Optional> get_number_format_pattern(NumberFormat& number_format, Value number, Unicode::NumberFormat& found_pattern); +Optional> get_number_format_pattern(GlobalObject& global_object, NumberFormat& number_format, Value number, Unicode::NumberFormat& found_pattern); Optional get_notation_sub_pattern(NumberFormat& number_format, int exponent); int compute_exponent(GlobalObject& global_object, NumberFormat& number_format, Value number); int compute_exponent_for_magnitude(NumberFormat& number_format, int magnitude);