Commit f5130158 authored by hjk's avatar hjk
Browse files

jsdebugger: use a real structure for a stack frame in the debuggeragent

parent f93fe86b
......@@ -69,8 +69,10 @@ QT_FORWARD_DECLARE_CLASS(QDeclarativeEngine);
namespace QmlJSDebugger {
class JSAgentWatchData;
class SetupExecEnv;
class QMLJSDEBUGGER_EXPORT JSDebuggerAgent : public QDeclarativeDebugService , public QScriptEngineAgent
class QMLJSDEBUGGER_EXPORT JSDebuggerAgent
: public QDeclarativeDebugService, public QScriptEngineAgent
{
Q_OBJECT
public:
......@@ -110,9 +112,7 @@ public slots:
// void pauses();
private:
class SetupExecEnv;
friend class SetupExecEnv;
enum State {
NoState,
SteppingIntoState,
......@@ -136,8 +136,6 @@ private:
QSet< QPair<QString, qint32> > breakpointList;
QStringList watchExpressions;
QSet<qint64> knownObjectIds;
Q_DISABLE_COPY(JSDebuggerAgent)
};
} // namespace QmlJSDebugger
......
......@@ -53,24 +53,27 @@
namespace QmlJSDebugger {
class JSDebuggerAgent::SetupExecEnv {
JSDebuggerAgent* agent;
JSDebuggerAgent::State previousState;
bool hadException;
class SetupExecEnv
{
public:
SetupExecEnv(JSDebuggerAgent *a)
: agent(a),
previousState(a->state),
hadException(a->engine()->hasUncaughtException())
{
agent->state = JSDebuggerAgent::Stopped;
}
{
agent->state = JSDebuggerAgent::Stopped;
}
~SetupExecEnv() {
if (!hadException && agent->engine()->hasUncaughtException())
agent->engine()->clearExceptions();
agent->state = previousState;
}
private:
JSDebuggerAgent *agent;
JSDebuggerAgent::State previousState;
bool hadException;
};
class JSAgentWatchData
......@@ -84,6 +87,26 @@ public:
quint64 objectId;
};
QDataStream &operator<<(QDataStream &s, const JSAgentWatchData &data)
{
return s << data.exp << data.name << data.value
<< data.type << data.hasChildren << data.objectId;
}
class JSAgentStackData
{
public:
QByteArray functionName;
QByteArray fileName;
qint32 lineNumber;
};
QDataStream &operator<<(QDataStream &s, const JSAgentStackData &data)
{
return s << data.functionName << data.fileName << data.lineNumber;
}
static JSAgentWatchData fromScriptValue(const QString &expression,
const QScriptValue &value)
{
......@@ -141,12 +164,6 @@ static JSAgentWatchData fromScriptValue(const QString &expression,
return data;
}
QDataStream &operator<<(QDataStream &s, const JSAgentWatchData &data)
{
return s << data.exp << data.name << data.value
<< data.type << data.hasChildren << data.objectId;
}
static QList<JSAgentWatchData> expandObject(const QScriptValue &object)
{
QList<JSAgentWatchData> result;
......@@ -270,7 +287,7 @@ void JSDebuggerAgent::positionChange(qint64 scriptId,
{
Q_UNUSED(columnNumber);
if(state == Stopped)
if (state == Stopped)
return; //no re-entrency
// check breakpoints
......@@ -461,42 +478,45 @@ void JSDebuggerAgent::messageReceived(const QByteArray& message)
QDeclarativeDebugService::messageReceived(message);
}
void JSDebuggerAgent::stopped(bool becauseOfException, const QScriptValue& exception)
void JSDebuggerAgent::stopped(bool becauseOfException, const QScriptValue &exception)
{
knownObjectIds.clear();
state = Stopped;
QList<QPair<QString, QPair<QString, qint32> > > backtrace;
QList<JSAgentStackData> backtrace;
for (QScriptContext* ctx = engine()->currentContext(); ctx; ctx = ctx->parentContext()) {
QScriptContextInfo info(ctx);
QString functionName = info.functionName();
if (functionName.isEmpty()) {
JSAgentStackData frame;
frame.functionName = info.functionName().toUtf8();
if (frame.functionName.isEmpty()) {
if (ctx->parentContext()) {
switch (info.functionType()) {
case QScriptContextInfo::ScriptFunction:
functionName = QLatin1String("<anonymous>");
frame.functionName = "<anonymous>";
break;
case QScriptContextInfo::NativeFunction:
functionName = QLatin1String("<native>");
frame.functionName = "<native>";
break;
case QScriptContextInfo::QtFunction:
case QScriptContextInfo::QtPropertyFunction:
functionName = QLatin1String("<native slot>");
frame.functionName = "<native slot>";
break;
}
} else {
functionName = QLatin1String("<global>");
frame.functionName = "<global>";
}
}
int lineNumber = info.lineNumber();
if (lineNumber == -1) // if the line number is unknown, fallback to the function line number
lineNumber = info.functionStartLineNumber();
backtrace.append(qMakePair(functionName, qMakePair( QUrl(info.fileName()).toLocalFile(), lineNumber ) ) );
frame.lineNumber = info.lineNumber();
// if the line number is unknown, fallback to the function line number
if (frame.lineNumber == -1)
frame.lineNumber = info.functionStartLineNumber();
frame.fileName = QUrl(info.fileName()).toLocalFile().toUtf8();
backtrace.append(frame);
}
QList<JSAgentWatchData> watches;
foreach (const QString &expr, watchExpressions)
watches << fromScriptValue(expr, engine()->evaluate(expr));
watches << fromScriptValue(expr, engine()->evaluate(expr));
recordKnownObjects(watches);
QList<JSAgentWatchData> locals = getLocals(engine()->currentContext());
......@@ -508,7 +528,8 @@ void JSDebuggerAgent::stopped(bool becauseOfException, const QScriptValue& excep
QByteArray reply;
QDataStream rs(&reply, QIODevice::WriteOnly);
rs << QByteArray("STOPPED") << backtrace << watches << locals << becauseOfException << exception.toString();
rs << QByteArray("STOPPED") << backtrace << watches << locals
<< becauseOfException << exception.toString();
sendMessage(reply);
loop.exec(QEventLoop::ExcludeUserInputEvents);
......
......@@ -100,6 +100,17 @@ QDataStream &operator>>(QDataStream &s, WatchData &data)
return s;
}
QDataStream &operator>>(QDataStream &s, StackFrame &frame)
{
frame = StackFrame();
QByteArray function;
QByteArray file;
s >> function >> file >> frame.line;
frame.function = QString::fromUtf8(function);
frame.file = QString::fromUtf8(file);
return s;
}
} // namespace Internal
struct QmlEnginePrivate
......@@ -619,22 +630,13 @@ void QmlEngine::messageReceived(const QByteArray &message)
notifyInferiorSpontaneousStop();
}
QList<QPair<QString, QPair<QString, qint32> > > backtrace;
Internal::StackFrames stackFrames;
QList<Internal::WatchData> watches;
QList<Internal::WatchData> locals;
stream >> backtrace >> watches >> locals;
stream >> stackFrames >> watches >> locals;
Internal::StackFrames stackFrames;
typedef QPair<QString, QPair<QString, qint32> > Iterator;
int level = 0;
foreach (const Iterator &it, backtrace) {
Internal::StackFrame frame;
frame.level = ++level;
frame.file = it.second.first;
frame.line = it.second.second;
frame.function = it.first;
stackFrames.append(frame);
}
for (int i = 0; i != stackFrames.size(); ++i)
stackFrames[i].level = i + 1;
gotoLocation(stackFrames.value(0), true);
stackHandler()->setFrames(stackFrames);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment