diff --git a/intl/components/src/TimeZone.h b/intl/components/src/TimeZone.h index 180092bd3fc0b70462cc6ba67e72946e4c4c7604..2439e44997d859574bb4f40933e3bce90d2a56bc 100644 --- a/intl/components/src/TimeZone.h +++ b/intl/components/src/TimeZone.h @@ -106,23 +106,7 @@ class TimeZone final { mTimeZone->getDisplayName(static_cast<bool>(aDaylightSavings), icu::TimeZone::LONG, icu::Locale(aLocale), displayName); - - int32_t length = displayName.length(); - if (!aBuffer.reserve(AssertedCast<size_t>(length))) { - return Err(ICUError::OutOfMemory); - } - - // Copy the display name. - UErrorCode status = U_ZERO_ERROR; - int32_t written = displayName.extract(aBuffer.data(), length, status); - if (!ICUSuccessForStringSpan(status)) { - return Err(ToICUError(status)); - } - MOZ_ASSERT(written == length); - - aBuffer.written(written); - - return Ok{}; + return FillBuffer(displayName, aBuffer); #else return FillBufferWithICUCall( aBuffer, [&](UChar* target, int32_t length, UErrorCode* status) { @@ -134,6 +118,23 @@ class TimeZone final { #endif } + /** + * Return the identifier for this time zone. + */ + template <typename B> + ICUResult GetId(B& aBuffer) { +#if MOZ_INTL_USE_ICU_CPP_TIMEZONE + icu::UnicodeString id; + mTimeZone->getID(id); + return FillBuffer(id, aBuffer); +#else + return FillBufferWithICUCall( + aBuffer, [&](UChar* target, int32_t length, UErrorCode* status) { + return ucal_getTimeZoneID(mCalendar, target, length, status); + }); +#endif + } + /** * Fill the buffer with the system's default IANA time zone identifier, e.g. * "America/Chicago". @@ -225,6 +226,25 @@ class TimeZone final { static Result<SpanEnumeration<char>, ICUError> GetAvailableTimeZones(); private: + template <typename B> + static ICUResult FillBuffer(const icu::UnicodeString& aString, B& aBuffer) { + int32_t length = aString.length(); + if (!aBuffer.reserve(AssertedCast<size_t>(length))) { + return Err(ICUError::OutOfMemory); + } + + UErrorCode status = U_ZERO_ERROR; + int32_t written = aString.extract(aBuffer.data(), length, status); + if (!ICUSuccessForStringSpan(status)) { + return Err(ToICUError(status)); + } + MOZ_ASSERT(written == length); + + aBuffer.written(written); + + return Ok{}; + } + #if MOZ_INTL_USE_ICU_CPP_TIMEZONE UniquePtr<icu::TimeZone> mTimeZone = nullptr; #else diff --git a/js/src/builtin/TestingFunctions.cpp b/js/src/builtin/TestingFunctions.cpp index 5a7774f136564097d7942f96d21dc4ea78717b40..7d9fa47b6b17c37e0fe32062c3eb668b47c3d96b 100644 --- a/js/src/builtin/TestingFunctions.cpp +++ b/js/src/builtin/TestingFunctions.cpp @@ -107,6 +107,7 @@ #include "util/Text.h" #include "vm/BooleanObject.h" #include "vm/DateObject.h" +#include "vm/DateTime.h" #include "vm/ErrorObject.h" #include "vm/GlobalObject.h" #include "vm/HelperThreads.h" @@ -7959,7 +7960,7 @@ static bool GetICUOptions(JSContext* cx, unsigned argc, Value* vp) { intl::FormatBuffer<char16_t, intl::INITIAL_CHAR_BUFFER_SIZE> buf(cx); - if (auto ok = mozilla::intl::TimeZone::GetDefaultTimeZone(buf); ok.isErr()) { + if (auto ok = DateTimeInfo::timeZoneId(buf); ok.isErr()) { intl::ReportInternalError(cx, ok.unwrapErr()); return false; } diff --git a/js/src/builtin/intl/DateTimeFormat.cpp b/js/src/builtin/intl/DateTimeFormat.cpp index bb5f259b9afb373f571d9f9a98ba54755159f7c9..893e6af31a85c7a6920ea0cb39acf5fa0436c697 100644 --- a/js/src/builtin/intl/DateTimeFormat.cpp +++ b/js/src/builtin/intl/DateTimeFormat.cpp @@ -402,13 +402,8 @@ bool js::intl_defaultTimeZone(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); MOZ_ASSERT(args.length() == 0); - // The current default might be stale, because JS::ResetTimeZone() doesn't - // immediately update ICU's default time zone. So perform an update if - // needed. - js::ResyncICUDefaultTimeZone(); - FormatBuffer<char16_t, intl::INITIAL_CHAR_BUFFER_SIZE> timeZone(cx); - auto result = mozilla::intl::TimeZone::GetDefaultTimeZone(timeZone); + auto result = DateTimeInfo::timeZoneId(timeZone); if (result.isErr()) { intl::ReportInternalError(cx, result.unwrapErr()); return false; @@ -455,13 +450,8 @@ bool js::intl_isDefaultTimeZone(JSContext* cx, unsigned argc, Value* vp) { return true; } - // The current default might be stale, because JS::ResetTimeZone() doesn't - // immediately update ICU's default time zone. So perform an update if - // needed. - js::ResyncICUDefaultTimeZone(); - FormatBuffer<char16_t, intl::INITIAL_CHAR_BUFFER_SIZE> chars(cx); - auto result = mozilla::intl::TimeZone::GetDefaultTimeZone(chars); + auto result = DateTimeInfo::timeZoneId(chars); if (result.isErr()) { intl::ReportInternalError(cx, result.unwrapErr()); return false; diff --git a/js/src/vm/DateTime.cpp b/js/src/vm/DateTime.cpp index cb3d1288c8b3f40fbcb40429381306c230960d76..6071d81dacf221445cead5d34d88d224d6dc7095 100644 --- a/js/src/vm/DateTime.cpp +++ b/js/src/vm/DateTime.cpp @@ -729,10 +729,6 @@ static bool ReadTimeZoneLink(std::string_view tz, # endif /* defined(XP_WIN) */ #endif /* JS_HAS_INTL_API */ -void js::ResyncICUDefaultTimeZone() { - js::DateTimeInfo::resyncICUDefaultTimeZone(); -} - void js::DateTimeInfo::internalResyncICUDefaultTimeZone() { #if JS_HAS_INTL_API if (const char* tzenv = std::getenv("TZ")) { diff --git a/js/src/vm/DateTime.h b/js/src/vm/DateTime.h index b70e4e0ae25947daed0079334956b8cabd5c52b7..efb20c392e7797ae9705dbf9ff8bc47056176de0 100644 --- a/js/src/vm/DateTime.h +++ b/js/src/vm/DateTime.h @@ -15,9 +15,8 @@ #include "threading/ExclusiveData.h" #if JS_HAS_INTL_API -namespace mozilla::intl { -class TimeZone; -} +# include "mozilla/intl/ICU4CGlue.h" +# include "mozilla/intl/TimeZone.h" #endif namespace js { @@ -62,15 +61,6 @@ enum class ResetTimeZoneMode : bool { */ extern void ResetTimeZoneInternal(ResetTimeZoneMode mode); -/** - * ICU's default time zone, used for various date/time formatting operations - * that include the local time in the representation, is allowed to go stale - * for unfortunate performance reasons. Call this function when an up-to-date - * default time zone is required, to resync ICU's default time zone with - * reality. - */ -extern void ResyncICUDefaultTimeZone(); - /** * Stores date/time information, particularly concerning the current local * time zone, and implements a small cache for daylight saving time offset @@ -186,6 +176,16 @@ class DateTimeInfo { return guard->internalTimeZoneDisplayName(buf, buflen, utcMilliseconds, locale); } + + /** + * Copy the identifier for the current time zone to the provided resizable + * buffer. + */ + template <typename B> + static mozilla::intl::ICUResult timeZoneId(B& buffer) { + auto guard = acquireLockWithValidTimeZone(); + return guard->timeZone()->GetId(buffer); + } #else /** * Return the local time zone adjustment (ES2019 20.3.1.7) as computed by @@ -197,21 +197,14 @@ class DateTimeInfo { #endif /* JS_HAS_INTL_API */ private: - // The two methods below should only be called via js::ResetTimeZoneInternal() - // and js::ResyncICUDefaultTimeZone(). + // The method below should only be called via js::ResetTimeZoneInternal(). friend void js::ResetTimeZoneInternal(ResetTimeZoneMode); - friend void js::ResyncICUDefaultTimeZone(); static void resetTimeZone(ResetTimeZoneMode mode) { auto guard = instance->lock(); guard->internalResetTimeZone(mode); } - static void resyncICUDefaultTimeZone() { - auto guard = acquireLockWithValidTimeZone(); - (void)guard; - } - struct RangeCache { // Start and end offsets in seconds describing the current and the // last cached range.