aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOswald Buddenhagen <oswald.buddenhagen@qt.io>2018-10-30 00:49:43 +0100
committerOswald Buddenhagen <oswald.buddenhagen@qt.io>2018-10-30 00:49:43 +0100
commit708e4f7e626468f53636b7d2ef7c6a99c129751f (patch)
tree18e983f3aa8cc15c73a24ededc1eabdbb4c6d800
parent4207940684b578469f7ec6b428403af85e579b2c (diff)
parent475c74a9926efcd968572563e678988e53804603 (diff)
Merge 5.12 into 5.12.0
-rw-r--r--src/qml/compiler/qqmlirbuilder.cpp14
-rw-r--r--src/qml/jsruntime/qv4promiseobject_p.h11
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp4
-rw-r--r--src/qml/jsruntime/qv4regexpobject.cpp14
-rw-r--r--src/qml/jsruntime/qv4stringobject.cpp4
-rw-r--r--src/qml/jsruntime/qv4vme_moth.cpp2
-rw-r--r--src/qml/qml/qqmlcomponent.cpp18
-rw-r--r--src/qml/qml/qqmlmetatype.cpp29
-rw-r--r--src/quick/items/qquickflickable_p.h9
-rw-r--r--src/quick/items/qquicktext_p.h6
-rw-r--r--src/quick/util/qquickstategroup.cpp9
-rw-r--r--tests/auto/qml/qqmlecmascript/data/importLexicalVariables.mjs31
-rw-r--r--tests/auto/qml/qqmlecmascript/data/importLexicalVariables_module.mjs8
-rw-r--r--tests/auto/qml/qqmlecmascript/data/importLexicalVariables_module.qml10
-rw-r--r--tests/auto/qml/qqmlecmascript/data/importLexicalVariables_pragmaLibrary.js9
-rw-r--r--tests/auto/qml/qqmlecmascript/data/importLexicalVariables_pragmaLibrary.qml10
-rw-r--r--tests/auto/qml/qqmlecmascript/data/importLexicalVariables_script.js8
-rw-r--r--tests/auto/qml/qqmlecmascript/data/importLexicalVariables_script.qml10
-rw-r--r--tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp34
-rw-r--r--tests/auto/qml/qqmlincubator/data/garbageCollection.qml19
-rw-r--r--tests/auto/qml/qqmlincubator/tst_qqmlincubator.cpp30
-rw-r--r--tests/auto/qml/qqmllanguage/data/polymorphicFunctionLookup.qml14
-rw-r--r--tests/auto/qml/qqmllanguage/testtypes.h2
-rw-r--r--tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp13
-rw-r--r--tests/auto/quick/qquicklistview/tst_qquicklistview.cpp2
-rw-r--r--tests/auto/quick/qquickstates/data/duplicateStateName.qml13
-rw-r--r--tests/auto/quick/qquickstates/tst_qquickstates.cpp12
27 files changed, 308 insertions, 37 deletions
diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp
index 883b21ab07..9021fd0284 100644
--- a/src/qml/compiler/qqmlirbuilder.cpp
+++ b/src/qml/compiler/qqmlirbuilder.cpp
@@ -1947,11 +1947,7 @@ QQmlPropertyData *JSCodeGen::lookupQmlCompliantProperty(QQmlPropertyCache *cache
{
QQmlPropertyData *pd = cache->property(name, /*object*/nullptr, /*context*/nullptr);
- // Q_INVOKABLEs can't be FINAL, so we have to look them up at run-time
- if (!pd || pd->isFunction())
- return nullptr;
-
- if (!cache->isAllowedInRevision(pd))
+ if (pd && !cache->isAllowedInRevision(pd))
return nullptr;
return pd;
@@ -2280,6 +2276,10 @@ QV4::Compiler::Codegen::Reference JSCodeGen::fallbackNameLookup(const QString &n
if (_scopeObject) {
QQmlPropertyData *data = lookupQmlCompliantProperty(_scopeObject, name);
if (data) {
+ // Q_INVOKABLEs can't be FINAL, so we have to look them up at run-time
+ if (data->isFunction())
+ return Reference::fromName(this, name);
+
Reference base = Reference::fromStackSlot(this, _qmlContextSlot);
Reference::PropertyCapturePolicy capturePolicy;
if (!data->isConstant() && !data->isQmlBinding())
@@ -2293,6 +2293,10 @@ QV4::Compiler::Codegen::Reference JSCodeGen::fallbackNameLookup(const QString &n
if (_contextObject) {
QQmlPropertyData *data = lookupQmlCompliantProperty(_contextObject, name);
if (data) {
+ // Q_INVOKABLEs can't be FINAL, so we have to look them up at run-time
+ if (data->isFunction())
+ return Reference::fromName(this, name);
+
Reference base = Reference::fromStackSlot(this, _qmlContextSlot);
Reference::PropertyCapturePolicy capturePolicy;
if (!data->isConstant() && !data->isQmlBinding())
diff --git a/src/qml/jsruntime/qv4promiseobject_p.h b/src/qml/jsruntime/qv4promiseobject_p.h
index 80f7183074..bce59b19a7 100644
--- a/src/qml/jsruntime/qv4promiseobject_p.h
+++ b/src/qml/jsruntime/qv4promiseobject_p.h
@@ -39,6 +39,17 @@
#ifndef QV4PROMISEOBJECT_H
#define QV4PROMISEOBJECT_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4object_p.h"
#include "qv4functionobject_p.h"
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index 2e4223de7d..8cdec2f6ee 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -764,11 +764,11 @@ struct QObjectWrapperOwnPropertyKeyIterator : ObjectOwnPropertyKeyIterator
{
int propertyIndex = 0;
~QObjectWrapperOwnPropertyKeyIterator() override = default;
- PropertyKey next(const Object *o, Property *pd = nullptr, PropertyAttributes *attrs = nullptr) override;
+ PropertyKey next(const QV4::Object *o, Property *pd = nullptr, PropertyAttributes *attrs = nullptr) override;
};
-PropertyKey QObjectWrapperOwnPropertyKeyIterator::next(const Object *o, Property *pd, PropertyAttributes *attrs)
+PropertyKey QObjectWrapperOwnPropertyKeyIterator::next(const QV4::Object *o, Property *pd, PropertyAttributes *attrs)
{
// Used to block access to QObject::destroyed() and QObject::deleteLater() from QML
static const int destroyedIdx1 = QObject::staticMetaObject.indexOfSignal("destroyed(QObject*)");
diff --git a/src/qml/jsruntime/qv4regexpobject.cpp b/src/qml/jsruntime/qv4regexpobject.cpp
index 634fbcbd97..4ef4fa2c9e 100644
--- a/src/qml/jsruntime/qv4regexpobject.cpp
+++ b/src/qml/jsruntime/qv4regexpobject.cpp
@@ -238,20 +238,20 @@ void Heap::RegExpCtor::clearLastMatch()
lastMatchEnd = 0;
}
-static bool isRegExp(ExecutionEngine *e, const Value *arg)
+static bool isRegExp(ExecutionEngine *e, const QV4::Value *arg)
{
- const Object *o = arg->objectValue();
+ const QV4::Object *o = arg->objectValue();
if (!o)
return false;
- Value isRegExp = Value::fromReturnedValue(o->get(e->symbol_match()));
+ QV4::Value isRegExp = QV4::Value::fromReturnedValue(o->get(e->symbol_match()));
if (!isRegExp.isUndefined())
return isRegExp.toBoolean();
const RegExpObject *re = o->as<RegExpObject>();
return re ? true : false;
}
-uint parseFlags(Scope &scope, const Value *f)
+uint parseFlags(Scope &scope, const QV4::Value *f)
{
uint flags = CompiledData::RegExp::RegExp_NoFlags;
if (!f->isUndefined()) {
@@ -546,13 +546,13 @@ static int advanceStringIndex(int index, const QString &str, bool unicode)
return index;
}
-static void advanceLastIndexOnEmptyMatch(ExecutionEngine *e, bool unicode, Object *rx, const String *matchString, const QString &str)
+static void advanceLastIndexOnEmptyMatch(ExecutionEngine *e, bool unicode, QV4::Object *rx, const String *matchString, const QString &str)
{
Scope scope(e);
if (matchString->d()->length() == 0) {
- ScopedValue v(scope, rx->get(scope.engine->id_lastIndex()));
+ QV4::ScopedValue v(scope, rx->get(scope.engine->id_lastIndex()));
int lastIndex = advanceStringIndex(v->toLength(), str, unicode);
- if (!rx->put(scope.engine->id_lastIndex(), Value::fromInt32(lastIndex)))
+ if (!rx->put(scope.engine->id_lastIndex(), QV4::Value::fromInt32(lastIndex)))
scope.engine->throwTypeError();
}
}
diff --git a/src/qml/jsruntime/qv4stringobject.cpp b/src/qml/jsruntime/qv4stringobject.cpp
index f6b9c5ba94..03f351b9e4 100644
--- a/src/qml/jsruntime/qv4stringobject.cpp
+++ b/src/qml/jsruntime/qv4stringobject.cpp
@@ -112,11 +112,11 @@ bool StringObject::virtualDeleteProperty(Managed *m, PropertyKey id)
struct StringObjectOwnPropertyKeyIterator : ObjectOwnPropertyKeyIterator
{
~StringObjectOwnPropertyKeyIterator() override = default;
- PropertyKey next(const Object *o, Property *pd = nullptr, PropertyAttributes *attrs = nullptr) override;
+ PropertyKey next(const QV4::Object *o, Property *pd = nullptr, PropertyAttributes *attrs = nullptr) override;
};
-PropertyKey StringObjectOwnPropertyKeyIterator::next(const Object *o, Property *pd, PropertyAttributes *attrs)
+PropertyKey StringObjectOwnPropertyKeyIterator::next(const QV4::Object *o, Property *pd, PropertyAttributes *attrs)
{
const StringObject *s = static_cast<const StringObject *>(o);
uint slen = s->d()->string->toQString().length();
diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp
index 29814246db..1cca50f6c1 100644
--- a/src/qml/jsruntime/qv4vme_moth.cpp
+++ b/src/qml/jsruntime/qv4vme_moth.cpp
@@ -377,7 +377,7 @@ static bool compareEqualInt(QV4::Value &accumulator, QV4::Value lhs, int rhs)
if (lhs.m()->internalClass->vtable->isString)
return RuntimeHelpers::stringToNumber(static_cast<String &>(lhs).toQString()) == rhs;
accumulator = lhs;
- lhs = Value::fromReturnedValue(RuntimeHelpers::objectDefaultValue(&static_cast<QV4::Object &>(accumulator), PREFERREDTYPE_HINT));
+ lhs = QV4::Value::fromReturnedValue(RuntimeHelpers::objectDefaultValue(&static_cast<QV4::Object &>(accumulator), PREFERREDTYPE_HINT));
goto redo;
case QV4::Value::QT_Empty:
Q_UNREACHABLE();
diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp
index a67c5c4a2b..5ed3cc5d6a 100644
--- a/src/qml/qml/qqmlcomponent.cpp
+++ b/src/qml/qml/qqmlcomponent.cpp
@@ -1132,22 +1132,23 @@ class QQmlComponentIncubator : public QQmlIncubator
public:
QQmlComponentIncubator(QV4::Heap::QmlIncubatorObject *inc, IncubationMode mode)
: QQmlIncubator(mode)
- , incubatorObject(inc)
- {}
+ {
+ incubatorObject.set(inc->internalClass->engine, inc);
+ }
void statusChanged(Status s) override {
- QV4::Scope scope(incubatorObject->internalClass->engine);
- QV4::Scoped<QV4::QmlIncubatorObject> i(scope, incubatorObject);
+ QV4::Scope scope(incubatorObject.engine());
+ QV4::Scoped<QV4::QmlIncubatorObject> i(scope, incubatorObject.as<QV4::QmlIncubatorObject>());
i->statusChanged(s);
}
void setInitialState(QObject *o) override {
- QV4::Scope scope(incubatorObject->internalClass->engine);
- QV4::Scoped<QV4::QmlIncubatorObject> i(scope, incubatorObject);
+ QV4::Scope scope(incubatorObject.engine());
+ QV4::Scoped<QV4::QmlIncubatorObject> i(scope, incubatorObject.as<QV4::QmlIncubatorObject>());
i->setInitialState(o);
}
- QV4::Heap::QmlIncubatorObject *incubatorObject;
+ QV4::PersistentValue incubatorObject; // keep a strong internal reference while incubating
};
@@ -1571,6 +1572,9 @@ void QV4::QmlIncubatorObject::statusChanged(QQmlIncubator::Status s)
QQmlEnginePrivate::warning(QQmlEnginePrivate::get(scope.engine->qmlEngine()), error);
}
}
+
+ if (s != QQmlIncubator::Loading)
+ d()->incubator->incubatorObject.clear();
}
#undef INITIALPROPERTIES_SOURCE
diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp
index ea4a69f05d..ba8d5831ad 100644
--- a/src/qml/qml/qqmlmetatype.cpp
+++ b/src/qml/qml/qqmlmetatype.cpp
@@ -847,21 +847,40 @@ void QQmlTypePrivate::insertEnums(const QMetaObject *metaObject) const
}
}
+ QSet<QString> localEnums;
+ const QMetaObject *localMetaObject = nullptr;
+
// Add any enum values defined by this class, overwriting any inherited values
for (int ii = 0; ii < metaObject->enumeratorCount(); ++ii) {
QMetaEnum e = metaObject->enumerator(ii);
const bool isScoped = e.isScoped();
QStringHash<int> *scoped = isScoped ? new QStringHash<int>() : nullptr;
+ // We allow enums in sub-classes to overwrite enums from base-classes, such as
+ // ListView.Center (from enum PositionMode) overwriting Item.Center (from enum TransformOrigin).
+ // This is acceptable because the _use_ of the enum from the QML side requires qualification
+ // anyway, i.e. ListView.Center vs. Item.Center.
+ // However if a class defines two enums with the same value, then that must produce a warning
+ // because it represents a valid conflict.
+ if (e.enclosingMetaObject() != localMetaObject) {
+ localEnums.clear();
+ localMetaObject = e.enclosingMetaObject();
+ }
+
for (int jj = 0; jj < e.keyCount(); ++jj) {
const QString key = QString::fromUtf8(e.key(jj));
const int value = e.value(jj);
if (!isScoped || (regType == QQmlType::CppType && extraData.cd->registerEnumClassesUnscoped)) {
- if (enums.contains(key)) {
- qWarning("Previously registered enum will be overwritten due to name clash: %s.%s", metaObject->className(), key.toUtf8().constData());
- createEnumConflictReport(metaObject, key);
- }
- enums.insert(key, value);
+ if (localEnums.contains(key)) {
+ auto existingEntry = enums.find(key);
+ if (existingEntry != enums.end() && existingEntry.value() != value) {
+ qWarning("Previously registered enum will be overwritten due to name clash: %s.%s", metaObject->className(), key.toUtf8().constData());
+ createEnumConflictReport(metaObject, key);
+ }
+ } else {
+ localEnums.insert(key);
+ }
+ enums.insert(key, value);
}
if (isScoped)
scoped->insert(key, value);
diff --git a/src/quick/items/qquickflickable_p.h b/src/quick/items/qquickflickable_p.h
index 1bd8fc1020..b7c4fa5b67 100644
--- a/src/quick/items/qquickflickable_p.h
+++ b/src/quick/items/qquickflickable_p.h
@@ -267,10 +267,11 @@ Q_SIGNALS:
Q_REVISION(9) void horizontalOvershootChanged();
Q_REVISION(9) void verticalOvershootChanged();
- Q_REVISION(12) void atXEndChanged();
- Q_REVISION(12) void atYEndChanged();
- Q_REVISION(12) void atXBeginningChanged();
- Q_REVISION(12) void atYBeginningChanged();
+ // The next four signals should be marked as Q_REVISION(12). See QTBUG-71243
+ void atXEndChanged();
+ void atYEndChanged();
+ void atXBeginningChanged();
+ void atYBeginningChanged();
protected:
bool childMouseEventFilter(QQuickItem *, QEvent *) override;
diff --git a/src/quick/items/qquicktext_p.h b/src/quick/items/qquicktext_p.h
index f4e7fa7046..1af60051fb 100644
--- a/src/quick/items/qquicktext_p.h
+++ b/src/quick/items/qquicktext_p.h
@@ -272,8 +272,10 @@ Q_SIGNALS:
void textFormatChanged(QQuickText::TextFormat textFormat);
void elideModeChanged(QQuickText::TextElideMode mode);
void contentSizeChanged();
- Q_REVISION(12) void contentWidthChanged(qreal contentWidth);
- Q_REVISION(12) void contentHeightChanged(qreal contentHeight);
+ // The next two signals should be marked as Q_REVISION(12). See QTBUG-71247
+ void contentWidthChanged(qreal contentWidth);
+ void contentHeightChanged(qreal contentHeight);
+
void lineHeightChanged(qreal lineHeight);
void lineHeightModeChanged(LineHeightMode mode);
void fontSizeModeChanged();
diff --git a/src/quick/util/qquickstategroup.cpp b/src/quick/util/qquickstategroup.cpp
index c852c16509..d8daec2f07 100644
--- a/src/quick/util/qquickstategroup.cpp
+++ b/src/quick/util/qquickstategroup.cpp
@@ -302,10 +302,19 @@ void QQuickStateGroup::componentComplete()
Q_D(QQuickStateGroup);
d->componentComplete = true;
+ QVarLengthArray<QString, 4> names;
+ names.reserve(d->states.count());
for (int ii = 0; ii < d->states.count(); ++ii) {
QQuickState *state = d->states.at(ii);
if (!state->isNamed())
state->setName(QLatin1String("anonymousState") + QString::number(++d->unnamedCount));
+
+ const QString stateName = state->name();
+ if (names.contains(stateName)) {
+ qmlWarning(state->parent()) << "Found duplicate state name: " << stateName;
+ } else {
+ names.append(std::move(stateName));
+ }
}
if (d->updateAutoState()) {
diff --git a/tests/auto/qml/qqmlecmascript/data/importLexicalVariables.mjs b/tests/auto/qml/qqmlecmascript/data/importLexicalVariables.mjs
new file mode 100644
index 0000000000..19c012d19b
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/importLexicalVariables.mjs
@@ -0,0 +1,31 @@
+export function runTest(libraryUnderTest) {
+ let state1 = state(libraryUnderTest);
+ try { modifyFromOutside(libraryUnderTest); } catch (e) {}
+ let state2 = state(libraryUnderTest);
+ try { modifyFromInside(libraryUnderTest); } catch (e) {}
+ let state3 = state(libraryUnderTest);
+ return state1 + " " + state2 + " " + state3;
+}
+
+function stringify(value) {
+ let s = "?";
+ if (value !== undefined)
+ s = value.toString();
+ return s;
+}
+
+function state(libraryUnderTest) {
+ return (stringify(libraryUnderTest.varValue) +
+ stringify(libraryUnderTest.letValue) +
+ stringify(libraryUnderTest.constValue));
+}
+
+function modifyFromOutside(libraryUnderTest) {
+ ++libraryUnderTest.varValue;
+ ++libraryUnderTest.letValue;
+ ++libraryUnderTest.constValue;
+}
+
+function modifyFromInside(libraryUnderTest) {
+ libraryUnderTest.incrementAll();
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/importLexicalVariables_module.mjs b/tests/auto/qml/qqmlecmascript/data/importLexicalVariables_module.mjs
new file mode 100644
index 0000000000..b6eb1a2623
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/importLexicalVariables_module.mjs
@@ -0,0 +1,8 @@
+export var varValue = 0;
+export let letValue = 0;
+export const constValue = 0;
+export function incrementAll() {
+ ++varValue;
+ ++letValue;
+ ++constValue;
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/importLexicalVariables_module.qml b/tests/auto/qml/qqmlecmascript/data/importLexicalVariables_module.qml
new file mode 100644
index 0000000000..bb4e759cbf
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/importLexicalVariables_module.qml
@@ -0,0 +1,10 @@
+import QtQuick 2.0
+import "importLexicalVariables.mjs" as TestRunner
+import "importLexicalVariables_module.mjs" as LibraryUnderTest
+
+QtObject {
+ id: root
+ function runTest() {
+ return TestRunner.runTest(LibraryUnderTest);
+ }
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/importLexicalVariables_pragmaLibrary.js b/tests/auto/qml/qqmlecmascript/data/importLexicalVariables_pragmaLibrary.js
new file mode 100644
index 0000000000..f8c215a5e7
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/importLexicalVariables_pragmaLibrary.js
@@ -0,0 +1,9 @@
+.pragma library
+var varValue = 0;
+let letValue = 0;
+const constValue = 0;
+function incrementAll() {
+ ++varValue;
+ ++letValue;
+ ++constValue;
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/importLexicalVariables_pragmaLibrary.qml b/tests/auto/qml/qqmlecmascript/data/importLexicalVariables_pragmaLibrary.qml
new file mode 100644
index 0000000000..1b3fe7fa2e
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/importLexicalVariables_pragmaLibrary.qml
@@ -0,0 +1,10 @@
+import QtQuick 2.0
+import "importLexicalVariables.mjs" as TestRunner
+import "importLexicalVariables_pragmaLibrary.js" as LibraryUnderTest
+
+QtObject {
+ id: root
+ function runTest() {
+ return TestRunner.runTest(LibraryUnderTest);
+ }
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/importLexicalVariables_script.js b/tests/auto/qml/qqmlecmascript/data/importLexicalVariables_script.js
new file mode 100644
index 0000000000..4fb68abc87
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/importLexicalVariables_script.js
@@ -0,0 +1,8 @@
+var varValue = 0;
+let letValue = 0;
+const constValue = 0;
+function incrementAll() {
+ ++varValue;
+ ++letValue;
+ ++constValue;
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/importLexicalVariables_script.qml b/tests/auto/qml/qqmlecmascript/data/importLexicalVariables_script.qml
new file mode 100644
index 0000000000..263511e802
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/importLexicalVariables_script.qml
@@ -0,0 +1,10 @@
+import QtQuick 2.0
+import "importLexicalVariables.mjs" as TestRunner
+import "importLexicalVariables_script.js" as LibraryUnderTest
+
+QtObject {
+ id: root
+ function runTest() {
+ return TestRunner.runTest(LibraryUnderTest);
+ }
+}
diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
index cf3eecff6d..8f388fcac6 100644
--- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
+++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
@@ -357,6 +357,8 @@ private slots:
void jumpStrictNotEqualUndefined();
void removeBindingsWithNoDependencies();
void temporaryDeadZone();
+ void importLexicalVariables_data();
+ void importLexicalVariables();
private:
// static void propertyVarWeakRefCallback(v8::Persistent<v8::Value> object, void* parameter);
@@ -8812,6 +8814,38 @@ void tst_qqmlecmascript::temporaryDeadZone()
QVERIFY(v.isError());
}
+void tst_qqmlecmascript::importLexicalVariables_data()
+{
+ QTest::addColumn<QUrl>("testFile");
+ QTest::addColumn<QString>("expected");
+
+ QTest::newRow("script")
+ << testFileUrl("importLexicalVariables_script.qml")
+ << QStringLiteral("0?? 1?? 2??");
+ QTest::newRow("pragmaLibrary")
+ << testFileUrl("importLexicalVariables_pragmaLibrary.qml")
+ << QStringLiteral("0?? 1?? 2??");
+ QTest::newRow("module")
+ << testFileUrl("importLexicalVariables_module.qml")
+ << QStringLiteral("000 000 110");
+}
+
+void tst_qqmlecmascript::importLexicalVariables()
+{
+ QFETCH(QUrl, testFile);
+ QFETCH(QString, expected);
+
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFile);
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(object != nullptr);
+ QVERIFY(!component.isError());
+
+ QVariant result;
+ QMetaObject::invokeMethod(object.data(), "runTest", Qt::DirectConnection, Q_RETURN_ARG(QVariant, result));
+ QCOMPARE(result, QVariant(expected));
+}
+
QTEST_MAIN(tst_qqmlecmascript)
#include "tst_qqmlecmascript.moc"
diff --git a/tests/auto/qml/qqmlincubator/data/garbageCollection.qml b/tests/auto/qml/qqmlincubator/data/garbageCollection.qml
new file mode 100644
index 0000000000..6866a02a00
--- /dev/null
+++ b/tests/auto/qml/qqmlincubator/data/garbageCollection.qml
@@ -0,0 +1,19 @@
+import QtQuick 2.0
+
+QtObject {
+ id: root
+
+ property var incubator
+
+ function getAndClearIncubator() {
+ var result = incubator
+ incubator = null
+ return result
+ }
+
+ Component.onCompleted: {
+ var c = Qt.createComponent("statusChanged.qml"); // use existing simple type for convenience
+ var incubator = c.incubateObject(root);
+ incubator.onStatusChanged = function(status) { if (status === 1) root.incubator = incubator }
+ }
+}
diff --git a/tests/auto/qml/qqmlincubator/tst_qqmlincubator.cpp b/tests/auto/qml/qqmlincubator/tst_qqmlincubator.cpp
index 8f0e04e12e..8e25079703 100644
--- a/tests/auto/qml/qqmlincubator/tst_qqmlincubator.cpp
+++ b/tests/auto/qml/qqmlincubator/tst_qqmlincubator.cpp
@@ -39,6 +39,7 @@
#include <QQmlComponent>
#include <QQmlIncubator>
#include "../../shared/util.h"
+#include <private/qjsvalue_p.h>
#include <private/qqmlincubator_p.h>
#include <private/qqmlobjectcreator_p.h>
@@ -68,6 +69,7 @@ private slots:
void chainedAsynchronousClear();
void selfDelete();
void contextDelete();
+ void garbageCollection();
private:
QQmlIncubationController controller;
@@ -1144,6 +1146,34 @@ void tst_qqmlincubator::contextDelete()
}
}
+// QTBUG-53111
+void tst_qqmlincubator::garbageCollection()
+{
+ QQmlComponent component(&engine, testFileUrl("garbageCollection.qml"));
+ QScopedPointer<QObject> obj(component.create());
+
+ engine.collectGarbage();
+
+ bool b = true;
+ controller.incubateWhile(&b);
+
+ // verify incubation completed (the incubator was not prematurely collected)
+ QVariant incubatorVariant;
+ QMetaObject::invokeMethod(obj.data(), "getAndClearIncubator", Q_RETURN_ARG(QVariant, incubatorVariant));
+ QJSValue strongRef = incubatorVariant.value<QJSValue>();
+ QVERIFY(!strongRef.isNull() && !strongRef.isUndefined());
+
+ // turn the last strong reference to the incubator into a weak one and collect
+ QV4::WeakValue weakIncubatorRef;
+ weakIncubatorRef.set(QQmlEnginePrivate::getV4Engine(&engine), *QJSValuePrivate::getValue(&strongRef));
+ strongRef = QJSValue();
+ incubatorVariant.clear();
+
+ // verify incubator is correctly collected now that incubation is complete and all references are gone
+ engine.collectGarbage();
+ QVERIFY(weakIncubatorRef.isNullOrUndefined());
+}
+
QTEST_MAIN(tst_qqmlincubator)
#include "tst_qqmlincubator.moc"
diff --git a/tests/auto/qml/qqmllanguage/data/polymorphicFunctionLookup.qml b/tests/auto/qml/qqmllanguage/data/polymorphicFunctionLookup.qml
new file mode 100644
index 0000000000..4a3cc52793
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/polymorphicFunctionLookup.qml
@@ -0,0 +1,14 @@
+import QtQml 2.0
+QtObject {
+ id: root
+ property bool testFunc;
+ property bool ok: false
+ property QtObject subObject: QtObject {
+ function testFunc()
+ {
+ root.ok = true
+ }
+
+ Component.onCompleted: testFunc()
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/testtypes.h b/tests/auto/qml/qqmllanguage/testtypes.h
index d890668655..bb6e9582c2 100644
--- a/tests/auto/qml/qqmllanguage/testtypes.h
+++ b/tests/auto/qml/qqmllanguage/testtypes.h
@@ -1392,7 +1392,7 @@ class ScopedEnumsWithNameClash
public:
enum class ScopedEnum : int { ScopedVal1, ScopedVal2, ScopedVal3, OtherScopedEnum };
- enum class OtherScopedEnum : int { ScopedVal1, ScopedVal2, ScopedVal3 };
+ enum class OtherScopedEnum : int { ScopedVal1 = 10, ScopedVal2 = 11, ScopedVal3 = 12 };
};
class ScopedEnumsWithResolvedNameClash
diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
index 157fd500ad..7a8de739f4 100644
--- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
+++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
@@ -298,6 +298,8 @@ private slots:
void retrieveQmlTypeId();
+ void polymorphicFunctionLookup();
+
private:
QQmlEngine engine;
QStringList defaultImportPathList;
@@ -5049,6 +5051,17 @@ void tst_qqmllanguage::retrieveQmlTypeId()
QVERIFY(qmlTypeId("Test", 1, 0, "MyTypeObjectSingleton") >= 0);
}
+void tst_qqmllanguage::polymorphicFunctionLookup()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("polymorphicFunctionLookup.qml"));
+ VERIFY_ERRORS(0);
+ QScopedPointer<QObject> o(component.create());
+ QVERIFY(!o.isNull());
+
+ QVERIFY(o->property("ok").toBool());
+}
+
QTEST_MAIN(tst_qqmllanguage)
#include "tst_qqmllanguage.moc"
diff --git a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
index ae02352293..ff796a5bd8 100644
--- a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
+++ b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
@@ -2676,7 +2676,7 @@ void tst_QQuickListView::sectionsSnap_data()
QTest::addColumn<int>("duration");
QTest::newRow("drag") << QQuickListView::NoSnap << QPoint(100, 45) << 500;
- QTest::newRow("flick") << QQuickListView::SnapOneItem << QPoint(100, 75) << 50;
+ QTest::newRow("flick") << QQuickListView::SnapOneItem << QPoint(100, 60) << 100;
}
void tst_QQuickListView::sectionsSnap()
diff --git a/tests/auto/quick/qquickstates/data/duplicateStateName.qml b/tests/auto/quick/qquickstates/data/duplicateStateName.qml
new file mode 100644
index 0000000000..7bfafbef1b
--- /dev/null
+++ b/tests/auto/quick/qquickstates/data/duplicateStateName.qml
@@ -0,0 +1,13 @@
+import QtQuick 2.0
+
+Rectangle {
+ property bool condition1: false
+ property bool condition2: false
+ property bool condition3: false
+
+ states: [
+ State { name: "state1"; when: condition1 },
+ State { name: "state2"; when: condition2 },
+ State { name: "state1"; when: condition3 }
+ ]
+}
diff --git a/tests/auto/quick/qquickstates/tst_qquickstates.cpp b/tests/auto/quick/qquickstates/tst_qquickstates.cpp
index 073fe33e20..50554f6333 100644
--- a/tests/auto/quick/qquickstates/tst_qquickstates.cpp
+++ b/tests/auto/quick/qquickstates/tst_qquickstates.cpp
@@ -137,6 +137,7 @@ private slots:
void revertListBug();
void QTBUG_38492();
void revertListMemoryLeak();
+ void duplicateStateName();
};
void tst_qquickstates::initTestCase()
@@ -1654,6 +1655,17 @@ void tst_qquickstates::revertListMemoryLeak()
QVERIFY(bindingPtr->ref == 1);
}
+void tst_qquickstates::duplicateStateName()
+{
+ QQmlEngine engine;
+
+ QQmlComponent c(&engine, testFileUrl("duplicateStateName.qml"));
+ QTest::ignoreMessage(QtWarningMsg, fullDataPath("duplicateStateName.qml") + ":3:1: QML Rectangle: Found duplicate state name: state1");
+ QScopedPointer<QQuickItem> item(qobject_cast<QQuickItem *>(c.create()));
+ QVERIFY(!item.isNull());
+}
+
+
QTEST_MAIN(tst_qquickstates)
#include "tst_qquickstates.moc"