diff options
-rw-r--r-- | src/declarative/qml/qmlcompiler.cpp | 60 | ||||
-rw-r--r-- | src/declarative/qml/qmlcompiler_p.h | 5 | ||||
-rw-r--r-- | src/declarative/qml/qmlengine_p.h | 12 | ||||
-rw-r--r-- | tests/auto/declarative/qmlparser/invalidID.5.errors.txt | 1 | ||||
-rw-r--r-- | tests/auto/declarative/qmlparser/invalidID.5.qml | 6 | ||||
-rw-r--r-- | tests/auto/declarative/qmlparser/tst_qmlparser.cpp | 2 |
6 files changed, 77 insertions, 9 deletions
diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp index 1771cb4..3dcc448 100644 --- a/src/declarative/qml/qmlcompiler.cpp +++ b/src/declarative/qml/qmlcompiler.cpp @@ -1176,11 +1176,19 @@ bool QmlCompiler::buildProperty(QmlParser::Property *prop, } QmlType *type = 0; - QmlEnginePrivate::get(engine)->resolveType(unit->imports, prop->name, &type, 0); - // 0: attached properties not supported in QML component files - - if (!type || !type->attachedPropertiesType()) + QmlEnginePrivate::ImportedNamespace *typeNamespace = 0; + QmlEnginePrivate::get(engine)->resolveType(unit->imports, prop->name, + &type, 0, &typeNamespace); + + if (typeNamespace) { + // ### We might need to indicate that this property is a namespace + // for the DOM API + COMPILE_CHECK(buildPropertyInNamespace(typeNamespace, prop, obj, + ctxt)); + return true; + } else if (!type || !type->attachedPropertiesType()) { COMPILE_EXCEPTION(prop, "Non-existant attached object"); + } if (!prop->value) COMPILE_EXCEPTION(prop, "Invalid attached object assignment"); @@ -1265,6 +1273,40 @@ bool QmlCompiler::buildProperty(QmlParser::Property *prop, return true; } +bool +QmlCompiler::buildPropertyInNamespace(QmlEnginePrivate::ImportedNamespace *ns, + QmlParser::Property *nsProp, + QmlParser::Object *obj, + const BindingContext &ctxt) +{ + if (!nsProp->value) + COMPILE_EXCEPTION(nsProp, "Invalid use of namespace"); + + foreach (Property *prop, nsProp->value->properties) { + + if (!isAttachedPropertyName(prop->name)) + COMPILE_EXCEPTION(prop, "Not an attached property name"); + + // Setup attached property data + + QmlType *type = 0; + QmlEnginePrivate::get(engine)->resolveTypeInNamespace(ns, prop->name, + &type, 0); + + if (!type || !type->attachedPropertiesType()) + COMPILE_EXCEPTION(prop, "Non-existant attached object"); + + if (!prop->value) + COMPILE_EXCEPTION(prop, "Invalid attached object assignment"); + + Q_ASSERT(type->attachedPropertiesFunction()); + prop->index = type->index(); + prop->value->metatype = type->attachedPropertiesType(); + + COMPILE_CHECK(buildAttachedProperty(prop, obj, ctxt)); + } +} + void QmlCompiler::genValueProperty(QmlParser::Property *prop, QmlParser::Object *obj) { @@ -1407,11 +1449,19 @@ bool QmlCompiler::buildIdProperty(QmlParser::Property *prop, prop->values.at(0)->object) COMPILE_EXCEPTION(prop, "Invalid use of id property"); - QString val = prop->values.at(0)->primitive(); + QmlParser::Value *idValue = prop->values.at(0); + QString val = idValue->primitive(); if (!isValidId(val)) COMPILE_EXCEPTION(prop, val << "is not a valid object id"); + // We disallow id's that conflict with import prefixes + QmlEnginePrivate::ImportedNamespace *ns = 0; + QmlEnginePrivate::get(engine)->resolveType(unit->imports, val.toUtf8(), + 0, 0, &ns); + if (ns) + COMPILE_EXCEPTION(idValue, "id conflicts with namespace prefix"); + if (compileState.ids.contains(val)) COMPILE_EXCEPTION(prop, "id is not unique"); diff --git a/src/declarative/qml/qmlcompiler_p.h b/src/declarative/qml/qmlcompiler_p.h index 58279c4..c42c2d9 100644 --- a/src/declarative/qml/qmlcompiler_p.h +++ b/src/declarative/qml/qmlcompiler_p.h @@ -60,6 +60,7 @@ #include <private/qmlinstruction_p.h> #include <private/qmlcompositetypemanager_p.h> #include <private/qmlparser_p.h> +#include <private/qmlengine_p.h> QT_BEGIN_NAMESPACE @@ -165,6 +166,10 @@ private: const BindingContext &); bool buildProperty(QmlParser::Property *prop, QmlParser::Object *obj, const BindingContext &); + bool buildPropertyInNamespace(QmlEnginePrivate::ImportedNamespace *ns, + QmlParser::Property *prop, + QmlParser::Object *obj, + const BindingContext &); bool buildIdProperty(QmlParser::Property *prop, QmlParser::Object *obj); bool buildAttachedProperty(QmlParser::Property *prop, QmlParser::Object *obj, diff --git a/src/declarative/qml/qmlengine_p.h b/src/declarative/qml/qmlengine_p.h index c84b3b5..18e3765 100644 --- a/src/declarative/qml/qmlengine_p.h +++ b/src/declarative/qml/qmlengine_p.h @@ -209,10 +209,14 @@ public: bool addToImport(Imports*, const QString& uri, const QString& prefix, int vmaj, int vmin, QmlScriptParser::Import::Type importType) const; - bool resolveType(const Imports&, const QByteArray& type, QmlType** type_return, QUrl* url_return, ImportedNamespace** ns_return=0) const; - - void resolveNamespace(const Imports& imports, const QByteArray &type, ImportedNamespace **s, QByteArray *unqualifiedType) const; - bool resolveTypeInNamespace(ImportedNamespace*, const QByteArray& type, QmlType** type_return, QUrl* url_return ) const; + bool resolveType(const Imports&, const QByteArray& type, + QmlType** type_return, QUrl* url_return, + ImportedNamespace** ns_return=0) const; + void resolveNamespace(const Imports& imports, const QByteArray &type, + ImportedNamespace **s, + QByteArray *unqualifiedType) const; + bool resolveTypeInNamespace(ImportedNamespace*, const QByteArray& type, + QmlType** type_return, QUrl* url_return ) const; static QScriptValue qmlScriptObject(QObject*, QmlEngine*); diff --git a/tests/auto/declarative/qmlparser/invalidID.5.errors.txt b/tests/auto/declarative/qmlparser/invalidID.5.errors.txt new file mode 100644 index 0000000..b0a63a0 --- /dev/null +++ b/tests/auto/declarative/qmlparser/invalidID.5.errors.txt @@ -0,0 +1 @@ +4:9:id conflicts with namespace prefix diff --git a/tests/auto/declarative/qmlparser/invalidID.5.qml b/tests/auto/declarative/qmlparser/invalidID.5.qml new file mode 100644 index 0000000..0545b0d --- /dev/null +++ b/tests/auto/declarative/qmlparser/invalidID.5.qml @@ -0,0 +1,6 @@ +import Test 1.0 +import Test 1.0 as Hello +MyQmlObject { + id: Hello +} + diff --git a/tests/auto/declarative/qmlparser/tst_qmlparser.cpp b/tests/auto/declarative/qmlparser/tst_qmlparser.cpp index a9c4351..3047bb0 100644 --- a/tests/auto/declarative/qmlparser/tst_qmlparser.cpp +++ b/tests/auto/declarative/qmlparser/tst_qmlparser.cpp @@ -135,6 +135,8 @@ void tst_qmlparser::errors_data() QTest::newRow("invalidID.2") << "invalidID.2.qml" << "invalidID.2.errors.txt" << false; QTest::newRow("invalidID.3") << "invalidID.3.qml" << "invalidID.3.errors.txt" << false; QTest::newRow("invalidID.4") << "invalidID.4.qml" << "invalidID.4.errors.txt" << false; + QTest::newRow("invalidID.5") << "invalidID.5.qml" << "invalidID.5.errors.txt" << false; + QTest::newRow("unsupportedProperty") << "unsupportedProperty.qml" << "unsupportedProperty.errors.txt" << false; QTest::newRow("nullDotProperty") << "nullDotProperty.qml" << "nullDotProperty.errors.txt" << true; |