Permalink
Browse files

Fix try ... catch exception handling.

The hasHandler flag passed to JSC::Debugger::exception only applies to
the current stack frame. It does not indicate if there are exception
handlers in earlier stack frames.

Therefore, we are saving the frame when an exception occurs, but only
reporting the exception if it is still present once the stack has been
fully unwound.

http://code.google.com/p/phantomjs/issues/detail?id=166
  • Loading branch information...
1 parent a48770c commit 35e8c949256d5bdadb5187971a7c78daf37be325 @jonleighton jonleighton committed with ariya Mar 18, 2012
@@ -295,6 +295,7 @@ static inline Qt::DropAction dragOpToDropAction(unsigned actions)
QWebPagePrivateDebugger::QWebPagePrivateDebugger(QWebPage* page)
: m_webPage(page)
+ , m_stackDepth(0)
{
}
@@ -312,14 +313,14 @@ void QWebPagePrivateDebugger::sourceParsed(JSC::ExecState*, JSC::SourceProvider*
void QWebPagePrivateDebugger::exception(const JSC::DebuggerCallFrame& frame, intptr_t sourceID, int lineNumber, bool hasHandler)
{
- if (!hasHandler) {
- reportError(frame.exception());
- }
+ m_exceptionFrame = m_callFrame;
}
void QWebPagePrivateDebugger::reportError(const JSC::JSValue& exception)
{
- WTF::RefPtr<WebCore::JavaScriptCallFrame> frame = m_callFrame;
+ if (!m_exceptionFrame) return;
+
+ WTF::RefPtr<WebCore::JavaScriptCallFrame> frame = m_exceptionFrame;
JSC::ExecState* exec = frame->dynamicGlobalObject()->globalExec();
JSC::UString message = exception.toString(exec);
@@ -345,6 +346,7 @@ void QWebPagePrivateDebugger::reportError(const JSC::JSValue& exception)
}
m_webPage->javaScriptError(QWebPage::JavaScriptError(qmessage, qbacktrace));
+ m_exceptionFrame = 0;
}
void QWebPagePrivateDebugger::atStatement(const JSC::DebuggerCallFrame& frame, intptr_t sourceID, int lineNumber)
@@ -357,19 +359,26 @@ void QWebPagePrivateDebugger::callEvent(const JSC::DebuggerCallFrame& frame, int
stepIn(frame, sourceID, lineNumber);
}
-void QWebPagePrivateDebugger::returnEvent(const JSC::DebuggerCallFrame&, intptr_t sourceID, int lineNumber)
+void QWebPagePrivateDebugger::returnEvent(const JSC::DebuggerCallFrame& frame, intptr_t sourceID, int lineNumber)
{
- stepOut();
+ stepOut(frame);
}
void QWebPagePrivateDebugger::willExecuteProgram(const JSC::DebuggerCallFrame& frame, intptr_t sourceID, int lineNumber)
{
stepIn(frame, sourceID, lineNumber);
}
-void QWebPagePrivateDebugger::didExecuteProgram(const JSC::DebuggerCallFrame&, intptr_t sourceID, int lineNumber)
+void QWebPagePrivateDebugger::didExecuteProgram(const JSC::DebuggerCallFrame& frame, intptr_t sourceID, int lineNumber)
{
- stepOut();
+ stepOut(frame);
+
+ // If there is still an exception present at the end of the program, then it hasn't
+ // been caught and we should report it.
+ JSC::JSValue exception = frame.exception();
+ if (exception) {
+ reportError(exception);
+ }
}
void QWebPagePrivateDebugger::didReachBreakpoint(const JSC::DebuggerCallFrame&, intptr_t sourceID, int lineNumber)
@@ -379,18 +388,30 @@ void QWebPagePrivateDebugger::didReachBreakpoint(const JSC::DebuggerCallFrame&,
void QWebPagePrivateDebugger::stepIn(const JSC::DebuggerCallFrame& frame, intptr_t sourceID, int lineNumber)
{
m_callFrame = WebCore::JavaScriptCallFrame::create(frame, m_callFrame, sourceID, textPosition(lineNumber));
+ m_stackDepth++;
}
void QWebPagePrivateDebugger::stepOver(const JSC::DebuggerCallFrame& frame, intptr_t sourceID, int lineNumber)
{
m_callFrame->update(frame, sourceID, textPosition(lineNumber));
}
-void QWebPagePrivateDebugger::stepOut()
+void QWebPagePrivateDebugger::stepOut(const JSC::DebuggerCallFrame& frame)
{
m_callFrame = m_callFrame->caller();
-}
+ m_stackDepth--;
+ // Sometimes an exception can occur without didExecuteProgram() firing.
+ // For example when a setTimeout callback fires. So if the stack is empty
+ // and there is still an exception present, we report it.
+ if (m_stackDepth == 0) {
+ JSC::JSValue exception = frame.exception();
+
+ if (exception) {
+ reportError(exception);
+ }
+ }
+}
QWebPagePrivate::QWebPagePrivate(QWebPage *qq)
: q(qq)
@@ -106,7 +106,7 @@ class QWebPagePrivateDebugger : public JSC::Debugger {
private:
void stepIn(const JSC::DebuggerCallFrame& frame, intptr_t sourceID, int lineNumber);
void stepOver(const JSC::DebuggerCallFrame& frame, intptr_t sourceID, int lineNumber);
- void stepOut();
+ void stepOut(const JSC::DebuggerCallFrame& frame);
void reportError(const JSC::JSValue& exception);
WTF::TextPosition0 textPosition(int lineNumber)
@@ -116,6 +116,8 @@ class QWebPagePrivateDebugger : public JSC::Debugger {
}
RefPtr<WebCore::JavaScriptCallFrame> m_callFrame;
+ RefPtr<WebCore::JavaScriptCallFrame> m_exceptionFrame;
+ int m_stackDepth;
QWebPage* m_webPage;
};

0 comments on commit 35e8c94

Please sign in to comment.