aboutsummaryrefslogtreecommitdiffstats
path: root/tests/auto/qml
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/qml')
-rw-r--r--tests/auto/qml/animation/qparallelanimationgroupjob/tst_qparallelanimationgroupjob.cpp4
-rw-r--r--tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/tst_qqmldebugjs.cpp5
-rw-r--r--tests/auto/qml/debugger/qqmlprofilerservice/data/controlFromJS.qml10
-rw-r--r--tests/auto/qml/debugger/qqmlprofilerservice/data/exit.qml4
-rw-r--r--tests/auto/qml/debugger/qqmlprofilerservice/data/javascript.qml8
-rw-r--r--tests/auto/qml/debugger/qqmlprofilerservice/data/signalSourceLocation.qml8
-rw-r--r--tests/auto/qml/debugger/qqmlprofilerservice/data/test.qml4
-rw-r--r--tests/auto/qml/debugger/qqmlprofilerservice/data/timer.qml10
-rw-r--r--tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp31
-rw-r--r--tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp4
-rw-r--r--tests/auto/qml/debugger/shared/debugutil_p.h2
-rw-r--r--tests/auto/qml/qjsengine/tst_qjsengine.cpp150
-rw-r--r--tests/auto/qml/qml.pro4
-rw-r--r--tests/auto/qml/qmldiskcache/qmldiskcache.pro7
-rw-r--r--tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp326
-rw-r--r--tests/auto/qml/qmlplugindump/tst_qmlplugindump.cpp1
-rw-r--r--tests/auto/qml/qqmlbinding/data/delayed.qml26
-rw-r--r--tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp22
-rw-r--r--tests/auto/qml/qqmlecmascript/data/NullObjectInitializerBase.qml5
-rw-r--r--tests/auto/qml/qqmlecmascript/data/nullObjectInitializer.2.qml8
-rw-r--r--tests/auto/qml/qqmlecmascript/data/nullObjectInitializer.qml4
-rw-r--r--tests/auto/qml/qqmlecmascript/testtypes.h3
-rw-r--r--tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp64
-rw-r--r--tests/auto/qml/qqmlengine/data/qtqmlModule.4.qml2
-rw-r--r--tests/auto/qml/qqmlengine/tst_qqmlengine.cpp9
-rw-r--r--tests/auto/qml/qqmlenginecleanup/data/types.qml3
-rw-r--r--tests/auto/qml/qqmllanguage/data/alias.12.qml15
-rw-r--r--tests/auto/qml/qqmllanguage/data/alias.13.qml16
-rw-r--r--tests/auto/qml/qqmllanguage/data/alias.14.errors.txt1
-rw-r--r--tests/auto/qml/qqmllanguage/data/alias.14.qml17
-rw-r--r--tests/auto/qml/qqmllanguage/data/arraybuffer_method_arg.qml11
-rw-r--r--tests/auto/qml/qqmllanguage/data/arraybuffer_method_overload.qml7
-rw-r--r--tests/auto/qml/qqmllanguage/data/arraybuffer_method_return.qml15
-rw-r--r--tests/auto/qml/qqmllanguage/data/arraybuffer_property_get.qml5
-rw-r--r--tests/auto/qml/qqmllanguage/data/arraybuffer_property_set.qml11
-rw-r--r--tests/auto/qml/qqmllanguage/data/arraybuffer_signal_arg.qml14
-rw-r--r--tests/auto/qml/qqmllanguage/data/badCompositeRegistration.1.errors.txt2
-rw-r--r--tests/auto/qml/qqmllanguage/data/invalidAlias.11.errors.txt1
-rw-r--r--tests/auto/qml/qqmllanguage/data/invalidAlias.11.qml10
-rw-r--r--tests/auto/qml/qqmllanguage/data/rootItemIsComponent.qml6
-rw-r--r--tests/auto/qml/qqmllanguage/data/singletonTest10.error.txt1
-rw-r--r--tests/auto/qml/qqmllanguage/data/singletonTest12.error.txt2
-rw-r--r--tests/auto/qml/qqmllanguage/data/singletonTest4.error.txt2
-rw-r--r--tests/auto/qml/qqmllanguage/data/uncreatableTypeAsProperty.qml6
-rw-r--r--tests/auto/qml/qqmllanguage/testtypes.cpp17
-rw-r--r--tests/auto/qml/qqmllanguage/testtypes.h63
-rw-r--r--tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp110
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/plugin.2.1/childplugin/childplugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/plugin.2/childplugin/childplugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/plugin/childplugin/childplugin.cpp2
-rw-r--r--tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp26
-rw-r--r--tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp199
-rw-r--r--tests/auto/qml/qqmlqt/data/LaterComponent.qml14
-rw-r--r--tests/auto/qml/qqmlqt/data/LaterComponent2.qml13
-rw-r--r--tests/auto/qml/qqmlqt/data/LaterComponent3.qml14
-rw-r--r--tests/auto/qml/qqmlqt/data/LaterComponent4.qml12
-rw-r--r--tests/auto/qml/qqmlqt/data/later.qml124
-rw-r--r--tests/auto/qml/qqmlqt/tst_qqmlqt.cpp159
-rw-r--r--tests/auto/qml/qqmltranslation/tst_qqmltranslation.cpp17
-rw-r--r--tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp3
-rw-r--r--tests/auto/qml/qqmlvaluetypes/data/color_read.qml6
-rw-r--r--tests/auto/qml/qqmlvaluetypes/data/color_write_HSL.qml8
-rw-r--r--tests/auto/qml/qqmlvaluetypes/data/color_write_HSV.qml8
-rw-r--r--tests/auto/qml/qqmlvaluetypes/testtypes.h6
-rw-r--r--tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp54
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/send_patch.expect17
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/send_patch.qml68
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/send_patch.reply3
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/tst_qqmlxmlhttprequest.cpp21
-rw-r--r--tests/auto/qml/qv4mm/qv4mm.pro8
-rw-r--r--tests/auto/qml/qv4mm/tst_qv4mm.cpp58
71 files changed, 1748 insertions, 152 deletions
diff --git a/tests/auto/qml/animation/qparallelanimationgroupjob/tst_qparallelanimationgroupjob.cpp b/tests/auto/qml/animation/qparallelanimationgroupjob/tst_qparallelanimationgroupjob.cpp
index ab8fa8a9ef..476ad2e955 100644
--- a/tests/auto/qml/animation/qparallelanimationgroupjob/tst_qparallelanimationgroupjob.cpp
+++ b/tests/auto/qml/animation/qparallelanimationgroupjob/tst_qparallelanimationgroupjob.cpp
@@ -63,8 +63,8 @@ private slots:
void tst_QParallelAnimationGroupJob::initTestCase()
{
qRegisterMetaType<QAbstractAnimationJob::State>("QAbstractAnimationJob::State");
-#if defined(Q_OS_MAC) || defined(Q_OS_WINCE)
- // give the mac/wince app start event queue time to clear
+#if defined(Q_OS_DARWIN)
+ // give the Apple application's start event queue time to clear
QTest::qWait(1000);
#endif
}
diff --git a/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/tst_qqmldebugjs.cpp b/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/tst_qqmldebugjs.cpp
index b800cc3715..d1150be831 100644
--- a/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/tst_qqmldebugjs.cpp
+++ b/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/tst_qqmldebugjs.cpp
@@ -42,11 +42,6 @@
#include <QtCore/qlibraryinfo.h>
#include <QtQml/qjsengine.h>
-#if defined (Q_OS_WINCE)
-#undef IN
-#undef OUT
-#endif
-
const char *V8REQUEST = "v8request";
const char *V8MESSAGE = "v8message";
const char *SEQ = "seq";
diff --git a/tests/auto/qml/debugger/qqmlprofilerservice/data/controlFromJS.qml b/tests/auto/qml/debugger/qqmlprofilerservice/data/controlFromJS.qml
index d1db2af367..dd7cb2055d 100644
--- a/tests/auto/qml/debugger/qqmlprofilerservice/data/controlFromJS.qml
+++ b/tests/auto/qml/debugger/qqmlprofilerservice/data/controlFromJS.qml
@@ -26,10 +26,10 @@
**
****************************************************************************/
-import QtQuick 2.0
+import QtQml 2.0
-Rectangle {
- Timer {
+QtObject {
+ property var timer: Timer {
running: true
interval: 1
onTriggered: {
@@ -38,7 +38,7 @@ Rectangle {
}
}
- Timer {
+ property var stopTimer: Timer {
id: stopTimer
interval: 1000
onTriggered: {
@@ -47,7 +47,7 @@ Rectangle {
}
}
- Timer {
+ property var endTimer: Timer {
id: endTimer
interval: 1000
onTriggered: Qt.quit();
diff --git a/tests/auto/qml/debugger/qqmlprofilerservice/data/exit.qml b/tests/auto/qml/debugger/qqmlprofilerservice/data/exit.qml
index b250524caa..4236d70ea3 100644
--- a/tests/auto/qml/debugger/qqmlprofilerservice/data/exit.qml
+++ b/tests/auto/qml/debugger/qqmlprofilerservice/data/exit.qml
@@ -1,6 +1,6 @@
-import QtQuick 2.0
+import QtQml 2.0
-Item {
+QtObject {
Timer {
running: true
interval: 1
diff --git a/tests/auto/qml/debugger/qqmlprofilerservice/data/javascript.qml b/tests/auto/qml/debugger/qqmlprofilerservice/data/javascript.qml
index 0555d49652..e25c7524f4 100644
--- a/tests/auto/qml/debugger/qqmlprofilerservice/data/javascript.qml
+++ b/tests/auto/qml/debugger/qqmlprofilerservice/data/javascript.qml
@@ -1,6 +1,6 @@
-import QtQuick 2.0
+import QtQml 2.0
-Rectangle {
+QtObject {
function something(i) {
if (i > 10) {
something(i / 4);
@@ -9,8 +9,8 @@ Rectangle {
}
}
- width: 400
- height: 400
+ property int width: 400
+ property int height: 400
onWidthChanged: something(width);
Component.onCompleted: width = 500;
diff --git a/tests/auto/qml/debugger/qqmlprofilerservice/data/signalSourceLocation.qml b/tests/auto/qml/debugger/qqmlprofilerservice/data/signalSourceLocation.qml
index 25e63669c4..0eff9e9030 100644
--- a/tests/auto/qml/debugger/qqmlprofilerservice/data/signalSourceLocation.qml
+++ b/tests/auto/qml/debugger/qqmlprofilerservice/data/signalSourceLocation.qml
@@ -1,8 +1,8 @@
-import QtQuick 2.0
+import QtQml 2.0
-Rectangle {
- width: 400
- height: 400
+QtObject {
+ property int width: 400
+ property int height: 400
onWidthChanged: console.log(width);
Component.onCompleted: width = 500;
diff --git a/tests/auto/qml/debugger/qqmlprofilerservice/data/test.qml b/tests/auto/qml/debugger/qqmlprofilerservice/data/test.qml
index 9c36e13c5b..5dd5caf12f 100644
--- a/tests/auto/qml/debugger/qqmlprofilerservice/data/test.qml
+++ b/tests/auto/qml/debugger/qqmlprofilerservice/data/test.qml
@@ -1,5 +1,5 @@
-import QtQuick 2.0
+import QtQml 2.0
-Item {
+QtObject {
}
diff --git a/tests/auto/qml/debugger/qqmlprofilerservice/data/timer.qml b/tests/auto/qml/debugger/qqmlprofilerservice/data/timer.qml
index 18b8947172..4af555a27b 100644
--- a/tests/auto/qml/debugger/qqmlprofilerservice/data/timer.qml
+++ b/tests/auto/qml/debugger/qqmlprofilerservice/data/timer.qml
@@ -1,10 +1,10 @@
-import QtQuick 2.0
+import QtQml 2.0
-Rectangle {
- width: 100
- height: 62
+QtObject {
+ property int width: 100
+ property int height: 62
- Timer {
+ property var timer: Timer {
running: true
repeat: true
interval: 50
diff --git a/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp b/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp
index 4f9088d67d..c4b17aa60a 100644
--- a/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp
+++ b/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp
@@ -64,7 +64,8 @@ class QQmlProfilerTestClient : public QQmlProfilerClient
Q_OBJECT
public:
- QQmlProfilerTestClient(QQmlDebugConnection *connection) : QQmlProfilerClient(connection) {}
+ QQmlProfilerTestClient(QQmlDebugConnection *connection) : QQmlProfilerClient(connection),
+ lastTimestamp(-1) {}
QVector<QQmlProfilerData> qmlMessages;
QVector<QQmlProfilerData> javascriptMessages;
@@ -72,6 +73,8 @@ public:
QVector<QQmlProfilerData> asynchronousMessages;
QVector<QQmlProfilerData> pixmapMessages;
+ qint64 lastTimestamp;
+
signals:
void recordingFinished();
@@ -114,6 +117,8 @@ void QQmlProfilerTestClient::traceFinished(qint64 time, int engineId)
void QQmlProfilerTestClient::rangeStart(QQmlProfilerDefinitions::RangeType type, qint64 startTime)
{
QVERIFY(type >= 0 && type < QQmlProfilerDefinitions::MaximumRangeType);
+ QVERIFY(lastTimestamp <= startTime);
+ lastTimestamp = startTime;
QQmlProfilerData data(startTime, QQmlProfilerDefinitions::RangeStart, type);
if (type == QQmlProfilerDefinitions::Javascript)
javascriptMessages.append(data);
@@ -125,6 +130,8 @@ void QQmlProfilerTestClient::rangeData(QQmlProfilerDefinitions::RangeType type,
const QString &string)
{
QVERIFY(type >= 0 && type < QQmlProfilerDefinitions::MaximumRangeType);
+ QVERIFY(lastTimestamp <= time);
+ lastTimestamp = time;
QQmlProfilerData data(time, QQmlProfilerDefinitions::RangeData, type, string);
if (type == QQmlProfilerDefinitions::Javascript)
javascriptMessages.append(data);
@@ -137,6 +144,8 @@ void QQmlProfilerTestClient::rangeLocation(QQmlProfilerDefinitions::RangeType ty
{
QVERIFY(type >= 0 && type < QQmlProfilerDefinitions::MaximumRangeType);
QVERIFY(location.line >= -2);
+ QVERIFY(lastTimestamp <= time);
+ lastTimestamp = time;
QQmlProfilerData data(time, QQmlProfilerDefinitions::RangeLocation, type, location.filename);
data.line = location.line;
data.column = location.column;
@@ -149,6 +158,8 @@ void QQmlProfilerTestClient::rangeLocation(QQmlProfilerDefinitions::RangeType ty
void QQmlProfilerTestClient::rangeEnd(QQmlProfilerDefinitions::RangeType type, qint64 endTime)
{
QVERIFY(type >= 0 && type < QQmlProfilerDefinitions::MaximumRangeType);
+ QVERIFY(lastTimestamp <= endTime);
+ lastTimestamp = endTime;
QQmlProfilerData data(endTime, QQmlProfilerDefinitions::RangeEnd, type);
if (type == QQmlProfilerDefinitions::Javascript)
javascriptMessages.append(data);
@@ -161,6 +172,8 @@ void QQmlProfilerTestClient::animationFrame(qint64 time, int frameRate, int anim
QVERIFY(threadId >= 0);
QVERIFY(frameRate != -1);
QVERIFY(animationCount != -1);
+ QVERIFY(lastTimestamp <= time);
+ lastTimestamp = time;
QQmlProfilerData data(time, QQmlProfilerDefinitions::Event,
QQmlProfilerDefinitions::AnimationFrame);
data.framerate = frameRate;
@@ -178,6 +191,8 @@ void QQmlProfilerTestClient::sceneGraphEvent(QQmlProfilerDefinitions::SceneGraph
Q_UNUSED(numericData3);
Q_UNUSED(numericData4);
Q_UNUSED(numericData5);
+ QVERIFY(lastTimestamp <= time);
+ lastTimestamp = time;
asynchronousMessages.append(QQmlProfilerData(time, QQmlProfilerDefinitions::SceneGraphFrame,
type));
}
@@ -186,6 +201,8 @@ void QQmlProfilerTestClient::pixmapCacheEvent(QQmlProfilerDefinitions::PixmapEve
qint64 time, const QString &url, int numericData1,
int numericData2)
{
+ QVERIFY(lastTimestamp <= time);
+ lastTimestamp = time;
QQmlProfilerData data(time, QQmlProfilerDefinitions::PixmapCacheEvent, type, url);
switch (type) {
case QQmlProfilerDefinitions::PixmapSizeKnown:
@@ -205,6 +222,8 @@ void QQmlProfilerTestClient::pixmapCacheEvent(QQmlProfilerDefinitions::PixmapEve
void QQmlProfilerTestClient::memoryAllocation(QQmlProfilerDefinitions::MemoryType type, qint64 time,
qint64 amount)
{
+ QVERIFY(lastTimestamp <= time);
+ lastTimestamp = time;
QQmlProfilerData data(time, QQmlProfilerDefinitions::MemoryAllocation, type);
data.amount = amount;
jsHeapMessages.append(data);
@@ -213,6 +232,8 @@ void QQmlProfilerTestClient::memoryAllocation(QQmlProfilerDefinitions::MemoryTyp
void QQmlProfilerTestClient::inputEvent(QQmlProfilerDefinitions::InputEventType type, qint64 time,
int a, int b)
{
+ QVERIFY(lastTimestamp <= time);
+ lastTimestamp = time;
qmlMessages.append(QQmlProfilerData(time, QQmlProfilerDefinitions::Event, type,
QString::number(a) + QLatin1Char('x') +
QString::number(b)));
@@ -597,7 +618,7 @@ void tst_QQmlProfilerService::scenegraphData()
// if the clocks are acting up.
qint64 contextFrameTime = -1;
qint64 renderFrameTime = -1;
-
+#ifndef QT_NO_OPENGL //Software renderer doesn't have context frames
foreach (const QQmlProfilerData &msg, m_client->asynchronousMessages) {
if (msg.messageType == QQmlProfilerDefinitions::SceneGraphFrame) {
if (msg.detailType == QQmlProfilerDefinitions::SceneGraphContextFrame) {
@@ -608,7 +629,7 @@ void tst_QQmlProfilerService::scenegraphData()
}
QVERIFY(contextFrameTime != -1);
-
+#endif
foreach (const QQmlProfilerData &msg, m_client->asynchronousMessages) {
if (msg.detailType == QQmlProfilerDefinitions::SceneGraphRendererFrame) {
QVERIFY(msg.time >= contextFrameTime);
@@ -667,11 +688,11 @@ void tst_QQmlProfilerService::signalSourceLocation()
QLatin1String("signalSourceLocation.qml"));
expected.line = 8;
expected.column = 28;
- VERIFY(MessageListQML, 13, expected, CheckAll);
+ VERIFY(MessageListQML, 9, expected, CheckAll);
expected.line = 7;
expected.column = 21;
- VERIFY(MessageListQML, 15, expected, CheckAll);
+ VERIFY(MessageListQML, 11, expected, CheckAll);
}
void tst_QQmlProfilerService::javascript()
diff --git a/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp b/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp
index 3f89913f3b..a23b7e37eb 100644
--- a/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp
+++ b/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp
@@ -326,7 +326,7 @@ private slots:
private:
QV4Debugger *debugger() const
{
- return static_cast<QV4Debugger *>(m_v4->debugger);
+ return static_cast<QV4Debugger *>(m_v4->debugger());
}
void evaluateJavaScript(const QString &script, const QString &fileName, int lineNumber = 1)
{
@@ -444,7 +444,7 @@ void tst_qv4debugger::addBreakPointWhilePaused()
static QV4::ReturnedValue someCall(QV4::CallContext *ctx)
{
- static_cast<QV4Debugger *>(ctx->d()->engine->debugger)
+ static_cast<QV4Debugger *>(ctx->d()->engine->debugger())
->removeBreakPoint("removeBreakPointForNextInstruction", 2);
return QV4::Encode::undefined();
}
diff --git a/tests/auto/qml/debugger/shared/debugutil_p.h b/tests/auto/qml/debugger/shared/debugutil_p.h
index 6fe5d897e0..1ec0a6513d 100644
--- a/tests/auto/qml/debugger/shared/debugutil_p.h
+++ b/tests/auto/qml/debugger/shared/debugutil_p.h
@@ -135,8 +135,6 @@ public:
int lastResponseId;
bool lastResult;
-public slots:
-
void recordResponse(int requestId, bool result)
{
lastResponseId = requestId;
diff --git a/tests/auto/qml/qjsengine/tst_qjsengine.cpp b/tests/auto/qml/qjsengine/tst_qjsengine.cpp
index b1d19b5796..3ceeb97718 100644
--- a/tests/auto/qml/qjsengine/tst_qjsengine.cpp
+++ b/tests/auto/qml/qjsengine/tst_qjsengine.cpp
@@ -73,6 +73,7 @@ private slots:
void newQObject();
void newQObject_ownership();
void newQObject_deletedEngine();
+ void newQMetaObject();
void exceptionInSlot();
void globalObjectProperties();
void globalObjectEquals();
@@ -714,6 +715,104 @@ void tst_QJSEngine::newQObject_deletedEngine()
QTRY_VERIFY(spy.count());
}
+class TestQMetaObject : public QObject {
+ Q_OBJECT
+ Q_PROPERTY(int called READ called)
+public:
+ enum Enum1 {
+ Zero = 0,
+ One,
+ Two
+ };
+ enum Enum2 {
+ A = 0,
+ B,
+ C
+ };
+ Q_ENUMS(Enum1 Enum2)
+
+ Q_INVOKABLE TestQMetaObject()
+ : m_called(1) {
+ }
+ Q_INVOKABLE TestQMetaObject(int)
+ : m_called(2) {
+ }
+ Q_INVOKABLE TestQMetaObject(QString)
+ : m_called(3) {
+ }
+ Q_INVOKABLE TestQMetaObject(QString, int)
+ : m_called(4) {
+ }
+ int called() const {
+ return m_called;
+ }
+private:
+ int m_called;
+};
+
+void tst_QJSEngine::newQMetaObject() {
+ {
+ QJSEngine engine;
+ QJSValue metaObject = engine.newQMetaObject(&TestQMetaObject::staticMetaObject);
+ QCOMPARE(metaObject.isNull(), false);
+ QCOMPARE(metaObject.isObject(), true);
+ QCOMPARE(metaObject.isQObject(), false);
+ QCOMPARE(metaObject.isCallable(), true);
+ QCOMPARE(metaObject.isQMetaObject(), true);
+
+ QCOMPARE(metaObject.toQMetaObject(), &TestQMetaObject::staticMetaObject);
+
+ QVERIFY(metaObject.strictlyEquals(engine.newQMetaObject<TestQMetaObject>()));
+
+
+ {
+ auto result = metaObject.callAsConstructor();
+ if (result.isError())
+ qDebug() << result.toString();
+ QCOMPARE(result.isError(), false);
+ QCOMPARE(result.isNull(), false);
+ QCOMPARE(result.isObject(), true);
+ QCOMPARE(result.isQObject(), true);
+ QVERIFY(result.property("constructor").strictlyEquals(metaObject));
+ QVERIFY(result.prototype().strictlyEquals(metaObject));
+
+
+ QCOMPARE(result.property("called").toInt(), 1);
+
+ }
+
+ QJSValue integer(42);
+ QJSValue string("foo");
+
+ {
+ auto result = metaObject.callAsConstructor({integer});
+ QCOMPARE(result.property("called").toInt(), 2);
+ }
+
+ {
+ auto result = metaObject.callAsConstructor({string});
+ QCOMPARE(result.property("called").toInt(), 3);
+ }
+
+ {
+ auto result = metaObject.callAsConstructor({string, integer});
+ QCOMPARE(result.property("called").toInt(), 4);
+ }
+ }
+
+ {
+ QJSEngine engine;
+ QJSValue metaObject = engine.newQMetaObject(&TestQMetaObject::staticMetaObject);
+ QCOMPARE(metaObject.property("Zero").toInt(), 0);
+ QCOMPARE(metaObject.property("One").toInt(), 1);
+ QCOMPARE(metaObject.property("Two").toInt(), 2);
+ QCOMPARE(metaObject.property("A").toInt(), 0);
+ QCOMPARE(metaObject.property("B").toInt(), 1);
+ QCOMPARE(metaObject.property("C").toInt(), 2);
+ }
+
+}
+
void tst_QJSEngine::exceptionInSlot()
{
QJSEngine engine;
@@ -1027,11 +1126,14 @@ void tst_QJSEngine::builtinFunctionNames_data()
QTest::newRow("Math.pow") << QString("Math.pow") << QString("pow");
QTest::newRow("Math.random") << QString("Math.random") << QString("random");
QTest::newRow("Math.round") << QString("Math.round") << QString("round");
+ QTest::newRow("Math.sign") << QString("Math.sign") << QString("sign");
QTest::newRow("Math.sin") << QString("Math.sin") << QString("sin");
QTest::newRow("Math.sqrt") << QString("Math.sqrt") << QString("sqrt");
QTest::newRow("Math.tan") << QString("Math.tan") << QString("tan");
QTest::newRow("Number") << QString("Number") << QString("Number");
+ QTest::newRow("Number.isFinite") << QString("Number.isFinite") << QString("isFinite");
+ QTest::newRow("Number.isNaN") << QString("Number.isNaN") << QString("isNaN");
QTest::newRow("Number.prototype.toString") << QString("Number.prototype.toString") << QString("toString");
QTest::newRow("Number.prototype.toLocaleString") << QString("Number.prototype.toLocaleString") << QString("toLocaleString");
QTest::newRow("Number.prototype.valueOf") << QString("Number.prototype.valueOf") << QString("valueOf");
@@ -1060,6 +1162,8 @@ void tst_QJSEngine::builtinFunctionNames_data()
QTest::newRow("String.prototype.charAt") << QString("String.prototype.charAt") << QString("charAt");
QTest::newRow("String.prototype.charCodeAt") << QString("String.prototype.charCodeAt") << QString("charCodeAt");
QTest::newRow("String.prototype.concat") << QString("String.prototype.concat") << QString("concat");
+ QTest::newRow("String.prototype.endsWith") << QString("String.prototype.endsWith") << QString("endsWith");
+ QTest::newRow("String.prototype.includes") << QString("String.prototype.includes") << QString("includes");
QTest::newRow("String.prototype.indexOf") << QString("String.prototype.indexOf") << QString("indexOf");
QTest::newRow("String.prototype.lastIndexOf") << QString("String.prototype.lastIndexOf") << QString("lastIndexOf");
QTest::newRow("String.prototype.localeCompare") << QString("String.prototype.localeCompare") << QString("localeCompare");
@@ -1068,6 +1172,7 @@ void tst_QJSEngine::builtinFunctionNames_data()
QTest::newRow("String.prototype.search") << QString("String.prototype.search") << QString("search");
QTest::newRow("String.prototype.slice") << QString("String.prototype.slice") << QString("slice");
QTest::newRow("String.prototype.split") << QString("String.prototype.split") << QString("split");
+ QTest::newRow("String.prototype.startsWith") << QString("String.prototype.startsWith") << QString("startsWith");
QTest::newRow("String.prototype.substring") << QString("String.prototype.substring") << QString("substring");
QTest::newRow("String.prototype.toLowerCase") << QString("String.prototype.toLowerCase") << QString("toLowerCase");
QTest::newRow("String.prototype.toLocaleLowerCase") << QString("String.prototype.toLocaleLowerCase") << QString("toLocaleLowerCase");
@@ -1920,6 +2025,7 @@ void tst_QJSEngine::jsNumberClass()
QVERIFY(ctor.property("NaN").isNumber());
QVERIFY(ctor.property("NEGATIVE_INFINITY").isNumber());
QVERIFY(ctor.property("POSITIVE_INFINITY").isNumber());
+ QVERIFY(ctor.property("EPSILON").isNumber());
}
QCOMPARE(proto.toNumber(), qreal(0));
QVERIFY(proto.property("constructor").strictlyEquals(ctor));
@@ -1958,6 +2064,50 @@ void tst_QJSEngine::jsNumberClass()
QCOMPARE(ret.toNumber(), qreal(456));
}
+ QVERIFY(ctor.property("isFinite").isCallable());
+ {
+ QJSValue ret = eng.evaluate("Number.isFinite()");
+ QVERIFY(ret.isBool());
+ QCOMPARE(ret.toBool(), false);
+ }
+ {
+ QJSValue ret = eng.evaluate("Number.isFinite(NaN)");
+ QVERIFY(ret.isBool());
+ QCOMPARE(ret.toBool(), false);
+ }
+ {
+ QJSValue ret = eng.evaluate("Number.isFinite(Infinity)");
+ QVERIFY(ret.isBool());
+ QCOMPARE(ret.toBool(), false);
+ }
+ {
+ QJSValue ret = eng.evaluate("Number.isFinite(-Infinity)");
+ QVERIFY(ret.isBool());
+ QCOMPARE(ret.toBool(), false);
+ }
+ {
+ QJSValue ret = eng.evaluate("Number.isFinite(123)");
+ QVERIFY(ret.isBool());
+ QCOMPARE(ret.toBool(), true);
+ }
+
+ QVERIFY(ctor.property("isNaN").isCallable());
+ {
+ QJSValue ret = eng.evaluate("Number.isNaN()");
+ QVERIFY(ret.isBool());
+ QCOMPARE(ret.toBool(), false);
+ }
+ {
+ QJSValue ret = eng.evaluate("Number.isNaN(NaN)");
+ QVERIFY(ret.isBool());
+ QCOMPARE(ret.toBool(), true);
+ }
+ {
+ QJSValue ret = eng.evaluate("Number.isNaN(123)");
+ QVERIFY(ret.isBool());
+ QCOMPARE(ret.toBool(), false);
+ }
+
QVERIFY(proto.property("toString").isCallable());
{
QJSValue ret = eng.evaluate("new Number(123).toString()");
diff --git a/tests/auto/qml/qml.pro b/tests/auto/qml/qml.pro
index 28f04be5d7..a1daa7a0c4 100644
--- a/tests/auto/qml/qml.pro
+++ b/tests/auto/qml/qml.pro
@@ -61,7 +61,9 @@ PRIVATETESTS += \
v4misc \
qqmltranslation \
qqmlimport \
- qqmlobjectmodel
+ qqmlobjectmodel \
+ qmldiskcache \
+ qv4mm
qtHaveModule(widgets) {
PUBLICTESTS += \
diff --git a/tests/auto/qml/qmldiskcache/qmldiskcache.pro b/tests/auto/qml/qmldiskcache/qmldiskcache.pro
new file mode 100644
index 0000000000..f2d1a04780
--- /dev/null
+++ b/tests/auto/qml/qmldiskcache/qmldiskcache.pro
@@ -0,0 +1,7 @@
+CONFIG += testcase
+TARGET = tst_qmldiskcache
+osx:CONFIG -= app_bundle
+
+SOURCES += tst_qmldiskcache.cpp
+
+QT += core-private qml-private testlib
diff --git a/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp b/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp
new file mode 100644
index 0000000000..1fe63bb99a
--- /dev/null
+++ b/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp
@@ -0,0 +1,326 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite 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$
+**
+****************************************************************************/
+
+#include <qtest.h>
+
+#include <private/qv4compileddata_p.h>
+#include <private/qv4compiler_p.h>
+#include <private/qv4jsir_p.h>
+#include <private/qv4isel_p.h>
+#include <private/qv8engine_p.h>
+#include <private/qv4engine_p.h>
+#include <QQmlComponent>
+#include <QQmlEngine>
+#include <QThread>
+
+class tst_qmldiskcache: public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void initTestCase();
+
+ void regenerateAfterChange();
+ void registerImportForImplicitComponent();
+ void basicVersionChecks();
+};
+
+struct TestCompiler
+{
+ TestCompiler(QQmlEngine *engine)
+ : engine(engine)
+ , tempDir()
+ , testFilePath(tempDir.path() + QStringLiteral("/test.qml"))
+ , cacheFilePath(tempDir.path() + QStringLiteral("/test.qmlc"))
+ , mappedFile(cacheFilePath)
+ , currentMapping(nullptr)
+ {
+ }
+
+ bool compile(const QByteArray &contents)
+ {
+ closeMapping();
+ engine->clearComponentCache();
+
+ // Qt API limits the precision of QFileInfo::modificationTime() to seconds, so to ensure that
+ // the newly written file has a modification date newer than an existing cache file, we must
+ // wait.
+ QThread::sleep(1);
+ {
+ QFile f(testFilePath);
+ if (!f.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
+ lastErrorString = f.errorString();
+ return false;
+ }
+ if (f.write(contents) != contents.size()) {
+ lastErrorString = f.errorString();
+ return false;
+ }
+ }
+
+ QQmlComponent component(engine, testFilePath);
+ if (!component.isReady()) {
+ lastErrorString = component.errorString();
+ return false;
+ }
+
+ return true;
+ }
+
+ const QV4::CompiledData::Unit *mapUnit()
+ {
+ if (!mappedFile.open(QIODevice::ReadOnly)) {
+ lastErrorString = mappedFile.errorString();
+ return nullptr;
+ }
+
+ currentMapping = mappedFile.map(/*offset*/0, mappedFile.size());
+ if (!currentMapping) {
+ lastErrorString = mappedFile.errorString();
+ return nullptr;
+ }
+ QV4::CompiledData::Unit *unitPtr;
+ memcpy(&unitPtr, &currentMapping, sizeof(unitPtr));
+ return unitPtr;
+ }
+
+ typedef void (*HeaderTweakFunction)(QV4::CompiledData::Unit *header);
+ bool tweakHeader(HeaderTweakFunction function)
+ {
+ closeMapping();
+
+ QFile f(cacheFilePath);
+ if (!f.open(QIODevice::ReadWrite))
+ return false;
+ QV4::CompiledData::Unit header;
+ if (f.read(reinterpret_cast<char *>(&header), sizeof(header)) != sizeof(header))
+ return false;
+ function(&header);
+ f.seek(0);
+ return f.write(reinterpret_cast<const char *>(&header), sizeof(header)) == sizeof(header);
+ }
+
+ bool verify()
+ {
+ QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
+ QQmlRefPointer<QV4::CompiledData::CompilationUnit> unit = v4->iselFactory->createUnitForLoading();
+ return unit->loadFromDisk(QUrl::fromLocalFile(testFilePath), v4->iselFactory.data(), &lastErrorString);
+ }
+
+ void closeMapping()
+ {
+ if (currentMapping) {
+ mappedFile.unmap(currentMapping);
+ currentMapping = nullptr;
+ }
+ mappedFile.close();
+ }
+
+ void clearCache()
+ {
+ closeMapping();
+ QFile::remove(cacheFilePath);
+ }
+
+ QQmlEngine *engine;
+ const QTemporaryDir tempDir;
+ const QString testFilePath;
+ const QString cacheFilePath;
+ QString lastErrorString;
+ QFile mappedFile;
+ uchar *currentMapping;
+};
+
+void tst_qmldiskcache::initTestCase()
+{
+ qputenv("QML_DISK_CACHE", "1");
+}
+
+void tst_qmldiskcache::regenerateAfterChange()
+{
+ QQmlEngine engine;
+ TestCompiler testCompiler(&engine);
+
+ QVERIFY(testCompiler.tempDir.isValid());
+
+ const QByteArray contents = QByteArrayLiteral("import QtQml 2.0\n"
+ "QtObject {\n"
+ " property string blah: Qt.platform;\n"
+ "}");
+
+ QVERIFY2(testCompiler.compile(contents), qPrintable(testCompiler.lastErrorString));
+
+ {
+ const QV4::CompiledData::Unit *testUnit = testCompiler.mapUnit();
+ QVERIFY2(testUnit, qPrintable(testCompiler.lastErrorString));
+
+ QCOMPARE(quint32(testUnit->nObjects), quint32(1));
+
+ const QV4::CompiledData::Object *obj = testUnit->objectAt(0);
+ QCOMPARE(quint32(obj->nBindings), quint32(1));
+ QCOMPARE(quint32(obj->bindingTable()->type), quint32(QV4::CompiledData::Binding::Type_Script));
+ QCOMPARE(quint32(obj->bindingTable()->value.compiledScriptIndex), quint32(1));
+
+ QCOMPARE(quint32(testUnit->functionTableSize), quint32(2));
+
+ const QV4::CompiledData::Function *bindingFunction = testUnit->functionAt(1);
+ QVERIFY(bindingFunction->codeOffset > testUnit->unitSize);
+ }
+
+ {
+ const QByteArray newContents = QByteArrayLiteral("import QtQml 2.0\n"
+ "QtObject {\n"
+ " property string blah: Qt.platform;\n"
+ " property int secondProperty: 42;\n"
+ "}");
+
+ QVERIFY2(testCompiler.compile(newContents), qPrintable(testCompiler.lastErrorString));
+ const QV4::CompiledData::Unit *testUnit = testCompiler.mapUnit();
+ QVERIFY2(testUnit, qPrintable(testCompiler.lastErrorString));
+
+ QCOMPARE(quint32(testUnit->nObjects), quint32(1));
+
+ const QV4::CompiledData::Object *obj = testUnit->objectAt(0);
+ QCOMPARE(quint32(obj->nBindings), quint32(2));
+ QCOMPARE(quint32(obj->bindingTable()->type), quint32(QV4::CompiledData::Binding::Type_Number));
+ QCOMPARE(obj->bindingTable()->valueAsNumber(), double(42));
+
+ QCOMPARE(quint32(testUnit->functionTableSize), quint32(2));
+
+ const QV4::CompiledData::Function *bindingFunction = testUnit->functionAt(1);
+ QVERIFY(bindingFunction->codeOffset > testUnit->unitSize);
+ }
+}
+
+void tst_qmldiskcache::registerImportForImplicitComponent()
+{
+ QQmlEngine engine;
+
+ TestCompiler testCompiler(&engine);
+ QVERIFY(testCompiler.tempDir.isValid());
+
+ const QByteArray contents = QByteArrayLiteral("import QtQuick 2.0\n"
+ "Loader {\n"
+ " sourceComponent: Item {}\n"
+ "}");
+
+ QVERIFY2(testCompiler.compile(contents), qPrintable(testCompiler.lastErrorString));
+ {
+ const QV4::CompiledData::Unit *testUnit = testCompiler.mapUnit();
+ QVERIFY2(testUnit, qPrintable(testCompiler.lastErrorString));
+
+ QCOMPARE(quint32(testUnit->nImports), quint32(2));
+ QCOMPARE(testUnit->stringAt(testUnit->importAt(0)->uriIndex), QStringLiteral("QtQuick"));
+
+ QQmlType *componentType = QQmlMetaType::qmlType(&QQmlComponent::staticMetaObject);
+
+ QCOMPARE(testUnit->stringAt(testUnit->importAt(1)->uriIndex), QString(componentType->module()));
+ QCOMPARE(testUnit->stringAt(testUnit->importAt(1)->qualifierIndex), QStringLiteral("QmlInternals"));
+
+ QCOMPARE(quint32(testUnit->nObjects), quint32(3));
+
+ const QV4::CompiledData::Object *obj = testUnit->objectAt(0);
+ QCOMPARE(quint32(obj->nBindings), quint32(1));
+ QCOMPARE(quint32(obj->bindingTable()->type), quint32(QV4::CompiledData::Binding::Type_Object));
+
+ const QV4::CompiledData::Object *implicitComponent = testUnit->objectAt(obj->bindingTable()->value.objectIndex);
+ QCOMPARE(testUnit->stringAt(implicitComponent->inheritedTypeNameIndex), QStringLiteral("QmlInternals.") + componentType->elementName());
+ }
+}
+
+void tst_qmldiskcache::basicVersionChecks()
+{
+ QQmlEngine engine;
+
+ TestCompiler testCompiler(&engine);
+ QVERIFY(testCompiler.tempDir.isValid());
+
+ const QByteArray contents = QByteArrayLiteral("import QtQml 2.0\n"
+ "QtObject {\n"
+ " property string blah: Qt.platform;\n"
+ "}");
+
+ {
+ testCompiler.clearCache();
+ QVERIFY2(testCompiler.compile(contents), qPrintable(testCompiler.lastErrorString));
+ QVERIFY2(testCompiler.verify(), qPrintable(testCompiler.lastErrorString));
+ }
+
+ {
+ testCompiler.clearCache();
+ QVERIFY2(testCompiler.compile(contents), qPrintable(testCompiler.lastErrorString));
+
+ testCompiler.tweakHeader([](QV4::CompiledData::Unit *header) {
+ header->qtVersion = 0;
+ });
+
+ QVERIFY(!testCompiler.verify());
+ QCOMPARE(testCompiler.lastErrorString, QString::fromUtf8("Qt version mismatch. Found 0 expected %1").arg(QT_VERSION, 0, 16));
+ testCompiler.clearCache();
+ }
+
+ {
+ testCompiler.clearCache();
+ QVERIFY2(testCompiler.compile(contents), qPrintable(testCompiler.lastErrorString));
+
+ testCompiler.tweakHeader([](QV4::CompiledData::Unit *header) {
+ header->version = 0;
+ });
+
+ QVERIFY(!testCompiler.verify());
+ QCOMPARE(testCompiler.lastErrorString, QString::fromUtf8("V4 data structure version mismatch. Found 0 expected %1").arg(QV4_DATA_STRUCTURE_VERSION, 0, 16));
+ }
+
+ {
+ testCompiler.clearCache();
+ QVERIFY2(testCompiler.compile(contents), qPrintable(testCompiler.lastErrorString));
+
+ testCompiler.tweakHeader([](QV4::CompiledData::Unit *header) {
+ header->architectureIndex = 0;
+ });
+
+ QVERIFY(!testCompiler.verify());
+ QCOMPARE(testCompiler.lastErrorString, QString::fromUtf8("Architecture mismatch. Found expected %1").arg(QSysInfo::buildAbi()));
+ }
+
+ {
+ testCompiler.clearCache();
+ QVERIFY2(testCompiler.compile(contents), qPrintable(testCompiler.lastErrorString));
+
+ testCompiler.tweakHeader([](QV4::CompiledData::Unit *header) {
+ header->codeGeneratorIndex = 0;
+ });
+
+ QVERIFY(!testCompiler.verify());
+ QCOMPARE(testCompiler.lastErrorString, QString::fromUtf8("Code generator mismatch. Found code generated by but expected %1").arg(QV8Engine::getV4(&engine)->iselFactory->codeGeneratorName));
+ }
+}
+
+QTEST_MAIN(tst_qmldiskcache)
+
+#include "tst_qmldiskcache.moc"
diff --git a/tests/auto/qml/qmlplugindump/tst_qmlplugindump.cpp b/tests/auto/qml/qmlplugindump/tst_qmlplugindump.cpp
index ee417bb480..838966e2a0 100644
--- a/tests/auto/qml/qmlplugindump/tst_qmlplugindump.cpp
+++ b/tests/auto/qml/qmlplugindump/tst_qmlplugindump.cpp
@@ -108,6 +108,7 @@ void tst_qmlplugindump::singleton()
dumper.waitForFinished();
const QString &result = dumper.readAllStandardOutput();
+ qDebug() << "result: " << result;
QVERIFY(result.contains(QLatin1String("exports: [\"Singleton 1.0\"]")));
QVERIFY(result.contains(QLatin1String("exportMetaObjectRevisions: [0]")));
}
diff --git a/tests/auto/qml/qqmlbinding/data/delayed.qml b/tests/auto/qml/qqmlbinding/data/delayed.qml
new file mode 100644
index 0000000000..6f8281cc33
--- /dev/null
+++ b/tests/auto/qml/qqmlbinding/data/delayed.qml
@@ -0,0 +1,26 @@
+import QtQuick 2.8
+
+Item {
+ width: 400
+ height: 400
+
+ property int changeCount: 0
+
+ property string text1
+ property string text2
+
+ function updateText() {
+ text1 = "Hello"
+ text2 = "World"
+ }
+
+ Text {
+ anchors.centerIn: parent
+ Binding on text {
+ value: text1 + " " + text2
+ delayed: true
+ }
+ onTextChanged: ++changeCount
+ }
+}
+
diff --git a/tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp b/tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp
index 3e8dfbdb12..6f1d82eca5 100644
--- a/tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp
+++ b/tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp
@@ -49,6 +49,7 @@ private slots:
void warningOnReadOnlyProperty();
void disabledOnUnknownProperty();
void disabledOnReadonlyProperty();
+ void delayed();
private:
QQmlEngine engine;
@@ -281,6 +282,27 @@ void tst_qqmlbinding::disabledOnReadonlyProperty()
QCOMPARE(messageHandler.messages().count(), 0);
}
+void tst_qqmlbinding::delayed()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("delayed.qml"));
+ QQuickItem *item = qobject_cast<QQuickItem*>(c.create());
+
+ QVERIFY(item != 0);
+ // update on creation
+ QCOMPARE(item->property("changeCount").toInt(), 1);
+
+ QMetaObject::invokeMethod(item, "updateText");
+ // doesn't update immediately
+ QCOMPARE(item->property("changeCount").toInt(), 1);
+
+ QCoreApplication::processEvents();
+ // only updates once (non-delayed would update twice)
+ QCOMPARE(item->property("changeCount").toInt(), 2);
+
+ delete item;
+}
+
QTEST_MAIN(tst_qqmlbinding)
#include "tst_qqmlbinding.moc"
diff --git a/tests/auto/qml/qqmlecmascript/data/NullObjectInitializerBase.qml b/tests/auto/qml/qqmlecmascript/data/NullObjectInitializerBase.qml
new file mode 100644
index 0000000000..4006a2a782
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/NullObjectInitializerBase.qml
@@ -0,0 +1,5 @@
+import QtQml 2.0
+QtObject {
+ property Component factory: Component { QtObject {} }
+ property QtObject testProperty: factory.createObject()
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/nullObjectInitializer.2.qml b/tests/auto/qml/qqmlecmascript/data/nullObjectInitializer.2.qml
new file mode 100644
index 0000000000..d59f8f99f9
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/nullObjectInitializer.2.qml
@@ -0,0 +1,8 @@
+import QtQml 2.0
+NullObjectInitializerBase {
+ testProperty: null
+ property bool success: false
+ Component.onCompleted: {
+ success = testProperty === null;
+ }
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/nullObjectInitializer.qml b/tests/auto/qml/qqmlecmascript/data/nullObjectInitializer.qml
new file mode 100644
index 0000000000..32bc62c9f2
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/nullObjectInitializer.qml
@@ -0,0 +1,4 @@
+import QtQml 2.0
+QtObject {
+ property QtObject testProperty: null
+}
diff --git a/tests/auto/qml/qqmlecmascript/testtypes.h b/tests/auto/qml/qqmlecmascript/testtypes.h
index d4d051443f..47fb2a56e7 100644
--- a/tests/auto/qml/qqmlecmascript/testtypes.h
+++ b/tests/auto/qml/qqmlecmascript/testtypes.h
@@ -790,7 +790,8 @@ public:
Q_INVOKABLE void method_QObject(QObject *a) { invoke(13); m_actuals << qVariantFromValue(a); }
Q_INVOKABLE void method_QScriptValue(QJSValue a) { invoke(14); m_actuals << qVariantFromValue(a); }
Q_INVOKABLE void method_intQScriptValue(int a, QJSValue b) { invoke(15); m_actuals << a << qVariantFromValue(b); }
- Q_INVOKABLE QJSValue method_intQJSValue(int a, QJSValue b) { invoke(29); m_actuals << a << qVariantFromValue(b); return b.call(); }
+ Q_INVOKABLE void method_QByteArray(QByteArray value) { invoke(29); m_actuals << value; }
+ Q_INVOKABLE QJSValue method_intQJSValue(int a, QJSValue b) { invoke(30); m_actuals << a << qVariantFromValue(b); return b.call(); }
Q_INVOKABLE QJSValue method_intQJSValue(int a, int b) { m_actuals << a << b; return QJSValue();} // Should never be called.
Q_INVOKABLE void method_overload(int a) { invoke(16); m_actuals << a; }
diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
index aeb8b08cd4..de3ead917f 100644
--- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
+++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
@@ -208,6 +208,7 @@ private slots:
void dynamicCreationOwnership();
void regExpBug();
void nullObjectBinding();
+ void nullObjectInitializer();
void deletedEngine();
void libraryScriptAssert();
void variantsAssignedUndefined();
@@ -2314,7 +2315,7 @@ static inline bool evaluate_error(QV8Engine *engine, const QV4::Value &o, const
QV4::ScopedCallData d(scope, 1);
d->args[0] = o;
d->thisObject = engine->global();
- function->call(d);
+ function->call(scope, d);
if (scope.engine->hasException) {
scope.engine->catchException();
return true;
@@ -2340,16 +2341,15 @@ static inline bool evaluate_value(QV8Engine *engine, const QV4::Value &o,
if (!function)
return false;
- QV4::ScopedValue value(scope);
QV4::ScopedCallData d(scope, 1);
d->args[0] = o;
d->thisObject = engine->global();
- value = function->call(d);
+ function->call(scope, d);
if (scope.engine->hasException) {
scope.engine->catchException();
return false;
}
- return QV4::Runtime::strictEqual(value, result);
+ return QV4::Runtime::method_strictEqual(scope.result, result);
}
static inline QV4::ReturnedValue evaluate(QV8Engine *engine, const QV4::Value &o,
@@ -2373,12 +2373,12 @@ static inline QV4::ReturnedValue evaluate(QV8Engine *engine, const QV4::Value &o
QV4::ScopedCallData d(scope, 1);
d->args[0] = o;
d->thisObject = engine->global();
- QV4::ScopedValue result(scope, function->call(d));
+ function->call(scope, d);
if (scope.engine->hasException) {
scope.engine->catchException();
return QV4::Encode::undefined();
}
- return result->asReturnedValue();
+ return scope.result.asReturnedValue();
}
#define EVALUATE_ERROR(source) evaluate_error(engine, object, source)
@@ -2942,9 +2942,16 @@ void tst_qqmlecmascript::callQtInvokables()
QCOMPARE(o->actuals().count(), 0);
o->reset();
- QV4::ScopedValue ret(scope, EVALUATE("object.method_intQJSValue(123, function() { return \"Hello world!\";})"));
+ QVERIFY(EVALUATE_VALUE("object.method_QByteArray(\"Hello\")", QV4::Primitive::undefinedValue()));
QCOMPARE(o->error(), false);
QCOMPARE(o->invoked(), 29);
+ QCOMPARE(o->actuals().count(), 1);
+ QCOMPARE(qvariant_cast<QByteArray>(o->actuals().at(0)), QByteArray("Hello"));
+
+ o->reset();
+ QV4::ScopedValue ret(scope, EVALUATE("object.method_intQJSValue(123, function() { return \"Hello world!\";})"));
+ QCOMPARE(o->error(), false);
+ QCOMPARE(o->invoked(), 30);
QVERIFY(ret->isString());
QCOMPARE(ret->toQStringNoThrow(), QString("Hello world!"));
QCOMPARE(o->actuals().count(), 2);
@@ -5703,6 +5710,49 @@ void tst_qqmlecmascript::nullObjectBinding()
delete object;
}
+void tst_qqmlecmascript::nullObjectInitializer()
+{
+ {
+ QQmlComponent component(&engine, testFileUrl("nullObjectInitializer.qml"));
+ QScopedPointer<QObject> obj(component.create());
+ QVERIFY(!obj.isNull());
+
+ QQmlData *ddata = QQmlData::get(obj.data(), /*create*/false);
+ QVERIFY(ddata);
+
+ {
+ const int propertyIndex = obj->metaObject()->indexOfProperty("testProperty");
+ QVERIFY(propertyIndex > 0);
+ QVERIFY(!ddata->hasBindingBit(propertyIndex));
+ }
+
+ QVariant value = obj->property("testProperty");
+ QVERIFY(value.userType() == qMetaTypeId<QObject*>());
+ QVERIFY(!value.value<QObject*>());
+ }
+
+ {
+ QQmlComponent component(&engine, testFileUrl("nullObjectInitializer.2.qml"));
+ QScopedPointer<QObject> obj(component.create());
+ QVERIFY(!obj.isNull());
+
+ QQmlData *ddata = QQmlData::get(obj.data(), /*create*/false);
+ QVERIFY(ddata);
+
+ {
+ const int propertyIndex = obj->metaObject()->indexOfProperty("testProperty");
+ QVERIFY(propertyIndex > 0);
+ QVERIFY(ddata->hasBindingBit(propertyIndex));
+ }
+
+ QVERIFY(obj->property("success").toBool());
+
+ QVariant value = obj->property("testProperty");
+ QVERIFY(value.userType() == qMetaTypeId<QObject*>());
+ QVERIFY(!value.value<QObject*>());
+ }
+}
+
// Test that bindings don't evaluate once the engine has been destroyed
void tst_qqmlecmascript::deletedEngine()
{
diff --git a/tests/auto/qml/qqmlengine/data/qtqmlModule.4.qml b/tests/auto/qml/qqmlengine/data/qtqmlModule.4.qml
index 9b9b7922da..94ee46ddf0 100644
--- a/tests/auto/qml/qqmlengine/data/qtqmlModule.4.qml
+++ b/tests/auto/qml/qqmlengine/data/qtqmlModule.4.qml
@@ -1,4 +1,4 @@
-import QtQml 2.5
+import QtQml 2.50
QtObject {
}
diff --git a/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp b/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp
index 3208745c5c..74e54b64e9 100644
--- a/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp
+++ b/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp
@@ -317,6 +317,11 @@ public:
QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
QCoreApplication::processEvents();
+ // There might be JS function objects around that hold a last ref to the compilation unit that's
+ // keeping the type compilation data (CompilationUnit) around. Let's collect them as well so that
+ // trim works well.
+ engine->collectGarbage();
+
engine->trimComponentCache();
}
@@ -615,9 +620,9 @@ void tst_qqmlengine::qtqmlModule_data()
<< QString(testFileUrl("qtqmlModule.3.qml").toString() + QLatin1String(":1 module \"QtQml\" version 1.0 is not installed\n"))
<< QStringList();
- QTest::newRow("import QtQml of incorrect version (2.5)")
+ QTest::newRow("import QtQml of incorrect version (2.50)")
<< testFileUrl("qtqmlModule.4.qml")
- << QString(testFileUrl("qtqmlModule.4.qml").toString() + QLatin1String(":1 module \"QtQml\" version 2.5 is not installed\n"))
+ << QString(testFileUrl("qtqmlModule.4.qml").toString() + QLatin1String(":1 module \"QtQml\" version 2.50 is not installed\n"))
<< QStringList();
QTest::newRow("QtQml 2.0 module provides Component, QtObject, Connections, Binding and Timer")
diff --git a/tests/auto/qml/qqmlenginecleanup/data/types.qml b/tests/auto/qml/qqmlenginecleanup/data/types.qml
index 3d27900744..7282c7dbfb 100644
--- a/tests/auto/qml/qqmlenginecleanup/data/types.qml
+++ b/tests/auto/qml/qqmlenginecleanup/data/types.qml
@@ -29,7 +29,7 @@
import QtQml 2.0
import QtQuick 2.0
import QtQuick.Window 2.0
-import QtQuick.Particles 2.0
+
import Test 2.0
import "."
@@ -37,7 +37,6 @@ QtObject {
//Doesn't create items, just checks that the types are accessible
property TestType tt
property TestTypeCpp ttc
- property ParticleSystem ps
property Window wi
property Item it
}
diff --git a/tests/auto/qml/qqmllanguage/data/alias.12.qml b/tests/auto/qml/qqmllanguage/data/alias.12.qml
new file mode 100644
index 0000000000..cc17318092
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/alias.12.qml
@@ -0,0 +1,15 @@
+import QtQml 2.0
+
+QtObject {
+ id: root
+ property alias topLevelAlias: subObject.targetProperty
+
+ property QtObject referencingSubObject: QtObject {
+ property alias success: root.topLevelAlias
+ }
+
+ property QtObject foo: QtObject {
+ id: subObject
+ property bool targetProperty: true
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/alias.13.qml b/tests/auto/qml/qqmllanguage/data/alias.13.qml
new file mode 100644
index 0000000000..cff8a72d9a
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/alias.13.qml
@@ -0,0 +1,16 @@
+import QtQml 2.0
+
+QtObject {
+ id: root
+ property bool targetProperty: true
+
+ property QtObject foo: QtObject {
+ id: otherSubObject
+ property alias theAlias: root.targetProperty
+ }
+
+ property QtObject referencingSubObject: QtObject {
+ property alias success: otherSubObject.theAlias
+ }
+
+}
diff --git a/tests/auto/qml/qqmllanguage/data/alias.14.errors.txt b/tests/auto/qml/qqmllanguage/data/alias.14.errors.txt
new file mode 100644
index 0000000000..90a3ea4317
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/alias.14.errors.txt
@@ -0,0 +1 @@
+10:34:References to other aliases within the same object are not supported at the moment
diff --git a/tests/auto/qml/qqmllanguage/data/alias.14.qml b/tests/auto/qml/qqmllanguage/data/alias.14.qml
new file mode 100644
index 0000000000..ff3c36d990
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/alias.14.qml
@@ -0,0 +1,17 @@
+import QtQml 2.0
+
+QtObject {
+ id: root
+ property bool targetProperty: true
+
+ property QtObject foo: QtObject {
+ id: otherSubObject
+ property alias theAliasOrigin: root.targetProperty
+ property alias theAlias: otherSubObject.theAliasOrigin
+ }
+
+ property QtObject referencingSubObject: QtObject {
+ property alias success: otherSubObject.theAlias
+ }
+
+}
diff --git a/tests/auto/qml/qqmllanguage/data/arraybuffer_method_arg.qml b/tests/auto/qml/qqmllanguage/data/arraybuffer_method_arg.qml
new file mode 100644
index 0000000000..b64a2e23c0
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/arraybuffer_method_arg.qml
@@ -0,0 +1,11 @@
+import QtQuick 2.7
+import Test 1.0
+
+MyArrayBufferTestClass {
+ property bool ok: false
+ Component.onCompleted: {
+ var data = new Uint8Array([1, 2, 3]);
+ var sum = byteArrayMethod_Sum(data.buffer);
+ ok = sum == 6;
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/arraybuffer_method_overload.qml b/tests/auto/qml/qqmllanguage/data/arraybuffer_method_overload.qml
new file mode 100644
index 0000000000..9e1c91810a
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/arraybuffer_method_overload.qml
@@ -0,0 +1,7 @@
+import QtQuick 2.7
+import Test 1.0
+
+MyArrayBufferTestClass {
+ property bool ok: false
+ Component.onCompleted: ok = byteArrayMethod_Overloaded(new ArrayBuffer());
+}
diff --git a/tests/auto/qml/qqmllanguage/data/arraybuffer_method_return.qml b/tests/auto/qml/qqmllanguage/data/arraybuffer_method_return.qml
new file mode 100644
index 0000000000..5a4f9fec0b
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/arraybuffer_method_return.qml
@@ -0,0 +1,15 @@
+import QtQuick 2.7
+import Test 1.0
+
+MyArrayBufferTestClass {
+ property bool ok: false
+ Component.onCompleted: {
+ var buf = byteArrayMethod_CountUp(1, 3);
+ var view = new DataView(buf);
+ ok = buf instanceof ArrayBuffer
+ && buf.byteLength == 3
+ && view.getUint8(0) == 1
+ && view.getUint8(1) == 2
+ && view.getUint8(2) == 3;
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/arraybuffer_property_get.qml b/tests/auto/qml/qqmllanguage/data/arraybuffer_property_get.qml
new file mode 100644
index 0000000000..78ebb1abe1
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/arraybuffer_property_get.qml
@@ -0,0 +1,5 @@
+import Test 1.0
+
+MyArrayBufferTestClass {
+ property bool ok: byteArrayProperty instanceof ArrayBuffer
+}
diff --git a/tests/auto/qml/qqmllanguage/data/arraybuffer_property_set.qml b/tests/auto/qml/qqmllanguage/data/arraybuffer_property_set.qml
new file mode 100644
index 0000000000..e8a51273ca
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/arraybuffer_property_set.qml
@@ -0,0 +1,11 @@
+import QtQuick 2.7
+import Test 1.0
+
+MyArrayBufferTestClass {
+ property bool ok: false
+ onByteArraySignal: ok = byteArrayProperty instanceof ArrayBuffer
+ Component.onCompleted: {
+ byteArrayProperty = new ArrayBuffer(42);
+ ok = byteArrayProperty instanceof ArrayBuffer && byteArrayProperty.byteLength == 42;
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/arraybuffer_signal_arg.qml b/tests/auto/qml/qqmllanguage/data/arraybuffer_signal_arg.qml
new file mode 100644
index 0000000000..d9f436e788
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/arraybuffer_signal_arg.qml
@@ -0,0 +1,14 @@
+import QtQuick 2.7
+import Test 1.0
+
+MyArrayBufferTestClass {
+ property bool ok: false
+ onByteArraySignal: {
+ var view = new DataView(arg);
+ ok = arg instanceof ArrayBuffer
+ && arg.byteLength == 2
+ && view.getUint8(0) == 42
+ && view.getUint8(1) == 43;
+ }
+ Component.onCompleted: emitByteArraySignal(42, 2)
+}
diff --git a/tests/auto/qml/qqmllanguage/data/badCompositeRegistration.1.errors.txt b/tests/auto/qml/qqmllanguage/data/badCompositeRegistration.1.errors.txt
index 7a75447a62..acf0d1da84 100644
--- a/tests/auto/qml/qqmllanguage/data/badCompositeRegistration.1.errors.txt
+++ b/tests/auto/qml/qqmllanguage/data/badCompositeRegistration.1.errors.txt
@@ -1,2 +1,2 @@
3:1:Type RegisteredCompositeType2 unavailable
--1:-1:File not found
+-1:-1:No such file or directory
diff --git a/tests/auto/qml/qqmllanguage/data/invalidAlias.11.errors.txt b/tests/auto/qml/qqmllanguage/data/invalidAlias.11.errors.txt
new file mode 100644
index 0000000000..b79b660c46
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/invalidAlias.11.errors.txt
@@ -0,0 +1 @@
+5:5:Circular alias reference detected
diff --git a/tests/auto/qml/qqmllanguage/data/invalidAlias.11.qml b/tests/auto/qml/qqmllanguage/data/invalidAlias.11.qml
new file mode 100644
index 0000000000..9b50b48df8
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/invalidAlias.11.qml
@@ -0,0 +1,10 @@
+import QtQml 2.0
+
+QtObject {
+ id: root
+ property alias a: subObject.b
+ property QtObject foo: QtObject {
+ id: subObject
+ property alias b: root.a
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/rootItemIsComponent.qml b/tests/auto/qml/qqmllanguage/data/rootItemIsComponent.qml
new file mode 100644
index 0000000000..dd653352d9
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/rootItemIsComponent.qml
@@ -0,0 +1,6 @@
+import QtQml 2.0
+Component {
+ QtObject {
+ id: blah
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/singletonTest10.error.txt b/tests/auto/qml/qqmllanguage/data/singletonTest10.error.txt
deleted file mode 100644
index 32d2ed857e..0000000000
--- a/tests/auto/qml/qqmllanguage/data/singletonTest10.error.txt
+++ /dev/null
@@ -1 +0,0 @@
-4:1:Composite Singleton Type SingletonType is not creatable.
diff --git a/tests/auto/qml/qqmllanguage/data/singletonTest12.error.txt b/tests/auto/qml/qqmllanguage/data/singletonTest12.error.txt
index 716cf5709a..b3082d80e6 100644
--- a/tests/auto/qml/qqmllanguage/data/singletonTest12.error.txt
+++ b/tests/auto/qml/qqmllanguage/data/singletonTest12.error.txt
@@ -1,2 +1,2 @@
5:5:Type RegisteredCompositeType unavailable
-2:1:pragma Singleton used with a non composite singleton type CompositeSingletonTest/RegisteredCompositeType
+-1:-1:pragma Singleton used with a non composite singleton type CompositeSingletonTest/RegisteredCompositeType
diff --git a/tests/auto/qml/qqmllanguage/data/singletonTest4.error.txt b/tests/auto/qml/qqmllanguage/data/singletonTest4.error.txt
index 77c26df310..ebeab6987b 100644
--- a/tests/auto/qml/qqmllanguage/data/singletonTest4.error.txt
+++ b/tests/auto/qml/qqmllanguage/data/singletonTest4.error.txt
@@ -1 +1 @@
-2:1:No matching type found, pragma Singleton files cannot be used by QQmlComponent.
+-1:-1:No matching type found, pragma Singleton files cannot be used by QQmlComponent.
diff --git a/tests/auto/qml/qqmllanguage/data/uncreatableTypeAsProperty.qml b/tests/auto/qml/qqmllanguage/data/uncreatableTypeAsProperty.qml
new file mode 100644
index 0000000000..8369ab1eea
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/uncreatableTypeAsProperty.qml
@@ -0,0 +1,6 @@
+import QtQml 2.0
+import Test 1.0
+
+QtObject {
+ property MyUncreateableBaseClass someProperty;
+}
diff --git a/tests/auto/qml/qqmllanguage/testtypes.cpp b/tests/auto/qml/qqmllanguage/testtypes.cpp
index 9593bfc940..3921f89d23 100644
--- a/tests/auto/qml/qqmllanguage/testtypes.cpp
+++ b/tests/auto/qml/qqmllanguage/testtypes.cpp
@@ -27,8 +27,6 @@
****************************************************************************/
#include "testtypes.h"
-#include <private/qqmlcompiler_p.h>
-
static QObject *myTypeObjectSingleton(QQmlEngine *engine, QJSEngine *scriptEngine)
{
Q_UNUSED(engine)
@@ -98,6 +96,8 @@ void registerTypes()
qmlRegisterType<MyCompositeBaseType>("Test", 1, 0, "MyCompositeBaseType");
qmlRegisterSingletonType<MyTypeObjectSingleton>("Test", 1, 0, "MyTypeObjectSingleton", myTypeObjectSingleton);
+
+ qmlRegisterType<MyArrayBufferTestClass>("Test", 1, 0, "MyArrayBufferTestClass");
}
QVariant myCustomVariantTypeConverter(const QString &data)
@@ -108,11 +108,11 @@ QVariant myCustomVariantTypeConverter(const QString &data)
}
-void CustomBindingParser::applyBindings(QObject *object, QQmlCompiledData *cdata, const QList<const QV4::CompiledData::Binding *> &bindings)
+void CustomBindingParser::applyBindings(QObject *object, QV4::CompiledData::CompilationUnit *compilationUnit, const QList<const QV4::CompiledData::Binding *> &bindings)
{
CustomBinding *customBinding = qobject_cast<CustomBinding*>(object);
Q_ASSERT(customBinding);
- customBinding->cdata = cdata;
+ customBinding->compilationUnit = compilationUnit;
customBinding->bindings = bindings;
}
@@ -121,17 +121,18 @@ void CustomBinding::componentComplete()
Q_ASSERT(m_target);
foreach (const QV4::CompiledData::Binding *binding, bindings) {
- QString name = cdata->compilationUnit->data->stringAt(binding->propertyNameIndex);
+ QString name = compilationUnit->data->stringAt(binding->propertyNameIndex);
int bindingId = binding->value.compiledScriptIndex;
QQmlContextData *context = QQmlContextData::get(qmlContext(this));
QV4::Scope scope(QQmlEnginePrivate::getV4Engine(qmlEngine(this)));
- QV4::ScopedValue function(scope, QV4::FunctionObject::createQmlFunction(context, m_target, cdata->compilationUnit->runtimeFunctions[bindingId]));
- QQmlBinding *qmlBinding = new QQmlBinding(function, m_target, context);
+ QV4::ScopedValue function(scope, QV4::FunctionObject::createQmlFunction(context, m_target, compilationUnit->runtimeFunctions[bindingId]));
QQmlProperty property(m_target, name, qmlContext(this));
+ QQmlBinding *qmlBinding = QQmlBinding::create(&QQmlPropertyPrivate::get(property)->core,
+ function, m_target, context);
qmlBinding->setTarget(property);
QQmlPropertyPrivate::setBinding(property, qmlBinding);
}
@@ -167,7 +168,7 @@ void EnumSupportingCustomParser::verifyBindings(const QV4::CompiledData::Unit *q
}
}
-void SimpleObjectCustomParser::applyBindings(QObject *object, QQmlCompiledData *, const QList<const QV4::CompiledData::Binding *> &bindings)
+void SimpleObjectCustomParser::applyBindings(QObject *object, QV4::CompiledData::CompilationUnit *, const QList<const QV4::CompiledData::Binding *> &bindings)
{
SimpleObjectWithCustomParser *o = qobject_cast<SimpleObjectWithCustomParser*>(object);
Q_ASSERT(o);
diff --git a/tests/auto/qml/qqmllanguage/testtypes.h b/tests/auto/qml/qqmllanguage/testtypes.h
index 337ba91532..af7dc155d0 100644
--- a/tests/auto/qml/qqmllanguage/testtypes.h
+++ b/tests/auto/qml/qqmllanguage/testtypes.h
@@ -43,7 +43,6 @@
#include <QtQml/qqmlpropertyvaluesource.h>
#include <QtQml/qqmlscriptstring.h>
#include <QtQml/qqmlproperty.h>
-#include <private/qqmlcompiler_p.h>
#include <private/qqmlcustomparser_p.h>
QVariant myCustomVariantTypeConverter(const QString &data);
@@ -757,14 +756,14 @@ class MyCustomParserTypeParser : public QQmlCustomParser
{
public:
virtual void verifyBindings(const QV4::CompiledData::Unit *, const QList<const QV4::CompiledData::Binding *> &) {}
- virtual void applyBindings(QObject *, QQmlCompiledData *, const QList<const QV4::CompiledData::Binding *> &) {}
+ virtual void applyBindings(QObject *, QV4::CompiledData::CompilationUnit *, const QList<const QV4::CompiledData::Binding *> &) {}
};
class EnumSupportingCustomParser : public QQmlCustomParser
{
public:
virtual void verifyBindings(const QV4::CompiledData::Unit *, const QList<const QV4::CompiledData::Binding *> &);
- virtual void applyBindings(QObject *, QQmlCompiledData *, const QList<const QV4::CompiledData::Binding *> &) {}
+ virtual void applyBindings(QObject *, QV4::CompiledData::CompilationUnit *, const QList<const QV4::CompiledData::Binding *> &) {}
};
class MyParserStatus : public QObject, public QQmlParserStatus
@@ -1114,6 +1113,58 @@ public:
static QObject *qmlAttachedProperties(QObject *parent) { return new QObject(parent); }
};
+class MyArrayBufferTestClass : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QByteArray byteArrayProperty READ byteArrayProperty WRITE setByteArrayProperty NOTIFY byteArrayPropertyChanged)
+
+signals:
+ void byteArrayPropertyChanged();
+ void byteArraySignal(QByteArray arg);
+
+public:
+ QByteArray byteArrayPropertyValue;
+ QByteArray byteArrayProperty() const {
+ return byteArrayPropertyValue;
+ }
+ void setByteArrayProperty(const QByteArray &v) {
+ byteArrayPropertyValue = v;
+ emit byteArrayPropertyChanged();
+ }
+ Q_INVOKABLE void emitByteArraySignal(char begin, char num) {
+ byteArraySignal(byteArrayMethod_CountUp(begin, num));
+ }
+ Q_INVOKABLE int byteArrayMethod_Sum(QByteArray arg) {
+ int sum = 0;
+ for (int i = 0; i < arg.size(); ++i) {
+ sum += arg[i];
+ }
+ return sum;
+ }
+ Q_INVOKABLE QByteArray byteArrayMethod_CountUp(char begin, int num) {
+ QByteArray ret;
+ for (int i = 0; i < num; ++i) {
+ ret.push_back(begin++);
+ }
+ return ret;
+ }
+ Q_INVOKABLE bool byteArrayMethod_Overloaded(QByteArray) {
+ return true;
+ }
+ Q_INVOKABLE bool byteArrayMethod_Overloaded(int) {
+ return false;
+ }
+ Q_INVOKABLE bool byteArrayMethod_Overloaded(QString) {
+ return false;
+ }
+ Q_INVOKABLE bool byteArrayMethod_Overloaded(QJSValue) {
+ return false;
+ }
+ Q_INVOKABLE bool byteArrayMethod_Overloaded(QVariant) {
+ return false;
+ }
+};
+
Q_DECLARE_METATYPE(MyEnum2Class::EnumB)
Q_DECLARE_METATYPE(MyEnum1Class::EnumA)
Q_DECLARE_METATYPE(Qt::TextFormat)
@@ -1142,7 +1193,7 @@ public:
void setTarget(QObject *newTarget) { m_target = newTarget; }
QPointer<QObject> m_target;
- QQmlRefPointer<QQmlCompiledData> cdata;
+ QQmlRefPointer<QV4::CompiledData::CompilationUnit> compilationUnit;
QList<const QV4::CompiledData::Binding*> bindings;
QByteArray m_bindingData;
};
@@ -1150,7 +1201,7 @@ public:
class CustomBindingParser : public QQmlCustomParser
{
virtual void verifyBindings(const QV4::CompiledData::Unit *, const QList<const QV4::CompiledData::Binding *> &) {}
- virtual void applyBindings(QObject *, QQmlCompiledData *, const QList<const QV4::CompiledData::Binding *> &);
+ virtual void applyBindings(QObject *, QV4::CompiledData::CompilationUnit *, const QList<const QV4::CompiledData::Binding *> &);
};
class SimpleObjectWithCustomParser : public QObject
@@ -1196,7 +1247,7 @@ private:
class SimpleObjectCustomParser : public QQmlCustomParser
{
virtual void verifyBindings(const QV4::CompiledData::Unit *, const QList<const QV4::CompiledData::Binding *> &) {}
- virtual void applyBindings(QObject *, QQmlCompiledData *, const QList<const QV4::CompiledData::Binding *> &);
+ virtual void applyBindings(QObject *, QV4::CompiledData::CompilationUnit *, const QList<const QV4::CompiledData::Binding *> &);
};
class RootObjectInCreationTester : public QObject
diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
index 4e4b939e8b..1a035be5e0 100644
--- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
+++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
@@ -108,6 +108,7 @@ private slots:
void bindTypeToJSValue();
void customParserTypes();
void rootAsQmlComponent();
+ void rootItemIsComponent();
void inlineQmlComponents();
void idProperty();
void autoNotifyConnection();
@@ -188,6 +189,8 @@ private slots:
void subclassedUncreateableRevision_data();
void subclassedUncreateableRevision();
+ void uncreatableTypesAsProperties();
+
void propertyInit();
void remoteLoadCrash();
void signalWithDefaultArg();
@@ -246,10 +249,11 @@ private slots:
void earlyIdObjectAccess();
- void dataAlignment();
-
void deleteSingletons();
+ void arrayBuffer_data();
+ void arrayBuffer();
+
private:
QQmlEngine engine;
QStringList defaultImportPathList;
@@ -490,6 +494,7 @@ void tst_qqmllanguage::errors_data()
QTest::newRow("invalidAlias.8") << "invalidAlias.8.qml" << "invalidAlias.8.errors.txt" << false;
QTest::newRow("invalidAlias.9") << "invalidAlias.9.qml" << "invalidAlias.9.errors.txt" << false;
QTest::newRow("invalidAlias.10") << "invalidAlias.10.qml" << "invalidAlias.10.errors.txt" << false;
+ QTest::newRow("invalidAlias.11") << "invalidAlias.11.qml" << "invalidAlias.11.errors.txt" << false;
QTest::newRow("invalidAttachedProperty.1") << "invalidAttachedProperty.1.qml" << "invalidAttachedProperty.1.errors.txt" << false;
QTest::newRow("invalidAttachedProperty.2") << "invalidAttachedProperty.2.qml" << "invalidAttachedProperty.2.errors.txt" << false;
@@ -1193,6 +1198,19 @@ void tst_qqmllanguage::rootAsQmlComponent()
QCOMPARE(object->getChildren()->count(), 2);
}
+void tst_qqmllanguage::rootItemIsComponent()
+{
+ QQmlComponent component(&engine, testFileUrl("rootItemIsComponent.qml"));
+ VERIFY_ERRORS(0);
+ QScopedPointer<QObject> root(component.create());
+ QVERIFY(qobject_cast<QQmlComponent*>(root.data()));
+ QScopedPointer<QObject> other(qobject_cast<QQmlComponent*>(root.data())->create());
+ QVERIFY(!other.isNull());
+ QQmlContext *context = qmlContext(other.data());
+ QVERIFY(context);
+ QCOMPARE(context->nameForObject(other.data()), QStringLiteral("blah"));
+}
+
// Tests that components can be specified inline
void tst_qqmllanguage::inlineQmlComponents()
{
@@ -1787,6 +1805,48 @@ void tst_qqmllanguage::aliasProperties()
delete object;
}
+
+ // Nested aliases with a qml file
+ {
+ QQmlComponent component(&engine, testFileUrl("alias.12.qml"));
+ VERIFY_ERRORS(0);
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+
+ QPointer<QObject> subObject = qvariant_cast<QObject*>(object->property("referencingSubObject"));
+ QVERIFY(!subObject.isNull());
+
+ QVERIFY(subObject->property("success").toBool());
+ }
+
+ // Nested aliases with a qml file with reverse ordering
+ {
+ // This is known to fail at the moment.
+ QQmlComponent component(&engine, testFileUrl("alias.13.qml"));
+ VERIFY_ERRORS(0);
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+
+ QPointer<QObject> subObject = qvariant_cast<QObject*>(object->property("referencingSubObject"));
+ QVERIFY(!subObject.isNull());
+
+ QVERIFY(subObject->property("success").toBool());
+ }
+
+ // "Nested" aliases within an object that require iterative resolution
+ {
+ // This is known to fail at the moment.
+ QQmlComponent component(&engine, testFileUrl("alias.14.qml"));
+ VERIFY_ERRORS(0);
+
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+
+ QPointer<QObject> subObject = qvariant_cast<QObject*>(object->property("referencingSubObject"));
+ QVERIFY(!subObject.isNull());
+
+ QVERIFY(subObject->property("success").toBool());
+ }
}
// QTBUG-13374 Test that alias properties and signals can coexist
@@ -2058,7 +2118,7 @@ void tst_qqmllanguage::scriptStringWithoutSourceCode()
QQmlTypeData *td = eng->typeLoader.getType(url);
Q_ASSERT(td);
- QV4::CompiledData::Unit *qmlUnit = td->compiledData()->compilationUnit->data;
+ const QV4::CompiledData::Unit *qmlUnit = td->compilationUnit()->data;
Q_ASSERT(qmlUnit);
const QV4::CompiledData::Object *rootObject = qmlUnit->objectAt(qmlUnit->indexOfRootObject);
QCOMPARE(qmlUnit->stringAt(rootObject->inheritedTypeNameIndex), QString("MyTypeObject"));
@@ -2882,7 +2942,7 @@ void tst_qqmllanguage::importIncorrectCase()
QCOMPARE(errors.count(), 1);
const QString expectedError = isCaseSensitiveFileSystem(dataDirectory()) ?
- QStringLiteral("File not found") :
+ QStringLiteral("No such file or directory") :
QStringLiteral("File name case mismatch");
QCOMPARE(errors.at(0).description(), expectedError);
@@ -3156,6 +3216,14 @@ void tst_qqmllanguage::subclassedUncreateableRevision()
delete obj;
}
+void tst_qqmllanguage::uncreatableTypesAsProperties()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("uncreatableTypeAsProperty.qml"));
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+}
+
void tst_qqmllanguage::initTestCase()
{
QQmlDataTest::initTestCase();
@@ -3861,12 +3929,11 @@ void tst_qqmllanguage::compositeSingletonInstantiateError()
VERIFY_ERRORS("singletonTest9.error.txt");
}
-// Having a composite singleton type as dynamic property type fails
-// (like C++ singleton)
+// Having a composite singleton type as dynamic property type is allowed
void tst_qqmllanguage::compositeSingletonDynamicPropertyError()
{
QQmlComponent component(&engine, testFile("singletonTest10.qml"));
- VERIFY_ERRORS("singletonTest10.error.txt");
+ VERIFY_ERRORS(0);
}
// Having a composite singleton type as dynamic signal parameter succeeds
@@ -4120,14 +4187,6 @@ void tst_qqmllanguage::earlyIdObjectAccess()
QVERIFY(o->property("success").toBool());
}
-void tst_qqmllanguage::dataAlignment()
-{
- QVERIFY(sizeof(QQmlVMEMetaData) % sizeof(int) == 0);
- QVERIFY(sizeof(QQmlVMEMetaData::AliasData) % sizeof(int) == 0);
- QVERIFY(sizeof(QQmlVMEMetaData::PropertyData) % sizeof(int) == 0);
- QVERIFY(sizeof(QQmlVMEMetaData::MethodData) % sizeof(int) == 0);
-}
-
void tst_qqmllanguage::deleteSingletons()
{
QPointer<QObject> singleton;
@@ -4146,6 +4205,27 @@ void tst_qqmllanguage::deleteSingletons()
QVERIFY(singleton.data() == 0);
}
+void tst_qqmllanguage::arrayBuffer_data()
+{
+ QTest::addColumn<QString>("file");
+ QTest::newRow("arraybuffer_property_get") << "arraybuffer_property_get.qml";
+ QTest::newRow("arraybuffer_property_set") << "arraybuffer_property_set.qml";
+ QTest::newRow("arraybuffer_signal_arg") << "arraybuffer_signal_arg.qml";
+ QTest::newRow("arraybuffer_method_arg") << "arraybuffer_method_arg.qml";
+ QTest::newRow("arraybuffer_method_return") << "arraybuffer_method_return.qml";
+ QTest::newRow("arraybuffer_method_overload") << "arraybuffer_method_overload.qml";
+}
+
+void tst_qqmllanguage::arrayBuffer()
+{
+ QFETCH(QString, file);
+ QQmlComponent component(&engine, testFile(file));
+ VERIFY_ERRORS(0);
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+ QCOMPARE(object->property("ok").toBool(), true);
+}
+
QTEST_MAIN(tst_qqmllanguage)
#include "tst_qqmllanguage.moc"
diff --git a/tests/auto/qml/qqmlmoduleplugin/plugin.2.1/childplugin/childplugin.cpp b/tests/auto/qml/qqmlmoduleplugin/plugin.2.1/childplugin/childplugin.cpp
index 53247e7912..515d56a3c4 100644
--- a/tests/auto/qml/qqmlmoduleplugin/plugin.2.1/childplugin/childplugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/plugin.2.1/childplugin/childplugin.cpp
@@ -53,7 +53,7 @@ private:
class MyChildPlugin : public QQmlExtensionPlugin
{
Q_OBJECT
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
+ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
public:
MyChildPlugin()
diff --git a/tests/auto/qml/qqmlmoduleplugin/plugin.2/childplugin/childplugin.cpp b/tests/auto/qml/qqmlmoduleplugin/plugin.2/childplugin/childplugin.cpp
index a59347d3a9..56545cfa3c 100644
--- a/tests/auto/qml/qqmlmoduleplugin/plugin.2/childplugin/childplugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/plugin.2/childplugin/childplugin.cpp
@@ -53,7 +53,7 @@ private:
class MyChildPlugin : public QQmlExtensionPlugin
{
Q_OBJECT
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
+ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
public:
MyChildPlugin()
diff --git a/tests/auto/qml/qqmlmoduleplugin/plugin/childplugin/childplugin.cpp b/tests/auto/qml/qqmlmoduleplugin/plugin/childplugin/childplugin.cpp
index 5f4f96f7e4..28490d3d98 100644
--- a/tests/auto/qml/qqmlmoduleplugin/plugin/childplugin/childplugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/plugin/childplugin/childplugin.cpp
@@ -52,7 +52,7 @@ private:
class MyChildPlugin : public QQmlExtensionPlugin
{
Q_OBJECT
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
+ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
public:
MyChildPlugin()
diff --git a/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp b/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp
index e140747881..63d7f1c12b 100644
--- a/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp
+++ b/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp
@@ -157,7 +157,7 @@ void tst_qqmlproperty::qmlmetaproperty()
QObject *obj = new QObject;
- QQmlAbstractBinding::Ptr binding(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext()));
+ QQmlAbstractBinding::Ptr binding(QQmlBinding::create(nullptr, QLatin1String("null"), 0, engine.rootContext()));
QVERIFY(binding);
QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(obj, QObjectPrivate::get(obj)->signalIndex("destroyed()"), QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), QString(), -1, -1);
QQmlJavaScriptExpression::DeleteWatcher sigExprWatcher(sigExpr);
@@ -406,7 +406,7 @@ void tst_qqmlproperty::qmlmetaproperty_object()
{
QQmlProperty prop(&object);
- QQmlAbstractBinding::Ptr binding(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext()));
+ QQmlAbstractBinding::Ptr binding(QQmlBinding::create(&QQmlPropertyPrivate::get(prop)->core, QLatin1String("null"), 0, engine.rootContext()));
QVERIFY(binding);
QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(&object, QObjectPrivate::get(&object)->signalIndex("destroyed()"), QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), QString(), -1, -1);
QQmlJavaScriptExpression::DeleteWatcher sigExprWatcher(sigExpr);
@@ -453,7 +453,7 @@ void tst_qqmlproperty::qmlmetaproperty_object()
{
QQmlProperty prop(&dobject);
- QQmlAbstractBinding::Ptr binding(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext()));
+ QQmlAbstractBinding::Ptr binding(QQmlBinding::create(&QQmlPropertyPrivate::get(prop)->core, QLatin1String("null"), 0, engine.rootContext()));
static_cast<QQmlBinding *>(binding.data())->setTarget(prop);
QVERIFY(binding);
QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(&dobject, QObjectPrivate::get(&dobject)->signalIndex("clicked()"), QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), QString(), -1, -1);
@@ -509,7 +509,7 @@ void tst_qqmlproperty::qmlmetaproperty_object_string()
{
QQmlProperty prop(&object, QString("defaultProperty"));
- QQmlAbstractBinding::Ptr binding(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext()));
+ QQmlAbstractBinding::Ptr binding(QQmlBinding::create(&QQmlPropertyPrivate::get(prop)->core, QLatin1String("null"), 0, engine.rootContext()));
QVERIFY(binding);
QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(&object, QObjectPrivate::get(&object)->signalIndex("destroyed()"), QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), QString(), -1, -1);
QQmlJavaScriptExpression::DeleteWatcher sigExprWatcher(sigExpr);
@@ -556,7 +556,7 @@ void tst_qqmlproperty::qmlmetaproperty_object_string()
{
QQmlProperty prop(&dobject, QString("defaultProperty"));
- QQmlAbstractBinding::Ptr binding(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext()));
+ QQmlAbstractBinding::Ptr binding(QQmlBinding::create(&QQmlPropertyPrivate::get(prop)->core, QLatin1String("null"), 0, engine.rootContext()));
static_cast<QQmlBinding *>(binding.data())->setTarget(prop);
QVERIFY(binding);
QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(&dobject, QObjectPrivate::get(&dobject)->signalIndex("clicked()"), QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), QString(), -1, -1);
@@ -606,7 +606,7 @@ void tst_qqmlproperty::qmlmetaproperty_object_string()
{
QQmlProperty prop(&dobject, QString("onClicked"));
- QQmlAbstractBinding::Ptr binding(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext()));
+ QQmlAbstractBinding::Ptr binding(QQmlBinding::create(&QQmlPropertyPrivate::get(prop)->core, QLatin1String("null"), 0, engine.rootContext()));
static_cast<QQmlBinding *>(binding.data())->setTarget(prop);
QVERIFY(binding);
QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(&dobject, QQmlPropertyPrivate::get(prop)->signalIndex(), QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), QString(), -1, -1);
@@ -655,7 +655,7 @@ void tst_qqmlproperty::qmlmetaproperty_object_string()
{
QQmlProperty prop(&dobject, QString("onPropertyWithNotifyChanged"));
- QQmlAbstractBinding::Ptr binding(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext()));
+ QQmlAbstractBinding::Ptr binding(QQmlBinding::create(&QQmlPropertyPrivate::get(prop)->core, QLatin1String("null"), 0, engine.rootContext()));
static_cast<QQmlBinding *>(binding.data())->setTarget(prop);
QVERIFY(binding);
QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(&dobject, QQmlPropertyPrivate::get(prop)->signalIndex(), QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), QString(), -1, -1);
@@ -710,7 +710,7 @@ void tst_qqmlproperty::qmlmetaproperty_object_context()
{
QQmlProperty prop(&object, engine.rootContext());
- QQmlAbstractBinding::Ptr binding(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext()));
+ QQmlAbstractBinding::Ptr binding(QQmlBinding::create(&QQmlPropertyPrivate::get(prop)->core, QLatin1String("null"), 0, engine.rootContext()));
QVERIFY(binding);
QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(&object, QObjectPrivate::get(&object)->signalIndex("destroyed()"), QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), QString(), -1, -1);
QQmlJavaScriptExpression::DeleteWatcher sigExprWatcher(sigExpr);
@@ -757,7 +757,7 @@ void tst_qqmlproperty::qmlmetaproperty_object_context()
{
QQmlProperty prop(&dobject, engine.rootContext());
- QQmlAbstractBinding::Ptr binding(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext()));
+ QQmlAbstractBinding::Ptr binding(QQmlBinding::create(&QQmlPropertyPrivate::get(prop)->core, QLatin1String("null"), 0, engine.rootContext()));
static_cast<QQmlBinding *>(binding.data())->setTarget(prop);
QVERIFY(binding);
QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(&dobject, QObjectPrivate::get(&dobject)->signalIndex("clicked()"), QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), QString(), -1, -1);
@@ -813,7 +813,7 @@ void tst_qqmlproperty::qmlmetaproperty_object_string_context()
{
QQmlProperty prop(&object, QString("defaultProperty"), engine.rootContext());
- QQmlAbstractBinding::Ptr binding(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext()));
+ QQmlAbstractBinding::Ptr binding(QQmlBinding::create(&QQmlPropertyPrivate::get(prop)->core, QLatin1String("null"), 0, engine.rootContext()));
QVERIFY(binding);
QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(&object, QObjectPrivate::get(&object)->signalIndex("destroyed()"), QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), QString(), -1, -1);
QQmlJavaScriptExpression::DeleteWatcher sigExprWatcher(sigExpr);
@@ -860,7 +860,7 @@ void tst_qqmlproperty::qmlmetaproperty_object_string_context()
{
QQmlProperty prop(&dobject, QString("defaultProperty"), engine.rootContext());
- QQmlAbstractBinding::Ptr binding(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext()));
+ QQmlAbstractBinding::Ptr binding(QQmlBinding::create(&QQmlPropertyPrivate::get(prop)->core, QLatin1String("null"), 0, engine.rootContext()));
static_cast<QQmlBinding *>(binding.data())->setTarget(prop);
QVERIFY(binding);
QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(&dobject, QObjectPrivate::get(&dobject)->signalIndex("clicked()"), QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), QString(), -1, -1);
@@ -910,7 +910,7 @@ void tst_qqmlproperty::qmlmetaproperty_object_string_context()
{
QQmlProperty prop(&dobject, QString("onClicked"), engine.rootContext());
- QQmlAbstractBinding::Ptr binding(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext()));
+ QQmlAbstractBinding::Ptr binding(QQmlBinding::create(&QQmlPropertyPrivate::get(prop)->core, QLatin1String("null"), 0, engine.rootContext()));
static_cast<QQmlBinding *>(binding.data())->setTarget(prop);
QVERIFY(binding);
QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(&dobject, QQmlPropertyPrivate::get(prop)->signalIndex(), QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), QString(), -1, -1);
@@ -959,7 +959,7 @@ void tst_qqmlproperty::qmlmetaproperty_object_string_context()
{
QQmlProperty prop(&dobject, QString("onPropertyWithNotifyChanged"), engine.rootContext());
- QQmlAbstractBinding::Ptr binding(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext()));
+ QQmlAbstractBinding::Ptr binding(QQmlBinding::create(&QQmlPropertyPrivate::get(prop)->core, QLatin1String("null"), 0, engine.rootContext()));
static_cast<QQmlBinding *>(binding.data())->setTarget(prop);
QVERIFY(binding);
QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(&dobject, QQmlPropertyPrivate::get(prop)->signalIndex(), QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), QString(), -1, -1);
diff --git a/tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp b/tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp
index 5f15afff85..2916d8455c 100644
--- a/tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp
+++ b/tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp
@@ -30,6 +30,8 @@
#include <private/qqmlpropertycache_p.h>
#include <QtQml/qqmlengine.h>
#include <private/qv8engine_p.h>
+#include <private/qmetaobjectbuilder_p.h>
+#include <QCryptographicHash>
#include "../../shared/util.h"
class tst_qqmlpropertycache : public QObject
@@ -45,6 +47,9 @@ private slots:
void methodsDerived();
void signalHandlers();
void signalHandlersDerived();
+ void metaObjectSize_data();
+ void metaObjectSize();
+ void metaObjectChecksum();
private:
QQmlEngine engine;
@@ -105,16 +110,16 @@ void tst_qqmlpropertycache::properties()
QQmlRefPointer<QQmlPropertyCache> cache(new QQmlPropertyCache(v4, metaObject));
QQmlPropertyData *data;
- QVERIFY(data = cacheProperty(cache, "propertyA"));
+ QVERIFY((data = cacheProperty(cache, "propertyA")));
QCOMPARE(data->coreIndex, metaObject->indexOfProperty("propertyA"));
- QVERIFY(data = cacheProperty(cache, "propertyB"));
+ QVERIFY((data = cacheProperty(cache, "propertyB")));
QCOMPARE(data->coreIndex, metaObject->indexOfProperty("propertyB"));
- QVERIFY(data = cacheProperty(cache, "propertyC"));
+ QVERIFY((data = cacheProperty(cache, "propertyC")));
QCOMPARE(data->coreIndex, metaObject->indexOfProperty("propertyC"));
- QVERIFY(data = cacheProperty(cache, "propertyD"));
+ QVERIFY((data = cacheProperty(cache, "propertyD")));
QCOMPARE(data->coreIndex, metaObject->indexOfProperty("propertyD"));
}
@@ -129,16 +134,16 @@ void tst_qqmlpropertycache::propertiesDerived()
QQmlRefPointer<QQmlPropertyCache> cache(parentCache->copyAndAppend(object.metaObject()));
QQmlPropertyData *data;
- QVERIFY(data = cacheProperty(cache, "propertyA"));
+ QVERIFY((data = cacheProperty(cache, "propertyA")));
QCOMPARE(data->coreIndex, metaObject->indexOfProperty("propertyA"));
- QVERIFY(data = cacheProperty(cache, "propertyB"));
+ QVERIFY((data = cacheProperty(cache, "propertyB")));
QCOMPARE(data->coreIndex, metaObject->indexOfProperty("propertyB"));
- QVERIFY(data = cacheProperty(cache, "propertyC"));
+ QVERIFY((data = cacheProperty(cache, "propertyC")));
QCOMPARE(data->coreIndex, metaObject->indexOfProperty("propertyC"));
- QVERIFY(data = cacheProperty(cache, "propertyD"));
+ QVERIFY((data = cacheProperty(cache, "propertyD")));
QCOMPARE(data->coreIndex, metaObject->indexOfProperty("propertyD"));
}
@@ -152,28 +157,28 @@ void tst_qqmlpropertycache::methods()
QQmlRefPointer<QQmlPropertyCache> cache(new QQmlPropertyCache(v4, metaObject));
QQmlPropertyData *data;
- QVERIFY(data = cacheProperty(cache, "slotA"));
+ QVERIFY((data = cacheProperty(cache, "slotA")));
QCOMPARE(data->coreIndex, metaObject->indexOfMethod("slotA()"));
- QVERIFY(data = cacheProperty(cache, "slotB"));
+ QVERIFY((data = cacheProperty(cache, "slotB")));
QCOMPARE(data->coreIndex, metaObject->indexOfMethod("slotB()"));
- QVERIFY(data = cacheProperty(cache, "signalA"));
+ QVERIFY((data = cacheProperty(cache, "signalA")));
QCOMPARE(data->coreIndex, metaObject->indexOfMethod("signalA()"));
- QVERIFY(data = cacheProperty(cache, "signalB"));
+ QVERIFY((data = cacheProperty(cache, "signalB")));
QCOMPARE(data->coreIndex, metaObject->indexOfMethod("signalB()"));
- QVERIFY(data = cacheProperty(cache, "propertyAChanged"));
+ QVERIFY((data = cacheProperty(cache, "propertyAChanged")));
QCOMPARE(data->coreIndex, metaObject->indexOfMethod("propertyAChanged()"));
- QVERIFY(data = cacheProperty(cache, "propertyBChanged"));
+ QVERIFY((data = cacheProperty(cache, "propertyBChanged")));
QCOMPARE(data->coreIndex, metaObject->indexOfMethod("propertyBChanged()"));
- QVERIFY(data = cacheProperty(cache, "propertyCChanged"));
+ QVERIFY((data = cacheProperty(cache, "propertyCChanged")));
QCOMPARE(data->coreIndex, metaObject->indexOfMethod("propertyCChanged()"));
- QVERIFY(data = cacheProperty(cache, "propertyDChanged"));
+ QVERIFY((data = cacheProperty(cache, "propertyDChanged")));
QCOMPARE(data->coreIndex, metaObject->indexOfMethod("propertyDChanged()"));
}
@@ -188,28 +193,28 @@ void tst_qqmlpropertycache::methodsDerived()
QQmlRefPointer<QQmlPropertyCache> cache(parentCache->copyAndAppend(object.metaObject()));
QQmlPropertyData *data;
- QVERIFY(data = cacheProperty(cache, "slotA"));
+ QVERIFY((data = cacheProperty(cache, "slotA")));
QCOMPARE(data->coreIndex, metaObject->indexOfMethod("slotA()"));
- QVERIFY(data = cacheProperty(cache, "slotB"));
+ QVERIFY((data = cacheProperty(cache, "slotB")));
QCOMPARE(data->coreIndex, metaObject->indexOfMethod("slotB()"));
- QVERIFY(data = cacheProperty(cache, "signalA"));
+ QVERIFY((data = cacheProperty(cache, "signalA")));
QCOMPARE(data->coreIndex, metaObject->indexOfMethod("signalA()"));
- QVERIFY(data = cacheProperty(cache, "signalB"));
+ QVERIFY((data = cacheProperty(cache, "signalB")));
QCOMPARE(data->coreIndex, metaObject->indexOfMethod("signalB()"));
- QVERIFY(data = cacheProperty(cache, "propertyAChanged"));
+ QVERIFY((data = cacheProperty(cache, "propertyAChanged")));
QCOMPARE(data->coreIndex, metaObject->indexOfMethod("propertyAChanged()"));
- QVERIFY(data = cacheProperty(cache, "propertyBChanged"));
+ QVERIFY((data = cacheProperty(cache, "propertyBChanged")));
QCOMPARE(data->coreIndex, metaObject->indexOfMethod("propertyBChanged()"));
- QVERIFY(data = cacheProperty(cache, "propertyCChanged"));
+ QVERIFY((data = cacheProperty(cache, "propertyCChanged")));
QCOMPARE(data->coreIndex, metaObject->indexOfMethod("propertyCChanged()"));
- QVERIFY(data = cacheProperty(cache, "propertyDChanged"));
+ QVERIFY((data = cacheProperty(cache, "propertyDChanged")));
QCOMPARE(data->coreIndex, metaObject->indexOfMethod("propertyDChanged()"));
}
@@ -223,22 +228,22 @@ void tst_qqmlpropertycache::signalHandlers()
QQmlRefPointer<QQmlPropertyCache> cache(new QQmlPropertyCache(v4, metaObject));
QQmlPropertyData *data;
- QVERIFY(data = cacheProperty(cache, "onSignalA"));
+ QVERIFY((data = cacheProperty(cache, "onSignalA")));
QCOMPARE(data->coreIndex, metaObject->indexOfMethod("signalA()"));
- QVERIFY(data = cacheProperty(cache, "onSignalB"));
+ QVERIFY((data = cacheProperty(cache, "onSignalB")));
QCOMPARE(data->coreIndex, metaObject->indexOfMethod("signalB()"));
- QVERIFY(data = cacheProperty(cache, "onPropertyAChanged"));
+ QVERIFY((data = cacheProperty(cache, "onPropertyAChanged")));
QCOMPARE(data->coreIndex, metaObject->indexOfMethod("propertyAChanged()"));
- QVERIFY(data = cacheProperty(cache, "onPropertyBChanged"));
+ QVERIFY((data = cacheProperty(cache, "onPropertyBChanged")));
QCOMPARE(data->coreIndex, metaObject->indexOfMethod("propertyBChanged()"));
- QVERIFY(data = cacheProperty(cache, "onPropertyCChanged"));
+ QVERIFY((data = cacheProperty(cache, "onPropertyCChanged")));
QCOMPARE(data->coreIndex, metaObject->indexOfMethod("propertyCChanged()"));
- QVERIFY(data = cacheProperty(cache, "onPropertyDChanged"));
+ QVERIFY((data = cacheProperty(cache, "onPropertyDChanged")));
QCOMPARE(data->coreIndex, metaObject->indexOfMethod("propertyDChanged()"));
}
@@ -253,25 +258,145 @@ void tst_qqmlpropertycache::signalHandlersDerived()
QQmlRefPointer<QQmlPropertyCache> cache(parentCache->copyAndAppend(object.metaObject()));
QQmlPropertyData *data;
- QVERIFY(data = cacheProperty(cache, "onSignalA"));
+ QVERIFY((data = cacheProperty(cache, "onSignalA")));
QCOMPARE(data->coreIndex, metaObject->indexOfMethod("signalA()"));
- QVERIFY(data = cacheProperty(cache, "onSignalB"));
+ QVERIFY((data = cacheProperty(cache, "onSignalB")));
QCOMPARE(data->coreIndex, metaObject->indexOfMethod("signalB()"));
- QVERIFY(data = cacheProperty(cache, "onPropertyAChanged"));
+ QVERIFY((data = cacheProperty(cache, "onPropertyAChanged")));
QCOMPARE(data->coreIndex, metaObject->indexOfMethod("propertyAChanged()"));
- QVERIFY(data = cacheProperty(cache, "onPropertyBChanged"));
+ QVERIFY((data = cacheProperty(cache, "onPropertyBChanged")));
QCOMPARE(data->coreIndex, metaObject->indexOfMethod("propertyBChanged()"));
- QVERIFY(data = cacheProperty(cache, "onPropertyCChanged"));
+ QVERIFY((data = cacheProperty(cache, "onPropertyCChanged")));
QCOMPARE(data->coreIndex, metaObject->indexOfMethod("propertyCChanged()"));
- QVERIFY(data = cacheProperty(cache, "onPropertyDChanged"));
+ QVERIFY((data = cacheProperty(cache, "onPropertyDChanged")));
QCOMPARE(data->coreIndex, metaObject->indexOfMethod("propertyDChanged()"));
}
-QTEST_MAIN(tst_qqmlpropertycache)
+class TestClass : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int prop READ prop WRITE setProp NOTIFY propChanged)
+ int m_prop;
+
+public:
+ enum MyEnum {
+ First, Second
+ };
+ Q_ENUM(MyEnum)
+
+ Q_CLASSINFO("Foo", "Bar")
+
+ TestClass() {}
+
+ int prop() const
+ {
+ return m_prop;
+ }
+
+public slots:
+ void setProp(int prop)
+ {
+ if (m_prop == prop)
+ return;
+
+ m_prop = prop;
+ emit propChanged(prop);
+ }
+signals:
+ void propChanged(int prop);
+};
+
+class TestClassWithParameters : public QObject
+{
+ Q_OBJECT
+
+public:
+ Q_INVOKABLE void slotWithArguments(int firstArg) {
+ Q_UNUSED(firstArg);
+ }
+};
+
+class TestClassWithClassInfo : public QObject
+{
+ Q_OBJECT
+ Q_CLASSINFO("Key", "Value")
+};
#include "tst_qqmlpropertycache.moc"
+
+#define ARRAY_SIZE(arr) \
+ int(sizeof(arr) / sizeof(arr[0]))
+
+#define TEST_CLASS(Class) \
+ QTest::newRow(#Class) << &Class::staticMetaObject << ARRAY_SIZE(qt_meta_data_##Class) << ARRAY_SIZE(qt_meta_stringdata_##Class.data)
+
+Q_DECLARE_METATYPE(const QMetaObject*);
+
+void tst_qqmlpropertycache::metaObjectSize_data()
+{
+ QTest::addColumn<const QMetaObject*>("metaObject");
+ QTest::addColumn<int>("expectedFieldCount");
+ QTest::addColumn<int>("expectedStringCount");
+
+ TEST_CLASS(TestClass);
+ TEST_CLASS(TestClassWithParameters);
+ TEST_CLASS(TestClassWithClassInfo);
+}
+
+void tst_qqmlpropertycache::metaObjectSize()
+{
+ QFETCH(const QMetaObject *, metaObject);
+ QFETCH(int, expectedFieldCount);
+ QFETCH(int, expectedStringCount);
+
+ int size = 0;
+ int stringDataSize = 0;
+ bool valid = QQmlPropertyCache::determineMetaObjectSizes(*metaObject, &size, &stringDataSize);
+ QVERIFY(valid);
+
+ QCOMPARE(size, expectedFieldCount - 1); // Remove trailing zero field until fixed in moc.
+ QCOMPARE(stringDataSize, expectedStringCount);
+}
+
+void tst_qqmlpropertycache::metaObjectChecksum()
+{
+ QMetaObjectBuilder builder;
+ builder.setClassName("Test");
+ builder.addClassInfo("foo", "bar");
+
+ QCryptographicHash hash(QCryptographicHash::Md5);
+
+ QScopedPointer<QMetaObject, QScopedPointerPodDeleter> mo(builder.toMetaObject());
+ QVERIFY(!mo.isNull());
+
+ QVERIFY(QQmlPropertyCache::addToHash(hash, *mo.data()));
+ QByteArray initialHash = hash.result();
+ QVERIFY(!initialHash.isEmpty());
+ hash.reset();
+
+ {
+ QVERIFY(QQmlPropertyCache::addToHash(hash, *mo.data()));
+ QByteArray nextHash = hash.result();
+ QVERIFY(!nextHash.isEmpty());
+ hash.reset();
+ QCOMPARE(initialHash, nextHash);
+ }
+
+ builder.addProperty("testProperty", "int", -1);
+
+ mo.reset(builder.toMetaObject());
+ {
+ QVERIFY(QQmlPropertyCache::addToHash(hash, *mo.data()));
+ QByteArray nextHash = hash.result();
+ QVERIFY(!nextHash.isEmpty());
+ hash.reset();
+ QVERIFY(initialHash != nextHash);
+ }
+}
+
+QTEST_MAIN(tst_qqmlpropertycache)
diff --git a/tests/auto/qml/qqmlqt/data/LaterComponent.qml b/tests/auto/qml/qqmlqt/data/LaterComponent.qml
new file mode 100644
index 0000000000..7dbd81d93d
--- /dev/null
+++ b/tests/auto/qml/qqmlqt/data/LaterComponent.qml
@@ -0,0 +1,14 @@
+import QtQuick 2.0
+import LaterImports 1.0
+
+TestElement {
+ id: deleteme
+ function testFn() {
+ gc(); // at this point, obj is deleted.
+ dangerousFunction(); // calling this function will throw an exeption
+ // because this object has been deleted and its context is not available
+
+ // which means that we shouldn't get to this line.
+ row.test10_1 = 1;
+ }
+}
diff --git a/tests/auto/qml/qqmlqt/data/LaterComponent2.qml b/tests/auto/qml/qqmlqt/data/LaterComponent2.qml
new file mode 100644
index 0000000000..56bcc0235b
--- /dev/null
+++ b/tests/auto/qml/qqmlqt/data/LaterComponent2.qml
@@ -0,0 +1,13 @@
+import QtQuick 2.0
+
+Item {
+ id: deleteme2
+ function testFn() {
+ // this function shouldn't be called,
+ // since the object will have been deleted.
+ var crashy = Qt.createQmlObject("import QtQuick 2.0; Item { }", deleteme2) // invalid calling context if invoked after gc
+ row.test11_1 = 2;
+ }
+
+ Component.onDestruction: row.test11_1 = 1; // success == the object was deleted, but testFn wasn't called.
+}
diff --git a/tests/auto/qml/qqmlqt/data/LaterComponent3.qml b/tests/auto/qml/qqmlqt/data/LaterComponent3.qml
new file mode 100644
index 0000000000..c6f445253a
--- /dev/null
+++ b/tests/auto/qml/qqmlqt/data/LaterComponent3.qml
@@ -0,0 +1,14 @@
+import QtQuick 2.0
+import LaterImports 1.0
+
+TestElement {
+ id: deleteme3
+ function testFn() {
+ gc(); // at this point, obj is deleted.
+ dangerousFunction(); // calling this function will throw an exeption
+ // because this object has been deleted and its context is not available
+
+ // which means that we shouldn't get to this line.
+ row.test12_1 = 1;
+ }
+}
diff --git a/tests/auto/qml/qqmlqt/data/LaterComponent4.qml b/tests/auto/qml/qqmlqt/data/LaterComponent4.qml
new file mode 100644
index 0000000000..0c53bd368b
--- /dev/null
+++ b/tests/auto/qml/qqmlqt/data/LaterComponent4.qml
@@ -0,0 +1,12 @@
+import QtQuick 2.0
+
+Item {
+ id: deleteme4
+ function testFn() {
+ // this function shouldn't be called,
+ // since the object will have been deleted.
+ row.test13_1 = 2;
+ }
+
+ Component.onDestruction: row.test13_1 = 1; // success == the object was deleted, but testFn wasn't called.
+}
diff --git a/tests/auto/qml/qqmlqt/data/later.qml b/tests/auto/qml/qqmlqt/data/later.qml
new file mode 100644
index 0000000000..a90f3aba9f
--- /dev/null
+++ b/tests/auto/qml/qqmlqt/data/later.qml
@@ -0,0 +1,124 @@
+import QtQuick 2.0
+import LaterImports 1.0
+
+Row {
+ id: row
+ Repeater {
+ id: repeater
+ model: 5
+ delegate: Item { }
+ }
+
+ property bool test1_1: false
+ property bool test1_2: row.focus
+ property bool test2_1: false
+ property bool test2_2: (firstFunctionCallCounter == 1 && secondFunctionCallCounter == 1 && signalCallCounter == 1)
+
+ property int firstFunctionCallCounter: 0
+ property int secondFunctionCallCounter: 0
+ property int signalCallCounter: 0
+
+ signal testSignal
+ onTestSignal: {
+ signalCallCounter++;
+ }
+
+ onChildrenChanged: {
+ Qt.callLater(row.forceActiveFocus); // built-in function
+ Qt.callLater(row.firstFunction); // JS function
+ Qt.callLater(row.testSignal); // signal
+ }
+
+ function firstFunction() {
+ firstFunctionCallCounter++;
+ }
+
+ function secondFunction() {
+ secondFunctionCallCounter++;
+ }
+
+ Component.onCompleted: {
+ test1_1 = !row.focus;
+ test2_1 = (firstFunctionCallCounter == 0);
+
+ Qt.callLater(secondFunction);
+ Qt.callLater(firstFunction);
+ Qt.callLater(secondFunction);
+ }
+
+ function test2() {
+ repeater.model = 2;
+ }
+
+ function test3() {
+ Qt.callLater(test3_recursive);
+ }
+
+ property int recursion: 0
+ property bool test3_1: (recursion == 1)
+ property bool test3_2: (recursion == 2)
+ property bool test3_3: (recursion == 3)
+ function test3_recursive() {
+ if (recursion < 3) {
+ Qt.callLater(test3_recursive);
+ Qt.callLater(test3_recursive);
+ }
+ recursion++;
+ }
+
+ function test4() {
+ Qt.callLater(functionThatDoesNotExist);
+ }
+
+ property bool test5_1: false
+ function test5() {
+ Qt.callLater(functionWithArguments, "THESE", "ARGS", "WILL", "BE", "OVERWRITTEN")
+ Qt.callLater(functionWithArguments, "firstArg", 2, "thirdArg")
+ }
+
+ function functionWithArguments(firstStr, secondInt, thirdString) {
+ test5_1 = (firstStr == "firstArg" && secondInt == 2 && thirdString == "thirdArg");
+ }
+
+
+ property bool test6_1: (callOrder_Later == "TWO THREE ") // not "THREE TWO "
+ function test6() {
+ Qt.callLater(test6Function1, "ONE");
+ Qt.callLater(test6Function2, "TWO");
+ Qt.callLater(test6Function1, "THREE");
+ }
+
+ property string callOrder_Later
+ function test6Function1(arg) { callOrder_Later += arg + " "; }
+ function test6Function2(arg) { callOrder_Later += arg + " "; }
+
+ property int test9_1: SingletonType.intProp;
+ function test9() {
+ SingletonType.resetIntProp();
+ Qt.callLater(SingletonType.testFunc)
+ Qt.callLater(SingletonType.testFunc)
+ Qt.callLater(SingletonType.testFunc)
+ Qt.callLater(SingletonType.testFunc)
+ // should only get called once.
+ }
+
+ property int test10_1: 0
+ function test10() {
+ var c = Qt.createComponent("LaterComponent.qml");
+ var obj = c.createObject(); // QML ownership.
+ Qt.callLater(obj.testFn);
+ // note: obj will be cleaned up during next gc().
+ }
+
+ property int test11_1: 0
+ function test11() {
+ var c = Qt.createComponent("LaterComponent2.qml");
+ var obj = c.createObject(); // QML ownership.
+ Qt.callLater(obj.testFn);
+ gc(); // this won't actually collect the obj, we need to trigger gc manually in the test.
+ }
+
+ function test14() {
+ Qt.callLater(console.log, "success")
+ }
+}
diff --git a/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp b/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp
index 2f44c34bc2..8150241e4a 100644
--- a/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp
+++ b/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp
@@ -53,6 +53,7 @@ public:
tst_qqmlqt() {}
private slots:
+ void initTestCase();
void enums();
void rgba();
void hsla();
@@ -87,12 +88,69 @@ private slots:
void fontFamilies();
void quit();
void resolvedUrl();
+ void later_data();
+ void later();
void qtObjectContents();
private:
QQmlEngine engine;
};
+// for callLater()
+class TestElement : public QQuickItem
+{
+ Q_OBJECT
+public:
+ TestElement() : m_intptr(new int) {}
+ ~TestElement() { delete m_intptr; }
+
+ Q_INVOKABLE void dangerousFunction() {
+ delete m_intptr;
+ m_intptr = new int;
+ *m_intptr = 5;
+ }
+private:
+ int *m_intptr;
+};
+
+// for callLater()
+class TestModuleApi : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int intProp READ intProp WRITE setIntProp NOTIFY intPropChanged)
+
+public:
+ TestModuleApi() : m_int(0) {}
+ ~TestModuleApi() {}
+
+ int intProp() const { return m_int; }
+ void setIntProp(int v) { m_int = v; emit intPropChanged(); }
+
+ Q_INVOKABLE void testFunc() { ++m_int; emit intPropChanged(); }
+ Q_INVOKABLE void resetIntProp() { m_int = 0; emit intPropChanged(); }
+
+signals:
+ void intPropChanged();
+
+private:
+ int m_int;
+};
+
+static QObject *test_module_api_factory(QQmlEngine *engine, QJSEngine *scriptEngine)
+{
+ Q_UNUSED(engine)
+ Q_UNUSED(scriptEngine)
+ TestModuleApi *api = new TestModuleApi;
+ return api;
+}
+
+void tst_qqmlqt::initTestCase()
+{
+ QQmlDataTest::initTestCase();
+ qmlRegisterSingletonType<TestModuleApi>("LaterImports", 1, 0, "SingletonType", test_module_api_factory);
+ qmlRegisterType<TestElement>("LaterImports", 1, 0, "TestElement");
+}
+
void tst_qqmlqt::enums()
{
QQmlComponent component(&engine, testFileUrl("enums.qml"));
@@ -935,6 +993,107 @@ void tst_qqmlqt::resolvedUrl()
delete object;
}
+void tst_qqmlqt::later_data()
+{
+ QTest::addColumn<QString>("function");
+ QTest::addColumn<QStringList>("expectedWarnings");
+ QTest::addColumn<QStringList>("propNames");
+ QTest::addColumn<QVariantList>("values");
+
+ QVariant vtrue = QVariant(true);
+
+ QTest::newRow("callLater from onCompleted")
+ << QString()
+ << QStringList()
+ << (QStringList() << "test1_1" << "test2_1" << "processEvents" << "test1_2" << "test2_2")
+ << (QVariantList() << vtrue << vtrue << QVariant() << vtrue << vtrue);
+
+ QTest::newRow("trigger Qt.callLater() via repeater")
+ << QString(QLatin1String("test2"))
+ << QStringList()
+ << (QStringList() << "processEvents" << "test2_2")
+ << (QVariantList() << QVariant() << vtrue);
+
+ QTest::newRow("recursive Qt.callLater()")
+ << QString(QLatin1String("test3"))
+ << QStringList()
+ << (QStringList() << "processEvents" << "test3_1" << "processEvents" << "test3_2" << "processEvents" << "test3_3")
+ << (QVariantList() << QVariant() << vtrue << QVariant() << vtrue << QVariant() << vtrue);
+
+ QTest::newRow("nonexistent function")
+ << QString(QLatin1String("test4"))
+ << (QStringList() << QString(testFileUrl("later.qml").toString() + QLatin1String(":70: ReferenceError: functionThatDoesNotExist is not defined")))
+ << QStringList()
+ << QVariantList();
+
+ QTest::newRow("callLater with different args")
+ << QString(QLatin1String("test5"))
+ << QStringList()
+ << (QStringList() << "processEvents" << "test5_1")
+ << (QVariantList() << QVariant() << vtrue);
+
+ QTest::newRow("delayed call ordering")
+ << QString(QLatin1String("test6"))
+ << QStringList()
+ << (QStringList() << "processEvents" << "test6_1")
+ << (QVariantList() << QVariant() << vtrue);
+
+ QTest::newRow("invoke module api invokable")
+ << QString(QLatin1String("test9"))
+ << QStringList()
+ << (QStringList() << "processEvents" << "test9_1" << "processEvents")
+ << (QVariantList() << QVariant() << QVariant(1) << QVariant());
+
+ QTest::newRow("invoke function of deleted QObject via callLater() causing deletion")
+ << QString(QLatin1String("test10"))
+ << (QStringList() << QString(testFileUrl("LaterComponent.qml").toString() + QLatin1String(":8: ReferenceError: dangerousFunction is not defined (exception occurred during delayed function evaluation)")))
+ << (QStringList() << "processEvents" << "test10_1" << "processEvents")
+ << (QVariantList() << QVariant() << QVariant(0) << QVariant());
+
+ QTest::newRow("invoke function of deleted QObject via callLater() after deletion")
+ << QString(QLatin1String("test11"))
+ << QStringList()
+ << (QStringList() << "collectGarbage" << "processEvents" << "test11_1" << "processEvents")
+ << (QVariantList() << QVariant() << QVariant() << QVariant(1) << QVariant());
+
+ QTest::newRow("invoke function which has no script origin")
+ << QString(QLatin1String("test14"))
+ << QStringList()
+ << (QStringList() << "collectGarbage")
+ << (QVariantList() << QVariant());
+}
+
+void tst_qqmlqt::later()
+{
+ QFETCH(QString, function);
+ QFETCH(QStringList, expectedWarnings);
+ QFETCH(QStringList, propNames);
+ QFETCH(QVariantList, values);
+
+ foreach (const QString &w, expectedWarnings)
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(w));
+
+ QQmlComponent component(&engine, testFileUrl("later.qml"));
+ QObject *root = component.create();
+ QVERIFY(root != 0);
+
+ if (!function.isEmpty())
+ QMetaObject::invokeMethod(root, qPrintable(function));
+
+ for (int i = 0; i < propNames.size(); ++i) {
+ if (propNames.at(i) == QLatin1String("processEvents")) {
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ QCoreApplication::processEvents();
+ } else if (propNames.at(i) == QLatin1String("collectGarbage")) {
+ engine.collectGarbage();
+ } else {
+ QCOMPARE(root->property(qPrintable(propNames.at(i))), values.at(i));
+ }
+ }
+
+ delete root;
+}
+
void tst_qqmlqt::qtObjectContents()
{
struct StaticQtMetaObject : public QObject
diff --git a/tests/auto/qml/qqmltranslation/tst_qqmltranslation.cpp b/tests/auto/qml/qqmltranslation/tst_qqmltranslation.cpp
index bf255ba6a0..1fc803a395 100644
--- a/tests/auto/qml/qqmltranslation/tst_qqmltranslation.cpp
+++ b/tests/auto/qml/qqmltranslation/tst_qqmltranslation.cpp
@@ -31,7 +31,6 @@
#include <QQmlComponent>
#include <QTranslator>
#include <QQmlContext>
-#include <private/qqmlcompiler_p.h>
#include <private/qqmlengine_p.h>
#include "../../shared/util.h"
@@ -77,15 +76,15 @@ void tst_qqmltranslation::translation()
QQmlContext *context = qmlContext(object);
QQmlEnginePrivate *engine = QQmlEnginePrivate::get(context->engine());
QQmlTypeData *typeData = engine->typeLoader.getType(context->baseUrl());
- QQmlCompiledData *cdata = typeData->compiledData();
- QVERIFY(cdata);
+ QV4::CompiledData::CompilationUnit *compilationUnit = typeData->compilationUnit();
+ QVERIFY(compilationUnit);
QSet<QString> compiledTranslations;
compiledTranslations << QStringLiteral("basic")
<< QStringLiteral("disambiguation")
<< QStringLiteral("singular") << QStringLiteral("plural");
- const QV4::CompiledData::Unit *unit = cdata->compilationUnit->data;
+ const QV4::CompiledData::Unit *unit = compilationUnit->data;
const QV4::CompiledData::Object *rootObject = unit->objectAt(unit->indexOfRootObject);
const QV4::CompiledData::Binding *binding = rootObject->bindingTable();
for (quint32 i = 0; i < rootObject->nBindings; ++i, ++binding) {
@@ -96,7 +95,7 @@ void tst_qqmltranslation::translation()
if (expectCompiledTranslation) {
if (binding->type != QV4::CompiledData::Binding::Type_Translation)
qDebug() << "binding for property" << propertyName << "is not a compiled translation";
- QCOMPARE(binding->type, quint32(QV4::CompiledData::Binding::Type_Translation));
+ QCOMPARE(quint32(binding->type), quint32(QV4::CompiledData::Binding::Type_Translation));
} else {
if (binding->type == QV4::CompiledData::Binding::Type_Translation)
qDebug() << "binding for property" << propertyName << "is not supposed to be a compiled translation";
@@ -137,10 +136,10 @@ void tst_qqmltranslation::idTranslation()
QQmlContext *context = qmlContext(object);
QQmlEnginePrivate *engine = QQmlEnginePrivate::get(context->engine());
QQmlTypeData *typeData = engine->typeLoader.getType(context->baseUrl());
- QQmlCompiledData *cdata = typeData->compiledData();
- QVERIFY(cdata);
+ QV4::CompiledData::CompilationUnit *compilationUnit = typeData->compilationUnit();
+ QVERIFY(compilationUnit);
- const QV4::CompiledData::Unit *unit = cdata->compilationUnit->data;
+ const QV4::CompiledData::Unit *unit = compilationUnit->data;
const QV4::CompiledData::Object *rootObject = unit->objectAt(unit->indexOfRootObject);
const QV4::CompiledData::Binding *binding = rootObject->bindingTable();
for (quint32 i = 0; i < rootObject->nBindings; ++i, ++binding) {
@@ -148,7 +147,7 @@ void tst_qqmltranslation::idTranslation()
if (propertyName == "idTranslation") {
if (binding->type != QV4::CompiledData::Binding::Type_TranslationById)
qDebug() << "binding for property" << propertyName << "is not a compiled translation";
- QCOMPARE(binding->type, quint32(QV4::CompiledData::Binding::Type_TranslationById));
+ QCOMPARE(quint32(binding->type), quint32(QV4::CompiledData::Binding::Type_TranslationById));
} else {
QVERIFY(binding->type != QV4::CompiledData::Binding::Type_Translation);
}
diff --git a/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp b/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp
index 3e8e1d23ea..74f3929783 100644
--- a/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp
+++ b/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp
@@ -32,7 +32,6 @@
#include <QtQuick/qquickitem.h>
#include <QtQml/private/qqmlengine_p.h>
#include <QtQml/private/qqmltypeloader_p.h>
-#include <QtQml/private/qqmlcompiler_p.h>
#include "../../shared/util.h"
class tst_QQMLTypeLoader : public QQmlDataTest
@@ -89,7 +88,7 @@ void tst_QQMLTypeLoader::trimCache()
if (i % 10 == 0) {
// keep ref on data, don't add ref on data->compiledData()
} else if (i % 5 == 0) {
- data->compiledData()->addref();
+ data->compilationUnit()->addref();
data->release();
} else {
data->release();
diff --git a/tests/auto/qml/qqmlvaluetypes/data/color_read.qml b/tests/auto/qml/qqmlvaluetypes/data/color_read.qml
index bc92b1e5f9..73d2b921a7 100644
--- a/tests/auto/qml/qqmlvaluetypes/data/color_read.qml
+++ b/tests/auto/qml/qqmlvaluetypes/data/color_read.qml
@@ -5,5 +5,11 @@ MyTypeObject {
property real v_g: color.g
property real v_b: color.b
property real v_a: color.a
+ property real hsv_h: color.hsvHue
+ property real hsv_s: color.hsvSaturation
+ property real hsv_v: color.hsvValue
+ property real hsl_h: color.hslHue
+ property real hsl_s: color.hslSaturation
+ property real hsl_l: color.hslLightness
property variant copy: color
}
diff --git a/tests/auto/qml/qqmlvaluetypes/data/color_write_HSL.qml b/tests/auto/qml/qqmlvaluetypes/data/color_write_HSL.qml
new file mode 100644
index 0000000000..0034163bbe
--- /dev/null
+++ b/tests/auto/qml/qqmlvaluetypes/data/color_write_HSL.qml
@@ -0,0 +1,8 @@
+import Test 1.0
+
+MyTypeObject {
+ color.hslHue: if (true) 0.43
+ color.hslSaturation: if (true) 0.74
+ color.hslLightness: if (true) 0.54
+ color.a: if (true) 0.7
+}
diff --git a/tests/auto/qml/qqmlvaluetypes/data/color_write_HSV.qml b/tests/auto/qml/qqmlvaluetypes/data/color_write_HSV.qml
new file mode 100644
index 0000000000..1fc47d460e
--- /dev/null
+++ b/tests/auto/qml/qqmlvaluetypes/data/color_write_HSV.qml
@@ -0,0 +1,8 @@
+import Test 1.0
+
+MyTypeObject {
+ color.hsvHue: if (true) 0.43
+ color.hsvSaturation: if (true) 0.77
+ color.hsvValue: if (true) 0.88
+ color.a: if (true) 0.7
+}
diff --git a/tests/auto/qml/qqmlvaluetypes/testtypes.h b/tests/auto/qml/qqmlvaluetypes/testtypes.h
index 77d723fbd4..bcfe4028c6 100644
--- a/tests/auto/qml/qqmlvaluetypes/testtypes.h
+++ b/tests/auto/qml/qqmlvaluetypes/testtypes.h
@@ -194,7 +194,7 @@ class MyOffsetValueInterceptor : public QObject, public QQmlPropertyValueInterce
Q_INTERFACES(QQmlPropertyValueInterceptor)
public:
virtual void setTarget(const QQmlProperty &p) { prop = p; }
- virtual void write(const QVariant &value) { QQmlPropertyPrivate::write(prop, value.toInt() + 13, QQmlPropertyPrivate::BypassInterceptor); }
+ virtual void write(const QVariant &value) { QQmlPropertyPrivate::write(prop, value.toInt() + 13, QQmlPropertyData::BypassInterceptor); }
private:
QQmlProperty prop;
@@ -215,7 +215,7 @@ public:
c.getRgb(&r, &g, &b, &a);
c.setRgb(a, b, g, r);
- QQmlPropertyPrivate::write(prop, c, QQmlPropertyPrivate::BypassInterceptor);
+ QQmlPropertyPrivate::write(prop, c, QQmlPropertyData::BypassInterceptor);
}
private:
@@ -230,7 +230,7 @@ public:
virtual void setTarget(const QQmlProperty &p) { prop = p; }
virtual void write(const QVariant &)
{
- QQmlPropertyPrivate::write(prop, 0.0f, QQmlPropertyPrivate::BypassInterceptor);
+ QQmlPropertyPrivate::write(prop, 0.0f, QQmlPropertyData::BypassInterceptor);
}
private:
diff --git a/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp b/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp
index 300f5b90e5..803bad197a 100644
--- a/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp
+++ b/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp
@@ -30,6 +30,7 @@
#include <QQmlEngine>
#include <QQmlComponent>
#include <QDebug>
+#include <QJSValueIterator>
#include <private/qquickvaluetypes_p.h>
#include <private/qqmlglobal_p.h>
#include "../../shared/util.h"
@@ -89,6 +90,7 @@ private slots:
void customValueTypeInQml();
void gadgetInheritance();
void toStringConversion();
+ void enumerableProperties();
private:
QQmlEngine engine;
@@ -905,6 +907,15 @@ void tst_qqmlvaluetypes::color()
QCOMPARE((float)object->property("v_g").toDouble(), (float)0.88);
QCOMPARE((float)object->property("v_b").toDouble(), (float)0.6);
QCOMPARE((float)object->property("v_a").toDouble(), (float)0.34);
+
+ QCOMPARE(qRound(object->property("hsv_h").toDouble() * 100), 43);
+ QCOMPARE(qRound(object->property("hsv_s").toDouble() * 100), 77);
+ QCOMPARE(qRound(object->property("hsv_v").toDouble() * 100), 88);
+
+ QCOMPARE(qRound(object->property("hsl_h").toDouble() * 100), 43);
+ QCOMPARE(qRound(object->property("hsl_s").toDouble() * 100), 74);
+ QCOMPARE(qRound(object->property("hsl_l").toDouble() * 100), 54);
+
QColor comparison;
comparison.setRedF(0.2);
comparison.setGreenF(0.88);
@@ -931,6 +942,30 @@ void tst_qqmlvaluetypes::color()
}
{
+ QQmlComponent component(&engine, testFileUrl("color_write_HSV.qml"));
+ MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
+ QVERIFY(object != 0);
+
+ QColor newColor;
+ newColor.setHsvF(0.43, 0.77, 0.88, 0.7);
+ QCOMPARE(object->color(), newColor);
+
+ delete object;
+ }
+
+ {
+ QQmlComponent component(&engine, testFileUrl("color_write_HSL.qml"));
+ MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
+ QVERIFY(object != 0);
+
+ QColor newColor;
+ newColor.setHslF(0.43, 0.74, 0.54, 0.7);
+ QCOMPARE(object->color(), newColor);
+
+ delete object;
+ }
+
+ {
QQmlComponent component(&engine, testFileUrl("color_compare.qml"));
MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
QVERIFY(object != 0);
@@ -1649,6 +1684,25 @@ void tst_qqmlvaluetypes::toStringConversion()
QCOMPARE(stringConversion.toString(), StringLessGadget_to_QString(g));
}
+void tst_qqmlvaluetypes::enumerableProperties()
+{
+ QJSEngine engine;
+ DerivedGadget g;
+ QJSValue value = engine.toScriptValue(g);
+ QSet<QString> names;
+ QJSValueIterator it(value);
+ while (it.hasNext()) {
+ it.next();
+ const QString name = it.name();
+ QVERIFY(!names.contains(name));
+ names.insert(name);
+ }
+
+ QCOMPARE(names.count(), 2);
+ QVERIFY(names.contains(QStringLiteral("baseProperty")));
+ QVERIFY(names.contains(QStringLiteral("derivedProperty")));
+}
+
QTEST_MAIN(tst_qqmlvaluetypes)
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/send_patch.expect b/tests/auto/qml/qqmlxmlhttprequest/data/send_patch.expect
new file mode 100644
index 0000000000..8c13977462
--- /dev/null
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/send_patch.expect
@@ -0,0 +1,17 @@
+PATCH /qqmlxmlhttprequest.cpp HTTP/1.1
+Accept-Language: en-US
+If-Match: "ETagNumber"
+Content-Type: application/example
+Content-Length: 247
+Connection: Keep-Alive
+Accept-Encoding: gzip, deflate
+User-Agent: Mozilla/5.0
+Host: {{ServerHostUrl}}
+
+--- a/qqmlxmlhttprequest.cpp
++++ b/qqmlxmlhttprequest.cpp
+@@ -1238,11 +1238,13 @@
+- } else if (m_method == QLatin1String("OPTIONS")) {
++ } else if (m_method == QLatin1String("OPTIONS") ||
++ (m_method == QLatin1String("PATCH"))) {
+
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/send_patch.qml b/tests/auto/qml/qqmlxmlhttprequest/data/send_patch.qml
new file mode 100644
index 0000000000..2abf1c60a8
--- /dev/null
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/send_patch.qml
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 Canonical Limited and/or its subsidiary(-ies).
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the test suite 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 QtQuick 2.0
+
+QtObject {
+ property string url
+
+ property bool dataOK: false
+ property bool headerOK: false
+
+ Component.onCompleted: {
+ var x = new XMLHttpRequest;
+ x.open("PATCH", url);
+ x.setRequestHeader("Accept-Language","en-US");
+ x.setRequestHeader("If-Match","\"ETagNumber\"");
+
+ // Test to the end
+ x.onreadystatechange = function() {
+ if (x.readyState == XMLHttpRequest.HEADERS_RECEIVED) {
+ headerOK = (x.getResponseHeader("Content-Location") == "/qqmlxmlhttprequest.cpp") &&
+ (x.getResponseHeader("ETag") == "\"ETagNumber\"") &&
+ (x.status == "204");
+ } else if (x.readyState == XMLHttpRequest.DONE) {
+ dataOK = (x.responseText === "");
+ }
+ }
+
+ var body = "--- a/qqmlxmlhttprequest.cpp\n" +
+ "+++ b/qqmlxmlhttprequest.cpp\n" +
+ "@@ -1238,11 +1238,13 @@\n" +
+ "- } else if (m_method == QLatin1String(\"OPTIONS\")) {\n" +
+ "+ } else if (m_method == QLatin1String(\"OPTIONS\") ||\n" +
+ "+ (m_method == QLatin1String(\"PATCH\"))) {\n"
+
+ x.send(body);
+ }
+}
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/send_patch.reply b/tests/auto/qml/qqmlxmlhttprequest/data/send_patch.reply
new file mode 100644
index 0000000000..cece41ced1
--- /dev/null
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/send_patch.reply
@@ -0,0 +1,3 @@
+HTTP/1.1 204 No Content
+Content-Location: /qqmlxmlhttprequest.cpp
+ETag: "ETagNumber"
diff --git a/tests/auto/qml/qqmlxmlhttprequest/tst_qqmlxmlhttprequest.cpp b/tests/auto/qml/qqmlxmlhttprequest/tst_qqmlxmlhttprequest.cpp
index 425e12677f..1ce07ecdab 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/tst_qqmlxmlhttprequest.cpp
+++ b/tests/auto/qml/qqmlxmlhttprequest/tst_qqmlxmlhttprequest.cpp
@@ -71,6 +71,7 @@ private slots:
void send_withdata_data();
void send_options();
void send_options_data();
+ void send_patch();
void abort();
void abort_unsent();
void abort_opened();
@@ -639,6 +640,26 @@ void tst_qqmlxmlhttprequest::send_options_data()
QTest::newRow("OPTIONS (with data)") << "testdocument.html" << "send_data.10.expect" << "send_data.9.qml" << "send_data.2.reply";
}
+void tst_qqmlxmlhttprequest::send_patch()
+{
+ TestHTTPServer server;
+ QVERIFY2(server.listen(), qPrintable(server.errorString()));
+ QVERIFY(server.wait(testFileUrl("send_patch.expect"),
+ testFileUrl("send_patch.reply"),
+ // the content of response file will be ignored due to 204 status code
+ testFileUrl("testdocument.html")));
+
+ QQmlComponent component(&engine, testFileUrl("send_patch.qml"));
+ QScopedPointer<QObject> object(component.beginCreate(engine.rootContext()));
+ QVERIFY(!object.isNull());
+ object->setProperty("url", server.urlString("/qqmlxmlhttprequest.cpp"));
+ component.completeCreate();
+
+ QTRY_VERIFY(object->property("dataOK").toBool());
+ QTRY_VERIFY(object->property("headerOK").toBool());
+}
+
+
// Test abort() has no effect in unsent state
void tst_qqmlxmlhttprequest::abort_unsent()
{
diff --git a/tests/auto/qml/qv4mm/qv4mm.pro b/tests/auto/qml/qv4mm/qv4mm.pro
new file mode 100644
index 0000000000..d9b749af4a
--- /dev/null
+++ b/tests/auto/qml/qv4mm/qv4mm.pro
@@ -0,0 +1,8 @@
+CONFIG += testcase
+TARGET = tst_qv4mm
+osx:CONFIG -= app_bundle
+
+SOURCES += tst_qv4mm.cpp
+
+QT += qml qml-private testlib
+
diff --git a/tests/auto/qml/qv4mm/tst_qv4mm.cpp b/tests/auto/qml/qv4mm/tst_qv4mm.cpp
new file mode 100644
index 0000000000..d4ba363d00
--- /dev/null
+++ b/tests/auto/qml/qv4mm/tst_qv4mm.cpp
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 basysKom GmbH.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite 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$
+**
+****************************************************************************/
+
+#include <qtest.h>
+#include <QQmlEngine>
+#include <private/qv4mm_p.h>
+
+class tst_qv4mm : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void gcStats();
+ void tweaks();
+};
+
+void tst_qv4mm::gcStats()
+{
+ qputenv(QV4_MM_STATS, "1");
+ QQmlEngine engine;
+ engine.collectGarbage();
+}
+
+void tst_qv4mm::tweaks()
+{
+ qputenv(QV4_MM_MAXBLOCK_SHIFT, "5");
+ qputenv(QV4_MM_MAX_CHUNK_SIZE, "65536");
+ QQmlEngine engine;
+}
+
+QTEST_MAIN(tst_qv4mm)
+
+#include "tst_qv4mm.moc"