From e39908c658c6caa2013bc7356eb904b669af1bfb Mon Sep 17 00:00:00 2001 From: Matthew Vogt Date: Fri, 27 Apr 2012 16:09:22 +1000 Subject: [PATCH] Ensure context is valid before VME method creation Ensure that a valid context exists prior to evaluation of a VME method function. Invalid contexts can occur if a method's first invocation is triggered after the destruction of the component's context. Task-number: QTBUG-25516 Change-Id: I349a73c5713e178f920c44f5ddcaa1dc6eec199f Reviewed-by: Chris Adams --- src/qml/qml/qqmlvmemetaobject.cpp | 5 +++++ .../qml/qqmlcontext/data/ContainerComponent.qml | 5 +++++ .../auto/qml/qqmlcontext/data/ContentComponent.qml | 10 ++++++++++ .../qml/qqmlcontext/data/evalAfterInvalidate.qml | 14 ++++++++++++++ tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp | 12 ++++++++++++ 5 files changed, 46 insertions(+), 0 deletions(-) create mode 100644 tests/auto/qml/qqmlcontext/data/ContainerComponent.qml create mode 100644 tests/auto/qml/qqmlcontext/data/ContentComponent.qml create mode 100644 tests/auto/qml/qqmlcontext/data/evalAfterInvalidate.qml diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp index 9778161..dd2fe4b 100644 --- a/src/qml/qml/qqmlvmemetaobject.cpp +++ b/src/qml/qml/qqmlvmemetaobject.cpp @@ -809,6 +809,11 @@ int QQmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a) v8::Handle QQmlVMEMetaObject::method(int index) { + if (!ctxt || !ctxt->isValid()) { + qWarning("QQmlVMEMetaObject: Internal error - attempted to evaluate a function in an invalid context"); + return v8::Handle(); + } + if (!v8methods) v8methods = new v8::Persistent[metaData->methodCount]; diff --git a/tests/auto/qml/qqmlcontext/data/ContainerComponent.qml b/tests/auto/qml/qqmlcontext/data/ContainerComponent.qml new file mode 100644 index 0000000..ae90c20 --- /dev/null +++ b/tests/auto/qml/qqmlcontext/data/ContainerComponent.qml @@ -0,0 +1,5 @@ +import QtQuick 2.0 + +Item { + function doSomething() { if (333 == 666) console.log('doSomething') } +} diff --git a/tests/auto/qml/qqmlcontext/data/ContentComponent.qml b/tests/auto/qml/qqmlcontext/data/ContentComponent.qml new file mode 100644 index 0000000..f937b19 --- /dev/null +++ b/tests/auto/qml/qqmlcontext/data/ContentComponent.qml @@ -0,0 +1,10 @@ +import QtQuick 2.0 + +Item { + property int count: 0 + property bool hasValidParent: parent && parent.children.length != 0 + + onHasValidParentChanged: { + if (++count > 1) parent.doSomething() + } +} diff --git a/tests/auto/qml/qqmlcontext/data/evalAfterInvalidate.qml b/tests/auto/qml/qqmlcontext/data/evalAfterInvalidate.qml new file mode 100644 index 0000000..27879c4 --- /dev/null +++ b/tests/auto/qml/qqmlcontext/data/evalAfterInvalidate.qml @@ -0,0 +1,14 @@ +import QtQuick 2.0 + +Rectangle { + id: root + + Component.onCompleted: { + var i = containerComponent.createObject(root); + contentComponent.createObject(i); + i.destroy() + } + + property Component containerComponent: ContainerComponent {} + property Component contentComponent: ContentComponent {} +} diff --git a/tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp b/tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp index 16365ee..55f93c6 100644 --- a/tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp +++ b/tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp @@ -71,6 +71,8 @@ private slots: void refreshExpressionsRootContext(); void qtbug_22535(); + void evalAfterInvalidate(); + private: QQmlEngine engine; }; @@ -647,6 +649,16 @@ void tst_qqmlcontext::qtbug_22535() delete o; } +void tst_qqmlcontext::evalAfterInvalidate() +{ + QQmlEngine engine; + QQmlComponent component(&engine, testFileUrl("evalAfterInvalidate.qml")); + QScopedPointer o(component.create()); + + QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); + QCoreApplication::processEvents(); +} + QTEST_MAIN(tst_qqmlcontext) #include "tst_qqmlcontext.moc" -- 1.7.2.5