mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-07-29 20:29:18 +00:00
LibJS: Ensure relevant extension keys are included in ICU locale data
This is a normative change in the ECMA-402 spec. See:
7508197
In our implementation, we don't have the affected AOs directly, as we
delegate to ICU. So instead, we must ensure we provide ICU a locale with
the relevant extension keys present.
This commit is contained in:
parent
37b8ba96f1
commit
00d00b84d3
Notes:
github-actions[bot]
2025-03-18 15:48:22 +00:00
Author: https://github.com/trflynn89
Commit: 00d00b84d3
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/3980
17 changed files with 82 additions and 67 deletions
|
@ -500,6 +500,8 @@ ResolvedLocale resolve_locale(ReadonlySpan<String> requested_locales, LocaleOpti
|
|||
// 12. Let supportedKeywords be a new empty List.
|
||||
Vector<Unicode::Keyword> supported_keywords;
|
||||
|
||||
Vector<Unicode::Keyword> icu_keywords;
|
||||
|
||||
// 13. For each element key of relevantExtensionKeys, do
|
||||
for (auto const& key : relevant_extension_keys) {
|
||||
// a. Let keyLocaleData be foundLocaleData.[[<key>]].
|
||||
|
@ -574,10 +576,23 @@ ResolvedLocale resolve_locale(ReadonlySpan<String> requested_locales, LocaleOpti
|
|||
if (supported_keyword.has_value())
|
||||
supported_keywords.append(supported_keyword.release_value());
|
||||
|
||||
if (auto* value_string = value.get_pointer<String>())
|
||||
icu_keywords.empend(MUST(String::from_utf8(key)), *value_string);
|
||||
|
||||
// m. Set result.[[<key>]] to value.
|
||||
find_key_in_value(result, key) = move(value);
|
||||
}
|
||||
|
||||
// AD-HOC: For ICU, we need to form a locale with all relevant extension keys present.
|
||||
if (icu_keywords.is_empty()) {
|
||||
result.icu_locale = found_locale;
|
||||
} else {
|
||||
auto locale_id = Unicode::parse_unicode_locale_id(found_locale);
|
||||
VERIFY(locale_id.has_value());
|
||||
|
||||
result.icu_locale = insert_unicode_extension_and_canonicalize(locale_id.release_value(), {}, move(icu_keywords));
|
||||
}
|
||||
|
||||
// 14. If supportedKeywords is not empty, then
|
||||
if (!supported_keywords.is_empty()) {
|
||||
auto locale_id = Unicode::parse_unicode_locale_id(found_locale);
|
||||
|
|
|
@ -38,6 +38,7 @@ struct MatchedLocale {
|
|||
|
||||
struct ResolvedLocale {
|
||||
String locale;
|
||||
String icu_locale;
|
||||
LocaleKey ca; // [[Calendar]]
|
||||
LocaleKey co; // [[Collation]]
|
||||
LocaleKey hc; // [[HourCycle]]
|
||||
|
|
|
@ -47,32 +47,32 @@ static Optional<Unicode::DateTimeFormat const&> get_or_create_formatter(StringVi
|
|||
|
||||
Optional<Unicode::DateTimeFormat const&> DateTimeFormat::temporal_plain_date_formatter()
|
||||
{
|
||||
return get_or_create_formatter(m_locale, m_temporal_time_zone, m_temporal_plain_date_formatter, m_temporal_plain_date_format);
|
||||
return get_or_create_formatter(m_icu_locale, m_temporal_time_zone, m_temporal_plain_date_formatter, m_temporal_plain_date_format);
|
||||
}
|
||||
|
||||
Optional<Unicode::DateTimeFormat const&> DateTimeFormat::temporal_plain_year_month_formatter()
|
||||
{
|
||||
return get_or_create_formatter(m_locale, m_temporal_time_zone, m_temporal_plain_year_month_formatter, m_temporal_plain_year_month_format);
|
||||
return get_or_create_formatter(m_icu_locale, m_temporal_time_zone, m_temporal_plain_year_month_formatter, m_temporal_plain_year_month_format);
|
||||
}
|
||||
|
||||
Optional<Unicode::DateTimeFormat const&> DateTimeFormat::temporal_plain_month_day_formatter()
|
||||
{
|
||||
return get_or_create_formatter(m_locale, m_temporal_time_zone, m_temporal_plain_month_day_formatter, m_temporal_plain_month_day_format);
|
||||
return get_or_create_formatter(m_icu_locale, m_temporal_time_zone, m_temporal_plain_month_day_formatter, m_temporal_plain_month_day_format);
|
||||
}
|
||||
|
||||
Optional<Unicode::DateTimeFormat const&> DateTimeFormat::temporal_plain_time_formatter()
|
||||
{
|
||||
return get_or_create_formatter(m_locale, m_temporal_time_zone, m_temporal_plain_time_formatter, m_temporal_plain_time_format);
|
||||
return get_or_create_formatter(m_icu_locale, m_temporal_time_zone, m_temporal_plain_time_formatter, m_temporal_plain_time_format);
|
||||
}
|
||||
|
||||
Optional<Unicode::DateTimeFormat const&> DateTimeFormat::temporal_plain_date_time_formatter()
|
||||
{
|
||||
return get_or_create_formatter(m_locale, m_temporal_time_zone, m_temporal_plain_date_time_formatter, m_temporal_plain_date_time_format);
|
||||
return get_or_create_formatter(m_icu_locale, m_temporal_time_zone, m_temporal_plain_date_time_formatter, m_temporal_plain_date_time_format);
|
||||
}
|
||||
|
||||
Optional<Unicode::DateTimeFormat const&> DateTimeFormat::temporal_instant_formatter()
|
||||
{
|
||||
return get_or_create_formatter(m_locale, m_temporal_time_zone, m_temporal_instant_formatter, m_temporal_instant_format);
|
||||
return get_or_create_formatter(m_icu_locale, m_temporal_time_zone, m_temporal_instant_formatter, m_temporal_instant_format);
|
||||
}
|
||||
|
||||
// 11.5.5 FormatDateTimePattern ( dateTimeFormat, patternParts, x, rangeFormatOptions ), https://tc39.es/ecma402/#sec-formatdatetimepattern
|
||||
|
|
|
@ -38,6 +38,9 @@ public:
|
|||
String const& locale() const { return m_locale; }
|
||||
void set_locale(String locale) { m_locale = move(locale); }
|
||||
|
||||
String const& icu_locale() const { return m_icu_locale; }
|
||||
void set_icu_locale(String icu_locale) { m_icu_locale = move(icu_locale); }
|
||||
|
||||
String const& calendar() const { return m_calendar; }
|
||||
void set_calendar(String calendar) { m_calendar = move(calendar); }
|
||||
|
||||
|
@ -107,6 +110,7 @@ private:
|
|||
GC::Ptr<NativeFunction> m_bound_format; // [[BoundFormat]]
|
||||
|
||||
// Non-standard. Stores the ICU date-time formatters for the Intl object's formatting options.
|
||||
String m_icu_locale;
|
||||
OwnPtr<Unicode::DateTimeFormat> m_formatter;
|
||||
OwnPtr<Unicode::DateTimeFormat> m_temporal_plain_date_formatter;
|
||||
OwnPtr<Unicode::DateTimeFormat> m_temporal_plain_year_month_formatter;
|
||||
|
|
|
@ -149,6 +149,7 @@ ThrowCompletionOr<GC::Ref<DateTimeFormat>> create_date_time_format(VM& vm, Funct
|
|||
|
||||
// 18. Set dateTimeFormat.[[Locale]] to r.[[Locale]].
|
||||
date_time_format->set_locale(move(result.locale));
|
||||
date_time_format->set_icu_locale(move(result.icu_locale));
|
||||
|
||||
// 19. Let resolvedCalendar be r.[[ca]].
|
||||
// 20. Set dateTimeFormat.[[Calendar]] to resolvedCalendar.
|
||||
|
@ -355,7 +356,7 @@ ThrowCompletionOr<GC::Ref<DateTimeFormat>> create_date_time_format(VM& vm, Funct
|
|||
// d. Let styles be resolvedLocaleData.[[styles]].[[<resolvedCalendar>]].
|
||||
// e. Let bestFormat be DateTimeStyleFormat(dateStyle, timeStyle, styles).
|
||||
formatter = Unicode::DateTimeFormat::create_for_date_and_time_style(
|
||||
date_time_format->locale(),
|
||||
date_time_format->icu_locale(),
|
||||
time_zone,
|
||||
format_options.hour_cycle,
|
||||
format_options.hour12,
|
||||
|
@ -443,7 +444,7 @@ ThrowCompletionOr<GC::Ref<DateTimeFormat>> create_date_time_format(VM& vm, Funct
|
|||
}
|
||||
|
||||
formatter = Unicode::DateTimeFormat::create_for_pattern_options(
|
||||
date_time_format->locale(),
|
||||
date_time_format->icu_locale(),
|
||||
time_zone,
|
||||
best_format);
|
||||
}
|
||||
|
|
|
@ -89,7 +89,7 @@ ThrowCompletionOr<GC::Ref<Object>> DurationFormatConstructor::construct(Function
|
|||
// 11. Let resolvedLocaleData be r.[[LocaleData]].
|
||||
|
||||
// 12. Let digitalFormat be resolvedLocaleData.[[DigitalFormat]].
|
||||
auto digital_format = Unicode::digital_format(duration_format->locale());
|
||||
auto digital_format = Unicode::digital_format(result.icu_locale);
|
||||
|
||||
// 13. Set durationFormat.[[HourMinuteSeparator]] to digitalFormat.[[HourMinuteSeparator]].
|
||||
duration_format->set_hour_minute_separator(move(digital_format.hours_minutes_separator));
|
||||
|
|
|
@ -184,8 +184,7 @@ ThrowCompletionOr<GC::Ref<Object>> NumberFormatConstructor::construct(FunctionOb
|
|||
|
||||
// Non-standard, create an ICU number formatter for this Intl object.
|
||||
auto formatter = Unicode::NumberFormat::create(
|
||||
number_format->locale(),
|
||||
number_format->numbering_system(),
|
||||
result.icu_locale,
|
||||
number_format->display_options(),
|
||||
number_format->rounding_options());
|
||||
number_format->set_formatter(move(formatter));
|
||||
|
|
|
@ -87,8 +87,7 @@ ThrowCompletionOr<GC::Ref<Object>> PluralRulesConstructor::construct(FunctionObj
|
|||
|
||||
// Non-standard, create an ICU number formatter for this Intl object.
|
||||
auto formatter = Unicode::NumberFormat::create(
|
||||
plural_rules->locale(),
|
||||
{},
|
||||
result.icu_locale,
|
||||
{},
|
||||
plural_rules->rounding_options());
|
||||
|
||||
|
|
|
@ -112,7 +112,7 @@ ThrowCompletionOr<GC::Ref<Object>> RelativeTimeFormatConstructor::construct(Func
|
|||
// 20. Let relativeTimeFormat.[[NumberFormat]] be ! Construct(%Intl.NumberFormat%, « locale »).
|
||||
// 21. Let relativeTimeFormat.[[PluralRules]] be ! Construct(%Intl.PluralRules%, « locale »).
|
||||
auto formatter = Unicode::RelativeTimeFormat::create(
|
||||
relative_time_format->locale(),
|
||||
result.icu_locale,
|
||||
relative_time_format->style());
|
||||
relative_time_format->set_formatter(move(formatter));
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue