aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQt Forward Merge Bot <qt_forward_merge_bot@qt-project.org>2019-02-15 01:00:06 +0100
committerUlf Hermann <ulf.hermann@qt.io>2019-02-15 10:41:32 +0100
commit1ffb45a3682c864f8071b8b19da49c9a7761dd5e (patch)
treeb714f329d1e2a1ecccc0d5c13fb829f924f0d801
parent3dcc9dde65c780fb87ff9feef60dfb16d6748eb0 (diff)
parentd96a700cc3611480ff76023287cb06f455a37b02 (diff)
Merge remote-tracking branch 'origin/5.12' into 5.13
Conflicts: src/qml/qml/qqmlpropertycache.cpp Change-Id: Ie7727499700b85cc0959ef3abb30d55dc728b659
-rw-r--r--src/qml/jit/qv4assemblercommon.cpp16
-rw-r--r--src/qml/jit/qv4assemblercommon_p.h1
-rw-r--r--src/qml/memory/qv4mm.cpp2
-rw-r--r--src/qml/types/qqmldelegatemodel.cpp17
-rw-r--r--src/qml/types/qqmldelegatemodel_p_p.h1
-rw-r--r--src/quick/items/context2d/qquickcontext2d.cpp9
-rw-r--r--tests/auto/qml/qqmlpropertycache/data/passQGadget.qml12
-rw-r--r--tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp39
-rw-r--r--tests/auto/quick/qquickcanvasitem/data/tst_strokeStyle.qml35
-rw-r--r--tests/auto/quick/qquickvisualdatamodel/data/externalManagedModel.qml65
-rw-r--r--tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp68
11 files changed, 250 insertions, 15 deletions
diff --git a/src/qml/jit/qv4assemblercommon.cpp b/src/qml/jit/qv4assemblercommon.cpp
index d5d97f8284..dd810d9d70 100644
--- a/src/qml/jit/qv4assemblercommon.cpp
+++ b/src/qml/jit/qv4assemblercommon.cpp
@@ -187,13 +187,6 @@ PlatformAssemblerCommon::Address PlatformAssemblerCommon::argStackAddress(int ar
return Address(StackPointerRegister, offset * PointerSize);
}
-JSC::MacroAssemblerBase::Address PlatformAssemblerCommon::inArgStackAddress(int arg)
-{
- int offset = arg - ArgInRegCount;
- Q_ASSERT(offset >= 0);
- return Address(FramePointerRegister, -(offset + 1) * PointerSize);
-}
-
void PlatformAssemblerCommon::passAccumulatorAsArg(int arg)
{
#ifndef QT_NO_DEBUG
@@ -342,10 +335,13 @@ void PlatformAssemblerCommon::tailCallRuntime(const char *functionName, const vo
void PlatformAssemblerCommon::setTailCallArg(RegisterID src, int arg)
{
- if (arg < ArgInRegCount)
+ if (arg < ArgInRegCount) {
move(src, registerForArg(arg));
- else
- storePtr(src, inArgStackAddress(arg));
+ } else {
+ // We never write to the incoming arguments space on the stack, and the tail call runtime
+ // method has the same signature as the jitted function, so it is safe for us to just reuse
+ // the arguments that we got in.
+ }
}
JSC::MacroAssemblerBase::Address PlatformAssemblerCommon::jsAlloca(int slotCount)
diff --git a/src/qml/jit/qv4assemblercommon_p.h b/src/qml/jit/qv4assemblercommon_p.h
index 3e70457bd8..d3d7eedae2 100644
--- a/src/qml/jit/qv4assemblercommon_p.h
+++ b/src/qml/jit/qv4assemblercommon_p.h
@@ -711,7 +711,6 @@ public:
private:
void passAccumulatorAsArg_internal(int arg, bool doPush);
static Address argStackAddress(int arg);
- static Address inArgStackAddress(int arg);
private:
const Value* constantTable;
diff --git a/src/qml/memory/qv4mm.cpp b/src/qml/memory/qv4mm.cpp
index 3cf22d82e5..203f1f424f 100644
--- a/src/qml/memory/qv4mm.cpp
+++ b/src/qml/memory/qv4mm.cpp
@@ -201,7 +201,7 @@ Chunk *MemorySegment::allocate(size_t size)
// chunk allocated for one huge allocation
Q_ASSERT(availableBytes >= size);
pageReservation.commit(base, size);
- allocatedMap = ~static_cast<quintptr>(0);
+ allocatedMap = ~static_cast<quint64>(0);
return base;
}
size_t requiredChunks = (size + sizeof(Chunk) - 1)/sizeof(Chunk);
diff --git a/src/qml/types/qqmldelegatemodel.cpp b/src/qml/types/qqmldelegatemodel.cpp
index 57bbf7465d..48cc77bc3d 100644
--- a/src/qml/types/qqmldelegatemodel.cpp
+++ b/src/qml/types/qqmldelegatemodel.cpp
@@ -1060,7 +1060,11 @@ QObject *QQmlDelegateModelPrivate::object(Compositor::Group group, int index, QQ
= qobject_cast<QQmlAdaptorModelProxyInterface *>(cacheItem)) {
ctxt = new QQmlContextData;
ctxt->setParent(cacheItem->contextData, /*stronglyReferencedByParent*/true);
- ctxt->contextObject = proxy->proxiedObject();
+ QObject *proxied = proxy->proxiedObject();
+ ctxt->contextObject = proxied;
+ // We don't own the proxied object. We need to clear it if it goes away.
+ QObject::connect(proxied, &QObject::destroyed,
+ cacheItem, &QQmlDelegateModelItem::childContextObjectDestroyed);
}
}
@@ -2009,6 +2013,17 @@ QV4::ReturnedValue QQmlDelegateModelItem::get_index(QQmlDelegateModelItem *thisI
return QV4::Encode((int)thisItem->groupIndex(Compositor::Group(flag)));
}
+void QQmlDelegateModelItem::childContextObjectDestroyed(QObject *childContextObject)
+{
+ if (!contextData)
+ return;
+
+ for (QQmlContextData *ctxt = contextData->childContexts; ctxt; ctxt = ctxt->nextChild) {
+ if (ctxt->contextObject == childContextObject)
+ ctxt->contextObject = nullptr;
+ }
+}
+
//---------------------------------------------------------------------------
diff --git a/src/qml/types/qqmldelegatemodel_p_p.h b/src/qml/types/qqmldelegatemodel_p_p.h
index 2d6fdf228e..5e480f4df6 100644
--- a/src/qml/types/qqmldelegatemodel_p_p.h
+++ b/src/qml/types/qqmldelegatemodel_p_p.h
@@ -106,6 +106,7 @@ public:
void referenceObject() { ++objectRef; }
bool releaseObject() { return --objectRef == 0 && !(groups & Compositor::PersistedFlag); }
bool isObjectReferenced() const { return objectRef != 0 || (groups & Compositor::PersistedFlag); }
+ void childContextObjectDestroyed(QObject *childContextObject);
bool isReferenced() const {
return scriptRef
diff --git a/src/quick/items/context2d/qquickcontext2d.cpp b/src/quick/items/context2d/qquickcontext2d.cpp
index de19a927a0..546f3011ec 100644
--- a/src/quick/items/context2d/qquickcontext2d.cpp
+++ b/src/quick/items/context2d/qquickcontext2d.cpp
@@ -1548,7 +1548,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_strokeStyle(const QV4::Function
if (value->as<Object>()) {
QColor color = scope.engine->toVariant(value, qMetaTypeId<QColor>()).value<QColor>();
if (color.isValid()) {
- r->d()->context()->state.fillStyle = color;
+ r->d()->context()->state.strokeStyle = color;
r->d()->context()->buffer()->setStrokeStyle(color);
r->d()->context()->m_strokeStyle.set(scope.engine, value);
} else {
@@ -1559,7 +1559,12 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_strokeStyle(const QV4::Function
r->d()->context()->m_strokeStyle.set(scope.engine, value);
r->d()->context()->state.strokePatternRepeatX = style->d()->patternRepeatX;
r->d()->context()->state.strokePatternRepeatY = style->d()->patternRepeatY;
-
+ } else if (!style && r->d()->context()->state.strokeStyle != QBrush(QColor())) {
+ // If there is no style object, then ensure that the strokeStyle is at least
+ // QColor in case it was previously set
+ r->d()->context()->state.strokeStyle = QBrush(QColor());
+ r->d()->context()->buffer()->setStrokeStyle(r->d()->context()->state.strokeStyle);
+ r->d()->context()->m_strokeStyle.set(scope.engine, value);
}
}
} else if (value->isString()) {
diff --git a/tests/auto/qml/qqmlpropertycache/data/passQGadget.qml b/tests/auto/qml/qqmlpropertycache/data/passQGadget.qml
new file mode 100644
index 0000000000..86fdd920ed
--- /dev/null
+++ b/tests/auto/qml/qqmlpropertycache/data/passQGadget.qml
@@ -0,0 +1,12 @@
+import QtQml 2.2
+
+QtObject {
+ property var result;
+
+ property Connections connections: Connections {
+ target: emitter
+ onEmitGadget: function(gadget) {
+ result = gadget.someProperty;
+ }
+ }
+}
diff --git a/tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp b/tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp
index 5abda7b854..07237c9157 100644
--- a/tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp
+++ b/tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp
@@ -50,6 +50,7 @@ private slots:
void signalHandlers();
void signalHandlersDerived();
void passForeignEnums();
+ void passQGadget();
void metaObjectSize_data();
void metaObjectSize();
void metaObjectChecksum();
@@ -362,6 +363,44 @@ void tst_qqmlpropertycache::passForeignEnums()
Q_DECLARE_METATYPE(MyEnum::Option1)
Q_DECLARE_METATYPE(MyEnum::ShortEnum)
+QT_BEGIN_NAMESPACE
+class SimpleGadget
+{
+ Q_GADGET
+ Q_PROPERTY(bool someProperty READ someProperty)
+public:
+ bool someProperty() const { return true; }
+};
+
+// Avoids NeedsCreation and NeedsDestruction flags
+Q_DECLARE_TYPEINFO(SimpleGadget, Q_PRIMITIVE_TYPE);
+QT_END_NAMESPACE
+
+class GadgetEmitter : public QObject
+{
+ Q_OBJECT
+signals:
+ void emitGadget(SimpleGadget);
+};
+
+void tst_qqmlpropertycache::passQGadget()
+{
+ qRegisterMetaType<SimpleGadget>();
+
+ GadgetEmitter emitter;
+ engine.rootContext()->setContextProperty("emitter", &emitter);
+ QQmlComponent component(&engine, testFile("passQGadget.qml"));
+ QVERIFY(component.isReady());
+
+ QScopedPointer<QObject> obj(component.create(engine.rootContext()));
+ QVariant before = obj->property("result");
+ QVERIFY(before.isNull());
+ emit emitter.emitGadget(SimpleGadget());
+ QVariant after = obj->property("result");
+ QCOMPARE(QMetaType::Type(after.type()), QMetaType::Bool);
+ QVERIFY(after.toBool());
+}
+
class TestClass : public QObject
{
Q_OBJECT
diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_strokeStyle.qml b/tests/auto/quick/qquickcanvasitem/data/tst_strokeStyle.qml
index 22803a19ce..a3f1ab0a9b 100644
--- a/tests/auto/quick/qquickcanvasitem/data/tst_strokeStyle.qml
+++ b/tests/auto/quick/qquickcanvasitem/data/tst_strokeStyle.qml
@@ -3,6 +3,8 @@ import QtQuick 2.0
CanvasTestCase {
id:testCase
name: "strokeStyle"
+ property color anotherColor: "#0000ff"
+ property color emptyColor
function init_data() { return testData("2d"); }
function test_default(row) {
var canvas = createCanvasObject(row);
@@ -46,4 +48,37 @@ CanvasTestCase {
comparePixel(ctx,0,0,255,255,255,255);
canvas.destroy()
}
+ function test_colorFromObjectToString(row) {
+ var canvas = createCanvasObject(row);
+ var ctx = canvas.getContext('2d');
+
+ ctx.reset();
+ ctx.strokeStyle = anotherColor
+ ctx.strokeStyle = "red";
+ compare(ctx.strokeStyle, "#ff0000");
+
+ ctx.strokeStyle = anotherColor
+ ctx.strokeStyle = "black";
+ compare(ctx.strokeStyle, "#000000");
+
+ ctx.strokeStyle = "white";
+ ctx.strokeStyle = anotherColor
+ compare(ctx.strokeStyle, "#0000ff");
+ canvas.destroy()
+ }
+ function test_withInvalidColor(row) {
+ var canvas = createCanvasObject(row);
+ var ctx = canvas.getContext('2d');
+
+ ctx.reset();
+ ctx.strokeStyle = emptyColor
+ compare(ctx.strokeStyle, "#000000");
+ ctx.strokeStyle = "red";
+ compare(ctx.strokeStyle, "#ff0000");
+ ctx.strokeStyle = emptyColor
+ compare(ctx.strokeStyle, "#000000");
+ ctx.strokeStyle = anotherColor;
+ compare(ctx.strokeStyle, "#0000ff");
+ canvas.destroy()
+ }
}
diff --git a/tests/auto/quick/qquickvisualdatamodel/data/externalManagedModel.qml b/tests/auto/quick/qquickvisualdatamodel/data/externalManagedModel.qml
new file mode 100644
index 0000000000..44c157b824
--- /dev/null
+++ b/tests/auto/quick/qquickvisualdatamodel/data/externalManagedModel.qml
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the tests of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick.Window 2.2
+import QtQuick 2.6
+import QtQml.Models 2.11
+import example 1.0
+
+Window {
+ visible: true
+ property bool running: rebuildTimer.running
+ ListView {
+ anchors.fill: parent
+ model: delegateModel
+ }
+
+ DelegateModel {
+ id: delegateModel
+ model: objectsProvider.objects
+ delegate: Item {}
+ }
+
+ Timer {
+ id: rebuildTimer
+ running: true
+ repeat: true
+ interval: 1
+
+ property int count: 0
+ onTriggered: {
+ objectsProvider.rebuild();
+ if (++count === 10)
+ running = false;
+ }
+ }
+
+ ObjectsProvider {
+ id: objectsProvider
+ }
+}
diff --git a/tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp b/tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp
index 1b8654ecdd..fac8283e2c 100644
--- a/tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp
+++ b/tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp
@@ -431,6 +431,7 @@ private slots:
void asynchronousMove_data();
void asynchronousCancel();
void invalidContext();
+ void externalManagedModel();
private:
template <int N> void groups_verify(
@@ -4234,6 +4235,73 @@ void tst_qquickvisualdatamodel::invalidContext()
QVERIFY(!item);
}
+class ObjectsProvider : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QQmlListProperty<QObject> objects READ objects NOTIFY objectsChanged)
+
+public:
+ explicit ObjectsProvider(QObject *parent = nullptr) : QObject(parent) {}
+
+ Q_INVOKABLE void rebuild()
+ {
+ for (auto old: m_objects)
+ old->deleteLater();
+
+ m_objects.clear();
+ emit objectsChanged();
+
+ const int size = std::rand() & 0xff;
+ for (int i = 0; i < size; ++i) {
+ auto newElement = new QObject(this);
+ QQmlEngine::setObjectOwnership(newElement, QQmlEngine::CppOwnership);
+ m_objects.push_back(newElement);
+ }
+ emit objectsChanged();
+ }
+
+ Q_INVOKABLE QQmlListProperty<QObject> objects()
+ {
+ return QQmlListProperty<QObject>(this, nullptr, &ObjectsProvider::listLength,
+ &ObjectsProvider::listAt);
+ }
+
+ static int listLength(QQmlListProperty<QObject> *property)
+ {
+ auto objectsProvider = qobject_cast<ObjectsProvider*>(property->object);
+ return objectsProvider ? objectsProvider->m_objects.length() : 0;
+ }
+
+ static QObject* listAt(QQmlListProperty<QObject> *property, int index)
+ {
+ auto objectsProvider = qobject_cast<ObjectsProvider*>(property->object);
+ return objectsProvider ? objectsProvider->m_objects.at(index) : nullptr;
+ }
+
+signals:
+ void objectsChanged();
+
+private:
+ QList<QObject *> m_objects;
+};
+
+void tst_qquickvisualdatamodel::externalManagedModel()
+{
+ qmlRegisterType<ObjectsProvider>("example", 1, 0, "ObjectsProvider");
+
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("externalManagedModel.qml"));
+ QVERIFY(component.isReady());
+
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+
+ QVERIFY(object->property("running").toBool());
+
+ // Make sure it runs to completion without crashing.
+ QTRY_VERIFY(!object->property("running").toBool());
+}
+
QTEST_MAIN(tst_qquickvisualdatamodel)
#include "tst_qquickvisualdatamodel.moc"