diff --git a/0007-Revert-Remove-this-piece-of-code.patch b/0007-Revert-Remove-this-piece-of-code.patch new file mode 100644 index 0000000..567b62d --- /dev/null +++ b/0007-Revert-Remove-this-piece-of-code.patch @@ -0,0 +1,99 @@ +From 6371b208a9e55845090dcd34234e314c6587c105 Mon Sep 17 00:00:00 2001 +From: Simon Hausmann +Date: Tue, 17 May 2016 15:18:12 +0200 +Subject: [PATCH 07/40] Revert "Remove this piece of code" + +This reverts commit bad007360a0f6fba304d8f4c99826a1250fd886c. + +The lookup in the global object is necessary to detect whether we've seen any +unresolved properties. This is used for the optimization of skipping binding +refresh updates when a context property changes. + +Task-number: QTBUG-53431 +Change-Id: Idb39a32e4b58b915496bbb9d8a098dc17a6f688a +Reviewed-by: Lars Knoll +--- + src/qml/qml/qqmlcontextwrapper.cpp | 13 +++++++++++-- + tests/auto/qml/qqmlcontext/data/qtbug_53431.qml | 7 +++++++ + tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp | 14 ++++++++++++++ + 3 files changed, 32 insertions(+), 2 deletions(-) + create mode 100644 tests/auto/qml/qqmlcontext/data/qtbug_53431.qml + +diff --git a/src/qml/qml/qqmlcontextwrapper.cpp b/src/qml/qml/qqmlcontextwrapper.cpp +index 0d84c3b..e3770a7 100644 +--- a/src/qml/qml/qqmlcontextwrapper.cpp ++++ b/src/qml/qml/qqmlcontextwrapper.cpp +@@ -99,14 +99,23 @@ ReturnedValue QmlContextWrapper::get(const Managed *m, String *name, bool *hasPr + QV4::ExecutionEngine *v4 = resource->engine(); + QV4::Scope scope(v4); + ++ // In V8 the JS global object would come _before_ the QML global object, ++ // so simulate that here. ++ bool hasProp; ++ QV4::ScopedValue result(scope, v4->globalObject->get(name, &hasProp)); ++ if (hasProp) { ++ if (hasProperty) ++ *hasProperty = hasProp; ++ return result->asReturnedValue(); ++ } ++ + if (resource->d()->isNullWrapper) + return Object::get(m, name, hasProperty); + + if (v4->callingQmlContext() != resource->d()->context) + return Object::get(m, name, hasProperty); + +- bool hasProp; +- QV4::ScopedValue result(scope, Object::get(m, name, &hasProp)); ++ result = Object::get(m, name, &hasProp); + if (hasProp) { + if (hasProperty) + *hasProperty = hasProp; +diff --git a/tests/auto/qml/qqmlcontext/data/qtbug_53431.qml b/tests/auto/qml/qqmlcontext/data/qtbug_53431.qml +new file mode 100644 +index 0000000..2ceee2b +--- /dev/null ++++ b/tests/auto/qml/qqmlcontext/data/qtbug_53431.qml +@@ -0,0 +1,7 @@ ++import QtQml 2.0 ++QtObject { ++ property int value: { ++ console.log("lookup in global object") ++ return 1 ++ } ++} +diff --git a/tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp b/tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp +index 18ef7ac..d338e6f 100644 +--- a/tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp ++++ b/tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp +@@ -61,6 +61,7 @@ private slots: + void refreshExpressions(); + void refreshExpressionsCrash(); + void refreshExpressionsRootContext(); ++ void skipExpressionRefresh_qtbug_53431(); + + void qtbug_22535(); + void evalAfterInvalidate(); +@@ -642,6 +643,19 @@ void tst_qqmlcontext::refreshExpressionsRootContext() + delete o1; + } + ++void tst_qqmlcontext::skipExpressionRefresh_qtbug_53431() ++{ ++ QQmlEngine engine; ++ QQmlComponent component(&engine, testFileUrl("qtbug_53431.qml")); ++ QScopedPointer object(component.create(0)); ++ QVERIFY(!object.isNull()); ++ QCOMPARE(object->property("value").toInt(), 1); ++ object->setProperty("value", 10); ++ QCOMPARE(object->property("value").toInt(), 10); ++ engine.rootContext()->setContextProperty("randomContextProperty", 42); ++ QCOMPARE(object->property("value").toInt(), 10); ++} ++ + void tst_qqmlcontext::qtbug_22535() + { + QQmlEngine engine; +-- +1.9.3 + diff --git a/0010-Fix-crash-for-unknown-QQmlListModel-roles-in-debug-b.patch b/0010-Fix-crash-for-unknown-QQmlListModel-roles-in-debug-b.patch new file mode 100644 index 0000000..6d697b0 --- /dev/null +++ b/0010-Fix-crash-for-unknown-QQmlListModel-roles-in-debug-b.patch @@ -0,0 +1,67 @@ +From 82b0b31fe47a6a54c500f2cbea45b37fc28f3bee Mon Sep 17 00:00:00 2001 +From: Filipe Azevedo +Date: Mon, 2 May 2016 13:11:26 +0200 +Subject: [PATCH 10/40] Fix crash for unknown QQmlListModel roles in debug + builds + +If a role is unknown, trying to access it will crash in getExistingRole. +Fixed that and now return QVariant() for unknown roles. + +Change-Id: Iad5c1292a4faee893fbc5a69984cf776aca85d70 +Reviewed-by: Shawn Rutledge +Reviewed-by: Robin Burchell +--- + src/qml/types/qqmllistmodel.cpp | 2 ++ + tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp | 16 ++++++++++++++++ + 2 files changed, 18 insertions(+) + +diff --git a/src/qml/types/qqmllistmodel.cpp b/src/qml/types/qqmllistmodel.cpp +index 4b0aa47..3d71621 100644 +--- a/src/qml/types/qqmllistmodel.cpp ++++ b/src/qml/types/qqmllistmodel.cpp +@@ -392,6 +392,8 @@ void ListModel::updateCacheIndices() + + QVariant ListModel::getProperty(int elementIndex, int roleIndex, const QQmlListModel *owner, QV4::ExecutionEngine *eng) + { ++ if (roleIndex >= m_layout->roleCount()) ++ return QVariant(); + ListElement *e = elements[elementIndex]; + const ListLayout::Role &r = m_layout->getExistingRole(roleIndex); + return e->getProperty(r, owner, eng); +diff --git a/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp b/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp +index d26c1c5..6b1dece 100644 +--- a/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp ++++ b/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp +@@ -110,6 +110,7 @@ private slots: + void get_nested(); + void get_nested_data(); + void crash_model_with_multiple_roles(); ++ void crash_model_with_unknown_roles(); + void set_model_cache(); + void property_changes(); + void property_changes_data(); +@@ -968,6 +969,21 @@ void tst_qqmllistmodel::crash_model_with_multiple_roles() + delete rootItem; + } + ++void tst_qqmllistmodel::crash_model_with_unknown_roles() ++{ ++ QQmlEngine eng; ++ QQmlComponent component(&eng, testFileUrl("multipleroles.qml")); ++ QScopedPointer rootItem(component.create()); ++ QVERIFY(component.errorString().isEmpty()); ++ QVERIFY(rootItem != 0); ++ QQmlListModel *model = rootItem->findChild("listModel"); ++ QVERIFY(model != 0); ++ ++ // used to cause a crash in debug builds ++ model->index(0, 0, QModelIndex()).data(Qt::DisplayRole); ++ model->index(0, 0, QModelIndex()).data(Qt::UserRole); ++} ++ + //QTBUG-15190 + void tst_qqmllistmodel::set_model_cache() + { +-- +1.9.3 + diff --git a/0011-Avoid-Canvas-crashes-with-qtquickcompiler.patch b/0011-Avoid-Canvas-crashes-with-qtquickcompiler.patch new file mode 100644 index 0000000..ba76088 --- /dev/null +++ b/0011-Avoid-Canvas-crashes-with-qtquickcompiler.patch @@ -0,0 +1,37 @@ +From 40a80ec9d712d8c40ebd6a6373322c3332ff5b50 Mon Sep 17 00:00:00 2001 +From: Laszlo Agocs +Date: Mon, 23 May 2016 16:01:44 +0200 +Subject: [PATCH 11/40] Avoid Canvas crashes with qtquickcompiler + +Change-Id: Ic87052308706b8ef71e2f27837abfbaea57c43cc +Task-number: QTBUG-49692 +Reviewed-by: Mitch Curtis +--- + src/quick/items/context2d/qquickcanvasitem.cpp | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/src/quick/items/context2d/qquickcanvasitem.cpp b/src/quick/items/context2d/qquickcanvasitem.cpp +index 9fb49f9..47ac2c4 100644 +--- a/src/quick/items/context2d/qquickcanvasitem.cpp ++++ b/src/quick/items/context2d/qquickcanvasitem.cpp +@@ -675,10 +675,14 @@ void QQuickCanvasItem::itemChange(QQuickItem::ItemChange change, const QQuickIte + QSGRenderContext *context = QQuickWindowPrivate::get(d->window)->context; + + // Rendering to FramebufferObject needs a valid OpenGL context. +- if (context != 0 && (d->renderTarget != FramebufferObject || context->isValid())) +- sceneGraphInitialized(); +- else ++ if (context != 0 && (d->renderTarget != FramebufferObject || context->isValid())) { ++ // Defer the call. In some (arguably incorrect) cases we get here due ++ // to ItemSceneChange with the user-supplied property values not yet ++ // set. Work this around by a deferred invoke. (QTBUG-49692) ++ QMetaObject::invokeMethod(this, "sceneGraphInitialized", Qt::QueuedConnection); ++ } else { + connect(d->window, SIGNAL(sceneGraphInitialized()), SLOT(sceneGraphInitialized())); ++ } + } + + void QQuickCanvasItem::updatePolish() +-- +1.9.3 + diff --git a/0016-Fix-crash-with-SignalTransition.patch b/0016-Fix-crash-with-SignalTransition.patch new file mode 100644 index 0000000..ce972fe --- /dev/null +++ b/0016-Fix-crash-with-SignalTransition.patch @@ -0,0 +1,155 @@ +From 7dcda224fe73cb51a29e8946afd641a989d7209a Mon Sep 17 00:00:00 2001 +From: Simon Hausmann +Date: Wed, 25 May 2016 16:22:44 +0200 +Subject: [PATCH 16/40] Fix crash with SignalTransition + +Don't crash when using SignalTransition with a signal object instead of the +slot used to emit the signal. A signal object is just as good. + +Task-number: QTBUG-53596 +Change-Id: I8a419d16ec0c257c9a798a83ee5bad338794cdd2 +Reviewed-by: Michael Brasser +--- + src/imports/statemachine/signaltransition.cpp | 26 ++++++-- + src/qml/jsruntime/qv4qobjectwrapper_p.h | 2 +- + .../qmltest/statemachine/tst_signaltransition.qml | 76 ++++++++++++++++++++++ + 3 files changed, 96 insertions(+), 8 deletions(-) + create mode 100644 tests/auto/qmltest/statemachine/tst_signaltransition.qml + +diff --git a/src/imports/statemachine/signaltransition.cpp b/src/imports/statemachine/signaltransition.cpp +index 33ee11c..4f6c769 100644 +--- a/src/imports/statemachine/signaltransition.cpp ++++ b/src/imports/statemachine/signaltransition.cpp +@@ -105,15 +105,27 @@ void SignalTransition::setSignal(const QJSValue &signal) + QV4::ExecutionEngine *jsEngine = QV8Engine::getV4(QQmlEngine::contextForObject(this)->engine()); + QV4::Scope scope(jsEngine); + +- QV4::Scoped qobjectSignal(scope, QJSValuePrivate::convertedToValue(jsEngine, m_signal)); +- Q_ASSERT(qobjectSignal); +- +- QObject *sender = qobjectSignal->object(); +- Q_ASSERT(sender); +- QMetaMethod metaMethod = sender->metaObject()->method(qobjectSignal->methodIndex()); ++ QObject *sender; ++ QMetaMethod signalMethod; ++ ++ QV4::ScopedValue value(scope, QJSValuePrivate::convertedToValue(jsEngine, m_signal)); ++ ++ // Did we get the "slot" that can be used to invoke the signal? ++ if (QV4::QObjectMethod *signalSlot = value->as()) { ++ sender = signalSlot->object(); ++ Q_ASSERT(sender); ++ signalMethod = sender->metaObject()->method(signalSlot->methodIndex()); ++ } else if (QV4::QmlSignalHandler *signalObject = value->as()) { // or did we get the signal object (the one with the connect()/disconnect() functions) ? ++ sender = signalObject->object(); ++ Q_ASSERT(sender); ++ signalMethod = sender->metaObject()->method(signalObject->signalIndex()); ++ } else { ++ qmlInfo(this) << tr("Specified signal does not exist."); ++ return; ++ } + + QSignalTransition::setSenderObject(sender); +- QSignalTransition::setSignal(metaMethod.methodSignature()); ++ QSignalTransition::setSignal(signalMethod.methodSignature()); + + connectTriggered(); + } +diff --git a/src/qml/jsruntime/qv4qobjectwrapper_p.h b/src/qml/jsruntime/qv4qobjectwrapper_p.h +index 1126013..0fc39b2 100644 +--- a/src/qml/jsruntime/qv4qobjectwrapper_p.h ++++ b/src/qml/jsruntime/qv4qobjectwrapper_p.h +@@ -166,7 +166,7 @@ struct Q_QML_EXPORT QObjectMethod : public QV4::FunctionObject + static void markObjects(Heap::Base *that, QV4::ExecutionEngine *e); + }; + +-struct QmlSignalHandler : public QV4::Object ++struct Q_QML_EXPORT QmlSignalHandler : public QV4::Object + { + V4_OBJECT2(QmlSignalHandler, QV4::Object) + V4_PROTOTYPE(signalHandlerPrototype) +diff --git a/tests/auto/qmltest/statemachine/tst_signaltransition.qml b/tests/auto/qmltest/statemachine/tst_signaltransition.qml +new file mode 100644 +index 0000000..0e35207 +--- /dev/null ++++ b/tests/auto/qmltest/statemachine/tst_signaltransition.qml +@@ -0,0 +1,76 @@ ++/**************************************************************************** ++** ++** Copyright (C) 2014 Ford Motor Company ++** Copyright (C) 2016 The Qt Company ++** Contact: https://www.qt.io/licensing/ ++** ++** This file is part of the test suite module of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:LGPL21$ ++** Commercial License Usage ++** Licensees holding valid commercial Qt licenses may use this file in ++** accordance with the commercial license agreement provided with the ++** Software or, alternatively, in accordance with the terms contained in ++** a written agreement between you and The Qt Company. For licensing terms ++** and conditions see http://www.qt.io/terms-conditions. For further ++** information use the contact form at http://www.qt.io/contact-us. ++** ++** GNU Lesser General Public License Usage ++** Alternatively, this file may be used under the terms of the GNU Lesser ++** General Public License version 2.1 or version 3 as published by the Free ++** Software Foundation and appearing in the file LICENSE.LGPLv21 and ++** LICENSE.LGPLv3 included in the packaging of this file. Please review the ++** following information to ensure the GNU Lesser General Public License ++** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ++** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ++** ++** As a special exception, The Qt Company gives you certain additional ++** rights. These rights are described in The Qt Company LGPL Exception ++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++import QtTest 1.1 ++import QtQml.StateMachine 1.0 ++ ++TestCase { ++ id: testCase ++ StateMachine { ++ id: machine ++ initialState: startState ++ State { ++ id: startState ++ SignalTransition { ++ id: signalTrans ++ signal: testCase.onMysignal ++ targetState: finalState ++ } ++ } ++ FinalState { ++ id: finalState ++ } ++ } ++ ++ SignalSpy { ++ id: finalStateActive ++ target: finalState ++ signalName: "activeChanged" ++ } ++ ++ signal mysignal() ++ ++ name: "testSignalTransition" ++ function test_signalTransition() ++ { ++ // Start statemachine, should not have reached finalState yet. ++ machine.start() ++ tryCompare(finalStateActive, "count", 0) ++ tryCompare(machine, "running", true) ++ ++ testCase.mysignal() ++ tryCompare(finalStateActive, "count", 1) ++ tryCompare(machine, "running", false) ++ } ++} +-- +1.9.3 + diff --git a/0024-Revert-removal-of-Fixed-MouseArea-threshold-with-pre.patch b/0024-Revert-removal-of-Fixed-MouseArea-threshold-with-pre.patch new file mode 100644 index 0000000..28b70ef --- /dev/null +++ b/0024-Revert-removal-of-Fixed-MouseArea-threshold-with-pre.patch @@ -0,0 +1,141 @@ +From 7039db4885a143f8f1d363c9b71665e9160d3d55 Mon Sep 17 00:00:00 2001 +From: Filippo Cucchetto +Date: Thu, 2 Jun 2016 21:49:37 +0200 +Subject: [PATCH 24/40] Revert removal of "Fixed MouseArea threshold with + preventStealing" + +This reverts commit 9c8dab537819f0d999e680490c2d125b8836cbbb +where commit e1400b5b4d8311769ad3b9f631479ee2b0271197 was removed +due to the breakage of QtLocation tests. + +After some hours of debugging it seems that the problem in QtLocation +was due to filtering of mouse move events in QDeclarativeGeoMapItemBase. +See QTBUG-52075 + +Task-number: QTBUG-52534 +Change-Id: I00f002c1d6f60f74a148b5a6ac2b9f63e93718a9 +Reviewed-by: Paolo Angelelli +Reviewed-by: Michal Klocek +--- + src/quick/items/qquickmousearea.cpp | 21 +++++++++++++-------- + src/quick/items/qquickmousearea_p_p.h | 1 + + .../quick/qquickmousearea/tst_qquickmousearea.cpp | 11 +++++++++++ + 3 files changed, 25 insertions(+), 8 deletions(-) + +diff --git a/src/quick/items/qquickmousearea.cpp b/src/quick/items/qquickmousearea.cpp +index ef053ab..d66e55a 100644 +--- a/src/quick/items/qquickmousearea.cpp ++++ b/src/quick/items/qquickmousearea.cpp +@@ -52,7 +52,7 @@ DEFINE_BOOL_CONFIG_OPTION(qmlVisualTouchDebugging, QML_VISUAL_TOUCH_DEBUGGING) + QQuickMouseAreaPrivate::QQuickMouseAreaPrivate() + : enabled(true), scrollGestureEnabled(true), hovered(false), longPress(false), + moved(false), stealMouse(false), doubleClick(false), preventStealing(false), +- propagateComposedEvents(false), pressed(0) ++ propagateComposedEvents(false), overThreshold(false), pressed(0) + #ifndef QT_NO_DRAGANDDROP + , drag(0) + #endif +@@ -715,7 +715,7 @@ void QQuickMouseArea::mouseMoveEvent(QMouseEvent *event) + curLocalPos = event->windowPos(); + } + +- if (keepMouseGrab() && d->stealMouse && !d->drag->active()) ++ if (keepMouseGrab() && d->stealMouse && d->overThreshold && !d->drag->active()) + d->drag->setActive(true); + + QPointF startPos = d->drag->target()->parentItem() +@@ -741,16 +741,19 @@ void QQuickMouseArea::mouseMoveEvent(QMouseEvent *event) + if (d->drag->active()) + d->drag->target()->setPosition(dragPos); + +- if (!keepMouseGrab() +- && (QQuickWindowPrivate::dragOverThreshold(dragPos.x() - startPos.x(), Qt::XAxis, event, d->drag->threshold()) +- || QQuickWindowPrivate::dragOverThreshold(dragPos.y() - startPos.y(), Qt::YAxis, event, d->drag->threshold()))) { +- setKeepMouseGrab(true); +- d->stealMouse = true; +- ++ if (!d->overThreshold && (QQuickWindowPrivate::dragOverThreshold(dragPos.x() - startPos.x(), Qt::XAxis, event, d->drag->threshold()) ++ || QQuickWindowPrivate::dragOverThreshold(dragPos.y() - startPos.y(), Qt::YAxis, event, d->drag->threshold()))) ++ { ++ d->overThreshold = true; + if (d->drag->smoothed()) + d->startScene = event->windowPos(); + } + ++ if (!keepMouseGrab() && d->overThreshold) { ++ setKeepMouseGrab(true); ++ d->stealMouse = true; ++ } ++ + d->moved = true; + } + #endif +@@ -767,6 +770,7 @@ void QQuickMouseArea::mouseReleaseEvent(QMouseEvent *event) + { + Q_D(QQuickMouseArea); + d->stealMouse = false; ++ d->overThreshold = false; + if (!d->enabled && !d->pressed) { + QQuickItem::mouseReleaseEvent(event); + } else { +@@ -875,6 +879,7 @@ void QQuickMouseArea::ungrabMouse() + d->pressed = 0; + d->stealMouse = false; + d->doubleClick = false; ++ d->overThreshold = false; + setKeepMouseGrab(false); + + #ifndef QT_NO_DRAGANDDROP +diff --git a/src/quick/items/qquickmousearea_p_p.h b/src/quick/items/qquickmousearea_p_p.h +index 014729b..f63c5f6 100644 +--- a/src/quick/items/qquickmousearea_p_p.h ++++ b/src/quick/items/qquickmousearea_p_p.h +@@ -86,6 +86,7 @@ public: + bool doubleClick : 1; + bool preventStealing : 1; + bool propagateComposedEvents : 1; ++ bool overThreshold : 1; + Qt::MouseButtons pressed; + #ifndef QT_NO_DRAGANDDROP + QQuickDrag *drag; +diff --git a/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp b/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp +index 82c053d..9cdfd21 100644 +--- a/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp ++++ b/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp +@@ -79,6 +79,7 @@ private slots: + void dragging_data() { acceptedButton_data(); } + void dragging(); + void dragSmoothed(); ++ void dragThreshold_data(); + void dragThreshold(); + void invalidDrag_data() { rejectedButton_data(); } + void invalidDrag(); +@@ -375,8 +376,17 @@ void tst_QQuickMouseArea::dragSmoothed() + QTest::mouseRelease(&window, Qt::LeftButton, 0, QPoint(100, 122)); + } + ++void tst_QQuickMouseArea::dragThreshold_data() ++{ ++ QTest::addColumn("preventStealing"); ++ QTest::newRow("without preventStealing") << false; ++ QTest::newRow("with preventStealing") << true; ++} ++ + void tst_QQuickMouseArea::dragThreshold() + { ++ QFETCH(bool, preventStealing); ++ + QQuickView window; + QByteArray errorMessage; + QVERIFY2(initView(window, testFileUrl("dragging.qml"), true, &errorMessage), errorMessage.constData()); +@@ -386,6 +396,7 @@ void tst_QQuickMouseArea::dragThreshold() + QVERIFY(window.rootObject() != 0); + + QQuickMouseArea *mouseRegion = window.rootObject()->findChild("mouseregion"); ++ mouseRegion->setPreventStealing(preventStealing); + QQuickDrag *drag = mouseRegion->drag(); + + drag->setThreshold(5); +-- +1.9.3 + diff --git a/0027-Fix-crash-when-using-with-statement-with-an-expressi.patch b/0027-Fix-crash-when-using-with-statement-with-an-expressi.patch new file mode 100644 index 0000000..ef62d93 --- /dev/null +++ b/0027-Fix-crash-when-using-with-statement-with-an-expressi.patch @@ -0,0 +1,75 @@ +From 6d54a59bd725ba83e758236c5ff0fc7855109dac Mon Sep 17 00:00:00 2001 +From: Simon Hausmann +Date: Thu, 2 Jun 2016 15:57:41 +0200 +Subject: [PATCH 27/40] Fix crash when using with statement with an expression + that throws + +We need to evaluate the expression for the "with" statement that is supposed to +define the new scope _before_ opening up the scope, otherwise - when the +evaluation of the expression throws an exception - we'll try to pop the "with" +scope we couldn't open in the first place. + +[ChangeLog][QtQml] Fix crash when using the "with" statement with an expression +that throws an exception. + +Task-number: QTBUG-53794 +Change-Id: I7733f5a4c5d844916302b9a91c789a0f6b421e8a +Reviewed-by: Lars Knoll +--- + src/qml/compiler/qv4codegen.cpp | 5 +++-- + tests/auto/qml/qjsengine/tst_qjsengine.cpp | 9 +++++++++ + 2 files changed, 12 insertions(+), 2 deletions(-) + +diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp +index ea82d07..c14163a 100644 +--- a/src/qml/compiler/qv4codegen.cpp ++++ b/src/qml/compiler/qv4codegen.cpp +@@ -2718,6 +2718,9 @@ bool Codegen::visit(WithStatement *ast) + + _function->hasWith = true; + ++ const int withObject = _block->newTemp(); ++ _block->MOVE(_block->TEMP(withObject), *expression(ast->expression)); ++ + // need an exception handler for with to cleanup the with scope + IR::BasicBlock *withExceptionHandler = _function->newBasicBlock(exceptionHandler()); + withExceptionHandler->EXP(withExceptionHandler->CALL(withExceptionHandler->NAME(IR::Name::builtin_pop_scope, 0, 0), 0)); +@@ -2732,8 +2735,6 @@ bool Codegen::visit(WithStatement *ast) + + _block->JUMP(withBlock); + _block = withBlock; +- int withObject = _block->newTemp(); +- _block->MOVE(_block->TEMP(withObject), *expression(ast->expression)); + IR::ExprList *args = _function->New(); + args->init(_block->TEMP(withObject)); + _block->EXP(_block->CALL(_block->NAME(IR::Name::builtin_push_with_scope, 0, 0), args)); +diff --git a/tests/auto/qml/qjsengine/tst_qjsengine.cpp b/tests/auto/qml/qjsengine/tst_qjsengine.cpp +index 9a0865c..8594aec 100644 +--- a/tests/auto/qml/qjsengine/tst_qjsengine.cpp ++++ b/tests/auto/qml/qjsengine/tst_qjsengine.cpp +@@ -193,6 +193,8 @@ private slots: + + void v4FunctionWithoutQML(); + ++ void withNoContext(); ++ + signals: + void testSignal(); + }; +@@ -3840,6 +3842,13 @@ void tst_QJSEngine::v4FunctionWithoutQML() + QVERIFY(obj.called); + } + ++void tst_QJSEngine::withNoContext() ++{ ++ // Don't crash (QTBUG-53794) ++ QJSEngine engine; ++ engine.evaluate("with (noContext) true"); ++} ++ + QTEST_MAIN(tst_QJSEngine) + + #include "tst_qjsengine.moc" +-- +1.9.3 + diff --git a/0033-QML-Only-release-types-if-they-aren-t-referenced-any.patch b/0033-QML-Only-release-types-if-they-aren-t-referenced-any.patch new file mode 100644 index 0000000..a274426 --- /dev/null +++ b/0033-QML-Only-release-types-if-they-aren-t-referenced-any.patch @@ -0,0 +1,63 @@ +From 2ac19881f92c94f4e9427bd9ff513210675f259e Mon Sep 17 00:00:00 2001 +From: Ulf Hermann +Date: Wed, 8 Jun 2016 17:32:32 +0200 +Subject: [PATCH 33/40] QML: Only release types if they aren't referenced + anymore + +Just checking for references on m_compiledData is not enough. The +actual component can also be referenced. Thus it won't be deleted +on release(), but cannot be found in the type cache anymore. + +Task-number: QTBUG-53761 +Change-Id: I8567af8e75a078598e4fed31e4717134e1332278 +Reviewed-by: Mitch Curtis +Reviewed-by: Simon Hausmann +--- + src/qml/qml/qqmltypeloader.cpp | 3 ++- + tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp | 15 ++++++++++++--- + 2 files changed, 14 insertions(+), 4 deletions(-) + +diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp +index c684c86..01200fd 100644 +--- a/src/qml/qml/qqmltypeloader.cpp ++++ b/src/qml/qml/qqmltypeloader.cpp +@@ -1961,7 +1961,8 @@ void QQmlTypeLoader::trimCache() + QList unneededTypes; + for (TypeCache::Iterator iter = m_typeCache.begin(), end = m_typeCache.end(); iter != end; ++iter) { + QQmlTypeData *typeData = iter.value(); +- if (typeData->m_compiledData && typeData->m_compiledData->count() == 1) { ++ if (typeData->m_compiledData && typeData->count() == 1 ++ && typeData->m_compiledData->count() == 1) { + // There are no live objects of this type + unneededTypes.append(iter); + } +diff --git a/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp b/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp +index 7045c7c..a1eaa05 100644 +--- a/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp ++++ b/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp +@@ -86,10 +86,19 @@ void tst_QQMLTypeLoader::trimCache() + url.setQuery(QString::number(i)); + + QQmlTypeData *data = loader.getType(url); +- if (i % 5 == 0) // keep references to some of them so that they aren't trimmed +- data->compiledData()->addref(); ++ // Run an event loop to receive the callback that release()es. ++ QTRY_COMPARE(data->count(), 2); + +- data->release(); ++ // keep references to some of them so that they aren't trimmed. References to either the ++ // QQmlTypeData or its compiledData() should prevent the trimming. ++ if (i % 10 == 0) { ++ // keep ref on data, don't add ref on data->compiledData() ++ } else if (i % 5 == 0) { ++ data->compiledData()->addref(); ++ data->release(); ++ } else { ++ data->release(); ++ } + } + + for (int i = 0; i < 256; ++i) { +-- +1.9.3 + diff --git a/qt5-qtdeclarative.spec b/qt5-qtdeclarative.spec index d55f7a9..d7a03d9 100644 --- a/qt5-qtdeclarative.spec +++ b/qt5-qtdeclarative.spec @@ -23,7 +23,7 @@ Summary: Qt5 - QtDeclarative component Name: qt5-%{qt_module} Version: 5.6.1 -Release: 4%{?prerelease:.%{prerelease}}%{?dist} +Release: 5%{?prerelease:.%{prerelease}}%{?dist} # See LICENSE.GPL LICENSE.LGPL LGPL_EXCEPTION.txt, for details License: LGPLv2 with exceptions or GPLv3 with exceptions @@ -40,6 +40,13 @@ Patch1: qtdeclarative-opensource-src-5.5.0-no_sse2.patch Patch2: qtdeclarative-QQuickShaderEffectSource_deadlock.patch ## upstream patches +Patch7: 0007-Revert-Remove-this-piece-of-code.patch +Patch10: 0010-Fix-crash-for-unknown-QQmlListModel-roles-in-debug-b.patch +Patch11: 0011-Avoid-Canvas-crashes-with-qtquickcompiler.patch +Patch16: 0016-Fix-crash-with-SignalTransition.patch +Patch24: 0024-Revert-removal-of-Fixed-MouseArea-threshold-with-pre.patch +Patch27: 0027-Fix-crash-when-using-with-statement-with-an-expressi.patch +Patch33: 0033-QML-Only-release-types-if-they-aren-t-referenced-any.patch ## upstreamable patches # use system double-conversation @@ -120,6 +127,14 @@ Requires: %{name}%{?_isa} = %{version}-%{release} %endif %patch2 -p1 -b .QQuickShaderEffectSource_deadlock +%patch7 -p1 -b .0007 +%patch10 -p1 -b .0010 +%patch11 -p1 -b .0011 +%patch16 -p1 -b .0016 +%patch24 -p1 -b .0024 +%patch27 -p1 -b .0027 +%patch33 -p1 -b .0033 + %if 0%{?system_doubleconv} %patch200 -p1 -b .system_doubleconv rm -rfv src/3rdparty/double-conversion @@ -273,6 +288,9 @@ make check -k -C %{_target_platform}/tests ||: %changelog +* Thu Jun 16 2016 Rex Dieter 5.6.1-5 +- backport 5.6 branch fixes + * Wed Jun 15 2016 Rex Dieter - 5.6.1-4 - drop pkgconfig-style Qt5 deps