aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/qml/compiler/qqmltypecompiler.cpp7
-rw-r--r--src/qml/compiler/qqmltypecompiler_p.h6
-rw-r--r--src/qml/qml/qqmlcompiler.cpp50
-rw-r--r--src/qml/qml/qqmlcompiler_p.h8
-rw-r--r--src/qml/qml/qqmlcustomparser.cpp39
-rw-r--r--src/qml/qml/qqmlcustomparser_p.h14
6 files changed, 89 insertions, 35 deletions
diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp
index 56351b0013..d6dde63d4b 100644
--- a/src/qml/compiler/qqmltypecompiler.cpp
+++ b/src/qml/compiler/qqmltypecompiler.cpp
@@ -1120,6 +1120,11 @@ bool QQmlPropertyValidator::validate()
return true;
}
+const QQmlImports &QQmlPropertyValidator::imports() const
+{
+ return *compiler->imports();
+}
+
bool QQmlPropertyValidator::validateObject(const QV4::CompiledData::Object *obj, int objectIndex, QQmlPropertyCache *propertyCache)
{
QQmlCustomParser *customParser = 0;
@@ -1181,7 +1186,9 @@ bool QQmlPropertyValidator::validateObject(const QV4::CompiledData::Object *obj,
if (customParser && !customBindings.isEmpty()) {
customParser->clearErrors();
+ customParser->compiler = this;
QByteArray data = customParser->compile(qmlUnit, customBindings);
+ customParser->compiler = 0;
customParserData->insert(objectIndex, data);
const QList<QQmlError> parserErrors = customParser->errors();
if (!parserErrors.isEmpty()) {
diff --git a/src/qml/compiler/qqmltypecompiler_p.h b/src/qml/compiler/qqmltypecompiler_p.h
index bd136ea9e6..248cd12796 100644
--- a/src/qml/compiler/qqmltypecompiler_p.h
+++ b/src/qml/compiler/qqmltypecompiler_p.h
@@ -172,7 +172,7 @@ protected:
QHash<int, QHash<int, int> > *objectIndexToIdPerComponent;
};
-class QQmlPropertyValidator : public QQmlCompilePass
+class QQmlPropertyValidator : public QQmlCompilePass, public QQmlCustomParserCompilerBackend
{
Q_DECLARE_TR_FUNCTIONS(QQmlPropertyValidator)
public:
@@ -180,6 +180,10 @@ public:
bool validate();
+ // Re-implemented for QQmlCustomParser
+ virtual const QQmlImports &imports() const;
+
+
private:
bool validateObject(const QV4::CompiledData::Object *obj, int objectIndex, QQmlPropertyCache *propertyCache);
diff --git a/src/qml/qml/qqmlcompiler.cpp b/src/qml/qml/qqmlcompiler.cpp
index 6717c97d88..069345ecd3 100644
--- a/src/qml/qml/qqmlcompiler.cpp
+++ b/src/qml/qml/qqmlcompiler.cpp
@@ -2614,7 +2614,7 @@ bool QQmlCompiler::testQualifiedEnumAssignment(QQmlScript::Property *prop,
if (isIntProp) {
// Allow enum assignment to ints.
bool ok;
- int enumval = evaluateEnum(typeName, enumValue.toUtf8(), &ok);
+ int enumval = evaluateEnum(typeName.toString(), enumValue.toUtf8(), &ok);
if (ok) {
v->type = Value::Literal;
v->value = QQmlScript::Variant((double)enumval);
@@ -2665,46 +2665,38 @@ bool QQmlCompiler::testQualifiedEnumAssignment(QQmlScript::Property *prop,
return true;
}
-// Similar logic to above, but not knowing target property.
-int QQmlCompiler::evaluateEnum(const QHashedStringRef &scope, const QByteArray& enumValue, bool *ok) const
+int QQmlCompiler::bindingIdentifier(const QString &name, const Variant &value, const BindingContext &ctxt)
{
- Q_ASSERT_X(ok, "QQmlCompiler::evaluateEnum", "ok must not be a null pointer");
- *ok = false;
+ JSBindingReference *reference = pool->New<JSBindingReference>();
+ reference->expression = value;
+ reference->property = pool->New<Property>();
+ reference->property->setName(name);
+ reference->value = 0;
+ reference->bindingContext = ctxt;
+ reference->bindingContext.owner++;
+ // Unfortunately this is required for example for PropertyChanges where the bindings
+ // will be executed in the dynamic scope of the target, so we can't resolve any lookups
+ // at run-time.
+ reference->disableLookupAcceleration = true;
- if (scope != QLatin1String("Qt")) {
- QQmlType *type = 0;
- unit->imports().resolveType(scope, &type, 0, 0, 0);
- return type ? type->enumValue(QHashedCStringRef(enumValue.constData(), enumValue.length()), ok) : -1;
- }
+ const int id = output->customParserBindings.count();
+ output->customParserBindings.append(0); // Filled in later.
+ reference->customParserBindingsIndex = id;
- const QMetaObject *mo = StaticQtMetaObject::get();
- int i = mo->enumeratorCount();
- while (i--) {
- int v = mo->enumerator(i).keyToValue(enumValue.constData(), ok);
- if (*ok)
- return v;
- }
- return -1;
-}
+ compileState->totalBindingsCount++;
+ compileState->bindings.prepend(reference);
-const QMetaObject *QQmlCompiler::resolveType(const QString& name) const
-{
- QQmlType *qmltype = 0;
- if (!unit->imports().resolveType(name, &qmltype, 0, 0, 0))
- return 0;
- if (!qmltype)
- return 0;
- return qmltype->metaObject();
+ return id;
}
-int QQmlCompiler::bindingIdentifier(const QString &name, const Variant &value, const BindingContext &ctxt)
+QQmlBinding::Identifier QQmlCompiler::bindingIdentifier(const Variant &value, const QString &name, QQmlCustomParser *customParser)
{
JSBindingReference *reference = pool->New<JSBindingReference>();
reference->expression = value;
reference->property = pool->New<Property>();
reference->property->setName(name);
reference->value = 0;
- reference->bindingContext = ctxt;
+ reference->bindingContext = QQmlCompilerTypes::BindingContext(customParser->object);
reference->bindingContext.owner++;
// Unfortunately this is required for example for PropertyChanges where the bindings
// will be executed in the dynamic scope of the target, so we can't resolve any lookups
diff --git a/src/qml/qml/qqmlcompiler_p.h b/src/qml/qml/qqmlcompiler_p.h
index c94cee16cf..788def0288 100644
--- a/src/qml/qml/qqmlcompiler_p.h
+++ b/src/qml/qml/qqmlcompiler_p.h
@@ -65,6 +65,7 @@
#include <private/qqmlcodegenerator_p.h>
#include "private/qv4identifier_p.h"
#include <private/qqmljsastfwd_p.h>
+#include "qqmlcustomparser_p.h"
#include <QtCore/qbytearray.h>
#include <QtCore/qset.h>
@@ -332,7 +333,7 @@ namespace QQmlCompilerTypes {
};
class QMetaObjectBuilder;
-class Q_AUTOTEST_EXPORT QQmlCompiler
+class Q_AUTOTEST_EXPORT QQmlCompiler : public QQmlCustomParserCompilerBackend
{
Q_DECLARE_TR_FUNCTIONS(QQmlCompiler)
public:
@@ -348,9 +349,10 @@ public:
static bool isAttachedPropertyName(const QHashedStringRef &);
static bool isSignalPropertyName(const QHashedStringRef &);
- int evaluateEnum(const QHashedStringRef &scope, const QByteArray& enumValue, bool *ok) const; // for QQmlCustomParser::evaluateEnum
- const QMetaObject *resolveType(const QString& name) const; // for QQmlCustomParser::resolveType
int bindingIdentifier(const QString &name, const QQmlScript::Variant& value, const QQmlCompilerTypes::BindingContext &ctxt); // for QQmlCustomParser::bindingIndex
+ virtual QQmlBinding::Identifier bindingIdentifier(const QQmlScript::Variant&value, const QString&name, QQmlCustomParser *customParser);
+
+ virtual const QQmlImports &imports() const { return unit->imports(); }
private:
typedef QQmlCompiledData::Instruction Instruction;
diff --git a/src/qml/qml/qqmlcustomparser.cpp b/src/qml/qml/qqmlcustomparser.cpp
index 3f8fc967f4..ca23451774 100644
--- a/src/qml/qml/qqmlcustomparser.cpp
+++ b/src/qml/qml/qqmlcustomparser.cpp
@@ -346,7 +346,44 @@ const QMetaObject *QQmlCustomParser::resolveType(const QString& name) const
*/
QQmlBinding::Identifier QQmlCustomParser::bindingIdentifier(const QQmlScript::Variant &value, const QString& name)
{
- return compiler->bindingIdentifier(name, value, QQmlCompilerTypes::BindingContext(object));
+ return compiler->bindingIdentifier(value, name, this);
+}
+
+struct StaticQtMetaObject : public QObject
+{
+ static const QMetaObject *get()
+ { return &staticQtMetaObject; }
+};
+
+int QQmlCustomParserCompilerBackend::evaluateEnum(const QString &scope, const QByteArray &enumValue, bool *ok) const
+{
+ Q_ASSERT_X(ok, "QQmlCompiler::evaluateEnum", "ok must not be a null pointer");
+ *ok = false;
+
+ if (scope != QLatin1String("Qt")) {
+ QQmlType *type = 0;
+ imports().resolveType(scope, &type, 0, 0, 0);
+ return type ? type->enumValue(QHashedCStringRef(enumValue.constData(), enumValue.length()), ok) : -1;
+ }
+
+ const QMetaObject *mo = StaticQtMetaObject::get();
+ int i = mo->enumeratorCount();
+ while (i--) {
+ int v = mo->enumerator(i).keyToValue(enumValue.constData(), ok);
+ if (*ok)
+ return v;
+ }
+ return -1;
+}
+
+const QMetaObject *QQmlCustomParserCompilerBackend::resolveType(const QString &name) const
+{
+ QQmlType *qmltype = 0;
+ if (!imports().resolveType(name, &qmltype, 0, 0, 0))
+ return 0;
+ if (!qmltype)
+ return 0;
+ return qmltype->metaObject();
}
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlcustomparser_p.h b/src/qml/qml/qqmlcustomparser_p.h
index 39afa2a28e..2f1a9ddec8 100644
--- a/src/qml/qml/qqmlcustomparser_p.h
+++ b/src/qml/qml/qqmlcustomparser_p.h
@@ -108,6 +108,17 @@ private:
QQmlCustomParserNodePrivate *d;
};
+struct QQmlCustomParserCompilerBackend
+{
+ virtual ~QQmlCustomParserCompilerBackend() {}
+ virtual const QQmlImports &imports() const = 0;
+
+ int evaluateEnum(const QString &scope, const QByteArray& enumValue, bool *ok) const;
+ const QMetaObject *resolveType(const QString& name) const;
+
+ virtual QQmlBinding::Identifier bindingIdentifier(const QQmlScript::Variant&, const QString&, QQmlCustomParser *) { return QQmlBinding::Invalid; }
+};
+
class Q_QML_PRIVATE_EXPORT QQmlCustomParser
{
public:
@@ -146,10 +157,11 @@ protected:
private:
QList<QQmlError> exceptions;
- QQmlCompiler *compiler;
+ QQmlCustomParserCompilerBackend *compiler;
QQmlScript::Object *object;
Flags m_flags;
friend class QQmlCompiler;
+ friend class QQmlPropertyValidator;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QQmlCustomParser::Flags)