From 2f4479857d2b68f8cd3267b2f2b3c652ada431ed Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Mon, 20 May 2019 16:09:13 +0200 Subject: 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 --- .../auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp | 50 ++++++++++++++++++++++ 1 file changed, 50 insertions(+) (limited to 'tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp') diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp index 007ad99655..c24c495b13 100644 --- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp +++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp @@ -369,6 +369,7 @@ private slots: void intMinDividedByMinusOne(); void undefinedPropertiesInObjectWrapper(); void hugeRegexpQuantifiers(); + void singletonTypeWrapperLookup(); private: // static void propertyVarWeakRefCallback(v8::Persistent object, void* parameter); @@ -8979,6 +8980,55 @@ void tst_qqmlecmascript::hugeRegexpQuantifiers() QVERIFY(value.isRegExp()); } +struct CppSingleton1 : public QObject +{ + Q_OBJECT + Q_PROPERTY(int testVar MEMBER testVar CONSTANT) +public: + const int testVar = 0; +}; + +struct CppSingleton2 : public QObject +{ + Q_OBJECT + Q_PROPERTY(int testVar MEMBER testVar CONSTANT) +public: + const int testVar = 1; +}; + +void tst_qqmlecmascript::singletonTypeWrapperLookup() +{ + QQmlEngine engine; + + auto singletonTypeId1 = qmlRegisterSingletonType("Test.Singletons", 1, 0, "CppSingleton1", + [](QQmlEngine *, QJSEngine *) -> QObject * { + return new CppSingleton1; + }); + + auto singletonTypeId2 = qmlRegisterSingletonType("Test.Singletons", 1, 0, "CppSingleton2", + [](QQmlEngine *, QJSEngine *) -> QObject * { + return new CppSingleton2; + }); + + auto cleanup = qScopeGuard([&]() { + qmlUnregisterType(singletonTypeId1); + qmlUnregisterType(singletonTypeId2); + }); + + QQmlComponent component(&engine, testFileUrl("SingletonLookupTest.qml")); + QScopedPointer test(component.create()); + QVERIFY2(!test.isNull(), qPrintable(component.errorString())); + + auto singleton1 = engine.singletonInstance(singletonTypeId1); + QVERIFY(singleton1); + + auto singleton2 = engine.singletonInstance(singletonTypeId2); + QVERIFY(singleton2); + + QCOMPARE(test->property("firstLookup").toInt(), singleton1->testVar); + QCOMPARE(test->property("secondLookup").toInt(), singleton2->testVar); +} + QTEST_MAIN(tst_qqmlecmascript) #include "tst_qqmlecmascript.moc" -- cgit v1.2.3