diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2021-12-07 23:18:48 +0100 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2021-12-09 23:16:36 +0100 |
commit | 90790ef23bb148b4ac4c055bd3c11153b4c9a502 (patch) | |
tree | 673d381dc354abb8b06a624197e1460a3b676fdf /src/qml/jsruntime/qv4qmlcontext.cpp | |
parent | 3c05e01dc502802c6118b0ac854c0208028875f3 (diff) |
V4 Lookup: Do not leak property caches
When a function that performs a lookup is called recursively via the
flushing of initial bindings, we may initialize the same lookup twice.
In that case, make sure to release the old property cache before
overwriting it.
We might suspect that this can only re-assign the same property cache
again and therefore we can skip the whole operation if it has been done
before. Yet, considering the dynamic nature of QML, it's very hard to
guarantee this. There are cases where we have to revert lookups because
the types don't match anymore at the time we call them again. I cannot
rule out the possibility of this happening during initialization.
Therefore, the code doesn't try to be clever about this case and instead
just blindly overwrites the lookup (like it did before, just without
leaking).
Fixes: QTBUG-99025
Pick-to: 5.15 6.2
Change-Id: I536deef282bbff723f79a82e4d9e694c3d2d32df
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'src/qml/jsruntime/qv4qmlcontext.cpp')
-rw-r--r-- | src/qml/jsruntime/qv4qmlcontext.cpp | 19 |
1 files changed, 7 insertions, 12 deletions
diff --git a/src/qml/jsruntime/qv4qmlcontext.cpp b/src/qml/jsruntime/qv4qmlcontext.cpp index 1af801163d..95a6d64d47 100644 --- a/src/qml/jsruntime/qv4qmlcontext.cpp +++ b/src/qml/jsruntime/qv4qmlcontext.cpp @@ -305,15 +305,12 @@ ReturnedValue QQmlContextWrapper::getPropertyAndBase(const QQmlContextWrapper *r if (base) *base = QV4::QObjectWrapper::wrap(v4, scopeObject); - if (lookup && propertyData) { + if (lookup && propertyData && lookup->qmlContextPropertyGetter + != QQmlContextWrapper::lookupScopeObjectProperty) { QQmlData *ddata = QQmlData::get(scopeObject, false); if (ddata && ddata->propertyCache) { ScopedValue val(scope, base ? *base : Value::fromReturnedValue(QV4::QObjectWrapper::wrap(v4, scopeObject))); - const QObjectWrapper *That = static_cast<const QObjectWrapper *>(val->objectValue()); - lookup->qobjectLookup.ic = That->internalClass(); - lookup->qobjectLookup.propertyCache = ddata->propertyCache.data(); - lookup->qobjectLookup.propertyCache->addref(); - lookup->qobjectLookup.propertyData = propertyData; + QV4::setupQObjectLookup(lookup, ddata, propertyData, val->objectValue()); lookup->qmlContextPropertyGetter = QQmlContextWrapper::lookupScopeObjectProperty; } } @@ -340,14 +337,12 @@ ReturnedValue QQmlContextWrapper::getPropertyAndBase(const QQmlContextWrapper *r if (propertyData) { if (lookup) { QQmlData *ddata = QQmlData::get(contextObject, false); - if (ddata && ddata->propertyCache) { + if (ddata && ddata->propertyCache + && lookup->qmlContextPropertyGetter != contextGetterFunction) { ScopedValue val(scope, base ? *base : Value::fromReturnedValue(QV4::QObjectWrapper::wrap(v4, contextObject))); - const QObjectWrapper *That = static_cast<const QObjectWrapper *>(val->objectValue()); - lookup->qobjectLookup.ic = That->internalClass(); - lookup->qobjectLookup.propertyCache = ddata->propertyCache.data(); - lookup->qobjectLookup.propertyCache->addref(); - lookup->qobjectLookup.propertyData = propertyData; + QV4::setupQObjectLookup(lookup, ddata, propertyData, + val->objectValue()); lookup->qmlContextPropertyGetter = contextGetterFunction; } } else if (originalLookup) { |