<!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>[185739] trunk/Source/WebCore</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/185739">185739</a></dd>
<dt>Author</dt> <dd>youenn.fablet@crf.canon.fr</dd>
<dt>Date</dt> <dd>2015-06-19 00:33:35 -0700 (Fri, 19 Jun 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>Bindings generator should generate code to catch exception and reject promises for Promise-based APIs
https://bugs.webkit.org/show_bug.cgi?id=146060

Reviewed by Darin Adler.

The binding generator splits the function that binds JS to the DOM class implementation in two for functions returning promise.
The first function, called from JS, is responsible of casting this to the expected JSXXX class.
If casting fails, an exception is raised. Otherwise, it calls the second function.
After calling the second function, it checks whether an exception is raised, in which case it returns a rejected promise.
The second function is responsible of argument conversion and calling the DOM class function.

Covered by expectations and AudioContext promise still working.
A test case is added for a promise returning function taking a typed argument as input (if argument value cannot be typed, the promise is rejected).
A second test case is a promise-returning function that can raise an exception. In that case the DOMException is used as rejection value.

As can be seen from generated code, this generalized code adds a mandatory check (is there an exception?) at the end of the function.
This check is done even in cases we know there will be no exception.
This may be covered by another patch if this optimization is thought useful enough.

* bindings/js/JSDOMPromise.cpp:
(WebCore::rejectPromiseWithExceptionIfAny): Utility method for the binding code.
(WebCore::callPromiseFunction): Ditto.
* bindings/js/JSDOMPromise.h:
* bindings/scripts/CodeGeneratorJS.pm:
(GenerateImplementation):
(GenerateFunctionCastedThis): Extracted from GenerateImplementationFunctionCall to reuse it in case of promise-returning functions.
(GenerateImplementationFunctionCall):
(GenerateCallbackImplementation): Deleted.
* bindings/scripts/test/JS/JSTestObj.cpp:
(WebCore::jsTestObjPrototypeFunctionTestPromiseFunction):
(WebCore::jsTestObjPrototypeFunctionTestPromiseFunctionPromise):
(WebCore::jsTestObjPrototypeFunctionTestPromiseFunctionWithFloatArgument):
(WebCore::jsTestObjPrototypeFunctionTestPromiseFunctionWithFloatArgumentPromise):
(WebCore::jsTestObjPrototypeFunctionTestPromiseFunctionWithException):
(WebCore::jsTestObjPrototypeFunctionTestPromiseFunctionWithExceptionPromise):
* bindings/scripts/test/TestObj.idl:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCorebindingsjsJSDOMPromisecpp">trunk/Source/WebCore/bindings/js/JSDOMPromise.cpp</a></li>
<li><a href="#trunkSourceWebCorebindingsjsJSDOMPromiseh">trunk/Source/WebCore/bindings/js/JSDOMPromise.h</a></li>
<li><a href="#trunkSourceWebCorebindingsscriptsCodeGeneratorJSpm">trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm</a></li>
<li><a href="#trunkSourceWebCorebindingsscriptstestJSJSTestObjcpp">trunk/Source/WebCore/bindings/scripts/test/JS/JSTestObj.cpp</a></li>
<li><a href="#trunkSourceWebCorebindingsscriptstestTestObjidl">trunk/Source/WebCore/bindings/scripts/test/TestObj.idl</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (185738 => 185739)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2015-06-19 06:55:38 UTC (rev 185738)
+++ trunk/Source/WebCore/ChangeLog        2015-06-19 07:33:35 UTC (rev 185739)
</span><span class="lines">@@ -1,3 +1,42 @@
</span><ins>+2015-06-19  Youenn Fablet  &lt;youenn.fablet@crf.canon.fr&gt;
+
+        Bindings generator should generate code to catch exception and reject promises for Promise-based APIs
+        https://bugs.webkit.org/show_bug.cgi?id=146060
+
+        Reviewed by Darin Adler.
+
+        The binding generator splits the function that binds JS to the DOM class implementation in two for functions returning promise.
+        The first function, called from JS, is responsible of casting this to the expected JSXXX class.
+        If casting fails, an exception is raised. Otherwise, it calls the second function.
+        After calling the second function, it checks whether an exception is raised, in which case it returns a rejected promise.
+        The second function is responsible of argument conversion and calling the DOM class function.
+
+        Covered by expectations and AudioContext promise still working.
+        A test case is added for a promise returning function taking a typed argument as input (if argument value cannot be typed, the promise is rejected).
+        A second test case is a promise-returning function that can raise an exception. In that case the DOMException is used as rejection value.
+
+        As can be seen from generated code, this generalized code adds a mandatory check (is there an exception?) at the end of the function.
+        This check is done even in cases we know there will be no exception.
+        This may be covered by another patch if this optimization is thought useful enough.
+
+        * bindings/js/JSDOMPromise.cpp:
+        (WebCore::rejectPromiseWithExceptionIfAny): Utility method for the binding code.
+        (WebCore::callPromiseFunction): Ditto.
+        * bindings/js/JSDOMPromise.h:
+        * bindings/scripts/CodeGeneratorJS.pm:
+        (GenerateImplementation):
+        (GenerateFunctionCastedThis): Extracted from GenerateImplementationFunctionCall to reuse it in case of promise-returning functions.
+        (GenerateImplementationFunctionCall):
+        (GenerateCallbackImplementation): Deleted.
+        * bindings/scripts/test/JS/JSTestObj.cpp:
+        (WebCore::jsTestObjPrototypeFunctionTestPromiseFunction):
+        (WebCore::jsTestObjPrototypeFunctionTestPromiseFunctionPromise):
+        (WebCore::jsTestObjPrototypeFunctionTestPromiseFunctionWithFloatArgument):
+        (WebCore::jsTestObjPrototypeFunctionTestPromiseFunctionWithFloatArgumentPromise):
+        (WebCore::jsTestObjPrototypeFunctionTestPromiseFunctionWithException):
+        (WebCore::jsTestObjPrototypeFunctionTestPromiseFunctionWithExceptionPromise):
+        * bindings/scripts/test/TestObj.idl:
+
</ins><span class="cx"> 2015-06-18  Jeremy Jones  &lt;jeremyj@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Disable UIWindow for fullscreen video for selected clients.
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsJSDOMPromisecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/JSDOMPromise.cpp (185738 => 185739)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/JSDOMPromise.cpp        2015-06-19 06:55:38 UTC (rev 185738)
+++ trunk/Source/WebCore/bindings/js/JSDOMPromise.cpp        2015-06-19 07:33:35 UTC (rev 185739)
</span><span class="lines">@@ -29,6 +29,7 @@
</span><span class="cx"> #if ENABLE(PROMISES)
</span><span class="cx"> 
</span><span class="cx"> #include &quot;ExceptionCode.h&quot;
</span><ins>+#include &lt;runtime/Exception.h&gt;
</ins><span class="cx"> 
</span><span class="cx"> using namespace JSC;
</span><span class="cx"> 
</span><span class="lines">@@ -62,6 +63,17 @@
</span><span class="cx">     m_deferred.clear();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void rejectPromiseWithExceptionIfAny(JSC::ExecState&amp; state, JSDOMGlobalObject&amp; globalObject, JSPromiseDeferred&amp; promiseDeferred)
+{
+    if (!state.hadException())
+        return;
+
+    JSValue error = state.exception()-&gt;value();
+    state.clearException();
+
+    DeferredWrapper(&amp;state, &amp;globalObject, &amp;promiseDeferred).reject(error);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+}
+
</ins><span class="cx"> #endif // ENABLE(PROMISES)
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsJSDOMPromiseh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/JSDOMPromise.h (185738 => 185739)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/JSDOMPromise.h        2015-06-19 06:55:38 UTC (rev 185738)
+++ trunk/Source/WebCore/bindings/js/JSDOMPromise.h        2015-06-19 07:33:35 UTC (rev 185739)
</span><span class="lines">@@ -57,6 +57,19 @@
</span><span class="cx">     JSC::Strong&lt;JSC::JSPromiseDeferred&gt; m_deferred;
</span><span class="cx"> };
</span><span class="cx"> 
</span><ins>+void rejectPromiseWithExceptionIfAny(JSC::ExecState&amp;, JSDOMGlobalObject&amp;, JSC::JSPromiseDeferred&amp;);
+
+template&lt;class JSClassName&gt;
+inline JSC::JSValue callPromiseFunction(JSC::ExecState&amp; state, JSClassName&amp; jsObject, JSC::EncodedJSValue promiseFunction(JSC::ExecState*, JSClassName*, JSC::JSPromiseDeferred*))
+{
+    JSC::JSPromiseDeferred* promiseDeferred = JSC::JSPromiseDeferred::create(&amp;state, jsObject.globalObject());
+    promiseFunction(&amp;state, &amp;jsObject, promiseDeferred);
+
+    rejectPromiseWithExceptionIfAny(state, *jsObject.globalObject(), *promiseDeferred);
+    ASSERT(!state.hadException());
+    return promiseDeferred-&gt;promise();
+}
+
</ins><span class="cx"> template &lt;typename Value, typename Error&gt;
</span><span class="cx"> class DOMPromise {
</span><span class="cx"> public:
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsscriptsCodeGeneratorJSpm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm (185738 => 185739)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm        2015-06-19 06:55:38 UTC (rev 185738)
+++ trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm        2015-06-19 07:33:35 UTC (rev 185739)
</span><span class="lines">@@ -2780,7 +2780,23 @@
</span><span class="cx"> 
</span><span class="cx">             my $functionImplementationName = $function-&gt;signature-&gt;extendedAttributes-&gt;{&quot;ImplementedAs&quot;} || $codeGenerator-&gt;WK_lcfirst($function-&gt;signature-&gt;name);
</span><span class="cx"> 
</span><del>-            push(@implContent, &quot;EncodedJSValue JSC_HOST_CALL ${functionName}(ExecState* exec)\n&quot;);
</del><ins>+            if (IsReturningPromise($function) &amp;&amp; !$isCustom) {
+                AddToImplIncludes(&quot;JSDOMPromise.h&quot;);
+
+                push(@implContent, &quot;static inline EncodedJSValue ${functionName}Promise(ExecState*, &quot; . $className . &quot;*, JSPromiseDeferred*);\n&quot;);
+                push(@implContent, &quot;EncodedJSValue JSC_HOST_CALL ${functionName}(ExecState* exec)\n&quot;);
+                push(@implContent, &quot;{\n&quot;);
+
+                GenerateFunctionCastedThis($interface, $interfaceName, $className, $function);
+                push(@implContent, &quot;    return JSValue::encode(callPromiseFunction(*exec, *castedThis, ${functionName}Promise));\n&quot;);
+
+                push(@implContent, &quot;}\n&quot;);
+                push(@implContent, &quot;\nstatic inline EncodedJSValue ${functionName}Promise(ExecState* exec, &quot; . $className . &quot;* castedThis, JSPromiseDeferred* promiseDeferred)\n&quot;);
+            }
+            else {
+                push(@implContent, &quot;EncodedJSValue JSC_HOST_CALL ${functionName}(ExecState* exec)\n&quot;);
+            }
+
</ins><span class="cx">             push(@implContent, &quot;{\n&quot;);
</span><span class="cx"> 
</span><span class="cx">             $implIncludes{&quot;&lt;runtime/Error.h&gt;&quot;} = 1;
</span><span class="lines">@@ -2799,24 +2815,8 @@
</span><span class="cx">                     GenerateImplementationFunctionCall($function, $functionString, &quot;    &quot;, $svgPropertyType, $interfaceName);
</span><span class="cx">                 }
</span><span class="cx">             } else {
</span><del>-                if ($interface-&gt;extendedAttributes-&gt;{&quot;CustomProxyToJSObject&quot;}) {
-                    push(@implContent, &quot;    $className* castedThis = to${className}(exec-&gt;thisValue().toThis(exec, NotStrictMode));\n&quot;);
-                    push(@implContent, &quot;    if (UNLIKELY(!castedThis))\n&quot;);
-                    push(@implContent, &quot;        return throwVMTypeError(exec);\n&quot;);
-                } elsif ($interface-&gt;extendedAttributes-&gt;{&quot;WorkerGlobalScope&quot;}) {
-                    push(@implContent, &quot;    $className* castedThis = to${className}(exec-&gt;thisValue().toThis(exec, NotStrictMode));\n&quot;);
-                    push(@implContent, &quot;    if (UNLIKELY(!castedThis))\n&quot;);
-                    push(@implContent, &quot;        return throwVMTypeError(exec);\n&quot;);
-                } else {
-                    push(@implContent, &quot;    JSValue thisValue = exec-&gt;thisValue();\n&quot;);
-                    push(@implContent, &quot;    $className* castedThis = &quot; . GetCastingHelperForThisObject($interface) . &quot;(thisValue);\n&quot;);
-                    my $domFunctionName = $function-&gt;signature-&gt;name;
-                    push(@implContent, &quot;    if (UNLIKELY(!castedThis))\n&quot;);
-                    push(@implContent, &quot;        return throwThisTypeError(*exec, \&quot;$interfaceName\&quot;, \&quot;$domFunctionName\&quot;);\n&quot;);
-                }
</del><ins>+                GenerateFunctionCastedThis($interface, $interfaceName, $className, $function) if not (IsReturningPromise($function) &amp;&amp; !$isCustom);
</ins><span class="cx"> 
</span><del>-                push(@implContent, &quot;    ASSERT_GC_OBJECT_INHERITS(castedThis, ${className}::info());\n&quot;);
-
</del><span class="cx">                 if ($interface-&gt;extendedAttributes-&gt;{&quot;CheckSecurity&quot;} and
</span><span class="cx">                     !$function-&gt;signature-&gt;extendedAttributes-&gt;{&quot;DoNotCheckSecurity&quot;}) {
</span><span class="cx">                     push(@implContent, &quot;    if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, castedThis-&gt;impl()))\n&quot;);
</span><span class="lines">@@ -3111,6 +3111,31 @@
</span><span class="cx">     push(@implContent, &quot;\n#endif // ${conditionalString}\n&quot;) if $conditionalString;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+sub GenerateFunctionCastedThis
+{
+    my $interface = shift;
+    my $interfaceName = shift;
+    my $className = shift;
+    my $function = shift;
+    if ($interface-&gt;extendedAttributes-&gt;{&quot;CustomProxyToJSObject&quot;}) {
+        push(@implContent, &quot;    $className* castedThis = to${className}(exec-&gt;thisValue().toThis(exec, NotStrictMode));\n&quot;);
+        push(@implContent, &quot;    if (UNLIKELY(!castedThis))\n&quot;);
+        push(@implContent, &quot;        return throwVMTypeError(exec);\n&quot;);
+    } elsif ($interface-&gt;extendedAttributes-&gt;{&quot;WorkerGlobalScope&quot;}) {
+        push(@implContent, &quot;    $className* castedThis = to${className}(exec-&gt;thisValue().toThis(exec, NotStrictMode));\n&quot;);
+        push(@implContent, &quot;    if (UNLIKELY(!castedThis))\n&quot;);
+        push(@implContent, &quot;        return throwVMTypeError(exec);\n&quot;);
+    } else {
+        push(@implContent, &quot;    JSValue thisValue = exec-&gt;thisValue();\n&quot;);
+        push(@implContent, &quot;    $className* castedThis = &quot; . GetCastingHelperForThisObject($interface) . &quot;(thisValue);\n&quot;);
+        my $domFunctionName = $function-&gt;signature-&gt;name;
+        push(@implContent, &quot;    if (UNLIKELY(!castedThis))\n&quot;);
+        push(@implContent, &quot;        return throwThisTypeError(*exec, \&quot;$interfaceName\&quot;, \&quot;$domFunctionName\&quot;);\n&quot;);
+    }
+
+    push(@implContent, &quot;    ASSERT_GC_OBJECT_INHERITS(castedThis, ${className}::info());\n&quot;);
+}
+
</ins><span class="cx"> sub GenerateCallWith
</span><span class="cx"> {
</span><span class="cx">     my $callWith = shift;
</span><span class="lines">@@ -3595,7 +3620,7 @@
</span><span class="cx">     my $nondeterministic = $function-&gt;signature-&gt;extendedAttributes-&gt;{&quot;Nondeterministic&quot;};
</span><span class="cx">     my $raisesException = $function-&gt;signature-&gt;extendedAttributes-&gt;{&quot;RaisesException&quot;};
</span><span class="cx"> 
</span><del>-    if ($function-&gt;signature-&gt;type eq &quot;void&quot;) {
</del><ins>+    if ($function-&gt;signature-&gt;type eq &quot;void&quot; || IsReturningPromise($function)) {
</ins><span class="cx">         if ($nondeterministic) {
</span><span class="cx">             AddToImplIncludes(&quot;&lt;replay/InputCursor.h&gt;&quot;, &quot;WEB_REPLAY&quot;);
</span><span class="cx">             push(@implContent, &quot;#if ENABLE(WEB_REPLAY)\n&quot;);
</span><span class="lines">@@ -3656,17 +3681,9 @@
</span><span class="cx">             push(@implContent, &quot;#else\n&quot;);
</span><span class="cx">             push(@implContent, $indent . &quot;result = &quot; . NativeToJSValue($function-&gt;signature, 1, $interfaceName, $functionString, $thisObject) . &quot;;\n&quot;);
</span><span class="cx">             push(@implContent, &quot;#endif\n&quot;);
</span><del>-        } elsif (IsReturningPromise($function)) {
-            AddToImplIncludes(&quot;JSDOMPromise.h&quot;);
-
-            push(@implContent, $indent . &quot;JSPromiseDeferred* promiseDeferred = JSPromiseDeferred::create(exec, castedThis-&gt;globalObject());\n&quot;);
-            push(@implContent, $indent . $functionString . &quot;;\n&quot;);
-            push(@implContent, $indent . &quot;JSValue result = promiseDeferred-&gt;promise();\n&quot;);
-
</del><span class="cx">         } else {
</span><span class="cx">             push(@implContent, $indent . &quot;JSValue result = &quot; . NativeToJSValue($function-&gt;signature, 1, $interfaceName, $functionString, $thisObject) . &quot;;\n&quot;);
</span><span class="cx">         }
</span><del>-        # FIXME: In case of IsReturningPromise($function), the function should not throw. Exception should be used to reject the promise callback.
</del><span class="cx">         push(@implContent, &quot;\n&quot; . $indent . &quot;setDOMException(exec, ec);\n&quot;) if $raisesException;
</span><span class="cx"> 
</span><span class="cx">         if ($codeGenerator-&gt;ExtendedAttributeContains($function-&gt;signature-&gt;extendedAttributes-&gt;{&quot;CallWith&quot;}, &quot;ScriptState&quot;)) {
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsscriptstestJSJSTestObjcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/scripts/test/JS/JSTestObj.cpp (185738 => 185739)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/scripts/test/JS/JSTestObj.cpp        2015-06-19 06:55:38 UTC (rev 185738)
+++ trunk/Source/WebCore/bindings/scripts/test/JS/JSTestObj.cpp        2015-06-19 07:33:35 UTC (rev 185739)
</span><span class="lines">@@ -156,6 +156,8 @@
</span><span class="cx"> JSC::EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionVariadicNodeMethod(JSC::ExecState*);
</span><span class="cx"> JSC::EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionAny(JSC::ExecState*);
</span><span class="cx"> JSC::EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionTestPromiseFunction(JSC::ExecState*);
</span><ins>+JSC::EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionTestPromiseFunctionWithFloatArgument(JSC::ExecState*);
+JSC::EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionTestPromiseFunctionWithException(JSC::ExecState*);
</ins><span class="cx"> 
</span><span class="cx"> // Attributes
</span><span class="cx"> 
</span><span class="lines">@@ -651,6 +653,8 @@
</span><span class="cx">     { &quot;variadicNodeMethod&quot;, JSC::Function, NoIntrinsic, (intptr_t)static_cast&lt;NativeFunction&gt;(jsTestObjPrototypeFunctionVariadicNodeMethod), (intptr_t) (2) },
</span><span class="cx">     { &quot;any&quot;, JSC::Function, NoIntrinsic, (intptr_t)static_cast&lt;NativeFunction&gt;(jsTestObjPrototypeFunctionAny), (intptr_t) (2) },
</span><span class="cx">     { &quot;testPromiseFunction&quot;, JSC::Function, NoIntrinsic, (intptr_t)static_cast&lt;NativeFunction&gt;(jsTestObjPrototypeFunctionTestPromiseFunction), (intptr_t) (0) },
</span><ins>+    { &quot;testPromiseFunctionWithFloatArgument&quot;, JSC::Function, NoIntrinsic, (intptr_t)static_cast&lt;NativeFunction&gt;(jsTestObjPrototypeFunctionTestPromiseFunctionWithFloatArgument), (intptr_t) (1) },
+    { &quot;testPromiseFunctionWithException&quot;, JSC::Function, NoIntrinsic, (intptr_t)static_cast&lt;NativeFunction&gt;(jsTestObjPrototypeFunctionTestPromiseFunctionWithException), (intptr_t) (0) },
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> const ClassInfo JSTestObjPrototype::s_info = { &quot;TestObjectPrototype&quot;, &amp;Base::s_info, 0, CREATE_METHOD_TABLE(JSTestObjPrototype) };
</span><span class="lines">@@ -4426,6 +4430,7 @@
</span><span class="cx">     return JSValue::encode(jsUndefined());
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static inline EncodedJSValue jsTestObjPrototypeFunctionTestPromiseFunctionPromise(ExecState*, JSTestObj*, JSPromiseDeferred*);
</ins><span class="cx"> EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionTestPromiseFunction(ExecState* exec)
</span><span class="cx"> {
</span><span class="cx">     JSValue thisValue = exec-&gt;thisValue();
</span><span class="lines">@@ -4433,13 +4438,63 @@
</span><span class="cx">     if (UNLIKELY(!castedThis))
</span><span class="cx">         return throwThisTypeError(*exec, &quot;TestObj&quot;, &quot;testPromiseFunction&quot;);
</span><span class="cx">     ASSERT_GC_OBJECT_INHERITS(castedThis, JSTestObj::info());
</span><ins>+    return JSValue::encode(callPromiseFunction(*exec, *castedThis, jsTestObjPrototypeFunctionTestPromiseFunctionPromise));
+}
+
+static inline EncodedJSValue jsTestObjPrototypeFunctionTestPromiseFunctionPromise(ExecState* exec, JSTestObj* castedThis, JSPromiseDeferred* promiseDeferred)
+{
</ins><span class="cx">     auto&amp; impl = castedThis-&gt;impl();
</span><del>-    JSPromiseDeferred* promiseDeferred = JSPromiseDeferred::create(exec, castedThis-&gt;globalObject());
</del><span class="cx">     impl.testPromiseFunction(DeferredWrapper(exec, castedThis-&gt;globalObject(), promiseDeferred));
</span><del>-    JSValue result = promiseDeferred-&gt;promise();
-    return JSValue::encode(result);
</del><ins>+    return JSValue::encode(jsUndefined());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static inline EncodedJSValue jsTestObjPrototypeFunctionTestPromiseFunctionWithFloatArgumentPromise(ExecState*, JSTestObj*, JSPromiseDeferred*);
+EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionTestPromiseFunctionWithFloatArgument(ExecState* exec)
+{
+    JSValue thisValue = exec-&gt;thisValue();
+    JSTestObj* castedThis = jsDynamicCast&lt;JSTestObj*&gt;(thisValue);
+    if (UNLIKELY(!castedThis))
+        return throwThisTypeError(*exec, &quot;TestObj&quot;, &quot;testPromiseFunctionWithFloatArgument&quot;);
+    ASSERT_GC_OBJECT_INHERITS(castedThis, JSTestObj::info());
+    return JSValue::encode(callPromiseFunction(*exec, *castedThis, jsTestObjPrototypeFunctionTestPromiseFunctionWithFloatArgumentPromise));
+}
+
+static inline EncodedJSValue jsTestObjPrototypeFunctionTestPromiseFunctionWithFloatArgumentPromise(ExecState* exec, JSTestObj* castedThis, JSPromiseDeferred* promiseDeferred)
+{
+    auto&amp; impl = castedThis-&gt;impl();
+    if (UNLIKELY(exec-&gt;argumentCount() &lt; 1))
+        return throwVMError(exec, createNotEnoughArgumentsError(exec));
+    float a = exec-&gt;argument(0).toFloat(exec);
+    if (UNLIKELY(exec-&gt;hadException()))
+        return JSValue::encode(jsUndefined());
+    if (!std::isfinite(a)) {
+        setDOMException(exec, TypeError);
+        return JSValue::encode(jsUndefined());
+    }
+    impl.testPromiseFunctionWithFloatArgument(a, DeferredWrapper(exec, castedThis-&gt;globalObject(), promiseDeferred));
+    return JSValue::encode(jsUndefined());
+}
+
+static inline EncodedJSValue jsTestObjPrototypeFunctionTestPromiseFunctionWithExceptionPromise(ExecState*, JSTestObj*, JSPromiseDeferred*);
+EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionTestPromiseFunctionWithException(ExecState* exec)
+{
+    JSValue thisValue = exec-&gt;thisValue();
+    JSTestObj* castedThis = jsDynamicCast&lt;JSTestObj*&gt;(thisValue);
+    if (UNLIKELY(!castedThis))
+        return throwThisTypeError(*exec, &quot;TestObj&quot;, &quot;testPromiseFunctionWithException&quot;);
+    ASSERT_GC_OBJECT_INHERITS(castedThis, JSTestObj::info());
+    return JSValue::encode(callPromiseFunction(*exec, *castedThis, jsTestObjPrototypeFunctionTestPromiseFunctionWithExceptionPromise));
+}
+
+static inline EncodedJSValue jsTestObjPrototypeFunctionTestPromiseFunctionWithExceptionPromise(ExecState* exec, JSTestObj* castedThis, JSPromiseDeferred* promiseDeferred)
+{
+    auto&amp; impl = castedThis-&gt;impl();
+    ExceptionCode ec = 0;
+    impl.testPromiseFunctionWithException(DeferredWrapper(exec, castedThis-&gt;globalObject(), promiseDeferred), ec);
+    setDOMException(exec, ec);
+    return JSValue::encode(jsUndefined());
+}
+
</ins><span class="cx"> void JSTestObj::visitChildren(JSCell* cell, SlotVisitor&amp; visitor)
</span><span class="cx"> {
</span><span class="cx">     auto* thisObject = jsCast&lt;JSTestObj*&gt;(cell);
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsscriptstestTestObjidl"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/scripts/test/TestObj.idl (185738 => 185739)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/scripts/test/TestObj.idl        2015-06-19 06:55:38 UTC (rev 185738)
+++ trunk/Source/WebCore/bindings/scripts/test/TestObj.idl        2015-06-19 07:33:35 UTC (rev 185739)
</span><span class="lines">@@ -276,6 +276,8 @@
</span><span class="cx"> 
</span><span class="cx">     // Promise function
</span><span class="cx">     Promise testPromiseFunction();
</span><ins>+    Promise testPromiseFunctionWithFloatArgument(float a);
+    [RaisesException] Promise testPromiseFunctionWithException();
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> // The following comment should not generate any code.
</span></span></pre>
</div>
</div>

</body>
</html>