Title: [258866] trunk
Revision
258866
Author
[email protected]
Date
2020-03-23 12:31:36 -0700 (Mon, 23 Mar 2020)

Log Message

XMLHttpRequest: getAllResponseHeaders() sorting
https://bugs.webkit.org/show_bug.cgi?id=200565

Patch by Rob Buis <[email protected]> on 2020-03-23
Reviewed by Darin Adler.

LayoutTests/imported/w3c:

Update improved test result.

* web-platform-tests/xhr/getallresponseheaders-expected.txt:

Source/WebCore:

Sort headers using the ASCII-uppercase header name as key but use ASCII-lowercase header
names in the string result.

Nehavior matches Firefox and Chrome.

Test: imported/web-platform-tests/xhr/getallresponseheaders.htm

[1] https://xhr.spec.whatwg.org/#dom-xmlhttprequest-getallresponseheaders

* xml/XMLHttpRequest.cpp:
(WebCore::XMLHttpRequest::getAllResponseHeaders const):

Source/WTF:

Add a new manipulator that can efficiently convert
Strings to lower or upper ASCII.

* wtf/text/StringConcatenate.h:
(WTF::lowercase):
(WTF::uppercase):
* wtf/text/StringView.cpp:
(WTF::getCharactersWithASCIICaseInternal):
(WTF::StringView::getCharactersWithASCIICase const):
* wtf/text/StringView.h:

LayoutTests:

Update improved test results.

* platform/ios/imported/w3c/web-platform-tests/xhr/getallresponseheaders-expected.txt:
* platform/mac-highsierra/imported/w3c/web-platform-tests/xhr/getallresponseheaders-expected.txt:
* platform/mac-mojave/imported/w3c/web-platform-tests/xhr/getallresponseheaders-expected.txt:

Modified Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (258865 => 258866)


--- trunk/LayoutTests/ChangeLog	2020-03-23 19:05:12 UTC (rev 258865)
+++ trunk/LayoutTests/ChangeLog	2020-03-23 19:31:36 UTC (rev 258866)
@@ -1,3 +1,16 @@
+2020-03-23  Rob Buis  <[email protected]>
+
+        XMLHttpRequest: getAllResponseHeaders() sorting
+        https://bugs.webkit.org/show_bug.cgi?id=200565
+
+        Reviewed by Darin Adler.
+
+        Update improved test results.
+
+        * platform/ios/imported/w3c/web-platform-tests/xhr/getallresponseheaders-expected.txt:
+        * platform/mac-highsierra/imported/w3c/web-platform-tests/xhr/getallresponseheaders-expected.txt:
+        * platform/mac-mojave/imported/w3c/web-platform-tests/xhr/getallresponseheaders-expected.txt:
+
 2020-03-23  Jacob Uphoff  <[email protected]>
 
         Fixing merge conflict

Modified: trunk/LayoutTests/imported/w3c/ChangeLog (258865 => 258866)


--- trunk/LayoutTests/imported/w3c/ChangeLog	2020-03-23 19:05:12 UTC (rev 258865)
+++ trunk/LayoutTests/imported/w3c/ChangeLog	2020-03-23 19:31:36 UTC (rev 258866)
@@ -1,3 +1,14 @@
+2020-03-23  Rob Buis  <[email protected]>
+
+        XMLHttpRequest: getAllResponseHeaders() sorting
+        https://bugs.webkit.org/show_bug.cgi?id=200565
+
+        Reviewed by Darin Adler.
+
+        Update improved test result.
+
+        * web-platform-tests/xhr/getallresponseheaders-expected.txt:
+
 2020-03-23  Chris Dumez  <[email protected]>
 
         Port window.postMessage to the HTML event loop

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/xhr/getallresponseheaders-expected.txt (258865 => 258866)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/xhr/getallresponseheaders-expected.txt	2020-03-23 19:05:12 UTC (rev 258865)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/xhr/getallresponseheaders-expected.txt	2020-03-23 19:31:36 UTC (rev 258866)
@@ -1,5 +1,5 @@
 
-FAIL XMLHttpRequest: getAllResponseHeaders() assert_equals: expected "also-here: Mr. PB\r\newok: lego\r\nfoo-test: 1, 2\r\n__custom: token\r\n" but got "__custom: token\r\nalso-here: Mr. PB\r\newok: lego\r\nfoo-test: 1, 2\r\n"
+PASS XMLHttpRequest: getAllResponseHeaders() 
 PASS XMLHttpRequest: getAllResponseHeaders() 1 
 PASS XMLHttpRequest: getAllResponseHeaders() 2 
 PASS XMLHttpRequest: getAllResponseHeaders() 3 

Modified: trunk/LayoutTests/platform/ios/imported/w3c/web-platform-tests/xhr/getallresponseheaders-expected.txt (258865 => 258866)


--- trunk/LayoutTests/platform/ios/imported/w3c/web-platform-tests/xhr/getallresponseheaders-expected.txt	2020-03-23 19:05:12 UTC (rev 258865)
+++ trunk/LayoutTests/platform/ios/imported/w3c/web-platform-tests/xhr/getallresponseheaders-expected.txt	2020-03-23 19:31:36 UTC (rev 258866)
@@ -1,5 +1,5 @@
 
-FAIL XMLHttpRequest: getAllResponseHeaders() assert_equals: expected "also-here: Mr. PB\r\newok: lego\r\nfoo-test: 1, 2\r\n__custom: token\r\n" but got "__custom: token\r\nalso-here: Mr. PB\r\newok: lego\r\nfoo-test: 1, 2\r\n"
+PASS XMLHttpRequest: getAllResponseHeaders() 
 PASS XMLHttpRequest: getAllResponseHeaders() 1 
 PASS XMLHttpRequest: getAllResponseHeaders() 2 
 PASS XMLHttpRequest: getAllResponseHeaders() 3 

Modified: trunk/LayoutTests/platform/mac-highsierra/imported/w3c/web-platform-tests/xhr/getallresponseheaders-expected.txt (258865 => 258866)


--- trunk/LayoutTests/platform/mac-highsierra/imported/w3c/web-platform-tests/xhr/getallresponseheaders-expected.txt	2020-03-23 19:05:12 UTC (rev 258865)
+++ trunk/LayoutTests/platform/mac-highsierra/imported/w3c/web-platform-tests/xhr/getallresponseheaders-expected.txt	2020-03-23 19:31:36 UTC (rev 258866)
@@ -1,5 +1,5 @@
 
-FAIL XMLHttpRequest: getAllResponseHeaders() assert_equals: expected "also-here: Mr. PB\r\newok: lego\r\nfoo-test: 1, 2\r\n__custom: token\r\n" but got "__custom: token\r\nalso-here: Mr. PB\r\newok: lego\r\nfoo-test: 1, 2\r\n"
+PASS XMLHttpRequest: getAllResponseHeaders() 
 PASS XMLHttpRequest: getAllResponseHeaders() 1 
 PASS XMLHttpRequest: getAllResponseHeaders() 2 
 PASS XMLHttpRequest: getAllResponseHeaders() 3 

Modified: trunk/LayoutTests/platform/mac-mojave/imported/w3c/web-platform-tests/xhr/getallresponseheaders-expected.txt (258865 => 258866)


--- trunk/LayoutTests/platform/mac-mojave/imported/w3c/web-platform-tests/xhr/getallresponseheaders-expected.txt	2020-03-23 19:05:12 UTC (rev 258865)
+++ trunk/LayoutTests/platform/mac-mojave/imported/w3c/web-platform-tests/xhr/getallresponseheaders-expected.txt	2020-03-23 19:31:36 UTC (rev 258866)
@@ -1,5 +1,5 @@
 
-FAIL XMLHttpRequest: getAllResponseHeaders() assert_equals: expected "also-here: Mr. PB\r\newok: lego\r\nfoo-test: 1, 2\r\n__custom: token\r\n" but got "__custom: token\r\nalso-here: Mr. PB\r\newok: lego\r\nfoo-test: 1, 2\r\n"
+PASS XMLHttpRequest: getAllResponseHeaders() 
 PASS XMLHttpRequest: getAllResponseHeaders() 1 
 PASS XMLHttpRequest: getAllResponseHeaders() 2 
 PASS XMLHttpRequest: getAllResponseHeaders() 3 

Modified: trunk/Source/WTF/ChangeLog (258865 => 258866)


--- trunk/Source/WTF/ChangeLog	2020-03-23 19:05:12 UTC (rev 258865)
+++ trunk/Source/WTF/ChangeLog	2020-03-23 19:31:36 UTC (rev 258866)
@@ -1,3 +1,21 @@
+2020-03-23  Rob Buis  <[email protected]>
+
+        XMLHttpRequest: getAllResponseHeaders() sorting
+        https://bugs.webkit.org/show_bug.cgi?id=200565
+
+        Reviewed by Darin Adler.
+
+        Add a new manipulator that can efficiently convert
+        Strings to lower or upper ASCII.
+
+        * wtf/text/StringConcatenate.h:
+        (WTF::lowercase):
+        (WTF::uppercase):
+        * wtf/text/StringView.cpp:
+        (WTF::getCharactersWithASCIICaseInternal):
+        (WTF::StringView::getCharactersWithASCIICase const):
+        * wtf/text/StringView.h:
+
 2020-03-23  Antoine Quint  <[email protected]>
 
         DocumentTimeline / CSSTransition objects are leaking on CNN.com

Modified: trunk/Source/WTF/wtf/text/StringConcatenate.h (258865 => 258866)


--- trunk/Source/WTF/wtf/text/StringConcatenate.h	2020-03-23 19:05:12 UTC (rev 258865)
+++ trunk/Source/WTF/wtf/text/StringConcatenate.h	2020-03-23 19:31:36 UTC (rev 258866)
@@ -287,6 +287,39 @@
     Indentation<N> m_indentation;
 };
 
+struct ASCIICaseConverter {
+    StringView::CaseConvertType type;
+    StringView string;
+};
+
+inline ASCIICaseConverter lowercase(const StringView& stringView)
+{
+    return { StringView::CaseConvertType::Lower, stringView };
+}
+
+inline ASCIICaseConverter uppercase(const StringView& stringView)
+{
+    return { StringView::CaseConvertType::Upper, stringView };
+}
+
+template<> class StringTypeAdapter<ASCIICaseConverter, void> {
+public:
+    StringTypeAdapter(const ASCIICaseConverter& converter)
+        : m_converter { converter }
+    {
+    }
+
+    unsigned length() const { return m_converter.string.length(); }
+    bool is8Bit() const { return m_converter.string.is8Bit(); }
+    template<typename CharacterType> void writeTo(CharacterType* destination) const
+    {
+        m_converter.string.getCharactersWithASCIICase(m_converter.type, destination);
+    }
+
+private:
+    const ASCIICaseConverter& m_converter;
+};
+
 template<typename Adapter>
 inline bool are8Bit(Adapter adapter)
 {
@@ -364,6 +397,8 @@
 using WTF::IndentationScope;
 using WTF::makeString;
 using WTF::pad;
+using WTF::lowercase;
 using WTF::tryMakeString;
+using WTF::uppercase;
 
 #include <wtf/text/StringOperators.h>

Modified: trunk/Source/WTF/wtf/text/StringView.cpp (258865 => 258866)


--- trunk/Source/WTF/wtf/text/StringView.cpp	2020-03-23 19:05:12 UTC (rev 258865)
+++ trunk/Source/WTF/wtf/text/StringView.cpp	2020-03-23 19:31:36 UTC (rev 258866)
@@ -30,6 +30,7 @@
 #include <mutex>
 #include <unicode/ubrk.h>
 #include <unicode/unorm2.h>
+#include <wtf/ASCIICType.h>
 #include <wtf/HashMap.h>
 #include <wtf/Lock.h>
 #include <wtf/NeverDestroyed.h>
@@ -242,6 +243,32 @@
     return convertASCIICase<ASCIICase::Upper>(static_cast<const UChar*>(m_characters), m_length);
 }
 
+template<typename DestinationCharacterType, typename SourceCharacterType>
+void getCharactersWithASCIICaseInternal(StringView::CaseConvertType type, DestinationCharacterType* destination, const SourceCharacterType* source, unsigned length)
+{
+    static_assert(std::is_same<SourceCharacterType, LChar>::value || std::is_same<SourceCharacterType, UChar>::value);
+    static_assert(std::is_same<DestinationCharacterType, LChar>::value || std::is_same<DestinationCharacterType, UChar>::value);
+    static_assert(sizeof(DestinationCharacterType) >= sizeof(SourceCharacterType));
+    auto caseConvert = (type == StringView::CaseConvertType::Lower) ? toASCIILower<SourceCharacterType> : toASCIIUpper<SourceCharacterType>;
+    for (unsigned i = 0; i < length; ++i)
+        destination[i] = caseConvert(source[i]);
+}
+
+void StringView::getCharactersWithASCIICase(CaseConvertType type, LChar* destination) const
+{
+    ASSERT(is8Bit());
+    getCharactersWithASCIICaseInternal(type, destination, characters8(), m_length);
+}
+
+void StringView::getCharactersWithASCIICase(CaseConvertType type, UChar* destination) const
+{
+    if (is8Bit()) {
+        getCharactersWithASCIICaseInternal(type, destination, characters8(), m_length);
+        return;
+    }
+    getCharactersWithASCIICaseInternal(type, destination, characters16(), m_length);
+}
+
 StringViewWithUnderlyingString normalizedNFC(StringView string)
 {
     // Latin-1 characters are unaffected by normalization.

Modified: trunk/Source/WTF/wtf/text/StringView.h (258865 => 258866)


--- trunk/Source/WTF/wtf/text/StringView.h	2020-03-23 19:05:12 UTC (rev 258865)
+++ trunk/Source/WTF/wtf/text/StringView.h	2020-03-23 19:31:36 UTC (rev 258866)
@@ -120,6 +120,10 @@
     void getCharactersWithUpconvert(LChar*) const;
     void getCharactersWithUpconvert(UChar*) const;
 
+    enum class CaseConvertType { Upper, Lower };
+    WTF_EXPORT_PRIVATE void getCharactersWithASCIICase(CaseConvertType, LChar*) const;
+    WTF_EXPORT_PRIVATE void getCharactersWithASCIICase(CaseConvertType, UChar*) const;
+
     StringView substring(unsigned start, unsigned length = std::numeric_limits<unsigned>::max()) const;
     StringView left(unsigned length) const { return substring(0, length); }
     StringView right(unsigned length) const { return substring(this->length() - length, length); }

Modified: trunk/Source/WebCore/ChangeLog (258865 => 258866)


--- trunk/Source/WebCore/ChangeLog	2020-03-23 19:05:12 UTC (rev 258865)
+++ trunk/Source/WebCore/ChangeLog	2020-03-23 19:31:36 UTC (rev 258866)
@@ -1,3 +1,22 @@
+2020-03-23  Rob Buis  <[email protected]>
+
+        XMLHttpRequest: getAllResponseHeaders() sorting
+        https://bugs.webkit.org/show_bug.cgi?id=200565
+
+        Reviewed by Darin Adler.
+
+        Sort headers using the ASCII-uppercase header name as key but use ASCII-lowercase header
+        names in the string result.
+
+        Nehavior matches Firefox and Chrome.
+
+        Test: imported/web-platform-tests/xhr/getallresponseheaders.htm
+
+        [1] https://xhr.spec.whatwg.org/#dom-xmlhttprequest-getallresponseheaders
+
+        * xml/XMLHttpRequest.cpp:
+        (WebCore::XMLHttpRequest::getAllResponseHeaders const):
+
 2020-03-23  Truitt Savell  <[email protected]>
 
         Unreviewed, reverting r258847.

Modified: trunk/Source/WebCore/xml/XMLHttpRequest.cpp (258865 => 258866)


--- trunk/Source/WebCore/xml/XMLHttpRequest.cpp	2020-03-23 19:05:12 UTC (rev 258865)
+++ trunk/Source/WebCore/xml/XMLHttpRequest.cpp	2020-03-23 19:31:36 UTC (rev 258866)
@@ -811,22 +811,29 @@
         return emptyString();
 
     if (!m_allResponseHeaders) {
-        Vector<String> headers;
+        Vector<std::pair<String, String>> headers;
         headers.reserveInitialCapacity(m_response.httpHeaderFields().size());
 
-        for (auto& header : m_response.httpHeaderFields()) {
-            StringBuilder stringBuilder;
-            stringBuilder.append(header.key.convertToASCIILowercase());
-            stringBuilder.appendLiteral(": ");
-            stringBuilder.append(header.value);
-            stringBuilder.appendLiteral("\r\n");
-            headers.uncheckedAppend(stringBuilder.toString());
-        }
-        std::sort(headers.begin(), headers.end(), WTF::codePointCompareLessThan);
+        for (auto& header : m_response.httpHeaderFields())
+            headers.uncheckedAppend(std::make_pair(header.key, header.value));
 
+        std::sort(headers.begin(), headers.end(), [] (const std::pair<String, String>& x, const std::pair<String, String>& y) {
+            unsigned xLength = x.first.length();
+            unsigned yLength = y.first.length();
+            unsigned commonLength = std::min(xLength, yLength);
+            for (unsigned i = 0; i < commonLength; ++i) {
+                auto xCharacter = toASCIIUpper(x.first[i]);
+                auto yCharacter = toASCIIUpper(y.first[i]);
+                if (xCharacter != yCharacter)
+                    return xCharacter < yCharacter;
+            }
+            return xLength < yLength;
+        });
+
         StringBuilder stringBuilder;
         for (auto& header : headers)
-            stringBuilder.append(header);
+            stringBuilder.append(lowercase(header.first), ": ", header.second, "\r\n");
+
         m_allResponseHeaders = stringBuilder.toString();
     }
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to