aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2018-05-24 08:57:40 +0200
committerLars Knoll <lars.knoll@qt.io>2018-05-24 09:15:57 +0200
commitb254bbb82b7d1b42950c4267d8e618b570f88cc6 (patch)
treec8f9fd1fcbd5c5d4a75ffea79ee623ce59e9ae9b
parent1b0e6861ba7af231c29ebba10c93976845f7f78d (diff)
parent5b8a94eb8e5d4e3b79ab73a9a0325f838ecbe41a (diff)
Merge remote-tracking branch 'origin/5.11' into dev
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp55
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h2
-rw-r--r--src/qml/compiler/qqmlirbuilder.cpp16
-rw-r--r--src/qml/jsruntime/qv4engine.cpp7
-rw-r--r--src/qml/qml/qqmltypeloader.cpp19
-rw-r--r--src/qml/qml/v8/qqmlbuiltinfunctions.cpp2
-rw-r--r--src/quick/doc/src/guidelines/qtquick-bestpractices.qdoc4
-rw-r--r--src/quick/items/context2d/qquickcontext2d.cpp2
-rw-r--r--src/quick/items/qquickevents.cpp10
-rw-r--r--src/quick/items/qquickitem.cpp5
-rw-r--r--tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/data/encodeQmlScope.qml19
-rw-r--r--tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/qqmldebugjs.pro3
-rw-r--r--tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/tst_qqmldebugjs.cpp67
-rw-r--r--tests/auto/qml/qjsengine/tst_qjsengine.cpp18
-rw-r--r--tests/auto/qml/qmlcachegen/Enums.qml9
-rw-r--r--tests/auto/qml/qmlcachegen/qmlcachegen.pro2
-rw-r--r--tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp11
-rw-r--r--tests/auto/qml/qqmlcomponent/data/InitialPropertyTest.qml4
-rw-r--r--tests/auto/qml/qqmlcomponent/data/nonExistentInitialProperty.qml9
-rw-r--r--tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp18
-rw-r--r--tests/auto/qml/qqmltypeloader/data/Base.qml3
-rw-r--r--tests/auto/qml/qqmltypeloader/data/Load.qml11
-rw-r--r--tests/auto/qml/qqmltypeloader/data/redirected/Imported.qml5
-rw-r--r--tests/auto/qml/qqmltypeloader/data/redirected/Redirected.qml5
-rw-r--r--tests/auto/qml/qqmltypeloader/data/redirected/qmldir1
-rw-r--r--tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp18
-rw-r--r--tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.pro7
-rw-r--r--tests/auto/quick/qquickanimatedsprite/qquickanimatedsprite.pro2
28 files changed, 279 insertions, 55 deletions
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp
index cc1db7b5ce..0993390483 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp
+++ b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp
@@ -73,17 +73,12 @@ QV4::Heap::ExecutionContext *QV4DataCollector::findContext(int frame)
return f ? f->context()->d() : nullptr;
}
-QV4::Heap::CallContext *QV4DataCollector::findScope(QV4::Heap::ExecutionContext *ctx, int scope)
+QV4::Heap::ExecutionContext *QV4DataCollector::findScope(QV4::Heap::ExecutionContext *ctx, int scope)
{
- if (!ctx)
- return nullptr;
-
for (; scope > 0 && ctx; --scope)
ctx = ctx->outer;
- if (!ctx || (ctx->type != QV4::Heap::ExecutionContext::Type_CallContext && ctx->type != QV4::Heap::ExecutionContext::Type_BlockContext))
- return nullptr;
- return static_cast<QV4::Heap::CallContext *>(ctx);
+ return ctx;
}
QVector<QV4::Heap::ExecutionContext::ContextType> QV4DataCollector::getScopeTypes(int frame)
@@ -102,16 +97,17 @@ int QV4DataCollector::encodeScopeType(QV4::Heap::ExecutionContext::ContextType s
{
switch (scopeType) {
case QV4::Heap::ExecutionContext::Type_GlobalContext:
- return 0;
+ break;
case QV4::Heap::ExecutionContext::Type_WithContext:
return 2;
case QV4::Heap::ExecutionContext::Type_CallContext:
return 1;
- case QV4::Heap::ExecutionContext::Type_BlockContext:
+ case QV4::Heap::ExecutionContext::Type_QmlContext:
return 3;
- default: // QV4::Heap::ExecutionContext::Type_QmlContext:
- return -1;
+ case QV4::Heap::ExecutionContext::Type_BlockContext:
+ return 4;
}
+ return 0;
}
QV4DataCollector::QV4DataCollector(QV4::ExecutionEngine *engine)
@@ -260,31 +256,32 @@ bool QV4DataCollector::isValidRef(QV4DataCollector::Ref ref) const
bool QV4DataCollector::collectScope(QJsonObject *dict, int frameNr, int scopeNr)
{
- QStringList names;
-
QV4::Scope scope(engine());
- QV4::Scoped<QV4::CallContext> ctxt(scope, findScope(findContext(frameNr), scopeNr));
+ QV4::Scoped<QV4::ExecutionContext> ctxt(scope, findScope(findContext(frameNr), scopeNr));
if (!ctxt)
return false;
- Refs collectedRefs;
- QV4::ScopedValue v(scope);
- QV4::Heap::InternalClass *ic = ctxt->internalClass();
- for (uint i = 0; i < ic->size; ++i) {
- QString name = ic->nameMap[i].toQString();
- names.append(name);
- v = ctxt->d()->locals[i];
- collectedRefs.append(collect(v));
- }
-
QV4::ScopedObject scopeObject(scope, engine()->newObject());
+ if (ctxt->d()->type == QV4::Heap::ExecutionContext::Type_CallContext) {
+ QStringList names;
+ Refs collectedRefs;
+
+ QV4::ScopedValue v(scope);
+ QV4::Heap::InternalClass *ic = ctxt->internalClass();
+ for (uint i = 0; i < ic->size; ++i) {
+ QString name = ic->nameMap[i].toQString();
+ names.append(name);
+ v = static_cast<QV4::Heap::CallContext *>(ctxt->d())->locals[i];
+ collectedRefs.append(collect(v));
+ }
- Q_ASSERT(names.size() == collectedRefs.size());
- QV4::ScopedString propName(scope);
- for (int i = 0, ei = collectedRefs.size(); i != ei; ++i) {
- propName = engine()->newString(names.at(i));
- scopeObject->put(propName, QV4::Value::fromReturnedValue(getValue(collectedRefs.at(i))));
+ Q_ASSERT(names.size() == collectedRefs.size());
+ QV4::ScopedString propName(scope);
+ for (int i = 0, ei = collectedRefs.size(); i != ei; ++i) {
+ propName = engine()->newString(names.at(i));
+ scopeObject->put(propName, (v = getValue(collectedRefs.at(i))));
+ }
}
Ref scopeObjectRef = addRef(scopeObject);
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h
index 87be009de5..5494e10e9a 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h
+++ b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h
@@ -58,7 +58,7 @@ public:
typedef uint Ref;
typedef QVector<uint> Refs;
- static QV4::Heap::CallContext *findScope(QV4::Heap::ExecutionContext *ctxt, int scope);
+ static QV4::Heap::ExecutionContext *findScope(QV4::Heap::ExecutionContext *ctxt, int scope);
static int encodeScopeType(QV4::Heap::ExecutionContext::ContextType scopeType);
QVector<QV4::Heap::ExecutionContext::ContextType> getScopeTypes(int frame);
diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp
index fcd535905b..820f127331 100644
--- a/src/qml/compiler/qqmlirbuilder.cpp
+++ b/src/qml/compiler/qqmlirbuilder.cpp
@@ -2427,6 +2427,22 @@ QmlIR::Object *IRLoader::loadObject(const QV4::CompiledData::Object *serializedO
object->qmlSignals->append(s);
}
+ for (uint i = 0; i < serializedObject->nEnums; ++i) {
+ const QV4::CompiledData::Enum *serializedEnum = serializedObject->enumAt(i);
+ QmlIR::Enum *e = pool->New<QmlIR::Enum>();
+ e->nameIndex = serializedEnum->nameIndex;
+ e->location = serializedEnum->location;
+ e->enumValues = pool->New<QmlIR::PoolList<QmlIR::EnumValue> >();
+
+ for (uint i = 0; i < serializedEnum->nEnumValues; ++i) {
+ QmlIR::EnumValue *v = pool->New<QmlIR::EnumValue>();
+ *static_cast<QV4::CompiledData::EnumValue*>(v) = *serializedEnum->enumValueAt(i);
+ e->enumValues->append(v);
+ }
+
+ object->qmlEnums->append(e);
+ }
+
const QV4::CompiledData::Property *serializedProperty = serializedObject->propertyTable();
for (uint i = 0; i < serializedObject->nProperties; ++i, ++serializedProperty) {
QmlIR::Property *p = pool->New<QmlIR::Property>();
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index ff32671dc8..96670154e1 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -852,16 +852,19 @@ QQmlContextData *ExecutionEngine::callingQmlContext() const
QString CppStackFrame::source() const
{
- return v4Function->sourceFile();
+ return v4Function ? v4Function->sourceFile() : QString();
}
QString CppStackFrame::function() const
{
- return v4Function->name()->toQString();
+ return v4Function ? v4Function->name()->toQString() : QString();
}
int CppStackFrame::lineNumber() const
{
+ if (!v4Function)
+ return -1;
+
auto findLine = [](const CompiledData::CodeOffsetToLine &entry, uint offset) {
return entry.codeOffset < offset;
};
diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp
index 8c3c487e96..d455885699 100644
--- a/src/qml/qml/qqmltypeloader.cpp
+++ b/src/qml/qml/qqmltypeloader.cpp
@@ -358,9 +358,8 @@ qreal QQmlDataBlob::progress() const
/*!
Returns the physical url of the data. Initially this is the same as
-finalUrl(), but if a network redirect happens while fetching the data, this url
-is updated to reflect the new location. Also, if a URL interceptor is set, it
-will work on this URL and leave finalUrl() alone.
+finalUrl(), but if a URL interceptor is set, it will work on this URL
+and leave finalUrl() alone.
\sa finalUrl()
*/
@@ -381,8 +380,12 @@ QString QQmlDataBlob::urlString() const
Returns the logical URL to be used for resolving further URLs referred to in
the code.
-This is the blob url passed to the constructor. If a network redirect
-happens while fetching the data, this url remains the same.
+This is the blob url passed to the constructor. If a URL interceptor rewrites
+the URL, this one stays the same. If a network redirect happens while fetching
+the data, this url is updated to reflect the new location. Therefore, if both
+an interception and a redirection happen, the final url will indirectly
+incorporate the result of the interception, potentially breaking further
+lookups.
\sa url()
*/
@@ -1190,15 +1193,15 @@ void QQmlTypeLoader::networkReplyFinished(QNetworkReply *reply)
QVariant redirect = reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
if (redirect.isValid()) {
QUrl url = reply->url().resolved(redirect.toUrl());
- blob->m_url = url;
- blob->m_urlString.clear();
+ blob->m_finalUrl = url;
+ blob->m_finalUrlString.clear();
QNetworkReply *reply = m_thread->networkAccessManager()->get(QNetworkRequest(url));
QObject *nrp = m_thread->networkReplyProxy();
QObject::connect(reply, SIGNAL(finished()), nrp, SLOT(finished()));
m_networkReplies.insert(reply, blob);
#ifdef DATABLOB_DEBUG
- qWarning("QQmlDataBlob: redirected to %s", qPrintable(blob->urlString()));
+ qWarning("QQmlDataBlob: redirected to %s", qPrintable(blob->finalUrlString()));
#endif
return;
}
diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
index 4ae78645ea..bff16441d0 100644
--- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
+++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
@@ -1703,7 +1703,7 @@ ReturnedValue ConsoleObject::method_count(const FunctionObject *b, const Value *
QString scriptName = frame->source();
- int value = v8engine->consoleCountHelper(scriptName, frame->lineNumber(), -1);
+ int value = v8engine->consoleCountHelper(scriptName, frame->lineNumber(), 0);
QString message = name + QLatin1String(": ") + QString::number(value);
QMessageLogger(qPrintable(scriptName), frame->lineNumber(),
diff --git a/src/quick/doc/src/guidelines/qtquick-bestpractices.qdoc b/src/quick/doc/src/guidelines/qtquick-bestpractices.qdoc
index b22b013684..30aca38678 100644
--- a/src/quick/doc/src/guidelines/qtquick-bestpractices.qdoc
+++ b/src/quick/doc/src/guidelines/qtquick-bestpractices.qdoc
@@ -318,8 +318,8 @@ component loaded by the engine. Context properties are useful for objects that
must be available as soon as the QML is loaded and cannot be instantiated in
QML.
-\l {Integrating QML and C++} demonstrates an alternative approach where QML is
-made aware of a C++ type so that it can instantiate it itself.
+For a quick guide to choosing the correct approach to expose C++ types to QML,
+see \l {Choosing the Correct Integration Method Between C++ and QML}.
\section2 Related Information
\list
diff --git a/src/quick/items/context2d/qquickcontext2d.cpp b/src/quick/items/context2d/qquickcontext2d.cpp
index e01e87b45a..07d5f6d39b 100644
--- a/src/quick/items/context2d/qquickcontext2d.cpp
+++ b/src/quick/items/context2d/qquickcontext2d.cpp
@@ -1637,7 +1637,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createRadialGradient(const
QV4::Scoped<QQuickContext2DStyle> gradient(scope, scope.engine->memoryManager->allocate<QQuickContext2DStyle>());
QV4::ScopedObject p(scope, ed->gradientProto.value());
gradient->setPrototype(p);
- *gradient->d()->brush = QRadialGradient(QPointF(x1, y1), r0+r1, QPointF(x0, y0));
+ *gradient->d()->brush = QRadialGradient(QPointF(x1, y1), r1, QPointF(x0, y0), r0);
RETURN_RESULT(*gradient);
}
diff --git a/src/quick/items/qquickevents.cpp b/src/quick/items/qquickevents.cpp
index d964f2bb32..d020ad7c4c 100644
--- a/src/quick/items/qquickevents.cpp
+++ b/src/quick/items/qquickevents.cpp
@@ -849,14 +849,16 @@ void QQuickEventPoint::setGrabberItem(QQuickItem *grabber)
qCDebug(lcPointerGrab) << pointDeviceName(this) << "point" << hex << m_pointId << pointStateString(this)
<< ": grab" << m_exclusiveGrabber << "->" << grabber;
}
+ QQuickItem *oldGrabberItem = grabberItem();
m_exclusiveGrabber = QPointer<QObject>(grabber);
m_grabberIsHandler = false;
m_sceneGrabPos = m_scenePos;
- QQuickItem *oldGrabberItem = grabberItem();
- if (oldGrabberHandler)
+ if (oldGrabberHandler) {
oldGrabberHandler->onGrabChanged(oldGrabberHandler, (grabber ? CancelGrabExclusive : UngrabExclusive), this);
- else if (oldGrabberItem && oldGrabberItem != grabber && grabber && pointerEvent()->asPointerTouchEvent())
- oldGrabberItem->touchUngrabEvent();
+ } else if (oldGrabberItem && oldGrabberItem != grabber && grabber && grabber->window()) {
+ QQuickWindowPrivate *windowPriv = QQuickWindowPrivate::get(grabber->window());
+ windowPriv->sendUngrabEvent(oldGrabberItem, windowPriv->isDeliveringTouchAsMouse());
+ }
for (QPointer<QQuickPointerHandler> passiveGrabber : m_passiveGrabbers)
passiveGrabber->onGrabChanged(passiveGrabber, OverrideGrabPassive, this);
}
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp
index f02ad24c5b..73fc12babd 100644
--- a/src/quick/items/qquickitem.cpp
+++ b/src/quick/items/qquickitem.cpp
@@ -7462,11 +7462,8 @@ void QQuickItem::grabMouse()
auto point = fromTouch ?
windowPriv->pointerEventInstance(windowPriv->touchMouseDevice)->pointById(windowPriv->touchMouseId) :
windowPriv->pointerEventInstance(QQuickPointerDevice::genericMouseDevice())->point(0);
- if (point) {
- QQuickItem *oldGrabber = point->grabberItem();
+ if (point)
point->setGrabberItem(this);
- windowPriv->sendUngrabEvent(oldGrabber, fromTouch);
- }
}
/*!
diff --git a/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/data/encodeQmlScope.qml b/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/data/encodeQmlScope.qml
new file mode 100644
index 0000000000..7ea048044f
--- /dev/null
+++ b/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/data/encodeQmlScope.qml
@@ -0,0 +1,19 @@
+import QtQuick 2.0
+
+Item {
+ property int a: 0
+ property int b: 0
+ onAChanged: console.log("inline")
+ onBChanged: {
+ console.log("extra braces");
+ }
+
+ Timer {
+ interval: 10
+ running: true
+ onTriggered: {
+ parent.a += 10;
+ parent.b -= 10;
+ }
+ }
+}
diff --git a/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/qqmldebugjs.pro b/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/qqmldebugjs.pro
index 90623c75a6..52d70bd1b1 100644
--- a/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/qqmldebugjs.pro
+++ b/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/qqmldebugjs.pro
@@ -20,4 +20,5 @@ OTHER_FILES += data/test.qml data/test.js \
data/changeBreakpoint.qml \
data/stepAction.qml \
data/breakpointRelocation.qml \
- data/createComponent.qml
+ data/createComponent.qml \
+ data/encodeQmlScope.qml
diff --git a/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/tst_qqmldebugjs.cpp b/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/tst_qqmldebugjs.cpp
index 37d4ef1160..b36e576320 100644
--- a/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/tst_qqmldebugjs.cpp
+++ b/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/tst_qqmldebugjs.cpp
@@ -124,6 +124,7 @@ const char *QUIT_QMLFILE = "quit.qml";
const char *CHANGEBREAKPOINT_QMLFILE = "changeBreakpoint.qml";
const char *STEPACTION_QMLFILE = "stepAction.qml";
const char *BREAKPOINTRELOCATION_QMLFILE = "breakpointRelocation.qml";
+const char *ENCODEQMLSCOPE_QMLFILE = "encodeQmlScope.qml";
#define VARIANTMAPINIT \
QString obj("{}"); \
@@ -217,6 +218,8 @@ private slots:
void getScripts_data() { targetData(); }
void getScripts();
+ void encodeQmlScope();
+
private:
ConnectResult init(bool qmlscene, const QString &qmlFile = QString(TEST_QMLFILE),
bool blockMode = true, bool restrictServices = false);
@@ -1457,6 +1460,70 @@ void tst_QQmlDebugJS::getScripts()
QVERIFY(scripts.first().toMap()[QStringLiteral("name")].toString().endsWith(QStringLiteral("data/test.qml")));
}
+void tst_QQmlDebugJS::encodeQmlScope()
+{
+ QString file(ENCODEQMLSCOPE_QMLFILE);
+ QCOMPARE(init(true, file), ConnectSuccess);
+
+ int numFrames = 0;
+ int numExpectedScopes = 0;
+ int numReceivedScopes = 0;
+ bool isStopped = false;
+ bool scopesFailed = false;
+
+ QObject::connect(m_client, &QJSDebugClient::failure, this, [&]() {
+ qWarning() << "received failure" << m_client->response;
+ scopesFailed = true;
+ m_process->stop();
+ numFrames = 2;
+ isStopped = false;
+ });
+
+ QObject::connect(m_client, &QJSDebugClient::stopped, this, [&]() {
+ m_client->frame();
+ isStopped = true;
+ });
+
+ QObject::connect(m_client, &QJSDebugClient::result, this, [&]() {
+ const QVariantMap value = m_client->parser.call(
+ QJSValueList() << QJSValue(QString(m_client->response))).toVariant().toMap();
+
+ const QMap<QString, QVariant> body = value.value("body").toMap();
+ const QString command = value.value("command").toString();
+
+ if (command == QString("scope")) {
+ // If the scope commands fail we get a failure() signal above.
+ if (++numReceivedScopes == numExpectedScopes) {
+ m_client->continueDebugging(QJSDebugClient::Continue);
+ isStopped = false;
+ }
+ } else if (command == QString("frame")) {
+
+ // We want at least a global scope and some kind of local scope here.
+ const QList<QVariant> scopes = body.value("scopes").toList();
+ if (scopes.length() < 2)
+ scopesFailed = true;
+
+ for (const QVariant &scope : scopes) {
+ ++numExpectedScopes;
+ m_client->scope(scope.toMap().value("index").toInt());
+ }
+
+ ++numFrames;
+ }
+ });
+
+ m_client->setBreakpoint(file, 6);
+ m_client->setBreakpoint(file, 8);
+ m_client->connect();
+
+ QTRY_COMPARE(numFrames, 2);
+ QVERIFY(numExpectedScopes > 3);
+ QVERIFY(!scopesFailed);
+ QTRY_VERIFY(!isStopped);
+ QCOMPARE(numReceivedScopes, numExpectedScopes);
+}
+
QList<QQmlDebugClient *> tst_QQmlDebugJS::createClients()
{
m_client = new QJSDebugClient(m_connection);
diff --git a/tests/auto/qml/qjsengine/tst_qjsengine.cpp b/tests/auto/qml/qjsengine/tst_qjsengine.cpp
index 911da1b20c..e4bf2ff1aa 100644
--- a/tests/auto/qml/qjsengine/tst_qjsengine.cpp
+++ b/tests/auto/qml/qjsengine/tst_qjsengine.cpp
@@ -215,6 +215,8 @@ private slots:
void functionToString_data();
void functionToString();
+ void protoChanges_QTBUG68369();
+
signals:
void testSignal();
};
@@ -4247,6 +4249,22 @@ void tst_QJSEngine::functionToString()
QCOMPARE(evaluationResult.toString(), expectedString);
}
+void tst_QJSEngine::protoChanges_QTBUG68369()
+{
+ QJSEngine engine;
+ QJSValue ok = engine.evaluate(
+ "var o = { x: true };"
+ "var p1 = {};"
+ "var p2 = {};"
+ "o.__proto__ = p1;"
+ "o.__proto__ = p2;"
+ "o.__proto__ = p1;"
+ "p1.y = true;"
+ "o.y"
+ );
+ QVERIFY(ok.toBool() == true);
+}
+
QTEST_MAIN(tst_QJSEngine)
#include "tst_qjsengine.moc"
diff --git a/tests/auto/qml/qmlcachegen/Enums.qml b/tests/auto/qml/qmlcachegen/Enums.qml
new file mode 100644
index 0000000000..830babb73e
--- /dev/null
+++ b/tests/auto/qml/qmlcachegen/Enums.qml
@@ -0,0 +1,9 @@
+import QtQml 2.0
+QtObject {
+ enum Test {
+ First = 100,
+ Second = 200
+ }
+ property int value: 0
+ Component.onCompleted: value = Enums.Second
+}
diff --git a/tests/auto/qml/qmlcachegen/qmlcachegen.pro b/tests/auto/qml/qmlcachegen/qmlcachegen.pro
index f62b950844..40de4548a7 100644
--- a/tests/auto/qml/qmlcachegen/qmlcachegen.pro
+++ b/tests/auto/qml/qmlcachegen/qmlcachegen.pro
@@ -14,4 +14,6 @@ RESOURCES += trickypaths.qrc
RESOURCES += jsimport.qml script.js library.js
+RESOURCES += Enums.qml
+
QT += core-private qml-private testlib
diff --git a/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp b/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp
index c95a5a5d25..3b7d268f7b 100644
--- a/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp
+++ b/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp
@@ -56,6 +56,8 @@ private slots:
void trickyPaths();
void scriptImport();
+
+ void enums();
};
// A wrapper around QQmlComponent to ensure the temporary reference counts
@@ -427,6 +429,15 @@ void tst_qmlcachegen::scriptImport()
QTRY_COMPARE(obj->property("value").toInt(), 42);
}
+void tst_qmlcachegen::enums()
+{
+ QQmlEngine engine;
+ CleanlyLoadingComponent component(&engine, QUrl("qrc:///Enums.qml"));
+ QScopedPointer<QObject> obj(component.create());
+ QVERIFY(!obj.isNull());
+ QTRY_COMPARE(obj->property("value").toInt(), 200);
+}
+
QTEST_GUILESS_MAIN(tst_qmlcachegen)
#include "tst_qmlcachegen.moc"
diff --git a/tests/auto/qml/qqmlcomponent/data/InitialPropertyTest.qml b/tests/auto/qml/qqmlcomponent/data/InitialPropertyTest.qml
new file mode 100644
index 0000000000..7de276f2d8
--- /dev/null
+++ b/tests/auto/qml/qqmlcomponent/data/InitialPropertyTest.qml
@@ -0,0 +1,4 @@
+import QtQml 2.0
+QtObject {
+ property bool ok: false
+}
diff --git a/tests/auto/qml/qqmlcomponent/data/nonExistentInitialProperty.qml b/tests/auto/qml/qqmlcomponent/data/nonExistentInitialProperty.qml
new file mode 100644
index 0000000000..ef89e46088
--- /dev/null
+++ b/tests/auto/qml/qqmlcomponent/data/nonExistentInitialProperty.qml
@@ -0,0 +1,9 @@
+import QtQml 2.0
+QtObject {
+ property Component factory: Qt.createComponent(Qt.resolvedUrl("InitialPropertyTest.qml"), Component.PreferSynchronous)
+ property var incubator
+ function startIncubation()
+ {
+ incubator = factory.incubateObject(null, { ok: true, nonExistent: 42 }, Qt.Asynchronous)
+ }
+}
diff --git a/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp b/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp
index 0263115db8..efd5bb571b 100644
--- a/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp
+++ b/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp
@@ -118,6 +118,7 @@ private slots:
void recursionContinuation();
void partialComponentCreation();
void callingContextForInitialProperties();
+ void setNonExistentInitialProperty();
void relativeUrl_data();
void relativeUrl();
@@ -607,6 +608,23 @@ void tst_qqmlcomponent::callingContextForInitialProperties()
QVERIFY(checker->scopeObject->metaObject()->indexOfProperty("incubatedObject") != -1);
}
+void tst_qqmlcomponent::setNonExistentInitialProperty()
+{
+ QQmlIncubationController controller;
+ QQmlEngine engine;
+ engine.setIncubationController(&controller);
+ QQmlComponent component(&engine, testFileUrl("nonExistentInitialProperty.qml"));
+ QScopedPointer<QObject> obj(component.create());
+ QVERIFY(!obj.isNull());
+ QMetaObject::invokeMethod(obj.data(), "startIncubation");
+ QJSValue incubatorStatus = obj->property("incubator").value<QJSValue>();
+ incubatorStatus.property("forceCompletion").callWithInstance(incubatorStatus);
+ QJSValue objectWrapper = incubatorStatus.property("object");
+ QVERIFY(objectWrapper.isQObject());
+ QPointer<QObject> object(objectWrapper.toQObject());
+ QVERIFY(object->property("ok").toBool());
+}
+
void tst_qqmlcomponent::relativeUrl_data()
{
QTest::addColumn<QUrl>("url");
diff --git a/tests/auto/qml/qqmltypeloader/data/Base.qml b/tests/auto/qml/qqmltypeloader/data/Base.qml
new file mode 100644
index 0000000000..431c659424
--- /dev/null
+++ b/tests/auto/qml/qqmltypeloader/data/Base.qml
@@ -0,0 +1,3 @@
+import QtQml 2.0
+
+QtObject {}
diff --git a/tests/auto/qml/qqmltypeloader/data/Load.qml b/tests/auto/qml/qqmltypeloader/data/Load.qml
new file mode 100644
index 0000000000..0b893bb5cd
--- /dev/null
+++ b/tests/auto/qml/qqmltypeloader/data/Load.qml
@@ -0,0 +1,11 @@
+import QtQuick 2.0
+
+Item {
+ property int xy: loader.xy
+ Loader {
+ id: loader
+ asynchronous: true
+ source: 'Base.qml'
+ property int xy: item.xy
+ }
+}
diff --git a/tests/auto/qml/qqmltypeloader/data/redirected/Imported.qml b/tests/auto/qml/qqmltypeloader/data/redirected/Imported.qml
new file mode 100644
index 0000000000..62954fe1b2
--- /dev/null
+++ b/tests/auto/qml/qqmltypeloader/data/redirected/Imported.qml
@@ -0,0 +1,5 @@
+import QtQml 2.0
+
+QtObject {
+ property int xy: 323232
+}
diff --git a/tests/auto/qml/qqmltypeloader/data/redirected/Redirected.qml b/tests/auto/qml/qqmltypeloader/data/redirected/Redirected.qml
new file mode 100644
index 0000000000..40fec5ed31
--- /dev/null
+++ b/tests/auto/qml/qqmltypeloader/data/redirected/Redirected.qml
@@ -0,0 +1,5 @@
+import QtQml 2.0
+
+Imported {
+
+}
diff --git a/tests/auto/qml/qqmltypeloader/data/redirected/qmldir b/tests/auto/qml/qqmltypeloader/data/redirected/qmldir
new file mode 100644
index 0000000000..8eb1fa5c18
--- /dev/null
+++ b/tests/auto/qml/qqmltypeloader/data/redirected/qmldir
@@ -0,0 +1 @@
+Imported 1.0 Imported.qml
diff --git a/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp b/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp
index 28737ceb2e..cf3bc8b050 100644
--- a/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp
+++ b/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp
@@ -33,6 +33,7 @@
#include <QtQuick/qquickitem.h>
#include <QtQml/private/qqmlengine_p.h>
#include <QtQml/private/qqmltypeloader_p.h>
+#include "../../shared/testhttpserver.h"
#include "../../shared/util.h"
class tst_QQMLTypeLoader : public QQmlDataTest
@@ -48,6 +49,7 @@ private slots:
void keepSingleton();
void keepRegistrations();
void intercept();
+ void redirect();
};
void tst_QQMLTypeLoader::testLoadComplete()
@@ -410,6 +412,22 @@ void tst_QQMLTypeLoader::intercept()
QVERIFY(factory.loadedFiles.contains(QLatin1String(QT_TESTCASE_BUILDDIR) + "/Slow/qmldir"));
}
+void tst_QQMLTypeLoader::redirect()
+{
+ TestHTTPServer server;
+ QVERIFY2(server.listen(), qPrintable(server.errorString()));
+ QVERIFY(server.serveDirectory(dataDirectory()));
+ server.addRedirect("Base.qml", server.urlString("/redirected/Redirected.qml"));
+
+ QQmlEngine engine;
+ QQmlComponent component(&engine);
+ component.loadUrl(server.urlString("/Load.qml"), QQmlComponent::Asynchronous);
+ QTRY_VERIFY2(component.isReady(), qPrintable(component.errorString()));
+
+ QObject *object = component.create();
+ QTRY_COMPARE(object->property("xy").toInt(), 323232);
+}
+
QTEST_MAIN(tst_QQMLTypeLoader)
#include "tst_qqmltypeloader.moc"
diff --git a/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.pro b/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.pro
index 3a20e94741..0352561e03 100644
--- a/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.pro
+++ b/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.pro
@@ -3,7 +3,12 @@ TARGET = tst_qqmltypeloader
QT += qml testlib qml-private quick
macx:CONFIG -= app_bundle
-SOURCES += tst_qqmltypeloader.cpp
+SOURCES += \
+ tst_qqmltypeloader.cpp \
+ ../../shared/testhttpserver.cpp
+
+HEADERS += \
+ ../../shared/testhttpserver.h
include (../../shared/util.pri)
diff --git a/tests/auto/quick/qquickanimatedsprite/qquickanimatedsprite.pro b/tests/auto/quick/qquickanimatedsprite/qquickanimatedsprite.pro
index 81c73be831..85f71bb605 100644
--- a/tests/auto/quick/qquickanimatedsprite/qquickanimatedsprite.pro
+++ b/tests/auto/quick/qquickanimatedsprite/qquickanimatedsprite.pro
@@ -11,4 +11,4 @@ TESTDATA = data/*
QT += core-private gui-private qml-private quick-private network testlib
OTHER_FILES += \
- data/largeAnimation.qml
+ $$files(data/*.qml)