From ee01f857d1b34fff815d64427a8f41852db03791 Mon Sep 17 00:00:00 2001 From: Timothy Flynn Date: Wed, 23 Jul 2025 14:24:25 -0400 Subject: [PATCH] LibJS+LibUnicode: Port Intl.DateTimeFormat to UTF-16 strings --- Libraries/LibJS/Runtime/Intl/DateTimeFormat.cpp | 8 ++++---- Libraries/LibJS/Runtime/Intl/DateTimeFormat.h | 4 ++-- Libraries/LibUnicode/DateTimeFormat.cpp | 14 +++++++------- Libraries/LibUnicode/DateTimeFormat.h | 10 +++++----- Libraries/LibUnicode/ICU.cpp | 5 +++++ Libraries/LibUnicode/ICU.h | 3 +++ 6 files changed, 26 insertions(+), 18 deletions(-) diff --git a/Libraries/LibJS/Runtime/Intl/DateTimeFormat.cpp b/Libraries/LibJS/Runtime/Intl/DateTimeFormat.cpp index 5e2f638302a..4c7f506c24a 100644 --- a/Libraries/LibJS/Runtime/Intl/DateTimeFormat.cpp +++ b/Libraries/LibJS/Runtime/Intl/DateTimeFormat.cpp @@ -119,11 +119,11 @@ ThrowCompletionOr> partition_date_tim // 11.5.7 FormatDateTime ( dateTimeFormat, x ), https://tc39.es/ecma402/#sec-formatdatetime // 15.9.6 FormatDateTime ( dateTimeFormat, x ), https://tc39.es/proposal-temporal/#sec-formatdatetime -ThrowCompletionOr format_date_time(VM& vm, DateTimeFormat& date_time_format, FormattableDateTime const& time) +ThrowCompletionOr format_date_time(VM& vm, DateTimeFormat& date_time_format, FormattableDateTime const& time) { // 1. Let parts be ? PartitionDateTimePattern(dateTimeFormat, x). // 2. Let result be the empty String. - String result; + Utf16String result; // NOTE: We short-circuit PartitionDateTimePattern as we do not need individual partitions. { @@ -196,11 +196,11 @@ ThrowCompletionOr> partition_date_tim // 11.5.10 FormatDateTimeRange ( dateTimeFormat, x, y ), https://tc39.es/ecma402/#sec-formatdatetimerange // 15.9.9 FormatDateTimeRange ( dateTimeFormat, x, y ), https://tc39.es/proposal-temporal/#sec-formatdatetimerange -ThrowCompletionOr format_date_time_range(VM& vm, DateTimeFormat& date_time_format, FormattableDateTime const& start, FormattableDateTime const& end) +ThrowCompletionOr format_date_time_range(VM& vm, DateTimeFormat& date_time_format, FormattableDateTime const& start, FormattableDateTime const& end) { // 1. Let parts be ? PartitionDateTimeRangePattern(dateTimeFormat, x, y). // 2. Let result be the empty String. - String result; + Utf16String result; // NOTE: We short-circuit PartitionDateTimeRangePattern as we do not need individual partitions. { diff --git a/Libraries/LibJS/Runtime/Intl/DateTimeFormat.h b/Libraries/LibJS/Runtime/Intl/DateTimeFormat.h index 1968a37f197..6fdcb8438f4 100644 --- a/Libraries/LibJS/Runtime/Intl/DateTimeFormat.h +++ b/Libraries/LibJS/Runtime/Intl/DateTimeFormat.h @@ -137,10 +137,10 @@ struct ValueFormat { Vector format_date_time_pattern(ValueFormat const&); ThrowCompletionOr> partition_date_time_pattern(VM&, DateTimeFormat&, FormattableDateTime const&); -ThrowCompletionOr format_date_time(VM&, DateTimeFormat&, FormattableDateTime const&); +ThrowCompletionOr format_date_time(VM&, DateTimeFormat&, FormattableDateTime const&); ThrowCompletionOr> format_date_time_to_parts(VM&, DateTimeFormat&, FormattableDateTime const&); ThrowCompletionOr> partition_date_time_range_pattern(VM&, DateTimeFormat&, FormattableDateTime const& start, FormattableDateTime const& end); -ThrowCompletionOr format_date_time_range(VM&, DateTimeFormat&, FormattableDateTime const& start, FormattableDateTime const& end); +ThrowCompletionOr format_date_time_range(VM&, DateTimeFormat&, FormattableDateTime const& start, FormattableDateTime const& end); ThrowCompletionOr> format_date_time_range_to_parts(VM&, DateTimeFormat&, FormattableDateTime const& start, FormattableDateTime const& end); Optional get_date_time_format(Unicode::CalendarPattern const& options, OptionRequired, OptionDefaults, OptionInherit); diff --git a/Libraries/LibUnicode/DateTimeFormat.cpp b/Libraries/LibUnicode/DateTimeFormat.cpp index 761bf523ee6..237173713ad 100644 --- a/Libraries/LibUnicode/DateTimeFormat.cpp +++ b/Libraries/LibUnicode/DateTimeFormat.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2024, Tim Flynn + * Copyright (c) 2021-2025, Tim Flynn * * SPDX-License-Identifier: BSD-2-Clause */ @@ -672,13 +672,13 @@ public: virtual CalendarPattern const& chosen_pattern() const override { return m_pattern; } - virtual String format(double time) const override + virtual Utf16String format(double time) const override { auto formatted_time = format_impl(time); if (!formatted_time.has_value()) return {}; - return icu_string_to_string(*formatted_time); + return icu_string_to_utf16_string(*formatted_time); } virtual Vector format_to_parts(double time) const override @@ -694,7 +694,7 @@ public: auto create_partition = [&](i32 field, i32 begin, i32 end) { Partition partition; partition.type = icu_date_time_format_field_to_string(field); - partition.value = icu_string_to_string(formatted_time->tempSubStringBetween(begin, end)); + partition.value = icu_string_to_utf16_string(formatted_time->tempSubStringBetween(begin, end)); partition.source = "shared"sv; result.append(move(partition)); }; @@ -717,7 +717,7 @@ public: return result; } - virtual String format_range(double start, double end) const override + virtual Utf16String format_range(double start, double end) const override { UErrorCode status = U_ZERO_ERROR; @@ -733,7 +733,7 @@ public: return {}; normalize_spaces(formatted_time); - return icu_string_to_string(formatted_time); + return icu_string_to_utf16_string(formatted_time); } virtual Vector format_range_to_parts(double start, double end) const override @@ -763,7 +763,7 @@ public: auto create_partition = [&](i32 field, i32 begin, i32 end) { Partition partition; partition.type = icu_date_time_format_field_to_string(field); - partition.value = icu_string_to_string(formatted_time.tempSubStringBetween(begin, end)); + partition.value = icu_string_to_utf16_string(formatted_time.tempSubStringBetween(begin, end)); if (start_range.has_value() && start_range->contains(begin)) partition.source = "startRange"sv; diff --git a/Libraries/LibUnicode/DateTimeFormat.h b/Libraries/LibUnicode/DateTimeFormat.h index 7ad970fc029..73796492d9c 100644 --- a/Libraries/LibUnicode/DateTimeFormat.h +++ b/Libraries/LibUnicode/DateTimeFormat.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2024, Tim Flynn + * Copyright (c) 2021-2025, Tim Flynn * * SPDX-License-Identifier: BSD-2-Clause */ @@ -8,10 +8,10 @@ #include #include -#include #include #include #include +#include #include #include @@ -151,16 +151,16 @@ public: struct Partition { StringView type; - String value; + Utf16String value; StringView source; }; virtual CalendarPattern const& chosen_pattern() const = 0; - virtual String format(double) const = 0; + virtual Utf16String format(double) const = 0; virtual Vector format_to_parts(double) const = 0; - virtual String format_range(double, double) const = 0; + virtual Utf16String format_range(double, double) const = 0; virtual Vector format_range_to_parts(double, double) const = 0; protected: diff --git a/Libraries/LibUnicode/ICU.cpp b/Libraries/LibUnicode/ICU.cpp index 6462b820e54..ec1ce4a3151 100644 --- a/Libraries/LibUnicode/ICU.cpp +++ b/Libraries/LibUnicode/ICU.cpp @@ -162,6 +162,11 @@ String icu_string_to_string(UChar const* string, i32 length) return MUST(Utf16View { string, static_cast(length) }.to_utf8()); } +Utf16String icu_string_to_utf16_string(icu::UnicodeString const& string) +{ + return Utf16String::from_utf16_without_validation({ string.getBuffer(), static_cast(string.length()) }); +} + UCharIterator icu_string_iterator(Utf16View const& string) { UCharIterator iterator; diff --git a/Libraries/LibUnicode/ICU.h b/Libraries/LibUnicode/ICU.h index ed7dc70bee0..fa9dc3a68df 100644 --- a/Libraries/LibUnicode/ICU.h +++ b/Libraries/LibUnicode/ICU.h @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -103,6 +104,8 @@ Vector icu_string_list(ReadonlySpan strings); String icu_string_to_string(icu::UnicodeString const& string); String icu_string_to_string(UChar const*, i32 length); +Utf16String icu_string_to_utf16_string(icu::UnicodeString const& string); + UCharIterator icu_string_iterator(Utf16View const&); template