aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2017-02-08 16:53:58 +0100
committerUlf Hermann <ulf.hermann@qt.io>2017-02-08 16:36:55 +0000
commitfedcd26ce80451e113b963d09cad97a3d21e4ab8 (patch)
treea9deacd2a0709e02b4ad221f361bd3c9dbd43417
parentade0ed7fa9ad06a1dc1312e7abad8baf20f7b756 (diff)
Use QQmlType for looking up enums, even on singletons
QQmlType has more information than the bare QMetaType. The optimizer already uses it for looking up enums, so some code would behave differently, depending on whether the optimizer was enabled or not. In some cases we cannot use QQmlType for lookup of enums because QQmlType might have been created with only a callback. The object only shows up later in that case. Then the only thing we can do is query the metatype. We can test this by adding an eval() because eval() disables optimization for the surrounding code. Task-number: QTBUG-58394 Change-Id: I8c90591b19fe1ed3e5339d877f9e6ec7c6f9aa73 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
-rw-r--r--src/qml/qml/qqmltypewrapper.cpp15
-rw-r--r--tests/auto/qml/qqmlmetatype/data/testExternalEnums.qml12
-rw-r--r--tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp33
3 files changed, 55 insertions, 5 deletions
diff --git a/src/qml/qml/qqmltypewrapper.cpp b/src/qml/qml/qqmltypewrapper.cpp
index fd1e9cc2be..be4ab68831 100644
--- a/src/qml/qml/qqmltypewrapper.cpp
+++ b/src/qml/qml/qqmltypewrapper.cpp
@@ -129,15 +129,20 @@ ReturnedValue QmlTypeWrapper::create(QV4::ExecutionEngine *engine, QObject *o, Q
return w.asReturnedValue();
}
-static int enumForSingleton(String *name, QObject *qobjectSingleton)
+static int enumForSingleton(QV4::ExecutionEngine *v4, String *name, QObject *qobjectSingleton,
+ QQmlType *type)
{
+ bool ok;
+ int value = type->enumValue(QQmlEnginePrivate::get(v4->qmlEngine()), name, &ok);
+ if (ok)
+ return value;
+
// ### Optimize
QByteArray enumName = name->toQString().toUtf8();
const QMetaObject *metaObject = qobjectSingleton->metaObject();
for (int ii = metaObject->enumeratorCount() - 1; ii >= 0; --ii) {
QMetaEnum e = metaObject->enumerator(ii);
- bool ok;
- int value = e.keyToValue(enumName.constData(), &ok);
+ value = e.keyToValue(enumName.constData(), &ok);
if (ok)
return value;
}
@@ -183,7 +188,7 @@ ReturnedValue QmlTypeWrapper::get(const Managed *m, String *name, bool *hasPrope
// check for enum value
const bool includeEnums = w->d()->mode == Heap::QmlTypeWrapper::IncludeEnums;
if (includeEnums && name->startsWithUpper()) {
- const int value = enumForSingleton(name, qobjectSingleton);
+ const int value = enumForSingleton(v4, name, qobjectSingleton, type);
if (value != -1)
return QV4::Primitive::fromInt32(value).asReturnedValue();
}
@@ -196,7 +201,7 @@ ReturnedValue QmlTypeWrapper::get(const Managed *m, String *name, bool *hasPrope
// Warn when attempting to access a lowercased enum value, singleton case
if (!ok && includeEnums && !name->startsWithUpper()) {
- const int value = enumForSingleton(name, qobjectSingleton);
+ const int value = enumForSingleton(v4, name, qobjectSingleton, type);
if (value != -1)
return throwLowercaseEnumError(v4, name, type);
}
diff --git a/tests/auto/qml/qqmlmetatype/data/testExternalEnums.qml b/tests/auto/qml/qqmlmetatype/data/testExternalEnums.qml
new file mode 100644
index 0000000000..8eb5616ab2
--- /dev/null
+++ b/tests/auto/qml/qqmlmetatype/data/testExternalEnums.qml
@@ -0,0 +1,12 @@
+import QtQml 2.2
+import x.y.z 1.0
+
+QtObject {
+ function x() {
+ eval("1");
+ return ExternalEnums.DocumentsLocation;
+ }
+
+ property var a: ExternalEnums.DocumentsLocation
+ property var b: x()
+}
diff --git a/tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp b/tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp
index 19cda21685..9fbd719d7b 100644
--- a/tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp
+++ b/tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp
@@ -26,6 +26,7 @@
**
****************************************************************************/
+#include <qstandardpaths.h>
#include <qtest.h>
#include <qqml.h>
#include <qqmlprivate.h>
@@ -53,6 +54,7 @@ private slots:
void invalidQmlTypeName();
void registrationType();
void compositeType();
+ void externalEnums();
void isList();
@@ -70,6 +72,20 @@ public:
};
QML_DECLARE_TYPE(TestType);
+class ExternalEnums : public QObject
+{
+ Q_OBJECT
+ Q_ENUMS(QStandardPaths::StandardLocation QStandardPaths::LocateOptions)
+public:
+ ExternalEnums(QObject *parent = nullptr) : QObject(parent) {}
+
+ static QObject *create(QQmlEngine *engine, QJSEngine *scriptEngine) {
+ Q_UNUSED(scriptEngine);
+ return new ExternalEnums(engine);
+ }
+};
+QML_DECLARE_TYPE(ExternalEnums);
+
QObject *testTypeProvider(QQmlEngine *engine, QJSEngine *scriptEngine)
{
Q_UNUSED(engine);
@@ -271,6 +287,23 @@ void tst_qqmlmetatype::compositeType()
QCOMPARE(type->sourceUrl(), testFileUrl("ImplicitType.qml"));
}
+void tst_qqmlmetatype::externalEnums()
+{
+ QQmlEngine engine;
+ qmlRegisterSingletonType<ExternalEnums>("x.y.z", 1, 0, "ExternalEnums", ExternalEnums::create);
+
+ QQmlComponent c(&engine, testFileUrl("testExternalEnums.qml"));
+ QObject *obj = c.create();
+ QVERIFY(obj);
+ QVariant a = obj->property("a");
+ QCOMPARE(a.type(), QVariant::Int);
+ QCOMPARE(a.toInt(), int(QStandardPaths::DocumentsLocation));
+ QVariant b = obj->property("b");
+ QCOMPARE(b.type(), QVariant::Int);
+ QCOMPARE(b.toInt(), int(QStandardPaths::DocumentsLocation));
+
+}
+
QTEST_MAIN(tst_qqmlmetatype)
#include "tst_qqmlmetatype.moc"