aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQt Forward Merge Bot <qt_forward_merge_bot@qt-project.org>2019-03-23 01:00:08 +0100
committerUlf Hermann <ulf.hermann@qt.io>2019-03-25 10:13:23 +0100
commita1e38651ce245edcd8628bc8e2aad7e83184066e (patch)
tree27d3a68ac4204975faa6d0d427970fb1013e0ed4
parent3980ccf785462dc7b2cb53f72790638eb9e7b8c0 (diff)
parent42ed40cf0abd0155d6e6d1ef01faf9bded065588 (diff)
Merge remote-tracking branch 'origin/5.12' into 5.13
Conflicts: .qmake.conf src/qmltest/quicktest.cpp tests/auto/qml/qmlcachegen/qmlcachegen.pro Change-Id: I70e96e8817d59647f876b8b77b30cdeede8f0662
-rw-r--r--src/plugins/qmltooling/qmldbg_preview/qqmlpreviewhandler.cpp66
-rw-r--r--src/plugins/qmltooling/qmldbg_preview/qqmlpreviewhandler.h2
-rw-r--r--src/plugins/qmltooling/qmldbg_preview/qqmlpreviewposition.cpp146
-rw-r--r--src/plugins/qmltooling/qmldbg_preview/qqmlpreviewposition.h37
-rw-r--r--src/qml/compiler/qqmlirbuilder.cpp2
-rw-r--r--src/qml/compiler/qv4codegen.cpp85
-rw-r--r--src/qml/compiler/qv4compileddata.cpp10
-rw-r--r--src/qml/compiler/qv4compileddata_p.h4
-rw-r--r--src/qml/jsruntime/qv4qmlcontext.cpp165
-rw-r--r--src/qml/jsruntime/qv4qmlcontext_p.h1
-rw-r--r--src/qmltest/doc/src/qtquicktest-index.qdoc13
-rw-r--r--src/qmltest/quicktest.cpp12
-rw-r--r--tests/auto/qml/debugger/qqmlpreview/tst_qqmlpreview.cpp12
-rw-r--r--tests/auto/qml/qjsengine/tst_qjsengine.cpp10
-rw-r--r--tests/auto/qml/qmlcachegen/data/Enums.qml (renamed from tests/auto/qml/qmlcachegen/Enums.qml)0
-rw-r--r--tests/auto/qml/qmlcachegen/data/Retain.qml (renamed from tests/auto/qml/qmlcachegen/Retain.qml)0
-rw-r--r--tests/auto/qml/qmlcachegen/data/componentInItem.qml15
-rw-r--r--tests/auto/qml/qmlcachegen/data/jsimport.qml (renamed from tests/auto/qml/qmlcachegen/jsimport.qml)0
-rw-r--r--tests/auto/qml/qmlcachegen/data/jsmoduleimport.qml (renamed from tests/auto/qml/qmlcachegen/jsmoduleimport.qml)0
-rw-r--r--tests/auto/qml/qmlcachegen/data/library.js (renamed from tests/auto/qml/qmlcachegen/library.js)0
-rw-r--r--tests/auto/qml/qmlcachegen/data/script.js (renamed from tests/auto/qml/qmlcachegen/script.js)0
-rw-r--r--tests/auto/qml/qmlcachegen/data/script.mjs (renamed from tests/auto/qml/qmlcachegen/script.mjs)0
-rw-r--r--tests/auto/qml/qmlcachegen/data/trickypaths.qml (renamed from tests/auto/qml/qmlcachegen/trickypaths.qml)0
-rw-r--r--tests/auto/qml/qmlcachegen/data/umlaut.qml (renamed from tests/auto/qml/qmlcachegen/umlaut.qml)0
-rw-r--r--tests/auto/qml/qmlcachegen/data/versionStyleSuffix-1.2-core-yc.qml (renamed from tests/auto/qml/qmlcachegen/versionStyleSuffix-1.2-core-yc.qml)0
-rw-r--r--tests/auto/qml/qmlcachegen/data/versionStyleSuffix-1.2-more.qml (renamed from tests/auto/qml/qmlcachegen/versionStyleSuffix-1.2-more.qml)0
-rw-r--r--tests/auto/qml/qmlcachegen/data/versionchecks.qml (renamed from tests/auto/qml/qmlcachegen/versionchecks.qml)0
-rw-r--r--tests/auto/qml/qmlcachegen/data/worker.js (renamed from tests/auto/qml/qmlcachegen/worker.js)0
-rw-r--r--tests/auto/qml/qmlcachegen/data/worker.qml (renamed from tests/auto/qml/qmlcachegen/worker.qml)0
-rw-r--r--tests/auto/qml/qmlcachegen/qmlcachegen.pro32
-rw-r--r--tests/auto/qml/qmlcachegen/retain.qrc2
-rw-r--r--tests/auto/qml/qmlcachegen/trickypaths.qrc6
-rw-r--r--tests/auto/qml/qmlcachegen/trickypaths_umlaut.qrc2
-rw-r--r--tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp86
-rw-r--r--tests/auto/quick/qquickmultipointtoucharea/BLACKLIST4
-rw-r--r--tests/auto/quick/qquickrectangle/tst_qquickrectangle.cpp6
-rw-r--r--tests/auto/quick/qquickwindow/tst_qquickwindow.cpp18
-rw-r--r--tests/auto/quicktest/quicktestmainwithsetup/data/tst_setup.qml6
-rw-r--r--tests/auto/quicktest/quicktestmainwithsetup/imports/ImportPathQmlModule/ImportPathQmlType.qml3
-rw-r--r--tests/auto/quicktest/quicktestmainwithsetup/imports/ImportPathQmlModule/qmldir2
-rw-r--r--tests/auto/quicktest/quicktestmainwithsetup/tst_quicktestmainwithsetup.cpp14
-rw-r--r--tools/qmlcachegen/qmlcachegen.cpp5
42 files changed, 523 insertions, 243 deletions
diff --git a/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewhandler.cpp b/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewhandler.cpp
index 5bd96af582..5d2684b510 100644
--- a/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewhandler.cpp
+++ b/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewhandler.cpp
@@ -106,16 +106,9 @@ static void closeAllWindows()
bool QQmlPreviewHandler::eventFilter(QObject *obj, QEvent *event)
{
- if (event->type() == QEvent::Show) {
- if (QWindow *window = qobject_cast<QQuickWindow*>(obj)) {
- m_lastPosition.initLastSavedWindowPosition(window);
- }
- }
- if (m_currentWindow && (event->type() == QEvent::Move || event->type() == QEvent::Resize) &&
+ if (m_currentWindow && (event->type() == QEvent::Move) &&
qobject_cast<QQuickWindow*>(obj) == m_currentWindow) {
- // we always start with factor 1 so calculate and save the origin as it would be not scaled
- m_lastPosition.setPosition(m_currentWindow->framePosition() *
- QHighDpiScaling::factor(m_currentWindow));
+ m_lastPosition.takePosition(m_currentWindow);
}
return QObject::eventFilter(obj, event);
@@ -196,49 +189,38 @@ void QQmlPreviewHandler::rerun()
void QQmlPreviewHandler::zoom(qreal newFactor)
{
+ m_zoomFactor = newFactor;
+ QTimer::singleShot(0, this, &QQmlPreviewHandler::doZoom);
+}
+
+void QQmlPreviewHandler::doZoom()
+{
if (!m_currentWindow)
return;
- if (qFuzzyIsNull(newFactor)) {
+ if (qFuzzyIsNull(m_zoomFactor)) {
emit error(QString::fromLatin1("Zooming with factor: %1 will result in nothing " \
- "so it will be ignored.").arg(newFactor));
+ "so it will be ignored.").arg(m_zoomFactor));
return;
}
- QString errorMessage;
- bool resetZoom = false;
- if (newFactor < 0) {
+ bool resetZoom = false;
+ if (m_zoomFactor < 0) {
resetZoom = true;
- newFactor = 1.0;
+ m_zoomFactor = 1.0;
}
- // On single-window devices we allow any scale factor as the window will adapt to the screen.
- if (m_supportsMultipleWindows) {
- const QSize newAvailableScreenSize = QQmlPreviewPosition::currentScreenSize(m_currentWindow)
- * QHighDpiScaling::factor(m_currentWindow) / newFactor;
- if (m_currentWindow->size().width() > newAvailableScreenSize.width()) {
- errorMessage = QString::fromLatin1(
- "Zooming with factor: "
- "%1 will result in a too wide preview.").arg(newFactor);
- }
- if (m_currentWindow->size().height() > newAvailableScreenSize.height()) {
- errorMessage = QString::fromLatin1(
- "Zooming with factor: "
- "%1 will result in a too heigh preview.").arg(newFactor);
- }
- }
+ m_currentWindow->setGeometry(m_currentWindow->geometry());
- if (errorMessage.isEmpty()) {
- const QPoint newToOriginMappedPosition = m_currentWindow->position() *
- QHighDpiScaling::factor(m_currentWindow) / newFactor;
- m_currentWindow->destroy();
- QHighDpiScaling::setScreenFactor(m_currentWindow->screen(), newFactor);
- if (resetZoom)
- QHighDpiScaling::updateHighDpiScaling();
- m_currentWindow->setPosition(newToOriginMappedPosition);
- m_currentWindow->show();
- } else {
- emit error(errorMessage);
- }
+ m_lastPosition.takePosition(m_currentWindow, QQmlPreviewPosition::InitializePosition);
+ m_currentWindow->destroy();
+
+ for (QScreen *screen : QGuiApplication::screens())
+ QHighDpiScaling::setScreenFactor(screen, m_zoomFactor);
+ if (resetZoom)
+ QHighDpiScaling::updateHighDpiScaling();
+
+ m_currentWindow->show();
+ m_lastPosition.initLastSavedWindowPosition(m_currentWindow);
}
void QQmlPreviewHandler::removeTranslators()
diff --git a/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewhandler.h b/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewhandler.h
index 21ea672580..47491b9d8f 100644
--- a/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewhandler.h
+++ b/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewhandler.h
@@ -104,6 +104,7 @@ signals:
protected:
bool eventFilter(QObject *obj, QEvent *event);
private:
+ void doZoom();
void tryCreateObject();
void showObject(QObject *object);
void setCurrentWindow(QQuickWindow *window);
@@ -121,6 +122,7 @@ private:
QVector<QPointer<QObject>> m_createdObjects;
QScopedPointer<QQmlComponent> m_component;
QPointer<QQuickWindow> m_currentWindow;
+ qreal m_zoomFactor = 1.0;
bool m_supportsMultipleWindows;
QQmlPreviewPosition m_lastPosition;
diff --git a/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewposition.cpp b/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewposition.cpp
index 3edcbac0a9..d4acd24da5 100644
--- a/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewposition.cpp
+++ b/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewposition.cpp
@@ -42,14 +42,47 @@
#include <QtGui/qwindow.h>
#include <QtGui/qscreen.h>
#include <QtGui/qguiapplication.h>
+#include <private/qhighdpiscaling_p.h>
QT_BEGIN_NAMESPACE
-static const QSize availableScreenSize(const QPoint &point)
+static QVector<QQmlPreviewPosition::ScreenData> initScreensData()
{
- if (const QScreen *screen = QGuiApplication::screenAt(point))
- return screen->availableGeometry().size();
- return QSize();
+ QVector<QQmlPreviewPosition::ScreenData> screensData;
+
+ for (QScreen *screen : QGuiApplication::screens()) {
+ QQmlPreviewPosition::ScreenData sd{screen->name(), screen->size()};
+ screensData.append(sd);
+ }
+ return screensData;
+}
+
+static QScreen *findScreen(const QString &nameOfScreen)
+{
+ for (QScreen *screen : QGuiApplication::screens()) {
+ if (screen->name() == nameOfScreen)
+ return screen;
+ }
+ return nullptr;
+}
+
+static QDataStream &operator<<(QDataStream &out, const QQmlPreviewPosition::ScreenData &screenData)
+{
+ out << screenData.name;
+ out << screenData.size;
+ return out;
+}
+
+static QDataStream &operator>>(QDataStream &in, QQmlPreviewPosition::ScreenData &screenData)
+{
+ in >> screenData.name;
+ in >> screenData.size;
+ return in;
+}
+
+bool QQmlPreviewPosition::ScreenData::operator==(const QQmlPreviewPosition::ScreenData &other) const
+{
+ return other.size == size && other.name == name;
}
QQmlPreviewPosition::QQmlPreviewPosition()
@@ -62,20 +95,36 @@ QQmlPreviewPosition::QQmlPreviewPosition()
});
}
-void QQmlPreviewPosition::setPosition(const QPoint &point)
+QQmlPreviewPosition::~QQmlPreviewPosition()
+{
+ saveWindowPosition();
+}
+
+void QQmlPreviewPosition::takePosition(QWindow *window, InitializeState state)
{
- m_hasPosition = true;
- m_lastWindowPosition = point;
- m_savePositionTimer.start();
+ Q_ASSERT(window);
+ // only save the position if we already tried to get the last saved position
+ if (m_initializeState == PositionInitialized) {
+ m_hasPosition = true;
+ auto screen = window->screen();
+ auto nativePosition = QHighDpiScaling::mapPositionToNative(window->framePosition(),
+ screen->handle());
+ m_lastWindowPosition = {screen->name(), nativePosition};
+
+ m_savePositionTimer.start();
+ }
+ if (state == InitializePosition)
+ m_initializeState = InitializePosition;
}
void QQmlPreviewPosition::saveWindowPosition()
{
if (m_hasPosition) {
+ const QByteArray positionAsByteArray = fromPositionToByteArray(m_lastWindowPosition);
if (!m_settingsKey.isNull())
- m_settings.setValue(m_settingsKey, m_lastWindowPosition);
+ m_settings.setValue(m_settingsKey, positionAsByteArray);
- m_settings.setValue(QLatin1String("global_lastpostion"), m_lastWindowPosition);
+ m_settings.setValue(QLatin1String("global_lastpostion"), positionAsByteArray);
}
}
@@ -85,29 +134,86 @@ void QQmlPreviewPosition::loadWindowPositionSettings(const QUrl &url)
if (m_settings.contains(m_settingsKey)) {
m_hasPosition = true;
- m_lastWindowPosition = m_settings.value(m_settingsKey).toPoint();
+ readLastPositionFromByteArray(m_settings.value(m_settingsKey).toByteArray());
}
}
void QQmlPreviewPosition::initLastSavedWindowPosition(QWindow *window)
{
- if (m_positionedWindows.contains(window))
- return;
+ Q_ASSERT(window);
+ m_initializeState = PositionInitialized;
+ if (m_currentInitScreensData.isEmpty())
+ m_currentInitScreensData = initScreensData();
+ // if it is the first time we just use the fall back from a last shown qml file
if (!m_hasPosition) {
- // in case there was nothing saved, we do not want to set anything
if (!m_settings.contains(QLatin1String("global_lastpostion")))
return;
- m_lastWindowPosition = m_settings.value(QLatin1String("global_lastpostion")).toPoint();
+ readLastPositionFromByteArray(m_settings.value(QLatin1String("global_lastpostion"))
+ .toByteArray());
}
- if (QGuiApplication::screenAt(m_lastWindowPosition))
- window->setFramePosition(m_lastWindowPosition);
+ setPosition(m_lastWindowPosition, window);
+}
+
+QByteArray QQmlPreviewPosition::fromPositionToByteArray(
+ const QQmlPreviewPosition::Position &position)
+{
+ QByteArray array;
+ QDataStream stream(&array, QIODevice::WriteOnly);
+ stream.setVersion(QDataStream::Qt_5_12);
+
+ const quint16 majorVersion = 1;
+ const quint16 minorVersion = 0;
+
+ stream << majorVersion
+ << minorVersion
+ << m_currentInitScreensData
+ << position.screenName
+ << position.nativePosition;
+ return array;
+}
+
+void QQmlPreviewPosition::readLastPositionFromByteArray(const QByteArray &array)
+{
+ QDataStream stream(array);
+ stream.setVersion(QDataStream::Qt_5_12);
+
+ // no version check for 1.0
+ //const quint16 currentMajorVersion = 1;
+ quint16 majorVersion = 0;
+ quint16 minorVersion = 0;
- m_positionedWindows.append(window);
+ stream >> majorVersion >> minorVersion;
+
+ QVector<ScreenData> initScreensData;
+ stream >> initScreensData;
+
+ if (m_currentInitScreensData != initScreensData)
+ return;
+
+ QString nameOfScreen;
+ stream >> nameOfScreen;
+
+ QScreen *screen = findScreen(nameOfScreen);
+ if (!screen)
+ return;
+
+ QPoint nativePosition;
+ stream >> nativePosition;
+ if (nativePosition.isNull())
+ return;
+ m_lastWindowPosition = {nameOfScreen, nativePosition};
}
-const QSize QQmlPreviewPosition::currentScreenSize(QWindow *window)
+void QQmlPreviewPosition::setPosition(const QQmlPreviewPosition::Position &position,
+ QWindow *window)
{
- return availableScreenSize(window->position());
+ if (position.nativePosition.isNull())
+ return;
+ if (QScreen *screen = findScreen(position.screenName)) {
+ window->setScreen(screen);
+ window->setFramePosition(QHighDpiScaling::mapPositionFromNative(position.nativePosition,
+ screen->handle()));
+ }
}
QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewposition.h b/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewposition.h
index 3d4ca9dc67..f403917f8c 100644
--- a/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewposition.h
+++ b/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewposition.h
@@ -56,6 +56,8 @@
#include <QtCore/qurl.h>
#include <QtCore/qtimer.h>
#include <QtCore/qsettings.h>
+#include <QtCore/qsize.h>
+#include <QtCore/qdatastream.h>
QT_BEGIN_NAMESPACE
@@ -64,23 +66,46 @@ class QWindow;
class QQmlPreviewPosition
{
public:
+ class ScreenData {
+ public:
+ bool operator==(const QQmlPreviewPosition::ScreenData &other) const;
+ QString name;
+ QSize size;
+ };
+ class Position {
+ public:
+ QString screenName;
+ QPoint nativePosition;
+ };
+ enum InitializeState {
+ InitializePosition,
+ PositionInitialized
+ };
+
QQmlPreviewPosition();
+ ~QQmlPreviewPosition();
- void setPosition(const QPoint &point);
- void saveWindowPosition();
- void loadWindowPositionSettings(const QUrl &url);
+
+ void takePosition(QWindow *window, InitializeState state = PositionInitialized);
void initLastSavedWindowPosition(QWindow *window);
- static const QSize currentScreenSize(QWindow *window);
+ void loadWindowPositionSettings(const QUrl &url);
private:
+ void setPosition(const QQmlPreviewPosition::Position &position, QWindow *window);
+ QByteArray fromPositionToByteArray(const Position &position);
+ void readLastPositionFromByteArray(const QByteArray &array);
+ void saveWindowPosition();
+
bool m_hasPosition = false;
- QPoint m_lastWindowPosition;
+ InitializeState m_initializeState = InitializePosition;
QSettings m_settings;
QString m_settingsKey;
QTimer m_savePositionTimer;
+ Position m_lastWindowPosition;
QVector<QWindow *> m_positionedWindows;
-};
+ QVector<ScreenData> m_currentInitScreensData;
+};
QT_END_NAMESPACE
diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp
index a22dd7aa32..6e077ec44c 100644
--- a/src/qml/compiler/qqmlirbuilder.cpp
+++ b/src/qml/compiler/qqmlirbuilder.cpp
@@ -1111,6 +1111,7 @@ void IRBuilder::tryGeneratingTranslationBinding(const QStringRef &base, AST::Arg
QV4::CompiledData::TranslationData translationData;
translationData.number = -1;
translationData.commentIndex = 0; // empty string
+ translationData.padding = 0;
if (!args || !args->expression)
return; // no arguments, stop
@@ -1151,6 +1152,7 @@ void IRBuilder::tryGeneratingTranslationBinding(const QStringRef &base, AST::Arg
QV4::CompiledData::TranslationData translationData;
translationData.number = -1;
translationData.commentIndex = 0; // empty string, but unused
+ translationData.padding = 0;
if (!args || !args->expression)
return; // no arguments, stop
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp
index f497184ab5..e0d259bd0c 100644
--- a/src/qml/compiler/qv4codegen.cpp
+++ b/src/qml/compiler/qv4codegen.cpp
@@ -1738,59 +1738,46 @@ Codegen::Reference Codegen::binopHelper(QSOperator::Op oper, Reference &left, Re
return Reference::fromAccumulator(this);
}
-static QSOperator::Op operatorForSwappedOperands(QSOperator::Op oper)
-{
- switch (oper) {
- case QSOperator::StrictEqual: return QSOperator::StrictEqual;
- case QSOperator::StrictNotEqual: return QSOperator::StrictNotEqual;
- case QSOperator::Equal: return QSOperator::Equal;
- case QSOperator::NotEqual: return QSOperator::NotEqual;
- case QSOperator::Gt: return QSOperator::Le;
- case QSOperator::Ge: return QSOperator::Lt;
- case QSOperator::Lt: return QSOperator::Ge;
- case QSOperator::Le: return QSOperator::Gt;
- default: Q_UNIMPLEMENTED(); return QSOperator::Invalid;
- }
-}
-
Codegen::Reference Codegen::jumpBinop(QSOperator::Op oper, Reference &left, Reference &right)
{
- if (left.isConstant()) {
- oper = operatorForSwappedOperands(oper);
- qSwap(left, right);
- }
+ // See if we can generate specialized comparison instructions:
+ if (oper == QSOperator::Equal || oper == QSOperator::NotEqual) {
+ // Because == and != are reflexive, we can do the following:
+ if (left.isConstant() && !right.isConstant())
+ qSwap(left, right); // null==a -> a==null
- if (right.isConstant() && (oper == QSOperator::Equal || oper == QSOperator::NotEqual)) {
- Value c = Value::fromReturnedValue(right.constant);
- if (c.isNull() || c.isUndefined()) {
- left.loadInAccumulator();
- if (oper == QSOperator::Equal) {
- Instruction::CmpEqNull cmp;
- bytecodeGenerator->addInstruction(cmp);
- addCJump();
- return Reference();
- } else if (oper == QSOperator::NotEqual) {
- Instruction::CmpNeNull cmp;
- bytecodeGenerator->addInstruction(cmp);
- addCJump();
- return Reference();
- }
- } else if (c.isInt32()) {
- left.loadInAccumulator();
- if (oper == QSOperator::Equal) {
- Instruction::CmpEqInt cmp;
- cmp.lhs = c.int_32();
- bytecodeGenerator->addInstruction(cmp);
- addCJump();
- return Reference();
- } else if (oper == QSOperator::NotEqual) {
- Instruction::CmpNeInt cmp;
- cmp.lhs = c.int_32();
- bytecodeGenerator->addInstruction(cmp);
- addCJump();
- return Reference();
- }
+ if (right.isConstant()) {
+ Value c = Value::fromReturnedValue(right.constant);
+ if (c.isNull() || c.isUndefined()) {
+ left.loadInAccumulator();
+ if (oper == QSOperator::Equal) {
+ Instruction::CmpEqNull cmp;
+ bytecodeGenerator->addInstruction(cmp);
+ addCJump();
+ return Reference();
+ } else if (oper == QSOperator::NotEqual) {
+ Instruction::CmpNeNull cmp;
+ bytecodeGenerator->addInstruction(cmp);
+ addCJump();
+ return Reference();
+ }
+ } else if (c.isInt32()) {
+ left.loadInAccumulator();
+ if (oper == QSOperator::Equal) {
+ Instruction::CmpEqInt cmp;
+ cmp.lhs = c.int_32();
+ bytecodeGenerator->addInstruction(cmp);
+ addCJump();
+ return Reference();
+ } else if (oper == QSOperator::NotEqual) {
+ Instruction::CmpNeInt cmp;
+ cmp.lhs = c.int_32();
+ bytecodeGenerator->addInstruction(cmp);
+ addCJump();
+ return Reference();
+ }
+ }
}
}
diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp
index b110fafaac..dc5466371d 100644
--- a/src/qml/compiler/qv4compileddata.cpp
+++ b/src/qml/compiler/qv4compileddata.cpp
@@ -98,18 +98,25 @@ CompilationUnit::CompilationUnit(const Unit *unitData, const QString &fileName,
setUnitData(unitData, nullptr, fileName, finalUrlString);
}
-#ifndef V4_BOOTSTRAP
CompilationUnit::~CompilationUnit()
{
+#ifndef V4_BOOTSTRAP
unlink();
+#endif
if (data) {
if (data->qmlUnit() != qmlData)
free(const_cast<QmlUnit *>(qmlData));
qmlData = nullptr;
+#ifndef V4_BOOTSTRAP
if (!(data->flags & QV4::CompiledData::Unit::StaticData))
free(const_cast<Unit *>(data));
+#else
+ // Unconditionally free the memory. In the dev tools we create units that have
+ // the flag set and will be saved to disk, so intended to persist later.
+ free(const_cast<Unit *>(data));
+#endif
}
data = nullptr;
#if Q_BYTE_ORDER == Q_BIG_ENDIAN
@@ -120,6 +127,7 @@ CompilationUnit::~CompilationUnit()
delete [] imports;
imports = nullptr;
}
+#ifndef V4_BOOTSTRAP
QString CompilationUnit::localCacheFilePath(const QUrl &url)
{
diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h
index 2d7a027b37..23e33247a8 100644
--- a/src/qml/compiler/qv4compileddata_p.h
+++ b/src/qml/compiler/qv4compileddata_p.h
@@ -1090,11 +1090,7 @@ struct Q_QML_PRIVATE_EXPORT CompilationUnit final : public CompilationUnitBase
const QmlUnit *qmlData = nullptr;
public:
CompilationUnit(const Unit *unitData = nullptr, const QString &fileName = QString(), const QString &finalUrlString = QString());
-#ifdef V4_BOOTSTRAP
- ~CompilationUnit() {}
-#else
~CompilationUnit();
-#endif
void addref()
{
diff --git a/src/qml/jsruntime/qv4qmlcontext.cpp b/src/qml/jsruntime/qv4qmlcontext.cpp
index 97b955632d..a2c8e3916f 100644
--- a/src/qml/jsruntime/qv4qmlcontext.cpp
+++ b/src/qml/jsruntime/qv4qmlcontext.cpp
@@ -79,6 +79,53 @@ void Heap::QQmlContextWrapper::destroy()
Object::destroy();
}
+static OptionalReturnedValue searchContextProperties(QV4::ExecutionEngine *v4, QQmlContextData *context, String *name,
+ bool *hasProperty, Value *base, QV4::Lookup *lookup,
+ QV4::Lookup *originalLookup, QQmlEnginePrivate *ep)
+{
+ const QV4::IdentifierHash &properties = context->propertyNames();
+ if (properties.count() == 0)
+ return OptionalReturnedValue();
+
+ const int propertyIdx = properties.value(name);
+
+ if (propertyIdx == -1)
+ return OptionalReturnedValue();
+
+ if (propertyIdx < context->idValueCount) {
+ if (hasProperty)
+ *hasProperty = true;
+
+ if (lookup) {
+ lookup->qmlContextIdObjectLookup.objectId = propertyIdx;
+ lookup->qmlContextPropertyGetter = QQmlContextWrapper::lookupIdObject;
+ return OptionalReturnedValue(lookup->qmlContextPropertyGetter(lookup, v4, base));
+ } else if (originalLookup) {
+ originalLookup->qmlContextPropertyGetter = QQmlContextWrapper::lookupInParentContextHierarchy;
+ }
+
+ if (ep->propertyCapture)
+ ep->propertyCapture->captureProperty(&context->idValues[propertyIdx].bindings);
+ return OptionalReturnedValue(QV4::QObjectWrapper::wrap(v4, context->idValues[propertyIdx]));
+ }
+
+ QQmlContextPrivate *cp = context->asQQmlContextPrivate();
+
+ if (ep->propertyCapture)
+ ep->propertyCapture->captureProperty(context->asQQmlContext(), -1, propertyIdx + cp->notifyIndex);
+
+ const QVariant &value = cp->propertyValues.at(propertyIdx);
+ if (hasProperty)
+ *hasProperty = true;
+ if (value.userType() == qMetaTypeId<QList<QObject*> >()) {
+ QQmlListProperty<QObject> prop(context->asQQmlContext(), (void*) qintptr(propertyIdx),
+ QQmlContextPrivate::context_count,
+ QQmlContextPrivate::context_at);
+ return OptionalReturnedValue(QmlListWrapper::create(v4, prop, qMetaTypeId<QQmlListProperty<QObject> >()));
+ }
+ return OptionalReturnedValue(v4->fromVariant(cp->propertyValues.at(propertyIdx)));
+}
+
ReturnedValue QQmlContextWrapper::getPropertyAndBase(const QQmlContextWrapper *resource, PropertyKey id, const Value *receiver, bool *hasProperty, Value *base, Lookup *lookup)
{
if (!id.isString())
@@ -224,47 +271,8 @@ ReturnedValue QQmlContextWrapper::getPropertyAndBase(const QQmlContextWrapper *r
}
while (context) {
- // Search context properties
- const QV4::IdentifierHash &properties = context->propertyNames();
- if (properties.count()) {
- int propertyIdx = properties.value(name);
-
- if (propertyIdx != -1) {
-
- if (propertyIdx < context->idValueCount) {
- if (hasProperty)
- *hasProperty = true;
-
- if (lookup) {
- lookup->qmlContextIdObjectLookup.objectId = propertyIdx;
- lookup->qmlContextPropertyGetter = QQmlContextWrapper::lookupIdObject;
- return lookup->qmlContextPropertyGetter(lookup, v4, base);
- }
-
- if (ep->propertyCapture)
- ep->propertyCapture->captureProperty(&context->idValues[propertyIdx].bindings);
- return QV4::QObjectWrapper::wrap(v4, context->idValues[propertyIdx]);
- } else {
-
- QQmlContextPrivate *cp = context->asQQmlContextPrivate();
-
- if (ep->propertyCapture)
- ep->propertyCapture->captureProperty(context->asQQmlContext(), -1, propertyIdx + cp->notifyIndex);
-
- const QVariant &value = cp->propertyValues.at(propertyIdx);
- if (hasProperty)
- *hasProperty = true;
- if (value.userType() == qMetaTypeId<QList<QObject*> >()) {
- QQmlListProperty<QObject> prop(context->asQQmlContext(), (void*) qintptr(propertyIdx),
- QQmlContextPrivate::context_count,
- QQmlContextPrivate::context_at);
- return QmlListWrapper::create(v4, prop, qMetaTypeId<QQmlListProperty<QObject> >());
- } else {
- return scope.engine->fromVariant(cp->propertyValues.at(propertyIdx));
- }
- }
- }
- }
+ if (auto property = searchContextProperties(v4, context, name, hasProperty, base, lookup, originalLookup, ep))
+ return *property;
// Search scope object
if (scopeObject) {
@@ -311,17 +319,21 @@ ReturnedValue QQmlContextWrapper::getPropertyAndBase(const QQmlContextWrapper *r
if (base)
*base = QV4::QObjectWrapper::wrap(v4, context->contextObject);
- if (lookup && propertyData) {
- QQmlData *ddata = QQmlData::get(context->contextObject, false);
- if (ddata && ddata->propertyCache) {
- ScopedValue val(scope, base ? *base : Value::fromReturnedValue(QV4::QObjectWrapper::wrap(v4, context->contextObject)));
- const QObjectWrapper *That = static_cast<const QObjectWrapper *>(val->objectValue());
- lookup->qobjectLookup.ic = That->internalClass();
- lookup->qobjectLookup.staticQObject = nullptr;
- lookup->qobjectLookup.propertyCache = ddata->propertyCache;
- lookup->qobjectLookup.propertyCache->addref();
- lookup->qobjectLookup.propertyData = propertyData;
- lookup->qmlContextPropertyGetter = contextGetterFunction;
+ if (propertyData) {
+ if (lookup) {
+ QQmlData *ddata = QQmlData::get(context->contextObject, false);
+ if (ddata && ddata->propertyCache) {
+ ScopedValue val(scope, base ? *base : Value::fromReturnedValue(QV4::QObjectWrapper::wrap(v4, context->contextObject)));
+ const QObjectWrapper *That = static_cast<const QObjectWrapper *>(val->objectValue());
+ lookup->qobjectLookup.ic = That->internalClass();
+ lookup->qobjectLookup.staticQObject = nullptr;
+ lookup->qobjectLookup.propertyCache = ddata->propertyCache;
+ lookup->qobjectLookup.propertyCache->addref();
+ lookup->qobjectLookup.propertyData = propertyData;
+ lookup->qmlContextPropertyGetter = contextGetterFunction;
+ }
+ } else if (originalLookup) {
+ originalLookup->qmlContextPropertyGetter = lookupInParentContextHierarchy;
}
}
@@ -576,6 +588,55 @@ ReturnedValue QQmlContextWrapper::lookupInGlobalObject(Lookup *l, ExecutionEngin
return result;
}
+ReturnedValue QQmlContextWrapper::lookupInParentContextHierarchy(Lookup *l, ExecutionEngine *engine, Value *base)
+{
+ Scope scope(engine);
+ Scoped<QmlContext> qmlContext(scope, engine->qmlContext());
+ if (!qmlContext)
+ return QV4::Encode::undefined();
+
+ QQmlContextData *context = qmlContext->qmlContext();
+ if (!context)
+ return QV4::Encode::undefined();
+
+ QQmlContextData *expressionContext = context;
+
+ QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine->qmlEngine());
+
+ PropertyKey id =engine->identifierTable->asPropertyKey(engine->currentStackFrame->v4Function->compilationUnit->
+ runtimeStrings[l->nameIndex]);
+ ScopedString name(scope, id.asStringOrSymbol());
+
+ ScopedValue result(scope);
+
+ for (context = context->parent; context; context = context->parent) {
+ if (auto property = searchContextProperties(engine, context, name, nullptr, base, nullptr, nullptr, ep))
+ return *property;
+
+ // Search context object
+ if (context->contextObject) {
+ bool hasProp = false;
+ result = QV4::QObjectWrapper::getQmlProperty(engine, context, context->contextObject,
+ name, QV4::QObjectWrapper::CheckRevision, &hasProp);
+ if (hasProp) {
+ if (base)
+ *base = QV4::QObjectWrapper::wrap(engine, context->contextObject);
+
+ return result->asReturnedValue();
+ }
+ }
+ }
+
+ bool hasProp = false;
+ result = engine->globalObject->get(name, &hasProp);
+ if (hasProp)
+ return result->asReturnedValue();
+
+ expressionContext->unresolvedNames = true;
+
+ return Encode::undefined();
+}
+
void Heap::QmlContext::init(QV4::ExecutionContext *outerContext, QV4::QQmlContextWrapper *qml)
{
Heap::ExecutionContext::init(Heap::ExecutionContext::Type_QmlContext);
diff --git a/src/qml/jsruntime/qv4qmlcontext_p.h b/src/qml/jsruntime/qv4qmlcontext_p.h
index 6375294375..4c8287ef2f 100644
--- a/src/qml/jsruntime/qv4qmlcontext_p.h
+++ b/src/qml/jsruntime/qv4qmlcontext_p.h
@@ -111,6 +111,7 @@ struct Q_QML_EXPORT QQmlContextWrapper : Object
static ReturnedValue lookupScopeObjectProperty(Lookup *l, ExecutionEngine *engine, Value *base);
static ReturnedValue lookupContextObjectProperty(Lookup *l, ExecutionEngine *engine, Value *base);
static ReturnedValue lookupInGlobalObject(Lookup *l, ExecutionEngine *engine, Value *base);
+ static ReturnedValue lookupInParentContextHierarchy(Lookup *l, ExecutionEngine *engine, Value *base);
};
struct Q_QML_EXPORT QmlContext : public ExecutionContext
diff --git a/src/qmltest/doc/src/qtquicktest-index.qdoc b/src/qmltest/doc/src/qtquicktest-index.qdoc
index 4c0124689b..668d6c1417 100644
--- a/src/qmltest/doc/src/qtquicktest-index.qdoc
+++ b/src/qmltest/doc/src/qtquicktest-index.qdoc
@@ -149,11 +149,13 @@
\header
\li Name
\li Purpose
+ \li Since
\row
\li \c {void applicationAvailable()}
\li Called right after the QApplication object was instantiated.
- Use this function to setup everything that is not related
- to QML directly.
+ Use this function to perform setup that does not require a
+ \l QQmlEngine instance.
+ \li Qt 5.12
\row
\li \c {void qmlEngineAvailable(QQmlEngine *)}
\li Called when the QML engine is available.
@@ -161,10 +163,17 @@
\l {QQmlEngine::addPluginPath}{plugin paths},
and \l {QQmlFileSelector::setExtraSelectors}{extra file selectors}
will have been set on the engine by this point.
+
+ This function can be used to \l {Choosing the Correct Integration
+ Method Between C++ and QML}{register QML types} and
+ \l {QQmlEngine::addImportPath()}{add import paths},
+ amongst other things.
+ \li Qt 5.11
\row
\li \c {void cleanupTestCase()}
\li Called right after the test execution has finished.
Use this function to clean up before everything will start to be destructed.
+ \li Qt 5.12
\endtable
Each function will be called once for each \c {tst_*.qml} file, so any
diff --git a/src/qmltest/quicktest.cpp b/src/qmltest/quicktest.cpp
index 9a73726797..9cddf61543 100644
--- a/src/qmltest/quicktest.cpp
+++ b/src/qmltest/quicktest.cpp
@@ -575,6 +575,13 @@ int quick_test_main_with_setup(int argc, char **argv, const char *name, const ch
qmlFileSelector->setExtraSelectors(fileSelectors);
}
+ // Do this down here so that import paths, plugin paths, file selectors, etc. are available
+ // in case the user needs access to them. Do it _before_ the TestCaseCollector parses the
+ // QML files though, because it attempts to import modules, which might not be available
+ // if qmlRegisterType()/QQmlEngine::addImportPath() are called in qmlEngineAvailable().
+ if (setup)
+ maybeInvokeSetupMethod(setup, "qmlEngineAvailable(QQmlEngine*)", Q_ARG(QQmlEngine*, &engine));
+
TestCaseCollector testCaseCollector(fi, &engine);
if (!testCaseCollector.errors().isEmpty()) {
for (const QQmlError &error : testCaseCollector.errors())
@@ -606,11 +613,6 @@ int quick_test_main_with_setup(int argc, char **argv, const char *name, const ch
view.rootContext()->setContextProperty
(QLatin1String("qtest"), QTestRootObject::instance()); // Deprecated. Use QTestRootObject from Qt.test.qtestroot instead
- // Do this down here so that import paths, plugin paths,
- // file selectors, etc. are available in case the user needs access to them.
- if (setup)
- maybeInvokeSetupMethod(setup, "qmlEngineAvailable(QQmlEngine*)", Q_ARG(QQmlEngine*, view.engine()));
-
view.setObjectName(fi.baseName());
view.setTitle(view.objectName());
QTestRootObject::instance()->init();
diff --git a/tests/auto/qml/debugger/qqmlpreview/tst_qqmlpreview.cpp b/tests/auto/qml/debugger/qqmlpreview/tst_qqmlpreview.cpp
index f713aa76c3..c7f8ec1118 100644
--- a/tests/auto/qml/debugger/qqmlpreview/tst_qqmlpreview.cpp
+++ b/tests/auto/qml/debugger/qqmlpreview/tst_qqmlpreview.cpp
@@ -319,12 +319,12 @@ void tst_QQmlPreview::zoom()
QTRY_VERIFY(m_files.contains(testFile(file)));
float baseZoomFactor = -1;
QTRY_VERIFY_WITH_TIMEOUT((baseZoomFactor = parseZoomFactor(m_process->output())) > 0, 30000);
- m_client->triggerZoom(2.0f);
- verifyZoomFactor(m_process, baseZoomFactor * 2.0f);
- m_client->triggerZoom(1.5f);
- verifyZoomFactor(m_process, baseZoomFactor * 1.5f);
- m_client->triggerZoom(0.5f);
- verifyZoomFactor(m_process, baseZoomFactor * 0.5f);
+
+ for (auto testZoomFactor : {2.0f, 1.5f, 0.5f}) {
+ m_client->triggerZoom(testZoomFactor);
+ verifyZoomFactor(m_process, baseZoomFactor * testZoomFactor);
+ }
+
m_client->triggerZoom(-1.0f);
verifyZoomFactor(m_process, baseZoomFactor);
m_process->stop();
diff --git a/tests/auto/qml/qjsengine/tst_qjsengine.cpp b/tests/auto/qml/qjsengine/tst_qjsengine.cpp
index fb9c7b0152..3e871108bc 100644
--- a/tests/auto/qml/qjsengine/tst_qjsengine.cpp
+++ b/tests/auto/qml/qjsengine/tst_qjsengine.cpp
@@ -235,6 +235,8 @@ private slots:
void importModuleWithLexicallyScopedVars();
void importExportErrors();
+ void equality();
+
public:
Q_INVOKABLE QJSValue throwingCppMethod1();
Q_INVOKABLE void throwingCppMethod2();
@@ -4622,6 +4624,14 @@ void tst_QJSEngine::importExportErrors()
}
}
+void tst_QJSEngine::equality()
+{
+ QJSEngine engine;
+ QJSValue ok = engine.evaluate("(0 < 0) ? 'ko' : 'ok'");
+ QVERIFY(ok.isString());
+ QCOMPARE(ok.toString(), QString("ok"));
+}
+
QTEST_MAIN(tst_QJSEngine)
#include "tst_qjsengine.moc"
diff --git a/tests/auto/qml/qmlcachegen/Enums.qml b/tests/auto/qml/qmlcachegen/data/Enums.qml
index 830babb73e..830babb73e 100644
--- a/tests/auto/qml/qmlcachegen/Enums.qml
+++ b/tests/auto/qml/qmlcachegen/data/Enums.qml
diff --git a/tests/auto/qml/qmlcachegen/Retain.qml b/tests/auto/qml/qmlcachegen/data/Retain.qml
index 0e69012662..0e69012662 100644
--- a/tests/auto/qml/qmlcachegen/Retain.qml
+++ b/tests/auto/qml/qmlcachegen/data/Retain.qml
diff --git a/tests/auto/qml/qmlcachegen/data/componentInItem.qml b/tests/auto/qml/qmlcachegen/data/componentInItem.qml
new file mode 100644
index 0000000000..820b9fddcd
--- /dev/null
+++ b/tests/auto/qml/qmlcachegen/data/componentInItem.qml
@@ -0,0 +1,15 @@
+import QtQuick 2.12
+
+Item {
+ Component {
+ Rectangle {
+ id: xxx
+ Text {
+ text: qsTr("&Undo")
+ }
+ Text {
+ text: qsTr("&Redo")
+ }
+ }
+ }
+}
diff --git a/tests/auto/qml/qmlcachegen/jsimport.qml b/tests/auto/qml/qmlcachegen/data/jsimport.qml
index 9c40878e60..9c40878e60 100644
--- a/tests/auto/qml/qmlcachegen/jsimport.qml
+++ b/tests/auto/qml/qmlcachegen/data/jsimport.qml
diff --git a/tests/auto/qml/qmlcachegen/jsmoduleimport.qml b/tests/auto/qml/qmlcachegen/data/jsmoduleimport.qml
index c1fad7fee2..c1fad7fee2 100644
--- a/tests/auto/qml/qmlcachegen/jsmoduleimport.qml
+++ b/tests/auto/qml/qmlcachegen/data/jsmoduleimport.qml
diff --git a/tests/auto/qml/qmlcachegen/library.js b/tests/auto/qml/qmlcachegen/data/library.js
index 51fb41dc23..51fb41dc23 100644
--- a/tests/auto/qml/qmlcachegen/library.js
+++ b/tests/auto/qml/qmlcachegen/data/library.js
diff --git a/tests/auto/qml/qmlcachegen/script.js b/tests/auto/qml/qmlcachegen/data/script.js
index fa55f9069e..fa55f9069e 100644
--- a/tests/auto/qml/qmlcachegen/script.js
+++ b/tests/auto/qml/qmlcachegen/data/script.js
diff --git a/tests/auto/qml/qmlcachegen/script.mjs b/tests/auto/qml/qmlcachegen/data/script.mjs
index 459c336125..459c336125 100644
--- a/tests/auto/qml/qmlcachegen/script.mjs
+++ b/tests/auto/qml/qmlcachegen/data/script.mjs
diff --git a/tests/auto/qml/qmlcachegen/trickypaths.qml b/tests/auto/qml/qmlcachegen/data/trickypaths.qml
index 0836808dc2..0836808dc2 100644
--- a/tests/auto/qml/qmlcachegen/trickypaths.qml
+++ b/tests/auto/qml/qmlcachegen/data/trickypaths.qml
diff --git a/tests/auto/qml/qmlcachegen/umlaut.qml b/tests/auto/qml/qmlcachegen/data/umlaut.qml
index 0836808dc2..0836808dc2 100644
--- a/tests/auto/qml/qmlcachegen/umlaut.qml
+++ b/tests/auto/qml/qmlcachegen/data/umlaut.qml
diff --git a/tests/auto/qml/qmlcachegen/versionStyleSuffix-1.2-core-yc.qml b/tests/auto/qml/qmlcachegen/data/versionStyleSuffix-1.2-core-yc.qml
index 0836808dc2..0836808dc2 100644
--- a/tests/auto/qml/qmlcachegen/versionStyleSuffix-1.2-core-yc.qml
+++ b/tests/auto/qml/qmlcachegen/data/versionStyleSuffix-1.2-core-yc.qml
diff --git a/tests/auto/qml/qmlcachegen/versionStyleSuffix-1.2-more.qml b/tests/auto/qml/qmlcachegen/data/versionStyleSuffix-1.2-more.qml
index 0836808dc2..0836808dc2 100644
--- a/tests/auto/qml/qmlcachegen/versionStyleSuffix-1.2-more.qml
+++ b/tests/auto/qml/qmlcachegen/data/versionStyleSuffix-1.2-more.qml
diff --git a/tests/auto/qml/qmlcachegen/versionchecks.qml b/tests/auto/qml/qmlcachegen/data/versionchecks.qml
index 77d67e7da4..77d67e7da4 100644
--- a/tests/auto/qml/qmlcachegen/versionchecks.qml
+++ b/tests/auto/qml/qmlcachegen/data/versionchecks.qml
diff --git a/tests/auto/qml/qmlcachegen/worker.js b/tests/auto/qml/qmlcachegen/data/worker.js
index dd2d0b843d..dd2d0b843d 100644
--- a/tests/auto/qml/qmlcachegen/worker.js
+++ b/tests/auto/qml/qmlcachegen/data/worker.js
diff --git a/tests/auto/qml/qmlcachegen/worker.qml b/tests/auto/qml/qmlcachegen/data/worker.qml
index 1f1c9d1ac7..1f1c9d1ac7 100644
--- a/tests/auto/qml/qmlcachegen/worker.qml
+++ b/tests/auto/qml/qmlcachegen/data/worker.qml
diff --git a/tests/auto/qml/qmlcachegen/qmlcachegen.pro b/tests/auto/qml/qmlcachegen/qmlcachegen.pro
index c7820ac1cd..7bd4414302 100644
--- a/tests/auto/qml/qmlcachegen/qmlcachegen.pro
+++ b/tests/auto/qml/qmlcachegen/qmlcachegen.pro
@@ -2,26 +2,34 @@ CONFIG += testcase qtquickcompiler
TARGET = tst_qmlcachegen
macos:CONFIG -= app_bundle
+include (../../shared/util.pri)
+TESTDATA = data/*
+
SOURCES += tst_qmlcachegen.cpp
-workerscripts_test.files = worker.js worker.qml
+RESOURCES += \
+ data/versionchecks.qml \
+ data/jsimport.qml \
+ data/script.js \
+ data/library.js \
+ data/Enums.qml \
+ data/componentInItem.qml \
+ data/jsmoduleimport.qml \
+ data/script.mjs
+
+workerscripts_test.files = \
+ data/worker.js \
+ data/worker.qml
workerscripts_test.prefix = /workerscripts
-RESOURCES += workerscripts_test
-
-RESOURCES += versionchecks.qml
-
-RESOURCES += trickypaths.qrc
-RESOURCES += jsimport.qml script.js library.js
-
-RESOURCES += Enums.qml
+RESOURCES += \
+ workerscripts_test \
+ trickypaths.qrc \
+ retain.qrc
# QTBUG-46375
!win32: RESOURCES += trickypaths_umlaut.qrc
-RESOURCES += jsmoduleimport.qml script.mjs
-
-RESOURCES += retain.qrc
QTQUICK_COMPILER_RETAINED_RESOURCES += retain.qrc
QT += core-private qml-private testlib
diff --git a/tests/auto/qml/qmlcachegen/retain.qrc b/tests/auto/qml/qmlcachegen/retain.qrc
index af042b25d8..e5eed9b12f 100644
--- a/tests/auto/qml/qmlcachegen/retain.qrc
+++ b/tests/auto/qml/qmlcachegen/retain.qrc
@@ -1,5 +1,5 @@
<RCC>
<qresource prefix="/">
- <file>Retain.qml</file>
+ <file alias="Retain.qml">data/Retain.qml</file>
</qresource>
</RCC>
diff --git a/tests/auto/qml/qmlcachegen/trickypaths.qrc b/tests/auto/qml/qmlcachegen/trickypaths.qrc
index 57977ccf6d..b0c3bcf209 100644
--- a/tests/auto/qml/qmlcachegen/trickypaths.qrc
+++ b/tests/auto/qml/qmlcachegen/trickypaths.qrc
@@ -1,7 +1,7 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource prefix="/directory with spaces">
-<file alias="file name with spaces.qml">trickypaths.qml</file>
-<file>versionStyleSuffix-1.2-core-yc.qml</file>
-<file>versionStyleSuffix-1.2-more.qml</file>
+<file alias="file name with spaces.qml">data/trickypaths.qml</file>
+<file alias="versionStyleSuffix-1.2-core-yc.qml">data/versionStyleSuffix-1.2-core-yc.qml</file>
+<file alias="versionStyleSuffix-1.2-more.qml">data/versionStyleSuffix-1.2-more.qml</file>
</qresource>
</RCC>
diff --git a/tests/auto/qml/qmlcachegen/trickypaths_umlaut.qrc b/tests/auto/qml/qmlcachegen/trickypaths_umlaut.qrc
index 9ca889d692..17aa30473f 100644
--- a/tests/auto/qml/qmlcachegen/trickypaths_umlaut.qrc
+++ b/tests/auto/qml/qmlcachegen/trickypaths_umlaut.qrc
@@ -1,5 +1,5 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource prefix="/">
-<file alias="Bäh.qml">umlaut.qml</file>
+<file alias="Bäh.qml">data/umlaut.qml</file>
</qresource>
</RCC>
diff --git a/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp b/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp
index 8cfa4cb6af..5462e6c8ae 100644
--- a/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp
+++ b/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp
@@ -38,7 +38,9 @@
#include <private/qqmlcomponent_p.h>
#include <qtranslator.h>
-class tst_qmlcachegen: public QObject
+#include "../../shared/util.h"
+
+class tst_qmlcachegen: public QQmlDataTest
{
Q_OBJECT
@@ -66,6 +68,9 @@ private slots:
void enums();
void sourceFileIndices();
+
+ void reproducibleCache_data();
+ void reproducibleCache();
};
// A wrapper around QQmlComponent to ensure the temporary reference counts
@@ -353,12 +358,13 @@ static QQmlPrivate::CachedQmlUnit *temporaryModifiedCachedUnit = nullptr;
void tst_qmlcachegen::versionChecksForAheadOfTimeUnits()
{
- QVERIFY(QFile::exists(":/versionchecks.qml"));
- QCOMPARE(QFileInfo(":/versionchecks.qml").size(), 0);
+ QVERIFY(QFile::exists(":/data/versionchecks.qml"));
+ QCOMPARE(QFileInfo(":/data/versionchecks.qml").size(), 0);
Q_ASSERT(!temporaryModifiedCachedUnit);
QQmlMetaType::CachedUnitLookupError error = QQmlMetaType::CachedUnitLookupError::NoError;
- const QV4::CompiledData::Unit *originalUnit = QQmlMetaType::findCachedCompilationUnit(QUrl("qrc:/versionchecks.qml"), &error);
+ const QV4::CompiledData::Unit *originalUnit = QQmlMetaType::findCachedCompilationUnit(
+ QUrl("qrc:/data/versionchecks.qml"), &error);
QVERIFY(originalUnit);
QV4::CompiledData::Unit *tweakedUnit = (QV4::CompiledData::Unit *)malloc(originalUnit->unitSize);
memcpy(reinterpret_cast<void *>(tweakedUnit), reinterpret_cast<const void *>(originalUnit), originalUnit->unitSize);
@@ -366,7 +372,7 @@ void tst_qmlcachegen::versionChecksForAheadOfTimeUnits()
temporaryModifiedCachedUnit = new QQmlPrivate::CachedQmlUnit{tweakedUnit, nullptr, nullptr};
auto testHandler = [](const QUrl &url) -> const QQmlPrivate::CachedQmlUnit * {
- if (url == QUrl("qrc:/versionchecks.qml"))
+ if (url == QUrl("qrc:/data/versionchecks.qml"))
return temporaryModifiedCachedUnit;
return nullptr;
};
@@ -374,15 +380,18 @@ void tst_qmlcachegen::versionChecksForAheadOfTimeUnits()
{
QQmlMetaType::CachedUnitLookupError error = QQmlMetaType::CachedUnitLookupError::NoError;
- QVERIFY(!QQmlMetaType::findCachedCompilationUnit(QUrl("qrc:/versionchecks.qml"), &error));
+ QVERIFY(!QQmlMetaType::findCachedCompilationUnit(QUrl("qrc:/data/versionchecks.qml"), &error));
QCOMPARE(error, QQmlMetaType::CachedUnitLookupError::VersionMismatch);
}
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl("qrc:/versionchecks.qml"));
+ QQmlComponent component(&engine, QUrl("qrc:/data/versionchecks.qml"));
QCOMPARE(component.status(), QQmlComponent::Error);
- QCOMPARE(component.errorString(), QString("qrc:/versionchecks.qml:-1 File was compiled ahead of time with an incompatible version of Qt and the original file cannot be found. Please recompile\n"));
+ QCOMPARE(component.errorString(),
+ QString("qrc:/data/versionchecks.qml:-1 File was compiled ahead of time with an "
+ "incompatible version of Qt and the original file cannot be found. Please "
+ "recompile\n"));
}
Q_ASSERT(temporaryModifiedCachedUnit);
@@ -402,12 +411,12 @@ void tst_qmlcachegen::retainedResources()
void tst_qmlcachegen::workerScripts()
{
- QVERIFY(QFile::exists(":/workerscripts/worker.js"));
- QVERIFY(QFile::exists(":/workerscripts/worker.qml"));
- QCOMPARE(QFileInfo(":/workerscripts/worker.js").size(), 0);
+ QVERIFY(QFile::exists(":/workerscripts/data/worker.js"));
+ QVERIFY(QFile::exists(":/workerscripts/data/worker.qml"));
+ QCOMPARE(QFileInfo(":/workerscripts/data/worker.js").size(), 0);
QQmlEngine engine;
- CleanlyLoadingComponent component(&engine, QUrl("qrc:///workerscripts/worker.qml"));
+ CleanlyLoadingComponent component(&engine, QUrl("qrc:///workerscripts/data/worker.qml"));
QScopedPointer<QObject> obj(component.create());
QVERIFY(!obj.isNull());
QTRY_VERIFY(obj->property("success").toBool());
@@ -504,7 +513,7 @@ void tst_qmlcachegen::trickyPaths()
void tst_qmlcachegen::qrcScriptImport()
{
QQmlEngine engine;
- CleanlyLoadingComponent component(&engine, QUrl("qrc:///jsimport.qml"));
+ CleanlyLoadingComponent component(&engine, QUrl("qrc:///data/jsimport.qml"));
QScopedPointer<QObject> obj(component.create());
QVERIFY(!obj.isNull());
QTRY_COMPARE(obj->property("value").toInt(), 42);
@@ -567,14 +576,14 @@ void tst_qmlcachegen::fsScriptImport()
void tst_qmlcachegen::moduleScriptImport()
{
QQmlEngine engine;
- CleanlyLoadingComponent component(&engine, QUrl("qrc:///jsmoduleimport.qml"));
+ CleanlyLoadingComponent component(&engine, QUrl("qrc:///data/jsmoduleimport.qml"));
QVERIFY2(!component.isError(), qPrintable(component.errorString()));
QScopedPointer<QObject> obj(component.create());
QVERIFY(!obj.isNull());
QTRY_VERIFY(obj->property("ok").toBool());
- QVERIFY(QFile::exists(":/script.mjs"));
- QCOMPARE(QFileInfo(":/script.mjs").size(), 0);
+ QVERIFY(QFile::exists(":/data/script.mjs"));
+ QCOMPARE(QFileInfo(":/data/script.mjs").size(), 0);
{
auto componentPrivate = QQmlComponentPrivate::get(&component);
@@ -587,7 +596,8 @@ void tst_qmlcachegen::moduleScriptImport()
QVERIFY(unitData->flags & QV4::CompiledData::Unit::IsESModule);
QQmlMetaType::CachedUnitLookupError error = QQmlMetaType::CachedUnitLookupError::NoError;
- const QV4::CompiledData::Unit *unitFromResources = QQmlMetaType::findCachedCompilationUnit(QUrl("qrc:/script.mjs"), &error);
+ const QV4::CompiledData::Unit *unitFromResources = QQmlMetaType::findCachedCompilationUnit(
+ QUrl("qrc:/data/script.mjs"), &error);
QVERIFY(unitFromResources);
QCOMPARE(unitFromResources, compilationUnit->unitData());
@@ -597,7 +607,7 @@ void tst_qmlcachegen::moduleScriptImport()
void tst_qmlcachegen::enums()
{
QQmlEngine engine;
- CleanlyLoadingComponent component(&engine, QUrl("qrc:///Enums.qml"));
+ CleanlyLoadingComponent component(&engine, QUrl("qrc:///data/Enums.qml"));
QScopedPointer<QObject> obj(component.create());
QVERIFY(!obj.isNull());
QTRY_COMPARE(obj->property("value").toInt(), 200);
@@ -605,16 +615,50 @@ void tst_qmlcachegen::enums()
void tst_qmlcachegen::sourceFileIndices()
{
- QVERIFY(QFile::exists(":/versionchecks.qml"));
- QCOMPARE(QFileInfo(":/versionchecks.qml").size(), 0);
+ QVERIFY(QFile::exists(":/data/versionchecks.qml"));
+ QCOMPARE(QFileInfo(":/data/versionchecks.qml").size(), 0);
QQmlMetaType::CachedUnitLookupError error = QQmlMetaType::CachedUnitLookupError::NoError;
- const QV4::CompiledData::Unit *unitFromResources = QQmlMetaType::findCachedCompilationUnit(QUrl("qrc:/versionchecks.qml"), &error);
+ const QV4::CompiledData::Unit *unitFromResources = QQmlMetaType::findCachedCompilationUnit(
+ QUrl("qrc:/data/versionchecks.qml"), &error);
QVERIFY(unitFromResources);
QVERIFY(unitFromResources->flags & QV4::CompiledData::Unit::PendingTypeCompilation);
QCOMPARE(uint(unitFromResources->sourceFileIndex), uint(0));
}
+void tst_qmlcachegen::reproducibleCache_data()
+{
+ QTest::addColumn<QString>("filePath");
+
+ QDir dir(dataDirectory());
+ for (const QString &entry : dir.entryList(QDir::Files)) {
+ QVERIFY(entry.endsWith(".qml") || entry.endsWith(".js") || entry.endsWith(".mjs"));
+ QTest::newRow(entry.toUtf8().constData()) << dir.filePath(entry);
+ }
+}
+
+void tst_qmlcachegen::reproducibleCache()
+{
+ QFETCH(QString, filePath);
+
+ QFile file(filePath);
+ QVERIFY(file.exists());
+
+ auto generate = [](const QString &path) {
+ if (!generateCache(path))
+ return QByteArray();
+ QFile generated(path + 'c');
+ [&](){ QVERIFY(generated.open(QIODevice::ReadOnly)); }();
+ const QByteArray result = generated.readAll();
+ generated.remove();
+ return result;
+ };
+
+ const QByteArray contents1 = generate(file.fileName());
+ const QByteArray contents2 = generate(file.fileName());
+ QCOMPARE(contents1, contents2);
+}
+
QTEST_GUILESS_MAIN(tst_qmlcachegen)
#include "tst_qmlcachegen.moc"
diff --git a/tests/auto/quick/qquickmultipointtoucharea/BLACKLIST b/tests/auto/quick/qquickmultipointtoucharea/BLACKLIST
index cdb3e7733b..de939b5273 100644
--- a/tests/auto/quick/qquickmultipointtoucharea/BLACKLIST
+++ b/tests/auto/quick/qquickmultipointtoucharea/BLACKLIST
@@ -1,6 +1,10 @@
[nonOverlapping]
ubuntu-16.04
ubuntu-18.04
+opensuse-42.3
+opensuse-leap
[nested]
ubuntu-16.04
ubuntu-18.04
+opensuse-42.3
+opensuse-leap
diff --git a/tests/auto/quick/qquickrectangle/tst_qquickrectangle.cpp b/tests/auto/quick/qquickrectangle/tst_qquickrectangle.cpp
index b34612ee88..832b973d96 100644
--- a/tests/auto/quick/qquickrectangle/tst_qquickrectangle.cpp
+++ b/tests/auto/quick/qquickrectangle/tst_qquickrectangle.cpp
@@ -159,17 +159,15 @@ void tst_qquickrectangle::gradient_multiple()
// Start off clean
QQuickItemPrivate *firstRectPriv = QQuickItemPrivate::get(firstRect);
QQuickItemPrivate *secondRectPriv = QQuickItemPrivate::get(secondRect);
- bool firstIsDirty = firstRectPriv->dirtyAttributes & QQuickItemPrivate::Content;
+ QTRY_VERIFY(!(firstRectPriv->dirtyAttributes & QQuickItemPrivate::Content));
bool secondIsDirty = secondRectPriv->dirtyAttributes & QQuickItemPrivate::Content;
- QVERIFY(!firstIsDirty);
QVERIFY(!secondIsDirty);
QMetaObject::invokeMethod(view.rootObject(), "changeGradient");
// Changing the gradient should have scheduled an update of both items
- firstIsDirty = firstRectPriv->dirtyAttributes & QQuickItemPrivate::Content;
+ QTRY_VERIFY(firstRectPriv->dirtyAttributes & QQuickItemPrivate::Content);
secondIsDirty = secondRectPriv->dirtyAttributes & QQuickItemPrivate::Content;
- QVERIFY(firstIsDirty);
QVERIFY(secondIsDirty);
}
diff --git a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
index a862604fc1..4cf7fa7119 100644
--- a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
+++ b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
@@ -1645,11 +1645,11 @@ void tst_qquickwindow::focusReason()
window->setTitle(QTest::currentTestFunction());
QVERIFY(QTest::qWaitForWindowExposed(window));
- QQuickItem *firstItem = new QQuickItem;
+ QScopedPointer<QQuickItem> firstItem(new QQuickItem);
firstItem->setSize(QSizeF(100, 100));
firstItem->setParentItem(window->contentItem());
- QQuickItem *secondItem = new QQuickItem;
+ QScopedPointer<QQuickItem> secondItem(new QQuickItem);
secondItem->setSize(QSizeF(100, 100));
secondItem->setParentItem(window->contentItem());
@@ -1673,7 +1673,7 @@ void tst_qquickwindow::ignoreUnhandledMouseEvents()
window->show();
QVERIFY(QTest::qWaitForWindowExposed(window));
- QQuickItem *item = new QQuickItem;
+ QScopedPointer<QQuickItem> item(new QQuickItem);
item->setSize(QSizeF(100, 100));
item->setParentItem(window->contentItem());
@@ -1883,8 +1883,8 @@ void tst_qquickwindow::hideThenDelete()
QFETCH(bool, persistentSG);
QFETCH(bool, persistentGL);
- QSignalSpy *openglDestroyed = nullptr;
- QSignalSpy *sgInvalidated = nullptr;
+ QScopedPointer<QSignalSpy> openglDestroyed;
+ QScopedPointer<QSignalSpy> sgInvalidated;
{
QQuickWindow window;
@@ -1903,10 +1903,10 @@ void tst_qquickwindow::hideThenDelete()
const bool isGL = window.rendererInterface()->graphicsApi() == QSGRendererInterface::OpenGL;
#if QT_CONFIG(opengl)
if (isGL)
- openglDestroyed = new QSignalSpy(window.openglContext(), SIGNAL(aboutToBeDestroyed()));
+ openglDestroyed.reset(new QSignalSpy(window.openglContext(), SIGNAL(aboutToBeDestroyed())));
#endif
- sgInvalidated = new QSignalSpy(&window, SIGNAL(sceneGraphInvalidated()));
+ sgInvalidated.reset(new QSignalSpy(&window, SIGNAL(sceneGraphInvalidated())));
window.hide();
@@ -1951,7 +1951,7 @@ void tst_qquickwindow::showHideAnimate()
QQmlEngine engine;
QQmlComponent component(&engine);
component.loadUrl(testFileUrl("showHideAnimate.qml"));
- QQuickItem* created = qobject_cast<QQuickItem *>(component.create());
+ QScopedPointer<QQuickItem> created(qobject_cast<QQuickItem *>(component.create()));
QVERIFY(created);
@@ -2293,7 +2293,7 @@ void tst_qquickwindow::contentItemSize()
QQmlEngine engine;
QQmlComponent component(&engine);
component.setData(QByteArray("import QtQuick 2.1\n Rectangle { anchors.fill: parent }"), QUrl());
- QQuickItem *rect = qobject_cast<QQuickItem *>(component.create());
+ QScopedPointer<QQuickItem> rect(qobject_cast<QQuickItem *>(component.create()));
QVERIFY(rect);
rect->setParentItem(window.contentItem());
QCOMPARE(QSizeF(rect->width(), rect->height()), size);
diff --git a/tests/auto/quicktest/quicktestmainwithsetup/data/tst_setup.qml b/tests/auto/quicktest/quicktestmainwithsetup/data/tst_setup.qml
index 0f5466998a..ea6b3e014b 100644
--- a/tests/auto/quicktest/quicktestmainwithsetup/data/tst_setup.qml
+++ b/tests/auto/quicktest/quicktestmainwithsetup/data/tst_setup.qml
@@ -29,9 +29,15 @@
import QtQuick 2.0
import QtTest 1.2
+import QmlRegisterTypeCppModule 1.0
+import ImportPathQmlModule 1.0
+
TestCase {
name: "setup"
+ QmlRegisterTypeCppType {}
+ ImportPathQmlType {}
+
function initTestCase()
{
verify(qmlEngineAvailableCalled)
diff --git a/tests/auto/quicktest/quicktestmainwithsetup/imports/ImportPathQmlModule/ImportPathQmlType.qml b/tests/auto/quicktest/quicktestmainwithsetup/imports/ImportPathQmlModule/ImportPathQmlType.qml
new file mode 100644
index 0000000000..617bdaaf67
--- /dev/null
+++ b/tests/auto/quicktest/quicktestmainwithsetup/imports/ImportPathQmlModule/ImportPathQmlType.qml
@@ -0,0 +1,3 @@
+import QtQuick 2.0
+
+Item {}
diff --git a/tests/auto/quicktest/quicktestmainwithsetup/imports/ImportPathQmlModule/qmldir b/tests/auto/quicktest/quicktestmainwithsetup/imports/ImportPathQmlModule/qmldir
new file mode 100644
index 0000000000..dea7c9a8a4
--- /dev/null
+++ b/tests/auto/quicktest/quicktestmainwithsetup/imports/ImportPathQmlModule/qmldir
@@ -0,0 +1,2 @@
+module ImportPathQmlModule
+ImportPathQmlType 1.0 ImportPathQmlType.qml
diff --git a/tests/auto/quicktest/quicktestmainwithsetup/tst_quicktestmainwithsetup.cpp b/tests/auto/quicktest/quicktestmainwithsetup/tst_quicktestmainwithsetup.cpp
index b0545d1a95..b5deeceac4 100644
--- a/tests/auto/quicktest/quicktestmainwithsetup/tst_quicktestmainwithsetup.cpp
+++ b/tests/auto/quicktest/quicktestmainwithsetup/tst_quicktestmainwithsetup.cpp
@@ -35,6 +35,14 @@
#include "../../shared/util.h"
+class QmlRegisterTypeCppType : public QObject
+{
+ Q_OBJECT
+
+public:
+ QmlRegisterTypeCppType() {}
+};
+
class CustomTestSetup : public QObject
{
Q_OBJECT
@@ -45,6 +53,12 @@ public:
public slots:
void qmlEngineAvailable(QQmlEngine *qmlEngine)
{
+ // Test that modules are successfully imported by the TestCaseCollector that
+ // parses the QML files (but doesn't run them). For that to happen, qmlEngineAvailable()
+ // must be called before TestCaseCollector does its thing.
+ qmlRegisterType<QmlRegisterTypeCppType>("QmlRegisterTypeCppModule", 1, 0, "QmlRegisterTypeCppType");
+ qmlEngine->addImportPath(QString::fromUtf8(QT_QMLTEST_DATADIR) + "/../imports");
+
qmlEngine->rootContext()->setContextProperty("qmlEngineAvailableCalled", true);
}
};
diff --git a/tools/qmlcachegen/qmlcachegen.cpp b/tools/qmlcachegen/qmlcachegen.cpp
index f6f1d99526..1c9a004cb3 100644
--- a/tools/qmlcachegen/qmlcachegen.cpp
+++ b/tools/qmlcachegen/qmlcachegen.cpp
@@ -204,7 +204,6 @@ static bool compileQmlFile(const QString &inputFileName, SaveFunction saveFuncti
&irDocument.jsGenerator, &irDocument.jsModule,
&irDocument.jsParserEngine, irDocument.program,
&irDocument.jsGenerator.stringTable, illegalNames);
- v4CodeGen.setUseFastLookups(false); // Disable lookups in non-standalone (aka QML) mode
for (QmlIR::Object *object: qAsConst(irDocument.objects)) {
if (object->functionsAndExpressions->count == 0)
continue;
@@ -236,8 +235,6 @@ static bool compileQmlFile(const QString &inputFileName, SaveFunction saveFuncti
if (!saveFunction(irDocument.javaScriptCompilationUnit, &error->message))
return false;
-
- free(unit);
}
return true;
}
@@ -245,7 +242,6 @@ static bool compileQmlFile(const QString &inputFileName, SaveFunction saveFuncti
static bool compileJSFile(const QString &inputFileName, const QString &inputFileUrl, SaveFunction saveFunction, Error *error)
{
QQmlRefPointer<QV4::CompiledData::CompilationUnit> unit;
- QScopedPointer<QV4::CompiledData::Unit, QScopedPointerPodDeleter> unitDataToFree;
QString sourceCode;
{
@@ -327,7 +323,6 @@ static bool compileJSFile(const QString &inputFileName, const QString &inputFile
generator.generate(irDocument);
QV4::CompiledData::Unit *unitData = const_cast<QV4::CompiledData::Unit*>(irDocument.javaScriptCompilationUnit->data);
unitData->flags |= QV4::CompiledData::Unit::StaticData;
- unitDataToFree.reset(unitData);
unit = irDocument.javaScriptCompilationUnit;
}
}