summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2021-05-03 19:23:49 +0200
committerUlf Hermann <ulf.hermann@qt.io>2021-05-05 14:15:01 +0200
commit8e400a48285e58c938fe24367251cc04c1d00985 (patch)
treedacd67ffaa3b20e542388e5614f9a75a9cd2dd73
parentafec4d5bb0440e290128250a176a42c459cc5b52 (diff)
V4 Debugger: Collect locals also from block scopes
Block scopes can contain "const" and "let" members. Fixes: QTBUG-92224 Change-Id: Ie13d7d573e2759c510e1ea48c6edc68a095f40a0 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> (cherry picked from commit 051dd3178bc4c9214af60c69cecfc2c28f13174d)
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp3
-rw-r--r--tests/auto/qml/debugger/qqmldebugjs/data/letConstLocals.qml16
-rw-r--r--tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp59
-rw-r--r--tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp12
4 files changed, 87 insertions, 3 deletions
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp
index d3134e0727..8758e3f004 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp
+++ b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp
@@ -216,7 +216,8 @@ bool QV4DataCollector::collectScope(QJsonObject *dict, int frameNr, int scopeNr)
return false;
QV4::ScopedObject scopeObject(scope, engine()->newObject());
- if (ctxt->d()->type == QV4::Heap::ExecutionContext::Type_CallContext) {
+ if (ctxt->d()->type == QV4::Heap::ExecutionContext::Type_CallContext ||
+ ctxt->d()->type == QV4::Heap::ExecutionContext::Type_BlockContext) {
QStringList names;
Refs collectedRefs;
diff --git a/tests/auto/qml/debugger/qqmldebugjs/data/letConstLocals.qml b/tests/auto/qml/debugger/qqmldebugjs/data/letConstLocals.qml
new file mode 100644
index 0000000000..1715992490
--- /dev/null
+++ b/tests/auto/qml/debugger/qqmldebugjs/data/letConstLocals.qml
@@ -0,0 +1,16 @@
+import QtQml 2.15
+
+Timer {
+ Component.onCompleted: {
+ var a = 97
+ var b = 98
+ var c = 99
+ let d = 100
+ const e = 101
+ console.log("onClicked") // Set breakpoint
+ running = true
+ }
+
+ interval: 0
+ onTriggered: Qt.quit()
+}
diff --git a/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp b/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp
index a07567aa7d..66c5f0dbf1 100644
--- a/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp
+++ b/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp
@@ -66,6 +66,7 @@ const char *BREAKPOINTRELOCATION_QMLFILE = "breakpointRelocation.qml";
const char *ENCODEQMLSCOPE_QMLFILE = "encodeQmlScope.qml";
const char *BREAKONANCHOR_QMLFILE = "breakOnAnchor.qml";
const char *BREAKPOINTIDS_QMLFILE = "breakPointIds.qml";
+const char *LETCONSTLOCALS_QMLFILE = "letConstLocals.qml";
#undef QVERIFY
#define QVERIFY(statement) \
@@ -158,6 +159,7 @@ private slots:
void breakOnAnchor();
void breakPointIds();
+ void letConstLocals();
private:
ConnectResult init(bool qmlscene, const QString &qmlFile = QString(TEST_QMLFILE),
@@ -1050,6 +1052,63 @@ void tst_QQmlDebugJS::breakPointIds()
QCOMPARE(breaks, 6);
}
+void tst_QQmlDebugJS::letConstLocals()
+{
+ QString file(LETCONSTLOCALS_QMLFILE);
+ QCOMPARE(init(true, file), ConnectSuccess);
+
+ QObject::connect(m_client.data(), &QV4DebugClient::stopped, this, [&]() {
+ m_client->frame();
+ });
+
+ int numScopes = 0;
+ QString expectedMembers = QStringLiteral("abcde");
+ QObject::connect(m_client.data(), &QV4DebugClient::result, this, [&]() {
+ const auto value = m_client->response();
+ if (value.command == QStringLiteral("frame")) {
+ const auto scopes = value.body.toObject().value(QStringLiteral("scopes")).toArray();
+ for (const auto &scope : scopes) {
+ const auto scopeObject = scope.toObject();
+ const int type = scopeObject.value("type").toInt();
+ if (type == 1 || type == 4) {
+ m_client->scope(scopeObject.value("index").toInt());
+ ++numScopes;
+ }
+ }
+ QVERIFY(numScopes > 0);
+ } else if (value.command == QStringLiteral("scope")) {
+ const auto props = value.body.toObject().value(QStringLiteral("object")).toObject()
+ .value(QStringLiteral("properties")).toArray();
+ for (const auto &prop : props) {
+ const auto propObj = prop.toObject();
+ const QString name = propObj.value(QStringLiteral("name")).toString();
+ if (name == QStringLiteral("onCompleted"))
+ continue;
+ QVERIFY(name.length() == 1);
+ auto i = expectedMembers.indexOf(name.at(0));
+ QVERIFY(i != -1);
+ expectedMembers.remove(i, 1);
+ QCOMPARE(propObj.value(QStringLiteral("type")).toString(),
+ QStringLiteral("number"));
+ QCOMPARE(propObj.value(QStringLiteral("value")).toInt(),
+ int(name.at(0).toLatin1()));
+ }
+ if (--numScopes == 0) {
+ QVERIFY(expectedMembers.isEmpty());
+ m_client->continueDebugging(QV4DebugClient::Continue);
+ }
+ }
+ });
+
+ setBreakPoint(file, 10, true);
+
+ QTRY_COMPARE(m_process->state(), QProcess::Running);
+ m_client->connect();
+
+ QTRY_COMPARE(m_process->state(), QProcess::NotRunning);
+ QCOMPARE(m_process->exitStatus(), QProcess::NormalExit);
+}
+
QList<QQmlDebugClient *> tst_QQmlDebugJS::createClients()
{
m_client = new QV4DebugClient(m_connection);
diff --git a/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp b/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp
index 8419b6a31c..33e644d6f2 100644
--- a/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp
+++ b/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp
@@ -575,21 +575,29 @@ void tst_qv4debugger::readLocals()
QString script =
"var f = function(a, b) {\n"
" var c = a + b\n"
+ " let e = 'jaja'\n"
+ " const ff = 'nenene'\n"
" var d = a - b\n" // breakpoint, c should be set, d should be undefined
" return c === d\n"
"}\n"
"f(1, 2, 3);\n";
- debugger()->addBreakPoint("readLocals", 3);
+ debugger()->addBreakPoint("readLocals", 5);
evaluateJavaScript(script, "readLocals");
QVERIFY(m_debuggerAgent->m_wasPaused);
QVERIFY(m_debuggerAgent->m_capturedScope.size() > 1);
const TestAgent::NamedRefs &frame0 = m_debuggerAgent->m_capturedScope.at(0);
- QCOMPARE(frame0.size(), 5); // locals and parameters
+ QCOMPARE(frame0.size(), 7); // locals and parameters
QVERIFY(frame0.contains("c"));
QCOMPARE(frame0.type("c"), QStringLiteral("number"));
QCOMPARE(frame0.value("c").toDouble(), 3.0);
QVERIFY(frame0.contains("d"));
QCOMPARE(frame0.type("d"), QStringLiteral("undefined"));
+ QVERIFY(frame0.contains("e"));
+ QCOMPARE(frame0.type("e"), QStringLiteral("string"));
+ QCOMPARE(frame0.value("e").toString(), QStringLiteral("jaja"));
+ QVERIFY(frame0.contains("ff"));
+ QCOMPARE(frame0.type("ff"), QStringLiteral("string"));
+ QCOMPARE(frame0.value("ff").toString(), QStringLiteral("nenene"));
}
void tst_qv4debugger::readObject()