diff options
author | Simon Hausmann <simon.hausmann@digia.com> | 2014-01-02 08:48:55 +0100 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2014-01-02 23:36:58 +0100 |
commit | eb3087e4b0b770200512925730c328a8bda7f3d7 (patch) | |
tree | f4511cfbf095be316d8a961a2242adcfa88f086f | |
parent | c988a8e450c6aea6e9588e1517c5bab1acff2a62 (diff) |
Fix lookups of enums in singletons
This is a regression against 5.2.0 (which didn't have this bug), due to
optimizations introduced in the stable branch after the release. The code path
for optimizing access to the members of C++ based singletons through the
regular meta-object properties would end up excluding access to enums when the
lookup happens at run-time. The run-time getter for the singleton itself would
return a wrapped QObject instead of a QQmlTypeWrapper, and only the latter
includes enums.
As QML based singletons (composite singletons) cannot declare enums, we can
continue to do fast lookups on these, but otherwise have to fall back to the
slower code path.
Task-number: QTBUG-35721
Change-Id: Icc66bdaf3572622cdb718f82b706e3204afa0167
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
-rw-r--r-- | src/qml/compiler/qqmlcodegenerator.cpp | 61 | ||||
-rw-r--r-- | tests/auto/qml/qqmlecmascript/data/singletontype/singletonWithEnum.qml | 9 | ||||
-rw-r--r-- | tests/auto/qml/qqmlecmascript/testtypes.cpp | 7 | ||||
-rw-r--r-- | tests/auto/qml/qqmlecmascript/testtypes.h | 10 | ||||
-rw-r--r-- | tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp | 13 |
5 files changed, 65 insertions, 35 deletions
diff --git a/src/qml/compiler/qqmlcodegenerator.cpp b/src/qml/compiler/qqmlcodegenerator.cpp index 8809221abe..ecb643e0f5 100644 --- a/src/qml/compiler/qqmlcodegenerator.cpp +++ b/src/qml/compiler/qqmlcodegenerator.cpp @@ -1347,38 +1347,29 @@ static V4IR::Type resolveQmlType(QQmlEnginePrivate *qmlEngine, V4IR::MemberExpre V4IR::Type result = V4IR::VarType; QQmlType *type = static_cast<QQmlType*>(resolver->data); - if (type->isSingleton()) { - if (type->isCompositeSingleton()) { - QQmlTypeData *tdata = qmlEngine->typeLoader.getType(type->singletonInstanceInfo()->url); - Q_ASSERT(tdata); - Q_ASSERT(tdata->isComplete()); - initMetaObjectResolver(resolver, qmlEngine->propertyCacheForType(tdata->compiledData()->metaTypeId)); - resolver->flags |= AllPropertiesAreFinal; - } else { - const QMetaObject *singletonMo = type->singletonInstanceInfo()->instanceMetaObject; - if (!singletonMo) { // We can only accelerate C++ singletons that were registered with their meta-type - resolver->clear(); - return result; - } - initMetaObjectResolver(resolver, qmlEngine->cache(singletonMo)); - resolver->flags |= LookupsIncludeEnums; + + if (member->name->constData()->isUpper()) { + bool ok = false; + int value = type->enumValue(*member->name, &ok); + if (ok) { + member->setEnumValue(value); + resolver->clear(); + return V4IR::SInt32Type; } + } + + if (type->isCompositeSingleton()) { + QQmlTypeData *tdata = qmlEngine->typeLoader.getType(type->singletonInstanceInfo()->url); + Q_ASSERT(tdata); + Q_ASSERT(tdata->isComplete()); + initMetaObjectResolver(resolver, qmlEngine->propertyCacheForType(tdata->compiledData()->metaTypeId)); + resolver->flags |= AllPropertiesAreFinal; + return resolver->resolveMember(qmlEngine, resolver, member); + } else if (const QMetaObject *attachedMeta = type->attachedPropertiesType()) { + QQmlPropertyCache *cache = qmlEngine->cache(attachedMeta); + initMetaObjectResolver(resolver, cache); + member->setAttachedPropertiesId(type->attachedPropertiesId()); return resolver->resolveMember(qmlEngine, resolver, member); - } else { - if (member->name->constData()->isUpper()) { - bool ok = false; - int value = type->enumValue(*member->name, &ok); - if (ok) { - member->setEnumValue(value); - resolver->clear(); - return V4IR::SInt32Type; - } - } else if (const QMetaObject *attachedMeta = type->attachedPropertiesType()) { - QQmlPropertyCache *cache = qmlEngine->cache(attachedMeta); - initMetaObjectResolver(resolver, cache); - member->setAttachedPropertiesId(type->attachedPropertiesId()); - return resolver->resolveMember(qmlEngine, resolver, member); - } } resolver->clear(); @@ -1573,14 +1564,14 @@ V4IR::Expr *JSCodeGen::fallbackNameLookup(const QString &name, int line, int col } else if (r.type) { V4IR::Name *typeName = _block->NAME(name, line, col); // Make sure the run-time loads this through the more efficient singleton getter. - typeName->qmlSingleton = r.type->isSingleton(); + typeName->qmlSingleton = r.type->isCompositeSingleton(); typeName->freeOfSideEffects = true; - V4IR::Temp *result = _block->TEMP(_block->newTemp()); - initQmlTypeResolver(&result->memberResolver, r.type); - _block->MOVE(result, typeName); - return _block->TEMP(result->index); + + result = _block->TEMP(result->index); + initQmlTypeResolver(&result->memberResolver, r.type); + return result; } else { Q_ASSERT(r.importNamespace); V4IR::Name *namespaceName = _block->NAME(name, line, col); diff --git a/tests/auto/qml/qqmlecmascript/data/singletontype/singletonWithEnum.qml b/tests/auto/qml/qqmlecmascript/data/singletontype/singletonWithEnum.qml new file mode 100644 index 0000000000..166f823667 --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/singletontype/singletonWithEnum.qml @@ -0,0 +1,9 @@ +import QtQml 2.0 +import Qt.test.singletonWithEnum 1.0 + +QtObject { + property int testValue: 0 + Component.onCompleted: { + testValue = SingletonWithEnum.TestValue; + } +} diff --git a/tests/auto/qml/qqmlecmascript/testtypes.cpp b/tests/auto/qml/qqmlecmascript/testtypes.cpp index 22fac2013e..eb06b9e57d 100644 --- a/tests/auto/qml/qqmlecmascript/testtypes.cpp +++ b/tests/auto/qml/qqmlecmascript/testtypes.cpp @@ -295,6 +295,11 @@ bool MyInheritedQmlObject::isItYouMyInheritedQmlObject(MyInheritedQmlObject *o) return o && o == theSingletonObject; } +static QObject *create_singletonWithEnum(QQmlEngine *, QJSEngine *) +{ + return new SingletonWithEnum; +} + void registerTypes() { qmlRegisterType<MyQmlObject>("Qt.test", 1,0, "MyQmlObjectAlias"); @@ -374,6 +379,8 @@ void registerTypes() qmlRegisterSingletonType<testImportOrderApi>("NamespaceAndType",1,0,"NamespaceAndType",testImportOrder_api); qmlRegisterSingletonType<testImportOrderApi>("Qt.test.importOrderApi1",1,0,"Data",testImportOrder_api1); qmlRegisterSingletonType<testImportOrderApi>("Qt.test.importOrderApi2",1,0,"Data",testImportOrder_api2); + + qmlRegisterSingletonType<SingletonWithEnum>("Qt.test.singletonWithEnum", 1, 0, "SingletonWithEnum", create_singletonWithEnum); } #include "testtypes.moc" diff --git a/tests/auto/qml/qqmlecmascript/testtypes.h b/tests/auto/qml/qqmlecmascript/testtypes.h index 556cc32fd3..2aef1d644d 100644 --- a/tests/auto/qml/qqmlecmascript/testtypes.h +++ b/tests/auto/qml/qqmlecmascript/testtypes.h @@ -1651,6 +1651,16 @@ public: QML_DECLARE_TYPEINFO(FallbackBindingsTypeObject, QML_HAS_ATTACHED_PROPERTIES) QML_DECLARE_TYPEINFO(FallbackBindingsTypeDerived, QML_HAS_ATTACHED_PROPERTIES) +class SingletonWithEnum : public QObject +{ + Q_OBJECT + Q_ENUMS(TestEnum) +public: + enum TestEnum { + TestValue = 42 + }; +}; + void registerTypes(); #endif // TESTTYPES_H diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp index 7b89709923..c45750caac 100644 --- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp +++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp @@ -320,6 +320,7 @@ private slots: void idsAsLValues(); void qtbug_34792(); void noCaptureWhenWritingProperty(); + void singletonWithEnum(); private: // static void propertyVarWeakRefCallback(v8::Persistent<v8::Value> object, void* parameter); @@ -7507,6 +7508,18 @@ void tst_qqmlecmascript::noCaptureWhenWritingProperty() QCOMPARE(obj->property("somePropertyEvaluated").toBool(), false); } +void tst_qqmlecmascript::singletonWithEnum() +{ + QQmlComponent component(&engine, testFileUrl("singletontype/singletonWithEnum.qml")); + QScopedPointer<QObject> obj(component.create()); + if (obj.isNull()) + qDebug() << component.errors().first().toString(); + QVERIFY(!obj.isNull()); + QVariant prop = obj->property("testValue"); + QVERIFY(prop.type() == QVariant::Int); + QCOMPARE(prop.toInt(), int(SingletonWithEnum::TestValue)); +} + QTEST_MAIN(tst_qqmlecmascript) #include "tst_qqmlecmascript.moc" |