diff options
| author | Ulf Hermann <ulf.hermann@qt.io> | 2024-03-19 15:55:12 +0100 |
|---|---|---|
| committer | Ulf Hermann <ulf.hermann@qt.io> | 2024-03-26 10:35:17 +0100 |
| commit | 1586ea1f15b78aa1319447b8a6a41b23c19eb2e0 (patch) | |
| tree | bac3aaed04e28f3bb12a7118419823027ddc9c4e | |
| parent | 4210e2c2f5c45a61b80e692a767dbc6344c8aee0 (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.cpp | 70 | ||||
| -rw-r--r-- | tests/auto/qml/qmlcppcodegen/data/idAccess.qml | 4 | ||||
| -rw-r--r-- | tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp | 12 |
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() |
