diff options
author | J-P Nurmi <jpnurmi@theqtcompany.com> | 2016-03-01 14:17:44 +0100 |
---|---|---|
committer | J-P Nurmi <jpnurmi@theqtcompany.com> | 2016-03-01 14:17:52 +0100 |
commit | 23712c568072422e49d41f039ad72c92fd117afe (patch) | |
tree | 423e84c8802074f9daa5422eb5c8c49b3074516a /src/qml | |
parent | ab2c5be35dd8f339ec39f52364625a53fa6d0ded (diff) | |
parent | 2b55b531b095a991376a26599d503223a67ae946 (diff) |
Merge remote-tracking branch 'origin/5.6' into 5.7
Conflicts:
src/plugins/qmltooling/qmldbg_native/qmldbg_native.pro
Change-Id: I3ca8f0422828191b7e19539c25f31f2d048e9f18
Diffstat (limited to 'src/qml')
-rw-r--r-- | src/qml/compiler/qqmltypecompiler.cpp | 24 | ||||
-rw-r--r-- | src/qml/compiler/qqmltypecompiler_p.h | 1 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4mathobject.cpp | 2 | ||||
-rw-r--r-- | src/qml/qml.pro | 9 | ||||
-rw-r--r-- | src/qml/qml/qqmltypewrapper.cpp | 74 | ||||
-rw-r--r-- | src/qml/types/qqmlbind.cpp | 4 |
6 files changed, 80 insertions, 34 deletions
diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index a708e90116..33716d57b8 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -1163,6 +1163,17 @@ struct StaticQtMetaObject : public QObject { return &staticQtMetaObject; } }; +bool QQmlEnumTypeResolver::assignEnumToBinding(QmlIR::Binding *binding, const QString &enumName, int enumValue, bool isQtObject) +{ + if (enumName.length() > 0 && enumName[0].isLower() && !isQtObject) { + COMPILE_EXCEPTION(binding, tr("Invalid property assignment: Enum value \"%1\" cannot start with a lowercase letter").arg(enumName)); + } + binding->type = QV4::CompiledData::Binding::Type_Number; + binding->value.d = (double)enumValue; + binding->flags |= QV4::CompiledData::Binding::IsResolvedEnum; + return true; +} + bool QQmlEnumTypeResolver::tryQualifiedEnumAssignment(const QmlIR::Object *obj, const QQmlPropertyCache *propertyCache, const QQmlPropertyData *prop, QmlIR::Binding *binding) { bool isIntProp = (prop->propType == QMetaType::Int) && !prop->isEnum(); @@ -1185,6 +1196,7 @@ bool QQmlEnumTypeResolver::tryQualifiedEnumAssignment(const QmlIR::Object *obj, return true; QHashedStringRef typeName(string.constData(), dot); + const bool isQtObject = (typeName == QLatin1String("Qt")); QString enumValue = string.mid(dot+1); if (isIntProp) { @@ -1192,16 +1204,15 @@ bool QQmlEnumTypeResolver::tryQualifiedEnumAssignment(const QmlIR::Object *obj, bool ok; int enumval = evaluateEnum(typeName.toString(), enumValue.toUtf8(), &ok); if (ok) { - binding->type = QV4::CompiledData::Binding::Type_Number; - binding->value.d = (double)enumval; - binding->flags |= QV4::CompiledData::Binding::IsResolvedEnum; + if (!assignEnumToBinding(binding, enumValue, enumval, isQtObject)) + return false; } return true; } QQmlType *type = 0; imports->resolveType(typeName, &type, 0, 0, 0); - if (!type && typeName != QLatin1String("Qt")) + if (!type && !isQtObject) return true; int value = 0; @@ -1234,10 +1245,7 @@ bool QQmlEnumTypeResolver::tryQualifiedEnumAssignment(const QmlIR::Object *obj, if (!ok) return true; - binding->type = QV4::CompiledData::Binding::Type_Number; - binding->value.d = (double)value; - binding->flags |= QV4::CompiledData::Binding::IsResolvedEnum; - return true; + return assignEnumToBinding(binding, enumValue, value, isQtObject); } int QQmlEnumTypeResolver::evaluateEnum(const QString &scope, const QByteArray &enumValue, bool *ok) const diff --git a/src/qml/compiler/qqmltypecompiler_p.h b/src/qml/compiler/qqmltypecompiler_p.h index 3404350ece..240f591f91 100644 --- a/src/qml/compiler/qqmltypecompiler_p.h +++ b/src/qml/compiler/qqmltypecompiler_p.h @@ -196,6 +196,7 @@ public: bool resolveEnumBindings(); private: + bool assignEnumToBinding(QmlIR::Binding *binding, const QString &enumName, int enumValue, bool isQtObject); bool tryQualifiedEnumAssignment(const QmlIR::Object *obj, const QQmlPropertyCache *propertyCache, const QQmlPropertyData *prop, QmlIR::Binding *binding); diff --git a/src/qml/jsruntime/qv4mathobject.cpp b/src/qml/jsruntime/qv4mathobject.cpp index f264ec028e..8c5e7d8be1 100644 --- a/src/qml/jsruntime/qv4mathobject.cpp +++ b/src/qml/jsruntime/qv4mathobject.cpp @@ -51,8 +51,6 @@ using namespace QV4; DEFINE_OBJECT_VTABLE(MathObject); -static const double qt_PI = 2.0 * ::asin(1.0); - Heap::MathObject::MathObject() { Scope scope(internalClass->engine); diff --git a/src/qml/qml.pro b/src/qml/qml.pro index d75262bf0b..e30c39c8b9 100644 --- a/src/qml/qml.pro +++ b/src/qml/qml.pro @@ -11,9 +11,6 @@ solaris-cc*:QMAKE_CXXFLAGS_RELEASE -= -O2 # Ensure this gcc optimization is switched off for mips platforms to avoid trouble with JIT. gcc:isEqual(QT_ARCH, "mips"): QMAKE_CXXFLAGS += -fno-reorder-blocks -MODULE_PLUGIN_TYPES = \ - qmltooling - exists("qqml_enable_gcov") { QMAKE_CXXFLAGS = -fprofile-arcs -ftest-coverage -fno-elide-constructors LIBS_PRIVATE += -lgcov @@ -29,8 +26,6 @@ greaterThan(QT_CLANG_MAJOR_VERSION, 3)|greaterThan(QT_CLANG_MINOR_VERSION, 3)| \ if(equals(QT_APPLE_CLANG_MAJOR_VERSION, 5):greaterThan(QT_APPLE_CLANG_MINOR_VERSION, 0)): \ WERROR += -Wno-error=unused-const-variable -load(qt_module) - HEADERS += qtqmlglobal.h \ qtqmlglobal_p.h @@ -46,3 +41,7 @@ include(qml/qml.pri) include(debugger/debugger.pri) include(animations/animations.pri) include(types/types.pri) + +MODULE_PLUGIN_TYPES = \ + qmltooling +load(qt_module) diff --git a/src/qml/qml/qqmltypewrapper.cpp b/src/qml/qml/qqmltypewrapper.cpp index 2f2c6cf7dc..33fe655368 100644 --- a/src/qml/qml/qqmltypewrapper.cpp +++ b/src/qml/qml/qqmltypewrapper.cpp @@ -125,6 +125,28 @@ ReturnedValue QmlTypeWrapper::create(QV4::ExecutionEngine *engine, QObject *o, Q return w.asReturnedValue(); } +static int enumForSingleton(String *name, QObject *qobjectSingleton) +{ + // ### 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); + if (ok) + return value; + } + return -1; +} + +static ReturnedValue throwLowercaseEnumError(QV4::ExecutionEngine *v4, String *name, QQmlType *type) +{ + const QString message = + QStringLiteral("Cannot access enum value '%1' of '%2', enum values need to start with an uppercase letter.") + .arg(name->toQString()).arg(QLatin1String(type->typeName())); + return v4->throwTypeError(message); +} ReturnedValue QmlTypeWrapper::get(const Managed *m, String *name, bool *hasProperty) { @@ -141,9 +163,9 @@ ReturnedValue QmlTypeWrapper::get(const Managed *m, String *name, bool *hasPrope QQmlContextData *context = v4->callingQmlContext(); QObject *object = w->d()->object; + QQmlType *type = w->d()->type; - if (w->d()->type) { - QQmlType *type = w->d()->type; + if (type) { // singleton types are handled differently to other types. if (type->isSingleton()) { @@ -153,24 +175,29 @@ ReturnedValue QmlTypeWrapper::get(const Managed *m, String *name, bool *hasPrope QObject *qobjectSingleton = siinfo->qobjectApi(e); if (qobjectSingleton) { + // check for enum value - if (name->startsWithUpper()) { - if (w->d()->mode == Heap::QmlTypeWrapper::IncludeEnums) { - // ### 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); - if (ok) - return QV4::Primitive::fromInt32(value).asReturnedValue(); - } - } + const bool includeEnums = w->d()->mode == Heap::QmlTypeWrapper::IncludeEnums; + if (includeEnums && name->startsWithUpper()) { + const int value = enumForSingleton(name, qobjectSingleton); + if (value != -1) + return QV4::Primitive::fromInt32(value).asReturnedValue(); } // check for property. - return QV4::QObjectWrapper::getQmlProperty(v4, context, qobjectSingleton, name, QV4::QObjectWrapper::IgnoreRevision, hasProperty); + bool ok; + const ReturnedValue result = QV4::QObjectWrapper::getQmlProperty(v4, context, qobjectSingleton, name, QV4::QObjectWrapper::IgnoreRevision, &ok); + if (hasProperty) + *hasProperty = ok; + + // Warn when attempting to access a lowercased enum value, singleton case + if (!ok && includeEnums && !name->startsWithUpper()) { + const int value = enumForSingleton(name, qobjectSingleton); + if (value != -1) + return throwLowercaseEnumError(v4, name, type); + } + + return result; } else if (!siinfo->scriptApi(e).isUndefined()) { // NOTE: if used in a binding, changes will not trigger re-evaluation since non-NOTIFYable. QV4::ScopedObject o(scope, QJSValuePrivate::convertedToValue(v4, siinfo->scriptApi(e))); @@ -227,9 +254,20 @@ ReturnedValue QmlTypeWrapper::get(const Managed *m, String *name, bool *hasPrope Q_ASSERT(!"Unreachable"); } + bool ok = false; + const ReturnedValue result = Object::get(m, name, &ok); if (hasProperty) - *hasProperty = false; - return Object::get(m, name, hasProperty); + *hasProperty = ok; + + // Warn when attempting to access a lowercased enum value, non-singleton case + if (!ok && type && !type->isSingleton() && !name->startsWithUpper()) { + bool enumOk = false; + type->enumValue(QQmlEnginePrivate::get(v4->qmlEngine()), name, &enumOk); + if (enumOk) + return throwLowercaseEnumError(v4, name, type); + } + + return result; } diff --git a/src/qml/types/qqmlbind.cpp b/src/qml/types/qqmlbind.cpp index e2063dee7d..ed9a8533c0 100644 --- a/src/qml/types/qqmlbind.cpp +++ b/src/qml/types/qqmlbind.cpp @@ -75,7 +75,7 @@ public: void QQmlBindPrivate::validate(QObject *binding) const { - if (!obj) + if (!obj || (when.isValid() && !when)) return; if (!prop.isValid()) { @@ -185,6 +185,8 @@ void QQmlBind::setWhen(bool v) return; d->when = v; + if (v && d->componentComplete) + d->validate(this); eval(); } |