diff options
author | Ulf Hermann <[email protected]> | 2019-04-29 16:44:48 +0200 |
---|---|---|
committer | Ulf Hermann <[email protected]> | 2019-04-29 15:07:12 +0000 |
commit | 4fea3ec29c9911522a379a01418394b5cad29ecc (patch) | |
tree | e05fd2790308a694c9922137d3e31e743d87dba3 | |
parent | a452f14fd9b20b429048fc28aeac0c0542484a50 (diff) |
Skip block context within call contexts when searching for parameters
Only the call context contains the signal parameters. However, there can
be any number of nested block contexts in a function. This manifests
itself when the function needs an execution context. The simplest way to
trigger this is attaching a debugger.
Fixes: QTBUG-75393
Change-Id: Iabdc06a9fe7bf88204525d6940b626575fee1579
Reviewed-by: Simon Hausmann <[email protected]>
-rw-r--r-- | src/qml/jsruntime/qv4qmlcontext.cpp | 16 | ||||
-rw-r--r-- | tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp | 27 |
2 files changed, 38 insertions, 5 deletions
diff --git a/src/qml/jsruntime/qv4qmlcontext.cpp b/src/qml/jsruntime/qv4qmlcontext.cpp index 12ada7ee70..0c5226d46c 100644 --- a/src/qml/jsruntime/qv4qmlcontext.cpp +++ b/src/qml/jsruntime/qv4qmlcontext.cpp @@ -458,11 +458,17 @@ ReturnedValue QQmlContextWrapper::resolveQmlContextPropertyLookupGetter(Lookup * // into the handler expression through the locals of the call context. So for onClicked: { ... } // the parameters of the clicked signal are injected and we must allow for them to be found here // before any other property from the QML context. - ExecutionContext &ctx = static_cast<ExecutionContext &>(engine->currentStackFrame->jsFrame->context); - if (ctx.d()->type == Heap::ExecutionContext::Type_CallContext) { - uint index = ctx.d()->internalClass->indexOfValueOrGetter(name); - if (index < UINT_MAX) - return static_cast<Heap::CallContext*>(ctx.d())->locals[index].asReturnedValue(); + for (Heap::ExecutionContext *ctx = engine->currentContext()->d(); ctx; ctx = ctx->outer) { + if (ctx->type == Heap::ExecutionContext::Type_CallContext) { + const uint index = ctx->internalClass->indexOfValueOrGetter(name); + if (index < std::numeric_limits<uint>::max()) + return static_cast<Heap::CallContext *>(ctx)->locals[index].asReturnedValue(); + } + + // Skip only block contexts within the current call context. + // Other contexts need a regular QML property lookup. See below. + if (ctx->type != Heap::ExecutionContext::Type_BlockContext) + break; } bool hasProperty = false; diff --git a/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp b/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp index b75fb6b895..497c721f50 100644 --- a/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp +++ b/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp @@ -322,6 +322,8 @@ private slots: void lastLineOfConditional(); void readThis(); + void signalParameters(); + private: QV4Debugger *debugger() const { @@ -899,6 +901,31 @@ void tst_qv4debugger::readThis() QCOMPARE(a.value("value").toInt(), 5); } +void tst_qv4debugger::signalParameters() +{ + QQmlEngine engine; + QV4::ExecutionEngine *v4 = engine.handle(); + v4->setDebugger(new QV4Debugger(v4)); + + QQmlComponent component(&engine); + component.setData("import QtQml 2.12\n" + "QtObject {\n" + " id: root\n" + " property string result\n" + " signal signalWithArg(string textArg)\n" + " property Connections connections : Connections {\n" + " target: root\n" + " onSignalWithArg: { root.result = textArg; }\n" + " }\n" + " Component.onCompleted: signalWithArg('something')\n" + "}", QUrl("test.qml")); + + QVERIFY(component.isReady()); + QScopedPointer<QObject> obj(component.create()); + QVERIFY(obj); + QCOMPARE(obj->property("result").toString(), QLatin1String("something")); +} + QTEST_MAIN(tst_qv4debugger) #include "tst_qv4debugger.moc" |