mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-08-07 16:49:54 +00:00
LibJS: Migrate Intl.Collator to use ResolveOptions
This is an editorial change in the ECMA-402 spec. See:
f822dc1
This commit is contained in:
parent
e40881ebb8
commit
636e214326
Notes:
github-actions[bot]
2025-04-08 10:53:03 +00:00
Author: https://github.com/trflynn89
Commit: 636e214326
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/4275
1 changed files with 30 additions and 64 deletions
|
@ -47,6 +47,7 @@ ThrowCompletionOr<Value> CollatorConstructor::call()
|
||||||
ThrowCompletionOr<GC::Ref<Object>> CollatorConstructor::construct(FunctionObject& new_target)
|
ThrowCompletionOr<GC::Ref<Object>> CollatorConstructor::construct(FunctionObject& new_target)
|
||||||
{
|
{
|
||||||
auto& vm = this->vm();
|
auto& vm = this->vm();
|
||||||
|
auto& realm = *vm.current_realm();
|
||||||
|
|
||||||
auto locales_value = vm.argument(0);
|
auto locales_value = vm.argument(0);
|
||||||
auto options_value = vm.argument(1);
|
auto options_value = vm.argument(1);
|
||||||
|
@ -55,105 +56,70 @@ ThrowCompletionOr<GC::Ref<Object>> CollatorConstructor::construct(FunctionObject
|
||||||
// 3. Let collator be ? OrdinaryCreateFromConstructor(newTarget, "%Intl.Collator.prototype%", internalSlotsList).
|
// 3. Let collator be ? OrdinaryCreateFromConstructor(newTarget, "%Intl.Collator.prototype%", internalSlotsList).
|
||||||
auto collator = TRY(ordinary_create_from_constructor<Collator>(vm, new_target, &Intrinsics::intl_collator_prototype));
|
auto collator = TRY(ordinary_create_from_constructor<Collator>(vm, new_target, &Intrinsics::intl_collator_prototype));
|
||||||
|
|
||||||
// 4. Let requestedLocales be ? CanonicalizeLocaleList(locales).
|
// 4. NOTE: The source of locale data for ResolveOptions depends upon the "usage" property of options, but the following
|
||||||
|
// two steps must observably precede that lookup (and must not observably repeat inside ResolveOptions).
|
||||||
|
|
||||||
|
// 5. Let requestedLocales be ? CanonicalizeLocaleList(locales).
|
||||||
auto requested_locales = TRY(canonicalize_locale_list(vm, locales_value));
|
auto requested_locales = TRY(canonicalize_locale_list(vm, locales_value));
|
||||||
|
|
||||||
// 5. Set options to ? CoerceOptionsToObject(options).
|
// 6. Set options to ? CoerceOptionsToObject(options).
|
||||||
auto* options = TRY(coerce_options_to_object(vm, options_value));
|
auto* options = TRY(coerce_options_to_object(vm, options_value));
|
||||||
|
|
||||||
// 6. Let usage be ? GetOption(options, "usage", string, « "sort", "search" », "sort").
|
// 7. Let usage be ? GetOption(options, "usage", string, « "sort", "search" », "sort").
|
||||||
auto usage = TRY(get_option(vm, *options, vm.names.usage, OptionType::String, { "sort"sv, "search"sv }, "sort"sv));
|
auto usage = TRY(get_option(vm, *options, vm.names.usage, OptionType::String, { "sort"sv, "search"sv }, "sort"sv));
|
||||||
|
|
||||||
// 7. Set collator.[[Usage]] to usage.
|
// 8. Set collator.[[Usage]] to usage.
|
||||||
collator->set_usage(usage.as_string().utf8_string_view());
|
collator->set_usage(usage.as_string().utf8_string_view());
|
||||||
|
|
||||||
// 8. If usage is "sort", then
|
// 9. If usage is "sort", then
|
||||||
// a. Let localeData be %Intl.Collator%.[[SortLocaleData]].
|
// a. Let localeData be %Intl.Collator%.[[SortLocaleData]].
|
||||||
// 9. Else,
|
// 10. Else,
|
||||||
// a. Let localeData be %Intl.Collator%.[[SearchLocaleData]].
|
// a. Let localeData be %Intl.Collator%.[[SearchLocaleData]].
|
||||||
|
|
||||||
// 10. Let opt be a new Record.
|
// 11. Let optionsResolution be ? ResolveOptions(%Intl.Collator%, localeData, CreateArrayFromList(requestedLocales), options).
|
||||||
LocaleOptions opt {};
|
auto requested_locales_array = Array::create_from<String>(realm, requested_locales, [&](auto& locale) { return PrimitiveString::create(vm, move(locale)); });
|
||||||
|
auto options_resolution = TRY(resolve_options(vm, collator, requested_locales_array, options_value));
|
||||||
|
|
||||||
// 11. Let matcher be ? GetOption(options, "localeMatcher", string, « "lookup", "best fit" », "best fit").
|
// 12. Let r be optionsResolution.[[ResolvedLocale]].
|
||||||
auto matcher = TRY(get_option(vm, *options, vm.names.localeMatcher, OptionType::String, { "lookup"sv, "best fit"sv }, "best fit"sv));
|
auto result = move(options_resolution.resolved_locale);
|
||||||
|
|
||||||
// 12. Set opt.[[localeMatcher]] to matcher.
|
// 13. Set collator.[[Locale]] to r.[[Locale]].
|
||||||
opt.locale_matcher = matcher;
|
|
||||||
|
|
||||||
// 13. Let collation be ? GetOption(options, "collation", string, empty, undefined).
|
|
||||||
auto collation = TRY(get_option(vm, *options, vm.names.collation, OptionType::String, {}, Empty {}));
|
|
||||||
|
|
||||||
// 14. If collation is not undefined, then
|
|
||||||
if (!collation.is_undefined()) {
|
|
||||||
// a. If collation cannot be matched by the type Unicode locale nonterminal, throw a RangeError exception.
|
|
||||||
if (!Unicode::is_type_identifier(collation.as_string().utf8_string_view()))
|
|
||||||
return vm.throw_completion<RangeError>(ErrorType::OptionIsNotValidValue, collation, "collation"sv);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 15. Set opt.[[co]] to collation.
|
|
||||||
opt.co = locale_key_from_value(collation);
|
|
||||||
|
|
||||||
// 16. Let numeric be ? GetOption(options, "numeric", boolean, empty, undefined).
|
|
||||||
auto numeric = TRY(get_option(vm, *options, vm.names.numeric, OptionType::Boolean, {}, Empty {}));
|
|
||||||
|
|
||||||
// 17. If numeric is not undefined, then
|
|
||||||
if (!numeric.is_undefined()) {
|
|
||||||
// a. Set numeric to ! ToString(numeric).
|
|
||||||
numeric = PrimitiveString::create(vm, MUST(numeric.to_string(vm)));
|
|
||||||
}
|
|
||||||
|
|
||||||
// 18. Set opt.[[kn]] to numeric.
|
|
||||||
opt.kn = locale_key_from_value(numeric);
|
|
||||||
|
|
||||||
// 19. Let caseFirst be ? GetOption(options, "caseFirst", string, « "upper", "lower", "false" », undefined).
|
|
||||||
auto case_first = TRY(get_option(vm, *options, vm.names.caseFirst, OptionType::String, { "upper"sv, "lower"sv, "false"sv }, Empty {}));
|
|
||||||
|
|
||||||
// 20. Set opt.[[kf]] to caseFirst.
|
|
||||||
opt.kf = locale_key_from_value(case_first);
|
|
||||||
|
|
||||||
// 21. Let r be ResolveLocale(%Intl.Collator%.[[AvailableLocales]], requestedLocales, opt, %Intl.Collator%.[[RelevantExtensionKeys]], localeData).
|
|
||||||
auto result = resolve_locale(requested_locales, opt, collator->relevant_extension_keys());
|
|
||||||
|
|
||||||
// 22. Set collator.[[Locale]] to r.[[Locale]].
|
|
||||||
collator->set_locale(move(result.locale));
|
collator->set_locale(move(result.locale));
|
||||||
|
|
||||||
// 23. Set collation to r.[[co]].
|
// 14. If r.[[co]] is null, let collation be "default". Otherwise, let collation be r.[[co]].
|
||||||
auto collation_value = move(result.co);
|
auto collation = result.co.has<Empty>()
|
||||||
|
? "default"_string
|
||||||
|
: move(result.co.get<String>());
|
||||||
|
|
||||||
// 24. If collation is null, set collation to "default".
|
// 15. Set collator.[[Collation]] to collation.
|
||||||
if (collation_value.has<Empty>())
|
collator->set_collation(move(collation));
|
||||||
collation_value = "default"_string;
|
|
||||||
|
|
||||||
// 25. Set collator.[[Collation]] to collation.
|
// 16. Set collator.[[Numeric]] to SameValue(r.[[kn]], "true").
|
||||||
collator->set_collation(move(collation_value.get<String>()));
|
|
||||||
|
|
||||||
// 26. Set collator.[[Numeric]] to SameValue(r.[[kn]], "true").
|
|
||||||
collator->set_numeric(result.kn == "true"_string);
|
collator->set_numeric(result.kn == "true"_string);
|
||||||
|
|
||||||
// 27. Set collator.[[CaseFirst]] to r.[[kf]].
|
// 17. Set collator.[[CaseFirst]] to r.[[kf]].
|
||||||
if (auto const* resolved_case_first = result.kf.get_pointer<String>())
|
if (auto const* resolved_case_first = result.kf.get_pointer<String>())
|
||||||
collator->set_case_first(*resolved_case_first);
|
collator->set_case_first(*resolved_case_first);
|
||||||
|
|
||||||
// 28. Let resolvedLocaleData be r.[[LocaleData]].
|
// 18. Let resolvedLocaleData be r.[[LocaleData]].
|
||||||
|
|
||||||
// 29. If usage is "sort", let defaultSensitivity be "variant". Otherwise, let defaultSensitivity be resolvedLocaleData.[[sensitivity]].
|
// 19. If usage is "sort", let defaultSensitivity be "variant". Otherwise, let defaultSensitivity be resolvedLocaleData.[[sensitivity]].
|
||||||
// NOTE: We do not acquire resolvedLocaleData.[[sensitivity]] here. Instead, we let LibUnicode fill in the
|
// NOTE: We do not acquire resolvedLocaleData.[[sensitivity]] here. Instead, we let LibUnicode fill in the
|
||||||
// default value if an override was not provided here.
|
// default value if an override was not provided here.
|
||||||
auto default_sensitivity = collator->usage() == Unicode::Usage::Sort ? "variant"sv : OptionDefault {};
|
auto default_sensitivity = collator->usage() == Unicode::Usage::Sort ? "variant"sv : OptionDefault {};
|
||||||
|
|
||||||
// 30. Set collator.[[Sensitivity]] to ? GetOption(options, "sensitivity", string, « "base", "accent", "case", "variant" », defaultSensitivity).
|
// 20. Set collator.[[Sensitivity]] to ? GetOption(options, "sensitivity", string, « "base", "accent", "case", "variant" », defaultSensitivity).
|
||||||
auto sensitivity_value = TRY(get_option(vm, *options, vm.names.sensitivity, OptionType::String, { "base"sv, "accent"sv, "case"sv, "variant"sv }, default_sensitivity));
|
auto sensitivity_value = TRY(get_option(vm, *options, vm.names.sensitivity, OptionType::String, { "base"sv, "accent"sv, "case"sv, "variant"sv }, default_sensitivity));
|
||||||
|
|
||||||
Optional<Unicode::Sensitivity> sensitivity;
|
Optional<Unicode::Sensitivity> sensitivity;
|
||||||
if (!sensitivity_value.is_undefined())
|
if (!sensitivity_value.is_undefined())
|
||||||
sensitivity = Unicode::sensitivity_from_string(sensitivity_value.as_string().utf8_string_view());
|
sensitivity = Unicode::sensitivity_from_string(sensitivity_value.as_string().utf8_string_view());
|
||||||
|
|
||||||
// 31. Let defaultIgnorePunctuation be resolvedLocaleData.[[ignorePunctuation]].
|
// 21. Let defaultIgnorePunctuation be resolvedLocaleData.[[ignorePunctuation]].
|
||||||
// NOTE: We do not acquire resolvedLocaleData.[[ignorePunctuation]] here. Instead, we let LibUnicode fill in the
|
// NOTE: We do not acquire resolvedLocaleData.[[ignorePunctuation]] here. Instead, we let LibUnicode fill in the
|
||||||
// default value if an override was not provided here.
|
// default value if an override was not provided here.
|
||||||
|
|
||||||
// 32. Set collator.[[IgnorePunctuation]] to ? GetOption(options, "ignorePunctuation", boolean, empty, defaultIgnorePunctuation).
|
// 22. Set collator.[[IgnorePunctuation]] to ? GetOption(options, "ignorePunctuation", boolean, empty, defaultIgnorePunctuation).
|
||||||
auto ignore_punctuation_value = TRY(get_option(vm, *options, vm.names.ignorePunctuation, OptionType::Boolean, {}, Empty {}));
|
auto ignore_punctuation_value = TRY(get_option(vm, *options, vm.names.ignorePunctuation, OptionType::Boolean, {}, Empty {}));
|
||||||
|
|
||||||
Optional<bool> ignore_punctuation;
|
Optional<bool> ignore_punctuation;
|
||||||
|
@ -174,7 +140,7 @@ ThrowCompletionOr<GC::Ref<Object>> CollatorConstructor::construct(FunctionObject
|
||||||
collator->set_sensitivity(collator->collator().sensitivity());
|
collator->set_sensitivity(collator->collator().sensitivity());
|
||||||
collator->set_ignore_punctuation(collator->collator().ignore_punctuation());
|
collator->set_ignore_punctuation(collator->collator().ignore_punctuation());
|
||||||
|
|
||||||
// 33. Return collator.
|
// 23. Return collator.
|
||||||
return collator;
|
return collator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue