LibJS: Differentiate between undefined and null locale keys

We were previously treating undefined and null as the same (an empty
Optional). However, there are edge cases in ECMA-402 where we must treat
them differently. Namely, the hour cycle (hc) keyword. An undefined hc
value has no effect on the resolved locale, whereas a null hc value can
actively override any hc specified in the locale string. For example:

    new Intl.DateTimeFormat("en-u-hc-h11", { hour12: false });

In that object, the hour12 option does not match the u-hc-h11 value. So
the spec dictates we remove the hc value by setting it to null.
This commit is contained in:
Timothy Flynn 2024-06-16 15:36:34 -04:00 committed by Andreas Kling
commit 4598a505b1
Notes: sideshowbarker 2024-07-17 00:25:35 +09:00
7 changed files with 100 additions and 58 deletions

View file

@ -77,8 +77,7 @@ ThrowCompletionOr<NonnullGCPtr<Object>> DurationFormatConstructor::construct(Fun
// 8. Let opt be the Record { [[localeMatcher]]: matcher, [[nu]]: numberingSystem }.
LocaleOptions opt {};
opt.locale_matcher = matcher;
if (!numbering_system.is_undefined())
opt.nu = numbering_system.as_string().utf8_string();
opt.nu = locale_key_from_value(numbering_system);
// 9. Let r be ResolveLocale(%DurationFormat%.[[AvailableLocales]], requestedLocales, opt, %DurationFormat%.[[RelevantExtensionKeys]], %DurationFormat%.[[LocaleData]]).
auto result = resolve_locale(requested_locales, opt, DurationFormat::relevant_extension_keys());
@ -110,8 +109,8 @@ ThrowCompletionOr<NonnullGCPtr<Object>> DurationFormatConstructor::construct(Fun
duration_format->set_minutes_seconds_separator(move(digital_format.minutes_seconds_separator));
// 22. Set durationFormat.[[NumberingSystem]] to r.[[nu]].
if (result.nu.has_value())
duration_format->set_numbering_system(result.nu.release_value());
if (auto* resolved_numbering_system = result.nu.get_pointer<String>())
duration_format->set_numbering_system(move(*resolved_numbering_system));
// 23. Let style be ? GetOption(options, "style", string, « "long", "short", "narrow", "digital" », "short").
auto style = TRY(get_option(vm, *options, vm.names.style, OptionType::String, { "long"sv, "short"sv, "narrow"sv, "digital"sv }, "short"sv));