aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@digia.com>2014-01-27 13:09:01 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-01-28 10:41:52 +0100
commitf9a285daf2033b5393d5b521d27c0cc659515632 (patch)
tree412c31c4a45847215aa82ed89c48526c9983a216
parentcad0f7e5b9915b1f4579f25121f7b9231405bfa2 (diff)
[new compiler] Report errors when trying to bind to read-only properties
The only exception are initializers for read-only property declarations. Also adjusted the error location of one test to point to the correct value location as opposed to the property location, as with all the other similar errors. Change-Id: I2333d3c485fc374b1b39a5f5a4408af5cf08a20f Reviewed-by: Lars Knoll <lars.knoll@digia.com>
-rw-r--r--src/qml/compiler/qqmlcodegenerator.cpp21
-rw-r--r--src/qml/compiler/qqmlcodegenerator_p.h1
-rw-r--r--src/qml/compiler/qv4compileddata_p.h3
-rw-r--r--src/qml/qml/qqmlcompiler.cpp2
-rw-r--r--src/qml/qml/qqmlobjectcreator.cpp13
-rw-r--r--tests/auto/qml/qqmllanguage/data/readOnly.2.errors.txt2
6 files changed, 34 insertions, 8 deletions
diff --git a/src/qml/compiler/qqmlcodegenerator.cpp b/src/qml/compiler/qqmlcodegenerator.cpp
index dfbee74446..344c38bf54 100644
--- a/src/qml/compiler/qqmlcodegenerator.cpp
+++ b/src/qml/compiler/qqmlcodegenerator.cpp
@@ -100,6 +100,7 @@ QStringList Signal::parameterStringList(const QStringList &stringPool) const
QQmlCodeGenerator::QQmlCodeGenerator(const QSet<QString> &illegalNames)
: illegalNames(illegalNames)
, _object(0)
+ , _propertyDeclaration(0)
, jsGenerator(0)
{
}
@@ -708,8 +709,11 @@ bool QQmlCodeGenerator::visit(AST::UiPublicMember *node)
propertyValue += alias.at(2);
}
property->aliasPropertyValueIndex = registerString(propertyValue);
- } else if (node->statement)
- appendBinding(node->identifierToken, property->nameIndex, node->statement);
+ } else if (node->statement) {
+ qSwap(_propertyDeclaration, property);
+ appendBinding(node->identifierToken, _propertyDeclaration->nameIndex, node->statement);
+ qSwap(_propertyDeclaration, property);
+ }
_object->properties->append(property);
@@ -725,8 +729,12 @@ bool QQmlCodeGenerator::visit(AST::UiPublicMember *node)
_object->indexOfDefaultProperty = _object->properties->count - 1;
}
- // process QML-like initializers (e.g. property Object o: Object {})
- AST::Node::accept(node->binding, this);
+ if (node->binding) {
+ qSwap(_propertyDeclaration, property);
+ // process QML-like initializers (e.g. property Object o: Object {})
+ AST::Node::accept(node->binding, this);
+ qSwap(_propertyDeclaration, property);
+ }
}
return false;
@@ -804,6 +812,8 @@ void QQmlCodeGenerator::setBindingValue(QV4::CompiledData::Binding *binding, AST
binding->valueLocation.line = loc.startLine;
binding->valueLocation.column = loc.startColumn;
binding->type = QV4::CompiledData::Binding::Type_Invalid;
+ if (_propertyDeclaration && (_propertyDeclaration->flags & QV4::CompiledData::Property::IsReadOnly))
+ binding->flags |= QV4::CompiledData::Binding::InitializerForReadOnlyDeclaration;
if (AST::ExpressionStatement *stmt = AST::cast<AST::ExpressionStatement *>(statement)) {
AST::ExpressionNode *expr = stmt->expression;
@@ -898,6 +908,9 @@ void QQmlCodeGenerator::appendBinding(const AST::SourceLocation &nameLocation, i
binding->flags = 0;
+ if (_propertyDeclaration && (_propertyDeclaration->flags & QV4::CompiledData::Property::IsReadOnly))
+ binding->flags |= QV4::CompiledData::Binding::InitializerForReadOnlyDeclaration;
+
// No type name on the initializer means it must be a group property
if (stringAt(_objects.at(objectIndex)->inheritedTypeNameIndex).isEmpty())
binding->type = QV4::CompiledData::Binding::Type_GroupProperty;
diff --git a/src/qml/compiler/qqmlcodegenerator_p.h b/src/qml/compiler/qqmlcodegenerator_p.h
index b597afc562..92692a2120 100644
--- a/src/qml/compiler/qqmlcodegenerator_p.h
+++ b/src/qml/compiler/qqmlcodegenerator_p.h
@@ -299,6 +299,7 @@ public:
QV4::CompiledData::TypeReferenceMap _typeReferences;
QmlObject *_object;
+ QmlProperty *_propertyDeclaration;
QQmlJS::MemoryPool *pool;
QString sourceCode;
diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h
index 8fa3f83ea4..06361fbf85 100644
--- a/src/qml/compiler/qv4compileddata_p.h
+++ b/src/qml/compiler/qv4compileddata_p.h
@@ -282,7 +282,8 @@ struct Q_QML_EXPORT Binding
enum Flags {
IsSignalHandlerExpression = 0x1,
- IsOnAssignment = 0x2
+ IsOnAssignment = 0x2,
+ InitializerForReadOnlyDeclaration = 0x4
};
quint32 flags : 16;
diff --git a/src/qml/qml/qqmlcompiler.cpp b/src/qml/qml/qqmlcompiler.cpp
index 0dd4ea015d..821ac4602d 100644
--- a/src/qml/qml/qqmlcompiler.cpp
+++ b/src/qml/qml/qqmlcompiler.cpp
@@ -3456,7 +3456,7 @@ bool QQmlCompiler::buildBinding(QQmlScript::Value *value,
Q_ASSERT(prop->parent->metatype);
if (!prop->core.isWritable() && !prop->core.isQList() && !prop->isReadOnlyDeclaration)
- COMPILE_EXCEPTION(prop, tr("Invalid property assignment: \"%1\" is a read-only property").arg(prop->name().toString()));
+ COMPILE_EXCEPTION(value, tr("Invalid property assignment: \"%1\" is a read-only property").arg(prop->name().toString()));
JSBindingReference *reference = pool->New<JSBindingReference>();
reference->expression = value->value;
diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp
index 67c21706c5..bd5a212408 100644
--- a/src/qml/qml/qqmlobjectcreator.cpp
+++ b/src/qml/qml/qqmlobjectcreator.cpp
@@ -594,7 +594,7 @@ void QmlObjectCreator::setupBindings()
QString id = stringAt(_compiledObject->idIndex);
if (!id.isEmpty()) {
QQmlPropertyData *idProperty = _propertyCache->property(QStringLiteral("id"), _qobject, context);
- if (idProperty) {
+ if (idProperty && idProperty->isWritable()) {
QV4::CompiledData::Binding idBinding;
idBinding.propertyNameIndex = 0; // Not used
idBinding.flags = 0;
@@ -635,6 +635,17 @@ void QmlObjectCreator::setupBindings()
bool QmlObjectCreator::setPropertyValue(QQmlPropertyData *property, int bindingIndex, const QV4::CompiledData::Binding *binding)
{
+ if (property && !property->isWritable()
+ && !property->isQList()
+ && binding->type != QV4::CompiledData::Binding::Type_GroupProperty
+ && !(binding->flags & QV4::CompiledData::Binding::InitializerForReadOnlyDeclaration)
+ && !(binding->flags & QV4::CompiledData::Binding::IsSignalHandlerExpression)
+ && !(binding->flags & QV4::CompiledData::Binding::IsOnAssignment)
+ ) {
+ recordError(binding->valueLocation, tr("Invalid property assignment: \"%1\" is a read-only property").arg(property->name(_qobject)));
+ return false;
+ }
+
if (binding->type == QV4::CompiledData::Binding::Type_AttachedProperty) {
Q_ASSERT(stringAt(qmlUnit->objectAt(binding->value.objectIndex)->inheritedTypeNameIndex).isEmpty());
QQmlCompiledData::TypeReference *tr = resolvedTypes.value(binding->propertyNameIndex);
diff --git a/tests/auto/qml/qqmllanguage/data/readOnly.2.errors.txt b/tests/auto/qml/qqmllanguage/data/readOnly.2.errors.txt
index d857a0440e..b8c34042be 100644
--- a/tests/auto/qml/qqmllanguage/data/readOnly.2.errors.txt
+++ b/tests/auto/qml/qqmllanguage/data/readOnly.2.errors.txt
@@ -1 +1 @@
-3:5:Invalid property assignment: "readOnlyString" is a read-only property
+3:21:Invalid property assignment: "readOnlyString" is a read-only property