Title: [276780] trunk
Revision
276780
Author
[email protected]
Date
2021-04-29 09:39:55 -0700 (Thu, 29 Apr 2021)

Log Message

Extend SortedArrayMap further to work on case-folded strings, use in MIMETypeRegistry
https://bugs.webkit.org/show_bug.cgi?id=224968

Reviewed by Sam Weinig.

Source/WebCore:

Using fewer HashSet in MIMETypeRegistry saves code size and reduces memory use.

* platform/MIMETypeRegistry.cpp:
(WebCore::MIMETypeRegistry::supportedImageMIMETypes): Deleted. Replaced
this function with a constexpr array, eliminating the use of HashSet.
(WebCore::makeFixedVector): Added. Helper function used below for the repeated patttern
of converting a constexpr array into a FixedVector<const char*>.
(WebCore::supportedJavaScriptMIMETypes): Deleted.
(WebCore::MIMETypeRegistry::supportedNonImageMIMETypes): Update since
supportedJavaScriptMIMETypeArray is now an array, not a HashSet.
(WebCore::MIMETypeRegistry::pdfMIMETypes): Rewrote to return a FixedVector<const char*>
instead of a HashSet. The only caller makes an NSArray<NSString *>, so there is no need
to involve a hash table or a WTF::String.
(WebCore::MIMETypeRegistry::unsupportedTextMIMETypes): Ditto.
(WebCore::commonMediaTypes): Deleted, merging into the function below.
(WebCore::commonMimeTypesMap): Moved the commonMediaTypes data in here
and use a constexpr array instead of an initializer_list.
(WebCore::MIMETypeRegistry::isSupportedImageMIMEType): Use SortedArraySet
instead of a HashSet for the core supported images types. Moved the code
that checks this against defaultSupportedImageTypes here.
(WebCore::MIMETypeRegistry::isSupportedJavaScriptMIMEType): Use SortedArraySet.
(WebCore::MIMETypeRegistry::isUnsupportedTextMIMEType): Ditto.
(WebCore::MIMETypeRegistry::isPDFMIMEType): Ditto.
(WebCore::MIMETypeRegistry::isPostScriptMIMEType): Use equalLettersIgnoringASCIICase.
For some reason this was the single case-sensitive function in this whole class!
(WebCore::MIMETypeRegistry::isSystemPreviewMIMEType): Use SortedArraySet.
(WebCore::MIMETypeRegistry::systemPreviewMIMETypes): Return a FixedVector.
(WebCore::normalizedImageMIMEType): Renamed this from its old name,
MIMETypeRegistry::normalizedMIMEType, to better reflect that it's only used in
one place. Also added comments to clarify that it's CURL-only and suggest it be
removed eventually.

* platform/MIMETypeRegistry.h: Changed supportedImageMIMETypes, pdfMIMETypes,
unsupportedTextMIMETypes, and systemPreviewMIMETypes to return FixedVector instead
of HashSet. Also removed normalizedMIMEType.

* svg/SVGTransformValue.h: Removed unneeded include of HashMap.h.
* testing/TypeConversions.h: Ditto.

Source/WebKit:

* UIProcess/API/ios/WKWebViewIOS.mm:
(-[WKWebView _isDisplayingPDF]): Updated since MIMETypeRegistry::pdfMIMETypes
returns a different type.
* UIProcess/Cocoa/WKWebViewContentProviderRegistry.mm:
(-[WKWebViewContentProviderRegistry initWithConfiguration:]): Updated since
MIMETypeRegistry::systemPreviewMIMETypes returns a different type.

Source/WebKitLegacy/mac:

* WebView/WebHTMLRepresentation.mm:
(createNSArray): Renamed from newArrayWithStrings so this overloads the createNSArray
function from VectorCocoa.h so we can use the two interchangably and handle both FixedVector
and HashSet with the smae code.
(+[WebHTMLRepresentation supportedMediaMIMETypes]): Updated for name change.
(+[WebHTMLRepresentation supportedNonImageMIMETypes]): Ditto.
(+[WebHTMLRepresentation supportedImageMIMETypes]): Ditto.
(+[WebHTMLRepresentation unsupportedTextMIMETypes]): Ditto.

Source/WTF:

* wtf/ASCIICType.h: Make most functions constexpr.

* wtf/Forward.h: Added FixedVector.

* wtf/SortedArrayMap.h: Added SortedArraySet. Added ComparableCaseFoldingASCIILiteral
and ComparableLettersLiteral, using a template shared with ComparableASCIILiteral.

* wtf/StdLibExtras.h: Added isSortedConstExpr and allOfConstExpr.

Tools:

* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj: Added SortedArrayMap.cpp,
and removed references to non-existent FullscreenRemoveNodeBeforeEnter.h and
FloatQuadTests.h.
* TestWebKitAPI/Tests/WTF/SortedArrayMap.cpp: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WTF/ChangeLog (276779 => 276780)


--- trunk/Source/WTF/ChangeLog	2021-04-29 16:26:38 UTC (rev 276779)
+++ trunk/Source/WTF/ChangeLog	2021-04-29 16:39:55 UTC (rev 276780)
@@ -1,3 +1,19 @@
+2021-04-29  Darin Adler  <[email protected]>
+
+        Extend SortedArrayMap further to work on case-folded strings, use in MIMETypeRegistry
+        https://bugs.webkit.org/show_bug.cgi?id=224968
+
+        Reviewed by Sam Weinig.
+
+        * wtf/ASCIICType.h: Make most functions constexpr.
+
+        * wtf/Forward.h: Added FixedVector.
+
+        * wtf/SortedArrayMap.h: Added SortedArraySet. Added ComparableCaseFoldingASCIILiteral
+        and ComparableLettersLiteral, using a template shared with ComparableASCIILiteral.
+
+        * wtf/StdLibExtras.h: Added isSortedConstExpr and allOfConstExpr.
+
 2021-04-29  Ben Nham  <[email protected]>
 
         Unreviewed, reverting r276619.

Modified: trunk/Source/WTF/wtf/ASCIICType.h (276779 => 276780)


--- trunk/Source/WTF/wtf/ASCIICType.h	2021-04-29 16:26:38 UTC (rev 276779)
+++ trunk/Source/WTF/wtf/ASCIICType.h	2021-04-29 16:39:55 UTC (rev 276780)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2019 Apple Inc. All rights reserved.
+ * Copyright (C) 2007-2021 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -40,16 +40,17 @@
 namespace WTF {
 
 template<typename CharacterType> constexpr bool isASCII(CharacterType);
-template<typename CharacterType> bool isASCIIAlpha(CharacterType);
-template<typename CharacterType> bool isASCIIAlphanumeric(CharacterType);
-template<typename CharacterType> bool isASCIIBinaryDigit(CharacterType);
-template<typename CharacterType> bool isASCIIDigit(CharacterType);
-template<typename CharacterType> bool isASCIIHexDigit(CharacterType);
-template<typename CharacterType> bool isASCIILower(CharacterType);
-template<typename CharacterType> bool isASCIIOctalDigit(CharacterType);
-template<typename CharacterType> bool isASCIIPrintable(CharacterType);
-template<typename CharacterType> bool isASCIISpace(CharacterType);
-template<typename CharacterType> bool isASCIIUpper(CharacterType);
+template<typename CharacterType> constexpr bool isASCIIAlpha(CharacterType);
+template<typename CharacterType> constexpr bool isASCIIAlphanumeric(CharacterType);
+template<typename CharacterType> constexpr bool isASCIIBinaryDigit(CharacterType);
+template<typename CharacterType> constexpr bool isASCIIDigit(CharacterType);
+template<typename CharacterType> constexpr bool isASCIIDigitOrPunctuation(CharacterType);
+template<typename CharacterType> constexpr bool isASCIIHexDigit(CharacterType);
+template<typename CharacterType> constexpr bool isASCIILower(CharacterType);
+template<typename CharacterType> constexpr bool isASCIIOctalDigit(CharacterType);
+template<typename CharacterType> constexpr bool isASCIIPrintable(CharacterType);
+template<typename CharacterType> constexpr bool isASCIISpace(CharacterType);
+template<typename CharacterType> constexpr bool isASCIIUpper(CharacterType);
 
 template<typename CharacterType> CharacterType toASCIILower(CharacterType);
 template<typename CharacterType> CharacterType toASCIIUpper(CharacterType);
@@ -57,18 +58,18 @@
 template<typename CharacterType> uint8_t toASCIIHexValue(CharacterType);
 template<typename CharacterType> uint8_t toASCIIHexValue(CharacterType firstCharacter, CharacterType secondCharacter);
 
-char lowerNibbleToASCIIHexDigit(uint8_t);
-char upperNibbleToASCIIHexDigit(uint8_t);
-char lowerNibbleToLowercaseASCIIHexDigit(uint8_t);
-char upperNibbleToLowercaseASCIIHexDigit(uint8_t);
+constexpr char lowerNibbleToASCIIHexDigit(uint8_t);
+constexpr char upperNibbleToASCIIHexDigit(uint8_t);
+constexpr char lowerNibbleToLowercaseASCIIHexDigit(uint8_t);
+constexpr char upperNibbleToLowercaseASCIIHexDigit(uint8_t);
 
-template<typename CharacterType> bool isASCIIAlphaCaselessEqual(CharacterType, char expectedASCIILowercaseLetter);
+template<typename CharacterType> constexpr bool isASCIIAlphaCaselessEqual(CharacterType, char expectedASCIILowercaseLetter);
 
 // The toASCIILowerUnchecked function can be used for comparing any input character
 // to a lowercase English character. The isASCIIAlphaCaselessEqual function should
 // be used for regular comparison of ASCII alpha characters, but switch statements
 // in the CSS tokenizer, for example, instead make direct use toASCIILowerUnchecked.
-template<typename CharacterType> CharacterType toASCIILowerUnchecked(CharacterType);
+template<typename CharacterType> constexpr CharacterType toASCIILowerUnchecked(CharacterType);
 
 extern WTF_EXPORT_PRIVATE const unsigned char asciiCaseFoldTable[256];
 
@@ -77,12 +78,12 @@
     return !(character & ~0x7F);
 }
 
-template<typename CharacterType> inline bool isASCIILower(CharacterType character)
+template<typename CharacterType> constexpr bool isASCIILower(CharacterType character)
 {
     return character >= 'a' && character <= 'z';
 }
 
-template<typename CharacterType> inline CharacterType toASCIILowerUnchecked(CharacterType character)
+template<typename CharacterType> constexpr CharacterType toASCIILowerUnchecked(CharacterType character)
 {
     // This function can be used for comparing any input character
     // to a lowercase English character. The isASCIIAlphaCaselessEqual
@@ -92,37 +93,37 @@
     return character | 0x20;
 }
 
-template<typename CharacterType> inline bool isASCIIAlpha(CharacterType character)
+template<typename CharacterType> constexpr bool isASCIIAlpha(CharacterType character)
 {
     return isASCIILower(toASCIILowerUnchecked(character));
 }
 
-template<typename CharacterType> inline bool isASCIIDigit(CharacterType character)
+template<typename CharacterType> constexpr bool isASCIIDigit(CharacterType character)
 {
     return character >= '0' && character <= '9';
 }
 
-template<typename CharacterType> inline bool isASCIIAlphanumeric(CharacterType character)
+template<typename CharacterType> constexpr bool isASCIIAlphanumeric(CharacterType character)
 {
     return isASCIIDigit(character) || isASCIIAlpha(character);
 }
 
-template<typename CharacterType> inline bool isASCIIHexDigit(CharacterType character)
+template<typename CharacterType> constexpr bool isASCIIHexDigit(CharacterType character)
 {
     return isASCIIDigit(character) || (toASCIILowerUnchecked(character) >= 'a' && toASCIILowerUnchecked(character) <= 'f');
 }
 
-template<typename CharacterType> inline bool isASCIIBinaryDigit(CharacterType character)
+template<typename CharacterType> constexpr bool isASCIIBinaryDigit(CharacterType character)
 {
     return character == '0' || character == '1';
 }
 
-template<typename CharacterType> inline bool isASCIIOctalDigit(CharacterType character)
+template<typename CharacterType> constexpr bool isASCIIOctalDigit(CharacterType character)
 {
     return character >= '0' && character <= '7';
 }
 
-template<typename CharacterType> inline bool isASCIIPrintable(CharacterType character)
+template<typename CharacterType> constexpr bool isASCIIPrintable(CharacterType character)
 {
     return character >= ' ' && character <= '~';
 }
@@ -143,12 +144,12 @@
     Because of those, we first check to quickly return false for non-control characters,
     then check for space itself to quickly return true for that case, then do the rest.
 */
-template<typename CharacterType> inline bool isASCIISpace(CharacterType character)
+template<typename CharacterType> constexpr bool isASCIISpace(CharacterType character)
 {
     return character <= ' ' && (character == ' ' || (character <= 0xD && character >= 0x9));
 }
 
-template<typename CharacterType> inline bool isASCIIUpper(CharacterType character)
+template<typename CharacterType> constexpr bool isASCIIUpper(CharacterType character)
 {
     return character >= 'A' && character <= 'Z';
 }
@@ -184,31 +185,31 @@
     return toASCIIHexValue(firstCharacter) << 4 | toASCIIHexValue(secondCharacter);
 }
 
-inline char lowerNibbleToASCIIHexDigit(uint8_t value)
+constexpr char lowerNibbleToASCIIHexDigit(uint8_t value)
 {
     uint8_t nibble = value & 0xF;
     return nibble + (nibble < 10 ? '0' : 'A' - 10);
 }
 
-inline char upperNibbleToASCIIHexDigit(uint8_t value)
+constexpr char upperNibbleToASCIIHexDigit(uint8_t value)
 {
     uint8_t nibble = value >> 4;
     return nibble + (nibble < 10 ? '0' : 'A' - 10);
 }
 
-inline char lowerNibbleToLowercaseASCIIHexDigit(uint8_t value)
+constexpr char lowerNibbleToLowercaseASCIIHexDigit(uint8_t value)
 {
     uint8_t nibble = value & 0xF;
     return nibble + (nibble < 10 ? '0' : 'a' - 10);
 }
 
-inline char upperNibbleToLowercaseASCIIHexDigit(uint8_t value)
+constexpr char upperNibbleToLowercaseASCIIHexDigit(uint8_t value)
 {
     uint8_t nibble = value >> 4;
     return nibble + (nibble < 10 ? '0' : 'a' - 10);
 }
 
-template<typename CharacterType> inline bool isASCIIAlphaCaselessEqual(CharacterType inputCharacter, char expectedASCIILowercaseLetter)
+template<typename CharacterType> constexpr bool isASCIIAlphaCaselessEqual(CharacterType inputCharacter, char expectedASCIILowercaseLetter)
 {
     // Name of this argument says this must be a lowercase letter, but it can actually be:
     //   - a lowercase letter
@@ -225,9 +226,9 @@
     return LIKELY(toASCIILowerUnchecked(inputCharacter) == expectedASCIILowercaseLetter);
 }
 
-template<typename CharacterType> inline bool isASCIIDigitOrPunctuation(CharacterType charCode)
+template<typename CharacterType> constexpr bool isASCIIDigitOrPunctuation(CharacterType character)
 {
-    return (charCode >= '!' && charCode <= '@') || (charCode >= '[' && charCode <= '`') || (charCode >= '{' && charCode <= '~');
+    return (character >= '!' && character <= '@') || (character >= '[' && character <= '`') || (character >= '{' && character <= '~');
 }
 
 }

Modified: trunk/Source/WTF/wtf/Forward.h (276779 => 276780)


--- trunk/Source/WTF/wtf/Forward.h	2021-04-29 16:26:38 UTC (rev 276779)
+++ trunk/Source/WTF/wtf/Forward.h	2021-04-29 16:39:55 UTC (rev 276780)
@@ -62,6 +62,7 @@
 template<typename> struct DefaultRefDerefTraits;
 
 template<typename> class CompletionHandler;
+template<typename> class FixedVector;
 template<typename> class Function;
 template<typename, typename = AnyThreadsAccessTraits> class LazyNeverDestroyed;
 template<typename, typename = AnyThreadsAccessTraits> class NeverDestroyed;
@@ -118,6 +119,7 @@
 using WTF::BinarySemaphore;
 using WTF::CString;
 using WTF::CompletionHandler;
+using WTF::FixedVector;
 using WTF::Function;
 using WTF::FunctionDispatcher;
 using WTF::HashCountedSet;

Modified: trunk/Source/WTF/wtf/SortedArrayMap.h (276779 => 276780)


--- trunk/Source/WTF/wtf/SortedArrayMap.h	2021-04-29 16:26:38 UTC (rev 276779)
+++ trunk/Source/WTF/wtf/SortedArrayMap.h	2021-04-29 16:39:55 UTC (rev 276780)
@@ -52,39 +52,69 @@
     const ArrayType& m_array;
 };
 
+template<typename ArrayType> class SortedArraySet {
+public:
+    constexpr SortedArraySet(const ArrayType&);
+    template<typename KeyArgument> bool contains(const KeyArgument&) const;
+
+private:
+    const ArrayType& m_array;
+};
+
 struct ComparableStringView {
     StringView string;
 };
 
-struct ComparableASCIILiteral {
-    const char* literal;
-    template<std::size_t size> constexpr ComparableASCIILiteral(const char (&characters)[size]) : literal { characters } { }
+// NoUppercaseLettersOptimized means no characters with the 0x20 bit set.
+// That means the strings can't include control characters, uppercase letters, or any of @[\]_.
+enum class ASCIISubset { All, NoUppercaseLetters, NoUppercaseLettersOptimized };
+
+template<ASCIISubset> struct ComparableASCIISubsetLiteral {
+    ASCIILiteral literal;
+    template<std::size_t size> constexpr ComparableASCIISubsetLiteral(const char (&characters)[size]);
     static Optional<ComparableStringView> parse(StringView string) { return { { string } }; }
 };
 
-constexpr bool operator==(ComparableASCIILiteral, ComparableASCIILiteral);
-constexpr bool operator<(ComparableASCIILiteral, ComparableASCIILiteral);
+using ComparableASCIILiteral = ComparableASCIISubsetLiteral<ASCIISubset::All>;
+using ComparableCaseFoldingASCIILiteral = ComparableASCIISubsetLiteral<ASCIISubset::NoUppercaseLetters>;
+using ComparableLettersLiteral = ComparableASCIISubsetLiteral<ASCIISubset::NoUppercaseLettersOptimized>;
 
+template<ASCIISubset subset> constexpr bool operator==(ComparableASCIISubsetLiteral<subset>, ComparableASCIISubsetLiteral<subset>);
+template<ASCIISubset subset> constexpr bool operator<(ComparableASCIISubsetLiteral<subset>, ComparableASCIISubsetLiteral<subset>);
+
 bool operator==(ComparableStringView, ComparableASCIILiteral);
+bool operator==(ComparableStringView, ComparableCaseFoldingASCIILiteral);
+bool operator==(ComparableStringView, ComparableLettersLiteral);
 bool operator<(ComparableStringView, ComparableASCIILiteral);
-bool operator!=(ComparableStringView, ComparableASCIILiteral);
-bool operator==(ComparableASCIILiteral, ComparableStringView);
+bool operator<(ComparableStringView, ComparableCaseFoldingASCIILiteral);
+bool operator<(ComparableStringView, ComparableLettersLiteral);
 
-// FIXME: Use std::is_sorted instead of this and remove it, once we require C++20.
-template<typename Iterator, typename Predicate> constexpr bool isSortedConstExpr(Iterator begin, Iterator end, Predicate predicate)
+template<typename OtherType> bool operator==(OtherType, ComparableStringView);
+template<typename OtherType> bool operator!=(ComparableStringView, OtherType);
+
+template<ASCIISubset subset> constexpr bool isInSubset(char character)
 {
-    if (begin == end)
+    if (!(character && isASCII(character)))
+        return false;
+    switch (subset) {
+    case ASCIISubset::All:
         return true;
-    auto current = begin;
-    auto previous = current;
-    while (++current != end) {
-        if (!predicate(*previous, *current))
-            return false;
-        previous = current;
+    case ASCIISubset::NoUppercaseLetters:
+        return !isASCIIUpper(character);
+    case ASCIISubset::NoUppercaseLettersOptimized:
+        return character == toASCIILowerUnchecked(character);
     }
-    return true;
 }
 
+template<ASCIISubset subset> template<std::size_t size> constexpr ComparableASCIISubsetLiteral<subset>::ComparableASCIISubsetLiteral(const char (&characters)[size])
+    : literal { ASCIILiteral::fromLiteralUnsafe(characters) }
+{
+    ASSERT_UNDER_CONSTEXPR_CONTEXT(allOfConstExpr(&characters[0], &characters[size - 1], [] (char character) {
+        return isInSubset<subset>(character);
+    }));
+    ASSERT_UNDER_CONSTEXPR_CONTEXT(!characters[size - 1]);
+}
+
 template<typename ArrayType> constexpr SortedArrayMap<ArrayType>::SortedArrayMap(const ArrayType& array)
     : m_array { array }
 {
@@ -112,6 +142,23 @@
     return result ? *result : defaultValue;
 }
 
+template<typename ArrayType> constexpr SortedArraySet<ArrayType>::SortedArraySet(const ArrayType& array)
+    : m_array { array }
+{
+    ASSERT_UNDER_CONSTEXPR_CONTEXT(isSortedConstExpr(std::begin(array), std::end(array)));
+}
+
+template<typename ArrayType> template<typename KeyArgument> inline bool SortedArraySet<ArrayType>::contains(const KeyArgument& key) const
+{
+    using ElementType = typename std::remove_extent_t<ArrayType>;
+    auto parsedKey = ElementType::parse(key);
+    // FIXME: We should enhance tryBinarySearch so it can deduce ElementType.
+    // FIXME: If the array's size is small enough, should do linear search since it is more efficient than binary search.
+    return parsedKey && tryBinarySearch<ElementType>(m_array, std::size(m_array), *parsedKey, [] (auto* element) {
+        return *element;
+    });
+}
+
 constexpr int strcmpConstExpr(const char* a, const char* b)
 {
     while (*a == *b && *a && *b) {
@@ -121,16 +168,35 @@
     return *a == *b ? 0 : *a < *b ? -1 : 1;
 }
 
-constexpr bool operator==(ComparableASCIILiteral a, ComparableASCIILiteral b)
+template<typename CharacterType> inline bool lessThanASCIICaseFolding(const CharacterType* characters, unsigned length, const char* literalWithNoUppercase)
 {
-    return !strcmpConstExpr(a.literal, b.literal);
+    for (unsigned i = 0; i < length; ++i) {
+        if (!literalWithNoUppercase[i])
+            return false;
+        auto character = toASCIILower(characters[i]);
+        if (character != literalWithNoUppercase[i])
+            return character < literalWithNoUppercase[i];
+    }
+    return true;
 }
 
-constexpr bool operator<(ComparableASCIILiteral a, ComparableASCIILiteral b)
+inline bool lessThanASCIICaseFolding(StringView string, const char* literalWithNoUppercase)
 {
-    return strcmpConstExpr(a.literal, b.literal) < 0;
+    if (string.is8Bit())
+        return lessThanASCIICaseFolding(string.characters8(), string.length(), literalWithNoUppercase);
+    return lessThanASCIICaseFolding(string.characters16(), string.length(), literalWithNoUppercase);
 }
 
+template<ASCIISubset subset> constexpr bool operator==(ComparableASCIISubsetLiteral<subset> a, ComparableASCIISubsetLiteral<subset> b)
+{
+    return !strcmpConstExpr(a.literal.characters(), b.literal.characters());
+}
+
+template<ASCIISubset subset> constexpr bool operator<(ComparableASCIISubsetLiteral<subset> a, ComparableASCIISubsetLiteral<subset> b)
+{
+    return strcmpConstExpr(a.literal.characters(), b.literal.characters()) < 0;
+}
+
 inline bool operator==(ComparableStringView a, ComparableASCIILiteral b)
 {
     return a.string == b.literal;
@@ -138,20 +204,45 @@
 
 inline bool operator<(ComparableStringView a, ComparableASCIILiteral b)
 {
-    return codePointCompare(a.string, b.literal) < 0;
+    return codePointCompare(a.string, b.literal.characters()) < 0;
 }
 
-inline bool operator!=(ComparableStringView a, ComparableASCIILiteral b)
+inline bool operator==(ComparableStringView a, ComparableLettersLiteral b)
 {
-    return !(a == b);
+    return equalLettersIgnoringASCIICaseCommonWithoutLength(a.string, b.literal);
 }
 
-inline bool operator==(ComparableASCIILiteral a, ComparableStringView b)
+inline bool operator<(ComparableStringView a, ComparableLettersLiteral b)
 {
+    return lessThanASCIICaseFolding(a.string, b.literal);
+}
+
+inline bool operator==(ComparableStringView a, ComparableCaseFoldingASCIILiteral b)
+{
+    return equalIgnoringASCIICase(a.string, b.literal);
+}
+
+inline bool operator<(ComparableStringView a, ComparableCaseFoldingASCIILiteral b)
+{
+    return lessThanASCIICaseFolding(a.string, b.literal);
+}
+
+template<typename OtherType> inline bool operator==(OtherType a, ComparableStringView b)
+{
     return b == a;
 }
 
+template<typename OtherType> inline bool operator!=(ComparableStringView a, OtherType b)
+{
+    return !(a == b);
 }
 
+}
+
+using WTF::ASCIISubset;
 using WTF::ComparableASCIILiteral;
+using WTF::ComparableASCIISubsetLiteral;
+using WTF::ComparableCaseFoldingASCIILiteral;
+using WTF::ComparableLettersLiteral;
 using WTF::SortedArrayMap;
+using WTF::SortedArraySet;

Modified: trunk/Source/WTF/wtf/StdLibExtras.h (276779 => 276780)


--- trunk/Source/WTF/wtf/StdLibExtras.h	2021-04-29 16:26:38 UTC (rev 276779)
+++ trunk/Source/WTF/wtf/StdLibExtras.h	2021-04-29 16:39:55 UTC (rev 276780)
@@ -527,6 +527,37 @@
     return constructFixedSizeArrayWithArgumentsImpl<ResultType>(tuple, std::forward<Args>(args)...);
 }
 
+// FIXME: Use std::is_sorted instead of this and remove it, once we require C++20.
+template<typename Iterator, typename Predicate> constexpr bool isSortedConstExpr(Iterator first, Iterator last, Predicate predicate)
+{
+    if (first == last)
+        return true;
+    auto current = first;
+    auto previous = current;
+    while (++current != last) {
+        if (!predicate(*previous, *current))
+            return false;
+        previous = current;
+    }
+    return true;
+}
+
+// FIXME: Use std::is_sorted instead of this and remove it, once we require C++20.
+template<typename Iterator> constexpr bool isSortedConstExpr(Iterator first, Iterator last)
+{
+    return isSortedConstExpr(first, last, [] (auto& a, auto& b) { return a < b; });
+}
+
+// FIXME: Use std::all_of instead of this and remove it, once we require C++20.
+template<typename Iterator, typename Predicate> constexpr bool allOfConstExpr(Iterator first, Iterator last, Predicate predicate)
+{
+    for (; first != last; ++first) {
+        if (!predicate(*first))
+            return false;
+    }
+    return true;
+}
+
 } // namespace WTF
 
 #define WTFMove(value) std::move<WTF::CheckMoveParameter>(value)

Modified: trunk/Source/WebCore/ChangeLog (276779 => 276780)


--- trunk/Source/WebCore/ChangeLog	2021-04-29 16:26:38 UTC (rev 276779)
+++ trunk/Source/WebCore/ChangeLog	2021-04-29 16:39:55 UTC (rev 276780)
@@ -1,3 +1,49 @@
+2021-04-29  Darin Adler  <[email protected]>
+
+        Extend SortedArrayMap further to work on case-folded strings, use in MIMETypeRegistry
+        https://bugs.webkit.org/show_bug.cgi?id=224968
+
+        Reviewed by Sam Weinig.
+
+        Using fewer HashSet in MIMETypeRegistry saves code size and reduces memory use.
+
+        * platform/MIMETypeRegistry.cpp:
+        (WebCore::MIMETypeRegistry::supportedImageMIMETypes): Deleted. Replaced
+        this function with a constexpr array, eliminating the use of HashSet.
+        (WebCore::makeFixedVector): Added. Helper function used below for the repeated patttern
+        of converting a constexpr array into a FixedVector<const char*>.
+        (WebCore::supportedJavaScriptMIMETypes): Deleted.
+        (WebCore::MIMETypeRegistry::supportedNonImageMIMETypes): Update since
+        supportedJavaScriptMIMETypeArray is now an array, not a HashSet.
+        (WebCore::MIMETypeRegistry::pdfMIMETypes): Rewrote to return a FixedVector<const char*>
+        instead of a HashSet. The only caller makes an NSArray<NSString *>, so there is no need
+        to involve a hash table or a WTF::String.
+        (WebCore::MIMETypeRegistry::unsupportedTextMIMETypes): Ditto.
+        (WebCore::commonMediaTypes): Deleted, merging into the function below.
+        (WebCore::commonMimeTypesMap): Moved the commonMediaTypes data in here
+        and use a constexpr array instead of an initializer_list.
+        (WebCore::MIMETypeRegistry::isSupportedImageMIMEType): Use SortedArraySet
+        instead of a HashSet for the core supported images types. Moved the code
+        that checks this against defaultSupportedImageTypes here.
+        (WebCore::MIMETypeRegistry::isSupportedJavaScriptMIMEType): Use SortedArraySet.
+        (WebCore::MIMETypeRegistry::isUnsupportedTextMIMEType): Ditto.
+        (WebCore::MIMETypeRegistry::isPDFMIMEType): Ditto.
+        (WebCore::MIMETypeRegistry::isPostScriptMIMEType): Use equalLettersIgnoringASCIICase.
+        For some reason this was the single case-sensitive function in this whole class!
+        (WebCore::MIMETypeRegistry::isSystemPreviewMIMEType): Use SortedArraySet.
+        (WebCore::MIMETypeRegistry::systemPreviewMIMETypes): Return a FixedVector.
+        (WebCore::normalizedImageMIMEType): Renamed this from its old name,
+        MIMETypeRegistry::normalizedMIMEType, to better reflect that it's only used in
+        one place. Also added comments to clarify that it's CURL-only and suggest it be
+        removed eventually.
+
+        * platform/MIMETypeRegistry.h: Changed supportedImageMIMETypes, pdfMIMETypes,
+        unsupportedTextMIMETypes, and systemPreviewMIMETypes to return FixedVector instead
+        of HashSet. Also removed normalizedMIMEType.
+
+        * svg/SVGTransformValue.h: Removed unneeded include of HashMap.h.
+        * testing/TypeConversions.h: Ditto.
+
 2021-04-29  Sam Weinig  <[email protected]>
 
         Add support for CanvasRenderingContext2DSettings

Modified: trunk/Source/WebCore/platform/MIMETypeRegistry.cpp (276779 => 276780)


--- trunk/Source/WebCore/platform/MIMETypeRegistry.cpp	2021-04-29 16:26:38 UTC (rev 276779)
+++ trunk/Source/WebCore/platform/MIMETypeRegistry.cpp	2021-04-29 16:39:55 UTC (rev 276780)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2019 Apple Inc. All rights reserved.
+ * Copyright (C) 2006-2021 Apple Inc. All rights reserved.
  * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
  *
  * Redistribution and use in source and binary forms, with or without
@@ -29,10 +29,13 @@
 
 #include "MediaPlayer.h"
 #include "ThreadGlobalData.h"
+#include <wtf/FixedVector.h>
 #include <wtf/HashMap.h>
 #include <wtf/MainThread.h>
 #include <wtf/NeverDestroyed.h>
+#include <wtf/SortedArrayMap.h>
 #include <wtf/StdLibExtras.h>
+#include <wtf/Vector.h>
 
 #if USE(CG)
 #include "ImageSourceCG.h"
@@ -64,110 +67,101 @@
 
 namespace WebCore {
 
-const HashSet<String, ASCIICaseInsensitiveHash>& MIMETypeRegistry::supportedImageMIMETypes()
-{
-    static NeverDestroyed<HashSet<String, ASCIICaseInsensitiveHash>> supportedImageMIMETypes = std::initializer_list<String> {
-#if USE(CG)
-        // This represents the subset of allowed image UTIs for which CoreServices has a corresponding MIME type.
-        "image/tiff"_s,
-        "image/gif"_s,
-        "image/jpeg"_s,
-        "image/vnd.microsoft.icon"_s,
-        "image/jp2"_s,
-        "image/apng"_s,
-        "image/png"_s,
-        "image/bmp"_s,
+static String normalizedImageMIMEType(const String&);
 
-        "image/x-icon"_s, // Favicons don't have a MIME type in the registry either.
-        "image/pjpeg"_s, //  We only get one MIME type per UTI, hence our need to add these manually
-#if HAVE(WEBP)
-        "image/webp"_s,
-#endif
+// On iOS, we include malformed image MIME types for compatibility with Mail.
+// These were removed for <rdar://problem/6564538> Re-enable UTI code in WebCore now that
+// MobileCoreServices exists. But Mail relies on at least image/tif reported as being
+// supported (should be image/tiff). This can be removed when Mail addresses:
+// <rdar://problem/7879510> Mail should use standard image mimetypes
+// and we fix sniffing so that it corrects items such as image/jpg -> image/jpeg.
+constexpr ComparableCaseFoldingASCIILiteral supportedImageMIMETypeArray[] = {
 #if PLATFORM(IOS_FAMILY)
-        // Add malformed image mimetype for compatibility with Mail and to handle malformed mimetypes from the net
-        // These were removed for <rdar://problem/6564538> Re-enable UTI code in WebCore now that MobileCoreServices exists
-        // But Mail relies on at least image/tif reported as being supported (should be image/tiff).
-        // This can be removed when Mail addresses:
-        // <rdar://problem/7879510> Mail should use standard image mimetypes
-        // and we fix sniffing so that it corrects items such as image/jpg -> image/jpeg.
-
-        // JPEG (image/jpeg)
-        "image/jpg"_s,
-        "image/jp_"_s,
-        "image/jpe_"_s,
-        "application/jpg"_s,
-        "application/x-jpg"_s,
-        "image/pipeg"_s,
-        "image/vnd.switfview-jpeg"_s,
-        "image/x-xbitmap"_s,
-
-        // GIF (image/gif)
-        "image/gi_"_s,
-
-        // PNG (image/png)
-        "application/png"_s,
-        "application/x-png"_s,
-
-        // TIFF (image/tiff)
-        "image/x-tif"_s,
-        "image/tif"_s,
-        "image/x-tiff"_s,
-        "application/tif"_s,
-        "application/x-tif"_s,
-        "application/tiff"_s,
-        "application/x-tiff"_s,
-
-        // BMP (image/bmp, image/x-bitmap)
-        "image/x-bmp"_s,
-        "image/x-win-bitmap"_s,
-        "image/x-windows-bmp"_s,
-        "image/ms-bmp"_s,
-        "image/x-ms-bmp"_s,
-        "application/bmp"_s,
-        "application/x-bmp"_s,
-        "application/x-win-bitmap"_s,
+    "application/bmp",
+    "application/jpg",
+    "application/png",
+    "application/tif",
+    "application/tiff",
+    "application/x-bmp",
+    "application/x-jpg",
+    "application/x-png",
+    "application/x-tif",
+    "application/x-tiff",
+    "application/x-win-bitmap",
 #endif
-#else
-        // assume that all implementations at least support the following standard
-        // image types:
-        "image/jpeg"_s,
-        "image/png"_s,
-        "image/gif"_s,
-        "image/bmp"_s,
-        "image/vnd.microsoft.icon"_s, // ico
-        "image/x-icon"_s, // ico
-        "image/x-xbitmap"_s, // xbm
-#if ENABLE(APNG)
-        "image/apng"_s,
+#if USE(CG) || ENABLE(APNG)
+    "image/apng",
 #endif
 #if USE(AVIF)
-        "image/avif"_s,
+    "image/avif",
 #endif
-#if USE(OPENJPEG)
-        "image/jp2"_s,
-        "image/jpeg2000"_s,
+    "image/bmp",
+#if PLATFORM(IOS_FAMILY)
+    "image/gi_",
 #endif
-#if USE(WEBP)
-        "image/webp"_s,
+    "image/gif",
+#if USE(CG) || USE(OPENJPEG)
+    "image/jp2",
 #endif
+#if PLATFORM(IOS_FAMILY)
+    "image/jp_",
+    "image/jpe_",
 #endif
-    };
-
+    "image/jpeg",
+#if !USE(CG) && USE(OPENJPEG)
+    "image/jpeg2000",
+#endif
+#if PLATFORM(IOS_FAMILY)
+    "image/ms-bmp",
+    "image/pipeg",
+#endif
 #if USE(CG)
-#ifndef NDEBUG
-    // Esnure supportedImageMIMETypes() is in sync with defaultSupportedImageTypes().
-    static std::once_flag onceFlag;
-    std::call_once(onceFlag, [] {
-        for (auto& imageType : defaultSupportedImageTypes()) {
-            auto mimeType = MIMETypeForImageType(imageType);
-            ASSERT_IMPLIES(!mimeType.isEmpty(), supportedImageMIMETypes.get().contains(mimeType));
-        }
-    });
+    "image/pjpeg",
 #endif
+    "image/png",
+#if PLATFORM(IOS_FAMILY)
+    "image/tif",
 #endif
-    return supportedImageMIMETypes;
+#if USE(CG)
+    "image/tiff",
+#endif
+    "image/vnd.microsoft.icon",
+#if PLATFORM(IOS_FAMILY)
+    "image/vnd.switfview-jpeg",
+#endif
+#if (USE(CG) && HAVE(WEBP)) || (!USE(CG) && USE(WEBP))
+    "image/webp",
+#endif
+#if PLATFORM(IOS_FAMILY)
+    "image/x-bmp",
+#endif
+    "image/x-icon",
+#if PLATFORM(IOS_FAMILY)
+    "image/x-ms-bmp",
+    "image/x-tif",
+    "image/x-tiff",
+    "image/x-win-bitmap",
+    "image/x-windows-bmp",
+#endif
+#if PLATFORM(IOS_FAMILY) || !USE(CG)
+    "image/x-xbitmap",
+#endif
+};
+
+template<ASCIISubset subset, unsigned size> static FixedVector<const char*> makeFixedVector(const ComparableASCIISubsetLiteral<subset> (&array)[size])
+{
+    FixedVector<const char*> result(std::size(array));
+    std::transform(std::begin(array), std::end(array), result.begin(), [] (auto literal) {
+        return literal.literal;
+    });
+    return result;
 }
 
+FixedVector<const char*> MIMETypeRegistry::supportedImageMIMETypes()
+{
+    return makeFixedVector(supportedImageMIMETypeArray);
+}
+
 HashSet<String, ASCIICaseInsensitiveHash>& MIMETypeRegistry::additionalSupportedImageMIMETypes()
 {
     static NeverDestroyed<HashSet<String, ASCIICaseInsensitiveHash>> additionalSupportedImageMIMETypes;
@@ -174,29 +168,25 @@
     return additionalSupportedImageMIMETypes;
 }
 
-static const HashSet<String, ASCIICaseInsensitiveHash>& supportedJavaScriptMIMETypes()
-{
-    static NeverDestroyed<HashSet<String, ASCIICaseInsensitiveHash>> supportedJavaScriptMIMETypes = std::initializer_list<String> {
-        // https://html.spec.whatwg.org/multipage/scripting.html#_javascript_-mime-type
-        "text/_javascript_"_s,
-        "text/ecmascript"_s,
-        "application/_javascript_"_s,
-        "application/ecmascript"_s,
-        "application/x-_javascript_"_s,
-        "application/x-ecmascript"_s,
-        "text/_javascript_1.0"_s,
-        "text/_javascript_1.1"_s,
-        "text/_javascript_1.2"_s,
-        "text/_javascript_1.3"_s,
-        "text/_javascript_1.4"_s,
-        "text/_javascript_1.5"_s,
-        "text/jscript"_s,
-        "text/livescript"_s,
-        "text/x-_javascript_"_s,
-        "text/x-ecmascript"_s,
-    };
-    return supportedJavaScriptMIMETypes;
-}
+// https://html.spec.whatwg.org/multipage/scripting.html#_javascript_-mime-type
+constexpr ComparableLettersLiteral supportedJavaScriptMIMETypeArray[] = {
+    "application/ecmascript",
+    "application/_javascript_",
+    "application/x-ecmascript",
+    "application/x-_javascript_",
+    "text/ecmascript",
+    "text/_javascript_",
+    "text/_javascript_1.0",
+    "text/_javascript_1.1",
+    "text/_javascript_1.2",
+    "text/_javascript_1.3",
+    "text/_javascript_1.4",
+    "text/_javascript_1.5",
+    "text/jscript",
+    "text/livescript",
+    "text/x-ecmascript",
+    "text/x-_javascript_",
+};
 
 HashSet<String, ASCIICaseInsensitiveHash>& MIMETypeRegistry::supportedNonImageMIMETypes()
 {
@@ -223,7 +213,8 @@
         // Note: Adding a new type here will probably render it as HTML.
         // This can result in cross-site scripting vulnerabilities.
         };
-        supportedNonImageMIMETypes.add(supportedJavaScriptMIMETypes().begin(), supportedJavaScriptMIMETypes().end());
+        for (auto& type : supportedJavaScriptMIMETypeArray)
+            supportedNonImageMIMETypes.add(type.literal);
 #if ENABLE(WEB_ARCHIVE) || ENABLE(MHTML)
         ArchiveFactory::registerKnownArchiveMIMETypes(supportedNonImageMIMETypes);
 #endif
@@ -244,131 +235,129 @@
     return supportedMediaMIMETypes;
 }
 
-const HashSet<String, ASCIICaseInsensitiveHash>& MIMETypeRegistry::pdfMIMETypes()
+constexpr ComparableLettersLiteral pdfMIMETypeArray[] = {
+    "application/pdf",
+    "text/pdf",
+};
+
+FixedVector<const char*> MIMETypeRegistry::pdfMIMETypes()
 {
-    static NeverDestroyed<HashSet<String, ASCIICaseInsensitiveHash>> pdfMIMETypes = std::initializer_list<String> {
-        "application/pdf"_s,
-        "text/pdf"_s,
-    };
-    return pdfMIMETypes;
+    return makeFixedVector(pdfMIMETypeArray);
 }
 
-const HashSet<String, ASCIICaseInsensitiveHash>& MIMETypeRegistry::unsupportedTextMIMETypes()
-{
-    static NeverDestroyed<HashSet<String, ASCIICaseInsensitiveHash>> unsupportedTextMIMETypes = std::initializer_list<String> {
-        "text/calendar"_s,
-        "text/x-calendar"_s,
-        "text/x-vcalendar"_s,
-        "text/vcalendar"_s,
-        "text/vcard"_s,
-        "text/x-vcard"_s,
-        "text/directory"_s,
-        "text/ldif"_s,
-        "text/qif"_s,
-        "text/x-qif"_s,
-        "text/x-csv"_s,
-        "text/x-vcf"_s,
+constexpr ComparableLettersLiteral unsupportedTextMIMETypeArray[] = {
+    "text/calendar",
+    "text/directory",
+    "text/ldif",
+    "text/qif",
 #if !PLATFORM(IOS_FAMILY)
-        "text/rtf"_s,
-#else
-        "text/vnd.sun.j2me.app-descriptor"_s,
+    "text/rtf",
 #endif
-    };
-    return unsupportedTextMIMETypes;
+    "text/vcalendar",
+    "text/vcard",
+#if PLATFORM(IOS_FAMILY)
+    "text/vnd.sun.j2me.app-descriptor",
+#endif
+    "text/x-calendar",
+    "text/x-csv",
+    "text/x-qif",
+    "text/x-vcalendar",
+    "text/x-vcard",
+    "text/x-vcf",
+};
+
+FixedVector<const char*> MIMETypeRegistry::unsupportedTextMIMETypes()
+{
+    return makeFixedVector(unsupportedTextMIMETypeArray);
 }
 
-const std::initializer_list<TypeExtensionPair>& commonMediaTypes()
+static const HashMap<String, Vector<String>, ASCIICaseInsensitiveHash>& commonMimeTypesMap()
 {
-    // A table of common media MIME types and file extensions used when a platform's
-    // specific MIME type lookup doesn't have a match for a media file extension.
-    static std::initializer_list<TypeExtensionPair> commonMediaTypes = {
-        // Ogg
-        { "application/ogg"_s, "ogx"_s },
-        { "audio/ogg"_s, "ogg"_s },
-        { "audio/ogg"_s, "oga"_s },
-        { "video/ogg"_s, "ogv"_s },
+    ASSERT(isMainThread());
+    static NeverDestroyed<HashMap<String, Vector<String>, ASCIICaseInsensitiveHash>> mimeTypesMap = [] {
+        HashMap<String, Vector<String>, ASCIICaseInsensitiveHash> map;
+        // A table of common media MIME types and file extensions used when a platform's
+        // specific MIME type lookup doesn't have a match for a media file extension.
+        static constexpr TypeExtensionPair commonMediaTypes[] = {
+            // Ogg
+            { "application/ogg"_s, "ogx"_s },
+            { "audio/ogg"_s, "ogg"_s },
+            { "audio/ogg"_s, "oga"_s },
+            { "video/ogg"_s, "ogv"_s },
 
-        // Annodex
-        { "application/annodex"_s, "anx"_s },
-        { "audio/annodex"_s, "axa"_s },
-        { "video/annodex"_s, "axv"_s },
-        { "audio/speex"_s, "spx"_s },
+            // Annodex
+            { "application/annodex"_s, "anx"_s },
+            { "audio/annodex"_s, "axa"_s },
+            { "video/annodex"_s, "axv"_s },
+            { "audio/speex"_s, "spx"_s },
 
-        // WebM
-        { "video/webm"_s, "webm"_s },
-        { "audio/webm"_s, "webm"_s },
+            // WebM
+            { "video/webm"_s, "webm"_s },
+            { "audio/webm"_s, "webm"_s },
 
-        // MPEG
-        { "audio/mpeg"_s, "m1a"_s },
-        { "audio/mpeg"_s, "m2a"_s },
-        { "audio/mpeg"_s, "m1s"_s },
-        { "audio/mpeg"_s, "mpa"_s },
-        { "video/mpeg"_s, "mpg"_s },
-        { "video/mpeg"_s, "m15"_s },
-        { "video/mpeg"_s, "m1s"_s },
-        { "video/mpeg"_s, "m1v"_s },
-        { "video/mpeg"_s, "m75"_s },
-        { "video/mpeg"_s, "mpa"_s },
-        { "video/mpeg"_s, "mpeg"_s },
-        { "video/mpeg"_s, "mpm"_s },
-        { "video/mpeg"_s, "mpv"_s },
+            // MPEG
+            { "audio/mpeg"_s, "m1a"_s },
+            { "audio/mpeg"_s, "m2a"_s },
+            { "audio/mpeg"_s, "m1s"_s },
+            { "audio/mpeg"_s, "mpa"_s },
+            { "video/mpeg"_s, "mpg"_s },
+            { "video/mpeg"_s, "m15"_s },
+            { "video/mpeg"_s, "m1s"_s },
+            { "video/mpeg"_s, "m1v"_s },
+            { "video/mpeg"_s, "m75"_s },
+            { "video/mpeg"_s, "mpa"_s },
+            { "video/mpeg"_s, "mpeg"_s },
+            { "video/mpeg"_s, "mpm"_s },
+            { "video/mpeg"_s, "mpv"_s },
 
-        // MPEG playlist
-        { "application/vnd.apple.mpegurl"_s, "m3u8"_s },
-        { "application/mpegurl"_s, "m3u8"_s },
-        { "application/x-mpegurl"_s, "m3u8"_s },
-        { "audio/mpegurl"_s, "m3url"_s },
-        { "audio/x-mpegurl"_s, "m3url"_s },
-        { "audio/mpegurl"_s, "m3u"_s },
-        { "audio/x-mpegurl"_s, "m3u"_s },
+            // MPEG playlist
+            { "application/vnd.apple.mpegurl"_s, "m3u8"_s },
+            { "application/mpegurl"_s, "m3u8"_s },
+            { "application/x-mpegurl"_s, "m3u8"_s },
+            { "audio/mpegurl"_s, "m3url"_s },
+            { "audio/x-mpegurl"_s, "m3url"_s },
+            { "audio/mpegurl"_s, "m3u"_s },
+            { "audio/x-mpegurl"_s, "m3u"_s },
 
-        // MPEG-4
-        { "video/x-m4v"_s, "m4v"_s },
-        { "audio/x-m4a"_s, "m4a"_s },
-        { "audio/x-m4b"_s, "m4b"_s },
-        { "audio/x-m4p"_s, "m4p"_s },
-        { "audio/mp4"_s, "m4a"_s },
+            // MPEG-4
+            { "video/x-m4v"_s, "m4v"_s },
+            { "audio/x-m4a"_s, "m4a"_s },
+            { "audio/x-m4b"_s, "m4b"_s },
+            { "audio/x-m4p"_s, "m4p"_s },
+            { "audio/mp4"_s, "m4a"_s },
 
-        // MP3
-        { "audio/mp3"_s, "mp3"_s },
-        { "audio/x-mp3"_s, "mp3"_s },
-        { "audio/x-mpeg"_s, "mp3"_s },
+            // MP3
+            { "audio/mp3"_s, "mp3"_s },
+            { "audio/x-mp3"_s, "mp3"_s },
+            { "audio/x-mpeg"_s, "mp3"_s },
 
-        // MPEG-2
-        { "video/x-mpeg2"_s, "mp2"_s },
-        { "video/mpeg2"_s, "vob"_s },
-        { "video/mpeg2"_s, "mod"_s },
-        { "video/m2ts"_s, "m2ts"_s },
-        { "video/x-m2ts"_s, "m2t"_s },
-        { "video/x-m2ts"_s, "ts"_s },
+            // MPEG-2
+            { "video/x-mpeg2"_s, "mp2"_s },
+            { "video/mpeg2"_s, "vob"_s },
+            { "video/mpeg2"_s, "mod"_s },
+            { "video/m2ts"_s, "m2ts"_s },
+            { "video/x-m2ts"_s, "m2t"_s },
+            { "video/x-m2ts"_s, "ts"_s },
 
-        // 3GP/3GP2
-        { "audio/3gpp"_s, "3gpp"_s },
-        { "audio/3gpp2"_s, "3g2"_s },
-        { "application/x-mpeg"_s, "amc"_s },
+            // 3GP/3GP2
+            { "audio/3gpp"_s, "3gpp"_s },
+            { "audio/3gpp2"_s, "3g2"_s },
+            { "application/x-mpeg"_s, "amc"_s },
 
-        // AAC
-        { "audio/aac"_s, "aac"_s },
-        { "audio/aac"_s, "adts"_s },
-        { "audio/x-aac"_s, "m4r"_s },
+            // AAC
+            { "audio/aac"_s, "aac"_s },
+            { "audio/aac"_s, "adts"_s },
+            { "audio/x-aac"_s, "m4r"_s },
 
-        // CoreAudio File
-        { "audio/x-caf"_s, "caf"_s },
-        { "audio/x-gsm"_s, "gsm"_s },
+            // CoreAudio File
+            { "audio/x-caf"_s, "caf"_s },
+            { "audio/x-gsm"_s, "gsm"_s },
 
-        // ADPCM
-        { "audio/x-wav"_s, "wav"_s },
-        { "audio/vnd.wave"_s, "wav"_s },
-    };
-    return commonMediaTypes;
-}
-
-static const HashMap<String, Vector<String>, ASCIICaseInsensitiveHash>& commonMimeTypesMap()
-{
-    ASSERT(isMainThread());
-    static NeverDestroyed<HashMap<String, Vector<String>, ASCIICaseInsensitiveHash>> mimeTypesMap = [] {
-        HashMap<String, Vector<String>, ASCIICaseInsensitiveHash> map;
-        for (auto& pair : commonMediaTypes()) {
+            // ADPCM
+            { "audio/x-wav"_s, "wav"_s },
+            { "audio/vnd.wave"_s, "wav"_s },
+        };
+        for (auto& pair : commonMediaTypes) {
             ASCIILiteral type = pair.type;
             ASCIILiteral extension = pair.extension;
             map.ensure(extension, [type, extension] {
@@ -418,8 +407,20 @@
 {
     if (mimeType.isEmpty())
         return false;
-    String normalizedMIMEType = MIMETypeRegistry::normalizedMIMEType(mimeType);
-    return supportedImageMIMETypes().contains(normalizedMIMEType) || additionalSupportedImageMIMETypes().contains(normalizedMIMEType);
+    static constexpr SortedArraySet supportedImageMIMETypeSet { supportedImageMIMETypeArray };
+#if USE(CG) && ASSERT_ENABLED
+    // Esnure supportedImageMIMETypeArray matches defaultSupportedImageTypes().
+    static std::once_flag onceFlag;
+    std::call_once(onceFlag, [] {
+        for (auto& imageType : defaultSupportedImageTypes()) {
+            auto mimeType = MIMETypeForImageType(imageType);
+            ASSERT_IMPLIES(!mimeType.isEmpty(), supportedImageMIMETypeSet.contains(mimeType));
+        }
+    });
+#endif
+    if (supportedImageMIMETypeSet.contains(mimeType))
+        return true;
+    return additionalSupportedImageMIMETypes().contains(normalizedImageMIMEType(mimeType));
 }
 
 bool MIMETypeRegistry::isSupportedImageVideoOrSVGMIMEType(const String& mimeType)
@@ -486,18 +487,8 @@
 
 bool MIMETypeRegistry::isSupportedJavaScriptMIMEType(const String& mimeType)
 {
-    if (mimeType.isEmpty())
-        return false;
-
-    if (!isMainThread()) {
-        bool isSupported = false;
-        callOnMainThreadAndWait([&isSupported, mimeType = mimeType.isolatedCopy()] {
-            isSupported = isSupportedJavaScriptMIMEType(mimeType);
-        });
-        return isSupported;
-    }
-
-    return supportedJavaScriptMIMETypes().contains(mimeType);
+    static constexpr SortedArraySet supportedJavaScriptMIMETypes { supportedJavaScriptMIMETypeArray };
+    return supportedJavaScriptMIMETypes.contains(mimeType);
 }
 
 bool MIMETypeRegistry::isSupportedStyleSheetMIMEType(const String& mimeType)
@@ -577,9 +568,8 @@
 
 bool MIMETypeRegistry::isUnsupportedTextMIMEType(const String& mimeType)
 {
-    if (mimeType.isEmpty())
-        return false;
-    return unsupportedTextMIMETypes().contains(mimeType);
+    static constexpr SortedArraySet unsupportedTextMIMETypes { unsupportedTextMIMETypeArray };
+    return unsupportedTextMIMETypes.contains(mimeType);
 }
 
 bool MIMETypeRegistry::isTextMIMEType(const String& mimeType)
@@ -641,14 +631,13 @@
 
 bool MIMETypeRegistry::isPDFMIMEType(const String& mimeType)
 {
-    if (mimeType.isEmpty())
-        return false;
-    return pdfMIMETypes().contains(mimeType);
+    static constexpr SortedArraySet set { pdfMIMETypeArray };
+    return set.contains(mimeType);
 }
 
 bool MIMETypeRegistry::isPostScriptMIMEType(const String& mimeType)
 {
-    return mimeType == "application/postscript";
+    return equalLettersIgnoringASCIICase(mimeType, "application/postscript");
 }
 
 bool MIMETypeRegistry::isPDFOrPostScriptMIMEType(const String& mimeType)
@@ -681,104 +670,85 @@
     return defaultMIMEType;
 }
 
-const HashSet<String, ASCIICaseInsensitiveHash>& MIMETypeRegistry::systemPreviewMIMETypes()
+constexpr ComparableLettersLiteral systemPreviewMIMETypeArray[] = {
+    "model/usd", // Unofficial, but supported because we documented this.
+    "model/vnd.pixar.usd", // Unofficial, but supported because we documented this.
+    "model/vnd.reality",
+    "model/vnd.usdz+zip", // The official type: https://www.iana.org/assignments/media-types/model/vnd.usdz+zip
+};
+
+FixedVector<const char*> MIMETypeRegistry::systemPreviewMIMETypes()
 {
-    static NeverDestroyed<HashSet<String, ASCIICaseInsensitiveHash>> systemPreviewMIMETypes = std::initializer_list<String> {
-        // The official type: https://www.iana.org/assignments/media-types/model/vnd.usdz+zip
-        "model/vnd.usdz+zip"_s,
-        // Unofficial, but supported because we documented them.
-        "model/usd"_s,
-        "model/vnd.pixar.usd"_s,
-        // Reality files.
-        "model/vnd.reality"_s,
-    };
-    return systemPreviewMIMETypes;
+    return makeFixedVector(systemPreviewMIMETypeArray);
 }
 
 bool MIMETypeRegistry::isSystemPreviewMIMEType(const String& mimeType)
 {
-    if (mimeType.isEmpty())
-        return false;
-    return systemPreviewMIMETypes().contains(mimeType);
+    static constexpr SortedArraySet systemPreviewMIMETypeSet { systemPreviewMIMETypeArray };
+    return systemPreviewMIMETypeSet.contains(mimeType);
 }
 
-#if !USE(CURL)
-
-// FIXME: Not sure why it makes sense to have a cross-platform function when only CURL has the concept
-// of a "normalized" MIME type.
-String MIMETypeRegistry::normalizedMIMEType(const String& mimeType)
+// FIXME: Not great that CURL needs this concept; other platforms do not.
+static String normalizedImageMIMEType(const String& mimeType)
 {
+#if USE(CURL)
     return mimeType;
-}
-
 #else
-
-String MIMETypeRegistry::normalizedMIMEType(const String& mimeType)
-{
-    static const auto mimeTypeAssociationMap = makeNeverDestroyed([] {
-        static const std::pair<ASCIILiteral, ASCIILiteral> mimeTypeAssociations[] = {
-            { "image/x-ms-bmp"_s, "image/bmp"_s },
-            { "image/x-windows-bmp"_s, "image/bmp"_s },
-            { "image/x-bmp"_s, "image/bmp"_s },
-            { "image/x-bitmap"_s, "image/bmp"_s },
-            { "image/x-ms-bitmap"_s, "image/bmp"_s },
-            { "image/jpg"_s, "image/jpeg"_s },
-            { "image/pjpeg"_s, "image/jpeg"_s },
-            { "image/x-png"_s, "image/png"_s },
-            { "image/vnd.rim.png"_s, "image/png"_s },
-            { "image/ico"_s, "image/vnd.microsoft.icon"_s },
-            { "image/icon"_s, "image/vnd.microsoft.icon"_s },
-            { "text/ico"_s, "image/vnd.microsoft.icon"_s },
-            { "application/ico"_s, "image/vnd.microsoft.icon"_s },
-            { "image/x-icon"_s, "image/vnd.microsoft.icon"_s },
-            { "audio/vnd.qcelp"_s, "audio/qcelp"_s },
-            { "audio/qcp"_s, "audio/qcelp"_s },
-            { "audio/vnd.qcp"_s, "audio/qcelp"_s },
-            { "audio/wav"_s, "audio/x-wav"_s },
-            { "audio/vnd.wave"_s, "audio/x-wav"_s },
-            { "audio/mid"_s, "audio/midi"_s },
-            { "audio/sp-midi"_s, "audio/midi"_s },
-            { "audio/x-mid"_s, "audio/midi"_s },
-            { "audio/x-midi"_s, "audio/midi"_s },
-            { "audio/x-mpeg"_s, "audio/mpeg"_s },
-            { "audio/mp3"_s, "audio/mpeg"_s },
-            { "audio/x-mp3"_s, "audio/mpeg"_s },
-            { "audio/mpeg3"_s, "audio/mpeg"_s },
-            { "audio/x-mpeg3"_s, "audio/mpeg"_s },
-            { "audio/mpg3"_s, "audio/mpeg"_s },
-            { "audio/mpg"_s, "audio/mpeg"_s },
-            { "audio/x-mpg"_s, "audio/mpeg"_s },
-            { "audio/m4a"_s, "audio/mp4"_s },
-            { "audio/x-m4a"_s, "audio/mp4"_s },
-            { "audio/x-mp4"_s, "audio/mp4"_s },
-            { "audio/x-aac"_s, "audio/aac"_s },
-            { "audio/x-amr"_s, "audio/amr"_s },
-            { "audio/mpegurl"_s, "audio/x-mpegurl"_s },
-            { "audio/flac"_s, "audio/x-flac"_s },
-            { "video/3gp"_s, "video/3gpp"_s },
-            { "video/avi"_s, "video/x-msvideo"_s },
-            { "video/x-m4v"_s, "video/mp4"_s },
-            { "video/x-quicktime"_s, "video/quicktime"_s },
-            { "application/java"_s, "application/java-archive"_s },
-            { "application/x-java-archive"_s, "application/java-archive"_s },
-            { "application/x-zip-compressed"_s, "application/zip"_s },
-            { "text/cache-manifest"_s, "text/plain"_s },
-        };
-
-        HashMap<String, String, ASCIICaseInsensitiveHash> map;
-        for (auto& pair : mimeTypeAssociations)
-            map.add(pair.first, pair.second);
-        return map;
-    }());
-
-    auto it = mimeTypeAssociationMap.get().find(mimeType);
-    if (it != mimeTypeAssociationMap.get().end())
-        return it->value;
-    return mimeType;
+    // FIXME: Since this is only used in isSupportedImageMIMEType, we should consider removing the non-image types below.
+    static constexpr std::pair<ComparableLettersLiteral, ASCIILiteral> mimeTypeAssociationArray[] = {
+        { "application/ico", "image/vnd.microsoft.icon"_s },
+        { "application/java", "application/java-archive"_s },
+        { "application/x-java-archive", "application/java-archive"_s },
+        { "application/x-zip-compressed", "application/zip"_s },
+        { "audio/flac", "audio/x-flac"_s },
+        { "audio/m4a", "audio/mp4"_s },
+        { "audio/mid", "audio/midi"_s },
+        { "audio/mp3", "audio/mpeg"_s },
+        { "audio/mpeg3", "audio/mpeg"_s },
+        { "audio/mpegurl", "audio/x-mpegurl"_s },
+        { "audio/mpg", "audio/mpeg"_s },
+        { "audio/mpg3", "audio/mpeg"_s },
+        { "audio/qcp", "audio/qcelp"_s },
+        { "audio/sp-midi", "audio/midi"_s },
+        { "audio/vnd.qcelp", "audio/qcelp"_s },
+        { "audio/vnd.qcp", "audio/qcelp"_s },
+        { "audio/vnd.wave", "audio/x-wav"_s },
+        { "audio/wav", "audio/x-wav"_s },
+        { "audio/x-aac", "audio/aac"_s },
+        { "audio/x-amr", "audio/amr"_s },
+        { "audio/x-m4a", "audio/mp4"_s },
+        { "audio/x-mid", "audio/midi"_s },
+        { "audio/x-midi", "audio/midi"_s },
+        { "audio/x-mp3", "audio/mpeg"_s },
+        { "audio/x-mp4", "audio/mp4"_s },
+        { "audio/x-mpeg", "audio/mpeg"_s },
+        { "audio/x-mpeg3", "audio/mpeg"_s },
+        { "audio/x-mpg", "audio/mpeg"_s },
+        { "image/ico", "image/vnd.microsoft.icon"_s },
+        { "image/icon", "image/vnd.microsoft.icon"_s },
+        { "image/jpg", "image/jpeg"_s },
+        { "image/pjpeg", "image/jpeg"_s },
+        { "image/vnd.rim.png", "image/png"_s },
+        { "image/x-bitmap", "image/bmp"_s },
+        { "image/x-bmp", "image/bmp"_s },
+        { "image/x-icon", "image/vnd.microsoft.icon"_s },
+        { "image/x-ms-bitmap", "image/bmp"_s },
+        { "image/x-ms-bmp", "image/bmp"_s },
+        { "image/x-png", "image/png"_s },
+        { "image/x-windows-bmp", "image/bmp"_s },
+        { "text/cache-manifest", "text/plain"_s },
+        { "text/ico", "image/vnd.microsoft.icon"_s },
+        { "video/3gp", "video/3gpp"_s },
+        { "video/avi", "video/x-msvideo"_s },
+        { "video/x-m4v", "video/mp4"_s },
+        { "video/x-quicktime", "video/quicktime"_s },
+    };
+    static constexpr SortedArrayMap associationMap { mimeTypeAssociationArray };
+    auto normalizedType = associationMap.tryGet(mimeType);
+    return normalizedType ? *normalizedType : mimeType;
+#endif
 }
 
-#endif
-
 String MIMETypeRegistry::appendFileExtensionIfNecessary(const String& filename, const String& mimeType)
 {
     if (filename.isEmpty() || filename.contains('.') || equalIgnoringASCIICase(mimeType, defaultMIMEType()))

Modified: trunk/Source/WebCore/platform/MIMETypeRegistry.h (276779 => 276780)


--- trunk/Source/WebCore/platform/MIMETypeRegistry.h	2021-04-29 16:26:38 UTC (rev 276779)
+++ trunk/Source/WebCore/platform/MIMETypeRegistry.h	2021-04-29 16:39:55 UTC (rev 276780)
@@ -26,7 +26,6 @@
 #pragma once
 
 #include <wtf/HashSet.h>
-#include <wtf/Vector.h>
 #include <wtf/text/StringHash.h>
 
 namespace WebCore {
@@ -128,18 +127,14 @@
     // makes this test is after many other tests are done on the MIME type.
     WEBCORE_EXPORT static bool isTextMIMEType(const String& mimeType);
 
-    // FIXME: Would be nice to find a way to avoid exposing these sets, even worse exposing non-const references.
-    WEBCORE_EXPORT static const HashSet<String, ASCIICaseInsensitiveHash>& supportedImageMIMETypes();
+    WEBCORE_EXPORT static FixedVector<const char*> supportedImageMIMETypes();
     static HashSet<String, ASCIICaseInsensitiveHash>& additionalSupportedImageMIMETypes();
     WEBCORE_EXPORT static HashSet<String, ASCIICaseInsensitiveHash>& supportedNonImageMIMETypes();
     WEBCORE_EXPORT static const HashSet<String, ASCIICaseInsensitiveHash>& supportedMediaMIMETypes();
-    WEBCORE_EXPORT static const HashSet<String, ASCIICaseInsensitiveHash>& pdfMIMETypes();
-    WEBCORE_EXPORT static const HashSet<String, ASCIICaseInsensitiveHash>& unsupportedTextMIMETypes();
-    WEBCORE_EXPORT static const HashSet<String, ASCIICaseInsensitiveHash>& systemPreviewMIMETypes();
+    WEBCORE_EXPORT static FixedVector<const char*> pdfMIMETypes();
+    WEBCORE_EXPORT static FixedVector<const char*> unsupportedTextMIMETypes();
+    WEBCORE_EXPORT static FixedVector<const char*> systemPreviewMIMETypes();
 
-    // FIXME: Unclear what the concept of a normalized MIME type is; currently it's a platform-specific notion.
-    static String normalizedMIMEType(const String&);
-
     WEBCORE_EXPORT static String appendFileExtensionIfNecessary(const String& filename, const String& mimeType);
 
     WEBCORE_EXPORT static String preferredImageMIMETypeForEncoding(const Vector<String>& mimeTypes, const Vector<String>& extensions);

Modified: trunk/Source/WebCore/svg/SVGTransformValue.h (276779 => 276780)


--- trunk/Source/WebCore/svg/SVGTransformValue.h	2021-04-29 16:26:38 UTC (rev 276779)
+++ trunk/Source/WebCore/svg/SVGTransformValue.h	2021-04-29 16:39:55 UTC (rev 276780)
@@ -25,7 +25,6 @@
 #include "FloatPoint.h"
 #include "FloatSize.h"
 #include "SVGMatrix.h"
-#include <wtf/HashMap.h>
 #include <wtf/NeverDestroyed.h>
 #include <wtf/text/StringBuilder.h>
 

Modified: trunk/Source/WebCore/testing/TypeConversions.h (276779 => 276780)


--- trunk/Source/WebCore/testing/TypeConversions.h	2021-04-29 16:26:38 UTC (rev 276779)
+++ trunk/Source/WebCore/testing/TypeConversions.h	2021-04-29 16:39:55 UTC (rev 276780)
@@ -27,7 +27,6 @@
 
 #include "Node.h"
 #include <wtf/FastMalloc.h>
-#include <wtf/HashMap.h>
 #include <wtf/RefCounted.h>
 #include <wtf/Variant.h>
 #include <wtf/Vector.h>

Modified: trunk/Source/WebKit/ChangeLog (276779 => 276780)


--- trunk/Source/WebKit/ChangeLog	2021-04-29 16:26:38 UTC (rev 276779)
+++ trunk/Source/WebKit/ChangeLog	2021-04-29 16:39:55 UTC (rev 276780)
@@ -1,3 +1,17 @@
+2021-04-29  Darin Adler  <[email protected]>
+
+        Extend SortedArrayMap further to work on case-folded strings, use in MIMETypeRegistry
+        https://bugs.webkit.org/show_bug.cgi?id=224968
+
+        Reviewed by Sam Weinig.
+
+        * UIProcess/API/ios/WKWebViewIOS.mm:
+        (-[WKWebView _isDisplayingPDF]): Updated since MIMETypeRegistry::pdfMIMETypes
+        returns a different type.
+        * UIProcess/Cocoa/WKWebViewContentProviderRegistry.mm:
+        (-[WKWebViewContentProviderRegistry initWithConfiguration:]): Updated since
+        MIMETypeRegistry::systemPreviewMIMETypes returns a different type.
+
 2021-04-29  Ben Nham  <[email protected]>
 
         Unreviewed, reverting r276619.

Modified: trunk/Source/WebKit/UIProcess/API/ios/WKWebViewIOS.mm (276779 => 276780)


--- trunk/Source/WebKit/UIProcess/API/ios/WKWebViewIOS.mm	2021-04-29 16:26:38 UTC (rev 276779)
+++ trunk/Source/WebKit/UIProcess/API/ios/WKWebViewIOS.mm	2021-04-29 16:39:55 UTC (rev 276780)
@@ -2700,8 +2700,8 @@
 
 - (BOOL)_isDisplayingPDF
 {
-    for (auto& mimeType : WebCore::MIMETypeRegistry::pdfMIMETypes()) {
-        Class providerClass = [[_configuration _contentProviderRegistry] providerForMIMEType:mimeType];
+    for (auto& type : WebCore::MIMETypeRegistry::pdfMIMETypes()) {
+        Class providerClass = [[_configuration _contentProviderRegistry] providerForMIMEType:@(type)];
         if ([_customContentView isKindOfClass:providerClass])
             return YES;
     }

Modified: trunk/Source/WebKit/UIProcess/Cocoa/WKWebViewContentProviderRegistry.mm (276779 => 276780)


--- trunk/Source/WebKit/UIProcess/Cocoa/WKWebViewContentProviderRegistry.mm	2021-04-29 16:26:38 UTC (rev 276779)
+++ trunk/Source/WebKit/UIProcess/Cocoa/WKWebViewContentProviderRegistry.mm	2021-04-29 16:39:55 UTC (rev 276780)
@@ -34,10 +34,10 @@
 #import "WKWebViewInternal.h"
 #import "WebPageProxy.h"
 #import <WebCore/MIMETypeRegistry.h>
+#import <wtf/FixedVector.h>
 #import <wtf/HashCountedSet.h>
 #import <wtf/HashMap.h>
 #import <wtf/text/StringHash.h>
-#import <wtf/text/WTFString.h>
 
 @implementation WKWebViewContentProviderRegistry {
     HashMap<String, Class <WKWebViewContentProvider>, ASCIICaseInsensitiveHash> _contentProviderForMIMEType;
@@ -50,14 +50,14 @@
         return nil;
 
 #if ENABLE(WKPDFVIEW)
-    for (auto& mimeType : WebCore::MIMETypeRegistry::pdfMIMETypes())
-        [self registerProvider:[WKPDFView class] forMIMEType:mimeType];
+    for (auto& type : WebCore::MIMETypeRegistry::pdfMIMETypes())
+        [self registerProvider:[WKPDFView class] forMIMEType:@(type)];
 #endif
 
 #if USE(SYSTEM_PREVIEW)
     if (configuration._systemPreviewEnabled) {
-        for (auto& mimeType : WebCore::MIMETypeRegistry::systemPreviewMIMETypes())
-            [self registerProvider:[WKSystemPreviewView class] forMIMEType:mimeType];
+        for (auto& type : WebCore::MIMETypeRegistry::systemPreviewMIMETypes())
+            [self registerProvider:[WKSystemPreviewView class] forMIMEType:@(type)];
     }
 #endif
 

Modified: trunk/Source/WebKitLegacy/mac/ChangeLog (276779 => 276780)


--- trunk/Source/WebKitLegacy/mac/ChangeLog	2021-04-29 16:26:38 UTC (rev 276779)
+++ trunk/Source/WebKitLegacy/mac/ChangeLog	2021-04-29 16:39:55 UTC (rev 276780)
@@ -1,3 +1,19 @@
+2021-04-29  Darin Adler  <[email protected]>
+
+        Extend SortedArrayMap further to work on case-folded strings, use in MIMETypeRegistry
+        https://bugs.webkit.org/show_bug.cgi?id=224968
+
+        Reviewed by Sam Weinig.
+
+        * WebView/WebHTMLRepresentation.mm:
+        (createNSArray): Renamed from newArrayWithStrings so this overloads the createNSArray
+        function from VectorCocoa.h so we can use the two interchangably and handle both FixedVector
+        and HashSet with the smae code.
+        (+[WebHTMLRepresentation supportedMediaMIMETypes]): Updated for name change.
+        (+[WebHTMLRepresentation supportedNonImageMIMETypes]): Ditto.
+        (+[WebHTMLRepresentation supportedImageMIMETypes]): Ditto.
+        (+[WebHTMLRepresentation unsupportedTextMIMETypes]): Ditto.
+
 2021-04-28  Alex Christensen  <[email protected]>
 
         Remove support for NPAPI plugins in WebView

Modified: trunk/Source/WebKitLegacy/mac/WebView/WebHTMLRepresentation.mm (276779 => 276780)


--- trunk/Source/WebKitLegacy/mac/WebView/WebHTMLRepresentation.mm	2021-04-29 16:26:38 UTC (rev 276779)
+++ trunk/Source/WebKitLegacy/mac/WebView/WebHTMLRepresentation.mm	2021-04-29 16:39:55 UTC (rev 276780)
@@ -63,6 +63,7 @@
 #import <WebCore/TextResourceDecoder.h>
 #import <WebKitLegacy/DOMHTMLInputElement.h>
 #import <wtf/Assertions.h>
+#import <wtf/FixedVector.h>
 #import <wtf/NeverDestroyed.h>
 #import <wtf/StdLibExtras.h>
 #import <wtf/cocoa/VectorCocoa.h>
@@ -89,7 +90,7 @@
 
 @implementation WebHTMLRepresentation
 
-static RetainPtr<NSArray> newArrayWithStrings(const HashSet<String, ASCIICaseInsensitiveHash>& set)
+static RetainPtr<NSArray> createNSArray(const HashSet<String, ASCIICaseInsensitiveHash>& set)
 {
     auto vector = copyToVectorOf<NSString *>(set);
     return adoptNS([[NSArray alloc] initWithObjects:vector.data() count:vector.size()]);
@@ -104,25 +105,25 @@
 
 + (NSArray *)supportedMediaMIMETypes
 {
-    static NeverDestroyed<RetainPtr<NSArray>> staticSupportedMediaMIMETypes = newArrayWithStrings(MIMETypeRegistry::supportedMediaMIMETypes());
+    static NeverDestroyed<RetainPtr<NSArray>> staticSupportedMediaMIMETypes = createNSArray(MIMETypeRegistry::supportedMediaMIMETypes());
     return staticSupportedMediaMIMETypes.get().get();
 }
 
 + (NSArray *)supportedNonImageMIMETypes
 {
-    static NeverDestroyed<RetainPtr<NSArray>> staticSupportedNonImageMIMETypes = newArrayWithStrings(MIMETypeRegistry::supportedNonImageMIMETypes());
+    static NeverDestroyed<RetainPtr<NSArray>> staticSupportedNonImageMIMETypes = createNSArray(MIMETypeRegistry::supportedNonImageMIMETypes());
     return staticSupportedNonImageMIMETypes.get().get();
 }
 
 + (NSArray *)supportedImageMIMETypes
 {
-    static NeverDestroyed<RetainPtr<NSArray>> staticSupportedImageMIMETypes = newArrayWithStrings(MIMETypeRegistry::supportedImageMIMETypes());
+    static NeverDestroyed<RetainPtr<NSArray>> staticSupportedImageMIMETypes = createNSArray(MIMETypeRegistry::supportedImageMIMETypes());
     return staticSupportedImageMIMETypes.get().get();
 }
 
 + (NSArray *)unsupportedTextMIMETypes
 {
-    static NeverDestroyed<RetainPtr<NSArray>> staticUnsupportedTextMIMETypes = newArrayWithStrings(MIMETypeRegistry::unsupportedTextMIMETypes());
+    static NeverDestroyed<RetainPtr<NSArray>> staticUnsupportedTextMIMETypes = createNSArray(MIMETypeRegistry::unsupportedTextMIMETypes());
     return staticUnsupportedTextMIMETypes.get().get();
 }
 

Modified: trunk/Tools/ChangeLog (276779 => 276780)


--- trunk/Tools/ChangeLog	2021-04-29 16:26:38 UTC (rev 276779)
+++ trunk/Tools/ChangeLog	2021-04-29 16:39:55 UTC (rev 276780)
@@ -1,3 +1,15 @@
+2021-04-29  Darin Adler  <[email protected]>
+
+        Extend SortedArrayMap further to work on case-folded strings, use in MIMETypeRegistry
+        https://bugs.webkit.org/show_bug.cgi?id=224968
+
+        Reviewed by Sam Weinig.
+
+        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj: Added SortedArrayMap.cpp,
+        and removed references to non-existent FullscreenRemoveNodeBeforeEnter.h and
+        FloatQuadTests.h.
+        * TestWebKitAPI/Tests/WTF/SortedArrayMap.cpp: Added.
+
 2021-04-29  Roy Reapor  <[email protected]>
 
         [webkitcorepy] Allow user to specify interpreter used by autoinstall.py to install imported dependencies

Modified: trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj (276779 => 276780)


--- trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj	2021-04-29 16:26:38 UTC (rev 276779)
+++ trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj	2021-04-29 16:39:55 UTC (rev 276780)
@@ -869,6 +869,7 @@
 		93F56DA91E5F919D003EDE84 /* WKWebViewSnapshot.mm in Sources */ = {isa = PBXBuildFile; fileRef = 93F56DA81E5F9181003EDE84 /* WKWebViewSnapshot.mm */; };
 		93F7E86F14DC8E5C00C84A99 /* NewFirstVisuallyNonEmptyLayoutFrames_Bundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93F7E86E14DC8E5B00C84A99 /* NewFirstVisuallyNonEmptyLayoutFrames_Bundle.cpp */; };
 		95095F20262FFFA50000D920 /* SampledPageTopColor.mm in Sources */ = {isa = PBXBuildFile; fileRef = 95095F1F262FFFA50000D920 /* SampledPageTopColor.mm */; };
+		93FCDB34263631560046DD7D /* SortedArrayMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93FCDB33263631560046DD7D /* SortedArrayMap.cpp */; };
 		950E4CC1252E75240071659F /* iOSStylusSupport.mm in Sources */ = {isa = PBXBuildFile; fileRef = 950E4CC0252E75230071659F /* iOSStylusSupport.mm */; };
 		953ABB3525C0D682004C8B73 /* PageExtendedBackgroundColor.mm in Sources */ = {isa = PBXBuildFile; fileRef = 953ABB3425C0D681004C8B73 /* PageExtendedBackgroundColor.mm */; };
 		95A524952581A10D00461FE9 /* WKWebViewThemeColor.mm in Sources */ = {isa = PBXBuildFile; fileRef = 95A524942581A10D00461FE9 /* WKWebViewThemeColor.mm */; };
@@ -1340,7 +1341,6 @@
 			dstPath = TestWebKitAPI.resources;
 			dstSubfolderSpec = 7;
 			files = (
-				498D030A26376B34009CBFAD /* resourceLoadStatisticsMissingUniqueIndex.db in Copy Resources */,
 				55A817FF2181021A0004A39A /* 100x100-red.tga in Copy Resources */,
 				1A9E52C913E65EF4006917F5 /* 18-characters.html in Copy Resources */,
 				55A81800218102210004A39A /* 400x400-green.png in Copy Resources */,
@@ -1652,6 +1652,7 @@
 				F41AB9A91EF4696B0083FA08 /* prevent-start.html in Copy Resources */,
 				F6FDDDD614241C6F004F1729 /* push-state.html in Copy Resources */,
 				A12DDC001E8373E700CF6CAE /* rendered-image-excluding-overflow.html in Copy Resources */,
+				498D030A26376B34009CBFAD /* resourceLoadStatisticsMissingUniqueIndex.db in Copy Resources */,
 				F46849C01EEF5EF300B937FE /* rich-and-plain-text.html in Copy Resources */,
 				1CE6FAC32320267C00E48F6E /* rich-color-filtered.html in Copy Resources */,
 				2E92B8F7216490D4005B64F0 /* rich-text-attributes.html in Copy Resources */,
@@ -2564,6 +2565,7 @@
 		93F7E86B14DC8E4D00C84A99 /* NewFirstVisuallyNonEmptyLayoutFrames.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NewFirstVisuallyNonEmptyLayoutFrames.cpp; sourceTree = "<group>"; };
 		93F7E86E14DC8E5B00C84A99 /* NewFirstVisuallyNonEmptyLayoutFrames_Bundle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NewFirstVisuallyNonEmptyLayoutFrames_Bundle.cpp; sourceTree = "<group>"; };
 		95095F1F262FFFA50000D920 /* SampledPageTopColor.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = SampledPageTopColor.mm; sourceTree = "<group>"; };
+		93FCDB33263631560046DD7D /* SortedArrayMap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SortedArrayMap.cpp; sourceTree = "<group>"; };
 		950E4CC0252E75230071659F /* iOSStylusSupport.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = iOSStylusSupport.mm; sourceTree = "<group>"; };
 		953ABB3425C0D681004C8B73 /* PageExtendedBackgroundColor.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = PageExtendedBackgroundColor.mm; sourceTree = "<group>"; };
 		95A524942581A10D00461FE9 /* WKWebViewThemeColor.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WKWebViewThemeColor.mm; sourceTree = "<group>"; };
@@ -2872,7 +2874,6 @@
 		CDCFA7A91E45122F00C2433D /* SampleMap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SampleMap.cpp; sourceTree = "<group>"; };
 		CDCFFEC022E268D500DF4223 /* NoPauseWhenSwitchingTabs.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = NoPauseWhenSwitchingTabs.mm; sourceTree = "<group>"; };
 		CDD68F0C22C18317000CF0AE /* WKWebViewCloseAllMediaPresentations.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WKWebViewCloseAllMediaPresentations.mm; sourceTree = "<group>"; };
-		CDDC7C6725FFF6D000224278 /* FullscreenRemoveNodeBeforeEnter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FullscreenRemoveNodeBeforeEnter.h; sourceTree = "<group>"; };
 		CDDC7C6825FFF6D000224278 /* FullscreenRemoveNodeBeforeEnter.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = FullscreenRemoveNodeBeforeEnter.mm; sourceTree = "<group>"; };
 		CDE195B21CFE0ADE0053D256 /* FullscreenTopContentInset.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = FullscreenTopContentInset.html; sourceTree = "<group>"; };
 		CDE195B31CFE0ADE0053D256 /* TopContentInset.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = TopContentInset.mm; sourceTree = "<group>"; };
@@ -3050,7 +3051,6 @@
 		F4A32ECA1F0642F40047C544 /* contenteditable-in-iframe.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = "contenteditable-in-iframe.html"; sourceTree = "<group>"; };
 		F4A9202E1FEE34C800F59590 /* apple-data-url.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "apple-data-url.html"; sourceTree = "<group>"; };
 		F4AB57891F65164B00DB0DA1 /* custom-draggable-div.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "custom-draggable-div.html"; sourceTree = "<group>"; };
-		F4AD183625ED791500B1A19F /* FloatQuadTests.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FloatQuadTests.h; sourceTree = "<group>"; };
 		F4AD183725ED791500B1A19F /* FloatQuadTests.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = FloatQuadTests.cpp; sourceTree = "<group>"; };
 		F4B0167F25AE02D600E445C4 /* DisableSpellcheckPlugIn.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = DisableSpellcheckPlugIn.mm; sourceTree = "<group>"; };
 		F4B0168225AE060F00E445C4 /* DisableSpellcheck.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = DisableSpellcheck.mm; sourceTree = "<group>"; };
@@ -3416,7 +3416,6 @@
 				CDCF78A7244A2EDB00480311 /* FullscreenAlert.mm */,
 				CD78E11A1DB7EA360014A2DE /* FullscreenDelegate.mm */,
 				3F1B52681D3D7129008D60C4 /* FullscreenLayoutConstraints.mm */,
-				CDDC7C6725FFF6D000224278 /* FullscreenRemoveNodeBeforeEnter.h */,
 				CDDC7C6825FFF6D000224278 /* FullscreenRemoveNodeBeforeEnter.mm */,
 				631EFFF51E7B5E8D00D2EBB8 /* Geolocation.mm */,
 				07E1F6A01FFC3A080096C7EC /* GetDisplayMedia.mm */,
@@ -3676,7 +3675,6 @@
 				7A32D7491F02151500162C44 /* FileMonitor.cpp */,
 				7A909A701D877475007E10F8 /* FloatPointTests.cpp */,
 				F4AD183725ED791500B1A19F /* FloatQuadTests.cpp */,
-				F4AD183625ED791500B1A19F /* FloatQuadTests.h */,
 				7A909A711D877475007E10F8 /* FloatRectTests.cpp */,
 				7A909A721D877475007E10F8 /* FloatSizeTests.cpp */,
 				8E4A85361E1D1AA100F53B0F /* GridPosition.cpp */,
@@ -3881,7 +3879,6 @@
 		A16F66B81C40E9E100BD4D24 /* Resources */ = {
 			isa = PBXGroup;
 			children = (
-				498D030926376B2C009CBFAD /* resourceLoadStatisticsMissingUniqueIndex.db */,
 				55A817FE218101DF0004A39A /* 100x100-red.tga */,
 				55A817FD218101DF0004A39A /* 400x400-green.png */,
 				F4CFCDD9249FC9D900527482 /* Ahem.ttf */,
@@ -4071,6 +4068,7 @@
 				F41AB9941EF4692C0083FA08 /* prevent-operation.html */,
 				F41AB99A1EF4692C0083FA08 /* prevent-start.html */,
 				A12DDBFF1E8373C100CF6CAE /* rendered-image-excluding-overflow.html */,
+				498D030926376B2C009CBFAD /* resourceLoadStatisticsMissingUniqueIndex.db */,
 				F46849BF1EEF5EDC00B937FE /* rich-and-plain-text.html */,
 				1CE6FAC12320264F00E48F6E /* rich-color-filtered.html */,
 				2E92B8F6216490C3005B64F0 /* rich-text-attributes.html */,
@@ -4450,6 +4448,7 @@
 				0BCD85691485C98B00EA2003 /* SetForScope.cpp */,
 				CD5393C91757BAC400C07123 /* SHA1.cpp */,
 				E3953F951F2CF32100A76A2E /* Signals.cpp */,
+				93FCDB33263631560046DD7D /* SortedArrayMap.cpp */,
 				FE2BCDC62470FC7000DEC33B /* StdLibExtras.cpp */,
 				81B50192140F232300D9EB58 /* StringBuilder.cpp */,
 				7CD4C26C1E2C0E6E00929470 /* StringConcatenate.cpp */,
@@ -5203,6 +5202,7 @@
 				7C83DF3D1D0A590C00FEBCF3 /* SetForScope.cpp in Sources */,
 				7C83DF2A1D0A590C00FEBCF3 /* SHA1.cpp in Sources */,
 				E373D7911F2CF35200C6FAAF /* Signals.cpp in Sources */,
+				93FCDB34263631560046DD7D /* SortedArrayMap.cpp in Sources */,
 				FE2BCDC72470FDA300DEC33B /* StdLibExtras.cpp in Sources */,
 				7C83DF321D0A590C00FEBCF3 /* StringBuilder.cpp in Sources */,
 				7CD4C26E1E2C0E6E00929470 /* StringConcatenate.cpp in Sources */,

Added: trunk/Tools/TestWebKitAPI/Tests/WTF/SortedArrayMap.cpp (0 => 276780)


--- trunk/Tools/TestWebKitAPI/Tests/WTF/SortedArrayMap.cpp	                        (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WTF/SortedArrayMap.cpp	2021-04-29 16:39:55 UTC (rev 276780)
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+#include "config.h"
+#include <wtf/SortedArrayMap.h>
+
+TEST(WTF, SortedArraySet)
+{
+    static constexpr ComparableCaseFoldingASCIILiteral caseFoldingArray[] = {
+        "_",
+        "a",
+        "c",
+        "delightful",
+        "q",
+        "q_",
+        "r/y",
+        "s-z",
+    };
+    static constexpr SortedArraySet caseFoldingSet { caseFoldingArray };
+
+    static constexpr ComparableLettersLiteral lettersArray[] = {
+        "a",
+        "c",
+        "delightful",
+        "q",
+        "r/y",
+        "s-z",
+    };
+    static constexpr SortedArraySet lettersSet { lettersArray };
+
+    static constexpr ComparableLettersLiteral scriptTypesArray[] = {
+        "application/ecmascript",
+        "application/_javascript_",
+        "application/x-ecmascript",
+        "application/x-_javascript_",
+        "text/ecmascript",
+        "text/_javascript_",
+        "text/_javascript_1.0",
+        "text/_javascript_1.1",
+        "text/_javascript_1.2",
+        "text/_javascript_1.3",
+        "text/_javascript_1.4",
+        "text/_javascript_1.5",
+        "text/jscript",
+        "text/livescript",
+        "text/x-ecmascript",
+        "text/x-_javascript_",
+    };
+    static constexpr SortedArraySet scriptTypesSet { scriptTypesArray };
+
+    EXPECT_FALSE(caseFoldingSet.contains(""));
+    EXPECT_TRUE(caseFoldingSet.contains("_"));
+    EXPECT_TRUE(caseFoldingSet.contains("c"));
+    EXPECT_TRUE(caseFoldingSet.contains("delightful"));
+    EXPECT_FALSE(caseFoldingSet.contains("d"));
+    EXPECT_TRUE(caseFoldingSet.contains("q_"));
+    EXPECT_FALSE(caseFoldingSet.contains("q__"));
+
+    EXPECT_FALSE(lettersSet.contains(""));
+    EXPECT_FALSE(lettersSet.contains("_"));
+    EXPECT_TRUE(lettersSet.contains("c"));
+    EXPECT_TRUE(lettersSet.contains("delightful"));
+    EXPECT_FALSE(lettersSet.contains("d"));
+    EXPECT_FALSE(lettersSet.contains("q_"));
+    EXPECT_FALSE(lettersSet.contains("q__"));
+
+    ASSERT_TRUE(scriptTypesSet.contains("text/_javascript_"));
+    ASSERT_TRUE(scriptTypesSet.contains("TEXT/_javascript_"));
+    ASSERT_TRUE(scriptTypesSet.contains("application/_javascript_"));
+    ASSERT_TRUE(scriptTypesSet.contains("application/ecmascript"));
+    ASSERT_TRUE(scriptTypesSet.contains("application/x-_javascript_"));
+    ASSERT_TRUE(scriptTypesSet.contains("application/x-ecmascript"));
+    ASSERT_FALSE(scriptTypesSet.contains("text/plain"));
+    ASSERT_FALSE(scriptTypesSet.contains("application/json"));
+    ASSERT_FALSE(scriptTypesSet.contains("foo/_javascript_"));
+}
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to