aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorErik Verbruggen <erik.verbruggen@digia.com>2014-12-05 13:16:14 +0100
committerErik Verbruggen <erik.verbruggen@theqtcompany.com>2014-12-09 11:55:04 +0100
commit8397f640e81f0eff1f6f32ae4a35d40f115ea339 (patch)
tree2bb50bc6be262979cb9e7c49f02d96cbc5c50be5
parent4524856ae21f85d572155c8a399d43116143e25c (diff)
QML Debugging: Fix crash when stepping through try-catch block.
Also fix the stack-trace generation, otherwise the debugger engine would report a breakpoint hit on the wrong line. Task-number: QTBUG-42723 Change-Id: I1f655a5174b28a1c9c31c85bbe023fbce5ddbb96 Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
-rw-r--r--src/qml/jsruntime/qv4context_p.h22
-rw-r--r--src/qml/jsruntime/qv4debugging.cpp17
-rw-r--r--src/qml/jsruntime/qv4engine.cpp14
-rw-r--r--src/qml/jsruntime/qv4functionobject_p.h2
-rw-r--r--tests/auto/qml/qv4debugger/tst_qv4debugger.cpp20
5 files changed, 57 insertions, 18 deletions
diff --git a/src/qml/jsruntime/qv4context_p.h b/src/qml/jsruntime/qv4context_p.h
index 6d95f039c5..c0ca4aec19 100644
--- a/src/qml/jsruntime/qv4context_p.h
+++ b/src/qml/jsruntime/qv4context_p.h
@@ -55,7 +55,6 @@ struct Function;
}
struct CallContext;
-struct CallContext;
struct CatchContext;
struct WithContext;
@@ -149,6 +148,9 @@ struct Q_QML_EXPORT ExecutionContext : public Managed
inline CallContext *asCallContext();
inline const CallContext *asCallContext() const;
+ inline const CatchContext *asCatchContext() const;
+
+ inline FunctionObject *getFunctionObject() const;
static void markObjects(Managed *m, ExecutionEngine *e);
};
@@ -225,6 +227,24 @@ inline const CallContext *ExecutionContext::asCallContext() const
return d()->type >= Type_SimpleCallContext ? static_cast<const CallContext *>(this) : 0;
}
+inline const CatchContext *ExecutionContext::asCatchContext() const
+{
+ return d()->type == Type_CatchContext ? static_cast<const CatchContext *>(this) : 0;
+}
+
+inline FunctionObject *ExecutionContext::getFunctionObject() const
+{
+ for (const ExecutionContext *it = this; it; it = it->d()->parent) {
+ if (const CallContext *callCtx = it->asCallContext())
+ return callCtx->d()->function;
+ else if (it->asCatchContext())
+ continue; // look in the parent context for a FunctionObject
+ else
+ break;
+ }
+
+ return 0;
+}
inline void ExecutionEngine::pushContext(CallContext *context)
{
diff --git a/src/qml/jsruntime/qv4debugging.cpp b/src/qml/jsruntime/qv4debugging.cpp
index 6a8d364a08..a835d835fb 100644
--- a/src/qml/jsruntime/qv4debugging.cpp
+++ b/src/qml/jsruntime/qv4debugging.cpp
@@ -509,7 +509,6 @@ void Debugger::maybeBreakAtInstruction()
return;
QMutexLocker locker(&m_lock);
- int lineNumber = engine()->currentContext()->d()->lineNumber;
if (m_gatherSources) {
m_gatherSources->run();
@@ -533,8 +532,12 @@ void Debugger::maybeBreakAtInstruction()
if (m_pauseRequested) { // Serve debugging requests from the agent
m_pauseRequested = false;
pauseAndWait(PauseRequest);
- } else if (m_haveBreakPoints && reallyHitTheBreakPoint(getFunction()->sourceFile(), lineNumber)) {
- pauseAndWait(BreakPoint);
+ } else if (m_haveBreakPoints) {
+ if (Function *f = getFunction()) {
+ const int lineNumber = engine()->currentContext()->d()->lineNumber;
+ if (reallyHitTheBreakPoint(f->sourceFile(), lineNumber))
+ pauseAndWait(BreakPoint);
+ }
}
}
@@ -579,12 +582,10 @@ void Debugger::aboutToThrow()
Function *Debugger::getFunction() const
{
ExecutionContext *context = m_engine->currentContext();
- if (CallContext *callCtx = context->asCallContext())
- return callCtx->d()->function->function();
- else {
- Q_ASSERT(context->d()->type == QV4::ExecutionContext::Type_GlobalContext);
+ if (const FunctionObject *function = context->getFunctionObject())
+ return function->function();
+ else
return context->d()->engine->globalCode;
- }
}
void Debugger::pauseAndWait(PauseReason reason)
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index ea075f9cbd..74b262e86d 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -700,19 +700,18 @@ QVector<StackFrame> ExecutionEngine::stackTrace(int frameLimit) const
QV4::ExecutionContext *c = currentContext();
while (c && frameLimit) {
- CallContext *callCtx = c->asCallContext();
- if (callCtx && callCtx->d()->function) {
+ if (FunctionObject *function = c->getFunctionObject()) {
StackFrame frame;
- if (callCtx->d()->function->function())
- frame.source = callCtx->d()->function->function()->sourceFile();
- name = callCtx->d()->function->name();
+ if (const Function *f = function->function())
+ frame.source = f->sourceFile();
+ name = function->name();
frame.function = name->toQString();
frame.line = -1;
frame.column = -1;
- if (callCtx->d()->function->function())
+ if (function->function())
// line numbers can be negative for places where you can't set a real breakpoint
- frame.line = qAbs(callCtx->d()->lineNumber);
+ frame.line = qAbs(c->d()->lineNumber);
stack.append(frame);
--frameLimit;
@@ -727,7 +726,6 @@ QVector<StackFrame> ExecutionEngine::stackTrace(int frameLimit) const
frame.line = rootContext->d()->lineNumber;
frame.column = -1;
-
stack.append(frame);
}
return stack;
diff --git a/src/qml/jsruntime/qv4functionobject_p.h b/src/qml/jsruntime/qv4functionobject_p.h
index c8edb765de..adedb9fb7d 100644
--- a/src/qml/jsruntime/qv4functionobject_p.h
+++ b/src/qml/jsruntime/qv4functionobject_p.h
@@ -116,7 +116,7 @@ struct Q_QML_EXPORT FunctionObject: Object {
ExecutionContext *scope() { return d()->scope; }
- Function *function() { return d()->function; }
+ Function *function() const { return d()->function; }
ReturnedValue name();
unsigned int formalParameterCount() { return function() ? function()->compiledFunction->nFormals : 0; }
diff --git a/tests/auto/qml/qv4debugger/tst_qv4debugger.cpp b/tests/auto/qml/qv4debugger/tst_qv4debugger.cpp
index 63bfffacaa..fcbdcbc201 100644
--- a/tests/auto/qml/qv4debugger/tst_qv4debugger.cpp
+++ b/tests/auto/qml/qv4debugger/tst_qv4debugger.cpp
@@ -286,6 +286,7 @@ private slots:
// exceptions:
void pauseOnThrow();
+ void breakInCatch();
void evaluateExpression();
@@ -612,6 +613,25 @@ void tst_qv4debugger::pauseOnThrow()
QCOMPARE(m_debuggerAgent->m_thrownValue.toString(), QString("hard"));
}
+void tst_qv4debugger::breakInCatch()
+{
+ QString script =
+ "try {\n"
+ " throw 'catch...'\n"
+ "} catch (e) {\n"
+ " console.log(e, 'me');\n"
+ "}\n";
+
+ m_debuggerAgent->addBreakPoint("breakInCatch", 4);
+ evaluateJavaScript(script, "breakInCatch");
+ QVERIFY(m_debuggerAgent->m_wasPaused);
+ QCOMPARE(m_debuggerAgent->m_pauseReason, BreakPoint);
+ QCOMPARE(m_debuggerAgent->m_statesWhenPaused.count(), 1);
+ QV4::Debugging::Debugger::ExecutionState state = m_debuggerAgent->m_statesWhenPaused.first();
+ QCOMPARE(state.fileName, QString("breakInCatch"));
+ QCOMPARE(state.lineNumber, 4);
+}
+
void tst_qv4debugger::evaluateExpression()
{
QString script =