<!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>[198005] 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/198005">198005</a></dd>
<dt>Author</dt> <dd>youenn.fablet@crf.canon.fr</dd>
<dt>Date</dt> <dd>2016-03-11 04:08:22 -0800 (Fri, 11 Mar 2016)</dd>
</dl>
<h3>Log Message</h3>
<pre>[Fetch API] Use DeferredWrapper directly in FetchBody promise handling
https://bugs.webkit.org/show_bug.cgi?id=155291
Reviewed by Darin Adler.
LayoutTests/imported/w3c:
* web-platform-tests/fetch/api/request/request-consume-empty-expected.txt: Added.
* web-platform-tests/fetch/api/request/request-consume-empty.html: Added.
* web-platform-tests/fetch/api/response/response-consume-empty-expected.txt: Added.
* web-platform-tests/fetch/api/response/response-consume-empty.html: Added.
Source/WebCore:
Moved from typed DOMPromise to DeferredWrapper as there can only be one promise resolved.
Started preparing the handling of blobs translation to other resolved types.
Fixed the case of empty body, in which case promises should resolve with empty objects (strings, buffers...) and not null.
Added Consumer structure to handle asynchronous resolution/rejection of promises.
Added preliminary API to resolve promises based on data stored as a Blob.
FetchBodyOwner will be responsible to do/stop blob loading.
Tests: imported/w3c/web-platform-tests/fetch/api/request/request-consume-empty.html
imported/w3c/web-platform-tests/fetch/api/response/response-consume-empty.html
* Modules/fetch/FetchBody.cpp:
(WebCore::FetchBody::processIfEmptyOrDisturbed): Fixed empty body case.
(WebCore::FetchBody::arrayBuffer):
(WebCore::FetchBody::blob):
(WebCore::FetchBody::json):
(WebCore::FetchBody::text):
(WebCore::FetchBody::consume):
(WebCore::FetchBody::consumeText):
(WebCore::FetchBody::loadingType):
(WebCore::FetchBody::consumeBlob):
(WebCore::FetchBody::resolveAsJSON):
(WebCore::FetchBody::loadingFailed):
(WebCore::FetchBody::loadedAsBlob):
* Modules/fetch/FetchBody.h:
(WebCore::FetchBody::formData):
(WebCore::FetchBody::Consumer::Consumer):
* Modules/fetch/FetchBody.idl:
* Modules/fetch/FetchBodyOwner.h:
(WebCore::FetchBodyOwner::arrayBuffer):
(WebCore::FetchBodyOwner::blob):
(WebCore::FetchBodyOwner::formData):
(WebCore::FetchBodyOwner::json):
(WebCore::FetchBodyOwner::text):
(WebCore::FetchBodyOwner::loadBlob):</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsimportedw3cChangeLog">trunk/LayoutTests/imported/w3c/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreModulesfetchFetchBodycpp">trunk/Source/WebCore/Modules/fetch/FetchBody.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesfetchFetchBodyh">trunk/Source/WebCore/Modules/fetch/FetchBody.h</a></li>
<li><a href="#trunkSourceWebCoreModulesfetchFetchBodyidl">trunk/Source/WebCore/Modules/fetch/FetchBody.idl</a></li>
<li><a href="#trunkSourceWebCoreModulesfetchFetchBodyOwnerh">trunk/Source/WebCore/Modules/fetch/FetchBodyOwner.h</a></li>
</ul>
<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestsfetchapirequestrequestconsumeemptyexpectedtxt">trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/request/request-consume-empty-expected.txt</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestsfetchapirequestrequestconsumeemptyhtml">trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/request/request-consume-empty.html</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestsfetchapiresponseresponseconsumeemptyexpectedtxt">trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/response/response-consume-empty-expected.txt</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestsfetchapiresponseresponseconsumeemptyhtml">trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/response/response-consume-empty.html</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsimportedw3cChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/ChangeLog (198004 => 198005)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/ChangeLog        2016-03-11 11:13:25 UTC (rev 198004)
+++ trunk/LayoutTests/imported/w3c/ChangeLog        2016-03-11 12:08:22 UTC (rev 198005)
</span><span class="lines">@@ -1,3 +1,15 @@
</span><ins>+2016-03-11 Youenn Fablet <youenn.fablet@crf.canon.fr>
+
+ [Fetch API] Use DeferredWrapper directly in FetchBody promise handling
+ https://bugs.webkit.org/show_bug.cgi?id=155291
+
+ Reviewed by Darin Adler.
+
+ * web-platform-tests/fetch/api/request/request-consume-empty-expected.txt: Added.
+ * web-platform-tests/fetch/api/request/request-consume-empty.html: Added.
+ * web-platform-tests/fetch/api/response/response-consume-empty-expected.txt: Added.
+ * web-platform-tests/fetch/api/response/response-consume-empty.html: Added.
+
</ins><span class="cx"> 2016-03-09 Chris Dumez <cdumez@apple.com>
</span><span class="cx">
</span><span class="cx"> focus() / blur() should be on HTMLElement / SVGElement, not Element
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestsfetchapirequestrequestconsumeemptyexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/request/request-consume-empty-expected.txt (0 => 198005)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/request/request-consume-empty-expected.txt         (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/request/request-consume-empty-expected.txt        2016-03-11 12:08:22 UTC (rev 198005)
</span><span class="lines">@@ -0,0 +1,7 @@
</span><ins>+
+PASS Consume request's body as text
+PASS Consume request's body as blob
+PASS Consume request's body as arrayBuffer
+PASS Consume request's body as json
+FAIL Consume request's body as formData promise_test: Unhandled rejection with value: undefined
+
</ins></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestsfetchapirequestrequestconsumeemptyhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/request/request-consume-empty.html (0 => 198005)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/request/request-consume-empty.html         (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/request/request-consume-empty.html        2016-03-11 12:08:22 UTC (rev 198005)
</span><span class="lines">@@ -0,0 +1,81 @@
</span><ins>+<!doctype html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>Request consume empty bodies</title>
+ <meta name="help" href="https://fetch.spec.whatwg.org/#request">
+ <meta name="help" href="https://fetch.spec.whatwg.org/#body-mixin">
+ <meta name="author" title="Canon Research France" href="https://www.crf.canon.fr">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <script>
+ function checkBodyText(request) {
+ return request.text().then( function(bodyAsText) {
+ assert_equals(bodyAsText, "", "Resolved value should be empty");
+ assert_false(request.bodyUsed);
+ });
+ }
+
+ function checkBodyBlob(request) {
+ return request.blob().then(function(bodyAsBlob) {
+ var promise = new Promise(function (resolve, reject) {
+ var reader = new FileReader();
+ reader.onload = function(evt) {
+ resolve(reader.result)
+ };
+ reader.onerror = function() {
+ reject("Blob's reader failed");
+ };
+ reader.readAsText(bodyAsBlob);
+ });
+ return promise.then(function(body) {
+ assert_equals(body, "", "Resolved value should be empty");
+ assert_false(request.bodyUsed);
+ });
+ });
+ }
+
+ function checkBodyArrayBuffer(request) {
+ return request.arrayBuffer().then( function(bodyAsArrayBuffer) {
+ assert_equals(bodyAsArrayBuffer.byteLength, 0, "Resolved value should be empty");
+ assert_false(request.bodyUsed);
+ });
+ }
+
+ function checkBodyJSON(request) {
+ return request.json().then(
+ (bodyAsJSON) => {
+ assert_unreached("JSON parsing should fail");
+ },
+ () => {
+ assert_false(request.bodyUsed);
+ });
+ }
+
+ function checkBodyFormData(request) {
+ return request.formData().then(function(bodyAsFormData) {
+ assert_true(bodyAsFormData instanceof FormData, "Should receive a FormData");
+ assert_false(request.bodyUsed);
+ });
+ }
+
+ function checkRequestBody(bodyType, checkFunction) {
+ promise_test(function(test) {
+ var request = new Request("", {"method": "POST"});
+ assert_false(request.bodyUsed);
+ return checkFunction(request);
+ }, "Consume request's body as " + bodyType);
+ }
+
+ var formData = new FormData();
+ checkRequestBody("text", checkBodyText);
+ checkRequestBody("blob", checkBodyBlob);
+ checkRequestBody("arrayBuffer", checkBodyArrayBuffer);
+ checkRequestBody("json", checkBodyJSON);
+ checkRequestBody("formData", checkBodyFormData);
+
+ </script>
+ </body>
+</html>
</ins></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestsfetchapiresponseresponseconsumeemptyexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/response/response-consume-empty-expected.txt (0 => 198005)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/response/response-consume-empty-expected.txt         (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/response/response-consume-empty-expected.txt        2016-03-11 12:08:22 UTC (rev 198005)
</span><span class="lines">@@ -0,0 +1,7 @@
</span><ins>+
+PASS Consume response's body as text
+PASS Consume response's body as blob
+PASS Consume response's body as arrayBuffer
+PASS Consume response's body as json
+FAIL Consume response's body as formData promise_test: Unhandled rejection with value: undefined
+
</ins></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestsfetchapiresponseresponseconsumeemptyhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/response/response-consume-empty.html (0 => 198005)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/response/response-consume-empty.html         (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/response/response-consume-empty.html        2016-03-11 12:08:22 UTC (rev 198005)
</span><span class="lines">@@ -0,0 +1,81 @@
</span><ins>+<!doctype html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>Response consume empty bodies</title>
+ <meta name="help" href="https://fetch.spec.whatwg.org/#response">
+ <meta name="help" href="https://fetch.spec.whatwg.org/#body-mixin">
+ <meta name="author" title="Canon Research France" href="https://www.crf.canon.fr">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <script>
+ function checkBodyText(response) {
+ return response.text().then( function(bodyAsText) {
+ assert_equals(bodyAsText, "", "Resolved value should be empty");
+ assert_false(response.bodyUsed);
+ });
+ }
+
+ function checkBodyBlob(response) {
+ return response.blob().then(function(bodyAsBlob) {
+ var promise = new Promise(function (resolve, reject) {
+ var reader = new FileReader();
+ reader.onload = function(evt) {
+ resolve(reader.result)
+ };
+ reader.onerror = function() {
+ reject("Blob's reader failed");
+ };
+ reader.readAsText(bodyAsBlob);
+ });
+ return promise.then(function(body) {
+ assert_equals(body, "", "Resolved value should be empty");
+ assert_false(response.bodyUsed);
+ });
+ });
+ }
+
+ function checkBodyArrayBuffer(response) {
+ return response.arrayBuffer().then( function(bodyAsArrayBuffer) {
+ assert_equals(bodyAsArrayBuffer.byteLength, 0, "Resolved value should be empty");
+ assert_false(response.bodyUsed);
+ });
+ }
+
+ function checkBodyJSON(response) {
+ return response.json().then(
+ (bodyAsJSON) => {
+ assert_unreached("JSON parsing should fail");
+ },
+ () => {
+ assert_false(response.bodyUsed);
+ });
+ }
+
+ function checkBodyFormData(response) {
+ return response.formData().then(function(bodyAsFormData) {
+ assert_true(bodyAsFormData instanceof FormData, "Should receive a FormData");
+ assert_false(response.bodyUsed);
+ });
+ }
+
+ function checkResponseBody(bodyType, checkFunction) {
+ promise_test(function(test) {
+ var response = new Response();
+ assert_false(response.bodyUsed);
+ return checkFunction(response);
+ }, "Consume response's body as " + bodyType);
+ }
+
+ var formData = new FormData();
+ checkResponseBody("text", checkBodyText);
+ checkResponseBody("blob", checkBodyBlob);
+ checkResponseBody("arrayBuffer", checkBodyArrayBuffer);
+ checkResponseBody("json", checkBodyJSON);
+ checkResponseBody("formData", checkBodyFormData);
+
+ </script>
+ </body>
+</html>
</ins></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (198004 => 198005)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-03-11 11:13:25 UTC (rev 198004)
+++ trunk/Source/WebCore/ChangeLog        2016-03-11 12:08:22 UTC (rev 198005)
</span><span class="lines">@@ -1,3 +1,47 @@
</span><ins>+2016-03-11 Youenn Fablet <youenn.fablet@crf.canon.fr>
+
+ [Fetch API] Use DeferredWrapper directly in FetchBody promise handling
+ https://bugs.webkit.org/show_bug.cgi?id=155291
+
+ Reviewed by Darin Adler.
+
+ Moved from typed DOMPromise to DeferredWrapper as there can only be one promise resolved.
+ Started preparing the handling of blobs translation to other resolved types.
+
+ Fixed the case of empty body, in which case promises should resolve with empty objects (strings, buffers...) and not null.
+
+ Added Consumer structure to handle asynchronous resolution/rejection of promises.
+ Added preliminary API to resolve promises based on data stored as a Blob.
+ FetchBodyOwner will be responsible to do/stop blob loading.
+
+ Tests: imported/w3c/web-platform-tests/fetch/api/request/request-consume-empty.html
+ imported/w3c/web-platform-tests/fetch/api/response/response-consume-empty.html
+
+ * Modules/fetch/FetchBody.cpp:
+ (WebCore::FetchBody::processIfEmptyOrDisturbed): Fixed empty body case.
+ (WebCore::FetchBody::arrayBuffer):
+ (WebCore::FetchBody::blob):
+ (WebCore::FetchBody::json):
+ (WebCore::FetchBody::text):
+ (WebCore::FetchBody::consume):
+ (WebCore::FetchBody::consumeText):
+ (WebCore::FetchBody::loadingType):
+ (WebCore::FetchBody::consumeBlob):
+ (WebCore::FetchBody::resolveAsJSON):
+ (WebCore::FetchBody::loadingFailed):
+ (WebCore::FetchBody::loadedAsBlob):
+ * Modules/fetch/FetchBody.h:
+ (WebCore::FetchBody::formData):
+ (WebCore::FetchBody::Consumer::Consumer):
+ * Modules/fetch/FetchBody.idl:
+ * Modules/fetch/FetchBodyOwner.h:
+ (WebCore::FetchBodyOwner::arrayBuffer):
+ (WebCore::FetchBodyOwner::blob):
+ (WebCore::FetchBodyOwner::formData):
+ (WebCore::FetchBodyOwner::json):
+ (WebCore::FetchBodyOwner::text):
+ (WebCore::FetchBodyOwner::loadBlob):
+
</ins><span class="cx"> 2016-03-11 Yoav Weiss <yoav@yoav.ws>
</span><span class="cx">
</span><span class="cx"> Avoid applying link tags with an invalid media attribute
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesfetchFetchBodycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/fetch/FetchBody.cpp (198004 => 198005)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/fetch/FetchBody.cpp        2016-03-11 11:13:25 UTC (rev 198004)
+++ trunk/Source/WebCore/Modules/fetch/FetchBody.cpp        2016-03-11 12:08:22 UTC (rev 198005)
</span><span class="lines">@@ -31,8 +31,10 @@
</span><span class="cx">
</span><span class="cx"> #if ENABLE(FETCH_API)
</span><span class="cx">
</span><ins>+#include "DOMRequestState.h"
</ins><span class="cx"> #include "Dictionary.h"
</span><span class="cx"> #include "ExceptionCode.h"
</span><ins>+#include "FetchBodyOwner.h"
</ins><span class="cx"> #include "HTTPParsers.h"
</span><span class="cx"> #include "JSBlob.h"
</span><span class="cx"> #include "JSDOMFormData.h"
</span><span class="lines">@@ -82,98 +84,138 @@
</span><span class="cx"> return FetchBody(WTFMove(*body));
</span><span class="cx"> }
</span><span class="cx">
</span><del>-template<typename T> inline bool FetchBody::processIfEmptyOrDisturbed(DOMPromise<T, ExceptionCode>& promise)
</del><ins>+bool FetchBody::processIfEmptyOrDisturbed(Consumer::Type type, DeferredWrapper& promise)
</ins><span class="cx"> {
</span><span class="cx"> if (m_type == Type::None) {
</span><del>- promise.resolve(T());
- return true;
</del><ins>+ switch (type) {
+ case Consumer::Type::Text:
+ promise.resolve(String());
+ return true;
+ case Consumer::Type::Blob:
+ promise.resolve<RefPtr<Blob>>(Blob::create());
+ return true;
+ case Consumer::Type::JSON:
+ promise.reject<ExceptionCode>(SYNTAX_ERR);
+ return true;
+ case Consumer::Type::ArrayBuffer:
+ promise.resolve(ArrayBuffer::create(nullptr, 0));
+ return true;
+ default:
+ ASSERT_NOT_REACHED();
+ promise.reject<ExceptionCode>(0);
+ return true;
+ };
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> if (m_isDisturbed) {
</span><del>- promise.reject(TypeError);
</del><ins>+ promise.reject<ExceptionCode>(TypeError);
</ins><span class="cx"> return true;
</span><span class="cx"> }
</span><span class="cx"> m_isDisturbed = true;
</span><span class="cx"> return false;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-void FetchBody::arrayBuffer(ArrayBufferPromise&& promise)
</del><ins>+void FetchBody::arrayBuffer(FetchBodyOwner& owner, DeferredWrapper&& promise)
</ins><span class="cx"> {
</span><del>- if (processIfEmptyOrDisturbed(promise))
</del><ins>+ if (processIfEmptyOrDisturbed(Consumer::Type::ArrayBuffer, promise))
</ins><span class="cx"> return;
</span><del>-
- if (m_type == Type::Text) {
- // FIXME: Ideally we would like to have an ArrayBuffer directly from m_text.
- Vector<char> data = extractFromText();
- RefPtr<ArrayBuffer> buffer = ArrayBuffer::create(data.data(), data.size());
- promise.resolve(buffer);
- return;
- }
- // FIXME: Support other types.
- promise.reject(0);
</del><ins>+ consume(owner, Consumer::Type::ArrayBuffer, WTFMove(promise));
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-void FetchBody::formData(FormDataPromise&& promise)
</del><ins>+void FetchBody::blob(FetchBodyOwner& owner, DeferredWrapper&& promise)
</ins><span class="cx"> {
</span><del>- if (m_type == Type::None || m_isDisturbed) {
- promise.reject(TypeError);
</del><ins>+ if (processIfEmptyOrDisturbed(Consumer::Type::Blob, promise))
</ins><span class="cx"> return;
</span><del>- }
- m_isDisturbed = true;
</del><span class="cx">
</span><del>- // FIXME: Support other types.
- promise.reject(0);
</del><ins>+ consume(owner, Consumer::Type::Blob, WTFMove(promise));
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-void FetchBody::blob(BlobPromise&& promise)
</del><ins>+void FetchBody::json(FetchBodyOwner& owner, DeferredWrapper&& promise)
</ins><span class="cx"> {
</span><del>- if (processIfEmptyOrDisturbed(promise))
</del><ins>+ if (processIfEmptyOrDisturbed(Consumer::Type::JSON, promise))
</ins><span class="cx"> return;
</span><span class="cx">
</span><del>- if (m_type == Type::Blob) {
- promise.resolve(m_blob);
- return;
- }
</del><span class="cx"> if (m_type == Type::Text) {
</span><del>- String contentType = Blob::normalizedContentType(extractMIMETypeFromMediaType(m_mimeType));
- promise.resolve(Blob::create(extractFromText(), contentType));
</del><ins>+ resolveAsJSON(owner.scriptExecutionContext(), m_text, WTFMove(promise));
</ins><span class="cx"> return;
</span><span class="cx"> }
</span><del>-
- // FIXME: Support other types.
- promise.reject(0);
</del><ins>+ consume(owner, Consumer::Type::JSON, WTFMove(promise));
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-void FetchBody::text(TextPromise&& promise)
</del><ins>+void FetchBody::text(FetchBodyOwner& owner, DeferredWrapper&& promise)
</ins><span class="cx"> {
</span><del>- if (processIfEmptyOrDisturbed(promise))
</del><ins>+ if (processIfEmptyOrDisturbed(Consumer::Type::Text, promise))
</ins><span class="cx"> return;
</span><span class="cx">
</span><span class="cx"> if (m_type == Type::Text) {
</span><span class="cx"> promise.resolve(m_text);
</span><span class="cx"> return;
</span><span class="cx"> }
</span><del>- // FIXME: Support other types.
- promise.reject(0);
</del><ins>+ consume(owner, Consumer::Type::Text, WTFMove(promise));
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-void FetchBody::json(JSC::ExecState& state, JSONPromise&& promise)
</del><ins>+void FetchBody::consume(FetchBodyOwner& owner, Consumer::Type type, DeferredWrapper&& promise)
</ins><span class="cx"> {
</span><del>- if (processIfEmptyOrDisturbed(promise))
- return;
-
</del><span class="cx"> if (m_type == Type::Text) {
</span><del>- JSC::JSValue value = JSC::JSONParse(&state, m_text);
- if (!value)
- promise.reject(SYNTAX_ERR);
- else
- promise.resolve(value);
</del><ins>+ consumeText(type, WTFMove(promise));
</ins><span class="cx"> return;
</span><span class="cx"> }
</span><ins>+ if (m_type == Type::Blob) {
+ consumeBlob(owner, type, WTFMove(promise));
+ return;
+ }
+
</ins><span class="cx"> // FIXME: Support other types.
</span><del>- promise.reject(0);
</del><ins>+ promise.reject<ExceptionCode>(0);
</ins><span class="cx"> }
</span><span class="cx">
</span><ins>+void FetchBody::consumeText(Consumer::Type type, DeferredWrapper&& promise)
+{
+ ASSERT(type == Consumer::Type::ArrayBuffer || type == Consumer::Type::Blob);
+
+ if (type == Consumer::Type::ArrayBuffer) {
+ Vector<char> data = extractFromText();
+ promise.resolve<RefPtr<ArrayBuffer>>(ArrayBuffer::create(data.data(), data.size()));
+ return;
+ }
+ String contentType = Blob::normalizedContentType(extractMIMETypeFromMediaType(m_mimeType));
+ promise.resolve<RefPtr<Blob>>(Blob::create(extractFromText(), contentType));
+}
+
+FetchLoadingType FetchBody::loadingType(Consumer::Type type)
+{
+ switch (type) {
+ case Consumer::Type::JSON:
+ case Consumer::Type::Text:
+ return FetchLoadingType::Text;
+ case Consumer::Type::Blob:
+ return FetchLoadingType::Blob;
+ case Consumer::Type::ArrayBuffer:
+ return FetchLoadingType::ArrayBuffer;
+ default:
+ ASSERT_NOT_REACHED();
+ return FetchLoadingType::ArrayBuffer;
+ };
+}
+
+void FetchBody::consumeBlob(FetchBodyOwner& owner, Consumer::Type type, DeferredWrapper&& promise)
+{
+ ASSERT(m_blob);
+
+ m_consumer = Consumer({type, WTFMove(promise)});
+ owner.loadBlob(*m_blob, loadingType(type));
+}
+
+void FetchBody::resolveAsJSON(ScriptExecutionContext* context, const String& data, DeferredWrapper&& promise)
+{
+ DOMRequestState state(context);
+ JSC::JSValue value = JSC::JSONParse(state.exec(), data);
+ if (!value)
+ promise.reject<ExceptionCode>(SYNTAX_ERR);
+ else
+ promise.resolve(value);
+}
+
</ins><span class="cx"> Vector<char> FetchBody::extractFromText() const
</span><span class="cx"> {
</span><span class="cx"> ASSERT(m_type == Type::Text);
</span><span class="lines">@@ -184,6 +226,20 @@
</span><span class="cx"> return value;
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+void FetchBody::loadingFailed()
+{
+ ASSERT(m_consumer);
+ m_consumer->promise.reject<ExceptionCode>(0);
+ m_consumer = Nullopt;
</ins><span class="cx"> }
</span><span class="cx">
</span><ins>+void FetchBody::loadedAsBlob(Blob& blob)
+{
+ ASSERT(m_consumer);
+ m_consumer->promise.resolve(&blob);
+ m_consumer = Nullopt;
+}
+
+}
+
</ins><span class="cx"> #endif // ENABLE(FETCH_API)
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesfetchFetchBodyh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/fetch/FetchBody.h (198004 => 198005)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/fetch/FetchBody.h        2016-03-11 11:13:25 UTC (rev 198004)
+++ trunk/Source/WebCore/Modules/fetch/FetchBody.h        2016-03-11 12:08:22 UTC (rev 198005)
</span><span class="lines">@@ -36,33 +36,23 @@
</span><span class="cx"> #include "JSDOMPromise.h"
</span><span class="cx">
</span><span class="cx"> namespace JSC {
</span><del>-class ArrayBuffer;
</del><span class="cx"> class ExecState;
</span><span class="cx"> class JSValue;
</span><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> namespace WebCore {
</span><span class="cx">
</span><del>-class Dictionary;
-typedef int ExceptionCode;
</del><ins>+class FetchBodyOwner;
+enum class FetchLoadingType;
</ins><span class="cx">
</span><span class="cx"> class FetchBody {
</span><span class="cx"> public:
</span><del>- typedef DOMPromise<RefPtr<JSC::ArrayBuffer>, ExceptionCode> ArrayBufferPromise;
- void arrayBuffer(ArrayBufferPromise&&);
</del><ins>+ void arrayBuffer(FetchBodyOwner&, DeferredWrapper&&);
+ void blob(FetchBodyOwner&, DeferredWrapper&&);
+ void json(FetchBodyOwner&, DeferredWrapper&&);
+ void text(FetchBodyOwner&, DeferredWrapper&&);
+ void formData(FetchBodyOwner&, DeferredWrapper&& promise) { promise.reject<ExceptionCode>(0); }
</ins><span class="cx">
</span><del>- typedef DOMPromise<RefPtr<DOMFormData>, ExceptionCode> FormDataPromise;
- void formData(FormDataPromise&&);
-
- typedef DOMPromise<RefPtr<Blob>, ExceptionCode> BlobPromise;
- void blob(BlobPromise&&);
-
- typedef DOMPromise<JSC::JSValue, ExceptionCode> JSONPromise;
- void json(JSC::ExecState&, JSONPromise&&);
-
- typedef DOMPromise<String, ExceptionCode> TextPromise;
- void text(TextPromise&&);
-
</del><span class="cx"> bool isDisturbed() const { return m_isDisturbed; }
</span><span class="cx"> bool isEmpty() const { return m_type == Type::None; }
</span><span class="cx">
</span><span class="lines">@@ -73,16 +63,30 @@
</span><span class="cx"> static FetchBody extractFromBody(FetchBody*);
</span><span class="cx"> FetchBody() = default;
</span><span class="cx">
</span><ins>+ void loadingFailed();
+ void loadedAsBlob(Blob&);
+
</ins><span class="cx"> private:
</span><del>- template<typename T> bool processIfEmptyOrDisturbed(DOMPromise<T, ExceptionCode>&);
-
</del><span class="cx"> enum class Type { None, Text, Blob, FormData };
</span><span class="cx">
</span><span class="cx"> FetchBody(Ref<Blob>&&);
</span><span class="cx"> FetchBody(Ref<DOMFormData>&&);
</span><span class="cx"> FetchBody(String&&);
</span><span class="cx">
</span><ins>+ struct Consumer {
+ enum class Type { Text, Blob, JSON, ArrayBuffer };
+
+ Type type;
+ DeferredWrapper promise;
+ };
+ void consume(FetchBodyOwner&, Consumer::Type, DeferredWrapper&&);
+
</ins><span class="cx"> Vector<char> extractFromText() const;
</span><ins>+ bool processIfEmptyOrDisturbed(Consumer::Type, DeferredWrapper&);
+ void consumeText(Consumer::Type, DeferredWrapper&&);
+ void consumeBlob(FetchBodyOwner&, Consumer::Type, DeferredWrapper&&);
+ void resolveAsJSON(ScriptExecutionContext*, const String&, DeferredWrapper&&);
+ static FetchLoadingType loadingType(Consumer::Type);
</ins><span class="cx">
</span><span class="cx"> Type m_type = Type::None;
</span><span class="cx"> String m_mimeType;
</span><span class="lines">@@ -92,6 +96,8 @@
</span><span class="cx"> RefPtr<Blob> m_blob;
</span><span class="cx"> RefPtr<DOMFormData> m_formData;
</span><span class="cx"> String m_text;
</span><ins>+
+ Optional<Consumer> m_consumer;
</ins><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesfetchFetchBodyidl"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/fetch/FetchBody.idl (198004 => 198005)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/fetch/FetchBody.idl        2016-03-11 11:13:25 UTC (rev 198004)
+++ trunk/Source/WebCore/Modules/fetch/FetchBody.idl        2016-03-11 12:08:22 UTC (rev 198005)
</span><span class="lines">@@ -37,6 +37,6 @@
</span><span class="cx"> [NewObject] Promise arrayBuffer();
</span><span class="cx"> [NewObject] Promise blob();
</span><span class="cx"> [NewObject] Promise formData();
</span><del>- [CallWith=ScriptState, NewObject] Promise json();
</del><ins>+ [NewObject] Promise json();
</ins><span class="cx"> [NewObject] Promise text();
</span><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesfetchFetchBodyOwnerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/fetch/FetchBodyOwner.h (198004 => 198005)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/fetch/FetchBodyOwner.h        2016-03-11 11:13:25 UTC (rev 198004)
+++ trunk/Source/WebCore/Modules/fetch/FetchBodyOwner.h        2016-03-11 12:08:22 UTC (rev 198005)
</span><span class="lines">@@ -36,18 +36,22 @@
</span><span class="cx">
</span><span class="cx"> namespace WebCore {
</span><span class="cx">
</span><ins>+enum class FetchLoadingType { Text, ArrayBuffer, Blob };
+
</ins><span class="cx"> class FetchBodyOwner : public RefCounted<FetchBodyOwner>, public ActiveDOMObject {
</span><span class="cx"> public:
</span><span class="cx"> FetchBodyOwner(ScriptExecutionContext&, FetchBody&&);
</span><span class="cx">
</span><span class="cx"> // Exposed Body API
</span><span class="cx"> bool isDisturbed() const { return m_body.isDisturbed(); }
</span><del>- void arrayBuffer(FetchBody::ArrayBufferPromise&& promise) { m_body.arrayBuffer(WTFMove(promise)); }
- void formData(FetchBody::FormDataPromise&& promise) { m_body.formData(WTFMove(promise)); }
- void blob(FetchBody::BlobPromise&& promise) { m_body.blob(WTFMove(promise)); }
- void json(JSC::ExecState& state, FetchBody::JSONPromise&& promise) { m_body.json(state, WTFMove(promise)); }
- void text(FetchBody::TextPromise&& promise) { m_body.text(WTFMove(promise)); }
</del><ins>+ void arrayBuffer(DeferredWrapper&& promise) { m_body.arrayBuffer(*this, WTFMove(promise)); }
+ void blob(DeferredWrapper&& promise) { m_body.blob(*this, WTFMove(promise)); }
+ void formData(DeferredWrapper&& promise) { m_body.formData(*this, WTFMove(promise)); }
+ void json(DeferredWrapper&& promise) { m_body.json(*this, WTFMove(promise)); }
+ void text(DeferredWrapper&& promise) { m_body.text(*this, WTFMove(promise)); }
</ins><span class="cx">
</span><ins>+ void loadBlob(Blob&, FetchLoadingType);
+
</ins><span class="cx"> protected:
</span><span class="cx"> FetchBody m_body;
</span><span class="cx"> };
</span><span class="lines">@@ -59,6 +63,17 @@
</span><span class="cx"> suspendIfNeeded();
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+inline void FetchBodyOwner::loadBlob(Blob& blob, FetchLoadingType type)
+{
+ if (type == FetchLoadingType::Blob) {
+ // FIXME: Clone blob.
+ m_body.loadedAsBlob(blob);
+ return;
+ }
+ // FIXME: Implement blob loading.
+ m_body.loadingFailed();
+}
+
</ins><span class="cx"> } // namespace WebCore
</span><span class="cx">
</span><span class="cx"> #endif // ENABLE(FETCH_API)
</span></span></pre>
</div>
</div>
</body>
</html>