diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2021-10-29 15:42:21 +0200 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2021-11-01 09:20:59 +0100 |
commit | 891072f3f5f8f988d4da6c39ab654b605e25dda7 (patch) | |
tree | f28b1623cbaa1e017e591775be13755a3ef76847 /src | |
parent | d00c76171de0c76794eb70a7284326332c0b3c66 (diff) |
QQmlComponent: Make it harder to leak deferred states
The previous pointer wrangling was ripe with foot guns. Let's just use a
vector of unique_ptr to keep track of the states.
Change-Id: I3ae225b3ab8644aa690d506d0a5de0bfb9ecce23
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'src')
-rw-r--r-- | src/qml/qml/qqmlcomponent.cpp | 18 | ||||
-rw-r--r-- | src/qml/qml/qqmlcomponent_p.h | 20 | ||||
-rw-r--r-- | src/quicktemplates2/qquickdeferredexecute.cpp | 16 |
3 files changed, 20 insertions, 34 deletions
diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp index 8293f17e7f..2b0e9ee31a 100644 --- a/src/qml/qml/qqmlcomponent.cpp +++ b/src/qml/qml/qqmlcomponent.cpp @@ -1006,30 +1006,30 @@ void QQmlComponentPrivate::beginDeferred(QQmlEnginePrivate *enginePriv, QQmlData *ddata = QQmlData::get(object); Q_ASSERT(!ddata->deferredData.isEmpty()); - deferredState->constructionStates.reserve(ddata->deferredData.size()); + deferredState->reserve(ddata->deferredData.size()); for (QQmlData::DeferredData *deferredData : qAsConst(ddata->deferredData)) { enginePriv->inProgressCreations++; - ConstructionState *state = new ConstructionState; - state->completePending = true; + ConstructionState state; + state.completePending = true; - state->creator.reset(new QQmlObjectCreator( + state.creator.reset(new QQmlObjectCreator( deferredData->context->parent(), deferredData->compilationUnit, QQmlRefPointer<QQmlContextData>())); - if (!state->creator->populateDeferredProperties(object, deferredData)) - state->errors << state->creator->errors; + if (!state.creator->populateDeferredProperties(object, deferredData)) + state.errors << state.creator->errors; deferredData->bindings.clear(); - deferredState->constructionStates += state; + deferredState->push_back(std::move(state)); } } void QQmlComponentPrivate::completeDeferred(QQmlEnginePrivate *enginePriv, QQmlComponentPrivate::DeferredState *deferredState) { - for (ConstructionState *state : qAsConst(deferredState->constructionStates)) - complete(enginePriv, state); + for (ConstructionState &state : *deferredState) + complete(enginePriv, &state); } void QQmlComponentPrivate::complete(QQmlEnginePrivate *enginePriv, ConstructionState *state) diff --git a/src/qml/qml/qqmlcomponent_p.h b/src/qml/qml/qqmlcomponent_p.h index 59ef47f2c3..f95e83f15e 100644 --- a/src/qml/qml/qqmlcomponent_p.h +++ b/src/qml/qml/qqmlcomponent_p.h @@ -112,27 +112,13 @@ public: QQmlRefPointer<QV4::ExecutableCompilationUnit> compilationUnit; struct ConstructionState { - ConstructionState() - : completePending(false) - {} - ~ConstructionState() - { - } - - QScopedPointer<QQmlObjectCreator> creator; + std::unique_ptr<QQmlObjectCreator> creator; QList<QQmlError> errors; - bool completePending; + bool completePending = false; }; ConstructionState state; - struct DeferredState { - ~DeferredState() { - qDeleteAll(constructionStates); - constructionStates.clear(); - } - QVector<ConstructionState *> constructionStates; - }; - + using DeferredState = std::vector<ConstructionState>; static void beginDeferred(QQmlEnginePrivate *enginePriv, QObject *object, DeferredState* deferredState); static void completeDeferred(QQmlEnginePrivate *enginePriv, DeferredState *deferredState); diff --git a/src/quicktemplates2/qquickdeferredexecute.cpp b/src/quicktemplates2/qquickdeferredexecute.cpp index 817415c492..8fb566a998 100644 --- a/src/quicktemplates2/qquickdeferredexecute.cpp +++ b/src/quicktemplates2/qquickdeferredexecute.cpp @@ -83,23 +83,23 @@ static bool beginDeferred(QQmlEnginePrivate *enginePriv, const QQmlProperty &pro if (range.first == bindings.end()) continue; - QQmlComponentPrivate::ConstructionState *state = new QQmlComponentPrivate::ConstructionState; - state->completePending = true; + QQmlComponentPrivate::ConstructionState state; + state.completePending = true; QQmlContextData *creationContext = nullptr; - state->creator.reset(new QQmlObjectCreator(deferData->context->parent(), deferData->compilationUnit, creationContext)); + state.creator.reset(new QQmlObjectCreator(deferData->context->parent(), deferData->compilationUnit, creationContext)); enginePriv->inProgressCreations++; std::deque<const QV4::CompiledData::Binding *> reversedBindings; std::copy(range.first, range.second, std::front_inserter(reversedBindings)); - state->creator->beginPopulateDeferred(deferData->context); + state.creator->beginPopulateDeferred(deferData->context); for (const QV4::CompiledData::Binding *binding : reversedBindings) - state->creator->populateDeferredBinding(property, deferData->deferredIdx, binding); - state->creator->finalizePopulateDeferred(); - state->errors << state->creator->errors; + state.creator->populateDeferredBinding(property, deferData->deferredIdx, binding); + state.creator->finalizePopulateDeferred(); + state.errors << state.creator->errors; - deferredState->constructionStates += state; + deferredState->push_back(std::move(state)); // Cleanup any remaining deferred bindings for this property, also in inner contexts, // to avoid executing them later and overriding the property that was just populated. |