aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrei Golubev <[email protected]>2022-06-08 12:33:14 +0200
committerAndrei Golubev <[email protected]>2022-06-09 16:22:22 +0200
commitd28f088371befbe5b50fed37e41025afa7b72c0c (patch)
tree6850b2af2f7801a0839c1ef924280aae0d4ec2d3
parentfa6074f654281920980bd529ca6537e96058a6a5 (diff)
Remember QML document context in each qmltc-generated object
There is an apparent problem in certain cases where using outer context to fetch ids is invalid: the outer context is the *outermost* context, meaning that if a type has a derived type in another QML document, the derived type would place its own context as a QQmlData::outerContext As a simpler solution, just remember the document's context in all the objects within this document. This automatically works in derived types since they appear in other documents with separate contexts Pick-to: 6.4 Fixes: QTBUG-103956 Change-Id: I29420ff4962b485502d87b2d2ac2f89b9e0f5736 Reviewed-by: Ulf Hermann <[email protected]> Reviewed-by: Sami Shalayel <[email protected]>
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/CMakeLists.txt4
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/qtbug103956/MainComponent.qml9
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/qtbug103956/SubComponent.qml5
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/qtbug103956/qtbug103956_main.qml9
-rw-r--r--tests/auto/qml/qmltc/tst_qmltc.cpp10
-rw-r--r--tests/auto/qml/qmltc/tst_qmltc.h1
-rw-r--r--tools/qmltc/qmltccompiler.cpp14
-rw-r--r--tools/qmltc/qmltccompilerpieces.h5
8 files changed, 46 insertions, 11 deletions
diff --git a/tests/auto/qml/qmltc/QmltcTests/CMakeLists.txt b/tests/auto/qml/qmltc/QmltcTests/CMakeLists.txt
index 3093c978f1..f9877f29bc 100644
--- a/tests/auto/qml/qmltc/QmltcTests/CMakeLists.txt
+++ b/tests/auto/qml/qmltc/QmltcTests/CMakeLists.txt
@@ -32,6 +32,10 @@ set(qml_sources
QmlTypeWithBaseTypeExtension.qml
extensionTypeBindings.qml
+ qtbug103956/SubComponent.qml
+ qtbug103956/MainComponent.qml
+ qtbug103956/qtbug103956_main.qml
+
signalHandlers.qml
javaScriptFunctions.qml
changingBindings.qml
diff --git a/tests/auto/qml/qmltc/QmltcTests/qtbug103956/MainComponent.qml b/tests/auto/qml/qmltc/QmltcTests/qtbug103956/MainComponent.qml
new file mode 100644
index 0000000000..8518bc0919
--- /dev/null
+++ b/tests/auto/qml/qmltc/QmltcTests/qtbug103956/MainComponent.qml
@@ -0,0 +1,9 @@
+import QtQuick
+import QmltcTests 1.0
+
+Item {
+ property alias firstComponent: firstComponent
+ SubComponent {
+ id: firstComponent
+ }
+}
diff --git a/tests/auto/qml/qmltc/QmltcTests/qtbug103956/SubComponent.qml b/tests/auto/qml/qmltc/QmltcTests/qtbug103956/SubComponent.qml
new file mode 100644
index 0000000000..80ff9edf4e
--- /dev/null
+++ b/tests/auto/qml/qmltc/QmltcTests/qtbug103956/SubComponent.qml
@@ -0,0 +1,5 @@
+import QtQuick
+
+Item {
+ property bool setMe: false
+}
diff --git a/tests/auto/qml/qmltc/QmltcTests/qtbug103956/qtbug103956_main.qml b/tests/auto/qml/qmltc/QmltcTests/qtbug103956/qtbug103956_main.qml
new file mode 100644
index 0000000000..f8d1549c4b
--- /dev/null
+++ b/tests/auto/qml/qmltc/QmltcTests/qtbug103956/qtbug103956_main.qml
@@ -0,0 +1,9 @@
+import QmltcTests 1.0
+
+MainComponent {
+ firstComponent.setMe: true
+
+ MainComponent {
+ firstComponent.setMe: true
+ }
+}
diff --git a/tests/auto/qml/qmltc/tst_qmltc.cpp b/tests/auto/qml/qmltc/tst_qmltc.cpp
index 654ce91c3b..8536a01c20 100644
--- a/tests/auto/qml/qmltc/tst_qmltc.cpp
+++ b/tests/auto/qml/qmltc/tst_qmltc.cpp
@@ -47,6 +47,7 @@
#include "gradients.h"
#include "qjsvalueassignments.h"
#include "extensiontypebindings.h"
+#include "qtbug103956_main.h"
#include "signalhandlers.h"
#include "javascriptfunctions.h"
@@ -837,6 +838,15 @@ void tst_qmltc::extensionTypeBindings()
}
}
+// QTBUG-103956
+void tst_qmltc::visibleAliasMethods()
+{
+ QQmlEngine e;
+ PREPEND_NAMESPACE(qtbug103956_main) created(&e);
+ QVERIFY(created.firstComponent());
+ QCOMPARE(created.firstComponent()->setMe(), true);
+}
+
void tst_qmltc::signalHandlers()
{
QQmlEngine e;
diff --git a/tests/auto/qml/qmltc/tst_qmltc.h b/tests/auto/qml/qmltc/tst_qmltc.h
index a2678054db..94411ea29a 100644
--- a/tests/auto/qml/qmltc/tst_qmltc.h
+++ b/tests/auto/qml/qmltc/tst_qmltc.h
@@ -59,6 +59,7 @@ private slots:
void gradients(); // QTBUG-102560
void jsvalueAssignments();
void extensionTypeBindings();
+ void visibleAliasMethods(); // QTBUG-103956
void signalHandlers();
void jsFunctions();
diff --git a/tools/qmltc/qmltccompiler.cpp b/tools/qmltc/qmltccompiler.cpp
index 7f4c6c0af4..a241cf0715 100644
--- a/tools/qmltc/qmltccompiler.cpp
+++ b/tools/qmltc/qmltccompiler.cpp
@@ -603,17 +603,9 @@ void QmltcCompiler::compileAlias(QmltcType &current, const QQmlJSMetaProperty &a
Q_ASSERT(id >= 0); // since the type is found by id, it must have an id
AliasResolutionFrame queryIdFrame {};
- queryIdFrame.prologue << u"auto context = QQmlData::get(%1)->outerContext;"_s.arg(
- AliasResolutionFrame::inVar);
- // there's a special case: when `this` type has compiled QML type as
- // a base type and it is not a root, it has a non-root first
- // context, so we need to step one level up
- if (QQmlJSUtils::hasCompositeBase(owner) && owner != m_visitor->result()) {
- Q_ASSERT(!owner->baseTypeName().isEmpty());
- queryIdFrame.prologue
- << u"// `this` is special: not a root and its base type is compiled"_s;
- queryIdFrame.prologue << u"context = context->parent().data();"_s;
- }
+ Q_ASSERT(frames.top().outVar == u"this"_s); // so inVar would be "this" as well
+ queryIdFrame.prologue << u"auto context = %1::q_qmltc_thisContext;"_s.arg(
+ owner->internalName());
// doing the above allows us to lookup id object by index (fast)
queryIdFrame.outVar = u"alias_objectById_" + aliasExprBits.front(); // unique enough
diff --git a/tools/qmltc/qmltccompilerpieces.h b/tools/qmltc/qmltccompilerpieces.h
index 545e347caf..6d4912f883 100644
--- a/tools/qmltc/qmltccompilerpieces.h
+++ b/tools/qmltc/qmltccompilerpieces.h
@@ -232,6 +232,11 @@ inline decltype(auto) QmltcCodeGenerator::generate_initCode(QmltcType &current,
current.init.body << u"context->setContextObject(this);"_s;
}
+ // context is this document's context. we must remember it in each type
+ current.variables.emplaceBack(u"QQmlRefPointer<QQmlContextData>"_s, u"q_qmltc_thisContext"_s,
+ u"nullptr"_s);
+ current.init.body << u"%1::q_qmltc_thisContext = context;"_s.arg(type->internalName());
+
if (int id = visitor->runtimeId(type); id >= 0) {
current.init.body << u"// 3. set id since it is provided"_s;
QString idString = visitor->addressableScopes().id(type);