Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qv4debugjob.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
4#include "qv4debugjob.h"
5
6#include <private/qqmlcontext_p.h>
7#include <private/qqmldebugservice_p.h>
8#include <private/qv4jscall_p.h>
9#include <private/qv4qmlcontext_p.h>
10#include <private/qv4qobjectwrapper_p.h>
11#include <private/qv4script_p.h>
12#include <private/qv4stackframe_p.h>
13
14#include <QtQml/qqmlengine.h>
15
17
19{
20}
21
23 const QString &script) :
24 engine(engine), frameNr(frameNr), context(context), script(script),
25 resultIsException(false)
26{}
27
29{
30 QV4::Scope scope(engine);
31
33 : engine->scriptContext());
34
36
37 for (int i = 0; frame && i < frameNr; ++i)
38 frame = frame->parentFrame();
39 if (frameNr > 0 && frame)
40 ctx = frame->context();
41
42 if (context >= 0) {
43 QObject *forId = QQmlDebugService::objectForId(context);
44 QQmlContext *extraContext = qmlContext(forId);
45 if (extraContext)
46 ctx = QV4::QmlContext::create(ctx, QQmlContextData::get(extraContext), forId);
47 } else if (frameNr < 0) { // Use QML context if available
48 QQmlEngine *qmlEngine = engine->qmlEngine();
49 if (qmlEngine) {
50 QQmlContext *qmlRootContext = qmlEngine->rootContext();
51 QQmlContextPrivate *ctxtPriv = QQmlContextPrivate::get(qmlRootContext);
52
53 QV4::ScopedObject withContext(scope, engine->newObject());
54 QV4::ScopedString k(scope);
55 QV4::ScopedValue v(scope);
56 const QList<QPointer<QObject>> instances = ctxtPriv->instances();
57 for (const QPointer<QObject> &object : instances) {
58 if (QQmlContext *context = qmlContext(object.data())) {
60 v = QV4::QObjectWrapper::wrap(engine, object);
61 k = engine->newString(cdata->findObjectId(object));
62 withContext->put(k, v);
63 }
64 }
65 }
66 if (!engine->qmlContext())
67 ctx = QV4::QmlContext::create(ctx, QQmlContextData::get(qmlRootContext), nullptr);
68 }
69 }
70
72 if (const QV4::Function *function = frame ? frame->v4Function : engine->globalCode)
73 script.strictMode = function->isStrict();
74
75 // In order for property lookups in QML to work, we need to disable fast v4 lookups. That
76 // is a side-effect of inheritContext.
77 script.inheritContext = true;
78 script.parse();
80 if (!scope.hasException()) {
81 if (frame) {
82 QV4::ScopedValue thisObject(scope, frame->thisObject());
83 result = script.run(thisObject);
84 } else {
85 result = script.run();
86 }
87 }
88 if (scope.hasException()) {
89 result = scope.engine->catchException();
90 resultIsException = true;
91 }
93}
94
96{
97 return resultIsException;
98}
99
100BacktraceJob::BacktraceJob(QV4DataCollector *collector, int fromFrame, int toFrame) :
101 CollectJob(collector), fromFrame(fromFrame), toFrame(toFrame)
102{
103}
104
106{
107 QJsonArray frameArray;
109 for (int i = fromFrame; i < toFrame && i < frames.size(); ++i)
110 frameArray.push_back(collector->buildFrame(frames[i], i));
111 if (frameArray.isEmpty()) {
112 result.insert(QStringLiteral("totalFrames"), 0);
113 } else {
114 result.insert(QStringLiteral("fromFrame"), fromFrame);
115 result.insert(QStringLiteral("toFrame"), fromFrame + frameArray.size());
116 result.insert(QStringLiteral("frames"), frameArray);
117 }
118}
119
120FrameJob::FrameJob(QV4DataCollector *collector, int frameNr) :
121 CollectJob(collector), frameNr(frameNr), success(false)
122{
123}
124
126{
127 QVector<QV4::StackFrame> frames = collector->engine()->stackTrace(frameNr + 1);
128 if (frameNr >= frames.size()) {
129 success = false;
130 } else {
131 result = collector->buildFrame(frames[frameNr], frameNr);
132 success = true;
133 }
134}
135
137{
138 return success;
139}
140
141ScopeJob::ScopeJob(QV4DataCollector *collector, int frameNr, int scopeNr) :
142 CollectJob(collector), frameNr(frameNr), scopeNr(scopeNr), success(false)
143{
144}
145
147{
149 success = collector->collectScope(&object, frameNr, scopeNr);
150
151 if (success) {
153 collector->getScopeTypes(frameNr);
154 result[QLatin1String("type")] = QV4DataCollector::encodeScopeType(scopeTypes[scopeNr]);
155 } else {
156 result[QLatin1String("type")] = -1;
157 }
158 result[QLatin1String("index")] = scopeNr;
159 result[QLatin1String("frameIndex")] = frameNr;
160 result[QLatin1String("object")] = object;
161}
162
164{
165 return success;
166}
167
169 CollectJob(collector), handles(handles) {}
170
172{
173 // Open a QML context if we don't have one, yet. We might run into QML objects when looking up
174 // refs and that will crash without a valid QML context. Mind that engine->qmlContext() is only
175 // set if the engine is currently executing QML code.
176 QScopedPointer<QObject> scopeObject;
178 QV4::Scope scope(engine);
179 QV4::Heap::ExecutionContext *qmlContext = engine->qmlContext();
180 if (engine->qmlEngine() && !qmlContext) {
181 scopeObject.reset(new QObject);
182 qmlContext = QV4::QmlContext::create(engine->currentContext(),
183 QQmlContextData::get(engine->qmlEngine()->rootContext()),
184 scopeObject.data());
185 }
187 QV4::ScopedStackFrame frame(scope, scopedContext);
188 for (const QJsonValue handle : handles) {
190 if (!collector->isValidRef(ref)) {
191 exception = QString::fromLatin1("Invalid Ref: %1").arg(ref);
192 break;
193 }
195 }
196}
197
199{
200 return exception;
201}
202
204 int context, const QString &expression,
205 QV4DataCollector *collector) :
206 JavaScriptJob(engine, frameNr, context, expression), collector(collector)
207{
208}
209
211{
212 if (hasExeption())
213 exception = value->toQStringNoThrow();
214 result = collector->lookupRef(collector->addValueRef(value));
215}
216
218{
219 return exception;
220}
221
223{
224 return result;
225}
226
228 : engine(engine)
229{}
230
232{
234 QString fileName = unit->fileName();
235 if (!fileName.isEmpty())
236 sources.append(fileName);
237 }
238}
239
241{
242 return sources;
243}
244
246 JavaScriptJob(engine, /*frameNr*/-1, /*context*/ -1, script), result(false)
247{}
248
250{
251 this->result = result->toBoolean();
252}
253
255{
256 return result;
257}
258
BacktraceJob(QV4DataCollector *collector, int fromFrame, int toFrame)
void run() override
QV4DataCollector * collector
Definition qv4debugjob.h:43
EvalJob(QV4::ExecutionEngine *engine, const QString &script)
bool resultAsBoolean() const
void handleResult(QV4::ScopedValue &result) override
const QJsonObject & returnValue() const
ExpressionEvalJob(QV4::ExecutionEngine *engine, int frameNr, int context, const QString &expression, QV4DataCollector *collector)
void handleResult(QV4::ScopedValue &value) override
const QString & exceptionMessage() const
void run() override
bool wasSuccessful() const
FrameJob(QV4DataCollector *collector, int frameNr)
const QStringList & result() const
void run() override
GatherSourcesJob(QV4::ExecutionEngine *engine)
bool hasExeption() const
virtual void handleResult(QV4::ScopedValue &result)=0
JavaScriptJob(QV4::ExecutionEngine *engine, int frameNr, int context, const QString &script)
void run() override
\inmodule QtCore\reentrant
Definition qjsonarray.h:18
bool isEmpty() const
Returns true if the object is empty.
qsizetype size() const
Returns the number of values stored in the array.
void push_back(const QJsonValue &t)
This function is provided for STL compatibility.
Definition qjsonarray.h:206
\inmodule QtCore\reentrant
Definition qjsonobject.h:20
\inmodule QtCore\reentrant
Definition qjsonvalue.h:24
Definition qlist.h:74
qsizetype size() const noexcept
Definition qlist.h:386
\inmodule QtCore
Definition qobject.h:90
\inmodule QtCore
Definition qpointer.h:18
static QQmlRefPointer< QQmlContextData > get(QQmlContext *context)
static QQmlContextPrivate * get(QQmlContext *context)
QList< QPointer< QObject > > instances() const
The QQmlContext class defines a context within a QML engine.
Definition qqmlcontext.h:25
static QObject * objectForId(int id)
The QQmlEngine class provides an environment for instantiating QML components.
Definition qqmlengine.h:57
QQmlContext * rootContext() const
Returns the engine's root context.
\inmodule QtCore
T * data() const noexcept
Returns the value of the pointer referenced by this object.
void reset(T *other=nullptr) noexcept(noexcept(Cleanup::cleanup(std::declval< T * >())))
Deletes the existing object it is pointing to (if any), and sets its pointer to other.
\inmodule QtCore
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5710
QString arg(qlonglong a, int fieldwidth=0, int base=10, QChar fillChar=u' ') const
Definition qstring.cpp:8606
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:7822
bool collectScope(QJsonObject *dict, int frameNr, int scopeNr)
bool isValidRef(Ref ref) const
Ref addValueRef(const QV4::ScopedValue &value)
static int encodeScopeType(QV4::Heap::ExecutionContext::ContextType scopeType)
QJsonObject lookupRef(Ref ref)
QV4::ExecutionEngine * engine() const
QVector< QV4::Heap::ExecutionContext::ContextType > getScopeTypes(int frame)
QJsonObject buildFrame(const QV4::StackFrame &stackFrame, int frameNr)
virtual ~QV4DebugJob()
bool wasSuccessful() const
ScopeJob(QV4DataCollector *collector, int frameNr, int scopeNr)
void run() override
const QString & exceptionMessage() const
ValueLookupJob(const QJsonArray &handles, QV4DataCollector *collector)
void run() override
EGLContext ctx
Combined button and popup list for selecting options.
static void * context
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction function
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
GLsizei const GLfloat * v
[13]
GLuint64 GLenum void * handle
GLuint object
[3]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLint ref
GLsizei GLenum * sources
GLuint64EXT * result
[6]
QQmlEngine * qmlEngine(const QObject *obj)
Definition qqml.cpp:76
QQmlContext * qmlContext(const QObject *obj)
Definition qqml.cpp:71
QLatin1StringView QLatin1String
Definition qstringfwd.h:31
#define QStringLiteral(str)
QFrame frame
[0]
QJSEngine engine
[0]
CppStackFrame * currentStackFrame
Heap::String * newString(const QString &s=QString())
Heap::Object * newObject()
QIntrusiveList< ExecutableCompilationUnit, &ExecutableCompilationUnit::nextCompilationUnit > compilationUnits
ExecutionContext * scriptContext() const
StackTrace stackTrace(int frameLimit=-1) const
QQmlEngine * qmlEngine() const
static Heap::ExecutionContext * qmlContext(Heap::ExecutionContext *ctx)
ReturnedValue catchException(StackTrace *trace=nullptr)
ExecutionContext * currentContext() const
static ReturnedValue wrap(ExecutionEngine *engine, QObject *object)
static Heap::QmlContext * create(QV4::ExecutionContext *parent, QQmlRefPointer< QQmlContextData > context, QObject *scopeObject)
bool hasException() const
ExecutionEngine * engine
ReturnedValue run(const QV4::Value *thisObject=nullptr)
bool strictMode
Definition qv4script_p.h:54
bool inheritContext
Definition qv4script_p.h:55
void parse()
Definition qv4script.cpp:43
bool toBoolean() const
Definition qv4value_p.h:97