summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp2
-rw-r--r--src/declarative/qml/qdeclarativebinding.cpp13
-rw-r--r--src/declarative/qml/qdeclarativedata_p.h10
-rw-r--r--src/declarative/qml/qdeclarativeengine.cpp12
-rw-r--r--src/declarative/qml/qdeclarativeobjectscriptclass.cpp3
-rw-r--r--src/declarative/qml/qdeclarativevmemetaobject.cpp3
-rw-r--r--src/declarative/util/qdeclarativepropertychanges.cpp11
-rw-r--r--tests/auto/declarative/qdeclarativeconnection/data/connection-unknownsignals-ignored.qml8
-rw-r--r--tests/auto/declarative/qdeclarativeconnection/data/connection-unknownsignals-notarget.qml7
-rw-r--r--tests/auto/declarative/qdeclarativeconnection/data/connection-unknownsignals-parent.qml7
-rw-r--r--tests/auto/declarative/qdeclarativeconnection/data/connection-unknownsignals.qml7
-rw-r--r--tests/auto/declarative/qdeclarativeecmascript/data/functionAssignment.1.qml5
-rw-r--r--tests/auto/declarative/qdeclarativeecmascript/data/functionAssignment.2.qml13
-rw-r--r--tests/auto/declarative/qdeclarativeecmascript/data/qtcreatorbug_1289.qml13
-rw-r--r--tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp61
-rw-r--r--tools/qml/main.cpp9
16 files changed, 164 insertions, 20 deletions
diff --git a/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp b/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp
index 2945b6c..7c55009 100644
--- a/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp
+++ b/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp
@@ -143,7 +143,9 @@ void QDeclarativeItemModule::defineModule()
qmlRegisterType<QAction>();
qmlRegisterType<QDeclarativePen>();
qmlRegisterType<QDeclarativeFlickableVisibleArea>();
+#ifndef QT_NO_GRAPHICSEFFECT
qmlRegisterType<QGraphicsEffect>();
+#endif
qmlRegisterUncreatableType<QDeclarativeKeyNavigationAttached>("Qt",4,7,"KeyNavigation",QDeclarativeKeyNavigationAttached::tr("KeyNavigation is only available via attached properties"));
qmlRegisterUncreatableType<QDeclarativeKeysAttached>("Qt",4,7,"Keys",QDeclarativeKeysAttached::tr("Keys is only available via attached properties"));
diff --git a/src/declarative/qml/qdeclarativebinding.cpp b/src/declarative/qml/qdeclarativebinding.cpp
index d44e7fb..8043ea9 100644
--- a/src/declarative/qml/qdeclarativebinding.cpp
+++ b/src/declarative/qml/qdeclarativebinding.cpp
@@ -193,7 +193,18 @@ void QDeclarativeBinding::update(QDeclarativePropertyPrivate::WriteFlags flags)
data->error.setColumn(-1);
data->error.setDescription(QLatin1String("Unable to assign [undefined] to ") + QLatin1String(QMetaType::typeName(data->property.propertyType())));
- } else if (data->property.object() &&
+ } else if (!scriptValue.isRegExp() && scriptValue.isFunction()) {
+
+ QUrl url = QUrl(data->url);
+ int line = data->line;
+ if (url.isEmpty()) url = QUrl(QLatin1String("<Unknown File>"));
+
+ data->error.setUrl(url);
+ data->error.setLine(line);
+ data->error.setColumn(-1);
+ data->error.setDescription(QLatin1String("Unable to assign a function to a property."));
+
+ } else if (data->property.object() &&
!QDeclarativePropertyPrivate::write(data->property, value, flags)) {
QUrl url = QUrl(data->url);
diff --git a/src/declarative/qml/qdeclarativedata_p.h b/src/declarative/qml/qdeclarativedata_p.h
index 4a56536..e916273 100644
--- a/src/declarative/qml/qdeclarativedata_p.h
+++ b/src/declarative/qml/qdeclarativedata_p.h
@@ -152,11 +152,11 @@ public:
template<class T>
void QDeclarativeGuard<T>::addGuard()
{
- if (QObjectPrivate::get(o)->wasDeleted) {
- if (prev) remGuard();
+ Q_ASSERT(!prev);
+
+ if (QObjectPrivate::get(o)->wasDeleted)
return;
- }
-
+
QDeclarativeData *data = QDeclarativeData::get(o, true);
next = data->guards;
if (next) reinterpret_cast<QDeclarativeGuard<T> *>(next)->prev = &next;
@@ -167,6 +167,8 @@ void QDeclarativeGuard<T>::addGuard()
template<class T>
void QDeclarativeGuard<T>::remGuard()
{
+ Q_ASSERT(prev);
+
if (next) reinterpret_cast<QDeclarativeGuard<T> *>(next)->prev = prev;
*prev = next;
next = 0;
diff --git a/src/declarative/qml/qdeclarativeengine.cpp b/src/declarative/qml/qdeclarativeengine.cpp
index 8a61f1e..3f4a735 100644
--- a/src/declarative/qml/qdeclarativeengine.cpp
+++ b/src/declarative/qml/qdeclarativeengine.cpp
@@ -870,14 +870,10 @@ void QDeclarativeData::destroyed(QObject *object)
if (ownContext && context)
context->destroy();
- QDeclarativeGuard<QObject> *guard = guards;
- while (guard) {
- QDeclarativeGuard<QObject> *g = guard;
- guard = guard->next;
- g->o = 0;
- g->prev = 0;
- g->next = 0;
- g->objectDestroyed(object);
+ while (guards) {
+ QDeclarativeGuard<QObject> *guard = guards;
+ *guard = (QObject *)0;
+ guard->objectDestroyed(object);
}
if (scriptValue)
diff --git a/src/declarative/qml/qdeclarativeobjectscriptclass.cpp b/src/declarative/qml/qdeclarativeobjectscriptclass.cpp
index 671a262..33e47fb 100644
--- a/src/declarative/qml/qdeclarativeobjectscriptclass.cpp
+++ b/src/declarative/qml/qdeclarativeobjectscriptclass.cpp
@@ -368,6 +368,9 @@ void QDeclarativeObjectScriptClass::setProperty(QObject *obj,
QString error = QLatin1String("Cannot assign [undefined] to ") +
QLatin1String(QMetaType::typeName(lastData->propType));
context->throwError(error);
+ } else if (!value.isRegExp() && value.isFunction()) {
+ QString error = QLatin1String("Cannot assign a function to a property.");
+ context->throwError(error);
} else {
QVariant v;
if (lastData->flags & QDeclarativePropertyCache::Data::IsQList)
diff --git a/src/declarative/qml/qdeclarativevmemetaobject.cpp b/src/declarative/qml/qdeclarativevmemetaobject.cpp
index 45f04a0..13e9c26 100644
--- a/src/declarative/qml/qdeclarativevmemetaobject.cpp
+++ b/src/declarative/qml/qdeclarativevmemetaobject.cpp
@@ -106,8 +106,7 @@ QDeclarativeVMEVariant::~QDeclarativeVMEVariant()
void QDeclarativeVMEVariant::cleanup()
{
if (type == QVariant::Invalid) {
- } else if (type == QMetaType::QObjectStar ||
- type == QMetaType::Int ||
+ } else if (type == QMetaType::Int ||
type == QMetaType::Bool ||
type == QMetaType::Double) {
type = QVariant::Invalid;
diff --git a/src/declarative/util/qdeclarativepropertychanges.cpp b/src/declarative/util/qdeclarativepropertychanges.cpp
index 4b2d5a0..c7e3bc5 100644
--- a/src/declarative/util/qdeclarativepropertychanges.cpp
+++ b/src/declarative/util/qdeclarativepropertychanges.cpp
@@ -51,6 +51,7 @@
#include <qdeclarativecontext.h>
#include <qdeclarativeguard_p.h>
#include <qdeclarativeproperty_p.h>
+#include <qdeclarativecontext_p.h>
#include <QtCore/qdebug.h>
@@ -302,12 +303,18 @@ void QDeclarativePropertyChangesPrivate::decode()
QDeclarativeProperty prop = property(name); //### better way to check for signal property?
if (prop.type() & QDeclarativeProperty::SignalProperty) {
QDeclarativeExpression *expression = new QDeclarativeExpression(qmlContext(q), data.toString(), object);
+ QDeclarativeData *ddata = QDeclarativeData::get(q);
+ if (ddata && ddata->outerContext && !ddata->outerContext->url.isEmpty())
+ expression->setSourceLocation(ddata->outerContext->url.toString(), ddata->lineNumber);
QDeclarativeReplaceSignalHandler *handler = new QDeclarativeReplaceSignalHandler;
handler->property = prop;
handler->expression = expression;
signalReplacements << handler;
} else if (isScript) {
QDeclarativeExpression *expression = new QDeclarativeExpression(qmlContext(q), data.toString(), object);
+ QDeclarativeData *ddata = QDeclarativeData::get(q);
+ if (ddata && ddata->outerContext && !ddata->outerContext->url.isEmpty())
+ expression->setSourceLocation(ddata->outerContext->url.toString(), ddata->lineNumber);
expressions << qMakePair(name, expression);
} else {
properties << qMakePair(name, data);
@@ -437,9 +444,11 @@ QDeclarativePropertyChanges::ActionList QDeclarativePropertyChanges::actions()
if (d->isExplicit) {
a.toValue = d->expressions.at(ii).second->evaluate();
} else {
+ QDeclarativeExpression *e = d->expressions.at(ii).second;
QDeclarativeBinding *newBinding =
- new QDeclarativeBinding(d->expressions.at(ii).second->expression(), object(), qmlContext(this));
+ new QDeclarativeBinding(e->expression(), object(), qmlContext(this));
newBinding->setTarget(prop);
+ newBinding->setSourceLocation(e->sourceFile(), e->lineNumber());
a.toBinding = newBinding;
a.deletableToBinding = true;
}
diff --git a/tests/auto/declarative/qdeclarativeconnection/data/connection-unknownsignals-ignored.qml b/tests/auto/declarative/qdeclarativeconnection/data/connection-unknownsignals-ignored.qml
new file mode 100644
index 0000000..764d5ab
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativeconnection/data/connection-unknownsignals-ignored.qml
@@ -0,0 +1,8 @@
+import Qt 4.7
+
+Item {
+ id: screen
+
+ Connections { target: screen; onNotFooBar1: {} ignoreUnknownSignals: true }
+ Connections { objectName: "connections"; onNotFooBar2: {} ignoreUnknownSignals: true }
+}
diff --git a/tests/auto/declarative/qdeclarativeconnection/data/connection-unknownsignals-notarget.qml b/tests/auto/declarative/qdeclarativeconnection/data/connection-unknownsignals-notarget.qml
new file mode 100644
index 0000000..09e7812
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativeconnection/data/connection-unknownsignals-notarget.qml
@@ -0,0 +1,7 @@
+import Qt 4.7
+
+Item {
+ id: screen
+
+ Connections { objectName: "connections"; target: null; onNotFooBar: {} }
+}
diff --git a/tests/auto/declarative/qdeclarativeconnection/data/connection-unknownsignals-parent.qml b/tests/auto/declarative/qdeclarativeconnection/data/connection-unknownsignals-parent.qml
new file mode 100644
index 0000000..478503d
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativeconnection/data/connection-unknownsignals-parent.qml
@@ -0,0 +1,7 @@
+import Qt 4.7
+
+Item {
+ id: screen
+
+ Connections { objectName: "connections"; onFooBar: {} }
+}
diff --git a/tests/auto/declarative/qdeclarativeconnection/data/connection-unknownsignals.qml b/tests/auto/declarative/qdeclarativeconnection/data/connection-unknownsignals.qml
new file mode 100644
index 0000000..d4e8d7e
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativeconnection/data/connection-unknownsignals.qml
@@ -0,0 +1,7 @@
+import Qt 4.7
+
+Item {
+ id: screen
+
+ Connections { objectName: "connections"; target: screen; onFooBar: {} }
+}
diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/functionAssignment.1.qml b/tests/auto/declarative/qdeclarativeecmascript/data/functionAssignment.1.qml
new file mode 100644
index 0000000..09540f1
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativeecmascript/data/functionAssignment.1.qml
@@ -0,0 +1,5 @@
+import Qt.test 1.0
+
+MyQmlObject {
+ property variant a: function myFunction() { return 2; }
+}
diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/functionAssignment.2.qml b/tests/auto/declarative/qdeclarativeecmascript/data/functionAssignment.2.qml
new file mode 100644
index 0000000..948b39c
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativeecmascript/data/functionAssignment.2.qml
@@ -0,0 +1,13 @@
+import Qt.test 1.0
+
+MyQmlObject {
+ property variant a
+ property bool runTest: false
+ onRunTestChanged: {
+ function myFunction() {
+ console.log("hello world");
+ }
+ a = myFunction;
+ }
+
+}
diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/qtcreatorbug_1289.qml b/tests/auto/declarative/qdeclarativeecmascript/data/qtcreatorbug_1289.qml
new file mode 100644
index 0000000..b6d31d5
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativeecmascript/data/qtcreatorbug_1289.qml
@@ -0,0 +1,13 @@
+import Qt 4.7
+
+QtObject {
+ id: root
+ property QtObject object: QtObject {
+ id: nested
+ property QtObject nestedObject
+ }
+
+ Component.onCompleted: {
+ nested.nestedObject = root;
+ }
+}
diff --git a/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp b/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp
index 6cde46b..49ee335 100644
--- a/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp
+++ b/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp
@@ -142,8 +142,10 @@ private slots:
void libraryScriptAssert();
void variantsAssignedUndefined();
void qtbug_9792();
+ void qtcreatorbug_1289();
void noSpuriousWarningsAtShutdown();
void canAssignNullToQObject();
+ void functionAssignment();
void callQtInvokables();
private:
@@ -2205,6 +2207,27 @@ void tst_qdeclarativeecmascript::qtbug_9792()
delete object;
}
+// Verifies that QDeclarativeGuard<>s used in the vmemetaobject are cleaned correctly
+void tst_qdeclarativeecmascript::qtcreatorbug_1289()
+{
+ QDeclarativeComponent component(&engine, TEST_FILE("qtcreatorbug_1289.qml"));
+
+ QObject *o = component.create();
+ QVERIFY(o != 0);
+
+ QObject *nested = qvariant_cast<QObject *>(o->property("object"));
+ QVERIFY(nested != 0);
+
+ QVERIFY(qvariant_cast<QObject *>(nested->property("nestedObject")) == o);
+
+ delete nested;
+ nested = qvariant_cast<QObject *>(o->property("object"));
+ QVERIFY(nested == 0);
+
+ // If the bug is present, the next line will crash
+ delete o;
+}
+
// Test that we shut down without stupid warnings
void tst_qdeclarativeecmascript::noSpuriousWarningsAtShutdown()
{
@@ -2269,6 +2292,44 @@ void tst_qdeclarativeecmascript::canAssignNullToQObject()
}
}
+void tst_qdeclarativeecmascript::functionAssignment()
+{
+ {
+ QDeclarativeComponent component(&engine, TEST_FILE("functionAssignment.1.qml"));
+
+ QString url = component.url().toString();
+ QString warning = url + ":4: Unable to assign a function to a property.";
+ QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
+
+ MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
+ QVERIFY(o != 0);
+
+ QVERIFY(!o->property("a").isValid());
+
+ delete o;
+ }
+
+ {
+ QDeclarativeComponent component(&engine, TEST_FILE("functionAssignment.2.qml"));
+
+ MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
+ QVERIFY(o != 0);
+
+ QVERIFY(!o->property("a").isValid());
+
+ QString url = component.url().toString();
+ QString warning = url + ":10: Error: Cannot assign a function to a property.";
+ QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
+
+ o->setProperty("runTest", true);
+
+ QVERIFY(!o->property("a").isValid());
+
+ delete o;
+ }
+}
+
+
QTEST_MAIN(tst_qdeclarativeecmascript)
#include "tst_qdeclarativeecmascript.moc"
diff --git a/tools/qml/main.cpp b/tools/qml/main.cpp
index 9ccc3d2..f2c0530 100644
--- a/tools/qml/main.cpp
+++ b/tools/qml/main.cpp
@@ -125,7 +125,7 @@ void usage()
qWarning(" -sizeviewtorootobject .................... the view resizes to the changes in the content");
qWarning(" -sizerootobjecttoview .................... the content resizes to the changes in the view");
qWarning(" -qmlbrowser .............................. use a QML-based file browser");
- qWarning(" -nolog ................................... do not show log window");
+ qWarning(" -warnings ................................ show warnings in a separate log window");
qWarning(" -recordfile <output> ..................... set video recording file");
qWarning(" - ImageMagick 'convert' for GIF)");
qWarning(" - png file for raw frames");
@@ -229,7 +229,8 @@ int main(int argc, char ** argv)
bool stayOnTop = false;
bool maximized = false;
bool useNativeFileBrowser = true;
- bool showLogWidget = true;
+
+ bool showLogWidget = false;
bool sizeToView = true;
#if defined(Q_OS_SYMBIAN)
@@ -290,8 +291,8 @@ int main(int argc, char ** argv)
useGL = true;
} else if (arg == "-qmlbrowser") {
useNativeFileBrowser = false;
- } else if (arg == "-nolog") {
- showLogWidget = false;
+ } else if (arg == "-warnings") {
+ showLogWidget = true;
} else if (arg == "-I" || arg == "-L") {
if (arg == "-L")
qWarning("-L option provided for compatibility only, use -I instead");