<!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>[203494] 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/203494">203494</a></dd>
<dt>Author</dt> <dd>commit-queue@webkit.org</dd>
<dt>Date</dt> <dd>2016-07-20 23:51:05 -0700 (Wed, 20 Jul 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>[XHR] Cache response JS object in case of arraybuffer and blob response types
https://bugs.webkit.org/show_bug.cgi?id=128903

Patch by Youenn Fablet &lt;youenn@apple.com&gt; on 2016-07-20
Reviewed by Alex Christensen.

Source/WebCore:

Covered by existing and modified tests.

Making response getter a JS builtin that caches response in @response private slot.
Handling invalidation of cached response with @responseCacheIsValid new private method.
Handling creation of cached response with @retrieveResponse new private method which reuses most of
JSXMLHttpRequest::response previous code.

Caching of responses is activated whenever load ended without any error for blob and arraybuffer response types.

Caching of response for document is also activated in case the response getter is used but not if responseXML getter is used.

* CMakeLists.txt: Adding XMLHttpRequest.js.
* DerivedSources.make: Ditto.
* bindings/js/JSXMLHttpRequestCustom.cpp:
(WebCore::JSXMLHttpRequest::retrieveResponse): Implements creation of to-be-cached response.
(WebCore::JSXMLHttpRequest::response): Deleted.
* bindings/js/WebCoreBuiltinNames.h: Adding new private names.
* xml/XMLHttpRequest.cpp:
(WebCore::XMLHttpRequest::didCacheResponse): Renamed from didCacheResponseJSON as all response types are now cached.
(WebCore::XMLHttpRequest::didCacheResponseJSON): Deleted.
* xml/XMLHttpRequest.h:
* xml/XMLHttpRequest.idl:

LayoutTests:

* http/tests/xmlhttprequest/onabort-response-getters-expected.txt:
* http/tests/xmlhttprequest/onabort-response-getters.html:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestshttptestsxmlhttprequestonabortresponsegettersexpectedtxt">trunk/LayoutTests/http/tests/xmlhttprequest/onabort-response-getters-expected.txt</a></li>
<li><a href="#trunkLayoutTestshttptestsxmlhttprequestonabortresponsegettershtml">trunk/LayoutTests/http/tests/xmlhttprequest/onabort-response-getters.html</a></li>
<li><a href="#trunkSourceWebCoreCMakeListstxt">trunk/Source/WebCore/CMakeLists.txt</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreDerivedSourcesmake">trunk/Source/WebCore/DerivedSources.make</a></li>
<li><a href="#trunkSourceWebCorebindingsjsJSXMLHttpRequestCustomcpp">trunk/Source/WebCore/bindings/js/JSXMLHttpRequestCustom.cpp</a></li>
<li><a href="#trunkSourceWebCorebindingsjsWebCoreBuiltinNamesh">trunk/Source/WebCore/bindings/js/WebCoreBuiltinNames.h</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="#trunkSourceWebCorexmlXMLHttpRequestjs">trunk/Source/WebCore/xml/XMLHttpRequest.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (203493 => 203494)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2016-07-21 06:41:43 UTC (rev 203493)
+++ trunk/LayoutTests/ChangeLog        2016-07-21 06:51:05 UTC (rev 203494)
</span><span class="lines">@@ -1,3 +1,13 @@
</span><ins>+2016-07-20  Youenn Fablet  &lt;youenn@apple.com&gt;
+
+        [XHR] Cache response JS object in case of arraybuffer and blob response types
+        https://bugs.webkit.org/show_bug.cgi?id=128903
+
+        Reviewed by Alex Christensen.
+
+        * http/tests/xmlhttprequest/onabort-response-getters-expected.txt:
+        * http/tests/xmlhttprequest/onabort-response-getters.html:
+
</ins><span class="cx"> 2016-07-19  Filip Pizlo  &lt;fpizlo@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Switching on symbols should be fast
</span></span></pre></div>
<a id="trunkLayoutTestshttptestsxmlhttprequestonabortresponsegettersexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/http/tests/xmlhttprequest/onabort-response-getters-expected.txt (203493 => 203494)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/http/tests/xmlhttprequest/onabort-response-getters-expected.txt        2016-07-21 06:41:43 UTC (rev 203493)
+++ trunk/LayoutTests/http/tests/xmlhttprequest/onabort-response-getters-expected.txt        2016-07-21 06:51:05 UTC (rev 203494)
</span><span class="lines">@@ -1,6 +1,12 @@
</span><span class="cx"> 
</span><span class="cx"> PASS getting arraybuffer response within abort event callback 
</span><ins>+PASS getting arraybuffer response within abort event callback (aborting in loadend) 
</ins><span class="cx"> PASS getting blob response within abort event callback 
</span><ins>+PASS getting blob response within abort event callback (aborting in loadend) 
</ins><span class="cx"> PASS getting json response within abort event callback 
</span><ins>+PASS getting json response within abort event callback (aborting in loadend) 
</ins><span class="cx"> PASS getting document response within abort event callback 
</span><ins>+PASS getting document response within abort event callback (aborting in loadend) 
+PASS getting text response within abort event callback 
+PASS getting text response within abort event callback (aborting in loadend) 
</ins><span class="cx"> 
</span></span></pre></div>
<a id="trunkLayoutTestshttptestsxmlhttprequestonabortresponsegettershtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/http/tests/xmlhttprequest/onabort-response-getters.html (203493 => 203494)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/http/tests/xmlhttprequest/onabort-response-getters.html        2016-07-21 06:41:43 UTC (rev 203493)
+++ trunk/LayoutTests/http/tests/xmlhttprequest/onabort-response-getters.html        2016-07-21 06:51:05 UTC (rev 203494)
</span><span class="lines">@@ -7,6 +7,14 @@
</span><span class="cx">   &lt;body&gt;
</span><span class="cx">     &lt;div id=&quot;log&quot;&gt;&lt;/div&gt;
</span><span class="cx">     &lt;script&gt;
</span><ins>+    function checkCachedResponse(client) {
+        assert_true(client.response === client.response);
+        if (client.responseType == &quot;text&quot;)
+            assert_true(client.responseText === client.response);
+        if (client.responseType == &quot;document&quot;)
+            assert_true(client.responseXML === client.response);
+    }
+
</ins><span class="cx">     function runTest(name, fileName, mimeType, setupClient, checkResponse) {
</span><span class="cx">       var test = async_test(name)
</span><span class="cx">       test.step(function() {
</span><span class="lines">@@ -28,6 +36,7 @@
</span><span class="cx">             if (client.readyState == 4) {
</span><span class="cx">                 checkResponse(test, client)
</span><span class="cx">                 client.isResponseChecked = true
</span><ins>+                checkCachedResponse(client);
</ins><span class="cx">             }
</span><span class="cx">         })
</span><span class="cx"> 
</span><span class="lines">@@ -38,10 +47,29 @@
</span><span class="cx">         client.onloadend = test.step_func(function () {
</span><span class="cx">             assert_true(client.hasAborted, &quot;xhr should have aborted&quot;)
</span><span class="cx">             assert_true(client.isResponseChecked, &quot;xhr response should have been checked&quot;)
</span><ins>+            checkCachedResponse(client);
</ins><span class="cx">             test.done()
</span><span class="cx">         })
</span><span class="cx">         client.send(null)
</span><span class="cx">       })
</span><ins>+
+      var test2 = async_test(name + &quot; (aborting in loadend)&quot;)
+      test2.step(function() {
+        var client = new XMLHttpRequest()
+        var url = &quot;/resources/load-then-wait.cgi?name=../xmlhttprequest/&quot; + fileName + &quot;&amp;waitFor=1&amp;mimeType=&quot; + mimeType
+        client.open(&quot;GET&quot;, url, true)
+        setupClient(test2, client)
+
+        client.onloadend = test2.step_func(function () {
+            assert_true(client.response != null);
+            checkCachedResponse(client);
+            client.abort();
+            checkResponse(test2, client);
+            checkCachedResponse(client);
+            test2.done();
+        })
+        client.send(null)
+      })
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     runTest(&quot;getting arraybuffer response within abort event callback&quot;,
</span><span class="lines">@@ -68,6 +96,12 @@
</span><span class="cx">         function(test, client) {assert_true(client.response == null, &quot;document response must be empty&quot;)}
</span><span class="cx">     )
</span><span class="cx"> 
</span><ins>+    runTest(&quot;getting text response within abort event callback&quot;,
+        &quot;resources/test.json&quot;,&quot;text/plain&quot;,
+        function(test, client) {client.responseType = &quot;text&quot;},
+        function(test, client) {assert_true(client.response == &quot;&quot;, &quot;text response must be an empty string&quot;)}
+    )
+
</ins><span class="cx">     &lt;/script&gt;
</span><span class="cx">   &lt;/body&gt;
</span><span class="cx"> &lt;/html&gt;
</span></span></pre></div>
<a id="trunkSourceWebCoreCMakeListstxt"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/CMakeLists.txt (203493 => 203494)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/CMakeLists.txt        2016-07-21 06:41:43 UTC (rev 203493)
+++ trunk/Source/WebCore/CMakeLists.txt        2016-07-21 06:51:05 UTC (rev 203494)
</span><span class="lines">@@ -3726,6 +3726,7 @@
</span><span class="cx">     ${WEBCORE_DIR}/Modules/streams/StreamInternals.js
</span><span class="cx">     ${WEBCORE_DIR}/Modules/streams/WritableStream.js
</span><span class="cx">     ${WEBCORE_DIR}/Modules/streams/WritableStreamInternals.js
</span><ins>+    ${WEBCORE_DIR}/xml/XMLHttpRequest.js
</ins><span class="cx"> )
</span><span class="cx"> 
</span><span class="cx"> set(BUILTINS_GENERATOR_SCRIPTS
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (203493 => 203494)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-07-21 06:41:43 UTC (rev 203493)
+++ trunk/Source/WebCore/ChangeLog        2016-07-21 06:51:05 UTC (rev 203494)
</span><span class="lines">@@ -1,5 +1,35 @@
</span><span class="cx"> 2016-07-20  Youenn Fablet  &lt;youenn@apple.com&gt;
</span><span class="cx"> 
</span><ins>+        [XHR] Cache response JS object in case of arraybuffer and blob response types
+        https://bugs.webkit.org/show_bug.cgi?id=128903
+
+        Reviewed by Alex Christensen.
+
+        Covered by existing and modified tests.
+
+        Making response getter a JS builtin that caches response in @response private slot.
+        Handling invalidation of cached response with @responseCacheIsValid new private method.
+        Handling creation of cached response with @retrieveResponse new private method which reuses most of
+        JSXMLHttpRequest::response previous code.
+
+        Caching of responses is activated whenever load ended without any error for blob and arraybuffer response types.
+
+        Caching of response for document is also activated in case the response getter is used but not if responseXML getter is used.
+
+        * CMakeLists.txt: Adding XMLHttpRequest.js.
+        * DerivedSources.make: Ditto.
+        * bindings/js/JSXMLHttpRequestCustom.cpp:
+        (WebCore::JSXMLHttpRequest::retrieveResponse): Implements creation of to-be-cached response.
+        (WebCore::JSXMLHttpRequest::response): Deleted.
+        * bindings/js/WebCoreBuiltinNames.h: Adding new private names.
+        * xml/XMLHttpRequest.cpp:
+        (WebCore::XMLHttpRequest::didCacheResponse): Renamed from didCacheResponseJSON as all response types are now cached.
+        (WebCore::XMLHttpRequest::didCacheResponseJSON): Deleted.
+        * xml/XMLHttpRequest.h:
+        * xml/XMLHttpRequest.idl:
+
+2016-07-20  Youenn Fablet  &lt;youenn@apple.com&gt;
+
</ins><span class="cx">         Remove crossOriginRequestPolicy from ThreadableLoaderOptions
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=159417
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreDerivedSourcesmake"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/DerivedSources.make (203493 => 203494)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/DerivedSources.make        2016-07-21 06:41:43 UTC (rev 203493)
+++ trunk/Source/WebCore/DerivedSources.make        2016-07-21 06:51:05 UTC (rev 203494)
</span><span class="lines">@@ -1299,6 +1299,7 @@
</span><span class="cx">     $(WebCore)/Modules/streams/StreamInternals.js \
</span><span class="cx">     $(WebCore)/Modules/streams/WritableStream.js \
</span><span class="cx">     $(WebCore)/Modules/streams/WritableStreamInternals.js \
</span><ins>+    $(WebCore)/xml/XMLHttpRequest.js \
</ins><span class="cx"> #
</span><span class="cx"> 
</span><span class="cx"> BUILTINS_GENERATOR_SCRIPTS = \
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsJSXMLHttpRequestCustomcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/JSXMLHttpRequestCustom.cpp (203493 => 203494)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/JSXMLHttpRequestCustom.cpp        2016-07-21 06:41:43 UTC (rev 203493)
+++ trunk/Source/WebCore/bindings/js/JSXMLHttpRequestCustom.cpp        2016-07-21 06:51:05 UTC (rev 203494)
</span><span class="lines">@@ -63,12 +63,6 @@
</span><span class="cx"> 
</span><span class="cx">     if (Document* responseDocument = wrapped().optionalResponseXML())
</span><span class="cx">         visitor.addOpaqueRoot(responseDocument);
</span><del>-
-    if (ArrayBuffer* responseArrayBuffer = wrapped().optionalResponseArrayBuffer())
-        visitor.addOpaqueRoot(responseArrayBuffer);
-
-    if (Blob* responseBlob = wrapped().optionalResponseBlob())
-        visitor.addOpaqueRoot(responseBlob);
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> class SendFunctor {
</span><span class="lines">@@ -151,12 +145,8 @@
</span><span class="cx">     return jsOwnedStringOrNull(&amp;state, text);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-JSValue JSXMLHttpRequest::response(ExecState&amp; state) const
</del><ins>+JSValue JSXMLHttpRequest::retrieveResponse(ExecState&amp; state)
</ins><span class="cx"> {
</span><del>-    // FIXME: Use CachedAttribute for other types than JSON as well.
-    if (m_response &amp;&amp; wrapped().responseCacheIsValid())
-        return m_response.get();
-
</del><span class="cx">     auto type = wrapped().responseType();
</span><span class="cx"> 
</span><span class="cx">     switch (type) {
</span><span class="lines">@@ -170,42 +160,36 @@
</span><span class="cx">     if (!wrapped().doneWithoutErrors())
</span><span class="cx">         return jsNull();
</span><span class="cx"> 
</span><ins>+    JSValue value;
</ins><span class="cx">     switch (type) {
</span><span class="cx">     case XMLHttpRequest::ResponseType::EmptyString:
</span><span class="cx">     case XMLHttpRequest::ResponseType::Text:
</span><span class="cx">         ASSERT_NOT_REACHED();
</span><del>-        break;
</del><ins>+        return jsUndefined();
</ins><span class="cx"> 
</span><span class="cx">     case XMLHttpRequest::ResponseType::Json:
</span><del>-        {
-            JSValue value = JSONParse(&amp;state, wrapped().responseTextIgnoringResponseType());
-            if (!value)
-                value = jsNull();
-            m_response.set(state.vm(), this, value);
-            wrapped().didCacheResponseJSON();
-            return value;
-        }
</del><ins>+        value = JSONParse(&amp;state, wrapped().responseTextIgnoringResponseType());
+        if (!value)
+            value = jsNull();
+        break;
</ins><span class="cx"> 
</span><del>-    case XMLHttpRequest::ResponseType::Document:
-        {
-            ExceptionCode ec = 0;
-            Document* document = wrapped().responseXML(ec);
-            if (ec) {
-                setDOMException(&amp;state, ec);
-                return jsUndefined();
-            }
-            return toJS(&amp;state, globalObject(), document);
-        }
-
</del><ins>+    case XMLHttpRequest::ResponseType::Document: {
+        ExceptionCode ec = 0;
+        auto document = wrapped().responseXML(ec);
+        ASSERT(!ec);
+        value = toJS(&amp;state, globalObject(), document);
+        break;
+    }
</ins><span class="cx">     case XMLHttpRequest::ResponseType::Blob:
</span><del>-        return toJS(&amp;state, globalObject(), wrapped().responseBlob());
</del><ins>+        value = toJSNewlyCreated(&amp;state, globalObject(), wrapped().createResponseBlob());
+        break;
</ins><span class="cx"> 
</span><span class="cx">     case XMLHttpRequest::ResponseType::Arraybuffer:
</span><del>-        return toJS(&amp;state, globalObject(), wrapped().responseArrayBuffer());
</del><ins>+        value = toJS(&amp;state, globalObject(), wrapped().createResponseArrayBuffer());
+        break;
</ins><span class="cx">     }
</span><del>-
-    ASSERT_NOT_REACHED();
-    return jsUndefined();
</del><ins>+    wrapped().didCacheResponse();
+    return value;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsWebCoreBuiltinNamesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/WebCoreBuiltinNames.h (203493 => 203494)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/WebCoreBuiltinNames.h        2016-07-21 06:41:43 UTC (rev 203493)
+++ trunk/Source/WebCore/bindings/js/WebCoreBuiltinNames.h        2016-07-21 06:51:05 UTC (rev 203494)
</span><span class="lines">@@ -62,6 +62,9 @@
</span><span class="cx">     macro(readRequests) \
</span><span class="cx">     macro(readyPromiseCapability) \
</span><span class="cx">     macro(removeTrack) \
</span><ins>+    macro(responseCacheIsValid) \
+    macro(retrieveResponse) \
+    macro(response) \
</ins><span class="cx">     macro(setStatus) \
</span><span class="cx">     macro(state) \
</span><span class="cx">     macro(started) \
</span><span class="lines">@@ -85,6 +88,7 @@
</span><span class="cx">     macro(ReadableStreamController) \
</span><span class="cx">     macro(RTCIceCandidate) \
</span><span class="cx">     macro(RTCSessionDescription) \
</span><ins>+    macro(XMLHttpRequest)
</ins><span class="cx"> 
</span><span class="cx"> class WebCoreBuiltinNames {
</span><span class="cx"> public:
</span></span></pre></div>
<a id="trunkSourceWebCorexmlXMLHttpRequestcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/xml/XMLHttpRequest.cpp (203493 => 203494)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/xml/XMLHttpRequest.cpp        2016-07-21 06:41:43 UTC (rev 203493)
+++ trunk/Source/WebCore/xml/XMLHttpRequest.cpp        2016-07-21 06:51:05 UTC (rev 203494)
</span><span class="lines">@@ -171,9 +171,8 @@
</span><span class="cx">     return responseTextIgnoringResponseType();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void XMLHttpRequest::didCacheResponseJSON()
</del><ins>+void XMLHttpRequest::didCacheResponse()
</ins><span class="cx"> {
</span><del>-    ASSERT(m_responseType == ResponseType::Json);
</del><span class="cx">     ASSERT(doneWithoutErrors());
</span><span class="cx">     m_responseCacheIsValid = true;
</span><span class="cx">     m_responseBuilder.clear();
</span><span class="lines">@@ -218,42 +217,30 @@
</span><span class="cx">     return m_responseDocument.get();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-Blob* XMLHttpRequest::responseBlob()
</del><ins>+Ref&lt;Blob&gt; XMLHttpRequest::createResponseBlob()
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(m_responseType == ResponseType::Blob);
</span><span class="cx">     ASSERT(doneWithoutErrors());
</span><span class="cx"> 
</span><del>-    if (!m_responseBlob) {
-        if (m_binaryResponseBuilder) {
-            // FIXME: We just received the data from NetworkProcess, and are sending it back. This is inefficient.
-            Vector&lt;uint8_t&gt; data;
-            data.append(m_binaryResponseBuilder-&gt;data(), m_binaryResponseBuilder-&gt;size());
-            String normalizedContentType = Blob::normalizedContentType(responseMIMEType()); // responseMIMEType defaults to text/xml which may be incorrect.
-            m_responseBlob = Blob::create(WTFMove(data), normalizedContentType);
-            m_binaryResponseBuilder = nullptr;
-        } else {
-            // If we errored out or got no data, we still return a blob, just an empty one.
-            m_responseBlob = Blob::create();
-        }
-    }
</del><ins>+    if (!m_binaryResponseBuilder)
+        return Blob::create();
</ins><span class="cx"> 
</span><del>-    return m_responseBlob.get();
</del><ins>+    // FIXME: We just received the data from NetworkProcess, and are sending it back. This is inefficient.
+    Vector&lt;uint8_t&gt; data;
+    data.append(m_binaryResponseBuilder-&gt;data(), m_binaryResponseBuilder-&gt;size());
+    m_binaryResponseBuilder = nullptr;
+    String normalizedContentType = Blob::normalizedContentType(responseMIMEType()); // responseMIMEType defaults to text/xml which may be incorrect.
+    return Blob::create(WTFMove(data), normalizedContentType);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-ArrayBuffer* XMLHttpRequest::responseArrayBuffer()
</del><ins>+RefPtr&lt;ArrayBuffer&gt; XMLHttpRequest::createResponseArrayBuffer()
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(m_responseType == ResponseType::Arraybuffer);
</span><span class="cx">     ASSERT(doneWithoutErrors());
</span><span class="cx"> 
</span><del>-    if (!m_responseArrayBuffer) {
-        if (m_binaryResponseBuilder)
-            m_responseArrayBuffer = m_binaryResponseBuilder-&gt;createArrayBuffer();
-        else
-            m_responseArrayBuffer = ArrayBuffer::create(nullptr, 0);
-        m_binaryResponseBuilder = nullptr;
-    }
-
-    return m_responseArrayBuffer.get();
</del><ins>+    auto result = m_binaryResponseBuilder ? m_binaryResponseBuilder-&gt;createArrayBuffer() : ArrayBuffer::create(nullptr, 0);
+    m_binaryResponseBuilder = nullptr;
+    return result;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void XMLHttpRequest::setTimeout(unsigned timeout, ExceptionCode&amp; ec)
</span><span class="lines">@@ -819,9 +806,7 @@
</span><span class="cx">     m_responseEncoding = String();
</span><span class="cx">     m_createdDocument = false;
</span><span class="cx">     m_responseDocument = nullptr;
</span><del>-    m_responseBlob = nullptr;
</del><span class="cx">     m_binaryResponseBuilder = nullptr;
</span><del>-    m_responseArrayBuffer = nullptr;
</del><span class="cx">     m_responseCacheIsValid = false;
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorexmlXMLHttpRequesth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/xml/XMLHttpRequest.h (203493 => 203494)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/xml/XMLHttpRequest.h        2016-07-21 06:41:43 UTC (rev 203493)
+++ trunk/Source/WebCore/xml/XMLHttpRequest.h        2016-07-21 06:51:05 UTC (rev 203494)
</span><span class="lines">@@ -88,15 +88,18 @@
</span><span class="cx">     String responseText(ExceptionCode&amp;);
</span><span class="cx">     String responseTextIgnoringResponseType() const { return m_responseBuilder.toStringPreserveCapacity(); }
</span><span class="cx">     String responseMIMEType() const;
</span><ins>+
+    Document* optionalResponseXML() const { return m_responseDocument.get(); }
</ins><span class="cx">     Document* responseXML(ExceptionCode&amp;);
</span><del>-    Document* optionalResponseXML() const { return m_responseDocument.get(); }
-    Blob* responseBlob();
-    Blob* optionalResponseBlob() const { return m_responseBlob.get(); }
</del><ins>+
+    Ref&lt;Blob&gt; createResponseBlob();
+    RefPtr&lt;JSC::ArrayBuffer&gt; createResponseArrayBuffer();
+
</ins><span class="cx">     unsigned timeout() const { return m_timeoutMilliseconds; }
</span><span class="cx">     void setTimeout(unsigned timeout, ExceptionCode&amp;);
</span><span class="cx"> 
</span><span class="cx">     bool responseCacheIsValid() const { return m_responseCacheIsValid; }
</span><del>-    void didCacheResponseJSON();
</del><ins>+    void didCacheResponse();
</ins><span class="cx"> 
</span><span class="cx">     // Expose HTTP validation methods for other untrusted requests.
</span><span class="cx">     static bool isAllowedHTTPMethod(const String&amp;);
</span><span class="lines">@@ -109,10 +112,6 @@
</span><span class="cx"> 
</span><span class="cx">     String responseURL() const;
</span><span class="cx"> 
</span><del>-    // response attribute has custom getter.
-    JSC::ArrayBuffer* responseArrayBuffer();
-    JSC::ArrayBuffer* optionalResponseArrayBuffer() const { return m_responseArrayBuffer.get(); }
-
</del><span class="cx">     void setLastSendLineAndColumnNumber(unsigned lineNumber, unsigned columnNumber);
</span><span class="cx">     void setLastSendURL(const String&amp; url) { m_lastSendURL = url; }
</span><span class="cx"> 
</span><span class="lines">@@ -187,7 +186,6 @@
</span><span class="cx">     String m_mimeTypeOverride;
</span><span class="cx">     bool m_async { true };
</span><span class="cx">     bool m_includeCredentials { false };
</span><del>-    RefPtr&lt;Blob&gt; m_responseBlob;
</del><span class="cx"> 
</span><span class="cx">     RefPtr&lt;ThreadableLoader&gt; m_loader;
</span><span class="cx">     State m_state { UNSENT };
</span><span class="lines">@@ -201,9 +199,8 @@
</span><span class="cx">     StringBuilder m_responseBuilder;
</span><span class="cx">     bool m_createdDocument { false };
</span><span class="cx">     RefPtr&lt;Document&gt; m_responseDocument;
</span><del>-    
</del><ins>+
</ins><span class="cx">     RefPtr&lt;SharedBuffer&gt; m_binaryResponseBuilder;
</span><del>-    RefPtr&lt;JSC::ArrayBuffer&gt; m_responseArrayBuffer;
</del><span class="cx"> 
</span><span class="cx">     bool m_error { false };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorexmlXMLHttpRequestidl"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/xml/XMLHttpRequest.idl (203493 => 203494)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/xml/XMLHttpRequest.idl        2016-07-21 06:41:43 UTC (rev 203493)
+++ trunk/Source/WebCore/xml/XMLHttpRequest.idl        2016-07-21 06:51:05 UTC (rev 203494)
</span><span class="lines">@@ -44,6 +44,8 @@
</span><span class="cx">     JSGenerateToNativeObject,
</span><span class="cx">     JSGenerateToJSObject,
</span><span class="cx">     ExportMacro=WEBCORE_EXPORT,
</span><ins>+    PublicIdentifier,
+    PrivateIdentifier,
</ins><span class="cx"> ] interface XMLHttpRequest : XMLHttpRequestEventTarget {
</span><span class="cx">     attribute EventHandler onreadystatechange;
</span><span class="cx"> 
</span><span class="lines">@@ -78,12 +80,15 @@
</span><span class="cx">     [GetterRaisesException] readonly attribute Document responseXML;
</span><span class="cx"> 
</span><span class="cx">     [SetterRaisesException] attribute XMLHttpRequestResponseType responseType;
</span><del>-    [GetterRaisesException, CachedAttribute, CustomGetter] readonly attribute Object response;
</del><ins>+    [JSBuiltin] readonly attribute Object response;
</ins><span class="cx"> 
</span><span class="cx">     readonly attribute unsigned short status;
</span><span class="cx">     readonly attribute DOMString statusText;
</span><span class="cx">     readonly attribute DOMString responseURL;
</span><span class="cx"> 
</span><ins>+    [PrivateIdentifier] boolean responseCacheIsValid();
+    [PrivateIdentifier, Custom] any retrieveResponse();
+
</ins><span class="cx">     // Extension
</span><span class="cx">     [RaisesException] void overrideMimeType(DOMString override);
</span><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceWebCorexmlXMLHttpRequestjs"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/xml/XMLHttpRequest.js (0 => 203494)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/xml/XMLHttpRequest.js                                (rev 0)
+++ trunk/Source/WebCore/xml/XMLHttpRequest.js        2016-07-21 06:51:05 UTC (rev 203494)
</span><span class="lines">@@ -0,0 +1,39 @@
</span><ins>+/*
+ * Copyright (C) 2016 Apple Inc.
+ *
+ * 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. ``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
+ * 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.
+ */
+
+function response()
+{
+    &quot;use strict&quot;;
+
+    // FIXME: Add a helper routine for that kind of checks.
+    if (!(this instanceof @XMLHttpRequest))
+        throw new @TypeError(&quot;The XMLHttpRequest.response getter can only be used on instances of XMLHttpRequest&quot;);
+
+    if (@XMLHttpRequest.prototype.@responseCacheIsValid.@call(this))
+        return this.@response;
+
+    this.@response = @XMLHttpRequest.prototype.@retrieveResponse.@call(this);
+    return this.@response;
+}
</ins></span></pre>
</div>
</div>

</body>
</html>