From ae0a2ea25714af603babe5aa0de364d1ebae1170 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Wed, 15 Jan 2014 17:29:04 +0100 Subject: [new compiler] Add support for QML list models List model definitions make heavy use of custom parsers, which requires AST access as well as a general port to the new QQmlCustomParser API. Additional fixes in the custom parser support were needed to pass all tests: * Fix support for AcceptsSignalHandlers and AcceptsAttachedProperties * Don't call setCustomData unless the compiler generated data earlier Change-Id: Ic42f8a890391267c94f63d35f055b60fdbf3c83d Reviewed-by: Lars Knoll --- src/qml/compiler/qqmlcodegenerator.cpp | 3 +- src/qml/compiler/qqmlcodegenerator_p.h | 3 +- src/qml/compiler/qqmltypecompiler.cpp | 66 ++++++++++++++++++++++++++++------ src/qml/compiler/qqmltypecompiler_p.h | 9 +++-- 4 files changed, 66 insertions(+), 15 deletions(-) (limited to 'src/qml/compiler') diff --git a/src/qml/compiler/qqmlcodegenerator.cpp b/src/qml/compiler/qqmlcodegenerator.cpp index 46bb07f8bc..629671399d 100644 --- a/src/qml/compiler/qqmlcodegenerator.cpp +++ b/src/qml/compiler/qqmlcodegenerator.cpp @@ -1640,7 +1640,8 @@ bool SignalHandlerConverter::convertSignalHandlerExpressionsToFunctionDeclaratio if (elementName.isEmpty()) continue; QQmlCompiledData::TypeReference *tr = unit->resolvedTypes.value(obj->inheritedTypeNameIndex); - if (tr && tr->type && tr->type->customParser()) + QQmlCustomParser *customParser = (tr && tr->type) ? tr->type->customParser() : 0; + if (customParser && !(customParser->flags() & QQmlCustomParser::AcceptsSignalHandlers)) continue; QQmlPropertyCache *cache = unit->propertyCaches.value(objectIndex); Q_ASSERT(cache); diff --git a/src/qml/compiler/qqmlcodegenerator_p.h b/src/qml/compiler/qqmlcodegenerator_p.h index f1050f4476..0b70701515 100644 --- a/src/qml/compiler/qqmlcodegenerator_p.h +++ b/src/qml/compiler/qqmlcodegenerator_p.h @@ -173,7 +173,8 @@ struct Pragma struct CompiledFunctionOrExpression { CompiledFunctionOrExpression() - : disableAcceleratedLookups(false) + : node(0) + , disableAcceleratedLookups(false) {} CompiledFunctionOrExpression(AST::Node *n) : node(n) diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index a684ebd959..00fc9c5925 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -201,7 +201,7 @@ bool QQmlTypeCompiler::compile() } // Sanity check property bindings - QQmlPropertyValidator validator(this); + QQmlPropertyValidator validator(this, runtimeFunctionIndices); if (!validator.validate()) return false; @@ -295,6 +295,16 @@ MemoryPool *QQmlTypeCompiler::memoryPool() return parsedQML->jsParserEngine.pool(); } +const QList &QQmlTypeCompiler::functions() const +{ + return parsedQML->functions; +} + +void QQmlTypeCompiler::setCustomParserBindings(const QVector &bindings) +{ + compiledData->customParserBindings = bindings; +} + QQmlCompilePass::QQmlCompilePass(QQmlTypeCompiler *typeCompiler) : compiler(typeCompiler) { @@ -1113,19 +1123,23 @@ bool QQmlComponentAndAliasResolver::resolveAliases() } -QQmlPropertyValidator::QQmlPropertyValidator(QQmlTypeCompiler *typeCompiler) +QQmlPropertyValidator::QQmlPropertyValidator(QQmlTypeCompiler *typeCompiler, const QVector &runtimeFunctionIndices) : QQmlCompilePass(typeCompiler) , qmlUnit(typeCompiler->qmlUnit()) , resolvedTypes(*typeCompiler->resolvedTypes()) , propertyCaches(typeCompiler->propertyCaches()) , objectIndexToIdPerComponent(*typeCompiler->objectIndexToIdPerComponent()) , customParserData(typeCompiler->customParserData()) + , runtimeFunctionIndices(runtimeFunctionIndices) { } bool QQmlPropertyValidator::validate() { - return validateObject(qmlUnit->indexOfRootObject); + if (!validateObject(qmlUnit->indexOfRootObject)) + return false; + compiler->setCustomParserBindings(customParserBindings); + return true; } const QQmlImports &QQmlPropertyValidator::imports() const @@ -1133,6 +1147,22 @@ const QQmlImports &QQmlPropertyValidator::imports() const return *compiler->imports(); } +AST::Node *QQmlPropertyValidator::astForBinding(int scriptIndex) const +{ + // #### + int reverseIndex = runtimeFunctionIndices.indexOf(scriptIndex); + if (reverseIndex == -1) + return 0; + return compiler->functions().value(reverseIndex).node; +} + +QQmlBinding::Identifier QQmlPropertyValidator::bindingIdentifier(const QV4::CompiledData::Binding *binding, QQmlCustomParser *) +{ + int id = customParserBindings.count(); + customParserBindings.append(binding->value.compiledScriptIndex); + return id; +} + bool QQmlPropertyValidator::validateObject(int objectIndex) { const QV4::CompiledData::Object *obj = qmlUnit->objectAt(objectIndex); @@ -1158,16 +1188,30 @@ bool QQmlPropertyValidator::validateObject(int objectIndex) const QV4::CompiledData::Binding *binding = obj->bindingTable(); for (quint32 i = 0; i < obj->nBindings; ++i, ++binding) { - if (binding->type >= QV4::CompiledData::Binding::Type_Object && !customParser) { - if (!validateObject(binding->value.objectIndex)) - return false; - } - if (binding->type == QV4::CompiledData::Binding::Type_AttachedProperty - || binding->type == QV4::CompiledData::Binding::Type_GroupProperty) { - if (customParser) + if (customParser) { + if (binding->type == QV4::CompiledData::Binding::Type_AttachedProperty) { + if (customParser->flags() & QQmlCustomParser::AcceptsAttachedProperties) { + customBindings << binding; + continue; + } + } else if ((binding->flags & QV4::CompiledData::Binding::IsSignalHandlerExpression) + && (!customParser->flags() & QQmlCustomParser::AcceptsSignalHandlers)) { customBindings << binding; - continue; + continue; + } else if (binding->type == QV4::CompiledData::Binding::Type_Object + || binding->type == QV4::CompiledData::Binding::Type_GroupProperty) { + customBindings << binding; + continue; + } + } + + if (binding->type >= QV4::CompiledData::Binding::Type_Object) { + if (!validateObject(binding->value.objectIndex)) + return false; + // Nothing further to check for attached properties. + if (binding->type == QV4::CompiledData::Binding::Type_AttachedProperty) + continue; } const QString name = stringAt(binding->propertyNameIndex); diff --git a/src/qml/compiler/qqmltypecompiler_p.h b/src/qml/compiler/qqmltypecompiler_p.h index e6a34fa376..4340279df8 100644 --- a/src/qml/compiler/qqmltypecompiler_p.h +++ b/src/qml/compiler/qqmltypecompiler_p.h @@ -92,6 +92,8 @@ struct QQmlTypeCompiler QHash > *objectIndexToIdPerComponent(); QHash *customParserData(); QQmlJS::MemoryPool *memoryPool(); + const QList &functions() const; + void setCustomParserBindings(const QVector &bindings); private: QList errors; @@ -176,13 +178,14 @@ class QQmlPropertyValidator : public QQmlCompilePass, public QQmlCustomParserCom { Q_DECLARE_TR_FUNCTIONS(QQmlPropertyValidator) public: - QQmlPropertyValidator(QQmlTypeCompiler *typeCompiler); + QQmlPropertyValidator(QQmlTypeCompiler *typeCompiler, const QVector &runtimeFunctionIndices); bool validate(); // Re-implemented for QQmlCustomParser virtual const QQmlImports &imports() const; - + virtual QQmlJS::AST::Node *astForBinding(int scriptIndex) const; + virtual QQmlBinding::Identifier bindingIdentifier(const QV4::CompiledData::Binding *binding, QQmlCustomParser *parser); private: bool validateObject(int objectIndex); @@ -194,6 +197,8 @@ private: const QVector &propertyCaches; const QHash > objectIndexToIdPerComponent; QHash *customParserData; + QVector customParserBindings; + const QVector &runtimeFunctionIndices; }; QT_END_NAMESPACE -- cgit v1.2.3