Title: [185487] trunk
Revision
185487
Author
[email protected]
Date
2015-06-11 22:39:28 -0700 (Thu, 11 Jun 2015)

Log Message

WebCore::reportException() needs to be able to accept a raw thrown value in addition to Exception objects.
https://bugs.webkit.org/show_bug.cgi?id=145872

Reviewed by Michael Saboff.

Source/_javascript_Core:

In r185259, we changed exception handling code inside the VM to work with
Exception objects instead of the thrown JSValue.  The handling code will get the
exception stack trace from the Exception object.

However, there is some code that cannot be updated to pass the Exception object.
An example of this are the ObjC API functions.  Those functions are specified to
return any thrown exception JSValue in a JSValueRef.  Since these APIs are
public, we cannot arbitrarily change them to use the Exception object.

There are client code that calls these APIs and then passes the returned exception
JSValue to WebCore::reportException() to be reported.  WebCore::reportException()
previously relied on the VM::exceptionStackTrace() to provide a cache of the
stack trace of the last thrown exception.  VM::exceptionStackTrace() no longer
exists in the current code.

To restore this functionality, we will introduce VM::lastException() which
caches the last thrown Exception object.  With this, if the exception passed to
WebCore::reportException() to be reported isn't an Exception object (which has its
own stack trace), reportException() can again use the cached exception stack trace
which is available from VM::lastException().

* heap/Heap.cpp:
(JSC::Heap::visitException):
- visit VM::m_lastException on GCs.

* interpreter/CallFrame.h:
(JSC::ExecState::lastException):
(JSC::ExecState::clearLastException):
- convenience functions to get and clear the last exception.

* runtime/Exception.cpp:
(JSC::Exception::create):
(JSC::Exception::finishCreation):
- add support to create an Exception object without capturing the JS stack trace.
  This is needed for making an Exception object to wrap a thrown value that does
  not have a stack trace.
  Currently, this is only used by WebCore::reportException() when there is no
  Exception object and no last exception available to provide a stack trace.

* runtime/Exception.h:
(JSC::Exception::cast): Deleted.  No longer needed.

* runtime/VM.h:
(JSC::VM::clearLastException):
(JSC::VM::setException):
(JSC::VM::lastException):
(JSC::VM::addressOfLastException):
- Added support for VM::m_lastException.
  VM::m_lastException serves to cache the exception stack of the most recently
  thrown exception like VM::exceptionStackTrace() used to before r185259.

* runtime/VMEntryScope.cpp:
(JSC::VMEntryScope::VMEntryScope):
- Clear VM::m_lastException when we re-enter the VM.  Exceptions should have been
  handled before we re-enter the VM anyway.  So, this is a good place to release
  the cached last exception.

  NOTE: this is also where the old code before r185259 clears the last exception
  stack trace.  So, we're just restoring the previous behavior here in terms of
  the lifecycle of the last exception stack.

Source/WebCore:

API test added: WebKit1.ReportExceptionTest.

* bindings/js/JSDOMBinding.cpp:
(WebCore::reportException):
- Added a version of reportException() that takes a JSValue instead of an Exception
  object.  This version will ensure that we have an Exception object before calling
  into the original reportException() as follows:

  1. If the JSValue is already an Exception object, we're good to go.

  2. Else, if VM::lastException() is available, use that as the exception.
     This is how the old code use to behave (in terms of where it gets the exception
     stack trace).  The assumption is that reportException() will be called in
     a timely manner before the exception stack trace has been purged.

  3. Else, create an Exception object with no stack trace.  This is the fall back
     in case the client did not call reportException() in a timely manner.

- Also clear the last exception after we've reported it.  This is how the old code
  before r185259 behave (in terms of the lifecycle of the last exception stack
  trace).  We're restoring that behavior here.

* bindings/js/JSDOMBinding.h:

Source/WebKit/mac:

* WebView/WebView.mm:
(+[WebView _reportException:inContext:]):
- Don't assume we have an Exception object.  Let WebCore::reportException() take
  care of it.

Source/WebKit/win:

* WebView.cpp:
(WebView::reportException):
- Don't assume we have an Exception object.  Let WebCore::reportException() take
  care of it.

Source/WebKit2:

* WebProcess/InjectedBundle/InjectedBundle.cpp:
(WebKit::InjectedBundle::reportException):
- Don't assume we have an Exception object.  Let WebCore::reportException() take
  care of it.

Tools:

* TestWebKitAPI/Tests/mac/WebViewDidCreateJavaScriptContext.mm:
(-[DidCreateJavaScriptContextFrameLoadDelegate webView:didCreateJavaScriptContext:forFrame:]):
- Exercises the JSC ObjC API to call a function which throws an exception.  That
  exception will be returned as a JSValue instead of an Exception object.  We
  will use this JSValue to test WebCore::reportException() to confirm that it is
  able to handle an exception value which is not an Exception object.

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (185486 => 185487)


--- trunk/Source/_javascript_Core/ChangeLog	2015-06-12 04:09:11 UTC (rev 185486)
+++ trunk/Source/_javascript_Core/ChangeLog	2015-06-12 05:39:28 UTC (rev 185487)
@@ -1,3 +1,71 @@
+2015-06-11  Mark Lam  <[email protected]>
+
+        WebCore::reportException() needs to be able to accept a raw thrown value in addition to Exception objects.
+        https://bugs.webkit.org/show_bug.cgi?id=145872
+
+        Reviewed by Michael Saboff.
+
+        In r185259, we changed exception handling code inside the VM to work with
+        Exception objects instead of the thrown JSValue.  The handling code will get the
+        exception stack trace from the Exception object.
+
+        However, there is some code that cannot be updated to pass the Exception object.
+        An example of this are the ObjC API functions.  Those functions are specified to
+        return any thrown exception JSValue in a JSValueRef.  Since these APIs are
+        public, we cannot arbitrarily change them to use the Exception object.
+
+        There are client code that calls these APIs and then passes the returned exception
+        JSValue to WebCore::reportException() to be reported.  WebCore::reportException()
+        previously relied on the VM::exceptionStackTrace() to provide a cache of the
+        stack trace of the last thrown exception.  VM::exceptionStackTrace() no longer
+        exists in the current code.
+
+        To restore this functionality, we will introduce VM::lastException() which
+        caches the last thrown Exception object.  With this, if the exception passed to
+        WebCore::reportException() to be reported isn't an Exception object (which has its
+        own stack trace), reportException() can again use the cached exception stack trace
+        which is available from VM::lastException().
+
+        * heap/Heap.cpp:
+        (JSC::Heap::visitException):
+        - visit VM::m_lastException on GCs.
+
+        * interpreter/CallFrame.h:
+        (JSC::ExecState::lastException):
+        (JSC::ExecState::clearLastException):
+        - convenience functions to get and clear the last exception.
+
+        * runtime/Exception.cpp:
+        (JSC::Exception::create):
+        (JSC::Exception::finishCreation):
+        - add support to create an Exception object without capturing the JS stack trace.
+          This is needed for making an Exception object to wrap a thrown value that does
+          not have a stack trace.
+          Currently, this is only used by WebCore::reportException() when there is no
+          Exception object and no last exception available to provide a stack trace.
+
+        * runtime/Exception.h:
+        (JSC::Exception::cast): Deleted.  No longer needed.
+
+        * runtime/VM.h:
+        (JSC::VM::clearLastException):
+        (JSC::VM::setException):
+        (JSC::VM::lastException):
+        (JSC::VM::addressOfLastException):
+        - Added support for VM::m_lastException.
+          VM::m_lastException serves to cache the exception stack of the most recently
+          thrown exception like VM::exceptionStackTrace() used to before r185259.
+
+        * runtime/VMEntryScope.cpp:
+        (JSC::VMEntryScope::VMEntryScope):
+        - Clear VM::m_lastException when we re-enter the VM.  Exceptions should have been
+          handled before we re-enter the VM anyway.  So, this is a good place to release
+          the cached last exception.
+
+          NOTE: this is also where the old code before r185259 clears the last exception
+          stack trace.  So, we're just restoring the previous behavior here in terms of
+          the lifecycle of the last exception stack.
+
 2015-06-11  Andreas Kling  <[email protected]>
 
         jsSubstring() should support creating substrings from substrings.

Modified: trunk/Source/_javascript_Core/heap/Heap.cpp (185486 => 185487)


--- trunk/Source/_javascript_Core/heap/Heap.cpp	2015-06-12 04:09:11 UTC (rev 185486)
+++ trunk/Source/_javascript_Core/heap/Heap.cpp	2015-06-12 05:39:28 UTC (rev 185487)
@@ -717,10 +717,11 @@
 void Heap::visitException(HeapRootVisitor& visitor)
 {
     GCPHASE(MarkingException);
-    if (!m_vm->exception())
+    if (!m_vm->exception() && !m_vm->lastException())
         return;
 
     visitor.visit(m_vm->addressOfException());
+    visitor.visit(m_vm->addressOfLastException());
 
     if (Options::logGC() == GCLogging::Verbose)
         dataLog("Exceptions:\n", m_slotVisitor);

Modified: trunk/Source/_javascript_Core/interpreter/CallFrame.h (185486 => 185487)


--- trunk/Source/_javascript_Core/interpreter/CallFrame.h	2015-06-12 04:09:11 UTC (rev 185486)
+++ trunk/Source/_javascript_Core/interpreter/CallFrame.h	2015-06-12 05:39:28 UTC (rev 185487)
@@ -79,6 +79,9 @@
         Exception* exception() const { return vm().exception(); }
         bool hadException() const { return !!vm().exception(); }
 
+        Exception* lastException() const { return vm().lastException(); }
+        void clearLastException() { vm().clearLastException(); }
+
         AtomicStringTable* atomicStringTable() const { return vm().atomicStringTable(); }
         const CommonIdentifiers& propertyNames() const { return *vm().propertyNames; }
         const MarkedArgumentBuffer& emptyList() const { return *vm().emptyList; }

Modified: trunk/Source/_javascript_Core/runtime/Exception.cpp (185486 => 185487)


--- trunk/Source/_javascript_Core/runtime/Exception.cpp	2015-06-12 04:09:11 UTC (rev 185486)
+++ trunk/Source/_javascript_Core/runtime/Exception.cpp	2015-06-12 05:39:28 UTC (rev 185487)
@@ -32,10 +32,10 @@
 
 const ClassInfo Exception::s_info = { "Exception", &Base::s_info, 0, CREATE_METHOD_TABLE(Exception) };
 
-Exception* Exception::create(VM& vm, JSValue thrownValue)
+Exception* Exception::create(VM& vm, JSValue thrownValue, StackCaptureAction action)
 {
     Exception* result = new (NotNull, allocateCell<Exception>(vm.heap)) Exception(vm);
-    result->finishCreation(vm, thrownValue);
+    result->finishCreation(vm, thrownValue, action);
     return result;
 }
 
@@ -68,14 +68,15 @@
 {
 }
 
-void Exception::finishCreation(VM& vm, JSValue thrownValue)
+void Exception::finishCreation(VM& vm, JSValue thrownValue, StackCaptureAction action)
 {
     Base::finishCreation(vm);
 
     m_value.set(vm, this, thrownValue);
 
     Vector<StackFrame> stackTrace;
-    vm.interpreter->getStackTrace(stackTrace);
+    if (action == StackCaptureAction::CaptureStack)
+        vm.interpreter->getStackTrace(stackTrace);
     m_stack = RefCountedArray<StackFrame>(stackTrace);
 }
 

Modified: trunk/Source/_javascript_Core/runtime/Exception.h (185486 => 185487)


--- trunk/Source/_javascript_Core/runtime/Exception.h	2015-06-12 04:09:11 UTC (rev 185486)
+++ trunk/Source/_javascript_Core/runtime/Exception.h	2015-06-12 05:39:28 UTC (rev 185487)
@@ -36,7 +36,11 @@
     typedef JSNonFinalObject Base;
     static const unsigned StructureFlags = StructureIsImmortal | Base::StructureFlags;
 
-    static Exception* create(VM&, JSValue thrownValue);
+    enum StackCaptureAction {
+        CaptureStack,
+        DoNotCaptureStack
+    };
+    JS_EXPORT_PRIVATE static Exception* create(VM&, JSValue thrownValue, StackCaptureAction = CaptureStack);
 
     static const bool needsDestruction = true;
     static void destroy(JSCell*);
@@ -52,11 +56,6 @@
         return OBJECT_OFFSETOF(Exception, m_value);
     }
 
-    static Exception* cast(JSValue exceptionAsJSValue)
-    {
-        return jsCast<Exception*>(exceptionAsJSValue.asCell());
-    }
-
     JSValue value() const { return m_value.get(); }
     const RefCountedArray<StackFrame>& stack() const { return m_stack; }
 
@@ -67,7 +66,7 @@
 
 private:
     Exception(VM&);
-    void finishCreation(VM&, JSValue thrownValue);
+    void finishCreation(VM&, JSValue thrownValue, StackCaptureAction);
 
     WriteBarrier<Unknown> m_value;
     RefCountedArray<StackFrame> m_stack;

Modified: trunk/Source/_javascript_Core/runtime/VM.h (185486 => 185487)


--- trunk/Source/_javascript_Core/runtime/VM.h	2015-06-12 04:09:11 UTC (rev 185486)
+++ trunk/Source/_javascript_Core/runtime/VM.h	2015-06-12 05:39:28 UTC (rev 185487)
@@ -374,11 +374,20 @@
     }
 
     void clearException() { m_exception = nullptr; }
-    void setException(Exception* exception) { m_exception = exception; }
+    void clearLastException() { m_lastException = nullptr; }
 
+    void setException(Exception* exception)
+    {
+        m_exception = exception;
+        m_lastException = exception;
+    }
+
     Exception* exception() const { return m_exception; }
     JSCell** addressOfException() { return reinterpret_cast<JSCell**>(&m_exception); }
 
+    Exception* lastException() const { return m_lastException; }
+    JSCell** addressOfLastException() { return reinterpret_cast<JSCell**>(&m_lastException); }
+
     JS_EXPORT_PRIVATE void throwException(ExecState*, Exception*);
     JS_EXPORT_PRIVATE JSValue throwException(ExecState*, JSValue);
     JS_EXPORT_PRIVATE JSObject* throwException(ExecState*, JSObject*);
@@ -570,6 +579,7 @@
 #endif
     void* m_lastStackTop;
     Exception* m_exception { nullptr };
+    Exception* m_lastException { nullptr };
     bool m_inDefineOwnProperty;
     std::unique_ptr<CodeCache> m_codeCache;
     LegacyProfiler* m_enabledProfiler;

Modified: trunk/Source/_javascript_Core/runtime/VMEntryScope.cpp (185486 => 185487)


--- trunk/Source/_javascript_Core/runtime/VMEntryScope.cpp	2015-06-12 04:09:11 UTC (rev 185486)
+++ trunk/Source/_javascript_Core/runtime/VMEntryScope.cpp	2015-06-12 05:39:28 UTC (rev 185487)
@@ -49,6 +49,8 @@
         // observe time xone changes.
         vm.resetDateCache();
     }
+
+    vm.clearLastException();
 }
 
 void VMEntryScope::setEntryScopeDidPopListener(void* key, EntryScopeDidPopListener listener)

Modified: trunk/Source/WebCore/ChangeLog (185486 => 185487)


--- trunk/Source/WebCore/ChangeLog	2015-06-12 04:09:11 UTC (rev 185486)
+++ trunk/Source/WebCore/ChangeLog	2015-06-12 05:39:28 UTC (rev 185487)
@@ -1,3 +1,34 @@
+2015-06-11  Mark Lam  <[email protected]>
+
+        WebCore::reportException() needs to be able to accept a raw thrown value in addition to Exception objects.
+        https://bugs.webkit.org/show_bug.cgi?id=145872
+
+        Reviewed by Michael Saboff.
+
+        API test added: WebKit1.ReportExceptionTest.
+
+        * bindings/js/JSDOMBinding.cpp:
+        (WebCore::reportException):
+        - Added a version of reportException() that takes a JSValue instead of an Exception
+          object.  This version will ensure that we have an Exception object before calling
+          into the original reportException() as follows:
+
+          1. If the JSValue is already an Exception object, we're good to go.
+
+          2. Else, if VM::lastException() is available, use that as the exception.
+             This is how the old code use to behave (in terms of where it gets the exception
+             stack trace).  The assumption is that reportException() will be called in
+             a timely manner before the exception stack trace has been purged.
+
+          3. Else, create an Exception object with no stack trace.  This is the fall back
+             in case the client did not call reportException() in a timely manner.
+
+        - Also clear the last exception after we've reported it.  This is how the old code
+          before r185259 behave (in terms of the lifecycle of the last exception stack
+          trace).  We're restoring that behavior here.
+
+        * bindings/js/JSDOMBinding.h:
+
 2015-06-11  Zalan Bujtas  <[email protected]>
 
         Do not crash when the descendant frame tree is destroyed during layout.

Modified: trunk/Source/WebCore/bindings/js/JSDOMBinding.cpp (185486 => 185487)


--- trunk/Source/WebCore/bindings/js/JSDOMBinding.cpp	2015-06-12 04:09:11 UTC (rev 185486)
+++ trunk/Source/WebCore/bindings/js/JSDOMBinding.cpp	2015-06-12 05:39:28 UTC (rev 185487)
@@ -139,6 +139,19 @@
     return JSC::constructArray(exec, 0, globalObject, list);
 }
 
+void reportException(ExecState* exec, JSValue exceptionValue, CachedScript* cachedScript)
+{
+    RELEASE_ASSERT(exec->vm().currentThreadIsHoldingAPILock());
+    Exception* exception = jsDynamicCast<Exception*>(exceptionValue);
+    if (!exception) {
+        exception = exec->lastException();
+        if (!exception)
+            exception = Exception::create(exec->vm(), exceptionValue, Exception::DoNotCaptureStack);
+    }
+
+    reportException(exec, exception, cachedScript);
+}
+
 void reportException(ExecState* exec, Exception* exception, CachedScript* cachedScript)
 {
     RELEASE_ASSERT(exec->vm().currentThreadIsHoldingAPILock());
@@ -149,6 +162,7 @@
 
     RefPtr<ScriptCallStack> callStack(createScriptCallStackFromException(exec, exception, ScriptCallStack::maxCallStackSizeToCapture));
     exec->clearException();
+    exec->clearLastException();
 
     JSDOMGlobalObject* globalObject = jsCast<JSDOMGlobalObject*>(exec->lexicalGlobalObject());
     if (JSDOMWindow* window = jsDynamicCast<JSDOMWindow*>(globalObject)) {
@@ -172,7 +186,11 @@
         // FIXME: <http://webkit.org/b/115087> Web Inspector: WebCore::reportException should not evaluate _javascript_ handling exceptions
         // If this is a custon exception object, call toString on it to try and get a nice string representation for the exception.
         errorMessage = exception->value().toString(exec)->value(exec);
+
+        // We need to clear any new exception that may be thrown in the toString() call above.
+        // reportException() is not supposed to be making new exceptions.
         exec->clearException();
+        exec->clearLastException();
     }
 
     ScriptExecutionContext* scriptExecutionContext = globalObject->scriptExecutionContext();

Modified: trunk/Source/WebCore/bindings/js/JSDOMBinding.h (185486 => 185487)


--- trunk/Source/WebCore/bindings/js/JSDOMBinding.h	2015-06-12 04:09:11 UTC (rev 185486)
+++ trunk/Source/WebCore/bindings/js/JSDOMBinding.h	2015-06-12 05:39:28 UTC (rev 185487)
@@ -242,6 +242,7 @@
 
 const JSC::HashTable& getHashTableForGlobalData(JSC::VM&, const JSC::HashTable& staticTable);
 
+WEBCORE_EXPORT void reportException(JSC::ExecState*, JSC::JSValue exception, CachedScript* = nullptr);
 WEBCORE_EXPORT void reportException(JSC::ExecState*, JSC::Exception*, CachedScript* = nullptr);
 void reportCurrentException(JSC::ExecState*);
 

Modified: trunk/Source/WebKit/mac/ChangeLog (185486 => 185487)


--- trunk/Source/WebKit/mac/ChangeLog	2015-06-12 04:09:11 UTC (rev 185486)
+++ trunk/Source/WebKit/mac/ChangeLog	2015-06-12 05:39:28 UTC (rev 185487)
@@ -1,3 +1,15 @@
+2015-06-11  Mark Lam  <[email protected]>
+
+        WebCore::reportException() needs to be able to accept a raw thrown value in addition to Exception objects.
+        https://bugs.webkit.org/show_bug.cgi?id=145872
+
+        Reviewed by Michael Saboff.
+
+        * WebView/WebView.mm:
+        (+[WebView _reportException:inContext:]):
+        - Don't assume we have an Exception object.  Let WebCore::reportException() take
+          care of it.
+
 2015-06-11  Jon Lee  <[email protected]>
 
         Update media controls JS and CSS to use picture-in-picture

Modified: trunk/Source/WebKit/mac/WebView/WebView.mm (185486 => 185487)


--- trunk/Source/WebKit/mac/WebView/WebView.mm	2015-06-12 04:09:11 UTC (rev 185486)
+++ trunk/Source/WebKit/mac/WebView/WebView.mm	2015-06-12 05:39:28 UTC (rev 185487)
@@ -722,8 +722,7 @@
     if (!toJSDOMWindow(execState->lexicalGlobalObject()))
         return;
 
-    Exception* vmException = Exception::cast(toJS(execState, exception));
-    reportException(execState, vmException);
+    reportException(execState, toJS(execState, exception));
 }
 
 static void WebKitInitializeApplicationCachePathIfNecessary()

Modified: trunk/Source/WebKit/win/ChangeLog (185486 => 185487)


--- trunk/Source/WebKit/win/ChangeLog	2015-06-12 04:09:11 UTC (rev 185486)
+++ trunk/Source/WebKit/win/ChangeLog	2015-06-12 05:39:28 UTC (rev 185487)
@@ -1,3 +1,15 @@
+2015-06-11  Mark Lam  <[email protected]>
+
+        WebCore::reportException() needs to be able to accept a raw thrown value in addition to Exception objects.
+        https://bugs.webkit.org/show_bug.cgi?id=145872
+
+        Reviewed by Michael Saboff.
+
+        * WebView.cpp:
+        (WebView::reportException):
+        - Don't assume we have an Exception object.  Let WebCore::reportException() take
+          care of it.
+
 2015-06-09  Hyungwook Lee  <[email protected]>
 
         Implement dumpProgressFinishedCallback() for Win layoutTestController.

Modified: trunk/Source/WebKit/win/WebView.cpp (185486 => 185487)


--- trunk/Source/WebKit/win/WebView.cpp	2015-06-12 04:09:11 UTC (rev 185486)
+++ trunk/Source/WebKit/win/WebView.cpp	2015-06-12 05:39:28 UTC (rev 185487)
@@ -6046,8 +6046,7 @@
     if (!toJSDOMWindow(execState->lexicalGlobalObject()))
         return E_FAIL;
 
-    JSC::Exception* vmException = JSC::Exception::cast(toJS(execState, exception));
-    WebCore::reportException(execState, vmException);
+    WebCore::reportException(execState, toJS(execState, exception));
     return S_OK;
 }
 

Modified: trunk/Source/WebKit2/ChangeLog (185486 => 185487)


--- trunk/Source/WebKit2/ChangeLog	2015-06-12 04:09:11 UTC (rev 185486)
+++ trunk/Source/WebKit2/ChangeLog	2015-06-12 05:39:28 UTC (rev 185487)
@@ -1,3 +1,15 @@
+2015-06-11  Mark Lam  <[email protected]>
+
+        WebCore::reportException() needs to be able to accept a raw thrown value in addition to Exception objects.
+        https://bugs.webkit.org/show_bug.cgi?id=145872
+
+        Reviewed by Michael Saboff.
+
+        * WebProcess/InjectedBundle/InjectedBundle.cpp:
+        (WebKit::InjectedBundle::reportException):
+        - Don't assume we have an Exception object.  Let WebCore::reportException() take
+          care of it.
+
 2015-06-11  Carlos Alberto Lopez Perez  <[email protected]>
 
         [CMake] Unreviewed build fix after r185479.

Modified: trunk/Source/WebKit2/WebProcess/InjectedBundle/InjectedBundle.cpp (185486 => 185487)


--- trunk/Source/WebKit2/WebProcess/InjectedBundle/InjectedBundle.cpp	2015-06-12 04:09:11 UTC (rev 185486)
+++ trunk/Source/WebKit2/WebProcess/InjectedBundle/InjectedBundle.cpp	2015-06-12 05:39:28 UTC (rev 185487)
@@ -523,7 +523,7 @@
     if (!toJSDOMWindow(execState->lexicalGlobalObject()))
         return;
 
-    WebCore::reportException(execState, Exception::cast(toJS(execState, exception)));
+    WebCore::reportException(execState, toJS(execState, exception));
 }
 
 void InjectedBundle::didCreatePage(WebPage* page)

Modified: trunk/Tools/ChangeLog (185486 => 185487)


--- trunk/Tools/ChangeLog	2015-06-12 04:09:11 UTC (rev 185486)
+++ trunk/Tools/ChangeLog	2015-06-12 05:39:28 UTC (rev 185487)
@@ -1,3 +1,17 @@
+2015-06-11  Mark Lam  <[email protected]>
+
+        WebCore::reportException() needs to be able to accept a raw thrown value in addition to Exception objects.
+        https://bugs.webkit.org/show_bug.cgi?id=145872
+
+        Reviewed by Michael Saboff.
+
+        * TestWebKitAPI/Tests/mac/WebViewDidCreateJavaScriptContext.mm:
+        (-[DidCreateJavaScriptContextFrameLoadDelegate webView:didCreateJavaScriptContext:forFrame:]):
+        - Exercises the JSC ObjC API to call a function which throws an exception.  That
+          exception will be returned as a JSValue instead of an Exception object.  We
+          will use this JSValue to test WebCore::reportException() to confirm that it is
+          able to handle an exception value which is not an Exception object.
+
 2015-06-11  Dewei Zhu  <[email protected]>
 
         Move cursor to corner and fix safari window size before running benchmark

Modified: trunk/Tools/TestWebKitAPI/Tests/mac/WebViewDidCreateJavaScriptContext.mm (185486 => 185487)


--- trunk/Tools/TestWebKitAPI/Tests/mac/WebViewDidCreateJavaScriptContext.mm	2015-06-12 04:09:11 UTC (rev 185486)
+++ trunk/Tools/TestWebKitAPI/Tests/mac/WebViewDidCreateJavaScriptContext.mm	2015-06-12 05:39:28 UTC (rev 185487)
@@ -28,6 +28,7 @@
 #import <_javascript_Core/JSExport.h>
 #import <_javascript_Core/JSContext.h>
 #import <WebKit/WebFrameLoadDelegatePrivate.h>
+#import <WebKit/WebViewPrivate.h>
 #import <wtf/RetainPtr.h>
 
 #if JSC_OBJC_API_ENABLED
@@ -39,6 +40,7 @@
 static bool didCallWindowCallback = false;
 static bool didFindMyCustomProperty = false;
 static bool didInsertMyCustomProperty = true;
+static bool didReportException = false;
 
 @protocol MyConsole<JSExport>
 - (void)log:(NSString *)s;
@@ -107,6 +109,27 @@
         [element setValue:fortyTwo forProperty:@"myCustomProperty"];
         didInsertMyCustomProperty = true;
     };
+
+    context[@"testReportException"] = ^{
+        JSContext* context = [JSContext currentContext];
+        [context evaluateScript:@"function doThrow() { throw 'TestError'; }"];
+
+        JSGlobalContextRef globalContext = [context JSGlobalContextRef];
+        JSObjectRef globalObject = JSContextGetGlobalObject(globalContext);
+
+        JSStringRef jsString = JSStringCreateWithUTF8CString("doThrow");
+        JSValueRef function = JSObjectGetProperty(globalContext, globalObject, jsString, nullptr);
+        JSStringRelease(jsString);
+
+        const JSValueRef arguments[] = { };
+
+        JSValueRef exception = 0;
+        JSObjectCallAsFunction(globalContext, (JSObjectRef)function, globalObject, 0, arguments, &exception);
+        if (exception) {
+            [WebView _reportException:exception inContext:globalContext];
+            didReportException = true;
+        }
+    };
 }
 
 @end
@@ -283,6 +306,29 @@
     }
 }
 
+TEST(WebKit1, ReportExceptionTest)
+{
+    didReportException = false;
+    @autoreleasepool {
+        RetainPtr<WebView> webView = adoptNS([[WebView alloc] initWithFrame:NSMakeRect(0, 0, 120, 200) frameName:nil groupName:nil]);
+        RetainPtr<DidCreateJavaScriptContextFrameLoadDelegate> frameLoadDelegate = adoptNS([[DidCreateJavaScriptContextFrameLoadDelegate alloc] init]);
+        
+        webView.get().frameLoadDelegate = frameLoadDelegate.get();
+        WebFrame *mainFrame = webView.get().mainFrame;
+        
+        NSString *bodyString =
+            @"<body> \
+                <script> \
+                    testReportException(); \
+                </script> \
+            </body>";
+        NSURL *aboutBlankURL = [NSURL URLWithString:@"about:blank"];
+        
+        [mainFrame loadHTMLString:bodyString baseURL:aboutBlankURL];
+        Util::run(&didReportException);
+    }
+}
+
 } // namespace TestWebKitAPI
 
 #endif // ENABLE(JSC_OBJC_API)
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to