diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2024-02-15 14:12:47 +0100 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2024-02-20 10:38:15 +0100 |
commit | 95965ba19f6a1cc04d8bc04e2c55ececcd87edbb (patch) | |
tree | 916dc2435f809ee2a8f58d4184f11ec27cf21eda /src/qml/qml | |
parent | 0a3290f2288695a2b05ae3824c18d01abe4195e0 (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.cpp | 25 |
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); |