aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/3rdparty/masm/assembler/LinkBuffer.h8
-rw-r--r--src/qml/compiler/qqmlpropertycachecreator_p.h40
-rw-r--r--src/qml/compiler/qqmlpropertyvalidator.cpp5
-rw-r--r--src/qml/compiler/qv4compileddata.cpp8
-rw-r--r--src/qml/compiler/qv4compilercontext_p.h1
-rw-r--r--src/qml/compiler/qv4compilerscanfunctions.cpp27
-rw-r--r--src/qml/jsruntime/qv4engine.cpp4
-rw-r--r--src/qml/jsruntime/qv4global_p.h3
-rw-r--r--src/qml/jsruntime/qv4identifiertable.cpp2
-rw-r--r--src/qml/jsruntime/qv4stringobject.cpp3
-rw-r--r--src/qml/qml/qqmlimport.cpp2
-rw-r--r--src/qml/qml/qqmlvaluetype.cpp29
-rw-r--r--src/qmltest/doc/src/qtquicktest-index.qdoc8
-rw-r--r--src/quick/doc/qtquick.qdocconf1
-rw-r--r--src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc12
-rw-r--r--src/quick/items/qquickwindow.cpp12
-rw-r--r--src/quick/items/qquickwindow.h1
-rw-r--r--src/quickwidgets/qquickwidget.cpp31
-rw-r--r--tests/auto/qml/qjsengine/tst_qjsengine.cpp28
-rw-r--r--tests/auto/qml/qmlmin/tst_qmlmin.cpp1
-rw-r--r--tests/auto/qml/qqmllanguage/data/cyclicAlias.errors.txt1
-rw-r--r--tests/auto/qml/qqmllanguage/data/cyclicAlias.qml5
-rw-r--r--tests/auto/qml/qqmllanguage/data/fuzzed.1.errors.txt2
-rw-r--r--tests/auto/qml/qqmllanguage/data/fuzzed.1.qml2
-rw-r--r--tests/auto/qml/qqmllanguage/data/fuzzed.2.errors.txt2
-rw-r--r--tests/auto/qml/qqmllanguage/data/fuzzed.2.qmlbin0 -> 404 bytes
-rw-r--r--tests/auto/qml/qqmllanguage/data/objectValueTypeProperty.errors.txt2
-rw-r--r--tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp7
-rw-r--r--tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp23
-rw-r--r--tests/auto/qml/qv4assembler/tst_qv4assembler.cpp23
-rw-r--r--tests/auto/quick/qquicklistview/BLACKLIST3
-rw-r--r--tests/auto/quick/qquickmultipointtoucharea/BLACKLIST2
-rw-r--r--tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp4
-rw-r--r--tools/qmlscene/main.cpp7
34 files changed, 236 insertions, 73 deletions
diff --git a/src/3rdparty/masm/assembler/LinkBuffer.h b/src/3rdparty/masm/assembler/LinkBuffer.h
index 4dfd051797..a1bb046d43 100644
--- a/src/3rdparty/masm/assembler/LinkBuffer.h
+++ b/src/3rdparty/masm/assembler/LinkBuffer.h
@@ -245,7 +245,7 @@ protected:
inline void linkCode(void* ownerUID, JITCompilationEffort);
- inline void performFinalization();
+ virtual void performFinalization();
#if DUMP_LINK_STATISTICS
static void dumpLinkStatistics(void* code, size_t initialSize, size_t finalSize);
@@ -344,7 +344,7 @@ inline void LinkBufferBase<MacroAssembler, ExecutableOffsetCalculator>::linkCode
}
template <typename MacroAssembler, template <typename T> class ExecutableOffsetCalculator>
-inline void LinkBufferBase<MacroAssembler, ExecutableOffsetCalculator>::performFinalization()
+void LinkBufferBase<MacroAssembler, ExecutableOffsetCalculator>::performFinalization()
{
// NOTE: This function is specialized in LinkBuffer<MacroAssemblerARMv7>
#ifndef NDEBUG
@@ -395,7 +395,7 @@ public:
linkCode(ownerUID, effort);
}
- inline void performFinalization();
+ virtual void performFinalization() override final;
inline void makeExecutable();
inline void linkCode(void* ownerUID, JITCompilationEffort);
@@ -420,7 +420,7 @@ private:
};
template <typename MacroAssembler>
-inline void BranchCompactingLinkBuffer<MacroAssembler>::performFinalization()
+void BranchCompactingLinkBuffer<MacroAssembler>::performFinalization()
{
#ifndef NDEBUG
ASSERT(!m_completed);
diff --git a/src/qml/compiler/qqmlpropertycachecreator_p.h b/src/qml/compiler/qqmlpropertycachecreator_p.h
index 7d416561bb..a1e93702d1 100644
--- a/src/qml/compiler/qqmlpropertycachecreator_p.h
+++ b/src/qml/compiler/qqmlpropertycachecreator_p.h
@@ -693,11 +693,6 @@ inline QQmlCompileError QQmlPropertyCacheAliasCreator<ObjectContainer>::property
const CompiledObject &component, const QV4::CompiledData::Alias &alias, int *type, int *minorVersion,
QQmlPropertyData::Flags *propertyFlags)
{
- const int targetObjectIndex = objectForId(component, alias.targetObjectId);
- Q_ASSERT(targetObjectIndex >= 0);
-
- const CompiledObject &targetObject = *objectContainer->objectAt(targetObjectIndex);
-
*type = 0;
bool writable = false;
bool resettable = false;
@@ -705,11 +700,36 @@ inline QQmlCompileError QQmlPropertyCacheAliasCreator<ObjectContainer>::property
propertyFlags->isAlias = true;
if (alias.aliasToLocalAlias) {
- auto targetAlias = targetObject.aliasesBegin();
- for (uint i = 0; i < alias.localAliasIndex; ++i)
- ++targetAlias;
- return propertyDataForAlias(component, *targetAlias, type, minorVersion, propertyFlags);
- } else if (alias.encodedMetaPropertyIndex == -1) {
+ const QV4::CompiledData::Alias *lastAlias = &alias;
+ QVarLengthArray<const QV4::CompiledData::Alias *, 4> seenAliases({lastAlias});
+
+ do {
+ const CompiledObject *targetObject = objectContainer->objectAt(
+ objectForId(component, lastAlias->targetObjectId));
+ Q_ASSERT(targetObject);
+
+ auto nextAlias = targetObject->aliasesBegin();
+ for (uint i = 0; i < lastAlias->localAliasIndex; ++i)
+ ++nextAlias;
+
+ const QV4::CompiledData::Alias *targetAlias = &(*nextAlias);
+ if (seenAliases.contains(targetAlias)) {
+ return QQmlCompileError(targetAlias->location,
+ QQmlPropertyCacheCreatorBase::tr("Cyclic alias"));
+ }
+
+ seenAliases.append(targetAlias);
+ lastAlias = targetAlias;
+ } while (lastAlias->aliasToLocalAlias);
+
+ return propertyDataForAlias(component, *lastAlias, type, minorVersion, propertyFlags);
+ }
+
+ const int targetObjectIndex = objectForId(component, alias.targetObjectId);
+ Q_ASSERT(targetObjectIndex >= 0);
+ const CompiledObject &targetObject = *objectContainer->objectAt(targetObjectIndex);
+
+ if (alias.encodedMetaPropertyIndex == -1) {
Q_ASSERT(alias.flags & QV4::CompiledData::Alias::AliasPointsToPointerObject);
auto *typeRef = objectContainer->resolvedType(targetObject.inheritedTypeNameIndex);
if (!typeRef) {
diff --git a/src/qml/compiler/qqmlpropertyvalidator.cpp b/src/qml/compiler/qqmlpropertyvalidator.cpp
index 4714f505a7..8c06760d42 100644
--- a/src/qml/compiler/qqmlpropertyvalidator.cpp
+++ b/src/qml/compiler/qqmlpropertyvalidator.cpp
@@ -693,7 +693,10 @@ QQmlCompileError QQmlPropertyValidator::validateObjectBinding(QQmlPropertyData *
} else if (binding->flags & QV4::CompiledData::Binding::IsSignalHandlerObject && property->isFunction()) {
return noError;
} else if (QQmlValueTypeFactory::isValueType(property->propType())) {
- return QQmlCompileError(binding->location, tr("Unexpected object assignment for property \"%1\"").arg(propertyName));
+ auto typeName = QMetaType::typeName(property->propType());
+ return QQmlCompileError(binding->location, tr("Can not assign value of type \"%1\" to property \"%2\", expecting an object")
+ .arg(typeName ? QString::fromLatin1(typeName) : QString::fromLatin1("<unknown type>"))
+ .arg(propertyName));
} else if (property->propType() == qMetaTypeId<QQmlScriptString>()) {
return QQmlCompileError(binding->valueLocation, tr("Invalid property assignment: script expected"));
} else {
diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp
index f280994d54..a78094f17c 100644
--- a/src/qml/compiler/qv4compileddata.cpp
+++ b/src/qml/compiler/qv4compileddata.cpp
@@ -470,8 +470,10 @@ Heap::Module *CompilationUnit::instantiate(ExecutionEngine *engine)
ScopedString importName(scope);
const uint importCount = data->importEntryTableSize;
- imports = new const Value *[importCount];
- memset(imports, 0, importCount * sizeof(Value *));
+ if (importCount > 0) {
+ imports = new const Value *[importCount];
+ memset(imports, 0, importCount * sizeof(Value *));
+ }
for (uint i = 0; i < importCount; ++i) {
const CompiledData::ImportEntry &entry = data->importEntryTable()[i];
auto dependentModuleUnit = engine->loadModule(QUrl(stringAt(entry.moduleRequest)), this);
@@ -897,6 +899,8 @@ bool ResolvedTypeReference::addToHash(QCryptographicHash *hash, QQmlEngine *engi
hash->addData(createPropertyCache(engine)->checksum(&ok));
return ok;
}
+ if (!compilationUnit)
+ return false;
hash->addData(compilationUnit->unitData()->md5Checksum, sizeof(compilationUnit->unitData()->md5Checksum));
return true;
}
diff --git a/src/qml/compiler/qv4compilercontext_p.h b/src/qml/compiler/qv4compilercontext_p.h
index cb20ea9d57..57ef4be36e 100644
--- a/src/qml/compiler/qv4compilercontext_p.h
+++ b/src/qml/compiler/qv4compilercontext_p.h
@@ -217,7 +217,6 @@ struct Context {
bool usesThis = false;
bool innerFunctionAccessesThis = false;
bool innerFunctionAccessesNewTarget = false;
- bool hasTry = false;
bool returnsClosure = false;
mutable bool argumentsCanEscape = false;
bool requiresExecutionContext = false;
diff --git a/src/qml/compiler/qv4compilerscanfunctions.cpp b/src/qml/compiler/qv4compilerscanfunctions.cpp
index 04593f202a..8984b6931e 100644
--- a/src/qml/compiler/qv4compilerscanfunctions.cpp
+++ b/src/qml/compiler/qv4compilerscanfunctions.cpp
@@ -741,9 +741,9 @@ void ScanFunctions::calcEscapingVariables()
if (c->contextType != ContextType::ESModule)
continue;
for (const auto &entry: c->exportEntries) {
- auto m = c->members.find(entry.localName);
- if (m != c->members.end())
- m->canEscape = true;
+ auto mIt = c->members.constFind(entry.localName);
+ if (mIt != c->members.constEnd())
+ mIt->canEscape = true;
}
break;
}
@@ -759,8 +759,8 @@ void ScanFunctions::calcEscapingVariables()
}
Q_ASSERT(c != inner);
while (c) {
- Context::MemberMap::const_iterator it = c->members.find(var);
- if (it != c->members.end()) {
+ Context::MemberMap::const_iterator it = c->members.constFind(var);
+ if (it != c->members.constEnd()) {
if (c->parent || it->isLexicallyScoped()) {
it->canEscape = true;
c->requiresExecutionContext = true;
@@ -816,15 +816,17 @@ void ScanFunctions::calcEscapingVariables()
// add an escaping 'this' variable
c->addLocalVar(QStringLiteral("this"), Context::VariableDefinition, VariableScope::Let);
c->requiresExecutionContext = true;
- auto m = c->members.find(QStringLiteral("this"));
- m->canEscape = true;
+ auto mIt = c->members.constFind(QStringLiteral("this"));
+ Q_ASSERT(mIt != c->members.constEnd());
+ mIt->canEscape = true;
}
if (c->innerFunctionAccessesNewTarget) {
// add an escaping 'new.target' variable
c->addLocalVar(QStringLiteral("new.target"), Context::VariableDefinition, VariableScope::Let);
c->requiresExecutionContext = true;
- auto m = c->members.find(QStringLiteral("new.target"));
- m->canEscape = true;
+ auto mIt = c->members.constFind(QStringLiteral("new.target"));
+ Q_ASSERT(mIt != c->members.constEnd());
+ mIt->canEscape = true;
}
if (c->allVarsEscape && c->contextType == ContextType::Block && c->members.isEmpty())
c->allVarsEscape = false;
@@ -845,8 +847,9 @@ void ScanFunctions::calcEscapingVariables()
}
if (c->contextType == ContextType::Block && c->isCatchBlock) {
c->requiresExecutionContext = true;
- auto m = c->members.find(c->caughtVariable);
- m->canEscape = true;
+ auto mIt = c->members.constFind(c->caughtVariable);
+ Q_ASSERT(mIt != c->members.constEnd());
+ mIt->canEscape = true;
}
const QLatin1String exprForOn("expression for on");
if (c->contextType == ContextType::Binding && c->name.length() > exprForOn.size() &&
@@ -855,7 +858,7 @@ void ScanFunctions::calcEscapingVariables()
// we don't know if the code is a signal handler or not.
c->requiresExecutionContext = true;
if (c->allVarsEscape) {
- for (auto &m : c->members)
+ for (const auto &m : qAsConst(c->members))
m.canEscape = true;
}
}
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index 5bc81de472..18927c637c 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -1544,6 +1544,10 @@ QV4::ReturnedValue QV4::ExecutionEngine::fromVariant(const QVariant &variant)
case QMetaType::QLocale:
return QQmlLocale::wrap(this, *reinterpret_cast<const QLocale*>(ptr));
#endif
+ case QMetaType::QPixmap:
+ case QMetaType::QImage:
+ // Scarce value types
+ return QV4::Encode(newVariantObject(variant));
default:
break;
}
diff --git a/src/qml/jsruntime/qv4global_p.h b/src/qml/jsruntime/qv4global_p.h
index 44adac26cd..d47393b3bb 100644
--- a/src/qml/jsruntime/qv4global_p.h
+++ b/src/qml/jsruntime/qv4global_p.h
@@ -94,7 +94,8 @@ inline double trunc(double d) { return d > 0 ? floor(d) : ceil(d); }
#elif defined(Q_PROCESSOR_X86_64) && (QT_POINTER_SIZE == 8) \
&& (defined(Q_OS_WIN) || defined(Q_OS_LINUX) || defined(Q_OS_QNX) || defined(Q_OS_MAC) || defined(Q_OS_FREEBSD))
# define V4_ENABLE_JIT
-#elif defined(Q_PROCESSOR_ARM_32) && (QT_POINTER_SIZE == 4)
+#elif defined(Q_PROCESSOR_ARM_32) && (QT_POINTER_SIZE == 4) \
+ && (defined(Q_OS_LINUX) || defined(Q_OS_QNX) || defined(Q_OS_FREEBSD) || defined(Q_OS_INTEGRITY))
# if defined(thumb2) || defined(__thumb2__) || ((defined(__thumb) || defined(__thumb__)) && __TARGET_ARCH_THUMB-0 == 4)
# define V4_ENABLE_JIT
# elif defined(__ARM_ARCH_ISA_THUMB) && __ARM_ARCH_ISA_THUMB == 2 // clang 3.5 and later will set this if the core supports the Thumb-2 ISA.
diff --git a/src/qml/jsruntime/qv4identifiertable.cpp b/src/qml/jsruntime/qv4identifiertable.cpp
index 102c06d9b0..ae937b2889 100644
--- a/src/qml/jsruntime/qv4identifiertable.cpp
+++ b/src/qml/jsruntime/qv4identifiertable.cpp
@@ -70,7 +70,7 @@ IdentifierTable::~IdentifierTable()
{
free(entriesByHash);
free(entriesById);
- for (auto &h : idHashes)
+ for (const auto &h : qAsConst(idHashes))
h->identifierTable = nullptr;
}
diff --git a/src/qml/jsruntime/qv4stringobject.cpp b/src/qml/jsruntime/qv4stringobject.cpp
index 1c6dfe0fdb..227df4014e 100644
--- a/src/qml/jsruntime/qv4stringobject.cpp
+++ b/src/qml/jsruntime/qv4stringobject.cpp
@@ -766,9 +766,8 @@ static void appendReplacementString(QString *result, const QString &input, const
i += skip;
if (substStart != JSC::Yarr::offsetNoMatch && substEnd != JSC::Yarr::offsetNoMatch)
*result += input.midRef(substStart, substEnd - substStart);
- else {
+ else if (skip == 0) // invalid capture reference. Taken as literal value
*result += replaceValue.at(i);
- }
} else {
*result += replaceValue.at(i);
}
diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp
index d2d37164a7..9d5801bbc6 100644
--- a/src/qml/qml/qqmlimport.cpp
+++ b/src/qml/qml/qqmlimport.cpp
@@ -796,7 +796,7 @@ bool QQmlImportInstance::resolveType(QQmlTypeLoader *typeLoader, const QHashedSt
*typeRecursionDetected = true;
} else {
QQmlType returnType = QQmlMetaType::typeForUrl(
- qmlUrl, type, registrationType == QQmlType::CompositeSingletonType, nullptr);
+ qmlUrl, type, registrationType == QQmlType::CompositeSingletonType, errors);
if (type_return)
*type_return = returnType;
return returnType.isValid();
diff --git a/src/qml/qml/qqmlvaluetype.cpp b/src/qml/qml/qqmlvaluetype.cpp
index 21505754bb..f08005fd20 100644
--- a/src/qml/qml/qqmlvaluetype.cpp
+++ b/src/qml/qml/qqmlvaluetype.cpp
@@ -80,19 +80,26 @@ QQmlValueTypeFactoryImpl::~QQmlValueTypeFactoryImpl()
bool QQmlValueTypeFactoryImpl::isValueType(int idx)
{
- if (idx >= (int)QVariant::UserType) {
- return (valueType(idx) != nullptr);
- } else if (idx >= 0
- && idx != QVariant::StringList
- && idx != QMetaType::QObjectStar
- && idx != QMetaType::VoidStar
- && idx != QMetaType::Nullptr
- && idx != QMetaType::QVariant
- && idx != QMetaType::QLocale) {
+ if (idx >= QMetaType::User)
+ return valueType(idx) != nullptr;
+
+ if (idx < 0)
+ return false;
+
+ // Qt internal types
+ switch (idx) {
+ case QMetaType::QStringList:
+ case QMetaType::QObjectStar:
+ case QMetaType::VoidStar:
+ case QMetaType::Nullptr:
+ case QMetaType::QVariant:
+ case QMetaType::QLocale:
+ case QMetaType::QImage: // scarce type, keep as QVariant
+ case QMetaType::QPixmap: // scarce type, keep as QVariant
+ return false;
+ default:
return true;
}
-
- return false;
}
const QMetaObject *QQmlValueTypeFactoryImpl::metaObjectForMetaType(int t)
diff --git a/src/qmltest/doc/src/qtquicktest-index.qdoc b/src/qmltest/doc/src/qtquicktest-index.qdoc
index 668d6c1417..a7a840f2b3 100644
--- a/src/qmltest/doc/src/qtquicktest-index.qdoc
+++ b/src/qmltest/doc/src/qtquicktest-index.qdoc
@@ -164,6 +164,10 @@
and \l {QQmlFileSelector::setExtraSelectors}{extra file selectors}
will have been set on the engine by this point.
+ This function is called once for each QML test file,
+ so any arguments are unique to that test. For example, this
+ means that each QML test file will have its own QML engine.
+
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},
@@ -176,10 +180,6 @@
\li Qt 5.12
\endtable
- Each function will be called once for each \c {tst_*.qml} file, so any
- arguments are unique to that test. For example, this means that each QML
- test file will have its own QML engine.
-
The following example demonstrates how the macro can be used to set context
properties on the QML engine:
diff --git a/src/quick/doc/qtquick.qdocconf b/src/quick/doc/qtquick.qdocconf
index b1268097fc..6620650d4a 100644
--- a/src/quick/doc/qtquick.qdocconf
+++ b/src/quick/doc/qtquick.qdocconf
@@ -43,7 +43,6 @@ headerdirs += ..\
../../quickwidgets
sourcedirs += .. \
- ../../imports/testlib \
../../quickwidgets
exampledirs += ../../../examples/quick \
diff --git a/src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc b/src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc
index 4c94259139..9383c78a42 100644
--- a/src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc
+++ b/src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2018 The Qt Company Ltd.
+** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt Toolkit.
@@ -269,7 +269,7 @@ animations, process events, etc.
\endlist
The threaded renderer is currently used by default on Windows with
-opengl32.dll, Linux with non-Mesa based drivers, \macos, mobile
+opengl32.dll, Linux with non-Mesa based drivers, mobile
platforms, and Embedded Linux with EGLFS but this is subject to
change. It is possible to force use of the threaded renderer by
setting \c {QSG_RENDER_LOOP=threaded} in the environment.
@@ -277,13 +277,19 @@ setting \c {QSG_RENDER_LOOP=threaded} in the environment.
\section2 Non-threaded Render Loops ("basic" and "windows")
The non-threaded render loop is currently used by default on Windows
-with ANGLE or a non-default opengl32 implementation and Linux with
+with ANGLE or a non-default opengl32 implementation, \macos, and Linux with
Mesa drivers. For the latter this is mostly a precautionary measure,
as not all combinations of OpenGL drivers and windowing systems have
been tested. At the same time implementations like ANGLE or Mesa
llvmpipe are not able to function properly with threaded rendering at
all so not using threaded rendering is essential for these.
+On macOS, the threaded render loop is not supported when building
+with XCode 10 (10.14 SDK) or later, since this opts in to layer-backed
+views on macOS 10.14. You can build with Xcode 9 (10.13 SDK) to opt
+out of layer-backing, in which case the threaded render loop is
+available and used by default.
+
By default \c windows is used for non-threaded rendering on Windows
with ANGLE, while \c basic is used for all other platforms when
non-threaded rendering is needed.
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index 88d419e2b3..9d0f4a6893 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -4892,10 +4892,18 @@ void QQuickWindow::scheduleRenderJob(QRunnable *job, RenderStage stage)
} else if (stage == AfterSwapStage) {
d->afterSwapJobs << job;
} else if (stage == NoStage) {
- if (isExposed())
+ if (d->renderControl && openglContext()
+#if QT_CONFIG(opengl)
+ && openglContext()->thread() == QThread::currentThread()
+#endif
+ ) {
+ job->run();
+ delete job;
+ } else if (isExposed()) {
d->windowManager->postJob(this, job);
- else
+ } else {
delete job;
+ }
}
d->renderJobMutex.unlock();
}
diff --git a/src/quick/items/qquickwindow.h b/src/quick/items/qquickwindow.h
index 79e8a11aa8..53fe0a4c4b 100644
--- a/src/quick/items/qquickwindow.h
+++ b/src/quick/items/qquickwindow.h
@@ -241,6 +241,7 @@ private:
friend class QQuickWidget;
friend class QQuickRenderControl;
friend class QQuickAnimatorController;
+ friend class QQuickWidgetPrivate;
Q_DISABLE_COPY(QQuickWindow)
};
diff --git a/src/quickwidgets/qquickwidget.cpp b/src/quickwidgets/qquickwidget.cpp
index a098c94670..f1a0f0c863 100644
--- a/src/quickwidgets/qquickwidget.cpp
+++ b/src/quickwidgets/qquickwidget.cpp
@@ -76,6 +76,18 @@
QT_BEGIN_NAMESPACE
+// override setVisble to prevent accidental offscreen window being created
+// by base class.
+class QQuickOffcreenWindowPrivate: public QQuickWindowPrivate {
+public:
+ void setVisible(bool visible) override {
+ Q_Q(QWindow);
+ // this stays always invisible
+ visibility = visible ? QWindow::Windowed : QWindow::Hidden;
+ q->visibilityChanged(visibility); // workaround for QTBUG-49054
+ }
+};
+
class QQuickWidgetRenderControl : public QQuickRenderControl
{
public:
@@ -94,7 +106,7 @@ void QQuickWidgetPrivate::init(QQmlEngine* e)
Q_Q(QQuickWidget);
renderControl = new QQuickWidgetRenderControl(q);
- offscreenWindow = new QQuickWindow(renderControl);
+ offscreenWindow = new QQuickWindow(*new QQuickOffcreenWindowPrivate(),renderControl);
offscreenWindow->setTitle(QString::fromLatin1("Offscreen"));
// Do not call create() on offscreenWindow.
@@ -1321,12 +1333,9 @@ void QQuickWidget::showEvent(QShowEvent *)
triggerUpdate();
}
}
- QWindowPrivate *offscreenPrivate = QWindowPrivate::get(d->offscreenWindow);
- if (!offscreenPrivate->visible) {
- offscreenPrivate->visible = true;
- emit d->offscreenWindow->visibleChanged(true);
- offscreenPrivate->updateVisibility();
- }
+
+ // note offscreenWindow is "QQuickOffScreenWindow" instance
+ d->offscreenWindow->setVisible(true);
if (QQmlInspectorService *service = QQmlDebugConnector::service<QQmlInspectorService>())
service->setParentWindow(d->offscreenWindow, window()->windowHandle());
}
@@ -1337,12 +1346,8 @@ void QQuickWidget::hideEvent(QHideEvent *)
Q_D(QQuickWidget);
if (!d->offscreenWindow->isPersistentSceneGraph())
d->invalidateRenderControl();
- QWindowPrivate *offscreenPrivate = QWindowPrivate::get(d->offscreenWindow);
- if (offscreenPrivate->visible) {
- offscreenPrivate->visible = false;
- emit d->offscreenWindow->visibleChanged(false);
- offscreenPrivate->updateVisibility();
- }
+ // note offscreenWindow is "QQuickOffScreenWindow" instance
+ d->offscreenWindow->setVisible(false);
if (QQmlInspectorService *service = QQmlDebugConnector::service<QQmlInspectorService>())
service->setParentWindow(d->offscreenWindow, d->offscreenWindow);
}
diff --git a/tests/auto/qml/qjsengine/tst_qjsengine.cpp b/tests/auto/qml/qjsengine/tst_qjsengine.cpp
index 02b7f79e42..9c3316e39f 100644
--- a/tests/auto/qml/qjsengine/tst_qjsengine.cpp
+++ b/tests/auto/qml/qjsengine/tst_qjsengine.cpp
@@ -4593,6 +4593,34 @@ void tst_QJSEngine::stringReplace()
val = engine.evaluate("'x'.replace(/()()()()()()()()()(x)/, '$10')");
QVERIFY(val.isString());
QCOMPARE(val.toString(), QString("x"));
+
+ val = engine.evaluate("'123'.replace(/\\.0*$|(\\.\\d*[1-9])(0+)$/, '$1')");
+ QVERIFY(val.isString());
+ QCOMPARE(val.toString(), QString("123"));
+
+ val = engine.evaluate("'123.00'.replace(/\\.0*$|(\\.\\d*[1-9])(0+)$/, '$1')");
+ QVERIFY(val.isString());
+ QCOMPARE(val.toString(), QString("123"));
+
+ val = engine.evaluate("'123.0'.replace(/\\.0*$|(\\.\\d*[1-9])(0+)$/, '$1')");
+ QVERIFY(val.isString());
+ QCOMPARE(val.toString(), QString("123"));
+
+ val = engine.evaluate("'123.'.replace(/\\.0*$|(\\.\\d*[1-9])(0+)$/, '$1')");
+ QVERIFY(val.isString());
+ QCOMPARE(val.toString(), QString("123"));
+
+ val = engine.evaluate("'123.50'.replace(/\\.0*$|(\\.\\d*[1-9])(0+)$/, '$1')");
+ QVERIFY(val.isString());
+ QCOMPARE(val.toString(), QString("123.5"));
+
+ val = engine.evaluate("'123.05'.replace(/\\.0*$|(\\.\\d*[1-9])(0+)$/, '$1')");
+ QVERIFY(val.isString());
+ QCOMPARE(val.toString(), QString("123.05"));
+
+ val = engine.evaluate("'0.050'.replace(/\\.0*$|(\\.\\d*[1-9])(0+)$/, '$1')");
+ QVERIFY(val.isString());
+ QCOMPARE(val.toString(), QString("0.05"));
}
void tst_QJSEngine::protoChanges_QTBUG68369()
diff --git a/tests/auto/qml/qmlmin/tst_qmlmin.cpp b/tests/auto/qml/qmlmin/tst_qmlmin.cpp
index c393149f59..d1e74aecef 100644
--- a/tests/auto/qml/qmlmin/tst_qmlmin.cpp
+++ b/tests/auto/qml/qmlmin/tst_qmlmin.cpp
@@ -128,6 +128,7 @@ void tst_qmlmin::initTestCase()
invalidFiles << "tests/auto/qml/parserstress/tests/ecma_3/FunExpr/fe-001.js";
invalidFiles << "tests/auto/qml/qjsengine/script/com/trolltech/syntaxerror/__init__.js";
invalidFiles << "tests/auto/qml/debugger/qqmlpreview/data/broken.qml";
+ invalidFiles << "tests/auto/qml/qqmllanguage/data/fuzzed.2.qml";
}
QStringList tst_qmlmin::findFiles(const QDir &d)
diff --git a/tests/auto/qml/qqmllanguage/data/cyclicAlias.errors.txt b/tests/auto/qml/qqmllanguage/data/cyclicAlias.errors.txt
new file mode 100644
index 0000000000..46951ef69f
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/cyclicAlias.errors.txt
@@ -0,0 +1 @@
+4:5:Cyclic alias
diff --git a/tests/auto/qml/qqmllanguage/data/cyclicAlias.qml b/tests/auto/qml/qqmllanguage/data/cyclicAlias.qml
new file mode 100644
index 0000000000..23129e210d
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/cyclicAlias.qml
@@ -0,0 +1,5 @@
+import QtQml 2.2
+QtObject {
+ id: o
+ property alias t: o.t
+}
diff --git a/tests/auto/qml/qqmllanguage/data/fuzzed.1.errors.txt b/tests/auto/qml/qqmllanguage/data/fuzzed.1.errors.txt
new file mode 100644
index 0000000000..e399799fe9
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/fuzzed.1.errors.txt
@@ -0,0 +1,2 @@
+2:8:Cannot assign to non-existent property "_G"
+
diff --git a/tests/auto/qml/qqmllanguage/data/fuzzed.1.qml b/tests/auto/qml/qqmllanguage/data/fuzzed.1.qml
new file mode 100644
index 0000000000..f80b9c3a2d
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/fuzzed.1.qml
@@ -0,0 +1,2 @@
+import QtQuick 2.4
+Item { _G.G.G:G }
diff --git a/tests/auto/qml/qqmllanguage/data/fuzzed.2.errors.txt b/tests/auto/qml/qqmllanguage/data/fuzzed.2.errors.txt
new file mode 100644
index 0000000000..92ce4c649f
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/fuzzed.2.errors.txt
@@ -0,0 +1,2 @@
+5:1:TetZ$ is not a type
+-1:-1:Invalid QML type name "TetZ$"
diff --git a/tests/auto/qml/qqmllanguage/data/fuzzed.2.qml b/tests/auto/qml/qqmllanguage/data/fuzzed.2.qml
new file mode 100644
index 0000000000..e726f6783c
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/fuzzed.2.qml
Binary files differ
diff --git a/tests/auto/qml/qqmllanguage/data/objectValueTypeProperty.errors.txt b/tests/auto/qml/qqmllanguage/data/objectValueTypeProperty.errors.txt
index cefd62f9d4..945dacf8ab 100644
--- a/tests/auto/qml/qqmllanguage/data/objectValueTypeProperty.errors.txt
+++ b/tests/auto/qml/qqmllanguage/data/objectValueTypeProperty.errors.txt
@@ -1 +1 @@
-4:18:Unexpected object assignment for property "x"
+4:18:Can not assign value of type "int" to property "x", expecting an object
diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
index 19927c5a8a..1b4ff71beb 100644
--- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
+++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
@@ -361,7 +361,7 @@ private:
} \
file.close(); \
} else { \
- QCOMPARE(expected, actual); \
+ QCOMPARE(actual, expected); \
} \
}
@@ -614,6 +614,10 @@ void tst_qqmllanguage::errors_data()
QTest::newRow("badCompositeRegistration.2") << "badCompositeRegistration.2.qml" << "badCompositeRegistration.2.errors.txt" << false;
QTest::newRow("assignComponentToWrongType") << "assignComponentToWrongType.qml" << "assignComponentToWrongType.errors.txt" << false;
+ QTest::newRow("cyclicAlias") << "cyclicAlias.qml" << "cyclicAlias.errors.txt" << false;
+
+ QTest::newRow("fuzzed.1") << "fuzzed.1.qml" << "fuzzed.1.errors.txt" << false;
+ QTest::newRow("fuzzed.2") << "fuzzed.2.qml" << "fuzzed.2.errors.txt" << false;
}
@@ -624,6 +628,7 @@ void tst_qqmllanguage::errors()
QFETCH(bool, create);
QQmlComponent component(&engine, testFileUrl(file));
+ QTRY_VERIFY(!component.isLoading());
QScopedPointer<QObject> object;
diff --git a/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp b/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp
index 8a01524b5b..83a37df797 100644
--- a/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp
+++ b/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp
@@ -33,6 +33,8 @@
#include <QJSValueIterator>
#include <private/qquickvaluetypes_p.h>
#include <private/qqmlglobal_p.h>
+#include <private/qv4engine_p.h>
+#include <private/qv4variantobject_p.h>
#include "../../shared/util.h"
#include "testtypes.h"
@@ -94,6 +96,7 @@ private slots:
void toStringConversion();
void enumerableProperties();
void enumProperties();
+ void scarceTypes();
private:
QQmlEngine engine;
@@ -1809,6 +1812,26 @@ void tst_qqmlvaluetypes::enumProperties()
QCOMPARE(enumValue.toInt(), int(g.enumProperty()));
}
+void tst_qqmlvaluetypes::scarceTypes()
+{
+ // These should not be treated as value types because we want the scarce resource
+ // mechanism to clear them when going out of scope. The scarce resource mechanism
+ // only works on QV4::VariantObject as that has an additional level of redirection.
+ QVERIFY(!QQmlValueTypeFactory::isValueType(qMetaTypeId<QImage>()));
+ QVERIFY(!QQmlValueTypeFactory::isValueType(qMetaTypeId<QPixmap>()));
+
+ QV4::ExecutionEngine engine;
+ QV4::Scope scope(&engine);
+
+ QImage img(20, 20, QImage::Format_ARGB32);
+ QV4::ScopedObject imgValue(scope, engine.fromVariant(QVariant::fromValue(img)));
+ QCOMPARE(QByteArray(imgValue->vtable()->className), QByteArray("VariantObject"));
+
+ QPixmap pixmap;
+ QV4::ScopedObject pixmapValue(scope, engine.fromVariant(QVariant::fromValue(img)));
+ QCOMPARE(QByteArray(pixmapValue->vtable()->className), QByteArray("VariantObject"));
+}
+
QTEST_MAIN(tst_qqmlvaluetypes)
diff --git a/tests/auto/qml/qv4assembler/tst_qv4assembler.cpp b/tests/auto/qml/qv4assembler/tst_qv4assembler.cpp
index 4916cb4cc0..fd50ff5020 100644
--- a/tests/auto/qml/qv4assembler/tst_qv4assembler.cpp
+++ b/tests/auto/qml/qv4assembler/tst_qv4assembler.cpp
@@ -34,6 +34,8 @@
#include <QtQml/qqml.h>
#include <QtQml/qqmlapplicationengine.h>
+#include <private/qv4global_p.h>
+
#ifdef Q_OS_WIN
#include <windows.h>
#endif
@@ -46,6 +48,7 @@ private slots:
void initTestCase() override;
void perfMapFile();
void functionTable();
+ void jitEnabled();
};
void tst_QV4Assembler::initTestCase()
@@ -137,6 +140,26 @@ void tst_QV4Assembler::functionTable()
#endif
}
+#ifdef V4_ENABLE_JIT
+#define JIT_ENABLED 1
+#else
+#define JIT_ENABLED 0
+#endif
+
+void tst_QV4Assembler::jitEnabled()
+{
+#if defined(Q_OS_IOS) || defined(Q_OS_TVOS)
+ /* JIT should be disabled on iOS and tvOS. */
+ QCOMPARE(JIT_ENABLED, 0);
+#elif defined(Q_OS_WIN) && defined(Q_PROCESSOR_ARM)
+ /* JIT should be disabled Windows on ARM/ARM64 for now. */
+ QCOMPARE(JIT_ENABLED, 0);
+#else
+ /* JIT should be enabled on all other architectures/OSes tested in CI. */
+ QCOMPARE(JIT_ENABLED, 1);
+#endif
+}
+
QTEST_MAIN(tst_QV4Assembler)
#include "tst_qv4assembler.moc"
diff --git a/tests/auto/quick/qquicklistview/BLACKLIST b/tests/auto/quick/qquicklistview/BLACKLIST
index ecdf8f558e..893f95dcea 100644
--- a/tests/auto/quick/qquicklistview/BLACKLIST
+++ b/tests/auto/quick/qquicklistview/BLACKLIST
@@ -6,3 +6,6 @@ opensuse-leap
[populateTransitions]
opensuse-42.1
#QTBUG-65964
+
+[contentHeightWithDelayRemove]
+osx-10.12
diff --git a/tests/auto/quick/qquickmultipointtoucharea/BLACKLIST b/tests/auto/quick/qquickmultipointtoucharea/BLACKLIST
index de939b5273..6af00ab76f 100644
--- a/tests/auto/quick/qquickmultipointtoucharea/BLACKLIST
+++ b/tests/auto/quick/qquickmultipointtoucharea/BLACKLIST
@@ -3,8 +3,10 @@ ubuntu-16.04
ubuntu-18.04
opensuse-42.3
opensuse-leap
+sles
[nested]
ubuntu-16.04
ubuntu-18.04
opensuse-42.3
opensuse-leap
+sles
diff --git a/tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp b/tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp
index aaf37b32cd..fd5c3653ad 100644
--- a/tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp
+++ b/tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp
@@ -161,7 +161,7 @@ void tst_qquickwidget::showHide()
window.show();
QVERIFY(QTest::qWaitForWindowExposed(&window));
- QVERIFY(childView->quickWindow()->isVisible());
+ QVERIFY(!childView->quickWindow()->isVisible()); // this window is always not visible see QTBUG-65761
QVERIFY(childView->quickWindow()->visibility() != QWindow::Hidden);
window.hide();
@@ -612,7 +612,7 @@ void tst_qquickwidget::synthMouseFromTouch()
childView->resize(300, 300);
window.show();
QVERIFY(QTest::qWaitForWindowActive(&window));
- QVERIFY(childView->quickWindow()->isVisible());
+ QVERIFY(!childView->quickWindow()->isVisible()); // this window is always not visible see QTBUG-65761
QVERIFY(item->isVisible());
QPoint p1 = QPoint(20, 20);
diff --git a/tools/qmlscene/main.cpp b/tools/qmlscene/main.cpp
index c6c6ed1c4a..867267c821 100644
--- a/tools/qmlscene/main.cpp
+++ b/tools/qmlscene/main.cpp
@@ -42,6 +42,7 @@
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlcomponent.h>
#include <QtQml/qqmlcontext.h>
+#include <QtQml/qqmlfileselector.h>
#include <QtQuick/qquickitem.h>
#include <QtQuick/qquickview.h>
@@ -361,6 +362,7 @@ static void usage()
#endif
puts(" --textrendertype [qt|native].......Select the default render type for text-like elements.");
puts(" -I <path> ........................ Add <path> to the list of import paths");
+ puts(" -S <selector> .....................Add <selector> to the list of QQmlFileSelector selectors");
puts(" -P <path> ........................ Add <path> to the list of plugin paths");
puts(" -translation <translationfile> ... Set the language to run in");
@@ -457,6 +459,7 @@ int main(int argc, char ** argv)
Options options;
QStringList imports;
+ QStringList customSelectors;
QStringList pluginPaths;
// Parse arguments for application attributes to be applied before Q[Gui]Application creation.
@@ -529,6 +532,8 @@ int main(int argc, char ** argv)
options.verbose = true;
else if (lowerArgument == QLatin1String("-i") && i + 1 < size)
imports.append(arguments.at(++i));
+ else if (lowerArgument == QLatin1String("-s") && i + 1 < size)
+ customSelectors.append(arguments.at(++i));
else if (lowerArgument == QLatin1String("-p") && i + 1 < size)
pluginPaths.append(arguments.at(++i));
else if (lowerArgument == QLatin1String("--apptype"))
@@ -584,6 +589,8 @@ int main(int argc, char ** argv)
// TODO: as soon as the engine construction completes, the debug service is
// listening for connections. But actually we aren't ready to debug anything.
QQmlEngine engine;
+ QQmlFileSelector* selector = new QQmlFileSelector(&engine, &engine);
+ selector->setExtraSelectors(customSelectors);
QPointer<QQmlComponent> component = new QQmlComponent(&engine);
for (int i = 0; i < imports.size(); ++i)
engine.addImportPath(imports.at(i));