Skip to content

Commit

Permalink
Fix try ... catch exception handling.
Browse files Browse the repository at this point in the history
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
jonleighton authored and ariya committed Mar 19, 2012
1 parent a48770c commit 35e8c94
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 11 deletions.
41 changes: 31 additions & 10 deletions src/qt/src/3rdparty/webkit/Source/WebKit/qt/Api/qwebpage.cpp
Expand Up @@ -295,6 +295,7 @@ static inline Qt::DropAction dragOpToDropAction(unsigned actions)

QWebPagePrivateDebugger::QWebPagePrivateDebugger(QWebPage* page)
: m_webPage(page)
, m_stackDepth(0)
{
}

Expand All @@ -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);
Expand All @@ -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)
Expand All @@ -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)
Expand All @@ -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)
Expand Down
4 changes: 3 additions & 1 deletion src/qt/src/3rdparty/webkit/Source/WebKit/qt/Api/qwebpage_p.h
Expand Up @@ -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)
Expand All @@ -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;
};

Expand Down

0 comments on commit 35e8c94

Please sign in to comment.