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
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
16#include <QtCore/qpointer.h>
17
19
23
25 const QString &script) :
26 engine(engine), frameNr(frameNr), context(context), script(script),
27 resultIsException(false)
28{}
29
31{
32 QV4::Scope scope(engine);
33
35 : engine->scriptContext());
36
38
39 for (int i = 0; frame && i < frameNr; ++i)
40 frame = frame->parentFrame();
41 if (frameNr > 0 && frame)
42 ctx = frame->context();
43
44 if (context >= 0) {
45 QObject *forId = QQmlDebugService::objectForId(context);
46 QQmlContext *extraContext = qmlContext(forId);
47 if (extraContext)
48 ctx = QV4::QmlContext::create(ctx, QQmlContextData::get(extraContext), forId);
49 } else if (frameNr < 0) { // Use QML context if available
50 QQmlEngine *qmlEngine = engine->qmlEngine();
51 if (qmlEngine) {
52 QQmlContext *qmlRootContext = qmlEngine->rootContext();
53 QQmlContextPrivate *ctxtPriv = QQmlContextPrivate::get(qmlRootContext);
54
55 QV4::ScopedObject withContext(scope, engine->newObject());
56 QV4::ScopedString k(scope);
57 QV4::ScopedValue v(scope);
58 const QList<QPointer<QObject>> instances = ctxtPriv->instances();
59 for (const QPointer<QObject> &object : instances) {
60 if (QQmlContext *context = qmlContext(object.data())) {
61 if (QQmlRefPointer<QQmlContextData> cdata = QQmlContextData::get(context)) {
62 v = QV4::QObjectWrapper::wrap(engine, object);
63 k = engine->newString(cdata->findObjectId(object));
64 withContext->put(k, v);
65 }
66 }
67 }
68 if (!engine->qmlContext())
69 ctx = QV4::QmlContext::create(ctx, QQmlContextData::get(qmlRootContext), nullptr);
70 }
71 }
72
74 if (const QV4::Function *function = frame ? frame->v4Function : engine->globalCode)
75 script.strictMode = function->isStrict();
76
77 // In order for property lookups in QML to work, we need to disable fast v4 lookups. That
78 // is a side-effect of inheritContext.
79 script.inheritContext = true;
80 script.parse();
82 if (!scope.hasException()) {
83 if (frame) {
84 QV4::ScopedValue thisObject(scope, frame->thisObject());
85 result = script.run(thisObject);
86 } else {
87 result = script.run();
88 }
89 }
90 if (scope.hasException()) {
91 result = scope.engine->catchException();
92 resultIsException = true;
93 }
95}
96
98{
99 return resultIsException;
100}
101
102BacktraceJob::BacktraceJob(QV4DataCollector *collector, int fromFrame, int toFrame) :
103 CollectJob(collector), fromFrame(fromFrame), toFrame(toFrame)
104{
105}
106
108{
109 QJsonArray frameArray;
110 QVector<QV4::StackFrame> frames = collector->engine()->stackTrace(toFrame);
111 for (int i = fromFrame; i < toFrame && i < frames.size(); ++i)
112 frameArray.push_back(collector->buildFrame(frames[i], i));
113 if (frameArray.isEmpty()) {
114 result.insert(QStringLiteral("totalFrames"), 0);
115 } else {
116 result.insert(QStringLiteral("fromFrame"), fromFrame);
117 result.insert(QStringLiteral("toFrame"), fromFrame + frameArray.size());
118 result.insert(QStringLiteral("frames"), frameArray);
119 }
120}
121
122FrameJob::FrameJob(QV4DataCollector *collector, int frameNr) :
123 CollectJob(collector), frameNr(frameNr), success(false)
124{
125}
126
128{
129 QVector<QV4::StackFrame> frames = collector->engine()->stackTrace(frameNr + 1);
130 if (frameNr >= frames.size()) {
131 success = false;
132 } else {
133 result = collector->buildFrame(frames[frameNr], frameNr);
134 success = true;
135 }
136}
137
139{
140 return success;
141}
142
143ScopeJob::ScopeJob(QV4DataCollector *collector, int frameNr, int scopeNr) :
144 CollectJob(collector), frameNr(frameNr), scopeNr(scopeNr), success(false)
145{
146}
147
149{
151 success = collector->collectScope(&object, frameNr, scopeNr);
152
153 if (success) {
154 QVector<QV4::Heap::ExecutionContext::ContextType> scopeTypes =
155 collector->getScopeTypes(frameNr);
156 result[QLatin1String("type")] = QV4DataCollector::encodeScopeType(scopeTypes[scopeNr]);
157 } else {
158 result[QLatin1String("type")] = -1;
159 }
160 result[QLatin1String("index")] = scopeNr;
161 result[QLatin1String("frameIndex")] = frameNr;
162 result[QLatin1String("object")] = object;
163}
164
166{
167 return success;
168}
169
171 CollectJob(collector), handles(handles) {}
172
174{
175 // Open a QML context if we don't have one, yet. We might run into QML objects when looking up
176 // refs and that will crash without a valid QML context. Mind that engine->qmlContext() is only
177 // set if the engine is currently executing QML code.
178 QScopedPointer<QObject> scopeObject;
180 QV4::Scope scope(engine);
181 QV4::Heap::ExecutionContext *qmlContext = engine->qmlContext();
182 if (engine->qmlEngine() && !qmlContext) {
183 scopeObject.reset(new QObject);
184 qmlContext = QV4::QmlContext::create(engine->currentContext(),
185 QQmlContextData::get(engine->qmlEngine()->rootContext()),
186 scopeObject.data());
187 }
189 QV4::ScopedStackFrame frame(scope, scopedContext);
190 for (const QJsonValue handle : handles) {
192 if (!collector->isValidRef(ref)) {
193 exception = QString::fromLatin1("Invalid Ref: %1").arg(ref);
194 break;
195 }
197 }
198}
199
201{
202 return exception;
203}
204
206 int context, const QString &expression,
207 QV4DataCollector *collector) :
208 JavaScriptJob(engine, frameNr, context, expression), collector(collector)
209{
210}
211
213{
214 if (hasExeption())
215 exception = value->toQStringNoThrow();
216 result = collector->lookupRef(collector->addValueRef(value));
217}
218
220{
221 return exception;
222}
223
225{
226 return result;
227}
228
232
234{
235 const auto compilationUnits = engine->compilationUnits();
236 for (const auto &unit : compilationUnits) {
237 QString fileName = unit->fileName();
238 if (!fileName.isEmpty())
240 }
241}
242
244{
245 return sources;
246}
247
249 JavaScriptJob(engine, /*frameNr*/-1, /*context*/ -1, script), result(false)
250{}
251
253{
254 this->result = result->toBoolean();
255}
256
258{
259 return result;
260}
261
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
\inmodule QtCore\reentrant
Definition qjsonobject.h:20
\inmodule QtCore\reentrant
Definition qjsonvalue.h:25
void push_back(parameter_type t)
Definition qlist.h:675
\inmodule QtCore
Definition qobject.h:103
static QQmlRefPointer< QQmlContextData > get(QQmlContext *context)
static QQmlContextPrivate * get(QQmlContext *context)
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
\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
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
QString & append(QChar c)
Definition qstring.cpp:3252
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.
Scoped< String > ScopedString
Scoped< ExecutionContext > ScopedContext
static void * context
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:80
QQmlContext * qmlContext(const QObject *obj)
Definition qqml.cpp:75
QLatin1StringView QLatin1String
Definition qstringfwd.h:31
#define QStringLiteral(str)
QFrame frame
[0]
QJSEngine engine
[0]
CppStackFrame * currentStackFrame
QMultiHash< QUrl, QQmlRefPointer< ExecutableCompilationUnit > > compilationUnits() const
Heap::Object * newObject()
Heap::String * newString(char16_t c)
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:44
bool toBoolean() const
Definition qv4value_p.h:97