diff options
author | Simon Hausmann <simon.hausmann@digia.com> | 2014-02-04 10:21:33 +0100 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2014-02-04 18:29:04 +0100 |
commit | 50269fc37a6a50864bf08b25327a05f2ab885a1a (patch) | |
tree | e04689e2afc058c404b70dbf0ccc4266df36664a | |
parent | 63b8285a2d528be82015133bd72a91c17c3a460b (diff) |
[new compiler] Fix order of alias vs non-alias bindings
qqmlecmascript's alias binding tests expect bindings on non-aliases to be bound
before bindings on aliases, as the latter may override parts of the former.
Change-Id: I23d25c2b7a449f0ed4672ef6865c4a7ef0ed0129
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
-rw-r--r-- | src/qml/compiler/qqmlcodegenerator.cpp | 3 | ||||
-rw-r--r-- | src/qml/compiler/qqmltypecompiler.cpp | 36 | ||||
-rw-r--r-- | src/qml/compiler/qqmltypecompiler_p.h | 12 | ||||
-rw-r--r-- | src/qml/compiler/qv4compileddata_p.h | 6 |
4 files changed, 55 insertions, 2 deletions
diff --git a/src/qml/compiler/qqmlcodegenerator.cpp b/src/qml/compiler/qqmlcodegenerator.cpp index 04db46667e..f933465100 100644 --- a/src/qml/compiler/qqmlcodegenerator.cpp +++ b/src/qml/compiler/qqmlcodegenerator.cpp @@ -1280,10 +1280,11 @@ QV4::CompiledData::QmlUnit *QmlUnitGenerator::generate(ParsedQML &output, const } char *bindingPtr = objectPtr + objectToWrite->offsetToBindings; - bindingPtr = writeBindings(bindingPtr, o, runtimeFunctionIndices, &QV4::CompiledData::Binding::isValueBinding); + bindingPtr = writeBindings(bindingPtr, o, runtimeFunctionIndices, &QV4::CompiledData::Binding::isValueBindingNoAlias); bindingPtr = writeBindings(bindingPtr, o, runtimeFunctionIndices, &QV4::CompiledData::Binding::isSignalHandler); bindingPtr = writeBindings(bindingPtr, o, runtimeFunctionIndices, &QV4::CompiledData::Binding::isAttachedProperty); bindingPtr = writeBindings(bindingPtr, o, runtimeFunctionIndices, &QV4::CompiledData::Binding::isGroupProperty); + bindingPtr = writeBindings(bindingPtr, o, runtimeFunctionIndices, &QV4::CompiledData::Binding::isValueBindingToAlias); Q_ASSERT((bindingPtr - objectToWrite->offsetToBindings - objectPtr) / sizeof(QV4::CompiledData::Binding) == unsigned(o->bindingCount())); quint32 *signalOffsetTable = reinterpret_cast<quint32*>(objectPtr + objectToWrite->offsetToSignals); diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index 6197ddf5d0..ea99c51bcf 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -156,6 +156,11 @@ bool QQmlTypeCompiler::compile() return false; } + { + QQmlAliasAnnotator annotator(this); + annotator.annotateBindingsToAliases(); + } + // Collect imported scripts const QList<QQmlTypeData::ScriptReference> &scripts = typeData->resolvedScripts(); compiledData->scripts.reserve(scripts.count()); @@ -963,6 +968,37 @@ int QQmlEnumTypeResolver::evaluateEnum(const QString &scope, const QByteArray &e return -1; } + +QQmlAliasAnnotator::QQmlAliasAnnotator(QQmlTypeCompiler *typeCompiler) + : QQmlCompilePass(typeCompiler) + , qmlObjects(*typeCompiler->qmlObjects()) + , propertyCaches(typeCompiler->propertyCaches()) +{ +} + +void QQmlAliasAnnotator::annotateBindingsToAliases() +{ + for (int i = 0; i < qmlObjects.count(); ++i) { + QQmlPropertyCache *propertyCache = propertyCaches.at(i); + if (!propertyCache) + continue; + + const QmlObject *obj = qmlObjects.at(i); + + PropertyResolver resolver(propertyCache); + QQmlPropertyData *defaultProperty = obj->indexOfDefaultProperty != -1 ? propertyCache->parent()->defaultProperty() : propertyCache->defaultProperty(); + + for (QtQml::Binding *binding = obj->firstBinding(); binding; binding = binding->next) { + if (!binding->isValueBinding()) + continue; + bool notInRevision = false; + QQmlPropertyData *pd = binding->propertyNameIndex != 0 ? resolver.property(stringAt(binding->propertyNameIndex), ¬InRevision) : defaultProperty; + if (pd && pd->isAlias()) + binding->flags |= QV4::CompiledData::Binding::IsBindingToAlias; + } + } +} + QQmlComponentAndAliasResolver::QQmlComponentAndAliasResolver(QQmlTypeCompiler *typeCompiler) : QQmlCompilePass(typeCompiler) , enginePrivate(typeCompiler->enginePrivate()) diff --git a/src/qml/compiler/qqmltypecompiler_p.h b/src/qml/compiler/qqmltypecompiler_p.h index 51ac36667e..2e97d13481 100644 --- a/src/qml/compiler/qqmltypecompiler_p.h +++ b/src/qml/compiler/qqmltypecompiler_p.h @@ -163,6 +163,18 @@ private: QHash<int, QQmlCompiledData::TypeReference *> *resolvedTypes; }; +// Annotate properties bound to aliases with a flag +class QQmlAliasAnnotator : public QQmlCompilePass +{ +public: + QQmlAliasAnnotator(QQmlTypeCompiler *typeCompiler); + + void annotateBindingsToAliases(); +private: + const QList<QtQml::QmlObject*> &qmlObjects; + const QVector<QQmlPropertyCache *> propertyCaches; +}; + class QQmlComponentAndAliasResolver : public QQmlCompilePass { Q_DECLARE_TR_FUNCTIONS(QQmlAnonymousComponentResolver) diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h index edb1737648..94ea4bdc90 100644 --- a/src/qml/compiler/qv4compileddata_p.h +++ b/src/qml/compiler/qv4compileddata_p.h @@ -302,7 +302,8 @@ struct Q_QML_EXPORT Binding IsOnAssignment = 0x4, InitializerForReadOnlyDeclaration = 0x8, IsResolvedEnum = 0x10, - IsListItem = 0x20 + IsListItem = 0x20, + IsBindingToAlias = 0x40 }; quint32 flags : 16; @@ -329,6 +330,9 @@ struct Q_QML_EXPORT Binding return true; } + bool isValueBindingNoAlias() const { return isValueBinding() && !(flags & IsBindingToAlias); } + bool isValueBindingToAlias() const { return isValueBinding() && (flags & IsBindingToAlias); } + bool isSignalHandler() const { if (flags & IsSignalHandlerExpression || flags & IsSignalHandlerObject) { |