aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2024-03-19 15:55:12 +0100
committerUlf Hermann <ulf.hermann@qt.io>2024-03-26 10:35:17 +0100
commit1586ea1f15b78aa1319447b8a6a41b23c19eb2e0 (patch)
treebac3aaed04e28f3bb12a7118419823027ddc9c4e
parent4210e2c2f5c45a61b80e692a767dbc6344c8aee0 (diff)
QmlCompiler: Do not use QQmlEngine from current QML context
We cannot be sure the current context is still alive when a function is called. We may be left with a skeleton context that doesn't have an engine anymore. However, we can always query the QJSEngine given in the AOT context. That one cannot disappear and is generally the right one for capturing properties. Pick-to: 6.5 6.2 Fixes: QTBUG-123395 Change-Id: I2a6c38baa159fa790f3ba2aba225fdc9cc37001e Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> (cherry picked from commit eb79815fbfad7d4e7fb4be856dc0dd43be76fdb9) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> (cherry picked from commit 8228f07a216dc6996be6584108d262829d68016b)
-rw-r--r--src/qml/qml/qqml.cpp70
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/idAccess.qml4
-rw-r--r--tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp12
3 files changed, 48 insertions, 38 deletions
diff --git a/src/qml/qml/qqml.cpp b/src/qml/qml/qqml.cpp
index e894f6e609..61967fa095 100644
--- a/src/qml/qml/qqml.cpp
+++ b/src/qml/qml/qqml.cpp
@@ -813,7 +813,13 @@ QObject *AOTCompiledContext::thisObject() const
QQmlEngine *AOTCompiledContext::qmlEngine() const
{
- return qmlContext ? qmlContext->engine() : nullptr;
+ return engine->handle()->qmlEngine();
+}
+
+static QQmlPropertyCapture *propertyCapture(const AOTCompiledContext *aotContext)
+{
+ QQmlEngine *engine = aotContext->qmlEngine();
+ return engine ? QQmlEnginePrivate::get(aotContext->qmlEngine())->propertyCapture : nullptr;
}
QJSValue AOTCompiledContext::jsMetaType(int index) const
@@ -836,37 +842,25 @@ void AOTCompiledContext::setReturnValueUndefined() const
}
}
-static QQmlPropertyCapture *propertyCapture(const QQmlContextData *qmlContext)
-{
- if (!qmlContext)
- return nullptr;
-
- QQmlEngine *engine = qmlContext->engine();
- Q_ASSERT(engine);
- QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine);
- Q_ASSERT(ep);
- return ep->propertyCapture;
-}
-
static void captureFallbackProperty(
QObject *object, int coreIndex, int notifyIndex, bool isConstant,
- const QQmlContextData *qmlContext)
+ const AOTCompiledContext *aotContext)
{
if (isConstant)
return;
- if (QQmlPropertyCapture *capture = propertyCapture(qmlContext))
+ if (QQmlPropertyCapture *capture = propertyCapture(aotContext))
capture->captureProperty(object, coreIndex, notifyIndex);
}
static void captureObjectProperty(
QObject *object, const QQmlPropertyCache *propertyCache,
- const QQmlPropertyData *property, QQmlContextData *qmlContext)
+ const QQmlPropertyData *property, const AOTCompiledContext *aotContext)
{
if (property->isConstant())
return;
- if (QQmlPropertyCapture *capture = propertyCapture(qmlContext))
+ if (QQmlPropertyCapture *capture = propertyCapture(aotContext))
capture->captureProperty(object, propertyCache, property);
}
@@ -883,7 +877,7 @@ enum class ObjectPropertyResult { OK, NeedsInit, Deleted };
template<bool StrictType = false>
ObjectPropertyResult loadObjectProperty(
- QV4::Lookup *l, QObject *object, void *target, QQmlContextData *qmlContext)
+ QV4::Lookup *l, QObject *object, void *target, const AOTCompiledContext *aotContext)
{
QQmlData *qmlData = QQmlData::get(object);
if (!qmlData)
@@ -904,13 +898,13 @@ ObjectPropertyResult loadObjectProperty(
if (qmlData->hasPendingBindingBit(coreIndex))
qmlData->flushPendingBinding(coreIndex);
- captureObjectProperty(object, propertyCache, property, qmlContext);
+ captureObjectProperty(object, propertyCache, property, aotContext);
property->readProperty(object, target);
return ObjectPropertyResult::OK;
}
static ObjectPropertyResult loadFallbackProperty(
- QV4::Lookup *l, QObject *object, void *target, QQmlContextData *qmlContext)
+ QV4::Lookup *l, QObject *object, void *target, const AOTCompiledContext *aotContext)
{
QQmlData *qmlData = QQmlData::get(object);
if (qmlData && qmlData->isQueuedForDeletion)
@@ -928,7 +922,7 @@ static ObjectPropertyResult loadFallbackProperty(
qmlData->flushPendingBinding(coreIndex);
captureFallbackProperty(object, coreIndex, l->qobjectFallbackLookup.notifyIndex,
- l->qobjectFallbackLookup.isConstant, qmlContext);
+ l->qobjectFallbackLookup.isConstant, aotContext);
void *a[] = { target, nullptr };
metaObject->metacall(object, QMetaObject::ReadProperty, coreIndex, a);
@@ -937,19 +931,19 @@ static ObjectPropertyResult loadFallbackProperty(
}
ObjectPropertyResult loadObjectAsVariant(
- QV4::Lookup *l, QObject *object, void *target, QQmlContextData *qmlContext)
+ QV4::Lookup *l, QObject *object, void *target, const AOTCompiledContext *aotContext)
{
QVariant *variant = static_cast<QVariant *>(target);
const QMetaType propType = l->qobjectLookup.propertyData->propType();
if (propType == QMetaType::fromType<QVariant>())
- return loadObjectProperty<true>(l, object, variant, qmlContext);
+ return loadObjectProperty<true>(l, object, variant, aotContext);
*variant = QVariant(propType);
- return loadObjectProperty<true>(l, object, variant->data(), qmlContext);
+ return loadObjectProperty<true>(l, object, variant->data(), aotContext);
}
ObjectPropertyResult loadFallbackAsVariant(
- QV4::Lookup *l, QObject *object, void *target, QQmlContextData *qmlContext)
+ QV4::Lookup *l, QObject *object, void *target, const AOTCompiledContext *aotContext)
{
const QMetaObject *metaObject
= reinterpret_cast<const QMetaObject *>(l->qobjectFallbackLookup.metaObject - 1);
@@ -958,10 +952,10 @@ ObjectPropertyResult loadFallbackAsVariant(
QVariant *variant = static_cast<QVariant *>(target);
const QMetaType propType = metaObject->property(l->qobjectFallbackLookup.coreIndex).metaType();
if (propType == QMetaType::fromType<QVariant>())
- return loadFallbackProperty(l, object, variant, qmlContext);
+ return loadFallbackProperty(l, object, variant, aotContext);
*variant = QVariant(propType);
- return loadFallbackProperty(l, object, variant->data(), qmlContext);
+ return loadFallbackProperty(l, object, variant->data(), aotContext);
}
template<bool StrictType, typename Op>
@@ -1283,7 +1277,7 @@ bool AOTCompiledContext::captureLookup(uint index, QObject *object) const
|| l->getter == QV4::Lookup::getterQObjectAsVariant) {
const QQmlPropertyData *property = l->qobjectLookup.propertyData;
QQmlData::flushPendingBinding(object, property->coreIndex());
- captureObjectProperty(object, l->qobjectLookup.propertyCache, property, qmlContext);
+ captureObjectProperty(object, l->qobjectLookup.propertyCache, property, this);
return true;
}
@@ -1293,7 +1287,7 @@ bool AOTCompiledContext::captureLookup(uint index, QObject *object) const
QQmlData::flushPendingBinding(object, coreIndex);
captureFallbackProperty(
object, coreIndex, l->qobjectFallbackLookup.notifyIndex,
- l->qobjectFallbackLookup.isConstant, qmlContext);
+ l->qobjectFallbackLookup.isConstant, this);
return true;
}
@@ -1307,7 +1301,7 @@ bool AOTCompiledContext::captureQmlContextPropertyLookup(uint index) const
&& l->qmlContextPropertyGetter == QV4::QQmlContextWrapper::lookupContextObjectProperty) {
const QQmlPropertyData *property = l->qobjectLookup.propertyData;
QQmlData::flushPendingBinding(qmlScopeObject, property->coreIndex());
- captureObjectProperty(qmlScopeObject, l->qobjectLookup.propertyCache, property, qmlContext);
+ captureObjectProperty(qmlScopeObject, l->qobjectLookup.propertyCache, property, this);
return true;
}
@@ -1315,7 +1309,7 @@ bool AOTCompiledContext::captureQmlContextPropertyLookup(uint index) const
const int coreIndex = l->qobjectFallbackLookup.coreIndex;
QQmlData::flushPendingBinding(qmlScopeObject, coreIndex);
captureFallbackProperty(qmlScopeObject, coreIndex, l->qobjectFallbackLookup.notifyIndex,
- l->qobjectFallbackLookup.isConstant, qmlContext);
+ l->qobjectFallbackLookup.isConstant, this);
return true;
}
@@ -1324,7 +1318,7 @@ bool AOTCompiledContext::captureQmlContextPropertyLookup(uint index) const
void AOTCompiledContext::captureTranslation() const
{
- if (QQmlPropertyCapture *capture = propertyCapture(qmlContext))
+ if (QQmlPropertyCapture *capture = propertyCapture(this))
capture->captureTranslation();
}
@@ -1672,9 +1666,9 @@ bool AOTCompiledContext::loadScopeObjectPropertyLookup(uint index, void *target)
ObjectPropertyResult result = ObjectPropertyResult::NeedsInit;
if (l->qmlContextPropertyGetter == QV4::QQmlContextWrapper::lookupScopeObjectProperty)
- result = loadObjectProperty(l, qmlScopeObject, target, qmlContext);
+ result = loadObjectProperty(l, qmlScopeObject, target, this);
else if (l->qmlContextPropertyGetter == QV4::QQmlContextWrapper::lookupScopeFallbackProperty)
- result = loadFallbackProperty(l, qmlScopeObject, target, qmlContext);
+ result = loadFallbackProperty(l, qmlScopeObject, target, this);
else
return false;
@@ -1871,13 +1865,13 @@ bool AOTCompiledContext::getObjectLookup(uint index, QObject *object, void *targ
ObjectPropertyResult result = ObjectPropertyResult::NeedsInit;
if (l->getter == QV4::Lookup::getterQObject)
- result = loadObjectProperty(l, object, target, qmlContext);
+ result = loadObjectProperty(l, object, target, this);
else if (l->getter == QV4::Lookup::getterFallback)
- result = loadFallbackProperty(l, object, target, qmlContext);
+ result = loadFallbackProperty(l, object, target, this);
else if (l->getter == QV4::Lookup::getterQObjectAsVariant)
- result = loadObjectAsVariant(l, object, target, qmlContext);
+ result = loadObjectAsVariant(l, object, target, this);
else if (l->getter == QV4::Lookup::getterFallbackAsVariant)
- result = loadFallbackAsVariant(l, object, target, qmlContext);
+ result = loadFallbackAsVariant(l, object, target, this);
else
return false;
diff --git a/tests/auto/qml/qmlcppcodegen/data/idAccess.qml b/tests/auto/qml/qmlcppcodegen/data/idAccess.qml
index 2090926872..51f40e0add 100644
--- a/tests/auto/qml/qmlcppcodegen/data/idAccess.qml
+++ b/tests/auto/qml/qmlcppcodegen/data/idAccess.qml
@@ -11,5 +11,9 @@ Item {
Text {
id: ttt
+ onTextChanged: {
+ root.objectName = "dead"
+ ttt.objectName = "context"
+ }
}
}
diff --git a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp
index 4c329afa31..793178409b 100644
--- a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp
+++ b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp
@@ -1930,6 +1930,18 @@ void tst_QmlCppCodegen::idAccess()
QObject *ttt = qmlContext(object.data())->objectForName(u"ttt"_s);
QFont f = qvariant_cast<QFont>(ttt->property("font"));
QCOMPARE(f.pointSize(), 22);
+
+ QObject::connect(object.data(), &QObject::objectNameChanged, ttt, [&](){
+ ttt->setParent(nullptr);
+ QJSEngine::setObjectOwnership(ttt, QJSEngine::CppOwnership);
+ object.reset(ttt);
+ });
+
+ QVERIFY(object->objectName().isEmpty());
+ QVERIFY(ttt->objectName().isEmpty());
+ ttt->setProperty("text", u"kill"_s);
+ QCOMPARE(object.data(), ttt);
+ QCOMPARE(ttt->objectName(), u"context"_s);
}
void tst_QmlCppCodegen::importsFromImportPath()