2012-10-02 09:12:39 +02:00
|
|
|
/****************************************************************************
|
2011-07-26 16:22:49 +02:00
|
|
|
**
|
2014-01-07 13:27:11 +01:00
|
|
|
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
|
2012-10-02 09:12:39 +02:00
|
|
|
** Contact: http://www.qt-project.org/legal
|
2011-07-26 16:22:49 +02:00
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
** This file is part of Qt Creator.
|
2011-07-26 16:22:49 +02:00
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
** Commercial License Usage
|
|
|
|
|
** Licensees holding valid commercial Qt licenses may use this file in
|
|
|
|
|
** accordance with the commercial license agreement provided with the
|
|
|
|
|
** Software or, alternatively, in accordance with the terms contained in
|
|
|
|
|
** a written agreement between you and Digia. For licensing terms and
|
2014-10-01 13:21:18 +02:00
|
|
|
** conditions see http://www.qt.io/licensing. For further information
|
|
|
|
|
** use the contact form at http://www.qt.io/contact-us.
|
2011-07-26 16:22:49 +02:00
|
|
|
**
|
|
|
|
|
** GNU Lesser General Public License Usage
|
2012-10-02 09:12:39 +02:00
|
|
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
2014-10-01 13:21:18 +02:00
|
|
|
** General Public License version 2.1 or version 3 as published by the Free
|
|
|
|
|
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
|
|
|
|
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
|
|
|
|
** following information to ensure the GNU Lesser General Public License
|
|
|
|
|
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
|
|
|
|
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
2012-10-02 09:12:39 +02:00
|
|
|
**
|
|
|
|
|
** In addition, as a special exception, Digia gives you certain additional
|
|
|
|
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
2011-07-26 16:22:49 +02:00
|
|
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
****************************************************************************/
|
2011-07-26 16:22:49 +02:00
|
|
|
|
|
|
|
|
#include "qmlv8debuggerclient.h"
|
2011-10-26 10:02:37 +02:00
|
|
|
#include "qmlv8debuggerclientconstants.h"
|
2011-07-26 16:22:49 +02:00
|
|
|
#include "qmlengine.h"
|
2013-08-29 16:36:42 +02:00
|
|
|
|
|
|
|
|
#include <debugger/debuggerstringutils.h>
|
|
|
|
|
#include <debugger/watchhandler.h>
|
|
|
|
|
#include <debugger/breakhandler.h>
|
|
|
|
|
#include <debugger/stackhandler.h>
|
|
|
|
|
#include <debugger/debuggercore.h>
|
|
|
|
|
#include <debugger/debuggeractions.h>
|
2011-07-26 16:22:49 +02:00
|
|
|
|
|
|
|
|
#include <utils/qtcassert.h>
|
2014-09-26 09:14:03 +02:00
|
|
|
#include <texteditor/texteditor.h>
|
2011-09-06 17:03:16 +02:00
|
|
|
|
2012-10-08 13:17:10 +02:00
|
|
|
#include <qmljs/consolemanagerinterface.h>
|
2012-10-04 14:54:59 +02:00
|
|
|
|
2012-02-15 10:42:41 +01:00
|
|
|
#include <QTextBlock>
|
|
|
|
|
#include <QFileInfo>
|
|
|
|
|
#include <QScriptEngine>
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-11-04 11:21:11 +01:00
|
|
|
#define DEBUG_QML 0
|
2011-10-26 10:02:37 +02:00
|
|
|
#if DEBUG_QML
|
2011-10-31 17:14:21 +01:00
|
|
|
# define SDEBUG(s) qDebug() << s << '\n'
|
2011-10-26 10:02:37 +02:00
|
|
|
#else
|
|
|
|
|
# define SDEBUG(s)
|
|
|
|
|
#endif
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-09-06 17:03:16 +02:00
|
|
|
using namespace Core;
|
2013-11-01 09:58:44 +01:00
|
|
|
using QmlDebug::QmlDebugStream;
|
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 {
|
2012-02-16 15:58:40 +01:00
|
|
|
int handle;
|
|
|
|
|
QByteArray name;
|
2011-10-26 10:02:37 +02:00
|
|
|
QByteArray type;
|
|
|
|
|
QVariant value;
|
2012-02-16 15:58:40 +01:00
|
|
|
QVariantList 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),
|
2012-04-06 11:03:33 +02:00
|
|
|
engine(0),
|
|
|
|
|
previousStepAction(QmlV8DebuggerClient::Continue)
|
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();
|
2013-11-07 15:23:26 +01:00
|
|
|
void continueDebugging(QmlV8DebuggerClient::StepAction stepAction);
|
2011-10-26 10:02:37 +02:00
|
|
|
|
|
|
|
|
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 scripts(int types = 4, const QList<int> ids = QList<int>(),
|
|
|
|
|
bool includeSource = false, const QVariant filter = QVariant());
|
|
|
|
|
|
2012-02-28 17:30:15 +01:00
|
|
|
void setBreakpoint(const QString type, const QString target,
|
|
|
|
|
bool enabled = true,int line = 0, int column = 0,
|
2011-10-26 10:02:37 +02:00
|
|
|
const QString condition = QString(), int ignoreCount = -1);
|
|
|
|
|
void clearBreakpoint(int breakpoint);
|
|
|
|
|
void setExceptionBreak(QmlV8DebuggerClient::Exceptions type, bool enabled = false);
|
|
|
|
|
|
|
|
|
|
void version();
|
|
|
|
|
//void profile(ProfileCommand command); //NOT SUPPORTED
|
2011-11-03 19:28:35 +01:00
|
|
|
void clearCache();
|
2011-10-26 10:02:37 +02:00
|
|
|
|
2011-12-07 10:23:26 +01:00
|
|
|
void logSendMessage(const QString &msg) const;
|
|
|
|
|
void logReceiveMessage(const QString &msg) const;
|
|
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
private:
|
2011-12-07 09:38:40 +01:00
|
|
|
QByteArray packMessage(const QByteArray &type, const QByteArray &message = QByteArray());
|
2011-10-26 10:02:37 +02:00
|
|
|
QScriptValue initObject();
|
2011-12-07 10:23:26 +01:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
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-12-22 18:43:09 +01:00
|
|
|
QList<int> breakpointsTemp;
|
2011-10-26 10:02:37 +02:00
|
|
|
|
|
|
|
|
QScriptValue parser;
|
|
|
|
|
QScriptValue stringifier;
|
2011-11-30 15:23:02 +01:00
|
|
|
QStringList scriptSourceRequests;
|
2011-10-26 10:02:37 +02:00
|
|
|
|
2011-12-07 09:38:40 +01:00
|
|
|
QHash<int, QString> evaluatingExpression;
|
|
|
|
|
QHash<int, QByteArray> localsAndWatchers;
|
2012-03-21 09:46:33 +01:00
|
|
|
QList<int> updateLocalsAndWatchers;
|
2012-03-21 11:51:36 +01:00
|
|
|
QList<int> debuggerCommands;
|
2011-11-03 19:28:35 +01:00
|
|
|
|
|
|
|
|
//Cache
|
2012-01-10 17:30:02 +01:00
|
|
|
QList<int> currentFrameScopes;
|
2012-04-06 11:03:33 +02:00
|
|
|
QHash<int, int> stackIndexLookup;
|
2011-12-07 09:38:40 +01:00
|
|
|
|
2012-04-06 11:03:33 +02:00
|
|
|
QmlV8DebuggerClient::StepAction previousStepAction;
|
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-12-07 09:38:40 +01:00
|
|
|
logSendMessage(QString(_("%1 %2")).arg(_(V8DEBUG), _(CONNECT)));
|
2012-02-27 12:14:00 +01:00
|
|
|
q->sendMessage(packMessage(CONNECT));
|
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);
|
2011-12-07 10:23:26 +01:00
|
|
|
logSendMessage(QString(_("%1 %2")).arg(_(V8DEBUG), jsonMessage.toString()));
|
2011-12-07 09:38:40 +01:00
|
|
|
q->sendMessage(packMessage(DISCONNECT, 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-12-07 09:38:40 +01:00
|
|
|
logSendMessage(QString(_("%1 %2")).arg(_(V8DEBUG), _(INTERRUPT)));
|
2012-02-27 12:14:00 +01:00
|
|
|
q->sendMessage(packMessage(INTERRUPT));
|
2011-07-26 16:22:49 +02:00
|
|
|
}
|
|
|
|
|
|
2013-11-07 15:23:26 +01:00
|
|
|
void QmlV8DebuggerClientPrivate::continueDebugging(QmlV8DebuggerClient::StepAction action)
|
2011-07-26 16:22:49 +02:00
|
|
|
{
|
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;
|
|
|
|
|
}
|
|
|
|
|
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);
|
2011-12-07 09:38:40 +01:00
|
|
|
logSendMessage(QString(_("%1 %2 %3")).arg(_(V8DEBUG), _(V8REQUEST), jsonMessage.toString()));
|
|
|
|
|
q->sendMessage(packMessage(V8REQUEST, jsonMessage.toString().toUtf8()));
|
2012-04-06 11:03:33 +02:00
|
|
|
previousStepAction = action;
|
2011-10-26 10:02:37 +02:00
|
|
|
}
|
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) {
|
2013-08-17 00:59:42 +02:00
|
|
|
WatchHandler *watchHandler = engine->watchHandler();
|
|
|
|
|
QAbstractItemModel *watchModel = watchHandler->model();
|
|
|
|
|
int rowCount = watchModel->rowCount();
|
2011-10-26 10:02:37 +02:00
|
|
|
|
|
|
|
|
QScriptValue ctxtList = parser.call(QScriptValue(), QScriptValueList() << _(ARRAY ));
|
|
|
|
|
while (rowCount) {
|
2013-08-17 00:59:42 +02:00
|
|
|
QModelIndex index = watchModel->index(--rowCount, 0);
|
|
|
|
|
const WatchData *data = watchHandler->watchData(index);
|
2011-10-26 10:02:37 +02:00
|
|
|
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);
|
2011-12-07 09:38:40 +01:00
|
|
|
logSendMessage(QString(_("%1 %2 %3")).arg(_(V8DEBUG), _(V8REQUEST), jsonMessage.toString()));
|
|
|
|
|
q->sendMessage(packMessage(V8REQUEST, 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);
|
2011-12-07 09:38:40 +01:00
|
|
|
logSendMessage(QString(_("%1 %2 %3")).arg(_(V8DEBUG), _(V8REQUEST), jsonMessage.toString()));
|
|
|
|
|
q->sendMessage(packMessage(V8REQUEST, 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);
|
2011-12-07 09:38:40 +01:00
|
|
|
logSendMessage(QString(_("%1 %2 %3")).arg(_(V8DEBUG), _(V8REQUEST), jsonMessage.toString()));
|
|
|
|
|
q->sendMessage(packMessage(V8REQUEST, jsonMessage.toString().toUtf8()));
|
2011-10-26 10:02:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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);
|
2011-12-07 09:38:40 +01:00
|
|
|
logSendMessage(QString(_("%1 %2 %3")).arg(_(V8DEBUG), _(V8REQUEST), jsonMessage.toString()));
|
|
|
|
|
q->sendMessage(packMessage(V8REQUEST, 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);
|
2011-12-07 09:38:40 +01:00
|
|
|
logSendMessage(QString(_("%1 %2 %3")).arg(_(V8DEBUG), _(V8REQUEST), jsonMessage.toString()));
|
|
|
|
|
q->sendMessage(packMessage(V8REQUEST, jsonMessage.toString().toUtf8()));
|
2011-10-26 10:02:37 +02:00
|
|
|
}
|
2011-09-06 17:03:16 +02:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
void QmlV8DebuggerClientPrivate::scripts(int types, const QList<int> ids, bool includeSource,
|
2011-11-30 15:23:02 +01:00
|
|
|
const QVariant filter)
|
2011-10-26 10:02:37 +02:00
|
|
|
{
|
|
|
|
|
// { "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));
|
|
|
|
|
|
2011-11-30 15:23:02 +01:00
|
|
|
QScriptValue filterValue;
|
|
|
|
|
if (filter.type() == QVariant::String)
|
|
|
|
|
filterValue = QScriptValue(filter.toString());
|
|
|
|
|
else if (filter.type() == QVariant::Int)
|
|
|
|
|
filterValue = QScriptValue(filter.toInt());
|
|
|
|
|
else
|
|
|
|
|
QTC_CHECK(!filter.isValid());
|
|
|
|
|
|
|
|
|
|
args.setProperty(_(FILTER), filterValue);
|
|
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
jsonVal.setProperty(_(ARGUMENTS), args);
|
|
|
|
|
|
|
|
|
|
const QScriptValue jsonMessage = stringifier.call(QScriptValue(), QScriptValueList() << jsonVal);
|
2011-12-07 09:38:40 +01:00
|
|
|
logSendMessage(QString(_("%1 %2 %3")).arg(_(V8DEBUG), _(V8REQUEST), jsonMessage.toString()));
|
|
|
|
|
q->sendMessage(packMessage(V8REQUEST, 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,
|
2012-02-28 17:30:15 +01:00
|
|
|
bool enabled, int line, int column,
|
2011-10-26 10:02:37 +02:00
|
|
|
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>
|
|
|
|
|
// }
|
|
|
|
|
// }
|
2012-02-27 12:14:00 +01:00
|
|
|
if (type == _(EVENT)) {
|
2011-12-07 09:38:40 +01:00
|
|
|
QByteArray params;
|
2013-11-01 09:58:44 +01:00
|
|
|
QmlDebugStream rs(¶ms, QIODevice::WriteOnly);
|
2011-12-07 09:38:40 +01:00
|
|
|
rs << target.toUtf8() << enabled;
|
2012-04-16 12:00:23 +02:00
|
|
|
logSendMessage(QString(_("%1 %2 %3 %4")).arg(_(V8DEBUG), _(BREAKONSIGNAL), target, enabled?_("enabled"):_("disabled")));
|
|
|
|
|
q->sendMessage(packMessage(BREAKONSIGNAL, params));
|
2011-10-26 10:02:37 +02:00
|
|
|
|
2011-12-07 09:38:40 +01:00
|
|
|
} else {
|
|
|
|
|
QScriptValue jsonVal = initObject();
|
|
|
|
|
jsonVal.setProperty(_(COMMAND), QScriptValue(_(SETBREAKPOINT)));
|
2011-10-26 10:02:37 +02:00
|
|
|
|
2011-12-07 09:38:40 +01:00
|
|
|
QScriptValue args = parser.call(QScriptValue(), QScriptValueList() << QScriptValue(_(OBJECT)));
|
2011-10-26 10:02:37 +02:00
|
|
|
|
2011-12-07 09:38:40 +01:00
|
|
|
args.setProperty(_(TYPE), QScriptValue(type));
|
2012-02-28 17:30:15 +01:00
|
|
|
if (type == _(SCRIPTREGEXP))
|
|
|
|
|
args.setProperty(_(TARGET),
|
|
|
|
|
QScriptValue(QFileInfo(target).fileName()));
|
|
|
|
|
else
|
|
|
|
|
args.setProperty(_(TARGET), QScriptValue(target));
|
2011-10-26 10:02:37 +02:00
|
|
|
|
2012-02-28 17:30:15 +01:00
|
|
|
if (line)
|
|
|
|
|
args.setProperty(_(LINE), QScriptValue(line - 1));
|
2011-10-26 10:02:37 +02:00
|
|
|
|
2012-02-28 17:30:15 +01:00
|
|
|
if (column)
|
|
|
|
|
args.setProperty(_(COLUMN), QScriptValue(column - 1));
|
2011-10-26 10:02:37 +02:00
|
|
|
|
2011-12-07 09:38:40 +01:00
|
|
|
args.setProperty(_(ENABLED), QScriptValue(enabled));
|
2011-10-26 10:02:37 +02:00
|
|
|
|
2011-12-07 09:38:40 +01:00
|
|
|
if (!condition.isEmpty())
|
|
|
|
|
args.setProperty(_(CONDITION), QScriptValue(condition));
|
2011-10-26 10:02:37 +02:00
|
|
|
|
2011-12-07 09:38:40 +01:00
|
|
|
if (ignoreCount != -1)
|
|
|
|
|
args.setProperty(_(IGNORECOUNT), QScriptValue(ignoreCount));
|
2011-10-26 10:02:37 +02:00
|
|
|
|
2011-12-07 09:38:40 +01:00
|
|
|
jsonVal.setProperty(_(ARGUMENTS), args);
|
|
|
|
|
|
|
|
|
|
const QScriptValue jsonMessage = stringifier.call(QScriptValue(), QScriptValueList() << jsonVal);
|
|
|
|
|
logSendMessage(QString(_("%1 %2 %3")).arg(_(V8DEBUG), _(V8REQUEST), jsonMessage.toString()));
|
|
|
|
|
q->sendMessage(packMessage(V8REQUEST, jsonMessage.toString().toUtf8()));
|
|
|
|
|
}
|
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);
|
2011-12-07 09:38:40 +01:00
|
|
|
logSendMessage(QString(_("%1 %2 %3")).arg(_(V8DEBUG), _(V8REQUEST), jsonMessage.toString()));
|
|
|
|
|
q->sendMessage(packMessage(V8REQUEST, jsonMessage.toString().toUtf8()));
|
2011-10-26 10:02:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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);
|
2011-12-07 09:38:40 +01:00
|
|
|
logSendMessage(QString(_("%1 %2 %3")).arg(_(V8DEBUG), _(V8REQUEST), jsonMessage.toString()));
|
|
|
|
|
q->sendMessage(packMessage(V8REQUEST, 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);
|
2011-12-07 09:38:40 +01:00
|
|
|
logSendMessage(QString(_("%1 %2 %3")).arg(_(V8DEBUG), _(V8REQUEST), jsonMessage.toString()));
|
|
|
|
|
q->sendMessage(packMessage(V8REQUEST, 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);
|
2011-12-07 09:38:40 +01:00
|
|
|
// logSendMessage(QString(_("%1 %2 %3")).arg(_(V8DEBUG), _(V8REQUEST), jsonMessage.toString()));
|
|
|
|
|
// q->sendMessage(packMessage(V8REQUEST, jsonMessage.toString().toUtf8()));
|
2011-10-26 10:02:37 +02:00
|
|
|
//}
|
|
|
|
|
|
2012-10-04 14:54:59 +02:00
|
|
|
QVariant valueFromRef(int handle, const QVariant &refsVal, bool *success)
|
|
|
|
|
{
|
|
|
|
|
*success = false;
|
|
|
|
|
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;
|
|
|
|
|
*success = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return variant;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QmlV8ObjectData extractData(const QVariant &data, const QVariant &refsVal)
|
2011-10-26 10:02:37 +02:00
|
|
|
{
|
|
|
|
|
// { "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();
|
|
|
|
|
|
2012-02-16 15:58:40 +01:00
|
|
|
objectData.name = dataMap.value(_(NAME)).toByteArray();
|
|
|
|
|
|
|
|
|
|
if (dataMap.contains(_(REF))) {
|
|
|
|
|
objectData.handle = dataMap.value(_(REF)).toInt();
|
|
|
|
|
bool success;
|
|
|
|
|
QVariant dataFromRef = valueFromRef(objectData.handle, refsVal, &success);
|
|
|
|
|
if (success) {
|
|
|
|
|
QmlV8ObjectData data = extractData(dataFromRef, refsVal);
|
|
|
|
|
objectData.type = data.type;
|
|
|
|
|
objectData.value = data.value;
|
|
|
|
|
objectData.properties = data.properties;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2012-03-21 09:46:33 +01:00
|
|
|
objectData.handle = dataMap.value(_(HANDLE)).toInt();
|
2012-02-16 15:58:40 +01:00
|
|
|
QString type = dataMap.value(_(TYPE)).toString();
|
|
|
|
|
|
|
|
|
|
if (type == _("undefined")) {
|
|
|
|
|
objectData.type = QByteArray("undefined");
|
|
|
|
|
objectData.value = QVariant(_("undefined"));
|
2011-10-26 10:02:37 +02:00
|
|
|
|
2012-02-16 15:58:40 +01:00
|
|
|
} else if (type == _("null")) {
|
|
|
|
|
objectData.type = QByteArray("null");
|
|
|
|
|
objectData.value= QVariant(_("null"));
|
2011-10-26 10:02:37 +02:00
|
|
|
|
2012-02-16 15:58:40 +01:00
|
|
|
} else if (type == _("boolean")) {
|
|
|
|
|
objectData.type = QByteArray("boolean");
|
|
|
|
|
objectData.value = dataMap.value(_(VALUE));
|
2011-10-26 10:02:37 +02:00
|
|
|
|
2012-02-16 15:58:40 +01:00
|
|
|
} else if (type == _("number")) {
|
|
|
|
|
objectData.type = QByteArray("number");
|
|
|
|
|
objectData.value = dataMap.value(_(VALUE));
|
2011-10-26 10:02:37 +02:00
|
|
|
|
2012-02-16 15:58:40 +01:00
|
|
|
} else if (type == _("string")) {
|
|
|
|
|
objectData.type = QByteArray("string");
|
|
|
|
|
objectData.value = dataMap.value(_(VALUE));
|
2011-10-26 10:02:37 +02:00
|
|
|
|
2012-02-16 15:58:40 +01:00
|
|
|
} else if (type == _("object")) {
|
|
|
|
|
objectData.type = QByteArray("object");
|
|
|
|
|
objectData.value = dataMap.value(_("className"));
|
|
|
|
|
objectData.properties = dataMap.value(_("properties")).toList();
|
2011-10-26 10:02:37 +02:00
|
|
|
|
2012-02-16 15:58:40 +01:00
|
|
|
} else if (type == _("function")) {
|
|
|
|
|
objectData.type = QByteArray("function");
|
|
|
|
|
objectData.value = dataMap.value(_(NAME));
|
|
|
|
|
objectData.properties = dataMap.value(_("properties")).toList();
|
2011-10-26 10:02:37 +02:00
|
|
|
|
2012-02-16 15:58:40 +01:00
|
|
|
} else if (type == _("script")) {
|
|
|
|
|
objectData.type = QByteArray("script");
|
|
|
|
|
objectData.value = dataMap.value(_(NAME));
|
|
|
|
|
}
|
2011-10-26 10:02:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return objectData;
|
|
|
|
|
}
|
|
|
|
|
|
2011-11-03 19:28:35 +01:00
|
|
|
void QmlV8DebuggerClientPrivate::clearCache()
|
|
|
|
|
{
|
2012-01-10 17:30:02 +01:00
|
|
|
currentFrameScopes.clear();
|
2012-03-21 11:51:36 +01:00
|
|
|
updateLocalsAndWatchers.clear();
|
2011-11-03 19:28:35 +01:00
|
|
|
}
|
|
|
|
|
|
2011-12-07 09:38:40 +01:00
|
|
|
QByteArray QmlV8DebuggerClientPrivate::packMessage(const QByteArray &type, const QByteArray &message)
|
2011-08-22 13:08:58 +02:00
|
|
|
{
|
2011-11-03 19:28:35 +01:00
|
|
|
SDEBUG(message);
|
2011-12-07 09:38:40 +01:00
|
|
|
QByteArray request;
|
2013-11-01 09:58:44 +01:00
|
|
|
QmlDebugStream rs(&request, QIODevice::WriteOnly);
|
2011-10-26 10:02:37 +02:00
|
|
|
QByteArray cmd = V8DEBUG;
|
2012-02-27 12:14:00 +01:00
|
|
|
rs << cmd << type << message;
|
2011-12-07 09:38:40 +01:00
|
|
|
return request;
|
2011-10-26 10:02:37 +02:00
|
|
|
}
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-07 10:23:26 +01:00
|
|
|
void QmlV8DebuggerClientPrivate::logSendMessage(const QString &msg) const
|
|
|
|
|
{
|
|
|
|
|
if (engine)
|
2011-12-21 13:29:31 +01:00
|
|
|
engine->logMessage(QLatin1String("V8DebuggerClient"), QmlEngine::LogSend, msg);
|
2011-12-07 10:23:26 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void QmlV8DebuggerClientPrivate::logReceiveMessage(const QString &msg) const
|
|
|
|
|
{
|
|
|
|
|
if (engine)
|
2011-12-21 13:29:31 +01:00
|
|
|
engine->logMessage(QLatin1String("V8DebuggerClient"), QmlEngine::LogReceive, msg);
|
2011-12-07 10:23:26 +01:00
|
|
|
}
|
|
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
|
//
|
|
|
|
|
// QmlV8DebuggerClient
|
|
|
|
|
//
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
2012-04-18 12:06:10 +02:00
|
|
|
QmlV8DebuggerClient::QmlV8DebuggerClient(QmlDebug::QmlDebugConnection *client)
|
|
|
|
|
: BaseQmlDebuggerClient(client, QLatin1String("V8Debugger")),
|
2011-10-26 10:02:37 +02:00
|
|
|
d(new QmlV8DebuggerClientPrivate(this))
|
|
|
|
|
{
|
|
|
|
|
}
|
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()
|
|
|
|
|
{
|
2011-12-07 09:38:40 +01:00
|
|
|
flushSendBuffer();
|
2011-10-26 10:02:37 +02:00
|
|
|
d->connect();
|
2011-12-07 11:13:46 +01:00
|
|
|
//Query for the V8 version. This is
|
|
|
|
|
//only for logging to the debuggerlog
|
|
|
|
|
d->version();
|
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:02:37 +02:00
|
|
|
d->disconnect();
|
|
|
|
|
}
|
|
|
|
|
|
2013-07-16 14:17:32 +02:00
|
|
|
void QmlV8DebuggerClient::resetSession()
|
|
|
|
|
{
|
|
|
|
|
clearExceptionSelection();
|
|
|
|
|
}
|
|
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
void QmlV8DebuggerClient::executeStep()
|
|
|
|
|
{
|
2011-12-07 09:38:40 +01:00
|
|
|
clearExceptionSelection();
|
2011-10-26 10:02:37 +02:00
|
|
|
d->continueDebugging(In);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void QmlV8DebuggerClient::executeStepOut()
|
|
|
|
|
{
|
2011-12-07 09:38:40 +01:00
|
|
|
clearExceptionSelection();
|
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-12-07 09:38:40 +01:00
|
|
|
clearExceptionSelection();
|
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-12-07 09:38:40 +01:00
|
|
|
clearExceptionSelection();
|
2011-10-26 10:02:37 +02:00
|
|
|
d->continueDebugging(In);
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-22 18:43:09 +01:00
|
|
|
void QmlV8DebuggerClient::executeRunToLine(const ContextData &data)
|
|
|
|
|
{
|
2012-02-28 17:30:15 +01:00
|
|
|
d->setBreakpoint(QString(_(SCRIPTREGEXP)), data.fileName,
|
2012-03-01 09:00:07 +01:00
|
|
|
true, data.lineNumber);
|
2011-12-22 18:43:09 +01:00
|
|
|
clearExceptionSelection();
|
|
|
|
|
d->continueDebugging(Continue);
|
|
|
|
|
}
|
|
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
void QmlV8DebuggerClient::continueInferior()
|
|
|
|
|
{
|
2011-12-07 09:38:40 +01:00
|
|
|
clearExceptionSelection();
|
2011-10-26 10:02:37 +02:00
|
|
|
d->continueDebugging(Continue);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void QmlV8DebuggerClient::interruptInferior()
|
|
|
|
|
{
|
|
|
|
|
d->interrupt();
|
2011-08-17 13:42:41 +02:00
|
|
|
}
|
|
|
|
|
|
2011-07-26 16:22:49 +02:00
|
|
|
void QmlV8DebuggerClient::activateFrame(int index)
|
|
|
|
|
{
|
2011-12-07 09:38:40 +01:00
|
|
|
if (index != d->engine->stackHandler()->currentIndex())
|
2012-04-06 11:03:33 +02:00
|
|
|
d->frame(d->stackIndexLookup.value(index));
|
2012-02-23 17:14:46 +01:00
|
|
|
d->engine->stackHandler()->setCurrentIndex(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;
|
2012-04-16 12:00:23 +02:00
|
|
|
return (type == BreakpointOnQmlSignalEmit
|
2011-12-07 09:38:40 +01:00
|
|
|
|| type == BreakpointByFileAndLine
|
2011-10-10 15:25:18 +02:00
|
|
|
|| type == BreakpointAtJavaScriptThrow);
|
2011-09-13 12:47:46 +02:00
|
|
|
}
|
|
|
|
|
|
2012-02-28 17:30:15 +01:00
|
|
|
void QmlV8DebuggerClient::insertBreakpoint(const BreakpointModelId &id,
|
|
|
|
|
int adjustedLine,
|
|
|
|
|
int adjustedColumn)
|
2011-07-26 16:22:49 +02:00
|
|
|
{
|
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) {
|
2012-02-28 17:30:15 +01:00
|
|
|
d->setBreakpoint(QString(_(SCRIPTREGEXP)), params.fileName,
|
|
|
|
|
params.enabled, adjustedLine, adjustedColumn,
|
2012-02-27 12:14:00 +01:00
|
|
|
QLatin1String(params.condition), params.ignoreCount);
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2012-04-16 12:00:23 +02:00
|
|
|
} else if (params.type == BreakpointOnQmlSignalEmit) {
|
2012-02-28 17:30:15 +01:00
|
|
|
d->setBreakpoint(QString(_(EVENT)), params.functionName, params.enabled);
|
2011-12-07 09:38:40 +01:00
|
|
|
d->engine->breakHandler()->notifyBreakpointInsertOk(id);
|
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:02:37 +02:00
|
|
|
BreakHandler *handler = d->engine->breakHandler();
|
2012-02-28 17:30:15 +01:00
|
|
|
const BreakpointParameters ¶ms = handler->breakpointData(id);
|
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
|
|
|
|
2012-02-28 17:30:15 +01:00
|
|
|
if (params.type == BreakpointAtJavaScriptThrow)
|
2011-10-26 10:02:37 +02:00
|
|
|
d->setExceptionBreak(AllExceptions);
|
2012-04-16 12:00:23 +02:00
|
|
|
else if (params.type == BreakpointOnQmlSignalEmit)
|
2012-02-28 17:30:15 +01:00
|
|
|
d->setBreakpoint(QString(_(EVENT)), params.functionName, false);
|
|
|
|
|
else
|
2011-10-26 10:02:37 +02:00
|
|
|
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-10 15:25:18 +02:00
|
|
|
BreakHandler *handler = d->engine->breakHandler();
|
|
|
|
|
const BreakpointParameters ¶ms = handler->breakpointData(id);
|
|
|
|
|
|
2012-03-09 09:06:21 +01:00
|
|
|
BreakpointResponse br = handler->response(id);
|
2011-10-10 15:25:18 +02:00
|
|
|
if (params.type == BreakpointAtJavaScriptThrow) {
|
2011-10-26 10:02:37 +02:00
|
|
|
d->setExceptionBreak(AllExceptions, params.enabled);
|
2012-03-09 09:06:21 +01:00
|
|
|
br.enabled = params.enabled;
|
|
|
|
|
handler->setResponse(id, br);
|
2012-04-16 12:00:23 +02:00
|
|
|
} else if (params.type == BreakpointOnQmlSignalEmit) {
|
2012-02-28 17:30:15 +01:00
|
|
|
d->setBreakpoint(QString(_(EVENT)), params.functionName, params.enabled);
|
2012-03-09 09:06:21 +01:00
|
|
|
br.enabled = params.enabled;
|
|
|
|
|
handler->setResponse(id, br);
|
2011-12-07 09:38:40 +01:00
|
|
|
} else {
|
2012-03-09 09:06:21 +01:00
|
|
|
//V8 supports only minimalistic changes in breakpoint
|
|
|
|
|
//Remove the breakpoint and add again
|
2012-06-06 14:10:07 +02:00
|
|
|
handler->notifyBreakpointChangeOk(id);
|
|
|
|
|
handler->removeBreakpoint(id);
|
|
|
|
|
handler->appendBreakpoint(params);
|
2011-12-07 09:38:40 +01:00
|
|
|
}
|
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
|
|
|
}
|
|
|
|
|
|
2012-03-14 11:58:31 +01:00
|
|
|
void QmlV8DebuggerClient::assignValueInDebugger(const WatchData * /*data*/,
|
|
|
|
|
const QString &expr,
|
|
|
|
|
const QVariant &valueV)
|
2011-07-26 16:22:49 +02:00
|
|
|
{
|
2011-10-26 10:40:15 +02:00
|
|
|
StackHandler *stackHandler = d->engine->stackHandler();
|
2012-03-14 11:58:31 +01:00
|
|
|
QString expression = QString(_("%1 = %2;")).arg(expr).arg(valueV.toString());
|
2011-12-13 16:45:32 +01:00
|
|
|
if (stackHandler->isContentsValid() && stackHandler->currentFrame().isUsable()) {
|
|
|
|
|
d->evaluate(expression, false, false, stackHandler->currentIndex());
|
2012-03-21 09:46:33 +01:00
|
|
|
d->updateLocalsAndWatchers.append(d->sequence);
|
2011-12-13 16:45:32 +01:00
|
|
|
} else {
|
2012-10-04 14:54:59 +02:00
|
|
|
d->engine->showMessage(QString(_("Cannot evaluate %1 in current stack frame")).arg(
|
|
|
|
|
expression), ConsoleOutput);
|
2011-10-26 10:40:15 +02:00
|
|
|
}
|
2011-07-26 16:22:49 +02:00
|
|
|
}
|
|
|
|
|
|
2011-12-07 09:38:40 +01:00
|
|
|
void QmlV8DebuggerClient::updateWatchData(const WatchData &/*data*/)
|
2011-07-26 16:22:49 +02:00
|
|
|
{
|
2011-12-07 09:38:40 +01:00
|
|
|
//NOT USED
|
2011-07-26 16:22:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void QmlV8DebuggerClient::executeDebuggerCommand(const QString &command)
|
|
|
|
|
{
|
2011-10-26 10:02:37 +02:00
|
|
|
StackHandler *stackHandler = d->engine->stackHandler();
|
2011-12-13 16:45:32 +01:00
|
|
|
if (stackHandler->isContentsValid() && stackHandler->currentFrame().isUsable()) {
|
|
|
|
|
d->evaluate(command, false, false, stackHandler->currentIndex());
|
2012-03-21 11:51:36 +01:00
|
|
|
d->debuggerCommands.append(d->sequence);
|
2011-10-26 10:02:37 +02:00
|
|
|
} else {
|
|
|
|
|
//Currently cannot evaluate if not in a javascript break
|
2012-10-04 14:54:59 +02:00
|
|
|
d->engine->showMessage(QString(_("Cannot evaluate %1 in current stack frame")).arg(
|
|
|
|
|
command), ConsoleOutput);
|
2011-10-26 10:02:37 +02:00
|
|
|
}
|
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);
|
2011-12-07 09:38:40 +01:00
|
|
|
foreach (const QString &exp, watchers) {
|
2014-11-21 16:58:39 +01:00
|
|
|
StackHandler *stackHandler = d->engine->stackHandler();
|
|
|
|
|
if (stackHandler->isContentsValid() && stackHandler->currentFrame().isUsable()) {
|
|
|
|
|
d->evaluate(exp, false, false, stackHandler->currentIndex());
|
|
|
|
|
d->evaluatingExpression.insert(d->sequence, exp);
|
2011-10-28 16:43:20 +02:00
|
|
|
}
|
|
|
|
|
}
|
2011-07-26 16:22:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void QmlV8DebuggerClient::expandObject(const QByteArray &iname, quint64 objectId)
|
|
|
|
|
{
|
2012-03-21 11:51:36 +01:00
|
|
|
if (objectId == 0) {
|
|
|
|
|
//We may have got the global object
|
2012-05-18 02:28:41 +02:00
|
|
|
const WatchData *watch = d->engine->watchHandler()->findData(iname);
|
2012-03-21 11:51:36 +01:00
|
|
|
if (watch->value == QLatin1String("global")) {
|
|
|
|
|
StackHandler *stackHandler = d->engine->stackHandler();
|
|
|
|
|
if (stackHandler->isContentsValid() && stackHandler->currentFrame().isUsable()) {
|
|
|
|
|
d->evaluate(watch->name, false, false, stackHandler->currentIndex());
|
|
|
|
|
d->evaluatingExpression.insert(d->sequence, QLatin1String(iname));
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
2012-03-21 09:46:33 +01:00
|
|
|
d->localsAndWatchers.insertMulti(objectId, iname);
|
2011-12-07 09:38:40 +01: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;
|
2012-10-09 16:13:29 +02:00
|
|
|
connect(this, SIGNAL(stackFrameCompleted()), engine, SIGNAL(stackFrameCompleted()));
|
2011-07-26 16:22:49 +02:00
|
|
|
}
|
|
|
|
|
|
2011-11-30 15:23:02 +01:00
|
|
|
void QmlV8DebuggerClient::getSourceFiles()
|
|
|
|
|
{
|
|
|
|
|
d->scripts(4, QList<int>(), true, QVariant());
|
|
|
|
|
}
|
|
|
|
|
|
2011-07-26 16:22:49 +02:00
|
|
|
void QmlV8DebuggerClient::messageReceived(const QByteArray &data)
|
|
|
|
|
{
|
2013-11-01 09:58:44 +01:00
|
|
|
QmlDebugStream ds(data);
|
2011-07-26 16:22:49 +02:00
|
|
|
QByteArray command;
|
|
|
|
|
ds >> command;
|
|
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
if (command == V8DEBUG) {
|
2011-12-07 09:38:40 +01:00
|
|
|
QByteArray type;
|
2011-07-26 16:22:49 +02:00
|
|
|
QByteArray response;
|
2011-12-07 09:38:40 +01:00
|
|
|
ds >> type >> response;
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-12-21 13:29:31 +01:00
|
|
|
d->logReceiveMessage(_(V8DEBUG) + QLatin1Char(' ') + QLatin1String(type));
|
2011-12-07 09:38:40 +01:00
|
|
|
if (type == CONNECT) {
|
|
|
|
|
//debugging session started
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-12-07 09:38:40 +01:00
|
|
|
} else if (type == INTERRUPT) {
|
|
|
|
|
//debug break requested
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2012-04-16 12:00:23 +02:00
|
|
|
} else if (type == BREAKONSIGNAL) {
|
2011-12-07 09:38:40 +01:00
|
|
|
//break on signal handler requested
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-12-07 09:38:40 +01:00
|
|
|
} else if (type == V8MESSAGE) {
|
2011-12-21 13:29:31 +01:00
|
|
|
const QString responseString = QLatin1String(response);
|
2011-12-07 09:38:40 +01:00
|
|
|
SDEBUG(responseString);
|
2011-12-21 13:29:31 +01:00
|
|
|
d->logReceiveMessage(QLatin1String(V8MESSAGE) + QLatin1Char(' ') + responseString);
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-12-07 09:38:40 +01:00
|
|
|
const QVariantMap resp = d->parser.call(QScriptValue(),
|
|
|
|
|
QScriptValueList() <<
|
|
|
|
|
QScriptValue(responseString)).toVariant().toMap();
|
|
|
|
|
const QString type(resp.value(_(TYPE)).toString());
|
2011-11-03 19:28:35 +01:00
|
|
|
|
2011-12-07 09:38:40 +01:00
|
|
|
if (type == _("response")) {
|
2011-09-13 12:47:46 +02:00
|
|
|
|
2011-12-07 09:38:40 +01:00
|
|
|
bool success = resp.value(_("success")).toBool();
|
|
|
|
|
if (!success) {
|
|
|
|
|
SDEBUG("Request was unsuccessful");
|
2011-11-03 19:28:35 +01:00
|
|
|
}
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-12-07 09:38:40 +01:00
|
|
|
const QString debugCommand(resp.value(_(COMMAND)).toString());
|
|
|
|
|
|
|
|
|
|
if (debugCommand == _(DISCONNECT)) {
|
|
|
|
|
//debugging session ended
|
|
|
|
|
|
|
|
|
|
} else if (debugCommand == _(CONTINEDEBUGGING)) {
|
|
|
|
|
//do nothing, wait for next break
|
|
|
|
|
|
|
|
|
|
} else if (debugCommand == _(BACKTRACE)) {
|
Remove braces for single lines of conditions
#!/usr/bin/env ruby
Dir.glob('**/*.cpp') { |file|
# skip ast (excluding paste, astpath, and canv'ast'imer)
next if file =~ /ast[^eip]|keywords\.|qualifiers|preprocessor|names.cpp/i
s = File.read(file)
next if s.include?('qlalr')
orig = s.dup
s.gsub!(/\n *if [^\n]*{\n[^\n]*\n\s+}(\s+else if [^\n]* {\n[^\n]*\n\s+})*(\s+else {\n[^\n]*\n\s+})?\n/m) { |m|
res = $&
if res =~ /^\s*(\/\/|[A-Z_]{3,})/ # C++ comment or macro (Q_UNUSED, SDEBUG), do not touch braces
res
else
res.gsub!('} else', 'else')
res.gsub!(/\n +} *\n/m, "\n")
res.gsub(/ *{$/, '')
end
}
s.gsub!(/ *$/, '')
File.open(file, 'wb').write(s) if s != orig
}
Change-Id: I3b30ee60df0986f66c02132c65fc38a3fbb6bbdc
Reviewed-by: hjk <qthjk@ovi.com>
2013-01-08 03:32:53 +02:00
|
|
|
if (success)
|
2011-12-07 09:38:40 +01:00
|
|
|
updateStack(resp.value(_(BODY)), resp.value(_(REFS)));
|
|
|
|
|
|
|
|
|
|
} else if (debugCommand == _(LOOKUP)) {
|
Remove braces for single lines of conditions
#!/usr/bin/env ruby
Dir.glob('**/*.cpp') { |file|
# skip ast (excluding paste, astpath, and canv'ast'imer)
next if file =~ /ast[^eip]|keywords\.|qualifiers|preprocessor|names.cpp/i
s = File.read(file)
next if s.include?('qlalr')
orig = s.dup
s.gsub!(/\n *if [^\n]*{\n[^\n]*\n\s+}(\s+else if [^\n]* {\n[^\n]*\n\s+})*(\s+else {\n[^\n]*\n\s+})?\n/m) { |m|
res = $&
if res =~ /^\s*(\/\/|[A-Z_]{3,})/ # C++ comment or macro (Q_UNUSED, SDEBUG), do not touch braces
res
else
res.gsub!('} else', 'else')
res.gsub!(/\n +} *\n/m, "\n")
res.gsub(/ *{$/, '')
end
}
s.gsub!(/ *$/, '')
File.open(file, 'wb').write(s) if s != orig
}
Change-Id: I3b30ee60df0986f66c02132c65fc38a3fbb6bbdc
Reviewed-by: hjk <qthjk@ovi.com>
2013-01-08 03:32:53 +02:00
|
|
|
if (success)
|
2011-12-07 09:38:40 +01:00
|
|
|
expandLocalsAndWatchers(resp.value(_(BODY)), resp.value(_(REFS)));
|
|
|
|
|
|
|
|
|
|
} else if (debugCommand == _(EVALUATE)) {
|
|
|
|
|
int seq = resp.value(_("request_seq")).toInt();
|
|
|
|
|
if (success) {
|
|
|
|
|
updateEvaluationResult(seq, success, resp.value(_(BODY)), resp.value(_(REFS)));
|
|
|
|
|
} else {
|
|
|
|
|
QVariantMap map;
|
|
|
|
|
map.insert(_(TYPE), QVariant(_("string")));
|
|
|
|
|
map.insert(_(VALUE), resp.value(_("message")));
|
|
|
|
|
updateEvaluationResult(seq, success, QVariant(map), QVariant());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} 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();
|
|
|
|
|
|
2011-12-22 18:43:09 +01:00
|
|
|
if (d->breakpointsSync.contains(seq)) {
|
|
|
|
|
BreakpointModelId id = d->breakpointsSync.take(seq);
|
|
|
|
|
d->breakpoints.insert(id, index);
|
2011-12-07 09:38:40 +01:00
|
|
|
|
2012-03-14 10:11:08 +01:00
|
|
|
//Is actual position info present? Then breakpoint was
|
|
|
|
|
//accepted
|
|
|
|
|
const QVariantList actualLocations =
|
|
|
|
|
breakpointData.value(
|
|
|
|
|
_("actual_locations")).toList();
|
|
|
|
|
if (actualLocations.count()) {
|
|
|
|
|
//The breakpoint requested line should be same as
|
|
|
|
|
//actual line
|
|
|
|
|
BreakHandler *handler = d->engine->breakHandler();
|
|
|
|
|
if (handler->state(id) != BreakpointInserted) {
|
|
|
|
|
BreakpointResponse br = handler->response(id);
|
|
|
|
|
br.lineNumber = breakpointData.value(_("line")
|
|
|
|
|
).toInt() + 1;
|
|
|
|
|
handler->setResponse(id, br);
|
|
|
|
|
handler->notifyBreakpointInsertOk(id);
|
|
|
|
|
}
|
2012-02-28 17:30:15 +01:00
|
|
|
}
|
|
|
|
|
|
2011-12-22 18:43:09 +01:00
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
d->breakpointsTemp.append(index);
|
|
|
|
|
}
|
2011-12-07 09:38:40 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
} else if (debugCommand == _(CLEARBREAKPOINT)) {
|
|
|
|
|
// DO NOTHING
|
|
|
|
|
|
|
|
|
|
} else if (debugCommand == _(SETEXCEPTIONBREAK)) {
|
|
|
|
|
// { "seq" : <number>,
|
|
|
|
|
// "type" : "response",
|
|
|
|
|
// "request_seq" : <number>,
|
|
|
|
|
// "command" : "setexceptionbreak",
|
2011-12-20 08:07:29 +08:00
|
|
|
// "body" : { "type" : <string: "all" or "uncaught" corresponding to the request.>,
|
2011-12-07 09:38:40 +01:00
|
|
|
// "enabled" : <bool: true if the break type is currently enabled as a result of the request>
|
|
|
|
|
// }
|
|
|
|
|
// "running" : true
|
|
|
|
|
// "success" : true
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} else if (debugCommand == _(FRAME)) {
|
Remove braces for single lines of conditions
#!/usr/bin/env ruby
Dir.glob('**/*.cpp') { |file|
# skip ast (excluding paste, astpath, and canv'ast'imer)
next if file =~ /ast[^eip]|keywords\.|qualifiers|preprocessor|names.cpp/i
s = File.read(file)
next if s.include?('qlalr')
orig = s.dup
s.gsub!(/\n *if [^\n]*{\n[^\n]*\n\s+}(\s+else if [^\n]* {\n[^\n]*\n\s+})*(\s+else {\n[^\n]*\n\s+})?\n/m) { |m|
res = $&
if res =~ /^\s*(\/\/|[A-Z_]{3,})/ # C++ comment or macro (Q_UNUSED, SDEBUG), do not touch braces
res
else
res.gsub!('} else', 'else')
res.gsub!(/\n +} *\n/m, "\n")
res.gsub(/ *{$/, '')
end
}
s.gsub!(/ *$/, '')
File.open(file, 'wb').write(s) if s != orig
}
Change-Id: I3b30ee60df0986f66c02132c65fc38a3fbb6bbdc
Reviewed-by: hjk <qthjk@ovi.com>
2013-01-08 03:32:53 +02:00
|
|
|
if (success)
|
2011-12-07 09:38:40 +01:00
|
|
|
setCurrentFrameDetails(resp.value(_(BODY)), resp.value(_(REFS)));
|
|
|
|
|
|
|
|
|
|
} else if (debugCommand == _(SCOPE)) {
|
Remove braces for single lines of conditions
#!/usr/bin/env ruby
Dir.glob('**/*.cpp') { |file|
# skip ast (excluding paste, astpath, and canv'ast'imer)
next if file =~ /ast[^eip]|keywords\.|qualifiers|preprocessor|names.cpp/i
s = File.read(file)
next if s.include?('qlalr')
orig = s.dup
s.gsub!(/\n *if [^\n]*{\n[^\n]*\n\s+}(\s+else if [^\n]* {\n[^\n]*\n\s+})*(\s+else {\n[^\n]*\n\s+})?\n/m) { |m|
res = $&
if res =~ /^\s*(\/\/|[A-Z_]{3,})/ # C++ comment or macro (Q_UNUSED, SDEBUG), do not touch braces
res
else
res.gsub!('} else', 'else')
res.gsub!(/\n +} *\n/m, "\n")
res.gsub(/ *{$/, '')
end
}
s.gsub!(/ *$/, '')
File.open(file, 'wb').write(s) if s != orig
}
Change-Id: I3b30ee60df0986f66c02132c65fc38a3fbb6bbdc
Reviewed-by: hjk <qthjk@ovi.com>
2013-01-08 03:32:53 +02:00
|
|
|
if (success)
|
2011-12-07 09:38:40 +01:00
|
|
|
updateScope(resp.value(_(BODY)), resp.value(_(REFS)));
|
|
|
|
|
|
|
|
|
|
} else if (debugCommand == _(SCRIPTS)) {
|
2011-11-30 15:23:02 +01:00
|
|
|
// { "seq" : <number>,
|
|
|
|
|
// "type" : "response",
|
|
|
|
|
// "request_seq" : <number>,
|
|
|
|
|
// "command" : "scripts",
|
|
|
|
|
// "body" : [ { "name" : <name of the script>,
|
|
|
|
|
// "id" : <id of the script>
|
|
|
|
|
// "lineOffset" : <line offset within the containing resource>
|
|
|
|
|
// "columnOffset" : <column offset within the containing resource>
|
|
|
|
|
// "lineCount" : <number of lines in the script>
|
|
|
|
|
// "data" : <optional data object added through the API>
|
|
|
|
|
// "source" : <source of the script if includeSource was specified in the request>
|
|
|
|
|
// "sourceStart" : <first 80 characters of the script if includeSource was not specified in the request>
|
|
|
|
|
// "sourceLength" : <total length of the script in characters>
|
|
|
|
|
// "scriptType" : <script type (see request for values)>
|
|
|
|
|
// "compilationType" : < How was this script compiled:
|
|
|
|
|
// 0 if script was compiled through the API
|
|
|
|
|
// 1 if script was compiled through eval
|
|
|
|
|
// >
|
|
|
|
|
// "evalFromScript" : <if "compilationType" is 1 this is the script from where eval was called>
|
|
|
|
|
// "evalFromLocation" : { line : < if "compilationType" is 1 this is the line in the script from where eval was called>
|
|
|
|
|
// column : < if "compilationType" is 1 this is the column in the script from where eval was called>
|
|
|
|
|
// ]
|
|
|
|
|
// "running" : <is the VM running after sending this response>
|
|
|
|
|
// "success" : true
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
if (success) {
|
|
|
|
|
const QVariantList body = resp.value(_(BODY)).toList();
|
|
|
|
|
|
|
|
|
|
QStringList sourceFiles;
|
|
|
|
|
for (int i = 0; i < body.size(); ++i) {
|
|
|
|
|
const QVariantMap entryMap = body.at(i).toMap();
|
2011-12-21 13:29:31 +01:00
|
|
|
const int lineOffset = entryMap.value(QLatin1String("lineOffset")).toInt();
|
|
|
|
|
const int columnOffset = entryMap.value(QLatin1String("columnOffset")).toInt();
|
|
|
|
|
const QString name = entryMap.value(QLatin1String("name")).toString();
|
|
|
|
|
const QString source = entryMap.value(QLatin1String("source")).toString();
|
2011-11-30 15:23:02 +01:00
|
|
|
|
|
|
|
|
if (name.isEmpty())
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (!sourceFiles.contains(name))
|
|
|
|
|
sourceFiles << name;
|
|
|
|
|
|
|
|
|
|
d->engine->updateScriptSource(name, lineOffset, columnOffset, source);
|
|
|
|
|
}
|
|
|
|
|
d->engine->setSourceFiles(sourceFiles);
|
|
|
|
|
}
|
2011-12-07 09:38:40 +01:00
|
|
|
} else if (debugCommand == _(VERSION)) {
|
2011-12-16 13:21:30 +01:00
|
|
|
d->logReceiveMessage(QString(_("Using V8 Version: %1")).arg(
|
|
|
|
|
resp.value(_(BODY)).toMap().
|
|
|
|
|
value(_("V8Version")).toString()));
|
2011-12-07 11:13:46 +01:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
} else {
|
2011-12-07 09:38:40 +01:00
|
|
|
// DO NOTHING
|
2011-10-26 10:02:37 +02:00
|
|
|
}
|
2011-08-23 15:05:30 +02:00
|
|
|
|
2011-12-07 09:38:40 +01:00
|
|
|
} else if (type == _(EVENT)) {
|
|
|
|
|
const QString eventType(resp.value(_(EVENT)).toString());
|
2011-11-03 19:28:35 +01:00
|
|
|
|
2011-12-07 09:38:40 +01:00
|
|
|
if (eventType == _("break")) {
|
2011-12-16 16:37:14 +01:00
|
|
|
const QVariantMap breakData = resp.value(_(BODY)).toMap();
|
|
|
|
|
const QString invocationText = breakData.value(_("invocationText")).toString();
|
|
|
|
|
const QString scriptUrl = breakData.value(_("script")).toMap().value(_("name")).toString();
|
2012-08-22 11:58:33 +02:00
|
|
|
const QString sourceLineText = breakData.value(_("sourceLineText")).toString();
|
2011-12-16 16:37:14 +01:00
|
|
|
|
2011-12-29 13:43:59 +01:00
|
|
|
bool inferiorStop = true;
|
|
|
|
|
|
2011-12-29 14:05:35 +01:00
|
|
|
QList<int> v8BreakpointIds;
|
|
|
|
|
{
|
|
|
|
|
const QVariantList v8BreakpointIdList = breakData.value(_("breakpoints")).toList();
|
|
|
|
|
foreach (const QVariant &breakpointId, v8BreakpointIdList)
|
|
|
|
|
v8BreakpointIds << breakpointId.toInt();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!v8BreakpointIds.isEmpty() && invocationText.startsWith(_("[anonymous]()"))
|
|
|
|
|
&& scriptUrl.endsWith(_(".qml"))
|
2011-12-16 16:37:14 +01:00
|
|
|
&& sourceLineText.trimmed().startsWith(QLatin1Char('('))) {
|
|
|
|
|
|
2011-12-29 14:05:35 +01:00
|
|
|
// we hit most likely the anonymous wrapper function automatically generated for bindings
|
|
|
|
|
// -> relocate the breakpoint to column: 1 and continue
|
2011-12-29 13:43:59 +01:00
|
|
|
|
2011-12-29 14:05:35 +01:00
|
|
|
int newColumn = sourceLineText.indexOf(QLatin1Char('(')) + 1;
|
|
|
|
|
BreakHandler *handler = d->engine->breakHandler();
|
2011-12-16 16:37:14 +01:00
|
|
|
|
2011-12-29 14:05:35 +01:00
|
|
|
foreach (int v8Id, v8BreakpointIds) {
|
2013-03-14 14:12:52 +01:00
|
|
|
const BreakpointModelId internalId = d->breakpoints.key(v8Id);
|
2011-12-16 16:37:14 +01:00
|
|
|
|
2011-12-29 14:05:35 +01:00
|
|
|
if (internalId.isValid()) {
|
|
|
|
|
const BreakpointParameters ¶ms = handler->breakpointData(internalId);
|
2011-12-16 16:37:14 +01:00
|
|
|
|
2011-12-29 14:05:35 +01:00
|
|
|
d->clearBreakpoint(v8Id);
|
2012-02-28 17:30:15 +01:00
|
|
|
d->setBreakpoint(QString(_(SCRIPTREGEXP)),
|
|
|
|
|
params.fileName,
|
|
|
|
|
params.enabled,
|
|
|
|
|
params.lineNumber,
|
|
|
|
|
newColumn,
|
2012-08-22 11:58:33 +02:00
|
|
|
QString(QString::fromLatin1(params.condition)),
|
2012-02-28 17:30:15 +01:00
|
|
|
params.ignoreCount);
|
2011-12-29 14:05:35 +01:00
|
|
|
d->breakpointsSync.insert(d->sequence, internalId);
|
2011-12-16 16:37:14 +01:00
|
|
|
}
|
|
|
|
|
}
|
2011-12-29 14:05:35 +01:00
|
|
|
d->continueDebugging(Continue);
|
|
|
|
|
inferiorStop = false;
|
2011-12-29 13:43:59 +01:00
|
|
|
}
|
|
|
|
|
|
2012-04-06 11:03:33 +02:00
|
|
|
//Skip debug break if this is an internal function
|
|
|
|
|
if (sourceLineText == _(INTERNAL_FUNCTION)) {
|
|
|
|
|
d->continueDebugging(d->previousStepAction);
|
|
|
|
|
inferiorStop = false;
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-29 14:05:35 +01:00
|
|
|
if (inferiorStop) {
|
|
|
|
|
//Update breakpoint data
|
|
|
|
|
BreakHandler *handler = d->engine->breakHandler();
|
|
|
|
|
foreach (int v8Id, v8BreakpointIds) {
|
2013-03-14 14:12:52 +01:00
|
|
|
const BreakpointModelId id = d->breakpoints.key(v8Id);
|
|
|
|
|
if (id.isValid()) {
|
|
|
|
|
BreakpointResponse br = handler->response(id);
|
|
|
|
|
if (br.functionName.isEmpty()) {
|
|
|
|
|
br.functionName = invocationText;
|
|
|
|
|
handler->setResponse(id, br);
|
|
|
|
|
}
|
|
|
|
|
if (handler->state(id) != BreakpointInserted) {
|
|
|
|
|
br.lineNumber = breakData.value(
|
|
|
|
|
_("sourceLine")).toInt() + 1;
|
|
|
|
|
handler->setResponse(id, br);
|
|
|
|
|
handler->notifyBreakpointInsertOk(id);
|
2011-12-29 14:05:35 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-10-26 10:02:37 +02:00
|
|
|
|
2011-12-29 14:05:35 +01:00
|
|
|
if (d->engine->state() == InferiorRunOk) {
|
2011-12-22 18:43:09 +01:00
|
|
|
foreach (const QVariant &breakpointId, v8BreakpointIds) {
|
|
|
|
|
if (d->breakpointsTemp.contains(breakpointId.toInt()))
|
|
|
|
|
d->clearBreakpoint(breakpointId.toInt());
|
|
|
|
|
}
|
2011-12-29 14:05:35 +01:00
|
|
|
d->engine->inferiorSpontaneousStop();
|
|
|
|
|
d->backtrace();
|
|
|
|
|
} else if (d->engine->state() == InferiorStopOk) {
|
|
|
|
|
d->backtrace();
|
|
|
|
|
}
|
2011-12-29 13:43:59 +01:00
|
|
|
}
|
|
|
|
|
|
2011-12-07 09:38:40 +01:00
|
|
|
} else if (eventType == _("exception")) {
|
|
|
|
|
const QVariantMap body = resp.value(_(BODY)).toMap();
|
|
|
|
|
int lineNumber = body.value(_("sourceLine")).toInt() + 1;
|
2011-11-03 19:28:35 +01:00
|
|
|
|
2011-12-07 09:38:40 +01:00
|
|
|
const QVariantMap script = body.value(_("script")).toMap();
|
|
|
|
|
QUrl fileUrl(script.value(_(NAME)).toString());
|
|
|
|
|
QString filePath = d->engine->toFileInProject(fileUrl);
|
2011-11-07 14:58:45 +01:00
|
|
|
|
2011-12-07 09:38:40 +01:00
|
|
|
const QVariantMap exception = body.value(_("exception")).toMap();
|
|
|
|
|
QString errorMessage = exception.value(_("text")).toString();
|
2011-10-26 10:02:37 +02:00
|
|
|
|
2011-12-07 09:38:40 +01:00
|
|
|
highlightExceptionCode(lineNumber, filePath, errorMessage);
|
2011-11-03 19:28:35 +01:00
|
|
|
|
2011-12-07 09:38:40 +01:00
|
|
|
if (d->engine->state() == InferiorRunOk) {
|
|
|
|
|
d->engine->inferiorSpontaneousStop();
|
|
|
|
|
d->backtrace();
|
|
|
|
|
}
|
2011-11-03 19:28:35 +01:00
|
|
|
|
Remove braces for single lines of conditions
#!/usr/bin/env ruby
Dir.glob('**/*.cpp') { |file|
# skip ast (excluding paste, astpath, and canv'ast'imer)
next if file =~ /ast[^eip]|keywords\.|qualifiers|preprocessor|names.cpp/i
s = File.read(file)
next if s.include?('qlalr')
orig = s.dup
s.gsub!(/\n *if [^\n]*{\n[^\n]*\n\s+}(\s+else if [^\n]* {\n[^\n]*\n\s+})*(\s+else {\n[^\n]*\n\s+})?\n/m) { |m|
res = $&
if res =~ /^\s*(\/\/|[A-Z_]{3,})/ # C++ comment or macro (Q_UNUSED, SDEBUG), do not touch braces
res
else
res.gsub!('} else', 'else')
res.gsub!(/\n +} *\n/m, "\n")
res.gsub(/ *{$/, '')
end
}
s.gsub!(/ *$/, '')
File.open(file, 'wb').write(s) if s != orig
}
Change-Id: I3b30ee60df0986f66c02132c65fc38a3fbb6bbdc
Reviewed-by: hjk <qthjk@ovi.com>
2013-01-08 03:32:53 +02:00
|
|
|
if (d->engine->state() == InferiorStopOk)
|
2011-12-29 13:43:59 +01:00
|
|
|
d->backtrace();
|
|
|
|
|
|
2011-12-07 09:38:40 +01:00
|
|
|
} else if (eventType == _("afterCompile")) {
|
|
|
|
|
//Currently break point relocation is disabled.
|
|
|
|
|
//Uncomment the line below when it will be enabled.
|
|
|
|
|
// d->listBreakpoints();
|
|
|
|
|
}
|
2011-11-03 19:28:35 +01:00
|
|
|
|
2011-12-07 09:38:40 +01:00
|
|
|
//Sometimes we do not get event type!
|
|
|
|
|
//This is most probably due to a wrong eval expression.
|
|
|
|
|
//Redirect output to console.
|
|
|
|
|
if (eventType.isEmpty()) {
|
|
|
|
|
bool success = resp.value(_("success")).toBool();
|
|
|
|
|
QVariantMap map;
|
|
|
|
|
map.insert(_(TYPE), QVariant(_("string")));
|
|
|
|
|
map.insert(_(VALUE), resp.value(_("message")));
|
|
|
|
|
//Since there is no sequence value, best estimate is
|
|
|
|
|
//last sequence value
|
|
|
|
|
updateEvaluationResult(d->sequence, success, QVariant(map), QVariant());
|
|
|
|
|
}
|
2011-10-26 10:32:46 +02:00
|
|
|
|
2011-12-07 09:38:40 +01:00
|
|
|
} //EVENT
|
|
|
|
|
} //V8MESSAGE
|
2011-11-03 19:28:35 +01:00
|
|
|
|
2011-10-26 10:02:37 +02:00
|
|
|
} else {
|
|
|
|
|
//DO NOTHING
|
2011-07-26 16:22:49 +02:00
|
|
|
}
|
2011-11-03 19:28:35 +01: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();
|
|
|
|
|
|
2011-11-03 19:28:35 +01:00
|
|
|
int fromFrameIndex = body.value(_("fromFrame")).toInt();
|
|
|
|
|
|
2011-12-16 13:21:30 +01:00
|
|
|
QTC_ASSERT(0 == fromFrameIndex, return);
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-12-07 09:38:40 +01:00
|
|
|
StackHandler *stackHandler = d->engine->stackHandler();
|
|
|
|
|
StackFrames stackFrames;
|
2012-04-06 11:03:33 +02:00
|
|
|
int i = 0;
|
|
|
|
|
d->stackIndexLookup.clear();
|
2011-12-07 09:38:40 +01:00
|
|
|
foreach (const QVariant &frame, frames) {
|
2012-04-06 11:03:33 +02:00
|
|
|
StackFrame stackFrame = extractStackFrame(frame, refsVal);
|
|
|
|
|
if (stackFrame.level < 0)
|
|
|
|
|
continue;
|
|
|
|
|
d->stackIndexLookup.insert(i, stackFrame.level);
|
|
|
|
|
stackFrame.level = i;
|
|
|
|
|
stackFrames << stackFrame;
|
|
|
|
|
i++;
|
2011-11-03 19:28:35 +01:00
|
|
|
}
|
2011-12-07 09:38:40 +01:00
|
|
|
stackHandler->setFrames(stackFrames);
|
2011-10-31 14:17:01 +01:00
|
|
|
|
2011-12-07 09:38:40 +01:00
|
|
|
//Populate locals and watchers wrt top frame
|
2011-11-03 19:28:35 +01:00
|
|
|
//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.
|
2011-12-07 09:38:40 +01:00
|
|
|
setCurrentFrameDetails(frames.value(0), refsVal);
|
2011-10-26 10:02:37 +02:00
|
|
|
}
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2012-04-06 11:03:33 +02:00
|
|
|
StackFrame QmlV8DebuggerClient::extractStackFrame(const QVariant &bodyVal, const QVariant &refsVal)
|
2011-10-26 10:02:37 +02:00
|
|
|
{
|
|
|
|
|
// { "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();
|
2012-04-06 11:03:33 +02:00
|
|
|
//Do not insert the frame corresponding to the internal function
|
2012-08-22 11:58:33 +02:00
|
|
|
if (body.value(QLatin1String("sourceLineText")) == QLatin1String(INTERNAL_FUNCTION)) {
|
2012-04-06 11:03:33 +02:00
|
|
|
stackFrame.level = -1;
|
|
|
|
|
return stackFrame;
|
|
|
|
|
}
|
2011-10-26 10:02:37 +02:00
|
|
|
|
2012-10-04 14:54:59 +02:00
|
|
|
QmlV8ObjectData objectData = extractData(body.value(_("func")), refsVal);
|
2012-02-16 15:58:40 +01:00
|
|
|
QString functionName = objectData.value.toString();
|
2011-12-07 09:38:40 +01:00
|
|
|
if (functionName.isEmpty())
|
2012-10-01 10:07:12 +02:00
|
|
|
functionName = tr("Anonymous Function");
|
2011-12-07 09:38:40 +01:00
|
|
|
stackFrame.function = functionName;
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2012-10-04 14:54:59 +02:00
|
|
|
objectData = extractData(body.value(_("script")), refsVal);
|
2012-02-16 15:58:40 +01:00
|
|
|
stackFrame.file = d->engine->toFileInProject(objectData.value.toString());
|
2011-10-26 10:02:37 +02:00
|
|
|
stackFrame.usable = QFileInfo(stackFrame.file).isReadable();
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2012-10-04 14:54:59 +02:00
|
|
|
objectData = extractData(body.value(_("receiver")), refsVal);
|
2012-02-16 15:58:40 +01:00
|
|
|
stackFrame.to = objectData.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-12-07 09:38:40 +01:00
|
|
|
void QmlV8DebuggerClient::setCurrentFrameDetails(const QVariant &bodyVal, const QVariant &refsVal)
|
2011-10-26 10:02:37 +02:00
|
|
|
{
|
2011-12-07 09:38:40 +01:00
|
|
|
// { "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> ],
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-12-07 09:38:40 +01:00
|
|
|
// }
|
|
|
|
|
// "running" : <is the VM running after sending this response>
|
|
|
|
|
// "success" : true
|
|
|
|
|
// }
|
|
|
|
|
QVariantMap currentFrame = bodyVal.toMap();
|
2011-08-23 15:14:48 +02:00
|
|
|
|
2011-12-07 09:38:40 +01:00
|
|
|
StackHandler *stackHandler = d->engine->stackHandler();
|
2012-10-09 16:13:29 +02:00
|
|
|
WatchHandler * watchHandler = d->engine->watchHandler();
|
2011-12-07 09:38:40 +01:00
|
|
|
d->clearCache();
|
2012-10-09 16:13:29 +02:00
|
|
|
|
|
|
|
|
const int frameIndex = stackHandler->currentIndex();
|
2013-03-08 15:54:06 +01:00
|
|
|
QSet<QByteArray> expandedInames = watchHandler->expandedINames();
|
|
|
|
|
QHash<quint64, QByteArray> handlesToLookup;
|
|
|
|
|
// Store handles of all expanded watch data
|
|
|
|
|
foreach (const QByteArray &iname, expandedInames) {
|
|
|
|
|
const WatchData *wd = watchHandler->findData(iname);
|
|
|
|
|
if (!wd || !wd->isLocal())
|
|
|
|
|
continue;
|
|
|
|
|
handlesToLookup.insert(wd->id, iname);
|
|
|
|
|
}
|
2012-10-09 16:13:29 +02:00
|
|
|
watchHandler->removeAllData();
|
|
|
|
|
if (frameIndex < 0)
|
|
|
|
|
return;
|
|
|
|
|
const StackFrame frame = stackHandler->currentFrame();
|
|
|
|
|
if (!frame.isUsable())
|
|
|
|
|
return;
|
|
|
|
|
|
2011-12-07 09:38:40 +01:00
|
|
|
//Set "this" variable
|
|
|
|
|
{
|
|
|
|
|
WatchData data;
|
|
|
|
|
data.exp = QByteArray("this");
|
2011-12-21 13:29:31 +01:00
|
|
|
data.name = QLatin1String(data.exp);
|
2011-12-07 09:38:40 +01:00
|
|
|
data.iname = QByteArray("local.") + data.exp;
|
2012-10-04 14:54:59 +02:00
|
|
|
QmlV8ObjectData objectData = extractData(currentFrame.value(_("receiver")), refsVal);
|
2012-02-16 15:58:40 +01:00
|
|
|
data.id = objectData.handle;
|
|
|
|
|
data.type = objectData.type;
|
|
|
|
|
data.value = objectData.value.toString();
|
|
|
|
|
data.setHasChildren(objectData.properties.count());
|
2012-03-21 11:51:36 +01:00
|
|
|
//Incase of global object, we do not get children
|
|
|
|
|
//Set children nevertheless and query later
|
|
|
|
|
if (data.value == QLatin1String("global")) {
|
|
|
|
|
data.setHasChildren(true);
|
|
|
|
|
data.id = 0;
|
|
|
|
|
}
|
2012-10-09 16:13:29 +02:00
|
|
|
watchHandler->insertData(data);
|
2011-10-26 10:02:37 +02:00
|
|
|
}
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2011-12-07 09:38:40 +01:00
|
|
|
const QVariantList currentFrameScopes = currentFrame.value(_("scopes")).toList();
|
|
|
|
|
foreach (const QVariant &scope, currentFrameScopes) {
|
|
|
|
|
//Do not query for global types (0)
|
|
|
|
|
//Showing global properties increases clutter.
|
|
|
|
|
if (scope.toMap().value(_("type")).toInt() == 0)
|
|
|
|
|
continue;
|
2012-01-10 17:30:02 +01:00
|
|
|
int scopeIndex = scope.toMap().value(_("index")).toInt();
|
|
|
|
|
d->currentFrameScopes.append(scopeIndex);
|
|
|
|
|
d->scope(scopeIndex);
|
2011-12-07 09:38:40 +01:00
|
|
|
}
|
|
|
|
|
d->engine->gotoLocation(stackHandler->currentFrame());
|
2013-03-08 15:54:06 +01:00
|
|
|
|
|
|
|
|
// Expand watch data that were previously expanded
|
|
|
|
|
QHash<quint64, QByteArray>::const_iterator itEnd = handlesToLookup.end();
|
|
|
|
|
for (QHash<quint64, QByteArray>::const_iterator it = handlesToLookup.begin(); it != itEnd; ++it)
|
|
|
|
|
expandObject(it.value(), it.key());
|
2012-10-09 16:13:29 +02:00
|
|
|
emit stackFrameCompleted();
|
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();
|
2011-12-07 09:38:40 +01:00
|
|
|
|
|
|
|
|
//Check if the frameIndex is same as current Stack Index
|
|
|
|
|
StackHandler *stackHandler = d->engine->stackHandler();
|
|
|
|
|
if (bodyMap.value(_("frameIndex")).toInt() != stackHandler->currentIndex())
|
|
|
|
|
return;
|
|
|
|
|
|
2012-10-04 14:54:59 +02:00
|
|
|
QmlV8ObjectData objectData = extractData(bodyMap.value(_("object")), refsVal);
|
2011-10-31 14:17:01 +01:00
|
|
|
|
2011-12-07 09:38:40 +01:00
|
|
|
QList<int> handlesToLookup;
|
|
|
|
|
QList<WatchData> locals;
|
2012-02-16 15:58:40 +01:00
|
|
|
foreach (const QVariant &property, objectData.properties) {
|
2012-10-04 14:54:59 +02:00
|
|
|
QmlV8ObjectData localData = extractData(property, refsVal);
|
2011-10-31 14:17:01 +01:00
|
|
|
WatchData data;
|
2012-02-16 15:58:40 +01:00
|
|
|
data.exp = localData.name;
|
2011-10-31 14:17:01 +01:00
|
|
|
//Check for v8 specific local data
|
2011-12-21 13:29:31 +01:00
|
|
|
if (data.exp.startsWith('.') || data.exp.isEmpty())
|
2011-10-31 14:17:01 +01:00
|
|
|
continue;
|
|
|
|
|
|
2011-12-21 13:29:31 +01:00
|
|
|
data.name = QLatin1String(data.exp);
|
2011-10-31 14:17:01 +01:00
|
|
|
data.iname = QByteArray("local.") + data.exp;
|
|
|
|
|
|
2012-02-16 15:58:40 +01:00
|
|
|
int handle = localData.handle;
|
|
|
|
|
if (localData.value.isValid()) {
|
|
|
|
|
data.id = handle;
|
|
|
|
|
data.type = localData.type;
|
|
|
|
|
data.value = localData.value.toString();
|
|
|
|
|
data.setHasChildren(localData.properties.count());
|
|
|
|
|
locals << data;
|
|
|
|
|
} else {
|
2011-12-07 09:38:40 +01:00
|
|
|
handlesToLookup << handle;
|
2012-03-21 11:51:36 +01:00
|
|
|
d->localsAndWatchers.insertMulti(handle, data.exp);
|
2011-10-31 17:14:21 +01:00
|
|
|
}
|
2011-10-31 14:17:01 +01:00
|
|
|
}
|
|
|
|
|
|
2011-12-07 09:38:40 +01:00
|
|
|
if (!handlesToLookup.isEmpty())
|
|
|
|
|
d->lookup(handlesToLookup);
|
|
|
|
|
|
2012-05-18 02:28:41 +02:00
|
|
|
if (!locals.isEmpty())
|
|
|
|
|
d->engine->watchHandler()->insertData(locals);
|
2011-10-31 14:17:01 +01:00
|
|
|
}
|
|
|
|
|
|
2012-10-08 13:17:10 +02:00
|
|
|
QmlJS::ConsoleItem *constructLogItemTree(QmlJS::ConsoleItem *parent,
|
2012-10-04 14:54:59 +02:00
|
|
|
const QmlV8ObjectData &objectData,
|
2011-10-26 10:02:37 +02:00
|
|
|
const QVariant &refsVal)
|
2012-10-04 14:54:59 +02:00
|
|
|
{
|
2012-10-08 13:17:10 +02:00
|
|
|
using namespace QmlJS;
|
2014-07-28 14:23:52 +02:00
|
|
|
bool sorted = boolSetting(SortStructMembers);
|
2012-10-04 14:54:59 +02:00
|
|
|
if (!objectData.value.isValid())
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
QString text;
|
|
|
|
|
if (objectData.name.isEmpty())
|
|
|
|
|
text = objectData.value.toString();
|
|
|
|
|
else
|
2013-02-26 09:24:54 +08:00
|
|
|
text = QString(_("%1: %2")).arg(QString::fromLatin1(objectData.name))
|
2012-10-04 14:54:59 +02:00
|
|
|
.arg(objectData.value.toString());
|
|
|
|
|
|
2012-10-08 13:17:10 +02:00
|
|
|
ConsoleItem *item = new ConsoleItem(parent, ConsoleItem::UndefinedType, text);
|
2012-10-04 14:54:59 +02:00
|
|
|
|
2013-07-10 15:48:49 +02:00
|
|
|
QSet<QString> childrenFetched;
|
2012-10-04 14:54:59 +02:00
|
|
|
foreach (const QVariant &property, objectData.properties) {
|
2013-07-10 15:44:43 +02:00
|
|
|
const QmlV8ObjectData childObjectData = extractData(property, refsVal);
|
|
|
|
|
if (childObjectData.handle == objectData.handle)
|
|
|
|
|
continue;
|
|
|
|
|
ConsoleItem *child = constructLogItemTree(item, childObjectData, refsVal);
|
2013-07-10 15:48:49 +02:00
|
|
|
if (child) {
|
|
|
|
|
const QString text = child->text();
|
|
|
|
|
if (childrenFetched.contains(text))
|
|
|
|
|
continue;
|
|
|
|
|
childrenFetched.insert(text);
|
2012-10-04 14:54:59 +02:00
|
|
|
item->insertChild(child, sorted);
|
2013-07-10 15:48:49 +02:00
|
|
|
}
|
2012-10-04 14:54:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return item;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void QmlV8DebuggerClient::updateEvaluationResult(int sequence, bool success,
|
|
|
|
|
const QVariant &bodyVal, const QVariant &refsVal)
|
2011-10-26 10:02:37 +02:00
|
|
|
{
|
|
|
|
|
// { "seq" : <number>,
|
|
|
|
|
// "type" : "response",
|
|
|
|
|
// "request_seq" : <number>,
|
|
|
|
|
// "command" : "evaluate",
|
|
|
|
|
// "body" : ...
|
|
|
|
|
// "running" : <is the VM running after sending this response>
|
|
|
|
|
// "success" : true
|
|
|
|
|
// }
|
2012-05-31 15:50:06 +02:00
|
|
|
WatchHandler *watchHandler = d->engine->watchHandler();
|
2012-03-21 09:46:33 +01:00
|
|
|
if (d->updateLocalsAndWatchers.contains(sequence)) {
|
|
|
|
|
d->updateLocalsAndWatchers.removeOne(sequence);
|
2012-01-10 17:30:02 +01:00
|
|
|
//Update the locals
|
|
|
|
|
foreach (int index, d->currentFrameScopes)
|
|
|
|
|
d->scope(index);
|
2012-03-21 11:51:36 +01:00
|
|
|
//Also update "this"
|
|
|
|
|
QByteArray iname("local.this");
|
2012-05-31 15:50:06 +02:00
|
|
|
const WatchData *parent = watchHandler->findData(iname);
|
2012-03-21 11:51:36 +01:00
|
|
|
d->localsAndWatchers.insertMulti(parent->id, iname);
|
|
|
|
|
d->lookup(QList<int>() << parent->id);
|
|
|
|
|
|
|
|
|
|
} else if (d->debuggerCommands.contains(sequence)) {
|
|
|
|
|
d->updateLocalsAndWatchers.removeOne(sequence);
|
2012-10-04 14:54:59 +02:00
|
|
|
QmlV8ObjectData body = extractData(bodyVal, refsVal);
|
2012-10-08 13:17:10 +02:00
|
|
|
using namespace QmlJS;
|
|
|
|
|
ConsoleManagerInterface *consoleManager = ConsoleManagerInterface::instance();
|
2012-10-04 14:54:59 +02:00
|
|
|
if (consoleManager) {
|
2012-10-08 13:17:10 +02:00
|
|
|
ConsoleItem *item = constructLogItemTree(consoleManager->rootItem(), body, refsVal);
|
2012-10-04 14:54:59 +02:00
|
|
|
if (item)
|
|
|
|
|
consoleManager->printToConsolePane(item);
|
|
|
|
|
}
|
2012-03-21 11:51:36 +01:00
|
|
|
//Update the locals
|
|
|
|
|
foreach (int index, d->currentFrameScopes)
|
|
|
|
|
d->scope(index);
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2012-01-10 17:30:02 +01:00
|
|
|
} else {
|
2012-10-04 14:54:59 +02:00
|
|
|
QmlV8ObjectData body = extractData(bodyVal, refsVal);
|
2012-03-21 09:46:33 +01:00
|
|
|
if (d->evaluatingExpression.contains(sequence)) {
|
|
|
|
|
QString exp = d->evaluatingExpression.take(sequence);
|
2012-03-21 11:51:36 +01:00
|
|
|
QList<WatchData> watchDataList;
|
2012-01-10 17:30:02 +01:00
|
|
|
WatchData data;
|
2012-03-21 11:51:36 +01:00
|
|
|
//Do we have request to evaluate a local?
|
2012-08-22 11:58:33 +02:00
|
|
|
if (exp.startsWith(QLatin1String("local."))) {
|
2012-05-31 15:50:06 +02:00
|
|
|
const WatchData *watch = watchHandler->findData(exp.toLatin1());
|
2012-03-21 11:51:36 +01:00
|
|
|
watchDataList << createWatchDataList(watch, body.properties, refsVal);
|
2012-01-10 17:30:02 +01:00
|
|
|
} else {
|
2012-05-31 15:50:06 +02:00
|
|
|
QByteArray iname = watchHandler->watcherName(exp.toLatin1());
|
2012-03-21 11:51:36 +01:00
|
|
|
SDEBUG(QString(iname));
|
|
|
|
|
|
|
|
|
|
data.exp = exp.toLatin1();
|
|
|
|
|
data.name = exp;
|
|
|
|
|
data.iname = iname;
|
|
|
|
|
data.id = body.handle;
|
|
|
|
|
if (success) {
|
|
|
|
|
data.type = body.type;
|
|
|
|
|
data.value = body.value.toString();
|
|
|
|
|
data.hasChildren = body.properties.count();
|
|
|
|
|
} else {
|
|
|
|
|
//Do not set type since it is unknown
|
|
|
|
|
data.setError(body.value.toString());
|
|
|
|
|
}
|
|
|
|
|
watchDataList << data << createWatchDataList(&data, body.properties, refsVal);
|
2012-01-10 17:30:02 +01:00
|
|
|
}
|
|
|
|
|
//Insert the newly evaluated expression to the Watchers Window
|
2012-05-31 15:50:06 +02:00
|
|
|
watchHandler->insertData(watchDataList);
|
2012-01-10 17:30:02 +01:00
|
|
|
}
|
2011-07-26 16:22:49 +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();
|
|
|
|
|
|
2011-10-31 17:14:21 +01:00
|
|
|
QList<WatchData> watchDataList;
|
2011-11-03 19:28:35 +01:00
|
|
|
QStringList handlesList = body.keys();
|
2012-05-31 15:50:06 +02:00
|
|
|
WatchHandler *watchHandler = d->engine->watchHandler();
|
2011-11-03 19:28:35 +01:00
|
|
|
foreach (const QString &handle, handlesList) {
|
2012-10-04 14:54:59 +02:00
|
|
|
QmlV8ObjectData bodyObjectData = extractData(
|
2012-02-16 15:58:40 +01:00
|
|
|
body.value(handle), refsVal);
|
2011-11-03 19:28:35 +01:00
|
|
|
QByteArray prepend = d->localsAndWatchers.take(handle.toInt());
|
|
|
|
|
|
2012-01-10 17:30:02 +01:00
|
|
|
if (prepend.startsWith("local.") || prepend.startsWith("watch.")) {
|
|
|
|
|
//Data for expanded local/watch
|
2012-03-21 09:46:33 +01:00
|
|
|
//Could be an object or function
|
2012-05-31 15:50:06 +02:00
|
|
|
const WatchData *parent = watchHandler->findData(prepend);
|
2012-03-21 09:46:33 +01:00
|
|
|
watchDataList << createWatchDataList(parent, bodyObjectData.properties, refsVal);
|
2011-11-03 19:28:35 +01:00
|
|
|
} else {
|
|
|
|
|
//rest
|
|
|
|
|
WatchData data;
|
|
|
|
|
data.exp = prepend;
|
2011-12-21 13:29:31 +01:00
|
|
|
data.name = QLatin1String(data.exp);
|
2011-11-03 19:28:35 +01:00
|
|
|
data.iname = QByteArray("local.") + data.exp;
|
|
|
|
|
data.id = handle.toInt();
|
2011-10-26 10:02:37 +02:00
|
|
|
|
2011-11-03 19:28:35 +01:00
|
|
|
data.type = bodyObjectData.type;
|
|
|
|
|
data.value = bodyObjectData.value.toString();
|
2011-10-26 10:02:37 +02:00
|
|
|
|
2012-02-16 15:58:40 +01:00
|
|
|
data.setHasChildren(bodyObjectData.properties.count());
|
2011-10-26 10:02:37 +02:00
|
|
|
|
2011-10-31 17:14:21 +01:00
|
|
|
watchDataList << data;
|
2011-10-26 10:02:37 +02:00
|
|
|
}
|
2011-08-23 15:05:30 +02:00
|
|
|
}
|
2011-10-31 17:14:21 +01:00
|
|
|
|
2012-05-31 15:50:06 +02:00
|
|
|
watchHandler->insertData(watchDataList);
|
2011-07-26 16:22:49 +02:00
|
|
|
}
|
|
|
|
|
|
2012-03-21 09:46:33 +01:00
|
|
|
QList<WatchData> QmlV8DebuggerClient::createWatchDataList(const WatchData *parent,
|
|
|
|
|
const QVariantList &properties,
|
|
|
|
|
const QVariant &refsVal)
|
|
|
|
|
{
|
|
|
|
|
QList<WatchData> watchDataList;
|
|
|
|
|
if (properties.count()) {
|
|
|
|
|
QTC_ASSERT(parent, return watchDataList);
|
|
|
|
|
foreach (const QVariant &property, properties) {
|
2012-10-04 14:54:59 +02:00
|
|
|
QmlV8ObjectData propertyData = extractData(property, refsVal);
|
2012-03-21 09:46:33 +01:00
|
|
|
WatchData data;
|
2012-08-22 11:58:33 +02:00
|
|
|
data.name = QString::fromUtf8(propertyData.name);
|
2012-03-21 09:46:33 +01:00
|
|
|
|
|
|
|
|
//Check for v8 specific local data
|
|
|
|
|
if (data.name.startsWith(QLatin1Char('.')) || data.name.isEmpty())
|
|
|
|
|
continue;
|
|
|
|
|
if (parent->type == "object") {
|
|
|
|
|
if (parent->value == _("Array"))
|
|
|
|
|
data.exp = parent->exp + '[' + data.name.toLatin1() + ']';
|
|
|
|
|
else if (parent->value == _("Object"))
|
|
|
|
|
data.exp = parent->exp + '.' + data.name.toLatin1();
|
|
|
|
|
} else {
|
|
|
|
|
data.exp = data.name.toLatin1();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
data.iname = parent->iname + '.' + data.name.toLatin1();
|
|
|
|
|
data.id = propertyData.handle;
|
|
|
|
|
data.type = propertyData.type;
|
|
|
|
|
data.value = propertyData.value.toString();
|
|
|
|
|
data.setHasChildren(propertyData.properties.count());
|
|
|
|
|
watchDataList << data;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return watchDataList;
|
|
|
|
|
}
|
|
|
|
|
|
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
|
|
|
{
|
2014-05-07 16:25:04 +02:00
|
|
|
QList<IEditor *> editors = DocumentModel::editorsForFilePath(filePath);
|
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
|
|
|
|
2013-07-16 13:51:44 +02:00
|
|
|
foreach (IEditor *editor, editors) {
|
2014-09-26 11:37:54 +02:00
|
|
|
TextEditor::TextEditorWidget *ed = qobject_cast<TextEditor::TextEditorWidget *>(editor->widget());
|
2013-07-16 13:51:44 +02:00
|
|
|
if (!ed)
|
|
|
|
|
continue;
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2013-07-16 13:51:44 +02:00
|
|
|
QList<QTextEdit::ExtraSelection> selections;
|
|
|
|
|
QTextEdit::ExtraSelection sel;
|
|
|
|
|
sel.format = errorFormat;
|
|
|
|
|
QTextCursor c(ed->document()->findBlockByNumber(lineNumber - 1));
|
|
|
|
|
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;
|
2011-10-26 10:02:37 +02:00
|
|
|
}
|
2013-07-16 13:51:44 +02:00
|
|
|
}
|
|
|
|
|
c.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor);
|
|
|
|
|
sel.cursor = c;
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2013-07-16 13:51:44 +02:00
|
|
|
sel.format.setToolTip(errorMessage);
|
2011-07-26 16:22:49 +02:00
|
|
|
|
2013-07-16 13:51:44 +02:00
|
|
|
selections.append(sel);
|
2014-09-26 11:37:54 +02:00
|
|
|
ed->setExtraSelections(TextEditor::TextEditorWidget::DebuggerExceptionSelection, selections);
|
2011-10-26 10:43:43 +02:00
|
|
|
|
2013-07-16 13:51:44 +02:00
|
|
|
QString message = QString(_("%1: %2: %3")).arg(filePath).arg(lineNumber)
|
|
|
|
|
.arg(errorMessage);
|
|
|
|
|
d->engine->showMessage(message, ConsoleOutput);
|
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
|
|
|
QList<QTextEdit::ExtraSelection> selections;
|
|
|
|
|
|
2014-05-07 16:25:04 +02:00
|
|
|
foreach (IEditor *editor, DocumentModel::editorsForOpenedDocuments()) {
|
2014-09-26 11:37:54 +02:00
|
|
|
TextEditor::TextEditorWidget *ed = qobject_cast<TextEditor::TextEditorWidget *>(editor->widget());
|
2011-10-26 10:02:37 +02:00
|
|
|
if (!ed)
|
|
|
|
|
continue;
|
|
|
|
|
|
2014-09-26 11:37:54 +02:00
|
|
|
ed->setExtraSelections(TextEditor::TextEditorWidget::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
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // Internal
|
|
|
|
|
} // Debugger
|