summaryrefslogtreecommitdiffstats
path: root/src/declarative/qml/qdeclarativeobjectscriptclass.cpp
diff options
context:
space:
mode:
authorAaron Kennedy <aaron.kennedy@nokia.com>2010-04-08 06:13:31 (GMT)
committerAaron Kennedy <aaron.kennedy@nokia.com>2010-04-08 06:18:43 (GMT)
commitdf1788b4dbbb2826ae63f26bdf166342595343f4 (patch)
treeb021f683c6da72f9c46d0decbf0f8aa97dd2a9d4 /src/declarative/qml/qdeclarativeobjectscriptclass.cpp
parent942a605a52dbbd6dfa824e3b76e37576c7d79f6e (diff)
downloadQt-df1788b4dbbb2826ae63f26bdf166342595343f4.zip
Qt-df1788b4dbbb2826ae63f26bdf166342595343f4.tar.gz
Qt-df1788b4dbbb2826ae63f26bdf166342595343f4.tar.bz2
Cleanup handling of errors in bindings and scripts
QML used to silently ignore a log of errors - such as a failed assignment to a QObject property. These errors are now all reported as exceptions in JavaScript. Other questionable activities, like assigning a JavaScript array to a "property var" property which appeared to work, thanks to QtScript's transparent conversion of arrays to a QVariantList, are now blocked entirely. QTBUG-9152 QTBUG-9382 QTBUG-9341 QTBUG-6886
Diffstat (limited to 'src/declarative/qml/qdeclarativeobjectscriptclass.cpp')
-rw-r--r--src/declarative/qml/qdeclarativeobjectscriptclass.cpp68
1 files changed, 44 insertions, 24 deletions
diff --git a/src/declarative/qml/qdeclarativeobjectscriptclass.cpp b/src/declarative/qml/qdeclarativeobjectscriptclass.cpp
index 32ba2c3..8f37a1e 100644
--- a/src/declarative/qml/qdeclarativeobjectscriptclass.cpp
+++ b/src/declarative/qml/qdeclarativeobjectscriptclass.cpp
@@ -52,6 +52,7 @@
#include <QtCore/qtimer.h>
#include <QtCore/qvarlengtharray.h>
+#include <QtScript/qscriptcontextinfo.h>
Q_DECLARE_METATYPE(QScriptValue);
@@ -225,15 +226,10 @@ QDeclarativeObjectScriptClass::property(QObject *obj, const Identifier &name)
if (lastData->flags & QDeclarativePropertyCache::Data::IsVMEFunction) {
return Value(scriptEngine, ((QDeclarativeVMEMetaObject *)(obj->metaObject()))->vmeMethod(lastData->coreIndex));
} else {
-#if (QT_VERSION > QT_VERSION_CHECK(4, 6, 2)) || defined(QT_HAVE_QSCRIPTDECLARATIVECLASS_VALUE)
// Uncomment to use QtScript method call logic
// QScriptValue sobj = scriptEngine->newQObject(obj);
// return Value(scriptEngine, sobj.property(toString(name)));
return Value(scriptEngine, methods.newMethod(obj, lastData));
-#else
- QScriptValue sobj = scriptEngine->newQObject(obj);
- return Value(scriptEngine, sobj.property(toString(name)));
-#endif
}
} else {
if (enginePriv->captureProperties && !(lastData->flags & QDeclarativePropertyCache::Data::IsConstant)) {
@@ -298,7 +294,6 @@ QDeclarativeObjectScriptClass::property(QObject *obj, const Identifier &name)
QVariant var = obj->metaObject()->property(lastData->coreIndex).read(obj);
return Value(scriptEngine, enginePriv->scriptValueFromVariant(var));
}
-
}
}
@@ -306,40 +301,40 @@ void QDeclarativeObjectScriptClass::setProperty(Object *object,
const Identifier &name,
const QScriptValue &value)
{
- return setProperty(toQObject(object), name, value);
+ return setProperty(toQObject(object), name, value, context());
}
void QDeclarativeObjectScriptClass::setProperty(QObject *obj,
- const Identifier &name,
- const QScriptValue &value,
- QDeclarativeContextData *evalContext)
+ const Identifier &name,
+ const QScriptValue &value,
+ QScriptContext *context,
+ QDeclarativeContextData *evalContext)
{
Q_UNUSED(name);
Q_ASSERT(obj);
Q_ASSERT(lastData);
+ Q_ASSERT(context);
if (!lastData->isValid()) {
QString error = QLatin1String("Cannot assign to non-existent property \"") +
toString(name) + QLatin1Char('\"');
- if (context())
- context()->throwError(error);
+ context->throwError(error);
return;
}
if (!(lastData->flags & QDeclarativePropertyCache::Data::IsWritable)) {
QString error = QLatin1String("Cannot assign to read-only property \"") +
toString(name) + QLatin1Char('\"');
- if (context())
- context()->throwError(error);
+ context->throwError(error);
return;
}
QDeclarativeEnginePrivate *enginePriv = QDeclarativeEnginePrivate::get(engine);
- if (!evalContext && context()) {
+ if (!evalContext) {
// Global object, QScriptContext activation object, QDeclarativeContext object
- QScriptValue scopeNode = scopeChainValue(context(), -3);
+ QScriptValue scopeNode = scopeChainValue(context, -3);
if (scopeNode.isValid()) {
Q_ASSERT(scriptClass(scopeNode) == enginePriv->contextClass);
@@ -355,10 +350,29 @@ void QDeclarativeObjectScriptClass::setProperty(QObject *obj,
if (value.isUndefined() && lastData->flags & QDeclarativePropertyCache::Data::IsResettable) {
void *a[] = { 0 };
QMetaObject::metacall(obj, QMetaObject::ResetProperty, lastData->coreIndex, a);
+ } else if (value.isUndefined()) {
+ QString error = QLatin1String("Cannot assign [undefined] to ") +
+ QLatin1String(QMetaType::typeName(lastData->propType));
+ context->throwError(error);
} else {
- // ### Can well known types be optimized?
- QVariant v = enginePriv->scriptValueToVariant(value);
- QDeclarativePropertyPrivate::write(obj, *lastData, v, evalContext);
+ QVariant v = enginePriv->scriptValueToVariant(value, lastData->propType);
+
+ if (!value.isVariant() && v.userType() == QMetaType::QVariantList &&
+ lastData->propType == qMetaTypeId<QVariant>()) {
+
+ QString error = QLatin1String("Cannot assign JavaScript array to QML variant property");
+ context->throwError(error);
+ } else if (!QDeclarativePropertyPrivate::write(obj, *lastData, v, evalContext)) {
+ const char *valueType = 0;
+ if (v.userType() == QVariant::Invalid) valueType = "null";
+ else valueType = QMetaType::typeName(v.userType());
+
+ QString error = QLatin1String("Cannot assign ") +
+ QLatin1String(valueType) +
+ QLatin1String(" to ") +
+ QLatin1String(QMetaType::typeName(lastData->propType));
+ context->throwError(error);
+ }
}
}
@@ -459,8 +473,6 @@ bool QDeclarativeObjectScriptClass::compare(Object *o1, Object *o2)
return d1 == d2 || d1->object == d2->object;
}
-#if (QT_VERSION > QT_VERSION_CHECK(4, 6, 2)) || defined(QT_HAVE_QSCRIPTDECLARATIVECLASS_VALUE)
-
struct MethodData : public QScriptDeclarativeClass::Object {
MethodData(QObject *o, const QDeclarativePropertyCache::Data &d) : object(o), data(d) {}
@@ -690,7 +702,17 @@ void MetaCallArgument::fromScriptValue(int callType, QDeclarativeEngine *engine,
new (&data) QVariant(QDeclarativeEnginePrivate::get(engine)->scriptValueToVariant(value));
type = callType;
} else if (callType == qMetaTypeId<QList<QObject*> >()) {
- new (&data) QList<QObject *>(); // We don't support passing in QList<QObject*>
+ QList<QObject *> *list = new (&data) QList<QObject *>();
+ if (value.isArray()) {
+ int length = value.property(QLatin1String("length")).toInt32();
+ for (int ii = 0; ii < length; ++ii) {
+ QScriptValue arrayItem = value.property(ii);
+ QObject *d = arrayItem.toQObject();
+ list->append(d);
+ }
+ } else if (QObject *d = value.toQObject()) {
+ list->append(d);
+ }
type = callType;
} else {
new (&data) QVariant();
@@ -803,7 +825,5 @@ QDeclarativeObjectMethodScriptClass::Value QDeclarativeObjectMethodScriptClass::
return Value();
}
-#endif
-
QT_END_NAMESPACE