<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[163022] trunk</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/163022">163022</a></dd>
<dt>Author</dt> <dd>commit-queue@webkit.org</dd>
<dt>Date</dt> <dd>2014-01-29 09:03:59 -0800 (Wed, 29 Jan 2014)</dd>
</dl>
<h3>Log Message</h3>
<pre>Source/WebCore: Have XHR.getResponseHeader() return null and XHR.getAllResponseHeader() return the empty string in initial ready states
https://bugs.webkit.org/show_bug.cgi?id=125840
Patch by Youenn Fablet <youennf@gmail.com> on 2014-01-29
Reviewed by Alexey Proskuryakov.
Merging https://chromium.googlesource.com/chromium/blink/+/d201caf874a0bd6f101f517462b3cf1d8c5fce3d
This patch makes it clear that null/empty string is returned whenever the error flag is set.
This new code path is covered by the added test.
Test: http/tests/xmlhttprequest/response-access-on-error.html
* xml/XMLHttpRequest.cpp:
(WebCore::XMLHttpRequest::getAllResponseHeaders):
(WebCore::XMLHttpRequest::getResponseHeader):
* xml/XMLHttpRequest.h:
* xml/XMLHttpRequest.idl:
LayoutTests: Have XHR.getResponseHeader() return null and XHR.getAllResponseHeaders() return empty string in initial ready states
https://bugs.webkit.org/show_bug.cgi?id=125840
Patch by Youenn Fablet <youennf@gmail.com> on 2014-01-29
Reviewed by Alexey Proskuryakov.
Merging https://chromium.googlesource.com/chromium/blink/+/d201caf874a0bd6f101f517462b3cf1d8c5fce3d
The new test exercices the new code path in case xhr received HTTP headers but m_error is set
* http/tests/xmlhttprequest/getAllResponseHeaders-expected.txt:
* http/tests/xmlhttprequest/getAllResponseHeaders.html:
* http/tests/xmlhttprequest/getResponseHeader-expected.txt:
* http/tests/xmlhttprequest/getResponseHeader.html:
* http/tests/xmlhttprequest/response-access-on-error-expected.txt: Added.
* http/tests/xmlhttprequest/response-access-on-error.html: Added.</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestshttptestsxmlhttprequestgetAllResponseHeadersexpectedtxt">trunk/LayoutTests/http/tests/xmlhttprequest/getAllResponseHeaders-expected.txt</a></li>
<li><a href="#trunkLayoutTestshttptestsxmlhttprequestgetAllResponseHeadershtml">trunk/LayoutTests/http/tests/xmlhttprequest/getAllResponseHeaders.html</a></li>
<li><a href="#trunkLayoutTestshttptestsxmlhttprequestgetResponseHeaderexpectedtxt">trunk/LayoutTests/http/tests/xmlhttprequest/getResponseHeader-expected.txt</a></li>
<li><a href="#trunkLayoutTestshttptestsxmlhttprequestgetResponseHeaderhtml">trunk/LayoutTests/http/tests/xmlhttprequest/getResponseHeader.html</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCorexmlXMLHttpRequestcpp">trunk/Source/WebCore/xml/XMLHttpRequest.cpp</a></li>
<li><a href="#trunkSourceWebCorexmlXMLHttpRequesth">trunk/Source/WebCore/xml/XMLHttpRequest.h</a></li>
<li><a href="#trunkSourceWebCorexmlXMLHttpRequestidl">trunk/Source/WebCore/xml/XMLHttpRequest.idl</a></li>
</ul>
<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestshttptestsxmlhttprequestresponseaccessonerrorexpectedtxt">trunk/LayoutTests/http/tests/xmlhttprequest/response-access-on-error-expected.txt</a></li>
<li><a href="#trunkLayoutTestshttptestsxmlhttprequestresponseaccessonerrorhtml">trunk/LayoutTests/http/tests/xmlhttprequest/response-access-on-error.html</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (163021 => 163022)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2014-01-29 16:26:31 UTC (rev 163021)
+++ trunk/LayoutTests/ChangeLog        2014-01-29 17:03:59 UTC (rev 163022)
</span><span class="lines">@@ -1,3 +1,20 @@
</span><ins>+2014-01-29 Youenn Fablet <youennf@gmail.com>
+
+ Have XHR.getResponseHeader() return null and XHR.getAllResponseHeaders() return empty string in initial ready states
+ https://bugs.webkit.org/show_bug.cgi?id=125840
+
+ Reviewed by Alexey Proskuryakov.
+
+ Merging https://chromium.googlesource.com/chromium/blink/+/d201caf874a0bd6f101f517462b3cf1d8c5fce3d
+ The new test exercices the new code path in case xhr received HTTP headers but m_error is set
+
+ * http/tests/xmlhttprequest/getAllResponseHeaders-expected.txt:
+ * http/tests/xmlhttprequest/getAllResponseHeaders.html:
+ * http/tests/xmlhttprequest/getResponseHeader-expected.txt:
+ * http/tests/xmlhttprequest/getResponseHeader.html:
+ * http/tests/xmlhttprequest/response-access-on-error-expected.txt: Added.
+ * http/tests/xmlhttprequest/response-access-on-error.html: Added.
+
</ins><span class="cx"> 2014-01-29 Antti Koivisto <antti@apple.com>
</span><span class="cx">
</span><span class="cx"> REGRESSION (r162947): Repaint test results are different between WK1 and WK2
</span></span></pre></div>
<a id="trunkLayoutTestshttptestsxmlhttprequestgetAllResponseHeadersexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/http/tests/xmlhttprequest/getAllResponseHeaders-expected.txt (163021 => 163022)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/http/tests/xmlhttprequest/getAllResponseHeaders-expected.txt        2014-01-29 16:26:31 UTC (rev 163021)
+++ trunk/LayoutTests/http/tests/xmlhttprequest/getAllResponseHeaders-expected.txt        2014-01-29 17:03:59 UTC (rev 163022)
</span><span class="lines">@@ -1,10 +1,27 @@
</span><del>-Test page for bug 15356 and bug 29121
</del><ins>+Test the required behavior of XMLHttpRequest.getAllResponseHeaders()
</ins><span class="cx">
</span><del>-Assertion: Invoking getAllResponseHeaders method when readyState >= 2 (HEADERS_RECEIVED) should return a conforming list of headers.
</del><ins>+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
</ins><span class="cx">
</span><del>-PASSED 0
-PASSED 1
-PASSED 2: getAllResponseHeaders returned what looks like a conforming headerlist.
-PASSED 3
-PASSED 4
</del><span class="cx">
</span><ins>+PASS {state: 0}; headerValues = xhr.getAllResponseHeaders(); did not throw exception.
+PASS headerValues is the empty string
+PASS {state: 1}; headerValues = xhr.getAllResponseHeaders(); did not throw exception.
+PASS headerValues is the empty string
+PASS getAllResponseHeaders() result is empty in ready state 1.
+PASS xhr.open("GET", "resources/1251.html", true); did not throw exception.
+PASS {state: 1}; headerValues = xhr.getAllResponseHeaders(); did not throw exception.
+PASS headerValues is the empty string
+PASS xhr.send(null); did not throw exception.
+PASS {state: 2}; headerValues = xhr.getAllResponseHeaders(); did not throw exception.
+PASS headerValues is not the empty string
+PASS Header values appears to be conforming.
+PASS {state: 3}; headerValues = xhr.getAllResponseHeaders(); did not throw exception.
+PASS headerValues is not the empty string
+PASS responseHeaders is savedHeaders
+PASS {state: 4}; headerValues = xhr.getAllResponseHeaders(); did not throw exception.
+PASS headerValues is not the empty string
+PASS responseHeaders is savedHeaders
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestshttptestsxmlhttprequestgetAllResponseHeadershtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/http/tests/xmlhttprequest/getAllResponseHeaders.html (163021 => 163022)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/http/tests/xmlhttprequest/getAllResponseHeaders.html        2014-01-29 16:26:31 UTC (rev 163021)
+++ trunk/LayoutTests/http/tests/xmlhttprequest/getAllResponseHeaders.html        2014-01-29 17:03:59 UTC (rev 163022)
</span><span class="lines">@@ -1,118 +1,69 @@
</span><ins>+<!doctype html>
</ins><span class="cx"> <html>
</span><span class="cx"> <head>
</span><del>- <title>Check exception thrown by getAllResponseHeaders and some
- characteristics of the return value</title>
</del><ins>+<title>Testing XMLHttpRequest.getReponseHeader behavior</title>
+<script src="/js-test-resources/js-test-pre.js"></script>
</ins><span class="cx"> <script type="text/javascript">
</span><ins>+description("Test the required behavior of XMLHttpRequest.getAllResponseHeaders()");
</ins><span class="cx">
</span><del>-function log (msg) {
- var paragraph = document.createElement("li");
- paragraph.innerHTML=msg.replace(/\n/gm,"<br>");
- document.getElementById("console").appendChild(paragraph);
-}
</del><ins>+window.jsTestIsAsync = true;
</ins><span class="cx">
</span><del>-var xhr;
</del><ins>+var xhr = new XMLHttpRequest();
</ins><span class="cx">
</span><del>-if (window.XMLHttpRequest) {
- xhr = new XMLHttpRequest();
-} else {
- try {
- xhr = new ActiveXObject("Msxml2.XMLHTTP");
- } catch (ex) {
- xhr = new ActiveXObject("Microsoft.XMLHTTP");
- }
</del><ins>+var savedHeaders = null;
+
+var headerValues;
+function testGetAllResponseHeaders(xhr, expectEmpty) {
+ shouldNotThrow("{state: " + xhr.readyState + "}; headerValues = xhr.getAllResponseHeaders();");
+ if (expectEmpty && headerValues !== "")
+ testFailed("Expected the empty string, got: '" + headerValues + "'");
+ else
+ testPassed("headerValues is " + (!expectEmpty ? "not " : "") + "the empty string");
+ return headerValues;
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-var savedHeader = null;
</del><ins>+var responseHeaders;
</ins><span class="cx"> xhr.onreadystatechange = function() {
</span><span class="cx"> var rState = this.readyState;
</span><del>- // We expect an INVALID_STATE_ERR exception for readyState < 2
- // and no exception for readyState >= 2
- try {
- var header = this.getAllResponseHeaders();
- if (rState != this.readyState)
- log("UNCERTAIN " + rState + ": readyState changed while getting headers.");
- if (rState < 2) {
- log("FAILED " + rState + ": headerlist=" + header);
- } else if (header)
- if (savedHeader)
- if (savedHeader != header) {
- log("FAILED " + rState +
-": headerlist changed after it was first returned. Previous header list:\n"
-+ savedHeader + "\n New headerlist:\n" + header);
- savedHeader = header;
- }
- else //savedHeader == header here; no need to reprint header
- log("PASSED " + rState);
- else {//first header list retrieved
- if (/^Set-Cookie:|^Set-Cookie2:/im.test(header))
- log("FAILED " + rState +
-": /^Set-Cookie:|^Set-Cookie2:/ matches. getAllResponseHeaders returned:\n" + header);
- else if (window.testRunner)
-//do not print list for automated tests to avoid false failures.
- log("PASSED " + rState +
-": getAllResponseHeaders returned what looks like a conforming headerlist.");
</del><ins>+ responseHeaders = testGetAllResponseHeaders(this, rState <= XMLHttpRequest.OPENED);
+ if (responseHeaders) {
+ if (savedHeaders) {
+ shouldBe("responseHeaders", "savedHeaders");
+ } else {
+ if (/^Set-Cookie:|^Set-Cookie2:/im.test(responseHeaders)) {
+ testFailed("Did not expect to find a Set-Cookie{2} header, got: '" + responseHeaders + "'");
+ } else {
+ // Do not print list for automated tests to avoid false failures.
+ if (self.testRunner)
+ testPassed("Header values appears to be conforming.");
</ins><span class="cx"> else
</span><del>- log("PASSED " + rState +
-": getAllResponseHeaders returned:\n" + header);
- savedHeader = header;
</del><ins>+ testPassed("Header values appears ok: " + JSON.stringify(headerValues));
</ins><span class="cx"> }
</span><del>- else //header is null
- log("FAILED " + rState + ": null header list returned");
- } catch (e) {
- if (rState < 2) {
- log("PASSED " + rState);
- } else {
- log("FAILED " + rState + ": EXCEPTION THROWN: " + e.message + ".");
</del><span class="cx"> }
</span><ins>+ savedHeaders = responseHeaders;
+ } else {
+ if (rState > XMLHttpRequest.OPENED)
+ testFailed("In ready state " + rState + ", unexpected empty value.");
+ else if (responseHeaders !== "")
+ testFailed("In ready state " + rState + ", expected the empty string, got: " + JSON.stringify(responseHeaders) + ".");
+ else
+ testPassed("getAllResponseHeaders() result is empty in ready state " + rState + ".");
</ins><span class="cx"> }
</span><del>- if ((rState == 4) && (window.testRunner))
- testRunner.notifyDone();
</del><ins>+
+ if (rState == XMLHttpRequest.DONE)
+ finishJSTest();
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-function test() {
- if (window.testRunner) {
- testRunner.waitUntilDone();
- testRunner.dumpAsText();
- }
</del><ins>+function runTest() {
</ins><span class="cx"> // Test for readyState = 0
</span><del>- try {
- var header = xhr.getAllResponseHeaders();
- log("FAILED " + xhr.readyState + ": header=" + header);
- } catch (e) {
- log("PASSED " + xhr.readyState);
- }
- try {
- xhr.open("GET","resources/1251.html", true);
- xhr.send(null);
- } catch(e) {
- log("FAILED open/send: EXCEPTION THROWN: " + e.message +".");
- if (window.testRunner)
- testRunner.notifyDone();
- }
</del><ins>+ testGetAllResponseHeaders(xhr, true);
+ shouldNotThrow('xhr.open("GET", "resources/1251.html", true);');
+ // Test for readyState = 1
+ testGetAllResponseHeaders(xhr, true);
+ shouldNotThrow("xhr.send(null);");
</ins><span class="cx"> }
</span><ins>+runTest();
</ins><span class="cx"> </script>
</span><ins>+<script src="/js-test-resources/js-test-post.js"></script>
</ins><span class="cx"> </head>
</span><del>-<body onload="test()">
-
-<p>Test page for <a href="http://bugs.webkit.org/show_bug.cgi?id=15356">bug 15356</a>
-and <a href="http://bugs.webkit.org/show_bug.cgi?id=29121">bug 29121</a></p>
-<p>Assertion: Invoking getAllResponseHeaders method when readyState >= 2
-(HEADERS_RECEIVED) should return a conforming list of headers.</p>
-<script>
- if (!window.testRunner)
- document.write("<p>If the test passes one should see \
-below the ruler the text \"passed\" in all capital letters, 5 times, \
-followed each time by a space and the readyState number.</p>\n\
-<p>ReadyStatenumbers should be in ascending order 0 to 4.</p>\n\
-<p>A conforming list of response headers should also be printed.</p>\n\
-<p>A conforming list of headers:</p> \
- <li> contains one header per line.</li> \
- <li> has header names and header values separated by a COLON and \
-a SPACE.</li>\
- <li> does not contain any headers that match (case-insensitively) \
-Set-Cookie or Set-Cookie2</li>");
- </script>
- <hr>
- <p><ol id=console></ol></p>
-</body>
</del><span class="cx"> </html>
</span></span></pre></div>
<a id="trunkLayoutTestshttptestsxmlhttprequestgetResponseHeaderexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/http/tests/xmlhttprequest/getResponseHeader-expected.txt (163021 => 163022)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/http/tests/xmlhttprequest/getResponseHeader-expected.txt        2014-01-29 16:26:31 UTC (rev 163021)
+++ trunk/LayoutTests/http/tests/xmlhttprequest/getResponseHeader-expected.txt        2014-01-29 17:03:59 UTC (rev 163022)
</span><span class="lines">@@ -4,35 +4,59 @@
</span><span class="cx"> CONSOLE MESSAGE: Refused to get unsafe header "sEt-coOkIE2"
</span><span class="cx"> CONSOLE MESSAGE: Refused to get unsafe header "SeT-COoKie"
</span><span class="cx"> CONSOLE MESSAGE: Refused to get unsafe header "sEt-coOkIE2"
</span><del>-Test page for bug 15356 and bug 29121
</del><ins>+Test the required behavior of XMLHttpRequest.getResponseHeader()
</ins><span class="cx">
</span><del>-Assertion: Invoking the getResponseHeader method when readyState >= 2 (HEADERS_RECEIVED) returns a header value if the header exists.
</del><ins>+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
</ins><span class="cx">
</span><del>-Assertion: Invoking the getResponseHeader method with the parameter satisfying the following conditions causes getResponseHeader to return null:
</del><span class="cx">
</span><del>-1a. The parameter case-insensitively matches Set-Cookie;
-1b. The parameter case-insensitively matches Set-Cookie2;
-2. The parameter does not match any header in the response;
-3a. The parameter is null (it is not a valid header name);
-3b. The parameter is "Content-Type:" (it is not a valid header name).
-PASSED 0 Content-Type: exception thrown.
-PASSED 1 Content-Type: exception thrown
-PASSED 2 Content-Type: ResponseHeader(Content-Type) returned a value.
-PASSED 2 SeT-COoKie: getResponseHeader(SeT-COoKie) returned null.
-PASSED 2 sEt-coOkIE2: getResponseHeader(sEt-coOkIE2) returned null.
-PASSED 2 xxx-mytest-headerabc: getResponseHeader(xxx-mytest-headerabc) returned null.
-PASSED 2 null: getResponseHeader(null) returned null.
-PASSED 2 Content-Type:: getResponseHeader(Content-Type:) returned null.
-PASSED 3 Content-Type: Content-Type
-PASSED 3 SeT-COoKie: getResponseHeader(SeT-COoKie) returned null.
-PASSED 3 sEt-coOkIE2: getResponseHeader(sEt-coOkIE2) returned null.
-PASSED 3 xxx-mytest-headerabc: getResponseHeader(xxx-mytest-headerabc) returned null.
-PASSED 3 null: getResponseHeader(null) returned null.
-PASSED 3 Content-Type:: getResponseHeader(Content-Type:) returned null.
-PASSED 4 Content-Type: Content-Type
-PASSED 4 SeT-COoKie: getResponseHeader(SeT-COoKie) returned null.
-PASSED 4 sEt-coOkIE2: getResponseHeader(sEt-coOkIE2) returned null.
-PASSED 4 xxx-mytest-headerabc: getResponseHeader(xxx-mytest-headerabc) returned null.
-PASSED 4 null: getResponseHeader(null) returned null.
-PASSED 4 Content-Type:: getResponseHeader(Content-Type:) returned null.
</del><ins>+PASS {state: 0}; headerValue = xhr.getResponseHeader('Content-Type'); did not throw exception.
+PASS headerValue is null
+PASS {state: 1}; headerValue = xhr.getResponseHeader('Content-Type'); did not throw exception.
+PASS headerValue is null
+PASS Header 'Content-Type' is null in ready state 1.
+PASS xhr.open("GET", "resources/1251.html", true); did not throw exception.
+PASS {state: 1}; headerValue = xhr.getResponseHeader('Content-Type'); did not throw exception.
+PASS headerValue is null
+PASS xhr.send(null); did not throw exception.
+PASS {state: 2}; headerValue = xhr.getResponseHeader('Content-Type'); did not throw exception.
+PASS headerValue is non-null.
+PASS {state: 2}; headerValue = xhr.getResponseHeader('SeT-COoKie'); did not throw exception.
+PASS headerValue is null
+PASS {state: 2}; headerValue = xhr.getResponseHeader('sEt-coOkIE2'); did not throw exception.
+PASS headerValue is null
+PASS {state: 2}; headerValue = xhr.getResponseHeader('xxx-mytest-headerabc'); did not throw exception.
+PASS headerValue is null
+PASS {state: 2}; headerValue = xhr.getResponseHeader('null'); did not throw exception.
+PASS headerValue is null
+PASS {state: 2}; headerValue = xhr.getResponseHeader('Content-Type:'); did not throw exception.
+PASS headerValue is null
+PASS {state: 3}; headerValue = xhr.getResponseHeader('Content-Type'); did not throw exception.
+PASS headerValue is non-null.
+PASS result is savedHeader
+PASS {state: 3}; headerValue = xhr.getResponseHeader('SeT-COoKie'); did not throw exception.
+PASS headerValue is null
+PASS {state: 3}; headerValue = xhr.getResponseHeader('sEt-coOkIE2'); did not throw exception.
+PASS headerValue is null
+PASS {state: 3}; headerValue = xhr.getResponseHeader('xxx-mytest-headerabc'); did not throw exception.
+PASS headerValue is null
+PASS {state: 3}; headerValue = xhr.getResponseHeader('null'); did not throw exception.
+PASS headerValue is null
+PASS {state: 3}; headerValue = xhr.getResponseHeader('Content-Type:'); did not throw exception.
+PASS headerValue is null
+PASS {state: 4}; headerValue = xhr.getResponseHeader('Content-Type'); did not throw exception.
+PASS headerValue is non-null.
+PASS result is savedHeader
+PASS {state: 4}; headerValue = xhr.getResponseHeader('SeT-COoKie'); did not throw exception.
+PASS headerValue is null
+PASS {state: 4}; headerValue = xhr.getResponseHeader('sEt-coOkIE2'); did not throw exception.
+PASS headerValue is null
+PASS {state: 4}; headerValue = xhr.getResponseHeader('xxx-mytest-headerabc'); did not throw exception.
+PASS headerValue is null
+PASS {state: 4}; headerValue = xhr.getResponseHeader('null'); did not throw exception.
+PASS headerValue is null
+PASS {state: 4}; headerValue = xhr.getResponseHeader('Content-Type:'); did not throw exception.
+PASS headerValue is null
+PASS successfullyParsed is true
</ins><span class="cx">
</span><ins>+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestshttptestsxmlhttprequestgetResponseHeaderhtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/http/tests/xmlhttprequest/getResponseHeader.html (163021 => 163022)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/http/tests/xmlhttprequest/getResponseHeader.html        2014-01-29 16:26:31 UTC (rev 163021)
+++ trunk/LayoutTests/http/tests/xmlhttprequest/getResponseHeader.html        2014-01-29 17:03:59 UTC (rev 163022)
</span><span class="lines">@@ -1,140 +1,69 @@
</span><ins>+<!doctype html>
</ins><span class="cx"> <html>
</span><span class="cx"> <head>
</span><del>- <title>Check exception thrown by getReponseHeader </title>
</del><ins>+<title>Testing XMLHttpRequest.getReponseHeader behavior</title>
+<script src="/js-test-resources/js-test-pre.js"></script>
</ins><span class="cx"> <script type="text/javascript">
</span><ins>+description("Test the required behavior of XMLHttpRequest.getResponseHeader()");
</ins><span class="cx">
</span><ins>+window.jsTestIsAsync = true;
+
</ins><span class="cx"> var savedHeader = null;
</span><del>-var headerName="Content-Type";
-var nullTests = new Array("SeT-COoKie", "sEt-coOkIE2",
- "xxx-mytest-headerabc", null, "Content-Type:");
</del><ins>+var headerName = "Content-Type";
+var nullTests = [ "SeT-COoKie",
+ "sEt-coOkIE2",
+ "xxx-mytest-headerabc",
+ null,
+ "Content-Type:" ];
</ins><span class="cx">
</span><del>-function log (msg) {
- var paragraph = document.createElement("li");
- paragraph.innerHTML=msg.replace(/\n/gm,"<br>");
- document.getElementById("console").appendChild(paragraph);
-}
</del><ins>+var xhr = new XMLHttpRequest();
</ins><span class="cx">
</span><del>-function log4(status, rState, subState, msg) {
- log(status + " " + rState + " " + subState + ": " + msg);
-}
</del><ins>+var headerValue;
+function testGetResponseHeader(xhr, headerName, expectNull) {
+ shouldNotThrow("{state: " + xhr.readyState + "}; headerValue = xhr.getResponseHeader('" + headerName + "');");
+ if (expectNull)
+ shouldBeNull("headerValue");
+ else
+ shouldBeNonNull("headerValue");
</ins><span class="cx">
</span><del>-function log3(status, rState, msg) {
- log4(status, rState, headerName, msg);
</del><ins>+ return headerValue;
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-if (window.XMLHttpRequest) {
- xhr = new XMLHttpRequest();
-} else {
- try {
- xhr = new ActiveXObject("Msxml2.XMLHTTP");
- } catch (ex) {
- xhr = new ActiveXObject("Microsoft.XMLHTTP");
- }
-}
-
</del><ins>+var result;
</ins><span class="cx"> xhr.onreadystatechange = function() {
</span><span class="cx"> var rState = this.readyState;
</span><del>- // We expect an INVALID_STATE_ERR exception for readyState < 2
- // and no exception for readyState >= 2
- try {
- var header = this.getResponseHeader(headerName);
- if (rState != this.readyState)
- log3("UNCERTAIN", rState, "readyState changed while getting the header.");
- if (rState < 2) {
- log3("FAILED", rState, headerName + "=" + header);
- } else if (header) {
- if (savedHeader)
- if (savedHeader != header) {
- log3("FAILED", rState,headerName + " changed after it was first returned. Previous " + headerName
- + "=" + savedHeader + "; New " + headerName + "=" + header + ".");
- savedHeader = header;
- }
- else //savedHeader == header here; no need to reprint header
- log3("PASSED", rState, headerName);
- else {//first header value retrieved
- if (window.testRunner)
-//do not print the header's value for automated tests to avoid false failures.
- log3("PASSED", rState, "ResponseHeader(" + headerName + ") returned a value.");
- else
- log3("PASSED", rState, "getResponseHeader(" + headerName + ") returned: " + header + ".");
- savedHeader = header;
- }
- for (var i=0;i<nullTests.length;++i) {
- try {
- var str = this.getResponseHeader(nullTests[i]);
- if (str == null)
- log4("PASSED", rState, nullTests[i], "getResponseHeader(" + nullTests[i] +
- ") returned null.");
- else
- log4("FAILED", rState, nullTests[i], "getResponseHeader(" + nullTests[i] +
- ") returned \"" + str + "\"");
- } catch(e) {
- log4("FAILED", rState, nullTests[i], "getResponseHeader(" + nullTests[i] + ") threw exception:" + e);
- }
- }
- }
- else //header is null
- log3("FAILED", rState, "null " + headerName + " returned.");
- } catch (e) {
- if (rState < 2)
- log3("PASSED", rState, "exception thrown");
</del><ins>+ result = testGetResponseHeader(this, headerName, rState <= XMLHttpRequest.OPENED);
+ if (result) {
+ if (savedHeader)
+ shouldBe("result", "savedHeader");
+
+ savedHeader = result;
+
+ for (var i = 0; i < nullTests.length; ++i)
+ testGetResponseHeader(this, nullTests[i], true);
+ } else {
+ if (rState > XMLHttpRequest.OPENED)
+ testFailed("In ready state " + rState + ", unexpected null value for '" + headerName + "'.");
+ else if (result !== null)
+ testFailed("In ready state " + rState + ", expected null for '" + headerName + ", got: " + JSON.stringify(result) + ".");
</ins><span class="cx"> else
</span><del>- log3("FAILED", rState, "exception thrown: " + e.message + ".");
</del><ins>+ testPassed("Header '" + headerName + "' is null in ready state " + rState + ".");
</ins><span class="cx"> }
</span><del>- if ((rState == 4) && (window.testRunner))
- testRunner.notifyDone();
-}
</del><span class="cx">
</span><del>-if (window.testRunner) {
- testRunner.waitUntilDone();
- testRunner.dumpAsText();
</del><ins>+ if (rState == XMLHttpRequest.DONE)
+ finishJSTest();
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-function test() {
</del><ins>+function runTest() {
</ins><span class="cx"> // Test for readyState = 0
</span><del>- try {
- var header = xhr.getResponseHeader(headerName);
- log3("FAILED", xhr.readyState, headerName + "=" + header + ".");
- } catch (e) {
- log3("PASSED", xhr.readyState, "exception thrown.");
- }
- try {
- xhr.open("GET","resources/1251.html", true);
- xhr.send(null);
- } catch(e) {
- log3("FAILED", "open/send", "exception thrown: " + e.message +".");
- if (window.testRunner)
- testRunner.notifyDone();
- }
</del><ins>+ testGetResponseHeader(xhr, headerName, true);
+ shouldNotThrow('xhr.open("GET", "resources/1251.html", true);');
+ // Test for readyState = 1
+ testGetResponseHeader(xhr, headerName, true);
+ shouldNotThrow("xhr.send(null);");
</ins><span class="cx"> }
</span><ins>+runTest();
</ins><span class="cx"> </script>
</span><ins>+<script src="/js-test-resources/js-test-post.js"></script>
</ins><span class="cx"> </head>
</span><del>-<body onload="test()">
-
-<p>Test page for <a href="http://bugs.webkit.org/show_bug.cgi?id=15356">bug
-15356</a>
-and <a href="http://bugs.webkit.org/show_bug.cgi?id=29121">bug 29121</a></p>
-<p>Assertion: Invoking the getResponseHeader method when readyState >= 2
-(HEADERS_RECEIVED) returns a header value if the header exists.</p>
-<p>Assertion: Invoking the getResponseHeader method with the parameter
- satisfying the following conditions causes getResponseHeader
- to return null:
-<li>1a. The parameter case-insensitively matches Set-Cookie;</li>
-<li>1b. The parameter case-insensitively matches Set-Cookie2;</li>
-<li>2. The parameter does not match any header in the response;</li>
-<li>3a. The parameter is null (it is not a valid header name);</li>
-<li>3b. The parameter is "Content-Type:" (it is not a valid header name).</li>
-
-<script>
- if (!window.testRunner)
- document.write("<p>If the test passes one should see \
-below the ruler the text \"passed\" in all capital letters, once for every ready state &lt; 2, \
-followed each time by a space and the readyState number and 6 times for every ready state >= 2.</p>\n\
-<p>ReadyState numbers should be in ascending order 0 to 4.</p>\n\
-<p>ReadyState numbers should be followed by a blank, the name of the header tested, colon a space and a message.</p>\
-<p>The value of the " + headerName + " header should be printed for ready state 2.</p>");
-</script>
- <hr>
- <p><ol id=console></ol></p>
-</body>
</del><span class="cx"> </html>
</span></span></pre></div>
<a id="trunkLayoutTestshttptestsxmlhttprequestresponseaccessonerrorexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/http/tests/xmlhttprequest/response-access-on-error-expected.txt (0 => 163022)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/http/tests/xmlhttprequest/response-access-on-error-expected.txt         (rev 0)
+++ trunk/LayoutTests/http/tests/xmlhttprequest/response-access-on-error-expected.txt        2014-01-29 17:03:59 UTC (rev 163022)
</span><span class="lines">@@ -0,0 +1,5 @@
</span><ins>+XMLHttpRequest: ensure that response getters properly handle error cases (see bug 125840)
+
+PASS error test
+PASS abort test
+
</ins></span></pre></div>
<a id="trunkLayoutTestshttptestsxmlhttprequestresponseaccessonerrorhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/http/tests/xmlhttprequest/response-access-on-error.html (0 => 163022)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/http/tests/xmlhttprequest/response-access-on-error.html         (rev 0)
+++ trunk/LayoutTests/http/tests/xmlhttprequest/response-access-on-error.html        2014-01-29 17:03:59 UTC (rev 163022)
</span><span class="lines">@@ -0,0 +1,51 @@
</span><ins>+<!DOCTYPE html>
+<html>
+<head>
+ <title>XMLHttpRequest: ensure that response getters properly handle error cases</title>
+ <script src="/js-test-resources/testharness.js"></script>
+ <script src="/js-test-resources/testharnessreport.js"></script>
+</head>
+
+<body>
+ <div>XMLHttpRequest: ensure that response getters properly handle error cases (see <a href="https://bugs.webkit.org/show_bug.cgi?id=125840">bug 125840</a>)</div>
+ <div id="log"></div>
+
+ <script type="text/javascript">
+ // These two tests check response getters when error flag is set and state is DONE
+ var test1 = async_test("error test")
+ test1.step(function() {
+
+ var xhr = new XMLHttpRequest()
+ xhr.onerror = test1.step_func(function(e)
+ {
+ assert_response(xhr)
+ test1.done()
+ })
+ xhr.open("GET", "resources/infinite-loop.php", true)
+ xhr.send("")
+ })
+
+ var test2 = async_test("abort test")
+ test2.step(function() {
+ var xhr = new XMLHttpRequest()
+ xhr.upload.onloadend = function(e) {
+ xhr.abort()
+ }
+ xhr.onreadystatechange = test2.step_func(function(e) {
+ if (xhr.readyState == xhr.DONE) {
+ assert_response(xhr)
+ test2.done()
+ }
+ })
+ xhr.open("POST", "resources/post-echo.cgi", true)
+ xhr.setRequestHeader("Content-Type","text/plain")
+ xhr.send("data")
+ })
+
+ function assert_response(xhr) {
+ assert_equals(xhr.getAllResponseHeaders().trim(), "", "getAllResponseHeaders should return the empty string")
+ assert_equals(xhr.getResponseHeader("Content-Type"), null, "getResponseHeader should return null")
+ }
+ </script>
+</body>
+</html>
</ins></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (163021 => 163022)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2014-01-29 16:26:31 UTC (rev 163021)
+++ trunk/Source/WebCore/ChangeLog        2014-01-29 17:03:59 UTC (rev 163022)
</span><span class="lines">@@ -1,3 +1,22 @@
</span><ins>+2014-01-29 Youenn Fablet <youennf@gmail.com>
+
+ Have XHR.getResponseHeader() return null and XHR.getAllResponseHeader() return the empty string in initial ready states
+ https://bugs.webkit.org/show_bug.cgi?id=125840
+
+ Reviewed by Alexey Proskuryakov.
+
+ Merging https://chromium.googlesource.com/chromium/blink/+/d201caf874a0bd6f101f517462b3cf1d8c5fce3d
+ This patch makes it clear that null/empty string is returned whenever the error flag is set.
+ This new code path is covered by the added test.
+
+ Test: http/tests/xmlhttprequest/response-access-on-error.html
+
+ * xml/XMLHttpRequest.cpp:
+ (WebCore::XMLHttpRequest::getAllResponseHeaders):
+ (WebCore::XMLHttpRequest::getResponseHeader):
+ * xml/XMLHttpRequest.h:
+ * xml/XMLHttpRequest.idl:
+
</ins><span class="cx"> 2014-01-29 Antti Koivisto <antti@apple.com>
</span><span class="cx">
</span><span class="cx"> REGRESSION (r162947): Repaint test results are different between WK1 and WK2
</span></span></pre></div>
<a id="trunkSourceWebCorexmlXMLHttpRequestcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/xml/XMLHttpRequest.cpp (163021 => 163022)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/xml/XMLHttpRequest.cpp        2014-01-29 16:26:31 UTC (rev 163021)
+++ trunk/Source/WebCore/xml/XMLHttpRequest.cpp        2014-01-29 17:03:59 UTC (rev 163022)
</span><span class="lines">@@ -986,12 +986,10 @@
</span><span class="cx"> return m_requestHeaders.get(name);
</span><span class="cx"> }
</span><span class="cx">
</span><del>-String XMLHttpRequest::getAllResponseHeaders(ExceptionCode& ec) const
</del><ins>+String XMLHttpRequest::getAllResponseHeaders() const
</ins><span class="cx"> {
</span><del>- if (m_state < HEADERS_RECEIVED) {
- ec = INVALID_STATE_ERR;
</del><ins>+ if (m_state < HEADERS_RECEIVED || m_error)
</ins><span class="cx"> return "";
</span><del>- }
</del><span class="cx">
</span><span class="cx"> StringBuilder stringBuilder;
</span><span class="cx">
</span><span class="lines">@@ -1022,12 +1020,10 @@
</span><span class="cx"> return stringBuilder.toString();
</span><span class="cx"> }
</span><span class="cx">
</span><del>-String XMLHttpRequest::getResponseHeader(const AtomicString& name, ExceptionCode& ec) const
</del><ins>+String XMLHttpRequest::getResponseHeader(const AtomicString& name) const
</ins><span class="cx"> {
</span><del>- if (m_state < HEADERS_RECEIVED) {
- ec = INVALID_STATE_ERR;
</del><ins>+ if (m_state < HEADERS_RECEIVED || m_error)
</ins><span class="cx"> return String();
</span><del>- }
</del><span class="cx">
</span><span class="cx"> // See comment in getAllResponseHeaders above.
</span><span class="cx"> if (isSetCookieHeader(name) && !securityOrigin()->canLoadLocalResources()) {
</span></span></pre></div>
<a id="trunkSourceWebCorexmlXMLHttpRequesth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/xml/XMLHttpRequest.h (163021 => 163022)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/xml/XMLHttpRequest.h        2014-01-29 16:26:31 UTC (rev 163021)
+++ trunk/Source/WebCore/xml/XMLHttpRequest.h        2014-01-29 17:03:59 UTC (rev 163022)
</span><span class="lines">@@ -105,8 +105,8 @@
</span><span class="cx"> void setRequestHeader(const AtomicString& name, const String& value, ExceptionCode&);
</span><span class="cx"> void overrideMimeType(const String& override);
</span><span class="cx"> bool doneWithoutErrors() const { return !m_error && m_state == DONE; }
</span><del>- String getAllResponseHeaders(ExceptionCode&) const;
- String getResponseHeader(const AtomicString& name, ExceptionCode&) const;
</del><ins>+ String getAllResponseHeaders() const;
+ String getResponseHeader(const AtomicString& name) const;
</ins><span class="cx"> String responseText(ExceptionCode&);
</span><span class="cx"> String responseTextIgnoringResponseType() const { return m_responseBuilder.toStringPreserveCapacity(); }
</span><span class="cx"> Document* responseXML(ExceptionCode&);
</span></span></pre></div>
<a id="trunkSourceWebCorexmlXMLHttpRequestidl"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/xml/XMLHttpRequest.idl (163021 => 163022)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/xml/XMLHttpRequest.idl        2014-01-29 16:26:31 UTC (rev 163021)
+++ trunk/Source/WebCore/xml/XMLHttpRequest.idl        2014-01-29 17:03:59 UTC (rev 163022)
</span><span class="lines">@@ -80,8 +80,8 @@
</span><span class="cx"> readonly attribute XMLHttpRequestUpload upload;
</span><span class="cx">
</span><span class="cx"> // response
</span><del>- [TreatReturnedNullStringAs=Undefined, RaisesException] DOMString getAllResponseHeaders();
- [TreatReturnedNullStringAs=Null, RaisesException] DOMString getResponseHeader(DOMString header);
</del><ins>+ [TreatReturnedNullStringAs=Undefined] DOMString getAllResponseHeaders();
+ [TreatReturnedNullStringAs=Null] DOMString getResponseHeader(DOMString header);
</ins><span class="cx"> [GetterRaisesException, CustomGetter] readonly attribute DOMString responseText; // The custom getter implements TreatReturnedNullStringAs=Null
</span><span class="cx"> [GetterRaisesException] readonly attribute Document responseXML;
</span><span class="cx">
</span></span></pre>
</div>
</div>
</body>
</html>