diff options
author | Aaron Kennedy <aaron.kennedy@nokia.com> | 2011-11-02 14:28:02 +0000 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2011-11-04 11:27:52 +0100 |
commit | f9261feb16d02e985982dd46783ea54c2cfce91b (patch) | |
tree | 205743bcd164628f882aa35580fd136384a28acb /tests | |
parent | 0dd867535bebf6db673d4f03959e62e94ff35ba2 (diff) |
Skip the captured properties step in bindings
Objects and notifiers in the capturedProperties list were not guarded
which can lead to crashes if they're deleted prior to the binding
completing. Now the notifiers are connected to and guarded immediately
to prevent this.
Change-Id: I912e323c52bf6169fb5077e552d5d38d9aa7faec
Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
Diffstat (limited to 'tests')
5 files changed, 77 insertions, 1 deletions
diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/deleteWhileBindingRunning.qml b/tests/auto/declarative/qdeclarativeecmascript/data/deleteWhileBindingRunning.qml new file mode 100644 index 0000000000..b5cc59e2c0 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/deleteWhileBindingRunning.qml @@ -0,0 +1,5 @@ +import Qt.test 1.0 + +MyDeleteObject { + property int result: nestedObject.intProperty + deleteNestedObject +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/nonNotifyable.qml b/tests/auto/declarative/qdeclarativeecmascript/data/nonNotifyable.qml new file mode 100644 index 0000000000..2b8b113c34 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/nonNotifyable.qml @@ -0,0 +1,6 @@ +import Qt.test 1.0 + +MyQmlObject { + id: root + property int test: root.value +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/testtypes.cpp b/tests/auto/declarative/qdeclarativeecmascript/testtypes.cpp index 781b78663f..9213b61a3c 100644 --- a/tests/auto/declarative/qdeclarativeecmascript/testtypes.cpp +++ b/tests/auto/declarative/qdeclarativeecmascript/testtypes.cpp @@ -161,6 +161,7 @@ void registerTypes() qmlRegisterExtendedType<DefaultPropertyExtendedObject, DefaultPropertyExtensionObject>("Qt.test", 1,0, "DefaultPropertyExtendedObject"); qmlRegisterType<OverrideDefaultPropertyObject>("Qt.test", 1,0, "OverrideDefaultPropertyObject"); qmlRegisterType<MyRevisionedClass>("Qt.test",1,0,"MyRevisionedClass"); + qmlRegisterType<MyDeleteObject>("Qt.test", 1,0, "MyDeleteObject"); qmlRegisterType<MyRevisionedClass,1>("Qt.test",1,1,"MyRevisionedClass"); // test scarce resource property binding post-evaluation optimisation diff --git a/tests/auto/declarative/qdeclarativeecmascript/testtypes.h b/tests/auto/declarative/qdeclarativeecmascript/testtypes.h index af4225c8da..9fbbd5052b 100644 --- a/tests/auto/declarative/qdeclarativeecmascript/testtypes.h +++ b/tests/auto/declarative/qdeclarativeecmascript/testtypes.h @@ -1229,6 +1229,26 @@ private: QList<QPoint> m_pointList; // not a supported sequence type }; +class MyDeleteObject : public QObject +{ + Q_OBJECT + Q_PROPERTY(QObject *nestedObject READ nestedObject NOTIFY nestedObjectChanged); + Q_PROPERTY(int deleteNestedObject READ deleteNestedObject NOTIFY deleteNestedObjectChanged); + +public: + MyDeleteObject() : m_nestedObject(new MyQmlObject) {} + + QObject *nestedObject() const { return m_nestedObject; } + int deleteNestedObject() { delete m_nestedObject; m_nestedObject = 0; return 1; } + +signals: + void nestedObjectChanged(); + void deleteNestedObjectChanged(); + +private: + MyQmlObject *m_nestedObject; +}; + void registerTypes(); #endif // TESTTYPES_H diff --git a/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp b/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp index ee228ec3b8..57e4fe1a46 100644 --- a/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp +++ b/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp @@ -51,6 +51,7 @@ #include <private/qdeclarativeengine_p.h> #include <private/qv8gccallback_p.h> #include <private/qdeclarativevmemetaobject_p.h> +#include <private/qv4compiler_p.h> #include "testtypes.h" #include "testhttpserver.h" #include "../shared/util.h" @@ -216,7 +217,8 @@ private slots: void signalHandlers(); void doubleEvaluate(); void forInLoop(); - + void nonNotifyable(); + void deleteWhileBindingRunning(); void callQtInvokables(); void invokableObjectArg(); void invokableObjectRet(); @@ -5046,6 +5048,39 @@ void tst_qdeclarativeecmascript::doubleEvaluate() delete object; } +static QStringList messages; +static void captureMsgHandler(QtMsgType, const char *msg) +{ + messages.append(QLatin1String(msg)); +} + +void tst_qdeclarativeecmascript::nonNotifyable() +{ + QV4Compiler::enableV4(false); + QDeclarativeComponent component(&engine, TEST_FILE("nonNotifyable.qml")); + QV4Compiler::enableV4(true); + + QtMsgHandler old = qInstallMsgHandler(captureMsgHandler); + messages.clear(); + QObject *object = component.create(); + qInstallMsgHandler(old); + + QVERIFY(object != 0); + + QString expected1 = QLatin1String("QDeclarativeExpression: Expression ") + + component.url().toString() + + QLatin1String(":5 depends on non-NOTIFYable properties:"); + QString expected2 = QLatin1String(" ") + + QLatin1String(object->metaObject()->className()) + + QLatin1String("::value"); + + QCOMPARE(messages.length(), 2); + QCOMPARE(messages.at(0), expected1); + QCOMPARE(messages.at(1), expected2); + + delete object; +} + void tst_qdeclarativeecmascript::forInLoop() { QDeclarativeComponent component(&engine, TEST_FILE("forInLoop.qml")); @@ -5065,6 +5100,15 @@ void tst_qdeclarativeecmascript::forInLoop() delete object; } +// An object the binding depends on is deleted while the binding is still running +void tst_qdeclarativeecmascript::deleteWhileBindingRunning() +{ + QDeclarativeComponent component(&engine, TEST_FILE("deleteWhileBindingRunning.qml")); + QObject *object = component.create(); + QVERIFY(object != 0); + delete object; +} + QTEST_MAIN(tst_qdeclarativeecmascript) #include "tst_qdeclarativeecmascript.moc" |