aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@digia.com>2014-03-17 14:42:05 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-03-17 15:45:45 +0100
commitacf1298e21abd2fb12d8364c593fbbff345374bc (patch)
tree30533bedc74cbf5f55ba767c34daa694e746c865
parent3f362cdf9304afeed06081cd5abfcaf6aaabe19e (diff)
Fix crash with lazy binding initialization and compile time calculated dependencies
During lazy binding initialization we may execute bindings where we calculated dependencies to the context object at compile time. In order to register those dependencies, the contet object needs to be set in the QQmlContextData. This patch makes sure to set it before setting up the bindings. Change-Id: Iacd360140cd9c389487bda82f6a7e6cc3a44c154 Reviewed-by: Lars Knoll <lars.knoll@digia.com>
-rw-r--r--src/qml/qml/qqmlcontextwrapper.cpp1
-rw-r--r--src/qml/qml/qqmlobjectcreator.cpp11
-rw-r--r--src/qml/qml/qqmlobjectcreator_p.h2
-rw-r--r--tests/auto/qml/qqmlecmascript/data/SubObject.qml8
-rw-r--r--tests/auto/qml/qqmlecmascript/data/contextObjectOnLazyBindings.qml10
-rw-r--r--tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp13
6 files changed, 40 insertions, 5 deletions
diff --git a/src/qml/qml/qqmlcontextwrapper.cpp b/src/qml/qml/qqmlcontextwrapper.cpp
index 07ef86e16f..54bf986b8e 100644
--- a/src/qml/qml/qqmlcontextwrapper.cpp
+++ b/src/qml/qml/qqmlcontextwrapper.cpp
@@ -387,6 +387,7 @@ void QmlContextWrapper::registerQmlDependencies(ExecutionEngine *engine, const C
capture->captureProperty(&qmlContext->idValues[*idObjectDependency].bindings);
}
+ Q_ASSERT(qmlContext->contextObject);
const quint32 *contextPropertyDependency = compiledFunction->qmlContextPropertiesDependencyTable();
const int contextPropertyDependencyCount = compiledFunction->nDependingContextProperties;
for (int i = 0; i < contextPropertyDependencyCount; ++i) {
diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp
index d0852bbef2..0825b8ec53 100644
--- a/src/qml/qml/qqmlobjectcreator.cpp
+++ b/src/qml/qml/qqmlobjectcreator.cpp
@@ -213,7 +213,7 @@ QObject *QQmlObjectCreator::create(int subComponentIndex, QObject *parent, QQmlI
context->importedScripts = sharedState->creationContext->importedScripts;
}
- QObject *instance = createInstance(objectToCreate, parent);
+ QObject *instance = createInstance(objectToCreate, parent, /*isContextObject*/true);
if (instance) {
QQmlData *ddata = QQmlData::get(instance);
Q_ASSERT(ddata);
@@ -221,8 +221,6 @@ QObject *QQmlObjectCreator::create(int subComponentIndex, QObject *parent, QQmlI
ddata->compiledData->release();
ddata->compiledData = compiledData;
ddata->compiledData->addref();
-
- context->contextObject = instance;
}
Q_QML_VME_PROFILE(sharedState->profiler, stop());
@@ -1014,7 +1012,7 @@ void QQmlObjectCreator::recordError(const QV4::CompiledData::Location &location,
errors << error;
}
-QObject *QQmlObjectCreator::createInstance(int index, QObject *parent)
+QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isContextObject)
{
ActiveOCRestorer ocRestorer(this, QQmlEnginePrivate::get(engine));
@@ -1111,6 +1109,11 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent)
if (idEntry != objectIndexToId.constEnd())
context->setIdProperty(idEntry.value(), instance);
+ // Register the context object in the context early on in order for pending binding
+ // initialization to find it available.
+ if (isContextObject)
+ context->contextObject = instance;
+
QBitArray bindingsToSkip;
if (customParser) {
QHash<int, QQmlCompiledData::CustomParserData>::ConstIterator entry = compiledData->customParserData.find(index);
diff --git a/src/qml/qml/qqmlobjectcreator_p.h b/src/qml/qml/qqmlobjectcreator_p.h
index 9fd52a9f48..379a3b2970 100644
--- a/src/qml/qml/qqmlobjectcreator_p.h
+++ b/src/qml/qml/qqmlobjectcreator_p.h
@@ -96,7 +96,7 @@ private:
void init(QQmlContextData *parentContext);
- QObject *createInstance(int index, QObject *parent = 0);
+ QObject *createInstance(int index, QObject *parent = 0, bool isContextObject = false);
bool populateInstance(int index, QObject *instance,
QObject *bindingTarget, QQmlPropertyData *valueTypeProperty,
diff --git a/tests/auto/qml/qqmlecmascript/data/SubObject.qml b/tests/auto/qml/qqmlecmascript/data/SubObject.qml
new file mode 100644
index 0000000000..4658edd1db
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/SubObject.qml
@@ -0,0 +1,8 @@
+import QtQml 2.0
+QtObject {
+ property int testValue: -1
+ property int subValue;
+ onSubValueChanged: {
+ testValue = this.someExpression
+ }
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/contextObjectOnLazyBindings.qml b/tests/auto/qml/qqmlecmascript/data/contextObjectOnLazyBindings.qml
new file mode 100644
index 0000000000..33b21c74a8
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/contextObjectOnLazyBindings.qml
@@ -0,0 +1,10 @@
+import QtQml 2.0
+QtObject {
+ property SubObject subObject: SubObject {
+ subValue: 20;
+ property int someExpression: {
+ return someValue;
+ }
+ }
+ property int someValue: 42
+}
diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
index b6c564a6ce..085bf24430 100644
--- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
+++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
@@ -320,6 +320,7 @@ private slots:
void singletonWithEnum();
void lazyBindingEvaluation();
void varPropertyAccessOnObjectWithInvalidContext();
+ void contextObjectOnLazyBindings();
private:
// static void propertyVarWeakRefCallback(v8::Persistent<v8::Value> object, void* parameter);
@@ -7579,6 +7580,18 @@ void tst_qqmlecmascript::varPropertyAccessOnObjectWithInvalidContext()
QVERIFY(obj->property("success") == true);
}
+void tst_qqmlecmascript::contextObjectOnLazyBindings()
+{
+ QQmlComponent component(&engine, testFileUrl("contextObjectOnLazyBindings.qml"));
+ QScopedPointer<QObject> obj(component.create());
+ if (obj.isNull())
+ qDebug() << component.errors().first().toString();
+ QVERIFY(!obj.isNull());
+ QObject *subObject = qvariant_cast<QObject*>(obj->property("subObject"));
+ QVERIFY(subObject);
+ QCOMPARE(subObject->property("testValue").toInt(), int(42));
+}
+
QTEST_MAIN(tst_qqmlecmascript)
#include "tst_qqmlecmascript.moc"