diff options
author | Simon Hausmann <simon.hausmann@digia.com> | 2014-01-27 13:09:01 +0100 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2014-01-28 10:41:52 +0100 |
commit | f9a285daf2033b5393d5b521d27c0cc659515632 (patch) | |
tree | 412c31c4a45847215aa82ed89c48526c9983a216 | |
parent | cad0f7e5b9915b1f4579f25121f7b9231405bfa2 (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.cpp | 21 | ||||
-rw-r--r-- | src/qml/compiler/qqmlcodegenerator_p.h | 1 | ||||
-rw-r--r-- | src/qml/compiler/qv4compileddata_p.h | 3 | ||||
-rw-r--r-- | src/qml/qml/qqmlcompiler.cpp | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmlobjectcreator.cpp | 13 | ||||
-rw-r--r-- | tests/auto/qml/qqmllanguage/data/readOnly.2.errors.txt | 2 |
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 |