Qt 4.8
qjsdebugservice.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtDeclarative module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "private/qjsdebugservice_p.h"
43 #include "private/qjsdebuggeragent_p.h"
44 
45 #include <QtCore/qdatastream.h>
46 #include <QtCore/qdebug.h>
47 #include <QtCore/qstringlist.h>
48 #include <QtDeclarative/qdeclarativeengine.h>
49 
50 Q_GLOBAL_STATIC(QJSDebugService, serviceInstance)
51 
52 // convert to a QByteArray that can be sent to the debug client
53 QByteArray JSAgentCoverageData::toByteArray() const
54 {
56  //### using QDataStream is relatively expensive
58  ds << prefix << time << messageType << scriptId << program << fileName << baseLineNumber
59  << lineNumber << columnNumber << returnValue;
60  return data;
61 }
62 
64  : QDeclarativeDebugService(QLatin1String("JSDebugger"), parent)
65  , m_agent(0), m_deferredSend(true)
66 {
67  m_timer.start();
68 }
69 
71 {
72  delete m_agent;
73 }
74 
76 {
77  return serviceInstance();
78 }
79 
81 {
82  Q_ASSERT(engine);
83  Q_ASSERT(!m_engines.contains(engine));
84 
85  m_engines.append(engine);
86 
87  if (status() == Enabled && !m_engines.isEmpty() && !m_agent) {
88  m_agent = new QJSDebuggerAgent(engine, engine);
90  this, SLOT(executionStopped(bool,QString)));
91 
92  while (!m_agent->isInitialized()) {
94  }
95  }
96 }
97 
99 {
100  Q_ASSERT(engine);
101  Q_ASSERT(m_engines.contains(engine));
102 
103  m_engines.removeAll(engine);
104 }
105 
107 {
108  if (status == Enabled && !m_engines.isEmpty() && !m_agent) {
109  // Multiple engines are currently unsupported
111  m_agent = new QJSDebuggerAgent(engine, engine);
112 
114  this, SLOT(executionStopped(bool,QString)));
115 
116  } else if (status != Enabled && m_agent) {
117  delete m_agent;
118  m_agent = 0;
119  }
120 }
121 
123 {
124  if (!m_agent) {
125  qWarning() << "QJSDebugService::messageReceived: No QJSDebuggerAgent available";
126  return;
127  }
128 
129  QDataStream ds(message);
130  QByteArray command;
131  ds >> command;
132  if (command == "BREAKPOINTS") {
134  ds >> breakpoints;
135  m_agent->setBreakpoints(breakpoints);
136 
137  //qDebug() << "BREAKPOINTS";
138  //foreach (const JSAgentBreakpointData &bp, breakpoints)
139  // qDebug() << "BREAKPOINT: " << bp.fileUrl << bp.lineNumber;
140  } else if (command == "WATCH_EXPRESSIONS") {
142  ds >> watchExpressions;
143  m_agent->setWatchExpressions(watchExpressions);
144  } else if (command == "STEPOVER") {
145  m_agent->stepOver();
146  } else if (command == "STEPINTO" || command == "INTERRUPT") {
147  m_agent->stepInto();
148  } else if (command == "STEPOUT") {
149  m_agent->stepOut();
150  } else if (command == "CONTINUE") {
152  } else if (command == "EXEC") {
153  QByteArray id;
154  QString expr;
155  ds >> id >> expr;
156 
158 
159  QByteArray reply;
160  QDataStream rs(&reply, QIODevice::WriteOnly);
161  rs << QByteArray("RESULT") << id << data;
162  sendMessage(reply);
163  } else if (command == "EXPAND") {
164  QByteArray requestId;
165  quint64 objectId;
166  ds >> requestId >> objectId;
167 
169 
170  QByteArray reply;
171  QDataStream rs(&reply, QIODevice::WriteOnly);
172  rs << QByteArray("EXPANDED") << requestId << result;
173  sendMessage(reply);
174  } else if (command == "ACTIVATE_FRAME") {
175  int frameId;
176  ds >> frameId;
177 
178  QList<JSAgentWatchData> locals = m_agent->localsAtFrame(frameId);
179 
180  QByteArray reply;
181  QDataStream rs(&reply, QIODevice::WriteOnly);
182  rs << QByteArray("LOCALS") << frameId << locals;
183  sendMessage(reply);
184  } else if (command == "SET_PROPERTY") {
185  QByteArray id;
186  qint64 objectId;
188  QString value;
189  ds >> id >> objectId >> property >> value;
190 
191  m_agent->setProperty(objectId, property, value);
192 
193  //TODO: feedback
194  } else if (command == "PING") {
195  int ping;
196  ds >> ping;
197  QByteArray reply;
198  QDataStream rs(&reply, QIODevice::WriteOnly);
199  rs << QByteArray("PONG") << ping;
200  sendMessage(reply);
201  } else if (command == "COVERAGE") {
202  bool enabled;
203  ds >> enabled;
204  m_agent->setCoverageEnabled(enabled);
205  if (!enabled) {
206  sendMessages();
207  }
208  } else {
209  qDebug() << Q_FUNC_INFO << "Unknown command" << command;
210  }
211 
213 }
214 
215 void QJSDebugService::executionStopped(bool becauseOfException,
216  const QString &exception)
217 {
218  const QList<JSAgentStackData> backtrace = m_agent->backtrace();
219  const QList<JSAgentWatchData> watches = m_agent->watches();
220  const QList<JSAgentWatchData> locals = m_agent->locals();
221 
222  QByteArray reply;
223  QDataStream rs(&reply, QIODevice::WriteOnly);
224  rs << QByteArray("STOPPED") << backtrace << watches << locals
225  << becauseOfException << exception;
226  sendMessage(reply);
227 }
228 
229 /*
230  Either send the message directly, or queue up
231  a list of messages to send later (via sendMessages)
232 */
234 {
235  if (m_deferredSend)
236  m_data.append(message);
237  else
238  sendMessage(message.toByteArray());
239 }
240 
241 /*
242  Send the messages queued up by processMessage
243 */
245 {
246  if (m_deferredSend) {
247  //### this is a suboptimal way to send batched messages
248  for (int i = 0; i < m_data.count(); ++i)
250  m_data.clear();
251 
252  //indicate completion
255  ds << QByteArray("COVERAGE") << (qint64)-1 << (int)CoverageComplete;
256  sendMessage(data);
257  }
258 }
259 
virtual void messageReceived(const QByteArray &)
QList< QDeclarativeEngine * > m_engines
JSAgentWatchData executeExpression(const QString &expr)
void addEngine(QDeclarativeEngine *)
QList< JSAgentCoverageData > m_data
void setProperty(qint64 objectId, const QString &property, const QString &value)
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:135
#define SLOT(a)
Definition: qobjectdefs.h:226
QPointer< QJSDebuggerAgent > m_agent
QList< JSAgentWatchData > watches()
void removeEngine(QDeclarativeEngine *)
int count(const T &t) const
Returns the number of occurrences of value in the list.
Definition: qlist.h:891
void messageReceived(const QByteArray &)
The QString class provides a Unicode character string.
Definition: qstring.h:83
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
The QObject class is the base class of all Qt objects.
Definition: qobject.h:111
bool isEmpty() const
Returns true if the list contains no items; otherwise returns false.
Definition: qlist.h:152
void processMessage(const JSAgentCoverageData &message)
Q_CORE_EXPORT void qDebug(const char *,...)
#define SIGNAL(a)
Definition: qobjectdefs.h:227
void append(const T &t)
Inserts value at the end of the list.
Definition: qlist.h:507
QList< JSAgentWatchData > locals()
JSAgentBreakpoints breakpoints
QBool contains(const T &t) const
Returns true if the list contains an occurrence of value; otherwise returns false.
Definition: qlist.h:880
unsigned __int64 quint64
Definition: qglobal.h:943
static bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
Creates a connection of the given type from the signal in the sender object to the method in the rece...
Definition: qobject.cpp:2580
QElapsedTimer m_timer
#define Q_GLOBAL_STATIC(TYPE, NAME)
Declares a global static variable with the given type and name.
Definition: qglobal.h:1968
const T & at(int i) const
Returns the item at index position i in the list.
Definition: qlist.h:468
The QStringList class provides a list of strings.
Definition: qstringlist.h:66
Q_CORE_EXPORT void qWarning(const char *,...)
QScriptEngine * engine()
QList< JSAgentWatchData > localsAtFrame(int frameId)
static const char * data(const QByteArray &arr)
The QLatin1String class provides a thin wrapper around an US-ASCII/Latin-1 encoded string literal...
Definition: qstring.h:654
void setBreakpoints(const JSAgentBreakpoints &)
void setCoverageEnabled(bool enabled)
void clear()
Removes all items from the list.
Definition: qlist.h:764
__int64 qint64
Definition: qglobal.h:942
void setWatchExpressions(const QStringList &)
QList< JSAgentStackData > backtrace()
T & first()
Returns a reference to the first item in the list.
Definition: qlist.h:282
QByteArray toByteArray() const
QJSDebugService(QObject *parent=0)
The QDeclarativeEngine class provides an environment for instantiating QML components.
QList< JSAgentWatchData > expandObjectById(quint64 objectId)
void executionStopped(bool becauseOfException, const QString &exception)
QVariant property(const char *name) const
Returns the value of the object&#39;s name property.
Definition: qobject.cpp:3807
The QDataStream class provides serialization of binary data to a QIODevice.
Definition: qdatastream.h:71
void statusChanged(Status status)
static QJSDebugService * instance()
bool isInitialized() const
Indicates whether the agent got the list of breakpoints.
static QString fileName(const QString &fileUrl)
void start()
Starts this timer.
#define enabled
void sendMessage(const QByteArray &)
The QList class is a template class that provides lists.
Definition: qdatastream.h:62
int removeAll(const T &t)
Removes all occurrences of value in the list and returns the number of entries removed.
Definition: qlist.h:770
#define Q_FUNC_INFO
Definition: qglobal.h:1871