From bc00353cffbfe0f74b602a16452f2e7bcd588152 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Mon, 8 Apr 2019 16:57:30 +0200 Subject: Detect and reject cyclic aliases Previously those would result in infinite recursion. Fixes: QTBUG-74867 Change-Id: I6c0043b43e72fe7bc3a2a139ca600af2d5bca5ad Reviewed-by: Simon Hausmann --- src/qml/compiler/qqmlpropertycachecreator_p.h | 40 ++++++++++++++++------ .../qml/qqmllanguage/data/cyclicAlias.errors.txt | 1 + tests/auto/qml/qqmllanguage/data/cyclicAlias.qml | 5 +++ tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp | 1 + 4 files changed, 37 insertions(+), 10 deletions(-) create mode 100644 tests/auto/qml/qqmllanguage/data/cyclicAlias.errors.txt create mode 100644 tests/auto/qml/qqmllanguage/data/cyclicAlias.qml diff --git a/src/qml/compiler/qqmlpropertycachecreator_p.h b/src/qml/compiler/qqmlpropertycachecreator_p.h index 6bee599c0a..074dc98648 100644 --- a/src/qml/compiler/qqmlpropertycachecreator_p.h +++ b/src/qml/compiler/qqmlpropertycachecreator_p.h @@ -692,11 +692,6 @@ inline QQmlCompileError QQmlPropertyCacheAliasCreator::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; @@ -704,11 +699,36 @@ inline QQmlCompileError QQmlPropertyCacheAliasCreator::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 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/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/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp index dea7c6c7ee..f7198415a2 100644 --- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp +++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp @@ -612,6 +612,7 @@ void tst_qqmllanguage::errors_data() QTest::newRow("badCompositeRegistration.1") << "badCompositeRegistration.1.qml" << "badCompositeRegistration.1.errors.txt" << false; QTest::newRow("badCompositeRegistration.2") << "badCompositeRegistration.2.qml" << "badCompositeRegistration.2.errors.txt" << false; + QTest::newRow("cyclicAlias") << "cyclicAlias.qml" << "cyclicAlias.errors.txt" << false; } -- cgit v1.2.3 From 1f4862ef5db138e9dcefe1ebc16df3e054200775 Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Tue, 26 Mar 2019 17:37:48 +0100 Subject: QQuickWindow: Run render jobs when there is a render control in NoStage When running a QML application with using Canvas3D component inside a QQuickWidget, the Canvas3D is not rendered. This is due to no scheduled OpenGL commands with RenderStage == NoStage are actually executed when there is a render control instead of a window manager. Fixes: QTBUG-51993 Change-Id: I33323893cd6144187feccb1c6bcd010eff0fff6d Reviewed-by: Laszlo Agocs --- src/quick/items/qquickwindow.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index c6bfcaa647..bd01e9b3ce 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -4828,10 +4828,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(); } -- cgit v1.2.3 From 936cc8adccecfdd32966bd9c1ff7a9f534a027fe Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Mon, 8 Apr 2019 11:42:29 +0200 Subject: Add support for selectors to qmlscene This allows to use qmlscene together with file selectors. Task-number: QDS-589 Change-Id: Icf613c938bfc2c56b33a36ab2da32c3c54b498a2 Reviewed-by: Ulf Hermann --- tools/qmlscene/main.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tools/qmlscene/main.cpp b/tools/qmlscene/main.cpp index 83d6ce5d72..a1a162cda7 100644 --- a/tools/qmlscene/main.cpp +++ b/tools/qmlscene/main.cpp @@ -42,6 +42,7 @@ #include #include #include +#include #include #include @@ -361,6 +362,7 @@ static void usage() #endif puts(" --textrendertype [qt|native].......Select the default render type for text-like elements."); puts(" -I ........................ Add to the list of import paths"); + puts(" -S .....................Add to the list of QQmlFileSelector selectors"); puts(" -P ........................ Add to the list of plugin paths"); puts(" -translation ... 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 component = new QQmlComponent(&engine); for (int i = 0; i < imports.size(); ++i) engine.addImportPath(imports.at(i)); -- cgit v1.2.3 From b2fd2b664212344eb82b44f916c849314d5e02fb Mon Sep 17 00:00:00 2001 From: Mitch Curtis Date: Tue, 9 Apr 2019 18:32:50 +0200 Subject: Doc: correct the info about when each Qt Quick Test function is called Only qmlEngineAvailable() is called for each QML test file; the rest are called once for the entire test application. Change-Id: I293c5a2491da75ddad68e7fb89bcd32b770fccf5 Reviewed-by: Paul Wicking --- src/qmltest/doc/src/qtquicktest-index.qdoc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/qmltest/doc/src/qtquicktest-index.qdoc b/src/qmltest/doc/src/qtquicktest-index.qdoc index bee160f6e8..4fad21e080 100644 --- a/src/qmltest/doc/src/qtquicktest-index.qdoc +++ b/src/qmltest/doc/src/qtquicktest-index.qdoc @@ -165,6 +165,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}, @@ -177,10 +181,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: -- cgit v1.2.3 From fe3e9110327f022daf676766ce04b8a0a147c7c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tony=20Saraj=C3=A4rvi?= Date: Thu, 11 Apr 2019 11:58:15 +0300 Subject: Extend blacklisting of qquickmultiponttoucharea to SLES Task-number: QTBUG-59960 Change-Id: I6684b1a63425233dbee1d37acfe3e785cb76a597 Reviewed-by: Ulf Hermann --- tests/auto/quick/qquickmultipointtoucharea/BLACKLIST | 2 ++ 1 file changed, 2 insertions(+) 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 -- cgit v1.2.3 From 72a16358112512c49022a8f80432d2d3a330fff2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Wed, 10 Apr 2019 14:25:59 +0200 Subject: Document macOS threaded render loop availability The threaded render loop (or specifically QPlatformIntegration::Capability::ThreadedOpenGL) is disabled when building with Xcode 10 (10.14 SDK). Task-number: QTBUG-75037 Change-Id: Ib0b4cab56c053958fcae5616cbb496602efbf5e1 Reviewed-by: Simon Hausmann --- src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) 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. -- cgit v1.2.3 From 0af154c41dc0dfbf5994e7eb3056b2333b5645b7 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Fri, 12 Apr 2019 10:42:56 +0200 Subject: Don't create value types for QImage and QPixmap Those are "scarce" resources which need to be kept as QVariant. Fixes: QTBUG-74751 Change-Id: I28381e2a754ed4bbf4e409dc275f6288b64416cc Reviewed-by: Simon Hausmann --- src/qml/jsruntime/qv4engine.cpp | 4 +++ src/qml/qml/qqmlvaluetype.cpp | 29 ++++++++++++++-------- .../auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp | 23 +++++++++++++++++ 3 files changed, 45 insertions(+), 11 deletions(-) diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index bcd577c24d..bd1124beb6 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -1537,6 +1537,10 @@ QV4::ReturnedValue QV4::ExecutionEngine::fromVariant(const QVariant &variant) case QMetaType::QLocale: return QQmlLocale::wrap(this, *reinterpret_cast(ptr)); #endif + case QMetaType::QPixmap: + case QMetaType::QImage: + // Scarce value types + return QV4::Encode(newVariantObject(variant)); default: break; } diff --git a/src/qml/qml/qqmlvaluetype.cpp b/src/qml/qml/qqmlvaluetype.cpp index 2b21591017..cb6a467c6c 100644 --- a/src/qml/qml/qqmlvaluetype.cpp +++ b/src/qml/qml/qqmlvaluetype.cpp @@ -81,19 +81,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/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp b/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp index 1ee4510e30..41fa87d848 100644 --- a/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp +++ b/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp @@ -33,6 +33,8 @@ #include #include #include +#include +#include #include "../../shared/util.h" #include "testtypes.h" @@ -93,6 +95,7 @@ private slots: void toStringConversion(); void enumerableProperties(); void enumProperties(); + void scarceTypes(); private: QQmlEngine engine; @@ -1766,6 +1769,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())); + QVERIFY(!QQmlValueTypeFactory::isValueType(qMetaTypeId())); + + 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) -- cgit v1.2.3 From 956099608b98d8f57798f59c8f5367a476e2d5ae Mon Sep 17 00:00:00 2001 From: Alec Rivers Date: Fri, 12 Apr 2019 10:58:13 -0700 Subject: Ensure the correct version of LinkBuffer's performFinalization is called Task-number: QTBUG-74876 Change-Id: I8e816d29b709750b121cc63edfc5f3493a3ed119 Reviewed-by: Simon Hausmann --- src/3rdparty/masm/assembler/LinkBuffer.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/3rdparty/masm/assembler/LinkBuffer.h b/src/3rdparty/masm/assembler/LinkBuffer.h index c79b0663c8..7f9979302e 100644 --- a/src/3rdparty/masm/assembler/LinkBuffer.h +++ b/src/3rdparty/masm/assembler/LinkBuffer.h @@ -243,7 +243,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); @@ -342,7 +342,7 @@ inline void LinkBufferBase::linkCode } template class ExecutableOffsetCalculator> -inline void LinkBufferBase::performFinalization() +void LinkBufferBase::performFinalization() { // NOTE: This function is specialized in LinkBuffer #ifndef NDEBUG @@ -388,7 +388,7 @@ public: linkCode(ownerUID, effort); } - inline void performFinalization(); + virtual void performFinalization() override final; inline void linkCode(void* ownerUID, JITCompilationEffort); @@ -412,7 +412,7 @@ private: }; template -inline void BranchCompactingLinkBuffer::performFinalization() +void BranchCompactingLinkBuffer::performFinalization() { #ifndef NDEBUG ASSERT(!m_completed); -- cgit v1.2.3 From 6dac2e7df7fbf0f29667bf92b4e72426db47dbe9 Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Sat, 13 Apr 2019 00:31:06 +0200 Subject: Only create the imports array if importCount is greater than 0 Since it is possible that CompilationUnit::instantiate() might be called more than once when the importCount is 0 then it should only create the imports array when it is greater than 0. This prevents a memory leak due to the recreation of this array each time it is called even though there is no imports to assign. Change-Id: I5d84b01de10bff2ca25248251e8337839e434bd5 Reviewed-by: Simon Hausmann --- src/qml/compiler/qv4compileddata.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp index 9ffcb81fa2..8f2f4a11c1 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); -- cgit v1.2.3