diff options
author | Simon Hausmann <simon.hausmann@theqtcompany.com> | 2016-05-11 15:22:51 +0200 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@theqtcompany.com> | 2016-05-18 10:08:30 +0000 |
commit | 72515ebe5a63c201fde09471bc646dbe15110a6b (patch) | |
tree | 22588014a613d0c2d72b909e28b1667a1c5dc9ec /tests/auto/qml/qqmlcomponent | |
parent | 74628af12aa8f72a56635bf27e7361861c50f796 (diff) |
Fix crashes when incubating objects asynchronously with initial properties
This is a regression from commit 94e337fa95425d259e81b4d21f4d0853108553bd where
we accidentally ended up not having a calling QML context set anymore when
initializing the properties on newly incubated objects as provided by the
caller. The QML context is necessary as for example when we set a URL property,
the URL can be relative and it will be resolved to the base url of the context
when written, such as in in QQmlPropertyPrivate::write.
Change-Id: I1d896381fc92f653a7d76f4d82174bca48828f5e
Reviewed-by: Lars Knoll <lars.knoll@theqtcompany.com>
Diffstat (limited to 'tests/auto/qml/qqmlcomponent')
3 files changed, 75 insertions, 0 deletions
diff --git a/tests/auto/qml/qqmlcomponent/data/callingQmlContext.qml b/tests/auto/qml/qqmlcomponent/data/callingQmlContext.qml new file mode 100644 index 0000000000..8193d0f36c --- /dev/null +++ b/tests/auto/qml/qqmlcomponent/data/callingQmlContext.qml @@ -0,0 +1,13 @@ +import QtQml 2.0 +import qqmlcomponenttest 1.0 +QtObject { + property Component factory + property QtObject incubatedObject + + Component.onCompleted: { + var incubatorState = factory.incubateObject(null, { value: 42 }) + incubatorState.onStatusChanged = function(status) { + incubatedObject = incubatorState.object + } + } +} diff --git a/tests/auto/qml/qqmlcomponent/data/callingQmlContextComponent.qml b/tests/auto/qml/qqmlcomponent/data/callingQmlContextComponent.qml new file mode 100644 index 0000000000..adf491c87e --- /dev/null +++ b/tests/auto/qml/qqmlcomponent/data/callingQmlContextComponent.qml @@ -0,0 +1,3 @@ +import qqmlcomponenttest 1.0 +CallingContextCheckingClass { +} diff --git a/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp b/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp index 85579a6019..680ea720a8 100644 --- a/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp +++ b/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp @@ -40,6 +40,7 @@ #include <QtQuick> #include <QtQuick/private/qquickrectangle_p.h> #include <QtQuick/private/qquickmousearea_p.h> +#include <private/qv8engine_p.h> #include <qcolor.h> #include "../../shared/util.h" #include "testhttpserver.h" @@ -116,6 +117,7 @@ private slots: void onDestructionCount(); void recursion(); void recursionContinuation(); + void callingContextForInitialProperties(); private: QQmlEngine engine; @@ -523,6 +525,63 @@ void tst_qqmlcomponent::recursionContinuation() QVERIFY(object->property("success").toBool()); } +class CallingContextCheckingClass : public QObject +{ + Q_OBJECT + Q_PROPERTY(int value READ value WRITE setValue) +public: + CallingContextCheckingClass() + : m_value(0) + {} + + int value() const { return m_value; } + void setValue(int v) { + scopeObject.clear(); + callingContextData.setContextData(0); + + m_value = v; + QJSEngine *jsEngine = qjsEngine(this); + if (!jsEngine) + return; + QV4::ExecutionEngine *v4 = QV8Engine::getV4(jsEngine); + if (!v4) + return; + QV4::Scope scope(v4); + QV4::Scoped<QV4::QmlContext> qmlContext(scope, v4->qmlContext()); + if (!qmlContext) + return; + callingContextData = qmlContext->qmlContext(); + scopeObject = qmlContext->qmlScope(); + } + + int m_value; + QQmlGuardedContextData callingContextData; + QPointer<QObject> scopeObject; +}; + +void tst_qqmlcomponent::callingContextForInitialProperties() +{ + qmlRegisterType<CallingContextCheckingClass>("qqmlcomponenttest", 1, 0, "CallingContextCheckingClass"); + + QQmlComponent testFactory(&engine, testFileUrl("callingQmlContextComponent.qml")); + + QQmlComponent component(&engine, testFileUrl("callingQmlContext.qml")); + QScopedPointer<QObject> root(component.beginCreate(engine.rootContext())); + QVERIFY(!root.isNull()); + root->setProperty("factory", QVariant::fromValue(&testFactory)); + component.completeCreate(); + QTRY_VERIFY(qvariant_cast<QObject *>(root->property("incubatedObject"))); + QObject *o = qvariant_cast<QObject *>(root->property("incubatedObject")); + CallingContextCheckingClass *checker = qobject_cast<CallingContextCheckingClass*>(o); + QVERIFY(checker); + + QVERIFY(!checker->callingContextData.isNull()); + QVERIFY(checker->callingContextData->urlString().endsWith(QStringLiteral("callingQmlContext.qml"))); + + QVERIFY(!checker->scopeObject.isNull()); + QVERIFY(checker->scopeObject->metaObject()->indexOfProperty("incubatedObject") != -1); +} + QTEST_MAIN(tst_qqmlcomponent) #include "tst_qqmlcomponent.moc" |