aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthew Vogt <matthew.vogt@nokia.com>2012-05-21 13:40:22 +1000
committerQt by Nokia <qt-info@nokia.com>2012-05-21 11:22:43 +0200
commitf16f4c3b78eb0138b2dca455f702b9335eb03f40 (patch)
tree323af783bc8cc4c132d6e6b8e24c207dae67b0b8
parent65500896a05344bdfd5fcbfa9a6456f48cd4e4a4 (diff)
Ensure repeated compilation does not fail
Failure could result from the allocation of an address previously used for the same class. The test is repeated for a surprisingly large count of repetitions to increase the chance of this occurring. Change-Id: I045902c50021f23adbbd61fccf41b9c38657387a Reviewed-by: Chris Adams <christopher.adams@nokia.com>
-rw-r--r--src/qml/qml/qqmlengine.cpp9
-rw-r--r--src/qml/qml/qqmltypeloader.cpp7
-rw-r--r--tests/auto/qml/qqmlengine/data/failedCompilation.1.qml4
-rw-r--r--tests/auto/qml/qqmlengine/data/repeatedCompilation.qml9
-rw-r--r--tests/auto/qml/qqmlengine/tst_qqmlengine.cpp43
5 files changed, 68 insertions, 4 deletions
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp
index 2ebd13bb14..5111a4c087 100644
--- a/src/qml/qml/qqmlengine.cpp
+++ b/src/qml/qml/qqmlengine.cpp
@@ -1962,7 +1962,14 @@ void QQmlEnginePrivate::trimCache()
void QQmlEnginePrivate::typeUnloaded(QQmlTypeData *typeData)
{
- unregisterCompositeType(typeData->compiledData()->root);
+ if (typeData && typeData->compiledData()) {
+ const QMetaObject *mo = typeData->compiledData()->root;
+ if (QQmlPropertyCache *pc = propertyCache.value(mo)) {
+ propertyCache.remove(mo);
+ pc->release();
+ }
+ unregisterCompositeType(mo);
+ }
}
bool QQmlEnginePrivate::isTypeLoaded(const QUrl &url) const
diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp
index d550a19874..228f2f96b6 100644
--- a/src/qml/qml/qqmltypeloader.cpp
+++ b/src/qml/qml/qqmltypeloader.cpp
@@ -1244,6 +1244,7 @@ QQmlTypeData *QQmlTypeLoader::getType(const QUrl &url, Mode mode)
if (!typeData) {
typeData = new QQmlTypeData(url, None, this);
+ // TODO: if (compiledData == 0), is it safe to omit this insertion?
m_typeCache.insert(url, typeData);
QQmlDataLoader::load(typeData, mode);
}
@@ -1606,11 +1607,11 @@ void QQmlTypeLoader::trimCache(void (*callback)(void *, QQmlTypeData *), void *a
TypeCache::Iterator iter = unneededTypes.last();
unneededTypes.removeLast();
+ QQmlTypeData *typeData = iter.value();
if (callback)
- (*callback)(arg, iter.value());
-
+ (*callback)(arg, typeData);
m_typeCache.erase(iter);
- iter.value()->release();
+ typeData->release();
}
}
diff --git a/tests/auto/qml/qqmlengine/data/failedCompilation.1.qml b/tests/auto/qml/qqmlengine/data/failedCompilation.1.qml
new file mode 100644
index 0000000000..0bd3cd0254
--- /dev/null
+++ b/tests/auto/qml/qqmlengine/data/failedCompilation.1.qml
@@ -0,0 +1,4 @@
+// No imports - intentional
+
+Item {
+}
diff --git a/tests/auto/qml/qqmlengine/data/repeatedCompilation.qml b/tests/auto/qml/qqmlengine/data/repeatedCompilation.qml
new file mode 100644
index 0000000000..797381e54c
--- /dev/null
+++ b/tests/auto/qml/qqmlengine/data/repeatedCompilation.qml
@@ -0,0 +1,9 @@
+import QtQuick 2.0
+
+VMEExtendVMEComponent {
+ property bool success: false
+
+ Component.onCompleted: {
+ success = (foo == 'bar') && (bar == 'baz')
+ }
+}
diff --git a/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp b/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp
index 727635ee2c..85c32d8118 100644
--- a/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp
+++ b/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp
@@ -69,6 +69,9 @@ private slots:
void clearComponentCache();
void trimComponentCache();
void trimComponentCache_data();
+ void repeatedCompilation();
+ void failedCompilation();
+ void failedCompilation_data();
void outputWarningsToStandardError();
void objectOwnership();
void multipleEngines();
@@ -372,6 +375,46 @@ void tst_qqmlengine::trimComponentCache_data()
QTest::newRow("ScriptComponent") << "testScriptComponent.qml";
}
+void tst_qqmlengine::repeatedCompilation()
+{
+ QQmlEngine engine;
+
+ for (int i = 0; i < 100; ++i) {
+ engine.collectGarbage();
+ engine.trimComponentCache();
+
+ QQmlComponent component(&engine, testFileUrl("repeatedCompilation.qml"));
+ QVERIFY(component.isReady());
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(object != 0);
+ QCOMPARE(object->property("success").toBool(), true);
+ }
+}
+
+void tst_qqmlengine::failedCompilation()
+{
+ QFETCH(QString, file);
+
+ QQmlEngine engine;
+
+ QQmlComponent component(&engine, testFileUrl(file));
+ QVERIFY(!component.isReady());
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(object == 0);
+
+ engine.collectGarbage();
+ engine.trimComponentCache();
+ engine.clearComponentCache();
+}
+
+void tst_qqmlengine::failedCompilation_data()
+{
+ QTest::addColumn<QString>("file");
+
+ QTest::newRow("Invalid URL") << "failedCompilation.does.not.exist.qml";
+ QTest::newRow("Invalid content") << "failedCompilation.1.qml";
+}
+
static QStringList warnings;
static void msgHandler(QtMsgType, const char *warning)
{