aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml/qqmltypewrapper.cpp
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@qt.io>2019-05-20 16:09:13 +0200
committerSimon Hausmann <simon.hausmann@qt.io>2019-05-21 12:42:45 +0200
commit2f4479857d2b68f8cd3267b2f2b3c652ada431ed (patch)
tree588c84d73801025dcc878bc5b51e04a66f1d1c19 /src/qml/qml/qqmltypewrapper.cpp
parentc61a75cd6a4a9cd7b3594b205fcac8fc1208d493 (diff)
Fix lookups of properties in QML singletons
An unqualified name that points to a QML singleton will evaluate to a QQmlTypeWrapper JS object. A member lookup in such an object is not guaranteed to always produce the same property. The property cache check may protect us from that, but we must still retrieve the QObject singleton for every lookup. Task-number: QTBUG-75896 Change-Id: Ibd9bac6e5c2047f838758811790b299ace636446 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Diffstat (limited to 'src/qml/qml/qqmltypewrapper.cpp')
-rw-r--r--src/qml/qml/qqmltypewrapper.cpp47
1 files changed, 42 insertions, 5 deletions
diff --git a/src/qml/qml/qqmltypewrapper.cpp b/src/qml/qml/qqmltypewrapper.cpp
index 24c5aecc00..c5fa4a04ec 100644
--- a/src/qml/qml/qqmltypewrapper.cpp
+++ b/src/qml/qml/qqmltypewrapper.cpp
@@ -459,16 +459,16 @@ ReturnedValue QQmlTypeWrapper::virtualResolveLookupGetter(const Object *object,
if (!includeEnums || !name->startsWithUpper()) {
QQmlData *ddata = QQmlData::get(qobjectSingleton, false);
if (ddata && ddata->propertyCache) {
- ScopedValue val(scope, Value::fromReturnedValue(QV4::QObjectWrapper::wrap(engine, qobjectSingleton)));
QQmlPropertyData *property = ddata->propertyCache->property(name.getPointer(), qobjectSingleton, qmlContext);
if (property) {
- lookup->qobjectLookup.ic = This->internalClass();
- lookup->qobjectLookup.staticQObject = static_cast<Heap::QObjectWrapper *>(val->heapObject());
+ ScopedValue val(scope, Value::fromReturnedValue(QV4::QObjectWrapper::wrap(engine, qobjectSingleton)));
+ lookup->qobjectLookup.qmlTypeIc = This->internalClass();
+ lookup->qobjectLookup.ic = val->objectValue()->internalClass();
lookup->qobjectLookup.propertyCache = ddata->propertyCache;
lookup->qobjectLookup.propertyCache->addref();
lookup->qobjectLookup.propertyData = property;
- lookup->getter = QV4::QObjectWrapper::lookupGetter;
- return lookup->getter(lookup, engine, *This);
+ lookup->getter = QQmlTypeWrapper::lookupSingletonProperty;
+ return lookup->getter(lookup, engine, *object);
}
// Fall through to base implementation
}
@@ -488,6 +488,43 @@ bool QQmlTypeWrapper::virtualResolveLookupSetter(Object *object, ExecutionEngine
return Object::virtualResolveLookupSetter(object, engine, lookup, value);
}
+ReturnedValue QQmlTypeWrapper::lookupSingletonProperty(Lookup *l, ExecutionEngine *engine, const Value &object)
+{
+ const auto revertLookup = [l, engine, &object]() {
+ l->qobjectLookup.propertyCache->release();
+ l->qobjectLookup.propertyCache = nullptr;
+ l->getter = Lookup::getterGeneric;
+ return Lookup::getterGeneric(l, engine, object);
+ };
+
+ // we can safely cast to a QV4::Object here. If object is something else,
+ // the internal class won't match
+ Heap::Object *o = static_cast<Heap::Object *>(object.heapObject());
+ if (!o || o->internalClass != l->qobjectLookup.qmlTypeIc)
+ return revertLookup();
+
+ Heap::QQmlTypeWrapper *This = static_cast<Heap::QQmlTypeWrapper *>(o);
+
+ QQmlType type = This->type();
+ if (!type.isValid())
+ return revertLookup();
+
+ if (!type.isSingleton())
+ return revertLookup();
+
+ QQmlEngine *e = engine->qmlEngine();
+ QQmlType::SingletonInstanceInfo *siinfo = type.singletonInstanceInfo();
+ siinfo->init(e);
+
+ QObject *qobjectSingleton = siinfo->qobjectApi(e);
+ if (!qobjectSingleton)
+ return revertLookup();
+
+ Scope scope(engine);
+ ScopedValue obj(scope, QV4::QObjectWrapper::wrap(engine, qobjectSingleton));
+ return QObjectWrapper::lookupGetterImpl(l, engine, obj, /*useOriginalProperty*/ true, revertLookup);
+}
+
void Heap::QQmlScopedEnumWrapper::destroy()
{
QQmlType::derefHandle(typePrivate);