diff options
| -rw-r--r-- | src/qml/compiler/qqmlirbuilder.cpp | 19 | ||||
| -rw-r--r-- | src/qml/compiler/qqmlirbuilder_p.h | 1 | ||||
| -rw-r--r-- | src/qml/compiler/qqmltypecompiler.cpp | 57 | ||||
| -rw-r--r-- | src/qml/compiler/qqmltypecompiler_p.h | 17 |
4 files changed, 87 insertions, 7 deletions
diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp index e85703e9aa..1c10a49fd1 100644 --- a/src/qml/compiler/qqmlirbuilder.cpp +++ b/src/qml/compiler/qqmlirbuilder.cpp @@ -188,6 +188,17 @@ void Object::insertSorted(Binding *b) bindings->insertAfter(insertionPoint, b); } +QString Object::bindingAsString(Document *doc, int scriptIndex) const +{ + CompiledFunctionOrExpression *foe = functionsAndExpressions->slowAt(scriptIndex); + QQmlJS::AST::Node *node = foe->node; + if (QQmlJS::AST::ExpressionStatement *exprStmt = QQmlJS::AST::cast<QQmlJS::AST::ExpressionStatement *>(node)) + node = exprStmt->expression; + QQmlJS::AST::SourceLocation start = node->firstSourceLocation(); + QQmlJS::AST::SourceLocation end = node->lastSourceLocation(); + return doc->code.mid(start.offset, end.offset + end.length - start.offset); +} + QStringList Signal::parameterStringList(const QV4::Compiler::StringTableGenerator *stringPool) const { QStringList result; @@ -1252,11 +1263,9 @@ void IRBuilder::setBindingValue(QV4::CompiledData::Binding *binding, QQmlJS::AST expr->disableAcceleratedLookups = false; const int index = bindingsTarget()->functionsAndExpressions->append(expr); binding->value.compiledScriptIndex = index; - - QQmlJS::AST::Node *nodeForString = statement; - if (exprStmt) - nodeForString = exprStmt->expression; - binding->stringIndex = registerString(asStringRef(nodeForString).toString()); + // We don't need to store the binding script as string, except for script strings + // and types with custom parsers. Those will be added later in the compilation phase. + binding->stringIndex = emptyStringIndex; } } diff --git a/src/qml/compiler/qqmlirbuilder_p.h b/src/qml/compiler/qqmlirbuilder_p.h index cd67c52ed7..4ea7e05639 100644 --- a/src/qml/compiler/qqmlirbuilder_p.h +++ b/src/qml/compiler/qqmlirbuilder_p.h @@ -283,6 +283,7 @@ public: Binding *findBinding(quint32 nameIndex) const; Binding *unlinkBinding(Binding *before, Binding *binding) { return bindings->unlink(before, binding); } void insertSorted(Binding *b); + QString bindingAsString(Document *doc, int scriptIndex) const; PoolList<CompiledFunctionOrExpression> *functionsAndExpressions; FixedPoolArray<int> *runtimeFunctionIndices; diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index d79143fdc3..b44d4e285a 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -167,6 +167,11 @@ bool QQmlTypeCompiler::compile() } { + QQmlCustomParserScriptIndexer cpi(this); + cpi.annotateBindingsWithScriptStrings(); + } + + { QQmlAliasAnnotator annotator(this); annotator.annotateBindingsToAliases(); } @@ -403,6 +408,11 @@ void QQmlTypeCompiler::setDeferredBindingsPerObject(const QHash<int, QBitArray> compiledData->deferredBindingsPerObject = deferredBindingsPerObject; } +QString QQmlTypeCompiler::bindingAsString(const QmlIR::Object *object, int scriptIndex) const +{ + return object->bindingAsString(document, scriptIndex); +} + QQmlCompilePass::QQmlCompilePass(QQmlTypeCompiler *typeCompiler) : compiler(typeCompiler) { @@ -1144,8 +1154,8 @@ bool QQmlEnumTypeResolver::tryQualifiedEnumAssignment(const QmlIR::Object *obj, COMPILE_EXCEPTION(binding, tr("Invalid property assignment: \"%1\" is a read-only property").arg(stringAt(binding->propertyNameIndex))); Q_ASSERT(binding->type = QV4::CompiledData::Binding::Type_Script); - QString string = stringAt(binding->stringIndex); - if (!string.at(0).isUpper()) + const QString string = compiler->bindingAsString(obj, binding->value.compiledScriptIndex); + if (!string.constData()->isUpper()) return true; int dot = string.indexOf(QLatin1Char('.')); @@ -1234,6 +1244,35 @@ int QQmlEnumTypeResolver::evaluateEnum(const QString &scope, const QByteArray &e return -1; } +QQmlCustomParserScriptIndexer::QQmlCustomParserScriptIndexer(QQmlTypeCompiler *typeCompiler) + : QQmlCompilePass(typeCompiler) + , qmlObjects(*typeCompiler->qmlObjects()) + , customParsers(typeCompiler->customParserCache()) +{ +} + +void QQmlCustomParserScriptIndexer::annotateBindingsWithScriptStrings() +{ + scanObjectRecursively(compiler->rootObjectIndex()); +} + +void QQmlCustomParserScriptIndexer::scanObjectRecursively(int objectIndex, bool annotateScriptBindings) +{ + const QmlIR::Object * const obj = qmlObjects.at(objectIndex); + if (!annotateScriptBindings) + annotateScriptBindings = customParsers.contains(obj->inheritedTypeNameIndex); + for (QmlIR::Binding *binding = obj->firstBinding(); binding; binding = binding->next) { + if (binding->type >= QV4::CompiledData::Binding::Type_Object) { + scanObjectRecursively(binding->value.objectIndex, annotateScriptBindings); + continue; + } else if (binding->type != QV4::CompiledData::Binding::Type_Script) + continue; + if (!annotateScriptBindings) + continue; + const QString script = compiler->bindingAsString(obj, binding->value.compiledScriptIndex); + binding->stringIndex = compiler->registerString(script); + } +} QQmlAliasAnnotator::QQmlAliasAnnotator(QQmlTypeCompiler *typeCompiler) : QQmlCompilePass(typeCompiler) @@ -1297,6 +1336,9 @@ void QQmlScriptStringScanner::scan() QmlIR::CompiledFunctionOrExpression *foe = obj->functionsAndExpressions->slowAt(binding->value.compiledScriptIndex); if (foe) foe->disableAcceleratedLookups = true; + + QString script = compiler->bindingAsString(obj, binding->value.compiledScriptIndex); + binding->stringIndex = compiler->registerString(script); } } } @@ -1702,6 +1744,17 @@ QQmlBinding::Identifier QQmlPropertyValidator::bindingIdentifier(const QV4::Comp return id; } +QString QQmlPropertyValidator::bindingAsString(int objectIndex, const QV4::CompiledData::Binding *binding) const +{ + const QmlIR::Object *object = compiler->qmlObjects()->value(objectIndex); + if (!object) + return QString(); + int reverseIndex = object->runtimeFunctionIndices->indexOf(binding->value.compiledScriptIndex); + if (reverseIndex == -1) + return QString(); + return compiler->bindingAsString(object, reverseIndex); +} + typedef QVarLengthArray<const QV4::CompiledData::Binding *, 8> GroupPropertyVector; static bool compareNameIndices(const QV4::CompiledData::Binding *binding, quint32 name) diff --git a/src/qml/compiler/qqmltypecompiler_p.h b/src/qml/compiler/qqmltypecompiler_p.h index 3b449bf9bd..fb8ac94fcd 100644 --- a/src/qml/compiler/qqmltypecompiler_p.h +++ b/src/qml/compiler/qqmltypecompiler_p.h @@ -105,6 +105,8 @@ public: const QHash<int, QQmlCustomParser*> &customParserCache() const { return customParsers; } + QString bindingAsString(const QmlIR::Object *object, int scriptIndex) const; + private: QList<QQmlError> errors; QQmlEnginePrivate *engine; @@ -195,6 +197,20 @@ private: QHash<int, QQmlCompiledData::TypeReference *> *resolvedTypes; }; +class QQmlCustomParserScriptIndexer: public QQmlCompilePass +{ +public: + QQmlCustomParserScriptIndexer(QQmlTypeCompiler *typeCompiler); + + void annotateBindingsWithScriptStrings(); + +private: + void scanObjectRecursively(int objectIndex, bool annotateScriptBindings = false); + + const QList<QmlIR::Object*> &qmlObjects; + const QHash<int, QQmlCustomParser*> &customParsers; +}; + // Annotate properties bound to aliases with a flag class QQmlAliasAnnotator : public QQmlCompilePass { @@ -267,6 +283,7 @@ public: // Re-implemented for QQmlCustomParser virtual const QQmlImports &imports() const; virtual QQmlBinding::Identifier bindingIdentifier(const QV4::CompiledData::Binding *binding, QQmlCustomParser *parser); + virtual QString bindingAsString(int objectIndex, const QV4::CompiledData::Binding *binding) const; private: bool validateObject(int objectIndex, const QV4::CompiledData::Binding *instantiatingBinding, bool populatingValueTypeGroupProperty = false); |
