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,11 +77,11 @@ ThrowCompletionOr<NonnullGCPtr<Object>> RelativeTimeFormatConstructor::construct
// a. If numberingSystem cannot be matched by the type Unicode locale nonterminal, throw a RangeError exception.
if (!::Locale::is_type_identifier(numbering_system.as_string().utf8_string_view()))
return vm.throw_completion<RangeError>(ErrorType::OptionIsNotValidValue, numbering_system, "numberingSystem"sv);
// 10. Set opt.[[nu]] to numberingSystem.
opt.nu = numbering_system.as_string().utf8_string();
}
// 10. Set opt.[[nu]] to numberingSystem.
opt.nu = locale_key_from_value(numbering_system);
// 11. Let r be ResolveLocale(%Intl.RelativeTimeFormat%.[[AvailableLocales]], requestedLocales, opt, %Intl.RelativeTimeFormat%.[[RelevantExtensionKeys]], %Intl.RelativeTimeFormat%.[[LocaleData]]).
auto result = resolve_locale(requested_locales, opt, RelativeTimeFormat::relevant_extension_keys());
@ -95,8 +95,8 @@ ThrowCompletionOr<NonnullGCPtr<Object>> RelativeTimeFormatConstructor::construct
relative_time_format->set_data_locale(move(result.data_locale));
// 15. Set relativeTimeFormat.[[NumberingSystem]] to r.[[nu]].
if (result.nu.has_value())
relative_time_format->set_numbering_system(result.nu.release_value());
if (auto* resolved_numbering_system = result.nu.get_pointer<String>())
relative_time_format->set_numbering_system(move(*resolved_numbering_system));
// 16. Let style be ? GetOption(options, "style", string, « "long", "short", "narrow" », "long").
auto style = TRY(get_option(vm, *options, vm.names.style, OptionType::String, { "long"sv, "short"sv, "narrow"sv }, "long"sv));