Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qv4debugclient.cpp
Go to the documentation of this file.
1// Copyright (C) 2018 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qv4debugclient_p.h"
7
8#include <private/qpacket_p.h>
9
10#include <QJsonDocument>
11#include <QJsonObject>
12#include <QJsonValue>
13#include <QJsonArray>
14
16
17const char *V8REQUEST = "v8request";
18const char *V8MESSAGE = "v8message";
19const char *SEQ = "seq";
20const char *TYPE = "type";
21const char *COMMAND = "command";
22const char *ARGUMENTS = "arguments";
23const char *STEPACTION = "stepaction";
24const char *STEPCOUNT = "stepcount";
25const char *EXPRESSION = "expression";
26const char *FRAME = "frame";
27const char *CONTEXT = "context";
28const char *GLOBAL = "global";
29const char *DISABLEBREAK = "disable_break";
30const char *HANDLES = "handles";
31const char *INCLUDESOURCE = "includeSource";
32const char *FROMFRAME = "fromFrame";
33const char *TOFRAME = "toFrame";
34const char *BOTTOM = "bottom";
35const char *NUMBER = "number";
36const char *FRAMENUMBER = "frameNumber";
37const char *TYPES = "types";
38const char *IDS = "ids";
39const char *FILTER = "filter";
40const char *FROMLINE = "fromLine";
41const char *TOLINE = "toLine";
42const char *TARGET = "target";
43const char *LINE = "line";
44const char *COLUMN = "column";
45const char *ENABLED = "enabled";
46const char *CONDITION = "condition";
47const char *IGNORECOUNT = "ignoreCount";
48const char *BREAKPOINT = "breakpoint";
49const char *FLAGS = "flags";
50
51const char *CONTINEDEBUGGING = "continue";
52const char *EVALUATE = "evaluate";
53const char *LOOKUP = "lookup";
54const char *BACKTRACE = "backtrace";
55const char *SCOPE = "scope";
56const char *SCOPES = "scopes";
57const char *SCRIPTS = "scripts";
58const char *SOURCE = "source";
59const char *SETBREAKPOINT = "setbreakpoint";
60const char *CLEARBREAKPOINT = "clearbreakpoint";
61const char *CHANGEBREAKPOINT = "changebreakpoint";
62const char *SETEXCEPTIONBREAK = "setexceptionbreak";
63const char *VERSION = "version";
64const char *DISCONNECT = "disconnect";
65const char *GARBAGECOLLECTOR = "gc";
66
67const char *CONNECT = "connect";
68const char *INTERRUPT = "interrupt";
69
70const char *REQUEST = "request";
71const char *IN = "in";
72const char *NEXT = "next";
73const char *OUT = "out";
74
75const char *SCRIPT = "script";
76const char *SCRIPTREGEXP = "scriptRegExp";
77const char *EVENT = "event";
78
79const char *ALL = "all";
80const char *UNCAUGHT = "uncaught";
81
82#define VARIANTMAPINIT \
83 Q_D(QV4DebugClient); \
84 QJsonObject jsonVal; \
85 jsonVal.insert(QLatin1String(SEQ), d->seq++); \
86 jsonVal.insert(QLatin1String(TYPE), QLatin1String(REQUEST));
87
94
99
101{
102 Q_D(QV4DebugClient);
103 d->sendMessage(CONNECT);
104}
105
107{
108 Q_D(QV4DebugClient);
109 d->sendMessage(INTERRUPT);
110}
111
113{
114 // { "seq" : <number>,
115 // "type" : "request",
116 // "command" : "continue",
117 // "arguments" : { "stepaction" : <"in", "next" or "out">,
118 // "stepcount" : <number of steps (default 1)>
119 // }
120 // }
123
124 if (action != Continue) {
126 switch (action) {
127 case In:
129 break;
130 case Out:
132 break;
133 case Next:
135 break;
136 default:
137 break;
138 }
139 jsonVal.insert(QLatin1String(ARGUMENTS), args);
140 }
141
142 d->sendMessage(V8REQUEST, jsonVal);
143}
144
146{
147 // { "seq" : <number>,
148 // "type" : "request",
149 // "command" : "evaluate",
150 // "arguments" : { "expression" : <expression to evaluate>,
151 // "frame" : <number>,
152 // "context" : <object ID>
153 // }
154 // }
156 jsonVal.insert(QLatin1String(COMMAND), QLatin1String(EVALUATE));
157
160
161 if (frame != -1)
163
164 if (context != -1)
166
167 jsonVal.insert(QLatin1String(ARGUMENTS), args);
168
169 d->sendMessage(V8REQUEST, jsonVal);
170}
171
172void QV4DebugClient::lookup(const QList<int> &handles, bool includeSource)
173{
174 // { "seq" : <number>,
175 // "type" : "request",
176 // "command" : "lookup",
177 // "arguments" : { "handles" : <array of handles>,
178 // "includeSource" : <boolean indicating whether the source will be included when script objects are returned>,
179 // }
180 // }
182 jsonVal.insert(QLatin1String(COMMAND),(QLatin1String(LOOKUP)));
183
186
187 for (int handle : handles)
189
191
192 if (includeSource)
193 args.insert(QLatin1String(INCLUDESOURCE), includeSource);
194
195 jsonVal.insert(QLatin1String(ARGUMENTS), args);
196
197 d->sendMessage(V8REQUEST, jsonVal);
198}
199
200void QV4DebugClient::backtrace(int fromFrame, int toFrame, bool bottom)
201{
202 // { "seq" : <number>,
203 // "type" : "request",
204 // "command" : "backtrace",
205 // "arguments" : { "fromFrame" : <number>
206 // "toFrame" : <number>
207 // "bottom" : <boolean, set to true if the bottom of the stack is requested>
208 // }
209 // }
211 jsonVal.insert(QLatin1String(COMMAND), QLatin1String(BACKTRACE));
212
214
215 if (fromFrame != -1)
216 args.insert(QLatin1String(FROMFRAME), fromFrame);
217
218 if (toFrame != -1)
219 args.insert(QLatin1String(TOFRAME), toFrame);
220
221 if (bottom)
223
224 jsonVal.insert(QLatin1String(ARGUMENTS), args);
225 d->sendMessage(V8REQUEST, jsonVal);
226}
227
229{
230 // { "seq" : <number>,
231 // "type" : "request",
232 // "command" : "frame",
233 // "arguments" : { "number" : <frame number>
234 // }
235 // }
237 jsonVal.insert(QLatin1String(COMMAND), QLatin1String(FRAME));
238
239 if (number != -1) {
242 jsonVal.insert(QLatin1String(ARGUMENTS), args);
243 }
244
245 d->sendMessage(V8REQUEST, jsonVal);
246}
247
248void QV4DebugClient::scope(int number, int frameNumber)
249{
250 // { "seq" : <number>,
251 // "type" : "request",
252 // "command" : "scope",
253 // "arguments" : { "number" : <scope number>
254 // "frameNumber" : <frame number, optional uses selected frame if missing>
255 // }
256 // }
258 jsonVal.insert(QLatin1String(COMMAND), QLatin1String(SCOPE));
259
260 if (number != -1) {
263
264 if (frameNumber != -1)
265 args.insert(QLatin1String(FRAMENUMBER), frameNumber);
266
267 jsonVal.insert(QLatin1String(ARGUMENTS), args);
268 }
269
270 d->sendMessage(V8REQUEST, jsonVal);
271}
272
273void QV4DebugClient::scripts(int types, const QList<int> &ids, bool includeSource)
274{
275 // { "seq" : <number>,
276 // "type" : "request",
277 // "command" : "scripts",
278 // "arguments" : { "types" : <types of scripts to retrieve
279 // set bit 0 for native scripts
280 // set bit 1 for extension scripts
281 // set bit 2 for normal scripts
282 // (default is 4 for normal scripts)>
283 // "ids" : <array of id's of scripts to return. If this is not specified all scripts are requrned>
284 // "includeSource" : <boolean indicating whether the source code should be included for the scripts returned>
285 // "filter" : <string or number: filter string or script id.
286 // If a number is specified, then only the script with the same number as its script id will be retrieved.
287 // If a string is specified, then only scripts whose names contain the filter string will be retrieved.>
288 // }
289 // }
291 jsonVal.insert(QLatin1String(COMMAND), QLatin1String(SCRIPTS));
292
295
296 if (ids.size()) {
298 for (int id : ids)
299 array.append(id);
300
302 }
303
304 if (includeSource)
305 args.insert(QLatin1String(INCLUDESOURCE), includeSource);
306
307 jsonVal.insert(QLatin1String(ARGUMENTS), args);
308 d->sendMessage(V8REQUEST, jsonVal);
309}
310
312 const QString &condition, int ignoreCount)
313{
314 // { "seq" : <number>,
315 // "type" : "request",
316 // "command" : "setbreakpoint",
317 // "arguments" : { "type" : "scriptRegExp"
318 // "target" : <function expression or script identification>
319 // "line" : <line in script or function>
320 // "column" : <character position within the line>
321 // "enabled" : <initial enabled state. True or false, default is true>
322 // "condition" : <string with break point condition>
323 // "ignoreCount" : <number specifying the number of break point hits to ignore, default value is 0>
324 // }
325 // }
326
329
331
334
335 if (line != -1)
337
338 if (column != -1)
340
342
343 if (!condition.isEmpty())
345
346 if (ignoreCount != -1)
347 args.insert(QLatin1String(IGNORECOUNT), ignoreCount);
348
349 jsonVal.insert(QLatin1String(ARGUMENTS),args);
350 d->sendMessage(V8REQUEST, jsonVal);
351}
352
354{
355 // { "seq" : <number>,
356 // "type" : "request",
357 // "command" : "clearbreakpoint",
358 // "arguments" : { "breakpoint" : <number of the break point to clear>
359 // }
360 // }
363
365 args.insert(QLatin1String(BREAKPOINT), breakpoint);
366 jsonVal.insert(QLatin1String(ARGUMENTS),args);
367
368 d->sendMessage(V8REQUEST, jsonVal);
369}
370
372{
373 // { "seq" : <number>,
374 // "type" : "request",
375 // "command" : "changebreakpoint",
376 // "arguments" : { "breakpoint" : <number of the break point to change>
377 // "enabled" : <bool: enables the break type if true, disables if false>
378 // }
379 // }
382
384 args.insert(QLatin1String(BREAKPOINT), breakpoint);
386
387 jsonVal.insert(QLatin1String(ARGUMENTS), args);
388 d->sendMessage(V8REQUEST, jsonVal);
389}
390
392{
393 // { "seq" : <number>,
394 // "type" : "request",
395 // "command" : "setexceptionbreak",
396 // "arguments" : { "type" : <string: "all", or "uncaught">,
397 // "enabled" : <optional bool: enables the break type if true>
398 // }
399 // }
402
404
405 if (type == All)
407 else if (type == Uncaught)
409
410 if (enabled)
412
413 jsonVal.insert(QLatin1String(ARGUMENTS), args);
414 d->sendMessage(V8REQUEST, jsonVal);
415}
416
418{
419 // { "seq" : <number>,
420 // "type" : "request",
421 // "command" : "version",
422 // }
424 jsonVal.insert(QLatin1String(COMMAND), QLatin1String(VERSION));
425 d->sendMessage(V8REQUEST, jsonVal);
426}
427
429{
430 Q_D(const QV4DebugClient);
431 const QJsonObject value = QJsonDocument::fromJson(d->response).object();
432 return {
433 value.value(QLatin1String(COMMAND)).toString(),
434 value.value(QLatin1String("body"))
435 };
436}
437
439{
440 // { "seq" : <number>,
441 // "type" : "request",
442 // "command" : "disconnect",
443 // }
446 d->sendMessage(DISCONNECT, jsonVal);
447}
448
454
456{
457 Q_D(QV4DebugClient);
458 QPacket ds(connection()->currentDataStreamVersion(), data);
459 QByteArray command;
460 ds >> command;
461
462 if (command == "V8DEBUG") {
464 ds >> type >> d->response;
465
466 if (type == CONNECT) {
467 emit connected();
468
469 } else if (type == INTERRUPT) {
471
472 } else if (type == V8MESSAGE) {
473 const QJsonObject value = QJsonDocument::fromJson(d->response).object();
474 QString type = value.value(QLatin1String(TYPE)).toString();
475
476 if (type == QLatin1String("response")) {
477
478 if (!value.value(QLatin1String("success")).toBool()) {
479 emit failure();
480 qDebug() << "Received success == false response from application:"
481 << value.value(QLatin1String("message")).toString();
482 return;
483 }
484
485 QString debugCommand(value.value(QLatin1String(COMMAND)).toString());
486 if (debugCommand == QLatin1String(BACKTRACE) ||
487 debugCommand == QLatin1String(LOOKUP) ||
488 debugCommand == QLatin1String(SETBREAKPOINT) ||
489 debugCommand == QLatin1String(EVALUATE) ||
490 debugCommand == QLatin1String(VERSION) ||
491 debugCommand == QLatin1String(DISCONNECT) ||
492 debugCommand == QLatin1String(GARBAGECOLLECTOR) ||
493 debugCommand == QLatin1String(CHANGEBREAKPOINT) ||
494 debugCommand == QLatin1String(CLEARBREAKPOINT) ||
495 debugCommand == QLatin1String(FRAME) ||
496 debugCommand == QLatin1String(SCOPE) ||
497 debugCommand == QLatin1String(SCOPES) ||
498 debugCommand == QLatin1String(SCRIPTS) ||
499 debugCommand == QLatin1String(SOURCE) ||
500 debugCommand == QLatin1String(SETEXCEPTIONBREAK)) {
501 emit result();
502 } else {
503 // DO NOTHING
504 }
505
506 } else if (type == QLatin1String(EVENT)) {
508
509 if (event == QLatin1String("break") || event == QLatin1String("exception"))
510 emit stopped();
511 }
512 }
513 }
514}
515
517{
518 Q_Q(QV4DebugClient);
519 const QByteArray msg = packMessage(command, args);
520 if (q->state() == QQmlDebugClient::Enabled) {
521 q->sendMessage(msg);
522 } else {
523 sendBuffer.append(msg);
524 }
525}
526
528{
529 for (const QByteArray &msg : std::as_const(sendBuffer))
530 sendMessage(msg);
532}
533
535{
537 QByteArray cmd = "V8DEBUG";
538 rs << cmd << type << QJsonDocument(object).toJson(QJsonDocument::Compact);
539 return rs.data();
540}
541
543
544#include "moc_qv4debugclient_p.cpp"
\inmodule QtCore
Definition qbytearray.h:57
char * data()
\macro QT_NO_CAST_FROM_BYTEARRAY
Definition qbytearray.h:611
\inmodule QtCore\reentrant
Definition qjsonarray.h:18
void append(const QJsonValue &value)
Inserts value at the end of the array.
\inmodule QtCore\reentrant
QByteArray toJson(JsonFormat format=Indented) const
static QJsonDocument fromJson(const QByteArray &json, QJsonParseError *error=nullptr)
Parses json as a UTF-8 encoded JSON document, and creates a QJsonDocument from it.
\inmodule QtCore\reentrant
Definition qjsonobject.h:20
iterator insert(qsizetype i, parameter_type t)
Definition qlist.h:488
void append(parameter_type t)
Definition qlist.h:458
void clear()
Definition qlist.h:434
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2960
The QPacket class encapsulates an unfragmentable packet of data to be transmitted by QPacketProtocol.
Definition qpacket_p.h:24
QPointer< QQmlDebugConnection > connection
void stateChanged(State state)
State state() const
QQmlDebugConnection * connection() const
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
void sendMessage(const QByteArray &command, const QJsonObject &args=QJsonObject())
QList< QByteArray > sendBuffer
QByteArray packMessage(const QByteArray &type, const QJsonObject &object)
QV4DebugClientPrivate(QQmlDebugConnection *connection)
void onStateChanged(QQmlDebugClient::State state)
void scripts(int types=4, const QList< int > &ids=QList< int >(), bool includeSource=false)
void frame(int number=-1)
void changeBreakpoint(int breakpoint, bool enabled)
QV4DebugClient(QQmlDebugConnection *connection)
void messageReceived(const QByteArray &data) override
void evaluate(const QString &expr, int frame=-1, int context=-1)
void setBreakpoint(const QString &target, int line=-1, int column=-1, bool enabled=true, const QString &condition=QString(), int ignoreCount=-1)
void interrupted()
void lookup(const QList< int > &handles, bool includeSource=false)
void continueDebugging(StepAction stepAction)
void scope(int number=-1, int frameNumber=-1)
void setExceptionBreak(Exception type, bool enabled=false)
Response response() const
void backtrace(int fromFrame=-1, int toFrame=-1, bool bottom=false)
void clearBreakpoint(int breakpoint)
else opt state
[0]
const char EVENT[]
Combined button and popup list for selecting options.
static void * context
DBusConnection * connection
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
#define qDebug
[1]
Definition qlogging.h:164
GLuint64 GLenum void * handle
GLenum condition
GLenum GLenum GLsizei const GLuint * ids
GLsizei GLenum GLenum * types
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum GLenum GLsizei const GLuint GLboolean enabled
GLenum type
GLint GLint bottom
GLenum target
GLenum GLenum GLsizei void GLsizei void * column
struct _cl_event * event
GLenum array
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
QLatin1StringView QLatin1String
Definition qstringfwd.h:31
#define emit
const char * VERSION
const char * UNCAUGHT
const char * SCOPES
const char * BACKTRACE
const char * FROMLINE
const char * EVALUATE
const char * TOFRAME
const char * CONTINEDEBUGGING
const char * TOLINE
const char * SOURCE
const char * TYPES
const char * DISCONNECT
const char * FLAGS
QT_BEGIN_NAMESPACE const char * V8REQUEST
const char * LOOKUP
const char * EXPRESSION
const char * CONNECT
const char * ENABLED
const char * TARGET
const char * EVENT
const char * OUT
const char * FILTER
const char * GARBAGECOLLECTOR
const char * V8MESSAGE
const char * DISABLEBREAK
const char * REQUEST
const char * ALL
const char * COLUMN
const char * BOTTOM
const char * SETEXCEPTIONBREAK
const char * SCOPE
const char * SCRIPTREGEXP
const char * SEQ
const char * TYPE
const char * IDS
const char * CONTEXT
const char * INTERRUPT
const char * NEXT
const char * IGNORECOUNT
const char * SCRIPTS
const char * SETBREAKPOINT
const char * COMMAND
const char * GLOBAL
const char * IN
const char * STEPCOUNT
const char * HANDLES
#define VARIANTMAPINIT
const char * CLEARBREAKPOINT
const char * FRAMENUMBER
const char * BREAKPOINT
const char * INCLUDESOURCE
const char * STEPACTION
const char * LINE
const char * SCRIPT
const char * NUMBER
const char * CHANGEBREAKPOINT
const char * ARGUMENTS
const char * FROMFRAME
const char * FRAME
const char * CONDITION
QFrame frame
[0]
char * toString(const MyType &t)
[31]
QJSValueList args
QT_BEGIN_NAMESPACE bool toBool(const QString &str)
Definition utils.h:14