aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/qml/compiler/qqmlirbuilder.cpp19
-rw-r--r--src/qml/compiler/qqmlirbuilder_p.h1
-rw-r--r--src/qml/compiler/qqmltypecompiler.cpp57
-rw-r--r--src/qml/compiler/qqmltypecompiler_p.h17
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);