diff --git a/.gitignore b/.gitignore index 7f031dc..7af52c1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,2 @@ -SOURCES/webkitgtk-2.46.6.tar.xz +SOURCES/webkitgtk-2.48.1.tar.xz SOURCES/webkitgtk-keys.gpg diff --git a/.webkit2gtk3.metadata b/.webkit2gtk3.metadata index 58928a5..af17198 100644 --- a/.webkit2gtk3.metadata +++ b/.webkit2gtk3.metadata @@ -1,2 +1,2 @@ -efadc17ef959747f3bef31a464bf7ce85b4b8ff1 SOURCES/webkitgtk-2.46.6.tar.xz +f7939f920f92f6b1395b8573f069d3fb9c085b3f SOURCES/webkitgtk-2.48.1.tar.xz 04b10b8a486542c4551269c20b18b5c1c6cb4f94 SOURCES/webkitgtk-keys.gpg diff --git a/SOURCES/CVE-2025-24201.patch b/SOURCES/CVE-2025-24201.patch deleted file mode 100644 index 64b676d..0000000 --- a/SOURCES/CVE-2025-24201.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 541280709a62351643fa7b456bc1f6d652fd9d0b Mon Sep 17 00:00:00 2001 -From: Kimmo Kinnunen -Date: Wed, 5 Mar 2025 16:49:53 -0800 -Subject: [PATCH] Cherry-pick b48791700366. rdar://146337054 - - WebGL context primitive restart can be toggled from WebContent process - https://bugs.webkit.org/show_bug.cgi?id=285858 - rdar://142693598 - - Reviewed by Cameron McCormack. - - Primitive restart is enabled for WebGL2 and disabled for WebGL 1 - contexts by default. There is no use-case for toggling it from - WCP. Do not pass enable/disable to ANGLE. - - * Source/WebCore/platform/graphics/angle/GraphicsContextGLANGLE.cpp: - (WebCore::GraphicsContextGLANGLE::disable): - (WebCore::GraphicsContextGLANGLE::enable): - - Canonical link: https://commits.webkit.org/289651.23@safari-7621-branch ---- - .../graphics/angle/GraphicsContextGLANGLE.cpp | 12 ++++++++++-- - 1 file changed, 10 insertions(+), 2 deletions(-) - -diff --git a/Source/WebCore/platform/graphics/angle/GraphicsContextGLANGLE.cpp b/Source/WebCore/platform/graphics/angle/GraphicsContextGLANGLE.cpp -index 39d148172b4f..81c9dff2fb89 100644 ---- a/Source/WebCore/platform/graphics/angle/GraphicsContextGLANGLE.cpp -+++ b/Source/WebCore/platform/graphics/angle/GraphicsContextGLANGLE.cpp -@@ -1169,7 +1169,11 @@ void GraphicsContextGLANGLE::disable(GCGLenum cap) - { - if (!makeContextCurrent()) - return; -- -+ if (cap == PRIMITIVE_RESTART_FIXED_INDEX) { -+ if (m_isForWebGL2) -+ addError(GCGLErrorCode::InvalidOperation); -+ return; -+ } - GL_Disable(cap); - } - -@@ -1203,7 +1207,11 @@ void GraphicsContextGLANGLE::enable(GCGLenum cap) - { - if (!makeContextCurrent()) - return; -- -+ if (cap == PRIMITIVE_RESTART_FIXED_INDEX) { -+ if (!m_isForWebGL2) -+ addError(GCGLErrorCode::InvalidOperation); -+ return; -+ } - GL_Enable(cap); - } - diff --git a/SOURCES/cairo-1.15.patch b/SOURCES/cairo-1.15.patch index 39dd0c1..c8107ce 100644 --- a/SOURCES/cairo-1.15.patch +++ b/SOURCES/cairo-1.15.patch @@ -1,20 +1,20 @@ diff --git a/Source/cmake/OptionsGTK.cmake b/Source/cmake/OptionsGTK.cmake -index 523177737358..9e714851a503 100644 +index 44ab9b35c6c9..f9c576764f43 100644 --- a/Source/cmake/OptionsGTK.cmake +++ b/Source/cmake/OptionsGTK.cmake -@@ -7,7 +7,7 @@ SET_PROJECT_VERSION(2 46 3) - +@@ -8,7 +8,7 @@ SET_PROJECT_VERSION(2 48 1) set(USER_AGENT_BRANDING "" CACHE STRING "Branding to add to user agent string") + find_package(GLIB 2.70.0 REQUIRED COMPONENTS gio gio-unix gobject gthread gmodule) -find_package(Cairo 1.16.0 REQUIRED) +find_package(Cairo 1.14.0 REQUIRED) find_package(LibGcrypt 1.7.0 REQUIRED) find_package(Libtasn1 REQUIRED) - find_package(HarfBuzz 1.4.2 REQUIRED COMPONENTS ICU) -@@ -142,7 +142,7 @@ WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_PERIODIC_MEMORY_MONITOR PRIVATE ON) + find_package(HarfBuzz 2.7.4 REQUIRED COMPONENTS ICU) +@@ -133,7 +133,7 @@ WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_THUNDER PRIVATE ${ENABLE_DEVELOPER_MODE} + WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_PERIODIC_MEMORY_MONITOR PRIVATE ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_POINTER_LOCK PRIVATE ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_SHAREABLE_RESOURCE PRIVATE ON) - WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_SPEECH_SYNTHESIS PRIVATE ${ENABLE_EXPERIMENTAL_FEATURES}) -WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_VARIATION_FONTS PRIVATE ON) +WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_VARIATION_FONTS PRIVATE OFF) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_WEB_API_STATISTICS PRIVATE ON) diff --git a/SOURCES/denormal-disabler-build.patch b/SOURCES/denormal-disabler-build.patch new file mode 100644 index 0000000..8660563 --- /dev/null +++ b/SOURCES/denormal-disabler-build.patch @@ -0,0 +1,12 @@ +diff --git a/Source/WebCore/platform/audio/DenormalDisabler.cpp b/Source/WebCore/platform/audio/DenormalDisabler.cpp +index 35715e663ce7..44ba08a33d5d 100644 +--- a/Source/WebCore/platform/audio/DenormalDisabler.cpp ++++ b/Source/WebCore/platform/audio/DenormalDisabler.cpp +@@ -91,7 +91,7 @@ DenormalDisabler::~DenormalDisabler() + } + } + #else +-DenormalDisabler::DenormalDisabler() = default ++DenormalDisabler::DenormalDisabler() = default; + DenormalDisabler::~DenormalDisabler() = default; + #endif diff --git a/SOURCES/glib-2.56.patch b/SOURCES/glib-2.56.patch index 8c35f1e..9f9e12f 100644 --- a/SOURCES/glib-2.56.patch +++ b/SOURCES/glib-2.56.patch @@ -37,3 +37,446 @@ index 8be643a54151..ae82b41400b5 100644 exit(EXIT_SUCCESS); } +From 4e525b9192df17a80b07188af6b6e7cf6476ff10 Mon Sep 17 00:00:00 2001 +From: Michael Catanzaro +Date: Fri, 4 Apr 2025 13:20:59 -0500 +Subject: [PATCH] Revert "[GLib] Remove all GLIB_CHECK_VERSION conditionals" + +This reverts commit 85b637b69f1c3a6242420b198d1c173477ce0f22. +--- + Source/WTF/wtf/URL.h | 4 ++-- + Source/WTF/wtf/glib/GRefPtr.cpp | 2 ++ + Source/WTF/wtf/glib/GRefPtr.h | 3 +++ + Source/WTF/wtf/glib/SocketConnection.cpp | 13 +++++++++++++ + Source/WTF/wtf/glib/URLGLib.cpp | 2 ++ + Source/WebCore/platform/LowPowerModeNotifier.h | 2 ++ + .../platform/glib/LowPowerModeNotifierGLib.cpp | 8 ++++++++ + .../platform/network/soup/CertificateInfoSoup.cpp | 8 ++++++++ + Source/WebKit/NetworkProcess/glib/DNSCache.cpp | 12 ++++++++++++ + Source/WebKit/NetworkProcess/glib/DNSCache.h | 2 ++ + .../NetworkProcess/glib/WebKitCachedResolver.cpp | 6 ++++++ + .../glib/WebKitOverridingResolver.cpp | 4 ++++ + Source/WebKit/Shared/glib/ArgumentCodersGLib.cpp | 6 ++++++ + Source/cmake/OptionsGTK.cmake | 13 ++++++++++++- + Source/cmake/OptionsWPE.cmake | 13 ++++++++++++- + 15 files changed, 94 insertions(+), 4 deletions(-) + +diff --git a/Source/WTF/wtf/URL.h b/Source/WTF/wtf/URL.h +index 8a7864508a8e..f065677c68ad 100644 +--- a/Source/WTF/wtf/URL.h ++++ b/Source/WTF/wtf/URL.h +@@ -27,7 +27,7 @@ + + #include + +-#if USE(GLIB) ++#if USE(GLIB) && HAVE(GURI) + #include + #endif + +@@ -237,7 +237,7 @@ public: + WTF_EXPORT_PRIVATE operator NSURL *() const; + #endif + +-#if USE(GLIB) ++#if USE(GLIB) && HAVE(GURI) + WTF_EXPORT_PRIVATE URL(GUri*); + WTF_EXPORT_PRIVATE GRefPtr createGUri() const; + #endif +diff --git a/Source/WTF/wtf/glib/GRefPtr.cpp b/Source/WTF/wtf/glib/GRefPtr.cpp +index 4c15aa9866c0..6faa98b7eab2 100644 +--- a/Source/WTF/wtf/glib/GRefPtr.cpp ++++ b/Source/WTF/wtf/glib/GRefPtr.cpp +@@ -207,6 +207,7 @@ template <> void derefGPtr(GDBusNodeInfo* ptr) + g_dbus_node_info_unref(ptr); + } + ++#if HAVE(GURI) + template <> GUri* refGPtr(GUri* ptr) + { + if (ptr) +@@ -219,6 +220,7 @@ template <> void derefGPtr(GUri* ptr) + if (ptr) + g_uri_unref(ptr); + } ++#endif + + template <> + GArray* refGPtr(GArray* ptr) +diff --git a/Source/WTF/wtf/glib/GRefPtr.h b/Source/WTF/wtf/glib/GRefPtr.h +index 87a9ef9760bf..d6c71c14a981 100644 +--- a/Source/WTF/wtf/glib/GRefPtr.h ++++ b/Source/WTF/wtf/glib/GRefPtr.h +@@ -264,8 +264,11 @@ template <> WTF_EXPORT_PRIVATE GArray* refGPtr(GArray*); + template <> WTF_EXPORT_PRIVATE void derefGPtr(GArray*); + template <> WTF_EXPORT_PRIVATE GResource* refGPtr(GResource*); + template <> WTF_EXPORT_PRIVATE void derefGPtr(GResource*); ++ ++#if HAVE(GURI) + template <> WTF_EXPORT_PRIVATE GUri* refGPtr(GUri*); + template <> WTF_EXPORT_PRIVATE void derefGPtr(GUri*); ++#endif + + template inline T* refGPtr(T* ptr) + { +diff --git a/Source/WTF/wtf/glib/SocketConnection.cpp b/Source/WTF/wtf/glib/SocketConnection.cpp +index d1185aeb2d47..80a622b83eba 100644 +--- a/Source/WTF/wtf/glib/SocketConnection.cpp ++++ b/Source/WTF/wtf/glib/SocketConnection.cpp +@@ -145,7 +145,20 @@ bool SocketConnection::readMessage() + if (!it->value.first.isNull()) { + GUniquePtr variantType(g_variant_type_new(it->value.first.data())); + size_t parametersSize = bodySize.value() - messageNameLength.value(); ++ // g_variant_new_from_data() requires the memory to be properly aligned for the type being loaded, ++ // but it's not possible to know the alignment because g_variant_type_info_query() is not public API. ++ // Since GLib 2.60 g_variant_new_from_data() already checks the alignment and reallocates the buffer ++ // in aligned memory only if needed. For older versions we can simply ensure the memory is 8 aligned. ++#if GLIB_CHECK_VERSION(2, 60, 0) + parameters = g_variant_new_from_data(variantType.get(), messageData, parametersSize, FALSE, nullptr, nullptr); ++#else ++ auto* alignedMemory = fastAlignedMalloc(8, parametersSize); ++ memcpy(alignedMemory, messageData, parametersSize); ++ GRefPtr bytes = g_bytes_new_with_free_func(alignedMemory, parametersSize, [](gpointer data) { ++ fastAlignedFree(data); ++ }, alignedMemory); ++ parameters = g_variant_new_from_bytes(variantType.get(), bytes.get(), FALSE); ++#endif + if (messageIsByteSwapped(flags)) + parameters = adoptGRef(g_variant_byteswap(parameters.get())); + } +diff --git a/Source/WTF/wtf/glib/URLGLib.cpp b/Source/WTF/wtf/glib/URLGLib.cpp +index 589dc1b52f8f..f67fe780f333 100644 +--- a/Source/WTF/wtf/glib/URLGLib.cpp ++++ b/Source/WTF/wtf/glib/URLGLib.cpp +@@ -35,6 +35,7 @@ + + namespace WTF { + ++#if HAVE(GURI) + URL::URL(GUri* uri) + { + if (!uri) { +@@ -56,6 +57,7 @@ GRefPtr URL::createGUri() const + static_cast(G_URI_FLAGS_HAS_PASSWORD | G_URI_FLAGS_ENCODED_PATH | G_URI_FLAGS_ENCODED_QUERY | G_URI_FLAGS_ENCODED_FRAGMENT | G_URI_FLAGS_SCHEME_NORMALIZE | G_URI_FLAGS_PARSE_RELAXED), + nullptr)); + } ++#endif + + bool URL::hostIsIPAddress(StringView host) + { +diff --git a/Source/WebCore/platform/LowPowerModeNotifier.h b/Source/WebCore/platform/LowPowerModeNotifier.h +index c8f2051d77f6..e2ea0dae3292 100644 +--- a/Source/WebCore/platform/LowPowerModeNotifier.h ++++ b/Source/WebCore/platform/LowPowerModeNotifier.h +@@ -61,8 +61,10 @@ private: + RetainPtr m_observer; + LowPowerModeChangeCallback m_callback; + #elif USE(GLIB) ++#if GLIB_CHECK_VERSION(2, 69, 1) + LowPowerModeChangeCallback m_callback; + GRefPtr m_powerProfileMonitor; ++#endif + bool m_lowPowerModeEnabled { false }; + #endif + }; +diff --git a/Source/WebCore/platform/glib/LowPowerModeNotifierGLib.cpp b/Source/WebCore/platform/glib/LowPowerModeNotifierGLib.cpp +index e083cc66934e..7c0f55d089e6 100644 +--- a/Source/WebCore/platform/glib/LowPowerModeNotifierGLib.cpp ++++ b/Source/WebCore/platform/glib/LowPowerModeNotifierGLib.cpp +@@ -28,10 +28,13 @@ namespace WebCore { + + + LowPowerModeNotifier::LowPowerModeNotifier(LowPowerModeChangeCallback&& callback) ++#if GLIB_CHECK_VERSION(2, 69, 1) + : m_callback(WTFMove(callback)) + , m_powerProfileMonitor(adoptGRef(g_power_profile_monitor_dup_default())) + , m_lowPowerModeEnabled(g_power_profile_monitor_get_power_saver_enabled(m_powerProfileMonitor.get())) ++#endif + { ++#if GLIB_CHECK_VERSION(2, 69, 1) + g_signal_connect_swapped(m_powerProfileMonitor.get(), "notify::power-saver-enabled", G_CALLBACK(+[] (LowPowerModeNotifier* self, GParamSpec*, GPowerProfileMonitor* monitor) { + bool powerSaverEnabled = g_power_profile_monitor_get_power_saver_enabled(monitor); + if (self->m_lowPowerModeEnabled != powerSaverEnabled) { +@@ -39,11 +42,16 @@ LowPowerModeNotifier::LowPowerModeNotifier(LowPowerModeChangeCallback&& callback + self->m_callback(self->m_lowPowerModeEnabled); + } + }), this); ++#else ++ UNUSED_PARAM(callback); ++#endif + } + + LowPowerModeNotifier::~LowPowerModeNotifier() + { ++#if GLIB_CHECK_VERSION(2, 69, 1) + g_signal_handlers_disconnect_by_data(m_powerProfileMonitor.get(), this); ++#endif + } + + bool LowPowerModeNotifier::isLowPowerModeEnabled() const +diff --git a/Source/WebCore/platform/network/soup/CertificateInfoSoup.cpp b/Source/WebCore/platform/network/soup/CertificateInfoSoup.cpp +index f32ecca7a300..e81a5433709d 100644 +--- a/Source/WebCore/platform/network/soup/CertificateInfoSoup.cpp ++++ b/Source/WebCore/platform/network/soup/CertificateInfoSoup.cpp +@@ -73,9 +73,11 @@ CertificateInfo CertificateInfo::isolatedCopy() const + certificatesDataList.append(certificateData.release()); + } + ++#if GLIB_CHECK_VERSION(2, 69, 0) + GUniqueOutPtr privateKey; + GUniqueOutPtr privateKeyPKCS11Uri; + g_object_get(m_certificate.get(), "private-key-pem", &privateKey.outPtr(), "private-key-pkcs11-uri", &privateKeyPKCS11Uri.outPtr(), nullptr); ++#endif + + GType certificateType = g_tls_backend_get_certificate_type(g_tls_backend_get_default()); + GRefPtr certificate; +@@ -86,8 +88,10 @@ CertificateInfo CertificateInfo::isolatedCopy() const + certificateType, nullptr, nullptr, + "certificate-pem", certificateData.get(), + "issuer", issuer, ++#if GLIB_CHECK_VERSION(2, 69, 0) + "private-key-pem", certificatesDataList.isEmpty() ? privateKey.get() : nullptr, + "private-key-pkcs11-uri", certificatesDataList.isEmpty() ? privateKeyPKCS11Uri.get() : nullptr, ++#endif + nullptr))); + RELEASE_ASSERT(certificate); + issuer = certificate.get(); +@@ -101,6 +105,7 @@ std::optional CertificateInfo::summary() const + if (!m_certificate) + return std::nullopt; + ++#if GLIB_CHECK_VERSION(2, 69, 0) + CertificateSummary summaryInfo; + + GRefPtr validNotBefore; +@@ -125,6 +130,9 @@ std::optional CertificateInfo::summary() const + } + + return summaryInfo; ++#else ++ return std::nullopt; ++#endif + } + + } // namespace WebCore +diff --git a/Source/WebKit/NetworkProcess/glib/DNSCache.cpp b/Source/WebKit/NetworkProcess/glib/DNSCache.cpp +index db92010baabf..b717b734e8e8 100644 +--- a/Source/WebKit/NetworkProcess/glib/DNSCache.cpp ++++ b/Source/WebKit/NetworkProcess/glib/DNSCache.cpp +@@ -50,9 +50,17 @@ DNSCache::DNSCacheMap& DNSCache::mapForType(Type type) + case Type::Default: + return m_dnsMap; + case Type::IPv4Only: ++#if GLIB_CHECK_VERSION(2, 59, 0) + return m_ipv4Map; ++#else ++ return m_dnsMap; ++#endif + case Type::IPv6Only: ++#if GLIB_CHECK_VERSION(2, 59, 0) + return m_ipv6Map; ++#else ++ return m_dnsMap; ++#endif + } + + RELEASE_ASSERT_NOT_REACHED(); +@@ -118,16 +126,20 @@ void DNSCache::removeExpiredResponsesFired() + { + Locker locker { m_lock }; + removeExpiredResponsesInMap(m_dnsMap); ++#if GLIB_CHECK_VERSION(2, 59, 0) + removeExpiredResponsesInMap(m_ipv4Map); + removeExpiredResponsesInMap(m_ipv6Map); ++#endif + } + + void DNSCache::clear() + { + Locker locker { m_lock }; + m_dnsMap.clear(); ++#if GLIB_CHECK_VERSION(2, 59, 0) + m_ipv4Map.clear(); + m_ipv6Map.clear(); ++#endif + } + + } // namespace WebKit +diff --git a/Source/WebKit/NetworkProcess/glib/DNSCache.h b/Source/WebKit/NetworkProcess/glib/DNSCache.h +index 6aa530f44321..49aded549588 100644 +--- a/Source/WebKit/NetworkProcess/glib/DNSCache.h ++++ b/Source/WebKit/NetworkProcess/glib/DNSCache.h +@@ -65,8 +65,10 @@ private: + + Lock m_lock; + DNSCacheMap m_dnsMap WTF_GUARDED_BY_LOCK(m_lock); ++#if GLIB_CHECK_VERSION(2, 59, 0) + DNSCacheMap m_ipv4Map; + DNSCacheMap m_ipv6Map; ++#endif + RunLoop::Timer m_expiredTimer; + }; + +diff --git a/Source/WebKit/NetworkProcess/glib/WebKitCachedResolver.cpp b/Source/WebKit/NetworkProcess/glib/WebKitCachedResolver.cpp +index 2752ff9cfc2c..7804e8b7a588 100644 +--- a/Source/WebKit/NetworkProcess/glib/WebKitCachedResolver.cpp ++++ b/Source/WebKit/NetworkProcess/glib/WebKitCachedResolver.cpp +@@ -67,7 +67,9 @@ static Vector> addressListGListToVector(GList* addressList + + struct LookupAsyncData { + CString hostname; ++#if GLIB_CHECK_VERSION(2, 59, 0) + DNSCache::Type dnsCacheType { DNSCache::Type::Default }; ++#endif + }; + WEBKIT_DEFINE_ASYNC_DATA_STRUCT(LookupAsyncData) + +@@ -117,6 +119,7 @@ static GList* webkitCachedResolverLookupByNameFinish(GResolver* resolver, GAsync + return static_cast(g_task_propagate_pointer(G_TASK(result), error)); + } + ++#if GLIB_CHECK_VERSION(2, 59, 0) + static inline DNSCache::Type dnsCacheType(GResolverNameLookupFlags flags) + { + // A cache is kept for each type of response to avoid the overcomplication of combining or filtering results. +@@ -177,6 +180,7 @@ static GList* webkitCachedResolverLookupByNameWithFlagsFinish(GResolver* resolve + + return static_cast(g_task_propagate_pointer(G_TASK(result), error)); + } ++#endif // GLIB_CHECK_VERSION(2, 59, 0) + + static char* webkitCachedResolverLookupByAddress(GResolver* resolver, GInetAddress* address, GCancellable* cancellable, GError** error) + { +@@ -219,9 +223,11 @@ static void webkit_cached_resolver_class_init(WebKitCachedResolverClass* klass) + resolverClass->lookup_by_name = webkitCachedResolverLookupByName; + resolverClass->lookup_by_name_async = webkitCachedResolverLookupByNameAsync; + resolverClass->lookup_by_name_finish = webkitCachedResolverLookupByNameFinish; ++#if GLIB_CHECK_VERSION(2, 59, 0) + resolverClass->lookup_by_name_with_flags = webkitCachedResolverLookupByNameWithFlags; + resolverClass->lookup_by_name_with_flags_async = webkitCachedResolverLookupByNameWithFlagsAsync; + resolverClass->lookup_by_name_with_flags_finish = webkitCachedResolverLookupByNameWithFlagsFinish; ++#endif + resolverClass->lookup_by_address = webkitCachedResolverLookupByAddress; + resolverClass->lookup_by_address_async = webkitCachedResolverLookupByAddressAsync; + resolverClass->lookup_by_address_finish = webkitCachedResolverLookupByAddressFinish; +diff --git a/Source/WebKit/NetworkProcess/glib/WebKitOverridingResolver.cpp b/Source/WebKit/NetworkProcess/glib/WebKitOverridingResolver.cpp +index 150d74ed0296..f461e3c695fe 100644 +--- a/Source/WebKit/NetworkProcess/glib/WebKitOverridingResolver.cpp ++++ b/Source/WebKit/NetworkProcess/glib/WebKitOverridingResolver.cpp +@@ -90,6 +90,7 @@ static GList* webkitOverridingResolverLookupByNameFinish(GResolver* resolver, GA + return static_cast(g_task_propagate_pointer(G_TASK(result), error)); + } + ++#if GLIB_CHECK_VERSION(2, 59, 0) + static GList* createLoobackAddressList(WebKitOverridingResolver* resolver, GResolverNameLookupFlags flags) + { + GList* list = nullptr; +@@ -129,6 +130,7 @@ static GList* webkitOverridingResolverLookupByNameWithFlagsFinish(GResolver* res + + return static_cast(g_task_propagate_pointer(G_TASK(result), error)); + } ++#endif // GLIB_CHECK_VERSION(2, 59, 0) + + static char* webkitOverridingResolverLookupByAddress(GResolver* resolver, GInetAddress* address, GCancellable* cancellable, GError** error) + { +@@ -166,9 +168,11 @@ static void webkit_overriding_resolver_class_init(WebKitOverridingResolverClass* + resolverClass->lookup_by_name = webkitOverridingResolverLookupByName; + resolverClass->lookup_by_name_async = webkitOverridingResolverLookupByNameAsync; + resolverClass->lookup_by_name_finish = webkitOverridingResolverLookupByNameFinish; ++#if GLIB_CHECK_VERSION(2, 59, 0) + resolverClass->lookup_by_name_with_flags = webkitOverridingResolverLookupByNameWithFlags; + resolverClass->lookup_by_name_with_flags_async = webkitOverridingResolverLookupByNameWithFlagsAsync; + resolverClass->lookup_by_name_with_flags_finish = webkitOverridingResolverLookupByNameWithFlagsFinish; ++#endif + resolverClass->lookup_by_address = webkitOverridingResolverLookupByAddress; + resolverClass->lookup_by_address_async = webkitOverridingResolverLookupByAddressAsync; + resolverClass->lookup_by_address_finish = webkitOverridingResolverLookupByAddressFinish; +diff --git a/Source/WebKit/Shared/glib/ArgumentCodersGLib.cpp b/Source/WebKit/Shared/glib/ArgumentCodersGLib.cpp +index a73466be12f1..9ab0cfb6f440 100644 +--- a/Source/WebKit/Shared/glib/ArgumentCodersGLib.cpp ++++ b/Source/WebKit/Shared/glib/ArgumentCodersGLib.cpp +@@ -121,11 +121,13 @@ void ArgumentCoder>::encode(Encoder& encoder, const GRe + + encoder << certificatesData; + ++#if GLIB_CHECK_VERSION(2, 69, 0) + GRefPtr privateKey; + GUniqueOutPtr privateKeyPKCS11Uri; + g_object_get(certificate.get(), "private-key", &privateKey.outPtr(), "private-key-pkcs11-uri", &privateKeyPKCS11Uri.outPtr(), nullptr); + encoder << privateKey; + encoder << CString(privateKeyPKCS11Uri.get()); ++#endif + } + + std::optional> ArgumentCoder>::decode(Decoder& decoder) +@@ -138,6 +140,7 @@ std::optional> ArgumentCoder>: + if (!certificatesData->size()) + return GRefPtr(); + ++#if GLIB_CHECK_VERSION(2, 69, 0) + std::optional> privateKey; + decoder >> privateKey; + if (UNLIKELY(!privateKey)) +@@ -147,6 +150,7 @@ std::optional> ArgumentCoder>: + decoder >> privateKeyPKCS11Uri; + if (UNLIKELY(!privateKeyPKCS11Uri)) + return std::nullopt; ++#endif + + GType certificateType = g_tls_backend_get_certificate_type(g_tls_backend_get_default()); + GRefPtr certificate; +@@ -156,8 +160,10 @@ std::optional> ArgumentCoder>: + certificateType, nullptr, nullptr, + "certificate", certificateData.get(), + "issuer", issuer, ++#if GLIB_CHECK_VERSION(2, 69, 0) + "private-key", i == certificatesData->size() - 1 ? privateKey->get() : nullptr, + "private-key-pkcs11-uri", i == certificatesData->size() - 1 ? privateKeyPKCS11Uri->data() : nullptr, ++#endif + nullptr))); + issuer = certificate.get(); + } +diff --git a/Source/cmake/OptionsGTK.cmake b/Source/cmake/OptionsGTK.cmake +index 4a285e849cfd..0aca16c1d25f 100644 +--- a/Source/cmake/OptionsGTK.cmake ++++ b/Source/cmake/OptionsGTK.cmake +@@ -205,6 +204,13 @@ else () + SET_AND_EXPOSE_TO_BUILD(ENABLE_2022_GLIB_API OFF) + endif () + ++if (ENABLE_2022_GLIB_API) ++ set(GLIB_MINIMUM_VERSION 2.70.0) ++else () ++ set(GLIB_MINIMUM_VERSION 2.56.4) ++endif () ++find_package(GLIB ${GLIB_MINIMUM_VERSION} REQUIRED COMPONENTS gio gio-unix gobject gthread gmodule) ++ + EXPOSE_STRING_VARIABLE_TO_BUILD(WEBKITGTK_API_INFIX) + EXPOSE_STRING_VARIABLE_TO_BUILD(WEBKITGTK_API_VERSION) + +@@ -277,6 +283,11 @@ if (ENABLED_COMPILER_SANITIZERS) + set(ENABLE_DOCUMENTATION OFF) + endif () + ++# GUri is available in GLib since version 2.66, but we only want to use it if version is >= 2.67.1. ++if (PC_GLIB_VERSION VERSION_GREATER "2.67.1" OR PC_GLIB_VERSION STREQUAL "2.67.1") ++ SET_AND_EXPOSE_TO_BUILD(HAVE_GURI 1) ++endif () ++ + if (ENABLE_GAMEPAD) + find_package(Manette 0.2.4) + if (NOT Manette_FOUND) +-- +2.49.0 +diff --git a/Source/cmake/OptionsGTK.cmake b/Source/cmake/OptionsGTK.cmake +index 6c39538ba6fc..0a30e0c4c7c1 100644 +--- a/Source/cmake/OptionsGTK.cmake ++++ b/Source/cmake/OptionsGTK.cmake +@@ -7,7 +7,6 @@ SET_PROJECT_VERSION(2 48 1) + + set(USER_AGENT_BRANDING "" CACHE STRING "Branding to add to user agent string") + +-find_package(GLIB 2.70.0 REQUIRED COMPONENTS gio gio-unix gobject gthread gmodule) + find_package(Cairo 1.14.0 REQUIRED) + find_package(LibGcrypt 1.7.0 REQUIRED) + find_package(Libtasn1 REQUIRED) diff --git a/SOURCES/gstreamer-1.16.patch b/SOURCES/gstreamer-1.16.patch index 76ac612..89717be 100644 --- a/SOURCES/gstreamer-1.16.patch +++ b/SOURCES/gstreamer-1.16.patch @@ -1,5 +1,22 @@ +From 08a5ccf6fc4a998ca1fb5aa13c314640dd95b874 Mon Sep 17 00:00:00 2001 +From: Michael Catanzaro +Date: Fri, 4 Apr 2025 14:00:12 -0500 +Subject: [PATCH] Build against GStreamer 1.16 + +--- + .../AudioSourceProviderGStreamer.cpp | 3 +- + .../gstreamer/GLVideoSinkGStreamer.cpp | 35 ++++----- + .../gstreamer/GStreamerAudioMixer.cpp | 2 +- + .../graphics/gstreamer/GStreamerCommon.cpp | 77 +++++++++++++------ + .../graphics/gstreamer/GStreamerCommon.h | 16 ++++ + .../gstreamer/MediaPlayerPrivateGStreamer.cpp | 22 +----- + .../gstreamer/GStreamerCodecUtilities.cpp | 39 ++++++---- + .../VideoEncoderPrivateGStreamer.cpp | 16 ---- + Source/cmake/GStreamerChecks.cmake | 4 +- + 9 files changed, 114 insertions(+), 100 deletions(-) + diff --git a/Source/WebCore/platform/audio/gstreamer/AudioSourceProviderGStreamer.cpp b/Source/WebCore/platform/audio/gstreamer/AudioSourceProviderGStreamer.cpp -index 51547b0226c0..2ab2d0c8688c 100644 +index 0abdeb14826e..65763f3cfde3 100644 --- a/Source/WebCore/platform/audio/gstreamer/AudioSourceProviderGStreamer.cpp +++ b/Source/WebCore/platform/audio/gstreamer/AudioSourceProviderGStreamer.cpp @@ -124,7 +124,8 @@ AudioSourceProviderGStreamer::AudioSourceProviderGStreamer(MediaStreamTrackPriva @@ -12,32 +29,33 @@ index 51547b0226c0..2ab2d0c8688c 100644 auto sinkPad = adoptGRef(gst_element_get_static_pad(provider->m_audioSinkBin.get(), "sink")); gst_pad_link(pad, sinkPad.get()); -diff --git a/Source/WebCore/platform/graphics/gstreamer/DMABufUtilities.h b/Source/WebCore/platform/graphics/gstreamer/DMABufUtilities.h -index da16adf3b556..7a78145f6228 100644 ---- a/Source/WebCore/platform/graphics/gstreamer/DMABufUtilities.h -+++ b/Source/WebCore/platform/graphics/gstreamer/DMABufUtilities.h -@@ -53,12 +53,6 @@ inline uint32_t dmaBufFourccValue(GstVideoFormat format) - return uint32_t(DMABufFormat::FourCC::BGRA8888); - case GST_VIDEO_FORMAT_ABGR: - return uint32_t(DMABufFormat::FourCC::RGBA8888); -- case GST_VIDEO_FORMAT_P010_10LE: -- case GST_VIDEO_FORMAT_P010_10BE: -- return uint32_t(DMABufFormat::FourCC::P010); -- case GST_VIDEO_FORMAT_P016_LE: -- case GST_VIDEO_FORMAT_P016_BE: -- return uint32_t(DMABufFormat::FourCC::P016); - default: - break; - } diff --git a/Source/WebCore/platform/graphics/gstreamer/GLVideoSinkGStreamer.cpp b/Source/WebCore/platform/graphics/gstreamer/GLVideoSinkGStreamer.cpp -index f8840e3e31e0..ce209d21fb69 100644 +index 12fed2ed3b21..fe0d6c660f80 100644 --- a/Source/WebCore/platform/graphics/gstreamer/GLVideoSinkGStreamer.cpp +++ b/Source/WebCore/platform/graphics/gstreamer/GLVideoSinkGStreamer.cpp -@@ -88,7 +88,19 @@ static void webKitGLVideoSinkConstructed(GObject* object) - ASSERT(colorconvert); - gst_bin_add_many(GST_BIN_CAST(sink), upload, colorconvert, sink->priv->appSink.get(), nullptr); +@@ -65,16 +65,7 @@ static bool s_isDMABufDisabled; -- GRefPtr caps = adoptGRef(gst_caps_from_string("video/x-raw, format = (string) " GST_GL_CAPS_FORMAT)); + static void initializeDMABufAvailability() + { +- static std::once_flag onceFlag; +- std::call_once(onceFlag, [] { +- if (!webkitGstCheckVersion(1, 20, 0)) +- return; +- +- auto value = unsafeSpan(g_getenv("WEBKIT_GST_DMABUF_SINK_DISABLED")); +- s_isDMABufDisabled = value.data() && (equalLettersIgnoringASCIICase(value, "true"_s) || equalLettersIgnoringASCIICase(value, "1"_s)); +- if (!s_isDMABufDisabled && !DRMDeviceManager::singleton().mainGBMDeviceNode(DRMDeviceManager::NodeType::Render)) +- s_isDMABufDisabled = true; +- }); ++ s_isDMABufDisabled = true; + } + #endif + +@@ -114,7 +105,19 @@ static void webKitGLVideoSinkConstructed(GObject* object) + if (!s_isDMABufDisabled) + gst_caps_append(caps.get(), buildDMABufCaps().leakRef()); + #endif +- GRefPtr glCaps = adoptGRef(gst_caps_from_string("video/x-raw, format = (string) " GST_GL_CAPS_FORMAT)); + // Workaround until we can depend on GStreamer 1.16.2. + // https://gitlab.freedesktop.org/gstreamer/gst-plugins-base/commit/8d32de090554cf29fe359f83aa46000ba658a693 + // Forcing a color conversion to RGBA here allows glupload to internally use @@ -50,19 +68,25 @@ index f8840e3e31e0..ce209d21fb69 100644 + // and set the WEBKIT_GST_NO_RGBA_CONVERSION environment variable until + // GStreamer 1.16.2 is released. + // See also https://bugs.webkit.org/show_bug.cgi?id=201422 -+ GRefPtr caps = adoptGRef(gst_caps_from_string("video/x-raw, format = (string) RGBA")); - gst_caps_set_features(caps.get(), 0, gst_caps_features_new(GST_CAPS_FEATURE_MEMORY_GL_MEMORY, nullptr)); - g_object_set(sink->priv->appSink.get(), "caps", caps.get(), nullptr); ++ GRefPtr glCaps = adoptGRef(gst_caps_from_string("video/x-raw, format = (string) RGBA")); + gst_caps_set_features(glCaps.get(), 0, gst_caps_features_new(GST_CAPS_FEATURE_MEMORY_GL_MEMORY, nullptr)); + gst_caps_append(caps.get(), glCaps.leakRef()); -@@ -186,12 +198,8 @@ static void webKitGLVideoSinkGetProperty(GObject* object, guint propertyId, GVal - WebKitGLVideoSink* sink = WEBKIT_GL_VIDEO_SINK(object); +@@ -172,17 +175,11 @@ static GstStateChangeReturn webKitGLVideoSinkChangeState(GstElement* element, Gs + return GST_ELEMENT_CLASS(webkit_gl_video_sink_parent_class)->change_state(element, transition); + } +-static void webKitGLVideoSinkGetProperty(GObject* object, guint propertyId, GValue* value, GParamSpec* paramSpec) ++static void webKitGLVideoSinkGetProperty(GObject* object, guint propertyId, GValue*, GParamSpec* paramSpec) + { +- WebKitGLVideoSink* sink = WEBKIT_GL_VIDEO_SINK(object); +- switch (propertyId) { -- case PROP_STATS: { +- case WEBKIT_GL_VIDEO_SINK_PROP_STATS: { - GUniqueOutPtr stats; - g_object_get(sink->priv->appSink.get(), "stats", &stats.outPtr(), nullptr); - gst_value_set_structure(value, stats.get()); -+ case PROP_STATS: ++ case WEBKIT_GL_VIDEO_SINK_PROP_STATS: break; - } default: @@ -82,13 +106,13 @@ index 8b30e0f14b6a..2d587f68a3b2 100644 GStreamerAudioMixer& GStreamerAudioMixer::singleton() diff --git a/Source/WebCore/platform/graphics/gstreamer/GStreamerCommon.cpp b/Source/WebCore/platform/graphics/gstreamer/GStreamerCommon.cpp -index a7392908eabd..4171e640de22 100644 +index 25c8abd3ec90..5ca712566cbd 100644 --- a/Source/WebCore/platform/graphics/gstreamer/GStreamerCommon.cpp +++ b/Source/WebCore/platform/graphics/gstreamer/GStreamerCommon.cpp -@@ -117,6 +117,24 @@ GstPad* webkitGstGhostPadFromStaticTemplate(GstStaticPadTemplate* staticPadTempl - return pad; +@@ -132,6 +132,24 @@ GstPad* webkitGstGhostPadFromStaticTemplate(GstStaticPadTemplate* staticPadTempl } + #if ENABLE(VIDEO) +#if !GST_CHECK_VERSION(1, 18, 0) +void webkitGstVideoFormatInfoComponent(const GstVideoFormatInfo* info, guint plane, gint components[GST_VIDEO_MAX_COMPONENTS]) +{ @@ -107,10 +131,10 @@ index a7392908eabd..4171e640de22 100644 +} +#endif + - #if ENABLE(VIDEO) bool getVideoSizeAndFormatFromCaps(const GstCaps* caps, WebCore::IntSize& size, GstVideoFormat& format, int& pixelAspectRatioNumerator, int& pixelAspectRatioDenominator, int& stride) { -@@ -566,31 +584,6 @@ void deinitializeGStreamer() + if (!doCapsHaveType(caps, GST_VIDEO_CAPS_TYPE_PREFIX)) { +@@ -633,31 +651,6 @@ void deinitializeGStreamer() teardownVideoEncoderSingleton(); teardownGStreamerImageDecoders(); #endif @@ -142,7 +166,7 @@ index a7392908eabd..4171e640de22 100644 } unsigned getGstPlayFlag(const char* nick) -@@ -1239,6 +1232,36 @@ String gstStructureToJSONString(const GstStructure* structure) +@@ -1358,6 +1351,36 @@ String gstStructureToJSONString(const GstStructure* structure) return value->toJSONString(); } @@ -179,7 +203,7 @@ index a7392908eabd..4171e640de22 100644 GstClockTime webkitGstInitTime() { return s_webkitGstInitTime; -@@ -1296,6 +1319,7 @@ PlatformVideoColorSpace videoColorSpaceFromInfo(const GstVideoInfo& info) +@@ -1415,6 +1438,7 @@ PlatformVideoColorSpace videoColorSpaceFromInfo(const GstVideoInfo& info) case GST_VIDEO_TRANSFER_BT709: colorSpace.transfer = PlatformVideoTransferCharacteristics::Bt709; break; @@ -187,7 +211,7 @@ index a7392908eabd..4171e640de22 100644 case GST_VIDEO_TRANSFER_BT601: colorSpace.transfer = PlatformVideoTransferCharacteristics::Smpte170m; break; -@@ -1308,6 +1332,7 @@ PlatformVideoColorSpace videoColorSpaceFromInfo(const GstVideoInfo& info) +@@ -1427,6 +1451,7 @@ PlatformVideoColorSpace videoColorSpaceFromInfo(const GstVideoInfo& info) case GST_VIDEO_TRANSFER_BT2020_10: colorSpace.transfer = PlatformVideoTransferCharacteristics::Bt2020_10bit; break; @@ -195,7 +219,7 @@ index a7392908eabd..4171e640de22 100644 case GST_VIDEO_TRANSFER_BT2020_12: colorSpace.transfer = PlatformVideoTransferCharacteristics::Bt2020_12bit; break; -@@ -1426,6 +1451,7 @@ void fillVideoInfoColorimetryFromColorSpace(GstVideoInfo* info, const PlatformVi +@@ -1545,6 +1570,7 @@ void fillVideoInfoColorimetryFromColorSpace(GstVideoInfo* info, const PlatformVi case PlatformVideoTransferCharacteristics::Bt709: GST_VIDEO_INFO_COLORIMETRY(info).transfer = GST_VIDEO_TRANSFER_BT709; break; @@ -203,7 +227,7 @@ index a7392908eabd..4171e640de22 100644 case PlatformVideoTransferCharacteristics::Smpte170m: GST_VIDEO_INFO_COLORIMETRY(info).transfer = GST_VIDEO_TRANSFER_BT601; break; -@@ -1438,6 +1464,7 @@ void fillVideoInfoColorimetryFromColorSpace(GstVideoInfo* info, const PlatformVi +@@ -1557,6 +1583,7 @@ void fillVideoInfoColorimetryFromColorSpace(GstVideoInfo* info, const PlatformVi case PlatformVideoTransferCharacteristics::Bt2020_10bit: GST_VIDEO_INFO_COLORIMETRY(info).transfer = GST_VIDEO_TRANSFER_BT2020_10; break; @@ -212,10 +236,10 @@ index a7392908eabd..4171e640de22 100644 GST_VIDEO_INFO_COLORIMETRY(info).transfer = GST_VIDEO_TRANSFER_BT2020_12; break; diff --git a/Source/WebCore/platform/graphics/gstreamer/GStreamerCommon.h b/Source/WebCore/platform/graphics/gstreamer/GStreamerCommon.h -index f9f42a940a58..766ebaf45b38 100644 +index f332ddd0e040..217132050db0 100644 --- a/Source/WebCore/platform/graphics/gstreamer/GStreamerCommon.h +++ b/Source/WebCore/platform/graphics/gstreamer/GStreamerCommon.h -@@ -57,6 +57,15 @@ inline bool webkitGstCheckVersion(guint major, guint minor, guint micro) +@@ -64,6 +64,15 @@ inline bool webkitGstCheckVersion(guint major, guint minor, guint micro) return true; } @@ -231,7 +255,7 @@ index f9f42a940a58..766ebaf45b38 100644 #define GST_VIDEO_CAPS_TYPE_PREFIX "video/" #define GST_AUDIO_CAPS_TYPE_PREFIX "audio/" #define GST_TEXT_CAPS_TYPE_PREFIX "text/" -@@ -287,6 +296,13 @@ Vector gstStructureGetArray(const GstStructure*, ASCIILiteral key); +@@ -301,6 +310,13 @@ Vector gstStructureGetArray(const GstStructure*, ASCIILiteral key); String gstStructureToJSONString(const GstStructure*); @@ -246,10 +270,10 @@ index f9f42a940a58..766ebaf45b38 100644 PlatformVideoColorSpace videoColorSpaceFromCaps(const GstCaps*); diff --git a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp -index 9b30c5cfac68..012241d680e3 100644 +index 80fdb52a342c..30a535eb816b 100644 --- a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp +++ b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp -@@ -604,7 +604,6 @@ bool MediaPlayerPrivateGStreamer::doSeek(const SeekTarget& target, float rate) +@@ -587,7 +587,6 @@ bool MediaPlayerPrivateGStreamer::doSeek(const SeekTarget& target, float rate) auto seekStart = toGstClockTime(startTime); auto seekStop = toGstClockTime(endTime); @@ -257,36 +281,7 @@ index 9b30c5cfac68..012241d680e3 100644 return gst_element_seek(m_pipeline.get(), rate, GST_FORMAT_TIME, m_seekFlags, GST_SEEK_TYPE_SET, seekStart, GST_SEEK_TYPE_SET, seekStop); } -@@ -4369,7 +4368,27 @@ GstElement* MediaPlayerPrivateGStreamer::createVideoSink() - g_signal_connect_swapped(m_videoSink.get(), "repaint-cancelled", G_CALLBACK(repaintCancelledCallback), this); - } - -- return m_videoSink.get(); -+ GstElement* videoSink = nullptr; -+ m_fpsSink = makeGStreamerElement("fpsdisplaysink", "sink"); -+ if (m_fpsSink) { -+ g_object_set(m_fpsSink.get(), "silent", TRUE , nullptr); -+ -+ // Turn off text overlay unless tracing is enabled. -+ if (gst_debug_category_get_threshold(webkit_media_player_debug) < GST_LEVEL_TRACE) -+ g_object_set(m_fpsSink.get(), "text-overlay", FALSE , nullptr); -+ -+ if (gstObjectHasProperty(m_fpsSink.get(), "video-sink")) { -+ g_object_set(m_fpsSink.get(), "video-sink", m_videoSink.get(), nullptr); -+ videoSink = m_fpsSink.get(); -+ } else -+ m_fpsSink = nullptr; -+ } -+ -+ if (!m_fpsSink) -+ videoSink = m_videoSink.get(); -+ -+ ASSERT(videoSink); -+ return videoSink; - } - - void MediaPlayerPrivateGStreamer::setStreamVolumeElement(GstStreamVolume* volume) -@@ -4399,25 +4418,18 @@ void MediaPlayerPrivateGStreamer::setStreamVolumeElement(GstStreamVolume* volume +@@ -4153,26 +4152,7 @@ void MediaPlayerPrivateGStreamer::setStreamVolumeElement(GstStreamVolume* volume bool MediaPlayerPrivateGStreamer::updateVideoSinkStatistics() { @@ -296,89 +291,88 @@ index 9b30c5cfac68..012241d680e3 100644 - GUniqueOutPtr stats; - g_object_get(m_videoSink.get(), "stats", &stats.outPtr(), nullptr); - if (!stats) -+ if (!m_videoSink || !m_fpsSink) - return false; - +- return false; +- - auto totalVideoFrames = gstStructureGet(stats.get(), "rendered"_s); - auto droppedVideoFrames = gstStructureGet(stats.get(), "dropped"_s); - - if (!totalVideoFrames || !droppedVideoFrames) - return false; -+ unsigned totalVideoFrames = 0; -+ unsigned droppedVideoFrames = 0; -+ g_object_get(m_fpsSink.get(), "frames-rendered", &totalVideoFrames, "frames-dropped", &droppedVideoFrames, nullptr); - - // Caching is required so that metrics queries performed after EOS still return valid values. +- +- // Caching is required so that metrics queries performed after EOS still return valid values. - if (*totalVideoFrames) - m_totalVideoFrames = *totalVideoFrames; - if (*droppedVideoFrames) - m_droppedVideoFrames = *droppedVideoFrames; -+ if (totalVideoFrames) -+ m_totalVideoFrames = totalVideoFrames; -+ if (droppedVideoFrames) -+ m_droppedVideoFrames = droppedVideoFrames; - return true; +- return true; ++ return false; } -diff --git a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h -index 687bb4648aef..53f1f7ab3dc9 100644 ---- a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h -+++ b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h -@@ -637,6 +637,7 @@ private: - uint64_t m_networkReadPosition { 0 }; - mutable uint64_t m_readPositionAtLastDidLoadingProgress { 0 }; - -+ GRefPtr m_fpsSink { nullptr }; - uint64_t m_totalVideoFrames { 0 }; - uint64_t m_droppedVideoFrames { 0 }; - uint64_t m_decodedVideoFrames { 0 }; + std::optional MediaPlayerPrivateGStreamer::videoPlaybackQualityMetrics() diff --git a/Source/WebCore/platform/gstreamer/GStreamerCodecUtilities.cpp b/Source/WebCore/platform/gstreamer/GStreamerCodecUtilities.cpp -index c701a84d2316..ec4c4b24347c 100644 +index 870570cf204a..cc41cdf8911c 100644 --- a/Source/WebCore/platform/gstreamer/GStreamerCodecUtilities.cpp +++ b/Source/WebCore/platform/gstreamer/GStreamerCodecUtilities.cpp -@@ -256,7 +256,7 @@ static std::pair, GRefPtr> vpxCapsFromCodecString(cons +@@ -256,9 +256,10 @@ static std::pair, GRefPtr> vpxCapsFromCodecString(cons + GST_VIDEO_INFO_COLORIMETRY(&info).transfer = GST_VIDEO_TRANSFER_BT709; else if (transfer == VPConfigurationTransferCharacteristics::BT_470_7_BG) GST_VIDEO_INFO_COLORIMETRY(&info).transfer = GST_VIDEO_TRANSFER_GAMMA28; - else if (transfer == VPConfigurationTransferCharacteristics::BT_601_7) +- else if (transfer == VPConfigurationTransferCharacteristics::BT_601_7) - GST_VIDEO_INFO_COLORIMETRY(&info).transfer = GST_VIDEO_TRANSFER_BT601; +- else if (transfer == VPConfigurationTransferCharacteristics::SMPTE_ST_240) ++ else if (transfer == VPConfigurationTransferCharacteristics::BT_601_7) { ++ GST_WARNING("VPConfigurationTransferCharacteristics::BT_601_7 not supported"); + GST_VIDEO_INFO_COLORIMETRY(&info).transfer = GST_VIDEO_TRANSFER_UNKNOWN; - else if (transfer == VPConfigurationTransferCharacteristics::SMPTE_ST_240) ++ } else if (transfer == VPConfigurationTransferCharacteristics::SMPTE_ST_240) GST_VIDEO_INFO_COLORIMETRY(&info).transfer = GST_VIDEO_TRANSFER_SMPTE240M; else if (transfer == VPConfigurationTransferCharacteristics::Linear) -@@ -271,16 +271,16 @@ static std::pair, GRefPtr> vpxCapsFromCodecString(cons + GST_VIDEO_INFO_COLORIMETRY(&info).transfer = GST_VIDEO_TRANSFER_GAMMA10; +@@ -271,17 +272,21 @@ static std::pair, GRefPtr> vpxCapsFromCodecString(cons + else if (transfer == VPConfigurationTransferCharacteristics::IEC_61966_2_1) { GST_WARNING("VPConfigurationTransferCharacteristics::IEC_61966_2_1 not supported"); GST_VIDEO_INFO_COLORIMETRY(&info).transfer = GST_VIDEO_TRANSFER_UNKNOWN; - } else if (transfer == VPConfigurationTransferCharacteristics::BT_2020_10bit) +- } else if (transfer == VPConfigurationTransferCharacteristics::BT_2020_10bit) - GST_VIDEO_INFO_COLORIMETRY(&info).transfer = GST_VIDEO_TRANSFER_BT2020_10; +- else if (transfer == VPConfigurationTransferCharacteristics::BT_2020_12bit) ++ } else if (transfer == VPConfigurationTransferCharacteristics::BT_2020_10bit) { ++ GST_WARNING("VPConfigurationTransferCharacteristics::BT_2020_10bit not supported"); + GST_VIDEO_INFO_COLORIMETRY(&info).transfer = GST_VIDEO_TRANSFER_UNKNOWN; - else if (transfer == VPConfigurationTransferCharacteristics::BT_2020_12bit) ++ } else if (transfer == VPConfigurationTransferCharacteristics::BT_2020_12bit) GST_VIDEO_INFO_COLORIMETRY(&info).transfer = GST_VIDEO_TRANSFER_BT2020_12; - else if (transfer == VPConfigurationTransferCharacteristics::SMPTE_ST_2084) +- else if (transfer == VPConfigurationTransferCharacteristics::SMPTE_ST_2084) - GST_VIDEO_INFO_COLORIMETRY(&info).transfer = GST_VIDEO_TRANSFER_SMPTE2084; +- else if (transfer == VPConfigurationTransferCharacteristics::SMPTE_ST_428_1) { ++ else if (transfer == VPConfigurationTransferCharacteristics::SMPTE_ST_2084) { ++ GST_WARNING("VPConfigurationTransferCharacteristics::SMPTE_ST_2084 not supported"); + GST_VIDEO_INFO_COLORIMETRY(&info).transfer = GST_VIDEO_TRANSFER_UNKNOWN; - else if (transfer == VPConfigurationTransferCharacteristics::SMPTE_ST_428_1) { ++ } else if (transfer == VPConfigurationTransferCharacteristics::SMPTE_ST_428_1) { GST_WARNING("VPConfigurationTransferCharacteristics::SMPTE_ST_428_1 not supported"); GST_VIDEO_INFO_COLORIMETRY(&info).transfer = GST_VIDEO_TRANSFER_UNKNOWN; - } else if (transfer == VPConfigurationTransferCharacteristics::BT_2100_HLG) +- } else if (transfer == VPConfigurationTransferCharacteristics::BT_2100_HLG) - GST_VIDEO_INFO_COLORIMETRY(&info).transfer = GST_VIDEO_TRANSFER_ARIB_STD_B67; ++ } else if (transfer == VPConfigurationTransferCharacteristics::BT_2100_HLG) { ++ GST_WARNING("VPConfigurationTransferCharacteristics::BT_2100_HLG not supported"); + GST_VIDEO_INFO_COLORIMETRY(&info).transfer = GST_VIDEO_TRANSFER_UNKNOWN; ++ } auto matrix = parameters->matrixCoefficients; if (matrix == VPConfigurationMatrixCoefficients::Identity) -@@ -421,7 +421,7 @@ static std::pair, GRefPtr> av1CapsFromCodecString(cons +@@ -422,7 +427,8 @@ static std::pair, GRefPtr> av1CapsFromCodecString(cons GST_VIDEO_INFO_COLORIMETRY(&info).transfer = GST_VIDEO_TRANSFER_GAMMA28; break; case AV1ConfigurationTransferCharacteristics::BT_601_7: - GST_VIDEO_INFO_COLORIMETRY(&info).transfer = GST_VIDEO_TRANSFER_BT601; ++ GST_WARNING("AV1ConfigurationTransferCharacteristics::BT_601_7 not supported"); + GST_VIDEO_INFO_COLORIMETRY(&info).transfer = GST_VIDEO_TRANSFER_UNKNOWN; break; case AV1ConfigurationTransferCharacteristics::SMPTE_ST_240: GST_VIDEO_INFO_COLORIMETRY(&info).transfer = GST_VIDEO_TRANSFER_SMPTE240M; -@@ -445,20 +445,20 @@ static std::pair, GRefPtr> av1CapsFromCodecString(cons +@@ -446,20 +452,23 @@ static std::pair, GRefPtr> av1CapsFromCodecString(cons GST_VIDEO_INFO_COLORIMETRY(&info).transfer = GST_VIDEO_TRANSFER_UNKNOWN; break; case AV1ConfigurationTransferCharacteristics::BT_2020_10bit: - GST_VIDEO_INFO_COLORIMETRY(&info).transfer = GST_VIDEO_TRANSFER_BT2020_10; ++ GST_WARNING("AV1ConfigurationTransferCharacteristics::BT_2020_10bit not supported"); + GST_VIDEO_INFO_COLORIMETRY(&info).transfer = GST_VIDEO_TRANSFER_UNKNOWN; break; case AV1ConfigurationTransferCharacteristics::BT_2020_12bit: @@ -386,6 +380,7 @@ index c701a84d2316..ec4c4b24347c 100644 break; case AV1ConfigurationTransferCharacteristics::SMPTE_ST_2084: - GST_VIDEO_INFO_COLORIMETRY(&info).transfer = GST_VIDEO_TRANSFER_SMPTE2084; ++ GST_WARNING("AV1ConfigurationTransferCharacteristics::SMPTE_ST_2084 not supported"); + GST_VIDEO_INFO_COLORIMETRY(&info).transfer = GST_VIDEO_TRANSFER_UNKNOWN; break; case AV1ConfigurationTransferCharacteristics::SMPTE_ST_428_1: @@ -394,42 +389,44 @@ index c701a84d2316..ec4c4b24347c 100644 break; case AV1ConfigurationTransferCharacteristics::BT_2100_HLG: - GST_VIDEO_INFO_COLORIMETRY(&info).transfer = GST_VIDEO_TRANSFER_ARIB_STD_B67; ++ GST_WARNING("AV1ConfigurationTransferCharacteristics::BT_2100_HLG not supported"); + GST_VIDEO_INFO_COLORIMETRY(&info).transfer = GST_VIDEO_TRANSFER_UNKNOWN; break; }; diff --git a/Source/WebCore/platform/gstreamer/VideoEncoderPrivateGStreamer.cpp b/Source/WebCore/platform/gstreamer/VideoEncoderPrivateGStreamer.cpp -index 655115564aa2..82204d5ff6d4 100644 +index d21b24cfe1ed..aa7492b14dd7 100644 --- a/Source/WebCore/platform/gstreamer/VideoEncoderPrivateGStreamer.cpp +++ b/Source/WebCore/platform/gstreamer/VideoEncoderPrivateGStreamer.cpp -@@ -754,7 +754,9 @@ static void webkit_video_encoder_class_init(WebKitVideoEncoderClass* klass) - gst_util_set_object_arg(G_OBJECT(encoder), "end-usage", "cq"); - break; - }; -- }, [](GstElement* encoder, const WebKitVideoEncoderBitRateAllocation& bitRateAllocation) { -+ } -+#if 0 -+ , [](GstElement* encoder, const WebKitVideoEncoderBitRateAllocation& bitRateAllocation) { - // Allow usage of deprecated GValueArray API. - ALLOW_DEPRECATED_DECLARATIONS_BEGIN; - GUniquePtr bitrates(g_value_array_new(3)); -@@ -887,7 +889,9 @@ static void webkit_video_encoder_class_init(WebKitVideoEncoderClass* klass) - } +@@ -898,22 +898,6 @@ static void webkit_video_encoder_class_init(WebKitVideoEncoderClass* klass) + "temporal-scalability-rate-decimator", decimators.get(), + "temporal-scalability-target-bitrate", bitrates.get(), nullptr); +- if (layerFlags) { +- GValue layerSyncFlagsValue G_VALUE_INIT; +- +- g_value_init(&boolValue, G_TYPE_BOOLEAN); +- gst_value_array_init(&layerSyncFlagsValue, layerSyncFlags.size()); +- for (auto& flag : layerSyncFlags) { +- g_value_set_boolean(&boolValue, flag); +- gst_value_array_append_value(&layerSyncFlagsValue, &boolValue); +- } +- +- g_object_set_property(G_OBJECT(encoder), "temporal-scalability-layer-sync-flags", &layerSyncFlagsValue); +- g_value_unset(&layerSyncFlagsValue); +- g_value_unset(&boolValue); +- gst_util_set_object_arg(G_OBJECT(encoder), "temporal-scalability-layer-flags", layerFlags.characters()); +- } +- ALLOW_DEPRECATED_DECLARATIONS_END; -- }); -+ } -+#endif -+ ); + }); - Encoders::registerEncoder(Vp9, "vp9enc"_s, nullptr, "video/x-vp9"_s, nullptr, - [&](WebKitVideoEncoder* self) { diff --git a/Source/cmake/GStreamerChecks.cmake b/Source/cmake/GStreamerChecks.cmake -index 63f183fa6e30..f26a924e9d02 100644 +index 27816a97ff26..94863212aee9 100644 --- a/Source/cmake/GStreamerChecks.cmake +++ b/Source/cmake/GStreamerChecks.cmake @@ -1,7 +1,7 @@ - if (ENABLE_VIDEO OR ENABLE_WEB_AUDIO) + if (ENABLE_VIDEO OR ENABLE_WEB_AUDIO OR ENABLE_WEB_CODECS) SET_AND_EXPOSE_TO_BUILD(USE_GSTREAMER TRUE) if (USE_GSTREAMER_FULL) - find_package(GStreamer 1.18.4 REQUIRED COMPONENTS full) @@ -437,7 +434,7 @@ index 63f183fa6e30..f26a924e9d02 100644 if (NOT PC_GSTREAMER_FULL_FOUND) message(FATAL_ERROR "GStreamer static library libgstreamer-full-1.0 not found") else () -@@ -25,7 +25,7 @@ if (ENABLE_VIDEO OR ENABLE_WEB_AUDIO) +@@ -25,7 +25,7 @@ if (ENABLE_VIDEO OR ENABLE_WEB_AUDIO OR ENABLE_WEB_CODECS) list(APPEND GSTREAMER_COMPONENTS webrtc) endif () @@ -446,3 +443,6 @@ index 63f183fa6e30..f26a924e9d02 100644 if (ENABLE_WEB_AUDIO) if (NOT PC_GSTREAMER_AUDIO_FOUND OR NOT PC_GSTREAMER_FFT_FOUND) +-- +2.49.0 + diff --git a/SOURCES/harfbuzz-1.7.5.patch b/SOURCES/harfbuzz-1.7.5.patch index e6528b1..f38e040 100644 --- a/SOURCES/harfbuzz-1.7.5.patch +++ b/SOURCES/harfbuzz-1.7.5.patch @@ -24,3 +24,25 @@ index 8bc21b21976c..68654f602c92 100644 if (int axisCount = typeface.getVariationDesignPosition(nullptr, 0)) { Vector axisValues(axisCount); +diff --git a/Source/ThirdParty/skia/modules/skshaper/src/SkShaper_harfbuzz.cpp b/Source/ThirdParty/skia/modules/skshaper/src/SkShaper_harfbuzz.cpp +index 065385774422..498994ff7aa7 100644 +--- a/Source/ThirdParty/skia/modules/skshaper/src/SkShaper_harfbuzz.cpp ++++ b/Source/ThirdParty/skia/modules/skshaper/src/SkShaper_harfbuzz.cpp +@@ -277,13 +277,10 @@ HBFace create_hb_face(const SkTypeface& typeface) { + // hb_face_create always succeeds. Check that the format is minimally recognized first. + // hb_face_create_for_tables may still create a working hb_face. + // See https://github.com/harfbuzz/harfbuzz/issues/248 . +- unsigned int num_hb_faces = hb_face_count(blob.get()); +- if (0 < num_hb_faces && (unsigned)index < num_hb_faces) { +- face.reset(hb_face_create(blob.get(), (unsigned)index)); +- // Check the number of glyphs as a basic sanitization step. +- if (face && hb_face_get_glyph_count(face.get()) == 0) { +- face.reset(); +- } ++ face.reset(hb_face_create(blob.get(), (unsigned)index)); ++ // Check the number of glyphs as a basic sanitization step. ++ if (face && hb_face_get_glyph_count(face.get()) == 0) { ++ face.reset(); + } + } + if (!face) { diff --git a/SOURCES/icu60.patch b/SOURCES/icu60.patch index f851d5d..15ddfc9 100644 --- a/SOURCES/icu60.patch +++ b/SOURCES/icu60.patch @@ -1,3 +1,1586 @@ +From 5f60bd9605e60231e6d430e7559a2af9d6aa4c33 Mon Sep 17 00:00:00 2001 +From: Michael Catanzaro +Date: Thu, 27 Mar 2025 15:56:41 -0500 +Subject: [PATCH 1/5] Revert "[CMake] Update minimum ICU version to 70.1" + +This reverts commit 95d71be25d5b838b1171e6b9b2cd526190118fba. +--- + Source/cmake/OptionsGTK.cmake | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/Source/cmake/OptionsGTK.cmake b/Source/cmake/OptionsGTK.cmake +index 0a30e0c4c7c1..814009146300 100644 +--- a/Source/cmake/OptionsGTK.cmake ++++ b/Source/cmake/OptionsGTK.cmake +@@ -10,11 +10,11 @@ set(USER_AGENT_BRANDING "" CACHE STRING "Branding to add to user agent string") + find_package(Cairo 1.14.0 REQUIRED) + find_package(LibGcrypt 1.7.0 REQUIRED) + find_package(Libtasn1 REQUIRED) +-find_package(HarfBuzz 2.7.4 REQUIRED COMPONENTS ICU) +-find_package(ICU 70.1 REQUIRED COMPONENTS data i18n uc) ++find_package(HarfBuzz 1.4.2 REQUIRED COMPONENTS ICU) ++find_package(ICU 61.2 REQUIRED COMPONENTS data i18n uc) + find_package(JPEG REQUIRED) + find_package(Epoxy 1.5.4 REQUIRED) +-find_package(LibXml2 2.9.13 REQUIRED) ++find_package(LibXml2 2.8.0 REQUIRED) + find_package(PNG REQUIRED) + find_package(SQLite3 REQUIRED) + find_package(Threads REQUIRED) +-- +2.49.0 + + +From 3e1a6690440b9cb3a11a4cadc69a985845a4a5bd Mon Sep 17 00:00:00 2001 +From: Michael Catanzaro +Date: Fri, 28 Mar 2025 14:45:03 -0500 +Subject: [PATCH 2/5] Revert "[JSC] Remove unnecessary ICU version checks" + +This reverts commit af62f09a1fad0b72293a7f0d082704d92116cb9a. +--- + .../runtime/IntlDurationFormat.cpp | 2 +- + .../runtime/IntlNumberFormat.cpp | 12 ++-- + .../runtime/IntlNumberFormatInlines.h | 57 ++++++++++++------- + 3 files changed, 47 insertions(+), 24 deletions(-) + +diff --git a/Source/JavaScriptCore/runtime/IntlDurationFormat.cpp b/Source/JavaScriptCore/runtime/IntlDurationFormat.cpp +index 61264bfe23d9..a1c628082dd5 100644 +--- a/Source/JavaScriptCore/runtime/IntlDurationFormat.cpp ++++ b/Source/JavaScriptCore/runtime/IntlDurationFormat.cpp +@@ -457,7 +457,7 @@ static Vector collectElements(JSGlobalObject* globalObject, const IntlD + + // 3.k. If style is "2-digit", then + // i. Perform ! CreateDataPropertyOrThrow(nfOpts, "minimumIntegerDigits", 2F). +- skeletonBuilder.append(" integer-width/*"_s); ++ skeletonBuilder.append(" integer-width/"_s, WTF::ICU::majorVersion() >= 67 ? '*' : '+'); // Prior to ICU 67, use the symbol + instead of *. + if (style == IntlDurationFormat::UnitStyle::TwoDigit) + skeletonBuilder.append("00"_s); + else +diff --git a/Source/JavaScriptCore/runtime/IntlNumberFormat.cpp b/Source/JavaScriptCore/runtime/IntlNumberFormat.cpp +index 67708f1d8d33..0938d2d5b4a5 100644 +--- a/Source/JavaScriptCore/runtime/IntlNumberFormat.cpp ++++ b/Source/JavaScriptCore/runtime/IntlNumberFormat.cpp +@@ -517,10 +517,14 @@ void IntlNumberFormat::initializeNumberFormat(JSGlobalObject* globalObject, JSVa + skeletonBuilder.append(" sign-except-zero"_s); + break; + case SignDisplay::Negative: +- if (useAccounting) +- skeletonBuilder.append(" sign-accounting-negative"_s); +- else +- skeletonBuilder.append(" sign-negative"_s); ++ // Only ICU69~ supports negative sign display. Ignore this option if linked ICU does not support it. ++ // https://github.com/unicode-org/icu/commit/1aa0dad8e06ecc99bff442dd37f6daa2d39d9a5a ++ if (WTF::ICU::majorVersion() >= 69) { ++ if (useAccounting) ++ skeletonBuilder.append(" sign-accounting-negative"_s); ++ else ++ skeletonBuilder.append(" sign-negative"_s); ++ } + break; + } + +diff --git a/Source/JavaScriptCore/runtime/IntlNumberFormatInlines.h b/Source/JavaScriptCore/runtime/IntlNumberFormatInlines.h +index ddccce2fd112..980da4e3c74a 100644 +--- a/Source/JavaScriptCore/runtime/IntlNumberFormatInlines.h ++++ b/Source/JavaScriptCore/runtime/IntlNumberFormatInlines.h +@@ -199,12 +199,24 @@ void appendNumberFormatDigitOptionsToSkeleton(IntlType* intlInstance, StringBuil + case RoundingMode::Trunc: + skeletonBuilder.append(" rounding-mode-down"_s); + break; +- case RoundingMode::HalfCeil: +- skeletonBuilder.append(" rounding-mode-half-ceiling"_s); ++ case RoundingMode::HalfCeil: { ++ // Only ICU69~ supports half-ceiling. Ignore this option if linked ICU does not support it. ++ // https://github.com/unicode-org/icu/commit/e8dfea9bb6bb27596731173b352759e44ad06b21 ++ if (WTF::ICU::majorVersion() >= 69) ++ skeletonBuilder.append(" rounding-mode-half-ceiling"_s); ++ else ++ skeletonBuilder.append(" rounding-mode-half-up"_s); // Default option. + break; +- case RoundingMode::HalfFloor: +- skeletonBuilder.append(" rounding-mode-half-floor"_s); ++ } ++ case RoundingMode::HalfFloor: { ++ // Only ICU69~ supports half-flooring. Ignore this option if linked ICU does not support it. ++ // https://github.com/unicode-org/icu/commit/e8dfea9bb6bb27596731173b352759e44ad06b21 ++ if (WTF::ICU::majorVersion() >= 69) ++ skeletonBuilder.append(" rounding-mode-half-floor"_s); ++ else ++ skeletonBuilder.append(" rounding-mode-half-up"_s); // Default option. + break; ++ } + case RoundingMode::HalfExpand: + skeletonBuilder.append(" rounding-mode-half-up"_s); + break; +@@ -217,7 +229,7 @@ void appendNumberFormatDigitOptionsToSkeleton(IntlType* intlInstance, StringBuil + } + + // https://github.com/unicode-org/icu/blob/master/docs/userguide/format_parse/numbers/skeletons.md#integer-width +- skeletonBuilder.append(" integer-width/*"_s); ++ skeletonBuilder.append(" integer-width/"_s, WTF::ICU::majorVersion() >= 67 ? '*' : '+'); // Prior to ICU 67, use the symbol + instead of *. + for (unsigned i = 0; i < intlInstance->m_minimumIntegerDigits; ++i) + skeletonBuilder.append('0'); + +@@ -255,19 +267,23 @@ void appendNumberFormatDigitOptionsToSkeleton(IntlType* intlInstance, StringBuil + } + case IntlRoundingType::MorePrecision: + case IntlRoundingType::LessPrecision: +- // https://github.com/unicode-org/icu/commit/d7db6c1f8655bb53153695b09a50029fd04a8364 +- // https://github.com/unicode-org/icu/blob/main/docs/userguide/format_parse/numbers/skeletons.md#precision +- skeletonBuilder.append(" ."_s); +- for (unsigned i = 0; i < intlInstance->m_minimumFractionDigits; ++i) +- skeletonBuilder.append('0'); +- for (unsigned i = 0; i < intlInstance->m_maximumFractionDigits - intlInstance->m_minimumFractionDigits; ++i) +- skeletonBuilder.append('#'); +- skeletonBuilder.append('/'); +- for (unsigned i = 0; i < intlInstance->m_minimumSignificantDigits; ++i) +- skeletonBuilder.append('@'); +- for (unsigned i = 0; i < intlInstance->m_maximumSignificantDigits - intlInstance->m_minimumSignificantDigits; ++i) +- skeletonBuilder.append('#'); +- skeletonBuilder.append(intlInstance->m_roundingType == IntlRoundingType::MorePrecision ? 'r' : 's'); ++ // Before Intl.NumberFormat v3, it was CompactRounding mode, where we do not configure anything. ++ // So, if linked ICU is ~68, we do nothing. ++ if (WTF::ICU::majorVersion() >= 69) { ++ // https://github.com/unicode-org/icu/commit/d7db6c1f8655bb53153695b09a50029fd04a8364 ++ // https://github.com/unicode-org/icu/blob/main/docs/userguide/format_parse/numbers/skeletons.md#precision ++ skeletonBuilder.append(" ."_s); ++ for (unsigned i = 0; i < intlInstance->m_minimumFractionDigits; ++i) ++ skeletonBuilder.append('0'); ++ for (unsigned i = 0; i < intlInstance->m_maximumFractionDigits - intlInstance->m_minimumFractionDigits; ++i) ++ skeletonBuilder.append('#'); ++ skeletonBuilder.append('/'); ++ for (unsigned i = 0; i < intlInstance->m_minimumSignificantDigits; ++i) ++ skeletonBuilder.append('@'); ++ for (unsigned i = 0; i < intlInstance->m_maximumSignificantDigits - intlInstance->m_minimumSignificantDigits; ++i) ++ skeletonBuilder.append('#'); ++ skeletonBuilder.append(intlInstance->m_roundingType == IntlRoundingType::MorePrecision ? 'r' : 's'); ++ } + break; + } + } +@@ -278,7 +294,10 @@ void appendNumberFormatDigitOptionsToSkeleton(IntlType* intlInstance, StringBuil + case IntlTrailingZeroDisplay::Auto: + break; + case IntlTrailingZeroDisplay::StripIfInteger: +- skeletonBuilder.append("/w"_s); ++ // Only ICU69~ supports trailing zero display. Ignore this option if linked ICU does not support it. ++ // https://github.com/unicode-org/icu/commit/b79c299f90d4023ac237db3d0335d568bf21cd36 ++ if (WTF::ICU::majorVersion() >= 69) ++ skeletonBuilder.append("/w"_s); + break; + } + } +-- +2.49.0 + + +From cf69f3f40771d8724228c3af3a2c96dc04e38f85 Mon Sep 17 00:00:00 2001 +From: Michael Catanzaro +Date: Fri, 28 Mar 2025 15:01:00 -0500 +Subject: [PATCH 3/5] Revert "[JSC] TimeZone Cache should be per-process level" + +This reverts commit c779aa30eced87609c7c808d672a8f23c5c4821d. +--- + Source/JavaScriptCore/runtime/JSDateMath.cpp | 59 +++++++------------- + 1 file changed, 20 insertions(+), 39 deletions(-) + +diff --git a/Source/JavaScriptCore/runtime/JSDateMath.cpp b/Source/JavaScriptCore/runtime/JSDateMath.cpp +index c6a194568dab..756cbccb1668 100644 +--- a/Source/JavaScriptCore/runtime/JSDateMath.cpp ++++ b/Source/JavaScriptCore/runtime/JSDateMath.cpp +@@ -453,12 +453,9 @@ String DateCache::timeZoneDisplayName(bool isDST) + return m_timeZoneStandardDisplayNameCache; + } + +-static Lock timeZoneCacheLock; +- + #if PLATFORM(COCOA) + static void timeZoneChangeNotification(CFNotificationCenterRef, void*, CFStringRef, const void*, CFDictionaryRef) + { +- Locker locker { timeZoneCacheLock }; + ASSERT(isMainThread()); + ++lastTimeZoneID; + } +@@ -475,40 +472,6 @@ DateCache::DateCache() + #endif + } + +-static std::tuple> retrieveTimeZoneInformation() +-{ +- Locker locker { timeZoneCacheLock }; +- static NeverDestroyed, uint64_t>> globalCache; +- +- bool isCacheStale = true; +- uint64_t currentID = 0; +-#if PLATFORM(COCOA) +- currentID = lastTimeZoneID.load(); +- isCacheStale = std::get<2>(globalCache.get()) != currentID; +-#endif +- if (isCacheStale) { +- Vector timeZoneID; +- getTimeZoneOverride(timeZoneID); +- String canonical; +- UErrorCode status = U_ZERO_ERROR; +- if (timeZoneID.isEmpty()) { +- status = callBufferProducingFunction(ucal_getHostTimeZone, timeZoneID); +- ASSERT_UNUSED(status, U_SUCCESS(status)); +- } +- if (U_SUCCESS(status)) { +- Vector canonicalBuffer; +- auto status = callBufferProducingFunction(ucal_getCanonicalTimeZoneID, timeZoneID.data(), timeZoneID.size(), canonicalBuffer, nullptr); +- if (U_SUCCESS(status)) +- canonical = String(canonicalBuffer); +- } +- if (canonical.isNull() || isUTCEquivalent(canonical)) +- canonical = "UTC"_s; +- +- globalCache.get() = std::tuple { canonical.isolatedCopy(), WTFMove(timeZoneID), currentID }; +- } +- return std::tuple { std::get<0>(globalCache.get()).isolatedCopy(), std::get<1>(globalCache.get()) }; +-} +- + DateCache::~DateCache() = default; + + Ref DateCache::cachedDateInstanceData(double millisecondsFromEpoch) +@@ -519,10 +482,28 @@ Ref DateCache::cachedDateInstanceData(double millisecondsFromE + void DateCache::timeZoneCacheSlow() + { + ASSERT(!m_timeZoneCache); +- auto [canonical, timeZoneID] = retrieveTimeZoneInformation(); ++ ++ Vector timeZoneID; ++ getTimeZoneOverride(timeZoneID); + auto* cache = new OpaqueICUTimeZone; +- cache->m_canonicalTimeZoneID = WTFMove(canonical); ++ ++ String canonical; + UErrorCode status = U_ZERO_ERROR; ++ if (timeZoneID.isEmpty()) { ++ status = callBufferProducingFunction(ucal_getHostTimeZone, timeZoneID); ++ ASSERT_UNUSED(status, U_SUCCESS(status)); ++ } ++ if (U_SUCCESS(status)) { ++ Vector canonicalBuffer; ++ auto status = callBufferProducingFunction(ucal_getCanonicalTimeZoneID, timeZoneID.data(), timeZoneID.size(), canonicalBuffer, nullptr); ++ if (U_SUCCESS(status)) ++ canonical = String(canonicalBuffer); ++ } ++ if (canonical.isNull() || isUTCEquivalent(canonical)) ++ canonical = "UTC"_s; ++ cache->m_canonicalTimeZoneID = WTFMove(canonical); ++ ++ status = U_ZERO_ERROR; + cache->m_calendar = std::unique_ptr>(ucal_open(timeZoneID.data(), timeZoneID.size(), "", UCAL_DEFAULT, &status)); + ASSERT_UNUSED(status, U_SUCCESS(status)); + ucal_setGregorianChange(cache->m_calendar.get(), minECMAScriptTime, &status); // Ignore "unsupported" error. +-- +2.49.0 + + +From 43c41bebf484bb3e08adf19cfadff01d820f6872 Mon Sep 17 00:00:00 2001 +From: Michael Catanzaro +Date: Fri, 28 Mar 2025 15:01:11 -0500 +Subject: [PATCH 4/5] Revert "[JSC] Rebaseline Intl implementation based on + lowest dependency ICU 70" + +This reverts commit 31a358087be7e5e70c7a03bdfcf89de35628a2a2. +--- + .../runtime/IntlDateTimeFormat.cpp | 27 ++++ + .../runtime/IntlDateTimeFormat.h | 6 + + .../runtime/IntlDateTimeFormatPrototype.cpp | 6 +- + .../runtime/IntlDurationFormat.cpp | 27 ++++ + .../runtime/IntlDurationFormat.h | 2 + + .../JavaScriptCore/runtime/IntlListFormat.cpp | 24 +++ + .../JavaScriptCore/runtime/IntlListFormat.h | 6 + + .../runtime/IntlNumberFormat.cpp | 150 ++++++++++++++++++ + .../JavaScriptCore/runtime/IntlNumberFormat.h | 35 ++++ + .../runtime/IntlNumberFormatPrototype.cpp | 35 +++- + Source/JavaScriptCore/runtime/IntlObject.cpp | 9 +- + .../runtime/IntlPluralRules.cpp | 41 +++++ + .../JavaScriptCore/runtime/IntlPluralRules.h | 12 +- + .../runtime/IntlPluralRulesPrototype.cpp | 8 +- + .../JavaScriptCore/runtime/IntlWorkaround.cpp | 12 +- + Source/JavaScriptCore/runtime/JSDateMath.cpp | 95 ++++++++++- + 16 files changed, 479 insertions(+), 16 deletions(-) + +diff --git a/Source/JavaScriptCore/runtime/IntlDateTimeFormat.cpp b/Source/JavaScriptCore/runtime/IntlDateTimeFormat.cpp +index e3e7671fcf45..2f2371649667 100644 +--- a/Source/JavaScriptCore/runtime/IntlDateTimeFormat.cpp ++++ b/Source/JavaScriptCore/runtime/IntlDateTimeFormat.cpp +@@ -42,12 +42,16 @@ + #include + #include + ++#if HAVE(ICU_U_DATE_INTERVAL_FORMAT_FORMAT_RANGE_TO_PARTS) + #include + #ifdef U_HIDE_DRAFT_API + #undef U_HIDE_DRAFT_API + #endif ++#endif // HAVE(ICU_U_DATE_INTERVAL_FORMAT_FORMAT_RANGE_TO_PARTS) + #include ++#if HAVE(ICU_U_DATE_INTERVAL_FORMAT_FORMAT_RANGE_TO_PARTS) + #define U_HIDE_DRAFT_API 1 ++#endif // HAVE(ICU_U_DATE_INTERVAL_FORMAT_FORMAT_RANGE_TO_PARTS) + + WTF_ALLOW_UNSAFE_BUFFER_USAGE_BEGIN + +@@ -1446,6 +1450,8 @@ UDateIntervalFormat* IntlDateTimeFormat::createDateIntervalFormatIfNecessary(JSG + return m_dateIntervalFormat.get(); + } + ++#if HAVE(ICU_U_DATE_INTERVAL_FORMAT_FORMAT_RANGE_TO_PARTS) ++ + static std::unique_ptr> formattedValueFromDateRange(UDateIntervalFormat& dateIntervalFormat, UDateFormat& dateFormat, double startDate, double endDate, UErrorCode& status) + { + auto result = std::unique_ptr>(udtitvfmt_openResult(&status)); +@@ -1524,6 +1530,8 @@ static bool dateFieldsPracticallyEqual(const UFormattedValue* formattedValue, UE + return !hasSpan; + } + ++#endif // HAVE(ICU_U_DATE_INTERVAL_FORMAT_FORMAT_RANGE_TO_PARTS) ++ + JSValue IntlDateTimeFormat::formatRange(JSGlobalObject* globalObject, double startDate, double endDate) + { + ASSERT(m_dateFormat); +@@ -1542,6 +1550,7 @@ JSValue IntlDateTimeFormat::formatRange(JSGlobalObject* globalObject, double sta + auto* dateIntervalFormat = createDateIntervalFormatIfNecessary(globalObject); + RETURN_IF_EXCEPTION(scope, { }); + ++#if HAVE(ICU_U_DATE_INTERVAL_FORMAT_FORMAT_RANGE_TO_PARTS) + UErrorCode status = U_ZERO_ERROR; + auto result = formattedValueFromDateRange(*dateIntervalFormat, *m_dateFormat, startDate, endDate, status); + if (U_FAILURE(status)) { +@@ -1579,6 +1588,17 @@ JSValue IntlDateTimeFormat::formatRange(JSGlobalObject* globalObject, double sta + replaceNarrowNoBreakSpaceOrThinSpaceWithNormalSpace(buffer); + + return jsString(vm, String(WTFMove(buffer))); ++#else ++ Vector buffer; ++ auto status = callBufferProducingFunction(udtitvfmt_format, dateIntervalFormat, startDate, endDate, buffer, nullptr); ++ if (U_FAILURE(status)) { ++ throwTypeError(globalObject, scope, "Failed to format date interval"_s); ++ return { }; ++ } ++ replaceNarrowNoBreakSpaceOrThinSpaceWithNormalSpace(buffer); ++ ++ return jsString(vm, String(WTFMove(buffer))); ++#endif + } + + JSValue IntlDateTimeFormat::formatRangeToParts(JSGlobalObject* globalObject, double startDate, double endDate) +@@ -1588,6 +1608,7 @@ JSValue IntlDateTimeFormat::formatRangeToParts(JSGlobalObject* globalObject, dou + VM& vm = globalObject->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + ++#if HAVE(ICU_U_DATE_INTERVAL_FORMAT_FORMAT_RANGE_TO_PARTS) + // http://tc39.es/proposal-intl-DateTimeFormat-formatRange/#sec-partitiondatetimerangepattern + startDate = timeClip(startDate); + endDate = timeClip(endDate); +@@ -1791,6 +1812,12 @@ JSValue IntlDateTimeFormat::formatRangeToParts(JSGlobalObject* globalObject, dou + } + + return parts; ++#else ++ UNUSED_PARAM(startDate); ++ UNUSED_PARAM(endDate); ++ throwTypeError(globalObject, scope, "Failed to format date interval"_s); ++ return { }; ++#endif + } + + +diff --git a/Source/JavaScriptCore/runtime/IntlDateTimeFormat.h b/Source/JavaScriptCore/runtime/IntlDateTimeFormat.h +index 121417aab9e1..14c476c72f69 100644 +--- a/Source/JavaScriptCore/runtime/IntlDateTimeFormat.h ++++ b/Source/JavaScriptCore/runtime/IntlDateTimeFormat.h +@@ -32,6 +32,12 @@ + + struct UDateIntervalFormat; + ++#if !defined(HAVE_ICU_U_DATE_INTERVAL_FORMAT_FORMAT_RANGE_TO_PARTS) ++#if U_ICU_VERSION_MAJOR_NUM >= 64 ++#define HAVE_ICU_U_DATE_INTERVAL_FORMAT_FORMAT_RANGE_TO_PARTS 1 ++#endif ++#endif ++ + namespace JSC { + + enum class RelevantExtensionKey : uint8_t; +diff --git a/Source/JavaScriptCore/runtime/IntlDateTimeFormatPrototype.cpp b/Source/JavaScriptCore/runtime/IntlDateTimeFormatPrototype.cpp +index b7ef4bab865f..694ab7afea0c 100644 +--- a/Source/JavaScriptCore/runtime/IntlDateTimeFormatPrototype.cpp ++++ b/Source/JavaScriptCore/runtime/IntlDateTimeFormatPrototype.cpp +@@ -56,7 +56,6 @@ const ClassInfo IntlDateTimeFormatPrototype::s_info = { "Intl.DateTimeFormat"_s, + @begin dateTimeFormatPrototypeTable + format intlDateTimeFormatPrototypeGetterFormat DontEnum|ReadOnly|CustomAccessor + formatRange intlDateTimeFormatPrototypeFuncFormatRange DontEnum|Function 2 +- formatRangeToParts intlDateTimeFormatPrototypeFuncFormatRangeToParts DontEnum|Function 2 + formatToParts intlDateTimeFormatPrototypeFuncFormatToParts DontEnum|Function 1 + resolvedOptions intlDateTimeFormatPrototypeFuncResolvedOptions DontEnum|Function 0 + @end +@@ -83,7 +82,12 @@ void IntlDateTimeFormatPrototype::finishCreation(VM& vm, JSGlobalObject* globalO + { + Base::finishCreation(vm); + ASSERT(inherits(info())); ++#if HAVE(ICU_U_DATE_INTERVAL_FORMAT_FORMAT_RANGE_TO_PARTS) ++ JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("formatRangeToParts"_s, intlDateTimeFormatPrototypeFuncFormatRangeToParts, static_cast(PropertyAttribute::DontEnum), 2, ImplementationVisibility::Public); ++#else + UNUSED_PARAM(globalObject); ++ UNUSED_PARAM(&intlDateTimeFormatPrototypeFuncFormatRangeToParts); ++#endif + JSC_TO_STRING_TAG_WITHOUT_TRANSITION(); + } + +diff --git a/Source/JavaScriptCore/runtime/IntlDurationFormat.cpp b/Source/JavaScriptCore/runtime/IntlDurationFormat.cpp +index a1c628082dd5..78e9106ee0a4 100644 +--- a/Source/JavaScriptCore/runtime/IntlDurationFormat.cpp ++++ b/Source/JavaScriptCore/runtime/IntlDurationFormat.cpp +@@ -36,14 +36,21 @@ + // While UListFormatter APIs are draft in ICU 67, they are stable in ICU 68 with the same function signatures. + // So we can assume that these signatures of draft APIs are stable. + // If UListFormatter is available, UNumberFormatter is also available. ++#if HAVE(ICU_U_LIST_FORMATTER) + #ifdef U_HIDE_DRAFT_API + #undef U_HIDE_DRAFT_API + #endif ++#endif + #include + #include + #include ++#if HAVE(ICU_U_LIST_FORMATTER) + #define U_HIDE_DRAFT_API 1 ++#endif ++ ++#if HAVE(ICU_U_LIST_FORMATTER) + #include ++#endif + + WTF_ALLOW_UNSAFE_BUFFER_USAGE_BEGIN + +@@ -240,6 +247,7 @@ void IntlDurationFormat::initializeDurationFormat(JSGlobalObject* globalObject, + m_fractionalDigits = intlNumberOption(globalObject, options, vm.propertyNames->fractionalDigits, 0, 9, fractionalDigitsUndefinedValue); + RETURN_IF_EXCEPTION(scope, void()); + ++#if HAVE(ICU_U_LIST_FORMATTER) + { + auto toUListFormatterWidth = [](Style style) { + // 6. Let listStyle be durationFormat.[[Style]]. +@@ -266,8 +274,15 @@ void IntlDurationFormat::initializeDurationFormat(JSGlobalObject* globalObject, + return; + } + } ++#else ++ UNUSED_PARAM(IntlDurationFormatInternal::verbose); ++ throwTypeError(globalObject, scope, "Failed to initialize Intl.DurationFormat since this feature is not supported in the linked ICU version"_s); ++ return; ++#endif + } + ++#if HAVE(ICU_U_LIST_FORMATTER) ++ + static String retrieveSeparator(const CString& locale, const String& numberingSystem) + { + ASCIILiteral fallbackTimeSeparator = ":"_s; +@@ -635,12 +650,15 @@ static Vector collectElements(JSGlobalObject* globalObject, const IntlD + return elements; + } + ++#endif ++ + // https://tc39.es/proposal-intl-duration-format/#sec-Intl.DurationFormat.prototype.format + JSValue IntlDurationFormat::format(JSGlobalObject* globalObject, ISO8601::Duration duration) const + { + VM& vm = globalObject->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + ++#if HAVE(ICU_U_LIST_FORMATTER) + auto elements = collectElements(globalObject, this, WTFMove(duration)); + RETURN_IF_EXCEPTION(scope, { }); + +@@ -676,6 +694,10 @@ JSValue IntlDurationFormat::format(JSGlobalObject* globalObject, ISO8601::Durati + return throwTypeError(globalObject, scope, "failed to format list of strings"_s); + + return jsString(vm, String(WTFMove(result))); ++#else ++ UNUSED_PARAM(duration); ++ return throwTypeError(globalObject, scope, "failed to format list of strings"_s); ++#endif + } + + // https://tc39.es/proposal-intl-duration-format/#sec-Intl.DurationFormat.prototype.formatToParts +@@ -684,6 +706,7 @@ JSValue IntlDurationFormat::formatToParts(JSGlobalObject* globalObject, ISO8601: + VM& vm = globalObject->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + ++#if HAVE(ICU_U_LIST_FORMATTER) + auto elements = collectElements(globalObject, this, WTFMove(duration)); + RETURN_IF_EXCEPTION(scope, { }); + +@@ -836,6 +859,10 @@ JSValue IntlDurationFormat::formatToParts(JSGlobalObject* globalObject, ISO8601: + } + + return parts; ++#else ++ UNUSED_PARAM(duration); ++ return throwTypeError(globalObject, scope, "failed to format list of strings"_s); ++#endif + } + + // https://tc39.es/proposal-intl-duration-format/#sec-Intl.DurationFormat.prototype.resolvedOptions +diff --git a/Source/JavaScriptCore/runtime/IntlDurationFormat.h b/Source/JavaScriptCore/runtime/IntlDurationFormat.h +index 69e64f9c8332..b3f781a54ad4 100644 +--- a/Source/JavaScriptCore/runtime/IntlDurationFormat.h ++++ b/Source/JavaScriptCore/runtime/IntlDurationFormat.h +@@ -101,7 +101,9 @@ private: + static ASCIILiteral unitStyleString(UnitStyle); + static ASCIILiteral displayString(Display); + ++#if HAVE(ICU_U_LIST_FORMATTER) + std::unique_ptr m_listFormat; ++#endif + String m_locale; + String m_numberingSystem; + CString m_dataLocaleWithExtensions; +diff --git a/Source/JavaScriptCore/runtime/IntlListFormat.cpp b/Source/JavaScriptCore/runtime/IntlListFormat.cpp +index 8fb342027af5..c25cc5f9e90f 100644 +--- a/Source/JavaScriptCore/runtime/IntlListFormat.cpp ++++ b/Source/JavaScriptCore/runtime/IntlListFormat.cpp +@@ -33,12 +33,19 @@ + + // While UListFormatter APIs are draft in ICU 67, they are stable in ICU 68 with the same function signatures. + // So we can assume that these signatures of draft APIs are stable. ++#if HAVE(ICU_U_LIST_FORMATTER) + #ifdef U_HIDE_DRAFT_API + #undef U_HIDE_DRAFT_API + #endif ++#endif + #include ++#if HAVE(ICU_U_LIST_FORMATTER) + #define U_HIDE_DRAFT_API 1 ++#endif ++ ++#if HAVE(ICU_U_LIST_FORMATTER) + #include ++#endif + + WTF_ALLOW_UNSAFE_BUFFER_USAGE_BEGIN + +@@ -107,6 +114,7 @@ void IntlListFormat::initializeListFormat(JSGlobalObject* globalObject, JSValue + m_style = intlOption