diff --git a/LayoutTests/fast/mediastream/image-capture-get-photo-settings-expected.txt b/LayoutTests/fast/mediastream/image-capture-get-photo-settings-expected.txt new file mode 100644 index 000000000000..bd6bb23b02c1 --- /dev/null +++ b/LayoutTests/fast/mediastream/image-capture-get-photo-settings-expected.txt @@ -0,0 +1,5 @@ + + +PASS getPhotoSettings() on an 'ended' track should throw "InvalidStateError" +PASS Check getPhotoSettings() + diff --git a/LayoutTests/fast/mediastream/image-capture-get-photo-settings.html b/LayoutTests/fast/mediastream/image-capture-get-photo-settings.html new file mode 100644 index 000000000000..ebf1598b1322 --- /dev/null +++ b/LayoutTests/fast/mediastream/image-capture-get-photo-settings.html @@ -0,0 +1,48 @@ + + + + + ImageCapture getPhotoSettings + + + + + + + + diff --git a/LayoutTests/platform/ios-16/TestExpectations b/LayoutTests/platform/ios-16/TestExpectations index 6bcf7865ecd0..f5e9a784737e 100644 --- a/LayoutTests/platform/ios-16/TestExpectations +++ b/LayoutTests/platform/ios-16/TestExpectations @@ -20,3 +20,13 @@ accessibility/ios-simulator/inline-prediction-attributed-string.html [ Skip ] # Only supported with iOS 17 and later. media/media-webm-opus-variable-length.html [ Failure ] + +# webkit.org/b/262663 (REGRESSION(iOS17/Sonoma): 8 WebCryptoAPI tests are constantly crashing.) +imported/w3c/web-platform-tests/WebCryptoAPI/generateKey/failures_X25519.https.any.html [ Pass ] +imported/w3c/web-platform-tests/WebCryptoAPI/generateKey/failures_X25519.https.any.worker.html [ Pass ] +imported/w3c/web-platform-tests/WebCryptoAPI/generateKey/successes_X25519.https.any.html [ Pass ] +imported/w3c/web-platform-tests/WebCryptoAPI/generateKey/successes_X25519.https.any.worker.html [ Pass ] +imported/w3c/web-platform-tests/WebCryptoAPI/import_export/okp_importKey.https.any.html [ Pass ] +imported/w3c/web-platform-tests/WebCryptoAPI/import_export/okp_importKey.https.any.worker.html [ Pass ] +imported/w3c/web-platform-tests/WebCryptoAPI/import_export/okp_importKey_failures_X25519.https.any.html [ Pass ] +imported/w3c/web-platform-tests/WebCryptoAPI/import_export/okp_importKey_failures_X25519.https.any.worker.html [ Pass ] diff --git a/LayoutTests/platform/ios/TestExpectations b/LayoutTests/platform/ios/TestExpectations index 5e964725c8b1..cfbc4b25192e 100644 --- a/LayoutTests/platform/ios/TestExpectations +++ b/LayoutTests/platform/ios/TestExpectations @@ -4649,3 +4649,13 @@ imported/w3c/web-platform-tests/css/css-fonts/font-palette-modify.html [ ImageOn imported/w3c/web-platform-tests/css/css-fonts/font-palette-remove.html [ ImageOnlyFailure ] imported/w3c/web-platform-tests/css/css-fonts/palette-values-rule-add.html [ ImageOnlyFailure ] imported/w3c/web-platform-tests/css/css-fonts/palette-values-rule-delete.html [ ImageOnlyFailure ] + +# webkit.org/b/262663 (REGRESSION(iOS17/Sonoma): 8 WebCryptoAPI tests are constantly crashing.) +imported/w3c/web-platform-tests/WebCryptoAPI/generateKey/failures_X25519.https.any.html [ Crash ] +imported/w3c/web-platform-tests/WebCryptoAPI/generateKey/failures_X25519.https.any.worker.html [ Crash ] +imported/w3c/web-platform-tests/WebCryptoAPI/generateKey/successes_X25519.https.any.html [ Crash ] +imported/w3c/web-platform-tests/WebCryptoAPI/generateKey/successes_X25519.https.any.worker.html [ Crash ] +imported/w3c/web-platform-tests/WebCryptoAPI/import_export/okp_importKey.https.any.html [ Crash ] +imported/w3c/web-platform-tests/WebCryptoAPI/import_export/okp_importKey.https.any.worker.html [ Crash ] +imported/w3c/web-platform-tests/WebCryptoAPI/import_export/okp_importKey_failures_X25519.https.any.html [ Crash ] +imported/w3c/web-platform-tests/WebCryptoAPI/import_export/okp_importKey_failures_X25519.https.any.worker.html [ Crash ] diff --git a/LayoutTests/platform/mac/TestExpectations b/LayoutTests/platform/mac/TestExpectations index 98966a5b8fac..10039033017c 100644 --- a/LayoutTests/platform/mac/TestExpectations +++ b/LayoutTests/platform/mac/TestExpectations @@ -2886,3 +2886,13 @@ webkit.org/b/261306 imported/w3c/web-platform-tests/content-security-policy/repo # rdar://114294654 (REGRESSION (265615@main): [ Sonoma ] fast/attachment/cocoa/wide-attachment-rendering.html is a constant failure) [ Sonoma+ ] fast/attachment/cocoa/wide-attachment-rendering.html [ Failure ] + +# webkit.org/b/262663 (REGRESSION(iOS17/Sonoma): 8 WebCryptoAPI tests are constantly crashing.) +[ Sonoma ] imported/w3c/web-platform-tests/WebCryptoAPI/generateKey/failures_X25519.https.any.html [ Crash ] +[ Sonoma ] imported/w3c/web-platform-tests/WebCryptoAPI/generateKey/failures_X25519.https.any.worker.html [ Crash ] +[ Sonoma ] imported/w3c/web-platform-tests/WebCryptoAPI/generateKey/successes_X25519.https.any.html [ Crash ] +[ Sonoma ] imported/w3c/web-platform-tests/WebCryptoAPI/generateKey/successes_X25519.https.any.worker.html [ Crash ] +[ Sonoma ] imported/w3c/web-platform-tests/WebCryptoAPI/import_export/okp_importKey.https.any.html [ Crash ] +[ Sonoma ] imported/w3c/web-platform-tests/WebCryptoAPI/import_export/okp_importKey.https.any.worker.html [ Crash ] +[ Sonoma ] imported/w3c/web-platform-tests/WebCryptoAPI/import_export/okp_importKey_failures_X25519.https.any.html [ Crash ] +[ Sonoma ] imported/w3c/web-platform-tests/WebCryptoAPI/import_export/okp_importKey_failures_X25519.https.any.worker.html [ Crash ] diff --git a/Source/WTF/Scripts/Preferences/UnifiedWebPreferences.yaml b/Source/WTF/Scripts/Preferences/UnifiedWebPreferences.yaml index 96f1cf72103b..0497568acddb 100644 --- a/Source/WTF/Scripts/Preferences/UnifiedWebPreferences.yaml +++ b/Source/WTF/Scripts/Preferences/UnifiedWebPreferences.yaml @@ -4914,6 +4914,22 @@ OffscreenCanvasInWorkersEnabled: "PLATFORM(COCOA)": true default: false +# FIXME: Reenable this on iOS once we can mitigate impact on memory use. +OpportunisticSweepingAndGarbageCollectionEnabled: + type: bool + status: internal + humanReadableName: "Opportunistic Sweeping and GC" + humanReadableDescription: "Enable Opportunistic Sweeping and GC" + category: javascript + defaultValue: + WebKitLegacy: + default: false + WebKit: + "PLATFORM(IOS_FAMILY)": false + default: true + WebCore: + default: false + OpusDecoderEnabled: type: bool status: mature diff --git a/Source/WTF/wtf/CrossThreadCopier.cpp b/Source/WTF/wtf/CrossThreadCopier.cpp index 17d971ada563..4f348bee7333 100644 --- a/Source/WTF/wtf/CrossThreadCopier.cpp +++ b/Source/WTF/wtf/CrossThreadCopier.cpp @@ -44,11 +44,6 @@ static_assert((std::is_same, CrossThreadC static_assert((std::is_same, CrossThreadCopier::Type>::value), "RawPointerTest"); static_assert((std::is_same, CrossThreadCopier>::Type>::value), "RawPointerTest"); -// Add specializations for RefCounted types which will let us verify that no other template matches. -template struct CrossThreadCopierBase> { - typedef int Type; -}; - template struct CrossThreadCopierBase { typedef int Type; }; @@ -57,7 +52,6 @@ template struct CrossThreadCopierBase { class CopierRefCountedTest : public RefCounted { }; -static_assert((std::is_same>::Type>::value), "CrossThreadCopier specialization improperly applied to RefPtr<> of a RefCounted (but not ThreadSafeRefCounted) type"); static_assert((std::is_same::Type>::value), "CrossThreadCopier specialization improperly applied to raw pointer of a RefCounted (but not ThreadSafeRefCounted) type"); } // namespace WTF diff --git a/Source/WTF/wtf/CrossThreadCopier.h b/Source/WTF/wtf/CrossThreadCopier.h index 1e44d4aed236..889741e20774 100644 --- a/Source/WTF/wtf/CrossThreadCopier.h +++ b/Source/WTF/wtf/CrossThreadCopier.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2009, 2010 Google Inc. All rights reserved. - * Copyright (C) 2014-2019 Apple Inc. All rights reserved. + * Copyright (C) 2014-2023 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -31,13 +31,17 @@ #pragma once +#include #include +#include #include +#include #include #include #include #include #include +#include #include namespace WTF { @@ -68,7 +72,9 @@ struct CrossThreadCopierBaseHelper { }; template struct CrossThreadCopierPassThrough { - typedef T Type; + static_assert(CrossThreadCopierBaseHelper::IsEnumOrConvertibleToInteger::value, "CrossThreadCopierPassThrough only used for enums or integers"); + using Type = T; + static constexpr bool IsNeeded = false; static Type copy(const T& parameter) { return parameter; @@ -82,37 +88,89 @@ template struct CrossThreadCopierBase : public Cross }; // Classes that have an isolatedCopy() method get a default specialization. -template struct CrossThreadCopierBase { - template static auto copy(U&& value) +template +struct CrossThreadCopierBase { + using Type = T; + static constexpr bool IsNeeded = HasIsolatedCopy::value; + template static auto copy(U&& value) -> Type { - return std::forward(value).isolatedCopy(); + if constexpr (HasIsolatedCopy::value) + return std::forward(value).isolatedCopy(); + else + return std::forward(value); } }; // Custom copy methods. template struct CrossThreadCopierBase { - typedef typename CrossThreadCopierBaseHelper::RemovePointer::Type RefCountedType; + using RefCountedType = typename CrossThreadCopierBaseHelper::RemovePointer::Type; static_assert(std::is_convertible::value, "T is not convertible to ThreadSafeRefCounted!"); - typedef RefPtr Type; + using Type = RefPtr; + static constexpr bool IsNeeded = false; + static Type copy(const T& refPtr) { return refPtr; } + static Type copy(T&& refPtr) + { + return WTFMove(refPtr); + } +}; + +// Can only be moved +template struct CrossThreadCopierBase> { + using Type = Ref; + static constexpr bool IsNeeded = false; + static Type copy(Type&& ref) + { + return WTFMove(ref); + } +}; + +// Can only be moved +template struct CrossThreadCopierBase> { + using Type = RefPtr; + static constexpr bool IsNeeded = false; + static Type copy(Type&& ref) + { + return WTFMove(ref); + } }; template struct CrossThreadCopierBase> { static_assert(std::is_convertible::value, "T is not convertible to ThreadSafeRefCounted!"); + static constexpr bool IsNeeded = false; - typedef Ref Type; + using Type = Ref; static Type copy(const Type& ref) { return ref; } + static Type copy(Type&& ref) + { + return WTFMove(ref); + } +}; + +// Default specialization for AtomString of CrossThreadCopyable classes. +template<> struct CrossThreadCopierBase { + using Type = String; + static constexpr bool IsNeeded = true; + static Type copy(const AtomString& source) + { + return source.string().isolatedCopy(); + } + static Type copy(AtomString&& source) + { + return source.releaseString().isolatedCopy(); + } }; template<> struct CrossThreadCopierBase { - typedef WTF::ASCIILiteral Type; + using Type = WTF::ASCIILiteral; + static constexpr bool IsNeeded = false; static Type copy(const Type& source) { return source; @@ -120,7 +178,8 @@ template<> struct CrossThreadCopierBase { }; template struct CrossThreadCopierBase> { - typedef ObjectIdentifierGeneric Type; + using Type = ObjectIdentifierGeneric; + static constexpr bool IsNeeded = false; static Type copy(const Type& source) { return source; @@ -134,6 +193,7 @@ struct CrossThreadCopier : public CrossThreadCopierBase struct CrossThreadCopierBase> { using Type = Vector; + static constexpr bool IsNeeded = CrossThreadCopier::IsNeeded; static Type copy(const Type& source) { return WTF::map(source, [](auto& object) { @@ -147,10 +207,11 @@ template struct CrossThreadCopierBase > { - typedef HashSet Type; + using Type = HashSet; + static constexpr bool IsNeeded = CrossThreadCopier::IsNeeded; static Type copy(const Type& source) { Type destination; @@ -171,7 +232,8 @@ template struct CrossThreadCopierBase > { // Default specialization for HashMaps of CrossThreadCopyable classes template struct CrossThreadCopierBase> { - typedef HashMap Type; + using Type = HashMap; + static constexpr bool IsNeeded = CrossThreadCopier::IsNeeded || CrossThreadCopier::IsNeeded; static Type copy(const Type& source) { Type destination; @@ -191,7 +253,8 @@ struct CrossThreadCopierBase struct CrossThreadCopierBase > { - typedef std::pair Type; + using Type = std::pair; + static constexpr bool IsNeeded = CrossThreadCopier::IsNeeded || CrossThreadCopier::IsNeeded; template static Type copy(U&& source) { return std::make_pair(CrossThreadCopier::copy(std::get<0>(std::forward(source))), CrossThreadCopier::copy(std::get<1>(std::forward(source)))); @@ -200,6 +263,8 @@ template struct CrossThreadCopierBase struct CrossThreadCopierBase> { + using Type = std::optional; + static constexpr bool IsNeeded = CrossThreadCopier::IsNeeded; template static std::optional copy(U&& source) { if (!source) @@ -210,7 +275,9 @@ template struct CrossThreadCopierBase // Default specialization for Markable of CrossThreadCopyable class. template struct CrossThreadCopierBase> { - template static Markable copy(V&& source) + using Type = Markable; + static constexpr bool IsNeeded = CrossThreadCopier::IsNeeded; + template static Type copy(V&& source) { if (!source) return std::nullopt; @@ -219,12 +286,14 @@ template struct CrossThreadCopierBase struct CrossThreadCopierBase { + static constexpr bool IsNeeded = false; static std::nullptr_t copy(std::nullptr_t) { return nullptr; } }; // Default specialization for std::variant of CrossThreadCopyable classes. template struct CrossThreadCopierBase> { using Type = std::variant; + static constexpr bool IsNeeded = (CrossThreadCopier>::IsNeeded || ...); static std::variant copy(const Type& source) { return std::visit([] (auto& type) -> std::variant { @@ -239,11 +308,61 @@ template struct CrossThreadCopierBase +struct CrossThreadCopierBase { + static constexpr bool IsNeeded = false; + using Type = void; +}; + +template struct CrossThreadCopierBase > { + using Type = Expected; + static constexpr bool IsNeeded = CrossThreadCopier>::IsNeeded || CrossThreadCopier>::IsNeeded; + static Type copy(const Type& source) + { + if (source.has_value()) { + if constexpr (std::is_void_v) + return source; + else + return CrossThreadCopier::copy(source.value()); + } + return Unexpected(CrossThreadCopier::copy(source.error())); + } + + static Type copy(Type&& source) + { + if (source.has_value()) { + if constexpr (std::is_void_v) + return WTFMove(source); + else + return CrossThreadCopier::copy(WTFMove(source.value())); + } + return Unexpected(CrossThreadCopier::copy(WTFMove(source.error()))); + } +}; + +// Default specialization for std::tuple of CrossThreadCopyable classes. +template struct CrossThreadCopierBase> { + using Type = std::tuple; + static constexpr bool IsNeeded = (CrossThreadCopier>::IsNeeded || ...); + static Type copy(const Type& source) + { + return std::apply([](Ts const&... ts) { + return std::make_tuple((CrossThreadCopier>::copy(ts), ...)); + }, source); + } + static Type copy(Type&& source) + { + return std::apply([](Ts&&... ts) { + return std::make_tuple((CrossThreadCopier>::copy(WTFMove(ts)), ...)); + }, WTFMove(source)); + } +}; + template auto crossThreadCopy(T&& source) { return CrossThreadCopier>::copy(std::forward(source)); } - + } // namespace WTF using WTF::CrossThreadCopierBaseHelper; diff --git a/Source/WTF/wtf/Forward.h b/Source/WTF/wtf/Forward.h index 02b60e80e16c..0d101674c60a 100644 --- a/Source/WTF/wtf/Forward.h +++ b/Source/WTF/wtf/Forward.h @@ -122,7 +122,7 @@ template, typename = HashTraits> class HashCountedSet; template, typename = HashTraits, typename = HashTraits, typename = HashTableTraits> class HashMap; template, typename = HashTraits, typename = HashTableTraits> class HashSet; -template class NativePromise; +template class NativePromise; } diff --git a/Source/WTF/wtf/Markable.h b/Source/WTF/wtf/Markable.h index 37b81a5639d7..f36867a4a8db 100644 --- a/Source/WTF/wtf/Markable.h +++ b/Source/WTF/wtf/Markable.h @@ -76,6 +76,18 @@ struct IntegralMarkableTraits { } }; +struct FloatMarkableTraits { + constexpr static bool isEmptyValue(float value) + { + return value != value; + } + + constexpr static float emptyValue() + { + return std::numeric_limits::quiet_NaN(); + } +}; + // The goal of Markable is offering Optional without sacrificing storage efficiency. // Markable takes Traits, which should have isEmptyValue and emptyValue functions. By using // one value of T as an empty value, we can remove bool flag in Optional. This strategy is @@ -129,6 +141,13 @@ class Markable { constexpr const T& operator*() const& { return m_value; } constexpr T& operator*() & { return m_value; } + template constexpr T value_or(U&& fallback) const + { + if (bool(*this)) + return m_value; + return static_cast(std::forward(fallback)); + } + operator std::optional() && { if (bool(*this)) diff --git a/Source/WTF/wtf/NativePromise.h b/Source/WTF/wtf/NativePromise.h index b501fba720a8..600307de8e74 100644 --- a/Source/WTF/wtf/NativePromise.h +++ b/Source/WTF/wtf/NativePromise.h @@ -33,7 +33,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -70,6 +72,10 @@ namespace WTF { * - values are passed to the resolve/reject callbacks through either const references or pointers. * - the resolve or reject object will be deleted on the last SerialFunctionDispatcher that got used. * + * By default, a NativePromise will use crossThreadCopy() on the resolved or rejected object if it contains a type with the `isolatedCopy()` method + * or an AtomString (be it directly, or in a composited object (e.g. Vector). + * This behaviour can be overridden with either PromiseOption::WithCrossThreadCopy or PromiseOption::WithoutCrossThreadCopy + * * A typical workflow would be as follow: * If the work is to be done immediately: * From the producer side: @@ -94,7 +100,8 @@ namespace WTF { * * By disconnecting the NativePromiseRequest (via NativePromiseRequest::disconnect(), the then()/whenSettled() callbacks will not be run. * - * For now, care should be taken by the Producer to only return an object that is usable on the target's queue (don't return an AtomString for example) + * The object given to resolve, reject or resolveOrReject must have a CrossThreadCopier specialisation as needed. + * The type of this object may not be identical to ResolveValueType or RejectValueType as the methods allow for implicit conversion. * * Examples: * 1. Basic usage. methodA runs on the main thread, methodB must run on a WorkQueue, and expects a std::unique. @@ -207,13 +214,40 @@ enum class PromiseDispatchMode : uint8_t { }; -template +enum class PromiseOption : uint8_t { + Default = 0, // Exclusive | WithAutomaticCrossThreadCopy + NonExclusive = (1 << 0), + WithCrossThreadCopy = (1 << 2), + WithoutCrossThreadCopy = (1 << 3), +}; +constexpr unsigned operator|(PromiseOption a, PromiseOption b) +{ + return static_cast(a) | static_cast(b); +} +constexpr unsigned operator|(unsigned a, PromiseOption b) +{ + return a | static_cast(b); +} +constexpr unsigned operator&(PromiseOption a, PromiseOption b) +{ + return static_cast(a) & static_cast(b); +} +constexpr unsigned operator&(unsigned a, PromiseOption b) +{ + return a & static_cast(b); +} + +template class NativePromise final : public NativePromiseBase, public ConvertibleToNativePromise { public: - using Result = Expected; - using Error = Unexpected; - using ResolveValueType = ResolveValueT; - using RejectValueType = RejectValueT; + static constexpr bool IsExclusive = !(options & PromiseOption::NonExclusive); + static constexpr bool WithCrossThreadCopy = !!(options & PromiseOption::WithCrossThreadCopy); + static constexpr bool WithAutomaticCrossThreadCopy = !(options & (PromiseOption::WithCrossThreadCopy | PromiseOption::WithoutCrossThreadCopy)) && (CrossThreadCopier::IsNeeded || CrossThreadCopier::IsNeeded); + static_assert(!WithAutomaticCrossThreadCopy || IsExclusive, "Using Non-Exclusive NativePromise with a ResolveValueT or RejectValueT requiring a call to isolatedCopy() must be explicitly set with WithCrossThreadCopy or WithoutCrossThreadCopy option"); + using ResolveValueType = std::conditional_t::Type, ResolveValueT>; + using RejectValueType = std::conditional_t::Type, RejectValueT>; + using Result = Expected; + using Error = Unexpected; // used by IsConvertibleToNativePromise to determine how to cast the result. using PromiseType = NativePromise; @@ -328,8 +362,8 @@ class NativePromise final : public NativePromiseBase, public ConvertibleToNative return p; } - using AllPromiseType = NativePromise, RejectValueType, IsExclusive>; - using AllSettledPromiseType = NativePromise, bool, IsExclusive>; + using AllPromiseType = NativePromise, RejectValueType, options>; + using AllSettledPromiseType = NativePromise, bool, options>; private: friend class Producer; @@ -340,7 +374,10 @@ class NativePromise final : public NativePromiseBase, public ConvertibleToNative Locker lock { m_lock }; PROMISE_LOG(resolveSite, " resolving ", *this); ASSERT(isNothing()); - m_result = std::forward(resolveValue); + if constexpr (WithCrossThreadCopy || WithAutomaticCrossThreadCopy) + m_result = crossThreadCopy(std::forward(resolveValue)); + else + m_result = std::forward(resolveValue); dispatchAll(lock); } @@ -361,17 +398,24 @@ class NativePromise final : public NativePromiseBase, public ConvertibleToNative Locker lock { m_lock }; PROMISE_LOG(rejectSite, " rejecting ", *this); ASSERT(isNothing()); - m_result = Unexpected(std::forward(rejectValue)); + if constexpr (WithCrossThreadCopy || WithAutomaticCrossThreadCopy) + m_result = Unexpected(crossThreadCopy(std::forward(rejectValue))); + else + m_result = Unexpected(std::forward(rejectValue)); dispatchAll(lock); } template void resolveOrReject(ResolveOrRejectValue_&& result, const Logger::LogSiteIdentifier& site) { + static_assert(std::is_convertible_v, "resolveOrReject() argument must be implicitly convertible to NativePromise's Result"); Locker lock { m_lock }; ASSERT(isNothing()); PROMISE_LOG(site, " resolveOrRejecting ", *this); - m_result = std::forward(result); + if constexpr (WithCrossThreadCopy || WithAutomaticCrossThreadCopy) + m_result = crossThreadCopy(std::forward(result)); + else + m_result = std::forward(result); dispatchAll(lock); } @@ -675,7 +719,7 @@ class NativePromise final : public NativePromiseBase, public ConvertibleToNative template class ThenCommand : public ConvertibleToNativePromise { // Allow Promise::then() to access the private constructor, - template + template friend class NativePromise; // used by IsConvertibleToNativePromise to determine how to cast the result. @@ -979,12 +1023,12 @@ class NativePromise final : public NativePromiseBase, public ConvertibleToNative std::atomic m_dispatchMode { PromiseDispatchMode::Default }; }; -template -class NativePromise::Producer final : public ConvertibleToNativePromise { +template +class NativePromise::Producer final : public ConvertibleToNativePromise { WTF_MAKE_FAST_ALLOCATED; public: // used by IsConvertibleToNativePromise to determine how to cast the result. - using PromiseType = NativePromise; + using PromiseType = NativePromise; explicit Producer(PromiseDispatchMode dispatchMode = PromiseDispatchMode::Default, const Logger::LogSiteIdentifier& creationSite = DEFAULT_LOGSITEIDENTIFIER) : m_promise(adoptRef(new PromiseType(creationSite))) @@ -1120,10 +1164,10 @@ class NativePromise::Producer final : }; // A generic promise type that does the trick for simple use cases. -using GenericPromise = NativePromise; +using GenericPromise = NativePromise; // A generic, non-exclusive promise type that does the trick for simple use cases. -using GenericNonExclusivePromise = NativePromise; +using GenericNonExclusivePromise = NativePromise; template class NativePromiseRequest final { @@ -1184,9 +1228,9 @@ static auto invokeAsync(SerialFunctionDispatcher& targetQueue, Function&& functi return promise; } -template -struct LogArgument> { - static String toString(const NativePromise& p) +template +struct LogArgument> { + static String toString(const NativePromise& p) { return makeString("NativePromise", LogArgument::toString(&p), '<', LogArgument::toString(p.logSiteIdentifier()), '>'); } diff --git a/Source/WTF/wtf/TypeTraits.h b/Source/WTF/wtf/TypeTraits.h index d5d306e3778c..d76ac6b1e2bd 100644 --- a/Source/WTF/wtf/TypeTraits.h +++ b/Source/WTF/wtf/TypeTraits.h @@ -107,6 +107,19 @@ static auto HasRefCountMethodsTest(long) -> std::false_type; template struct HasRefCountMethods : decltype(detail::HasRefCountMethodsTest(0)) { }; +// HasIsolatedCopy() +namespace detail { + +template +static auto HasIsolatedCopyTest(int) -> SFINAE1True().isolatedCopy())>; +template +static auto HasIsolatedCopyTest(long) -> std::false_type; + +} // namespace detail + +template +struct HasIsolatedCopy : decltype(detail::HasIsolatedCopyTest(0)) { }; + // LooksLikeRCSerialDispatcher implementation namespace detail { diff --git a/Source/WTF/wtf/URLParser.cpp b/Source/WTF/wtf/URLParser.cpp index 800872baf935..56c50e8e0879 100644 --- a/Source/WTF/wtf/URLParser.cpp +++ b/Source/WTF/wtf/URLParser.cpp @@ -47,9 +47,7 @@ ALWAYS_INLINE static void appendCodePoint(Vector& destination, UChar32 co destination.append(static_cast(codePoint)); return; } - destination.reserveCapacity(destination.size() + 2); - destination.uncheckedAppend(U16_LEAD(codePoint)); - destination.uncheckedAppend(U16_TRAIL(codePoint)); + destination.appendList({ U16_LEAD(codePoint), U16_TRAIL(codePoint) }); } enum URLCharacterClass { diff --git a/Source/WTF/wtf/Vector.h b/Source/WTF/wtf/Vector.h index e194403e70eb..1c1152e50822 100644 --- a/Source/WTF/wtf/Vector.h +++ b/Source/WTF/wtf/Vector.h @@ -862,6 +862,7 @@ class Vector : private VectorBuffer { template ALWAYS_INLINE void append(const U* u, size_t size) { append(u, size); } template ALWAYS_INLINE bool tryAppend(const U* u, size_t size) { return append(u, size); } template ALWAYS_INLINE void append(std::span span) { append(span.data(), span.size()); } + template ALWAYS_INLINE void appendList(std::initializer_list initializerList) { append(std::data(initializerList), initializerList.size()); } template void appendVector(const Vector&); template void appendVector(Vector&&); diff --git a/Source/WebCore/CMakeLists.txt b/Source/WebCore/CMakeLists.txt index cdbd0f9ac004..14858ef2a6a0 100644 --- a/Source/WebCore/CMakeLists.txt +++ b/Source/WebCore/CMakeLists.txt @@ -459,6 +459,7 @@ set(WebCore_NON_SVG_IDL_FILES Modules/mediastream/OverconstrainedError.idl Modules/mediastream/OverconstrainedErrorEvent.idl Modules/mediastream/PhotoCapabilities.idl + Modules/mediastream/PhotoSettings.idl Modules/mediastream/RTCAnswerOptions.idl Modules/mediastream/RTCCertificate.idl Modules/mediastream/RTCConfiguration.idl diff --git a/Source/WebCore/DerivedSources.make b/Source/WebCore/DerivedSources.make index 628808d00706..503a7228a692 100644 --- a/Source/WebCore/DerivedSources.make +++ b/Source/WebCore/DerivedSources.make @@ -454,6 +454,7 @@ JS_BINDING_IDLS := \ $(WebCore)/Modules/mediastream/OverconstrainedError.idl \ $(WebCore)/Modules/mediastream/OverconstrainedErrorEvent.idl \ $(WebCore)/Modules/mediastream/PhotoCapabilities.idl \ + $(WebCore)/Modules/mediastream/PhotoSettings.idl \ $(WebCore)/Modules/mediastream/RedEyeReduction.idl \ $(WebCore)/Modules/mediastream/RTCAnswerOptions.idl \ $(WebCore)/Modules/mediastream/RTCCertificate.idl \ diff --git a/Source/WebCore/Headers.cmake b/Source/WebCore/Headers.cmake index 964b0a2aea25..0e5a2800cf1e 100644 --- a/Source/WebCore/Headers.cmake +++ b/Source/WebCore/Headers.cmake @@ -2152,6 +2152,7 @@ set(WebCore_PRIVATE_FRAMEWORK_HEADERS platform/mediastream/MediaStreamTrackPrivate.h platform/mediastream/MeteringMode.h platform/mediastream/PhotoCapabilities.h + platform/mediastream/PhotoSettings.h platform/mediastream/RedEyeReduction.h platform/mediastream/RTCDataChannelHandler.h platform/mediastream/RTCDataChannelHandlerClient.h diff --git a/Source/WebCore/Modules/mediastream/ImageCapture.cpp b/Source/WebCore/Modules/mediastream/ImageCapture.cpp index 0e3ac2b9223d..3fb8da362196 100644 --- a/Source/WebCore/Modules/mediastream/ImageCapture.cpp +++ b/Source/WebCore/Modules/mediastream/ImageCapture.cpp @@ -63,6 +63,16 @@ void ImageCapture::getPhotoCapabilities(PhotoCapabilitiesPromise&& promise) m_track->getPhotoCapabilities(WTFMove(promise)); } +void ImageCapture::getPhotoSettings(PhotoSettingsPromise&& promise) +{ + if (m_track->readyState() == MediaStreamTrack::State::Ended) { + promise.reject(Exception { InvalidStateError, "Track has ended"_s }); + return; + } + + m_track->getPhotoSettings(WTFMove(promise)); +} + const char* ImageCapture::activeDOMObjectName() const { return "ImageCapture"; diff --git a/Source/WebCore/Modules/mediastream/ImageCapture.h b/Source/WebCore/Modules/mediastream/ImageCapture.h index eaa2024fd3aa..ff03eda74dc8 100644 --- a/Source/WebCore/Modules/mediastream/ImageCapture.h +++ b/Source/WebCore/Modules/mediastream/ImageCapture.h @@ -32,6 +32,7 @@ #include "JSDOMPromiseDeferred.h" #include "MediaStreamTrack.h" #include "PhotoCapabilities.h" +#include "PhotoSettings.h" namespace WebCore { @@ -45,6 +46,9 @@ class ImageCapture : public RefCounted, public ActiveDOMObject { using PhotoCapabilitiesPromise = DOMPromiseDeferred>; void getPhotoCapabilities(PhotoCapabilitiesPromise&&); + using PhotoSettingsPromise = DOMPromiseDeferred>; + void getPhotoSettings(PhotoSettingsPromise&&); + Ref track() const { return m_track; } private: diff --git a/Source/WebCore/Modules/mediastream/ImageCapture.idl b/Source/WebCore/Modules/mediastream/ImageCapture.idl index a5a11da93201..0dd7ff529f56 100644 --- a/Source/WebCore/Modules/mediastream/ImageCapture.idl +++ b/Source/WebCore/Modules/mediastream/ImageCapture.idl @@ -37,8 +37,7 @@ // FIXME: https://bugs.webkit.org/show_bug.cgi?id=262467 // Promise takePhoto(optional PhotoSettings photoSettings = {}); - // FIXME: https://bugs.webkit.org/show_bug.cgi?id=262466 - // Promise getPhotoSettings(); + Promise getPhotoSettings(); readonly attribute MediaStreamTrack track; }; diff --git a/Source/WebCore/Modules/mediastream/MediaStreamTrack.cpp b/Source/WebCore/Modules/mediastream/MediaStreamTrack.cpp index f87658719064..2f44070603b7 100644 --- a/Source/WebCore/Modules/mediastream/MediaStreamTrack.cpp +++ b/Source/WebCore/Modules/mediastream/MediaStreamTrack.cpp @@ -39,6 +39,7 @@ #include "JSMeteringMode.h" #include "JSOverconstrainedError.h" #include "JSPhotoCapabilities.h" +#include "JSPhotoSettings.h" #include "LocalFrame.h" #include "Logging.h" #include "MediaConstraints.h" @@ -58,6 +59,7 @@ #include "WebAudioSourceProvider.h" #include #include +#include #include namespace WebCore { @@ -328,6 +330,22 @@ void MediaStreamTrack::getPhotoCapabilities(DOMPromiseDeferred>&& promise) const +{ + m_private->getPhotoSettings()->whenSettled(RunLoop::main(), [protectedThis = Ref { *this }, promise = WTFMove(promise)] (RealtimeMediaSource::PhotoSettingsPromise::Result&& result) mutable { + if (!result) { + // https://w3c.github.io/mediacapture-image/#ref-for-dom-imagecapture-getphotosettings② + // If the data cannot be gathered for any reason (for example, the MediaStreamTrack being ended + // asynchronously), then reject p with a new DOMException whose name is OperationError, and + // abort these steps. + promise.reject(Exception { OperationError, WTFMove(result.error()) }); + return; + } + + promise.resolve(WTFMove(result.value())); + }); +} + static MediaConstraints createMediaConstraints(const std::optional& constraints) { if (!constraints) { diff --git a/Source/WebCore/Modules/mediastream/MediaStreamTrack.h b/Source/WebCore/Modules/mediastream/MediaStreamTrack.h index db7d35ac13bd..a8d32011d050 100644 --- a/Source/WebCore/Modules/mediastream/MediaStreamTrack.h +++ b/Source/WebCore/Modules/mediastream/MediaStreamTrack.h @@ -39,6 +39,7 @@ #include "MediaTrackCapabilities.h" #include "MediaTrackConstraints.h" #include "PhotoCapabilities.h" +#include "PhotoSettings.h" #include "PlatformMediaSession.h" #include @@ -130,6 +131,7 @@ class MediaStreamTrack TrackCapabilities getCapabilities() const; void getPhotoCapabilities(DOMPromiseDeferred>&&) const; + void getPhotoSettings(DOMPromiseDeferred>&&) const; const MediaTrackConstraints& getConstraints() const { return m_constraints; } void setConstraints(MediaTrackConstraints&& constraints) { m_constraints = WTFMove(constraints); } diff --git a/Source/WebCore/Modules/mediastream/PhotoSettings.idl b/Source/WebCore/Modules/mediastream/PhotoSettings.idl new file mode 100644 index 000000000000..9c7f355ef4ec --- /dev/null +++ b/Source/WebCore/Modules/mediastream/PhotoSettings.idl @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2023 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// https://w3c.github.io/mediacapture-image/#photosettings-section + +[ + Conditional=MEDIA_STREAM, + JSGenerateToJSObject +] dictionary PhotoSettings { + FillLightMode fillLightMode; + double imageHeight; + double imageWidth; + boolean redEyeReduction; +}; diff --git a/Source/WebCore/Modules/webaudio/AsyncAudioDecoder.cpp b/Source/WebCore/Modules/webaudio/AsyncAudioDecoder.cpp index 47bfb9244738..0eb7477c35d0 100644 --- a/Source/WebCore/Modules/webaudio/AsyncAudioDecoder.cpp +++ b/Source/WebCore/Modules/webaudio/AsyncAudioDecoder.cpp @@ -47,7 +47,7 @@ Ref AsyncAudioDecoder::decodeAsync(Ref&& audio // The ArrayBuffer must be deleted on the main thread, send it back there to be derefed. callOnMainThread([audioData = WTFMove(audioData)] { }); if (!audioBuffer) - return DecodingTaskPromise::createAndReject(EncodingError); + return DecodingTaskPromise::createAndReject(Exception { EncodingError, "Decoding failed"_s }); return DecodingTaskPromise::createAndResolve(audioBuffer.releaseNonNull()); }); } diff --git a/Source/WebCore/Modules/webaudio/AsyncAudioDecoder.h b/Source/WebCore/Modules/webaudio/AsyncAudioDecoder.h index 20faf4efa898..7a69d9d19c5d 100644 --- a/Source/WebCore/Modules/webaudio/AsyncAudioDecoder.h +++ b/Source/WebCore/Modules/webaudio/AsyncAudioDecoder.h @@ -24,7 +24,8 @@ #pragma once -#include "ExceptionCode.h" +#include "Exception.h" +#include #include #include @@ -32,18 +33,13 @@ namespace JSC { class ArrayBuffer; } -namespace WTF { -template -class NativePromise; -} - namespace WebCore { class AudioBuffer; // AsyncAudioDecoder asynchronously decodes audio file data from an ArrayBuffer in a worker thread. // Upon successful decoding, the DecodingTaskPromise will be resolved with the decoded AudioBuffer -// otherwise an ExceptionCode will be returned. -using DecodingTaskPromise = WTF::NativePromise, ExceptionCode, true /* isExclusive */>; +// otherwise an Exception will be returned. +using DecodingTaskPromise = WTF::NativePromise, Exception>; class AsyncAudioDecoder final { WTF_MAKE_FAST_ALLOCATED; diff --git a/Source/WebCore/Modules/webaudio/BaseAudioContext.cpp b/Source/WebCore/Modules/webaudio/BaseAudioContext.cpp index 062c709ff628..eb384263fb4c 100644 --- a/Source/WebCore/Modules/webaudio/BaseAudioContext.cpp +++ b/Source/WebCore/Modules/webaudio/BaseAudioContext.cpp @@ -304,7 +304,7 @@ void BaseAudioContext::decodeAudioData(Ref&& audioData, RefPtrreject(Exception { result.error(), "Decoding failed"_s }); + promise.value()->reject(WTFMove(result.error())); if (errorCallback) errorCallback->handleEvent(nullptr); return; diff --git a/Source/WebCore/Modules/webtransport/WebTransport.cpp b/Source/WebCore/Modules/webtransport/WebTransport.cpp index 911dd2113520..d1683d3108a8 100644 --- a/Source/WebCore/Modules/webtransport/WebTransport.cpp +++ b/Source/WebCore/Modules/webtransport/WebTransport.cpp @@ -212,16 +212,16 @@ static CString trimToValidUTF8Length1024(CString&& string) if (string.length() > 1024) string = CString(string.data(), 1024); else - return string; + return WTFMove(string); while (true) { if (!string.length()) - return string; + return WTFMove(string); auto decoded = String::fromUTF8(string.data(), string.length()); if (!decoded) string = CString(string.data(), string.length() - 1); else - return string; + return WTFMove(string); } } diff --git a/Source/WebCore/PAL/pal/text/TextCodecCJK.cpp b/Source/WebCore/PAL/pal/text/TextCodecCJK.cpp index 5c231e5f7aa9..9227b3a5c71b 100644 --- a/Source/WebCore/PAL/pal/text/TextCodecCJK.cpp +++ b/Source/WebCore/PAL/pal/text/TextCodecCJK.cpp @@ -1124,23 +1124,15 @@ static void appendDecimal(UChar32 c, Vector& result) static void urlEncodedEntityUnencodableHandler(UChar32 c, Vector& result) { result.reserveCapacity(result.size() + 9 + maxUChar32Digits); - result.uncheckedAppend('%'); - result.uncheckedAppend('2'); - result.uncheckedAppend('6'); - result.uncheckedAppend('%'); - result.uncheckedAppend('2'); - result.uncheckedAppend('3'); + result.appendList({ '%', '2', '6', '%', '2', '3' }); appendDecimal(c, result); - result.uncheckedAppend('%'); - result.uncheckedAppend('3'); - result.uncheckedAppend('B'); + result.appendList({ '%', '3', 'B' }); } static void entityUnencodableHandler(UChar32 c, Vector& result) { result.reserveCapacity(result.size() + 3 + maxUChar32Digits); - result.uncheckedAppend('&'); - result.uncheckedAppend('#'); + result.appendList({ '&', '#' }); appendDecimal(c, result); result.uncheckedAppend(';'); } diff --git a/Source/WebCore/Sources.txt b/Source/WebCore/Sources.txt index f0bcd009d37f..016c117a3825 100644 --- a/Source/WebCore/Sources.txt +++ b/Source/WebCore/Sources.txt @@ -3966,6 +3966,7 @@ JSPermissionState.cpp JSPermissionStatus.cpp JSPermissions.cpp JSPhotoCapabilities.cpp +JSPhotoSettings.cpp JSPictureInPictureEvent.cpp JSPictureInPictureWindow.cpp JSPlaneLayout.cpp diff --git a/Source/WebCore/WebCore.xcodeproj/project.pbxproj b/Source/WebCore/WebCore.xcodeproj/project.pbxproj index f26f29258155..4cc7429f38c2 100644 --- a/Source/WebCore/WebCore.xcodeproj/project.pbxproj +++ b/Source/WebCore/WebCore.xcodeproj/project.pbxproj @@ -136,6 +136,8 @@ 073930DC2AC6452800C1D1B1 /* MeteringMode.h in Headers */ = {isa = PBXBuildFile; fileRef = 073930DB2AC6452700C1D1B1 /* MeteringMode.h */; settings = {ATTRIBUTES = (Private, ); }; }; 073930DE2AC6478C00C1D1B1 /* MediaSettingsRange.h in Headers */ = {isa = PBXBuildFile; fileRef = 073930DD2AC6478B00C1D1B1 /* MediaSettingsRange.h */; settings = {ATTRIBUTES = (Private, ); }; }; 073930E02AC6490B00C1D1B1 /* PhotoCapabilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 073930DF2AC6490B00C1D1B1 /* PhotoCapabilities.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 073931172ACC6D1E00C1D1B1 /* PhotoSettings.h in Headers */ = {isa = PBXBuildFile; fileRef = 073931162ACC6D1D00C1D1B1 /* PhotoSettings.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 0739311A2ACCBF3C00C1D1B1 /* JSPhotoSettings.h in Headers */ = {isa = PBXBuildFile; fileRef = 073931182ACCBF3B00C1D1B1 /* JSPhotoSettings.h */; }; 073955BB27AB277F009A08D2 /* ScreenCaptureKitSharingSessionManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 07035D3227A9B60B00FB03E4 /* ScreenCaptureKitSharingSessionManager.h */; settings = {ATTRIBUTES = (Private, ); }; }; 073B87671E4385AC0071C0EC /* AudioSampleBufferList.h in Headers */ = {isa = PBXBuildFile; fileRef = 073B87631E43859D0071C0EC /* AudioSampleBufferList.h */; settings = {ATTRIBUTES = (Private, ); }; }; 073B87691E4385AC0071C0EC /* AudioSampleDataSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 073B87651E43859D0071C0EC /* AudioSampleDataSource.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -6735,6 +6737,10 @@ 073930DB2AC6452700C1D1B1 /* MeteringMode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MeteringMode.h; sourceTree = ""; }; 073930DD2AC6478B00C1D1B1 /* MediaSettingsRange.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MediaSettingsRange.h; sourceTree = ""; }; 073930DF2AC6490B00C1D1B1 /* PhotoCapabilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PhotoCapabilities.h; sourceTree = ""; }; + 073931142ACC6CEE00C1D1B1 /* PhotoSettings.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = PhotoSettings.idl; sourceTree = ""; }; + 073931162ACC6D1D00C1D1B1 /* PhotoSettings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PhotoSettings.h; sourceTree = ""; }; + 073931182ACCBF3B00C1D1B1 /* JSPhotoSettings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JSPhotoSettings.h; path = JSPhotoSettings.h; sourceTree = ""; }; + 073931192ACCBF3B00C1D1B1 /* JSPhotoSettings.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JSPhotoSettings.cpp; path = JSPhotoSettings.cpp; sourceTree = ""; }; 073B87561E40DCE50071C0EC /* AudioStreamDescription.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AudioStreamDescription.h; sourceTree = ""; }; 073B87571E40DCFD0071C0EC /* CAAudioStreamDescription.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CAAudioStreamDescription.cpp; sourceTree = ""; }; 073B87581E40DCFD0071C0EC /* CAAudioStreamDescription.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CAAudioStreamDescription.h; sourceTree = ""; }; @@ -20493,6 +20499,7 @@ 41E408381DCB747900EFCE19 /* PeerConnectionBackend.cpp */, 5E2C434D1BCEE2E50001E2BC /* PeerConnectionBackend.h */, 073FF3A12AC4C96D0099275E /* PhotoCapabilities.idl */, + 073931142ACC6CEE00C1D1B1 /* PhotoSettings.idl */, 073FF37F2AC3ADED0099275E /* RedEyeReduction.idl */, 316DCB2B1E78F3A9001B5F87 /* RTCAnswerOptions.h */, 316DCB2C1E78F3A9001B5F87 /* RTCAnswerOptions.idl */, @@ -20720,6 +20727,7 @@ 073930DB2AC6452700C1D1B1 /* MeteringMode.h */, 5EBB89381C77BDA400C65D41 /* PeerMediaDescription.h */, 073930DF2AC6490B00C1D1B1 /* PhotoCapabilities.h */, + 073931162ACC6D1D00C1D1B1 /* PhotoSettings.h */, 41103AAA1E39790A00769F03 /* RealtimeIncomingAudioSource.cpp */, 41103AA91E39790A00769F03 /* RealtimeIncomingAudioSource.h */, 5CDD83391E4324BB00621E92 /* RealtimeIncomingVideoSource.cpp */, @@ -20916,6 +20924,8 @@ 0704A4141D6F39FB0086DCDB /* JSOverconstrainedErrorEvent.h */, 073930BB2AC4D2CA00C1D1B1 /* JSPhotoCapabilities.cpp */, 073930B72AC4D29E00C1D1B1 /* JSPhotoCapabilities.h */, + 073931192ACCBF3B00C1D1B1 /* JSPhotoSettings.cpp */, + 073931182ACCBF3B00C1D1B1 /* JSPhotoSettings.h */, 073FF3862AC4825E0099275E /* JSRedEyeReduction.cpp */, 073FF3872AC4825E0099275E /* JSRedEyeReduction.h */, 316DCB2D1E78F496001B5F87 /* JSRTCAnswerOptions.cpp */, @@ -39630,6 +39640,7 @@ 8A9A588811E84F37008ACFD1 /* JSPerformanceTiming.h in Headers */, FDEA6247152102FC00479DF0 /* JSPeriodicWave.h in Headers */, 073930B92AC4D29F00C1D1B1 /* JSPhotoCapabilities.h in Headers */, + 0739311A2ACCBF3C00C1D1B1 /* JSPhotoSettings.h in Headers */, 1D0026A42374D62400CA6CDF /* JSPictureInPictureWindow.h in Headers */, 712BE4891FE86875002031CC /* JSPlaybackDirection.h in Headers */, 93B70D6C09EB0C7C009D8468 /* JSPluginElementFunctions.h in Headers */, @@ -40628,6 +40639,7 @@ 93B0A65626CDD14100AA21E4 /* PermissionStatus.h in Headers */, 49D5DC2E0F423A73008F20FD /* PerspectiveTransformOperation.h in Headers */, 073930E02AC6490B00C1D1B1 /* PhotoCapabilities.h in Headers */, + 073931172ACC6D1E00C1D1B1 /* PhotoSettings.h in Headers */, 1D2F8E042344751600993B68 /* PictureInPictureEvent.h in Headers */, 1DBC1B562347B3D200B901AF /* PictureInPictureObserver.h in Headers */, 1D2C82B7236A3F6A0055D6C5 /* PictureInPictureSupport.h in Headers */, diff --git a/Source/WebCore/dom/ExceptionOr.h b/Source/WebCore/dom/ExceptionOr.h index cdc616985af7..09ae01665bb3 100644 --- a/Source/WebCore/dom/ExceptionOr.h +++ b/Source/WebCore/dom/ExceptionOr.h @@ -202,7 +202,8 @@ template using TypeOrExceptionOrUnderlyingType = typename TypeOrExc namespace WTF { template struct CrossThreadCopierBase > { - typedef WebCore::ExceptionOr Type; + using Type = WebCore::ExceptionOr; + static constexpr bool IsNeeded = true; static Type copy(const Type& source) { if (source.hasException()) @@ -218,7 +219,8 @@ template struct CrossThreadCopierBase struct CrossThreadCopierBase > { - typedef WebCore::ExceptionOr Type; + using Type = WebCore::ExceptionOr; + static constexpr bool IsNeeded = true; static Type copy(const Type& source) { if (source.hasException()) diff --git a/Source/WebCore/layout/formattingContexts/inline/InlineContentBalancer.cpp b/Source/WebCore/layout/formattingContexts/inline/InlineContentBalancer.cpp index 3ab5b388202f..94a9a62ca2fd 100644 --- a/Source/WebCore/layout/formattingContexts/inline/InlineContentBalancer.cpp +++ b/Source/WebCore/layout/formattingContexts/inline/InlineContentBalancer.cpp @@ -112,7 +112,7 @@ InlineContentBalancer::InlineContentBalancer(InlineFormattingContext& inlineForm void InlineContentBalancer::initialize() { - if (!m_inlineFormattingContext.placedFloats().isEmpty()) { + if (!m_inlineFormattingContext.inlineLayoutState().placedFloats().isEmpty()) { m_cannotBalanceContent = true; return; } diff --git a/Source/WebCore/layout/formattingContexts/inline/InlineFormattingContext.cpp b/Source/WebCore/layout/formattingContexts/inline/InlineFormattingContext.cpp index 3aba2ae07c05..de951de9de28 100644 --- a/Source/WebCore/layout/formattingContexts/inline/InlineFormattingContext.cpp +++ b/Source/WebCore/layout/formattingContexts/inline/InlineFormattingContext.cpp @@ -72,7 +72,7 @@ InlineFormattingContext::InlineFormattingContext(const ElementBox& formattingCon InlineLayoutResult InlineFormattingContext::layout(const ConstraintsForInlineContent& constraints, const InlineDamage* lineDamage) { - auto& placedFloats = this->placedFloats(); + auto& placedFloats = inlineLayoutState().placedFloats(); if (!root().hasInFlowChild() && !root().hasOutOfFlowChild()) { // Float only content does not support partial layout. ASSERT(!lineDamage); @@ -176,7 +176,7 @@ InlineLayoutResult InlineFormattingContext::lineLayout(AbstractLineBuilder& line return layoutResult; } - auto floatingContext = FloatingContext { *this, placedFloats() }; + auto floatingContext = FloatingContext { *this, inlineLayoutState().placedFloats() }; auto lineLogicalTop = InlineLayoutUnit { constraints.logicalTop() }; auto previousLineEnd = std::optional { }; auto leadingInlineItemPosition = needsLayoutRange.start; @@ -217,7 +217,7 @@ void InlineFormattingContext::layoutFloatContentOnly(const ConstraintsForInlineC ASSERT(!root().hasInFlowChild()); auto& inlineContentCache = this->inlineContentCache(); - auto& placedFloats = this->placedFloats(); + auto& placedFloats = inlineLayoutState().placedFloats(); auto floatingContext = FloatingContext { *this, placedFloats }; InlineItemsBuilder { inlineContentCache, root() }.build({ }); @@ -339,7 +339,7 @@ bool InlineFormattingContext::createDisplayContentForLineFromCachedContent(const inlineContentCache.clearMaximumIntrinsicWidthLayoutResult(); return false; } - if (!placedFloats().isEmpty()) { + if (!inlineLayoutState().placedFloats().isEmpty()) { inlineContentCache.clearMaximumIntrinsicWidthLayoutResult(); return false; } diff --git a/Source/WebCore/layout/formattingContexts/inline/InlineFormattingContext.h b/Source/WebCore/layout/formattingContexts/inline/InlineFormattingContext.h index 66f70b2b702a..f9329faa8675 100644 --- a/Source/WebCore/layout/formattingContexts/inline/InlineFormattingContext.h +++ b/Source/WebCore/layout/formattingContexts/inline/InlineFormattingContext.h @@ -65,13 +65,11 @@ class InlineFormattingContext : public FormattingContext { const InlineFormattingUtils& formattingUtils() const { return m_inlineFormattingUtils; } const InlineQuirks& quirks() const { return m_inlineQuirks; } + // FIXME: This should just be "layout state" (pending on renaming LayoutState). InlineLayoutState& inlineLayoutState() { return m_inlineLayoutState; } const InlineLayoutState& inlineLayoutState() const { return m_inlineLayoutState; } - PlacedFloats& placedFloats() { return inlineLayoutState().parentBlockLayoutState().placedFloats(); } - const PlacedFloats& placedFloats() const { return inlineLayoutState().parentBlockLayoutState().placedFloats(); } - private: InlineLayoutResult lineLayout(AbstractLineBuilder&, const InlineItemList&, InlineItemRange, std::optional, const ConstraintsForInlineContent&, const InlineDamage* = nullptr); void layoutFloatContentOnly(const ConstraintsForInlineContent&); diff --git a/Source/WebCore/layout/formattingContexts/inline/InlineLayoutState.h b/Source/WebCore/layout/formattingContexts/inline/InlineLayoutState.h index 895950216c87..525a59f70ea5 100644 --- a/Source/WebCore/layout/formattingContexts/inline/InlineLayoutState.h +++ b/Source/WebCore/layout/formattingContexts/inline/InlineLayoutState.h @@ -44,6 +44,9 @@ class InlineLayoutState { const BlockLayoutState& parentBlockLayoutState() const { return m_parentBlockLayoutState; } BlockLayoutState& parentBlockLayoutState() { return m_parentBlockLayoutState; } + const PlacedFloats& placedFloats() const { return m_parentBlockLayoutState.placedFloats(); } + PlacedFloats& placedFloats() { return m_parentBlockLayoutState.placedFloats(); } + void setAvailableLineWidthOverride(AvailableLineWidthOverride availableLineWidthOverride) { m_availableLineWidthOverride = availableLineWidthOverride; } const AvailableLineWidthOverride& availableLineWidthOverride() const { return m_availableLineWidthOverride; } diff --git a/Source/WebCore/layout/formattingContexts/inline/InlineLineBoxBuilder.cpp b/Source/WebCore/layout/formattingContexts/inline/InlineLineBoxBuilder.cpp index 4efabdb199ad..47873b24a0ad 100644 --- a/Source/WebCore/layout/formattingContexts/inline/InlineLineBoxBuilder.cpp +++ b/Source/WebCore/layout/formattingContexts/inline/InlineLineBoxBuilder.cpp @@ -694,7 +694,7 @@ void LineBoxBuilder::computeLineBoxGeometry(LineBox& lineBox) const void LineBoxBuilder::adjustOutsideListMarkersPosition(LineBox& lineBox) { - auto floatingContext = FloatingContext { formattingContext(), formattingContext().placedFloats() }; + auto floatingContext = FloatingContext { formattingContext(), inlineLayoutState().placedFloats() }; auto lineBoxRect = lineBox.logicalRect(); auto floatConstraints = floatingContext.constraints(LayoutUnit { lineBoxRect.top() }, LayoutUnit { lineBoxRect.bottom() }, FloatingContext::MayBeAboveLastFloat::No); diff --git a/Source/WebCore/layout/formattingContexts/inline/InlineLineBuilder.cpp b/Source/WebCore/layout/formattingContexts/inline/InlineLineBuilder.cpp index 505292f2e441..fff51fd581e9 100644 --- a/Source/WebCore/layout/formattingContexts/inline/InlineLineBuilder.cpp +++ b/Source/WebCore/layout/formattingContexts/inline/InlineLineBuilder.cpp @@ -229,6 +229,7 @@ LineBuilder::LineBuilder(InlineFormattingContext& inlineFormattingContext, Horiz : m_inlineFormattingContext(inlineFormattingContext) , m_rootHorizontalConstraints(rootHorizontalConstraints) , m_line(inlineFormattingContext) + , m_floatingContext(inlineFormattingContext, inlineFormattingContext.inlineLayoutState().placedFloats()) , m_inlineItemList(inlineItemList) { } @@ -742,10 +743,10 @@ static inline InlineLayoutUnit availableWidth(const LineCandidate::InlineContent LineBuilder::UsedConstraints LineBuilder::floatConstrainedRect(const InlineRect& logicalRect, InlineLayoutUnit marginStart) const { auto constraints = [&]() -> LineBuilder::UsedConstraints { - if (isInIntrinsicWidthMode() || placedFloats().isEmpty()) + if (isInIntrinsicWidthMode() || floatingContext().isEmpty()) return { logicalRect, marginStart, { } }; - auto constraints = formattingContext().formattingUtils().floatConstraintsForLine(logicalRect.top(), logicalRect.height(), FloatingContext { formattingContext(), placedFloats() }); + auto constraints = formattingContext().formattingUtils().floatConstraintsForLine(logicalRect.top(), logicalRect.height(), floatingContext()); if (!constraints.left && !constraints.right) return { logicalRect, marginStart, { } }; @@ -888,7 +889,7 @@ bool LineBuilder::tryPlacingFloatBox(const Box& floatBox, MayOverConstrainLine m if (isFloatLayoutSuspended()) return false; - auto floatingContext = FloatingContext { formattingContext(), placedFloats() }; + auto& floatingContext = this->floatingContext(); auto boxGeometry = [&]() -> BoxGeometry { auto marginTrim = rootStyle().marginTrim(); if (!marginTrim.containsAny({ MarginTrimType::InlineStart, MarginTrimType::InlineEnd }) || m_lineIsConstrainedByFloat.containsAll({ UsedFloat::Left, UsedFloat::Right })) @@ -955,8 +956,7 @@ bool LineBuilder::tryPlacingFloatBox(const Box& floatBox, MayOverConstrainLine m auto placeFloatBox = [&] { auto lineIndex = m_previousLine ? (m_previousLine->lineIndex + 1) : 0lu; auto floatItem = floatingContext.makeFloatItem(floatBox, boxGeometry, lineIndex); - // FIXME: Maybe FloatingContext should be able to preserve FloatItems and the caller should mutate the PlacedFloats instead. - placedFloats().append(floatItem); + inlineLayoutState().placedFloats().append(floatItem); m_placedFloats.append(floatItem); }; placeFloatBox(); @@ -1238,9 +1238,9 @@ const InlineLayoutState& LineBuilder::inlineLayoutState() const return formattingContext().inlineLayoutState(); } -PlacedFloats& LineBuilder::placedFloats() +InlineLayoutState& LineBuilder::inlineLayoutState() { - return formattingContext().placedFloats(); + return formattingContext().inlineLayoutState(); } } diff --git a/Source/WebCore/layout/formattingContexts/inline/InlineLineBuilder.h b/Source/WebCore/layout/formattingContexts/inline/InlineLineBuilder.h index e2467ae8677c..553c6f1d6e1f 100644 --- a/Source/WebCore/layout/formattingContexts/inline/InlineLineBuilder.h +++ b/Source/WebCore/layout/formattingContexts/inline/InlineLineBuilder.h @@ -93,10 +93,11 @@ class LineBuilder : public AbstractLineBuilder { InlineFormattingContext& formattingContext() { return m_inlineFormattingContext; } const InlineFormattingContext& formattingContext() const { return m_inlineFormattingContext; } + const FloatingContext& floatingContext() const { return m_floatingContext; } + const InlineLayoutState& inlineLayoutState() const; + InlineLayoutState& inlineLayoutState(); const BlockLayoutState& blockLayoutState() const { return inlineLayoutState().parentBlockLayoutState(); } - PlacedFloats& placedFloats(); - const PlacedFloats& placedFloats() const { return const_cast(*this).placedFloats(); } const ElementBox& root() const; const RenderStyle& rootStyle() const; @@ -106,6 +107,7 @@ class LineBuilder : public AbstractLineBuilder { std::optional m_rootHorizontalConstraints; Line m_line; + FloatingContext m_floatingContext; InlineRect m_lineInitialLogicalRect; InlineRect m_lineLogicalRect; InlineLayoutUnit m_lineMarginStart { 0.f }; diff --git a/Source/WebCore/page/OpportunisticTaskScheduler.cpp b/Source/WebCore/page/OpportunisticTaskScheduler.cpp index 445a1dd85308..e217e186fd2c 100644 --- a/Source/WebCore/page/OpportunisticTaskScheduler.cpp +++ b/Source/WebCore/page/OpportunisticTaskScheduler.cpp @@ -101,6 +101,9 @@ void OpportunisticTaskScheduler::runLoopObserverFired() if (UNLIKELY(!page)) return; + if (!page->settings().opportunisticSweepingAndGarbageCollectionEnabled()) + return; + page->performOpportunisticallyScheduledTasks(deadline); } diff --git a/Source/WebCore/page/UserScript.h b/Source/WebCore/page/UserScript.h index 503342a3550f..e28fdbc6ead7 100644 --- a/Source/WebCore/page/UserScript.h +++ b/Source/WebCore/page/UserScript.h @@ -60,9 +60,6 @@ class UserScript { UserContentInjectedFrames injectedFrames() const { return m_injectedFrames; } WaitForNotificationBeforeInjecting waitForNotificationBeforeInjecting() const { return m_waitForNotificationBeforeInjecting; } - template void encode(Encoder&) const; - template static std::optional decode(Decoder&); - private: String m_source; URL m_url; @@ -73,65 +70,4 @@ class UserScript { WaitForNotificationBeforeInjecting m_waitForNotificationBeforeInjecting { WaitForNotificationBeforeInjecting::No }; }; -template -void UserScript::encode(Encoder& encoder) const -{ - encoder << m_source; - encoder << m_url; - encoder << m_allowlist; - encoder << m_blocklist; - encoder << m_injectionTime; - encoder << m_injectedFrames; - encoder << m_waitForNotificationBeforeInjecting; -} - -template -std::optional UserScript::decode(Decoder& decoder) -{ - std::optional source; - decoder >> source; - if (!source) - return std::nullopt; - - std::optional url; - decoder >> url; - if (!url) - return std::nullopt; - - std::optional> allowlist; - decoder >> allowlist; - if (!allowlist) - return std::nullopt; - - std::optional> blocklist; - decoder >> blocklist; - if (!blocklist) - return std::nullopt; - - std::optional injectionTime; - decoder >> injectionTime; - if (!injectionTime) - return std::nullopt; - - std::optional injectedFrames; - decoder >> injectedFrames; - if (!injectedFrames) - return std::nullopt; - - std::optional waitForNotification; - decoder >> waitForNotification; - if (!waitForNotification) - return std::nullopt; - - return {{ - WTFMove(*source), - WTFMove(*url), - WTFMove(*allowlist), - WTFMove(*blocklist), - WTFMove(*injectionTime), - WTFMove(*injectedFrames), - WTFMove(*waitForNotification) - }}; -} - } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/FontSizeAdjust.h b/Source/WebCore/platform/graphics/FontSizeAdjust.h index 911d252bda13..a4a92eb858db 100644 --- a/Source/WebCore/platform/graphics/FontSizeAdjust.h +++ b/Source/WebCore/platform/graphics/FontSizeAdjust.h @@ -31,18 +31,6 @@ namespace WebCore { -struct FloatMarkableTraits { - constexpr static bool isEmptyValue(float value) - { - return value != value; - } - - constexpr static float emptyValue() - { - return std::numeric_limits::quiet_NaN(); - } -}; - struct FontSizeAdjust { friend bool operator==(const FontSizeAdjust&, const FontSizeAdjust&) = default; @@ -55,7 +43,7 @@ struct FontSizeAdjust { }; Metric metric { Metric::ExHeight }; bool isFromFont { false }; - Markable value { }; + Markable value { }; }; inline void add(Hasher& hasher, const FontSizeAdjust& fontSizeAdjust) diff --git a/Source/WebCore/platform/graphics/cg/GradientRendererCG.cpp b/Source/WebCore/platform/graphics/cg/GradientRendererCG.cpp index f61a8e537a02..c3fd9794c5ef 100644 --- a/Source/WebCore/platform/graphics/cg/GradientRendererCG.cpp +++ b/Source/WebCore/platform/graphics/cg/GradientRendererCG.cpp @@ -486,10 +486,7 @@ GradientRendererCG::Strategy GradientRendererCG::makeGradient(ColorInterpolation if (hasOnlyBoundedSRGBColorStops(stops)) { for (const auto& stop : stops) { auto [r, g, b, a] = stop.color.toColorTypeLossy>().resolved(); - colorComponents.uncheckedAppend(r); - colorComponents.uncheckedAppend(g); - colorComponents.uncheckedAppend(b); - colorComponents.uncheckedAppend(a); + colorComponents.appendList({ r, g, b, a }); locations.uncheckedAppend(stop.offset); } @@ -499,10 +496,7 @@ GradientRendererCG::Strategy GradientRendererCG::makeGradient(ColorInterpolation using OutputSpaceColorType = std::conditional_t, ExtendedSRGBA, SRGBA>; for (const auto& stop : stops) { auto [r, g, b, a] = stop.color.toColorTypeLossy().resolved(); - colorComponents.uncheckedAppend(r); - colorComponents.uncheckedAppend(g); - colorComponents.uncheckedAppend(b); - colorComponents.uncheckedAppend(a); + colorComponents.appendList({ r, g, b, a }); locations.uncheckedAppend(stop.offset); } diff --git a/Source/WebCore/platform/graphics/gstreamer/eme/CDMThunder.cpp b/Source/WebCore/platform/graphics/gstreamer/eme/CDMThunder.cpp index f9cb1e675129..2bdbafd656ac 100644 --- a/Source/WebCore/platform/graphics/gstreamer/eme/CDMThunder.cpp +++ b/Source/WebCore/platform/graphics/gstreamer/eme/CDMThunder.cpp @@ -150,11 +150,7 @@ Vector CDMPrivateThunder::supportedInitDataTypes() const static std::once_flag onceFlag; static Vector supportedInitDataTypes; std::call_once(onceFlag, [] { - supportedInitDataTypes.reserveInitialCapacity(4); - supportedInitDataTypes.uncheckedAppend("keyids"_s); - supportedInitDataTypes.uncheckedAppend("cenc"_s); - supportedInitDataTypes.uncheckedAppend("webm"_s); - supportedInitDataTypes.uncheckedAppend("cbcs"_s); + supportedInitDataTypes.appendList({ "keyids"_s, "cenc"_s, "webm"_s, "cbcs"_s }); }); return supportedInitDataTypes; } diff --git a/Source/WebCore/platform/mediastream/MediaStreamTrackPrivate.cpp b/Source/WebCore/platform/mediastream/MediaStreamTrackPrivate.cpp index 1df3c4f7f2d2..e0f404b05bf0 100644 --- a/Source/WebCore/platform/mediastream/MediaStreamTrackPrivate.cpp +++ b/Source/WebCore/platform/mediastream/MediaStreamTrackPrivate.cpp @@ -34,6 +34,7 @@ #include "IntRect.h" #include "Logging.h" #include "PlatformMediaSessionManager.h" +#include #include #if PLATFORM(COCOA) @@ -188,6 +189,11 @@ void MediaStreamTrackPrivate::getPhotoCapabilities(RealtimeMediaSource::PhotoCap m_source->getPhotoCapabilities(WTFMove(completion)); } +Ref MediaStreamTrackPrivate::getPhotoSettings() +{ + return m_source->getPhotoSettings(); +} + void MediaStreamTrackPrivate::applyConstraints(const MediaConstraints& constraints, RealtimeMediaSource::ApplyConstraintsHandler&& completionHandler) { m_source->applyConstraints(constraints, WTFMove(completionHandler)); diff --git a/Source/WebCore/platform/mediastream/MediaStreamTrackPrivate.h b/Source/WebCore/platform/mediastream/MediaStreamTrackPrivate.h index b7017a9b65c4..7d35c42c29ab 100644 --- a/Source/WebCore/platform/mediastream/MediaStreamTrackPrivate.h +++ b/Source/WebCore/platform/mediastream/MediaStreamTrackPrivate.h @@ -111,6 +111,7 @@ class MediaStreamTrackPrivate final const RealtimeMediaSourceCapabilities& capabilities() const; void getPhotoCapabilities(RealtimeMediaSource::PhotoCapabilitiesHandler&&); + Ref getPhotoSettings(); void applyConstraints(const MediaConstraints&, RealtimeMediaSource::ApplyConstraintsHandler&&); diff --git a/Source/WebCore/platform/mediastream/PhotoSettings.h b/Source/WebCore/platform/mediastream/PhotoSettings.h new file mode 100644 index 000000000000..3e3a15ef41c8 --- /dev/null +++ b/Source/WebCore/platform/mediastream/PhotoSettings.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2023 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#if ENABLE(MEDIA_STREAM) + +#include + +namespace WebCore { + +enum class FillLightMode : uint8_t; + +struct PhotoSettings { + std::optional fillLightMode; + std::optional imageHeight; + std::optional imageWidth; + std::optional redEyeReduction; +}; + +} + +#endif diff --git a/Source/WebCore/platform/mediastream/RealtimeMediaSource.cpp b/Source/WebCore/platform/mediastream/RealtimeMediaSource.cpp index b688267b0a00..d610c620c5fe 100644 --- a/Source/WebCore/platform/mediastream/RealtimeMediaSource.cpp +++ b/Source/WebCore/platform/mediastream/RealtimeMediaSource.cpp @@ -45,6 +45,7 @@ #include #include #include +#include #include #include @@ -1460,6 +1461,11 @@ void RealtimeMediaSource::getPhotoCapabilities(PhotoCapabilitiesHandler&& comple completion(PhotoCapabilitiesOrError("Not supported"_s)); } +auto RealtimeMediaSource::getPhotoSettings() -> Ref +{ + return PhotoSettingsPromise::createAndReject("Not supported"_s); +} + RealtimeMediaSource::Observer::~Observer() { } diff --git a/Source/WebCore/platform/mediastream/RealtimeMediaSource.h b/Source/WebCore/platform/mediastream/RealtimeMediaSource.h index 286cade60155..1504e07d52c5 100644 --- a/Source/WebCore/platform/mediastream/RealtimeMediaSource.h +++ b/Source/WebCore/platform/mediastream/RealtimeMediaSource.h @@ -41,6 +41,7 @@ #include "MediaConstraints.h" #include "MediaDeviceHashSalts.h" #include "PhotoCapabilities.h" +#include "PhotoSettings.h" #include "PlatformLayer.h" #include "RealtimeMediaSourceCapabilities.h" #include "RealtimeMediaSourceFactory.h" @@ -48,6 +49,7 @@ #include "VideoFrameTimeMetadata.h" #include #include +#include #include #include #include @@ -212,6 +214,9 @@ class WEBCORE_EXPORT RealtimeMediaSource using PhotoCapabilitiesHandler = CompletionHandler; virtual void getPhotoCapabilities(PhotoCapabilitiesHandler&&); + using PhotoSettingsPromise = NativePromise; + virtual Ref getPhotoSettings(); + struct ApplyConstraintsError { String badConstraint; String message; diff --git a/Source/WebCore/platform/mediastream/mac/AVVideoCaptureSource.h b/Source/WebCore/platform/mediastream/mac/AVVideoCaptureSource.h index 21f55776067c..685055f14462 100644 --- a/Source/WebCore/platform/mediastream/mac/AVVideoCaptureSource.h +++ b/Source/WebCore/platform/mediastream/mac/AVVideoCaptureSource.h @@ -85,6 +85,7 @@ class AVVideoCaptureSource : public RealtimeVideoCaptureSource, private Orientat const RealtimeMediaSourceCapabilities& capabilities() final; const RealtimeMediaSourceSettings& settings() final; void getPhotoCapabilities(PhotoCapabilitiesHandler&&) final; + Ref getPhotoSettings() final; double facingModeFitnessScoreAdjustment() const final; void startProducingData() final; void stopProducingData() final; @@ -147,6 +148,7 @@ class AVVideoCaptureSource : public RealtimeVideoCaptureSource, private Orientat std::optional m_currentSettings; std::optional m_capabilities; std::optional m_photoCapabilities; + std::optional m_photoSettings; RetainPtr m_objcObserver; RetainPtr m_session; RetainPtr m_device; diff --git a/Source/WebCore/platform/mediastream/mac/AVVideoCaptureSource.mm b/Source/WebCore/platform/mediastream/mac/AVVideoCaptureSource.mm index 31b66ccb79ef..ff5a0905d6ed 100644 --- a/Source/WebCore/platform/mediastream/mac/AVVideoCaptureSource.mm +++ b/Source/WebCore/platform/mediastream/mac/AVVideoCaptureSource.mm @@ -28,6 +28,7 @@ #if ENABLE(MEDIA_STREAM) && USE(AVFOUNDATION) +#import "FillLightMode.h" #import "ImageBuffer.h" #import "ImageTransferSessionVT.h" #import "IntRect.h" @@ -46,6 +47,7 @@ #import #import #import +#import #import #import "CoreVideoSoftLink.h" @@ -467,6 +469,43 @@ static bool isZoomSupported(const Vector& presets) completion({ *m_photoCapabilities }); } +static FillLightMode toFillLightMode(AVCaptureTorchMode mode) +{ + switch (mode) { + case AVCaptureTorchModeOff: + return FillLightMode::Off; + break; + case AVCaptureTorchModeOn: + return FillLightMode::Flash; + break; + case AVCaptureTorchModeAuto: + return FillLightMode::Auto; + break; + } + + ASSERT_NOT_REACHED(); + return FillLightMode::Auto; +} + +auto AVVideoCaptureSource::getPhotoSettings() -> Ref +{ + if (m_photoSettings) + return PhotoSettingsPromise::createAndResolve(*m_photoSettings); + + PhotoSettings photoSettings; + auto settings = this->settings(); + + photoSettings.imageHeight = settings.height(); + photoSettings.imageWidth = settings.width(); + + if ([device() hasTorch]) + photoSettings.fillLightMode = { toFillLightMode([device() torchMode]) }; + + m_photoSettings = WTFMove(photoSettings); + + return PhotoSettingsPromise::createAndResolve(*m_photoSettings); +} + NSMutableArray* AVVideoCaptureSource::cameraCaptureDeviceTypes() { ASSERT(isMainThread()); diff --git a/Source/WebCore/platform/mock/MockRealtimeVideoSource.cpp b/Source/WebCore/platform/mock/MockRealtimeVideoSource.cpp index 44b79b790d89..254733df46d7 100644 --- a/Source/WebCore/platform/mock/MockRealtimeVideoSource.cpp +++ b/Source/WebCore/platform/mock/MockRealtimeVideoSource.cpp @@ -33,6 +33,7 @@ #if ENABLE(MEDIA_STREAM) #include "CaptureDevice.h" +#include "FillLightMode.h" #include "GraphicsContext.h" #include "ImageBuffer.h" #include "IntRect.h" @@ -44,6 +45,7 @@ #include "RealtimeMediaSourceSettings.h" #include "VideoFrame.h" #include +#include #include #include @@ -86,9 +88,7 @@ MockRealtimeVideoSource::MockRealtimeVideoSource(String&& deviceID, AtomString&& ASSERT(device); m_device = *device; - m_dashWidths.reserveInitialCapacity(2); - m_dashWidths.uncheckedAppend(6); - m_dashWidths.uncheckedAppend(6); + m_dashWidths.appendList({ 6, 6 }); if (mockDisplay()) { auto& properties = std::get(m_device.properties); @@ -204,6 +204,27 @@ void MockRealtimeVideoSource::getPhotoCapabilities(PhotoCapabilitiesHandler&& co completion({ *m_photoCapabilities }); } +auto MockRealtimeVideoSource::getPhotoSettings() -> Ref +{ + if (m_photoSettings) + return PhotoSettingsPromise::createAndResolve(*m_photoSettings); + + PhotoSettings photoSettings; + auto settings = this->settings(); + + photoSettings.imageHeight = settings.height(); + photoSettings.imageWidth = settings.width(); + + if (std::get(m_device.properties).hasTorch) { + auto fillLightMode = torch() ? FillLightMode::Flash : FillLightMode::Off; + photoSettings.fillLightMode = { fillLightMode }; + } + + m_photoSettings = WTFMove(photoSettings); + + return PhotoSettingsPromise::createAndResolve(*m_photoSettings); +} + static bool isZoomSupported(const Vector& presets) { return anyOf(presets, [](auto& preset) { @@ -302,6 +323,8 @@ void MockRealtimeVideoSource::settingsDidChange(OptionSet getPhotoSettings() final; void startProducingData() override; void stopProducingData() override; @@ -124,6 +125,7 @@ class MockRealtimeVideoSource : public RealtimeVideoCaptureSource, private Orien std::optional m_capabilities; std::optional m_currentSettings; std::optional m_photoCapabilities; + std::optional m_photoSettings; RealtimeMediaSourceSupportedConstraints m_supportedConstraints; Color m_fillColor { Color::black }; Color m_fillColorWithZoom { Color::red }; diff --git a/Source/WebCore/platform/text/LocaleNone.cpp b/Source/WebCore/platform/text/LocaleNone.cpp index a8da65620974..55824cf26807 100644 --- a/Source/WebCore/platform/text/LocaleNone.cpp +++ b/Source/WebCore/platform/text/LocaleNone.cpp @@ -136,9 +136,7 @@ const Vector& LocaleNone::timeAMPMLabels() { if (!m_timeAMPMLabels.isEmpty()) return m_timeAMPMLabels; - m_timeAMPMLabels.reserveCapacity(2); - m_timeAMPMLabels.uncheckedAppend("AM"); - m_timeAMPMLabels.uncheckedAppend("PM"); + m_timeAMPMLabels.appendList({ "AM"_s, "PM"_s }); return m_timeAMPMLabels; } diff --git a/Source/WebCore/rendering/RenderBox.h b/Source/WebCore/rendering/RenderBox.h index c5b3e62ddd76..0723d468834d 100644 --- a/Source/WebCore/rendering/RenderBox.h +++ b/Source/WebCore/rendering/RenderBox.h @@ -134,6 +134,7 @@ class RenderBox : public RenderBoxModelObject { void addFocusRingRects(Vector&, const LayoutPoint& additionalOffset, const RenderLayerModelObject* paintContainer = nullptr) const override; FloatRect repaintRectInLocalCoordinates() const override { return borderBoxRect(); } + FloatRect fastRepaintRectInLocalCoordinates() const override { return borderBoxRect(); } FloatRect objectBoundingBox() const override { return borderBoxRect(); } // Note these functions are not equivalent of childrenOfType diff --git a/Source/WebCore/rendering/RenderObject.cpp b/Source/WebCore/rendering/RenderObject.cpp index 04beaa430b08..343120581cc0 100644 --- a/Source/WebCore/rendering/RenderObject.cpp +++ b/Source/WebCore/rendering/RenderObject.cpp @@ -2089,6 +2089,12 @@ FloatRect RenderObject::repaintRectInLocalCoordinates() const return FloatRect(); } +FloatRect RenderObject::fastRepaintRectInLocalCoordinates() const +{ + ASSERT_NOT_REACHED(); + return FloatRect(); +} + AffineTransform RenderObject::localTransform() const { return AffineTransform(); diff --git a/Source/WebCore/rendering/RenderObject.h b/Source/WebCore/rendering/RenderObject.h index 6fae4a3c7fe8..71c981c8fe2d 100644 --- a/Source/WebCore/rendering/RenderObject.h +++ b/Source/WebCore/rendering/RenderObject.h @@ -507,6 +507,10 @@ class RenderObject : public CachedImageClient, public CanMakeCheckedPtr { // respecting clipping, masking, filters, opacity, stroke-width and markers virtual FloatRect repaintRectInLocalCoordinates() const; + // Returns approximate rectangle enclosing all of the painted content. + // This is always larger-or-equal to repaintRectInLocalCoordinates(). + virtual FloatRect fastRepaintRectInLocalCoordinates() const; + // This only returns the transform="" value from the element // most callsites want localToParentTransform() instead. virtual AffineTransform localTransform() const; diff --git a/Source/WebCore/rendering/RenderText.cpp b/Source/WebCore/rendering/RenderText.cpp index 739a14185e10..12d1763d25a6 100644 --- a/Source/WebCore/rendering/RenderText.cpp +++ b/Source/WebCore/rendering/RenderText.cpp @@ -84,16 +84,14 @@ using namespace WTF::Unicode; WTF_MAKE_ISO_ALLOCATED_IMPL(RenderText); struct SameSizeAsRenderText : public RenderObject { - void* pointers[2]; - uint32_t bitfields : 16; #if ENABLE(TEXT_AUTOSIZING) float candidateTextSize; #endif - float widths[2]; - std::optional minWidth; - std::optional maxWidth; - std::optional canUseSimplifiedTextMeasuring; + float widths[4]; + void* pointers[2]; String text; + std::optional canUseSimplifiedTextMeasuring; + uint32_t bitfields : 16; }; static_assert(sizeof(RenderText) == sizeof(SameSizeAsRenderText), "RenderText should stay small"); @@ -247,8 +245,8 @@ static unsigned offsetForPositionInRun(const InlineIterator::TextBox& textBox, f inline RenderText::RenderText(Type type, Node& node, const String& text) : RenderObject(type, node) - , m_containsOnlyASCII(text.impl()->containsOnlyASCII()) , m_text(text) + , m_containsOnlyASCII(text.impl()->containsOnlyASCII()) { ASSERT(!m_text.isNull()); setIsText(); diff --git a/Source/WebCore/rendering/RenderText.h b/Source/WebCore/rendering/RenderText.h index 8bb51d342e49..e92fa3340ff8 100644 --- a/Source/WebCore/rendering/RenderText.h +++ b/Source/WebCore/rendering/RenderText.h @@ -26,6 +26,7 @@ #include "RenderTextLineBoxes.h" #include "Text.h" #include +#include #include namespace WebCore { @@ -229,16 +230,27 @@ class RenderText : public RenderObject { float maxWordFragmentWidth(const RenderStyle&, const FontCascade&, StringView word, unsigned minimumPrefixLength, unsigned minimumSuffixLength, bool currentCharacterIsSpace, unsigned characterIndex, float xPos, float entireWordWidth, WordTrailingSpace&, WeakHashSet& fallbackFonts, GlyphOverflow&); float widthFromCacheConsideringPossibleTrailingSpace(const RenderStyle&, const FontCascade&, unsigned startIndex, unsigned wordLen, float xPos, bool currentCharacterIsSpace, WordTrailingSpace&, WeakHashSet& fallbackFonts, GlyphOverflow&) const; - // We put the bitfield first to minimize padding on 64-bit. +#if ENABLE(TEXT_AUTOSIZING) + // FIXME: This should probably be part of the text sizing structures in Document instead. That would save some memory. + float m_candidateComputedTextSize { 0 }; +#endif + Markable m_minWidth; + Markable m_maxWidth; + float m_beginMinWidth { 0 }; + float m_endMinWidth { 0 }; + + String m_text; + + std::optional m_canUseSimplifiedTextMeasuring; unsigned m_hasBreakableChar : 1 { false }; // Whether or not we can be broken into multiple lines. unsigned m_hasBreak : 1 { false }; // Whether or not we have a hard break (e.g.,
 with '\n').
     unsigned m_hasTab : 1 { false }; // Whether or not we have a variable width tab character (e.g., 
 with '\t').
     unsigned m_hasBeginWS : 1 { false }; // Whether or not we begin with WS (only true if we aren't pre)
     unsigned m_hasEndWS : 1 { false }; // Whether or not we end with WS (only true if we aren't pre)
     unsigned m_linesDirty : 1 { false }; // This bit indicates that the text run has already dirtied specific
-                           // line boxes, and this hint will enable layoutInlineChildren to avoid
-                           // just dirtying everything when character data is modified (e.g., appended/inserted
-                           // or removed).
+                                         // line boxes, and this hint will enable layoutInlineChildren to avoid
+                                         // just dirtying everything when character data is modified (e.g., appended/inserted
+                                         // or removed).
     unsigned m_needsVisualReordering : 1 { false };
     unsigned m_containsOnlyASCII : 1 { false };
     unsigned m_canUseSimpleFontCodePath : 1 { false };
@@ -246,18 +258,6 @@ class RenderText : public RenderObject {
     unsigned m_useBackslashAsYenSymbol : 1 { false };
     unsigned m_originalTextDiffersFromRendered : 1 { false };
     unsigned m_hasInlineWrapperForDisplayContents : 1 { false };
-
-#if ENABLE(TEXT_AUTOSIZING)
-    // FIXME: This should probably be part of the text sizing structures in Document instead. That would save some memory.
-    float m_candidateComputedTextSize { 0 };
-#endif
-    std::optional m_minWidth;
-    std::optional m_maxWidth;
-    std::optional m_canUseSimplifiedTextMeasuring { };
-    float m_beginMinWidth { 0 };
-    float m_endMinWidth { 0 };
-
-    String m_text;
 };
 
 String applyTextTransform(const RenderStyle&, const String&, UChar previousCharacter);
diff --git a/Source/WebCore/rendering/svg/RenderSVGContainer.h b/Source/WebCore/rendering/svg/RenderSVGContainer.h
index 130f5be006bc..bb05d9bbc247 100644
--- a/Source/WebCore/rendering/svg/RenderSVGContainer.h
+++ b/Source/WebCore/rendering/svg/RenderSVGContainer.h
@@ -46,6 +46,7 @@ class RenderSVGContainer : public RenderSVGModelObject {
     FloatRect objectBoundingBoxWithoutTransformations() const final { return m_objectBoundingBoxWithoutTransformations; }
     FloatRect strokeBoundingBox() const final { return m_strokeBoundingBox; }
     FloatRect repaintRectInLocalCoordinates() const final { return SVGBoundingBoxComputation::computeRepaintBoundingBox(*this); }
+    FloatRect fastRepaintRectInLocalCoordinates() const final { return repaintRectInLocalCoordinates(); }
 
 protected:
     RenderSVGContainer(Type, Document&, RenderStyle&&);
diff --git a/Source/WebCore/rendering/svg/RenderSVGForeignObject.h b/Source/WebCore/rendering/svg/RenderSVGForeignObject.h
index f4b264084c54..8290c8172cd6 100644
--- a/Source/WebCore/rendering/svg/RenderSVGForeignObject.h
+++ b/Source/WebCore/rendering/svg/RenderSVGForeignObject.h
@@ -47,6 +47,7 @@ class RenderSVGForeignObject final : public RenderSVGBlock {
     FloatRect objectBoundingBox() const final { return m_viewport; }
     FloatRect strokeBoundingBox() const final { return m_viewport; }
     FloatRect repaintRectInLocalCoordinates() const final { return SVGBoundingBoxComputation::computeRepaintBoundingBox(*this); }
+    FloatRect fastRepaintRectInLocalCoordinates() const final { return repaintRectInLocalCoordinates(); }
 
 private:
     void graphicsElement() const = delete;
diff --git a/Source/WebCore/rendering/svg/RenderSVGGradientStop.h b/Source/WebCore/rendering/svg/RenderSVGGradientStop.h
index 08ffed03301b..d0391165dcc3 100644
--- a/Source/WebCore/rendering/svg/RenderSVGGradientStop.h
+++ b/Source/WebCore/rendering/svg/RenderSVGGradientStop.h
@@ -49,6 +49,7 @@ class RenderSVGGradientStop final : public RenderElement {
     FloatRect objectBoundingBox() const override { return FloatRect(); }
     FloatRect strokeBoundingBox() const override { return FloatRect(); }
     FloatRect repaintRectInLocalCoordinates() const override { return FloatRect(); }
+    FloatRect fastRepaintRectInLocalCoordinates() const override { return repaintRectInLocalCoordinates(); }
     bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint&, HitTestAction) override { return false; }
 
     ASCIILiteral renderName() const override { return "RenderSVGGradientStop"_s; }
diff --git a/Source/WebCore/rendering/svg/RenderSVGImage.h b/Source/WebCore/rendering/svg/RenderSVGImage.h
index 16b52dbc7013..f700c685b060 100644
--- a/Source/WebCore/rendering/svg/RenderSVGImage.h
+++ b/Source/WebCore/rendering/svg/RenderSVGImage.h
@@ -58,6 +58,7 @@ class RenderSVGImage final : public RenderSVGModelObject {
     FloatRect objectBoundingBox() const final { return m_objectBoundingBox; }
     FloatRect strokeBoundingBox() const final { return m_objectBoundingBox; }
     FloatRect repaintRectInLocalCoordinates() const final { return SVGBoundingBoxComputation::computeRepaintBoundingBox(*this); }
+    FloatRect fastRepaintRectInLocalCoordinates() const final { return repaintRectInLocalCoordinates(); }
 
     void imageChanged(WrappedImagePtr, const IntRect* = nullptr) final;
 
diff --git a/Source/WebCore/rendering/svg/RenderSVGInline.h b/Source/WebCore/rendering/svg/RenderSVGInline.h
index 55138c136204..75cf40f6959f 100644
--- a/Source/WebCore/rendering/svg/RenderSVGInline.h
+++ b/Source/WebCore/rendering/svg/RenderSVGInline.h
@@ -49,6 +49,7 @@ class RenderSVGInline : public RenderInline {
     FloatRect objectBoundingBox() const final;
     FloatRect strokeBoundingBox() const final;
     FloatRect repaintRectInLocalCoordinates() const final;
+    FloatRect fastRepaintRectInLocalCoordinates() const final { return repaintRectInLocalCoordinates(); }
 
 #if ENABLE(LAYER_BASED_SVG_ENGINE)
     LayoutPoint currentSVGLayoutLocation() const final { return { }; }
diff --git a/Source/WebCore/rendering/svg/RenderSVGRoot.h b/Source/WebCore/rendering/svg/RenderSVGRoot.h
index 49b6572aa5e6..e039638b7761 100644
--- a/Source/WebCore/rendering/svg/RenderSVGRoot.h
+++ b/Source/WebCore/rendering/svg/RenderSVGRoot.h
@@ -68,6 +68,7 @@ class RenderSVGRoot final : public RenderReplaced {
     FloatRect objectBoundingBoxWithoutTransformations() const final { return m_objectBoundingBoxWithoutTransformations; }
     FloatRect strokeBoundingBox() const final { return m_strokeBoundingBox; }
     FloatRect repaintRectInLocalCoordinates() const final { return SVGBoundingBoxComputation::computeRepaintBoundingBox(*this); }
+    FloatRect fastRepaintRectInLocalCoordinates() const final { return repaintRectInLocalCoordinates(); }
 
     LayoutRect visualOverflowRectEquivalent() const { return SVGBoundingBoxComputation::computeVisualOverflowRect(*this); }
 
diff --git a/Source/WebCore/rendering/svg/RenderSVGShape.h b/Source/WebCore/rendering/svg/RenderSVGShape.h
index 8f4cade05c8c..95cf30364ead 100644
--- a/Source/WebCore/rendering/svg/RenderSVGShape.h
+++ b/Source/WebCore/rendering/svg/RenderSVGShape.h
@@ -79,6 +79,7 @@ class RenderSVGShape : public RenderSVGModelObject {
     FloatRect objectBoundingBox() const final { return m_fillBoundingBox; }
     FloatRect strokeBoundingBox() const final { return m_strokeBoundingBox; }
     FloatRect repaintRectInLocalCoordinates() const final { return SVGBoundingBoxComputation::computeRepaintBoundingBox(*this); }
+    FloatRect fastRepaintRectInLocalCoordinates() const final { return repaintRectInLocalCoordinates(); }
 
     FloatRect computeMarkerBoundingBox(const SVGBoundingBoxComputation::DecorationOptions&) const;
 
diff --git a/Source/WebCore/rendering/svg/RenderSVGText.h b/Source/WebCore/rendering/svg/RenderSVGText.h
index 05333242ba93..c99ecdd9c245 100644
--- a/Source/WebCore/rendering/svg/RenderSVGText.h
+++ b/Source/WebCore/rendering/svg/RenderSVGText.h
@@ -63,6 +63,7 @@ class RenderSVGText final : public RenderSVGBlock {
     FloatRect objectBoundingBox() const final { return m_objectBoundingBox; }
     FloatRect strokeBoundingBox() const final;
     FloatRect repaintRectInLocalCoordinates() const final;
+    FloatRect fastRepaintRectInLocalCoordinates() const final { return repaintRectInLocalCoordinates(); }
 
 #if ENABLE(LAYER_BASED_SVG_ENGINE)
     LayoutRect visualOverflowRectEquivalent() const { return SVGBoundingBoxComputation::computeVisualOverflowRect(*this); }
diff --git a/Source/WebCore/rendering/svg/legacy/LegacyRenderSVGContainer.h b/Source/WebCore/rendering/svg/legacy/LegacyRenderSVGContainer.h
index b3b8153454e1..6f038bd6e48c 100644
--- a/Source/WebCore/rendering/svg/legacy/LegacyRenderSVGContainer.h
+++ b/Source/WebCore/rendering/svg/legacy/LegacyRenderSVGContainer.h
@@ -53,6 +53,7 @@ class LegacyRenderSVGContainer : public LegacyRenderSVGModelObject {
     FloatRect objectBoundingBox() const final { return m_objectBoundingBox; }
     FloatRect strokeBoundingBox() const final { return m_strokeBoundingBox; }
     FloatRect repaintRectInLocalCoordinates() const final { return m_repaintBoundingBox; }
+    FloatRect fastRepaintRectInLocalCoordinates() const final { return repaintRectInLocalCoordinates(); }
 
     bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction) override;
 
diff --git a/Source/WebCore/rendering/svg/legacy/LegacyRenderSVGForeignObject.h b/Source/WebCore/rendering/svg/legacy/LegacyRenderSVGForeignObject.h
index d95486a3f865..988f80614009 100644
--- a/Source/WebCore/rendering/svg/legacy/LegacyRenderSVGForeignObject.h
+++ b/Source/WebCore/rendering/svg/legacy/LegacyRenderSVGForeignObject.h
@@ -45,6 +45,7 @@ class LegacyRenderSVGForeignObject final : public RenderSVGBlock {
     FloatRect objectBoundingBox() const override { return FloatRect(FloatPoint(), m_viewport.size()); }
     FloatRect strokeBoundingBox() const override { return FloatRect(FloatPoint(), m_viewport.size()); }
     FloatRect repaintRectInLocalCoordinates() const override { return FloatRect(FloatPoint(), m_viewport.size()); }
+    FloatRect fastRepaintRectInLocalCoordinates() const override { return repaintRectInLocalCoordinates(); }
 
     bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction) override;
 
diff --git a/Source/WebCore/rendering/svg/legacy/LegacyRenderSVGImage.h b/Source/WebCore/rendering/svg/legacy/LegacyRenderSVGImage.h
index 9197394249e4..45ff9c45d2cc 100644
--- a/Source/WebCore/rendering/svg/legacy/LegacyRenderSVGImage.h
+++ b/Source/WebCore/rendering/svg/legacy/LegacyRenderSVGImage.h
@@ -65,6 +65,7 @@ class LegacyRenderSVGImage final : public LegacyRenderSVGModelObject {
     FloatRect objectBoundingBox() const override { return m_objectBoundingBox; }
     FloatRect strokeBoundingBox() const override { return m_objectBoundingBox; }
     FloatRect repaintRectInLocalCoordinates() const override { return m_repaintBoundingBox; }
+    FloatRect fastRepaintRectInLocalCoordinates() const override { return repaintRectInLocalCoordinates(); }
 
     void addFocusRingRects(Vector&, const LayoutPoint& additionalOffset, const RenderLayerModelObject* paintContainer = 0) const override;
 
diff --git a/Source/WebCore/rendering/svg/legacy/LegacyRenderSVGRoot.h b/Source/WebCore/rendering/svg/legacy/LegacyRenderSVGRoot.h
index 5f947dcd444e..21ce9d5b2deb 100644
--- a/Source/WebCore/rendering/svg/legacy/LegacyRenderSVGRoot.h
+++ b/Source/WebCore/rendering/svg/legacy/LegacyRenderSVGRoot.h
@@ -88,6 +88,7 @@ class LegacyRenderSVGRoot final : public RenderReplaced {
     FloatRect objectBoundingBox() const override { return m_objectBoundingBox; }
     FloatRect strokeBoundingBox() const override { return m_strokeBoundingBox; }
     FloatRect repaintRectInLocalCoordinates() const override { return m_repaintBoundingBox; }
+    FloatRect fastRepaintRectInLocalCoordinates() const override { return repaintRectInLocalCoordinates(); }
 
     bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) override;
 
diff --git a/Source/WebCore/rendering/svg/legacy/LegacyRenderSVGShape.h b/Source/WebCore/rendering/svg/legacy/LegacyRenderSVGShape.h
index 4170dcbc6222..e2fb76e5f607 100644
--- a/Source/WebCore/rendering/svg/legacy/LegacyRenderSVGShape.h
+++ b/Source/WebCore/rendering/svg/legacy/LegacyRenderSVGShape.h
@@ -96,6 +96,7 @@ class LegacyRenderSVGShape : public LegacyRenderSVGModelObject {
     bool strokeContains(const FloatPoint&, bool requiresStroke = true);
 
     FloatRect repaintRectInLocalCoordinates() const final { return m_repaintBoundingBox; }
+    FloatRect fastRepaintRectInLocalCoordinates() const final { return repaintRectInLocalCoordinates(); }
     const AffineTransform& localToParentTransform() const final { return m_localTransform; }
     AffineTransform localTransform() const final { return m_localTransform; }
 
diff --git a/Source/WebGPU/WGSL/WGSL.h b/Source/WebGPU/WGSL/WGSL.h
index d67c232baafa..d89011ee6bbc 100644
--- a/Source/WebGPU/WGSL/WGSL.h
+++ b/Source/WebGPU/WGSL/WGSL.h
@@ -151,10 +151,15 @@ struct BindGroupLayoutEntry {
     using BindingMember = std::variant;
     BindingMember bindingMember;
     std::optional vertexArgumentBufferIndex;
+    std::optional vertexArgumentBufferSizeIndex;
     std::optional vertexBufferDynamicOffset;
+
     std::optional fragmentArgumentBufferIndex;
+    std::optional fragmentArgumentBufferSizeIndex;
     std::optional fragmentBufferDynamicOffset;
+
     std::optional computeArgumentBufferIndex;
+    std::optional computeArgumentBufferSizeIndex;
     std::optional computeBufferDynamicOffset;
 };
 
diff --git a/Source/WebGPU/WebGPU/BindGroup.mm b/Source/WebGPU/WebGPU/BindGroup.mm
index dd76865b209b..e4a03c3c2ea5 100644
--- a/Source/WebGPU/WebGPU/BindGroup.mm
+++ b/Source/WebGPU/WebGPU/BindGroup.mm
@@ -478,6 +478,7 @@ static MTLResourceUsage resourceUsageForBindingAcccess(BindGroupLayout::BindingA
                 continue;
 
             auto index = bindGroupLayout.argumentBufferIndexForEntryIndex(entry.binding, stage);
+            auto bufferSizeArgumentBufferIndex = bindGroupLayout.bufferSizeIndexForEntryIndex(entry.binding, stage);
             MTLResourceUsage resourceUsage = resourceUsageForBindingAcccess(*optionalAccess);
 
             if (bufferIsPresent) {
@@ -487,6 +488,8 @@ static MTLResourceUsage resourceUsageForBindingAcccess(BindGroupLayout::BindingA
 
                 [argumentEncoder[stage] setBuffer:buffer offset:entry.offset atIndex:index];
                 stageResources[metalRenderStage(stage)][resourceUsage - 1].append(buffer);
+                RELEASE_ASSERT(bufferSizeArgumentBufferIndex);
+                *(uint32_t*)[argumentEncoder[stage] constantDataAtIndex:*bufferSizeArgumentBufferIndex] = static_cast(entry.size == WGPU_WHOLE_MAP_SIZE ? buffer.length : entry.size);
             } else if (samplerIsPresent) {
                 id sampler = WebGPU::fromAPI(entry.sampler).samplerState();
                 [argumentEncoder[stage] setSamplerState:sampler atIndex:index];
diff --git a/Source/WebGPU/WebGPU/BindGroupLayout.h b/Source/WebGPU/WebGPU/BindGroupLayout.h
index 54fa7d94155a..91bc8d5b1466 100644
--- a/Source/WebGPU/WebGPU/BindGroupLayout.h
+++ b/Source/WebGPU/WebGPU/BindGroupLayout.h
@@ -59,6 +59,7 @@ class BindGroupLayout : public WGPUBindGroupLayoutImpl, public RefCounted;
         BindingLayout bindingLayout;
         ArgumentBufferIndices argumentBufferIndices;
+        ArgumentBufferIndices bufferSizeArgumentBufferIndices;
         std::optional vertexDynamicOffset;
         std::optional fragmentDynamicOffset;
         std::optional computeDynamicOffset;
@@ -102,6 +103,7 @@ class BindGroupLayout : public WGPUBindGroupLayoutImpl, public RefCounted bindingAccessForBindingIndex(uint32_t bindingIndex, ShaderStage renderStage) const;
     NSUInteger argumentBufferIndexForEntryIndex(uint32_t bindingIndex, ShaderStage renderStage) const;
+    std::optional bufferSizeIndexForEntryIndex(uint32_t bindingIndex, ShaderStage renderStage) const;
 
     static bool isPresent(const WGPUBufferBindingLayout&);
     static bool isPresent(const WGPUSamplerBindingLayout&);
diff --git a/Source/WebGPU/WebGPU/BindGroupLayout.mm b/Source/WebGPU/WebGPU/BindGroupLayout.mm
index aa3b2b39ac1a..307201057df0 100644
--- a/Source/WebGPU/WebGPU/BindGroupLayout.mm
+++ b/Source/WebGPU/WebGPU/BindGroupLayout.mm
@@ -160,6 +160,7 @@ static bool containsStage(WGPUShaderStageFlags stageBitfield, auto stage)
     BindGroupLayout::EntriesContainer bindGroupLayoutEntries;
     size_t sizeOfDynamicOffsets[stageCount] = { 0, 0, 0 };
     uint32_t bindingOffset[stageCount] = { 0, 0, 0 };
+    uint32_t bufferCounts[stageCount] = { 0, 0, 0 };
     for (auto& entry : descriptorEntries) {
         if (entry.nextInChain) {
             if (entry.nextInChain->sType != static_cast(WGPUSTypeExtended_BindGroupLayoutEntryExternalTexture))
@@ -213,6 +214,7 @@ static bool containsStage(WGPUShaderStageFlags stageBitfield, auto stage)
 
         std::optional dynamicOffsets[stageCount];
         BindGroupLayout::ArgumentBufferIndices argumentBufferIndices;
+        BindGroupLayout::ArgumentBufferIndices bufferSizeArgumentBufferIndices;
         for (uint32_t stage = 0; stage < stageCount; ++stage) {
             if (containsStage(entry.visibility, stage)) {
                 indicesForBinding.add(makeKey(entry.binding, stage), descriptors[0].access);
@@ -222,6 +224,10 @@ static bool containsStage(WGPUShaderStageFlags stageBitfield, auto stage)
                     dynamicOffsets[stage] = sizeOfDynamicOffsets[stage];
                     sizeOfDynamicOffsets[stage] += sizeof(uint32_t);
                 }
+                if (BindGroupLayout::isPresent(entry.buffer)) {
+                    ++bufferCounts[stage];
+                    bufferSizeArgumentBufferIndices[renderStage] = bufferCounts[stage];
+                }
 
                 for (int descriptorIndex = 0; descriptorIndex < maxGeneratedDescriptors; ++descriptorIndex) {
                     if (MTLArgumentDescriptor *descriptor = descriptors[descriptorIndex])
@@ -240,6 +246,7 @@ static bool containsStage(WGPUShaderStageFlags stageBitfield, auto stage)
             entry.visibility,
             WTFMove(bindingLayout),
             WTFMove(argumentBufferIndices),
+            WTFMove(bufferSizeArgumentBufferIndices),
             WTFMove(dynamicOffsets[0]),
             WTFMove(dynamicOffsets[1]),
             WTFMove(dynamicOffsets[2])
@@ -249,6 +256,20 @@ static bool containsStage(WGPUShaderStageFlags stageBitfield, auto stage)
     auto label = fromAPI(descriptor.label);
     id argumentEncoders[stageCount];
     for (size_t stage = 0; stage < stageCount; ++stage) {
+        auto renderStage = stages[stage];
+        if (auto bufferCountPerStage = bufferCounts[stage]) {
+            NSUInteger maxIndex = [arguments[stage] objectAtIndex:arguments[stage].count - 1].index;
+            for (auto& entry : bindGroupLayoutEntries) {
+                if (entry.value.bufferSizeArgumentBufferIndices[renderStage])
+                    *entry.value.bufferSizeArgumentBufferIndices[renderStage] += maxIndex;
+            }
+            for (size_t bufferLengthIndex = 0; bufferLengthIndex < bufferCountPerStage; ++bufferLengthIndex) {
+                auto descriptor = [MTLArgumentDescriptor new];
+                descriptor.dataType = MTLDataTypeInt;
+                descriptor.access = BindGroupLayout::BindingAccessReadOnly;
+                addDescriptor(arguments[stage], descriptor, maxIndex + bufferLengthIndex + 1);
+            }
+        }
         argumentEncoders[stage] = arguments[stage].count ? [m_device newArgumentEncoderWithArguments:arguments[stage]] : nil;
         argumentEncoders[stage].label = label;
         if (arguments[stage].count && !argumentEncoders[stage])
@@ -331,6 +352,16 @@ static bool containsStage(WGPUShaderStageFlags stageBitfield, auto stage)
     return NSNotFound;
 }
 
+std::optional BindGroupLayout::bufferSizeIndexForEntryIndex(uint32_t bindingIndex, ShaderStage renderStage) const
+{
+    if (auto it = m_bindGroupLayoutEntries.find(bindingIndex); it != m_bindGroupLayoutEntries.end()) {
+        auto result = it->value.bufferSizeArgumentBufferIndices[renderStage];
+        return result ? *result : NSNotFound;
+    }
+
+    return NSNotFound;
+}
+
 } // namespace WebGPU
 
 #pragma mark WGPU Stubs
diff --git a/Source/WebGPU/WebGPU/ShaderModule.mm b/Source/WebGPU/WebGPU/ShaderModule.mm
index 32049d28e276..303e98b2a117 100644
--- a/Source/WebGPU/WebGPU/ShaderModule.mm
+++ b/Source/WebGPU/WebGPU/ShaderModule.mm
@@ -368,10 +368,13 @@ static auto wgslViewDimension(WGPUTextureViewDimension viewDimension)
             wgslEntry.visibility.fromRaw(entry.value.visibility);
             wgslEntry.bindingMember = convertBindingLayout(entry.value.bindingLayout);
             wgslEntry.vertexArgumentBufferIndex = entry.value.argumentBufferIndices[WebGPU::ShaderStage::Vertex];
+            wgslEntry.vertexArgumentBufferSizeIndex = entry.value.bufferSizeArgumentBufferIndices[WebGPU::ShaderStage::Vertex];
             wgslEntry.vertexBufferDynamicOffset = entry.value.vertexDynamicOffset;
             wgslEntry.fragmentArgumentBufferIndex = entry.value.argumentBufferIndices[WebGPU::ShaderStage::Fragment];
+            wgslEntry.fragmentArgumentBufferSizeIndex = entry.value.bufferSizeArgumentBufferIndices[WebGPU::ShaderStage::Fragment];
             wgslEntry.fragmentBufferDynamicOffset = entry.value.fragmentDynamicOffset;
             wgslEntry.computeArgumentBufferIndex = entry.value.argumentBufferIndices[WebGPU::ShaderStage::Compute];
+            wgslEntry.computeArgumentBufferSizeIndex = entry.value.bufferSizeArgumentBufferIndices[WebGPU::ShaderStage::Compute];
             wgslEntry.computeBufferDynamicOffset = entry.value.computeDynamicOffset;
             wgslBindGroupLayout.entries.append(wgslEntry);
         }
diff --git a/Source/WebKit/DerivedSources-input.xcfilelist b/Source/WebKit/DerivedSources-input.xcfilelist
index f444590d08e8..d04d49cd0fae 100644
--- a/Source/WebKit/DerivedSources-input.xcfilelist
+++ b/Source/WebKit/DerivedSources-input.xcfilelist
@@ -326,6 +326,7 @@ $(PROJECT_DIR)/Shared/WebsitePoliciesData.serialization.in
 $(PROJECT_DIR)/Shared/XR/XRSystem.serialization.in
 $(PROJECT_DIR)/Shared/ios/DynamicViewportSizeUpdate.serialization.in
 $(PROJECT_DIR)/Shared/ios/InteractionInformationAtPosition.serialization.in
+$(PROJECT_DIR)/Shared/ios/InteractionInformationRequest.serialization.in
 $(PROJECT_DIR)/Shared/ios/WebAutocorrectionContext.serialization.in
 $(PROJECT_DIR)/Shared/ios/WebAutocorrectionData.serialization.in
 $(PROJECT_DIR)/Shared/mac/PDFContextMenuItem.serialization.in
diff --git a/Source/WebKit/DerivedSources.make b/Source/WebKit/DerivedSources.make
index 605294ec1555..4ec0ab87b078 100644
--- a/Source/WebKit/DerivedSources.make
+++ b/Source/WebKit/DerivedSources.make
@@ -521,6 +521,7 @@ SERIALIZATION_DESCRIPTION_FILES = \
 	Shared/GoToBackForwardItemParameters.serialization.in \
 	Shared/ios/DynamicViewportSizeUpdate.serialization.in \
 	Shared/ios/InteractionInformationAtPosition.serialization.in \
+	Shared/ios/InteractionInformationRequest.serialization.in \
 	Shared/ios/WebAutocorrectionContext.serialization.in \
 	Shared/ios/WebAutocorrectionData.serialization.in \
 	Shared/LayerTreeContext.serialization.in \
diff --git a/Source/WebKit/NetworkProcess/webrtc/NetworkRTCTCPSocketCocoa.mm b/Source/WebKit/NetworkProcess/webrtc/NetworkRTCTCPSocketCocoa.mm
index 2b5d2bfc692c..df6f051dbd4d 100644
--- a/Source/WebKit/NetworkProcess/webrtc/NetworkRTCTCPSocketCocoa.mm
+++ b/Source/WebKit/NetworkProcess/webrtc/NetworkRTCTCPSocketCocoa.mm
@@ -195,8 +195,7 @@ static inline void processIncomingData(RetainPtr&& nwConnection
     // Prepend length.
     Vector buffer;
     buffer.reserveInitialCapacity(size + 2);
-    buffer.uncheckedAppend((size >> 8) & 0xFF);
-    buffer.uncheckedAppend(size & 0xFF);
+    buffer.appendList({ (size >> 8) & 0xFF, size & 0xFF });
     buffer.append(data, size);
     return buffer;
 }
diff --git a/Source/WebKit/Scripts/webkit/messages.py b/Source/WebKit/Scripts/webkit/messages.py
index 35cbaebac27f..ce4cea2042f7 100644
--- a/Source/WebKit/Scripts/webkit/messages.py
+++ b/Source/WebKit/Scripts/webkit/messages.py
@@ -234,11 +234,11 @@ def message_to_struct_declaration(receiver, message):
         result.append('    using ReplyArguments = std::tuple<%s>;\n' % ', '.join([parameter.type for parameter in message.reply_parameters]))
         if not message.has_attribute(SYNCHRONOUS_ATTRIBUTE):
             if len(message.reply_parameters) == 0:
-                result.append('    using Promise = WTF::NativePromise;\n')
+                result.append('    using Promise = WTF::NativePromise;\n')
             elif len(message.reply_parameters) == 1:
-                result.append('    using Promise = WTF::NativePromise<%s, IPC::Error, true>;\n' % message.reply_parameters[0].type)
+                result.append('    using Promise = WTF::NativePromise<%s, IPC::Error>;\n' % message.reply_parameters[0].type)
             else:
-                result.append('    using Promise = WTF::NativePromise, IPC::Error, true>;\n' % ', '.join([parameter.type for parameter in message.reply_parameters]))
+                result.append('    using Promise = WTF::NativePromise, IPC::Error>;\n' % ', '.join([parameter.type for parameter in message.reply_parameters]))
 
     if len(function_parameters):
         result.append('    %s%s(%s)' % (len(function_parameters) == 1 and 'explicit ' or '', message.name, ', '.join([' '.join(x) for x in function_parameters])))
diff --git a/Source/WebKit/Scripts/webkit/tests/TestWithCVPixelBufferMessages.h b/Source/WebKit/Scripts/webkit/tests/TestWithCVPixelBufferMessages.h
index 28cb7ee40f86..a4b0cd71bb1c 100644
--- a/Source/WebKit/Scripts/webkit/tests/TestWithCVPixelBufferMessages.h
+++ b/Source/WebKit/Scripts/webkit/tests/TestWithCVPixelBufferMessages.h
@@ -81,7 +81,7 @@ class ReceiveCVPixelBuffer {
     static IPC::MessageName asyncMessageReplyName() { return IPC::MessageName::TestWithCVPixelBuffer_ReceiveCVPixelBufferReply; }
     static constexpr auto callbackThread = WTF::CompletionHandlerCallThread::ConstructionThread;
     using ReplyArguments = std::tuple>;
-    using Promise = WTF::NativePromise, IPC::Error, true>;
+    using Promise = WTF::NativePromise, IPC::Error>;
     auto&& arguments()
     {
         return WTFMove(m_arguments);
diff --git a/Source/WebKit/Scripts/webkit/tests/TestWithImageDataMessages.h b/Source/WebKit/Scripts/webkit/tests/TestWithImageDataMessages.h
index a31afe8042ef..1b179c2e0e14 100644
--- a/Source/WebKit/Scripts/webkit/tests/TestWithImageDataMessages.h
+++ b/Source/WebKit/Scripts/webkit/tests/TestWithImageDataMessages.h
@@ -76,7 +76,7 @@ class ReceiveImageData {
     static IPC::MessageName asyncMessageReplyName() { return IPC::MessageName::TestWithImageData_ReceiveImageDataReply; }
     static constexpr auto callbackThread = WTF::CompletionHandlerCallThread::ConstructionThread;
     using ReplyArguments = std::tuple>;
-    using Promise = WTF::NativePromise, IPC::Error, true>;
+    using Promise = WTF::NativePromise, IPC::Error>;
     auto&& arguments()
     {
         return WTFMove(m_arguments);
diff --git a/Source/WebKit/Scripts/webkit/tests/TestWithLegacyReceiverMessages.h b/Source/WebKit/Scripts/webkit/tests/TestWithLegacyReceiverMessages.h
index cc52297ec6d3..2e613ee93334 100644
--- a/Source/WebKit/Scripts/webkit/tests/TestWithLegacyReceiverMessages.h
+++ b/Source/WebKit/Scripts/webkit/tests/TestWithLegacyReceiverMessages.h
@@ -307,7 +307,7 @@ class CreatePlugin {
     static IPC::MessageName asyncMessageReplyName() { return IPC::MessageName::TestWithLegacyReceiver_CreatePluginReply; }
     static constexpr auto callbackThread = WTF::CompletionHandlerCallThread::ConstructionThread;
     using ReplyArguments = std::tuple;
-    using Promise = WTF::NativePromise;
+    using Promise = WTF::NativePromise;
     CreatePlugin(uint64_t pluginInstanceID, const WebKit::Plugin::Parameters& parameters)
         : m_arguments(pluginInstanceID, parameters)
     {
@@ -334,7 +334,7 @@ class RunJavaScriptAlert {
     static IPC::MessageName asyncMessageReplyName() { return IPC::MessageName::TestWithLegacyReceiver_RunJavaScriptAlertReply; }
     static constexpr auto callbackThread = WTF::CompletionHandlerCallThread::ConstructionThread;
     using ReplyArguments = std::tuple<>;
-    using Promise = WTF::NativePromise;
+    using Promise = WTF::NativePromise;
     RunJavaScriptAlert(uint64_t frameID, const String& message)
         : m_arguments(frameID, message)
     {
@@ -361,7 +361,7 @@ class GetPlugins {
     static IPC::MessageName asyncMessageReplyName() { return IPC::MessageName::TestWithLegacyReceiver_GetPluginsReply; }
     static constexpr auto callbackThread = WTF::CompletionHandlerCallThread::ConstructionThread;
     using ReplyArguments = std::tuple>;
-    using Promise = WTF::NativePromise, IPC::Error, true>;
+    using Promise = WTF::NativePromise, IPC::Error>;
     explicit GetPlugins(bool refresh)
         : m_arguments(refresh)
     {
@@ -528,7 +528,7 @@ class InterpretKeyEvent {
     static IPC::MessageName asyncMessageReplyName() { return IPC::MessageName::TestWithLegacyReceiver_InterpretKeyEventReply; }
     static constexpr auto callbackThread = WTF::CompletionHandlerCallThread::ConstructionThread;
     using ReplyArguments = std::tuple>;
-    using Promise = WTF::NativePromise, IPC::Error, true>;
+    using Promise = WTF::NativePromise, IPC::Error>;
     explicit InterpretKeyEvent(uint32_t type)
         : m_arguments(type)
     {
diff --git a/Source/WebKit/Scripts/webkit/tests/TestWithSemaphoreMessages.h b/Source/WebKit/Scripts/webkit/tests/TestWithSemaphoreMessages.h
index 1024ffee70ad..f3abe81e0844 100644
--- a/Source/WebKit/Scripts/webkit/tests/TestWithSemaphoreMessages.h
+++ b/Source/WebKit/Scripts/webkit/tests/TestWithSemaphoreMessages.h
@@ -75,7 +75,7 @@ class ReceiveSemaphore {
     static IPC::MessageName asyncMessageReplyName() { return IPC::MessageName::TestWithSemaphore_ReceiveSemaphoreReply; }
     static constexpr auto callbackThread = WTF::CompletionHandlerCallThread::ConstructionThread;
     using ReplyArguments = std::tuple;
-    using Promise = WTF::NativePromise;
+    using Promise = WTF::NativePromise;
     auto&& arguments()
     {
         return WTFMove(m_arguments);
diff --git a/Source/WebKit/Scripts/webkit/tests/TestWithStreamMessages.h b/Source/WebKit/Scripts/webkit/tests/TestWithStreamMessages.h
index ff43dcd614d2..da6be4080425 100644
--- a/Source/WebKit/Scripts/webkit/tests/TestWithStreamMessages.h
+++ b/Source/WebKit/Scripts/webkit/tests/TestWithStreamMessages.h
@@ -81,7 +81,7 @@ class SendStringAsync {
     static IPC::MessageName asyncMessageReplyName() { return IPC::MessageName::TestWithStream_SendStringAsyncReply; }
     static constexpr auto callbackThread = WTF::CompletionHandlerCallThread::ConstructionThread;
     using ReplyArguments = std::tuple;
-    using Promise = WTF::NativePromise;
+    using Promise = WTF::NativePromise;
     explicit SendStringAsync(const String& url)
         : m_arguments(url)
     {
@@ -139,7 +139,7 @@ class CallWithIdentifier {
     static IPC::MessageName asyncMessageReplyName() { return IPC::MessageName::TestWithStream_CallWithIdentifierReply; }
     static constexpr auto callbackThread = WTF::CompletionHandlerCallThread::ConstructionThread;
     using ReplyArguments = std::tuple<>;
-    using Promise = WTF::NativePromise;
+    using Promise = WTF::NativePromise;
     auto&& arguments()
     {
         return WTFMove(m_arguments);
diff --git a/Source/WebKit/Scripts/webkit/tests/TestWithSuperclassMessages.h b/Source/WebKit/Scripts/webkit/tests/TestWithSuperclassMessages.h
index 42a7dcd0cae3..b7ab69fbedcb 100644
--- a/Source/WebKit/Scripts/webkit/tests/TestWithSuperclassMessages.h
+++ b/Source/WebKit/Scripts/webkit/tests/TestWithSuperclassMessages.h
@@ -81,7 +81,7 @@ class TestAsyncMessage {
     static IPC::MessageName asyncMessageReplyName() { return IPC::MessageName::TestWithSuperclass_TestAsyncMessageReply; }
     static constexpr auto callbackThread = WTF::CompletionHandlerCallThread::MainThread;
     using ReplyArguments = std::tuple;
-    using Promise = WTF::NativePromise;
+    using Promise = WTF::NativePromise;
     explicit TestAsyncMessage(WebKit::TestTwoStateEnum twoStateEnum)
         : m_arguments(twoStateEnum)
     {
@@ -110,7 +110,7 @@ class TestAsyncMessageWithNoArguments {
     static IPC::MessageName asyncMessageReplyName() { return IPC::MessageName::TestWithSuperclass_TestAsyncMessageWithNoArgumentsReply; }
     static constexpr auto callbackThread = WTF::CompletionHandlerCallThread::ConstructionThread;
     using ReplyArguments = std::tuple<>;
-    using Promise = WTF::NativePromise;
+    using Promise = WTF::NativePromise;
     auto&& arguments()
     {
         return WTFMove(m_arguments);
@@ -134,7 +134,7 @@ class TestAsyncMessageWithMultipleArguments {
     static IPC::MessageName asyncMessageReplyName() { return IPC::MessageName::TestWithSuperclass_TestAsyncMessageWithMultipleArgumentsReply; }
     static constexpr auto callbackThread = WTF::CompletionHandlerCallThread::ConstructionThread;
     using ReplyArguments = std::tuple;
-    using Promise = WTF::NativePromise, IPC::Error, true>;
+    using Promise = WTF::NativePromise, IPC::Error>;
     auto&& arguments()
     {
         return WTFMove(m_arguments);
@@ -158,7 +158,7 @@ class TestAsyncMessageWithConnection {
     static IPC::MessageName asyncMessageReplyName() { return IPC::MessageName::TestWithSuperclass_TestAsyncMessageWithConnectionReply; }
     static constexpr auto callbackThread = WTF::CompletionHandlerCallThread::ConstructionThread;
     using ReplyArguments = std::tuple;
-    using Promise = WTF::NativePromise;
+    using Promise = WTF::NativePromise;
     explicit TestAsyncMessageWithConnection(const int& value)
         : m_arguments(value)
     {
diff --git a/Source/WebKit/Scripts/webkit/tests/TestWithoutAttributesMessages.h b/Source/WebKit/Scripts/webkit/tests/TestWithoutAttributesMessages.h
index 0f2e88a5ed81..6b49b21a6a24 100644
--- a/Source/WebKit/Scripts/webkit/tests/TestWithoutAttributesMessages.h
+++ b/Source/WebKit/Scripts/webkit/tests/TestWithoutAttributesMessages.h
@@ -307,7 +307,7 @@ class CreatePlugin {
     static IPC::MessageName asyncMessageReplyName() { return IPC::MessageName::TestWithoutAttributes_CreatePluginReply; }
     static constexpr auto callbackThread = WTF::CompletionHandlerCallThread::ConstructionThread;
     using ReplyArguments = std::tuple;
-    using Promise = WTF::NativePromise;
+    using Promise = WTF::NativePromise;
     CreatePlugin(uint64_t pluginInstanceID, const WebKit::Plugin::Parameters& parameters)
         : m_arguments(pluginInstanceID, parameters)
     {
@@ -334,7 +334,7 @@ class RunJavaScriptAlert {
     static IPC::MessageName asyncMessageReplyName() { return IPC::MessageName::TestWithoutAttributes_RunJavaScriptAlertReply; }
     static constexpr auto callbackThread = WTF::CompletionHandlerCallThread::ConstructionThread;
     using ReplyArguments = std::tuple<>;
-    using Promise = WTF::NativePromise;
+    using Promise = WTF::NativePromise;
     RunJavaScriptAlert(uint64_t frameID, const String& message)
         : m_arguments(frameID, message)
     {
@@ -361,7 +361,7 @@ class GetPlugins {
     static IPC::MessageName asyncMessageReplyName() { return IPC::MessageName::TestWithoutAttributes_GetPluginsReply; }
     static constexpr auto callbackThread = WTF::CompletionHandlerCallThread::ConstructionThread;
     using ReplyArguments = std::tuple>;
-    using Promise = WTF::NativePromise, IPC::Error, true>;
+    using Promise = WTF::NativePromise, IPC::Error>;
     explicit GetPlugins(bool refresh)
         : m_arguments(refresh)
     {
@@ -528,7 +528,7 @@ class InterpretKeyEvent {
     static IPC::MessageName asyncMessageReplyName() { return IPC::MessageName::TestWithoutAttributes_InterpretKeyEventReply; }
     static constexpr auto callbackThread = WTF::CompletionHandlerCallThread::ConstructionThread;
     using ReplyArguments = std::tuple>;
-    using Promise = WTF::NativePromise, IPC::Error, true>;
+    using Promise = WTF::NativePromise, IPC::Error>;
     explicit InterpretKeyEvent(uint32_t type)
         : m_arguments(type)
     {
diff --git a/Source/WebKit/Scripts/webkit/tests/TestWithoutUsingIPCConnectionMessages.h b/Source/WebKit/Scripts/webkit/tests/TestWithoutUsingIPCConnectionMessages.h
index 70119ac4f05d..d66e21b65311 100644
--- a/Source/WebKit/Scripts/webkit/tests/TestWithoutUsingIPCConnectionMessages.h
+++ b/Source/WebKit/Scripts/webkit/tests/TestWithoutUsingIPCConnectionMessages.h
@@ -70,7 +70,7 @@ class MessageWithoutArgumentAndEmptyReply {
     static IPC::MessageName asyncMessageReplyName() { return IPC::MessageName::TestWithoutUsingIPCConnection_MessageWithoutArgumentAndEmptyReplyReply; }
     static constexpr auto callbackThread = WTF::CompletionHandlerCallThread::ConstructionThread;
     using ReplyArguments = std::tuple<>;
-    using Promise = WTF::NativePromise;
+    using Promise = WTF::NativePromise;
     auto&& arguments()
     {
         return WTFMove(m_arguments);
@@ -92,7 +92,7 @@ class MessageWithoutArgumentAndReplyWithArgument {
     static IPC::MessageName asyncMessageReplyName() { return IPC::MessageName::TestWithoutUsingIPCConnection_MessageWithoutArgumentAndReplyWithArgumentReply; }
     static constexpr auto callbackThread = WTF::CompletionHandlerCallThread::ConstructionThread;
     using ReplyArguments = std::tuple;
-    using Promise = WTF::NativePromise;
+    using Promise = WTF::NativePromise;
     auto&& arguments()
     {
         return WTFMove(m_arguments);
@@ -137,7 +137,7 @@ class MessageWithArgumentAndEmptyReply {
     static IPC::MessageName asyncMessageReplyName() { return IPC::MessageName::TestWithoutUsingIPCConnection_MessageWithArgumentAndEmptyReplyReply; }
     static constexpr auto callbackThread = WTF::CompletionHandlerCallThread::ConstructionThread;
     using ReplyArguments = std::tuple<>;
-    using Promise = WTF::NativePromise;
+    using Promise = WTF::NativePromise;
     explicit MessageWithArgumentAndEmptyReply(const String& argument)
         : m_arguments(argument)
     {
@@ -164,7 +164,7 @@ class MessageWithArgumentAndReplyWithArgument {
     static IPC::MessageName asyncMessageReplyName() { return IPC::MessageName::TestWithoutUsingIPCConnection_MessageWithArgumentAndReplyWithArgumentReply; }
     static constexpr auto callbackThread = WTF::CompletionHandlerCallThread::ConstructionThread;
     using ReplyArguments = std::tuple;
-    using Promise = WTF::NativePromise;
+    using Promise = WTF::NativePromise;
     explicit MessageWithArgumentAndReplyWithArgument(const String& argument)
         : m_arguments(argument)
     {
diff --git a/Source/WebKit/Shared/WebCoreArgumentCoders.serialization.in b/Source/WebKit/Shared/WebCoreArgumentCoders.serialization.in
index b31bdc8eb208..15623d4cdfc4 100644
--- a/Source/WebKit/Shared/WebCoreArgumentCoders.serialization.in
+++ b/Source/WebKit/Shared/WebCoreArgumentCoders.serialization.in
@@ -5877,12 +5877,19 @@ header: 
     std::optional> fillLightMode;
 };
 
+header: 
+[CustomHeader] struct WebCore::PhotoSettings {
+    std::optional fillLightMode;
+    std::optional imageHeight;
+    std::optional imageWidth;
+    std::optional redEyeReduction;
+};
+
 header: 
 [CustomHeader] struct WebCore::PhotoCapabilitiesOrError {
     std::optional capabilities;
     String errorMessage;
 };
-#endif
 
 header: 
 enum class WebCore::WebGPU::TextureAspect : uint8_t {
@@ -6299,3 +6306,19 @@ header: 
 [Alias=class FontTaggedSettings, CustomHeader, LegacyPopulateFromEmptyConstructor] class WebCore::FontFeatureSettings {
     Vector m_list;
 };
+
+enum class WebCore::UserScriptInjectionTime : bool;
+
+enum class WebCore::WaitForNotificationBeforeInjecting : bool;
+
+enum class WebCore::UserContentInjectedFrames : bool;
+
+class WebCore::UserScript {
+    String source();
+    URL url();
+    Vector allowlist();
+    Vector blocklist();
+    WebCore::UserScriptInjectionTime injectionTime();
+    WebCore::UserContentInjectedFrames injectedFrames();
+    WebCore::WaitForNotificationBeforeInjecting waitForNotificationBeforeInjecting();
+}
diff --git a/Source/WebKit/Shared/ios/InteractionInformationRequest.cpp b/Source/WebKit/Shared/ios/InteractionInformationRequest.cpp
index 050b870bd7bb..19718398c2a0 100644
--- a/Source/WebKit/Shared/ios/InteractionInformationRequest.cpp
+++ b/Source/WebKit/Shared/ios/InteractionInformationRequest.cpp
@@ -33,51 +33,6 @@ namespace WebKit {
 
 #if PLATFORM(IOS_FAMILY)
 
-void InteractionInformationRequest::encode(IPC::Encoder& encoder) const
-{
-    encoder << point;
-    encoder << includeSnapshot;
-    encoder << includeLinkIndicator;
-    encoder << includeCaretContext;
-    encoder << includeHasDoubleClickHandler;
-    encoder << includeImageData;
-    encoder << gatherAnimations;
-    encoder << linkIndicatorShouldHaveLegacyMargins;
-    encoder << disallowUserAgentShadowContent;
-}
-
-bool InteractionInformationRequest::decode(IPC::Decoder& decoder, InteractionInformationRequest& result)
-{
-    if (!decoder.decode(result.point))
-        return false;
-
-    if (!decoder.decode(result.includeSnapshot))
-        return false;
-
-    if (!decoder.decode(result.includeLinkIndicator))
-        return false;
-
-    if (!decoder.decode(result.includeCaretContext))
-        return false;
-
-    if (!decoder.decode(result.includeHasDoubleClickHandler))
-        return false;
-
-    if (!decoder.decode(result.includeImageData))
-        return false;
-
-    if (!decoder.decode(result.gatherAnimations))
-        return false;
-
-    if (!decoder.decode(result.linkIndicatorShouldHaveLegacyMargins))
-        return false;
-
-    if (!decoder.decode(result.disallowUserAgentShadowContent))
-        return false;
-
-    return true;
-}
-
 bool InteractionInformationRequest::isValidForRequest(const InteractionInformationRequest& other, int radius) const
 {
     if (other.includeSnapshot && !includeSnapshot)
diff --git a/Source/WebKit/Shared/ios/InteractionInformationRequest.h b/Source/WebKit/Shared/ios/InteractionInformationRequest.h
index c3ddf1495713..b8cc9f064365 100644
--- a/Source/WebKit/Shared/ios/InteractionInformationRequest.h
+++ b/Source/WebKit/Shared/ios/InteractionInformationRequest.h
@@ -51,15 +51,26 @@ struct InteractionInformationRequest {
 
     InteractionInformationRequest() { }
     explicit InteractionInformationRequest(WebCore::IntPoint point)
+        : point(point)
+    {
+    }
+
+    explicit InteractionInformationRequest(WebCore::IntPoint point, bool includeSnapshot, bool includeLinkIndicator, bool includeCaretContext, bool includeHasDoubleClickHandler,
+        bool includeImageData, bool gatherAnimations, bool linkIndicatorShouldHaveLegacyMargins, bool disallowUserAgentShadowContent)
+        : point(point)
+        , includeSnapshot(includeSnapshot)
+        , includeLinkIndicator(includeLinkIndicator)
+        , includeCaretContext(includeCaretContext)
+        , includeHasDoubleClickHandler(includeHasDoubleClickHandler)
+        , includeImageData(includeImageData)
+        , gatherAnimations(gatherAnimations)
+        , linkIndicatorShouldHaveLegacyMargins(linkIndicatorShouldHaveLegacyMargins)
+        , disallowUserAgentShadowContent(disallowUserAgentShadowContent)
     {
-        this->point = point;
     }
 
     bool isValidForRequest(const InteractionInformationRequest&, int radius = 0) const;
     bool isApproximatelyValidForRequest(const InteractionInformationRequest&, int radius) const;
-
-    void encode(IPC::Encoder&) const;
-    static WARN_UNUSED_RETURN bool decode(IPC::Decoder&, InteractionInformationRequest&);
 };
 
 }
diff --git a/Source/WebKit/Shared/ios/InteractionInformationRequest.serialization.in b/Source/WebKit/Shared/ios/InteractionInformationRequest.serialization.in
new file mode 100644
index 000000000000..2aa8b28b8d7f
--- /dev/null
+++ b/Source/WebKit/Shared/ios/InteractionInformationRequest.serialization.in
@@ -0,0 +1,39 @@
+# Copyright (C) 2023 Apple Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1.  Redistributions of source code must retain the above copyright
+#     notice, this list of conditions and the following disclaimer.
+# 2.  Redistributions in binary form must reproduce the above copyright
+#     notice, this list of conditions and the following disclaimer in the
+#     documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR
+# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#if PLATFORM(IOS_FAMILY)
+
+struct WebKit::InteractionInformationRequest {
+    WebCore::IntPoint point;
+
+    bool includeSnapshot;
+    bool includeLinkIndicator;
+    bool includeCaretContext;
+    bool includeHasDoubleClickHandler;
+    bool includeImageData;
+
+    bool gatherAnimations;
+    bool linkIndicatorShouldHaveLegacyMargins;
+    bool disallowUserAgentShadowContent;
+};
+
+#endif
diff --git a/Source/WebKit/UIProcess/Cocoa/UserMediaCaptureManagerProxy.cpp b/Source/WebKit/UIProcess/Cocoa/UserMediaCaptureManagerProxy.cpp
index 5f1f1956d4aa..18c999b7e05f 100644
--- a/Source/WebKit/UIProcess/Cocoa/UserMediaCaptureManagerProxy.cpp
+++ b/Source/WebKit/UIProcess/Cocoa/UserMediaCaptureManagerProxy.cpp
@@ -44,6 +44,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #define MESSAGE_CHECK(assertion) MESSAGE_CHECK_BASE(assertion, &m_connectionProxy->connection())
@@ -194,6 +195,11 @@ class UserMediaCaptureManagerProxy::SourceProxy
         m_source->getPhotoCapabilities(WTFMove(handler));
     }
 
+    Ref getPhotoSettings()
+    {
+        return m_source->getPhotoSettings();
+    }
+
 private:
     void sourceStopped() final {
         m_connection->send(Messages::UserMediaCaptureManager::SourceStopped(m_id, m_source->captureDidFail()), 0);
@@ -536,6 +542,18 @@ void UserMediaCaptureManagerProxy::getPhotoCapabilities(RealtimeMediaSourceIdent
     handler(PhotoCapabilitiesOrError("Device not available"_s));
 }
 
+void UserMediaCaptureManagerProxy::getPhotoSettings(RealtimeMediaSourceIdentifier sourceID, GetPhotoSettingsCallback&& handler)
+{
+    if (auto* proxy = m_proxies.get(sourceID)) {
+        proxy->getPhotoSettings()->whenSettled(RunLoop::main(), [handler = WTFMove(handler)] (RealtimeMediaSource::PhotoSettingsPromise::Result&& result) mutable {
+            handler(WTFMove(result));
+        });
+        return;
+    }
+
+    handler(Unexpected("Device not available"_s));
+}
+
 void UserMediaCaptureManagerProxy::endProducingData(RealtimeMediaSourceIdentifier sourceID)
 {
     if (auto* proxy = m_proxies.get(sourceID))
diff --git a/Source/WebKit/UIProcess/Cocoa/UserMediaCaptureManagerProxy.h b/Source/WebKit/UIProcess/Cocoa/UserMediaCaptureManagerProxy.h
index 34cc6a3ee90a..e5c67a731ef7 100644
--- a/Source/WebKit/UIProcess/Cocoa/UserMediaCaptureManagerProxy.h
+++ b/Source/WebKit/UIProcess/Cocoa/UserMediaCaptureManagerProxy.h
@@ -98,7 +98,10 @@ class UserMediaCaptureManagerProxy : private IPC::MessageReceiver {
     void setIsInBackground(WebCore::RealtimeMediaSourceIdentifier, bool);
 
     using GetPhotoCapabilitiesCallback = CompletionHandler;
-    void getPhotoCapabilities(WebCore::RealtimeMediaSourceIdentifier, GetPhotoCapabilitiesCallback&& handler);
+    void getPhotoCapabilities(WebCore::RealtimeMediaSourceIdentifier, GetPhotoCapabilitiesCallback&&);
+
+    using GetPhotoSettingsCallback = CompletionHandler&&)>;
+    void getPhotoSettings(WebCore::RealtimeMediaSourceIdentifier, GetPhotoSettingsCallback&&);
 
     WebCore::CaptureSourceOrError createMicrophoneSource(const WebCore::CaptureDevice&, WebCore::MediaDeviceHashSalts&&, const WebCore::MediaConstraints*, WebCore::PageIdentifier);
     WebCore::CaptureSourceOrError createCameraSource(const WebCore::CaptureDevice&, WebCore::MediaDeviceHashSalts&&, WebCore::PageIdentifier);
diff --git a/Source/WebKit/UIProcess/Cocoa/UserMediaCaptureManagerProxy.messages.in b/Source/WebKit/UIProcess/Cocoa/UserMediaCaptureManagerProxy.messages.in
index 50ab776789b7..0a76b4f88a2c 100644
--- a/Source/WebKit/UIProcess/Cocoa/UserMediaCaptureManagerProxy.messages.in
+++ b/Source/WebKit/UIProcess/Cocoa/UserMediaCaptureManagerProxy.messages.in
@@ -30,6 +30,7 @@ messages -> UserMediaCaptureManagerProxy NotRefCounted {
     RemoveSource(WebCore::RealtimeMediaSourceIdentifier id)
     ApplyConstraints(WebCore::RealtimeMediaSourceIdentifier id, struct WebCore::MediaConstraints constraints)
     GetPhotoCapabilities(WebCore::RealtimeMediaSourceIdentifier sourceID) -> (struct WebCore::PhotoCapabilitiesOrError result) Async
+    GetPhotoSettings(WebCore::RealtimeMediaSourceIdentifier sourceID) -> (Expected result) Async
     Clone(WebCore::RealtimeMediaSourceIdentifier clonedID, WebCore::RealtimeMediaSourceIdentifier cloneID, WebCore::PageIdentifier pageIdentifier)
     EndProducingData(WebCore::RealtimeMediaSourceIdentifier sourceID)
     SetShouldApplyRotation(WebCore::RealtimeMediaSourceIdentifier sourceID, bool shouldApplyRotation)
diff --git a/Source/WebKit/WebProcess/WebCoreSupport/WebLocalFrameLoaderClient.cpp b/Source/WebKit/WebProcess/WebCoreSupport/WebLocalFrameLoaderClient.cpp
index 9c27ea6ed436..53003e097a66 100644
--- a/Source/WebKit/WebProcess/WebCoreSupport/WebLocalFrameLoaderClient.cpp
+++ b/Source/WebKit/WebProcess/WebCoreSupport/WebLocalFrameLoaderClient.cpp
@@ -560,7 +560,7 @@ void WebLocalFrameLoaderClient::dispatchDidStartProvisionalLoad()
 
 #if ENABLE(WK_WEB_EXTENSIONS)
     // Notify the extensions controller.
-    if (auto* extensionControllerProxy = webPage->webExtensionControllerProxy())
+    if (RefPtr extensionControllerProxy = webPage->webExtensionControllerProxy())
         extensionControllerProxy->didStartProvisionalLoadForFrame(*webPage, m_frame, url);
 #endif
 
@@ -617,7 +617,7 @@ void WebLocalFrameLoaderClient::dispatchDidCommitLoad(std::optionalwebExtensionControllerProxy())
+    if (RefPtr extensionControllerProxy = webPage->webExtensionControllerProxy())
         extensionControllerProxy->didCommitLoadForFrame(*webPage, m_frame, m_frame->url());
 #endif
 
@@ -736,7 +736,7 @@ void WebLocalFrameLoaderClient::dispatchDidFinishLoad()
 
 #if ENABLE(WK_WEB_EXTENSIONS)
     // Notify the extensions controller.
-    if (auto* extensionControllerProxy = webPage->webExtensionControllerProxy())
+    if (RefPtr extensionControllerProxy = webPage->webExtensionControllerProxy())
         extensionControllerProxy->didFinishLoadForFrame(*webPage, m_frame, m_frame->url());
 #endif
 
@@ -1698,12 +1698,12 @@ void WebLocalFrameLoaderClient::dispatchGlobalObjectAvailable(DOMWrapperWorld& w
     if (!webPage)
         return;
 
-    webPage->injectedBundleLoaderClient().globalObjectIsAvailableForFrame(*webPage, m_frame, world);
-
 #if ENABLE(WK_WEB_EXTENSIONS)
-    if (auto* extensionControllerProxy = webPage->webExtensionControllerProxy())
+    if (RefPtr extensionControllerProxy = webPage->webExtensionControllerProxy())
         extensionControllerProxy->globalObjectIsAvailableForFrame(*webPage, m_frame, world);
 #endif
+
+    webPage->injectedBundleLoaderClient().globalObjectIsAvailableForFrame(*webPage, m_frame, world);
 }
 
 void WebLocalFrameLoaderClient::dispatchServiceWorkerGlobalObjectAvailable(DOMWrapperWorld& world)
@@ -1712,12 +1712,12 @@ void WebLocalFrameLoaderClient::dispatchServiceWorkerGlobalObjectAvailable(DOMWr
     if (!webPage)
         return;
 
-    webPage->injectedBundleLoaderClient().serviceWorkerGlobalObjectIsAvailableForFrame(*webPage, m_frame, world);
-
 #if ENABLE(WK_WEB_EXTENSIONS)
-    if (auto* extensionControllerProxy = webPage->webExtensionControllerProxy())
+    if (RefPtr extensionControllerProxy = webPage->webExtensionControllerProxy())
         extensionControllerProxy->serviceWorkerGlobalObjectIsAvailableForFrame(*webPage, m_frame, world);
 #endif
+
+    webPage->injectedBundleLoaderClient().serviceWorkerGlobalObjectIsAvailableForFrame(*webPage, m_frame, world);
 }
 
 void WebLocalFrameLoaderClient::willInjectUserScript(DOMWrapperWorld& world)
diff --git a/Source/WebKit/WebProcess/cocoa/RemoteRealtimeMediaSource.cpp b/Source/WebKit/WebProcess/cocoa/RemoteRealtimeMediaSource.cpp
index 4efa31682ff5..82441f710179 100644
--- a/Source/WebKit/WebProcess/cocoa/RemoteRealtimeMediaSource.cpp
+++ b/Source/WebKit/WebProcess/cocoa/RemoteRealtimeMediaSource.cpp
@@ -85,6 +85,11 @@ void RemoteRealtimeMediaSource::getPhotoCapabilities(PhotoCapabilitiesHandler&&
     m_proxy.getPhotoCapabilities(WTFMove(callback));
 }
 
+Ref RemoteRealtimeMediaSource::getPhotoSettings()
+{
+    return m_proxy.getPhotoSettings();
+}
+
 void RemoteRealtimeMediaSource::configurationChanged(String&& persistentID, WebCore::RealtimeMediaSourceSettings&& settings, WebCore::RealtimeMediaSourceCapabilities&& capabilities)
 {
     setPersistentId(WTFMove(persistentID));
diff --git a/Source/WebKit/WebProcess/cocoa/RemoteRealtimeMediaSource.h b/Source/WebKit/WebProcess/cocoa/RemoteRealtimeMediaSource.h
index 28ada928de24..3af943413d54 100644
--- a/Source/WebKit/WebProcess/cocoa/RemoteRealtimeMediaSource.h
+++ b/Source/WebKit/WebProcess/cocoa/RemoteRealtimeMediaSource.h
@@ -74,6 +74,7 @@ class RemoteRealtimeMediaSource : public WebCore::RealtimeMediaSource
     const WebCore::RealtimeMediaSourceSettings& settings() final { return m_settings; }
     const WebCore::RealtimeMediaSourceCapabilities& capabilities() final { return m_capabilities; }
     void getPhotoCapabilities(PhotoCapabilitiesHandler&&) final;
+    Ref getPhotoSettings() final;
 
 private:
     // RealtimeMediaSource
diff --git a/Source/WebKit/WebProcess/cocoa/RemoteRealtimeMediaSourceProxy.cpp b/Source/WebKit/WebProcess/cocoa/RemoteRealtimeMediaSourceProxy.cpp
index 4f0519167185..f367d9e4cc01 100644
--- a/Source/WebKit/WebProcess/cocoa/RemoteRealtimeMediaSourceProxy.cpp
+++ b/Source/WebKit/WebProcess/cocoa/RemoteRealtimeMediaSourceProxy.cpp
@@ -39,6 +39,7 @@
 #include 
 #include 
 #include 
+#include 
 
 namespace WebKit {
 using namespace WebCore;
@@ -117,6 +118,15 @@ void RemoteRealtimeMediaSourceProxy::getPhotoCapabilities(WebCore::RealtimeMedia
     m_connection->sendWithAsyncReply(Messages::UserMediaCaptureManagerProxy::GetPhotoCapabilities(identifier()), WTFMove(handler));
 }
 
+Ref RemoteRealtimeMediaSourceProxy::getPhotoSettings()
+{
+    return m_connection->sendWithPromisedReply(Messages::UserMediaCaptureManagerProxy::GetPhotoSettings(identifier()))->whenSettled(RunLoop::main(), [](Messages::UserMediaCaptureManagerProxy::GetPhotoSettings::Promise::Result&& result) {
+        if (result)
+            return WebCore::RealtimeMediaSource::PhotoSettingsPromise::createAndResolveOrReject(WTFMove(result.value()));
+        return WebCore::RealtimeMediaSource::PhotoSettingsPromise::createAndReject(String("IPC Connection closed"_s));
+    });
+}
+
 void RemoteRealtimeMediaSourceProxy::applyConstraintsSucceeded()
 {
     auto callback = m_pendingApplyConstraintsCallbacks.takeFirst();
diff --git a/Source/WebKit/WebProcess/cocoa/RemoteRealtimeMediaSourceProxy.h b/Source/WebKit/WebProcess/cocoa/RemoteRealtimeMediaSourceProxy.h
index 806f8fc52f0d..1112d506f87b 100644
--- a/Source/WebKit/WebProcess/cocoa/RemoteRealtimeMediaSourceProxy.h
+++ b/Source/WebKit/WebProcess/cocoa/RemoteRealtimeMediaSourceProxy.h
@@ -74,6 +74,7 @@ class RemoteRealtimeMediaSourceProxy {
     void endProducingData();
     void applyConstraints(const WebCore::MediaConstraints&, WebCore::RealtimeMediaSource::ApplyConstraintsHandler&&);
     void getPhotoCapabilities(WebCore::RealtimeMediaSource::PhotoCapabilitiesHandler&&);
+    Ref getPhotoSettings();
 
     void whenReady(CompletionHandler&&);
     void setAsReady();
diff --git a/Tools/Scripts/update-angle b/Tools/Scripts/update-angle
index dc63c2fed841..435c3e6d2f4e 100755
--- a/Tools/Scripts/update-angle
+++ b/Tools/Scripts/update-angle
@@ -12,7 +12,7 @@ q="-q"
 
 # Check for modified files in WebKit ignoring untracked file except in ANGLE dir
 check_uncommitted_changes() {
-    modified_files=$(git status --porcelain | grep -e "^[^?]" -e "^?? Source/ThirdParty/ANGLE")
+    modified_files=$(git status --porcelain | grep -e "^[^?]" -e "^?? Source/ThirdParty/ANGLE") || true
     if [ -n "$modified_files" ]; then
         echo "WebKit has uncommitted or untracked changes. Commit, stash, or remove them:"
         echo "$modified_files"
diff --git a/Tools/TestWebKitAPI/Tests/IPC/IPCTestUtilities.h b/Tools/TestWebKitAPI/Tests/IPC/IPCTestUtilities.h
index 09ef203783b7..a4d981680ad8 100644
--- a/Tools/TestWebKitAPI/Tests/IPC/IPCTestUtilities.h
+++ b/Tools/TestWebKitAPI/Tests/IPC/IPCTestUtilities.h
@@ -65,7 +65,7 @@ struct MockTestMessageWithAsyncReply1 {
     static constexpr IPC::MessageName asyncMessageReplyName() { return IPC::MessageName::WebPage_GetBytecodeProfileReply; }
     std::tuple<> arguments() { return { }; }
     using ReplyArguments = std::tuple;
-    using Promise = WTF::NativePromise;
+    using Promise = WTF::NativePromise;
 };
 
 class MockConnectionClient final : public IPC::Connection::Client {
diff --git a/Tools/TestWebKitAPI/Tests/WTF/NativePromise.cpp b/Tools/TestWebKitAPI/Tests/WTF/NativePromise.cpp
index 591483265789..3d5cc1b53d32 100644
--- a/Tools/TestWebKitAPI/Tests/WTF/NativePromise.cpp
+++ b/Tools/TestWebKitAPI/Tests/WTF/NativePromise.cpp
@@ -49,8 +49,8 @@ using namespace WTF;
 
 namespace TestWebKitAPI {
 
-using TestPromise = NativePromise;
-using TestPromiseExcl = NativePromise;
+using TestPromise = NativePromise;
+using TestPromiseExcl = NativePromise;
 
 class WorkQueueWithShutdown : public WorkQueue {
 public:
@@ -293,7 +293,7 @@ TEST(NativePromise, GenericPromise)
         // You can mix & match promise types and chain them together.
         // Producer also accepts syntax using operator-> for consistency with a consumer's promise.
         GenericPromise::Producer p5;
-        using MyPromise = NativePromise;
+        using MyPromise = NativePromise;
         p5->whenSettled(queue,
             [](GenericPromise::Result result) {
                 EXPECT_TRUE(result.has_value());
@@ -313,7 +313,7 @@ TEST(NativePromise, PromiseRequest)
 {
     // We declare the Request holder before using the runLoop to ensure it stays in scope for the entire run.
     // ASSERTION FAILED: !m_request
-    using MyPromise = NativePromise;
+    using MyPromise = NativePromise;
     NativePromiseRequest request1;
 
     runInCurrentRunLoop([&](auto& runLoop) {
@@ -777,7 +777,7 @@ TEST(NativePromise, Chaining)
 
 TEST(NativePromise, MoveOnlyType)
 {
-    using MyPromise = NativePromise, bool, true>;
+    using MyPromise = NativePromise, std::unique_ptr>;
 
     AutoWorkQueue awq;
     auto queue = awq.queue();
@@ -794,14 +794,284 @@ TEST(NativePromise, MoveOnlyType)
         [queue](MyPromise::Result&& val) {
             EXPECT_TRUE(val.has_value());
             EXPECT_EQ(87, *(val.value()));
+        });
+
+    MyPromise::createAndReject(makeUniqueWithoutFastMallocCheck(87))->whenSettled(queue,
+        [queue](MyPromise::Result&& val) {
+            EXPECT_FALSE(val.has_value());
+            EXPECT_EQ(87, *(val.error()));
+            queue->beginShutdown();
+        });
+}
+
+TEST(NativePromise, WTFString)
+{
+    using MyPromise = NativePromise;
+
+    AutoWorkQueue awq2;
+    auto queue2 = awq2.queue();
+
+    AutoWorkQueue awq;
+    auto queue = awq.queue();
+
+    MyPromise::createAndResolve("hello"_s)->then(queue,
+        [](String&& val) {
+            EXPECT_EQ(String("hello"_s), val);
+        },
+        [] {
+            EXPECT_TRUE(false);
+        });
+
+    MyPromise::createAndResolve("hello"_s)->whenSettled(queue,
+        [queue](MyPromise::Result&& val) {
+            EXPECT_TRUE(val.has_value());
+            EXPECT_EQ(String("hello"_s), val.value());
+            EXPECT_TRUE(val.value().isSafeToSendToAnotherThread());
+        });
+
+    MyPromise::createAndReject("error"_s)->whenSettled(queue,
+        [queue](MyPromise::Result&& val) {
+            EXPECT_FALSE(val.has_value());
+            EXPECT_EQ(String("error"_s), val.error());
+            EXPECT_TRUE(val.error().isSafeToSendToAnotherThread());
+        });
+
+    MyPromise::createAndResolve(String("hello"_s))->then(queue,
+        [](String&& val) {
+            EXPECT_EQ(String("hello"_s), val);
+            EXPECT_TRUE(val.isSafeToSendToAnotherThread());
+        },
+        [] {
+            EXPECT_TRUE(false);
+        });
+
+    // Check that we can receive the value by const reference too.
+    MyPromise::createAndResolve(String("hello"_s))->then(queue,
+        [](const String& val) {
+            EXPECT_EQ(String("hello"_s), val);
+            EXPECT_TRUE(val.isSafeToSendToAnotherThread());
+        },
+        [] {
+            EXPECT_TRUE(false);
+        });
+
+    // Can pass object implecitly convertible to ResolveValueType
+    MyPromise::createAndResolve(AtomString("hello"_s))->then(queue,
+        [](String&& val) {
+            EXPECT_EQ(String("hello"_s), val);
+            EXPECT_TRUE(val.isSafeToSendToAnotherThread());
+        },
+        [] {
+            EXPECT_TRUE(false);
+        });
+
+    MyPromise::createAndResolve(AtomString("hello"_s))->then(queue,
+        [](const String& val) {
+            EXPECT_EQ(String("hello"_s), val);
+            EXPECT_TRUE(val.isSafeToSendToAnotherThread());
+        },
+        [] {
+            EXPECT_TRUE(false);
+        });
+
+    MyPromise::createAndResolve(AtomString("hello"_s))->then(queue,
+        [](String val) {
+            EXPECT_EQ(String("hello"_s), val);
+            EXPECT_TRUE(val.isSafeToSendToAnotherThread());
+        },
+        [] {
+            EXPECT_TRUE(false);
+        });
+
+    MyPromise::createAndResolve(String("hello"_s))->whenSettled(queue,
+        [](MyPromise::Result&& val) {
+            EXPECT_TRUE(val.has_value());
+            EXPECT_TRUE(val.value().isSafeToSendToAnotherThread());
+            EXPECT_EQ(String("hello"_s), val.value());
+        });
+
+    MyPromise::createAndResolve(String("hello"_s))->whenSettled(queue,
+        [](MyPromise::Result val) {
+            EXPECT_TRUE(val.has_value());
+            EXPECT_TRUE(val.value().isSafeToSendToAnotherThread());
+            EXPECT_EQ(String("hello"_s), val.value());
+        });
+
+    MyPromise::createAndResolve(String("hello"_s))->whenSettled(queue,
+        [](const MyPromise::Result& val) {
+            EXPECT_TRUE(val.has_value());
+            EXPECT_TRUE(val.value().isSafeToSendToAnotherThread());
+            EXPECT_EQ(String("hello"_s), val.value());
+        });
+
+    MyPromise::createAndReject(String("error"_s))->whenSettled(queue,
+        [](MyPromise::Result&& val) {
+            EXPECT_FALSE(val.has_value());
+            EXPECT_TRUE(val.error().isSafeToSendToAnotherThread());
+            EXPECT_EQ(String("error"_s), val.error());
+        });
+
+    MyPromise::createAndResolve(AtomString("hello"_s))->whenSettled(queue,
+        [](MyPromise::Result&& val) {
+            EXPECT_TRUE(val.has_value());
+            EXPECT_TRUE(val.value().isSafeToSendToAnotherThread());
+            EXPECT_EQ(String("hello"_s), val.value());
+            return MyPromise::createAndResolveOrReject(WTFMove(val));
+        })->whenSettled(queue2,
+            [](MyPromise::Result val) {
+                EXPECT_TRUE(val.has_value());
+                EXPECT_TRUE(val.value().isSafeToSendToAnotherThread());
+                EXPECT_EQ(String("hello"_s), val.value());
+            });
+
+    MyPromise::createAndResolve(AtomString("hello"_s))->whenSettled(queue,
+        [queue](MyPromise::Result val) {
+            EXPECT_TRUE(val.has_value());
+            EXPECT_TRUE(val.value().isSafeToSendToAnotherThread());
+            EXPECT_EQ(String("hello"_s), val.value());
             queue->beginShutdown();
+            // Don't move the result to make sure we get a new isolatedCopy.
+            return MyPromise::createAndResolveOrReject(val);
+        })->whenSettled(queue2,
+            [queue2](MyPromise::Result val) {
+                EXPECT_TRUE(val.has_value());
+                EXPECT_TRUE(val.value().isSafeToSendToAnotherThread());
+                EXPECT_EQ(String("hello"_s), val.value());
+                queue2->beginShutdown();
+            });
+}
+
+TEST(NativePromise, WTFStringWithDelayedResolve)
+{
+    using MyPromise = NativePromise;
+
+    // The following steps runs strictly serially.
+    // 1. We create a promise on the main thread.
+    // 2. Dispatch a task that will `whenSettled()` on that promise on WorkQueue2.
+    // 3. We resolve on the main thread the promise with an AtomString.
+    // 4. Resolver will be called on WorkQueue1 and check that the string content is correct and the string created on the main thread was safely moved.
+
+    AutoWorkQueue awq1;
+    awq1.queue();
+    auto queue1 = awq1.queue();
+    MyPromise::Producer producer;
+    bool hasRun = false; // AutoWorkQueue guarantees that there can't be concurrent accesses to hasRun.
+    {
+        AutoWorkQueue awq2;
+        auto queue2 = awq2.queue();
+        queue2->dispatch([queue1, queue2, promise = Ref { producer }, &hasRun] {
+            promise->whenSettled(queue1,
+                [queue1](MyPromise::Result val) {
+                    EXPECT_TRUE(val.has_value());
+                    EXPECT_TRUE(val.value().isSafeToSendToAnotherThread());
+                    EXPECT_EQ(String("hello"_s), val.value());
+                    queue1->beginShutdown();
+                });
+            hasRun = true;
+            queue2->beginShutdown();
         });
+    }
+    EXPECT_TRUE(hasRun);
+    producer.resolve(AtomString("hello"_s));
 }
 
+TEST(NativePromise, NonExclusiveWithCrossThreadCopy)
+{
+    int resolution = 0;
+    {
+        AutoWorkQueue awq;
+        auto queue = awq.queue();
+        // If you replace PromiseOption::WithCrossThreadCopy with PromiseOption::WithoutCrossThreadCopy, this test will crash due to the AtomString being deleted on the target queue.
+        using MyPromise = NativePromise, bool, PromiseOption::NonExclusive | PromiseOption::WithCrossThreadCopy>;
+        static_assert(CrossThreadCopier>::IsNeeded);
+        MyPromise::Producer producer;
+        Ref p = producer;
+        p->whenSettled(queue, [&resolution] (const MyPromise::Result& val) {
+            EXPECT_TRUE(val.has_value());
+            EXPECT_TRUE(val.value().has_value());
+            EXPECT_TRUE(val.value().value().isSafeToSendToAnotherThread());
+            EXPECT_EQ(String("that worked"_s), val.value().value());
+            resolution++;
+        });
+        p->whenSettled(queue, [&resolution] (MyPromise::Result val) {
+            EXPECT_TRUE(val.has_value());
+            EXPECT_TRUE(val.value().has_value());
+            // Being a non-exclusive promise, the value is passed by const reference, so we copied the object in val.
+            EXPECT_TRUE(!val.value().value().isSafeToSendToAnotherThread());
+            EXPECT_EQ(String("that worked"_s), val.value().value());
+            resolution++;
+        });
+        p->whenSettled(queue, [queue, &resolution] (const MyPromise::Result& val) {
+            EXPECT_TRUE(val.has_value());
+            EXPECT_TRUE(val.value().has_value());
+            // The previous whenSettled() has run already, and the object was derefed.
+            EXPECT_TRUE(val.value().value().isSafeToSendToAnotherThread());
+            EXPECT_EQ(String("that worked"_s), val.value().value());
+            resolution++;
+            queue->beginShutdown();
+        });
+        producer.resolve(String(AtomString("that worked"_s)));
+    }
+    EXPECT_EQ(3, resolution);
+}
+
+TEST(NativePromise, WithCrossThreadCopyType)
+{
+    using MyPromiseWithString = NativePromise;
+    static_assert(MyPromiseWithString::WithAutomaticCrossThreadCopy);
+    static_assert(CrossThreadCopier::IsNeeded);
+    // Check that if making a NativePromise with an AtomString, you actually get a String
+    static_assert(std::is_same_v);
+
+    using MyPromiseWithoutString = NativePromise;
+    static_assert(!MyPromiseWithoutString::WithAutomaticCrossThreadCopy);
+
+    using MyPromiseWithArrayOfString = NativePromise, bool>;
+    static_assert(MyPromiseWithArrayOfString::WithAutomaticCrossThreadCopy);
+
+    using MyNonExclusivePromise = NativePromise, bool, PromiseOption::Default | PromiseOption::NonExclusive>;
+    // No need for crossThreadProxy for a Vector not containing a type with isolatedCopy() method.
+    static_assert(!MyNonExclusivePromise::WithAutomaticCrossThreadCopy);
+}
+
+TEST(NativePromise, ExpectedWithString)
+{
+    using MyPromise = NativePromise, int>;
+
+    AutoWorkQueue awq;
+    auto queue = awq.queue();
+
+    MyPromise::createAndResolve(String("hello"_s))->then(queue,
+        [](MyPromise::ResolveValueType&& val) {
+            EXPECT_TRUE(val.has_value());
+            EXPECT_EQ(String("hello"_s), val.value());
+            EXPECT_TRUE(val.value().isSafeToSendToAnotherThread());
+        },
+        [] {
+            EXPECT_TRUE(false);
+        });
+
+    MyPromise::createAndResolve(String("hello"_s))->whenSettled(queue,
+        [queue](MyPromise::Result&& val) {
+            EXPECT_TRUE(val.has_value());
+            EXPECT_EQ(String("hello"_s), val.value());
+            EXPECT_TRUE(val.value().value().isSafeToSendToAnotherThread());
+        });
+
+    Expected error = Unexpected("error"_s);
+    MyPromise::createAndResolve(WTFMove(error))->whenSettled(queue,
+        [queue](MyPromise::Result&& val) {
+            EXPECT_TRUE(val.has_value());
+            EXPECT_FALSE(val.value().has_value());
+            EXPECT_EQ(String("error"_s), val.value().error());
+            EXPECT_TRUE(val.value().error().isSafeToSendToAnotherThread());
+            queue->beginShutdown();
+        });
+}
 TEST(NativePromise, HeterogeneousChaining)
 {
-    using Promise1 = NativePromise, bool, true>;
-    using Promise2 = NativePromise, bool, true>;
+    using Promise1 = NativePromise, bool>;
+    using Promise2 = NativePromise, bool>;
 
     NativePromiseRequest holder;
 
diff --git a/Tools/TestWebKitAPI/Tests/WTF/Vector.cpp b/Tools/TestWebKitAPI/Tests/WTF/Vector.cpp
index 409550d73977..6a7fb4d55357 100644
--- a/Tools/TestWebKitAPI/Tests/WTF/Vector.cpp
+++ b/Tools/TestWebKitAPI/Tests/WTF/Vector.cpp
@@ -339,6 +339,23 @@ TEST(WTF_Vector, ConstructorTakingLengthAndFunctor)
     EXPECT_EQ(vector[4], 4U);
 }
 
+TEST(WTF_Vector, AppendList)
+{
+    Vector vector({ 1, 2, 3 });
+    EXPECT_EQ(vector.size(), 3U);
+    EXPECT_EQ(vector[0], 1U);
+    EXPECT_EQ(vector[1], 2U);
+    EXPECT_EQ(vector[2], 3U);
+    vector.appendList({ 4, 5, 6 });
+    EXPECT_EQ(vector.size(), 6U);
+    EXPECT_EQ(vector[0], 1U);
+    EXPECT_EQ(vector[1], 2U);
+    EXPECT_EQ(vector[2], 3U);
+    EXPECT_EQ(vector[3], 4U);
+    EXPECT_EQ(vector[4], 5U);
+    EXPECT_EQ(vector[5], 6U);
+}
+
 TEST(WTF_Vector, Reverse)
 {
     Vector intVector;
diff --git a/Tools/TestWebKitAPI/glib/TestExpectations.json b/Tools/TestWebKitAPI/glib/TestExpectations.json
index 200e7599d5b3..ff013cf49dbf 100644
--- a/Tools/TestWebKitAPI/glib/TestExpectations.json
+++ b/Tools/TestWebKitAPI/glib/TestExpectations.json
@@ -72,6 +72,9 @@
             },
             "/webkit/WebKitWebView/fullscreen": {
                 "expected": {"gtk": {"status": ["SKIP"], "bug": "webkit.org/b/248203"}}
+            },
+            "/webkit/WebKitWebView/external-audio-rendering": {
+                "expected": {"wpe": {"status": ["TIMEOUT"], "bug": "webkit.org/b/262625"}}
             }
         }
     },