summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibJS/Runtime
diff options
context:
space:
mode:
authorTimothy Flynn <trflynn89@pm.me>2022-09-02 09:06:55 -0400
committerLinus Groh <mail@linusgroh.de>2022-11-03 18:37:48 +0000
commit99fc94e138e604d9395d7a76072d5f82b42a0519 (patch)
tree10a32b3eb640c32cf8490a7dd45c519d0d5da671 /Userland/Libraries/LibJS/Runtime
parenta5bf32018f6e9ea87f9d01c072ca439cb9eed94d (diff)
downloadserenity-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.cpp78
-rw-r--r--Userland/Libraries/LibJS/Runtime/Intl/DurationFormat.h2
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;
};