2011-07-26 16:22:49 +02:00
|
|
|
/**************************************************************************
|
|
|
|
|
**
|
|
|
|
|
** This file is part of Qt Creator
|
|
|
|
|
**
|
|
|
|
|
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
|
|
|
|
**
|
|
|
|
|
** Contact: Nokia Corporation (info@qt.nokia.com)
|
|
|
|
|
**
|
|
|
|
|
**
|
|
|
|
|
** GNU Lesser General Public License Usage
|
|
|
|
|
**
|
|
|
|
|
** This file may be used under the terms of the GNU Lesser General Public
|
|
|
|
|
** License version 2.1 as published by the Free Software Foundation and
|
|
|
|
|
** appearing in the file LICENSE.LGPL included in the packaging of this file.
|
|
|
|
|
** Please review the following information to ensure the GNU Lesser General
|
|
|
|
|
** Public License version 2.1 requirements will be met:
|
|
|
|
|
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
|
|
|
**
|
|
|
|
|
** In addition, as a special exception, Nokia gives you certain additional
|
|
|
|
|
** rights. These rights are described in the Nokia Qt LGPL Exception
|
|
|
|
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
|
|
|
**
|
|
|
|
|
** Other Usage
|
|
|
|
|
**
|
|
|
|
|
** Alternatively, this file may be used in accordance with the terms and
|
|
|
|
|
** conditions contained in a signed written agreement between you and Nokia.
|
|
|
|
|
**
|
|
|
|
|
** If you have questions regarding the use of this file, please contact
|
|
|
|
|
** Nokia at info@qt.nokia.com.
|
|
|
|
|
**
|
|
|
|
|
**************************************************************************/
|
|
|
|
|
|
|
|
|
|
#include "qmlv8debuggerclient.h"
|
2011-10-26 10:02:37 +02:00
|
|
|
#include "qmlv8debuggerclientconstants.h"
|
|
|
|
|
#include "debuggerstringutils.h"
|
2011-07-26 16:22:49 +02:00
|
|
|
|
|
|
|
|
#include "watchhandler.h"
|
|
|
|
|
#include "breakpoint.h"
|
|
|
|
|
#include "breakhandler.h"
|
|
|
|
|
#include "qmlengine.h"
|
|
|
|
|
#include "stackhandler.h"
|
|
|
|
|
|
|
|
|
|
#include <utils/qtcassert.h>
|
2011-09-06 17:03:16 +02:00
|
|
|
#include <coreplugin/editormanager/editormanager.h>
|
|
|
|
|
#include <texteditor/basetexteditor.h>
|
|
|
|
|
|
|
|
|
|
#include <QtGui/QTextBlock>
|
2011-07-26 16:22:49 +02:00
|
|
|
#include <QtCore/QVariant>
|
2011-10-31 14:17:01 +01:00
|
|
|
#include <QtCore/QStack>
|
2011-07-26 16:22:49 +02:00
|
|
|
#include <QtCore/QFileInfo>
|
|
|
|
|
#include <QtGui/QTextDocument>
|
2011-10-26 10:02:37 +02:00
|
|
|
#include <QtScript/QScriptEngine>
|
|
|
|
|
#include <QtScript/QScriptValue>
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
#define DEBUG_QML 0
|
|
|
|
|
#if DEBUG_QML
|
|
|
|
|
# define SDEBUG(s) qDebug() << s
|
|
|
|
|
#else
|
|
|
|
|
# define SDEBUG(s)
|
|
|
|
|
#endif
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-09-06 17:03:16 +02:00
|
|
|
using namespace Core;
|
2011-07-26 16:22:49 +02:00
|
|
|
|
|
|
|
|
namespace Debugger {
|
|
|
|
|
namespace Internal {
|
|
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
typedef QPair<QByteArray, QByteArray> WatchDataPair;
|
|
|
|
|
|
|
|
|
|
struct QmlV8ObjectData {
|
|
|
|
|
QByteArray type;
|
|
|
|
|
QVariant value;
|
|
|
|
|
QVariant properties;
|
2011-09-06 17:03:16 +02:00
|
|
|
};
|
|
|
|
|
|
2011-07-26 16:22:49 +02:00
|
|
|
class QmlV8DebuggerClientPrivate
|
|
|
|
|
{
|
|
|
|
|
public:
|
2011-10-26 10:02:37 +02:00
|
|
|
explicit QmlV8DebuggerClientPrivate(QmlV8DebuggerClient *q) :
|
|
|
|
|
q(q),
|
|
|
|
|
sequence(-1),
|
2011-09-06 17:03:16 +02:00
|
|
|
engine(0)
|
2011-07-26 16:22:49 +02:00
|
|
|
{
|
2011-10-26 10:02:37 +02:00
|
|
|
parser = m_scriptEngine.evaluate(_("JSON.parse"));
|
|
|
|
|
stringifier = m_scriptEngine.evaluate(_("JSON.stringify"));
|
2011-07-26 16:22:49 +02:00
|
|
|
}
|
|
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
void connect();
|
|
|
|
|
void disconnect();
|
|
|
|
|
|
|
|
|
|
void interrupt();
|
|
|
|
|
void continueDebugging(QmlV8DebuggerClient::StepAction stepAction, int stepCount = 1);
|
|
|
|
|
|
|
|
|
|
void evaluate(const QString expr, bool global = false, bool disableBreak = false,
|
|
|
|
|
int frame = -1, bool addContext = false);
|
|
|
|
|
void lookup(const QList<int> handles, bool includeSource = false);
|
|
|
|
|
void backtrace(int fromFrame = -1, int toFrame = -1, bool bottom = false);
|
|
|
|
|
void frame(int number = -1);
|
|
|
|
|
void scope(int number = -1, int frameNumber = -1);
|
|
|
|
|
void scopes(int frameNumber = -1);
|
|
|
|
|
void scripts(int types = 4, const QList<int> ids = QList<int>(),
|
|
|
|
|
bool includeSource = false, const QVariant filter = QVariant());
|
|
|
|
|
void source(int frame = -1, int fromLine = -1, int toLine = -1);
|
|
|
|
|
|
|
|
|
|
void setBreakpoint(const QString type, const QString target, int line = -1,
|
|
|
|
|
int column = -1, bool enabled = true,
|
|
|
|
|
const QString condition = QString(), int ignoreCount = -1);
|
|
|
|
|
void changeBreakpoint(int breakpoint, bool enabled = true,
|
|
|
|
|
const QString condition = QString(), int ignoreCount = -1);
|
|
|
|
|
void clearBreakpoint(int breakpoint);
|
|
|
|
|
void setExceptionBreak(QmlV8DebuggerClient::Exceptions type, bool enabled = false);
|
|
|
|
|
void listBreakpoints();
|
|
|
|
|
|
|
|
|
|
void v8flags(const QString flags);
|
|
|
|
|
void version();
|
|
|
|
|
//void profile(ProfileCommand command); //NOT SUPPORTED
|
|
|
|
|
void gc();
|
|
|
|
|
|
|
|
|
|
QmlV8ObjectData extractData(const QVariant &data);
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
QByteArray packMessage(const QByteArray &message);
|
|
|
|
|
QScriptValue initObject();
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
QmlV8DebuggerClient *q;
|
|
|
|
|
|
2011-07-26 16:22:49 +02:00
|
|
|
int sequence;
|
|
|
|
|
QmlEngine *engine;
|
2011-10-26 10:02:37 +02:00
|
|
|
QHash<BreakpointModelId, int> breakpoints;
|
|
|
|
|
QHash<int, BreakpointModelId> breakpointsSync;
|
2011-10-28 16:43:20 +02:00
|
|
|
QHash<int, QByteArray> localsAndWatchers;
|
|
|
|
|
QHash<int, QString> evaluatingWatches;
|
|
|
|
|
QStringList watchedExpressions;
|
|
|
|
|
QStack<QString> watchesToEvaluate;
|
2011-10-26 10:02:37 +02:00
|
|
|
|
|
|
|
|
QScriptValue parser;
|
|
|
|
|
QScriptValue stringifier;
|
|
|
|
|
|
2011-10-26 10:32:46 +02:00
|
|
|
QmlV8DebuggerClient::V8DebuggerStates state;
|
2011-10-26 10:02:37 +02:00
|
|
|
int currentFrameIndex;
|
|
|
|
|
bool updateCurrentStackFrameIndex;
|
2011-10-31 14:17:01 +01:00
|
|
|
QStack<int> currentFrameScopes;
|
|
|
|
|
QVariant refsVal;
|
|
|
|
|
QList<WatchData> localDataList;
|
2011-10-26 10:02:37 +02:00
|
|
|
private:
|
|
|
|
|
QScriptEngine m_scriptEngine;
|
2011-07-26 16:22:49 +02:00
|
|
|
};
|
|
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
|
//
|
|
|
|
|
// QmlV8DebuggerClientPrivate
|
|
|
|
|
//
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
void QmlV8DebuggerClientPrivate::connect()
|
2011-07-26 16:22:49 +02:00
|
|
|
{
|
2011-10-26 10:02:37 +02:00
|
|
|
// { "seq" : <number>,
|
|
|
|
|
// "type" : "request",
|
|
|
|
|
// "command" : "connect",
|
|
|
|
|
// }
|
|
|
|
|
QScriptValue jsonVal = initObject();
|
|
|
|
|
jsonVal.setProperty(_(COMMAND), QScriptValue(_(CONNECT)));
|
|
|
|
|
|
|
|
|
|
const QScriptValue jsonMessage = stringifier.call(QScriptValue(), QScriptValueList() << jsonVal);
|
|
|
|
|
q->sendMessage(packMessage(jsonMessage.toString().toUtf8()));
|
2011-07-26 16:22:49 +02:00
|
|
|
}
|
|
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
void QmlV8DebuggerClientPrivate::disconnect()
|
2011-07-26 16:22:49 +02:00
|
|
|
{
|
2011-10-26 10:02:37 +02:00
|
|
|
// { "seq" : <number>,
|
|
|
|
|
// "type" : "request",
|
|
|
|
|
// "command" : "disconnect",
|
|
|
|
|
// }
|
|
|
|
|
QScriptValue jsonVal = initObject();
|
|
|
|
|
jsonVal.setProperty(_(COMMAND), QScriptValue(_(DISCONNECT)));
|
|
|
|
|
|
|
|
|
|
const QScriptValue jsonMessage = stringifier.call(QScriptValue(), QScriptValueList() << jsonVal);
|
|
|
|
|
q->sendMessage(packMessage(jsonMessage.toString().toUtf8()));
|
2011-07-26 16:22:49 +02:00
|
|
|
}
|
|
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
void QmlV8DebuggerClientPrivate::interrupt()
|
2011-07-26 16:22:49 +02:00
|
|
|
{
|
2011-10-26 10:02:37 +02:00
|
|
|
// { "seq" : <number>,
|
|
|
|
|
// "type" : "request",
|
|
|
|
|
// "command" : "interrupt",
|
|
|
|
|
// }
|
|
|
|
|
QScriptValue jsonVal = initObject();
|
|
|
|
|
jsonVal.setProperty(_(COMMAND), QScriptValue(_(INTERRUPT)));
|
|
|
|
|
|
|
|
|
|
const QScriptValue jsonMessage = stringifier.call(QScriptValue(), QScriptValueList() << jsonVal);
|
|
|
|
|
q->sendMessage(packMessage(jsonMessage.toString().toUtf8()));
|
2011-07-26 16:22:49 +02:00
|
|
|
}
|
|
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
void QmlV8DebuggerClientPrivate::continueDebugging(QmlV8DebuggerClient::StepAction action,
|
|
|
|
|
int count)
|
2011-07-26 16:22:49 +02:00
|
|
|
{
|
2011-10-26 10:02:37 +02:00
|
|
|
//First reset
|
2011-10-26 10:32:46 +02:00
|
|
|
q->resetState();
|
2011-10-26 10:02:37 +02:00
|
|
|
|
|
|
|
|
// { "seq" : <number>,
|
|
|
|
|
// "type" : "request",
|
|
|
|
|
// "command" : "continue",
|
|
|
|
|
// "arguments" : { "stepaction" : <"in", "next" or "out">,
|
|
|
|
|
// "stepcount" : <number of steps (default 1)>
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
QScriptValue jsonVal = initObject();
|
|
|
|
|
jsonVal.setProperty(_(COMMAND),
|
|
|
|
|
QScriptValue(_(CONTINEDEBUGGING)));
|
|
|
|
|
|
|
|
|
|
if (action != QmlV8DebuggerClient::Continue) {
|
|
|
|
|
QScriptValue args = parser.call(QScriptValue(), QScriptValueList() << QScriptValue(_(OBJECT)));
|
|
|
|
|
switch (action) {
|
|
|
|
|
case QmlV8DebuggerClient::In:
|
|
|
|
|
args.setProperty(_(STEPACTION), QScriptValue(_(IN)));
|
|
|
|
|
break;
|
|
|
|
|
case QmlV8DebuggerClient::Out:
|
|
|
|
|
args.setProperty(_(STEPACTION), QScriptValue(_(OUT)));
|
|
|
|
|
break;
|
|
|
|
|
case QmlV8DebuggerClient::Next:
|
|
|
|
|
args.setProperty(_(STEPACTION), QScriptValue(_(NEXT)));
|
|
|
|
|
break;
|
|
|
|
|
default:break;
|
|
|
|
|
}
|
|
|
|
|
if (count != 1)
|
|
|
|
|
args.setProperty(_(STEPCOUNT), QScriptValue(count));
|
|
|
|
|
jsonVal.setProperty(_(ARGUMENTS), args);
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
}
|
|
|
|
|
const QScriptValue jsonMessage = stringifier.call(QScriptValue(), QScriptValueList() << jsonVal);
|
|
|
|
|
q->sendMessage(packMessage(jsonMessage.toString().toUtf8()));
|
|
|
|
|
}
|
2011-09-06 17:03:16 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
void QmlV8DebuggerClientPrivate::evaluate(const QString expr, bool global,
|
|
|
|
|
bool disableBreak, int frame,
|
|
|
|
|
bool addContext)
|
|
|
|
|
{
|
|
|
|
|
// { "seq" : <number>,
|
|
|
|
|
// "type" : "request",
|
|
|
|
|
// "command" : "evaluate",
|
|
|
|
|
// "arguments" : { "expression" : <expression to evaluate>,
|
|
|
|
|
// "frame" : <number>,
|
|
|
|
|
// "global" : <boolean>,
|
|
|
|
|
// "disable_break" : <boolean>,
|
|
|
|
|
// "additional_context" : [
|
|
|
|
|
// { "name" : <name1>, "handle" : <handle1> },
|
|
|
|
|
// { "name" : <name2>, "handle" : <handle2> },
|
|
|
|
|
// ...
|
|
|
|
|
// ]
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
QScriptValue jsonVal = initObject();
|
|
|
|
|
jsonVal.setProperty(_(COMMAND), QScriptValue(_(EVALUATE)));
|
|
|
|
|
|
|
|
|
|
QScriptValue args = parser.call(QScriptValue(), QScriptValueList() << QScriptValue(_(OBJECT)));
|
|
|
|
|
args.setProperty(_(EXPRESSION), QScriptValue(expr));
|
|
|
|
|
|
|
|
|
|
if (frame != -1)
|
|
|
|
|
args.setProperty(_(FRAME), QScriptValue(frame));
|
|
|
|
|
|
|
|
|
|
if (global)
|
|
|
|
|
args.setProperty(_(GLOBAL), QScriptValue(global));
|
|
|
|
|
|
|
|
|
|
if (disableBreak)
|
|
|
|
|
args.setProperty(_(DISABLE_BREAK), QScriptValue(disableBreak));
|
|
|
|
|
|
|
|
|
|
if (addContext) {
|
|
|
|
|
QAbstractItemModel *localsModel = engine->localsModel();
|
|
|
|
|
int rowCount = localsModel->rowCount();
|
|
|
|
|
|
|
|
|
|
QScriptValue ctxtList = parser.call(QScriptValue(), QScriptValueList() << _(ARRAY ));
|
|
|
|
|
while (rowCount) {
|
|
|
|
|
QModelIndex index = localsModel->index(--rowCount, 0);
|
|
|
|
|
const WatchData *data = engine->watchHandler()->watchData(LocalsWatch, index);
|
|
|
|
|
QScriptValue ctxt = parser.call(QScriptValue(), QScriptValueList() << QScriptValue(_(OBJECT)));
|
|
|
|
|
ctxt.setProperty(_(NAME), QScriptValue(data->name));
|
|
|
|
|
ctxt.setProperty(_(HANDLE), QScriptValue(int(data->id)));
|
|
|
|
|
|
|
|
|
|
ctxtList.setProperty(rowCount, ctxt);
|
|
|
|
|
}
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
args.setProperty(_(ADDITIONAL_CONTEXT), QScriptValue(ctxtList));
|
|
|
|
|
}
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
jsonVal.setProperty(_(ARGUMENTS), args);
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
const QScriptValue jsonMessage = stringifier.call(QScriptValue(), QScriptValueList() << jsonVal);
|
|
|
|
|
q->sendMessage(packMessage(jsonMessage.toString().toUtf8()));
|
2011-07-26 16:22:49 +02:00
|
|
|
}
|
|
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
void QmlV8DebuggerClientPrivate::lookup(QList<int> handles, bool includeSource)
|
2011-07-26 16:22:49 +02:00
|
|
|
{
|
2011-10-26 10:02:37 +02:00
|
|
|
// { "seq" : <number>,
|
|
|
|
|
// "type" : "request",
|
|
|
|
|
// "command" : "lookup",
|
|
|
|
|
// "arguments" : { "handles" : <array of handles>,
|
|
|
|
|
// "includeSource" : <boolean indicating whether
|
|
|
|
|
// the source will be included when
|
|
|
|
|
// script objects are returned>,
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
QScriptValue jsonVal = initObject();
|
|
|
|
|
jsonVal.setProperty(_(COMMAND), QScriptValue(_(LOOKUP)));
|
|
|
|
|
|
|
|
|
|
QScriptValue args = parser.call(QScriptValue(), QScriptValueList() << QScriptValue(_(OBJECT)));
|
|
|
|
|
|
|
|
|
|
QScriptValue array = parser.call(QScriptValue(), QScriptValueList() << _(ARRAY));
|
|
|
|
|
int index = 0;
|
|
|
|
|
foreach (int handle, handles) {
|
|
|
|
|
array.setProperty(index++, QScriptValue(handle));
|
|
|
|
|
}
|
|
|
|
|
args.setProperty(_(HANDLES), array);
|
|
|
|
|
|
|
|
|
|
if (includeSource)
|
|
|
|
|
args.setProperty(_(INCLUDESOURCE), QScriptValue(includeSource));
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
jsonVal.setProperty(_(ARGUMENTS), args);
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
const QScriptValue jsonMessage = stringifier.call(QScriptValue(), QScriptValueList() << jsonVal);
|
|
|
|
|
q->sendMessage(packMessage(jsonMessage.toString().toUtf8()));
|
2011-07-26 16:22:49 +02:00
|
|
|
}
|
|
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
void QmlV8DebuggerClientPrivate::backtrace(int fromFrame, int toFrame, bool bottom)
|
2011-07-26 16:22:49 +02:00
|
|
|
{
|
2011-10-26 10:02:37 +02:00
|
|
|
// { "seq" : <number>,
|
|
|
|
|
// "type" : "request",
|
|
|
|
|
// "command" : "backtrace",
|
|
|
|
|
// "arguments" : { "fromFrame" : <number>
|
|
|
|
|
// "toFrame" : <number>
|
|
|
|
|
// "bottom" : <boolean, set to true if the bottom of the
|
|
|
|
|
// stack is requested>
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
QScriptValue jsonVal = initObject();
|
|
|
|
|
jsonVal.setProperty(_(COMMAND), QScriptValue(_(BACKTRACE)));
|
2011-09-06 17:03:16 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
QScriptValue args = parser.call(QScriptValue(), QScriptValueList() << QScriptValue(_(OBJECT)));
|
2011-09-06 17:03:16 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
if (fromFrame != -1)
|
|
|
|
|
args.setProperty(_(FROMFRAME), QScriptValue(fromFrame));
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
if (toFrame != -1)
|
|
|
|
|
args.setProperty(_(TOFRAME), QScriptValue(toFrame));
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
if (bottom)
|
|
|
|
|
args.setProperty(_(BOTTOM), QScriptValue(bottom));
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
jsonVal.setProperty(_(ARGUMENTS), args);
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
const QScriptValue jsonMessage = stringifier.call(QScriptValue(), QScriptValueList() << jsonVal);
|
|
|
|
|
q->sendMessage(packMessage(jsonMessage.toString().toUtf8()));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void QmlV8DebuggerClientPrivate::frame(int number)
|
|
|
|
|
{
|
|
|
|
|
// { "seq" : <number>,
|
|
|
|
|
// "type" : "request",
|
|
|
|
|
// "command" : "frame",
|
|
|
|
|
// "arguments" : { "number" : <frame number>
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
QScriptValue jsonVal = initObject();
|
|
|
|
|
jsonVal.setProperty(_(COMMAND), QScriptValue(_(FRAME)));
|
|
|
|
|
|
|
|
|
|
if (number != -1) {
|
|
|
|
|
QScriptValue args = parser.call(QScriptValue(), QScriptValueList() << QScriptValue(_(OBJECT)));
|
|
|
|
|
args.setProperty(_(NUMBER), QScriptValue(number));
|
|
|
|
|
|
|
|
|
|
jsonVal.setProperty(_(ARGUMENTS), args);
|
2011-09-06 17:03:16 +02:00
|
|
|
}
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
const QScriptValue jsonMessage = stringifier.call(QScriptValue(), QScriptValueList() << jsonVal);
|
|
|
|
|
q->sendMessage(packMessage(jsonMessage.toString().toUtf8()));
|
2011-09-06 17:03:16 +02:00
|
|
|
}
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
void QmlV8DebuggerClientPrivate::scope(int number, int frameNumber)
|
2011-09-06 17:03:16 +02:00
|
|
|
{
|
2011-10-26 10:02:37 +02:00
|
|
|
// { "seq" : <number>,
|
|
|
|
|
// "type" : "request",
|
|
|
|
|
// "command" : "scope",
|
|
|
|
|
// "arguments" : { "number" : <scope number>
|
|
|
|
|
// "frameNumber" : <frame number, optional uses selected
|
|
|
|
|
// frame if missing>
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
QScriptValue jsonVal = initObject();
|
|
|
|
|
jsonVal.setProperty(_(COMMAND), QScriptValue(_(SCOPE)));
|
|
|
|
|
|
|
|
|
|
if (number != -1) {
|
|
|
|
|
QScriptValue args = parser.call(QScriptValue(), QScriptValueList() << QScriptValue(_(OBJECT)));
|
|
|
|
|
args.setProperty(_(NUMBER), QScriptValue(number));
|
|
|
|
|
|
|
|
|
|
if (frameNumber != -1)
|
|
|
|
|
args.setProperty(_(FRAMENUMBER), QScriptValue(frameNumber));
|
|
|
|
|
|
|
|
|
|
jsonVal.setProperty(_(ARGUMENTS), args);
|
|
|
|
|
}
|
2011-09-06 17:03:16 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
const QScriptValue jsonMessage = stringifier.call(QScriptValue(), QScriptValueList() << jsonVal);
|
|
|
|
|
q->sendMessage(packMessage(jsonMessage.toString().toUtf8()));
|
|
|
|
|
}
|
2011-09-06 17:03:16 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
void QmlV8DebuggerClientPrivate::scopes(int frameNumber)
|
|
|
|
|
{
|
|
|
|
|
// { "seq" : <number>,
|
|
|
|
|
// "type" : "request",
|
|
|
|
|
// "command" : "scopes",
|
|
|
|
|
// "arguments" : { "frameNumber" : <frame number, optional uses selected
|
|
|
|
|
// frame if missing>
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
QScriptValue jsonVal = initObject();
|
|
|
|
|
jsonVal.setProperty(_(COMMAND), QScriptValue(_(SCOPES)));
|
|
|
|
|
|
|
|
|
|
if (frameNumber != -1) {
|
|
|
|
|
QScriptValue args = parser.call(QScriptValue(), QScriptValueList() << QScriptValue(_(OBJECT)));
|
|
|
|
|
args.setProperty(_(FRAMENUMBER), QScriptValue(frameNumber));
|
|
|
|
|
|
|
|
|
|
jsonVal.setProperty(_(ARGUMENTS), args);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const QScriptValue jsonMessage = stringifier.call(QScriptValue(), QScriptValueList() << jsonVal);
|
|
|
|
|
q->sendMessage(packMessage(jsonMessage.toString().toUtf8()));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void QmlV8DebuggerClientPrivate::scripts(int types, const QList<int> ids, bool includeSource,
|
|
|
|
|
const QVariant /*filter*/)
|
|
|
|
|
{
|
|
|
|
|
// { "seq" : <number>,
|
|
|
|
|
// "type" : "request",
|
|
|
|
|
// "command" : "scripts",
|
|
|
|
|
// "arguments" : { "types" : <types of scripts to retrieve
|
|
|
|
|
// set bit 0 for native scripts
|
|
|
|
|
// set bit 1 for extension scripts
|
|
|
|
|
// set bit 2 for normal scripts
|
|
|
|
|
// (default is 4 for normal scripts)>
|
|
|
|
|
// "ids" : <array of id's of scripts to return. If this is not specified all scripts are requrned>
|
|
|
|
|
// "includeSource" : <boolean indicating whether the source code should be included for the scripts returned>
|
|
|
|
|
// "filter" : <string or number: filter string or script id.
|
|
|
|
|
// If a number is specified, then only the script with the same number as its script id will be retrieved.
|
|
|
|
|
// If a string is specified, then only scripts whose names contain the filter string will be retrieved.>
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
QScriptValue jsonVal = initObject();
|
|
|
|
|
jsonVal.setProperty(_(COMMAND), QScriptValue(_(SCRIPTS)));
|
|
|
|
|
|
|
|
|
|
QScriptValue args = parser.call(QScriptValue(), QScriptValueList() << QScriptValue(_(OBJECT)));
|
|
|
|
|
args.setProperty(_(TYPES), QScriptValue(types));
|
|
|
|
|
|
|
|
|
|
if (ids.count()) {
|
|
|
|
|
QScriptValue array = parser.call(QScriptValue(), QScriptValueList() << _(ARRAY));
|
|
|
|
|
int index = 0;
|
|
|
|
|
foreach (int id, ids) {
|
|
|
|
|
array.setProperty(index++, QScriptValue(id));
|
2011-09-06 17:03:16 +02:00
|
|
|
}
|
2011-10-26 10:02:37 +02:00
|
|
|
args.setProperty(_(IDS), array);
|
2011-09-06 17:03:16 +02:00
|
|
|
}
|
2011-10-26 10:02:37 +02:00
|
|
|
|
|
|
|
|
if (includeSource)
|
|
|
|
|
args.setProperty(_(INCLUDESOURCE), QScriptValue(includeSource));
|
|
|
|
|
|
|
|
|
|
jsonVal.setProperty(_(ARGUMENTS), args);
|
|
|
|
|
|
|
|
|
|
const QScriptValue jsonMessage = stringifier.call(QScriptValue(), QScriptValueList() << jsonVal);
|
|
|
|
|
q->sendMessage(packMessage(jsonMessage.toString().toUtf8()));
|
2011-07-26 16:22:49 +02:00
|
|
|
}
|
|
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
void QmlV8DebuggerClientPrivate::source(int frame, int fromLine, int toLine)
|
2011-07-26 16:22:49 +02:00
|
|
|
{
|
2011-10-26 10:02:37 +02:00
|
|
|
// { "seq" : <number>,
|
|
|
|
|
// "type" : "request",
|
|
|
|
|
// "command" : "source",
|
|
|
|
|
// "arguments" : { "frame" : <frame number (default selected frame)>
|
|
|
|
|
// "fromLine" : <from line within the source default is line 0>
|
|
|
|
|
// "toLine" : <to line within the source this line is not included in
|
|
|
|
|
// the result default is the number of lines in the script>
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
QScriptValue jsonVal = initObject();
|
|
|
|
|
jsonVal.setProperty(_(COMMAND), QScriptValue(_(SOURCE)));
|
2011-09-06 17:03:16 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
QScriptValue args = parser.call(QScriptValue(), QScriptValueList() << QScriptValue(_(OBJECT)));
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
if (frame != -1)
|
|
|
|
|
args.setProperty(_(FRAME), QScriptValue(frame));
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
if (fromLine != -1)
|
|
|
|
|
args.setProperty(_(FROMLINE), QScriptValue(fromLine));
|
2011-09-06 17:03:16 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
if (toLine != -1)
|
|
|
|
|
args.setProperty(_(TOLINE), QScriptValue(toLine));
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
jsonVal.setProperty(_(ARGUMENTS), args);
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
const QScriptValue jsonMessage = stringifier.call(QScriptValue(), QScriptValueList() << jsonVal);
|
|
|
|
|
q->sendMessage(packMessage(jsonMessage.toString().toUtf8()));
|
|
|
|
|
}
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
void QmlV8DebuggerClientPrivate::setBreakpoint(const QString type, const QString target,
|
|
|
|
|
int line, int column, bool enabled,
|
|
|
|
|
const QString condition, int ignoreCount)
|
|
|
|
|
{
|
|
|
|
|
// { "seq" : <number>,
|
|
|
|
|
// "type" : "request",
|
|
|
|
|
// "command" : "setbreakpoint",
|
|
|
|
|
// "arguments" : { "type" : <"function" or "script" or "scriptId" or "scriptRegExp">
|
|
|
|
|
// "target" : <function expression or script identification>
|
|
|
|
|
// "line" : <line in script or function>
|
|
|
|
|
// "column" : <character position within the line>
|
|
|
|
|
// "enabled" : <initial enabled state. True or false, default is true>
|
|
|
|
|
// "condition" : <string with break point condition>
|
|
|
|
|
// "ignoreCount" : <number specifying the number of break point hits to ignore, default value is 0>
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
QScriptValue jsonVal = initObject();
|
|
|
|
|
jsonVal.setProperty(_(COMMAND), QScriptValue(_(SETBREAKPOINT)));
|
|
|
|
|
|
|
|
|
|
QScriptValue args = parser.call(QScriptValue(), QScriptValueList() << QScriptValue(_(OBJECT)));
|
|
|
|
|
|
|
|
|
|
args.setProperty(_(TYPE), QScriptValue(type));
|
|
|
|
|
args.setProperty(_(TARGET), QScriptValue(target));
|
|
|
|
|
|
|
|
|
|
if (line != -1)
|
|
|
|
|
args.setProperty(_(LINE), QScriptValue(line));
|
|
|
|
|
|
|
|
|
|
if (column != -1)
|
|
|
|
|
args.setProperty(_(COLUMN), QScriptValue(column));
|
|
|
|
|
|
|
|
|
|
args.setProperty(_(ENABLED), QScriptValue(enabled));
|
|
|
|
|
|
|
|
|
|
if (!condition.isEmpty())
|
|
|
|
|
args.setProperty(_(CONDITION), QScriptValue(condition));
|
|
|
|
|
|
|
|
|
|
if (ignoreCount != -1)
|
|
|
|
|
args.setProperty(_(IGNORECOUNT), QScriptValue(ignoreCount));
|
|
|
|
|
|
|
|
|
|
jsonVal.setProperty(_(ARGUMENTS), args);
|
|
|
|
|
|
|
|
|
|
const QScriptValue jsonMessage = stringifier.call(QScriptValue(), QScriptValueList() << jsonVal);
|
|
|
|
|
q->sendMessage(packMessage(jsonMessage.toString().toUtf8()));
|
2011-07-26 16:22:49 +02:00
|
|
|
}
|
|
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
void QmlV8DebuggerClientPrivate::changeBreakpoint(int breakpoint, bool enabled,
|
|
|
|
|
const QString condition, int ignoreCount)
|
2011-07-26 16:22:49 +02:00
|
|
|
{
|
2011-10-26 10:02:37 +02:00
|
|
|
// { "seq" : <number>,
|
|
|
|
|
// "type" : "request",
|
|
|
|
|
// "command" : "changebreakpoint",
|
|
|
|
|
// "arguments" : { "breakpoint" : <number of the break point to clear>
|
|
|
|
|
// "enabled" : <initial enabled state. True or false,
|
|
|
|
|
// default is true>
|
|
|
|
|
// "condition" : <string with break point condition>
|
|
|
|
|
// "ignoreCount" : <number specifying the number of break point hits }
|
|
|
|
|
// }
|
|
|
|
|
QScriptValue jsonVal = initObject();
|
|
|
|
|
jsonVal.setProperty(_(COMMAND),
|
|
|
|
|
QScriptValue(_(CHANGEBREAKPOINT)));
|
|
|
|
|
|
|
|
|
|
QScriptValue args = parser.call(QScriptValue(), QScriptValueList() << QScriptValue(_(OBJECT)));
|
|
|
|
|
|
|
|
|
|
args.setProperty(_(BREAKPOINT), QScriptValue(breakpoint));
|
|
|
|
|
|
|
|
|
|
args.setProperty(_(ENABLED), QScriptValue(enabled));
|
|
|
|
|
|
|
|
|
|
if (!condition.isEmpty())
|
|
|
|
|
args.setProperty(_(CONDITION), QScriptValue(condition));
|
|
|
|
|
|
|
|
|
|
if (ignoreCount != -1)
|
|
|
|
|
args.setProperty(_(IGNORECOUNT), QScriptValue(ignoreCount));
|
|
|
|
|
|
|
|
|
|
jsonVal.setProperty(_(ARGUMENTS), args);
|
|
|
|
|
|
|
|
|
|
const QScriptValue jsonMessage = stringifier.call(QScriptValue(), QScriptValueList() << jsonVal);
|
|
|
|
|
q->sendMessage(packMessage(jsonMessage.toString().toUtf8()));
|
2011-09-06 17:03:16 +02:00
|
|
|
}
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
void QmlV8DebuggerClientPrivate::clearBreakpoint(int breakpoint)
|
|
|
|
|
{
|
|
|
|
|
// { "seq" : <number>,
|
|
|
|
|
// "type" : "request",
|
|
|
|
|
// "command" : "clearbreakpoint",
|
|
|
|
|
// "arguments" : { "breakpoint" : <number of the break point to clear>
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
QScriptValue jsonVal = initObject();
|
|
|
|
|
jsonVal.setProperty(_(COMMAND),
|
|
|
|
|
QScriptValue(_(CLEARBREAKPOINT)));
|
|
|
|
|
|
|
|
|
|
QScriptValue args = parser.call(QScriptValue(), QScriptValueList() << QScriptValue(_(OBJECT)));
|
|
|
|
|
|
|
|
|
|
args.setProperty(_(BREAKPOINT), QScriptValue(breakpoint));
|
|
|
|
|
|
|
|
|
|
jsonVal.setProperty(_(ARGUMENTS), args);
|
|
|
|
|
|
|
|
|
|
const QScriptValue jsonMessage = stringifier.call(QScriptValue(), QScriptValueList() << jsonVal);
|
|
|
|
|
q->sendMessage(packMessage(jsonMessage.toString().toUtf8()));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void QmlV8DebuggerClientPrivate::setExceptionBreak(QmlV8DebuggerClient::Exceptions type,
|
|
|
|
|
bool enabled)
|
2011-09-06 17:03:16 +02:00
|
|
|
{
|
2011-10-26 10:02:37 +02:00
|
|
|
// { "seq" : <number>,
|
|
|
|
|
// "type" : "request",
|
|
|
|
|
// "command" : "setexceptionbreak",
|
|
|
|
|
// "arguments" : { "type" : <string: "all", or "uncaught">,
|
|
|
|
|
// "enabled" : <optional bool: enables the break type if true>
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
QScriptValue jsonVal = initObject();
|
|
|
|
|
jsonVal.setProperty(_(COMMAND),
|
|
|
|
|
QScriptValue(_(SETEXCEPTIONBREAK)));
|
|
|
|
|
|
|
|
|
|
QScriptValue args = parser.call(QScriptValue(), QScriptValueList() << QScriptValue(_(OBJECT)));
|
|
|
|
|
|
|
|
|
|
if (type == QmlV8DebuggerClient::AllExceptions)
|
|
|
|
|
args.setProperty(_(TYPE), QScriptValue(_(ALL)));
|
|
|
|
|
//Not Supported
|
|
|
|
|
// else if (type == QmlV8DebuggerClient::UncaughtExceptions)
|
|
|
|
|
// args.setProperty(_(TYPE),QScriptValue(_(UNCAUGHT)));
|
|
|
|
|
|
|
|
|
|
if (enabled)
|
|
|
|
|
args.setProperty(_(ENABLED), QScriptValue(enabled));
|
|
|
|
|
|
|
|
|
|
jsonVal.setProperty(_(ARGUMENTS), args);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const QScriptValue jsonMessage = stringifier.call(QScriptValue(), QScriptValueList() << jsonVal);
|
|
|
|
|
q->sendMessage(packMessage(jsonMessage.toString().toUtf8()));
|
2011-09-06 17:03:16 +02:00
|
|
|
}
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
void QmlV8DebuggerClientPrivate::listBreakpoints()
|
2011-09-06 17:03:16 +02:00
|
|
|
{
|
2011-10-26 10:02:37 +02:00
|
|
|
// { "seq" : <number>,
|
|
|
|
|
// "type" : "request",
|
|
|
|
|
// "command" : "listbreakpoints",
|
|
|
|
|
// }
|
|
|
|
|
QScriptValue jsonVal = initObject();
|
|
|
|
|
jsonVal.setProperty(_(COMMAND),
|
|
|
|
|
QScriptValue(_(LISTBREAKPOINTS)));
|
|
|
|
|
|
|
|
|
|
const QScriptValue jsonMessage = stringifier.call(QScriptValue(), QScriptValueList() << jsonVal);
|
|
|
|
|
q->sendMessage(packMessage(jsonMessage.toString().toUtf8()));
|
2011-09-06 17:03:16 +02:00
|
|
|
}
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
void QmlV8DebuggerClientPrivate::v8flags(const QString flags)
|
2011-09-06 17:03:16 +02:00
|
|
|
{
|
2011-10-26 10:02:37 +02:00
|
|
|
// { "seq" : <number>,
|
|
|
|
|
// "type" : "request",
|
|
|
|
|
// "command" : "v8flags",
|
|
|
|
|
// "arguments" : { "flags" : <string: a sequence of v8 flags just like
|
|
|
|
|
// those used on the command line>
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
QScriptValue jsonVal = initObject();
|
|
|
|
|
jsonVal.setProperty(_(COMMAND), QScriptValue(_(V8FLAGS)));
|
|
|
|
|
|
|
|
|
|
QScriptValue args = parser.call(QScriptValue(), QScriptValueList() << QScriptValue(_(OBJECT)));
|
|
|
|
|
|
|
|
|
|
args.setProperty(_(FLAGS), QScriptValue(flags));
|
|
|
|
|
|
|
|
|
|
jsonVal.setProperty(_(ARGUMENTS), args);
|
|
|
|
|
|
|
|
|
|
const QScriptValue jsonMessage = stringifier.call(QScriptValue(), QScriptValueList() << jsonVal);
|
|
|
|
|
q->sendMessage(packMessage(jsonMessage.toString().toUtf8()));
|
2011-09-06 17:03:16 +02:00
|
|
|
}
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
void QmlV8DebuggerClientPrivate::version()
|
2011-09-06 17:03:16 +02:00
|
|
|
{
|
2011-10-26 10:02:37 +02:00
|
|
|
// { "seq" : <number>,
|
|
|
|
|
// "type" : "request",
|
|
|
|
|
// "command" : "version",
|
|
|
|
|
// }
|
|
|
|
|
QScriptValue jsonVal = initObject();
|
|
|
|
|
jsonVal.setProperty(_(COMMAND), QScriptValue(_(VERSION)));
|
|
|
|
|
|
|
|
|
|
const QScriptValue jsonMessage = stringifier.call(QScriptValue(), QScriptValueList() << jsonVal);
|
|
|
|
|
q->sendMessage(packMessage(jsonMessage.toString().toUtf8()));
|
2011-07-26 16:22:49 +02:00
|
|
|
}
|
|
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
//void QmlV8DebuggerClientPrivate::profile(ProfileCommand command)
|
|
|
|
|
//{
|
|
|
|
|
//// { "seq" : <number>,
|
|
|
|
|
//// "type" : "request",
|
|
|
|
|
//// "command" : "profile",
|
|
|
|
|
//// "arguments" : { "command" : "resume" or "pause" }
|
|
|
|
|
//// }
|
|
|
|
|
// QScriptValue jsonVal = initObject();
|
|
|
|
|
// jsonVal.setProperty(_(COMMAND), QScriptValue(_(PROFILE)));
|
|
|
|
|
|
|
|
|
|
// QScriptValue args = m_parser.call(QScriptValue(), QScriptValueList() << QScriptValue(_(OBJECT)));
|
|
|
|
|
|
|
|
|
|
// if (command == Resume)
|
|
|
|
|
// args.setProperty(_(COMMAND), QScriptValue(_(RESUME)));
|
|
|
|
|
// else
|
|
|
|
|
// args.setProperty(_(COMMAND), QScriptValue(_(PAUSE)));
|
|
|
|
|
|
|
|
|
|
// args.setProperty(_("modules"), QScriptValue(1));
|
|
|
|
|
// jsonVal.setProperty(_(ARGUMENTS), args);
|
|
|
|
|
|
|
|
|
|
// const QScriptValue jsonMessage = m_stringifier.call(QScriptValue(), QScriptValueList() << jsonVal);
|
|
|
|
|
// q->sendMessage(packMessage(jsonMessage.toString().toUtf8()));
|
|
|
|
|
//}
|
|
|
|
|
|
|
|
|
|
void QmlV8DebuggerClientPrivate::gc()
|
2011-07-26 16:22:49 +02:00
|
|
|
{
|
2011-10-26 10:02:37 +02:00
|
|
|
// { "seq" : <number>,
|
|
|
|
|
// "type" : "request",
|
|
|
|
|
// "command" : "gc",
|
|
|
|
|
// "arguments" : { "type" : <string: "all">,
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
QScriptValue jsonVal = initObject();
|
|
|
|
|
jsonVal.setProperty(_(COMMAND),
|
|
|
|
|
QScriptValue(_(GARBAGECOLLECTOR)));
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
QScriptValue args = parser.call(QScriptValue(), QScriptValueList() << QScriptValue(_(OBJECT)));
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
args.setProperty(_(TYPE), QScriptValue(_(ALL)));
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
jsonVal.setProperty(_(ARGUMENTS), args);
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
const QScriptValue jsonMessage = stringifier.call(QScriptValue(), QScriptValueList() << jsonVal);
|
|
|
|
|
q->sendMessage(packMessage(jsonMessage.toString().toUtf8()));
|
2011-07-26 16:22:49 +02:00
|
|
|
}
|
|
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
QmlV8ObjectData QmlV8DebuggerClientPrivate::extractData(const QVariant &data)
|
|
|
|
|
{
|
|
|
|
|
// { "handle" : <handle>,
|
|
|
|
|
// "type" : <"undefined", "null", "boolean", "number", "string", "object", "function" or "frame">
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// {"handle":<handle>,"type":"undefined"}
|
|
|
|
|
|
|
|
|
|
// {"handle":<handle>,"type":"null"}
|
|
|
|
|
|
|
|
|
|
// { "handle":<handle>,
|
|
|
|
|
// "type" : <"boolean", "number" or "string">
|
|
|
|
|
// "value" : <JSON encoded value>
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// {"handle":7,"type":"boolean","value":true}
|
|
|
|
|
|
|
|
|
|
// {"handle":8,"type":"number","value":42}
|
|
|
|
|
|
|
|
|
|
// { "handle" : <handle>,
|
|
|
|
|
// "type" : "object",
|
|
|
|
|
// "className" : <Class name, ECMA-262 property [[Class]]>,
|
|
|
|
|
// "constructorFunction" : {"ref":<handle>},
|
|
|
|
|
// "protoObject" : {"ref":<handle>},
|
|
|
|
|
// "prototypeObject" : {"ref":<handle>},
|
|
|
|
|
// "properties" : [ {"name" : <name>,
|
|
|
|
|
// "ref" : <handle>
|
|
|
|
|
// },
|
|
|
|
|
// ...
|
|
|
|
|
// ]
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// { "handle" : <handle>,
|
|
|
|
|
// "type" : "function",
|
|
|
|
|
// "className" : "Function",
|
|
|
|
|
// "constructorFunction" : {"ref":<handle>},
|
|
|
|
|
// "protoObject" : {"ref":<handle>},
|
|
|
|
|
// "prototypeObject" : {"ref":<handle>},
|
|
|
|
|
// "name" : <function name>,
|
|
|
|
|
// "inferredName" : <inferred function name for anonymous functions>
|
|
|
|
|
// "source" : <function source>,
|
|
|
|
|
// "script" : <reference to function script>,
|
|
|
|
|
// "scriptId" : <id of function script>,
|
|
|
|
|
// "position" : <function begin position in script>,
|
|
|
|
|
// "line" : <function begin source line in script>,
|
|
|
|
|
// "column" : <function begin source column in script>,
|
|
|
|
|
// "properties" : [ {"name" : <name>,
|
|
|
|
|
// "ref" : <handle>
|
|
|
|
|
// },
|
|
|
|
|
// ...
|
|
|
|
|
// ]
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
QmlV8ObjectData objectData;
|
|
|
|
|
const QVariantMap dataMap = data.toMap();
|
|
|
|
|
QString type = dataMap.value(_(TYPE)).toString();
|
|
|
|
|
|
|
|
|
|
if (type == _("undefined")) {
|
|
|
|
|
objectData.type = QByteArray("undefined");
|
|
|
|
|
objectData.value = QVariant(_("undefined"));
|
|
|
|
|
|
|
|
|
|
} else if (type == _("null")) {
|
|
|
|
|
objectData.type = QByteArray("null");
|
|
|
|
|
objectData.value= QVariant(_("null"));
|
|
|
|
|
|
|
|
|
|
} else if (type == _("boolean")) {
|
|
|
|
|
objectData.type = QByteArray("boolean");
|
|
|
|
|
objectData.value = dataMap.value(_(VALUE));
|
|
|
|
|
|
|
|
|
|
} else if (type == _("number")) {
|
|
|
|
|
objectData.type = QByteArray("number");
|
|
|
|
|
objectData.value = dataMap.value(_(VALUE));
|
|
|
|
|
|
|
|
|
|
} else if (type == _("string")) {
|
|
|
|
|
objectData.type = QByteArray("string");
|
|
|
|
|
objectData.value = dataMap.value(_(VALUE));
|
|
|
|
|
|
|
|
|
|
} else if (type == _("object")) {
|
|
|
|
|
objectData.type = QByteArray("object");
|
|
|
|
|
objectData.value = dataMap.value(_("className"));
|
|
|
|
|
objectData.properties = dataMap.value(_("properties"));
|
|
|
|
|
|
|
|
|
|
} else if (type == _("function")) {
|
|
|
|
|
objectData.type = QByteArray("function");
|
|
|
|
|
objectData.value = dataMap.value(_(NAME));
|
|
|
|
|
objectData.properties = dataMap.value(_("properties"));
|
|
|
|
|
|
|
|
|
|
} else if (type == _("script")) {
|
|
|
|
|
objectData.type = QByteArray("script");
|
|
|
|
|
objectData.value = dataMap.value(_(NAME));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return objectData;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QByteArray QmlV8DebuggerClientPrivate::packMessage(const QByteArray &message)
|
2011-08-22 13:08:58 +02:00
|
|
|
{
|
2011-10-26 10:02:37 +02:00
|
|
|
QByteArray reply;
|
|
|
|
|
QDataStream rs(&reply, QIODevice::WriteOnly);
|
|
|
|
|
QByteArray cmd = V8DEBUG;
|
|
|
|
|
rs << cmd << message;
|
|
|
|
|
SDEBUG(QString(message));
|
|
|
|
|
return reply;
|
|
|
|
|
}
|
2011-08-22 13:08:58 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
QScriptValue QmlV8DebuggerClientPrivate::initObject()
|
|
|
|
|
{
|
|
|
|
|
QScriptValue jsonVal = parser.call(QScriptValue(),
|
|
|
|
|
QScriptValueList() << QScriptValue(_(OBJECT)));
|
|
|
|
|
jsonVal.setProperty(_(SEQ), QScriptValue(++sequence));
|
|
|
|
|
jsonVal.setProperty(_(TYPE), _(REQUEST));
|
|
|
|
|
return jsonVal;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
|
//
|
|
|
|
|
// QmlV8DebuggerClient
|
|
|
|
|
//
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
QmlV8DebuggerClient::QmlV8DebuggerClient(QmlJsDebugClient::QDeclarativeDebugConnection *client)
|
|
|
|
|
: QmlDebuggerClient(client, QLatin1String("V8Debugger")),
|
|
|
|
|
d(new QmlV8DebuggerClientPrivate(this))
|
|
|
|
|
{
|
2011-10-27 13:03:35 +02:00
|
|
|
resetState();
|
2011-10-26 10:02:37 +02:00
|
|
|
}
|
2011-08-22 13:08:58 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
QmlV8DebuggerClient::~QmlV8DebuggerClient()
|
|
|
|
|
{
|
|
|
|
|
delete d;
|
|
|
|
|
}
|
2011-08-22 13:08:58 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
void QmlV8DebuggerClient::startSession()
|
|
|
|
|
{
|
|
|
|
|
d->connect();
|
2011-08-22 13:08:58 +02:00
|
|
|
}
|
|
|
|
|
|
2011-08-24 17:35:07 +02:00
|
|
|
void QmlV8DebuggerClient::endSession()
|
2011-08-17 13:42:41 +02:00
|
|
|
{
|
2011-10-26 10:32:46 +02:00
|
|
|
resetState();
|
2011-10-26 10:02:37 +02:00
|
|
|
d->disconnect();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void QmlV8DebuggerClient::executeStep()
|
|
|
|
|
{
|
2011-10-26 10:32:46 +02:00
|
|
|
QTC_CHECK(d->state == QmlV8DebuggerClient::WaitingForRequestState);
|
2011-10-26 10:02:37 +02:00
|
|
|
d->continueDebugging(In);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void QmlV8DebuggerClient::executeStepOut()
|
|
|
|
|
{
|
2011-10-26 10:32:46 +02:00
|
|
|
QTC_CHECK(d->state == QmlV8DebuggerClient::WaitingForRequestState);
|
2011-10-26 10:02:37 +02:00
|
|
|
d->continueDebugging(Out);
|
|
|
|
|
}
|
2011-09-06 17:03:16 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
void QmlV8DebuggerClient::executeNext()
|
|
|
|
|
{
|
2011-10-26 10:32:46 +02:00
|
|
|
QTC_CHECK(d->state == QmlV8DebuggerClient::WaitingForRequestState);
|
2011-10-26 10:02:37 +02:00
|
|
|
d->continueDebugging(Next);
|
|
|
|
|
}
|
2011-08-17 13:42:41 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
void QmlV8DebuggerClient::executeStepI()
|
|
|
|
|
{
|
2011-10-26 10:32:46 +02:00
|
|
|
QTC_CHECK(d->state == QmlV8DebuggerClient::WaitingForRequestState);
|
2011-10-26 10:02:37 +02:00
|
|
|
d->continueDebugging(In);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void QmlV8DebuggerClient::continueInferior()
|
|
|
|
|
{
|
2011-10-26 10:32:46 +02:00
|
|
|
QTC_CHECK(d->state == QmlV8DebuggerClient::WaitingForRequestState);
|
2011-10-26 10:02:37 +02:00
|
|
|
d->continueDebugging(Continue);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void QmlV8DebuggerClient::interruptInferior()
|
|
|
|
|
{
|
2011-10-26 10:32:46 +02:00
|
|
|
QTC_CHECK(d->state == QmlV8DebuggerClient::WaitingForRequestState
|
|
|
|
|
|| d->state == QmlV8DebuggerClient::RunningState);
|
2011-10-26 10:02:37 +02:00
|
|
|
d->interrupt();
|
2011-08-17 13:42:41 +02:00
|
|
|
}
|
|
|
|
|
|
2011-07-26 16:22:49 +02:00
|
|
|
void QmlV8DebuggerClient::activateFrame(int index)
|
|
|
|
|
{
|
2011-10-26 10:32:46 +02:00
|
|
|
QTC_CHECK(d->state == QmlV8DebuggerClient::WaitingForRequestState);
|
2011-10-26 10:02:37 +02:00
|
|
|
d->backtrace(index);
|
2011-07-26 16:22:49 +02:00
|
|
|
}
|
|
|
|
|
|
2011-09-13 12:47:46 +02:00
|
|
|
bool QmlV8DebuggerClient::acceptsBreakpoint(const BreakpointModelId &id)
|
|
|
|
|
{
|
|
|
|
|
BreakpointType type = d->engine->breakHandler()->breakpointData(id).type;
|
2011-10-10 15:25:18 +02:00
|
|
|
return (type == BreakpointOnQmlSignalHandler
|
|
|
|
|
|| type == BreakpointByFunction
|
|
|
|
|
|| type == BreakpointAtJavaScriptThrow);
|
2011-09-13 12:47:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void QmlV8DebuggerClient::insertBreakpoint(const BreakpointModelId &id)
|
2011-07-26 16:22:49 +02:00
|
|
|
{
|
2011-10-26 10:32:46 +02:00
|
|
|
QTC_CHECK(d->state == QmlV8DebuggerClient::WaitingForRequestState
|
|
|
|
|
|| d->state == QmlV8DebuggerClient::RunningState);
|
2011-10-28 16:43:20 +02:00
|
|
|
SDEBUG(QString(_("State: %1")).arg(d->state));
|
2011-08-22 17:23:34 +02:00
|
|
|
BreakHandler *handler = d->engine->breakHandler();
|
2011-10-10 15:25:18 +02:00
|
|
|
const BreakpointParameters ¶ms = handler->breakpointData(id);
|
|
|
|
|
|
|
|
|
|
if (params.type == BreakpointAtJavaScriptThrow) {
|
|
|
|
|
handler->notifyBreakpointInsertOk(id);
|
2011-10-26 10:02:37 +02:00
|
|
|
d->setExceptionBreak(AllExceptions, params.enabled);
|
2011-10-10 15:25:18 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
} else if (params.type == BreakpointByFileAndLine) {
|
|
|
|
|
d->setBreakpoint(QString(_(SCRIPT)), QFileInfo(params.fileName).fileName(),
|
|
|
|
|
params.lineNumber - 1, -1, params.enabled,
|
|
|
|
|
QString(params.condition), params.ignoreCount);
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-10-10 15:25:18 +02:00
|
|
|
} else if (params.type == BreakpointByFunction) {
|
2011-10-26 10:02:37 +02:00
|
|
|
d->setBreakpoint(QString(_(FUNCTION)), params.functionName,
|
|
|
|
|
-1, -1, params.enabled, QString(params.condition),
|
|
|
|
|
params.ignoreCount);
|
|
|
|
|
|
2011-10-10 15:25:18 +02:00
|
|
|
} else if (params.type == BreakpointOnQmlSignalHandler) {
|
2011-10-26 10:02:37 +02:00
|
|
|
d->setBreakpoint(QString(_(EVENT)), params.functionName,
|
|
|
|
|
-1, -1, params.enabled);
|
2011-07-26 16:22:49 +02:00
|
|
|
}
|
|
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
d->breakpointsSync.insert(d->sequence, id);
|
2011-07-26 16:22:49 +02:00
|
|
|
}
|
|
|
|
|
|
2011-09-13 12:47:46 +02:00
|
|
|
void QmlV8DebuggerClient::removeBreakpoint(const BreakpointModelId &id)
|
2011-07-26 16:22:49 +02:00
|
|
|
{
|
2011-10-26 10:32:46 +02:00
|
|
|
QTC_CHECK(d->state == QmlV8DebuggerClient::WaitingForRequestState
|
|
|
|
|
|| d->state == QmlV8DebuggerClient::RunningState);
|
2011-10-26 10:02:37 +02:00
|
|
|
BreakHandler *handler = d->engine->breakHandler();
|
2011-10-10 15:25:18 +02:00
|
|
|
|
2011-08-23 15:05:30 +02:00
|
|
|
int breakpoint = d->breakpoints.value(id);
|
2011-08-17 11:47:42 +02:00
|
|
|
d->breakpoints.remove(id);
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
if (handler->breakpointData(id).type == BreakpointAtJavaScriptThrow) {
|
|
|
|
|
d->setExceptionBreak(AllExceptions);
|
|
|
|
|
} else {
|
|
|
|
|
d->clearBreakpoint(breakpoint);
|
|
|
|
|
}
|
2011-07-26 16:22:49 +02:00
|
|
|
}
|
|
|
|
|
|
2011-10-10 15:25:18 +02:00
|
|
|
void QmlV8DebuggerClient::changeBreakpoint(const BreakpointModelId &id)
|
2011-08-17 11:47:42 +02:00
|
|
|
{
|
2011-10-26 10:32:46 +02:00
|
|
|
QTC_CHECK(d->state == QmlV8DebuggerClient::WaitingForRequestState
|
|
|
|
|
|| d->state == QmlV8DebuggerClient::RunningState);
|
2011-10-10 15:25:18 +02:00
|
|
|
BreakHandler *handler = d->engine->breakHandler();
|
|
|
|
|
const BreakpointParameters ¶ms = handler->breakpointData(id);
|
|
|
|
|
|
|
|
|
|
if (params.type == BreakpointAtJavaScriptThrow) {
|
2011-10-26 10:02:37 +02:00
|
|
|
d->setExceptionBreak(AllExceptions, params.enabled);
|
2011-10-10 15:25:18 +02:00
|
|
|
}
|
2011-10-26 10:35:47 +02:00
|
|
|
|
|
|
|
|
int breakpoint = d->breakpoints.value(id);
|
|
|
|
|
d->changeBreakpoint(breakpoint, params.enabled, QString(params.condition),
|
|
|
|
|
params.ignoreCount);
|
|
|
|
|
|
|
|
|
|
BreakpointResponse br = handler->response(id);
|
|
|
|
|
br.enabled = params.enabled;
|
|
|
|
|
br.condition = params.condition;
|
|
|
|
|
br.ignoreCount = params.ignoreCount;
|
|
|
|
|
handler->setResponse(id, br);
|
2011-08-17 11:47:42 +02:00
|
|
|
}
|
|
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
void QmlV8DebuggerClient::synchronizeBreakpoints()
|
2011-07-26 16:22:49 +02:00
|
|
|
{
|
2011-10-26 10:02:37 +02:00
|
|
|
//NOT USED
|
2011-07-26 16:22:49 +02:00
|
|
|
}
|
|
|
|
|
|
2011-08-04 15:12:09 +02:00
|
|
|
void QmlV8DebuggerClient::assignValueInDebugger(const QByteArray /*expr*/, const quint64 &/*id*/,
|
2011-10-26 10:40:15 +02:00
|
|
|
const QString &property, const QString &value)
|
2011-07-26 16:22:49 +02:00
|
|
|
{
|
2011-10-26 10:40:15 +02:00
|
|
|
QTC_CHECK(d->state == QmlV8DebuggerClient::WaitingForRequestState);
|
|
|
|
|
StackHandler *stackHandler = d->engine->stackHandler();
|
|
|
|
|
QString expression = QString(_("%1 = %2;")).arg(property).arg(value);
|
|
|
|
|
if (stackHandler->isContentsValid()) {
|
|
|
|
|
d->state = QmlV8DebuggerClient::BacktraceRequestedState;
|
2011-10-28 16:43:20 +02:00
|
|
|
d->updateCurrentStackFrameIndex = false;
|
2011-10-26 10:40:15 +02:00
|
|
|
d->evaluate(expression, false, false, stackHandler->currentIndex());
|
|
|
|
|
}
|
2011-07-26 16:22:49 +02:00
|
|
|
}
|
|
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
void QmlV8DebuggerClient::updateWatchData(const WatchData &data)
|
2011-07-26 16:22:49 +02:00
|
|
|
{
|
2011-10-28 16:43:20 +02:00
|
|
|
QTC_CHECK(d->state == QmlV8DebuggerClient::WaitingForRequestState
|
|
|
|
|
|| d->state == QmlV8DebuggerClient::RunningState);
|
|
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
if (data.isWatcher()) {
|
2011-10-28 16:43:20 +02:00
|
|
|
QString exp(data.exp);
|
|
|
|
|
if (!d->watchedExpressions.contains(exp)) {
|
|
|
|
|
//Push new expression to the stack
|
|
|
|
|
d->watchesToEvaluate.push(exp);
|
2011-10-26 10:02:37 +02:00
|
|
|
}
|
|
|
|
|
}
|
2011-07-26 16:22:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void QmlV8DebuggerClient::executeDebuggerCommand(const QString &command)
|
|
|
|
|
{
|
2011-10-26 10:32:46 +02:00
|
|
|
QTC_CHECK(d->state == QmlV8DebuggerClient::WaitingForRequestState
|
|
|
|
|
|| d->state == QmlV8DebuggerClient::RunningState);
|
2011-10-26 10:02:37 +02:00
|
|
|
StackHandler *stackHandler = d->engine->stackHandler();
|
|
|
|
|
if (stackHandler->isContentsValid()) {
|
2011-10-26 10:32:46 +02:00
|
|
|
//Set the state
|
|
|
|
|
d->state = QmlV8DebuggerClient::BacktraceRequestedState;
|
2011-10-28 16:43:20 +02:00
|
|
|
d->updateCurrentStackFrameIndex = false;
|
2011-10-26 10:02:37 +02:00
|
|
|
d->evaluate(command, false, false, stackHandler->currentIndex());
|
|
|
|
|
} else {
|
|
|
|
|
//Currently cannot evaluate if not in a javascript break
|
|
|
|
|
d->engine->showMessage(_("Request Was Unsuccessful"), ScriptConsoleOutput);
|
|
|
|
|
// d->evaluate(command);
|
|
|
|
|
}
|
2011-07-26 16:22:49 +02:00
|
|
|
}
|
|
|
|
|
|
2011-10-28 16:43:20 +02:00
|
|
|
void QmlV8DebuggerClient::synchronizeWatchers(const QStringList &watchers)
|
2011-07-26 16:22:49 +02:00
|
|
|
{
|
2011-10-28 16:43:20 +02:00
|
|
|
SDEBUG(watchers);
|
|
|
|
|
//Cache the watched expression List
|
|
|
|
|
d->watchedExpressions = watchers;
|
|
|
|
|
//Evaluate new expressions one at a time.
|
|
|
|
|
if (!d->watchesToEvaluate.isEmpty()) {
|
|
|
|
|
StackHandler *stackHandler = d->engine->stackHandler();
|
|
|
|
|
const QString exp = d->watchesToEvaluate.pop();
|
|
|
|
|
if (stackHandler->isContentsValid()) {
|
|
|
|
|
d->evaluate(exp, false, false, stackHandler->currentIndex());
|
|
|
|
|
} else {
|
|
|
|
|
d->evaluate(exp);
|
|
|
|
|
}
|
|
|
|
|
d->evaluatingWatches.insert(d->sequence, exp);
|
|
|
|
|
}
|
2011-07-26 16:22:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void QmlV8DebuggerClient::expandObject(const QByteArray &iname, quint64 objectId)
|
|
|
|
|
{
|
2011-10-26 10:32:46 +02:00
|
|
|
QTC_CHECK(d->state == QmlV8DebuggerClient::WaitingForRequestState);
|
2011-10-28 16:43:20 +02:00
|
|
|
d->localsAndWatchers.insertMulti(objectId, iname);
|
2011-10-26 10:02:37 +02:00
|
|
|
d->lookup(QList<int>() << objectId);
|
2011-08-23 15:05:30 +02:00
|
|
|
}
|
|
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
void QmlV8DebuggerClient::setEngine(QmlEngine *engine)
|
2011-07-26 16:22:49 +02:00
|
|
|
{
|
2011-10-26 10:02:37 +02:00
|
|
|
d->engine = engine;
|
2011-07-26 16:22:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void QmlV8DebuggerClient::messageReceived(const QByteArray &data)
|
|
|
|
|
{
|
|
|
|
|
QDataStream ds(data);
|
|
|
|
|
QByteArray command;
|
|
|
|
|
ds >> command;
|
|
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
if (command == V8DEBUG) {
|
2011-07-26 16:22:49 +02:00
|
|
|
QByteArray response;
|
|
|
|
|
ds >> response;
|
2011-10-26 10:02:37 +02:00
|
|
|
QString responseString(response);
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
SDEBUG(responseString);
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
const QVariantMap resp = d->parser.call(QScriptValue(),
|
|
|
|
|
QScriptValueList() <<
|
|
|
|
|
QScriptValue(responseString)).toVariant().toMap();
|
|
|
|
|
const QString type(resp.value(_(TYPE)).toString());
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
if (type == _("response")) {
|
|
|
|
|
|
|
|
|
|
bool success = resp.value(_("success")).toBool();
|
|
|
|
|
if (!success) {
|
|
|
|
|
SDEBUG("Request was unsuccessful");
|
|
|
|
|
d->engine->logMessage(QmlEngine::LogReceive,
|
|
|
|
|
QString(_("V8 Response Error: %1")).arg(
|
|
|
|
|
resp.value(_("message")).toString()));
|
2011-07-26 16:22:49 +02:00
|
|
|
}
|
|
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
const QString debugCommand(resp.value(_(COMMAND)).toString());
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
if (debugCommand == _(CONNECT)) {
|
|
|
|
|
//debugging session started
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
} else if (debugCommand == _(DISCONNECT)) {
|
|
|
|
|
//debugging session ended
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
} else if (debugCommand == _(BACKTRACE)) {
|
|
|
|
|
if (success) {
|
|
|
|
|
updateStack(resp.value(_(BODY)), resp.value(_(REFS)));
|
2011-09-13 12:47:46 +02:00
|
|
|
}
|
|
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
} else if (debugCommand == _(LOOKUP)) {
|
2011-10-28 16:43:20 +02:00
|
|
|
expandLocalsAndWatchers(resp.value(_(BODY)), resp.value(_(REFS)));
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
} else if (debugCommand == _(EVALUATE)) {
|
2011-10-28 16:43:20 +02:00
|
|
|
int seq = resp.value(_("request_seq")).toInt();
|
2011-10-26 10:02:37 +02:00
|
|
|
if (success) {
|
|
|
|
|
updateEvaluationResult(seq, resp.value(_(BODY)), resp.value(_(REFS)));
|
|
|
|
|
} else {
|
|
|
|
|
d->engine->showMessage(resp.value(_("message")).toString(), ScriptConsoleOutput);
|
2011-10-28 16:43:20 +02:00
|
|
|
if (d->evaluatingWatches.contains(seq))
|
|
|
|
|
updateEvaluationResult(seq, QVariant(), QVariant());
|
2011-10-26 10:02:37 +02:00
|
|
|
}
|
2011-08-23 15:05:30 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
} else if (debugCommand == _(LISTBREAKPOINTS)) {
|
|
|
|
|
updateBreakpoints(resp.value(_(BODY)));
|
|
|
|
|
|
|
|
|
|
} else if (debugCommand == _(SETBREAKPOINT)) {
|
|
|
|
|
// { "seq" : <number>,
|
|
|
|
|
// "type" : "response",
|
|
|
|
|
// "request_seq" : <number>,
|
|
|
|
|
// "command" : "setbreakpoint",
|
|
|
|
|
// "body" : { "type" : <"function" or "script">
|
|
|
|
|
// "breakpoint" : <break point number of the new break point>
|
|
|
|
|
// }
|
|
|
|
|
// "running" : <is the VM running after sending this response>
|
|
|
|
|
// "success" : true
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
int seq = resp.value(_("request_seq")).toInt();
|
|
|
|
|
const QVariantMap breakpointData = resp.value(_(BODY)).toMap();
|
|
|
|
|
int index = breakpointData.value(_("breakpoint")).toInt();
|
|
|
|
|
|
|
|
|
|
BreakpointModelId id = d->breakpointsSync.take(seq);
|
|
|
|
|
d->breakpoints.insert(id, index);
|
|
|
|
|
|
|
|
|
|
d->engine->breakHandler()->notifyBreakpointInsertOk(id);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} else if (debugCommand == _(CHANGEBREAKPOINT)) {
|
|
|
|
|
// DO NOTHING
|
|
|
|
|
|
|
|
|
|
} else if (debugCommand == _(CLEARBREAKPOINT)) {
|
|
|
|
|
// DO NOTHING
|
|
|
|
|
|
|
|
|
|
} else if (debugCommand == _(SETEXCEPTIONBREAK)) {
|
|
|
|
|
// { "seq" : <number>,
|
|
|
|
|
// "type" : "response",
|
|
|
|
|
// "request_seq" : <number>,
|
|
|
|
|
// "command" : "setexceptionbreak",
|
|
|
|
|
// “body” : { "type" : <string: "all" or "uncaught" corresponding to the request.>,
|
|
|
|
|
// "enabled" : <bool: true if the break type is currently enabled as a result of the request>
|
|
|
|
|
// }
|
|
|
|
|
// "running" : true
|
|
|
|
|
// "success" : true
|
|
|
|
|
// }
|
|
|
|
|
//TODO::
|
|
|
|
|
|
|
|
|
|
} else if (debugCommand == _(FRAME)) {
|
|
|
|
|
if (success) {
|
|
|
|
|
const QVariant body = resp.value(_(BODY));
|
|
|
|
|
const QVariant refs = resp.value(_(REFS));
|
|
|
|
|
const QVariant locals = body.toMap().value(_("locals"));
|
|
|
|
|
StackFrame frame = createStackFrame(body, refs);
|
|
|
|
|
updateLocals(locals, refs);
|
|
|
|
|
d->engine->stackHandler()->setCurrentIndex(frame.level);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} else if (debugCommand == _(SCOPE)) {
|
2011-10-31 14:17:01 +01:00
|
|
|
if (success) {
|
|
|
|
|
const QVariant body = resp.value(_(BODY)).toMap().value(_("object"));
|
|
|
|
|
const QVariant refs = resp.value(_(REFS));
|
|
|
|
|
updateScope(body, refs);
|
|
|
|
|
}
|
|
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
} else if (debugCommand == _(SCOPES)) {
|
|
|
|
|
} else if (debugCommand == _(SOURCE)) {
|
|
|
|
|
} else if (debugCommand == _(SCRIPTS)) {
|
|
|
|
|
} else if (debugCommand == _(VERSION)) {
|
|
|
|
|
} else if (debugCommand == _(V8FLAGS)) {
|
|
|
|
|
} else if (debugCommand == _(GARBAGECOLLECTOR)) {
|
2011-07-26 16:22:49 +02:00
|
|
|
} else {
|
2011-10-26 10:02:37 +02:00
|
|
|
// DO NOTHING
|
2011-07-26 16:22:49 +02:00
|
|
|
}
|
2011-10-26 10:02:37 +02:00
|
|
|
} else if (type == _(EVENT)) {
|
|
|
|
|
const QString eventType(resp.value(_(EVENT)).toString());
|
|
|
|
|
|
|
|
|
|
if (eventType == _("break")) {
|
|
|
|
|
//DO NOTHING
|
|
|
|
|
} else if (eventType == _("exception")) {
|
|
|
|
|
const QVariantMap body = resp.value(_(BODY)).toMap();
|
|
|
|
|
int lineNumber = body.value(_("sourceLine")).toInt() + 1;
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
const QVariantMap script = body.value(_("script")).toMap();
|
|
|
|
|
QUrl fileUrl(script.value(_(NAME)).toString());
|
|
|
|
|
QString filePath = d->engine->toFileInProject(fileUrl);
|
|
|
|
|
|
|
|
|
|
const QVariantMap exception = body.value(_("exception")).toMap();
|
|
|
|
|
QString errorMessage = exception.value(_("text")).toString();
|
|
|
|
|
|
|
|
|
|
highlightExceptionCode(lineNumber, filePath, errorMessage);
|
2011-07-26 16:22:49 +02:00
|
|
|
}
|
|
|
|
|
}
|
2011-10-26 10:02:37 +02:00
|
|
|
|
|
|
|
|
if (resp.value(_("running")).toBool()) {
|
2011-10-26 10:32:46 +02:00
|
|
|
d->state = QmlV8DebuggerClient::RunningState;
|
|
|
|
|
SDEBUG(QString(_("State: %1")).arg(d->state));
|
2011-10-26 10:02:37 +02:00
|
|
|
} else {
|
2011-10-26 10:32:46 +02:00
|
|
|
if (d->state == QmlV8DebuggerClient::RunningState) {
|
|
|
|
|
d->state = QmlV8DebuggerClient::BreakpointsRequestedState;
|
|
|
|
|
SDEBUG(QString(_("State: %1")).arg(d->state));
|
|
|
|
|
}
|
2011-10-26 10:02:37 +02:00
|
|
|
d->engine->inferiorSpontaneousStop();
|
2011-10-26 10:32:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (d->state == QmlV8DebuggerClient::BreakpointsRequestedState) {
|
|
|
|
|
d->state = QmlV8DebuggerClient::BacktraceRequestedState;
|
|
|
|
|
SDEBUG(QString(_("State: %1")).arg(d->state));
|
2011-10-26 10:02:37 +02:00
|
|
|
d->listBreakpoints();
|
2011-10-26 10:32:46 +02:00
|
|
|
} else if (d->state == QmlV8DebuggerClient::BacktraceRequestedState) {
|
|
|
|
|
d->state = QmlV8DebuggerClient::WaitingForRequestState;
|
|
|
|
|
SDEBUG(QString(_("State: %1")).arg(d->state));
|
2011-10-26 10:02:37 +02:00
|
|
|
d->backtrace(d->currentFrameIndex);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
//DO NOTHING
|
2011-07-26 16:22:49 +02:00
|
|
|
}
|
2011-10-26 10:02:37 +02:00
|
|
|
|
2011-07-26 16:22:49 +02:00
|
|
|
}
|
|
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
void QmlV8DebuggerClient::updateStack(const QVariant &bodyVal, const QVariant &refsVal)
|
2011-07-26 16:22:49 +02:00
|
|
|
{
|
2011-10-26 10:02:37 +02:00
|
|
|
// { "seq" : <number>,
|
|
|
|
|
// "type" : "response",
|
|
|
|
|
// "request_seq" : <number>,
|
|
|
|
|
// "command" : "backtrace",
|
|
|
|
|
// "body" : { "fromFrame" : <number>
|
|
|
|
|
// "toFrame" : <number>
|
|
|
|
|
// "totalFrames" : <number>
|
|
|
|
|
// "frames" : <array of frames - see frame request for details>
|
|
|
|
|
// }
|
|
|
|
|
// "running" : <is the VM running after sending this response>
|
|
|
|
|
// "success" : true
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
const QVariantMap body = bodyVal.toMap();
|
|
|
|
|
const QVariantList frames = body.value(_("frames")).toList();
|
|
|
|
|
|
|
|
|
|
d->currentFrameIndex = body.value(_("fromFrame")).toInt();
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
if (!d->currentFrameIndex ) {
|
2011-10-31 14:17:01 +01:00
|
|
|
StackFrames stackFrames;
|
|
|
|
|
foreach (const QVariant &frame, frames) {
|
|
|
|
|
stackFrames << createStackFrame(frame, refsVal);
|
|
|
|
|
}
|
2011-10-26 10:02:37 +02:00
|
|
|
d->engine->stackHandler()->setFrames(stackFrames);
|
|
|
|
|
}
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
if (d->updateCurrentStackFrameIndex) {
|
2011-10-31 14:17:01 +01:00
|
|
|
StackHandler *stackHandler = d->engine->stackHandler();
|
|
|
|
|
stackHandler->setCurrentIndex(d->currentFrameIndex);
|
|
|
|
|
d->engine->gotoLocation(stackHandler->currentFrame());
|
|
|
|
|
|
|
|
|
|
//Update all Locals visible in current scope
|
|
|
|
|
//Traverse the scope chain and store the local properties
|
|
|
|
|
//in a list and show them in the Locals Window.
|
|
|
|
|
const QVariantMap currentFrame = frames.value(0).toMap();
|
|
|
|
|
const QVariantList currentFrameScopes = currentFrame.value(_("scopes")).toList();
|
|
|
|
|
d->localDataList.clear();
|
|
|
|
|
d->currentFrameScopes.clear();
|
|
|
|
|
d->refsVal = refsVal;
|
|
|
|
|
foreach (const QVariant &scope, currentFrameScopes) {
|
|
|
|
|
d->currentFrameScopes.push(scope.toMap().value(_("index")).toInt());
|
|
|
|
|
}
|
|
|
|
|
if (!d->currentFrameScopes.isEmpty()) {
|
|
|
|
|
QTC_CHECK(d->state == QmlV8DebuggerClient::WaitingForRequestState);
|
|
|
|
|
d->scope(d->currentFrameScopes.pop(), d->currentFrameIndex);
|
|
|
|
|
} else {
|
|
|
|
|
updateLocalsAndWatchers();
|
|
|
|
|
}
|
2011-10-26 10:02:37 +02:00
|
|
|
}
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
d->updateCurrentStackFrameIndex = true;
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
}
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
StackFrame QmlV8DebuggerClient::createStackFrame(const QVariant &bodyVal, const QVariant &refsVal)
|
|
|
|
|
{
|
|
|
|
|
// { "seq" : <number>,
|
|
|
|
|
// "type" : "response",
|
|
|
|
|
// "request_seq" : <number>,
|
|
|
|
|
// "command" : "frame",
|
|
|
|
|
// "body" : { "index" : <frame number>,
|
|
|
|
|
// "receiver" : <frame receiver>,
|
|
|
|
|
// "func" : <function invoked>,
|
|
|
|
|
// "script" : <script for the function>,
|
|
|
|
|
// "constructCall" : <boolean indicating whether the function was called as constructor>,
|
|
|
|
|
// "debuggerFrame" : <boolean indicating whether this is an internal debugger frame>,
|
|
|
|
|
// "arguments" : [ { name: <name of the argument - missing of anonymous argument>,
|
|
|
|
|
// value: <value of the argument>
|
|
|
|
|
// },
|
|
|
|
|
// ... <the array contains all the arguments>
|
|
|
|
|
// ],
|
|
|
|
|
// "locals" : [ { name: <name of the local variable>,
|
|
|
|
|
// value: <value of the local variable>
|
|
|
|
|
// },
|
|
|
|
|
// ... <the array contains all the locals>
|
|
|
|
|
// ],
|
|
|
|
|
// "position" : <source position>,
|
|
|
|
|
// "line" : <source line>,
|
|
|
|
|
// "column" : <source column within the line>,
|
|
|
|
|
// "sourceLineText" : <text for current source line>,
|
|
|
|
|
// "scopes" : [ <array of scopes, see scope request below for format> ],
|
|
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
// "running" : <is the VM running after sending this response>
|
|
|
|
|
// "success" : true
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
const QVariantMap body = bodyVal.toMap();
|
|
|
|
|
|
|
|
|
|
StackFrame stackFrame;
|
|
|
|
|
stackFrame.level = body.value(_("index")).toInt();
|
|
|
|
|
|
|
|
|
|
QVariantMap func = body.value(_("func")).toMap();
|
|
|
|
|
if (func.contains(_(REF))) {
|
|
|
|
|
func = valueFromRef(func.value(_(REF)).toInt(), refsVal).toMap();
|
2011-07-26 16:22:49 +02:00
|
|
|
}
|
2011-10-26 10:02:37 +02:00
|
|
|
stackFrame.function = d->extractData(QVariant(func)).value.toString();
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
QVariantMap file = body.value(_("script")).toMap();
|
|
|
|
|
if (file.contains(_(REF))) {
|
|
|
|
|
file = valueFromRef(file.value(_(REF)).toInt(), refsVal).toMap();
|
2011-07-26 16:22:49 +02:00
|
|
|
}
|
2011-10-26 10:02:37 +02:00
|
|
|
stackFrame.file = d->engine->toFileInProject(d->extractData(QVariant(file)).value.toString());
|
|
|
|
|
stackFrame.usable = QFileInfo(stackFrame.file).isReadable();
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
QVariantMap receiver = body.value(_("receiver")).toMap();
|
|
|
|
|
if (receiver.contains(_(REF))) {
|
|
|
|
|
receiver = valueFromRef(receiver.value(_(REF)).toInt(), refsVal).toMap();
|
2011-09-06 17:03:16 +02:00
|
|
|
}
|
2011-10-26 10:02:37 +02:00
|
|
|
stackFrame.to = d->extractData(QVariant(receiver)).value.toString();
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
stackFrame.line = body.value(_("line")).toInt() + 1;
|
2011-07-26 16:22:49 +02:00
|
|
|
|
|
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
return stackFrame;
|
|
|
|
|
}
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
void QmlV8DebuggerClient::updateLocals(const QVariant &localsVal, const QVariant &refsVal)
|
|
|
|
|
{
|
|
|
|
|
//Add Locals
|
|
|
|
|
const QVariantList locals = localsVal.toList();
|
|
|
|
|
QList<WatchData> localDataList;
|
|
|
|
|
foreach (const QVariant &localValue, locals) {
|
|
|
|
|
QVariantMap localData = localValue.toMap();
|
|
|
|
|
WatchData data;
|
|
|
|
|
data.exp = localData.value(_(NAME)).toByteArray();
|
|
|
|
|
//Check for v8 specific local data
|
|
|
|
|
if (data.exp.startsWith(".") || data.exp.isEmpty())
|
2011-07-26 16:22:49 +02:00
|
|
|
continue;
|
|
|
|
|
|
2011-10-28 16:43:20 +02:00
|
|
|
data.name = QString(data.exp);
|
2011-10-31 14:17:01 +01:00
|
|
|
data.iname = QByteArray("local.") + data.exp;
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
localData = valueFromRef(localData.value(_(VALUE)).toMap()
|
|
|
|
|
.value(_(REF)).toInt(), refsVal).toMap();
|
|
|
|
|
data.id = localData.value(_(HANDLE)).toInt();
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
QmlV8ObjectData objectData = d->extractData(QVariant(localData));
|
|
|
|
|
data.type = objectData.type;
|
|
|
|
|
data.value = objectData.value.toString();
|
2011-08-23 15:14:48 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
data.setHasChildren(objectData.properties.toList().count());
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
localDataList << data;
|
|
|
|
|
}
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
d->engine->watchHandler()->insertBulkData(localDataList);
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
}
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-10-31 14:17:01 +01:00
|
|
|
void QmlV8DebuggerClient::updateScope(const QVariant &bodyVal, const QVariant &refsVal)
|
|
|
|
|
{
|
|
|
|
|
// { "seq" : <number>,
|
|
|
|
|
// "type" : "response",
|
|
|
|
|
// "request_seq" : <number>,
|
|
|
|
|
// "command" : "scope",
|
|
|
|
|
// "body" : { "index" : <index of this scope in the scope chain. Index 0 is the top scope
|
|
|
|
|
// and the global scope will always have the highest index for a
|
|
|
|
|
// frame>,
|
|
|
|
|
// "frameIndex" : <index of the frame>,
|
|
|
|
|
// "type" : <type of the scope:
|
|
|
|
|
// 0: Global
|
|
|
|
|
// 1: Local
|
|
|
|
|
// 2: With
|
|
|
|
|
// 3: Closure
|
|
|
|
|
// 4: Catch >,
|
|
|
|
|
// "object" : <the scope object defining the content of the scope.
|
|
|
|
|
// For local and closure scopes this is transient objects,
|
|
|
|
|
// which has a negative handle value>
|
|
|
|
|
// }
|
|
|
|
|
// "running" : <is the VM running after sending this response>
|
|
|
|
|
// "success" : true
|
|
|
|
|
// }
|
|
|
|
|
QVariantMap bodyMap = bodyVal.toMap();
|
|
|
|
|
if (bodyMap.contains(_(REF))) {
|
|
|
|
|
bodyMap = valueFromRef(bodyMap.value(_(REF)).toInt(),
|
|
|
|
|
refsVal).toMap();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const QVariantList properties = bodyMap.value(_("properties")).toList();
|
|
|
|
|
|
|
|
|
|
foreach (const QVariant &property, properties) {
|
|
|
|
|
QVariantMap localData = property.toMap();
|
|
|
|
|
//Do Not show global types (0)
|
|
|
|
|
//Showing global properties increases clutter.
|
|
|
|
|
if (!localData.value(_("propertyType")).toInt())
|
|
|
|
|
continue;
|
|
|
|
|
WatchData data;
|
|
|
|
|
data.exp = localData.value(_(NAME)).toByteArray();
|
|
|
|
|
//Check for v8 specific local data
|
|
|
|
|
if (data.exp.startsWith(".") || data.exp.isEmpty())
|
|
|
|
|
continue;
|
|
|
|
|
|
2011-10-28 16:43:20 +02:00
|
|
|
data.name = QString(data.exp);
|
2011-10-31 14:17:01 +01:00
|
|
|
data.iname = QByteArray("local.") + data.exp;
|
|
|
|
|
|
|
|
|
|
localData = valueFromRef(localData.value(_(REF)).toInt(), d->refsVal).toMap();
|
|
|
|
|
data.id = localData.value(_(HANDLE)).toInt();
|
|
|
|
|
|
|
|
|
|
QmlV8ObjectData objectData = d->extractData(QVariant(localData));
|
|
|
|
|
data.type = objectData.type;
|
|
|
|
|
data.value = objectData.value.toString();
|
|
|
|
|
|
|
|
|
|
data.setHasChildren(objectData.properties.toList().count());
|
|
|
|
|
|
|
|
|
|
d->localDataList << data;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!d->currentFrameScopes.isEmpty()) {
|
|
|
|
|
QTC_CHECK(d->state == QmlV8DebuggerClient::WaitingForRequestState);
|
|
|
|
|
d->scope(d->currentFrameScopes.pop(), d->currentFrameIndex);
|
|
|
|
|
} else {
|
|
|
|
|
updateLocalsAndWatchers();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
void QmlV8DebuggerClient::updateEvaluationResult(int sequence, const QVariant &bodyVal,
|
|
|
|
|
const QVariant &refsVal)
|
|
|
|
|
{
|
|
|
|
|
// { "seq" : <number>,
|
|
|
|
|
// "type" : "response",
|
|
|
|
|
// "request_seq" : <number>,
|
|
|
|
|
// "command" : "evaluate",
|
|
|
|
|
// "body" : ...
|
|
|
|
|
// "running" : <is the VM running after sending this response>
|
|
|
|
|
// "success" : true
|
|
|
|
|
// }
|
|
|
|
|
QVariantMap bodyMap = bodyVal.toMap();
|
|
|
|
|
if (bodyMap.contains(_(REF))) {
|
|
|
|
|
bodyMap = valueFromRef(bodyMap.value(_(REF)).toInt(),
|
|
|
|
|
refsVal).toMap();
|
|
|
|
|
}
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
QmlV8ObjectData body = d->extractData(QVariant(bodyMap));
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-10-28 16:43:20 +02:00
|
|
|
if (!d->evaluatingWatches.contains(sequence)) {
|
2011-10-26 10:02:37 +02:00
|
|
|
//Console
|
|
|
|
|
d->engine->showMessage(body.value.toString(), ScriptConsoleOutput);
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
} else {
|
2011-10-28 16:43:20 +02:00
|
|
|
QString exp = d->evaluatingWatches.take(sequence);
|
|
|
|
|
QByteArray iname = d->engine->watchHandler()->watcherName(exp.toLatin1());
|
|
|
|
|
SDEBUG(QString(iname));
|
2011-10-26 10:02:37 +02:00
|
|
|
WatchData data;
|
2011-10-28 16:43:20 +02:00
|
|
|
data.exp = exp.toLatin1();
|
|
|
|
|
data.name = exp;
|
2011-10-26 10:02:37 +02:00
|
|
|
data.iname = iname;
|
|
|
|
|
data.id = bodyMap.value(_(HANDLE)).toInt();
|
|
|
|
|
data.type = body.type;
|
|
|
|
|
data.value = body.value.toString();
|
|
|
|
|
|
2011-10-28 16:43:20 +02:00
|
|
|
//TODO:: Fix expanding watched objects/expressions
|
|
|
|
|
// const QVariantList properties = body.properties.toList();
|
|
|
|
|
// data.setHasChildren(properties.count());
|
|
|
|
|
//Insert the newly evaluated expression to the Watchers Window
|
|
|
|
|
d->engine->watchHandler()->beginCycle(false);
|
2011-10-26 10:02:37 +02:00
|
|
|
d->engine->watchHandler()->insertData(data);
|
2011-10-28 16:43:20 +02:00
|
|
|
d->engine->watchHandler()->endCycle();
|
|
|
|
|
|
|
|
|
|
//Check if there are more expressions to be evaluated
|
|
|
|
|
//Evaluate one at a time.
|
|
|
|
|
if (!d->watchesToEvaluate.isEmpty()) {
|
|
|
|
|
QTC_CHECK(d->state == QmlV8DebuggerClient::WaitingForRequestState);
|
|
|
|
|
StackHandler *stackHandler = d->engine->stackHandler();
|
|
|
|
|
const QString exp = d->watchesToEvaluate.pop();
|
|
|
|
|
if (stackHandler->isContentsValid()) {
|
|
|
|
|
d->evaluate(exp, false, false, stackHandler->currentIndex());
|
|
|
|
|
} else {
|
|
|
|
|
d->evaluate(exp);
|
|
|
|
|
}
|
|
|
|
|
d->evaluatingWatches.insert(d->sequence, exp);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
|
|
|
|
|
// foreach (const QVariant &property, properties) {
|
|
|
|
|
// QVariantMap propertyData = property.toMap();
|
|
|
|
|
// WatchData data;
|
|
|
|
|
// data.exp = propertyData.value(_(NAME)).toByteArray();
|
|
|
|
|
|
|
|
|
|
// //Check for v8 specific local data
|
|
|
|
|
// if (data.exp.startsWith(".") || data.exp.isEmpty())
|
|
|
|
|
// continue;
|
|
|
|
|
|
|
|
|
|
// data.name = data.exp;
|
|
|
|
|
// data.iname = prepend + '.' + data.exp;
|
|
|
|
|
// propertyData = valueFromRef(propertyData.value(_(REF)).toInt(),
|
|
|
|
|
// refsVal).toMap();
|
|
|
|
|
// data.id = propertyData.value(_(HANDLE)).toInt();
|
|
|
|
|
|
|
|
|
|
// QmlV8ObjectData objectData = d->extractData(QVariant(propertyData));
|
|
|
|
|
// data.type = objectData.type;
|
|
|
|
|
// data.value = objectData.value.toString();
|
|
|
|
|
|
|
|
|
|
// data.setHasChildren(objectData.properties.toList().count());
|
|
|
|
|
// d->engine->watchHandler()->insertData(data);
|
|
|
|
|
// }
|
2011-07-26 16:22:49 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
void QmlV8DebuggerClient::updateBreakpoints(const QVariant &bodyVal)
|
2011-07-26 16:22:49 +02:00
|
|
|
{
|
2011-10-26 10:02:37 +02:00
|
|
|
// { "seq" : <number>,
|
|
|
|
|
// "type" : "response",
|
|
|
|
|
// "request_seq" : <number>,
|
|
|
|
|
// "command" : "listbreakpoints",
|
|
|
|
|
// "body" : { "breakpoints": [ { "type" : <string: "scriptId" or "scriptName".>,
|
|
|
|
|
// "script_id" : <int: script id. Only defined if type is scriptId.>,
|
|
|
|
|
// "script_name" : <string: script name. Only defined if type is scriptName.>,
|
|
|
|
|
// "number" : <int: breakpoint number. Starts from 1.>,
|
|
|
|
|
// "line" : <int: line number of this breakpoint. Starts from 0.>,
|
|
|
|
|
// "column" : <int: column number of this breakpoint. Starts from 0.>,
|
|
|
|
|
// "groupId" : <int: group id of this breakpoint.>,
|
|
|
|
|
// "hit_count" : <int: number of times this breakpoint has been hit. Starts from 0.>,
|
|
|
|
|
// "active" : <bool: true if this breakpoint is enabled.>,
|
|
|
|
|
// "ignoreCount" : <int: remaining number of times to ignore breakpoint. Starts from 0.>,
|
|
|
|
|
// "actual_locations" : <actual locations of the breakpoint.>,
|
|
|
|
|
// }
|
|
|
|
|
// ],
|
|
|
|
|
// "breakOnExceptions" : <true if break on all exceptions is enabled>,
|
|
|
|
|
// "breakOnUncaughtExceptions" : <true if break on uncaught exceptions is enabled>
|
|
|
|
|
// }
|
|
|
|
|
// "running" : <is the VM running after sending this response>
|
|
|
|
|
// "success" : true
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
const QVariantMap body = bodyVal.toMap();
|
|
|
|
|
const QVariantList breakpoints = body.value(_("breakpoints")).toList();
|
|
|
|
|
BreakHandler *handler = d->engine->breakHandler();
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
foreach (const QVariant &breakpoint, breakpoints) {
|
|
|
|
|
const QVariantMap breakpointData = breakpoint.toMap();
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
int index = breakpointData.value(_("number")).toInt();
|
|
|
|
|
BreakpointModelId id = d->breakpoints.key(index);
|
|
|
|
|
BreakpointResponse br = handler->response(id);
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
const QVariantList actualLocations = breakpointData.value(_("actual_locations")).toList();
|
|
|
|
|
foreach (const QVariant &location, actualLocations) {
|
|
|
|
|
const QVariantMap locationData = location.toMap();
|
|
|
|
|
br.lineNumber = locationData.value(_("line")).toInt() + 1;;
|
|
|
|
|
br.enabled = breakpointData.value(_("active")).toBool();
|
|
|
|
|
br.hitCount = breakpointData.value(_("hit_count")).toInt();
|
|
|
|
|
br.ignoreCount = breakpointData.value(_("ignoreCount")).toInt();
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
handler->setResponse(id, br);
|
|
|
|
|
}
|
2011-07-26 16:22:49 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
QVariant QmlV8DebuggerClient::valueFromRef(int handle, const QVariant &refsVal)
|
2011-07-26 16:22:49 +02:00
|
|
|
{
|
2011-10-26 10:02:37 +02:00
|
|
|
QVariant variant;
|
|
|
|
|
const QVariantList refs = refsVal.toList();
|
|
|
|
|
foreach (const QVariant &ref, refs) {
|
|
|
|
|
const QVariantMap refData = ref.toMap();
|
|
|
|
|
if (refData.value(_(HANDLE)).toInt() == handle) {
|
|
|
|
|
variant = refData;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2011-07-26 16:22:49 +02:00
|
|
|
}
|
2011-10-26 10:02:37 +02:00
|
|
|
return variant;
|
2011-08-23 15:05:30 +02:00
|
|
|
}
|
|
|
|
|
|
2011-10-28 16:43:20 +02:00
|
|
|
void QmlV8DebuggerClient::expandLocalsAndWatchers(const QVariant &bodyVal, const QVariant &refsVal)
|
2011-08-23 15:05:30 +02:00
|
|
|
{
|
2011-10-26 10:02:37 +02:00
|
|
|
// { "seq" : <number>,
|
|
|
|
|
// "type" : "response",
|
|
|
|
|
// "request_seq" : <number>,
|
|
|
|
|
// "command" : "lookup",
|
|
|
|
|
// "body" : <array of serialized objects indexed using their handle>
|
|
|
|
|
// "running" : <is the VM running after sending this response>
|
|
|
|
|
// "success" : true
|
|
|
|
|
// }
|
|
|
|
|
const QVariantMap body = bodyVal.toMap();
|
|
|
|
|
|
|
|
|
|
int handle = body.keys().value(0).toInt();
|
2011-10-28 16:43:20 +02:00
|
|
|
QByteArray prepend = d->localsAndWatchers.take(handle);
|
2011-10-26 10:02:37 +02:00
|
|
|
const WatchData *parent = d->engine->watchHandler()->findItem(prepend);
|
|
|
|
|
QmlV8ObjectData bodyObjectData = d->extractData(
|
|
|
|
|
body.value(body.keys().value(0)));
|
|
|
|
|
|
|
|
|
|
const QVariantList properties = bodyObjectData.properties.toList();
|
|
|
|
|
|
|
|
|
|
QList<WatchData> children;
|
|
|
|
|
foreach (const QVariant &property, properties) {
|
|
|
|
|
QVariantMap propertyData = property.toMap();
|
|
|
|
|
WatchData data;
|
|
|
|
|
data.name = propertyData.value(_(NAME)).toString();
|
|
|
|
|
|
|
|
|
|
//Check for v8 specific local data
|
|
|
|
|
if (data.name.startsWith(".") || data.name.isEmpty())
|
2011-08-23 15:05:30 +02:00
|
|
|
continue;
|
2011-10-26 10:02:37 +02:00
|
|
|
if (parent->type == "object") {
|
|
|
|
|
if (parent->value == _("Array"))
|
2011-10-31 14:17:01 +01:00
|
|
|
data.exp = parent->exp + QByteArray("[") + data.name.toLatin1() + QByteArray("]");
|
2011-10-26 10:02:37 +02:00
|
|
|
else if (parent->value == _("Object"))
|
2011-10-31 14:17:01 +01:00
|
|
|
data.exp = parent->exp + QByteArray(".") + data.name.toLatin1();
|
2011-10-26 10:02:37 +02:00
|
|
|
}
|
2011-10-28 16:43:20 +02:00
|
|
|
if (prepend.startsWith("local."))
|
|
|
|
|
data.iname = prepend + '.' + data.name.toLatin1();
|
|
|
|
|
if (prepend.startsWith("watch."))
|
|
|
|
|
data.iname = prepend;
|
2011-10-26 10:02:37 +02:00
|
|
|
propertyData = valueFromRef(propertyData.value(_(REF)).toInt(),
|
|
|
|
|
refsVal).toMap();
|
|
|
|
|
data.id = propertyData.value(_(HANDLE)).toInt();
|
2011-08-23 15:05:30 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
QmlV8ObjectData objectData = d->extractData(QVariant(propertyData));
|
|
|
|
|
data.type = objectData.type;
|
|
|
|
|
data.value = objectData.value.toString();
|
2011-08-23 15:05:30 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
data.setHasChildren(objectData.properties.toList().count());
|
|
|
|
|
children << data;
|
2011-08-23 15:05:30 +02:00
|
|
|
}
|
2011-10-26 10:02:37 +02:00
|
|
|
d->engine->watchHandler()->insertBulkData(children);
|
2011-07-26 16:22:49 +02:00
|
|
|
}
|
|
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
void QmlV8DebuggerClient::highlightExceptionCode(int lineNumber,
|
|
|
|
|
const QString &filePath,
|
|
|
|
|
const QString &errorMessage)
|
2011-07-26 16:22:49 +02:00
|
|
|
{
|
2011-10-26 10:02:37 +02:00
|
|
|
EditorManager *editorManager = EditorManager::instance();
|
|
|
|
|
QList<IEditor *> openedEditors = editorManager->openedEditors();
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
// set up the format for the errors
|
|
|
|
|
QTextCharFormat errorFormat;
|
|
|
|
|
errorFormat.setUnderlineStyle(QTextCharFormat::WaveUnderline);
|
|
|
|
|
errorFormat.setUnderlineColor(Qt::red);
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
foreach (IEditor *editor, openedEditors) {
|
|
|
|
|
if (editor->file()->fileName() == filePath) {
|
|
|
|
|
TextEditor::BaseTextEditorWidget *ed = qobject_cast<TextEditor::BaseTextEditorWidget *>(editor->widget());
|
|
|
|
|
if (!ed)
|
|
|
|
|
continue;
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
QList<QTextEdit::ExtraSelection> selections;
|
|
|
|
|
QTextEdit::ExtraSelection sel;
|
|
|
|
|
sel.format = errorFormat;
|
2011-10-28 16:44:55 +02:00
|
|
|
QTextCursor c(ed->document()->findBlockByNumber(lineNumber - 1));
|
2011-10-26 10:02:37 +02:00
|
|
|
const QString text = c.block().text();
|
|
|
|
|
for (int i = 0; i < text.size(); ++i) {
|
|
|
|
|
if (! text.at(i).isSpace()) {
|
|
|
|
|
c.setPosition(c.position() + i);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
c.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor);
|
|
|
|
|
sel.cursor = c;
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
sel.format.setToolTip(errorMessage);
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
selections.append(sel);
|
|
|
|
|
ed->setExtraSelections(TextEditor::BaseTextEditorWidget::DebuggerExceptionSelection, selections);
|
2011-10-26 10:43:43 +02:00
|
|
|
|
|
|
|
|
QString message = QString(_("%1: %2: %3")).arg(filePath).arg(lineNumber)
|
|
|
|
|
.arg(errorMessage);
|
|
|
|
|
d->engine->showMessage(message, ScriptConsoleOutput);
|
2011-10-26 10:02:37 +02:00
|
|
|
}
|
2011-07-26 16:22:49 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
void QmlV8DebuggerClient::clearExceptionSelection()
|
2011-07-26 16:22:49 +02:00
|
|
|
{
|
2011-10-26 10:02:37 +02:00
|
|
|
EditorManager *editorManager = EditorManager::instance();
|
|
|
|
|
QList<IEditor *> openedEditors = editorManager->openedEditors();
|
|
|
|
|
QList<QTextEdit::ExtraSelection> selections;
|
|
|
|
|
|
|
|
|
|
foreach (IEditor *editor, openedEditors) {
|
|
|
|
|
TextEditor::BaseTextEditorWidget *ed = qobject_cast<TextEditor::BaseTextEditorWidget *>(editor->widget());
|
|
|
|
|
if (!ed)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
ed->setExtraSelections(TextEditor::BaseTextEditorWidget::DebuggerExceptionSelection, selections);
|
2011-07-26 16:22:49 +02:00
|
|
|
}
|
2011-10-26 10:02:37 +02:00
|
|
|
|
2011-07-26 16:22:49 +02:00
|
|
|
}
|
|
|
|
|
|
2011-10-26 10:32:46 +02:00
|
|
|
void QmlV8DebuggerClient::resetState()
|
2011-07-26 16:22:49 +02:00
|
|
|
{
|
2011-10-26 10:02:37 +02:00
|
|
|
clearExceptionSelection();
|
|
|
|
|
d->currentFrameIndex = 0;
|
|
|
|
|
d->updateCurrentStackFrameIndex = true;
|
2011-10-28 18:06:24 +02:00
|
|
|
d->state = QmlV8DebuggerClient::RunningState;
|
2011-10-26 10:32:46 +02:00
|
|
|
SDEBUG(QString(_("State: %1")).arg(d->state));
|
2011-07-26 16:22:49 +02:00
|
|
|
}
|
|
|
|
|
|
2011-10-31 14:17:01 +01:00
|
|
|
void QmlV8DebuggerClient::updateLocalsAndWatchers()
|
|
|
|
|
{
|
|
|
|
|
d->engine->watchHandler()->beginCycle();
|
|
|
|
|
d->engine->watchHandler()->insertBulkData(d->localDataList);
|
|
|
|
|
d->engine->watchHandler()->endCycle();
|
2011-10-28 16:43:20 +02:00
|
|
|
|
|
|
|
|
//Push all Watched expressions to a stack.
|
|
|
|
|
//Evaluate the expressions one at a time
|
|
|
|
|
//and append the evaluated result to the watchers
|
|
|
|
|
//window (see updateEvaluationResult())
|
|
|
|
|
foreach (const QString &expr, d->watchedExpressions)
|
|
|
|
|
d->watchesToEvaluate.push(expr);
|
|
|
|
|
|
|
|
|
|
if (!d->watchesToEvaluate.isEmpty()) {
|
|
|
|
|
StackHandler *stackHandler = d->engine->stackHandler();
|
|
|
|
|
const QString exp = d->watchesToEvaluate.pop();
|
|
|
|
|
if (stackHandler->isContentsValid()) {
|
|
|
|
|
d->evaluate(exp, false, false, stackHandler->currentIndex());
|
|
|
|
|
} else {
|
|
|
|
|
d->evaluate(exp);
|
|
|
|
|
}
|
|
|
|
|
d->evaluatingWatches.insert(d->sequence, exp);
|
|
|
|
|
}
|
2011-10-31 14:17:01 +01:00
|
|
|
}
|
|
|
|
|
|
2011-07-26 16:22:49 +02:00
|
|
|
} // Internal
|
|
|
|
|
} // Debugger
|