diff options
author | Simon Hausmann <simon.hausmann@qt.io> | 2018-01-30 09:47:06 +0100 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@qt.io> | 2018-01-31 08:07:41 +0000 |
commit | 406ef45aaa3e84eb402a451eb4900afa17d20ea9 (patch) | |
tree | b60d76c4bb6516857d48d8e00244825cc31f91dc | |
parent | eec58534ab9c3fae74a1b4cb0861d4b40253cd2d (diff) |
Fix exposure of -1 as enum value in QML exposed C++ singletons
When a C++ singleton has an enum with the value -1, we would expose that
value correctly when taking the accelerated property access code path in
the optimizer, but when going through the slower QQmlTypeWrapper we
would return undefined. This turned out to be a silly logic error that
assumed that -1 is not a valid value for an enum and instead indicates
an enum value not present.
[ChangeLog][Qml] Fix -1 as enum value in QML exposed C++ singletons
showing up as undefined.
Task-number: QTBUG-66067
Change-Id: Ib66dad7a4b59822b2c40ad6bd9af4b72469582e9
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Reviewed-by: Michael Brasser <michael.brasser@live.com>
-rw-r--r-- | src/qml/qml/qqmltypewrapper.cpp | 22 | ||||
-rw-r--r-- | tests/auto/qml/qqmlecmascript/testtypes.h | 3 | ||||
-rw-r--r-- | tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp | 9 |
3 files changed, 23 insertions, 11 deletions
diff --git a/src/qml/qml/qqmltypewrapper.cpp b/src/qml/qml/qqmltypewrapper.cpp index d4e1910a72..0fae76066d 100644 --- a/src/qml/qml/qqmltypewrapper.cpp +++ b/src/qml/qml/qqmltypewrapper.cpp @@ -133,11 +133,11 @@ ReturnedValue QmlTypeWrapper::create(QV4::ExecutionEngine *engine, QObject *o, Q } static int enumForSingleton(QV4::ExecutionEngine *v4, String *name, QObject *qobjectSingleton, - const QQmlType &type) + const QQmlType &type, bool *ok) { - bool ok; - int value = type.enumValue(QQmlEnginePrivate::get(v4->qmlEngine()), name, &ok); - if (ok) + Q_ASSERT(ok != nullptr); + int value = type.enumValue(QQmlEnginePrivate::get(v4->qmlEngine()), name, ok); + if (*ok) return value; // ### Optimize @@ -145,10 +145,11 @@ static int enumForSingleton(QV4::ExecutionEngine *v4, String *name, QObject *qob const QMetaObject *metaObject = qobjectSingleton->metaObject(); for (int ii = metaObject->enumeratorCount() - 1; ii >= 0; --ii) { QMetaEnum e = metaObject->enumerator(ii); - value = e.keyToValue(enumName.constData(), &ok); - if (ok) + value = e.keyToValue(enumName.constData(), ok); + if (*ok) return value; } + *ok = false; return -1; } @@ -191,8 +192,9 @@ 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(v4, name, qobjectSingleton, type); - if (value != -1) + bool ok = false; + const int value = enumForSingleton(v4, name, qobjectSingleton, type, &ok); + if (ok) return QV4::Primitive::fromInt32(value).asReturnedValue(); } @@ -204,8 +206,8 @@ 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(v4, name, qobjectSingleton, type); - if (value != -1) + enumForSingleton(v4, name, qobjectSingleton, type, &ok); + if (ok) return throwLowercaseEnumError(v4, name, type); } diff --git a/tests/auto/qml/qqmlecmascript/testtypes.h b/tests/auto/qml/qqmlecmascript/testtypes.h index e15a05a00c..ec20714c51 100644 --- a/tests/auto/qml/qqmlecmascript/testtypes.h +++ b/tests/auto/qml/qqmlecmascript/testtypes.h @@ -1670,7 +1670,8 @@ class SingletonWithEnum : public QObject Q_ENUMS(TestEnum) public: enum TestEnum { - TestValue = 42 + TestValue = 42, + TestValue_MinusOne = -1 }; }; diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp index 14c2aa18bf..db7ec87c02 100644 --- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp +++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp @@ -7914,6 +7914,15 @@ void tst_qqmlecmascript::singletonWithEnum() QVariant prop = obj->property("testValue"); QCOMPARE(prop.type(), QVariant::Int); QCOMPARE(prop.toInt(), int(SingletonWithEnum::TestValue)); + + { + QQmlExpression expr(qmlContext(obj.data()), obj.data(), "SingletonWithEnum.TestValue_MinusOne"); + bool valueUndefined = false; + QVariant result = expr.evaluate(&valueUndefined); + QVERIFY2(!expr.hasError(), qPrintable(expr.error().toString())); + QVERIFY(!valueUndefined); + QCOMPARE(result.toInt(), -1); + } } void tst_qqmlecmascript::lazyBindingEvaluation() |