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
qqmlnativedebugservice.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 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
5
6#include <private/qqmldebugconnector_p.h>
7#include <private/qv4debugging_p.h>
8#include <private/qv4engine_p.h>
9#include <private/qv4debugging_p.h>
10#include <private/qv4script_p.h>
11#include <private/qv4string_p.h>
12#include <private/qv4objectiterator_p.h>
13#include <private/qv4identifierhash_p.h>
14#include <private/qv4runtime_p.h>
15#include <private/qversionedpacket_p.h>
16#include <private/qqmldebugserviceinterfaces_p.h>
17#include <private/qv4identifiertable_p.h>
18
19#include <QtQml/qjsengine.h>
20#include <QtCore/qjsonarray.h>
21#include <QtCore/qjsondocument.h>
22#include <QtCore/qjsonobject.h>
23#include <QtCore/qjsonvalue.h>
24#include <QtCore/qvector.h>
25#include <QtCore/qpointer.h>
26
27//#define TRACE_PROTOCOL(s) qDebug() << s
28#define TRACE_PROTOCOL(s)
29
31
32using QQmlDebugPacket = QVersionedPacket<QQmlDebugConnector>;
33
35{
36public:
38 bool isValid() const { return lineNumber >= 0 && !fileName.isEmpty(); }
39
40 int id;
43 bool enabled;
46
48};
49
50inline size_t qHash(const BreakPoint &b, size_t seed = 0) noexcept
51{
52 return qHash(b.fileName, seed) ^ b.lineNumber;
53}
54
55inline bool operator==(const BreakPoint &a, const BreakPoint &b)
56{
57 return a.lineNumber == b.lineNumber && a.fileName == b.fileName
58 && a.enabled == b.enabled && a.condition == b.condition
59 && a.ignoreCount == b.ignoreCount;
60}
61
62static void setError(QJsonObject *response, const QString &msg)
63{
64 response->insert(QStringLiteral("type"), QStringLiteral("error"));
65 response->insert(QStringLiteral("msg"), msg);
66}
67
68class NativeDebugger;
69
71{
72public:
76
77 void collect(QJsonArray *output, const QString &parentIName, const QString &name,
78 const QV4::Value &value);
79
80 bool isExpanded(const QString &iname) const { return m_expanded.contains(iname); }
81
82public:
86};
87
88// Encapsulate Breakpoint handling
89// Could be made per-NativeDebugger (i.e. per execution engine, if needed)
91{
92public:
94
97
98 void removeBreakPoint(int id);
99 void enableBreakPoint(int id, bool onoff);
100
101 void setBreakOnThrow(bool onoff);
105 QVector<BreakPoint> m_breakPoints;
106};
107
109{
110 TRACE_PROTOCOL("SET BREAKPOINT" << arguments);
112
114 if (fileName.isEmpty()) {
115 setError(response, QStringLiteral("breakpoint has no file name"));
116 return;
117 }
118
119 int line = arguments.value(QLatin1String("line")).toInt(-1);
120 if (line < 0) {
121 setError(response, QStringLiteral("breakpoint has an invalid line number"));
122 return;
123 }
124
125 BreakPoint bp;
126 bp.id = m_lastBreakpoint++;
127 bp.fileName = fileName.mid(fileName.lastIndexOf('/') + 1);
128 bp.lineNumber = line;
129 bp.enabled = arguments.value(QLatin1String("enabled")).toBool(true);
130 bp.condition = arguments.value(QLatin1String("condition")).toString();
131 bp.ignoreCount = arguments.value(QLatin1String("ignorecount")).toInt();
132 m_breakPoints.append(bp);
133
134 m_haveBreakPoints = true;
135
136 response->insert(QStringLiteral("type"), type);
137 response->insert(QStringLiteral("breakpoint"), bp.id);
138}
139
141{
142 int id = arguments.value(QLatin1String("id")).toInt();
144 response->insert(QStringLiteral("id"), id);
145}
146
148{
149public:
151
152 void signalEmitted(const QString &signal);
153
154 QV4::ExecutionEngine *engine() const { return m_engine; }
155
156 bool pauseAtNextOpportunity() const override {
157 return m_pauseRequested
158 || m_service->m_breakHandler->m_haveBreakPoints
159 || m_stepping >= StepOver;
160 }
161
162 void maybeBreakAtInstruction() override;
163 void enteringFunction() override;
164 void leavingFunction(const QV4::ReturnedValue &retVal) override;
165 void aboutToThrow() override;
166
167 void handleCommand(QJsonObject *response, const QString &cmd, const QJsonObject &arguments);
168
169private:
170 void handleBacktrace(QJsonObject *response, const QJsonObject &arguments);
171 void handleVariables(QJsonObject *response, const QJsonObject &arguments);
172 void handleExpressions(QJsonObject *response, const QJsonObject &arguments);
173
174 void handleDebuggerDeleted(QObject *debugger);
175
176 QV4::ReturnedValue evaluateExpression(const QString &expression);
177 bool checkCondition(const QString &expression);
178
179 QStringList breakOnSignals;
180
181 enum Speed {
182 NotStepping = 0,
183 StepOut,
184 StepOver,
185 StepIn,
186 };
187
188 void pauseAndWait();
189 void pause();
190 void handleContinue(QJsonObject *reponse, Speed speed);
191
192 QV4::Function *getFunction() const;
193
194 bool reallyHitTheBreakPoint(const QV4::Function *function, int lineNumber);
195
196 QV4::ExecutionEngine *m_engine;
198 QV4::CppStackFrame *m_currentFrame = nullptr;
199 Speed m_stepping;
200 bool m_pauseRequested;
201 bool m_runningJob;
202
203 QV4::PersistentValue m_returnedValue;
204};
205
206bool NativeDebugger::checkCondition(const QString &expression)
207{
208 QV4::Scope scope(m_engine);
209 QV4::ScopedValue r(scope, evaluateExpression(expression));
210 return r->booleanValue();
211}
212
213QV4::ReturnedValue NativeDebugger::evaluateExpression(const QString &expression)
214{
215 QV4::Scope scope(m_engine);
216 m_runningJob = true;
217
219 : m_engine->scriptContext();
220
222 if (const QV4::Function *function = m_engine->currentStackFrame
223 ? m_engine->currentStackFrame->v4Function : m_engine->globalCode)
224 script.strictMode = function->isStrict();
225 // In order for property lookups in QML to work, we need to disable fast v4 lookups.
226 // That is a side-effect of inheritContext.
227 script.inheritContext = true;
228 script.parse();
229 if (!m_engine->hasException) {
230 if (m_engine->currentStackFrame) {
231 QV4::ScopedValue thisObject(scope, m_engine->currentStackFrame->thisObject());
232 script.run(thisObject);
233 } else {
234 script.run();
235 }
236 }
237
238 m_runningJob = false;
239 return QV4::Encode::undefined();
240}
241
243 : m_returnedValue(engine, QV4::Value::undefinedValue())
244{
245 m_stepping = NotStepping;
246 m_pauseRequested = false;
247 m_runningJob = false;
248 m_service = service;
249 m_engine = engine;
250 TRACE_PROTOCOL("Creating native debugger");
251}
252
254{
255 //This function is only called by QQmlBoundSignal
256 //only if there is a slot connected to the signal. Hence, there
257 //is no need for additional check.
258
259 //Parse just the name and remove the class info
260 //Normalize to Lower case.
261 QString signalName = signal.left(signal.indexOf(QLatin1Char('('))).toLower();
262
263 for (const QString &signal : std::as_const(breakOnSignals)) {
264 if (signal == signalName) {
265 // TODO: pause debugger
266 break;
267 }
268 }
269}
270
272 const QJsonObject &arguments)
273{
274 if (cmd == QLatin1String("backtrace"))
275 handleBacktrace(response, arguments);
276 else if (cmd == QLatin1String("variables"))
277 handleVariables(response, arguments);
278 else if (cmd == QLatin1String("expressions"))
279 handleExpressions(response, arguments);
280 else if (cmd == QLatin1String("stepin"))
281 handleContinue(response, StepIn);
282 else if (cmd == QLatin1String("stepout"))
283 handleContinue(response, StepOut);
284 else if (cmd == QLatin1String("stepover"))
285 handleContinue(response, StepOver);
286 else if (cmd == QLatin1String("continue"))
287 handleContinue(response, NotStepping);
288}
289
291{
293 ds << quintptr(f);
294 return QString::fromLatin1(ds.data().toHex());
295}
296
298{
299 quintptr rawFrame;
300 QQmlDebugPacket ds(QByteArray::fromHex(f.toLatin1()));
301 ds >> rawFrame;
302 *frame = reinterpret_cast<QV4::CppStackFrame *>(rawFrame);
303}
304
305void NativeDebugger::handleBacktrace(QJsonObject *response, const QJsonObject &arguments)
306{
307 int limit = arguments.value(QLatin1String("limit")).toInt(0);
308
309 QJsonArray frameArray;
311 for (int i = 0; i < limit && f; ++i) {
312 QV4::Function *function = f->v4Function;
313
315 frame.insert(QStringLiteral("language"), QStringLiteral("js"));
316 frame.insert(QStringLiteral("context"), encodeFrame(f));
317
318 if (QV4::Heap::String *functionName = function->name())
319 frame.insert(QStringLiteral("function"), functionName->toQString());
320 frame.insert(QStringLiteral("file"), function->sourceFile());
321
322 int line = f->lineNumber();
323 frame.insert(QStringLiteral("line"), (line < 0 ? -line : line));
324
325 frameArray.push_back(frame);
326
327 f = f->parentFrame();
328 }
329
330 response->insert(QStringLiteral("frames"), frameArray);
331}
332
333void Collector::collect(QJsonArray *out, const QString &parentIName, const QString &name,
334 const QV4::Value &value)
335{
336 QJsonObject dict;
337 QV4::Scope scope(m_engine);
338
339 QString nonEmptyName = name.isEmpty() ? QString::fromLatin1("@%1").arg(m_anonCount++) : name;
340 QString iname = parentIName + QLatin1Char('.') + nonEmptyName;
341 dict.insert(QStringLiteral("iname"), iname);
342 dict.insert(QStringLiteral("name"), nonEmptyName);
343
345 dict.insert(QStringLiteral("type"), typeString->toQStringNoThrow());
346
347 switch (value.type()) {
349 dict.insert(QStringLiteral("valueencoded"), QStringLiteral("empty"));
350 dict.insert(QStringLiteral("haschild"), false);
351 break;
353 dict.insert(QStringLiteral("valueencoded"), QStringLiteral("undefined"));
354 dict.insert(QStringLiteral("haschild"), false);
355 break;
357 dict.insert(QStringLiteral("type"), QStringLiteral("object"));
358 dict.insert(QStringLiteral("valueencoded"), QStringLiteral("null"));
359 dict.insert(QStringLiteral("haschild"), false);
360 break;
362 dict.insert(QStringLiteral("value"), value.booleanValue());
363 dict.insert(QStringLiteral("haschild"), false);
364 break;
366 if (const QV4::String *string = value.as<QV4::String>()) {
367 dict.insert(QStringLiteral("value"), string->toQStringNoThrow());
368 dict.insert(QStringLiteral("haschild"), false);
369 dict.insert(QStringLiteral("valueencoded"), QStringLiteral("utf16"));
370 dict.insert(QStringLiteral("quoted"), true);
371 } else if (const QV4::ArrayObject *array = value.as<QV4::ArrayObject>()) {
372 // The size of an array is number of its numerical properties.
373 // We don't consider free form object properties here.
374 const uint n = array->getLength();
375 dict.insert(QStringLiteral("value"), qint64(n));
376 dict.insert(QStringLiteral("valueencoded"), QStringLiteral("itemcount"));
377 dict.insert(QStringLiteral("haschild"), qint64(n));
378 if (isExpanded(iname)) {
379 QJsonArray children;
380 for (uint i = 0; i < n; ++i) {
381 QV4::ReturnedValue v = array->get(i);
382 QV4::ScopedValue sval(scope, v);
383 collect(&children, iname, QString::number(i), *sval);
384 }
385 dict.insert(QStringLiteral("children"), children);
386 }
387 } else if (const QV4::Object *object = value.as<QV4::Object>()) {
388 QJsonArray children;
389 bool expanded = isExpanded(iname);
390 qint64 numProperties = 0;
392 QV4::ScopedProperty p(scope);
394 while (true) {
396 name = it.next(p, &attrs);
397 if (!name->isValid())
398 break;
399 if (name->isStringOrSymbol()) {
400 ++numProperties;
401 if (expanded) {
402 QV4::Value v = p.property->value;
403 collect(&children, iname, name->toQString(), v);
404 }
405 }
406 }
407 dict.insert(QStringLiteral("value"), numProperties);
408 dict.insert(QStringLiteral("valueencoded"), QStringLiteral("itemcount"));
409 dict.insert(QStringLiteral("haschild"), numProperties > 0);
410 if (expanded)
411 dict.insert(QStringLiteral("children"), children);
412 }
413 break;
415 dict.insert(QStringLiteral("value"), value.integerValue());
416 dict.insert(QStringLiteral("haschild"), false);
417 break;
418 default: // double
419 dict.insert(QStringLiteral("value"), value.doubleValue());
420 dict.insert(QStringLiteral("haschild"), false);
421 }
422
423 out->append(dict);
424}
425
426void NativeDebugger::handleVariables(QJsonObject *response, const QJsonObject &arguments)
427{
428 TRACE_PROTOCOL("Build variables");
429 QV4::CppStackFrame *frame = nullptr;
431 if (!frame) {
432 setError(response, QStringLiteral("No stack frame passed"));
433 return;
434 }
435 TRACE_PROTOCOL("Context: " << frame);
436
437 QV4::ExecutionEngine *engine = frame->v4Function->internalClass->engine;
438 if (!engine) {
439 setError(response, QStringLiteral("No execution engine passed"));
440 return;
441 }
442 TRACE_PROTOCOL("Engine: " << engine);
443
444 Collector collector(engine);
445 const QJsonArray expanded = arguments.value(QLatin1String("expanded")).toArray();
446 for (const QJsonValue ex : expanded)
447 collector.m_expanded.append(ex.toString());
448 TRACE_PROTOCOL("Expanded: " << collector.m_expanded);
449
451 QV4::Scope scope(engine);
452
453 QV4::ScopedValue thisObject(scope, frame->thisObject());
454 collector.collect(&output, QString(), QStringLiteral("this"), thisObject);
455 QV4::Scoped<QV4::CallContext> callContext(scope, frame->callContext());
456 if (callContext) {
457 QV4::Heap::InternalClass *ic = callContext->internalClass();
458 QV4::ScopedValue v(scope);
459 for (uint i = 0; i < ic->size; ++i) {
460 QV4::ScopedValue stringOrSymbol(scope, ic->keyAt(i));
461 QV4::ScopedString propName(scope, stringOrSymbol->toString(scope.engine));
462 v = callContext->getProperty(propName);
463 collector.collect(&output, QString(), propName->toQString(), v);
464 }
465 }
466
467 response->insert(QStringLiteral("variables"), output);
468}
469
470void NativeDebugger::handleExpressions(QJsonObject *response, const QJsonObject &arguments)
471{
472 TRACE_PROTOCOL("Evaluate expressions");
473 QV4::CppStackFrame *frame = nullptr;
475 if (!frame) {
476 setError(response, QStringLiteral("No stack frame passed"));
477 return;
478 }
479 TRACE_PROTOCOL("Context: " << executionContext);
480
481 QV4::ExecutionEngine *engine = frame->v4Function->internalClass->engine;
482 if (!engine) {
483 setError(response, QStringLiteral("No execution engine passed"));
484 return;
485 }
486 TRACE_PROTOCOL("Engines: " << engine << m_engine);
487
488 Collector collector(engine);
489 const QJsonArray expanded = arguments.value(QLatin1String("expanded")).toArray();
490 for (const QJsonValue ex : expanded)
491 collector.m_expanded.append(ex.toString());
492 TRACE_PROTOCOL("Expanded: " << collector.m_expanded);
493
495 QV4::Scope scope(engine);
496
497 const QJsonArray expressions = arguments.value(QLatin1String("expressions")).toArray();
498 for (const QJsonValue expr : expressions) {
499 QString expression = expr.toObject().value(QLatin1String("expression")).toString();
500 QString name = expr.toObject().value(QLatin1String("name")).toString();
501 TRACE_PROTOCOL("Evaluate expression: " << expression);
502 m_runningJob = true;
503
504 QV4::ScopedValue result(scope, evaluateExpression(expression));
505
506 m_runningJob = false;
507 if (result->isUndefined()) {
508 QJsonObject dict;
509 dict.insert(QStringLiteral("name"), name);
510 dict.insert(QStringLiteral("valueencoded"), QStringLiteral("undefined"));
511 output.append(dict);
512 } else if (result.ptr && result.ptr->rawValue()) {
513 collector.collect(&output, QString(), name, *result);
514 } else {
515 QJsonObject dict;
516 dict.insert(QStringLiteral("name"), name);
517 dict.insert(QStringLiteral("valueencoded"), QStringLiteral("notaccessible"));
518 output.append(dict);
519 }
520 TRACE_PROTOCOL("EXCEPTION: " << engine->hasException);
521 engine->hasException = false;
522 }
523
524 response->insert(QStringLiteral("expressions"), output);
525}
526
528{
529 for (int i = 0; i != m_breakPoints.size(); ++i) {
530 if (m_breakPoints.at(i).id == id) {
531 m_breakPoints.remove(i);
532 m_haveBreakPoints = !m_breakPoints.isEmpty();
533 return;
534 }
535 }
536}
537
539{
540 m_breakPoints[id].enabled = enabled;
541}
542
543void NativeDebugger::pause()
544{
545 m_pauseRequested = true;
546}
547
548void NativeDebugger::handleContinue(QJsonObject *response, Speed speed)
549{
550 Q_UNUSED(response);
551
552 if (!m_returnedValue.isUndefined())
553 m_returnedValue.set(m_engine, QV4::Encode::undefined());
554
555 m_currentFrame = m_engine->currentStackFrame;
556 m_stepping = speed;
557}
558
560{
561 if (m_runningJob) // do not re-enter when we're doing a job for the debugger.
562 return;
563
564 if (m_stepping == StepOver) {
565 if (m_currentFrame == m_engine->currentStackFrame)
566 pauseAndWait();
567 return;
568 }
569
570 if (m_stepping == StepIn) {
571 pauseAndWait();
572 return;
573 }
574
575 if (m_pauseRequested) { // Serve debugging requests from the agent
576 m_pauseRequested = false;
577 pauseAndWait();
578 return;
579 }
580
581 if (m_service->m_breakHandler->m_haveBreakPoints) {
582 if (QV4::Function *function = getFunction()) {
583 // lineNumber will be negative for Ret instructions, so those won't match
584 const int lineNumber = m_engine->currentStackFrame->lineNumber();
585 if (reallyHitTheBreakPoint(function, lineNumber))
586 pauseAndWait();
587 }
588 }
589}
590
592{
593 if (m_runningJob)
594 return;
595
596 if (m_stepping == StepIn) {
597 m_currentFrame = m_engine->currentStackFrame;
598 }
599}
600
602{
603 if (m_runningJob)
604 return;
605
606 if (m_stepping != NotStepping && m_currentFrame == m_engine->currentStackFrame) {
607 m_currentFrame = m_currentFrame->parentFrame();
608 m_stepping = StepOver;
609 m_returnedValue.set(m_engine, retVal);
610 }
611}
612
614{
615 if (!m_service->m_breakHandler->m_breakOnThrow)
616 return;
617
618 if (m_runningJob) // do not re-enter when we're doing a job for the debugger.
619 return;
620
622 // TODO: complete this!
623 event.insert(QStringLiteral("event"), QStringLiteral("exception"));
625}
626
627QV4::Function *NativeDebugger::getFunction() const
628{
629 if (m_engine->currentStackFrame)
630 return m_engine->currentStackFrame->v4Function;
631 else
632 return m_engine->globalCode;
633}
634
635void NativeDebugger::pauseAndWait()
636{
638
639 event.insert(QStringLiteral("event"), QStringLiteral("break"));
640 event.insert(QStringLiteral("language"), QStringLiteral("js"));
641 if (QV4::CppStackFrame *frame = m_engine->currentStackFrame) {
642 QV4::Function *function = frame->v4Function;
643 event.insert(QStringLiteral("file"), function->sourceFile());
644 int line = frame->lineNumber();
645 event.insert(QStringLiteral("line"), (line < 0 ? -line : line));
646 }
647
649}
650
651bool NativeDebugger::reallyHitTheBreakPoint(const QV4::Function *function, int lineNumber)
652{
653 for (int i = 0, n = m_service->m_breakHandler->m_breakPoints.size(); i != n; ++i) {
654 const BreakPoint &bp = m_service->m_breakHandler->m_breakPoints.at(i);
655 if (bp.lineNumber == lineNumber) {
656 const QString base = QUrl(function->sourceFile()).fileName();
657 if (bp.fileName.endsWith(base)) {
658 if (bp.condition.isEmpty() || checkCondition(bp.condition)) {
659 BreakPoint &mbp = m_service->m_breakHandler->m_breakPoints[i];
660 ++mbp.hitCount;
661 if (mbp.hitCount > mbp.ignoreCount)
662 return true;
663 }
664 }
665 }
666 }
667 return false;
668}
669
675
677{
678 delete m_breakHandler;
679}
680
682{
683 TRACE_PROTOCOL("Adding engine" << engine);
684 if (engine) {
686 TRACE_PROTOCOL("Adding execution engine" << ee);
687 if (ee) {
688 NativeDebugger *debugger = new NativeDebugger(this, ee);
689 if (state() == Enabled)
690 ee->setDebugger(debugger);
691 m_debuggers.append(QPointer<NativeDebugger>(debugger));
692 }
693 }
695}
696
698{
699 TRACE_PROTOCOL("Removing engine" << engine);
700 if (engine) {
701 QV4::ExecutionEngine *executionEngine = engine->handle();
702 const auto debuggersCopy = m_debuggers;
703 for (NativeDebugger *debugger : debuggersCopy) {
704 if (debugger->engine() == executionEngine)
705 m_debuggers.removeAll(debugger);
706 }
707 }
709}
710
712{
713 if (state == Enabled) {
714 for (NativeDebugger *debugger : std::as_const(m_debuggers)) {
715 QV4::ExecutionEngine *engine = debugger->engine();
716 if (!engine->debugger())
717 engine->setDebugger(debugger);
718 }
719 }
721}
722
724{
725 TRACE_PROTOCOL("Native message received: " << message);
727 QJsonObject response;
728 QJsonObject arguments = request.value(QLatin1String("arguments")).toObject();
729 QString cmd = request.value(QLatin1String("command")).toString();
730
731 if (cmd == QLatin1String("setbreakpoint")) {
732 m_breakHandler->handleSetBreakpoint(&response, arguments);
733 } else if (cmd == QLatin1String("removebreakpoint")) {
734 m_breakHandler->handleRemoveBreakpoint(&response, arguments);
735 } else if (cmd == QLatin1String("echo")) {
736 response.insert(QStringLiteral("result"), arguments);
737 } else {
738 for (NativeDebugger *debugger : std::as_const(m_debuggers))
739 if (debugger)
740 debugger->handleCommand(&response, cmd, arguments);
741 }
742 QJsonDocument doc;
743 doc.setObject(response);
745 TRACE_PROTOCOL("Sending synchronous response:" << ba.constData() << endl);
746 emit messageToClient(s_key, ba);
747}
748
750{
751 QJsonDocument doc;
752 doc.setObject(message);
754 TRACE_PROTOCOL("Sending asynchronous message:" << ba.constData() << endl);
755 emit messageToClient(s_key, ba);
756}
757
QVector< BreakPoint > m_breakPoints
void setBreakOnThrow(bool onoff)
void enableBreakPoint(int id, bool onoff)
void handleRemoveBreakpoint(QJsonObject *response, const QJsonObject &arguments)
void handleSetBreakpoint(QJsonObject *response, const QJsonObject &arguments)
Collector(QV4::ExecutionEngine *engine)
void collect(QJsonArray *output, const QString &parentIName, const QString &name, const QV4::Value &value)
QV4::ExecutionEngine * m_engine
bool isExpanded(const QString &iname) const
void maybeBreakAtInstruction() override
void aboutToThrow() override
void handleCommand(QJsonObject *response, const QString &cmd, const QJsonObject &arguments)
QV4::ExecutionEngine * engine() const
NativeDebugger(QQmlNativeDebugServiceImpl *service, QV4::ExecutionEngine *engine)
void leavingFunction(const QV4::ReturnedValue &retVal) override
void enteringFunction() override
bool pauseAtNextOpportunity() const override
void signalEmitted(const QString &signal)
\inmodule QtCore
Definition qbytearray.h:57
static QByteArray fromHex(const QByteArray &hexEncoded)
Returns a decoded copy of the hex encoded array hexEncoded.
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
Definition qbytearray.h:124
QByteArray toHex(char separator='\0') const
Returns a hex encoded copy of the byte array.
The QJSEngine class provides an environment for evaluating JavaScript code.
Definition qjsengine.h:26
QV4::ExecutionEngine * handle() const
Definition qjsengine.h:298
\inmodule QtCore\reentrant
Definition qjsonarray.h:18
\inmodule QtCore\reentrant
QByteArray toJson(JsonFormat format=Indented) const
void setObject(const QJsonObject &object)
Sets object as the main object of this document.
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(const QString &key, const QJsonValue &value)
Inserts a new item with the key key and a value of value.
\inmodule QtCore\reentrant
Definition qjsonvalue.h:25
T value(qsizetype i) const
Definition qlist.h:664
qsizetype removeAll(const AT &t)
Definition qlist.h:592
void append(parameter_type t)
Definition qlist.h:458
\inmodule QtCore
Definition qobject.h:103
const QByteArray & data() const
Returns a reference to the raw packet data.
Definition qpacket.cpp:77
virtual void stateAboutToBeChanged(State)
virtual void engineAboutToBeAdded(QJSEngine *engine)
virtual void engineAboutToBeRemoved(QJSEngine *engine)
void stateAboutToBeChanged(State state) override
void engineAboutToBeRemoved(QJSEngine *engine) override
void engineAboutToBeAdded(QJSEngine *engine) override
void emitAsynchronousMessageToClient(const QJsonObject &message)
void messageReceived(const QByteArray &message) override
\inmodule QtCore
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5871
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:192
static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:8084
\inmodule QtCore
Definition qurl.h:94
QString fileName(ComponentFormattingOptions options=FullyDecoded) const
Definition qurl.cpp:2497
void set(ExecutionEngine *engine, const Value &value)
int toInt(bool *ok=nullptr) const
Returns the variant as an int if the variant has userType() \l QMetaType::Int, \l QMetaType::Bool,...
QString toString() const
Returns the variant as a QString if the variant has a userType() including, but not limited to:
bool toBool() const
Returns the variant as a bool if the variant has userType() Bool.
EGLContext ctx
list append(new Employee("Blackpool", "Stephen"))
QSet< QString >::iterator it
auto signal
QList< QVariant > arguments
else opt state
[0]
Combined button and popup list for selecting options.
quint64 ReturnedValue
Scoped< String > ScopedString
static struct AttrInfo attrs[]
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
GLboolean GLboolean GLboolean b
GLsizei const GLfloat * v
[13]
GLboolean GLboolean GLboolean GLboolean a
[7]
GLboolean r
[2]
GLenum GLuint id
[7]
GLenum GLenum GLsizei const GLuint GLboolean enabled
GLfloat GLfloat f
GLenum type
GLuint GLsizei const GLchar * message
GLuint name
GLfloat n
struct _cl_event * event
GLenum array
GLint limit
GLuint64EXT * result
[6]
GLfloat GLfloat p
[1]
GLsizei const GLchar *const * string
[0]
Definition qopenglext.h:694
static bool isStrict(const QmlIR::Document *doc)
static void setError(QJsonObject *response, const QString &msg)
static QString encodeFrame(QV4::CppStackFrame *f)
#define TRACE_PROTOCOL(s)
size_t qHash(const BreakPoint &b, size_t seed=0) noexcept
bool operator==(const BreakPoint &a, const BreakPoint &b)
static void decodeFrame(const QString &f, QV4::CppStackFrame **frame)
static Q_CONSTINIT QBasicAtomicInteger< unsigned > seed
Definition qrandom.cpp:196
QLatin1StringView QLatin1String
Definition qstringfwd.h:31
#define QStringLiteral(str)
#define emit
#define Q_UNUSED(x)
size_t quintptr
Definition qtypes.h:167
unsigned int uint
Definition qtypes.h:34
long long qint64
Definition qtypes.h:60
static const uint base
Definition qurlidna.cpp:20
#define TRACE_PROTOCOL(x)
QT_BEGIN_NAMESPACE typedef uchar * output
#define enabled
QByteArray ba
[0]
QTextStream out(stdout)
[7]
QFrame frame
[0]
QNetworkRequest request(url)
char * toString(const MyType &t)
[31]
QJSEngine engine
[0]
\inmodule QtCore \reentrant
Definition qchar.h:18
ReturnedValue thisObject() const
CppStackFrame * parentFrame() const
static constexpr ReturnedValue undefined()
CppStackFrame * currentStackFrame
ExecutionContext * scriptContext() const
void setDebugger(Debugging::Debugger *)
ExecutionContext * currentContext() const
Pointer< InternalClass *, 0 > internalClass
Definition qv4heap_p.h:63
Q_QML_EXPORT ReturnedValue keyAt(uint index) const
static ReturnedValue call(ExecutionEngine *, const Value &)
QV4_NEARLY_ALWAYS_INLINE constexpr quint32 value() const
const T * as() const
Definition qv4value_p.h:132