aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2024-02-15 14:12:47 +0100
committerUlf Hermann <ulf.hermann@qt.io>2024-02-20 10:38:15 +0100
commit95965ba19f6a1cc04d8bc04e2c55ececcd87edbb (patch)
tree916dc2435f809ee2a8f58d4184f11ec27cf21eda /src/qml/qml
parent0a3290f2288695a2b05ae3824c18d01abe4195e0 (diff)
QtQml: Don't let objects be deleted during incubation
As long as the incubator object is alive, it should hold on to the object being incubated. Anything else makes no sense. Re-use the "valuemap" slot to hold on to the object once its ready. Pick-to: 6.7 6.6 6.5 Fixes: QTBUG-119911 Change-Id: Ia9823aced5ec16a8da00e61ad7d606c63e40ed31 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'src/qml/qml')
-rw-r--r--src/qml/qml/qqmlcomponent.cpp25
1 files changed, 15 insertions, 10 deletions
diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp
index c45291a856..1b6bac5d0e 100644
--- a/src/qml/qml/qqmlcomponent.cpp
+++ b/src/qml/qml/qqmlcomponent.cpp
@@ -1499,7 +1499,7 @@ namespace QV4 {
namespace Heap {
#define QmlIncubatorObjectMembers(class, Member) \
- Member(class, HeapValue, HeapValue, valuemap) \
+ Member(class, HeapValue, HeapValue, valuemapOrObject) \
Member(class, HeapValue, HeapValue, statusChanged) \
Member(class, Pointer, QmlContext *, qmlContext) \
Member(class, NoMark, QQmlComponentIncubator *, incubator) \
@@ -1912,7 +1912,7 @@ void QQmlComponent::incubateObject(QQmlV4Function *args)
r->setPrototypeOf(p);
if (!valuemap->isUndefined())
- r->d()->valuemap.set(scope.engine, valuemap);
+ r->d()->valuemapOrObject.set(scope.engine, valuemap);
r->d()->qmlContext.set(scope.engine, v4->qmlContext());
r->d()->parent = parent;
@@ -2015,7 +2015,7 @@ QQmlComponentExtension::~QQmlComponentExtension()
void QV4::Heap::QmlIncubatorObject::init(QQmlIncubator::IncubationMode m)
{
Object::init();
- valuemap.set(internalClass->engine, QV4::Value::undefinedValue());
+ valuemapOrObject.set(internalClass->engine, QV4::Value::undefinedValue());
statusChanged.set(internalClass->engine, QV4::Value::undefinedValue());
parent.init();
qmlContext.set(internalClass->engine, nullptr);
@@ -2032,13 +2032,13 @@ void QV4::QmlIncubatorObject::setInitialState(QObject *o, RequiredProperties *re
{
QQmlComponent_setQmlParent(o, d()->parent);
- if (!d()->valuemap.isUndefined()) {
+ if (!d()->valuemapOrObject.isUndefined()) {
QV4::ExecutionEngine *v4 = engine();
QV4::Scope scope(v4);
QV4::ScopedObject obj(scope, QV4::QObjectWrapper::wrap(v4, o));
QV4::Scoped<QV4::QmlContext> qmlCtxt(scope, d()->qmlContext);
QQmlComponentPrivate::setInitialProperties(
- v4, qmlCtxt, obj, d()->valuemap, requiredProperties, o,
+ v4, qmlCtxt, obj, d()->valuemapOrObject, requiredProperties, o,
QQmlIncubatorPrivate::get(d()->incubator)->creator.data());
}
}
@@ -2046,13 +2046,18 @@ void QV4::QmlIncubatorObject::setInitialState(QObject *o, RequiredProperties *re
void QV4::QmlIncubatorObject::statusChanged(QQmlIncubator::Status s)
{
QV4::Scope scope(engine());
- // hold the incubated object in a scoped value to prevent it's destruction before this method returns
- QV4::ScopedObject incubatedObject(scope, QV4::QObjectWrapper::wrap(scope.engine, d()->incubator->object()));
+
+ QObject *object = d()->incubator->object();
if (s == QQmlIncubator::Ready) {
- Q_ASSERT(QQmlData::get(d()->incubator->object()));
- QQmlData::get(d()->incubator->object())->explicitIndestructibleSet = false;
- QQmlData::get(d()->incubator->object())->indestructible = false;
+ // We don't need the arguments anymore, but we still want to hold on to the object so
+ // that it doesn't get gc'd
+ d()->valuemapOrObject.set(scope.engine, QV4::QObjectWrapper::wrap(scope.engine, object));
+
+ QQmlData *ddata = QQmlData::get(object);
+ Q_ASSERT(ddata);
+ ddata->explicitIndestructibleSet = false;
+ ddata->indestructible = false;
}
QV4::ScopedFunctionObject f(scope, d()->statusChanged);