#include <private/qqmlcustomparser_p.h>
#include <private/qqmlvmemetaobject_p.h>
#include <private/qqmlcomponent_p.h>
+#include <private/qqmlstringconverters_p.h>
#define COMPILE_EXCEPTION(token, desc) \
{ \
bool notInRevision = false;
instantiatingProperty = PropertyResolver(parentCache).property(stringAt(instantiatingBinding->propertyNameIndex), ¬InRevision);
- if (instantiatingProperty && instantiatingProperty->isQObject()) {
- baseTypeCache = enginePrivate->rawPropertyCacheForType(instantiatingProperty->propType);
- Q_ASSERT(baseTypeCache);
+ if (instantiatingProperty) {
+ if (instantiatingProperty->isQObject()) {
+ baseTypeCache = enginePrivate->rawPropertyCacheForType(instantiatingProperty->propType);
+ Q_ASSERT(baseTypeCache);
+ } else if (QQmlValueType *vt = QQmlValueTypeFactory::valueType(instantiatingProperty->propType)) {
+ baseTypeCache = enginePrivate->cache(vt->metaObject());
+ Q_ASSERT(baseTypeCache);
+ }
}
}
QQmlPropertyValidator::QQmlPropertyValidator(QQmlTypeCompiler *typeCompiler, const QVector<int> &runtimeFunctionIndices)
: QQmlCompilePass(typeCompiler)
+ , enginePrivate(typeCompiler->enginePrivate())
, qmlUnit(typeCompiler->qmlUnit())
, resolvedTypes(*typeCompiler->resolvedTypes())
, propertyCaches(typeCompiler->propertyCaches())
PropertyResolver propertyResolver(propertyCache);
- QQmlPropertyData *defaultProperty = obj->indexOfDefaultProperty != -1 ? propertyCache->parent()->defaultProperty() : propertyCache->defaultProperty();
+ QString defaultPropertyName;
+ QQmlPropertyData *defaultProperty = 0;
+ if (obj->indexOfDefaultProperty != -1) {
+ QQmlPropertyCache *cache = propertyCache->parent();
+ defaultPropertyName = cache->defaultPropertyName();
+ defaultProperty = cache->defaultProperty();
+ } else {
+ defaultPropertyName = propertyCache->defaultPropertyName();
+ defaultProperty = propertyCache->defaultProperty();
+ }
const QV4::CompiledData::Binding *binding = obj->bindingTable();
for (quint32 i = 0; i < obj->nBindings; ++i, ++binding) {
continue;
}
- const QString name = stringAt(binding->propertyNameIndex);
+ QString name = stringAt(binding->propertyNameIndex);
bool bindingToDefaultProperty = false;
COMPILE_EXCEPTION(binding, tr("Cannot assign a value directly to a grouped property"));
pd = defaultProperty;
+ name = defaultPropertyName;
bindingToDefaultProperty = true;
}
- if (!pd) {
+ if (pd) {
+ if (!pd->isWritable()
+ && !pd->isQList()
+ && binding->type != QV4::CompiledData::Binding::Type_GroupProperty
+ && !(binding->flags & QV4::CompiledData::Binding::InitializerForReadOnlyDeclaration)
+ && !(binding->flags & QV4::CompiledData::Binding::IsSignalHandlerExpression)
+ ) {
+ recordError(binding->valueLocation, tr("Invalid property assignment: \"%1\" is a read-only property").arg(name));
+ return false;
+ }
+
+ if (binding->type < QV4::CompiledData::Binding::Type_Script) {
+ if (!validateLiteralBinding(propertyCache, pd, binding))
+ return false;
+ } else if (binding->type == QV4::CompiledData::Binding::Type_Object) {
+ if (!validateObjectBinding(pd, binding))
+ return false;
+ }
+ } else {
if (customParser) {
customBindings << binding;
continue;
return true;
}
+bool QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache *propertyCache, QQmlPropertyData *property, const QV4::CompiledData::Binding *binding)
+{
+ if (property->isEnum()) {
+ QString value = binding->valueAsString(&qmlUnit->header);
+ QMetaProperty p = propertyCache->firstCppMetaObject()->property(property->coreIndex);
+ bool ok;
+ if (p.isFlagType()) {
+ p.enumerator().keysToValue(value.toUtf8().constData(), &ok);
+ } else
+ p.enumerator().keyToValue(value.toUtf8().constData(), &ok);
+
+ if (!ok) {
+ recordError(binding->valueLocation, tr("Invalid property assignment: unknown enumeration"));
+ return false;
+ }
+ return true;
+ }
+
+ switch (property->propType) {
+ case QMetaType::QVariant:
+ break;
+ case QVariant::String: {
+ if (binding->type != QV4::CompiledData::Binding::Type_String) {
+ recordError(binding->valueLocation, tr("Invalid property assignment: string expected"));
+ return false;
+ }
+ }
+ break;
+ case QVariant::StringList: {
+ if (binding->type != QV4::CompiledData::Binding::Type_String) {
+ recordError(binding->valueLocation, tr("Invalid property assignment: string or string list expected"));
+ return false;
+ }
+ }
+ break;
+ case QVariant::ByteArray: {
+ if (binding->type != QV4::CompiledData::Binding::Type_String) {
+ recordError(binding->valueLocation, tr("Invalid property assignment: byte array expected"));
+ return false;
+ }
+ }
+ break;
+ case QVariant::Url: {
+ if (binding->type != QV4::CompiledData::Binding::Type_String) {
+ recordError(binding->valueLocation, tr("Invalid property assignment: url expected"));
+ return false;
+ }
+ }
+ break;
+ case QVariant::UInt: {
+ if (binding->type == QV4::CompiledData::Binding::Type_Number) {
+ double d = binding->valueAsNumber();
+ if (double(uint(d)) == d)
+ return true;
+ }
+ recordError(binding->valueLocation, tr("Invalid property assignment: unsigned int expected"));
+ return false;
+ }
+ break;
+ case QVariant::Int: {
+ if (binding->type == QV4::CompiledData::Binding::Type_Number) {
+ double d = binding->valueAsNumber();
+ if (double(int(d)) == d)
+ return true;
+ }
+ recordError(binding->valueLocation, tr("Invalid property assignment: int expected"));
+ return false;
+ }
+ break;
+ case QMetaType::Float: {
+ if (binding->type != QV4::CompiledData::Binding::Type_Number) {
+ recordError(binding->valueLocation, tr("Invalid property assignment: number expected"));
+ return false;
+ }
+ }
+ break;
+ case QVariant::Double: {
+ if (binding->type != QV4::CompiledData::Binding::Type_Number) {
+ recordError(binding->valueLocation, tr("Invalid property assignment: number expected"));
+ return false;
+ }
+ }
+ break;
+ case QVariant::Color: {
+ bool ok = false;
+ QQmlStringConverters::rgbaFromString(binding->valueAsString(&qmlUnit->header), &ok);
+ if (!ok) {
+ recordError(binding->valueLocation, tr("Invalid property assignment: color expected"));
+ return false;
+ }
+ }
+ break;
+#ifndef QT_NO_DATESTRING
+ case QVariant::Date: {
+ bool ok = false;
+ QQmlStringConverters::dateFromString(binding->valueAsString(&qmlUnit->header), &ok);
+ if (!ok) {
+ recordError(binding->valueLocation, tr("Invalid property assignment: date expected"));
+ return false;
+ }
+ }
+ break;
+ case QVariant::Time: {
+ bool ok = false;
+ QQmlStringConverters::timeFromString(binding->valueAsString(&qmlUnit->header), &ok);
+ if (!ok) {
+ recordError(binding->valueLocation, tr("Invalid property assignment: time expected"));
+ return false;
+ }
+ }
+ break;
+ case QVariant::DateTime: {
+ bool ok = false;
+ QQmlStringConverters::dateTimeFromString(binding->valueAsString(&qmlUnit->header), &ok);
+ if (!ok) {
+ recordError(binding->valueLocation, tr("Invalid property assignment: datetime expected"));
+ return false;
+ }
+ }
+ break;
+#endif // QT_NO_DATESTRING
+ case QVariant::Point: {
+ bool ok = false;
+ QQmlStringConverters::pointFFromString(binding->valueAsString(&qmlUnit->header), &ok).toPoint();
+ if (!ok) {
+ recordError(binding->valueLocation, tr("Invalid property assignment: point expected"));
+ return false;
+ }
+ }
+ break;
+ case QVariant::PointF: {
+ bool ok = false;
+ QQmlStringConverters::pointFFromString(binding->valueAsString(&qmlUnit->header), &ok);
+ if (!ok) {
+ recordError(binding->valueLocation, tr("Invalid property assignment: point expected"));
+ return false;
+ }
+ }
+ break;
+ case QVariant::Size: {
+ bool ok = false;
+ QQmlStringConverters::sizeFFromString(binding->valueAsString(&qmlUnit->header), &ok).toSize();
+ if (!ok) {
+ recordError(binding->valueLocation, tr("Invalid property assignment: size expected"));
+ return false;
+ }
+ }
+ break;
+ case QVariant::SizeF: {
+ bool ok = false;
+ QQmlStringConverters::sizeFFromString(binding->valueAsString(&qmlUnit->header), &ok);
+ if (!ok) {
+ recordError(binding->valueLocation, tr("Invalid property assignment: size expected"));
+ return false;
+ }
+ }
+ break;
+ case QVariant::Rect: {
+ bool ok = false;
+ QQmlStringConverters::rectFFromString(binding->valueAsString(&qmlUnit->header), &ok).toRect();
+ if (!ok) {
+ recordError(binding->valueLocation, tr("Invalid property assignment: rect expected"));
+ return false;
+ }
+ }
+ break;
+ case QVariant::RectF: {
+ bool ok = false;
+ QQmlStringConverters::rectFFromString(binding->valueAsString(&qmlUnit->header), &ok);
+ if (!ok) {
+ recordError(binding->valueLocation, tr("Invalid property assignment: point expected"));
+ return false;
+ }
+ }
+ break;
+ case QVariant::Bool: {
+ if (binding->type != QV4::CompiledData::Binding::Type_Boolean) {
+ recordError(binding->valueLocation, tr("Invalid property assignment: boolean expected"));
+ return false;
+ }
+ }
+ break;
+ case QVariant::Vector3D: {
+ struct {
+ float xp;
+ float yp;
+ float zy;
+ } vec;
+ if (!QQmlStringConverters::createFromString(QMetaType::QVector3D, binding->valueAsString(&qmlUnit->header), &vec, sizeof(vec))) {
+ recordError(binding->valueLocation, tr("Invalid property assignment: 3D vector expected"));
+ return false;
+ }
+ }
+ break;
+ case QVariant::Vector4D: {
+ struct {
+ float xp;
+ float yp;
+ float zy;
+ float wp;
+ } vec;
+ if (!QQmlStringConverters::createFromString(QMetaType::QVector4D, binding->valueAsString(&qmlUnit->header), &vec, sizeof(vec))) {
+ recordError(binding->valueLocation, tr("Invalid property assignment: 4D vector expected"));
+ return false;
+ }
+ }
+ break;
+ case QVariant::RegExp:
+ recordError(binding->valueLocation, tr("Invalid property assignment: regular expression expected; use /pattern/ syntax"));
+ break;
+ default: {
+ // generate single literal value assignment to a list property if required
+ if (property->propType == qMetaTypeId<QList<qreal> >()) {
+ if (binding->type != QV4::CompiledData::Binding::Type_Number) {
+ recordError(binding->valueLocation, tr("Invalid property assignment: real or array of reals expected"));
+ return false;
+ }
+ break;
+ } else if (property->propType == qMetaTypeId<QList<int> >()) {
+ bool ok = (binding->type == QV4::CompiledData::Binding::Type_Number);
+ if (ok) {
+ double n = binding->valueAsNumber();
+ if (double(int(n)) != n)
+ ok = false;
+ }
+ if (!ok)
+ recordError(binding->valueLocation, tr("Invalid property assignment: int or array of ints expected"));
+ break;
+ } else if (property->propType == qMetaTypeId<QList<bool> >()) {
+ if (binding->type != QV4::CompiledData::Binding::Type_Boolean) {
+ recordError(binding->valueLocation, tr("Invalid property assignment: bool or array of bools expected"));
+ return false;
+ }
+ break;
+ } else if (property->propType == qMetaTypeId<QList<QUrl> >()) {
+ if (binding->type != QV4::CompiledData::Binding::Type_String) {
+ recordError(binding->valueLocation, tr("Invalid property assignment: url or array of urls expected"));
+ return false;
+ }
+ break;
+ } else if (property->propType == qMetaTypeId<QList<QString> >()) {
+ if (binding->type != QV4::CompiledData::Binding::Type_String) {
+ recordError(binding->valueLocation, tr("Invalid property assignment: string or array of strings expected"));
+ return false;
+ }
+ break;
+ } else if (property->propType == qMetaTypeId<QJSValue>()) {
+ break;
+ } else if (property->propType == qMetaTypeId<QQmlScriptString>()) {
+ break;
+ }
+
+ // otherwise, try a custom type assignment
+ QQmlMetaType::StringConverter converter = QQmlMetaType::customStringConverter(property->propType);
+ if (!converter) {
+ recordError(binding->location, tr("Invalid property assignment: unsupported type \"%1\"").arg(QString::fromLatin1(QMetaType::typeName(property->propType))));
+ return false;
+ }
+ }
+ break;
+ }
+ return true;
+}
+
+bool QQmlPropertyValidator::validateObjectBinding(QQmlPropertyData *property, const QV4::CompiledData::Binding *binding)
+{
+ if (binding->flags & QV4::CompiledData::Binding::IsOnAssignment)
+ return true;
+ if (isComponent(binding->value.objectIndex))
+ return true;
+
+ if (QQmlMetaType::isInterface(property->propType)) {
+ // Can only check at instantiation time if the created sub-object successfully casts to the
+ // target interface.
+ return true;
+ } else if (property->propType == QMetaType::QVariant) {
+ // We can convert everything to QVariant :)
+ return true;
+ } else if (property->isQList()) {
+ // ### TODO: list error handling
+ return true;
+ } else if (QQmlValueTypeFactory::isValueType(property->propType)) {
+ recordError(binding->location, tr("Unexpected object assignment"));
+ return false;
+ } else {
+ // We want to raw metaObject here as the raw metaobject is the
+ // actual property type before we applied any extensions that might
+ // effect the properties on the type, but don't effect assignability
+ QQmlPropertyCache *propertyMetaObject = enginePrivate->rawPropertyCacheForType(property->propType);
+
+ // Will be true if the assgned type inherits propertyMetaObject
+ bool isAssignable = false;
+ // Determine isAssignable value
+ if (propertyMetaObject) {
+ QQmlPropertyCache *c = propertyCaches.value(binding->value.objectIndex);
+ while (c && !isAssignable) {
+ isAssignable |= c == propertyMetaObject;
+ c = c->parent();
+ }
+ }
+
+ if (!isAssignable) {
+ recordError(binding->valueLocation, tr("Cannot assign object to property"));
+ return false;
+ }
+ }
+ return true;
+}
+
QT_END_NAMESPACE
// ### This should be resolved earlier at compile time and the binding value should be changed accordingly.
if (property->isEnum()) {
QVariant value = binding->valueAsString(&qmlUnit->header);
- if (!QQmlPropertyPrivate::write(_qobject, *property, value, context))
- recordError(binding->valueLocation, tr("Invalid property assignment: unknown enumeration"));
+ bool ok = QQmlPropertyPrivate::write(_qobject, *property, value, context);
+ Q_ASSERT(ok);
+ Q_UNUSED(ok);
return;
}
}
break;
case QVariant::String: {
- if (binding->type == QV4::CompiledData::Binding::Type_String) {
- QString value = binding->valueAsString(&qmlUnit->header);
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
- } else {
- recordError(binding->valueLocation, tr("Invalid property assignment: string expected"));
- }
+ Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_String);
+ QString value = binding->valueAsString(&qmlUnit->header);
+ argv[0] = &value;
+ QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
}
break;
case QVariant::StringList: {
- if (binding->type == QV4::CompiledData::Binding::Type_String) {
- QStringList value(binding->valueAsString(&qmlUnit->header));
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
- } else {
- recordError(binding->valueLocation, tr("Invalid property assignment: string or string list expected"));
- }
+ Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_String);
+ QStringList value(binding->valueAsString(&qmlUnit->header));
+ argv[0] = &value;
+ QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
}
break;
case QVariant::ByteArray: {
- if (binding->type == QV4::CompiledData::Binding::Type_String) {
- QByteArray value(binding->valueAsString(&qmlUnit->header).toUtf8());
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
- } else {
- recordError(binding->valueLocation, tr("Invalid property assignment: byte array expected"));
- }
+ Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_String);
+ QByteArray value(binding->valueAsString(&qmlUnit->header).toUtf8());
+ argv[0] = &value;
+ QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
}
break;
case QVariant::Url: {
- if (binding->type == QV4::CompiledData::Binding::Type_String) {
- QString string = binding->valueAsString(&qmlUnit->header);
- // Encoded dir-separators defeat QUrl processing - decode them first
- string.replace(QLatin1String("%2f"), QLatin1String("/"), Qt::CaseInsensitive);
- QUrl value = string.isEmpty() ? QUrl() : this->url.resolved(QUrl(string));
- // Apply URL interceptor
- if (engine->urlInterceptor())
- value = engine->urlInterceptor()->intercept(value, QQmlAbstractUrlInterceptor::UrlString);
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
- } else {
- recordError(binding->valueLocation, tr("Invalid property assignment: url expected"));
- }
+ Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_String);
+ QString string = binding->valueAsString(&qmlUnit->header);
+ // Encoded dir-separators defeat QUrl processing - decode them first
+ string.replace(QLatin1String("%2f"), QLatin1String("/"), Qt::CaseInsensitive);
+ QUrl value = string.isEmpty() ? QUrl() : this->url.resolved(QUrl(string));
+ // Apply URL interceptor
+ if (engine->urlInterceptor())
+ value = engine->urlInterceptor()->intercept(value, QQmlAbstractUrlInterceptor::UrlString);
+ argv[0] = &value;
+ QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
}
break;
case QVariant::UInt: {
- if (binding->type == QV4::CompiledData::Binding::Type_Number) {
- double d = binding->valueAsNumber();
- if (double(uint(d)) == d) {
- uint value = uint(d);
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
- break;
- }
- }
- recordError(binding->valueLocation, tr("Invalid property assignment: unsigned int expected"));
+ Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Number);
+ double d = binding->valueAsNumber();
+ uint value = uint(d);
+ argv[0] = &value;
+ QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ break;
}
break;
case QVariant::Int: {
- if (binding->type == QV4::CompiledData::Binding::Type_Number) {
- double d = binding->valueAsNumber();
- if (double(int(d)) == d) {
- int value = int(d);
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
- break;
- }
- }
- recordError(binding->valueLocation, tr("Invalid property assignment: int expected"));
+ Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Number);
+ double d = binding->valueAsNumber();
+ int value = int(d);
+ argv[0] = &value;
+ QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ break;
}
break;
case QMetaType::Float: {
- if (binding->type == QV4::CompiledData::Binding::Type_Number) {
- float value = float(binding->valueAsNumber());
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
- } else {
- recordError(binding->valueLocation, tr("Invalid property assignment: number expected"));
- }
+ Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Number);
+ float value = float(binding->valueAsNumber());
+ argv[0] = &value;
+ QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
}
break;
case QVariant::Double: {
- if (binding->type == QV4::CompiledData::Binding::Type_Number) {
- double value = binding->valueAsNumber();
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
- } else {
- recordError(binding->valueLocation, tr("Invalid property assignment: number expected"));
- }
+ Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Number);
+ double value = binding->valueAsNumber();
+ argv[0] = &value;
+ QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
}
break;
case QVariant::Color: {
bool ok = false;
uint colorValue = QQmlStringConverters::rgbaFromString(binding->valueAsString(&qmlUnit->header), &ok);
-
- if (ok) {
- struct { void *data[4]; } buffer;
- if (QQml_valueTypeProvider()->storeValueType(property->propType, &colorValue, &buffer, sizeof(buffer))) {
- argv[0] = reinterpret_cast<void *>(&buffer);
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
- }
- } else {
- recordError(binding->valueLocation, tr("Invalid property assignment: color expected"));
+ Q_ASSERT(ok);
+ struct { void *data[4]; } buffer;
+ if (QQml_valueTypeProvider()->storeValueType(property->propType, &colorValue, &buffer, sizeof(buffer))) {
+ argv[0] = reinterpret_cast<void *>(&buffer);
+ QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
}
}
break;
case QVariant::Date: {
bool ok = false;
QDate value = QQmlStringConverters::dateFromString(binding->valueAsString(&qmlUnit->header), &ok);
- if (ok) {
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
- } else {
- recordError(binding->valueLocation, tr("Invalid property assignment: date expected"));
- }
+ Q_ASSERT(ok);
+ argv[0] = &value;
+ QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
}
break;
case QVariant::Time: {
bool ok = false;
QTime value = QQmlStringConverters::timeFromString(binding->valueAsString(&qmlUnit->header), &ok);
- if (ok) {
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
- } else {
- recordError(binding->valueLocation, tr("Invalid property assignment: time expected"));
- }
+ Q_ASSERT(ok);
+ argv[0] = &value;
+ QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
}
break;
case QVariant::DateTime: {
bool ok = false;
QDateTime value = QQmlStringConverters::dateTimeFromString(binding->valueAsString(&qmlUnit->header), &ok);
- if (ok) {
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
- } else {
- recordError(binding->valueLocation, tr("Invalid property assignment: datetime expected"));
- }
+ Q_ASSERT(ok);
+ argv[0] = &value;
+ QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
}
break;
#endif // QT_NO_DATESTRING
case QVariant::Point: {
bool ok = false;
QPoint value = QQmlStringConverters::pointFFromString(binding->valueAsString(&qmlUnit->header), &ok).toPoint();
- if (ok) {
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
- } else {
- recordError(binding->valueLocation, tr("Invalid property assignment: point expected"));
- }
+ Q_ASSERT(ok);
+ argv[0] = &value;
+ QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
}
break;
case QVariant::PointF: {
bool ok = false;
QPointF value = QQmlStringConverters::pointFFromString(binding->valueAsString(&qmlUnit->header), &ok);
- if (ok) {
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
- } else {
- recordError(binding->valueLocation, tr("Invalid property assignment: point expected"));
- }
+ Q_ASSERT(ok);
+ argv[0] = &value;
+ QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
}
break;
case QVariant::Size: {
bool ok = false;
QSize value = QQmlStringConverters::sizeFFromString(binding->valueAsString(&qmlUnit->header), &ok).toSize();
- if (ok) {
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
- } else {
- recordError(binding->valueLocation, tr("Invalid property assignment: size expected"));
- }
+ Q_ASSERT(ok);
+ argv[0] = &value;
+ QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
}
break;
case QVariant::SizeF: {
bool ok = false;
QSizeF value = QQmlStringConverters::sizeFFromString(binding->valueAsString(&qmlUnit->header), &ok);
- if (ok) {
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
- } else {
- recordError(binding->valueLocation, tr("Invalid property assignment: size expected"));
- }
+ Q_ASSERT(ok);
+ argv[0] = &value;
+ QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
}
break;
case QVariant::Rect: {
bool ok = false;
QRect value = QQmlStringConverters::rectFFromString(binding->valueAsString(&qmlUnit->header), &ok).toRect();
- if (ok) {
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
- } else {
- recordError(binding->valueLocation, tr("Invalid property assignment: rect expected"));
- }
+ Q_ASSERT(ok);
+ argv[0] = &value;
+ QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
}
break;
case QVariant::RectF: {
bool ok = false;
QRectF value = QQmlStringConverters::rectFFromString(binding->valueAsString(&qmlUnit->header), &ok);
- if (ok) {
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
- } else {
- recordError(binding->valueLocation, tr("Invalid property assignment: point expected"));
- }
+ Q_ASSERT(ok);
+ argv[0] = &value;
+ QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
}
break;
case QVariant::Bool: {
- if (binding->type == QV4::CompiledData::Binding::Type_Boolean) {
- bool value = binding->valueAsBoolean();
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
- } else {
- recordError(binding->valueLocation, tr("Invalid property assignment: boolean expected"));
- }
+ Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Boolean);
+ bool value = binding->valueAsBoolean();
+ argv[0] = &value;
+ QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
}
break;
case QVariant::Vector3D: {
float yp;
float zy;
} vec;
- if (QQmlStringConverters::createFromString(QMetaType::QVector3D, binding->valueAsString(&qmlUnit->header), &vec, sizeof(vec))) {
- argv[0] = reinterpret_cast<void *>(&vec);
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
- } else {
- recordError(binding->valueLocation, tr("Invalid property assignment: 3D vector expected"));
- }
+ bool ok = QQmlStringConverters::createFromString(QMetaType::QVector3D, binding->valueAsString(&qmlUnit->header), &vec, sizeof(vec));
+ Q_ASSERT(ok);
+ Q_UNUSED(ok);
+ argv[0] = reinterpret_cast<void *>(&vec);
+ QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
}
break;
case QVariant::Vector4D: {
float zy;
float wp;
} vec;
- if (QQmlStringConverters::createFromString(QMetaType::QVector4D, binding->valueAsString(&qmlUnit->header), &vec, sizeof(vec))) {
- argv[0] = reinterpret_cast<void *>(&vec);
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
- } else {
- recordError(binding->valueLocation, tr("Invalid property assignment: 4D vector expected"));
- }
+ bool ok = QQmlStringConverters::createFromString(QMetaType::QVector4D, binding->valueAsString(&qmlUnit->header), &vec, sizeof(vec));
+ Q_ASSERT(ok);
+ Q_UNUSED(ok);
+ argv[0] = reinterpret_cast<void *>(&vec);
+ QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
}
break;
case QVariant::RegExp:
- recordError(binding->valueLocation, tr("Invalid property assignment: regular expression expected; use /pattern/ syntax"));
+ Q_ASSERT(!"not possible");
break;
default: {
// generate single literal value assignment to a list property if required
if (property->propType == qMetaTypeId<QList<qreal> >()) {
- if (binding->type == QV4::CompiledData::Binding::Type_Number) {
- QList<qreal> value;
- value.append(binding->valueAsNumber());
- argv[0] = reinterpret_cast<void *>(&value);
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
- } else {
- recordError(binding->valueLocation, tr("Invalid property assignment: real or array of reals expected"));
- }
+ Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Number);
+ QList<qreal> value;
+ value.append(binding->valueAsNumber());
+ argv[0] = reinterpret_cast<void *>(&value);
+ QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
break;
} else if (property->propType == qMetaTypeId<QList<int> >()) {
- if (binding->type == QV4::CompiledData::Binding::Type_Number) {
- double n = binding->valueAsNumber();
- if (double(int(n)) == n) {
- QList<int> value;
- value.append(int(n));
- argv[0] = reinterpret_cast<void *>(&value);
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
- break;
- } else {
- recordError(binding->valueLocation, tr("Invalid property assignment: int or array of ints expected"));
- }
- }
+ Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Number);
+ double n = binding->valueAsNumber();
+ QList<int> value;
+ value.append(int(n));
+ argv[0] = reinterpret_cast<void *>(&value);
+ QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
break;
} else if (property->propType == qMetaTypeId<QList<bool> >()) {
- if (binding->type == QV4::CompiledData::Binding::Type_Boolean) {
- QList<bool> value;
- value.append(binding->valueAsBoolean());
- argv[0] = reinterpret_cast<void *>(&value);
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
- } else {
- recordError(binding->valueLocation, tr("Invalid property assignment: bool or array of bools expected"));
- }
+ Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Boolean);
+ QList<bool> value;
+ value.append(binding->valueAsBoolean());
+ argv[0] = reinterpret_cast<void *>(&value);
+ QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
break;
} else if (property->propType == qMetaTypeId<QList<QUrl> >()) {
- if (binding->type == QV4::CompiledData::Binding::Type_String) {
- QString urlString = binding->valueAsString(&qmlUnit->header);
- QUrl u = urlString.isEmpty() ? QUrl() : this->url.resolved(QUrl(urlString));
- QList<QUrl> value;
- value.append(u);
- argv[0] = reinterpret_cast<void *>(&value);
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
- } else {
- recordError(binding->valueLocation, tr("Invalid property assignment: url or array of urls expected"));
- }
+ Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_String);
+ QString urlString = binding->valueAsString(&qmlUnit->header);
+ QUrl u = urlString.isEmpty() ? QUrl() : this->url.resolved(QUrl(urlString));
+ QList<QUrl> value;
+ value.append(u);
+ argv[0] = reinterpret_cast<void *>(&value);
+ QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
break;
} else if (property->propType == qMetaTypeId<QList<QString> >()) {
- if (binding->type == QV4::CompiledData::Binding::Type_String) {
- QList<QString> value;
- value.append(binding->valueAsString(&qmlUnit->header));
- argv[0] = reinterpret_cast<void *>(&value);
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
- } else {
- recordError(binding->valueLocation, tr("Invalid property assignment: string or array of strings expected"));
- }
+ Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_String);
+ QList<QString> value;
+ value.append(binding->valueAsString(&qmlUnit->header));
+ argv[0] = reinterpret_cast<void *>(&value);
+ QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
break;
} else if (property->propType == qMetaTypeId<QJSValue>()) {
QJSValue value;
// otherwise, try a custom type assignment
QString stringValue = binding->valueAsString(&qmlUnit->header);
QQmlMetaType::StringConverter converter = QQmlMetaType::customStringConverter(property->propType);
- if (converter) {
- QVariant value = (*converter)(stringValue);
+ Q_ASSERT(converter);
+ QVariant value = (*converter)(stringValue);
- QMetaProperty metaProperty = _qobject->metaObject()->property(property->coreIndex);
- if (value.isNull() || ((int)metaProperty.type() != property->propType && metaProperty.userType() != property->propType)) {
- recordError(binding->location, tr("Cannot assign value %1 to property %2").arg(stringValue).arg(QString::fromUtf8(metaProperty.name())));
- break;
- }
-
- argv[0] = value.data();
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
- } else {
- recordError(binding->location, tr("Invalid property assignment: unsupported type \"%1\"").arg(QString::fromLatin1(QMetaType::typeName(property->propType))));
+ QMetaProperty metaProperty = _qobject->metaObject()->property(property->coreIndex);
+ if (value.isNull() || ((int)metaProperty.type() != property->propType && metaProperty.userType() != property->propType)) {
+ recordError(binding->location, tr("Cannot assign value %1 to property %2").arg(stringValue).arg(QString::fromUtf8(metaProperty.name())));
+ break;
}
+
+ argv[0] = value.data();
+ QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
}
break;
}
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);
QObject *createdSubObject = 0;
if (binding->type == QV4::CompiledData::Binding::Type_Object) {
- if (_valueTypeProperty) {
- recordError(binding->location, tr("Unexpected object assignment"));
- return false;
- }
+ Q_ASSERT(!_valueTypeProperty);
createdSubObject = createInstance(binding->value.objectIndex, _bindingTarget);
if (!createdSubObject)
return false;
if (_currentList.append)
_currentList.append(&_currentList, itemToAdd);
} else {
- QQmlEnginePrivate *enginePrivate = QQmlEnginePrivate::get(engine);
-
- // We want to raw metaObject here as the raw metaobject is the
- // actual property type before we applied any extensions that might
- // effect the properties on the type, but don't effect assignability
- QQmlPropertyCache *propertyMetaObject = enginePrivate->rawPropertyCacheForType(property->propType);
-
- // Will be true if the assgned type inherits propertyMetaObject
- bool isAssignable = false;
- // Determine isAssignable value
- if (propertyMetaObject) {
- QQmlPropertyCache *c = propertyCaches.value(binding->value.objectIndex);
- if (!c)
- c = enginePrivate->cache(createdSubObject);
- while (c && !isAssignable) {
- isAssignable |= c == propertyMetaObject;
- c = c->parent();
- }
- }
-
- if (isAssignable) {
- argv[0] = &createdSubObject;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
- } else {
- recordError(binding->valueLocation, tr("Cannot assign object to property"));
- return false;
- }
+ // pointer compatibility was tested in QQmlPropertyValidator at type compile time
+ argv[0] = &createdSubObject;
+ QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
}
return true;
}