<!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>[167142] 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/167142">167142</a></dd>
<dt>Author</dt> <dd>mark.lam@apple.com</dd>
<dt>Date</dt> <dd>2014-04-11 13:24:56 -0700 (Fri, 11 Apr 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>JSMainThreadExecState::call() should clear exceptions before returning.
&lt;https://webkit.org/b/131530&gt;

Reviewed by Geoffrey Garen.

Source/JavaScriptCore: 

Added a version of JSC::call() that return any uncaught exception instead
of leaving it pending in the VM.

As part of this change, I updated various parts of the code base to use the
new API as needed.

* bindings/ScriptFunctionCall.cpp:
(Deprecated::ScriptFunctionCall::call):
- ScriptFunctionCall::call() is only used by the inspector to inject scripts.
  The injected scripts that will include Inspector scripts that should catch
  and handle any exceptions that were thrown.  We should not be seeing any
  exceptions returned from this call.  However, we do have checks for
  exceptions in case there are bugs in the Inspector scripts which allowed
  the exception to leak through.  Hence, it is proper to clear the exception
  here, and only record the fact that an exception was seen (if present).

* bindings/ScriptFunctionCall.h:
* inspector/InspectorEnvironment.h:
* runtime/CallData.cpp:
(JSC::call):
* runtime/CallData.h:

Source/WebCore: 

Test: fast/dom/regress-131530.html

Previously, JSMainThreadExecState::call() did not clear any pending
exceptions in the VM before returning.  On returning, the
JSMainThreadExecState destructor may re-enter the VM to notify
MutationObservers.  This may result in a crash because the VM expects
exceptions to be cleared at entry.

We now change JSMainThreadExecState::call() to return the exception
(if present) via an argument, and clear it from the VM before returning.

As part of this change, I updated various parts of the code base to use the
new API as needed.

* bindings/js/JSCallbackData.cpp:
(WebCore::JSCallbackData::invokeCallback):
* bindings/js/JSCustomXPathNSResolver.cpp:
(WebCore::JSCustomXPathNSResolver::lookupNamespaceURI):
* bindings/js/JSDOMGlobalObjectTask.cpp:
- Assert that there's no unhandled exception after the Microtask returns.
  See comment for WebCore::JSMainThreadExecState::runTask below for more
  details.

* bindings/js/JSErrorHandler.cpp:
(WebCore::JSErrorHandler::handleEvent):
* bindings/js/JSEventListener.cpp:
(WebCore::JSEventListener::handleEvent):
* bindings/js/JSHTMLDocumentCustom.cpp:
(WebCore::JSHTMLDocument::open):
- Document.open() cannot be the first function on the JS stack.  Hence,
  there is no need to use JSMainThreadExecState to call into the VM, as
  this is only needed to catch the event of returning from the first
  function for the purpose of notifying MutationObservers.  Change to
  call JSC::call() directly.

* bindings/js/JSMainThreadExecState.cpp:
(WebCore::functionCallHandlerFromAnyThread):
* bindings/js/JSMainThreadExecState.h:
(WebCore::JSMainThreadExecState::call):
(WebCore::JSMainThreadExecState::evaluate):
- Remove the explicitly acquisition of the JSLock here because we now
  acquire the JSLock as part of the JSMainThreadExecState instance.
(WebCore::JSMainThreadExecState::runTask):
- Added an assert to verify that the task does not return with an
  unhandled exception.  Currently, the only Microtask in use is for the
  Promise implementation, which will eat the exception before returning.
  This assertion is added here to verify that this contract does not
  inadvertantly change in the future.
(WebCore::JSMainThreadExecState::JSMainThreadExecState):
- Now acquires the JSLock as well since by definition, we're only
  instantiating the JSMainThreadExecState because we're about to enter
  the VM.

* bindings/js/JSMutationCallback.cpp:
(WebCore::JSMutationCallback::call):
* bindings/js/JSNodeFilterCondition.cpp:
(WebCore::JSNodeFilterCondition::acceptNode):
- acceptNode() is only used in the TreeWalker and NodeIterator APIs which
  cannot be the first function on the JS stack.  Hence, we should call
  JSC::call() directly instead of going through JSMainThreadExecState.

* bindings/js/ScheduledAction.cpp:
(WebCore::ScheduledAction::executeFunctionInContext):
* bindings/objc/WebScriptObject.mm:
(WebCore::addExceptionToConsole):
(-[WebScriptObject callWebScriptMethod:withArguments:]):

LayoutTests: 

* fast/dom/regress-131530-expected.txt: Added.
* fast/dom/regress-131530.html: Added.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCorebindingsScriptFunctionCallcpp">trunk/Source/JavaScriptCore/bindings/ScriptFunctionCall.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebindingsScriptFunctionCallh">trunk/Source/JavaScriptCore/bindings/ScriptFunctionCall.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreinspectorInspectorEnvironmenth">trunk/Source/JavaScriptCore/inspector/InspectorEnvironment.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeCallDatacpp">trunk/Source/JavaScriptCore/runtime/CallData.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeCallDatah">trunk/Source/JavaScriptCore/runtime/CallData.h</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCorebindingsjsJSCallbackDatacpp">trunk/Source/WebCore/bindings/js/JSCallbackData.cpp</a></li>
<li><a href="#trunkSourceWebCorebindingsjsJSCustomXPathNSResolvercpp">trunk/Source/WebCore/bindings/js/JSCustomXPathNSResolver.cpp</a></li>
<li><a href="#trunkSourceWebCorebindingsjsJSDOMGlobalObjectTaskcpp">trunk/Source/WebCore/bindings/js/JSDOMGlobalObjectTask.cpp</a></li>
<li><a href="#trunkSourceWebCorebindingsjsJSErrorHandlercpp">trunk/Source/WebCore/bindings/js/JSErrorHandler.cpp</a></li>
<li><a href="#trunkSourceWebCorebindingsjsJSEventListenercpp">trunk/Source/WebCore/bindings/js/JSEventListener.cpp</a></li>
<li><a href="#trunkSourceWebCorebindingsjsJSHTMLDocumentCustomcpp">trunk/Source/WebCore/bindings/js/JSHTMLDocumentCustom.cpp</a></li>
<li><a href="#trunkSourceWebCorebindingsjsJSMainThreadExecStatecpp">trunk/Source/WebCore/bindings/js/JSMainThreadExecState.cpp</a></li>
<li><a href="#trunkSourceWebCorebindingsjsJSMainThreadExecStateh">trunk/Source/WebCore/bindings/js/JSMainThreadExecState.h</a></li>
<li><a href="#trunkSourceWebCorebindingsjsJSMutationCallbackcpp">trunk/Source/WebCore/bindings/js/JSMutationCallback.cpp</a></li>
<li><a href="#trunkSourceWebCorebindingsjsJSNodeFilterConditioncpp">trunk/Source/WebCore/bindings/js/JSNodeFilterCondition.cpp</a></li>
<li><a href="#trunkSourceWebCorebindingsjsScheduledActioncpp">trunk/Source/WebCore/bindings/js/ScheduledAction.cpp</a></li>
<li><a href="#trunkSourceWebCorebindingsobjcWebScriptObjectmm">trunk/Source/WebCore/bindings/objc/WebScriptObject.mm</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsfastdomregress131530expectedtxt">trunk/LayoutTests/fast/dom/regress-131530-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfastdomregress131530html">trunk/LayoutTests/fast/dom/regress-131530.html</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (167141 => 167142)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2014-04-11 20:22:17 UTC (rev 167141)
+++ trunk/LayoutTests/ChangeLog        2014-04-11 20:24:56 UTC (rev 167142)
</span><span class="lines">@@ -1,3 +1,13 @@
</span><ins>+2014-04-11  Mark Lam  &lt;mark.lam@apple.com&gt;
+
+        JSMainThreadExecState::call() should clear exceptions before returning.
+        &lt;https://webkit.org/b/131530&gt;
+
+        Reviewed by Geoffrey Garen.
+
+        * fast/dom/regress-131530-expected.txt: Added.
+        * fast/dom/regress-131530.html: Added.
+
</ins><span class="cx"> 2014-04-11  Carlos Alberto Lopez Perez  &lt;clopez@igalia.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [GTK] Unreviewed GTK gardening.
</span></span></pre></div>
<a id="trunkLayoutTestsfastdomregress131530expectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/dom/regress-131530-expected.txt (0 => 167142)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/dom/regress-131530-expected.txt                                (rev 0)
+++ trunk/LayoutTests/fast/dom/regress-131530-expected.txt        2014-04-11 20:24:56 UTC (rev 167142)
</span><span class="lines">@@ -0,0 +1,5 @@
</span><ins>+CONSOLE MESSAGE: line 5: Exception to trigger unwinding in MutationObserver
+CONSOLE MESSAGE: Pending exception before MutationObservers are called.
+Regression test for https://webkit.org/b/131530. This test should not crash.
+
+Mutate that node
</ins></span></pre></div>
<a id="trunkLayoutTestsfastdomregress131530html"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/dom/regress-131530.html (0 => 167142)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/dom/regress-131530.html                                (rev 0)
+++ trunk/LayoutTests/fast/dom/regress-131530.html        2014-04-11 20:24:56 UTC (rev 167142)
</span><span class="lines">@@ -0,0 +1,29 @@
</span><ins>+&lt;head&gt;
+&lt;script&gt;
+var observer = new MutationObserver(function(mutations) {
+    function foo() {
+        throw &quot;Exception to trigger unwinding in MutationObserver&quot;;
+    }
+    mutations.forEach(function(mutation) {
+        foo();
+    });
+});
+
+function test()
+{
+    if (window.testRunner)
+        testRunner.dumpAsText();
+
+    var node = document.getElementById('res');
+    var config = { attribute: true, childList: true, characterData: true };
+    observer.observe(node, config);
+
+    node.innerText += &quot;Mutate that node&quot;;
+    throw &quot;Pending exception before MutationObservers are called.&quot;;
+}
+&lt;/script&gt;
+&lt;/head&gt;
+&lt;body onload=&quot;test();&quot;&gt;
+&lt;p&gt;Regression test for https://webkit.org/b/131530. This test should not crash.&lt;form&gt;
+&lt;div id=&quot;res&quot;&gt;&lt;/div&gt;
+&lt;/body&gt;
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (167141 => 167142)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2014-04-11 20:22:17 UTC (rev 167141)
+++ trunk/Source/JavaScriptCore/ChangeLog        2014-04-11 20:24:56 UTC (rev 167142)
</span><span class="lines">@@ -1,3 +1,32 @@
</span><ins>+2014-04-11  Mark Lam  &lt;mark.lam@apple.com&gt;
+
+        JSMainThreadExecState::call() should clear exceptions before returning.
+        &lt;https://webkit.org/b/131530&gt;
+
+        Reviewed by Geoffrey Garen.
+
+        Added a version of JSC::call() that return any uncaught exception instead
+        of leaving it pending in the VM.
+
+        As part of this change, I updated various parts of the code base to use the
+        new API as needed.
+
+        * bindings/ScriptFunctionCall.cpp:
+        (Deprecated::ScriptFunctionCall::call):
+        - ScriptFunctionCall::call() is only used by the inspector to inject scripts.
+          The injected scripts that will include Inspector scripts that should catch
+          and handle any exceptions that were thrown.  We should not be seeing any
+          exceptions returned from this call.  However, we do have checks for
+          exceptions in case there are bugs in the Inspector scripts which allowed
+          the exception to leak through.  Hence, it is proper to clear the exception
+          here, and only record the fact that an exception was seen (if present).
+
+        * bindings/ScriptFunctionCall.h:
+        * inspector/InspectorEnvironment.h:
+        * runtime/CallData.cpp:
+        (JSC::call):
+        * runtime/CallData.h:
+
</ins><span class="cx"> 2014-04-11  Oliver Hunt  &lt;oliver@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Add BuiltinLog function to make debugging builtins easier
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebindingsScriptFunctionCallcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bindings/ScriptFunctionCall.cpp (167141 => 167142)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bindings/ScriptFunctionCall.cpp        2014-04-11 20:22:17 UTC (rev 167141)
+++ trunk/Source/JavaScriptCore/bindings/ScriptFunctionCall.cpp        2014-04-11 20:24:56 UTC (rev 167142)
</span><span class="lines">@@ -133,12 +133,13 @@
</span><span class="cx">         return Deprecated::ScriptValue();
</span><span class="cx"> 
</span><span class="cx">     JSValue result;
</span><ins>+    JSValue exception;
</ins><span class="cx">     if (m_callHandler)
</span><del>-        result = m_callHandler(m_exec, function, callType, callData, thisObject, m_arguments);
</del><ins>+        result = m_callHandler(m_exec, function, callType, callData, thisObject, m_arguments, &amp;exception);
</ins><span class="cx">     else
</span><del>-        result = JSC::call(m_exec, function, callType, callData, thisObject, m_arguments);
</del><ins>+        result = JSC::call(m_exec, function, callType, callData, thisObject, m_arguments, &amp;exception);
</ins><span class="cx"> 
</span><del>-    if (m_exec-&gt;hadException()) {
</del><ins>+    if (exception) {
</ins><span class="cx">         hadException = true;
</span><span class="cx">         return Deprecated::ScriptValue();
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebindingsScriptFunctionCallh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bindings/ScriptFunctionCall.h (167141 => 167142)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bindings/ScriptFunctionCall.h        2014-04-11 20:22:17 UTC (rev 167141)
+++ trunk/Source/JavaScriptCore/bindings/ScriptFunctionCall.h        2014-04-11 20:24:56 UTC (rev 167142)
</span><span class="lines">@@ -71,7 +71,7 @@
</span><span class="cx"> 
</span><span class="cx"> class JS_EXPORT_PRIVATE ScriptFunctionCall : public ScriptCallArgumentHandler {
</span><span class="cx"> public:
</span><del>-    typedef JSC::JSValue (*ScriptFunctionCallHandler)(JSC::ExecState* exec, JSC::JSValue functionObject, JSC::CallType callType, const JSC::CallData&amp; callData, JSC::JSValue thisValue, const JSC::ArgList&amp; args);
</del><ins>+    typedef JSC::JSValue (*ScriptFunctionCallHandler)(JSC::ExecState* exec, JSC::JSValue functionObject, JSC::CallType callType, const JSC::CallData&amp; callData, JSC::JSValue thisValue, const JSC::ArgList&amp; args, JSC::JSValue* exception);
</ins><span class="cx">     ScriptFunctionCall(const ScriptObject&amp; thisObject, const String&amp; name, ScriptFunctionCallHandler handler = nullptr);
</span><span class="cx">     ScriptValue call(bool&amp; hadException);
</span><span class="cx">     ScriptValue call();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinspectorInspectorEnvironmenth"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/inspector/InspectorEnvironment.h (167141 => 167142)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/inspector/InspectorEnvironment.h        2014-04-11 20:22:17 UTC (rev 167141)
+++ trunk/Source/JavaScriptCore/inspector/InspectorEnvironment.h        2014-04-11 20:24:56 UTC (rev 167142)
</span><span class="lines">@@ -34,7 +34,7 @@
</span><span class="cx"> 
</span><span class="cx"> namespace Inspector {
</span><span class="cx"> 
</span><del>-typedef JSC::JSValue (*InspectorFunctionCallHandler)(JSC::ExecState* exec, JSC::JSValue functionObject, JSC::CallType callType, const JSC::CallData&amp; callData, JSC::JSValue thisValue, const JSC::ArgList&amp; args);
</del><ins>+typedef JSC::JSValue (*InspectorFunctionCallHandler)(JSC::ExecState* exec, JSC::JSValue functionObject, JSC::CallType callType, const JSC::CallData&amp; callData, JSC::JSValue thisValue, const JSC::ArgList&amp; args, JSC::JSValue* exception);
</ins><span class="cx"> typedef JSC::JSValue (*InspectorEvaluateHandler)(JSC::ExecState*, const JSC::SourceCode&amp;, JSC::JSValue thisValue, JSC::JSValue* exception);
</span><span class="cx"> 
</span><span class="cx"> class InspectorEnvironment {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeCallDatacpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/CallData.cpp (167141 => 167142)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/CallData.cpp        2014-04-11 20:22:17 UTC (rev 167141)
+++ trunk/Source/JavaScriptCore/runtime/CallData.cpp        2014-04-11 20:24:56 UTC (rev 167142)
</span><span class="lines">@@ -39,4 +39,17 @@
</span><span class="cx">     return exec-&gt;interpreter()-&gt;executeCall(exec, asObject(functionObject), callType, callData, thisValue, args);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+JSValue call(ExecState* exec, JSValue functionObject, CallType callType, const CallData&amp; callData, JSValue thisValue, const ArgList&amp; args, JSValue* exception)
+{
+    JSValue result = call(exec, functionObject, callType, callData, thisValue, args);
+    if (exec-&gt;hadException()) {
+        if (exception)
+            *exception = exec-&gt;exception();
+        exec-&gt;clearException();
+        return jsUndefined();
+    }
+    RELEASE_ASSERT(result);
+    return result;
+}
+
</ins><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeCallDatah"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/CallData.h (167141 => 167142)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/CallData.h        2014-04-11 20:22:17 UTC (rev 167141)
+++ trunk/Source/JavaScriptCore/runtime/CallData.h        2014-04-11 20:24:56 UTC (rev 167142)
</span><span class="lines">@@ -58,6 +58,7 @@
</span><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> JS_EXPORT_PRIVATE JSValue call(ExecState*, JSValue functionObject, CallType, const CallData&amp;, JSValue thisValue, const ArgList&amp;);
</span><ins>+JS_EXPORT_PRIVATE JSValue call(ExecState*, JSValue functionObject, CallType, const CallData&amp;, JSValue thisValue, const ArgList&amp;, JSValue* exception);
</ins><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (167141 => 167142)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2014-04-11 20:22:17 UTC (rev 167141)
+++ trunk/Source/WebCore/ChangeLog        2014-04-11 20:24:56 UTC (rev 167142)
</span><span class="lines">@@ -1,3 +1,77 @@
</span><ins>+2014-04-11  Mark Lam  &lt;mark.lam@apple.com&gt;
+
+        JSMainThreadExecState::call() should clear exceptions before returning.
+        &lt;https://webkit.org/b/131530&gt;
+
+        Reviewed by Geoffrey Garen.
+
+        Test: fast/dom/regress-131530.html
+
+        Previously, JSMainThreadExecState::call() did not clear any pending
+        exceptions in the VM before returning.  On returning, the
+        JSMainThreadExecState destructor may re-enter the VM to notify
+        MutationObservers.  This may result in a crash because the VM expects
+        exceptions to be cleared at entry.
+
+        We now change JSMainThreadExecState::call() to return the exception
+        (if present) via an argument, and clear it from the VM before returning.
+
+        As part of this change, I updated various parts of the code base to use the
+        new API as needed.
+
+        * bindings/js/JSCallbackData.cpp:
+        (WebCore::JSCallbackData::invokeCallback):
+        * bindings/js/JSCustomXPathNSResolver.cpp:
+        (WebCore::JSCustomXPathNSResolver::lookupNamespaceURI):
+        * bindings/js/JSDOMGlobalObjectTask.cpp:
+        - Assert that there's no unhandled exception after the Microtask returns.
+          See comment for WebCore::JSMainThreadExecState::runTask below for more
+          details.
+
+        * bindings/js/JSErrorHandler.cpp:
+        (WebCore::JSErrorHandler::handleEvent):
+        * bindings/js/JSEventListener.cpp:
+        (WebCore::JSEventListener::handleEvent):
+        * bindings/js/JSHTMLDocumentCustom.cpp:
+        (WebCore::JSHTMLDocument::open):
+        - Document.open() cannot be the first function on the JS stack.  Hence,
+          there is no need to use JSMainThreadExecState to call into the VM, as
+          this is only needed to catch the event of returning from the first
+          function for the purpose of notifying MutationObservers.  Change to
+          call JSC::call() directly.
+
+        * bindings/js/JSMainThreadExecState.cpp:
+        (WebCore::functionCallHandlerFromAnyThread):
+        * bindings/js/JSMainThreadExecState.h:
+        (WebCore::JSMainThreadExecState::call):
+        (WebCore::JSMainThreadExecState::evaluate):
+        - Remove the explicitly acquisition of the JSLock here because we now
+          acquire the JSLock as part of the JSMainThreadExecState instance.
+        (WebCore::JSMainThreadExecState::runTask):
+        - Added an assert to verify that the task does not return with an
+          unhandled exception.  Currently, the only Microtask in use is for the
+          Promise implementation, which will eat the exception before returning.
+          This assertion is added here to verify that this contract does not
+          inadvertantly change in the future.
+        (WebCore::JSMainThreadExecState::JSMainThreadExecState):
+        - Now acquires the JSLock as well since by definition, we're only
+          instantiating the JSMainThreadExecState because we're about to enter
+          the VM.
+
+        * bindings/js/JSMutationCallback.cpp:
+        (WebCore::JSMutationCallback::call):
+        * bindings/js/JSNodeFilterCondition.cpp:
+        (WebCore::JSNodeFilterCondition::acceptNode):
+        - acceptNode() is only used in the TreeWalker and NodeIterator APIs which
+          cannot be the first function on the JS stack.  Hence, we should call
+          JSC::call() directly instead of going through JSMainThreadExecState.
+
+        * bindings/js/ScheduledAction.cpp:
+        (WebCore::ScheduledAction::executeFunctionInContext):
+        * bindings/objc/WebScriptObject.mm:
+        (WebCore::addExceptionToConsole):
+        (-[WebScriptObject callWebScriptMethod:withArguments:]):
+
</ins><span class="cx"> 2014-04-11  Brian J. Burg  &lt;burg@cs.washington.edu&gt;
</span><span class="cx"> 
</span><span class="cx">         Web Replay: CodeGeneratorJS should guard includes of replay-related headers
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsJSCallbackDatacpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/JSCallbackData.cpp (167141 => 167142)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/JSCallbackData.cpp        2014-04-11 20:22:17 UTC (rev 167141)
+++ trunk/Source/WebCore/bindings/js/JSCallbackData.cpp        2014-04-11 20:24:56 UTC (rev 167142)
</span><span class="lines">@@ -73,14 +73,15 @@
</span><span class="cx"> 
</span><span class="cx">     InspectorInstrumentationCookie cookie = JSMainThreadExecState::instrumentFunctionCall(context, callType, callData);
</span><span class="cx"> 
</span><ins>+    JSValue exception;
</ins><span class="cx">     JSValue result = context-&gt;isDocument()
</span><del>-        ? JSMainThreadExecState::call(exec, function, callType, callData, thisValue, args)
-        : JSC::call(exec, function, callType, callData, thisValue, args);
</del><ins>+        ? JSMainThreadExecState::call(exec, function, callType, callData, thisValue, args, &amp;exception)
+        : JSC::call(exec, function, callType, callData, thisValue, args, &amp;exception);
</ins><span class="cx"> 
</span><span class="cx">     InspectorInstrumentation::didCallFunction(cookie, context);
</span><span class="cx"> 
</span><del>-    if (exec-&gt;hadException()) {
-        reportCurrentException(exec);
</del><ins>+    if (exception) {
+        reportException(exec, exception);
</ins><span class="cx">         if (raisedException)
</span><span class="cx">             *raisedException = true;
</span><span class="cx">         return result;
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsJSCustomXPathNSResolvercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/JSCustomXPathNSResolver.cpp (167141 => 167142)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/JSCustomXPathNSResolver.cpp        2014-04-11 20:22:17 UTC (rev 167141)
+++ trunk/Source/WebCore/bindings/js/JSCustomXPathNSResolver.cpp        2014-04-11 20:24:56 UTC (rev 167142)
</span><span class="lines">@@ -92,11 +92,12 @@
</span><span class="cx">     MarkedArgumentBuffer args;
</span><span class="cx">     args.append(jsStringWithCache(exec, prefix));
</span><span class="cx"> 
</span><del>-    JSValue retval = JSMainThreadExecState::call(exec, function, callType, callData, m_customResolver.get(), args);
</del><ins>+    JSValue exception;
+    JSValue retval = JSMainThreadExecState::call(exec, function, callType, callData, m_customResolver.get(), args, &amp;exception);
</ins><span class="cx"> 
</span><span class="cx">     String result;
</span><del>-    if (exec-&gt;hadException())
-        reportCurrentException(exec);
</del><ins>+    if (exception)
+        reportException(exec, exception);
</ins><span class="cx">     else {
</span><span class="cx">         if (!retval.isUndefinedOrNull())
</span><span class="cx">             result = retval.toString(exec)-&gt;value(exec);
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsJSDOMGlobalObjectTaskcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/JSDOMGlobalObjectTask.cpp (167141 => 167142)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/JSDOMGlobalObjectTask.cpp        2014-04-11 20:22:17 UTC (rev 167141)
+++ trunk/Source/WebCore/bindings/js/JSDOMGlobalObjectTask.cpp        2014-04-11 20:24:56 UTC (rev 167142)
</span><span class="lines">@@ -64,6 +64,7 @@
</span><span class="cx">             JSMainThreadExecState::runTask(exec, *m_task.get());
</span><span class="cx">         else
</span><span class="cx">             m_task-&gt;run(exec);
</span><ins>+        ASSERT(!exec-&gt;hadException());
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> private:
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsJSErrorHandlercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/JSErrorHandler.cpp (167141 => 167142)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/JSErrorHandler.cpp        2014-04-11 20:22:17 UTC (rev 167141)
+++ trunk/Source/WebCore/bindings/js/JSErrorHandler.cpp        2014-04-11 20:24:56 UTC (rev 167142)
</span><span class="lines">@@ -98,14 +98,15 @@
</span><span class="cx">         VM&amp; vm = globalObject-&gt;vm();
</span><span class="cx">         VMEntryScope entryScope(vm, vm.entryScope ? vm.entryScope-&gt;globalObject() : globalObject);
</span><span class="cx"> 
</span><ins>+        JSValue exception;
</ins><span class="cx">         JSValue returnValue = scriptExecutionContext-&gt;isDocument()
</span><del>-            ? JSMainThreadExecState::call(exec, jsFunction, callType, callData, globalObject, args)
-            : JSC::call(exec, jsFunction, callType, callData, globalObject, args);
</del><ins>+            ? JSMainThreadExecState::call(exec, jsFunction, callType, callData, globalObject, args, &amp;exception)
+            : JSC::call(exec, jsFunction, callType, callData, globalObject, args, &amp;exception);
</ins><span class="cx"> 
</span><span class="cx">         globalObject-&gt;setCurrentEvent(savedEvent);
</span><span class="cx"> 
</span><del>-        if (exec-&gt;hadException())
-            reportCurrentException(exec);
</del><ins>+        if (exception)
+            reportException(exec, exception);
</ins><span class="cx">         else {
</span><span class="cx">             if (returnValue.isTrue())
</span><span class="cx">                 event-&gt;preventDefault();
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsJSEventListenercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/JSEventListener.cpp (167141 => 167142)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/JSEventListener.cpp        2014-04-11 20:22:17 UTC (rev 167141)
+++ trunk/Source/WebCore/bindings/js/JSEventListener.cpp        2014-04-11 20:24:56 UTC (rev 167142)
</span><span class="lines">@@ -122,9 +122,10 @@
</span><span class="cx">         InspectorInstrumentationCookie cookie = JSMainThreadExecState::instrumentFunctionCall(scriptExecutionContext, callType, callData);
</span><span class="cx"> 
</span><span class="cx">         JSValue thisValue = handleEventFunction == jsFunction ? toJS(exec, globalObject, event-&gt;currentTarget()) : jsFunction;
</span><ins>+        JSValue exception;
</ins><span class="cx">         JSValue retval = scriptExecutionContext-&gt;isDocument()
</span><del>-            ? JSMainThreadExecState::call(exec, handleEventFunction, callType, callData, thisValue, args)
-            : JSC::call(exec, handleEventFunction, callType, callData, thisValue, args);
</del><ins>+            ? JSMainThreadExecState::call(exec, handleEventFunction, callType, callData, thisValue, args, &amp;exception)
+            : JSC::call(exec, handleEventFunction, callType, callData, thisValue, args, &amp;exception);
</ins><span class="cx"> 
</span><span class="cx">         InspectorInstrumentation::didCallFunction(cookie, scriptExecutionContext);
</span><span class="cx"> 
</span><span class="lines">@@ -136,9 +137,9 @@
</span><span class="cx">                 toWorkerGlobalScope(scriptExecutionContext)-&gt;script()-&gt;forbidExecution();
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        if (exec-&gt;hadException()) {
</del><ins>+        if (exception) {
</ins><span class="cx">             event-&gt;target()-&gt;uncaughtExceptionInEventHandler();
</span><del>-            reportCurrentException(exec);
</del><ins>+            reportException(exec, exception);
</ins><span class="cx">         } else {
</span><span class="cx">             if (!retval.isUndefinedOrNull() &amp;&amp; event-&gt;isBeforeUnloadEvent())
</span><span class="cx">                 toBeforeUnloadEvent(event)-&gt;setReturnValue(retval.toString(exec)-&gt;value(exec));
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsJSHTMLDocumentCustomcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/JSHTMLDocumentCustom.cpp (167141 => 167142)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/JSHTMLDocumentCustom.cpp        2014-04-11 20:22:17 UTC (rev 167141)
+++ trunk/Source/WebCore/bindings/js/JSHTMLDocumentCustom.cpp        2014-04-11 20:24:56 UTC (rev 167142)
</span><span class="lines">@@ -113,7 +113,7 @@
</span><span class="cx">                 CallType callType = ::getCallData(function, callData);
</span><span class="cx">                 if (callType == CallTypeNone)
</span><span class="cx">                     return throwTypeError(exec);
</span><del>-                return JSMainThreadExecState::call(exec, function, callType, callData, wrapper, ArgList(exec));
</del><ins>+                return JSC::call(exec, function, callType, callData, wrapper, ArgList(exec));
</ins><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx">         return jsUndefined();
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsJSMainThreadExecStatecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/JSMainThreadExecState.cpp (167141 => 167142)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/JSMainThreadExecState.cpp        2014-04-11 20:22:17 UTC (rev 167141)
+++ trunk/Source/WebCore/bindings/js/JSMainThreadExecState.cpp        2014-04-11 20:24:56 UTC (rev 167142)
</span><span class="lines">@@ -46,11 +46,11 @@
</span><span class="cx">     MutationObserver::deliverAllMutations();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-JSC::JSValue functionCallHandlerFromAnyThread(JSC::ExecState* exec, JSC::JSValue functionObject, JSC::CallType callType, const JSC::CallData&amp; callData, JSC::JSValue thisValue, const JSC::ArgList&amp; args)
</del><ins>+JSC::JSValue functionCallHandlerFromAnyThread(JSC::ExecState* exec, JSC::JSValue functionObject, JSC::CallType callType, const JSC::CallData&amp; callData, JSC::JSValue thisValue, const JSC::ArgList&amp; args, JSC::JSValue* exception)
</ins><span class="cx"> {
</span><span class="cx">     if (isMainThread())
</span><del>-        return JSMainThreadExecState::call(exec, functionObject, callType, callData, thisValue, args);
-    return JSC::call(exec, functionObject, callType, callData, thisValue, args);
</del><ins>+        return JSMainThreadExecState::call(exec, functionObject, callType, callData, thisValue, args, exception);
+    return JSC::call(exec, functionObject, callType, callData, thisValue, args, exception);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> JSC::JSValue evaluateHandlerFromAnyThread(JSC::ExecState* exec, const JSC::SourceCode&amp; source, JSC::JSValue thisValue, JSC::JSValue* exception)
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsJSMainThreadExecStateh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/JSMainThreadExecState.h (167141 => 167142)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/JSMainThreadExecState.h        2014-04-11 20:22:17 UTC (rev 167141)
+++ trunk/Source/WebCore/bindings/js/JSMainThreadExecState.h        2014-04-11 20:24:56 UTC (rev 167142)
</span><span class="lines">@@ -50,16 +50,15 @@
</span><span class="cx">         return s_mainThreadState;
</span><span class="cx">     };
</span><span class="cx">     
</span><del>-    static JSC::JSValue call(JSC::ExecState* exec, JSC::JSValue functionObject, JSC::CallType callType, const JSC::CallData&amp; callData, JSC::JSValue thisValue, const JSC::ArgList&amp; args)
</del><ins>+    static JSC::JSValue call(JSC::ExecState* exec, JSC::JSValue functionObject, JSC::CallType callType, const JSC::CallData&amp; callData, JSC::JSValue thisValue, const JSC::ArgList&amp; args, JSC::JSValue* exception)
</ins><span class="cx">     {
</span><span class="cx">         JSMainThreadExecState currentState(exec);
</span><del>-        return JSC::call(exec, functionObject, callType, callData, thisValue, args);
</del><ins>+        return JSC::call(exec, functionObject, callType, callData, thisValue, args, exception);
</ins><span class="cx">     };
</span><span class="cx"> 
</span><span class="cx">     static JSC::JSValue evaluate(JSC::ExecState* exec, const JSC::SourceCode&amp; source, JSC::JSValue thisValue, JSC::JSValue* exception)
</span><span class="cx">     {
</span><span class="cx">         JSMainThreadExecState currentState(exec);
</span><del>-        JSC::JSLockHolder lock(exec);
</del><span class="cx">         return JSC::evaluate(exec, source, thisValue, exception);
</span><span class="cx">     };
</span><span class="cx"> 
</span><span class="lines">@@ -74,6 +73,7 @@
</span><span class="cx"> private:
</span><span class="cx">     explicit JSMainThreadExecState(JSC::ExecState* exec)
</span><span class="cx">         : m_previousState(s_mainThreadState)
</span><ins>+        , m_lock(exec)
</ins><span class="cx">     {
</span><span class="cx">         ASSERT(isMainThread());
</span><span class="cx">         s_mainThreadState = exec;
</span><span class="lines">@@ -82,6 +82,7 @@
</span><span class="cx">     ~JSMainThreadExecState()
</span><span class="cx">     {
</span><span class="cx">         ASSERT(isMainThread());
</span><ins>+        ASSERT(!s_mainThreadState-&gt;hadException());
</ins><span class="cx"> 
</span><span class="cx">         bool didExitJavaScript = s_mainThreadState &amp;&amp; !m_previousState;
</span><span class="cx"> 
</span><span class="lines">@@ -93,6 +94,7 @@
</span><span class="cx"> 
</span><span class="cx">     static JSC::ExecState* s_mainThreadState;
</span><span class="cx">     JSC::ExecState* m_previousState;
</span><ins>+    JSC::JSLockHolder m_lock;
</ins><span class="cx"> 
</span><span class="cx">     static void didLeaveScriptContext();
</span><span class="cx"> };
</span><span class="lines">@@ -119,7 +121,7 @@
</span><span class="cx">     JSC::ExecState* m_previousState;
</span><span class="cx"> };
</span><span class="cx"> 
</span><del>-JSC::JSValue functionCallHandlerFromAnyThread(JSC::ExecState*, JSC::JSValue functionObject, JSC::CallType callType, const JSC::CallData&amp; callData, JSC::JSValue thisValue, const JSC::ArgList&amp; args);
</del><ins>+JSC::JSValue functionCallHandlerFromAnyThread(JSC::ExecState*, JSC::JSValue functionObject, JSC::CallType, const JSC::CallData&amp;, JSC::JSValue thisValue, const JSC::ArgList&amp; args, JSC::JSValue* exception);
</ins><span class="cx"> JSC::JSValue evaluateHandlerFromAnyThread(JSC::ExecState*, const JSC::SourceCode&amp;, JSC::JSValue thisValue, JSC::JSValue* exception);
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsJSMutationCallbackcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/JSMutationCallback.cpp (167141 => 167142)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/JSMutationCallback.cpp        2014-04-11 20:22:17 UTC (rev 167141)
+++ trunk/Source/WebCore/bindings/js/JSMutationCallback.cpp        2014-04-11 20:24:56 UTC (rev 167142)
</span><span class="lines">@@ -87,12 +87,13 @@
</span><span class="cx"> 
</span><span class="cx">     InspectorInstrumentationCookie cookie = JSMainThreadExecState::instrumentFunctionCall(context, callType, callData);
</span><span class="cx"> 
</span><del>-    JSMainThreadExecState::call(exec, callback, callType, callData, jsObserver, args);
</del><ins>+    JSValue exception;
+    JSMainThreadExecState::call(exec, callback, callType, callData, jsObserver, args, &amp;exception);
</ins><span class="cx"> 
</span><span class="cx">     InspectorInstrumentation::didCallFunction(cookie, context);
</span><span class="cx"> 
</span><del>-    if (exec-&gt;hadException())
-        reportCurrentException(exec);
</del><ins>+    if (exception)
+        reportException(exec, exception);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsJSNodeFilterConditioncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/JSNodeFilterCondition.cpp (167141 => 167142)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/JSNodeFilterCondition.cpp        2014-04-11 20:22:17 UTC (rev 167141)
+++ trunk/Source/WebCore/bindings/js/JSNodeFilterCondition.cpp        2014-04-11 20:24:56 UTC (rev 167142)
</span><span class="lines">@@ -67,7 +67,7 @@
</span><span class="cx">     if (exec-&gt;hadException())
</span><span class="cx">         return NodeFilter::FILTER_REJECT;
</span><span class="cx"> 
</span><del>-    JSValue result = JSMainThreadExecState::call(exec, filter, callType, callData, m_filter.get(), args);
</del><ins>+    JSValue result = JSC::call(exec, filter, callType, callData, m_filter.get(), args);
</ins><span class="cx">     if (exec-&gt;hadException())
</span><span class="cx">         return NodeFilter::FILTER_REJECT;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsScheduledActioncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/ScheduledAction.cpp (167141 => 167142)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/ScheduledAction.cpp        2014-04-11 20:22:17 UTC (rev 167141)
+++ trunk/Source/WebCore/bindings/js/ScheduledAction.cpp        2014-04-11 20:24:56 UTC (rev 167142)
</span><span class="lines">@@ -99,15 +99,16 @@
</span><span class="cx"> 
</span><span class="cx">     InspectorInstrumentationCookie cookie = JSMainThreadExecState::instrumentFunctionCall(context, callType, callData);
</span><span class="cx"> 
</span><ins>+    JSValue exception;
</ins><span class="cx">     if (context-&gt;isDocument())
</span><del>-        JSMainThreadExecState::call(exec, m_function.get(), callType, callData, thisValue, args);
</del><ins>+        JSMainThreadExecState::call(exec, m_function.get(), callType, callData, thisValue, args, &amp;exception);
</ins><span class="cx">     else
</span><del>-        JSC::call(exec, m_function.get(), callType, callData, thisValue, args);
</del><ins>+        JSC::call(exec, m_function.get(), callType, callData, thisValue, args, &amp;exception);
</ins><span class="cx"> 
</span><span class="cx">     InspectorInstrumentation::didCallFunction(cookie, context);
</span><span class="cx"> 
</span><del>-    if (exec-&gt;hadException())
-        reportCurrentException(exec);
</del><ins>+    if (exception)
+        reportException(exec, exception);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void ScheduledAction::execute(Document* document)
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsobjcWebScriptObjectmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/objc/WebScriptObject.mm (167141 => 167142)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/objc/WebScriptObject.mm        2014-04-11 20:22:17 UTC (rev 167141)
+++ trunk/Source/WebCore/bindings/objc/WebScriptObject.mm        2014-04-11 20:24:56 UTC (rev 167142)
</span><span class="lines">@@ -120,14 +120,21 @@
</span><span class="cx">     return [[[WebScriptObject alloc] _initWithJSObject:object originRootObject:origin rootObject:root] autorelease];
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static void addExceptionToConsole(ExecState* exec)
</del><ins>+static void addExceptionToConsole(ExecState* exec, JSC::JSValue&amp; exception)
</ins><span class="cx"> {
</span><span class="cx">     JSDOMWindow* window = asJSDOMWindow(exec-&gt;vmEntryGlobalObject());
</span><del>-    if (!window || !exec-&gt;hadException())
</del><ins>+    if (!window || !exception)
</ins><span class="cx">         return;
</span><del>-    reportCurrentException(exec);
</del><ins>+    reportException(exec, exception);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static void addExceptionToConsole(ExecState* exec)
+{
+    JSC::JSValue exception = exec-&gt;exception();
+    exec-&gt;clearException();
+    addExceptionToConsole(exec, exception);
+}
+
</ins><span class="cx"> } // namespace WebCore
</span><span class="cx"> 
</span><span class="cx"> @implementation WebScriptObjectPrivate
</span><span class="lines">@@ -334,12 +341,12 @@
</span><span class="cx">     if (![self _isSafeScript])
</span><span class="cx">         return nil;
</span><span class="cx"> 
</span><del>-    JSC::JSValue result = JSMainThreadExecState::call(exec, function, callType, callData, [self _imp], argList);
</del><ins>+    JSC::JSValue exception;
+    JSC::JSValue result = JSMainThreadExecState::call(exec, function, callType, callData, [self _imp], argList, &amp;exception);
</ins><span class="cx"> 
</span><del>-    if (exec-&gt;hadException()) {
-        addExceptionToConsole(exec);
</del><ins>+    if (exception) {
+        addExceptionToConsole(exec, exception);
</ins><span class="cx">         result = jsUndefined();
</span><del>-        exec-&gt;clearException();
</del><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // Convert and return the result of the function call.
</span></span></pre>
</div>
</div>

</body>
</html>