2021-09-02 08:32:43 -04:00
/*
2023-01-12 10:22:37 -05:00
* Copyright ( c ) 2021 - 2023 , Tim Flynn < trflynn89 @ serenityos . org >
2021-09-02 08:32:43 -04:00
*
* SPDX - License - Identifier : BSD - 2 - Clause
*/
2021-09-01 22:08:15 -04:00
# include <AK/Optional.h>
2023-01-19 10:53:20 -05:00
# include <AK/String.h>
2022-11-23 13:41:50 +01:00
# include <AK/TypeCasts.h>
2021-09-02 08:32:43 -04:00
# include <LibJS/Runtime/AbstractOperations.h>
# include <LibJS/Runtime/GlobalObject.h>
2021-09-01 22:08:15 -04:00
# include <LibJS/Runtime/Intl/AbstractOperations.h>
2021-09-02 08:32:43 -04:00
# include <LibJS/Runtime/Intl/Locale.h>
# include <LibJS/Runtime/Intl/LocaleConstructor.h>
2022-09-02 12:11:30 -04:00
# include <LibLocale/Locale.h>
2021-09-02 08:32:43 -04:00
namespace JS : : Intl {
2021-09-01 22:08:15 -04:00
struct LocaleAndKeys {
2023-01-19 10:53:20 -05:00
String locale ;
Optional < String > ca ;
Optional < String > co ;
Optional < String > hc ;
Optional < String > kf ;
Optional < String > kn ;
Optional < String > nu ;
2021-09-01 22:08:15 -04:00
} ;
// Note: This is not an AO in the spec. This just serves to abstract very similar steps in ApplyOptionsToTag and the Intl.Locale constructor.
2023-02-05 19:02:54 +00:00
static ThrowCompletionOr < Optional < String > > get_string_option ( VM & vm , Object const & options , PropertyKey const & property , Function < bool ( StringView ) > validator , ReadonlySpan < StringView > values = { } )
2021-09-01 22:08:15 -04:00
{
2022-08-20 08:52:42 +01:00
auto option = TRY ( get_option ( vm , options , property , OptionType : : String , values , Empty { } ) ) ;
2021-09-01 22:08:15 -04:00
if ( option . is_undefined ( ) )
2023-01-19 17:11:00 -05:00
return OptionalNone { } ;
2021-09-01 22:08:15 -04:00
2023-01-15 10:31:39 -05:00
if ( validator & & ! validator ( TRY ( option . as_string ( ) . utf8_string_view ( ) ) ) )
2022-08-16 20:33:17 +01:00
return vm . throw_completion < RangeError > ( ErrorType : : OptionIsNotValidValue , option , property ) ;
2021-09-01 22:08:15 -04:00
2023-01-19 10:53:20 -05:00
return TRY ( option . as_string ( ) . utf8_string ( ) ) ;
2021-09-01 22:08:15 -04:00
}
2022-03-15 10:43:33 -04:00
// 14.1.2 ApplyOptionsToTag ( tag, options ), https://tc39.es/ecma402/#sec-apply-options-to-tag
2023-01-19 13:13:57 -05:00
static ThrowCompletionOr < String > apply_options_to_tag ( VM & vm , StringView tag , Object const & options )
2021-09-01 22:08:15 -04:00
{
// 1. Assert: Type(tag) is String.
// 2. Assert: Type(options) is Object.
2022-03-28 08:30:48 -04:00
// 3. If ! IsStructurallyValidLanguageTag(tag) is false, throw a RangeError exception.
2023-01-20 14:26:48 -05:00
auto locale_id = MUST_OR_THROW_OOM ( is_structurally_valid_language_tag ( vm , tag ) ) ;
2021-10-22 01:23:16 +03:00
if ( ! locale_id . has_value ( ) )
2022-08-16 20:33:17 +01:00
return vm . throw_completion < RangeError > ( ErrorType : : IntlInvalidLanguageTag , tag ) ;
2021-09-01 22:08:15 -04:00
2023-01-12 10:22:37 -05:00
// 4. Let language be ? GetOption(options, "language", string, empty, undefined).
2021-09-01 22:08:15 -04:00
// 5. If language is not undefined, then
// a. If language does not match the unicode_language_subtag production, throw a RangeError exception.
2022-09-02 12:01:10 -04:00
auto language = TRY ( get_string_option ( vm , options , vm . names . language , : : Locale : : is_unicode_language_subtag ) ) ;
2021-09-01 22:08:15 -04:00
2023-01-12 10:22:37 -05:00
// 6. Let script be ? GetOption(options, "script", string, empty, undefined).
2021-09-01 22:08:15 -04:00
// 7. If script is not undefined, then
// a. If script does not match the unicode_script_subtag production, throw a RangeError exception.
2022-09-02 12:01:10 -04:00
auto script = TRY ( get_string_option ( vm , options , vm . names . script , : : Locale : : is_unicode_script_subtag ) ) ;
2021-09-01 22:08:15 -04:00
2023-01-12 10:22:37 -05:00
// 8. Let region be ? GetOption(options, "region", string, empty, undefined).
2021-09-01 22:08:15 -04:00
// 9. If region is not undefined, then
// a. If region does not match the unicode_region_subtag production, throw a RangeError exception.
2022-09-02 12:01:10 -04:00
auto region = TRY ( get_string_option ( vm , options , vm . names . region , : : Locale : : is_unicode_region_subtag ) ) ;
2021-09-01 22:08:15 -04:00
2022-03-28 08:30:48 -04:00
// 10. Set tag to ! CanonicalizeUnicodeLocaleId(tag).
2023-01-20 14:26:48 -05:00
auto canonicalized_tag = MUST_OR_THROW_OOM ( canonicalize_unicode_locale_id ( vm , * locale_id ) ) ;
2021-09-01 22:08:15 -04:00
// 11. Assert: tag matches the unicode_locale_id production.
2023-01-19 10:53:20 -05:00
locale_id = TRY_OR_THROW_OOM ( vm , : : Locale : : parse_unicode_locale_id ( canonicalized_tag ) ) ;
2021-09-01 22:08:15 -04:00
VERIFY ( locale_id . has_value ( ) ) ;
// 12. Let languageId be the substring of tag corresponding to the unicode_language_id production.
auto & language_id = locale_id - > language_id ;
// 13. If language is not undefined, then
if ( language . has_value ( ) ) {
// a. Set languageId to languageId with the substring corresponding to the unicode_language_subtag production replaced by the string language.
language_id . language = language . release_value ( ) ;
}
// 14. If script is not undefined, then
if ( script . has_value ( ) ) {
// a. If languageId does not contain a unicode_script_subtag production, then
// i. Set languageId to the string-concatenation of the unicode_language_subtag production of languageId, "-", script, and the rest of languageId.
// b. Else,
// i. Set languageId to languageId with the substring corresponding to the unicode_script_subtag production replaced by the string script.
language_id . script = script . release_value ( ) ;
}
// 15. If region is not undefined, then
if ( region . has_value ( ) ) {
// a. If languageId does not contain a unicode_region_subtag production, then
// i. Set languageId to the string-concatenation of the unicode_language_subtag production of languageId, the substring corresponding to "-"` and the `unicode_script_subtag` production if present, `"-", region, and the rest of languageId.
// b. Else,
// i. Set languageId to languageId with the substring corresponding to the unicode_region_subtag production replaced by the string region.
language_id . region = region . release_value ( ) ;
}
// 16. Set tag to tag with the substring corresponding to the unicode_language_id production replaced by the string languageId.
2022-03-28 08:30:48 -04:00
// 17. Return ! CanonicalizeUnicodeLocaleId(tag).
2023-01-20 14:26:48 -05:00
return MUST_OR_THROW_OOM ( canonicalize_unicode_locale_id ( vm , * locale_id ) ) ;
2021-09-01 22:08:15 -04:00
}
2022-03-15 10:43:33 -04:00
// 14.1.3 ApplyUnicodeExtensionToTag ( tag, options, relevantExtensionKeys ), https://tc39.es/ecma402/#sec-apply-unicode-extension-to-tag
2023-02-05 19:02:54 +00:00
static ThrowCompletionOr < LocaleAndKeys > apply_unicode_extension_to_tag ( VM & vm , StringView tag , LocaleAndKeys options , ReadonlySpan < StringView > relevant_extension_keys )
2021-09-01 22:08:15 -04:00
{
// 1. Assert: Type(tag) is String.
// 2. Assert: tag matches the unicode_locale_id production.
2023-01-21 22:27:42 -05:00
auto locale_id = TRY_OR_THROW_OOM ( vm , : : Locale : : parse_unicode_locale_id ( tag ) ) ;
2021-09-01 22:08:15 -04:00
VERIFY ( locale_id . has_value ( ) ) ;
2023-01-19 10:53:20 -05:00
Vector < String > attributes ;
2022-09-02 12:01:10 -04:00
Vector < : : Locale : : Keyword > keywords ;
2021-09-01 22:08:15 -04:00
// 3. If tag contains a substring that is a Unicode locale extension sequence, then
for ( auto & extension : locale_id - > extensions ) {
2022-09-02 12:01:10 -04:00
if ( ! extension . has < : : Locale : : LocaleExtension > ( ) )
2021-09-01 22:08:15 -04:00
continue ;
// a. Let extension be the String value consisting of the substring of the Unicode locale extension sequence within tag.
// b. Let components be ! UnicodeExtensionComponents(extension).
2022-09-02 12:01:10 -04:00
auto & components = extension . get < : : Locale : : LocaleExtension > ( ) ;
2021-09-01 22:08:15 -04:00
// c. Let attributes be components.[[Attributes]].
attributes = move ( components . attributes ) ;
// d. Let keywords be components.[[Keywords]].
keywords = move ( components . keywords ) ;
break ;
}
// 4. Else,
// a. Let attributes be a new empty List.
// b. Let keywords be a new empty List.
2023-01-19 10:53:20 -05:00
auto field_from_key = [ ] ( LocaleAndKeys & value , StringView key ) - > Optional < String > & {
2021-09-01 22:08:15 -04:00
if ( key = = " ca " sv )
return value . ca ;
if ( key = = " co " sv )
return value . co ;
if ( key = = " hc " sv )
return value . hc ;
if ( key = = " kf " sv )
return value . kf ;
if ( key = = " kn " sv )
return value . kn ;
if ( key = = " nu " sv )
return value . nu ;
VERIFY_NOT_REACHED ( ) ;
} ;
// 5. Let result be a new Record.
LocaleAndKeys result { } ;
// 6. For each element key of relevantExtensionKeys, do
for ( auto const & key : relevant_extension_keys ) {
// a. Let value be undefined.
2023-01-19 10:53:20 -05:00
Optional < String > value { } ;
2021-09-01 22:08:15 -04:00
2022-09-02 12:01:10 -04:00
: : Locale : : Keyword * entry = nullptr ;
2021-09-01 22:08:15 -04:00
// b. If keywords contains an element whose [[Key]] is the same as key, then
if ( auto it = keywords . find_if ( [ & ] ( auto const & k ) { return key = = k . key ; } ) ; it ! = keywords . end ( ) ) {
// i. Let entry be the element of keywords whose [[Key]] is the same as key.
entry = & ( * it ) ;
// ii. Let value be entry.[[Value]].
2021-09-08 15:25:35 -04:00
value = entry - > value ;
2021-09-01 22:08:15 -04:00
}
// c. Else,
// i. Let entry be empty.
// d. Assert: options has a field [[<key>]].
// e. Let optionsValue be options.[[<key>]].
auto options_value = field_from_key ( options , key ) ;
// f. If optionsValue is not undefined, then
if ( options_value . has_value ( ) ) {
// i. Assert: Type(optionsValue) is String.
// ii. Let value be optionsValue.
value = options_value . release_value ( ) ;
// iii. If entry is not empty, then
if ( entry ! = nullptr ) {
// 1. Set entry.[[Value]] to value.
2021-09-08 15:25:35 -04:00
entry - > value = * value ;
2021-09-01 22:08:15 -04:00
}
// iv. Else,
else {
// 1. Append the Record { [[Key]]: key, [[Value]]: value } to keywords.
2023-02-02 19:46:33 -05:00
TRY_OR_THROW_OOM ( vm , keywords . try_append ( { TRY_OR_THROW_OOM ( vm , String : : from_utf8 ( key ) ) , * value } ) ) ;
2021-09-01 22:08:15 -04:00
}
}
// g. Set result.[[<key>]] to value.
field_from_key ( result , key ) = move ( value ) ;
}
// 7. Let locale be the String value that is tag with any Unicode locale extension sequences removed.
2022-09-02 12:01:10 -04:00
locale_id - > remove_extension_type < : : Locale : : LocaleExtension > ( ) ;
2023-01-19 13:13:57 -05:00
auto locale = TRY_OR_THROW_OOM ( vm , locale_id - > to_string ( ) ) ;
2021-09-01 22:08:15 -04:00
// 8. Let newExtension be a Unicode BCP 47 U Extension based on attributes and keywords.
2022-09-02 12:01:10 -04:00
: : Locale : : LocaleExtension new_extension { move ( attributes ) , move ( keywords ) } ;
2021-09-01 22:08:15 -04:00
// 9. If newExtension is not the empty String, then
if ( ! new_extension . attributes . is_empty ( ) | | ! new_extension . keywords . is_empty ( ) ) {
// a. Let locale be ! InsertUnicodeExtensionAndCanonicalize(locale, newExtension).
2023-01-20 14:26:48 -05:00
locale = MUST_OR_THROW_OOM ( insert_unicode_extension_and_canonicalize ( vm , locale_id . release_value ( ) , move ( new_extension ) ) ) ;
2021-09-01 22:08:15 -04:00
}
// 10. Set result.[[locale]] to locale.
result . locale = move ( locale ) ;
// 11. Return result.
return result ;
}
2021-09-02 08:32:43 -04:00
// 14.1 The Intl.Locale Constructor, https://tc39.es/ecma402/#sec-intl-locale-constructor
2022-08-16 00:20:49 +01:00
LocaleConstructor : : LocaleConstructor ( Realm & realm )
2022-09-14 19:10:27 -04:00
: NativeFunction ( realm . vm ( ) . names . Locale . as_string ( ) , * realm . intrinsics ( ) . function_prototype ( ) )
2021-09-02 08:32:43 -04:00
{
}
2023-01-28 12:33:35 -05:00
ThrowCompletionOr < void > LocaleConstructor : : initialize ( Realm & realm )
2021-09-02 08:32:43 -04:00
{
2023-01-28 12:33:35 -05:00
MUST_OR_THROW_OOM ( NativeFunction : : initialize ( realm ) ) ;
2021-09-02 08:32:43 -04:00
auto & vm = this - > vm ( ) ;
// 14.2.1 Intl.Locale.prototype, https://tc39.es/ecma402/#sec-Intl.Locale.prototype
2022-08-27 00:54:55 +01:00
define_direct_property ( vm . names . prototype , realm . intrinsics ( ) . intl_locale_prototype ( ) , 0 ) ;
2021-09-02 08:32:43 -04:00
define_direct_property ( vm . names . length , Value ( 1 ) , Attribute : : Configurable ) ;
2023-01-28 12:33:35 -05:00
return { } ;
2021-09-02 08:32:43 -04:00
}
2022-03-15 10:43:33 -04:00
// 14.1.1 Intl.Locale ( tag [ , options ] ), https://tc39.es/ecma402/#sec-Intl.Locale
2021-10-20 21:16:30 +01:00
ThrowCompletionOr < Value > LocaleConstructor : : call ( )
2021-09-02 08:32:43 -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.Locale " ) ;
2021-09-02 08:32:43 -04:00
}
2022-03-15 10:43:33 -04:00
// 14.1.1 Intl.Locale ( tag [ , options ] ), https://tc39.es/ecma402/#sec-Intl.Locale
2022-12-14 19:18:10 +00:00
ThrowCompletionOr < NonnullGCPtr < Object > > LocaleConstructor : : construct ( FunctionObject & new_target )
2021-09-02 08:32:43 -04:00
{
auto & vm = this - > vm ( ) ;
2021-09-11 08:24:17 -04:00
auto tag_value = vm . argument ( 0 ) ;
auto options_value = vm . argument ( 1 ) ;
2021-09-01 22:08:15 -04:00
// 2. Let relevantExtensionKeys be %Locale%.[[RelevantExtensionKeys]].
2021-11-29 19:11:49 -05:00
auto relevant_extension_keys = Locale : : relevant_extension_keys ( ) ;
2021-09-01 22:08:15 -04:00
// 3. Let internalSlotsList be « [[InitializedLocale]], [[Locale]], [[Calendar]], [[Collation]], [[HourCycle]], [[NumberingSystem]] ».
// 4. If relevantExtensionKeys contains "kf", then
// a. Append [[CaseFirst]] as the last element of internalSlotsList.
// 5. If relevantExtensionKeys contains "kn", then
// a. Append [[Numeric]] as the last element of internalSlotsList.
2021-09-02 08:32:43 -04:00
// 6. Let locale be ? OrdinaryCreateFromConstructor(NewTarget, "%Locale.prototype%", internalSlotsList).
2022-12-14 18:34:32 +00:00
auto locale = TRY ( ordinary_create_from_constructor < Locale > ( vm , new_target , & Intrinsics : : intl_locale_prototype ) ) ;
2021-09-02 08:32:43 -04:00
2023-01-19 13:13:57 -05:00
String tag ;
2021-09-11 08:31:26 -04:00
2021-09-01 22:08:15 -04:00
// 7. If Type(tag) is not String or Object, throw a TypeError exception.
2021-10-20 21:16:30 +01:00
if ( ! tag_value . is_string ( ) & & ! tag_value . is_object ( ) )
2022-08-16 20:33:17 +01:00
return vm . throw_completion < TypeError > ( ErrorType : : NotAnObjectOrString , " tag " sv ) ;
2021-09-01 22:08:15 -04:00
// 8. If Type(tag) is Object and tag has an [[InitializedLocale]] internal slot, then
2021-09-11 08:24:17 -04:00
if ( tag_value . is_object ( ) & & is < Locale > ( tag_value . as_object ( ) ) ) {
2021-09-01 22:08:15 -04:00
// a. Let tag be tag.[[Locale]].
2021-09-11 08:24:17 -04:00
auto const & tag_object = static_cast < Locale const & > ( tag_value . as_object ( ) ) ;
2021-09-11 08:31:26 -04:00
tag = tag_object . locale ( ) ;
2021-09-01 22:08:15 -04:00
}
// 9. Else,
else {
// a. Let tag be ? ToString(tag).
2023-01-19 13:13:57 -05:00
tag = TRY ( tag_value . to_string ( vm ) ) ;
2021-09-01 22:08:15 -04:00
}
// 10. Set options to ? CoerceOptionsToObject(options).
2022-08-20 08:25:24 +01:00
auto * options = TRY ( coerce_options_to_object ( vm , options_value ) ) ;
2021-09-01 22:08:15 -04:00
// 11. Set tag to ? ApplyOptionsToTag(tag, options).
2022-08-20 08:25:24 +01:00
tag = TRY ( apply_options_to_tag ( vm , tag , * options ) ) ;
2021-09-01 22:08:15 -04:00
// 12. Let opt be a new Record.
LocaleAndKeys opt { } ;
2023-01-12 10:22:37 -05:00
// 13. Let calendar be ? GetOption(options, "calendar", string, empty, undefined).
2021-09-01 22:08:15 -04:00
// 14. If calendar is not undefined, then
// a. If calendar does not match the Unicode Locale Identifier type nonterminal, throw a RangeError exception.
// 15. Set opt.[[ca]] to calendar.
2022-09-02 12:01:10 -04:00
opt . ca = TRY ( get_string_option ( vm , * options , vm . names . calendar , : : Locale : : is_type_identifier ) ) ;
2021-09-01 22:08:15 -04:00
2023-01-12 10:22:37 -05:00
// 16. Let collation be ? GetOption(options, "collation", string, empty, undefined).
2021-09-01 22:08:15 -04:00
// 17. If collation is not undefined, then
// a. If collation does not match the Unicode Locale Identifier type nonterminal, throw a RangeError exception.
// 18. Set opt.[[co]] to collation.
2022-09-02 12:01:10 -04:00
opt . co = TRY ( get_string_option ( vm , * options , vm . names . collation , : : Locale : : is_type_identifier ) ) ;
2021-09-01 22:08:15 -04:00
2023-01-12 10:22:37 -05:00
// 19. Let hc be ? GetOption(options, "hourCycle", string, « "h11", "h12", "h23", "h24" », undefined).
2021-09-01 22:08:15 -04:00
// 20. Set opt.[[hc]] to hc.
2022-08-20 08:25:24 +01:00
opt . hc = TRY ( get_string_option ( vm , * options , vm . names . hourCycle , nullptr , AK : : Array { " h11 " sv , " h12 " sv , " h23 " sv , " h24 " sv } ) ) ;
2021-09-01 22:08:15 -04:00
2023-01-12 10:22:37 -05:00
// 21. Let kf be ? GetOption(options, "caseFirst", string, « "upper", "lower", "false" », undefined).
2021-09-01 22:08:15 -04:00
// 22. Set opt.[[kf]] to kf.
2022-08-20 08:25:24 +01:00
opt . kf = TRY ( get_string_option ( vm , * options , vm . names . caseFirst , nullptr , AK : : Array { " upper " sv , " lower " sv , " false " sv } ) ) ;
2021-09-01 22:08:15 -04:00
2023-01-12 10:22:37 -05:00
// 23. Let kn be ? GetOption(options, "numeric", boolean, empty, undefined).
2022-08-20 08:52:42 +01:00
auto kn = TRY ( get_option ( vm , * options , vm . names . numeric , OptionType : : Boolean , { } , Empty { } ) ) ;
2021-09-01 22:08:15 -04:00
// 24. If kn is not undefined, set kn to ! ToString(kn).
// 25. Set opt.[[kn]] to kn.
if ( ! kn . is_undefined ( ) )
2023-01-19 10:53:20 -05:00
opt . kn = TRY ( kn . to_string ( vm ) ) ;
2021-09-01 22:08:15 -04:00
2023-01-12 10:22:37 -05:00
// 26. Let numberingSystem be ? GetOption(options, "numberingSystem", string, empty, undefined).
2021-09-01 22:08:15 -04:00
// 27. If numberingSystem is not undefined, then
// a. If numberingSystem does not match the Unicode Locale Identifier type nonterminal, throw a RangeError exception.
// 28. Set opt.[[nu]] to numberingSystem.
2022-09-02 12:01:10 -04:00
opt . nu = TRY ( get_string_option ( vm , * options , vm . names . numberingSystem , : : Locale : : is_type_identifier ) ) ;
2021-09-01 22:08:15 -04:00
// 29. Let r be ! ApplyUnicodeExtensionToTag(tag, opt, relevantExtensionKeys).
2023-01-20 14:26:48 -05:00
auto result = MUST_OR_THROW_OOM ( apply_unicode_extension_to_tag ( vm , tag , move ( opt ) , relevant_extension_keys ) ) ;
2021-09-01 22:08:15 -04:00
// 30. Set locale.[[Locale]] to r.[[locale]].
2023-01-19 13:13:57 -05:00
locale - > set_locale ( move ( result . locale ) ) ;
2021-09-01 22:08:15 -04:00
// 31. Set locale.[[Calendar]] to r.[[ca]].
if ( result . ca . has_value ( ) )
2023-01-19 13:13:57 -05:00
locale - > set_calendar ( result . ca . release_value ( ) ) ;
2021-09-01 22:08:15 -04:00
// 32. Set locale.[[Collation]] to r.[[co]].
if ( result . co . has_value ( ) )
2023-01-19 13:13:57 -05:00
locale - > set_collation ( result . co . release_value ( ) ) ;
2021-09-01 22:08:15 -04:00
// 33. Set locale.[[HourCycle]] to r.[[hc]].
if ( result . hc . has_value ( ) )
2023-01-19 13:13:57 -05:00
locale - > set_hour_cycle ( result . hc . release_value ( ) ) ;
2021-09-01 22:08:15 -04:00
// 34. If relevantExtensionKeys contains "kf", then
2021-11-29 19:11:49 -05:00
if ( relevant_extension_keys . span ( ) . contains_slow ( " kf " sv ) ) {
2021-09-01 22:08:15 -04:00
// a. Set locale.[[CaseFirst]] to r.[[kf]].
if ( result . kf . has_value ( ) )
2023-01-19 13:13:57 -05:00
locale - > set_case_first ( result . kf . release_value ( ) ) ;
2021-09-01 22:08:15 -04:00
}
// 35. If relevantExtensionKeys contains "kn", then
2021-11-29 19:11:49 -05:00
if ( relevant_extension_keys . span ( ) . contains_slow ( " kn " sv ) ) {
2022-05-02 20:54:39 +02:00
// a. If SameValue(r.[[kn]], "true") is true or r.[[kn]] is the empty String, then
2023-01-19 13:13:57 -05:00
if ( result . kn . has_value ( ) & & ( result . kn = = " true " sv | | result . kn - > is_empty ( ) ) ) {
2021-09-01 22:08:15 -04:00
// i. Set locale.[[Numeric]] to true.
locale - > set_numeric ( true ) ;
}
// b. Else,
else {
// i. Set locale.[[Numeric]] to false.
locale - > set_numeric ( false ) ;
}
}
// 36. Set locale.[[NumberingSystem]] to r.[[nu]].
if ( result . nu . has_value ( ) )
2023-01-19 13:13:57 -05:00
locale - > set_numbering_system ( result . nu . release_value ( ) ) ;
2021-09-01 22:08:15 -04:00
// 37. Return locale.
2022-12-14 19:18:10 +00:00
return locale ;
2021-09-02 08:32:43 -04:00
}
}