2021-08-24 22:27:05 -04:00
/*
2024-06-18 10:13:30 -04:00
* Copyright ( c ) 2021 - 2024 , Tim Flynn < trflynn89 @ serenityos . org >
2021-08-24 22:27:05 -04:00
*
* SPDX - License - Identifier : BSD - 2 - Clause
*/
# include <LibJS/Runtime/AbstractOperations.h>
2021-09-04 17:08:57 +01:00
# include <LibJS/Runtime/Array.h>
2021-08-24 22:27:05 -04:00
# include <LibJS/Runtime/GlobalObject.h>
2021-08-24 22:58:45 -04:00
# include <LibJS/Runtime/Intl/AbstractOperations.h>
2021-08-24 22:27:05 -04:00
# include <LibJS/Runtime/Intl/DisplayNames.h>
# include <LibJS/Runtime/Intl/DisplayNamesConstructor.h>
2021-08-24 22:58:45 -04:00
# include <LibJS/Runtime/Temporal/AbstractOperations.h>
2024-06-23 09:14:27 -04:00
# include <LibUnicode/Locale.h>
2021-08-24 22:27:05 -04:00
namespace JS : : Intl {
2023-11-19 09:45:05 +01:00
JS_DEFINE_ALLOCATOR ( DisplayNamesConstructor ) ;
2022-03-15 10:40:51 -04:00
// 12.1 The Intl.DisplayNames Constructor, https://tc39.es/ecma402/#sec-intl-displaynames-constructor
2022-08-16 00:20:49 +01:00
DisplayNamesConstructor : : DisplayNamesConstructor ( Realm & realm )
2023-04-13 00:47:15 +02:00
: NativeFunction ( realm . vm ( ) . names . DisplayNames . as_string ( ) , realm . intrinsics ( ) . function_prototype ( ) )
2021-08-24 22:27:05 -04:00
{
}
2023-08-07 08:41:28 +02:00
void DisplayNamesConstructor : : initialize ( Realm & realm )
2021-08-24 22:27:05 -04:00
{
2023-08-07 08:41:28 +02:00
Base : : initialize ( realm ) ;
2021-08-24 22:27:05 -04:00
auto & vm = this - > vm ( ) ;
2022-03-15 10:40:51 -04:00
// 12.2.1 Intl.DisplayNames.prototype, https://tc39.es/ecma402/#sec-Intl.DisplayNames.prototype
2022-08-27 00:54:55 +01:00
define_direct_property ( vm . names . prototype , realm . intrinsics ( ) . intl_display_names_prototype ( ) , 0 ) ;
2021-09-04 17:08:57 +01:00
u8 attr = Attribute : : Writable | Attribute : : Configurable ;
2022-08-22 21:47:35 +01:00
define_native_function ( realm , vm . names . supportedLocalesOf , supported_locales_of , 1 , attr ) ;
2021-09-04 17:08:57 +01:00
2021-08-24 22:27:05 -04:00
define_direct_property ( vm . names . length , Value ( 2 ) , Attribute : : Configurable ) ;
}
2022-03-15 10:40:51 -04:00
// 12.1.1 Intl.DisplayNames ( locales, options ), https://tc39.es/ecma402/#sec-Intl.DisplayNames
2021-10-20 21:16:30 +01:00
ThrowCompletionOr < Value > DisplayNamesConstructor : : call ( )
2021-08-24 22:27:05 -04:00
{
// 1. If NewTarget is undefined, throw a TypeError exception.
2022-08-16 20:33:17 +01:00
return vm ( ) . throw_completion < TypeError > ( ErrorType : : ConstructorWithoutNew , " Intl.DisplayNames " ) ;
2021-08-24 22:27:05 -04:00
}
2022-03-15 10:40:51 -04:00
// 12.1.1 Intl.DisplayNames ( locales, options ), https://tc39.es/ecma402/#sec-Intl.DisplayNames
2022-12-14 19:18:10 +00:00
ThrowCompletionOr < NonnullGCPtr < Object > > DisplayNamesConstructor : : construct ( FunctionObject & new_target )
2021-08-24 22:27:05 -04:00
{
auto & vm = this - > vm ( ) ;
2021-09-11 08:24:17 -04:00
auto locale_value = vm . argument ( 0 ) ;
auto options_value = vm . argument ( 1 ) ;
2021-08-24 22:58:45 -04:00
2024-08-15 15:55:33 -04:00
// 2. Let displayNames be ? OrdinaryCreateFromConstructor(NewTarget, "%Intl.DisplayNames.prototype%", « [[InitializedDisplayNames]], [[Locale]], [[Style]], [[Type]], [[Fallback]], [[LanguageDisplay]], [[Fields]] »).
2022-12-14 18:34:32 +00:00
auto display_names = TRY ( ordinary_create_from_constructor < DisplayNames > ( vm , new_target , & Intrinsics : : intl_display_names_prototype ) ) ;
2021-08-24 22:27:05 -04:00
2021-08-24 22:58:45 -04:00
// 3. Let requestedLocales be ? CanonicalizeLocaleList(locales).
2022-08-20 08:25:24 +01:00
auto requested_locales = TRY ( canonicalize_locale_list ( vm , locale_value ) ) ;
2021-08-24 22:58:45 -04:00
// 4. If options is undefined, throw a TypeError exception.
2021-10-20 21:16:30 +01:00
if ( options_value . is_undefined ( ) )
2022-08-16 20:33:17 +01:00
return vm . throw_completion < TypeError > ( ErrorType : : IsUndefined , " options " sv ) ;
2021-08-24 22:58:45 -04:00
// 5. Set options to ? GetOptionsObject(options).
2022-08-20 08:52:42 +01:00
auto * options = TRY ( Temporal : : get_options_object ( vm , options_value ) ) ;
2021-08-24 22:58:45 -04:00
// 6. Let opt be a new Record.
LocaleOptions opt { } ;
2024-08-15 15:55:33 -04:00
// 7. Let matcher be ? GetOption(options, "localeMatcher", string, « "lookup", "best fit" », "best fit").
2022-08-20 08:52:42 +01:00
auto matcher = TRY ( get_option ( vm , * options , vm . names . localeMatcher , OptionType : : String , { " lookup " sv , " best fit " sv } , " best fit " sv ) ) ;
2021-08-24 22:58:45 -04:00
2024-08-15 15:55:33 -04:00
// 8. Set opt.[[localeMatcher]] to matcher.
2021-08-24 22:58:45 -04:00
opt . locale_matcher = matcher ;
2024-08-15 15:55:33 -04:00
// 9. Let r be ResolveLocale(%Intl.DisplayNames%.[[AvailableLocales]], requestedLocales, opt, %Intl.DisplayNames%.[[RelevantExtensionKeys]], %Intl.DisplayNames%.[[LocaleData]]).
2023-08-30 11:08:15 -04:00
auto result = resolve_locale ( requested_locales , opt , { } ) ;
2021-08-24 22:58:45 -04:00
2024-08-15 15:55:33 -04:00
// 10. Let style be ? GetOption(options, "style", string, « "narrow", "short", "long" », "long").
2022-08-20 08:52:42 +01:00
auto style = TRY ( get_option ( vm , * options , vm . names . style , OptionType : : String , { " narrow " sv , " short " sv , " long " sv } , " long " sv ) ) ;
2021-08-24 22:58:45 -04:00
2024-08-15 15:55:33 -04:00
// 11. Set displayNames.[[Style]] to style.
2023-08-08 19:17:55 +02:00
display_names - > set_style ( style . as_string ( ) . utf8_string_view ( ) ) ;
2021-08-24 22:58:45 -04:00
2024-08-15 15:55:33 -04:00
// 12. Let type be ? GetOption(options, "type", string, « "language", "region", "script", "currency", "calendar", "dateTimeField" », undefined).
2022-08-20 08:52:42 +01:00
auto type = TRY ( get_option ( vm , * options , vm . names . type , OptionType : : String , { " language " sv , " region " sv , " script " sv , " currency " sv , " calendar " sv , " dateTimeField " sv } , Empty { } ) ) ;
2021-08-24 22:58:45 -04:00
2024-08-15 15:55:33 -04:00
// 13. If type is undefined, throw a TypeError exception.
2021-10-20 21:16:30 +01:00
if ( type . is_undefined ( ) )
2022-08-16 20:33:17 +01:00
return vm . throw_completion < TypeError > ( ErrorType : : IsUndefined , " options.type " sv ) ;
2021-08-24 22:58:45 -04:00
2024-08-15 15:55:33 -04:00
// 14. Set displayNames.[[Type]] to type.
2023-08-08 19:17:55 +02:00
display_names - > set_type ( type . as_string ( ) . utf8_string_view ( ) ) ;
2021-08-24 22:58:45 -04:00
2024-08-15 15:55:33 -04:00
// 15. Let fallback be ? GetOption(options, "fallback", string, « "code", "none" », "code").
2022-08-20 08:52:42 +01:00
auto fallback = TRY ( get_option ( vm , * options , vm . names . fallback , OptionType : : String , { " code " sv , " none " sv } , " code " sv ) ) ;
2021-08-24 22:58:45 -04:00
2024-08-15 15:55:33 -04:00
// 16. Set displayNames.[[Fallback]] to fallback.
2023-08-08 19:17:55 +02:00
display_names - > set_fallback ( fallback . as_string ( ) . utf8_string_view ( ) ) ;
2021-08-24 22:58:45 -04:00
2024-08-15 15:55:33 -04:00
// 17. Set displayNames.[[Locale]] to r.[[Locale]].
2021-08-24 22:58:45 -04:00
display_names - > set_locale ( move ( result . locale ) ) ;
2024-08-15 15:55:33 -04:00
// 18. Let resolvedLocaleData be r.[[LocaleData]].
// 19. Let types be resolvedLocaleData.[[types]].
// 20. Assert: types is a Record (see 12.2.3).
2022-01-12 13:52:51 -05:00
2024-08-15 15:55:33 -04:00
// 21. Let languageDisplay be ? GetOption(options, "languageDisplay", string, « "dialect", "standard" », "dialect").
2022-08-20 08:52:42 +01:00
auto language_display = TRY ( get_option ( vm , * options , vm . names . languageDisplay , OptionType : : String , { " dialect " sv , " standard " sv } , " dialect " sv ) ) ;
2022-01-12 13:52:51 -05:00
2024-08-15 15:55:33 -04:00
// 22. Let typeFields be types.[[<type>]].
// 23. Assert: typeFields is a Record (see 12.2.3).
2022-01-12 13:52:51 -05:00
2024-08-15 15:55:33 -04:00
// 24. If type is "language", then
2022-01-12 13:52:51 -05:00
if ( display_names - > type ( ) = = DisplayNames : : Type : : Language ) {
// a. Set displayNames.[[LanguageDisplay]] to languageDisplay.
2023-08-08 19:17:55 +02:00
display_names - > set_language_display ( language_display . as_string ( ) . utf8_string_view ( ) ) ;
2022-01-12 13:52:51 -05:00
2024-08-15 15:55:33 -04:00
// b. Set typeFields to typeFields.[[<languageDisplay>]].
// c. Assert: typeFields is a Record (see 12.2.3).
2022-01-12 13:52:51 -05:00
}
2024-08-15 15:55:33 -04:00
// 25. Let styleFields be typeFields.[[<style>]].
// 26. Assert: styleFields is a Record (see 12.2.3).
// 27. Set displayNames.[[Fields]] to styleFields.
2022-01-12 13:52:51 -05:00
2024-08-15 15:55:33 -04:00
// 28. Return displayNames.
2022-12-14 19:18:10 +00:00
return display_names ;
2021-08-24 22:27:05 -04:00
}
2022-03-15 10:40:51 -04:00
// 12.2.2 Intl.DisplayNames.supportedLocalesOf ( locales [ , options ] ), https://tc39.es/ecma402/#sec-Intl.DisplayNames.supportedLocalesOf
2021-10-22 22:48:25 +01:00
JS_DEFINE_NATIVE_FUNCTION ( DisplayNamesConstructor : : supported_locales_of )
2021-09-04 17:08:57 +01:00
{
auto locales = vm . argument ( 0 ) ;
auto options = vm . argument ( 1 ) ;
// 1. Let availableLocales be %DisplayNames%.[[AvailableLocales]].
2024-06-23 09:14:27 -04:00
// No-op, availability of each requested locale is checked via Unicode::is_locale_available()
2021-09-04 17:08:57 +01:00
// 2. Let requestedLocales be ? CanonicalizeLocaleList(locales).
2022-08-20 08:25:24 +01:00
auto requested_locales = TRY ( canonicalize_locale_list ( vm , locales ) ) ;
2021-09-04 17:08:57 +01:00
2024-06-18 10:13:30 -04:00
// 3. Return ? FilterLocales(availableLocales, requestedLocales, options).
return TRY ( filter_locales ( vm , requested_locales , options ) ) ;
2021-09-04 17:08:57 +01:00
}
2021-08-24 22:27:05 -04:00
}