<!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>[206954] 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/206954">206954</a></dd>
<dt>Author</dt> <dd>commit-queue@webkit.org</dd>
<dt>Date</dt> <dd>2016-10-08 07:49:47 -0700 (Sat, 08 Oct 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>[Fetch API] Request constructor should provide exception messages
https://bugs.webkit.org/show_bug.cgi?id=162382

Source/WebCore:

Patch by Youenn Fablet &lt;youenn@apple.com&gt; on 2016-10-08
Reviewed by Darin Adler.

No change of behavior, except that exceptions now have error messages.

Added support of exception messages to ExceptionOr.
Making use of ExceptionOr for Request constructor parameter checking.

* Modules/fetch/FetchRequest.cpp:
(WebCore::setReferrerPolicy):
(WebCore::setMode):
(WebCore::setCredentials):
(WebCore::setCache):
(WebCore::setRedirect):
(WebCore::setMethod):
(WebCore::setReferrer):
(WebCore::buildOptions):
(WebCore::FetchRequest::initializeOptions):
(WebCore::FetchRequest::initializeWith):
* Modules/fetch/FetchRequest.h:
* Modules/fetch/FetchRequest.idl:
* bindings/js/JSDOMBinding.cpp:
(WebCore::setDOMException):
* bindings/js/JSDOMBinding.h:
(WebCore::toJS):
(WebCore::toJSNewlyCreated):
* dom/Exception.h:
(WebCore::Exception::code):
(WebCore::Exception::message):
(WebCore::Exception::Exception):
* dom/ExceptionOr.h:
(WebCore::ExceptionOr&lt;ReturnType&gt;::exceptionMessage):

LayoutTests:

Patch by Youenn Fablet &lt;youennf@gmail.com&gt; on 2016-10-08
Reviewed by Darin Adler.

* fetch/fetch-url-serialization-expected.txt: Rebasing test expectation.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsfetchfetchurlserializationexpectedtxt">trunk/LayoutTests/fetch/fetch-url-serialization-expected.txt</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreModulesfetchFetchRequestcpp">trunk/Source/WebCore/Modules/fetch/FetchRequest.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesfetchFetchRequesth">trunk/Source/WebCore/Modules/fetch/FetchRequest.h</a></li>
<li><a href="#trunkSourceWebCoreModulesfetchFetchRequestidl">trunk/Source/WebCore/Modules/fetch/FetchRequest.idl</a></li>
<li><a href="#trunkSourceWebCorebindingsjsJSDOMBindingcpp">trunk/Source/WebCore/bindings/js/JSDOMBinding.cpp</a></li>
<li><a href="#trunkSourceWebCorebindingsjsJSDOMBindingh">trunk/Source/WebCore/bindings/js/JSDOMBinding.h</a></li>
<li><a href="#trunkSourceWebCoredomExceptionh">trunk/Source/WebCore/dom/Exception.h</a></li>
<li><a href="#trunkSourceWebCoredomExceptionOrh">trunk/Source/WebCore/dom/ExceptionOr.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (206953 => 206954)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2016-10-08 13:09:30 UTC (rev 206953)
+++ trunk/LayoutTests/ChangeLog        2016-10-08 14:49:47 UTC (rev 206954)
</span><span class="lines">@@ -1,3 +1,12 @@
</span><ins>+2016-10-08  Youenn Fablet  &lt;youennf@gmail.com&gt;
+
+        [Fetch API] Request constructor should provide exception messages
+        https://bugs.webkit.org/show_bug.cgi?id=162382
+
+        Reviewed by Darin Adler.
+
+        * fetch/fetch-url-serialization-expected.txt: Rebasing test expectation.
+
</ins><span class="cx"> 2016-10-07  Chris Dumez  &lt;cdumez@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         window.navigator.language incorrectly returns all lowercase string
</span></span></pre></div>
<a id="trunkLayoutTestsfetchfetchurlserializationexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fetch/fetch-url-serialization-expected.txt (206953 => 206954)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fetch/fetch-url-serialization-expected.txt        2016-10-08 13:09:30 UTC (rev 206953)
+++ trunk/LayoutTests/fetch/fetch-url-serialization-expected.txt        2016-10-08 14:49:47 UTC (rev 206954)
</span><span class="lines">@@ -97,7 +97,7 @@
</span><span class="cx"> FAIL Testing Request url '  File:c|////foo\bar.html' with base 'file:///tmp/mock/path' assert_equals: expected &quot;file:///c:////foo/bar.html&quot; but got &quot;file:///tmp/mock/c|////foo/bar.html&quot;
</span><span class="cx"> FAIL Testing Request url 'C|/foo/bar' with base 'file:///tmp/mock/path' assert_equals: expected &quot;file:///C:/foo/bar&quot; but got &quot;file:///tmp/mock/C|/foo/bar&quot;
</span><span class="cx"> FAIL Testing Request url '/C|\foo\bar' with base 'file:///tmp/mock/path' assert_equals: expected &quot;file:///C:/foo/bar&quot; but got &quot;file:///C|/foo/bar&quot;
</span><del>-FAIL Testing Request url '//C|/foo/bar' with base 'file:///tmp/mock/path' Type error
</del><ins>+FAIL Testing Request url '//C|/foo/bar' with base 'file:///tmp/mock/path' URL is not valid or contains user credentials.
</ins><span class="cx"> PASS Testing Request url '//server/file' with base 'file:///tmp/mock/path' 
</span><span class="cx"> PASS Testing Request url '\\server\file' with base 'file:///tmp/mock/path' 
</span><span class="cx"> PASS Testing Request url '/\server/file' with base 'file:///tmp/mock/path' 
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (206953 => 206954)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-10-08 13:09:30 UTC (rev 206953)
+++ trunk/Source/WebCore/ChangeLog        2016-10-08 14:49:47 UTC (rev 206954)
</span><span class="lines">@@ -1,5 +1,42 @@
</span><span class="cx"> 2016-10-08  Youenn Fablet  &lt;youenn@apple.com&gt;
</span><span class="cx"> 
</span><ins>+        [Fetch API] Request constructor should provide exception messages
+        https://bugs.webkit.org/show_bug.cgi?id=162382
+
+        Reviewed by Darin Adler.
+
+        No change of behavior, except that exceptions now have error messages.
+
+        Added support of exception messages to ExceptionOr.
+        Making use of ExceptionOr for Request constructor parameter checking.
+
+        * Modules/fetch/FetchRequest.cpp:
+        (WebCore::setReferrerPolicy):
+        (WebCore::setMode):
+        (WebCore::setCredentials):
+        (WebCore::setCache):
+        (WebCore::setRedirect):
+        (WebCore::setMethod):
+        (WebCore::setReferrer):
+        (WebCore::buildOptions):
+        (WebCore::FetchRequest::initializeOptions):
+        (WebCore::FetchRequest::initializeWith):
+        * Modules/fetch/FetchRequest.h:
+        * Modules/fetch/FetchRequest.idl:
+        * bindings/js/JSDOMBinding.cpp:
+        (WebCore::setDOMException):
+        * bindings/js/JSDOMBinding.h:
+        (WebCore::toJS):
+        (WebCore::toJSNewlyCreated):
+        * dom/Exception.h:
+        (WebCore::Exception::code):
+        (WebCore::Exception::message):
+        (WebCore::Exception::Exception):
+        * dom/ExceptionOr.h:
+        (WebCore::ExceptionOr&lt;ReturnType&gt;::exceptionMessage):
+
+2016-10-08  Youenn Fablet  &lt;youenn@apple.com&gt;
+
</ins><span class="cx">         Refactor binding generated casted-this checks
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=162677
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesfetchFetchRequestcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/fetch/FetchRequest.cpp (206953 => 206954)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/fetch/FetchRequest.cpp        2016-10-08 13:09:30 UTC (rev 206953)
+++ trunk/Source/WebCore/Modules/fetch/FetchRequest.cpp        2016-10-08 14:49:47 UTC (rev 206954)
</span><span class="lines">@@ -39,7 +39,7 @@
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><del>-static bool setReferrerPolicy(FetchOptions&amp; options, const String&amp; referrerPolicy)
</del><ins>+static Optional&lt;Exception&gt; setReferrerPolicy(FetchOptions&amp; options, const String&amp; referrerPolicy)
</ins><span class="cx"> {
</span><span class="cx">     if (referrerPolicy.isEmpty())
</span><span class="cx">         options.referrerPolicy = FetchOptions::ReferrerPolicy::EmptyString;
</span><span class="lines">@@ -54,11 +54,11 @@
</span><span class="cx">     else if (referrerPolicy == &quot;unsafe-url&quot;)
</span><span class="cx">         options.referrerPolicy = FetchOptions::ReferrerPolicy::UnsafeUrl;
</span><span class="cx">     else
</span><del>-        return false;
-    return true;
</del><ins>+        return Exception { TypeError, ASCIILiteral(&quot;Bad referrer policy value.&quot;) };
+    return Nullopt;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-static bool setMode(FetchOptions&amp; options, const String&amp; mode)
</del><ins>+static Optional&lt;Exception&gt; setMode(FetchOptions&amp; options, const String&amp; mode)
</ins><span class="cx"> {
</span><span class="cx">     if (mode == &quot;navigate&quot;)
</span><span class="cx">         options.mode = FetchOptions::Mode::Navigate;
</span><span class="lines">@@ -69,11 +69,11 @@
</span><span class="cx">     else if (mode == &quot;cors&quot;)
</span><span class="cx">         options.mode = FetchOptions::Mode::Cors;
</span><span class="cx">     else
</span><del>-        return false;
-    return true;
</del><ins>+        return Exception { TypeError, ASCIILiteral(&quot;Bad fetch mode value.&quot;) };
+    return Nullopt;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-static bool setCredentials(FetchOptions&amp; options, const String&amp; credentials)
</del><ins>+static Optional&lt;Exception&gt; setCredentials(FetchOptions&amp; options, const String&amp; credentials)
</ins><span class="cx"> {
</span><span class="cx">     if (credentials == &quot;omit&quot;)
</span><span class="cx">         options.credentials = FetchOptions::Credentials::Omit;
</span><span class="lines">@@ -82,11 +82,11 @@
</span><span class="cx">     else if (credentials == &quot;include&quot;)
</span><span class="cx">         options.credentials = FetchOptions::Credentials::Include;
</span><span class="cx">     else
</span><del>-        return false;
-    return true;
</del><ins>+        return Exception { TypeError, ASCIILiteral(&quot;Bad credentials mode value.&quot;) };
+    return Nullopt;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-static bool setCache(FetchOptions&amp; options, const String&amp; cache)
</del><ins>+static Optional&lt;Exception&gt; setCache(FetchOptions&amp; options, const String&amp; cache)
</ins><span class="cx"> {
</span><span class="cx">     if (cache == &quot;default&quot;)
</span><span class="cx">         options.cache = FetchOptions::Cache::Default;
</span><span class="lines">@@ -99,11 +99,11 @@
</span><span class="cx">     else if (cache == &quot;force-cache&quot;)
</span><span class="cx">         options.cache = FetchOptions::Cache::ForceCache;
</span><span class="cx">     else
</span><del>-        return false;
-    return true;
</del><ins>+        return Exception { TypeError, ASCIILiteral(&quot;Bad cache mode value.&quot;) };
+    return Nullopt;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-static bool setRedirect(FetchOptions&amp; options, const String&amp; redirect)
</del><ins>+static Optional&lt;Exception&gt; setRedirect(FetchOptions&amp; options, const String&amp; redirect)
</ins><span class="cx"> {
</span><span class="cx">     if (redirect == &quot;follow&quot;)
</span><span class="cx">         options.redirect = FetchOptions::Redirect::Follow;
</span><span class="lines">@@ -112,85 +112,103 @@
</span><span class="cx">     else if (redirect == &quot;manual&quot;)
</span><span class="cx">         options.redirect = FetchOptions::Redirect::Manual;
</span><span class="cx">     else
</span><del>-        return false;
-    return true;
</del><ins>+        return Exception { TypeError, ASCIILiteral(&quot;Bad redirect mode value.&quot;) };
+    return Nullopt;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-static bool setMethod(ResourceRequest&amp; request, const String&amp; initMethod)
</del><ins>+static Optional&lt;Exception&gt; setMethod(ResourceRequest&amp; request, const String&amp; initMethod)
</ins><span class="cx"> {
</span><span class="cx">     if (!isValidHTTPToken(initMethod))
</span><del>-        return false;
</del><ins>+        return Exception { TypeError, ASCIILiteral(&quot;Method is not a valid HTTP token.&quot;) };
</ins><span class="cx"> 
</span><span class="cx">     String method = initMethod.convertToASCIIUppercase();
</span><span class="cx">     if (method == &quot;CONNECT&quot; || method == &quot;TRACE&quot; || method == &quot;TRACK&quot;)
</span><del>-        return false;
</del><ins>+        return Exception { TypeError, ASCIILiteral(&quot;Method is forbidden.&quot;) };
</ins><span class="cx"> 
</span><span class="cx">     request.setHTTPMethod((method == &quot;DELETE&quot; || method == &quot;GET&quot; || method == &quot;HEAD&quot; || method == &quot;OPTIONS&quot; || method == &quot;POST&quot; || method == &quot;PUT&quot;) ? method : initMethod);
</span><span class="cx"> 
</span><del>-    return true;
</del><ins>+    return Nullopt;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-static bool setReferrer(FetchRequest::InternalRequest&amp; request, ScriptExecutionContext&amp; context, const Dictionary&amp; init)
</del><ins>+static Optional&lt;Exception&gt; setReferrer(FetchRequest::InternalRequest&amp; request, ScriptExecutionContext&amp; context, const Dictionary&amp; init)
</ins><span class="cx"> {
</span><span class="cx">     String referrer;
</span><span class="cx">     if (!init.get(&quot;referrer&quot;, referrer))
</span><del>-        return true;
</del><ins>+        return Nullopt;
</ins><span class="cx">     if (referrer.isEmpty()) {
</span><span class="cx">         request.referrer = ASCIILiteral(&quot;no-referrer&quot;);
</span><del>-        return true;
</del><ins>+        return Nullopt;
</ins><span class="cx">     }
</span><span class="cx">     // FIXME: Tighten the URL parsing algorithm according https://url.spec.whatwg.org/#concept-url-parser.
</span><span class="cx">     URL referrerURL = context.completeURL(referrer);
</span><span class="cx">     if (!referrerURL.isValid())
</span><del>-        return false;
</del><ins>+        return Exception { TypeError, ASCIILiteral(&quot;Referrer is not a valid URL.&quot;) };
</ins><span class="cx"> 
</span><span class="cx">     if (referrerURL.protocolIs(&quot;about&quot;) &amp;&amp; referrerURL.path() == &quot;client&quot;) {
</span><span class="cx">         request.referrer = ASCIILiteral(&quot;client&quot;);
</span><del>-        return true;
</del><ins>+        return Nullopt;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     if (!(context.securityOrigin() &amp;&amp; context.securityOrigin()-&gt;canRequest(referrerURL)))
</span><del>-        return false;
</del><ins>+        return Exception { TypeError, ASCIILiteral(&quot;Referrer is not same-origin.&quot;) };
</ins><span class="cx"> 
</span><span class="cx">     request.referrer = referrerURL.string();
</span><del>-    return true;
</del><ins>+    return Nullopt;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-static bool buildOptions(FetchRequest::InternalRequest&amp; request, ScriptExecutionContext&amp; context, const Dictionary&amp; init)
</del><ins>+static Optional&lt;Exception&gt; buildOptions(FetchRequest::InternalRequest&amp; request, ScriptExecutionContext&amp; context, const Dictionary&amp; init)
</ins><span class="cx"> {
</span><span class="cx">     JSC::JSValue window;
</span><span class="cx">     if (init.get(&quot;window&quot;, window)) {
</span><span class="cx">         if (!window.isNull())
</span><del>-            return false;
</del><ins>+            return Exception { TypeError, ASCIILiteral(&quot;Window can only be null.&quot;) };
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    if (!setReferrer(request, context, init))
-        return false;
</del><ins>+    auto exception = setReferrer(request, context, init);
+    if (exception)
+        return exception;
</ins><span class="cx"> 
</span><span class="cx">     String value;
</span><del>-    if (init.get(&quot;referrerPolicy&quot;, value) &amp;&amp; !setReferrerPolicy(request.options, value))
-        return false;
</del><ins>+    if (init.get(&quot;referrerPolicy&quot;, value)) {
+        exception = setReferrerPolicy(request.options, value);
+        if (exception)
+            return exception;
+    }
</ins><span class="cx"> 
</span><del>-    if (init.get(&quot;mode&quot;, value) &amp;&amp; !setMode(request.options, value))
-        return false;
</del><ins>+    if (init.get(&quot;mode&quot;, value)) {
+        exception = setMode(request.options, value);
+        if (exception)
+            return exception;
+    }
</ins><span class="cx">     if (request.options.mode == FetchOptions::Mode::Navigate)
</span><del>-        return false;
</del><ins>+        return Exception { TypeError, ASCIILiteral(&quot;Request constructor does not accept navigate fetch mode.&quot;) };
</ins><span class="cx"> 
</span><del>-    if (init.get(&quot;credentials&quot;, value) &amp;&amp; !setCredentials(request.options, value))
-        return false;
</del><ins>+    if (init.get(&quot;credentials&quot;, value)) {
+        exception = setCredentials(request.options, value);
+        if (exception)
+            return exception;
+    }
</ins><span class="cx"> 
</span><del>-    if (init.get(&quot;cache&quot;, value) &amp;&amp; !setCache(request.options, value))
-        return false;
</del><ins>+    if (init.get(&quot;cache&quot;, value)) {
+        exception = setCache(request.options, value);
+        if (exception)
+            return exception;
+    }
</ins><span class="cx"> 
</span><del>-    if (init.get(&quot;redirect&quot;, value) &amp;&amp; !setRedirect(request.options, value))
-        return false;
</del><ins>+    if (init.get(&quot;redirect&quot;, value)) {
+        exception = setRedirect(request.options, value);
+        if (exception)
+            return exception;
+    }
</ins><span class="cx"> 
</span><span class="cx">     init.get(&quot;integrity&quot;, request.integrity);
</span><span class="cx"> 
</span><del>-    if (init.get(&quot;method&quot;, value) &amp;&amp; !setMethod(request.request, value))
-        return false;
-
-    return true;
</del><ins>+    if (init.get(&quot;method&quot;, value)) {
+        exception = setMethod(request.request, value);
+        if (exception)
+            return exception;
+    }
+    return Nullopt;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> static bool methodCanHaveBody(const FetchRequest::InternalRequest&amp; internalRequest)
</span><span class="lines">@@ -198,37 +216,32 @@
</span><span class="cx">     return internalRequest.request.httpMethod() != &quot;GET&quot; &amp;&amp; internalRequest.request.httpMethod() != &quot;HEAD&quot;;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void FetchRequest::initializeOptions(const Dictionary&amp; init, ExceptionCode&amp; ec)
</del><ins>+ExceptionOr&lt;Ref&lt;FetchHeaders&gt;&gt; FetchRequest::initializeOptions(const Dictionary&amp; init)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(scriptExecutionContext());
</span><del>-    if (!buildOptions(m_internalRequest, *scriptExecutionContext(), init)) {
-        ec = TypeError;
-        return;
-    }
</del><span class="cx"> 
</span><ins>+    auto exception = buildOptions(m_internalRequest, *scriptExecutionContext(), init);
+    if (exception)
+        return WTFMove(exception.value());
+
</ins><span class="cx">     if (m_internalRequest.options.mode == FetchOptions::Mode::NoCors) {
</span><span class="cx">         const String&amp; method = m_internalRequest.request.httpMethod();
</span><del>-        if (method != &quot;GET&quot; &amp;&amp; method != &quot;POST&quot; &amp;&amp; method != &quot;HEAD&quot;) {
-            ec = TypeError;
-            return;
-        }
-        if (!m_internalRequest.integrity.isEmpty()) {
-            ec = TypeError;
-            return;
-        }
</del><ins>+        if (method != &quot;GET&quot; &amp;&amp; method != &quot;POST&quot; &amp;&amp; method != &quot;HEAD&quot;)
+            return Exception { TypeError, ASCIILiteral(&quot;Method must be GET, POST or HEAD in no-cors mode.&quot;) };
+        if (!m_internalRequest.integrity.isEmpty())
+            return Exception { TypeError, ASCIILiteral(&quot;There cannot be an integrity in no-cors mode.&quot;) };
</ins><span class="cx">         m_headers-&gt;setGuard(FetchHeaders::Guard::RequestNoCors);
</span><span class="cx">     }
</span><ins>+    return m_headers.copyRef();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-FetchHeaders* FetchRequest::initializeWith(const String&amp; url, const Dictionary&amp; init, ExceptionCode&amp; ec)
</del><ins>+ExceptionOr&lt;Ref&lt;FetchHeaders&gt;&gt; FetchRequest::initializeWith(const String&amp; url, const Dictionary&amp; init)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(scriptExecutionContext());
</span><span class="cx">     // FIXME: Tighten the URL parsing algorithm according https://url.spec.whatwg.org/#concept-url-parser.
</span><span class="cx">     URL requestURL = scriptExecutionContext()-&gt;completeURL(url);
</span><del>-    if (!requestURL.isValid() || !requestURL.user().isEmpty() || !requestURL.pass().isEmpty()) {
-        ec = TypeError;
-        return nullptr;
-    }
</del><ins>+    if (!requestURL.isValid() || !requestURL.user().isEmpty() || !requestURL.pass().isEmpty())
+        return Exception { TypeError, ASCIILiteral(&quot;URL is not valid or contains user credentials.&quot;) };
</ins><span class="cx"> 
</span><span class="cx">     m_internalRequest.options.mode = Mode::Cors;
</span><span class="cx">     m_internalRequest.options.credentials = Credentials::Omit;
</span><span class="lines">@@ -235,21 +248,17 @@
</span><span class="cx">     m_internalRequest.referrer = ASCIILiteral(&quot;client&quot;);
</span><span class="cx">     m_internalRequest.request.setURL(requestURL);
</span><span class="cx"> 
</span><del>-    initializeOptions(init, ec);
-    return m_headers.ptr();
</del><ins>+    return initializeOptions(init);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-FetchHeaders* FetchRequest::initializeWith(FetchRequest&amp; input, const Dictionary&amp; init, ExceptionCode&amp; ec)
</del><ins>+ExceptionOr&lt;Ref&lt;FetchHeaders&gt;&gt; FetchRequest::initializeWith(FetchRequest&amp; input, const Dictionary&amp; init)
</ins><span class="cx"> {
</span><del>-    if (input.isDisturbedOrLocked()) {
-        ec = TypeError;
-        return nullptr;
-    }
</del><ins>+    if (input.isDisturbedOrLocked())
+        return Exception {TypeError, ASCIILiteral(&quot;Request input is disturbed or locked.&quot;) };
</ins><span class="cx"> 
</span><span class="cx">     m_internalRequest = input.m_internalRequest;
</span><span class="cx"> 
</span><del>-    initializeOptions(init, ec);
-    return m_headers.ptr();
</del><ins>+    return initializeOptions(init);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void FetchRequest::setBody(JSC::ExecState&amp; execState, JSC::JSValue body, FetchRequest* request, ExceptionCode&amp; ec)
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesfetchFetchRequesth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/fetch/FetchRequest.h (206953 => 206954)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/fetch/FetchRequest.h        2016-10-08 13:09:30 UTC (rev 206953)
+++ trunk/Source/WebCore/Modules/fetch/FetchRequest.h        2016-10-08 14:49:47 UTC (rev 206954)
</span><span class="lines">@@ -31,9 +31,11 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(FETCH_API)
</span><span class="cx"> 
</span><ins>+#include &quot;ExceptionOr.h&quot;
</ins><span class="cx"> #include &quot;FetchBodyOwner.h&quot;
</span><span class="cx"> #include &quot;FetchOptions.h&quot;
</span><span class="cx"> #include &quot;ResourceRequest.h&quot;
</span><ins>+#include &lt;wtf/Optional.h&gt;
</ins><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><span class="lines">@@ -46,8 +48,8 @@
</span><span class="cx"> public:
</span><span class="cx">     static Ref&lt;FetchRequest&gt; create(ScriptExecutionContext&amp; context) { return adoptRef(*new FetchRequest(context, Nullopt, FetchHeaders::create(FetchHeaders::Guard::Request), { })); }
</span><span class="cx"> 
</span><del>-    FetchHeaders* initializeWith(FetchRequest&amp;, const Dictionary&amp;, ExceptionCode&amp;);
-    FetchHeaders* initializeWith(const String&amp;, const Dictionary&amp;, ExceptionCode&amp;);
</del><ins>+    ExceptionOr&lt;Ref&lt;FetchHeaders&gt;&gt; initializeWith(FetchRequest&amp;, const Dictionary&amp;);
+    ExceptionOr&lt;Ref&lt;FetchHeaders&gt;&gt; initializeWith(const String&amp;, const Dictionary&amp;);
</ins><span class="cx">     void setBody(JSC::ExecState&amp;, JSC::JSValue, FetchRequest*, ExceptionCode&amp;);
</span><span class="cx"> 
</span><span class="cx">     const String&amp; method() const { return m_internalRequest.request.httpMethod(); }
</span><span class="lines">@@ -96,7 +98,7 @@
</span><span class="cx"> private:
</span><span class="cx">     FetchRequest(ScriptExecutionContext&amp;, Optional&lt;FetchBody&gt;&amp;&amp;, Ref&lt;FetchHeaders&gt;&amp;&amp;, InternalRequest&amp;&amp;);
</span><span class="cx"> 
</span><del>-    void initializeOptions(const Dictionary&amp;, ExceptionCode&amp;);
</del><ins>+    ExceptionOr&lt;Ref&lt;FetchHeaders&gt;&gt; initializeOptions(const Dictionary&amp;);
</ins><span class="cx"> 
</span><span class="cx">     // ActiveDOMObject API.
</span><span class="cx">     const char* activeDOMObjectName() const final;
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesfetchFetchRequestidl"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/fetch/FetchRequest.idl (206953 => 206954)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/fetch/FetchRequest.idl        2016-10-08 13:09:30 UTC (rev 206953)
+++ trunk/Source/WebCore/Modules/fetch/FetchRequest.idl        2016-10-08 14:49:47 UTC (rev 206954)
</span><span class="lines">@@ -62,8 +62,8 @@
</span><span class="cx"> 
</span><span class="cx">     [NewObject, CallWith=ScriptExecutionContext, MayThrowLegacyException] FetchRequest clone();
</span><span class="cx"> 
</span><del>-    [PrivateIdentifier, MayThrowLegacyException] FetchHeaders initializeWith(FetchRequest input, Dictionary init);
-    [PrivateIdentifier, MayThrowLegacyException] FetchHeaders initializeWith(DOMString input, Dictionary init);
</del><ins>+    [PrivateIdentifier, NewObject] FetchHeaders initializeWith(FetchRequest input, Dictionary init);
+    [PrivateIdentifier, NewObject] FetchHeaders initializeWith(DOMString input, Dictionary init);
</ins><span class="cx">     [PrivateIdentifier, MayThrowLegacyException, CallWith=ScriptState] void setBody(any body, FetchRequest? request);
</span><span class="cx"> };
</span><span class="cx"> FetchRequest implements FetchBody;
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsJSDOMBindingcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/JSDOMBinding.cpp (206953 => 206954)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/JSDOMBinding.cpp        2016-10-08 13:09:30 UTC (rev 206953)
+++ trunk/Source/WebCore/bindings/js/JSDOMBinding.cpp        2016-10-08 14:49:47 UTC (rev 206954)
</span><span class="lines">@@ -376,6 +376,17 @@
</span><span class="cx">     throwDOMException(exec, scope, ec);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void setDOMException(ExecState* exec, ExceptionCode ec, const String&amp; message)
+{
+    VM&amp; vm = exec-&gt;vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
+    if (!ec || scope.exception())
+        return;
+
+    throwException(exec, scope, createDOMException(exec, ec, message));
+}
+
</ins><span class="cx"> void setDOMException(ExecState* exec, const ExceptionCodeWithMessage&amp; ec)
</span><span class="cx"> {
</span><span class="cx">     VM&amp; vm = exec-&gt;vm();
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsJSDOMBindingh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/JSDOMBinding.h (206953 => 206954)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/JSDOMBinding.h        2016-10-08 13:09:30 UTC (rev 206953)
+++ trunk/Source/WebCore/bindings/js/JSDOMBinding.h        2016-10-08 14:49:47 UTC (rev 206954)
</span><span class="lines">@@ -187,6 +187,7 @@
</span><span class="cx"> 
</span><span class="cx"> // Convert a DOM implementation exception code into a JavaScript exception in the execution state.
</span><span class="cx"> WEBCORE_EXPORT void setDOMException(JSC::ExecState*, ExceptionCode);
</span><ins>+void setDOMException(JSC::ExecState*, ExceptionCode, const String&amp;);
</ins><span class="cx"> void setDOMException(JSC::ExecState*, const ExceptionCodeWithMessage&amp;);
</span><span class="cx"> 
</span><span class="cx"> WEBCORE_EXPORT void setDOMExceptionSlow(JSC::ExecState*, JSC::ThrowScope&amp;, ExceptionCode);
</span><span class="lines">@@ -946,7 +947,7 @@
</span><span class="cx"> template&lt;typename T&gt; inline JSC::JSValue toJS(JSC::ExecState* state, JSDOMGlobalObject* globalObject, ExceptionOr&lt;T&gt;&amp;&amp; value)
</span><span class="cx"> {
</span><span class="cx">     if (UNLIKELY(value.hasException())) {
</span><del>-        setDOMException(state, value.exceptionCode());
</del><ins>+        setDOMException(state, value.exceptionCode(), value.exceptionMessage());
</ins><span class="cx">         return JSC::jsUndefined();
</span><span class="cx">     }
</span><span class="cx">     return toJS(state, globalObject, value.takeReturnValue());
</span><span class="lines">@@ -956,7 +957,7 @@
</span><span class="cx"> {
</span><span class="cx">     // FIXME: It's really annoying to have two of these functions. Should find a way to combine toJS and toJSNewlyCreated.
</span><span class="cx">     if (UNLIKELY(value.hasException())) {
</span><del>-        setDOMException(state, value.exceptionCode());
</del><ins>+        setDOMException(state, value.exceptionCode(), value.exceptionMessage());
</ins><span class="cx">         return JSC::jsUndefined();
</span><span class="cx">     }
</span><span class="cx">     return toJSNewlyCreated(state, globalObject, value.takeReturnValue());
</span></span></pre></div>
<a id="trunkSourceWebCoredomExceptionh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/Exception.h (206953 => 206954)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/Exception.h        2016-10-08 13:09:30 UTC (rev 206953)
+++ trunk/Source/WebCore/dom/Exception.h        2016-10-08 14:49:47 UTC (rev 206954)
</span><span class="lines">@@ -26,6 +26,8 @@
</span><span class="cx"> 
</span><span class="cx"> #pragma once
</span><span class="cx"> 
</span><ins>+#include &lt;wtf/text/WTFString.h&gt;
+
</ins><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><span class="cx"> using ExceptionCode = int;
</span><span class="lines">@@ -33,11 +35,14 @@
</span><span class="cx"> class Exception {
</span><span class="cx"> public:
</span><span class="cx">     explicit Exception(ExceptionCode);
</span><ins>+    explicit Exception(ExceptionCode, const String&amp;);
</ins><span class="cx"> 
</span><del>-    ExceptionCode code() const;
</del><ins>+    ExceptionCode code() const { return m_code; }
+    const String&amp; message() const { return m_message; }
</ins><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     ExceptionCode m_code;
</span><ins>+    String m_message;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> inline Exception::Exception(ExceptionCode code)
</span><span class="lines">@@ -45,9 +50,10 @@
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline ExceptionCode Exception::code() const
</del><ins>+inline Exception::Exception(ExceptionCode code, const String&amp; message)
+    : m_code(code)
+    , m_message(message)
</ins><span class="cx"> {
</span><del>-    return m_code;
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCoredomExceptionOrh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/ExceptionOr.h (206953 => 206954)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/ExceptionOr.h        2016-10-08 13:09:30 UTC (rev 206953)
+++ trunk/Source/WebCore/dom/ExceptionOr.h        2016-10-08 14:49:47 UTC (rev 206954)
</span><span class="lines">@@ -38,6 +38,7 @@
</span><span class="cx"> 
</span><span class="cx">     bool hasException() const;
</span><span class="cx">     ExceptionCode exceptionCode() const;
</span><ins>+    const String&amp; exceptionMessage() const;
</ins><span class="cx">     ReturnType&amp;&amp; takeReturnValue();
</span><span class="cx"> 
</span><span class="cx"> private:
</span><span class="lines">@@ -64,6 +65,11 @@
</span><span class="cx">     return std::experimental::get&lt;Exception&gt;(m_value).code();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+template&lt;typename ReturnType&gt; inline const String&amp; ExceptionOr&lt;ReturnType&gt;::exceptionMessage() const
+{
+    return std::experimental::get&lt;Exception&gt;(m_value).message();
+}
+
</ins><span class="cx"> template&lt;typename ReturnType&gt; inline ReturnType&amp;&amp; ExceptionOr&lt;ReturnType&gt;::takeReturnValue()
</span><span class="cx"> {
</span><span class="cx">     return std::experimental::get&lt;ReturnType&gt;(WTFMove(m_value));
</span></span></pre>
</div>
</div>

</body>
</html>