Changeset 203494 in webkit
- Timestamp:
- Jul 20, 2016, 11:51:05 PM (10 years ago)
- Location:
- trunk
- Files:
-
- 1 added
- 11 edited
-
LayoutTests/ChangeLog (modified) (1 diff)
-
LayoutTests/http/tests/xmlhttprequest/onabort-response-getters-expected.txt (modified) (1 diff)
-
LayoutTests/http/tests/xmlhttprequest/onabort-response-getters.html (modified) (4 diffs)
-
Source/WebCore/CMakeLists.txt (modified) (1 diff)
-
Source/WebCore/ChangeLog (modified) (1 diff)
-
Source/WebCore/DerivedSources.make (modified) (1 diff)
-
Source/WebCore/bindings/js/JSXMLHttpRequestCustom.cpp (modified) (3 diffs)
-
Source/WebCore/bindings/js/WebCoreBuiltinNames.h (modified) (2 diffs)
-
Source/WebCore/xml/XMLHttpRequest.cpp (modified) (3 diffs)
-
Source/WebCore/xml/XMLHttpRequest.h (modified) (4 diffs)
-
Source/WebCore/xml/XMLHttpRequest.idl (modified) (3 diffs)
-
Source/WebCore/xml/XMLHttpRequest.js (added)
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r203491 r203494 1 2016-07-20 Youenn Fablet <youenn@apple.com> 2 3 [XHR] Cache response JS object in case of arraybuffer and blob response types 4 https://bugs.webkit.org/show_bug.cgi?id=128903 5 6 Reviewed by Alex Christensen. 7 8 * http/tests/xmlhttprequest/onabort-response-getters-expected.txt: 9 * http/tests/xmlhttprequest/onabort-response-getters.html: 10 1 11 2016-07-19 Filip Pizlo <fpizlo@apple.com> 2 12 -
trunk/LayoutTests/http/tests/xmlhttprequest/onabort-response-getters-expected.txt
r163527 r203494 1 1 2 2 PASS getting arraybuffer response within abort event callback 3 PASS getting arraybuffer response within abort event callback (aborting in loadend) 3 4 PASS getting blob response within abort event callback 5 PASS getting blob response within abort event callback (aborting in loadend) 4 6 PASS getting json response within abort event callback 7 PASS getting json response within abort event callback (aborting in loadend) 5 8 PASS getting document response within abort event callback 9 PASS getting document response within abort event callback (aborting in loadend) 10 PASS getting text response within abort event callback 11 PASS getting text response within abort event callback (aborting in loadend) 6 12 -
trunk/LayoutTests/http/tests/xmlhttprequest/onabort-response-getters.html
r163527 r203494 8 8 <div id="log"></div> 9 9 <script> 10 function checkCachedResponse(client) { 11 assert_true(client.response === client.response); 12 if (client.responseType == "text") 13 assert_true(client.responseText === client.response); 14 if (client.responseType == "document") 15 assert_true(client.responseXML === client.response); 16 } 17 10 18 function runTest(name, fileName, mimeType, setupClient, checkResponse) { 11 19 var test = async_test(name) … … 29 37 checkResponse(test, client) 30 38 client.isResponseChecked = true 39 checkCachedResponse(client); 31 40 } 32 41 }) … … 39 48 assert_true(client.hasAborted, "xhr should have aborted") 40 49 assert_true(client.isResponseChecked, "xhr response should have been checked") 50 checkCachedResponse(client); 41 51 test.done() 52 }) 53 client.send(null) 54 }) 55 56 var test2 = async_test(name + " (aborting in loadend)") 57 test2.step(function() { 58 var client = new XMLHttpRequest() 59 var url = "/resources/load-then-wait.cgi?name=../xmlhttprequest/" + fileName + "&waitFor=1&mimeType=" + mimeType 60 client.open("GET", url, true) 61 setupClient(test2, client) 62 63 client.onloadend = test2.step_func(function () { 64 assert_true(client.response != null); 65 checkCachedResponse(client); 66 client.abort(); 67 checkResponse(test2, client); 68 checkCachedResponse(client); 69 test2.done(); 42 70 }) 43 71 client.send(null) … … 69 97 ) 70 98 99 runTest("getting text response within abort event callback", 100 "resources/test.json","text/plain", 101 function(test, client) {client.responseType = "text"}, 102 function(test, client) {assert_true(client.response == "", "text response must be an empty string")} 103 ) 104 71 105 </script> 72 106 </body> -
trunk/Source/WebCore/CMakeLists.txt
r203445 r203494 3727 3727 ${WEBCORE_DIR}/Modules/streams/WritableStream.js 3728 3728 ${WEBCORE_DIR}/Modules/streams/WritableStreamInternals.js 3729 ${WEBCORE_DIR}/xml/XMLHttpRequest.js 3729 3730 ) 3730 3731 -
trunk/Source/WebCore/ChangeLog
r203490 r203494 1 2016-07-20 Youenn Fablet <youenn@apple.com> 2 3 [XHR] Cache response JS object in case of arraybuffer and blob response types 4 https://bugs.webkit.org/show_bug.cgi?id=128903 5 6 Reviewed by Alex Christensen. 7 8 Covered by existing and modified tests. 9 10 Making response getter a JS builtin that caches response in @response private slot. 11 Handling invalidation of cached response with @responseCacheIsValid new private method. 12 Handling creation of cached response with @retrieveResponse new private method which reuses most of 13 JSXMLHttpRequest::response previous code. 14 15 Caching of responses is activated whenever load ended without any error for blob and arraybuffer response types. 16 17 Caching of response for document is also activated in case the response getter is used but not if responseXML getter is used. 18 19 * CMakeLists.txt: Adding XMLHttpRequest.js. 20 * DerivedSources.make: Ditto. 21 * bindings/js/JSXMLHttpRequestCustom.cpp: 22 (WebCore::JSXMLHttpRequest::retrieveResponse): Implements creation of to-be-cached response. 23 (WebCore::JSXMLHttpRequest::response): Deleted. 24 * bindings/js/WebCoreBuiltinNames.h: Adding new private names. 25 * xml/XMLHttpRequest.cpp: 26 (WebCore::XMLHttpRequest::didCacheResponse): Renamed from didCacheResponseJSON as all response types are now cached. 27 (WebCore::XMLHttpRequest::didCacheResponseJSON): Deleted. 28 * xml/XMLHttpRequest.h: 29 * xml/XMLHttpRequest.idl: 30 1 31 2016-07-20 Youenn Fablet <youenn@apple.com> 2 32 -
trunk/Source/WebCore/DerivedSources.make
r203445 r203494 1300 1300 $(WebCore)/Modules/streams/WritableStream.js \ 1301 1301 $(WebCore)/Modules/streams/WritableStreamInternals.js \ 1302 $(WebCore)/xml/XMLHttpRequest.js \ 1302 1303 # 1303 1304 -
trunk/Source/WebCore/bindings/js/JSXMLHttpRequestCustom.cpp
r203470 r203494 64 64 if (Document* responseDocument = wrapped().optionalResponseXML()) 65 65 visitor.addOpaqueRoot(responseDocument); 66 67 if (ArrayBuffer* responseArrayBuffer = wrapped().optionalResponseArrayBuffer())68 visitor.addOpaqueRoot(responseArrayBuffer);69 70 if (Blob* responseBlob = wrapped().optionalResponseBlob())71 visitor.addOpaqueRoot(responseBlob);72 66 } 73 67 … … 152 146 } 153 147 154 JSValue JSXMLHttpRequest::re sponse(ExecState& state) const148 JSValue JSXMLHttpRequest::retrieveResponse(ExecState& state) 155 149 { 156 // FIXME: Use CachedAttribute for other types than JSON as well.157 if (m_response && wrapped().responseCacheIsValid())158 return m_response.get();159 160 150 auto type = wrapped().responseType(); 161 151 … … 171 161 return jsNull(); 172 162 163 JSValue value; 173 164 switch (type) { 174 165 case XMLHttpRequest::ResponseType::EmptyString: 175 166 case XMLHttpRequest::ResponseType::Text: 176 167 ASSERT_NOT_REACHED(); 168 return jsUndefined(); 169 170 case XMLHttpRequest::ResponseType::Json: 171 value = JSONParse(&state, wrapped().responseTextIgnoringResponseType()); 172 if (!value) 173 value = jsNull(); 177 174 break; 178 175 179 case XMLHttpRequest::ResponseType::Json: 180 { 181 JSValue value = JSONParse(&state, wrapped().responseTextIgnoringResponseType()); 182 if (!value) 183 value = jsNull(); 184 m_response.set(state.vm(), this, value); 185 wrapped().didCacheResponseJSON(); 186 return value; 187 } 188 189 case XMLHttpRequest::ResponseType::Document: 190 { 191 ExceptionCode ec = 0; 192 Document* document = wrapped().responseXML(ec); 193 if (ec) { 194 setDOMException(&state, ec); 195 return jsUndefined(); 196 } 197 return toJS(&state, globalObject(), document); 198 } 199 176 case XMLHttpRequest::ResponseType::Document: { 177 ExceptionCode ec = 0; 178 auto document = wrapped().responseXML(ec); 179 ASSERT(!ec); 180 value = toJS(&state, globalObject(), document); 181 break; 182 } 200 183 case XMLHttpRequest::ResponseType::Blob: 201 return toJS(&state, globalObject(), wrapped().responseBlob()); 184 value = toJSNewlyCreated(&state, globalObject(), wrapped().createResponseBlob()); 185 break; 202 186 203 187 case XMLHttpRequest::ResponseType::Arraybuffer: 204 return toJS(&state, globalObject(), wrapped().responseArrayBuffer()); 188 value = toJS(&state, globalObject(), wrapped().createResponseArrayBuffer()); 189 break; 205 190 } 206 207 ASSERT_NOT_REACHED(); 208 return jsUndefined(); 191 wrapped().didCacheResponse(); 192 return value; 209 193 } 210 194 -
trunk/Source/WebCore/bindings/js/WebCoreBuiltinNames.h
r203445 r203494 63 63 macro(readyPromiseCapability) \ 64 64 macro(removeTrack) \ 65 macro(responseCacheIsValid) \ 66 macro(retrieveResponse) \ 67 macro(response) \ 65 68 macro(setStatus) \ 66 69 macro(state) \ … … 86 89 macro(RTCIceCandidate) \ 87 90 macro(RTCSessionDescription) \ 91 macro(XMLHttpRequest) 88 92 89 93 class WebCoreBuiltinNames { -
trunk/Source/WebCore/xml/XMLHttpRequest.cpp
r203490 r203494 172 172 } 173 173 174 void XMLHttpRequest::didCacheResponseJSON() 175 { 176 ASSERT(m_responseType == ResponseType::Json); 174 void XMLHttpRequest::didCacheResponse() 175 { 177 176 ASSERT(doneWithoutErrors()); 178 177 m_responseCacheIsValid = true; … … 219 218 } 220 219 221 Blob* XMLHttpRequest::responseBlob()220 Ref<Blob> XMLHttpRequest::createResponseBlob() 222 221 { 223 222 ASSERT(m_responseType == ResponseType::Blob); 224 223 ASSERT(doneWithoutErrors()); 225 224 226 if (!m_responseBlob) { 227 if (m_binaryResponseBuilder) { 228 // FIXME: We just received the data from NetworkProcess, and are sending it back. This is inefficient. 229 Vector<uint8_t> data; 230 data.append(m_binaryResponseBuilder->data(), m_binaryResponseBuilder->size()); 231 String normalizedContentType = Blob::normalizedContentType(responseMIMEType()); // responseMIMEType defaults to text/xml which may be incorrect. 232 m_responseBlob = Blob::create(WTFMove(data), normalizedContentType); 233 m_binaryResponseBuilder = nullptr; 234 } else { 235 // If we errored out or got no data, we still return a blob, just an empty one. 236 m_responseBlob = Blob::create(); 237 } 238 } 239 240 return m_responseBlob.get(); 241 } 242 243 ArrayBuffer* XMLHttpRequest::responseArrayBuffer() 225 if (!m_binaryResponseBuilder) 226 return Blob::create(); 227 228 // FIXME: We just received the data from NetworkProcess, and are sending it back. This is inefficient. 229 Vector<uint8_t> data; 230 data.append(m_binaryResponseBuilder->data(), m_binaryResponseBuilder->size()); 231 m_binaryResponseBuilder = nullptr; 232 String normalizedContentType = Blob::normalizedContentType(responseMIMEType()); // responseMIMEType defaults to text/xml which may be incorrect. 233 return Blob::create(WTFMove(data), normalizedContentType); 234 } 235 236 RefPtr<ArrayBuffer> XMLHttpRequest::createResponseArrayBuffer() 244 237 { 245 238 ASSERT(m_responseType == ResponseType::Arraybuffer); 246 239 ASSERT(doneWithoutErrors()); 247 240 248 if (!m_responseArrayBuffer) { 249 if (m_binaryResponseBuilder) 250 m_responseArrayBuffer = m_binaryResponseBuilder->createArrayBuffer(); 251 else 252 m_responseArrayBuffer = ArrayBuffer::create(nullptr, 0); 253 m_binaryResponseBuilder = nullptr; 254 } 255 256 return m_responseArrayBuffer.get(); 241 auto result = m_binaryResponseBuilder ? m_binaryResponseBuilder->createArrayBuffer() : ArrayBuffer::create(nullptr, 0); 242 m_binaryResponseBuilder = nullptr; 243 return result; 257 244 } 258 245 … … 820 807 m_createdDocument = false; 821 808 m_responseDocument = nullptr; 822 m_responseBlob = nullptr;823 809 m_binaryResponseBuilder = nullptr; 824 m_responseArrayBuffer = nullptr;825 810 m_responseCacheIsValid = false; 826 811 } -
trunk/Source/WebCore/xml/XMLHttpRequest.h
r203470 r203494 89 89 String responseTextIgnoringResponseType() const { return m_responseBuilder.toStringPreserveCapacity(); } 90 90 String responseMIMEType() const; 91 92 Document* optionalResponseXML() const { return m_responseDocument.get(); } 91 93 Document* responseXML(ExceptionCode&); 92 Document* optionalResponseXML() const { return m_responseDocument.get(); } 93 Blob* responseBlob(); 94 Blob* optionalResponseBlob() const { return m_responseBlob.get(); } 94 95 Ref<Blob> createResponseBlob(); 96 RefPtr<JSC::ArrayBuffer> createResponseArrayBuffer(); 97 95 98 unsigned timeout() const { return m_timeoutMilliseconds; } 96 99 void setTimeout(unsigned timeout, ExceptionCode&); 97 100 98 101 bool responseCacheIsValid() const { return m_responseCacheIsValid; } 99 void didCacheResponse JSON();102 void didCacheResponse(); 100 103 101 104 // Expose HTTP validation methods for other untrusted requests. … … 109 112 110 113 String responseURL() const; 111 112 // response attribute has custom getter.113 JSC::ArrayBuffer* responseArrayBuffer();114 JSC::ArrayBuffer* optionalResponseArrayBuffer() const { return m_responseArrayBuffer.get(); }115 114 116 115 void setLastSendLineAndColumnNumber(unsigned lineNumber, unsigned columnNumber); … … 188 187 bool m_async { true }; 189 188 bool m_includeCredentials { false }; 190 RefPtr<Blob> m_responseBlob;191 189 192 190 RefPtr<ThreadableLoader> m_loader; … … 202 200 bool m_createdDocument { false }; 203 201 RefPtr<Document> m_responseDocument; 204 202 205 203 RefPtr<SharedBuffer> m_binaryResponseBuilder; 206 RefPtr<JSC::ArrayBuffer> m_responseArrayBuffer;207 204 208 205 bool m_error { false }; -
trunk/Source/WebCore/xml/XMLHttpRequest.idl
r203470 r203494 45 45 JSGenerateToJSObject, 46 46 ExportMacro=WEBCORE_EXPORT, 47 PublicIdentifier, 48 PrivateIdentifier, 47 49 ] interface XMLHttpRequest : XMLHttpRequestEventTarget { 48 50 attribute EventHandler onreadystatechange; … … 79 81 80 82 [SetterRaisesException] attribute XMLHttpRequestResponseType responseType; 81 [ GetterRaisesException, CachedAttribute, CustomGetter] readonly attribute Object response;83 [JSBuiltin] readonly attribute Object response; 82 84 83 85 readonly attribute unsigned short status; … … 85 87 readonly attribute DOMString responseURL; 86 88 89 [PrivateIdentifier] boolean responseCacheIsValid(); 90 [PrivateIdentifier, Custom] any retrieveResponse(); 91 87 92 // Extension 88 93 [RaisesException] void overrideMimeType(DOMString override);
Note:
See TracChangeset
for help on using the changeset viewer.