V4 Debugger: Collect locals also from block scopes
Block scopes can contain "const" and "let" members. Fixes: QTBUG-92224 Pick-to: 5.15 6.1 Change-Id: Ie13d7d573e2759c510e1ea48c6edc68a095f40a0 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
This commit is contained in:
parent
a0d74b122a
commit
051dd3178b
|
@ -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;
|
||||
|
||||
|
|
|
@ -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()
|
||||
}
|
|
@ -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,61 @@ 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();
|
||||
QString name = propObj.value(QStringLiteral("name")).toString();
|
||||
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);
|
||||
|
|
|
@ -580,21 +580,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()
|
||||
|
|
Loading…
Reference in New Issue