diff options
author | Semih Yavuz <semih.yavuz@qt.io> | 2022-11-17 14:36:47 +0100 |
---|---|---|
committer | Semih Yavuz <semih.yavuz@qt.io> | 2022-11-25 15:47:00 +0000 |
commit | fe32f58008f89b7174e9f41a781e6fba5799c026 (patch) | |
tree | 3ebda2cae678b0382ede57d0d70a55ce9563a27b | |
parent | d9dfe91417e87db59825500d7b2791ad4d7516b6 (diff) |
Debugger: Initialize scoped context correctly
Initialize scopedContext with valid qmlContext. Otherwise debugger
crashes on attempt to lookup an object that includes a v4Function
property
Pick-to: 6.2 6.4
Fixes: QTBUG-107607
Change-Id: Iea59bdf9d379a5415abe1767f76f851978b1be3f
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
5 files changed, 97 insertions, 4 deletions
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.cpp index 383668833b..6ed24f29d1 100644 --- a/src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.cpp +++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.cpp @@ -175,8 +175,8 @@ void ValueLookupJob::run() QScopedPointer<QObject> scopeObject; QV4::ExecutionEngine *engine = collector->engine(); QV4::Scope scope(engine); - QV4::Heap::ExecutionContext *qmlContext = nullptr; - if (engine->qmlEngine() && !engine->qmlContext()) { + QV4::Heap::ExecutionContext *qmlContext = engine->qmlContext(); + if (engine->qmlEngine() && !qmlContext) { scopeObject.reset(new QObject); qmlContext = QV4::QmlContext::create(engine->currentContext(), QQmlContextData::get(engine->qmlEngine()->rootContext()), diff --git a/tests/auto/qml/debugger/qv4debugger/CMakeLists.txt b/tests/auto/qml/debugger/qv4debugger/CMakeLists.txt index 4d45ecdd1a..519acaedff 100644 --- a/tests/auto/qml/debugger/qv4debugger/CMakeLists.txt +++ b/tests/auto/qml/debugger/qv4debugger/CMakeLists.txt @@ -13,6 +13,17 @@ file(GLOB_RECURSE test_data_glob data/*) list(APPEND test_data ${test_data_glob}) +qt_add_library(testCppTypes STATIC) +qt_autogen_tools_initial_setup(testCppTypes) +target_link_libraries(testCppTypes PRIVATE Qt::Qml Qt::QmlPrivate Qt::Quick) + +qt6_add_qml_module(testCppTypes + VERSION 1.0 + URI TestTypes + SOURCES + commontypes.h +) + qt_internal_add_test(tst_qv4debugger SOURCES ../../../../../src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp ../../../../../src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h @@ -28,6 +39,7 @@ qt_internal_add_test(tst_qv4debugger Qt::Network Qt::QmlPrivate Qt::QuickTestUtilsPrivate + testCppTypesplugin TESTDATA ${test_data} ) diff --git a/tests/auto/qml/debugger/qv4debugger/commontypes.h b/tests/auto/qml/debugger/qv4debugger/commontypes.h new file mode 100644 index 0000000000..01b2125ae3 --- /dev/null +++ b/tests/auto/qml/debugger/qv4debugger/commontypes.h @@ -0,0 +1,20 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#ifndef COMMONTYPES_H +#define COMMONTYPES_H + +#include <QtQuick/qquickitem.h> +#include <QtQml/qqmlregistration.h> +#include <QtQml/private/qv4engine_p.h> + +class MyType : public QQuickItem +{ + Q_OBJECT + QML_ELEMENT +public: + MyType(QQuickItem *parent = nullptr) : QQuickItem(parent) {} + Q_INVOKABLE void name(QQmlV4Function*) const {} +}; + +#endif // COMMONTYPES_H diff --git a/tests/auto/qml/debugger/qv4debugger/data/qtbug_107607.qml b/tests/auto/qml/debugger/qv4debugger/data/qtbug_107607.qml new file mode 100644 index 0000000000..a7758de8a8 --- /dev/null +++ b/tests/auto/qml/debugger/qv4debugger/data/qtbug_107607.qml @@ -0,0 +1,10 @@ +import QtQuick +import TestTypes +MyType { + objectName: "patron" + Item { + Component.onCompleted: { + console.log("Hallo Welt"); + } + } +}
\ No newline at end of file diff --git a/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp b/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp index cdb7b1dee0..6f147446f0 100644 --- a/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp +++ b/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp @@ -16,10 +16,13 @@ #include <private/qv4string_p.h> #include <private/qqmlbuiltinfunctions_p.h> #include <private/qqmldebugservice_p.h> +#include <QtQml/qqmlextensionplugin.h> using namespace QV4; using namespace QV4::Debugging; +Q_IMPORT_QML_PLUGIN(TestTypesPlugin); + typedef QV4::ReturnedValue (*InjectedFunction)(const FunctionObject *b, const QV4::Value *, const QV4::Value *, int); Q_DECLARE_METATYPE(InjectedFunction) @@ -176,7 +179,15 @@ public slots: ExpressionEvalJob job(debugger->engine(), request.frameNr, request.context, request.expression, &collector); debugger->runInEngine(&job); - m_expressionResults << job.returnValue(); + const QJsonObject& result = job.returnValue(); + m_expressionResults << result; + + if (request.shouldLookup) { + QJsonArray handles {result.value("handle").toInt()}; + ValueLookupJob job(handles, &collector); + debugger->runInEngine(&job); + m_lookupResults << job.returnValue(); + } } if (m_captureContextInfo) @@ -249,10 +260,14 @@ public: QString expression; int frameNr; int context; + bool shouldLookup = false; }; + + QVector<ExpressionRequest> m_expressionRequests; QV4Debugger::Speed m_resumeSpeed; QList<QJsonObject> m_expressionResults; + QList<QJsonObject> m_lookupResults; QV4Debugger *m_debugger; // Utility methods: @@ -306,7 +321,7 @@ private slots: void readThis(); void signalParameters(); - + void debuggerNoCrash(); private: QV4Debugger *debugger() const { @@ -916,6 +931,42 @@ void tst_qv4debugger::signalParameters() QCOMPARE(obj->property("resultCallbackExternal").toString(), QLatin1String("unset")); } +void tst_qv4debugger::debuggerNoCrash() +{ + QQmlEngine engine; + QV4::ExecutionEngine *v4 = engine.handle(); + QPointer<QV4Debugger> v4Debugger = new QV4Debugger(v4); + v4->setDebugger(v4Debugger.data()); + + QScopedPointer<QThread> debugThread(new QThread); + debugThread->start(); + QScopedPointer<TestAgent> debuggerAgent(new TestAgent(v4)); + debuggerAgent->addDebugger(v4Debugger); + debuggerAgent->moveToThread(debugThread.data()); + + const QString qmlFileName("qtbug_107607.qml"); + const QString qmlFilePath(testFile(qmlFileName)); + QQmlComponent component(&engine, qmlFilePath); + + TestAgent::ExpressionRequest request; + request.expression = "this.parent"; + request.frameNr = 0; + request.context = -1; + request.shouldLookup = true; + debuggerAgent->m_expressionRequests << request; + v4Debugger->addBreakPoint(qmlFileName, 7); + + QScopedPointer<QObject> obj(component.create()); + + QVERIFY(debuggerAgent->m_lookupResults.size() > 0); + const QJsonObject result = debuggerAgent->m_lookupResults[0]; + const QJsonArray properties = result["0"].toObject().value("properties").toArray(); + QCOMPARE(properties[0].toObject().value("value").toString(), QStringLiteral("patron")); + + debugThread->quit(); + debugThread->wait(); +} + tst_qv4debugger::tst_qv4debugger() : QQmlDataTest(QT_QMLTEST_DATADIR) { } QTEST_MAIN(tst_qv4debugger) |